feat(cli): support NodeJS callback style migration functions

This commit is contained in:
Joakim Carlstein 2023-11-16 11:24:00 +01:00
parent 0c49249bd9
commit 8dadfe9a5b
3 changed files with 25 additions and 3 deletions

View file

@ -0,0 +1,5 @@
---
'@emigrate/cli': minor
---
Support migration functions using the old NodeJS callback style API, i.e. accepting a callback as a single parameter which in turns takes any error as its first parameter (any other parameters are ignored)

View file

@ -17,6 +17,7 @@ It's effectively a successor of [klei-migrate](https://www.npmjs.com/package/kle
- Emigrate makes sure the migration history does not get stuck in a locked state if that's the case - Emigrate makes sure the migration history does not get stuck in a locked state if that's the case
- Supports any file type for your migration files - Supports any file type for your migration files
- You can easily write migrations in JavaScript, TypeScript or plain SQL (or any other language) - You can easily write migrations in JavaScript, TypeScript or plain SQL (or any other language)
- JavaScript migration files written using CommonJS or ES modules (ESM) are supported out of the box
- You can customize the template for your migration files to fit your needs (or use a plugin to do it for you) - You can customize the template for your migration files to fit your needs (or use a plugin to do it for you)
- Easy to debug - Easy to debug
- Emigrate will store any errors that occur during migration in the migration history so you can easily debug them - Emigrate will store any errors that occur during migration in the migration history so you can easily debug them

View file

@ -1,5 +1,21 @@
import { promisify } from 'node:util';
import { type LoaderPlugin } from '@emigrate/plugin-tools/types'; import { type LoaderPlugin } from '@emigrate/plugin-tools/types';
// eslint-disable-next-line @typescript-eslint/ban-types
const promisifyIfNeeded = <T extends Function>(fn: T) => {
if (fn.length === 0) {
return fn;
}
if (fn.length === 1) {
return promisify(fn);
}
throw new Error(
`Unexpected arguments length of migration function, expected 0 or 1 argument but got: ${fn.length} arguments`,
);
};
const loaderJs: LoaderPlugin = { const loaderJs: LoaderPlugin = {
loadableExtensions: ['.js', '.cjs', '.mjs'], loadableExtensions: ['.js', '.cjs', '.mjs'],
async loadMigration(migration) { async loadMigration(migration) {
@ -7,7 +23,7 @@ const loaderJs: LoaderPlugin = {
if (typeof migrationModule === 'function') { if (typeof migrationModule === 'function') {
return async () => { return async () => {
await migrationModule(); await promisifyIfNeeded(migrationModule)();
}; };
} }
@ -19,7 +35,7 @@ const loaderJs: LoaderPlugin = {
) { ) {
const migrationFunction = migrationModule.default; const migrationFunction = migrationModule.default;
return async () => { return async () => {
await migrationFunction(); await promisifyIfNeeded(migrationFunction)();
}; };
} }
@ -31,7 +47,7 @@ const loaderJs: LoaderPlugin = {
) { ) {
const migrationFunction = migrationModule.up; const migrationFunction = migrationModule.up;
return async () => { return async () => {
await migrationFunction(); await promisifyIfNeeded(migrationFunction)();
}; };
} }