/** * Shared seed bootstrap: ports + system roles + super admin profile. * * Both the realistic seed (`seed.ts`) and the synthetic seed * (`seed-synthetic.ts`) call into this so we don't drift on the * permission maps or the operator account ids. * * Idempotent. Returns the resolved port ids so callers can chain * per-port fixture builders. */ import { eq } from 'drizzle-orm'; import { db } from './index'; import { ports } from './schema/ports'; import { roles, userProfiles } from './schema/users'; import { ALL_PERMISSIONS, DIRECTOR_PERMISSIONS, SALES_MANAGER_PERMISSIONS, SALES_AGENT_PERMISSIONS, VIEWER_PERMISSIONS, RESIDENTIAL_PARTNER_PERMISSIONS, } from './seed-permissions'; export interface BootstrappedPort { id: string; name: string; slug: string; } export const PORT_DEFINITIONS: Array<{ name: string; slug: string; primaryColor: string; defaultCurrency: string; timezone: string; }> = [ { name: 'Port Nimara', slug: 'port-nimara', primaryColor: '#0F4C81', defaultCurrency: 'USD', timezone: 'America/Anguilla', }, { name: 'Port Amador', slug: 'port-amador', primaryColor: '#D97706', defaultCurrency: 'USD', timezone: 'America/Panama', }, ]; export const SUPER_ADMIN_USER_ID = 'super-admin-matt-portnimara'; export async function seedBootstrap(): Promise { console.log('Bootstrap: ports + roles + super admin profile'); // ── Ports ────────────────────────────────────────────────────────────────── const portIds: BootstrappedPort[] = []; for (const def of PORT_DEFINITIONS) { const [inserted] = await db .insert(ports) .values({ id: crypto.randomUUID(), name: def.name, slug: def.slug, logoUrl: null, primaryColor: def.primaryColor, defaultCurrency: def.defaultCurrency, timezone: def.timezone, settings: {}, isActive: true, }) .onConflictDoNothing() .returning(); if (inserted) { console.log(` Port created: ${def.name} (${inserted.id})`); portIds.push({ id: inserted.id, name: def.name, slug: def.slug }); } else { const [existing] = await db.select().from(ports).where(eq(ports.slug, def.slug)).limit(1); if (existing) { console.log(` Port exists: ${def.name} (${existing.id})`); portIds.push({ id: existing.id, name: def.name, slug: def.slug }); } } } // ── System roles ────────────────────────────────────────────────────────── const systemRoles = [ { id: crypto.randomUUID(), name: 'super_admin', description: 'Full system access. Bypasses all permission checks.', permissions: ALL_PERMISSIONS, isGlobal: true, isSystem: true, }, { id: crypto.randomUUID(), name: 'director', description: 'Operational admin within assigned port(s). Can manage users and settings.', permissions: DIRECTOR_PERMISSIONS, isGlobal: true, isSystem: true, }, { id: crypto.randomUUID(), name: 'sales_manager', description: 'Full sales access. Can view all reminders, assign tasks, and export reports.', permissions: SALES_MANAGER_PERMISSIONS, isGlobal: true, isSystem: true, }, { id: crypto.randomUUID(), name: 'sales_agent', description: 'Standard sales role. View/create/edit clients and interests, manage own reminders.', permissions: SALES_AGENT_PERMISSIONS, isGlobal: true, isSystem: true, }, { id: crypto.randomUUID(), name: 'viewer', description: 'Read-only access to all records.', permissions: VIEWER_PERMISSIONS, isGlobal: true, isSystem: true, }, { id: crypto.randomUUID(), name: 'residential_partner', description: 'External partner who handles residential inquiries. Sees only the residential pages — no marina clients, yachts, berths, or financial data.', permissions: RESIDENTIAL_PARTNER_PERMISSIONS, isGlobal: true, isSystem: true, }, ]; for (const role of systemRoles) { await db.insert(roles).values(role).onConflictDoNothing(); } console.log(` Roles ensured: ${systemRoles.map((r) => r.name).join(', ')}`); // ── Super admin profile placeholder ─────────────────────────────────────── await db .insert(userProfiles) .values({ id: crypto.randomUUID(), userId: SUPER_ADMIN_USER_ID, displayName: 'Matt', avatarUrl: null, phone: null, isSuperAdmin: true, isActive: true, lastLoginAt: null, preferences: {}, }) .onConflictDoNothing(); console.log(` Super admin profile ensured (user_id: ${SUPER_ADMIN_USER_ID})`); return portIds; }