import { PrismaClient, TaskStatus, TaskPriority, ProjectStatus, WorkspaceMemberRole, } from "@prisma/client"; const prisma = new PrismaClient(); async function main() { console.log("Seeding database..."); // IMPORTANT: This seed script should not be run concurrently // If running in CI/CD, ensure serialization of seed operations // to prevent race conditions and data corruption // Create test user const user = await prisma.user.upsert({ where: { email: "dev@mosaic.local" }, update: {}, create: { email: "dev@mosaic.local", name: "Development User", preferences: { theme: "system", notifications: true, }, }, }); console.log(`Created user: ${user.email}`); // Create workspace const workspace = await prisma.workspace.upsert({ where: { id: "00000000-0000-0000-0000-000000000001" }, update: {}, create: { id: "00000000-0000-0000-0000-000000000001", name: "Development Workspace", ownerId: user.id, settings: { timezone: "America/New_York", }, }, }); console.log(`Created workspace: ${workspace.name}`); // Add user as workspace owner await prisma.workspaceMember.upsert({ where: { workspaceId_userId: { workspaceId: workspace.id, userId: user.id, }, }, update: {}, create: { workspaceId: workspace.id, userId: user.id, role: WorkspaceMemberRole.OWNER, }, }); // Use transaction for atomic seed data reset and creation await prisma.$transaction(async (tx) => { // Delete existing seed data for idempotency (avoids duplicates on re-run) await tx.task.deleteMany({ where: { workspaceId: workspace.id } }); await tx.event.deleteMany({ where: { workspaceId: workspace.id } }); await tx.project.deleteMany({ where: { workspaceId: workspace.id } }); // Create sample project const project = await tx.project.create({ data: { workspaceId: workspace.id, name: "Sample Project", description: "A sample project for development", status: ProjectStatus.ACTIVE, creatorId: user.id, color: "#3B82F6", }, }); console.log(`Created project: ${project.name}`); // Create sample tasks const tasks = [ { title: "Set up development environment", status: TaskStatus.COMPLETED, priority: TaskPriority.HIGH, }, { title: "Review project requirements", status: TaskStatus.IN_PROGRESS, priority: TaskPriority.MEDIUM, }, { title: "Design database schema", status: TaskStatus.COMPLETED, priority: TaskPriority.HIGH, }, { title: "Implement NestJS integration", status: TaskStatus.COMPLETED, priority: TaskPriority.HIGH, }, { title: "Create seed data", status: TaskStatus.IN_PROGRESS, priority: TaskPriority.MEDIUM, }, ]; // Use createMany for batch insertion (better performance) await tx.task.createMany({ data: tasks.map((taskData) => ({ workspaceId: workspace.id, title: taskData.title, status: taskData.status, priority: taskData.priority, creatorId: user.id, projectId: project.id, })), }); console.log(`Created ${tasks.length} sample tasks`); // Create sample event const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setHours(10, 0, 0, 0); await tx.event.create({ data: { workspaceId: workspace.id, title: "Morning standup", description: "Daily team sync", startTime: tomorrow, endTime: new Date(tomorrow.getTime() + 30 * 60000), // 30 minutes later creatorId: user.id, projectId: project.id, }, }); console.log("Created sample event"); }); console.log("Seeding completed successfully!"); } main() .catch((e) => { console.error("Error seeding database:", e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });