Files
2026-04-01 22:01:36 +02:00

264 lines
6.9 KiB
JavaScript

#!/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();