🎭 Add Collection Seeding Script for Alice & Bob
✨ Created Comprehensive Collection Seeding: - Wipes all existing collections cleanly - Seeds 4 collections for Alice (vintage MTG, modern decks, Pokemon, Lorcana) - Seeds 5 collections for Bob (commander, standard, rare Pokemon, Japanese, budget) - Generates proper URL slugs for all collections - Creates proper ownership permissions 🎨 Alice's Collections (4): - Alice's Vintage MTG Collection (Public) - Power 9 & vintage cards - Modern Competitive Decks (Private) - Tournament-ready decks - Pokemon Base Set Complete (Public) - Complete 1998 base set - Disney Lorcana Treasures (Private) - Beautiful Disney characters 🎮 Bob's Collections (5): - Bob's Commander Arsenal (Public) - EDH multiplayer decks - Standard Rotation Collection (Private) - Current standard cards - Rare Pokemon Cards (Public) - First editions & promos - Japanese Exclusive Cards (Private) - Unique Japanese artwork - Budget Deck Collection (Public) - Beginner-friendly decks 🔧 Technical Features: - Proper user ownership (Alice ID: 5, Bob ID: 6) - Mix of public/private collections for testing - Realistic descriptions and tags - Clean database wipe before seeding - URL-friendly slug generation Perfect for testing authentication, permissions, and collection management! 🎯
This commit is contained in:
parent
7c9368a739
commit
e4ea9b4e73
1 changed files with 211 additions and 0 deletions
211
scripts/seed-collections-alice-bob.js
Normal file
211
scripts/seed-collections-alice-bob.js
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
import { neon } from '@neondatabase/serverless';
|
||||
import { generateUniqueSlug } from '../lib/slug-utils.js';
|
||||
|
||||
dotenv.config({ path: '.env.local' });
|
||||
|
||||
async function seedCollectionsForAliceAndBob() {
|
||||
const sql = neon(process.env.POSTGRES_URL);
|
||||
|
||||
try {
|
||||
console.log('🧹 Wiping existing collections...');
|
||||
|
||||
// Delete all collection-related data
|
||||
await sql`DELETE FROM collection_cards`;
|
||||
await sql`DELETE FROM collection_permissions`;
|
||||
await sql`DELETE FROM collections`;
|
||||
|
||||
console.log('✅ All collections wiped clean!');
|
||||
|
||||
// Get Alice and Bob's user IDs
|
||||
const users = await sql`
|
||||
SELECT id, email FROM users
|
||||
WHERE email IN ('alice@tcgvault.com', 'bob@tcgvault.com')
|
||||
ORDER BY email
|
||||
`;
|
||||
|
||||
if (users.length !== 2) {
|
||||
console.error('❌ Could not find Alice and Bob users');
|
||||
return;
|
||||
}
|
||||
|
||||
const alice = users.find(u => u.email === 'alice@tcgvault.com');
|
||||
const bob = users.find(u => u.email === 'bob@tcgvault.com');
|
||||
|
||||
console.log(`👩 Alice: ID ${alice.id}`);
|
||||
console.log(`👨 Bob: ID ${bob.id}`);
|
||||
|
||||
// Alice's Collections
|
||||
const aliceCollections = [
|
||||
{
|
||||
name: "Alice's Vintage MTG Collection",
|
||||
description: "My precious vintage Magic cards including some Power 9 pieces and classic sets from the early days of Magic.",
|
||||
tcg: "MTG",
|
||||
isPublic: true,
|
||||
tags: ["vintage", "power-nine", "alpha", "beta", "unlimited", "investment"]
|
||||
},
|
||||
{
|
||||
name: "Modern Competitive Decks",
|
||||
description: "Tournament-ready Modern format decks for competitive play. Always updating with the latest meta shifts.",
|
||||
tcg: "MTG",
|
||||
isPublic: false,
|
||||
tags: ["modern", "competitive", "tournament", "meta", "deck-building"]
|
||||
},
|
||||
{
|
||||
name: "Pokemon Base Set Complete",
|
||||
description: "Complete Pokemon Base Set from 1998 including all holos. Childhood memories preserved in mint condition!",
|
||||
tcg: "Pokemon",
|
||||
isPublic: true,
|
||||
tags: ["pokemon", "base-set", "complete", "holographic", "childhood", "mint"]
|
||||
},
|
||||
{
|
||||
name: "Disney Lorcana Treasures",
|
||||
description: "Beautiful Disney Lorcana cards featuring my favorite Disney characters. Love the art style!",
|
||||
tcg: "Lorcana",
|
||||
isPublic: false,
|
||||
tags: ["disney", "lorcana", "characters", "artwork", "collecting"]
|
||||
}
|
||||
];
|
||||
|
||||
// Bob's Collections
|
||||
const bobCollections = [
|
||||
{
|
||||
name: "Bob's Commander Arsenal",
|
||||
description: "My collection of powerful Commander cards and complete EDH decks. Always ready for multiplayer mayhem!",
|
||||
tcg: "MTG",
|
||||
isPublic: true,
|
||||
tags: ["commander", "edh", "multiplayer", "powerful", "deck-building"]
|
||||
},
|
||||
{
|
||||
name: "Standard Rotation Collection",
|
||||
description: "Current Standard-legal cards organized by set. Perfect for building new Standard decks quickly.",
|
||||
tcg: "MTG",
|
||||
isPublic: false,
|
||||
tags: ["standard", "rotation", "current", "deck-building", "competitive"]
|
||||
},
|
||||
{
|
||||
name: "Rare Pokemon Cards",
|
||||
description: "My rarest Pokemon cards including first editions, shadowless, and special promotional cards.",
|
||||
tcg: "Pokemon",
|
||||
isPublic: true,
|
||||
tags: ["rare", "first-edition", "shadowless", "promotional", "investment"]
|
||||
},
|
||||
{
|
||||
name: "Japanese Exclusive Cards",
|
||||
description: "Hard-to-find Japanese exclusive cards from various TCGs. Unique artwork and special editions.",
|
||||
tcg: "MTG",
|
||||
isPublic: false,
|
||||
tags: ["japanese", "exclusive", "special-edition", "artwork", "rare"]
|
||||
},
|
||||
{
|
||||
name: "Budget Deck Collection",
|
||||
description: "Affordable but effective decks for new players and casual games. Great for teaching friends!",
|
||||
tcg: "MTG",
|
||||
isPublic: true,
|
||||
tags: ["budget", "casual", "beginner-friendly", "teaching", "affordable"]
|
||||
}
|
||||
];
|
||||
|
||||
console.log('🎨 Creating Alice\'s collections...');
|
||||
|
||||
// Create Alice's collections
|
||||
let existingSlugs = [];
|
||||
for (const collection of aliceCollections) {
|
||||
const uniqueSlug = await generateUniqueSlug(collection.name, existingSlugs);
|
||||
existingSlugs.push(uniqueSlug);
|
||||
|
||||
const result = await sql`
|
||||
INSERT INTO collections (name, description, tcg, is_public, tags, user_id, slug, created_at, updated_at)
|
||||
VALUES (
|
||||
${collection.name},
|
||||
${collection.description},
|
||||
${collection.tcg},
|
||||
${collection.isPublic},
|
||||
${collection.tags.join(',')},
|
||||
${alice.id},
|
||||
${uniqueSlug},
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
)
|
||||
RETURNING id, name, slug
|
||||
`;
|
||||
|
||||
// Create owner permission
|
||||
await sql`
|
||||
INSERT INTO collection_permissions (collection_id, user_id, role, status, created_at)
|
||||
VALUES (${result[0].id}, ${alice.id}, 'owner', 'active', CURRENT_TIMESTAMP)
|
||||
`;
|
||||
|
||||
console.log(` ✅ "${collection.name}" → "${uniqueSlug}"`);
|
||||
}
|
||||
|
||||
console.log('🎨 Creating Bob\'s collections...');
|
||||
|
||||
// Create Bob's collections
|
||||
for (const collection of bobCollections) {
|
||||
const uniqueSlug = await generateUniqueSlug(collection.name, existingSlugs);
|
||||
existingSlugs.push(uniqueSlug);
|
||||
|
||||
const result = await sql`
|
||||
INSERT INTO collections (name, description, tcg, is_public, tags, user_id, slug, created_at, updated_at)
|
||||
VALUES (
|
||||
${collection.name},
|
||||
${collection.description},
|
||||
${collection.tcg},
|
||||
${collection.isPublic},
|
||||
${collection.tags.join(',')},
|
||||
${bob.id},
|
||||
${uniqueSlug},
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
)
|
||||
RETURNING id, name, slug
|
||||
`;
|
||||
|
||||
// Create owner permission
|
||||
await sql`
|
||||
INSERT INTO collection_permissions (collection_id, user_id, role, status, created_at)
|
||||
VALUES (${result[0].id}, ${bob.id}, 'owner', 'active', CURRENT_TIMESTAMP)
|
||||
`;
|
||||
|
||||
console.log(` ✅ "${collection.name}" → "${uniqueSlug}"`);
|
||||
}
|
||||
|
||||
console.log('\n🎉 Collections seeded successfully!');
|
||||
console.log('\n📊 Summary:');
|
||||
console.log(` 👩 Alice's Collections: ${aliceCollections.length}`);
|
||||
console.log(` 👨 Bob's Collections: ${bobCollections.length}`);
|
||||
console.log(` 📦 Total Collections: ${aliceCollections.length + bobCollections.length}`);
|
||||
|
||||
console.log('\n🔗 Alice\'s Collections:');
|
||||
aliceCollections.forEach((collection, index) => {
|
||||
const slug = collection.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
||||
console.log(` • ${collection.name} (${collection.tcg}) - ${collection.isPublic ? 'Public' : 'Private'}`);
|
||||
});
|
||||
|
||||
console.log('\n🔗 Bob\'s Collections:');
|
||||
bobCollections.forEach((collection, index) => {
|
||||
const slug = collection.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
||||
console.log(` • ${collection.name} (${collection.tcg}) - ${collection.isPublic ? 'Public' : 'Private'}`);
|
||||
});
|
||||
|
||||
console.log('\n🎯 Ready to test!');
|
||||
console.log(' 1. Login as Alice → See her 4 collections');
|
||||
console.log(' 2. Login as Bob → See his 5 collections');
|
||||
console.log(' 3. Each user can only edit/delete their own collections');
|
||||
console.log(' 4. Public collections are visible to other users');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to seed collections:', error.message);
|
||||
console.error('Full error:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
seedCollectionsForAliceAndBob();
|
||||
}
|
||||
|
||||
export { seedCollectionsForAliceAndBob };
|
||||
Loading…
Reference in a new issue