UNPKG

@accounter/server

Version:
50 lines (49 loc) 2.5 kB
import type { Pool, PoolClient } from 'pg'; /** * Unique role name per worker. `process.pid` alone is not enough: in Vitest's * thread pool, parallel workers share one process (and thus one pid), so a random * suffix is appended to avoid role-name collisions across concurrent test files. */ export declare const RLS_TEST_ROLE: string; /** A table privilege grant: e.g. `{ table: 'sort_codes', privileges: 'INSERT, SELECT' }`. */ export interface RlsRoleGrant { /** Unqualified table name (schema prefix is added automatically). */ table: string; /** Comma-separated SQL privileges, e.g. `'SELECT'` or `'INSERT, SELECT'`. */ privileges: string; } export interface RlsRoleOptions { /** Table privileges to grant the role for the queries under test. */ grants?: RlsRoleGrant[]; } /** * Idempotently create the per-process non-superuser RLS role and grant it schema * usage plus any requested table privileges. * * `CREATE ROLE` / `GRANT` are not meant to be rolled back per-test, so this runs * on its own connection outside any test transaction. Call from `beforeAll` and * pair with {@link dropRlsRole} in `afterAll`. */ export declare function ensureRlsRole(pool: Pool, options?: RlsRoleOptions): Promise<void>; /** * Drop the RLS role. Mirror of {@link ensureRlsRole}. * * A bare `DROP ROLE` would fail while the role still holds the schema/table grants * from ensureRlsRole — Postgres tracks them in pg_shdepend and refuses to drop a * role other objects depend on. So we first `DROP OWNED BY`, which revokes every * privilege granted to the role in the current database, then drop the role. The * whole thing is guarded on role existence so a failed setup (role never created) * surfaces the real error instead of a "role does not exist" during teardown. */ export declare function dropRlsRole(pool: Pool): Promise<void>; /** * Run `fn` with the connection's role dropped to the non-superuser RLS role, so * Postgres evaluates the RLS policies. The role switch is confined to a SAVEPOINT: * on success the role is reset and the savepoint released; on any error the * savepoint is rolled back (which also restores the original role) and the error * is rethrown for the caller to interpret (e.g. `42501` = WITH CHECK rejection). * * Set the relevant `app.*` session variables BEFORE calling this — as superuser, * before privileges are dropped. */ export declare function runAsRlsRole<T>(client: PoolClient, fn: () => Promise<T>): Promise<T>;