import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); const categories = [ { name: 'Apparel', slug: 'APPAREL' }, { name: 'Drinkware', slug: 'DRINKWARE' }, { name: 'Phone case', slug: 'PHONE_CASE' }, ]; const products: Array<{ slug: string; name: string; category: string; description: string; basePrice: number; colors: string[]; sizes: string[]; mockup: string; printArea: { xPct: number; yPct: number; wPct: number; hPct: number }; imageUrl: string | null; imageUrlBack: string | null; photoRecolorable: boolean; }> = [ { slug: 'classic-tee', name: 'Classic Tee', category: 'APPAREL', description: 'Heavyweight 220gsm combed cotton. Your artwork, printed dead-center on the chest.', basePrice: 2900, colors: ['#FFFFFF', '#17181C', '#2B4C3F', '#8A8578', '#1EA7E0', '#E5227E', '#F5871F', '#5B2C86', '#7A1F1F', '#D8D2C2'], sizes: ['S', 'M', 'L', 'XL', 'XXL'], mockup: 'tshirt', printArea: { xPct: 0.32, yPct: 0.27, wPct: 0.36, hPct: 0.34 }, imageUrl: '/seed/tee-front.png', imageUrlBack: '/seed/tee-back.png', photoRecolorable: true, }, { slug: 'heavyweight-hoodie', name: 'Heavyweight Hoodie', category: 'APPAREL', description: 'Brushed-fleece interior, boxy fit. Built for a bold front print.', basePrice: 5400, colors: ['#17181C', '#8A8578', '#2B4C3F', '#7A1F1F', '#1EA7E0', '#D8D2C2', '#5B2C86'], sizes: ['S', 'M', 'L', 'XL', 'XXL'], mockup: 'hoodie', printArea: { xPct: 0.33, yPct: 0.34, wPct: 0.34, hPct: 0.28 }, imageUrl: null, imageUrlBack: null, photoRecolorable: false, }, { slug: 'ceramic-mug', name: 'Ceramic Mug', category: 'DRINKWARE', description: '11oz glossy ceramic. Dishwasher-safe, wraparound print.', basePrice: 1800, colors: ['#FFFFFF', '#17181C', '#1EA7E0', '#E5227E', '#F5871F', '#5B2C86'], sizes: [], mockup: 'mug', printArea: { xPct: 0.22, yPct: 0.32, wPct: 0.56, hPct: 0.28 }, imageUrl: null, imageUrlBack: null, photoRecolorable: false, }, { slug: 'travel-tumbler', name: 'Travel Tumbler', category: 'DRINKWARE', description: '16oz double-wall stainless steel, keeps drinks cold for 24 hours.', basePrice: 3200, colors: ['#17181C', '#8A8578', '#C9A227', '#1EA7E0', '#E5227E', '#2B4C3F'], sizes: [], mockup: 'tumbler', printArea: { xPct: 0.26, yPct: 0.28, wPct: 0.48, hPct: 0.36 }, imageUrl: null, imageUrlBack: null, photoRecolorable: false, }, { slug: 'snap-phone-case', name: 'Snap Phone Case', category: 'PHONE_CASE', description: 'Slim polycarbonate snap case with a matte finish.', basePrice: 2200, colors: ['#FFFFFF', '#17181C', '#2B4C3F', '#E5227E', '#1EA7E0', '#F5871F'], sizes: [], mockup: 'phonecase', printArea: { xPct: 0.28, yPct: 0.16, wPct: 0.44, hPct: 0.5 }, imageUrl: null, imageUrlBack: null, photoRecolorable: false, }, { slug: 'tough-phone-case', name: 'Tough Phone Case', category: 'PHONE_CASE', description: 'Dual-layer shock-resistant case with raised edges.', basePrice: 2900, colors: ['#17181C', '#8A8578', '#5B2C86', '#7A1F1F'], sizes: [], mockup: 'phonecase', printArea: { xPct: 0.3, yPct: 0.18, wPct: 0.4, hPct: 0.46 }, imageUrl: null, imageUrlBack: null, photoRecolorable: false, }, { slug: 'shaker-bottle', name: 'Shaker Bottle', category: 'DRINKWARE', description: '20oz insulated shaker bottle with a secure flip-top lid. Your artwork, printed on the body.', basePrice: 1500, colors: ['#FFFFFF'], sizes: [], mockup: 'tumbler', printArea: { xPct: 0.32, yPct: 0.36, wPct: 0.36, hPct: 0.38 }, imageUrl: '/seed/shaker-bottle.png', imageUrlBack: null, photoRecolorable: false, }, ]; async function main() { for (const c of categories) { await prisma.category.upsert({ where: { slug: c.slug }, update: {}, create: c, }); } for (const p of products) { const data = { name: p.name, category: p.category, description: p.description, basePrice: p.basePrice, colors: JSON.stringify(p.colors), sizes: p.sizes.length > 0 ? JSON.stringify(p.sizes) : null, mockup: p.mockup, printArea: JSON.stringify(p.printArea), imageUrl: p.imageUrl, imageUrlBack: p.imageUrlBack, photoRecolorable: p.photoRecolorable, }; await prisma.product.upsert({ where: { slug: p.slug }, update: data, // keeps these 6 starter products in sync when the seed file changes create: { slug: p.slug, ...data }, }); } console.log(`Seeded ${categories.length} categories and ${products.length} products.`); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });