import { loadEnvFile } from 'node:process'; import { randomUUID } from 'node:crypto'; import { resolve } from 'node:path'; import { eq } from 'drizzle-orm'; import { loadConfig } from '../apps/server/src/config.ts'; import { createApp } from '../apps/server/src/app.ts'; import { users } from '../apps/server/src/db/schema.ts'; try { loadEnvFile('.env'); } catch (error) { if (error.code !== 'ENOENT') throw error; } if (process.env.NODE_ENV === 'production') throw Error('개발 환경에서만 실행할 수 있습니다.'); const cfg = loadConfig({ ...process.env, NODE_ENV: 'development', DATABASE_PATH: process.env.HOP_DEV_DATABASE_PATH ?? resolve('.data/hop.sqlite'), UPLOAD_DIR: process.env.HOP_DEV_UPLOAD_DIR ?? resolve('.data/uploads'), }); const runtime = await createApp(cfg); try { const password = '1234'; const passwordHash = await runtime.service.auth.password(password); const accounts = [1, 2].map((n) => ({ email: `test${n}@hop.test`, displayName: `hop. 테스트 ${n}`, })); // Only these named development fixtures may have their passwords reset. for (const account of accounts) { const existing = runtime.service.db .select() .from(users) .where(eq(users.email, account.email)) .get(); if (existing && (existing.displayName !== account.displayName || existing.role !== 'user')) throw Error(`테스트 계정이 아닌 기존 계정입니다: ${account.email}`); } runtime.service.db.transaction(() => { for (const account of accounts) { const existing = runtime.service.db .select() .from(users) .where(eq(users.email, account.email)) .get(); if (existing) runtime.service.db .update(users) .set({ passwordHash }) .where(eq(users.id, existing.id)) .run(); else runtime.service.db .insert(users) .values({ id: randomUUID(), ...account, passwordHash, role: 'user', status: 'active', verifiedAt: Date.now(), createdAt: Date.now(), }) .run(); } }); for (const account of accounts) { const result = await runtime.service.auth.login(account.email, password, 'local-test-seed'); if (!result.account.verified) throw Error('인증 상태 검증 실패'); runtime.service.auth.logout(result.token); console.log(`${account.email}: 생성 및 로그인 검증 완료`); } } finally { await runtime.app.close(); }