UNPKG

semgrator

Version:

Run migrations code based on semantic version rules

81 lines 2.82 kB
import semver from 'semver'; import { join } from 'node:path'; import { pathToFileURL } from 'node:url'; import { readdir } from 'node:fs/promises'; import rfdc from 'rfdc'; import abstractLogger from 'abstract-logging'; const clone = rfdc(); async function processAll(iterator) { let lastResult; do { const result = await iterator.next(); if (result.done) { return result.value || lastResult; } lastResult = result.value; } while (true); } export async function* loadMigrationsFromPath(path) { const files = (await readdir(path)).filter(file => file.match(/\.(c|m)?js$/)); const migrations = (await Promise.all(files.map(async (file) => { const module = await import(pathToFileURL(join(path, file)).toString()); if (module.migration) { return module.migration; } else if (module.default?.version && typeof module.default?.up === 'function') { return module.default; } }))).filter(migration => !!migration); migrations.sort((a, b) => semver.compare(a.version, b.version)); for (const migration of migrations) { yield migration; } } async function* processMigrations(input, migrations, version, logger) { let result = input; let lastVersion = version; let changed = false; for await (const migration of migrations) { if (semver.gt(migration.version, lastVersion)) { logger.info(`Migrating to version ${migration.version}`); result = await migration.up(clone(result)); lastVersion = migration.toVersion || migration.version; changed = true; } yield { version: lastVersion, result: result, changed }; } } function semgratorWithMigrations(params) { const iterator = processMigrations(params.input, params.migrations, params.version, params.logger || abstractLogger); let processing; return { [Symbol.asyncIterator]() { return iterator; }, then(onFulfilled, onRejected) { if (!processing) { processing = processAll(iterator); } return processing.then(onFulfilled, onRejected); }, }; } export function semgrator(params) { if (typeof params.version !== 'string') { throw new Error(`Invalid version. Must be a string. Got type "${typeof params.version}".`); } if ('path' in params) { return semgratorWithMigrations({ ...params, migrations: loadMigrationsFromPath(params.path), }); } else if ('migrations' in params) { return semgratorWithMigrations(params); } else { throw new Error('Specify either path or migrations'); } } //# sourceMappingURL=semgrator.js.map