Skip to content

Commit

Permalink
Fix some issues around seed and migration generation (#3479)
Browse files Browse the repository at this point in the history
  • Loading branch information
lorefnon authored and kibertoad committed Oct 13, 2019
1 parent 6b9fb0e commit b0c0db6
Show file tree
Hide file tree
Showing 14 changed files with 698 additions and 213 deletions.
23 changes: 15 additions & 8 deletions bin/cli.js
Expand Up @@ -18,9 +18,10 @@ const {
success,
checkLocalModule,
getMigrationExtension,
getSeedExtension,
getStubPath,
} = require('./utils/cli-config-utils');
const { DEFAULT_EXT } = require('./utils/constants');

const { listMigrations } = require('./utils/migrationsLister');

function initKnex(env, opts) {
Expand Down Expand Up @@ -157,7 +158,7 @@ function invoke(env) {
const ext = getMigrationExtension(env, opts);
const configOverrides = { extension: ext };

const stub = getStubPath(env, opts);
const stub = getStubPath('migrations', env, opts);
if (stub) {
configOverrides.stub = stub;
}
Expand Down Expand Up @@ -292,17 +293,23 @@ function invoke(env) {
`-x [${filetypes.join('|')}]`,
'Specify the stub extension (default js)'
)
.option(
`--stub [<relative/path/from/knexfile>|<name>]`,
'Specify the seed stub to use. If using <name> the file must be located in config.seeds.directory'
)
.action((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 ext = (
argv.x ||
env.configuration.ext ||
DEFAULT_EXT
).toLowerCase();
const ext = getSeedExtension(env, opts);
const configOverrides = { extension: ext };
const stub = getStubPath('seeds', env, opts);
if (stub) {
configOverrides.stub = stub;
}

pending = instance.seed
.make(name, { extension: ext })
.make(name, configOverrides)
.then((name) => {
success(color.green(`Created seed file: ${name}`));
})
Expand Down
23 changes: 19 additions & 4 deletions bin/utils/cli-config-utils.js
Expand Up @@ -119,9 +119,23 @@ function getMigrationExtension(env, opts) {
return ext.toLowerCase();
}

function getStubPath(env, opts) {
function getSeedExtension(env, opts) {
const config = resolveEnvironmentConfig(opts, env.configuration);
const stubDirectory = config.migrations && config.migrations.directory;

let ext = DEFAULT_EXT;
if (argv.x) {
ext = argv.x;
} else if (config.seeds && config.seeds.extension) {
ext = config.seeds.extension;
} else if (config.ext) {
ext = config.ext;
}
return ext.toLowerCase();
}

function getStubPath(configKey, env, opts) {
const config = resolveEnvironmentConfig(opts, env.configuration);
const stubDirectory = config[configKey] && config[configKey].directory;

const { stub } = argv;
if (!stub) {
Expand All @@ -131,10 +145,10 @@ function getStubPath(env, opts) {
return stub;
}

// using stub <name> must have config.migrations.directory defined
// using stub <name> must have config[configKey].directory defined
if (!stubDirectory) {
console.log(color.red('Failed to load stub'), color.magenta(stub));
exit('config.migrations.directory in knexfile must be defined');
exit(`config.${configKey}.directory in knexfile must be defined`);
}

return path.join(stubDirectory, stub);
Expand All @@ -147,6 +161,7 @@ module.exports = {
exit,
success,
checkLocalModule,
getSeedExtension,
getMigrationExtension,
getStubPath,
};
60 changes: 29 additions & 31 deletions lib/migrate/MigrationGenerator.js
@@ -1,8 +1,8 @@
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');
const bluebird = require('bluebird');
const { template } = require('lodash');
const {promisify} = require('util');
const { writeJsFileUsingTemplate } = require('../util/template');
const { getMergedConfig } = require('./configuration-merger');

class MigrationGenerator {
Expand All @@ -11,17 +11,16 @@ class MigrationGenerator {
}

// Creates a new migration, with a given name.
make(name, config) {
async make(name, config) {
this.config = getMergedConfig(config, this.config);
if (!name) {
return Promise.reject(
new Error('A name must be specified for the generated migration')
);
}

return this._ensureFolder(config)
.then((val) => this._generateStubTemplate(val))
.then((val) => this._writeNewMigration(name, val));
await this._ensureFolder();
const createdMigrationFilePath = await this._writeNewMigration(name);
return createdMigrationFilePath;
}

// Ensures a folder for the migrations exist, dependent on the migration
Expand All @@ -30,42 +29,41 @@ class MigrationGenerator {
const dirs = this._absoluteConfigDirs();

const promises = dirs.map((dir) => {
return bluebird
.promisify(fs.stat, { context: fs })(dir)
.catch(() => bluebird.promisify(mkdirp)(dir));
return promisify(fs.stat)(dir)
.catch(() => promisify(mkdirp)(dir));
});

return Promise.all(promises);
}

// Generates the stub template for the current migration, returning a compiled
// template.
_generateStubTemplate() {
const stubPath =
this.config.stub ||
_getStubPath() {
return this.config.stub ||
path.join(__dirname, 'stub', this.config.extension + '.stub');
}

return bluebird
.promisify(fs.readFile, { context: fs })(stubPath)
.then((stub) => template(stub.toString(), { variable: 'd' }));
_getNewMigrationName(name) {
if (name[0] === '-') name = name.slice(1);
return yyyymmddhhmmss() + '_' + name + '.' + this.config.extension;
}

// Write a new migration to disk, using the config and generated filename,
// passing any `variables` given in the config to the template.
_writeNewMigration(name, tmpl) {
const { config } = this;
_getNewMigrationPath(name) {
const fileName = this._getNewMigrationName(name);
const dirs = this._absoluteConfigDirs();
const dir = dirs.slice(-1)[0]; // Get last specified directory
return path.join(dir, fileName);
}

if (name[0] === '-') name = name.slice(1);
const filename = yyyymmddhhmmss() + '_' + name + '.' + config.extension;

return bluebird
.promisify(fs.writeFile, { context: fs })(
path.join(dir, filename),
tmpl(config.variables || {})
)
.return(path.join(dir, filename));
// Write a new migration to disk, using the config and generated filename,
// passing any `variables` given in the config to the template.
async _writeNewMigration(name) {
const migrationPath = this._getNewMigrationPath(name);
await writeJsFileUsingTemplate(
migrationPath,
this._getStubPath(),
{ variable: 'd' },
this.config.variables || {}
);
return migrationPath;
}

_absoluteConfigDirs() {
Expand Down

0 comments on commit b0c0db6

Please sign in to comment.