From 24017bbde3333a4c858bbf91472e98ae734603c0 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Feb 2018 12:09:40 +0100 Subject: [PATCH 01/16] refactor(files): First write down of the walker and separating file API Refers to #215 Signed-off-by: Tobias Gurtzick --- lib/file.js | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/walker.js | 141 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 295 insertions(+) create mode 100644 lib/file.js create mode 100644 lib/walker.js diff --git a/lib/file.js b/lib/file.js new file mode 100644 index 00000000..b817a128 --- /dev/null +++ b/lib/file.js @@ -0,0 +1,154 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var log = require('db-migrate-shared').log; +var inflection = require('inflection'); +var Promise = require('bluebird'); +var lpad = require('db-migrate-shared').util.lpad; + +function formatPath (dir, name) { + return path.join(dir, name); +} + +function formatName (title, date) { + return formatDate(date) + '-' + formatTitle(title); +} + +function formatDate (date) { + return [ + date.getUTCFullYear(), + lpad(date.getUTCMonth() + 1, '0', 2), + lpad(date.getUTCDate(), '0', 2), + lpad(date.getUTCHours(), '0', 2), + lpad(date.getUTCMinutes(), '0', 2), + lpad(date.getUTCSeconds(), '0', 2) + ].join(''); +} + +function formatTitle (title) { + return inflection.dasherize(title); +} + +function parseDate (name) { + var date = new Date(); + var match = name.match(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-[^.]+/); + date.setUTCFullYear(match[1]); + date.setUTCDate(match[3]); + date.setUTCMonth(match[2] - 1); + date.setUTCHours(match[4]); + date.setUTCMinutes(match[5]); + date.setUTCSeconds(match[6]); + return date; +} + +function parseTitle (name) { + var match = name.match(/\d{14}-([^.]+)/); + var dashed = match[1]; + return inflection.humanize(dashed, true); +} + +var filesRegEx = /\.js$/; + +var File = { + init: function () { + if (arguments.length >= 3) { + this.title = arguments[0]; + this.date = arguments[2]; + this.name = this.formatName(this.title, this.date); + this.path = this.formatPath(arguments[1], this.name); + this.templateType = arguments[3]; + this.internals = arguments[4]; + } else if (arguments.length === 2) { + this.path = arguments[0]; + this.name = this.parseName(this.path); + this.date = this.parseDate(this.name); + this.title = this.parseTitle(this.name); + this.internals = arguments[1]; + } + + this._super(this.internals); + }, + + parseName: function (path) { + var match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); + return match[1]; + }, + + parseTitle: parseTitle, + parseDate: parseDate, + formatTitle: formatTitle, + formatPath: formatPath, + formatName: formatName +}; + +File.registerHook = function (Plugin, prefix, internals) { + var plugin = Plugin.hook(prefix + ':hook:require'); + internals.parser = internals.parser || { + filesRegEx: filesRegEx, + extensions: 'js' + }; + + if (!plugin) { + return Promise.resolve(null); + } + + return Promise.resolve(plugin) + .map(function (plugin) { + return plugin[prefix + ':hook:require'](); + }) + .each(function (parser) { + if (parser && parser.extensions) { + internals.parser.extensions = + internals.parser.extensions + '|' + parser.extensions; + } + }) + .then(function () { + internals.parser.filesRegEx = new RegExp( + '\\.(' + internals.parser.extensions + ')$' + ); + + return internals.parser; + }); +}; + +File.loadFromFileystem = function (dir, type, internals) { + log.verbose('loading ' + type + ' from dir', dir); + + return fs + .readdirAsync(dir) + .filter(function (files) { + return internals.parser.filesRegEx.test(files); + }) + .then(function (files) { + return files.sort(); + }) + .map(function (file) { + return new File(path.join(dir, file), internals); + }); +}; + +File.loadFromDatabase = function (dir, type, loader, internals) { + log.verbose('loading ' + type + ' from database'); + return loader() + .catch(function (err) { + if (internals.dryRun) { + return []; + } else { + return Promise.reject(err); + } + }) + .filter(function (result) { + return ( + result.name.substr(0, result.name.lastIndexOf('/')) === + internals.matching + ); + }) + .map(function (result) { + return new File(path.join(dir, result.name), internals); + }); +}; + +Promise.promisifyAll(fs); + +module.exports = File; diff --git a/lib/walker.js b/lib/walker.js new file mode 100644 index 00000000..ef5ea439 --- /dev/null +++ b/lib/walker.js @@ -0,0 +1,141 @@ +var dbmUtil = require('db-migrate-shared').util; +var log = require('db-migrate-shared').log; +var Promise = require('bluebird'); +var File = require('./file.js'); + +// Not sure what will happen to this yet +function SeedLink(driver, internals) { + this.seeder = require('./seeder.js')( + driver, + internals.argv['vcseeder-dir'], + true, + internals + ); + this.internals = internals; + this.links = []; +} + +var Walker = function(driver, directory, interface, empty, intern) { + this.driver = dbmUtil.reduceToInterface(driver, interface); + this._driver = driver; + this.directory = directory; + this.internals = intern; + + // keep it until we decide how we do the cross linking + if (intern.linked === false) { + this.seedLink = new SeedLink(driver, intern); + intern.linked = true; + } +}; + +Walker.prototype = { + createMigrationsTable: function(callback) { + this._driver.createMigrationsTable(callback); + }, + + writeMigrationRecord: function(migration, callback) { + function onComplete(err) { + if (err) { + log.error(this.prefix + migration.name, err); + } else { + log.info(this.prefix + 'Processed', migration.name); + } + callback(err); + } + this._driver.addMigrationRecord( + this.internals.matching + '/' + migration.name, + onComplete + ); + }, + + deleteMigrationRecord: function(migration, callback) { + function onComplete(err) { + if (err) { + log.error(this.prefix + migration.name, err); + } else { + log.info(this.prefix + 'Processed', migration.name); + } + callback(err); + } + this._driver.deleteMigration( + this.internals.matching + '/' + migration.name, + function(err) { + if (!this.internals.matching) { + this._driver.deleteMigration(migration.name, onComplete); + } else { + onComplete.apply(err); + } + }.bind(this) + ); + }, + + sync: function(options, callback) { + return Migration.loadFromDatabase( + this.directory, + this._driver, + this.internals + ) + .then(completedMigrations => { + var mode = dbmUtil.syncMode( + completedMigrations, + funcOrOpts.destination + ); + if (mode === 1) { + log.info(this.prefix + 'Syncing upwards.'); + return this.up(options); + } else { + log.info(this.prefix + 'Syncing downwards.'); + return this.down(options); + } + }) + .nodeify(callback); + }, + + up: function({ partialName, count }, callback) { + return Promise.all([ + File.loadFromFilesystem(this.directory, this.internals), + File.loadFromDatabase(this.directory, this._driver, this.internals) + ]) + .then(function(allMigrations, completedMigrations) { + var toRun = dbmUtil.filterUp( + allMigrations, + completedMigrations, + partialName, + count + ); + + if (toRun.length === 0) { + log.info(this.prefix + 'Nothing to run'); + } + + return toRun; + }) + .each(function(migration) { + log.verbose(this.prefix + 'preparing to run up:', migration.name); + var version = migration._meta.version || 1; + require('./executors/versioned/v' + version).up(this.driver, migration); + }) + .nodeify(callback); + }, + + down: function({ partialName, count }, callback) { + return File.loadFromDatabase(this.directory, this._driver, this.internals) + .then(completedMigrations => { + let toRun = dbmUtil.filterDown(completedMigrations, partialName, count); + + if (toRun.length === 0) { + log.info(this.prefix + 'Nothing to run'); + } + + return toRun; + }) + .each(migration => { + log.verbose(this.prefix + 'preparing to run down:', migration.name); + let version = migration._meta.version || 1; + require('./executors/versioned/v' + version).up(this.driver, migration); + }) + .nodeify(callback); + } +}; + +module.exports = Walker; From 349fb7b19e9121a3599e406048f17af7736a50c8 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Feb 2018 12:09:40 +0100 Subject: [PATCH 02/16] refactor(files): some more changes to file, walker as well as the start of the port of the version 1 schema. Refers to #215 Signed-off-by: Tobias Gurtzick --- lib/executors/versioned/v1.js | 46 +++++++++++++++++++++++ lib/file.js | 71 ++++++++++++++++++----------------- lib/walker.js | 51 +++++++++++-------------- 3 files changed, 105 insertions(+), 63 deletions(-) create mode 100644 lib/executors/versioned/v1.js diff --git a/lib/executors/versioned/v1.js b/lib/executors/versioned/v1.js new file mode 100644 index 00000000..105bd6c4 --- /dev/null +++ b/lib/executors/versioned/v1.js @@ -0,0 +1,46 @@ +var log = require('db-migrate-shared').log; +var Promise = require('bluebird'); + +const execUnit = { + up: function (context, driver, execUnit) { + return context.driver + .startMigration() + .then(() => { + var setup = execUnit.setup; + + if (typeof setup === 'function') { + setup(context.internals.execUnitOptions, context.seedLink); + } + + return execUnit.up(); + }) + .then(() => { + return Promise.promisify(context.writeexecUnitRecord.bind(context))( + execUnit + ); + }) + .then(context.driver.endMigration.bind(context.driver)); + }, + + down: function (context, driver, execUnit) { + return driver + .startMigration() + .then(() => { + var setup = execUnit.setup; + + if (typeof setup === 'function') { + setup(context.internals.execUnitOptions, context.seedLink); + } + + return execUnit.down(); + }) + .then(() => { + return Promise.promisify(context.deleteexecUnitRecord.bind(context))( + execUnit + ); + }) + .then(context.driver.endMigration.bind(context.driver)); + } +}; + +module.exports = execUnit; diff --git a/lib/file.js b/lib/file.js index b817a128..4255dafc 100644 --- a/lib/file.js +++ b/lib/file.js @@ -1,11 +1,11 @@ 'use strict'; -var fs = require('fs'); -var path = require('path'); -var log = require('db-migrate-shared').log; -var inflection = require('inflection'); -var Promise = require('bluebird'); -var lpad = require('db-migrate-shared').util.lpad; +const fs = require('fs'); +const path = require('path'); +const log = require('db-migrate-shared').log; +const inflection = require('inflection'); +const Promise = require('bluebird'); +const lpad = require('db-migrate-shared').util.lpad; function formatPath (dir, name) { return path.join(dir, name); @@ -31,8 +31,8 @@ function formatTitle (title) { } function parseDate (name) { - var date = new Date(); - var match = name.match(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-[^.]+/); + let date = new Date(); + const match = name.match(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-[^.]+/); date.setUTCFullYear(match[1]); date.setUTCDate(match[3]); date.setUTCMonth(match[2] - 1); @@ -43,38 +43,41 @@ function parseDate (name) { } function parseTitle (name) { - var match = name.match(/\d{14}-([^.]+)/); - var dashed = match[1]; - return inflection.humanize(dashed, true); + const match = name.match(/\d{14}-([^.]+)/); + return inflection.humanize(match[1], true); } -var filesRegEx = /\.js$/; - -var File = { - init: function () { - if (arguments.length >= 3) { - this.title = arguments[0]; - this.date = arguments[2]; - this.name = this.formatName(this.title, this.date); - this.path = this.formatPath(arguments[1], this.name); - this.templateType = arguments[3]; - this.internals = arguments[4]; - } else if (arguments.length === 2) { - this.path = arguments[0]; - this.name = this.parseName(this.path); - this.date = this.parseDate(this.name); - this.title = this.parseTitle(this.name); - this.internals = arguments[1]; - } - - this._super(this.internals); - }, +const filesRegEx = /\.js$/; + +const File = function () { + if (arguments.length >= 3) { + this.title = arguments[0]; + this.date = arguments[2]; + this.name = this.formatName(this.title, this.date); + this.path = this.formatPath(arguments[1], this.name); + this.templateType = arguments[3]; + this.internals = arguments[4]; + } else if (arguments.length === 2) { + this.path = arguments[0]; + this.name = this.parseName(this.path); + this.date = this.parseDate(this.name); + this.title = this.parseTitle(this.name); + this.internals = arguments[1]; + } + + this._super(this.internals); +}; +File.protoype = { parseName: function (path) { - var match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); + const match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); return match[1]; }, + get: function () { + return this._required || (this._required = require(this.path)); + }, + parseTitle: parseTitle, parseDate: parseDate, formatTitle: formatTitle, @@ -83,7 +86,7 @@ var File = { }; File.registerHook = function (Plugin, prefix, internals) { - var plugin = Plugin.hook(prefix + ':hook:require'); + const plugin = Plugin.hook(prefix + ':hook:require'); internals.parser = internals.parser || { filesRegEx: filesRegEx, extensions: 'js' diff --git a/lib/walker.js b/lib/walker.js index ef5ea439..b4406188 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -1,7 +1,7 @@ -var dbmUtil = require('db-migrate-shared').util; -var log = require('db-migrate-shared').log; -var Promise = require('bluebird'); -var File = require('./file.js'); +const dbmUtil = require('db-migrate-shared').util; +const log = require('db-migrate-shared').log; +const Promise = require('bluebird'); +const File = require('./file.js'); // Not sure what will happen to this yet function SeedLink(driver, internals) { @@ -15,7 +15,7 @@ function SeedLink(driver, internals) { this.links = []; } -var Walker = function(driver, directory, interface, empty, intern) { +const Walker = function(driver, directory, interface, empty, intern) { this.driver = dbmUtil.reduceToInterface(driver, interface); this._driver = driver; this.directory = directory; @@ -70,16 +70,9 @@ Walker.prototype = { }, sync: function(options, callback) { - return Migration.loadFromDatabase( - this.directory, - this._driver, - this.internals - ) - .then(completedMigrations => { - var mode = dbmUtil.syncMode( - completedMigrations, - funcOrOpts.destination - ); + return File.loadFromDatabase(this.directory, this._driver, this.internals) + .then(completedFiles => { + const mode = dbmUtil.syncMode(completedFiles, funcOrOpts.destination); if (mode === 1) { log.info(this.prefix + 'Syncing upwards.'); return this.up(options); @@ -96,10 +89,10 @@ Walker.prototype = { File.loadFromFilesystem(this.directory, this.internals), File.loadFromDatabase(this.directory, this._driver, this.internals) ]) - .then(function(allMigrations, completedMigrations) { - var toRun = dbmUtil.filterUp( - allMigrations, - completedMigrations, + .then((allFiles, completedFiles) => { + const toRun = dbmUtil.filterUp( + allFiles, + completedFiles, partialName, count ); @@ -110,18 +103,18 @@ Walker.prototype = { return toRun; }) - .each(function(migration) { - log.verbose(this.prefix + 'preparing to run up:', migration.name); - var version = migration._meta.version || 1; - require('./executors/versioned/v' + version).up(this.driver, migration); + .each(file => { + log.verbose(this.prefix + 'preparing to run up:', file.name); + const version = file.get()._meta.version || 1; + require('./executors/versioned/v' + version).up(this.driver, file); }) .nodeify(callback); }, down: function({ partialName, count }, callback) { return File.loadFromDatabase(this.directory, this._driver, this.internals) - .then(completedMigrations => { - let toRun = dbmUtil.filterDown(completedMigrations, partialName, count); + .then(completedFiles => { + const toRun = dbmUtil.filterDown(completedFiles, partialName, count); if (toRun.length === 0) { log.info(this.prefix + 'Nothing to run'); @@ -129,10 +122,10 @@ Walker.prototype = { return toRun; }) - .each(migration => { - log.verbose(this.prefix + 'preparing to run down:', migration.name); - let version = migration._meta.version || 1; - require('./executors/versioned/v' + version).up(this.driver, migration); + .each(file => { + log.verbose(this.prefix + 'preparing to run down:', file.name); + const version = file.get()._meta.version || 1; + require('./executors/versioned/v' + version).down(this.driver, file); }) .nodeify(callback); } From 89c6ec37adef320ffd96bc7a15ca80e2da63da51 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Feb 2018 16:34:34 +0100 Subject: [PATCH 03/16] refactor(executor): use file api Referst to #215 Signed-off-by: Tobias Gurtzick --- lib/executors/versioned/v1.js | 32 +++++++++------------ lib/temputils.js | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 lib/temputils.js diff --git a/lib/executors/versioned/v1.js b/lib/executors/versioned/v1.js index 105bd6c4..8ca69325 100644 --- a/lib/executors/versioned/v1.js +++ b/lib/executors/versioned/v1.js @@ -1,43 +1,39 @@ -var log = require('db-migrate-shared').log; -var Promise = require('bluebird'); +const Promise = require('bluebird'); +const { maybePromise } = require('../../temputils.js'); const execUnit = { - up: function (context, driver, execUnit) { + up: function (context, driver, file) { return context.driver .startMigration() .then(() => { - var setup = execUnit.setup; + const _file = file.get(); - if (typeof setup === 'function') { - setup(context.internals.execUnitOptions, context.seedLink); + if (typeof _file.setup === 'function') { + _file.setup(context.internals.fileOptions, context.seedLink); } - return execUnit.up(); + return maybePromise(_file.up); }) .then(() => { - return Promise.promisify(context.writeexecUnitRecord.bind(context))( - execUnit - ); + return Promise.promisify(context.writeRecord.bind(context))(file); }) .then(context.driver.endMigration.bind(context.driver)); }, - down: function (context, driver, execUnit) { + down: function (context, driver, file) { return driver .startMigration() .then(() => { - var setup = execUnit.setup; + const _file = file.get(); - if (typeof setup === 'function') { - setup(context.internals.execUnitOptions, context.seedLink); + if (typeof _file.setup === 'function') { + _file.setup(context.internals.fileOptions, context.seedLink); } - return execUnit.down(); + return maybePromise(_file.down); }) .then(() => { - return Promise.promisify(context.deleteexecUnitRecord.bind(context))( - execUnit - ); + return Promise.promisify(context.deleteRecord.bind(context))(file); }) .then(context.driver.endMigration.bind(context.driver)); } diff --git a/lib/temputils.js b/lib/temputils.js new file mode 100644 index 00000000..fdce2b2f --- /dev/null +++ b/lib/temputils.js @@ -0,0 +1,54 @@ +'use strict'; + +function isPromise (probe) { + return ( + probe instanceof Promise || + (probe && + probe.then && + probe.constructor && + probe.constructor.name === 'Promise') + ); +} + +function maybePromise (context, action, params) { + let cbExecuted = false; + + return new Promise((resolve, reject) => { + const r = err => { + if (cbExecuted === false) { + cbExecuted = true; + + if (err) { + reject(err); + } else { + resolve(); + } + } + }; + + params[params.length++] = r; + + if (typeof action === 'function') action = action.apply(context, params); + else action = Promise.resolve(); + + if (isPromise(action)) { + action + .then(() => { + if (cbExecuted === false) { + cbExecuted = true; + resolve(); + } + }) + .catch(err => { + if (cbExecuted === false) { + cbExecuted = true; + reject(err); + } + }); + } + }); +} + +module.exports = { + maybePromise: maybePromise +}; From 6234d4285998d9d9e6779b56335fcdcaf350b853 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Feb 2018 18:10:05 +0100 Subject: [PATCH 04/16] fix(walker): rename interface to Interface Signed-off-by: Tobias Gurtzick --- lib/walker.js | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lib/walker.js b/lib/walker.js index b4406188..4829281e 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -1,10 +1,12 @@ +'use strict'; + const dbmUtil = require('db-migrate-shared').util; const log = require('db-migrate-shared').log; const Promise = require('bluebird'); const File = require('./file.js'); // Not sure what will happen to this yet -function SeedLink(driver, internals) { +function SeedLink (driver, internals) { this.seeder = require('./seeder.js')( driver, internals.argv['vcseeder-dir'], @@ -15,8 +17,8 @@ function SeedLink(driver, internals) { this.links = []; } -const Walker = function(driver, directory, interface, empty, intern) { - this.driver = dbmUtil.reduceToInterface(driver, interface); +const Walker = function (driver, directory, Interface, empty, intern) { + this.driver = dbmUtil.reduceToInterface(driver, Interface); this._driver = driver; this.directory = directory; this.internals = intern; @@ -29,12 +31,12 @@ const Walker = function(driver, directory, interface, empty, intern) { }; Walker.prototype = { - createMigrationsTable: function(callback) { + createMigrationsTable: function (callback) { this._driver.createMigrationsTable(callback); }, - writeMigrationRecord: function(migration, callback) { - function onComplete(err) { + writeMigrationRecord: function (migration, callback) { + function onComplete (err) { if (err) { log.error(this.prefix + migration.name, err); } else { @@ -48,8 +50,8 @@ Walker.prototype = { ); }, - deleteMigrationRecord: function(migration, callback) { - function onComplete(err) { + deleteMigrationRecord: function (migration, callback) { + function onComplete (err) { if (err) { log.error(this.prefix + migration.name, err); } else { @@ -59,7 +61,7 @@ Walker.prototype = { } this._driver.deleteMigration( this.internals.matching + '/' + migration.name, - function(err) { + function (err) { if (!this.internals.matching) { this._driver.deleteMigration(migration.name, onComplete); } else { @@ -69,10 +71,10 @@ Walker.prototype = { ); }, - sync: function(options, callback) { + sync: function (options, callback) { return File.loadFromDatabase(this.directory, this._driver, this.internals) .then(completedFiles => { - const mode = dbmUtil.syncMode(completedFiles, funcOrOpts.destination); + const mode = dbmUtil.syncMode(completedFiles, options.destination); if (mode === 1) { log.info(this.prefix + 'Syncing upwards.'); return this.up(options); @@ -84,7 +86,7 @@ Walker.prototype = { .nodeify(callback); }, - up: function({ partialName, count }, callback) { + up: function ({ partialName, count }, callback) { return Promise.all([ File.loadFromFilesystem(this.directory, this.internals), File.loadFromDatabase(this.directory, this._driver, this.internals) @@ -106,12 +108,12 @@ Walker.prototype = { .each(file => { log.verbose(this.prefix + 'preparing to run up:', file.name); const version = file.get()._meta.version || 1; - require('./executors/versioned/v' + version).up(this.driver, file); + require(`./executors/versioned/v${version}`).up(this.driver, file); }) .nodeify(callback); }, - down: function({ partialName, count }, callback) { + down: function ({ partialName, count }, callback) { return File.loadFromDatabase(this.directory, this._driver, this.internals) .then(completedFiles => { const toRun = dbmUtil.filterDown(completedFiles, partialName, count); @@ -125,7 +127,7 @@ Walker.prototype = { .each(file => { log.verbose(this.prefix + 'preparing to run down:', file.name); const version = file.get()._meta.version || 1; - require('./executors/versioned/v' + version).down(this.driver, file); + require(`./executors/versioned/v${version}`).down(this.driver, file); }) .nodeify(callback); } From 90038fc67a8068ac663219d03dfd3c15cc0b92ba Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Feb 2018 20:40:14 +0100 Subject: [PATCH 05/16] refactor(loader): functioning loader Signed-off-by: Tobias Gurtzick --- api.js | 28 +++++++------ connect.js | 43 +++++++++++++------- lib/commands/up.js | 46 ++++++++++++++-------- lib/executors/versioned/v1.js | 16 +++++--- lib/file.js | 19 +++++---- lib/migration.js | 2 +- lib/temputils.js | 4 +- lib/walker.js | 74 +++++++++++++++++++++++++---------- 8 files changed, 152 insertions(+), 80 deletions(-) diff --git a/api.js b/api.js index ccf3e973..da5e50b9 100644 --- a/api.js +++ b/api.js @@ -73,14 +73,20 @@ function dbmigrate (plugins, isModule, options, callback) { // delayed loading of bluebird Promise = require('bluebird'); this.internals.migrationOptions = { - dbmigrate: this.internals.dbm, + dbmigrate: { + version: this.internals.dbm.version, + dataType: this.internals.dbm.dataType + }, + dryRun: this.internals.dryRun, + cwd: this.internals.cwd, + noTransactions: this.internals.notransactions, + verbose: this.internals.verbose, + type: this.internals.dbm.dataType, + log: log, ignoreOnInit: this.internals.argv['ignore-on-init'], Promise: Promise }; - this.internals.seederOptions = { - dbmigrate: this.internals.dbm, - Promise: Promise - }; + this.internals.safeOptions = this.internals.migrationOptions; } dbmigrate.prototype = { @@ -101,10 +107,10 @@ dbmigrate.prototype = { }, /** - * Registers and initializes hooks. - * - * @returns Promise - */ + * Registers and initializes hooks. + * + * @returns Promise + */ registerAPIHook: function (callback) { var plugins = this.internals.plugins; var self = this; @@ -309,8 +315,8 @@ dbmigrate.prototype = { }, /** - * Transition migrations to the latest defined protocol. - */ + * Transition migrations to the latest defined protocol. + */ transition: function () { load('transition')(this.internals); }, diff --git a/connect.js b/connect.js index 590aadc9..1d5aeb6d 100644 --- a/connect.js +++ b/connect.js @@ -1,3 +1,7 @@ +/** + * This file is going to disappear. + * Only still here for backwards compatibility. + * */ var recursive = require('final-fs').readdirRecursive; var fs = require('fs'); var driver = require('./lib/driver'); @@ -6,8 +10,10 @@ var log = require('db-migrate-shared').log; exports.connect = function (config, PassedClass, callback) { var internals = {}; - + var prefix = 'migration'; + var migrationsDir; if (config.config) { + prefix = config.prefix || prefix; internals = config.internals; config = config.config; } @@ -19,15 +25,16 @@ exports.connect = function (config, PassedClass, callback) { } if (internals.migrationMode) { - var dirPath = path.resolve(config['migrations-dir'] || 'migrations'); - + var dirPath = path.resolve( + internals.argv['migrations-dir'] || 'migrations' + ); if (internals.migrationMode !== 'all') { var switched = false; var newConf; try { newConf = require(path.resolve( - config['migrations-dir'] || 'migrations', + internals.argv['migrations-dir'] || 'migrations', internals.migrationMode ) + '/config.json'); log.info( @@ -48,9 +55,10 @@ exports.connect = function (config, PassedClass, callback) { null, new PassedClass( db, - config['migrations-dir'], + internals.argv['migrations-dir'], internals.mode !== 'static', - internals + internals, + prefix ) ); }); @@ -60,9 +68,10 @@ exports.connect = function (config, PassedClass, callback) { null, new PassedClass( db, - config['migrations-dir'], + internals.argv['migrations-dir'], internals.mode !== 'static', - internals + internals, + prefix ) ); } @@ -70,7 +79,7 @@ exports.connect = function (config, PassedClass, callback) { recursive( dirPath, false, - config['migrations-dir'] || 'migrations' + internals.argv['migrations-dir'] || 'migrations' ).then(function (files) { var oldClose = db.close; @@ -89,6 +98,7 @@ exports.connect = function (config, PassedClass, callback) { PassedClass, db, oldClose, + prefix, cb ); }; @@ -101,9 +111,10 @@ exports.connect = function (config, PassedClass, callback) { null, new PassedClass( db, - config['migrations-dir'], + internals.argv['migrations-dir'], internals.mode !== 'static', - internals + internals, + prefix ) ); } @@ -128,6 +139,7 @@ function migrationFiles ( PassedClass, db, close, + prefix, cb ) { var file; @@ -156,8 +168,8 @@ function migrationFiles ( db.switchDatabase(switched ? newConf : config.database, function () { internals.matching = file.substr( - file.indexOf(config['migrations-dir'] || 'migrations') + - (config['migrations-dir'] || 'migrations').length + + file.indexOf(internals.argv['migrations-dir'] || 'migrations') + + (internals.argv['migrations-dir'] || 'migrations').length + 1 ); @@ -170,9 +182,10 @@ function migrationFiles ( null, new PassedClass( db, - config['migrations-dir'], + internals.argv['migrations-dir'], internals.mode !== 'static', - internals + internals, + prefix ) ); diff --git a/lib/commands/up.js b/lib/commands/up.js index fccd9348..77f4ebc4 100644 --- a/lib/commands/up.js +++ b/lib/commands/up.js @@ -4,24 +4,33 @@ var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); module.exports = function (internals, config, callback) { - migrationHook(internals) - .then(function () { - var Migrator = require('../migrator.js'); - var index = require('../../connect'); + migrationHook(internals).then(function () { + var Migrator = require('../walker.js'); + var index = require('../../connect'); - if (!internals.argv.count) { - internals.argv.count = Number.MAX_VALUE; - } - index.connect({ + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect( + { config: config.getCurrent().settings, - internals: internals - }, Migrator, function (err, migrator) { + internals: internals, + prefix: 'migration' + }, + Migrator, + function (err, migrator) { if (!assert(err, callback)) return; if (internals.locTitle) { - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], - internals.locTitle); - } else { migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); } + migrator.migrationsDir = path.resolve( + internals.argv['migrations-dir'], + internals.locTitle + ); + } else { + migrator.migrationsDir = path.resolve( + internals.argv['migrations-dir'] + ); + } internals.migrationsDir = migrator.migrationsDir; @@ -29,9 +38,12 @@ module.exports = function (internals, config, callback) { if (!assert(err, callback)) return; log.verbose('migration table created'); - migrator.up(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); + migrator.up( + internals.argv, + internals.onComplete.bind(this, migrator, internals, callback) + ); }); - }); - }); + } + ); + }); }; diff --git a/lib/executors/versioned/v1.js b/lib/executors/versioned/v1.js index 8ca69325..9c3c2a5b 100644 --- a/lib/executors/versioned/v1.js +++ b/lib/executors/versioned/v1.js @@ -1,5 +1,7 @@ +'use strict'; + const Promise = require('bluebird'); -const { maybePromise } = require('../../temputils.js'); +const { maybePromised } = require('../../temputils.js'); const execUnit = { up: function (context, driver, file) { @@ -9,13 +11,15 @@ const execUnit = { const _file = file.get(); if (typeof _file.setup === 'function') { - _file.setup(context.internals.fileOptions, context.seedLink); + _file.setup(context.internals.safeOptions, context.seedLink); } - return maybePromise(_file.up); + return maybePromised(file, _file.up, [context.driver]); }) .then(() => { - return Promise.promisify(context.writeRecord.bind(context))(file); + return Promise.promisify(context.writeMigrationRecord.bind(context))( + file + ); }) .then(context.driver.endMigration.bind(context.driver)); }, @@ -27,10 +31,10 @@ const execUnit = { const _file = file.get(); if (typeof _file.setup === 'function') { - _file.setup(context.internals.fileOptions, context.seedLink); + _file.setup(context.internals.safeOptions, context.seedLink); } - return maybePromise(_file.down); + return maybePromised(file, _file.down, [context.driver]); }) .then(() => { return Promise.promisify(context.deleteRecord.bind(context))(file); diff --git a/lib/file.js b/lib/file.js index 4255dafc..1bd29835 100644 --- a/lib/file.js +++ b/lib/file.js @@ -7,6 +7,11 @@ const inflection = require('inflection'); const Promise = require('bluebird'); const lpad = require('db-migrate-shared').util.lpad; +const LOADER = { + seeder: 'allLoadedSeedsAsync', + migration: 'allLoadedMigrationsAsync' +}; + function formatPath (dir, name) { return path.join(dir, name); } @@ -65,10 +70,10 @@ const File = function () { this.internals = arguments[1]; } - this._super(this.internals); + this.internals = this.internals.safeOptions; }; -File.protoype = { +File.prototype = { parseName: function (path) { const match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); return match[1]; @@ -115,8 +120,8 @@ File.registerHook = function (Plugin, prefix, internals) { }); }; -File.loadFromFileystem = function (dir, type, internals) { - log.verbose('loading ' + type + ' from dir', dir); +File.loadFromFileystem = function (dir, prefix, internals) { + log.verbose(`[${prefix}] loading from dir`, dir); return fs .readdirAsync(dir) @@ -131,9 +136,9 @@ File.loadFromFileystem = function (dir, type, internals) { }); }; -File.loadFromDatabase = function (dir, type, loader, internals) { - log.verbose('loading ' + type + ' from database'); - return loader() +File.loadFromDatabase = function (dir, prefix, driver, internals) { + log.verbose(`[${prefix}] loading from database`); + return driver[LOADER[prefix]]() .catch(function (err) { if (internals.dryRun) { return []; diff --git a/lib/migration.js b/lib/migration.js index d94ae5e2..996b8e80 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -23,7 +23,7 @@ var Migration = Skeleton.extend({ this.internals = arguments[1]; } - this._super(this.internals); + this._super(this.internals.migrationOptions); } }); diff --git a/lib/temputils.js b/lib/temputils.js index fdce2b2f..a3846742 100644 --- a/lib/temputils.js +++ b/lib/temputils.js @@ -10,7 +10,7 @@ function isPromise (probe) { ); } -function maybePromise (context, action, params) { +function maybePromised (context, action, params) { let cbExecuted = false; return new Promise((resolve, reject) => { @@ -50,5 +50,5 @@ function maybePromise (context, action, params) { } module.exports = { - maybePromise: maybePromise + maybePromised: maybePromised }; diff --git a/lib/walker.js b/lib/walker.js index 4829281e..9d562044 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -17,11 +17,20 @@ function SeedLink (driver, internals) { this.links = []; } -const Walker = function (driver, directory, Interface, empty, intern) { - this.driver = dbmUtil.reduceToInterface(driver, Interface); +const INTERFACES = { + migration: require('./interface/migratorInterface.js'), + seed: require('./interface/seederInterface.js'), + 'static-seed': require('./interface/seederInterface.js') +}; + +const Walker = function (driver, directory, mode, intern, prefix) { + this.driver = dbmUtil.reduceToInterface(driver, INTERFACES[prefix]); this._driver = driver; + Promise.promisifyAll(this._driver); this.directory = directory; this.internals = intern; + this.prefix = prefix; + this.title = `[${prefix}] `; // keep it until we decide how we do the cross linking if (intern.linked === false) { @@ -36,14 +45,14 @@ Walker.prototype = { }, writeMigrationRecord: function (migration, callback) { - function onComplete (err) { + const onComplete = err => { if (err) { - log.error(this.prefix + migration.name, err); + log.error(this.title + migration.name, err); } else { - log.info(this.prefix + 'Processed', migration.name); + log.info(this.title + 'Processed', migration.name); } callback(err); - } + }; this._driver.addMigrationRecord( this.internals.matching + '/' + migration.name, onComplete @@ -53,9 +62,9 @@ Walker.prototype = { deleteMigrationRecord: function (migration, callback) { function onComplete (err) { if (err) { - log.error(this.prefix + migration.name, err); + log.error(this.title + migration.name, err); } else { - log.info(this.prefix + 'Processed', migration.name); + log.info(this.title + 'Processed', migration.name); } callback(err); } @@ -72,14 +81,19 @@ Walker.prototype = { }, sync: function (options, callback) { - return File.loadFromDatabase(this.directory, this._driver, this.internals) + return File.loadFromDatabase( + this.directory, + this.prefix, + this._driver, + this.internals + ) .then(completedFiles => { const mode = dbmUtil.syncMode(completedFiles, options.destination); if (mode === 1) { - log.info(this.prefix + 'Syncing upwards.'); + log.info(this.title + 'Syncing upwards.'); return this.up(options); } else { - log.info(this.prefix + 'Syncing downwards.'); + log.info(this.title + 'Syncing downwards.'); return this.down(options); } }) @@ -88,10 +102,15 @@ Walker.prototype = { up: function ({ partialName, count }, callback) { return Promise.all([ - File.loadFromFilesystem(this.directory, this.internals), - File.loadFromDatabase(this.directory, this._driver, this.internals) + File.loadFromFileystem(this.directory, this.prefix, this.internals), + File.loadFromDatabase( + this.directory, + this.prefix, + this._driver, + this.internals + ) ]) - .then((allFiles, completedFiles) => { + .spread((allFiles, completedFiles) => { const toRun = dbmUtil.filterUp( allFiles, completedFiles, @@ -100,34 +119,47 @@ Walker.prototype = { ); if (toRun.length === 0) { - log.info(this.prefix + 'Nothing to run'); + log.info(this.title + 'Nothing to run'); } return toRun; }) .each(file => { - log.verbose(this.prefix + 'preparing to run up:', file.name); + log.verbose(this.title + 'preparing to run up:', file.name); const version = file.get()._meta.version || 1; - require(`./executors/versioned/v${version}`).up(this.driver, file); + return require(`./executors/versioned/v${version}`).up( + this, + this.driver, + file + ); }) .nodeify(callback); }, down: function ({ partialName, count }, callback) { - return File.loadFromDatabase(this.directory, this._driver, this.internals) + return File.loadFromDatabase( + this.directory, + this.title, + this._driver, + this.internals + ) .then(completedFiles => { const toRun = dbmUtil.filterDown(completedFiles, partialName, count); if (toRun.length === 0) { - log.info(this.prefix + 'Nothing to run'); + log.info(this.title + 'Nothing to run'); } return toRun; }) .each(file => { - log.verbose(this.prefix + 'preparing to run down:', file.name); + log.verbose(this.title + 'preparing to run down:', file.name); const version = file.get()._meta.version || 1; - require(`./executors/versioned/v${version}`).down(this.driver, file); + return require(`./executors/versioned/v${version}`).down( + this, + this.driver, + file + ); }) .nodeify(callback); } From 68361feb57fefdfa7a6ecb84d79a73b4b0e02431 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Feb 2018 20:54:33 +0100 Subject: [PATCH 06/16] fix(utils): resolve when returned null Signed-off-by: Tobias Gurtzick --- lib/temputils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/temputils.js b/lib/temputils.js index a3846742..4d3013e6 100644 --- a/lib/temputils.js +++ b/lib/temputils.js @@ -29,7 +29,7 @@ function maybePromised (context, action, params) { params[params.length++] = r; if (typeof action === 'function') action = action.apply(context, params); - else action = Promise.resolve(); + if (action === null) action = Promise.resolve(); if (isPromise(action)) { action From b2421e3f953d0081211bab41326bf488c6007f99 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Feb 2018 20:58:40 +0100 Subject: [PATCH 07/16] fix(scope): new scoping errored out when using templates Signed-off-by: Tobias Gurtzick --- lib/migration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/migration.js b/lib/migration.js index 996b8e80..b039d262 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -23,7 +23,7 @@ var Migration = Skeleton.extend({ this.internals = arguments[1]; } - this._super(this.internals.migrationOptions); + if (this.internals) this._super(this.internals.migrationOptions); } }); From 657ebe2dc2aef4041b042f6a6a4f8ffaed1c2e2a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 15:20:41 +0100 Subject: [PATCH 08/16] refactor: adding down and sync to user walker and apply patches patched to make sync and down working properly. Signed-off-by: Tobias Gurtzick --- lib/commands/down.js | 36 +++++++++++++++------------ lib/commands/sync.js | 46 ++++++++++++++++++++++------------- lib/executors/versioned/v1.js | 4 ++- lib/walker.js | 10 ++++---- 4 files changed, 58 insertions(+), 38 deletions(-) diff --git a/lib/commands/down.js b/lib/commands/down.js index 4454f1ed..ad05bcfe 100644 --- a/lib/commands/down.js +++ b/lib/commands/down.js @@ -4,29 +4,35 @@ var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); module.exports = function (internals, config, callback) { - migrationHook(internals) - .then(function () { - var Migrator = require('../migrator.js'); - var index = require('../../connect'); + migrationHook(internals).then(function () { + var Migrator = require('../walker.js'); + var index = require('../../connect'); - if (!internals.argv.count) { - log.info('Defaulting to running 1 down migration.'); - internals.argv.count = 1; - } + if (!internals.argv.count) { + log.info('Defaulting to running 1 down migration.'); + internals.argv.count = 1; + } - index.connect({ + index.connect( + { config: config.getCurrent().settings, - internals: internals - }, Migrator, function (err, migrator) { + internals: internals, + prefix: 'migration' + }, + Migrator, + function (err, migrator) { if (!assert(err)) return; migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); migrator.driver.createMigrationsTable(function (err) { if (!assert(err)) return; - migrator.down(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); + migrator.down( + internals.argv, + internals.onComplete.bind(this, migrator, internals, callback) + ); }); - }); - }); + } + ); + }); }; diff --git a/lib/commands/sync.js b/lib/commands/sync.js index ed1d3fc0..1674cb22 100644 --- a/lib/commands/sync.js +++ b/lib/commands/sync.js @@ -4,24 +4,33 @@ var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); module.exports = function (internals, config, callback) { - migrationHook(internals) - .then(function () { - var Migrator = require('../migrator.js'); - var index = require('../../connect'); + migrationHook(internals).then(function () { + var Migrator = require('../walker.js'); + var index = require('../../connect'); - if (!internals.argv.count) { - internals.argv.count = Number.MAX_VALUE; - } - index.connect({ + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect( + { config: config.getCurrent().settings, - internals: internals - }, Migrator, function (err, migrator) { + internals: internals, + prefix: 'migration' + }, + Migrator, + function (err, migrator) { if (!assert(err)) return; if (internals.locTitle) { - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], - internals.locTitle); - } else { migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); } + migrator.migrationsDir = path.resolve( + internals.argv['migrations-dir'], + internals.locTitle + ); + } else { + migrator.migrationsDir = path.resolve( + internals.argv['migrations-dir'] + ); + } internals.migrationsDir = migrator.migrationsDir; @@ -29,9 +38,12 @@ module.exports = function (internals, config, callback) { if (!assert(err)) return; log.verbose('migration table created'); - migrator.sync(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); + migrator.sync( + internals.argv, + internals.onComplete.bind(this, migrator, internals, callback) + ); }); - }); - }); + } + ); + }); }; diff --git a/lib/executors/versioned/v1.js b/lib/executors/versioned/v1.js index 9c3c2a5b..46ab5e08 100644 --- a/lib/executors/versioned/v1.js +++ b/lib/executors/versioned/v1.js @@ -37,7 +37,9 @@ const execUnit = { return maybePromised(file, _file.down, [context.driver]); }) .then(() => { - return Promise.promisify(context.deleteRecord.bind(context))(file); + return Promise.promisify(context.deleteMigrationRecord.bind(context))( + file + ); }) .then(context.driver.endMigration.bind(context.driver)); } diff --git a/lib/walker.js b/lib/walker.js index 9d562044..0575c327 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -60,14 +60,14 @@ Walker.prototype = { }, deleteMigrationRecord: function (migration, callback) { - function onComplete (err) { + const onComplete = err => { if (err) { log.error(this.title + migration.name, err); } else { log.info(this.title + 'Processed', migration.name); } callback(err); - } + }; this._driver.deleteMigration( this.internals.matching + '/' + migration.name, function (err) { @@ -100,7 +100,7 @@ Walker.prototype = { .nodeify(callback); }, - up: function ({ partialName, count }, callback) { + up: function ({ destination: partialName, count }, callback) { return Promise.all([ File.loadFromFileystem(this.directory, this.prefix, this.internals), File.loadFromDatabase( @@ -136,10 +136,10 @@ Walker.prototype = { .nodeify(callback); }, - down: function ({ partialName, count }, callback) { + down: function ({ destination: partialName, count }, callback) { return File.loadFromDatabase( this.directory, - this.title, + this.prefix, this._driver, this.internals ) From 35b956e2c5d49b49c5ca4021e4dc45e4934a41db Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 16:05:50 +0100 Subject: [PATCH 09/16] refactor: differenciate between modes and add seeds Signed-off-by: Tobias Gurtzick --- lib/commands/seed.js | 5 +++-- lib/commands/undo-seed.js | 5 +++-- lib/walker.js | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/commands/seed.js b/lib/commands/seed.js index 72b18a66..3a295c37 100644 --- a/lib/commands/seed.js +++ b/lib/commands/seed.js @@ -6,7 +6,7 @@ var _assert = require('./helper/assert'); function executeSeed (internals, config, callback) { var index = require('../../connect'); - var Seeder = require('../seeder.js'); + var Seeder = require('../walker.js'); if (internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); @@ -15,7 +15,8 @@ function executeSeed (internals, config, callback) { index.connect( { config: config.getCurrent().settings, - internals: internals + internals: internals, + prefix: 'seed' }, Seeder, function (err, seeder) { diff --git a/lib/commands/undo-seed.js b/lib/commands/undo-seed.js index 6f2cd09f..7c07acc6 100644 --- a/lib/commands/undo-seed.js +++ b/lib/commands/undo-seed.js @@ -7,7 +7,7 @@ var _assert = require('./helper/assert'); function executeUndoSeed (internals, config, callback) { var index = require('./connect'); - var Seeder = require('./lib/seeder.js'); + var Seeder = require('./lib/walker.js'); if (!internals.argv.count) { log.info('Defaulting to running 1 down seed.'); @@ -21,7 +21,8 @@ function executeUndoSeed (internals, config, callback) { index.connect( { config: config.getCurrent().settings, - internals: internals + internals: internals, + prefix: 'seed' }, Seeder, function (err, seeder) { diff --git a/lib/walker.js b/lib/walker.js index 0575c327..88bb8f39 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -29,7 +29,11 @@ const Walker = function (driver, directory, mode, intern, prefix) { Promise.promisifyAll(this._driver); this.directory = directory; this.internals = intern; - this.prefix = prefix; + this.mode = mode; + + if (!this.mode) this.prefix = `static-${prefix}`; + else this.prefix = prefix; + this.title = `[${prefix}] `; // keep it until we decide how we do the cross linking From 141d50996e3ba33bfcd9ad07ff7452730da0ac01 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 17:35:20 +0100 Subject: [PATCH 10/16] refactor: prepare removal and adjust hooks and deprecate Deprecate old hook 'migrator:migration:hook:require' and add a warning. Prepare to finally remove all other unnecessary files. Signed-off-by: Tobias Gurtzick --- lib/commands/create-migration.js | 50 ++++++----- lib/commands/helper/migration-hook.js | 3 +- lib/file.js | 40 +++++++-- lib/transitions/transitioner.js | 2 +- lib/walker.js | 6 +- test/integration/create_test.js | 122 ++++++++++++++------------ test/migration_test.js | 85 +++++++++--------- 7 files changed, 174 insertions(+), 134 deletions(-) diff --git a/lib/commands/create-migration.js b/lib/commands/create-migration.js index 92adc3fb..23162c54 100644 --- a/lib/commands/create-migration.js +++ b/lib/commands/create-migration.js @@ -1,11 +1,11 @@ 'use strict'; -var _assert = require('./helper/assert'); -var log = require('db-migrate-shared').log; -var mkdirp = require('mkdirp'); -var fs = require('fs'); -var optimist = require('optimist'); -var util = require('util'); +const _assert = require('./helper/assert'); +const log = require('db-migrate-shared').log; +const mkdirp = require('mkdirp'); +const fs = require('fs'); +const optimist = require('optimist'); +const util = require('util'); function createMigrationDir (dir, callback) { fs.stat(dir, function (err) { @@ -18,7 +18,8 @@ function createMigrationDir (dir, callback) { } function executeCreateMigration (internals, config, callback) { - var migrationsDir = internals.argv['migrations-dir']; + let migrationsDir = internals.argv['migrations-dir']; + let folder, path; internals.runTimestamp = new Date(); @@ -27,8 +28,6 @@ function executeCreateMigration (internals, config, callback) { internals.argv['migrations-dir'] + '/' + internals.migrationMode; } - var folder, path; - if (internals.argv._.length === 0) { log.error("'migrationName' is required."); if (!internals.isModule) { @@ -43,8 +42,8 @@ function executeCreateMigration (internals, config, callback) { } createMigrationDir(migrationsDir, function (err) { - var index = require('../../connect'); - var Migration = require('../migration.js'); + const index = require('../../connect'); + const Migration = require('../template.js'); if (err) { log.error('Failed to create migration directory at ', migrationsDir, err); @@ -64,12 +63,12 @@ function executeCreateMigration (internals, config, callback) { if (folder.length > 1) { path += '/'; - for (var i = 0; i < folder.length - 1; ++i) { + for (let i = 0; i < folder.length - 1; ++i) { path += folder[i] + '/'; } } - var templateType = Migration.TemplateType.DEFAULT_JS; + let templateType = Migration.TemplateType.DEFAULT_JS; if ( shouldCreateSqlFiles(internals, config) && shouldCreateCoffeeFile(internals, config) @@ -85,7 +84,7 @@ function executeCreateMigration (internals, config, callback) { } else if (shouldCreateCoffeeFile(internals, config)) { templateType = Migration.TemplateType.DEFAULT_COFFEE; } - var migration = new Migration( + const migration = new Migration( internals.argv.title + (shouldCreateCoffeeFile(internals, config) ? '.coffee' : '.js'), path, @@ -94,7 +93,7 @@ function executeCreateMigration (internals, config, callback) { ); index.createMigration(migration, function (err, migration) { if (_assert(err, callback)) { - log.info(util.format('Created migration at %s', migration.path)); + log.info(util.format('Created migration at %s', migration.file.path)); if (shouldCreateSqlFiles(internals, config)) { createSqlFiles(internals, config, callback); } else { @@ -120,17 +119,17 @@ function shouldCreateCoffeeFile (internals, config) { } function createSqlFiles (internals, config, callback) { - var migrationsDir = internals.argv['migrations-dir']; + let migrationsDir = internals.argv['migrations-dir']; if (internals.migrationMode && internals.migrationMode !== 'all') { migrationsDir = internals.argv['migrations-dir'] + '/' + internals.migrationMode; } - var sqlDir = migrationsDir + '/sqls'; + const sqlDir = migrationsDir + '/sqls'; createMigrationDir(sqlDir, function (err) { - var index = require('../../connect'); - var Migration = require('../migration.js'); + const index = require('../../connect'); + const Migration = require('../template.js'); if (err) { log.error('Failed to create migration directory at ', sqlDir, err); @@ -142,8 +141,8 @@ function createSqlFiles (internals, config, callback) { } } - var templateTypeDefaultSQL = Migration.TemplateType.DEFAULT_SQL; - var migrationUpSQL = new Migration( + let templateTypeDefaultSQL = Migration.TemplateType.DEFAULT_SQL; + const migrationUpSQL = new Migration( internals.argv.title + '-up.sql', sqlDir, internals.runTimestamp, @@ -152,10 +151,13 @@ function createSqlFiles (internals, config, callback) { index.createMigration(migrationUpSQL, function (err, migration) { if (_assert(err, callback)) { log.info( - util.format('Created migration up sql file at %s', migration.path) + util.format( + 'Created migration up sql file at %s', + migration.file.path + ) ); - var migrationDownSQL = new Migration( + const migrationDownSQL = new Migration( internals.argv.title + '-down.sql', sqlDir, internals.runTimestamp, @@ -166,7 +168,7 @@ function createSqlFiles (internals, config, callback) { log.info( util.format( 'Created migration down sql file at %s', - migration.path + migration.file.path ) ); if (typeof callback === 'function') callback(); diff --git a/lib/commands/helper/migration-hook.js b/lib/commands/helper/migration-hook.js index cb69a90e..8662fa5f 100644 --- a/lib/commands/helper/migration-hook.js +++ b/lib/commands/helper/migration-hook.js @@ -1,5 +1,4 @@ - module.exports = function (internals) { - var Migration = require('../../migration.js'); + var Migration = require('../../file.js'); return Migration.registerHook(internals.plugins, internals); }; diff --git a/lib/file.js b/lib/file.js index 1bd29835..04b1186b 100644 --- a/lib/file.js +++ b/lib/file.js @@ -7,6 +7,8 @@ const inflection = require('inflection'); const Promise = require('bluebird'); const lpad = require('db-migrate-shared').util.lpad; +Promise.promisifyAll(fs); + const LOADER = { seeder: 'allLoadedSeedsAsync', migration: 'allLoadedMigrationsAsync' @@ -60,7 +62,6 @@ const File = function () { this.date = arguments[2]; this.name = this.formatName(this.title, this.date); this.path = this.formatPath(arguments[1], this.name); - this.templateType = arguments[3]; this.internals = arguments[4]; } else if (arguments.length === 2) { this.path = arguments[0]; @@ -70,7 +71,7 @@ const File = function () { this.internals = arguments[1]; } - this.internals = this.internals.safeOptions; + if (this.internals) this.internals = this.internals.safeOptions; }; File.prototype = { @@ -83,6 +84,10 @@ File.prototype = { return this._required || (this._required = require(this.path)); }, + write: function (data) { + return fs.writeFileAsync(this.path, data); + }, + parseTitle: parseTitle, parseDate: parseDate, formatTitle: formatTitle, @@ -90,8 +95,11 @@ File.prototype = { formatName: formatName }; -File.registerHook = function (Plugin, prefix, internals) { - const plugin = Plugin.hook(prefix + ':hook:require'); +File.registerHook = function (Plugin, internals) { + const plugin = [].concat(Plugin.hook('file:hook:require') || []).concat( + Plugin.hook('migrator:migration:hook:require') || [] // backwards compatible + ); + internals.parser = internals.parser || { filesRegEx: filesRegEx, extensions: 'js' @@ -103,7 +111,29 @@ File.registerHook = function (Plugin, prefix, internals) { return Promise.resolve(plugin) .map(function (plugin) { - return plugin[prefix + ':hook:require'](); + // Backwards compatibility and notice for everyone so they + // can bug the plugin maintainer + if (plugin['migrator:migration:hook:require']) { + log.warn( + `The plugin '${plugin.name}' is outdated! The hook` + + `migrator:migration:hook:require was deprecated!` + ); + log.warn( + `Report the maintainer of '${plugin.name}' to patch the ` + + `hook instead with file:hook:require.` + ); + + if (plugin.maintainer && plugin.maintainer.repository) { + log.verbose( + `The repo of the ${plugin.name} plugin is ${ + plugin.maintainer.repository + }!` + ); + } + return plugin['migrator:migration:hook:require'](); + } + + return plugin['file:hook:require'](); }) .each(function (parser) { if (parser && parser.extensions) { diff --git a/lib/transitions/transitioner.js b/lib/transitions/transitioner.js index ea19caa1..d26c861d 100644 --- a/lib/transitions/transitioner.js +++ b/lib/transitions/transitioner.js @@ -1,4 +1,4 @@ -var Migration = require('../migration.js'); +var Migration = require('../file.js'); var tryRequire = require('./try-require.js'); var updateVersion = require('./update-version.js'); var ask = require('./ask.js'); diff --git a/lib/walker.js b/lib/walker.js index 88bb8f39..cc8027a1 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -130,7 +130,8 @@ Walker.prototype = { }) .each(file => { log.verbose(this.title + 'preparing to run up:', file.name); - const version = file.get()._meta.version || 1; + const _meta = file.get()._meta || {}; + const version = _meta.version || 1; return require(`./executors/versioned/v${version}`).up( this, this.driver, @@ -158,7 +159,8 @@ Walker.prototype = { }) .each(file => { log.verbose(this.title + 'preparing to run down:', file.name); - const version = file.get()._meta.version || 1; + const _meta = file.get()._meta || {}; + const version = _meta.version || 1; return require(`./executors/versioned/v${version}`).down( this, this.driver, diff --git a/test/integration/create_test.js b/test/integration/create_test.js index dd18106c..61a5b8c4 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -1,28 +1,28 @@ -var Code = require('code'); -var Lab = require('lab'); -var lab = (exports.lab = Lab.script()); -var fs = require('fs'); -var path = require('path'); -var cp = require('child_process'); -var dbmUtil = require('db-migrate-shared').util; +const Code = require('code'); +const Lab = require('lab'); +const lab = (exports.lab = Lab.script()); +const fs = require('fs'); +const path = require('path'); +const cp = require('child_process'); +const dbmUtil = require('db-migrate-shared').util; -var rmdir = require('rimraf'); +const rmdir = require('rimraf'); function wipeMigrations (callback) { - var dir = path.join(__dirname, 'migrations'); + const dir = path.join(__dirname, 'migrations'); rmdir(dir, callback); } function dbMigrate () { - var args = dbmUtil.toArray(arguments); - var dbm = path.join(__dirname, '..', '..', 'bin', 'db-migrate'); + const args = dbmUtil.toArray(arguments); + const dbm = path.join(__dirname, '..', '..', 'bin', 'db-migrate'); args.unshift(dbm); return cp.spawn('node', args, { cwd: __dirname }); } lab.experiment('create', function () { lab.experiment('without a migration directory', function () { - var exitCode; + let exitCode; lab.before(function (done) { wipeMigrations(function (err) { @@ -40,15 +40,15 @@ lab.experiment('create', function () { }); lab.test('will create a new migration directory', function (done) { - var stats = fs.statSync(path.join(__dirname, 'migrations')); + const stats = fs.statSync(path.join(__dirname, 'migrations')); Code.expect(stats.isDirectory()).to.be.true(); done(); }); lab.test('will create a new migration', function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + const files = fs.readdirSync(path.join(__dirname, 'migrations')); Code.expect(files.length).to.equal(1); - var file = files[0]; + const file = files[0]; Code.expect(file).to.match(/first-migration\.js$/); done(); }); @@ -57,10 +57,10 @@ lab.experiment('create', function () { lab.experiment( 'with sql-file option set to true from config file', function () { - var exitCode; + let exitCode; lab.before(function (done) { - var configOption = path.join( + const configOption = path.join( '--config=', __dirname, 'database_with_sql_file.json' @@ -84,27 +84,29 @@ lab.experiment('create', function () { }); lab.test('will create a new migration', function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + const files = fs.readdirSync(path.join(__dirname, 'migrations')); - for (var i = 0; i < files.length; i++) { - var file = files[i]; - var stats = fs.statSync(path.join(__dirname, 'migrations', file)); - if (stats.isFile()) { Code.expect(file).to.match(/second-migration\.js$/); } + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const stats = fs.statSync(path.join(__dirname, 'migrations', file)); + if (stats.isFile()) { + Code.expect(file).to.match(/second-migration\.js$/); + } } done(); }); lab.test('will create a new migration/sqls directory', function (done) { - var stats = fs.statSync(path.join(__dirname, 'migrations/sqls')); + const stats = fs.statSync(path.join(__dirname, 'migrations/sqls')); Code.expect(stats.isDirectory()).to.be.true(); done(); }); lab.test('will create a new migration sql up file', function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations/sqls')); + const files = fs.readdirSync(path.join(__dirname, 'migrations/sqls')); Code.expect(files.length).to.equal(2); - var file = files[1]; + const file = files[1]; Code.expect(file).to.match(/second-migration-up\.sql$/); done(); }); @@ -114,10 +116,10 @@ lab.experiment('create', function () { lab.experiment( 'with sql-file option set to true as a command parameter', function () { - var exitCode; + let exitCode; lab.before(function (done) { - var configOption = path.join('--sql-file'); + const configOption = path.join('--sql-file'); wipeMigrations(function (err) { Code.expect(err).to.not.exist(); dbMigrate('create', 'third migration', configOption).on( @@ -136,26 +138,28 @@ lab.experiment('create', function () { }); lab.test('will create a new migration', function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + const files = fs.readdirSync(path.join(__dirname, 'migrations')); - for (var i = 0; i < files.length; i++) { - var file = files[i]; - var stats = fs.statSync(path.join(__dirname, 'migrations', file)); - if (stats.isFile()) { Code.expect(file).to.match(/third-migration\.js$/); } + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const stats = fs.statSync(path.join(__dirname, 'migrations', file)); + if (stats.isFile()) { + Code.expect(file).to.match(/third-migration\.js$/); + } } done(); }); lab.test('will create a new migration/sqls directory', function (done) { - var stats = fs.statSync(path.join(__dirname, 'migrations/sqls')); + const stats = fs.statSync(path.join(__dirname, 'migrations/sqls')); Code.expect(stats.isDirectory()).to.be.true(); done(); }); lab.test('will create a new migration sql up file', function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations/sqls')); + const files = fs.readdirSync(path.join(__dirname, 'migrations/sqls')); Code.expect(files.length).to.equal(2); - var file = files[1]; + const file = files[1]; Code.expect(file).to.match(/third-migration-up\.sql$/); done(); }); @@ -165,10 +169,10 @@ lab.experiment('create', function () { lab.experiment( 'with coffee-file option set to true from config file', function () { - var exitCode; + let exitCode; lab.before(function (done) { - var configOption = path.join( + const configOption = path.join( '--config=', __dirname, 'database_with_coffee_file.json' @@ -192,11 +196,11 @@ lab.experiment('create', function () { }); lab.test('will create a new coffeescript migration', function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + const files = fs.readdirSync(path.join(__dirname, 'migrations')); - for (var i = 0; i < files.length; i++) { - var file = files[i]; - var stats = fs.statSync(path.join(__dirname, 'migrations', file)); + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const stats = fs.statSync(path.join(__dirname, 'migrations', file)); if (stats.isFile()) { Code.expect(file).to.match(/fourth-migration\.coffee$/); } @@ -210,10 +214,10 @@ lab.experiment('create', function () { lab.experiment( 'with coffee-file option set to true as a command parameter', function () { - var exitCode; + let exitCode; lab.before(function (done) { - var configOption = path.join('--coffee-file'); + const configOption = path.join('--coffee-file'); wipeMigrations(function (err) { Code.expect(err).to.not.exist(); dbMigrate('create', 'fifth migration', configOption).on( @@ -232,11 +236,11 @@ lab.experiment('create', function () { }); lab.test('will create a new coffeescript migration', function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + const files = fs.readdirSync(path.join(__dirname, 'migrations')); - for (var i = 0; i < files.length; i++) { - var file = files[i]; - var stats = fs.statSync(path.join(__dirname, 'migrations', file)); + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const stats = fs.statSync(path.join(__dirname, 'migrations', file)); if (stats.isFile()) { Code.expect(file).to.match(/fifth-migration\.coffee$/); } @@ -249,20 +253,20 @@ lab.experiment('create', function () { lab.experiment( 'with sql-file and a bad migration, causes an exit', function () { - var exitCode; + let exitCode; lab.before(function (done) { - var configOption = path.join('--sql-file'); + const configOption = path.join('--sql-file'); wipeMigrations(function (err) { Code.expect(err).to.not.exist(); dbMigrate('create', 'sixth migration', configOption).on( 'exit', function () { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + const files = fs.readdirSync(path.join(__dirname, 'migrations')); - for (var i = 0; i < files.length; i++) { - var file = files[i]; - var stats = fs.statSync( + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const stats = fs.statSync( path.join(__dirname, 'migrations', file) ); @@ -288,12 +292,14 @@ lab.experiment('create', function () { }); lab.test('did create the new migration', function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + const files = fs.readdirSync(path.join(__dirname, 'migrations')); - for (var i = 0; i < files.length; i++) { - var file = files[i]; - var stats = fs.statSync(path.join(__dirname, 'migrations', file)); - if (stats.isFile()) { Code.expect(file).to.match(/sixth-migration\.js$/); } + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const stats = fs.statSync(path.join(__dirname, 'migrations', file)); + if (stats.isFile()) { + Code.expect(file).to.match(/sixth-migration\.js$/); + } } done(); diff --git a/test/migration_test.js b/test/migration_test.js index daac3a68..985451e9 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -1,17 +1,18 @@ -var Code = require('code'); -var Lab = require('lab'); -var proxyquire = require('proxyquire').noPreserveCache(); -var lab = (exports.lab = Lab.script()); -var Migration = require('../lib/migration.js'); - -var date = createDateForTest(); -var dateString = '20140220143050'; -var dirName = '/directory/name/'; -var fileNameNoExtension = 'filename'; -var fileName = 'filename.js'; -var templateType = Migration.TemplateType.SQL_FILE_LOADER; - -var internals = {}; +const Code = require('code'); +const Lab = require('lab'); +const proxyquire = require('proxyquire').noPreserveCache(); +const lab = (exports.lab = Lab.script()); +const Migration = require('../lib/file.js'); +const Template = require('../lib/template.js'); + +const date = createDateForTest(); +const dateString = '20140220143050'; +const dirName = '/directory/name/'; +const fileNameNoExtension = 'filename'; +const fileName = 'filename.js'; +const templateType = Template.TemplateType.SQL_FILE_LOADER; + +let internals = {}; internals.migrationTable = 'migrations'; lab.experiment('migration', function () { @@ -32,7 +33,7 @@ lab.experiment('migration', function () { function asModule () { lab.test('should create migration', function (done) { - var dbmigrate = stubApiInstance(true, {}, {}); + const dbmigrate = stubApiInstance(true, {}, {}); dbmigrate.setConfigParam('_', []); dbmigrate.create('migrationName').then(done); @@ -44,7 +45,7 @@ function newMigrationObject () { 'with 2 parameters as the complete filepath', function () { - var migration = new Migration( + const migration = new Migration( dirName + dateString + '-' + fileName, internals ); @@ -91,7 +92,7 @@ function newMigrationObject () { ); lab.experiment('with 3 parameters', function () { - var migration = new Migration(fileName, dirName, date); + const migration = new Migration(fileName, dirName, date); lab.test('should have title set', function (done) { Code.expect(migration.title).to.equal(fileName); @@ -122,7 +123,7 @@ function newMigrationObject () { }); lab.experiment('with 5 parameters', function () { - var migration = new Migration( + const migration = new Template( fileName, dirName, date, @@ -131,22 +132,22 @@ function newMigrationObject () { ); lab.test('should have title set', function (done) { - Code.expect(migration.title).to.equal(fileName); + Code.expect(migration.file.title).to.equal(fileName); done(); }); lab.test('should have date set', function (done) { - Code.expect(migration.date).to.equal(date); + Code.expect(migration.file.date).to.equal(date); done(); }); lab.test('should have name set', function (done) { - Code.expect(migration.name).to.equal(dateString + '-' + fileName); + Code.expect(migration.file.name).to.equal(dateString + '-' + fileName); done(); }); lab.test('should have path set', function (done) { - Code.expect(migration.path).to.equal( + Code.expect(migration.file.path).to.equal( dirName + dateString + '-' + fileName ); done(); @@ -164,13 +165,13 @@ function getTemplate () { 'when template type is not set', function () { - var migration = new Migration(fileName, dirName, date, internals); + const migration = new Template(fileName, dirName, date, internals); lab.test( 'should return default javascript template', function (done) { - var actual = migration.getTemplate(); + const actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultJsTemplate()); done(); } @@ -180,11 +181,11 @@ function getTemplate () { lab.experiment('when template type is set', function () { lab.experiment('as sql file loader', function () { - var migration = new Migration( + const migration = new Template( fileName, dirName, date, - Migration.TemplateType.SQL_FILE_LOADER, + Template.TemplateType.SQL_FILE_LOADER, internals ); @@ -192,7 +193,7 @@ function getTemplate () { 'should return sql file loader template', function (done) { - var actual = migration.getTemplate(); + const actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.sqlFileLoaderTemplate()); done(); } @@ -200,11 +201,11 @@ function getTemplate () { }); lab.experiment('as default sql', function () { - var migration = new Migration( + const migration = new Template( fileName, dirName, date, - Migration.TemplateType.DEFAULT_SQL, + Template.TemplateType.DEFAULT_SQL, internals ); @@ -212,7 +213,7 @@ function getTemplate () { 'should return default sql template', function (done) { - var actual = migration.getTemplate(); + const actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultSqlTemplate()); done(); } @@ -220,11 +221,11 @@ function getTemplate () { }); lab.experiment('as default coffee', function () { - var migration = new Migration( + const migration = new Template( fileName, dirName, date, - Migration.TemplateType.DEFAULT_COFFEE, + Template.TemplateType.DEFAULT_COFFEE, internals ); @@ -232,7 +233,7 @@ function getTemplate () { 'should return default coffee template', function (done) { - var actual = migration.getTemplate(); + const actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultCoffeeTemplate()); done(); } @@ -240,11 +241,11 @@ function getTemplate () { }); lab.experiment('as coffee sql loader', function () { - var migration = new Migration( + const migration = new Template( fileName, dirName, date, - Migration.TemplateType.COFFEE_SQL_FILE_LOADER, + Template.TemplateType.COFFEE_SQL_FILE_LOADER, internals ); @@ -252,7 +253,7 @@ function getTemplate () { 'should return default coffee template', function (done) { - var actual = migration.getTemplate(); + const actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.coffeeSqlFileLoaderTemplate()); done(); } @@ -260,11 +261,11 @@ function getTemplate () { }); lab.experiment('as default javascript', function () { - var migration = new Migration( + const migration = new Template( fileName, dirName, date, - Migration.TemplateType.DEFAULT_JS, + Template.TemplateType.DEFAULT_JS, internals ); @@ -272,7 +273,7 @@ function getTemplate () { 'should return default sql template', function (done) { - var actual = migration.getTemplate(); + const actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultJsTemplate()); done(); } @@ -284,8 +285,8 @@ function getTemplate () { function stubApiInstance (isModule, stubs, options, callback) { delete require.cache[require.resolve('../api.js')]; delete require.cache[require.resolve('optimist')]; - var Mod = proxyquire('../api.js', stubs); - var plugins = {}; + const Mod = proxyquire('../api.js', stubs); + const plugins = {}; options = options || {}; options = Object.assign(options, { @@ -297,7 +298,7 @@ function stubApiInstance (isModule, stubs, options, callback) { } function createDateForTest () { - var date = new Date(); + const date = new Date(); date.setUTCFullYear(2014); date.setUTCDate('20'); date.setUTCMonth('01'); From e7099b8a0b9bc1e3a5b73df862d21cfca9b43fd1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 18:06:00 +0100 Subject: [PATCH 11/16] refactor: restore node v4 support Signed-off-by: Tobias Gurtzick --- lib/executors/versioned/v1.js | 2 +- lib/template.js | 282 ++++++++++++++++++++++++++++++++ lib/walker.js | 9 +- test/integration/create_test.js | 2 + test/migration_test.js | 2 + 5 files changed, 294 insertions(+), 3 deletions(-) create mode 100644 lib/template.js diff --git a/lib/executors/versioned/v1.js b/lib/executors/versioned/v1.js index 46ab5e08..fc1e42f4 100644 --- a/lib/executors/versioned/v1.js +++ b/lib/executors/versioned/v1.js @@ -1,7 +1,7 @@ 'use strict'; const Promise = require('bluebird'); -const { maybePromised } = require('../../temputils.js'); +const maybePromised = require('../../temputils.js').maybePromised; const execUnit = { up: function (context, driver, file) { diff --git a/lib/template.js b/lib/template.js new file mode 100644 index 00000000..b0629664 --- /dev/null +++ b/lib/template.js @@ -0,0 +1,282 @@ +'use strict'; + +const File = require('./file.js'); +const dbmUtil = require('db-migrate-shared').util; + +const Template = function () { + this.templateType = arguments[3]; + // this is a tweak for node 4 this can be translated + // to ...arguments instead in upcoming node versions + const Comp = File.bind.apply(File, [null].concat(dbmUtil.toArray(arguments))); + this.file = new Comp(); +}; + +Template.prototype.defaultCoffeeTemplate = function () { + return [ + "'use strict';", + '', + 'dbm = undefined', + 'type = undefined', + 'seed = undefined', + '', + 'exports.setup = (options, seedLink) ->', + ' dbm = options.dbmigrate', + ' type = dbm.dataType', + ' seed = seedLink', + '', + 'exports.up = (db) ->', + ' null', + '', + 'exports.down = (db) ->', + ' null', + '', + '' + ].join('\n'); +}; + +Template.prototype.defaultJsTemplate = function () { + return [ + "'use strict';", + '', + 'var dbm;', + 'var type;', + 'var seed;', + '', + '/**', + ' * We receive the dbmigrate dependency from dbmigrate initially.', + ' * This enables us to not have to rely on NODE_PATH.', + ' */', + 'exports.setup = function(options, seedLink) {', + ' dbm = options.dbmigrate;', + ' type = dbm.dataType;', + ' seed = seedLink;', + '};', + '', + 'exports.up = function(db) {', + ' return null;', + '};', + '', + 'exports.down = function(db) {', + ' return null;', + '};', + '', + 'exports._meta = {', + ' "version": 1', + '};', + '' + ].join('\n'); +}; + +Template.prototype.defaultSqlTemplate = function () { + return '/* Replace with your SQL commands */'; +}; + +Template.prototype.sqlFileLoaderTemplate = function () { + return [ + "'use strict';", + '', + 'var dbm;', + 'var type;', + 'var seed;', + "var fs = require('fs');", + "var path = require('path');", + 'var Promise;', + '', + '/**', + ' * We receive the dbmigrate dependency from dbmigrate initially.', + ' * This enables us to not have to rely on NODE_PATH.', + ' */', + 'exports.setup = function(options, seedLink) {', + ' dbm = options.dbmigrate;', + ' type = dbm.dataType;', + ' seed = seedLink;', + ' Promise = options.Promise;', + '};', + '', + 'exports.up = function(db) {', + " var filePath = path.join(__dirname, 'sqls', '" + + this.file.name.replace('.js', '') + + "-up.sql');", + ' return new Promise( function( resolve, reject ) {', + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", + ' if (err) return reject(err);', + " console.log('received data: ' + data);", + '', + ' resolve(data);', + ' });', + ' })', + ' .then(function(data) {', + ' return db.runSql(data);', + ' });', + '};', + '', + 'exports.down = function(db) {', + " var filePath = path.join(__dirname, 'sqls', '" + + this.file.name.replace('.js', '') + + "-down.sql');", + ' return new Promise( function( resolve, reject ) {', + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", + ' if (err) return reject(err);', + " console.log('received data: ' + data);", + '', + ' resolve(data);', + ' });', + ' })', + ' .then(function(data) {', + ' return db.runSql(data);', + ' });', + '};', + '', + 'exports._meta = {', + ' "version": 1', + '};', + '' + ].join('\n'); +}; + +Template.prototype.sqlFileLoaderIgnoreOnInitTemplate = function () { + return [ + "'use strict';", + '', + 'var dbm;', + 'var type;', + 'var seed;', + "var fs = require('fs');", + "var path = require('path');", + 'var ignoreOnInit = false;', + 'var Promise;', + '', + '/**', + ' * We receive the dbmigrate dependency from dbmigrate initially.', + ' * This enables us to not have to rely on NODE_PATH.', + ' */', + 'exports.setup = function(options, seedLink) {', + ' dbm = options.dbmigrate;', + ' ignoreOnInit = options.ignoreOnInit;', + ' type = dbm.dataType;', + ' seed = seedLink;', + ' Promise = options.Promise;', + '};', + '', + 'exports.up = function(db, callback) {', + " var filePath = path.join(__dirname + '/sqls/" + + this.file.name.replace('.js', '') + + "-up.sql');", + ' if (!ignoreOnInit) {', + ' return new Promise( function( resolve, reject ) {', + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", + ' if (err) return reject(err);', + " console.log('received data: ' + data);", + '', + ' resolve(data);', + ' });', + ' })', + ' .then(function(data) {', + ' return db.runSql(data);', + ' });', + ' }', + ' else {', + " console.log('ignoring on init: ' + filePath)", + ' return null;', + ' }', + '};', + '', + 'exports.down = function(db, callback) {', + " var filePath = path.join(__dirname + '/sqls/" + + this.file.name.replace('.js', '') + + "-down.sql');", + ' return new Promise( function( resolve, reject ) {', + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", + ' if (err) return reject(err);', + " console.log('received data: ' + data);", + '', + ' resolve(data);', + ' });', + ' })', + ' .then(function(data) {', + ' return db.runSql(data);', + ' });', + '};', + '', + 'exports._meta = {', + ' "version": 1', + '};', + '' + ].join('\n'); +}; + +Template.prototype.coffeeSqlFileLoaderTemplate = function () { + return [ + "'use strict';", + '', + 'dbm = undefined', + 'type = undefined', + 'seed = undefined', + "fs = require 'fs'", + "path = require 'path'", + '', + '#', + '# We receive the dbmigrate dependency from dbmigrate initially.', + '# This enables us to not have to rely on NODE_PATH.', + '#', + 'exports.setup = (options, seedLink) ->', + ' dbm = options.dbmigrate', + ' type = dbm.dataType', + ' seed = seedLink', + '', + '', + 'exports.up = (db, callback) ->', + ' filePath = path.join "#{__dirname}/sqls/' + + this.file.name.replace('.coffee', '') + + '-up.sql"', + " fs.readFile filePath, {encoding: 'utf-8'}, (err,data) ->", + ' return callback err if err', + '', + ' db.runSql data, callback', + '', + 'exports.down = (db, callback) ->', + ' filePath = path.join "#{__dirname}/sqls/' + + this.file.name.replace('.coffee', '') + + '-down.sql"', + + " fs.readFile filePath, {encoding: 'utf-8'}, (err,data) ->", + ' return callback err if err', + '', + ' db.runSql data, callback', + '' + ].join('\n'); +}; + +Template.TemplateType = { + DEFAULT_JS: 0, + DEFAULT_SQL: 1, + SQL_FILE_LOADER: 2, + DEFAULT_COFFEE: 3, + COFFEE_SQL_FILE_LOADER: 4, + SQL_FILE_LOADER_IGNORE_ON_INIT: 5 +}; + +Template.prototype.getTemplate = function () { + switch (this.templateType) { + case Template.TemplateType.DEFAULT_SQL: + return this.defaultSqlTemplate(); + case Template.TemplateType.SQL_FILE_LOADER: + return this.sqlFileLoaderTemplate(); + case Template.TemplateType.DEFAULT_COFFEE: + return this.defaultCoffeeTemplate(); + case Template.TemplateType.COFFEE_SQL_FILE_LOADER: + return this.coffeeSqlFileLoaderTemplate(); + case Template.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT: + return this.sqlFileLoaderIgnoreOnInitTemplate(); + case Template.TemplateType.DEFAULT_JS: + /* falls through */ + default: + return this.defaultJsTemplate(); + } +}; + +Template.prototype.write = function (callback) { + return this.file.write(this.getTemplate()).nodeify(callback); +}; + +module.exports = Template; diff --git a/lib/walker.js b/lib/walker.js index cc8027a1..086ff005 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -104,7 +104,9 @@ Walker.prototype = { .nodeify(callback); }, - up: function ({ destination: partialName, count }, callback) { + up: function (options, callback) { + const partialName = options.destination; + const count = options.count; return Promise.all([ File.loadFromFileystem(this.directory, this.prefix, this.internals), File.loadFromDatabase( @@ -141,7 +143,10 @@ Walker.prototype = { .nodeify(callback); }, - down: function ({ destination: partialName, count }, callback) { + down: function (options, callback) { + const partialName = options.destination; + const count = options.count; + return File.loadFromDatabase( this.directory, this.prefix, diff --git a/test/integration/create_test.js b/test/integration/create_test.js index 61a5b8c4..11b63a45 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -1,3 +1,5 @@ +'use strict'; + const Code = require('code'); const Lab = require('lab'); const lab = (exports.lab = Lab.script()); diff --git a/test/migration_test.js b/test/migration_test.js index 985451e9..8b51d0dc 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -1,3 +1,5 @@ +'use strict'; + const Code = require('code'); const Lab = require('lab'); const proxyquire = require('proxyquire').noPreserveCache(); From 4d3b626b618d13ed05bdb264a60bfa5b2ec985da Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 18:11:31 +0100 Subject: [PATCH 12/16] chore: finally remove old loaders Signed-off-by: Tobias Gurtzick --- lib/migration.js | 373 ----------------------------------------------- lib/migrator.js | 320 ---------------------------------------- lib/seed.js | 139 ------------------ lib/seeder.js | 367 ---------------------------------------------- lib/skeleton.js | 173 ---------------------- 5 files changed, 1372 deletions(-) delete mode 100644 lib/migration.js delete mode 100644 lib/migrator.js delete mode 100644 lib/seed.js delete mode 100644 lib/seeder.js delete mode 100644 lib/skeleton.js diff --git a/lib/migration.js b/lib/migration.js deleted file mode 100644 index b039d262..00000000 --- a/lib/migration.js +++ /dev/null @@ -1,373 +0,0 @@ -var fs = require('fs'); -var path = require('path'); -var log = require('db-migrate-shared').log; -var Skeleton = require('./skeleton'); -var Promise = require('bluebird'); - -var filesRegEx = /\.js$/; - -var Migration = Skeleton.extend({ - init: function () { - if (arguments.length >= 3) { - this.title = arguments[0]; - this.date = arguments[2]; - this.name = this.formatName(this.title, this.date); - this.path = this.formatPath(arguments[1], this.name); - this.templateType = arguments[3]; - this.internals = arguments[4]; - } else if (arguments.length === 2) { - this.path = arguments[0]; - this.name = this.parseName(this.path); - this.date = this.parseDate(this.name); - this.title = this.parseTitle(this.name); - this.internals = arguments[1]; - } - - if (this.internals) this._super(this.internals.migrationOptions); - } -}); - -Migration.registerHook = function (Plugin, internals) { - var plugin = Plugin.hook('migrator:migration:hook:require'); - internals.parser = internals.parser || { - filesRegEx: filesRegEx, - extensions: 'js' - }; - - if (!plugin) { - return Promise.resolve(null); - } - - return Promise.resolve(plugin) - .map(function (plugin) { - return plugin['migrator:migration:hook:require'](); - }) - .each(function (parser) { - if (parser && parser.extensions) { - internals.parser.extensions = - internals.parser.extensions + '|' + parser.extensions; - } - }) - .then(function () { - internals.parser.filesRegEx = new RegExp( - '\\.(' + internals.parser.extensions + ')$' - ); - - return internals.parser; - }); -}; - -Migration.prototype.defaultCoffeeTemplate = function () { - return [ - "'use strict';", - '', - 'dbm = undefined', - 'type = undefined', - 'seed = undefined', - '', - 'exports.setup = (options, seedLink) ->', - ' dbm = options.dbmigrate', - ' type = dbm.dataType', - ' seed = seedLink', - '', - 'exports.up = (db) ->', - ' null', - '', - 'exports.down = (db) ->', - ' null', - '', - '' - ].join('\n'); -}; - -Migration.prototype.defaultJsTemplate = function () { - return [ - "'use strict';", - '', - 'var dbm;', - 'var type;', - 'var seed;', - '', - '/**', - ' * We receive the dbmigrate dependency from dbmigrate initially.', - ' * This enables us to not have to rely on NODE_PATH.', - ' */', - 'exports.setup = function(options, seedLink) {', - ' dbm = options.dbmigrate;', - ' type = dbm.dataType;', - ' seed = seedLink;', - '};', - '', - 'exports.up = function(db) {', - ' return null;', - '};', - '', - 'exports.down = function(db) {', - ' return null;', - '};', - '', - 'exports._meta = {', - ' "version": 1', - '};', - '' - ].join('\n'); -}; - -Migration.prototype.defaultSqlTemplate = function () { - return '/* Replace with your SQL commands */'; -}; - -Migration.prototype.sqlFileLoaderTemplate = function () { - return [ - "'use strict';", - '', - 'var dbm;', - 'var type;', - 'var seed;', - "var fs = require('fs');", - "var path = require('path');", - 'var Promise;', - '', - '/**', - ' * We receive the dbmigrate dependency from dbmigrate initially.', - ' * This enables us to not have to rely on NODE_PATH.', - ' */', - 'exports.setup = function(options, seedLink) {', - ' dbm = options.dbmigrate;', - ' type = dbm.dataType;', - ' seed = seedLink;', - ' Promise = options.Promise;', - '};', - '', - 'exports.up = function(db) {', - " var filePath = path.join(__dirname, 'sqls', '" + - this.name.replace('.js', '') + - "-up.sql');", - ' return new Promise( function( resolve, reject ) {', - " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", - ' if (err) return reject(err);', - " console.log('received data: ' + data);", - '', - ' resolve(data);', - ' });', - ' })', - ' .then(function(data) {', - ' return db.runSql(data);', - ' });', - '};', - '', - 'exports.down = function(db) {', - " var filePath = path.join(__dirname, 'sqls', '" + - this.name.replace('.js', '') + - "-down.sql');", - ' return new Promise( function( resolve, reject ) {', - " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", - ' if (err) return reject(err);', - " console.log('received data: ' + data);", - '', - ' resolve(data);', - ' });', - ' })', - ' .then(function(data) {', - ' return db.runSql(data);', - ' });', - '};', - '', - 'exports._meta = {', - ' "version": 1', - '};', - '' - ].join('\n'); -}; - -Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function () { - return [ - "'use strict';", - '', - 'var dbm;', - 'var type;', - 'var seed;', - "var fs = require('fs');", - "var path = require('path');", - 'var ignoreOnInit = false;', - 'var Promise;', - '', - '/**', - ' * We receive the dbmigrate dependency from dbmigrate initially.', - ' * This enables us to not have to rely on NODE_PATH.', - ' */', - 'exports.setup = function(options, seedLink) {', - ' dbm = options.dbmigrate;', - ' ignoreOnInit = options.ignoreOnInit;', - ' type = dbm.dataType;', - ' seed = seedLink;', - ' Promise = options.Promise;', - '};', - '', - 'exports.up = function(db, callback) {', - " var filePath = path.join(__dirname + '/sqls/" + - this.name.replace('.js', '') + - "-up.sql');", - ' if (!ignoreOnInit) {', - ' return new Promise( function( resolve, reject ) {', - " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", - ' if (err) return reject(err);', - " console.log('received data: ' + data);", - '', - ' resolve(data);', - ' });', - ' })', - ' .then(function(data) {', - ' return db.runSql(data);', - ' });', - ' }', - ' else {', - " console.log('ignoring on init: ' + filePath)", - ' return null;', - ' }', - '};', - '', - 'exports.down = function(db, callback) {', - " var filePath = path.join(__dirname + '/sqls/" + - this.name.replace('.js', '') + - "-down.sql');", - ' return new Promise( function( resolve, reject ) {', - " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", - ' if (err) return reject(err);', - " console.log('received data: ' + data);", - '', - ' resolve(data);', - ' });', - ' })', - ' .then(function(data) {', - ' return db.runSql(data);', - ' });', - '};', - '', - 'exports._meta = {', - ' "version": 1', - '};', - '' - ].join('\n'); -}; - -Migration.prototype.coffeeSqlFileLoaderTemplate = function () { - return [ - "'use strict';", - '', - 'dbm = undefined', - 'type = undefined', - 'seed = undefined', - "fs = require 'fs'", - "path = require 'path'", - '', - '#', - '# We receive the dbmigrate dependency from dbmigrate initially.', - '# This enables us to not have to rely on NODE_PATH.', - '#', - 'exports.setup = (options, seedLink) ->', - ' dbm = options.dbmigrate', - ' type = dbm.dataType', - ' seed = seedLink', - '', - '', - 'exports.up = (db, callback) ->', - ' filePath = path.join "#{__dirname}/sqls/' + - this.name.replace('.coffee', '') + - '-up.sql"', - " fs.readFile filePath, {encoding: 'utf-8'}, (err,data) ->", - ' return callback err if err', - '', - ' db.runSql data, callback', - '', - 'exports.down = (db, callback) ->', - ' filePath = path.join "#{__dirname}/sqls/' + - this.name.replace('.coffee', '') + - '-down.sql"', - - " fs.readFile filePath, {encoding: 'utf-8'}, (err,data) ->", - ' return callback err if err', - '', - ' db.runSql data, callback', - '' - ].join('\n'); -}; - -Migration.TemplateType = { - DEFAULT_JS: 0, - DEFAULT_SQL: 1, - SQL_FILE_LOADER: 2, - DEFAULT_COFFEE: 3, - COFFEE_SQL_FILE_LOADER: 4, - SQL_FILE_LOADER_IGNORE_ON_INIT: 5 -}; - -Migration.prototype.getTemplate = function () { - switch (this.templateType) { - case Migration.TemplateType.DEFAULT_SQL: - return this.defaultSqlTemplate(); - case Migration.TemplateType.SQL_FILE_LOADER: - return this.sqlFileLoaderTemplate(); - case Migration.TemplateType.DEFAULT_COFFEE: - return this.defaultCoffeeTemplate(); - case Migration.TemplateType.COFFEE_SQL_FILE_LOADER: - return this.coffeeSqlFileLoaderTemplate(); - case Migration.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT: - return this.sqlFileLoaderIgnoreOnInitTemplate(); - case Migration.TemplateType.DEFAULT_JS: - /* falls through */ - default: - return this.defaultJsTemplate(); - } -}; - -Migration.prototype.write = function (callback) { - fs.writeFile(this.path, this.getTemplate(), callback); -}; - -Migration.loadFromFilesystem = function (dir, internals, callback) { - log.verbose('loading migrations from dir', dir); - fs.readdir(dir, function (err, files) { - if (err) { - callback(err); - return; - } - files = files.filter(function (file) { - return internals.parser.filesRegEx.test(file); - }); - var migrations = files.sort().map(function (file) { - return new Migration(path.join(dir, file), internals); - }); - callback(null, migrations); - }); -}; - -Migration.loadFromDatabase = function (dir, driver, internals, callback) { - if (internals.ignoreCompleted) { - callback(null, []); - } else { - log.verbose('loading migrations from database'); - driver.allLoadedMigrations(function (err, dbResults) { - if (err && !internals.dryRun) { - callback(err); - return; - } else if (err && internals.dryRun) { - dbResults = []; - } - var migrations = dbResults - .filter(function (result) { - return ( - result.name.substr(0, result.name.lastIndexOf('/')) === - internals.matching - ); - }) - .map(function (result) { - return new Migration(path.join(dir, result.name), internals); - }); - - callback(null, migrations); - }); - } -}; - -module.exports = Migration; diff --git a/lib/migrator.js b/lib/migrator.js deleted file mode 100644 index 02a62909..00000000 --- a/lib/migrator.js +++ /dev/null @@ -1,320 +0,0 @@ -var dbmUtil = require('db-migrate-shared').util; -var Migration = require('./migration'); -var log = require('db-migrate-shared').log; -var Promise = require('bluebird'); -var MigratorInterface = require('./interface/migratorInterface.js'); - -function SeedLink (driver, internals) { - this.seeder = require('./seeder.js')( - driver, - internals.argv['vcseeder-dir'], - true, - internals - ); - this.internals = internals; - this.links = []; -} -SeedLink.prototype = { - seed: function (partialName) { - var reset = !this.internals.notransactions; - - this.internals.notransactions = true; - - return new Promise(function (resolve, reject) { - this.seeder.up(partialName, function (err) { - if (reset) { - this.internals.notransactions = false; - } - - if (err) { - reject(err); - } else { - resolve(err); - } - }); - }); - }, - - link: function (partialName) { - this.links.push(partialName); - }, - - process: function () { - this.clear(); - }, - - clear: function () { - this.links = []; - } -}; - -var Migrator = function (driver, migrationsDir, empty, intern) { - this.driver = dbmUtil.reduceToInterface(driver, MigratorInterface); - this._driver = driver; - this.migrationsDir = migrationsDir; - this.internals = intern; - - if (intern.linked === false) { - this.seedLink = new SeedLink(driver, intern); - intern.linked = true; - } - - this.internals.migrationOptions.relation = require('./relation'); -}; - -Migrator.prototype = { - createMigrationsTable: function (callback) { - this._driver.createMigrationsTable(callback); - }, - - writeMigrationRecord: function (migration, callback) { - function onComplete (err) { - if (err) { - log.error(migration.name, err); - } else { - log.info('Processed migration', migration.name); - } - callback(err); - } - this._driver.addMigrationRecord( - this.internals.matching + '/' + migration.name, - onComplete - ); - }, - - deleteMigrationRecord: function (migration, callback) { - function onComplete (err) { - if (err) { - log.error(migration.name, err); - } else { - log.info('Processed migration', migration.name); - } - callback(err); - } - this._driver.deleteMigration( - this.internals.matching + '/' + migration.name, - function (err) { - if (!this.internals.matching) { - this._driver.deleteMigration(migration.name, onComplete); - } else { - onComplete.apply(err); - } - }.bind(this) - ); - }, - - up: function (funcOrOpts, callback) { - if (dbmUtil.isFunction(funcOrOpts)) { - return funcOrOpts(this.driver, callback); - } else { - this.upToBy(funcOrOpts.destination, funcOrOpts.count, callback); - } - }, - - down: function (funcOrOpts, callback) { - if (dbmUtil.isFunction(funcOrOpts)) { - return funcOrOpts(this.driver, callback); - } else { - this.downToBy(funcOrOpts.destination, funcOrOpts.count, callback); - } - }, - - check: function (funcOrOpts, callback) { - var self = this; - Migration.loadFromFilesystem(self.migrationsDir, self.internals, function ( - err, - allMigrations - ) { - if (err) { - callback(err); - return; - } - - Migration.loadFromDatabase( - self.migrationsDir, - self._driver, - self.internals, - function (err, completedMigrations) { - if (err) { - callback(err); - return; - } - - // Requires pr to export filterCompleted from db-migrate-shared - var toRun = dbmUtil.filterCompleted( - allMigrations, - completedMigrations - ); - - log.info('Migrations to run:', toRun.map(migration => migration.name)); - callback(null, toRun); - } - ); - }); - }, - - sync: function (funcOrOpts, callback) { - var self = this; - - Migration.loadFromDatabase( - self.migrationsDir, - self._driver, - self.internals, - function (err, completedMigrations) { - if (err) { - callback(err); - return; - } - - var mode = dbmUtil.syncMode( - completedMigrations, - funcOrOpts.destination - ); - if (mode === 1) { - log.info('Syncing upwards.'); - self.up(funcOrOpts, callback); - } else { - log.info('Syncing downwards.'); - self.down(funcOrOpts, callback); - } - } - ); - }, - - upToBy: function (partialName, count, callback) { - var self = this; - Migration.loadFromFilesystem(self.migrationsDir, self.internals, function ( - err, - allMigrations - ) { - if (err) { - callback(err); - return; - } - - Migration.loadFromDatabase( - self.migrationsDir, - self._driver, - self.internals, - function (err, completedMigrations) { - if (err) { - callback(err); - return; - } - var toRun = dbmUtil.filterUp( - allMigrations, - completedMigrations, - partialName, - count - ); - - if (toRun.length === 0) { - log.info('No migrations to run'); - callback(null); - return; - } - - if (self.internals.check) { - var toRunNames = toRun.map(migration => migration.name); - log.info('Migrations to run:', toRunNames); - callback(null, toRunNames); - return; - } - - return Promise.resolve(toRun) - .each(function (migration) { - log.verbose('preparing to run up migration:', migration.name); - - return self.driver - .startMigration() - .then(function () { - var setup = migration.setup(); - - if (typeof setup === 'function') { - setup(self.internals.migrationOptions, self.seedLink); - } - - return self.up(migration.up.bind(migration)); - }) - .then(function () { - if (self.seedLink && self.seedLink.links.length) { - log.info('Calling linked seeds'); - - return self.seedLink.process(); - } - }) - .then(function () { - return Promise.promisify( - self.writeMigrationRecord.bind(self) - )(migration); - }) - .then(self.driver.endMigration.bind(self.driver)); - }) - .nodeify(callback); - } - ); - }); - }, - - downToBy: function (partialName, count, callback) { - var self = this; - Migration.loadFromDatabase( - self.migrationsDir, - self._driver, - self.internals, - function (err, completedMigrations) { - if (err) { - return callback(err); - } - - var toRun = dbmUtil.filterDown(completedMigrations, partialName, count); - - if (toRun.length === 0) { - log.info('No migrations to run'); - callback(null); - return; - } - - if (self.internals.check) { - var toRunNames = toRun.map(migration => migration.name); - log.info('Migrations to run:', toRunNames); - callback(null, toRunNames); - return; - } - - return Promise.resolve(toRun) - .each(function (migration) { - log.verbose('preparing to run down migration:', migration.name); - - return self.driver - .startMigration() - .then(function () { - var setup = migration.setup(); - - if (typeof setup === 'function') { - setup(self.internals.migrationOptions, self.seedLink); - } - - return self.down(migration.down.bind(migration)); - }) - .then(function () { - if (self.seedLink && self.seedLink.links.length) { - log.info('Calling linked seeds'); - - return self.seedLink.process(); - } - }) - .then(function () { - return Promise.promisify( - self.deleteMigrationRecord.bind(self) - )(migration); - }) - .then(self.driver.endMigration.bind(self.driver)); - }) - .nodeify(callback); - } - ); - } -}; - -module.exports = Migrator; diff --git a/lib/seed.js b/lib/seed.js deleted file mode 100644 index 5bdbf6fc..00000000 --- a/lib/seed.js +++ /dev/null @@ -1,139 +0,0 @@ -var fs = require('fs'); -var path = require('path'); -var log = require('db-migrate-shared').log; -var Skeleton = require('./skeleton'); - -var Seed = Skeleton.extend({ - init: function () { - if (arguments.length >= 3) { - this.title = arguments[0]; - this.date = arguments[2]; - this.name = this.formatName(this.title, this.date); - this.path = this.formatPath(arguments[1], this.name); - this.templateType = arguments[3]; - this.internals = arguments[4]; - } else if (arguments.length === 2) { - this.path = arguments[0]; - this.name = this.parseName(this.path); - this.date = this.parseDate(this.name); - this.title = this.parseTitle(this.name); - this.internals = arguments[1]; - } - - this._super(this.internals); - }, - - up: function (db, isStatic) { - if (isStatic) { - var seed = require(this.path); - var cbExecuted = false; - - return new Promise( - function (resolve, reject) { - var r = function (err) { - if (cbExecuted === false) { - cbExecuted = true; - - if (err) { - log.error('Error while truncating static seed.'); - reject(err); - } else resolve(); - } - }; - - Promise.resolve(seed.truncate.apply(this, [db, r])) - .then(function (Promise) { - if (Promise !== undefined && cbExecuted === false) { - cbExecuted = true; - resolve(); - } - }) - .catch(function (err) { - if (cbExecuted === false) { - cbExecuted = true; - reject(err); - } - }); - }.bind(this) - ).then(function () { - var seedExecuted = false; - - return new Promise(function (resolve, reject) { - var r = function (err) { - if (seedExecuted === false) { - seedExecuted = true; - - if (err) { - log.error('Error while seeding static seed.'); - reject(err); - } else resolve(); - } - }; - - Promise.resolve(seed.seed.apply(this, [db, r])) - .then(function (Promise) { - if (Promise !== undefined && seedExecuted === false) { - seedExecuted = true; - resolve(); - } - }) - .catch(function (err) { - if (seedExecuted === false) { - seedExecuted = true; - reject(err); - } - }); - }); - }); - } else { - return this._up(db); - } - }, - - down: function (db) { - return this._down(db); - } -}); - -Seed.loadFromFilesystem = function (dir, internals, callback) { - log.verbose('loading seeds from dir', dir); - fs.readdir(dir, function (err, files) { - if (err) { - callback(err); - return; - } - files = files.filter(function (file) { - return internals.parser.filesRegEx.test(file); - }); - var seeds = files.sort().map(function (file) { - return new Seed(path.join(dir, file), internals); - }); - callback(null, seeds); - }); -}; - -Seed.loadFromDatabase = function (dir, driver, internals, callback) { - log.verbose('loading seeds from database'); - driver.allLoadedSeeds(function (err, dbResults) { - if (err && !internals.dryRun) { - callback(err); - return; - } else if (err && internals.dryRun) { - dbResults = []; - } - var seeds = dbResults - .filter(function (result) { - return ( - result.name.substr(0, result.name.lastIndexOf('/')) === - internals.matching - ); - }) - .map(function (result) { - return new Seed(path.join(dir, result.name), internals); - }); - - callback(null, seeds); - }); -}; - -module.exports = Seed; diff --git a/lib/seeder.js b/lib/seeder.js deleted file mode 100644 index 072fc7ff..00000000 --- a/lib/seeder.js +++ /dev/null @@ -1,367 +0,0 @@ -var Seed = require('./seed'); -var log = require('db-migrate-shared').log; -var dbmUtil = require('db-migrate-shared').util; -var Promise = require('bluebird'); -var SeederInterface = require('./interface/seederInterface.js'); - -var internals = {}; - -function MigrationLink (driver, internals) { - this.migrator = require('./migrator.js')( - driver, - internals.migrationsDir, - null, - internals - ); - this.links = []; -} - -MigrationLink.prototype = { - link: function (partialName) { - this.links.push(partialName); - }, - - migrate: function (partialName) { - var reset = !internals.notransactions; - - internals.notransactions = true; - - return new Promise(function (resolve, reject) { - this.migrator.up(partialName, function (err) { - if (reset) { - internals.notransactions = false; - } - - if (err) { - reject(err); - } else { - resolve(err); - } - }); - }); - }, - - process: function () { - var reset = !internals.notransactions; - - internals.notransactions = true; - - return new Promise( - function (resolve, reject) { - var keys = Object.keys(this.links); - var i = 0; - - var migrate = function (i) { - if (i < keys.length) { - if (reset) { - internals.notransactions = false; - } - - resolve(); - this.clear(); - } - - this.migrator.up( - { - destination: this.links[keys[i]] - }, - function (err) { - if (err) { - if (reset) { - internals.notransactions = false; - } - - reject(err); - } else { - migrate(++i); - } - } - ); - }.bind(this); - - migrate(i); - }.bind(this) - ); - }, - - clear: function () { - this.links = []; - } -}; - -var Seeder = function (driver, seedsDir, versionControlled, intern) { - SeederInterface.extending = intern.interfaces.SeederInterface; - this.driver = dbmUtil.reduceToInterface(driver, SeederInterface); - this._driver = driver; - this.seedDir = seedsDir; - this.isVC = versionControlled; - - if (intern.linked === false) { - intern.linked = true; - this.migrationLink = new MigrationLink(driver, intern); - } - - internals = intern; - this.internals = intern; -}; - -Seeder.prototype = { - createSeedsTable: function (callback) { - this._driver.createSeedsTable(callback); - }, - - seed: function (argv, callback) { - if (this.isVC) { - this.up(argv, callback); - } else { - this._staticSeed(argv.destination, callback); - } - }, - - up: function (funcOrOpts, callback) { - if (dbmUtil.isFunction(funcOrOpts)) { - return funcOrOpts(this.driver, false, callback); - } else { - this.upToBy(funcOrOpts.destination, funcOrOpts.count, callback); - } - }, - - down: function (funcOrOpts, callback) { - if (dbmUtil.isFunction(funcOrOpts)) { - return funcOrOpts(this.driver, callback); - } else { - this.downToBy(funcOrOpts.count, callback); - } - }, - - /** - * Statically call two methods from a static seeder. - * - * First: cleanSeeds - * Second: seed - * - * It's highly recommended to not use version controlled seeders at the same - * time as statics. While the cleanSeeds most of the time, the user executes - * truncates or deletes on his database. A VC-Seeder can't detect this - * and thus the state keeps the same, even if all changes of the VC-Seeder - * are gone. - * - * Nevertheless, there is a possiblity to use static seeders together with - * VC-Seeder, if you keep everything organized well at least. - * - * If a single seed is linked with it's tables and databases which it got - * applied to, the state table of the seeds will automatically cleaned up. - * - */ - _staticSeed: function (partialName, callback) { - var self = this; - - return Seed.loadFromFilesystem(self.seedDir, self.internals, function ( - err, - allSeeds - ) { - if (err) { - callback(err); - return; - } - - var toRun = dbmUtil.filterUp(allSeeds, [], partialName); - - if (toRun.length === 0) { - log.info('No seeds to run'); - callback(null); - return; - } - - return Promise.resolve(toRun) - .each(function (seeder) { - log.verbose('preparing to run up seeder:', seeder.name); - - var setup = seeder.setup(); - if (typeof setup === 'function') { - setup(self.internals.seederOptions); - } - - return self._driver - .startMigration() - .catch(callback) - .then(function () { - return seeder.up(self.driver, true); - }); - }) - .then(self._driver.endMigration.bind(self.driver)) - .then(function () { - callback(); - }) - .catch(function (e) { - throw e; - }); - }); - }, - - writeSeedRecord: function (seed, callback) { - function onComplete (err) { - if (err) { - log.error(seed.name, err); - } else { - log.info('Processed seed', seed.name); - } - callback(err); - } - this._driver.addSeedRecord( - this.internals.matching + '/' + seed.name, - onComplete - ); - }, - - deleteSeedRecord: function (seed, callback) { - function onComplete (err) { - if (err) { - log.error(seed.name, err); - } else { - log.info('Processed seed', seed.name); - } - callback(err); - } - this._driver.deleteSeed( - this.internals.matching + '/' + seed.name, - function (err) { - if (!this.internals.matching) { - this._driver.deleteSeed(seed.name, onComplete); - } else { - onComplete.apply(err); - } - }.bind(this) - ); - }, - - upToBy: function (partialName, count, callback) { - var self = this; - - return Seed.loadFromFilesystem(self.seedDir, self.internals, function ( - err, - allMigrations - ) { - if (err) { - callback(err); - return; - } - - return Seed.loadFromDatabase( - self.seedDir, - self._driver, - self.internals, - function (err, completedSeeds) { - if (err) { - callback(err); - return; - } - var toRun = dbmUtil.filterUp( - allMigrations, - completedSeeds, - partialName, - count - ); - - if (toRun.length === 0) { - log.info('No seeds to run'); - callback(null); - return; - } - - return Promise.resolve(toRun) - .each(function (seeder) { - log.verbose('preparing to run up seeder:', seeder.name); - - return self._driver - .startMigration() - .then(function () { - var setup = seeder.setup(); - if (typeof setup === 'function') { - setup(self.internals.seederOptions, self.migrationLink); - } - - return self.up(seeder.up.bind(seeder)); - }) - .then(function () { - if (self.seedLink && self.seedLink.links.length) { - log.info('Calling linked migrations'); - - return self.seedLink.process(self.migrationLink); - } - }) - .then(function () { - return Promise.promisify( - self.writeSeedRecord.bind(self) - )(seeder); - }) - .then(self._driver.endMigration.bind(self.driver)) - .catch(function (e) { - throw e; - }); - }) - .then(function () { - callback(); - }); - } - ); - }); - }, - - downToBy: function (count, callback) { - var self = this; - Seed.loadFromDatabase(self.seedDir, self._driver, self.internals, function ( - err, - completedSeeds - ) { - if (err) { - return callback(err); - } - - var toRun = dbmUtil.filterDown(completedSeeds, count); - - if (toRun.length === 0) { - log.info('No migrations to run'); - callback(null); - return; - } - - return Promise.resolve(toRun) - .each(function (seeder) { - log.verbose('preparing to run down seeder:', seeder.name); - - return self._driver - .startMigration() - .then(function () { - var setup = seeder.setup(); - - if (typeof setup === 'function') { - setup(self.internals.seederOptions, self.migrationLink); - } - - return self.down(seeder.down.bind(seeder)); - }) - .then(function () { - if (self.seedLink && self.seedLink.links.length) { - log.info('Calling linked migrations'); - - return self.seedLink.process(); - } - }) - .then(function () { - return Promise.promisify( - self.deleteSeedRecord.bind(self) - )(seeder); - }) - .then(self._driver.endMigration.bind(self.driver)) - .catch(function (e) { - throw e; - }); - }) - .then(function () { - callback(); - }); - }); - } -}; -module.exports = Seeder; diff --git a/lib/skeleton.js b/lib/skeleton.js deleted file mode 100644 index 0adca10b..00000000 --- a/lib/skeleton.js +++ /dev/null @@ -1,173 +0,0 @@ -var path = require('path'); -var inflection = require('inflection'); -var Promise = require('bluebird'); -var lpad = require('db-migrate-shared').util.lpad; -var Class = require('./class'); - -function isPromise (probe) { - return ( - probe instanceof Promise || - (probe && - probe.then && - probe.constructor && - probe.constructor.name === 'Promise') - ); -} - -function formatPath (dir, name) { - return path.join(dir, name); -} - -function formatName (title, date) { - return formatDate(date) + '-' + formatTitle(title); -} - -function formatDate (date) { - return [ - date.getUTCFullYear(), - lpad(date.getUTCMonth() + 1, '0', 2), - lpad(date.getUTCDate(), '0', 2), - lpad(date.getUTCHours(), '0', 2), - lpad(date.getUTCMinutes(), '0', 2), - lpad(date.getUTCSeconds(), '0', 2) - ].join(''); -} - -function formatTitle (title) { - return inflection.dasherize(title); -} - -function parseDate (name) { - var date = new Date(); - var match = name.match(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-[^.]+/); - date.setUTCFullYear(match[1]); - date.setUTCDate(match[3]); - date.setUTCMonth(match[2] - 1); - date.setUTCHours(match[4]); - date.setUTCMinutes(match[5]); - date.setUTCSeconds(match[6]); - return date; -} - -function parseTitle (name) { - var match = name.match(/\d{14}-([^.]+)/); - var dashed = match[1]; - return inflection.humanize(dashed, true); -} - -var Skeleton = Class.extend({ - init: function (intern) { - this.internals = intern; - }, - - _up: function () { - var params = arguments; - - var cbExecuted = false; - - return new Promise( - function (resolve, reject) { - var migration; - var r = function (err) { - if (cbExecuted === false) { - cbExecuted = true; - - if (err) { - reject(err); - } else { - resolve(); - } - } - }; - - params[params.length++] = r; - - migration = require(this.path).up.apply(this, params); - - if (migration === null) migration = Promise.resolve(); - if (isPromise(migration)) { - migration - .then(function () { - if (cbExecuted === false) { - cbExecuted = true; - resolve(); - } - }) - .catch(function (err) { - if (cbExecuted === false) { - cbExecuted = true; - reject(err); - } - }); - } - }.bind(this) - ); - }, - - _down: function () { - var params = arguments; - var cbExecuted = false; - - return new Promise( - function (resolve, reject) { - var migration; - var r = function (err) { - if (cbExecuted === false) { - cbExecuted = true; - - if (err) { - reject(err); - } else { - resolve(); - } - } - }; - - params[params.length++] = r; - migration = require(this.path).down.apply(this, params); - - if (migration === null) migration = Promise.resolve(); - if (isPromise(migration)) { - migration - .then(function () { - if (cbExecuted === false) { - cbExecuted = true; - resolve(); - } - }) - .catch(function (err) { - if (cbExecuted === false) { - cbExecuted = true; - reject(err); - } - }); - } - }.bind(this) - ); - }, - - up: function (db) { - return this._up(db); - }, - - down: function (db) { - return this._down(db); - }, - - setup: function () { - return require(this.path).setup; - }, - - parseName: function (path) { - var match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); - return match[1]; - }, - - parseTitle: parseTitle, - parseDate: parseDate, - formatTitle: formatTitle, - formatPath: formatPath, - formatName: formatName -}); - -module.exports = Skeleton; From 29c703dfe46fa743333937ca753fd49278bc55d4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 18:27:34 +0100 Subject: [PATCH 13/16] refactor: disconnect create from connect Signed-off-by: Tobias Gurtzick --- connect.js | 12 ------------ lib/commands/create-migration.js | 12 +++++------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/connect.js b/connect.js index 1d5aeb6d..897389db 100644 --- a/connect.js +++ b/connect.js @@ -11,7 +11,6 @@ var log = require('db-migrate-shared').log; exports.connect = function (config, PassedClass, callback) { var internals = {}; var prefix = 'migration'; - var migrationsDir; if (config.config) { prefix = config.prefix || prefix; internals = config.internals; @@ -194,14 +193,3 @@ function migrationFiles ( } }); } - -exports.createMigration = function (migration, callback) { - migration.write(function (err) { - if (err) { - callback(err); - return; - } - - callback(null, migration); - }); -}; diff --git a/lib/commands/create-migration.js b/lib/commands/create-migration.js index 23162c54..3d0e0006 100644 --- a/lib/commands/create-migration.js +++ b/lib/commands/create-migration.js @@ -42,7 +42,6 @@ function executeCreateMigration (internals, config, callback) { } createMigrationDir(migrationsDir, function (err) { - const index = require('../../connect'); const Migration = require('../template.js'); if (err) { @@ -91,7 +90,7 @@ function executeCreateMigration (internals, config, callback) { internals.runTimestamp, templateType ); - index.createMigration(migration, function (err, migration) { + migration.write(function (err) { if (_assert(err, callback)) { log.info(util.format('Created migration at %s', migration.file.path)); if (shouldCreateSqlFiles(internals, config)) { @@ -128,7 +127,6 @@ function createSqlFiles (internals, config, callback) { const sqlDir = migrationsDir + '/sqls'; createMigrationDir(sqlDir, function (err) { - const index = require('../../connect'); const Migration = require('../template.js'); if (err) { @@ -148,12 +146,12 @@ function createSqlFiles (internals, config, callback) { internals.runTimestamp, templateTypeDefaultSQL ); - index.createMigration(migrationUpSQL, function (err, migration) { + migrationUpSQL.write(function (err) { if (_assert(err, callback)) { log.info( util.format( 'Created migration up sql file at %s', - migration.file.path + migrationUpSQL.file.path ) ); @@ -163,12 +161,12 @@ function createSqlFiles (internals, config, callback) { internals.runTimestamp, templateTypeDefaultSQL ); - index.createMigration(migrationDownSQL, function (err, migration) { + migrationDownSQL.write(function (err) { if (_assert(err, callback)) { log.info( util.format( 'Created migration down sql file at %s', - migration.file.path + migrationDownSQL.file.path ) ); if (typeof callback === 'function') callback(); From dd0e50783034fd8b356ae254463b1d06285a169d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 10 Apr 2018 21:15:58 +0200 Subject: [PATCH 14/16] chore: refactor check to new loader Signed-off-by: Tobias Gurtzick --- lib/commands/check.js | 46 +++++++++++++++++++++++++++---------------- lib/walker.js | 32 ++++++++++++++++++++++++++++++ test/migrator_test.js | 25 ++++++++++++----------- 3 files changed, 74 insertions(+), 29 deletions(-) diff --git a/lib/commands/check.js b/lib/commands/check.js index 63891ff6..d4c1f6b0 100644 --- a/lib/commands/check.js +++ b/lib/commands/check.js @@ -4,24 +4,33 @@ var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); module.exports = function (internals, config, callback) { - migrationHook(internals) - .then(function () { - var Migrator = require('../migrator.js'); - var index = require('../../connect'); + migrationHook(internals).then(function () { + var Migrator = require('../walker.js'); + var index = require('../../connect'); - if (!internals.argv.count) { - internals.argv.count = Number.MAX_VALUE; - } - index.connect({ + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect( + { config: config.getCurrent().settings, - internals: internals - }, Migrator, function (err, migrator) { + internals: internals, + prefix: 'migration' + }, + Migrator, + function (err, migrator) { if (!assert(err, callback)) return; if (internals.locTitle) { - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], - internals.locTitle); - } else { migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); } + migrator.migrationsDir = path.resolve( + internals.argv['migrations-dir'], + internals.locTitle + ); + } else { + migrator.migrationsDir = path.resolve( + internals.argv['migrations-dir'] + ); + } internals.migrationsDir = migrator.migrationsDir; @@ -29,9 +38,12 @@ module.exports = function (internals, config, callback) { if (!assert(err, callback)) return; log.verbose('migration table created'); - migrator.check(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); + migrator.check( + internals.argv, + internals.onComplete.bind(this, migrator, internals, callback) + ); }); - }); - }); + } + ); + }); }; diff --git a/lib/walker.js b/lib/walker.js index 086ff005..81f9c5df 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -128,6 +128,12 @@ Walker.prototype = { log.info(this.title + 'Nothing to run'); } + if (this.internals.check) { + const toRunNames = toRun.map(migration => migration.name); + log.info(this.title + 'run:', toRunNames); + return []; + } + return toRun; }) .each(file => { @@ -160,6 +166,12 @@ Walker.prototype = { log.info(this.title + 'Nothing to run'); } + if (this.internals.check) { + const toRunNames = toRun.map(migration => migration.name); + log.info(this.title + 'To run:', toRunNames); + return []; + } + return toRun; }) .each(file => { @@ -173,6 +185,26 @@ Walker.prototype = { ); }) .nodeify(callback); + }, + + check: function (options, callback) { + return Promise.all([ + File.loadFromDatabase( + this.directory, + this.prefix, + this._driver, + this.internals + ), + File.loadFromFileystem(this.directory, this.prefix, this.internals) + ]) + .spread((completedFiles, allFiles) => { + // Requires pr to export filterCompleted from db-migrate-shared + const toRun = dbmUtil.filterCompleted(allFiles, completedFiles); + + log.info('Files to run:', toRun.map(migration => migration.name)); + return toRun; + }) + .nodeify(callback); } }; diff --git a/test/migrator_test.js b/test/migrator_test.js index 3ac29fc7..f3493fc1 100644 --- a/test/migrator_test.js +++ b/test/migrator_test.js @@ -1,24 +1,25 @@ -var Code = require('code'); -var Lab = require('lab'); -var proxyquire = require('proxyquire').noPreserveCache(); -var lab = (exports.lab = Lab.script()); +const Promise = require('bluebird'); +const Code = require('code'); +const Lab = require('lab'); +const proxyquire = require('proxyquire').noPreserveCache(); +const lab = (exports.lab = Lab.script()); lab.experiment('migrators', function () { lab.experiment('check', function () { lab.test('should return the migrations to be run', function (done) { - var completedMigration = { + const completedMigration = { name: '20180330020329-thisMigrationIsCompleted' }; - var uncompletedMigration = { + const uncompletedMigration = { name: '20180330020330-thisMigrationIsNotCompleted' }; - var Migrator = proxyquire('../lib/migrator.js', { - './migration': { - loadFromFilesystem: (migrationsDir, internals, cb) => { - return cb(null, [completedMigration, uncompletedMigration]); + const Migrator = proxyquire('../lib/walker.js', { + './file.js': { + loadFromFileystem: (migrationsDir, prefix, internals) => { + return Promise.resolve([uncompletedMigration]); }, - loadFromDatabase: (migrationsDir, driver, internals, cb) => { - return cb(null, [completedMigration]); + loadFromDatabase: (migrationsDir, prefix, driver, internals) => { + return Promise.resolve([completedMigration]); } } }); From 6144472631dda7e79108a648a5eb7be04b106057 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 11 Apr 2018 01:38:37 +0200 Subject: [PATCH 15/16] chore: return array of files correctly on check Signed-off-by: Tobias Gurtzick --- lib/walker.js | 76 +++++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/lib/walker.js b/lib/walker.js index 81f9c5df..603ec278 100644 --- a/lib/walker.js +++ b/lib/walker.js @@ -107,7 +107,7 @@ Walker.prototype = { up: function (options, callback) { const partialName = options.destination; const count = options.count; - return Promise.all([ + const files = Promise.all([ File.loadFromFileystem(this.directory, this.prefix, this.internals), File.loadFromDatabase( this.directory, @@ -115,27 +115,32 @@ Walker.prototype = { this._driver, this.internals ) - ]) - .spread((allFiles, completedFiles) => { - const toRun = dbmUtil.filterUp( - allFiles, - completedFiles, - partialName, - count - ); + ]).spread((allFiles, completedFiles) => { + const toRun = dbmUtil.filterUp( + allFiles, + completedFiles, + partialName, + count + ); + + if (toRun.length === 0) { + log.info(this.title + 'Nothing to run'); + } - if (toRun.length === 0) { - log.info(this.title + 'Nothing to run'); - } + if (this.internals.check) { + const toRunNames = toRun.map(migration => migration.name); + log.info(this.title + 'run:', toRunNames); + return toRunNames; + } - if (this.internals.check) { - const toRunNames = toRun.map(migration => migration.name); - log.info(this.title + 'run:', toRunNames); - return []; - } + return toRun; + }); - return toRun; - }) + if (this.internals.check) { + return files.nodeify(callback); + } + + return files .each(file => { log.verbose(this.title + 'preparing to run up:', file.name); const _meta = file.get()._meta || {}; @@ -153,27 +158,32 @@ Walker.prototype = { const partialName = options.destination; const count = options.count; - return File.loadFromDatabase( + const files = File.loadFromDatabase( this.directory, this.prefix, this._driver, this.internals - ) - .then(completedFiles => { - const toRun = dbmUtil.filterDown(completedFiles, partialName, count); + ).then(completedFiles => { + const toRun = dbmUtil.filterDown(completedFiles, partialName, count); - if (toRun.length === 0) { - log.info(this.title + 'Nothing to run'); - } + if (toRun.length === 0) { + log.info(this.title + 'Nothing to run'); + } - if (this.internals.check) { - const toRunNames = toRun.map(migration => migration.name); - log.info(this.title + 'To run:', toRunNames); - return []; - } + if (this.internals.check) { + const toRunNames = toRun.map(migration => migration.name); + log.info(this.title + 'run:', toRunNames); + return toRunNames; + } - return toRun; - }) + return toRun; + }); + + if (this.internals.check) { + return files.nodeify(callback); + } + + return files .each(file => { log.verbose(this.title + 'preparing to run down:', file.name); const _meta = file.get()._meta || {}; From 61ca5bb3a6067759984de6d5f141d38efe997805 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 11 Apr 2018 01:50:13 +0200 Subject: [PATCH 16/16] fix(reset): regression introduced in check functionality #552 introduced a regression and effectively disfunctioned the reset function, since it did append just to the actionables within the run context. It was moved into its own context. Signed-off-by: Tobias Gurtzick --- lib/commands/run.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/commands/run.js b/lib/commands/run.js index 40bffeb5..bfdfe819 100644 --- a/lib/commands/run.js +++ b/lib/commands/run.js @@ -42,7 +42,6 @@ function run (internals, config) { break; case 'up': case 'down': - case 'check': case 'reset': if (action === 'reset') internals.argv.count = Number.MAX_VALUE; @@ -63,15 +62,22 @@ function run (internals, config) { if (action === 'up') { var executeUp = load('up'); executeUp(internals, config); - } else if (action === 'down') { + } else { var executeDown = load('down'); executeDown(internals, config); - } else { - var executeCheck = load('check'); - executeCheck(internals, config); } break; + case 'check': + var executeCheck = load('check'); + + if (folder[1]) { + internals.matching = folder[1]; + internals.migrationMode = folder[1]; + } + + executeCheck(internals, config); + break; case 'db': if (folder.length < 1) { log.info('Please enter a valid command, i.e. db:create|db:drop');