From 41d02ba5c1a3cde7eebb9442e30d4a75abe2df34 Mon Sep 17 00:00:00 2001 From: Florent Vilmart <364568+flovilmart@users.noreply.github.com> Date: Tue, 24 Mar 2020 12:07:05 -0400 Subject: [PATCH] CLI: adds support for asynchronous knexfile loading (#3748) --- bin/cli.js | 35 ++++++++++++--------- test/cli/knexfile-test.spec.js | 27 ++++++++++++++++ test/cli/seed.spec.js | 10 ++++++ test/jake-util/knexfile/knexfile_async.js | 12 +++++++ test/jake-util/knexfile/knexfile_func.js | 12 +++++++ test/jake-util/knexfile/knexfile_promise.js | 12 +++++++ test/jake-util/seeds-knexfile-async.js | 9 ++++++ 7 files changed, 102 insertions(+), 15 deletions(-) create mode 100644 test/jake-util/knexfile/knexfile_async.js create mode 100644 test/jake-util/knexfile/knexfile_func.js create mode 100644 test/jake-util/knexfile/knexfile_promise.js create mode 100644 test/jake-util/seeds-knexfile-async.js diff --git a/bin/cli.js b/bin/cli.js index be0403ab71..0669942b50 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -22,8 +22,11 @@ const { readFile, writeFile } = require('./../lib/util/fs'); const { listMigrations } = require('./utils/migrationsLister'); -function openKnexfile(configPath) { - const config = require(configPath); +async function openKnexfile(configPath) { + let config = require(configPath); + if (typeof config === 'function') { + config = await config(); + } // FYI: By default, the extension for the migration files is inferred // from the knexfile's extension. So, the following lines are in @@ -33,7 +36,7 @@ function openKnexfile(configPath) { return config; } -function initKnex(env, opts) { +async function initKnex(env, opts) { checkLocalModule(env); if (process.cwd() !== env.cwd) { process.chdir(env.cwd); @@ -49,7 +52,7 @@ function initKnex(env, opts) { } env.configuration = env.configPath - ? openKnexfile(env.configPath) + ? await openKnexfile(env.configPath) : mkConfigObj(opts); const resolvedConfig = resolveEnvironmentConfig(opts, env.configuration); @@ -138,10 +141,10 @@ function invoke(env) { `--stub [|]`, 'Specify the migration stub to use. If using the file must be located in config.migrations.directory' ) - .action((name) => { + .action(async (name) => { const opts = commander.opts(); opts.client = opts.client || 'sqlite3'; // We don't really care about client when creating migrations - const instance = initKnex(env, opts); + const instance = await initKnex(env, opts); const ext = getMigrationExtension(env, opts); const configOverrides = { extension: ext }; @@ -164,7 +167,7 @@ function invoke(env) { .option('--verbose', 'verbose') .action(() => { pending = initKnex(env, commander.opts()) - .migrate.latest() + .then((instance) => instance.migrate.latest()) .then(([batchNo, log]) => { if (log.length === 0) { success(color.cyan('Already up to date')); @@ -184,7 +187,7 @@ function invoke(env) { ) .action((name) => { pending = initKnex(env, commander.opts()) - .migrate.up({ name }) + .then((instance) => instance.migrate.up({ name })) .then(([batchNo, log]) => { if (log.length === 0) { success(color.cyan('Already up to date')); @@ -210,7 +213,7 @@ function invoke(env) { const { all } = cmd; pending = initKnex(env, commander.opts()) - .migrate.rollback(null, all) + .then((instance) => instance.migrate.rollback(null, all)) .then(([batchNo, log]) => { if (log.length === 0) { success(color.cyan('Already at the base migration')); @@ -231,7 +234,7 @@ function invoke(env) { ) .action((name) => { pending = initKnex(env, commander.opts()) - .migrate.down({ name }) + .then((instance) => instance.migrate.down({ name })) .then(([batchNo, log]) => { if (log.length === 0) { success(color.cyan('Already at the base migration')); @@ -253,7 +256,7 @@ function invoke(env) { .description(' View the current version for the migration.') .action(() => { pending = initKnex(env, commander.opts()) - .migrate.currentVersion() + .then((instance) => instance.migrate.currentVersion()) .then((version) => { success(color.green('Current Version: ') + color.blue(version)); }) @@ -266,7 +269,9 @@ function invoke(env) { .description(' List all migrations files with status.') .action(() => { pending = initKnex(env, commander.opts()) - .migrate.list() + .then((instance) => { + return instance.migrate.list(); + }) .then(([completed, newMigrations]) => { listMigrations(completed, newMigrations); }) @@ -284,10 +289,10 @@ function invoke(env) { `--stub [|]`, 'Specify the seed stub to use. If using the file must be located in config.seeds.directory' ) - .action((name) => { + .action(async (name) => { const opts = commander.opts(); opts.client = opts.client || 'sqlite3'; // We don't really care about client when creating seeds - const instance = initKnex(env, opts); + const instance = await initKnex(env, opts); const ext = getSeedExtension(env, opts); const configOverrides = { extension: ext }; const stub = getStubPath('seeds', env, opts); @@ -310,7 +315,7 @@ function invoke(env) { .option('--specific', 'run specific seed file') .action(() => { pending = initKnex(env, commander.opts()) - .seed.run({ specific: argv.specific }) + .then((instance) => instance.seed.run({ specific: argv.specific })) .then(([log]) => { if (log.length === 0) { success(color.cyan('No seed files exist')); diff --git a/test/cli/knexfile-test.spec.js b/test/cli/knexfile-test.spec.js index 159e94d088..cd8b48c126 100644 --- a/test/cli/knexfile-test.spec.js +++ b/test/cli/knexfile-test.spec.js @@ -65,6 +65,33 @@ module.exports = { ); }); + it('Run migrations with knexfile returning function passed', () => { + return execCommand( + `node ${KNEX} migrate:latest --knexfile=test/jake-util/knexfile/knexfile_func.js --knexpath=../knex.js`, + { + expectedOutput: 'Batch 1 run: 1 migrations', + } + ); + }); + + it('Run migrations with knexfile with async passed', () => { + return execCommand( + `node ${KNEX} migrate:latest --knexfile=test/jake-util/knexfile/knexfile_async.js --knexpath=../knex.js`, + { + expectedOutput: 'Batch 1 run: 1 migrations', + } + ); + }); + + it('Run migrations with knexfile with promise passed', () => { + return execCommand( + `node ${KNEX} migrate:latest --knexfile=test/jake-util/knexfile/knexfile_promise.js --knexpath=../knex.js`, + { + expectedOutput: 'Batch 1 run: 1 migrations', + } + ); + }); + it("changes the process's cwd to the directory that contains the knexfile", () => { const knexfile = 'test/jake-util/knexfile-relative/knexfile.js'; const expectedCWD = tildify(path.resolve(path.dirname(knexfile))); diff --git a/test/cli/seed.spec.js b/test/cli/seed.spec.js index cd8ea63c7e..dd46c03365 100644 --- a/test/cli/seed.spec.js +++ b/test/cli/seed.spec.js @@ -20,6 +20,16 @@ describe('seed:run', () => { ); }); + it('supports async configuration', () => { + return execCommand( + `node ${KNEX} seed:run --knexfile=test/jake-util/seeds-knexfile-async.js`, + { + expectedOutput: 'Ran 2 seed files', + notExpectedOutput: ['first.js', 'second.js'], + } + ); + }); + it('prints verbose logs', () => { return execCommand( `node ${KNEX} seed:run --knexfile=test/jake-util/seeds-knexfile.js --verbose`, diff --git a/test/jake-util/knexfile/knexfile_async.js b/test/jake-util/knexfile/knexfile_async.js new file mode 100644 index 0000000000..a4481b03be --- /dev/null +++ b/test/jake-util/knexfile/knexfile_async.js @@ -0,0 +1,12 @@ +module.exports = async () => ({ + client: 'sqlite3', + connection: { + filename: __dirname + '/../test.sqlite3', + }, + migrations: { + directory: __dirname + '/../knexfile_migrations', + }, + seeds: { + directory: __dirname + '/../knexfile_seeds', + }, +}); diff --git a/test/jake-util/knexfile/knexfile_func.js b/test/jake-util/knexfile/knexfile_func.js new file mode 100644 index 0000000000..14bd1d3379 --- /dev/null +++ b/test/jake-util/knexfile/knexfile_func.js @@ -0,0 +1,12 @@ +module.exports = () => ({ + client: 'sqlite3', + connection: { + filename: __dirname + '/../test.sqlite3', + }, + migrations: { + directory: __dirname + '/../knexfile_migrations', + }, + seeds: { + directory: __dirname + '/../knexfile_seeds', + }, +}); diff --git a/test/jake-util/knexfile/knexfile_promise.js b/test/jake-util/knexfile/knexfile_promise.js new file mode 100644 index 0000000000..36c7314f67 --- /dev/null +++ b/test/jake-util/knexfile/knexfile_promise.js @@ -0,0 +1,12 @@ +module.exports = Promise.resolve({ + client: 'sqlite3', + connection: { + filename: __dirname + '/../test.sqlite3', + }, + migrations: { + directory: __dirname + '/../knexfile_migrations', + }, + seeds: { + directory: __dirname + '/../knexfile_seeds', + }, +}); diff --git a/test/jake-util/seeds-knexfile-async.js b/test/jake-util/seeds-knexfile-async.js new file mode 100644 index 0000000000..a104ac53a2 --- /dev/null +++ b/test/jake-util/seeds-knexfile-async.js @@ -0,0 +1,9 @@ +module.exports = async () => ({ + client: 'sqlite3', + connection: { + filename: __dirname + '/../test.sqlite3', + }, + seeds: { + directory: __dirname + '/seeds', + }, +});