From 8dadfe9a5b86635e6b4abc1323f4df30f5e3c237 Mon Sep 17 00:00:00 2001 From: Joakim Carlstein Date: Thu, 16 Nov 2023 11:24:00 +0100 Subject: [PATCH] feat(cli): support NodeJS callback style migration functions --- .changeset/blue-steaks-hide.md | 5 +++++ README.md | 1 + packages/cli/src/plugin-loader-js.ts | 22 +++++++++++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 .changeset/blue-steaks-hide.md diff --git a/.changeset/blue-steaks-hide.md b/.changeset/blue-steaks-hide.md new file mode 100644 index 0000000..00e89e8 --- /dev/null +++ b/.changeset/blue-steaks-hide.md @@ -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) diff --git a/README.md b/README.md index e6d277f..7a7c877 100644 --- a/README.md +++ b/README.md @@ -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 - Supports any file type for your migration files - 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) - Easy to debug - Emigrate will store any errors that occur during migration in the migration history so you can easily debug them diff --git a/packages/cli/src/plugin-loader-js.ts b/packages/cli/src/plugin-loader-js.ts index f8f5e62..45cff1c 100644 --- a/packages/cli/src/plugin-loader-js.ts +++ b/packages/cli/src/plugin-loader-js.ts @@ -1,5 +1,21 @@ +import { promisify } from 'node:util'; import { type LoaderPlugin } from '@emigrate/plugin-tools/types'; +// eslint-disable-next-line @typescript-eslint/ban-types +const promisifyIfNeeded = (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 = { loadableExtensions: ['.js', '.cjs', '.mjs'], async loadMigration(migration) { @@ -7,7 +23,7 @@ const loaderJs: LoaderPlugin = { if (typeof migrationModule === 'function') { return async () => { - await migrationModule(); + await promisifyIfNeeded(migrationModule)(); }; } @@ -19,7 +35,7 @@ const loaderJs: LoaderPlugin = { ) { const migrationFunction = migrationModule.default; return async () => { - await migrationFunction(); + await promisifyIfNeeded(migrationFunction)(); }; } @@ -31,7 +47,7 @@ const loaderJs: LoaderPlugin = { ) { const migrationFunction = migrationModule.up; return async () => { - await migrationFunction(); + await promisifyIfNeeded(migrationFunction)(); }; }