Skip to content

Commit

Permalink
Extract MigrationGenerator from Migrator (knex#2786)
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeGinnivan authored and elhigu committed Sep 17, 2018
1 parent f01d5fa commit d0e3be4
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 85 deletions.
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
root = true

[*]
end_of_line = lf
indent_style = space
indent_size = 2
97 changes: 97 additions & 0 deletions src/migrate/MigrationGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import fs from 'fs';
import path from 'path';
import mkdirp from 'mkdirp';
import Promise from 'bluebird';
import { template } from 'lodash';
import { getMergedConfig } from './Migrator';

export default class MigrationGenerator {
constructor(migrationConfig) {
this.config = getMergedConfig(migrationConfig);
}

// Creates a new migration, with a given name.
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));
}

// Ensures a folder for the migrations exist, dependent on the migration
// config settings.
_ensureFolder() {
const dirs = this._absoluteConfigDirs();

const promises = dirs.map((dir) => {
return Promise.promisify(fs.stat, { context: fs })(dir).catch(() =>
Promise.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 ||
path.join(__dirname, 'stub', this.config.extension + '.stub');

return Promise.promisify(fs.readFile, { context: fs })(stubPath).then(
(stub) => template(stub.toString(), { variable: 'd' })
);
}

// 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;
const dirs = this._absoluteConfigDirs();
const dir = dirs.slice(-1)[0]; // Get last specified directory

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

return Promise.promisify(fs.writeFile, { context: fs })(
path.join(dir, filename),
tmpl(config.variables || {})
).return(path.join(dir, filename));
}

_absoluteConfigDirs() {
const directories = Array.isArray(this.config.directory)
? this.config.directory
: [this.config.directory];
return directories.map((directory) => {
return path.resolve(process.cwd(), directory);
});
}
}

// Ensure that we have 2 places for each of the date segments.
function padDate(segment) {
segment = segment.toString();
return segment[1] ? segment : `0${segment}`;
}

// Get a date object in the correct format, without requiring a full out library
// like "moment.js".
function yyyymmddhhmmss() {
const d = new Date();
return (
d.getFullYear().toString() +
padDate(d.getMonth() + 1) +
padDate(d.getDate()) +
padDate(d.getHours()) +
padDate(d.getMinutes()) +
padDate(d.getSeconds())
);
}
88 changes: 3 additions & 85 deletions src/migrate/Migrator.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// Migrator
// -------
import fs from 'fs';
import path from 'path';
import mkdirp from 'mkdirp';
import Promise from 'bluebird';
import {
assign,
Expand All @@ -14,7 +11,6 @@ import {
isEmpty,
isUndefined,
max,
template,
} from 'lodash';
import inherits from 'inherits';
import {
Expand All @@ -26,6 +22,7 @@ import {
import { getSchemaBuilder } from './table-creator';
import * as migrationListResolver from './migration-list-resolver';
import FsMigrations, { DEFAULT_LOAD_EXTENSIONS } from './sources/fs-migrations';
import MigrationGenerator from './MigrationGenerator';

function LockError(msg) {
this.name = 'MigrationLocked';
Expand All @@ -51,6 +48,7 @@ export default class Migrator {
constructor(knex) {
this.knex = knex;
this.config = getMergedConfig(knex.client.config.migrations);
this.generator = new MigrationGenerator(knex.client.config.migrations);

this._activeMigration = {
fileName: null,
Expand Down Expand Up @@ -145,30 +143,7 @@ export default class Migrator {
// Creates a new migration, with a given name.
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));
}

// Ensures a folder for the migrations exist, dependent on the migration
// config settings.
_ensureFolder() {
const dirs = this._absoluteConfigDirs();

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

return Promise.all(promises);
return this.generator.make(name, this.config);
}

_isLocked(trx) {
Expand Down Expand Up @@ -305,33 +280,6 @@ export default class Migrator {
return migration;
}

// Generates the stub template for the current migration, returning a compiled
// template.
_generateStubTemplate() {
const stubPath =
this.config.stub ||
path.join(__dirname, 'stub', this.config.extension + '.stub');
return Promise.promisify(fs.readFile, { context: fs })(stubPath).then(
(stub) => template(stub.toString(), { variable: 'd' })
);
}

// 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;
const dirs = this._absoluteConfigDirs();
const dir = dirs.slice(-1)[0]; // Get last specified directory

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

return Promise.promisify(fs.writeFile, { context: fs })(
path.join(dir, filename),
tmpl(config.variables || {})
).return(path.join(dir, filename));
}

// Get the last batch of migrations, by name, ordered by insert id in reverse
// order.
_getLastBatch([allMigrations]) {
Expand Down Expand Up @@ -433,16 +381,6 @@ export default class Migrator {
);
});
}

/** Returns */
_absoluteConfigDirs() {
const directories = Array.isArray(this.config.directory)
? this.config.directory
: [this.config.directory];
return directories.map((directory) => {
return path.resolve(process.cwd(), directory);
});
}
}

export function getMergedConfig(config, currentConfig) {
Expand Down Expand Up @@ -510,23 +448,3 @@ function warnPromise(knex, value, name, fn) {
}
return value;
}

// Ensure that we have 2 places for each of the date segments.
function padDate(segment) {
segment = segment.toString();
return segment[1] ? segment : `0${segment}`;
}

// Get a date object in the correct format, without requiring a full out library
// like "moment.js".
function yyyymmddhhmmss() {
const d = new Date();
return (
d.getFullYear().toString() +
padDate(d.getMonth() + 1) +
padDate(d.getDate()) +
padDate(d.getHours()) +
padDate(d.getMinutes()) +
padDate(d.getSeconds())
);
}

0 comments on commit d0e3be4

Please sign in to comment.