#!/usr/bin/env node /** * Seed script โ€” injects mock data into the VidReview database. * * Creates: * 1 admin * 3 members (each owns 2-3 projects) * Per project: 1 editor + 1 reviewer (taken from the 3 members) * * Usage: * node scripts/seed-mock-data.js * * Env vars (optional, defaults work for local docker): * DATABASE_URL=postgresql://vidreview:vidreview123@localhost:5432/vidreview */ import { PrismaClient } from '@prisma/client'; import bcrypt from 'bcryptjs'; const prisma = new PrismaClient(); const BCRYPT_ROUNDS = 10; const PASSWORD = 'demo1234'; async function cleanAll() { console.log('\n๐Ÿงน Cleaning existing data...'); await prisma.comment.deleteMany(); await prisma.asset.deleteMany(); await prisma.invitation.deleteMany(); await prisma.projectMember.deleteMany(); await prisma.project.deleteMany(); await prisma.user.deleteMany(); console.log(' All tables cleared.'); } async function createUser(email: string, name: string, globalRole: 'ADMIN' | 'MEMBER', projectRole?: 'ADMIN' | 'EDITOR' | 'REVIEWER' | 'VIEWER') { const password = await bcrypt.hash(PASSWORD, BCRYPT_ROUNDS); return prisma.user.create({ data: { email, name, password, globalRole, storageQuota: 524288000, storageUsed: 0 }, select: { id: true, email: true, name: true, globalRole: true }, }); } async function createProject(name: string, ownerId: string, editorId: string, reviewerId: string) { const slug = name.toLowerCase().replace(/\s+/g, '-'); // Create project const project = await prisma.project.create({ data: { name, ownerId, }, }); // Add owner as ADMIN of project await prisma.projectMember.create({ data: { userId: ownerId, projectId: project.id, role: 'ADMIN', invitedBy: ownerId }, }); // Add editor await prisma.projectMember.create({ data: { userId: editorId, projectId: project.id, role: 'EDITOR', invitedBy: ownerId }, }); // Add reviewer await prisma.projectMember.create({ data: { userId: reviewerId, projectId: project.id, role: 'REVIEWER', invitedBy: ownerId }, }); return project; } async function main() { console.log('\nโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”'); console.log(' VidReview โ€” Mock Data Seeder'); console.log('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n'); await cleanAll(); // โ”€โ”€ 1. Admin โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const admin = await createUser('admin@vidreview.local', 'Admin', 'ADMIN'); console.log(`โœ… Admin created`); // โ”€โ”€ 2. Members โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const memberDefs = [ { email: 'alice@vidreview.local', name: 'Alice Johnson' }, { email: 'bob@vidreview.local', name: 'Bob Smith' }, { email: 'carol@vidreview.local', name: 'Carol White' }, ]; const members = await Promise.all( memberDefs.map(m => createUser(m.email, m.name, 'MEMBER')) ); console.log(`โœ… ${members.length} members created`); // โ”€โ”€ 3. Projects per member โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const projectDefs = [ // Alice owns 3 projects { name: 'Brand Campaign Q2', ownerIdx: 0, editorIdx: 1, reviewerIdx: 2 }, { name: 'Product Launch Video', ownerIdx: 0, editorIdx: 2, reviewerIdx: 1 }, { name: 'Internal Training Clips', ownerIdx: 0, editorIdx: 1, reviewerIdx: 2 }, // Bob owns 2 projects { name: 'Customer Testimonials', ownerIdx: 1, editorIdx: 0, reviewerIdx: 2 }, { name: 'Event Highlights Reel', ownerIdx: 1, editorIdx: 2, reviewerIdx: 0 }, // Carol owns 3 projects { name: 'Social Media Shorts', ownerIdx: 2, editorIdx: 0, reviewerIdx: 1 }, { name: 'How-To Tutorial Series', ownerIdx: 2, editorIdx: 1, reviewerIdx: 0 }, { name: 'Partner Collaboration', ownerIdx: 2, editorIdx: 0, reviewerIdx: 1 }, ]; const projects = await Promise.all( projectDefs.map(p => createProject( p.name, members[p.ownerIdx].id, members[p.editorIdx].id, members[p.reviewerIdx].id, ) ) ); console.log(`โœ… ${projects.length} projects created\n`); // โ”€โ”€ Output credentials table โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const divider = 'โ”€'.repeat(72); console.log(divider); console.log(' ๐Ÿ“‹ Login Credentials'); console.log(divider); console.log(` ${'Type'.padEnd(10)} ${'Name'.padEnd(22)} ${'Email'.padEnd(35)} Password`); console.log(divider); console.log(` ${'ADMIN'.padEnd(10)} ${admin.name.padEnd(22)} ${admin.email.padEnd(35)} ${PASSWORD}`); for (const m of members) { console.log(` ${'MEMBER'.padEnd(10)} ${m.name.padEnd(22)} ${m.email.padEnd(35)} ${PASSWORD}`); } console.log(divider); console.log(`\n All users have storage quota: 500 MB`); console.log(` Password for all accounts: ${PASSWORD}`); console.log(''); console.log(' Project membership per user:'); console.log(divider); for (const m of members) { const memberProjects = projects.filter((_, i) => projectDefs[i].ownerIdx === members.indexOf(m)); const roleMap: Record = {}; for (const proj of memberProjects) { const def = projectDefs.find(p => p.name === proj.name)!; const role = members[projectDefs.findIndex(p => p.name === proj.name)].id === m.id ? 'owner โ†’ project ADMIN' : `project ${projectDefs.findIndex(p => p.name === proj.name) < 3 ? ['EDITOR', 'REVIEWER', 'EDITOR'][projectDefs.findIndex(p => p.name === proj.name) % 3] : ['REVIEWER', 'EDITOR', 'REVIEWER'][projectDefs.findIndex(p => p.name === proj.name) % 3]}`; } const memberships = await prisma.projectMember.findMany({ where: { userId: m.id }, include: { project: true }, }); const roles = await prisma.projectMember.findMany({ where: { userId: m.id } }); const lines = memberships.map((pm, i) => { const def = projectDefs.find(p => p.name === pm.project.name)!; const role = pm.userId === members[def.ownerIdx].id ? 'ADMIN (owner)' : roles[i].role; return ` โ€ข ${pm.project.name.padEnd(30)} [${role}]`; }); console.log(` ${m.name} (${m.email}):`); lines.forEach(l => console.log(l)); } console.log(divider); console.log('\nโœ… Done!\n'); await prisma.$disconnect(); } main().catch(err => { console.error('\nโŒ Seed failed:', err); process.exit(1); });