UNPKG

@accounter/server

Version:
101 lines (100 loc) 4.08 kB
/** * Fixture insertion logic with ordered insertion and rollback support * * Inserts fixture data into the database in the correct order to satisfy * foreign key constraints, with savepoint-based rollback for detailed error messages. * * @see packages/server/src/__tests__/helpers/fixture-types.ts for fixture structure * @see packages/server/src/__tests__/helpers/fixture-validation.ts for validation logic */ import type { Client, PoolClient } from 'pg'; import type { Fixture } from './fixture-types.js'; /** * Custom error for fixture insertion failures * * Provides context about which section of the fixture failed to insert * and includes the underlying database error. */ export declare class FixtureInsertionError extends Error { readonly section: string; readonly originalError: Error; readonly context?: Record<string, unknown> | undefined; constructor(section: string, originalError: Error, context?: Record<string, unknown> | undefined); toJSON(): { name: string; message: string; section: string; originalError: { name: string; message: string; }; context: Record<string, unknown> | undefined; }; } /** * ID mapping result from fixture insertion * * Maps logical IDs from the fixture to actual database-generated IDs. * Currently, factories generate UUIDs directly, so this is mostly a pass-through, * but the infrastructure is in place for future auto-generated IDs. */ export type FixtureIdMapping = Map<string, string>; /** * Insert a complete fixture into the database * * Performs ordered insertion of all fixture entities with savepoint-based * error handling for clear diagnostics. Insertion order ensures foreign key * constraints are satisfied: * * 1. Businesses (financial entities) * 2. Tax categories (financial entities) * 3. Financial accounts (references businesses) * 4. Charges (references businesses and tax categories) * 5. Transactions (references charges, accounts, businesses) * 6. Documents (references charges and businesses) * * Each section is wrapped in a SAVEPOINT so that partial failures can be * rolled back to a known state with clear error context. * * **Transaction Handling:** * - Must be called within an existing transaction (client has active BEGIN) * - Creates savepoints for each section (SAVEPOINT section_name) * - On section error, rolls back to savepoint (ROLLBACK TO SAVEPOINT section_name) * - Does NOT commit or rollback the outer transaction * * **Validation:** * - Validates fixture before any insertion (assertValidFixture) * - Checks referential integrity (charge IDs, business IDs, etc.) * - Validates required fields * * @param client - PostgreSQL client (PoolClient or standalone Client) within an active transaction * @param fixture - Complete fixture to insert * @returns Promise resolving to ID mapping (fixture ID → database ID) * @throws {Error} If fixture validation fails (via assertValidFixture) * @throws {FixtureInsertionError} If any insertion section fails * * @remarks * Type Safety: Accepts both PoolClient and Client to support both test transactions * (pool.connect()) and standalone connections (new pg.Client()) used in seed scripts. * * @example * ```typescript * import { withTestTransaction } from './test-transaction.js'; * import { insertFixture } from './fixture-loader.js'; * import { expenseScenarioA } from '../fixtures/expenses/expense-scenario-a.js'; * * it('should insert expense scenario', () => * withTestTransaction(pool, async (client) => { * const idMap = await insertFixture(client, expenseScenarioA); * * // Verify insertion * const result = await client.query( * 'SELECT * FROM accounter_schema.charges WHERE id = $1', * [expenseScenarioA.charges!.charges[0].id!] * ); * expect(result.rows).toHaveLength(1); * }) * ); * ``` */ export declare function insertFixture(client: PoolClient | Client, fixture: Fixture, adminBusinessId?: string): Promise<FixtureIdMapping>;