Skip to content

Commit

Permalink
Override knexfile options with CLI options (#4047)
Browse files Browse the repository at this point in the history
Co-authored-by: Olivier Cavadenti <olivier.cavadenti@gmail.com>
  • Loading branch information
KoryNunn and OlivierCavadenti committed Mar 30, 2022
1 parent 93f94d6 commit 0232bec
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 32 deletions.
27 changes: 16 additions & 11 deletions bin/cli.js
@@ -1,5 +1,6 @@
#!/usr/bin/env node
const rechoir = require('rechoir');
const merge = require('lodash/merge');
const interpret = require('interpret');
const resolveFrom = require('resolve-from');
const path = require('path');
Expand All @@ -9,6 +10,7 @@ const color = require('colorette');
const argv = require('getopts')(process.argv.slice(2));
const cliPkg = require('../package');
const {
parseConfigObj,
mkConfigObj,
resolveEnvironmentConfig,
exit,
Expand Down Expand Up @@ -59,8 +61,17 @@ async function initKnex(env, opts) {
env.configuration,
env.configPath
);

const optionsConfig = parseConfigObj(opts);
const config = merge(resolvedConfig, optionsConfig);

// Migrations directory gets defaulted if it is undefined.
if (!env.configPath && !config.migrations.directory) {
config.migrations.directory = null;
}

const knex = require(env.modulePath);
return knex(resolvedConfig);
return knex(config);
}

function invoke() {
Expand Down Expand Up @@ -138,16 +149,10 @@ function invoke() {
.option('--knexfile [path]', 'Specify the knexfile path.')
.option('--knexpath [path]', 'Specify the path to knex instance.')
.option('--cwd [path]', 'Specify the working directory.')
.option('--client [name]', 'Set DB client without a knexfile.')
.option('--connection [address]', 'Set DB connection without a knexfile.')
.option(
'--migrations-directory [path]',
'Set migrations directory without a knexfile.'
)
.option(
'--migrations-table-name [path]',
'Set migrations table name without a knexfile.'
)
.option('--client [name]', 'Set DB client.')
.option('--connection [address]', 'Set DB connection.')
.option('--migrations-directory [path]', 'Set migrations directory.')
.option('--migrations-table-name [path]', 'Set migrations table name.')
.option(
'--env [name]',
'environment, default: process.env.NODE_ENV || development'
Expand Down
40 changes: 33 additions & 7 deletions bin/utils/cli-config-utils.js
@@ -1,12 +1,39 @@
const { DEFAULT_EXT, DEFAULT_TABLE_NAME } = require('./constants');
const { resolveClientNameWithAliases } = require('../../lib/util/helpers');
const fs = require('fs');
const path = require('path');
const escalade = require('escalade/sync');
const tildify = require('tildify');
const color = require('colorette');
const argv = require('getopts')(process.argv.slice(2));

function findCaseInsensitiveProperty(propertyName, object) {
return Object.keys(object).find(
(key) => key.toLowerCase() === propertyName.toLowerCase()
);
}

function parseConfigObj(opts) {
const config = { migrations: {} };

if (opts.client) {
config.client = opts.client;
}

if (opts.connection) {
config.connection = opts.connection;
}

if (opts.migrationsDirectory) {
config.migrations.directory = opts.migrationsDirectory;
}

if (opts.migrationsTableName) {
config.migrations.tableName = opts.migrationsTableName;
}

return config;
}

function mkConfigObj(opts) {
if (!opts.client) {
throw new Error(
Expand All @@ -17,16 +44,14 @@ function mkConfigObj(opts) {
const envName = opts.env || process.env.NODE_ENV || 'development';
const resolvedClientName = resolveClientNameWithAliases(opts.client);
const useNullAsDefault = resolvedClientName === 'sqlite3';
const parsedConfig = parseConfigObj(opts);

return {
ext: DEFAULT_EXT,
[envName]: {
...parsedConfig,
useNullAsDefault,
client: opts.client,
connection: opts.connection,
migrations: {
directory: opts.migrationsDirectory,
tableName: opts.migrationsTableName || DEFAULT_TABLE_NAME,
},
tableName: parsedConfig.tableName || DEFAULT_TABLE_NAME,
},
};
}
Expand Down Expand Up @@ -174,6 +199,7 @@ function findUpConfig(cwd, name, extensions) {
}

module.exports = {
parseConfigObj,
mkConfigObj,
resolveEnvironmentConfig,
exit,
Expand Down
10 changes: 10 additions & 0 deletions test/cli/cli-test-utils.js
Expand Up @@ -75,10 +75,20 @@ function setupFileHelper() {
return fileHelper;
}

function createTable(db, ddl) {
return new Promise((resolve, reject) =>
db.exec(`create TABLE if not exists ${ddl};`, (err) => {
if (err) reject(err);
else resolve();
})
);
}

module.exports = {
expectContentMatchesStub,
getRootDir,
migrationStubOptionSetup,
seedStubOptionSetup,
setupFileHelper,
createTable,
};
10 changes: 1 addition & 9 deletions test/cli/esm-interop.spec.js
Expand Up @@ -5,6 +5,7 @@ const fs = require('fs');
const { execCommand } = require('cli-testlab');
const sqlite3 = require('@vscode/sqlite3');
const semver = require('semver');
const { createTable } = require('./cli-test-utils');
const KNEX = path.normalize(__dirname + '/../../bin/cli.js');
const TEST_BASE = '../test/jake-util';

Expand Down Expand Up @@ -734,15 +735,6 @@ describe('esm interop and mjs support', () => {
}
});

function createTable(db, ddl) {
return new Promise((resolve, reject) =>
db.exec(`create TABLE if not exists ${ddl};`, (err) => {
if (err) reject(err);
else resolve();
})
);
}

function getSchema(db) {
return new Promise((resolve, reject) => {
db.all('SELECT name from SQLITE_MASTER', (err, rows) => {
Expand Down
10 changes: 5 additions & 5 deletions test/cli/migrate-make.spec.js
Expand Up @@ -124,7 +124,7 @@ module.exports = {
migrations: {
directory: __dirname + '/test/jake-util/knexfile_migrations',
},
};
};
`,
{ isPathAbsolute: true }
);
Expand Down Expand Up @@ -152,7 +152,7 @@ module.exports = {
migrations: {
directory: __dirname + '/test/jake-util/knexfile_migrations',
},
};
};
`,
{ isPathAbsolute: true }
);
Expand Down Expand Up @@ -187,7 +187,7 @@ module.exports = {
directory: __dirname + '/test/jake-util/knexfile_migrations',
}
}
};
};
`,
{ isPathAbsolute: true }
);
Expand Down Expand Up @@ -237,7 +237,7 @@ module.exports = {
extension: 'ts',
directory: __dirname + '/test/jake-util/knexfile_migrations',
},
};
};
`,
{ isPathAbsolute: true }
);
Expand Down Expand Up @@ -272,7 +272,7 @@ development: {
directory: __dirname + '/test/jake-util/knexfile_migrations',
},
}
};
};
`,
{ isPathAbsolute: true }
);
Expand Down
51 changes: 51 additions & 0 deletions test/cli/migrate.spec.js
Expand Up @@ -56,4 +56,55 @@ describe('migrate:latest', () => {
expect(row.name).to.equal('000_create_rule_table.js');
db.close();
});

it('CLI Options override knexfile', async () => {
const path = process.cwd() + '/knexfile.js';
fileHelper.createFile(
path,
`
module.exports = {
client: 'sqlite3',
connection: {
filename: '${dbPath}',
},
migrations: {
directory: __dirname + '/test//jake-util/knexfile_migrations',
},
};
`,
{ isPathAbsolute: true }
);

fileHelper.createFile(
'migrations/subdirectory/000_create_rule_table.js',
`
exports.up = (knex)=> knex.schema.createTable('rules', (table)=> {
table.string('name');
});
exports.down = (knex)=> knex.schema.dropTable('rules');
`,
{ willBeCleanedUp: true, isPathAbsolute: false }
);

expect(fileHelper.fileExists(dbPath)).to.equal(false);

await execCommand(`node ${KNEX} migrate:latest \
--knexpath=../knexfile.js \
--migrations-directory=${rootDir}/migrations/subdirectory/ \
--migrations-table-name=migration_table \
create_rule_table`);
expect(fileHelper.fileExists(dbPath)).to.equal(true);

const db = await new sqlite3.Database(dbPath);
const row = await new Promise((resolve, reject) => {
db.get('SELECT name FROM migration_table', {}, (err, row) => {
if (err) {
reject(err);
}
resolve(row);
});
});
expect(row.name).to.equal('000_create_rule_table.js');
db.close();
});
});

0 comments on commit 0232bec

Please sign in to comment.