import pg from 'pg'; import pino from 'pino'; import { config } from '../config/index.js'; const logger = pino({ name: 'data' }); const pool = new pg.Pool({ connectionString: config.DATABASE_URL }); /** * RLS tenant isolation wrapper. * Sets `app.tenant_id` for the duration of the callback, then resets. */ export async function withTenant(tenantId: string, fn: (client: pg.PoolClient) => Promise): Promise { const client = await pool.connect(); try { await client.query('BEGIN'); await client.query('SELECT set_config($1, $2, true)', ['app.tenant_id', tenantId]); const result = await fn(client); await client.query('COMMIT'); return result; } catch (err) { await client.query('ROLLBACK'); throw err; } finally { await client.query('RESET app.tenant_id'); client.release(); } } /** System-level queries that intentionally bypass RLS (auth, migrations, health) */ export async function systemQuery( text: string, params?: any[] ): Promise> { return pool.query(text, params); } /** For auth middleware that needs direct pool access for API key lookups */ export function getPoolForAuth(): pg.Pool { return pool; }