Files
dd0c/products/shared/db.ts

42 lines
1017 B
TypeScript
Raw Normal View History

/**
* Shared withTenant() RLS helper.
* Copy into each product's src/data/db.ts or import from shared.
*
* CRITICAL (BMad must-have): Always RESET app.tenant_id in finally block
* to prevent connection pool tenant context leakage.
*/
import pg from 'pg';
export async function withTenant<T>(
pool: pg.Pool,
tenantId: string,
fn: (client: pg.PoolClient) => Promise<T>,
): Promise<T> {
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query(`SET LOCAL 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();
}
}
/**
* Health check query verifies DB connectivity.
*/
export async function healthCheck(pool: pg.Pool): Promise<boolean> {
try {
await pool.query('SELECT 1');
return true;
} catch {
return false;
}
}