#!/usr/bin/env node /** * Script to generate bulk test data for the webstore database * Usage: node scripts/generate-test-data.js [options] * * Options: * --products N Generate N additional products (default: 10) * --orders N Generate N test orders (default: 5) * --reset Delete all data before seeding (careful!) */ require("dotenv").config({ path: ".env" }); const { PrismaClient } = require("@prisma/client"); const bcryptjs = require("bcryptjs"); const prisma = new PrismaClient(); // Parse command line arguments const args = process.argv.slice(2); const options = { productsCount: 10, ordersCount: 5, shouldReset: false }; for (let i = 0; i < args.length; i++) { if (args[i] === "--products" && args[i + 1]) { options.productsCount = parseInt(args[i + 1], 10); i++; } else if (args[i] === "--orders" && args[i + 1]) { options.ordersCount = parseInt(args[i + 1], 10); i++; } else if (args[i] === "--reset") { options.shouldReset = true; } } const productNames = [ "Premium Leather Boots", "Summer Canvas Shoes", "Minimalist Sneakers", "Casual Loafers", "Running Shoes Pro", "Hiking Boots", "Beach Sandals", "Formal Dress Shoes", "Winter Snow Boots", "Slip-on Comfort Shoes", "Designer Heels", "Waterproof Outdoor Boots", "Lightweight Mesh Runners", "Classic Oxfords", "Athletic Training Shoes" ]; const descriptions = [ "Premium quality with exceptional comfort", "Perfect for everyday wear and activities", "Stylish design with modern aesthetics", "Durable materials built to last", "Eco-friendly sustainable production", "Handcrafted with attention to detail", "Weather-resistant and waterproof", "Ergonomic design for all-day comfort", "Available in multiple colors", "Perfect for professional environments" ]; function generateRandomPrice() { return (Math.floor(Math.random() * 20) + 5).toString() + "990.00"; } function generateRandomStock() { return Math.floor(Math.random() * 50) + 5; } function getRandomElement(arr) { return arr[Math.floor(Math.random() * arr.length)]; } async function resetDatabase() { console.log("⚠️ Resetting database..."); try { // Delete in order of dependencies await prisma.orderItem.deleteMany({}); await prisma.order.deleteMany({}); await prisma.product.deleteMany({}); await prisma.category.deleteMany({}); await prisma.user.deleteMany({}); console.log("✓ Database reset completed"); } catch (error) { console.error("Error resetting database:", error.message); throw error; } } async function seedInitialData() { console.log("Seeding initial categories..."); const categories = [ { name: "Shoes", slug: "shoes" }, { name: "Bags", slug: "bags" }, { name: "Accessories", slug: "accessories" }, { name: "Clothing", slug: "clothing" }, { name: "Electronics", slug: "electronics" } ]; for (const category of categories) { await prisma.category.upsert({ where: { slug: category.slug }, update: {}, create: category }); } console.log("✓ Categories seeded"); } async function generateProducts(count) { console.log(`\nGenerating ${count} additional products...`); const categories = await prisma.category.findMany(); const generatedProducts = []; for (let i = 0; i < count; i++) { const category = getRandomElement(categories); const name = `${getRandomElement(productNames)} ${i + 1}`; try { const product = await prisma.product.create({ data: { name, description: getRandomElement(descriptions), price: generateRandomPrice(), stock: generateRandomStock(), categoryId: category.id, imageUrl: `/images/placeholder-${i + 1}.jpg` } }); generatedProducts.push(product); if ((i + 1) % 5 === 0) { process.stdout.write(`\r Progress: ${i + 1}/${count} products`); } } catch (error) { if (!error.message.includes("Unique constraint failed")) { console.error(`\nError creating product: ${error.message}`); } } } console.log(`\r✓ Generated ${generatedProducts.length} products`); return generatedProducts; } async function generateTestUsers(count = 5) { console.log(`\nGenerating ${count} test users...`); const users = []; for (let i = 1; i <= count; i++) { const email = `user${i}@test.com`; const passwordHash = await bcryptjs.hash("password123", 10); try { const user = await prisma.user.upsert({ where: { email }, update: {}, create: { name: `Test User ${i}`, email, passwordHash } }); users.push(user); } catch (error) { console.error(`Error creating user: ${error.message}`); } } console.log(`✓ Generated ${users.length} test users`); return users; } async function generateOrders(count) { console.log(`\nGenerating ${count} test orders...`); const products = await prisma.product.findMany({ take: 20 }); const createdOrders = []; for (let i = 0; i < count; i++) { try { const itemsCount = Math.floor(Math.random() * 3) + 1; const items = []; let totalPrice = 0; for (let j = 0; j < itemsCount; j++) { const product = getRandomElement(products); const quantity = Math.floor(Math.random() * 3) + 1; items.push({ productId: product.id, quantity, unitPrice: product.price }); totalPrice += parseFloat(product.price) * quantity; } const order = await prisma.order.create({ data: { customerName: `Customer ${i + 1}`, customerEmail: `customer${i + 1}@example.com`, totalPrice: totalPrice.toFixed(2), items: { create: items } }, include: { items: true } }); createdOrders.push(order); if ((i + 1) % 2 === 0) { process.stdout.write(`\r Progress: ${i + 1}/${count} orders`); } } catch (error) { console.error(`\nError creating order: ${error.message}`); } } console.log(`\r✓ Generated ${createdOrders.length} orders`); return createdOrders; } async function main() { console.log("🚀 Test Data Generator for Webstore\n"); console.log("Options:"); console.log(` Products to generate: ${options.productsCount}`); console.log(` Orders to generate: ${options.ordersCount}`); console.log(` Reset database first: ${options.shouldReset ? "YES" : "NO"}\n`); try { if (options.shouldReset) { await resetDatabase(); } await seedInitialData(); await generateTestUsers(5); await generateProducts(options.productsCount); await generateOrders(options.ordersCount); console.log("\n✨ Test data generation completed successfully!"); } catch (error) { console.error("\n❌ Error during data generation:", error.message); process.exit(1); } finally { await prisma.$disconnect(); } } main();