UNPKG

@accounter/server

Version:
77 lines (75 loc) 2.57 kB
import type { PoolClient, QueryResult, QueryResultRow } from 'pg'; import { AuthContextProvider } from '../auth/providers/auth-context.provider.js'; import { DBProvider } from './db.provider.js'; /** * TenantAwareDBClient enforces Row-Level Security (RLS) by setting PostgreSQL * session variables for every database transaction. * * RLS Enforcement: * - app.current_business_id: Set to the authenticated user's active business * - app.current_user_id: Set to the authenticated user's ID (or NULL for API keys) * - app.auth_type: Set to 'jwt' or 'apiKey' * * **Usage:** * Inject into Operation-scoped providers via constructor DI: * * @example * @Injectable({ scope: Scope.Operation }) * class BusinessesProvider { * constructor(private db: TenantAwareDBClient) {} * * async getBusinesses() { * return this.db.query('SELECT * FROM businesses') * } * } * * Transaction Management: * - Supports nested transactions via SAVEPOINTs * - Automatically rolls back on error * - Automatically releases connection on dispose * * **DO NOT** access from Yoga context - use DI injection instead. * * @throws {GraphQLError} UNAUTHENTICATED if auth context is null */ export declare class TenantAwareDBClient { private dbProvider; private authContextProvider; private mutex; private storage; private activeClient; private transactionDepth; private isDisposed; private initializationPromise; private authContext; private authContextInitialized; constructor(dbProvider: DBProvider, authContextProvider: AuthContextProvider); /** * Execute a query with RLS enforcement. * If a transaction is already active, uses it. * If not, starts a new transaction/session, executes the query, and commits. */ query<T extends QueryResultRow = QueryResultRow>(text: string, params?: unknown[]): Promise<QueryResult<T> & { rowCount: number; }>; /** * Execute a function within a transaction block. * Handles nested transactions using SAVEPOINTs. */ transaction<T>(fn: (client: PoolClient) => Promise<T>): Promise<T>; private executeTransactionInternal; /** * Set PostgreSQL session variables for Row-Level Security. */ private setRLSVariables; /** * Manually dispose the client. */ dispose(): Promise<void>; private ensureNotDisposed; /** * Lazy initialization of auth context on first use. * This ensures the async provider is called only when needed. */ private ensureAuthContext; }