// prisma/seed.ts import { PrismaClient, UserRole, ContentStatus, ProficiencyLevel, ExerciseType } from '@prisma/client' import { Pool } from 'pg' import { PrismaPg } from '@prisma/adapter-pg' const connectionString = process.env.DIRECT_URL async function main() { console.log('🌱 Starting seed...') // 1. Setup the Adapter (Crucial for Prisma 7 + Serverless) const pool = new Pool({ connectionString }) const adapter = new PrismaPg(pool) const prisma = new PrismaClient({ adapter }) try { // 2. Create a Teacher/Super Admin const teacher = await prisma.profile.upsert({ where: { email: 'admin@acve.com' }, update: {}, create: { email: 'admin@acve.com', fullName: 'ACVE Admin', // ✅ CORRECT: Uses the strict Enum value role: UserRole.SUPER_ADMIN, avatarUrl: 'https://github.com/shadcn.png', }, }) console.log(`👤 Created User: ${teacher.email}`) // 3. Create a Law Firm (B2B) const lawFirm = await prisma.company.create({ data: { name: 'García & Partners', billingEmail: 'billing@garcia.com', maxSeats: 10, memberships: { create: { userId: teacher.id, // ✅ FIXED: Use 'ORG_ADMIN' to match your UserRole terminology // Since this field is a String in schema, we use the string value explicitly. role: 'ORG_ADMIN', }, }, }, }) console.log(`🏢 Created Law Firm: ${lawFirm.name}`) // 4. Create the Bilingual Course (Contract Law) const course = await prisma.course.create({ data: { title: { en: "Legal English: Contract Basics", es: "Inglés Jurídico: Fundamentos de Contratos" }, slug: "contract-law-101", description: { en: "Master the terminology of international contracts.", es: "Domina la terminología de contratos internacionales." }, level: ProficiencyLevel.INTERMEDIATE, status: ContentStatus.PUBLISHED, price: 499.00, authorId: teacher.id, tags: ["contracts", "civil law", "compliance"], modules: { create: { title: { en: "Module 1: Offer and Acceptance", es: "Módulo 1: Oferta y Aceptación" }, orderIndex: 1, lessons: { create: { title: { en: "The Elements of a Contract", es: "Los Elementos de un Contrato" }, slug: "elements-of-contract", orderIndex: 1, estimatedDuration: 600, isFreePreview: true, exercises: { create: { type: ExerciseType.MULTIPLE_CHOICE, orderIndex: 1, content: { question: "What is 'Consideration' in a contract?", options: ["Payment", "Thoughtfulness", "A value exchange", "A signature"], correctAnswer: "A value exchange" } } } } } } } }, }) console.log(`📚 Created Course: ${course.slug}`) const miniGames = [ { slug: "translation", title: "Legal Translation Challenge", description: "Translate legal terms accurately in context.", difficulty: "BEGINNER", questions: [ { prompt: "Spanish term: incumplimiento contractual", choices: ["Contractual compliance", "Breach of contract", "Contract interpretation", "Mutual assent"], answerIndex: 1, }, { prompt: "Spanish term: medida cautelar", choices: ["Class action", "Summary judgment", "Injunctive relief", "Arbitration clause"], answerIndex: 2, }, ], }, { slug: "term-matching", title: "Term Matching Game", description: "Match legal terms with accurate definitions.", difficulty: "INTERMEDIATE", questions: [ { prompt: "Match: consideration", choices: [ "A legally binding command from the court", "A bargained-for exchange of value between parties", "A prior case that has no legal effect", "A statement made outside of court", ], answerIndex: 1, }, { prompt: "Match: injunction", choices: [ "A court order requiring a party to do or stop doing something", "A clause that sets venue for disputes", "A witness statement under oath", "A mandatory arbitration waiver", ], answerIndex: 0, }, ], }, { slug: "contract-clauses", title: "Contract Clause Practice", description: "Pick the best clause drafting option for each scenario.", difficulty: "ADVANCED", questions: [ { prompt: "Choose the strongest force majeure clause element:", choices: [ "No definition of triggering events", "Broad reference without notice obligations", "Defined events, notice timeline, and mitigation duty", "Automatic termination without limits", ], answerIndex: 2, }, { prompt: "Best limitation of liability drafting choice:", choices: [ "Exclude all damages including willful misconduct", "Cap liability with carve-outs for fraud and gross negligence", "No cap and no exclusions", "Cap liability only for one party", ], answerIndex: 1, }, ], }, ] const prismaAny = prisma as unknown as { miniGame: { upsert: (args: object) => Promise<{ id: string }> } miniGameQuestion: { deleteMany: (args: object) => Promise createMany: (args: object) => Promise } } for (const game of miniGames) { const saved = await prismaAny.miniGame.upsert({ where: { slug: game.slug }, update: { title: game.title, description: game.description, difficulty: game.difficulty, isActive: true, }, create: { slug: game.slug, title: game.title, description: game.description, difficulty: game.difficulty, isActive: true, }, }) await prismaAny.miniGameQuestion.deleteMany({ where: { miniGameId: saved.id }, }) await prismaAny.miniGameQuestion.createMany({ data: game.questions.map((q, index) => ({ miniGameId: saved.id, prompt: q.prompt, choices: q.choices, answerIndex: q.answerIndex, orderIndex: index, })), }) } console.log(`🧩 Seeded ${miniGames.length} mini-games`) console.log('✅ Seed complete!') } catch (e) { console.error(e) process.exit(1) } finally { await prisma.$disconnect() } } main()