@accounter/server
Version:
Accounter GraphQL server
77 lines (75 loc) • 2.57 kB
TypeScript
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;
}