import postgres, { createPool, PgDb } from "./pg.ts"; import { config } from "./config.ts"; /** * panels_platform: control plane SaaS (tenants, platform_users, * smtp_settings). Base de datos separada de panels_product -- ningún * código de iam/core debe importar este módulo, y viceversa. Sin RLS: no * es multi-tenant en el mismo sentido (son las cuentas del propio equipo * de PANELS), así que un solo pool basta. * * El bootstrap del primer platform_admin ya NO ocurre aquí en cada arranque * (antes: seedPlatform() en cada getPlatformDb()) -- es un comando explícito * y one-shot, ver scripts/bootstrap-admin.ts (Fase 4). */ let pool: postgres.Sql | null = null; export type PlatformDb = PgDb; export type PlatformUser = { id: number; username: string; display_name: string; status: string; }; export async function getPlatformDb(): Promise { if (!pool) { pool = createPool(config.databaseUrlPlatform, { max: 10 }); await pool`SELECT 1`; } return new PgDb(pool); } export async function closePlatformDb(): Promise { await pool?.end({ timeout: 5 }); pool = null; } export async function pingPlatformDb(): Promise { await getPlatformDb().then((db) => db.prepare("SELECT 1").get()); } export async function listTenants(database: PlatformDb) { return await database.prepare( `SELECT id, code, name, status, created_at, COALESCE(plan, 'trial') AS plan, valid_until, COALESCE(notes, '') AS notes, COALESCE(contact_email, '') AS contact_email, COALESCE(contact_name, '') AS contact_name, access_sent_at FROM tenants ORDER BY id`, ).all() as { id: number; code: string; name: string; status: string; created_at: string; plan: string; valid_until: string | null; notes: string; contact_email: string; contact_name: string; access_sent_at: string | null; }[]; } export async function tenantByCode(database: PlatformDb, code: string) { return await database.prepare("SELECT * FROM tenants WHERE code = ?").get( code.trim().toUpperCase(), ) as | { id: number; code: string; name: string; status: string; plan?: string; valid_until?: string | null; notes?: string; } | undefined; } export async function tenantById(database: PlatformDb, id: number) { return await database.prepare("SELECT * FROM tenants WHERE id = ?").get(id) as | { id: number; code: string; name: string; status: string; plan?: string; valid_until?: string | null; notes?: string; created_at?: string; } | undefined; } export async function lastInsertId(database: PlatformDb): Promise { return await database.lastInsertId(); }