import type { Auth, Role } from '../auth/options'; import type { DbHandle } from './index'; export interface SeedAccount { email: string; password: string; name: string; role: Role; } /** * Accounts per CONTRACTS.md section 4. Deterministic and idempotent: running the seed * twice leaves the same rows. * * Their profiles, documents and declarations are seeded by the phases that own those * tables. Until then `GET /me/profile` correctly answers 404 for each of them, which is * the documented state for a user who has not finished setup. */ export const SEED_ACCOUNTS: readonly SeedAccount[] = [ { email: 'superadmin@demo.local', password: 'demo-superadmin-1', name: 'Super Admin', role: 'superadmin' }, { email: 'staff@demo.local', password: 'demo-staff-1', name: 'Staff Demo', role: 'staff' }, { email: 'maria@demo.local', password: 'demo-maria-1', name: 'Maria Gonzalez', role: 'user' }, { email: 'carlos@demo.local', password: 'demo-carlos-1', name: 'Carlos Benitez', role: 'user' }, ]; export interface SeedResult { created: string[]; existing: string[]; } export async function seed(handle: DbHandle, auth: Auth): Promise { const result: SeedResult = { created: [], existing: [] }; for (const account of SEED_ACCOUNTS) { const found = await handle.db .selectFrom('user') .select('id') .where('email', '=', account.email) .executeTakeFirst(); if (found) { result.existing.push(account.email); continue; } await auth.api.signUpEmail({ body: { email: account.email, password: account.password, name: account.name }, }); // Roles and verification are set directly: the sign up endpoint always creates a // plain unverified `user`, and demo accounts need to be usable straight away. await handle.db .updateTable('user') .set({ role: account.role, emailVerified: 1, updatedAt: new Date().toISOString() }) .where('email', '=', account.email) .execute(); result.created.push(account.email); } return result; }