UNPKG

@dossierhq/sqlite-core

Version:

A library used by concrete SQLite adapters for Dossier.

84 lines 3.64 kB
/// <reference types="./SchemaMigrator.d.ts" /> import { notOk, ok } from '@dossierhq/core'; import { queryOne, queryRun } from './QueryFunctions.js'; export async function getCurrentSchemaVersion(database, context) { const result = await queryOne(database, context, 'PRAGMA user_version'); if (result.isError()) return result; const { user_version: version } = result.value; return ok(version); } /** Migrates the database to the latest version. * * The latest version is determined by `schemaVersionGenerator` returning null. The migration of * each version is run in a transaction. */ export async function migrate(database, context, schemaVersionGenerator) { const { logger } = context; const initialVersionResult = await getCurrentSchemaVersion(database, context); if (initialVersionResult.isError()) return initialVersionResult; const initialVersion = initialVersionResult.value; let version = initialVersion + 1; let done = false; while (!done) { const plan = schemaVersionGenerator(version); if (!plan) { done = true; break; } const migrateVersionResult = await migrateVersion(database, context, version, plan); if (migrateVersionResult.isError()) { logger.error(`Failed to migrate database schema to version=${version} (initial version=${initialVersion})`); return migrateVersionResult; } version += 1; } if (version !== initialVersion + 1) { logger.info(`Finished migration of database schema from version ${initialVersion} to ${version - 1}`); } return ok(undefined); } async function migrateVersion(database, context, version, plan) { if (plan.temporarilyDisableForeignKeys) { const disableForeignKeysResult = await queryRun(database, context, 'PRAGMA foreign_keys=OFF'); if (disableForeignKeysResult.isError()) return disableForeignKeysResult; } const transactionResult = await context.withTransaction(async (context) => { for (const query of plan.queries) { if (typeof query === 'function') { const queryResult = await query(database, context); if (queryResult.isError()) return queryResult; } else { const queryResult = await queryRun(database, context, query); if (queryResult.isError()) return queryResult; } } if (plan.temporarilyDisableForeignKeys) { const checkForeignKeysResult = await queryRun(database, context, 'PRAGMA foreign_key_check'); if (checkForeignKeysResult.isError()) return checkForeignKeysResult; } // PRAGMA can't use values, so create query manually. No SQL injection since we know it's a number if (typeof version !== 'number') { return notOk.Generic(`version is for some reason NaN (${version})`); } const updateVersionResult = await queryRun(database, context, 'PRAGMA user_version=' + version); if (updateVersionResult.isError()) return updateVersionResult; return ok(undefined); }); if (transactionResult.isError()) return transactionResult; if (plan.temporarilyDisableForeignKeys) { const enableForeignKeysResult = await queryRun(database, context, 'PRAGMA foreign_keys=ON'); if (enableForeignKeysResult.isError()) return enableForeignKeysResult; } return ok(undefined); } //# sourceMappingURL=SchemaMigrator.js.map