UNPKG

@accounter/server

Version:
75 lines (67 loc) 2.16 kB
import { type Client, Pool, type PoolClient } from 'pg'; import { LATEST_MIGRATION_NAME } from '../../../../migrations/src/run-pg-migrations.js'; export { LATEST_MIGRATION_NAME }; interface MigrationCheckResult { isLatest: boolean; latestMigrationName: string | undefined; errorMessage?: string; } /** * Check if the latest migration has been applied to the database. * Returns result object with status - does not throw. */ export async function checkLatestMigration( clientOrPool: Pool | PoolClient | Client, schema = 'accounter_schema', ): Promise<MigrationCheckResult> { let client: PoolClient | Client; let shouldRelease = false; if (clientOrPool instanceof Pool) { const poolClient = await clientOrPool.connect(); client = poolClient; shouldRelease = true; } else { // It's already a Client or PoolClient client = clientOrPool; } try { const result = await client.query( `SELECT 1 FROM ${schema}.migration WHERE name = $1 LIMIT 1`, [LATEST_MIGRATION_NAME], ); const isLatest = result.rowCount === 1; return { isLatest, latestMigrationName: LATEST_MIGRATION_NAME, errorMessage: isLatest ? undefined : `Latest migration "${LATEST_MIGRATION_NAME}" not found in database`, }; } catch (error) { return { isLatest: false, latestMigrationName: LATEST_MIGRATION_NAME, errorMessage: `Failed to check migrations: ${error instanceof Error ? error.message : String(error)}`, }; } finally { if (shouldRelease && 'release' in client) { await client.release(); } } } /** * Assert that the latest migration has been applied. * Throws an error with helpful message if not. */ export async function assertLatestMigrationApplied( clientOrPool: Pool | PoolClient | Client, schema = 'accounter_schema', ): Promise<void> { const result = await checkLatestMigration(clientOrPool, schema); if (!result.isLatest) { throw new Error( result.errorMessage || `Migration check failed for ${result.latestMigrationName}. Run: yarn workspace @accounter/migrations migration:run`, ); } }