/** * Dev seed — creates a default demo user with 수능 과목/태그 preset. * Run via: `pnpm prisma:seed` (or `ts-node prisma/seed.ts`). * * Idempotent: re-running just upserts. */ import { PrismaClient, Persona, ReviewIntensity } from '@prisma/client'; import * as bcrypt from 'bcrypt'; const prisma = new PrismaClient(); const DEMO_EMAIL = 'demo@reloop.local'; const DEMO_PASSWORD = 'demo1234'; interface SubjectSeed { name: string; color: string; tags: string[]; } const SUBJECTS: SubjectSeed[] = [ { name: '국어', color: '#ef4444', tags: ['문학', '독서(비문학)', '화법과작문', '언어와매체', '고전시가'], }, { name: '수학', color: '#3b82f6', tags: ['미적분', '확률과통계', '기하', '수1 지수로그', '수1 삼각함수', '수2 미분', '수2 적분'], }, { name: '영어', color: '#22c55e', tags: ['문법/어법', '어휘', '빈칸추론', '순서배열', '삽입', '주제/제목', '함축의미'], }, { name: '사회탐구', color: '#f59e0b', tags: ['생활과윤리', '사회문화', '한국지리', '세계사'], }, { name: '과학탐구', color: '#8b5cf6', tags: ['물리1', '화학1', '생명과학1', '지구과학1'], }, ]; async function main() { console.log('🌱 ReLoop seed start'); // Demo user const hash = await bcrypt.hash(DEMO_PASSWORD, 10); const user = await prisma.user.upsert({ where: { email: DEMO_EMAIL }, update: {}, create: { email: DEMO_EMAIL, password: hash, nickname: '데모', persona: Persona.mid, currentGrade: 4, targetGrade: 2, reviewIntensity: ReviewIntensity.moderate, onboardedAt: new Date(), }, }); console.log(` user: ${user.email} (id=${user.id}) password=${DEMO_PASSWORD}`); for (const s of SUBJECTS) { const subject = await prisma.subject.upsert({ where: { userId_name: { userId: user.id, name: s.name } }, update: { color: s.color }, create: { name: s.name, color: s.color, userId: user.id }, }); console.log(` subject: ${subject.name}`); for (const tagName of s.tags) { await prisma.tag.upsert({ where: { subjectId_name: { subjectId: subject.id, name: tagName } }, update: {}, create: { name: tagName, subjectId: subject.id }, }); } } console.log('✅ seed done'); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });