From 1bea1994dec298b26fe95836e8c55149179b0f36 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 26 Mar 2015 07:49:03 +0100 Subject: [PATCH 001/412] update dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 05285080..01177c4f 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "mkdirp": "~0.5.0", "moment": "~2.9.0", "mongodb": "^2.0.23", - "mysql": "~2.5.4", + "mysql": "~2.6.0", "optimist": "~0.6.1", "parse-database-url": "~0.2.2", "pg": "~4.3.0", From 50429e0957e2f47ce96b613d7f17a0f8f3e0da41 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 28 Mar 2015 08:35:50 +0100 Subject: [PATCH 002/412] add relation.js --- lib/driver/shadow.js | 1 + lib/migrator.js | 2 ++ lib/relation.js | 0 3 files changed, 3 insertions(+) create mode 100644 lib/relation.js diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 29c67dc7..5b41529f 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -42,6 +42,7 @@ exports.infect = function(db, intern) { db._shadowsHost[prop] = db[prop]; (function(property) { + db[property] = function() { this._shadowsHost[property].apply(this, arguments); }; }(prop)); } diff --git a/lib/migrator.js b/lib/migrator.js index 8999e364..0fb69cc9 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -11,6 +11,8 @@ Migrator = function(driver, migrationsDir, empty, intern) { this.migrationsDir = migrationsDir; internals = intern; + internals.migrationOptions.relation = require('./relation'); + Migration.exportInternals(intern); }; diff --git a/lib/relation.js b/lib/relation.js new file mode 100644 index 00000000..e69de29b From d82633a0f3d2572d615e3f69be70314ae9da0e91 Mon Sep 17 00:00:00 2001 From: Jared Wolinsky Date: Sun, 29 Mar 2015 13:34:59 -0400 Subject: [PATCH 003/412] Add support for connecting to the database through an SSH tunnel. --- README.md | 26 ++++++++++ lib/driver/index.js | 51 +++++++++++++++---- package.json | 5 +- test/driver/index_test.js | 104 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 11 deletions(-) create mode 100644 test/driver/index_test.js diff --git a/README.md b/README.md index 126ab9cb..9817b103 100644 --- a/README.md +++ b/README.md @@ -381,6 +381,32 @@ It's currently also not possible to switch the database over this config with ** "schema": "test" } ``` + +## Connecting through an SSH tunnel + +If you need to connect to the database through an SSH tunnel, you can set the `tunnel` config: + +```json +{ + "tunnel": { + "localPort" : 33333, + "host": "ssh-machine.example.com", + "username": "sshuser", + "privateKeyPath": "/home/sshuser/privatekey.pem" + } +} +``` + +One common use case for this is when the remote DB does not accept connections from the host that will be running db-migrate. For example, a database within an AWS +[Virtual Private Cloud (VPC)](http://aws.amazon.com/vpc) that is only open to [EC2](http://aws.amazon.com/ec2) hosts within the same VPC. By pointing the tunnel sshConfig to a host within the DB's +VPC, you can run your migrations from any host. + +### Tunnel configuration properties + +The `tunnel` config must specify the `localPort` in addition to any configuration necessary to connect to the SSH tunnel. Please see the [https://github.com/Finanzchef24-GmbH/tunnel-ssh](tunnel-ssh) +documentation for more details about what properties to set on the tunnel config. The only addition to that config is the `privateKeyPath` property. If the connection to your SSH host +requires a private key file, you can specify its path using this property. + ## Defaults ## Generic Datatypes diff --git a/lib/driver/index.js b/lib/driver/index.js index bdf3c331..50731cf9 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -6,7 +6,7 @@ internals.mod.type = require('../data_type'); internals.mod.Class = require('../class'); var Shadow = require('./shadow'); var log = internals.mod.log; - +var tunnel = require('tunnel-ssh'); exports.connect = function (config, intern, callback) { var driver, req; @@ -51,18 +51,49 @@ exports.connect = function (config, intern, callback) { } log.verbose('connecting'); - driver.connect(config, intern, function (err, db) { - if (err) { + var connect = function(config) { + driver.connect(config, intern, function (err, db) { + + if (err) { + + callback(err); + return; + } + log.verbose('connected'); + + if (!global.immunity) + db = Shadow.infect(db); + + callback(null, db); + }); + }; + + if (config.tunnel) { + var tunnelConfig = JSON.parse(JSON.stringify(config.tunnel)); + tunnelConfig.dstHost = config.host; + tunnelConfig.dstPort = config.port; - callback(err); - return; + if (tunnelConfig.privateKeyPath) { + tunnelConfig.privateKey = require('fs').readFileSync(tunnelConfig.privateKeyPath); } - log.verbose('connected'); - if(!global.immunity) - db = Shadow.infect(db); + // Reassign the db host/port to point to our local ssh tunnel + config.host = '127.0.0.1'; + config.port = tunnelConfig.localPort; - callback(null, db); - }); + tunnel(tunnelConfig, function (err) { + + if (err) { + callback(err); + return; + } + log.verbose('SSH tunnel connected on port ', tunnelConfig.localPort); + + connect(config); + }); + } + else { + connect(config); + } }; \ No newline at end of file diff --git a/package.json b/package.json index 01177c4f..f5302bc3 100644 --- a/package.json +++ b/package.json @@ -38,13 +38,16 @@ "pg-native": "^1.8.0", "pkginfo": "~0.3.0", "semver": "~4.3.0", - "sqlite3": "~3.0.4" + "sqlite3": "~3.0.4", + "tunnel-ssh": "^1.0.0" }, "devDependencies": { "code": "^1.3.0", "db-meta": "~0.4.1", "lab": "^5.2.1", + "proxyquire": "^1.4.0", "rimraf": "~2.3.2", + "sinon": "^1.14.1", "vows": "0.8.0" }, "scripts": { diff --git a/test/driver/index_test.js b/test/driver/index_test.js new file mode 100644 index 00000000..3ce511b6 --- /dev/null +++ b/test/driver/index_test.js @@ -0,0 +1,104 @@ +var vows = require('vows'); +var assert = require('assert'); +var proxyquire = require('proxyquire'); +var sinon = require('sinon'); + +var validDbConfigWithTunnel = { + driver: 'mysql', + host: 'dbHost', + port: 'dbPort', + tunnel: { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort' + } +}; + +var indexConnectCallback = function(self, tunnelStub, driverSpy) { + return function(err, db) { + if (err) { + self.callback(err, db, tunnelStub, driverSpy); + return; + } + db.close(function() { + self.callback(err, db, tunnelStub, driverSpy); + }); + } +}; + +vows.describe('index').addBatch({ + 'a connection with ssh tunnel': { + topic: function() { + // Ensure that require gets a new copy of the module for each test + delete require.cache[require.resolve('../../lib/driver/mysql')]; + var driver = require('../../lib/driver/mysql'); + + // Set up stubs/spies to verify correct flow + var driverSpy = sinon.spy(driver, 'connect'); + var tunnelStub = sinon.stub().callsArg(1); + + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + './mysql': driver + }); + + index.connect(validDbConfigWithTunnel, {}, indexConnectCallback(this, tunnelStub, driverSpy)); + }, + 'should call tunnel once with db config properties added': function(err, db, tunnelStub) { + var expectedTunnelConfig = { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort', + dstHost: 'dbHost', + dstPort: 'dbPort' + }; + + assert.isNull(err); + assert.isNotNull(db); + assert(tunnelStub.withArgs(expectedTunnelConfig).calledOnce); + }, + 'should replace the db host and port with localhost and the tunnel localPort': function(err, db, tunnelStub, driverSpy) { + var expectedDbConfig = { + driver: 'mysql', + host: '127.0.0.1', + port: 'localPort', + tunnel: { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort' + } + }; + + assert(driverSpy.withArgs(expectedDbConfig).calledOnce); + }, + teardown: function(db, tunnelStub, driverSpy) { + driverSpy.restore(); + } + }, + 'a failed tunnel connection': { + topic: function() { + // Ensure that require gets a new copy of the module for each test + delete require.cache[require.resolve('../../lib/driver/mysql')]; + var driver = require('../../lib/driver/mysql'); + + // Set up stubs/spies to verify correct flow + var tunnelStub = sinon.stub().callsArgWith(1, new Error("error")); + var driverSpy = sinon.spy(driver, 'connect'); + + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + './mysql': driver + }); + + index.connect(validDbConfigWithTunnel, {}, indexConnectCallback(this, tunnelStub, driverSpy)); + }, + 'should pass the error to the callback': function (err, db) { + assert(err, "err should be non-null"); + assert(!db, "driver should be null or undefined"); + }, + 'should call tunnel, but not driver.connect': function (err, db, tunnelStub, driverSpy) { + assert(tunnelStub.calledOnce, "tunnel should be called once"); + assert(driverSpy.notCalled, "driver.connect should not be called"); + } + } +}).export(module); \ No newline at end of file From b14c3f3faa57fe72d458503f1001b88328abf1ab Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 29 Mar 2015 23:30:51 +0200 Subject: [PATCH 004/412] Add ability to directly choose the target dbms When migrating generally database specific and such bound to its specific architecture and specifications like functions and procedures, there was no generic way to accomplish this task. Resolves #245. --- lib/driver/base.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/driver/base.js b/lib/driver/base.js index 7da06930..ce7198a9 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -57,6 +57,14 @@ module.exports = Base = Class.extend({ } }, + checkDBMS: function(dbms, callback) { + + if( this.dbms === dbms ) + return Promise.resolve(dbms).nodeify(callback); + else + return Promise.reject('dbms does not match'); + }, + createDatabase: function() { throw new Error('not implemented'); From f4a4917cfd82224de16854109920071769fb4099 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 30 Mar 2015 00:43:34 +0200 Subject: [PATCH 005/412] fix summer time issue revers to #251 --- lib/skeleton.js | 4 ++-- test/migration_test.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/skeleton.js b/lib/skeleton.js index 5fd6b03c..99682831 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -16,7 +16,7 @@ function formatName(title, date) { function formatDate(date) { return [ date.getUTCFullYear(), - lpad(date.getUTCMonth() + 1, '0', 2), + lpad(date.getMonth(), '0', 2), lpad(date.getUTCDate(), '0', 2), lpad(date.getUTCHours(), '0', 2), lpad(date.getUTCMinutes(), '0', 2), @@ -32,7 +32,7 @@ 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.setUTCMonth(match[2] - 1); + date.setMonth(match[2]); date.setUTCDate(match[3]); date.setUTCHours(match[4]); date.setUTCMinutes(match[5]); diff --git a/test/migration_test.js b/test/migration_test.js index 375bc9a0..b640bd49 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -141,7 +141,7 @@ vows.describe('migration').addBatch({ function createDateForTest() { var date = new Date(); date.setUTCFullYear(2014); - date.setUTCMonth('01'); + date.setMonth('02'); date.setUTCDate('20'); date.setUTCHours('14'); date.setUTCMinutes('30'); From b784245228f5e87bbb771d5cdaf2d3b53426b967 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 30 Mar 2015 21:46:48 +0200 Subject: [PATCH 006/412] add migrator interface, add reduceToInterface method --- lib/interface/migratorInterface.js | 100 +++++++++++++++++++++++++++++ lib/util.js | 35 ++++++++++ 2 files changed, 135 insertions(+) create mode 100644 lib/interface/migratorInterface.js diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js new file mode 100644 index 00000000..c11a465d --- /dev/null +++ b/lib/interface/migratorInterface.js @@ -0,0 +1,100 @@ + +function MigratorInterface() { + +} + +MigratorInterface.prototype = { + + checkDBMS: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + + createDatabase: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + switchDatabase: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + dropDatabase: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + bindForeignKey: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + createTable: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + dropTable: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + renameTable: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + addColumn: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + removeColumn: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + renameColumn: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + changeColumn: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + addIndex: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + insert: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + removeIndex: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + addForeignKey: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + removeForeignKey: function() { + + arguments[arugments.length - 1]('not implemented'); + }, + + runSql: function() { + + arguments[arugments.length - 1]('not implemented'); + } +}; + +module.exports = MigratorInterface; diff --git a/lib/util.js b/lib/util.js index fa9b83a2..b63d00e4 100644 --- a/lib/util.js +++ b/lib/util.js @@ -26,6 +26,41 @@ exports.filterUp = function(allMigrations, completedMigrations, destination, cou .slice(0, count); }; +/** + * Similar to the shadow driver, but we reduce to a subset of an existing + * driver. + */ +exports.reduceToInterface = function(db, originInterface) { + + var Interface = {}; + Interface._original = {}; + + for(var prop in db) { + + if (typeof Interface[prop] === "function" && + typeof db[prop] === "function") { + + Interface._original[prop] = db[prop]; + + (function(property) { + + Interface[property] = function() { this._original[property].apply(this, arguments); }; + }(prop)); + } + else if(typeof Interface[prop] === "function") + { + Interface._original[prop] = originInterface[prop]; + + (function(property) { + + Interface[property] = function() { this._original[property].apply(this, arguments); }; + }(prop)); + } + } + + return Interface; +}; + exports.filterDown = function(completedMigrations, count) { return completedMigrations.slice(0, count); }; From 2531721001c9803831522312de485c876d03d830 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 30 Mar 2015 22:05:51 +0200 Subject: [PATCH 007/412] fix typo in migratorInterface --- lib/interface/migratorInterface.js | 42 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index c11a465d..7b7b9f47 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -7,94 +7,98 @@ MigratorInterface.prototype = { checkDBMS: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, createDatabase: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, switchDatabase: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, dropDatabase: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, bindForeignKey: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, createTable: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, dropTable: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, renameTable: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, addColumn: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, removeColumn: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, renameColumn: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, changeColumn: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, addIndex: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, insert: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, removeIndex: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, addForeignKey: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, removeForeignKey: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); }, runSql: function() { - arguments[arugments.length - 1]('not implemented'); + arguments[arguments.length - 1]('not implemented'); } }; -module.exports = MigratorInterface; + +exports.extending = { +}; + +exports.MigratorInterface = MigratorInterface; From 0354de8036a32a05f438368fa728b8d68fdb5ef2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 31 Mar 2015 22:39:58 +0200 Subject: [PATCH 008/412] change resolving, move index to connect --- api.js | 2 +- bin/db-migrate | 23 +++++++-- connect.js | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ index.js | 137 +------------------------------------------------ package.json | 1 + 5 files changed, 159 insertions(+), 140 deletions(-) create mode 100644 connect.js diff --git a/api.js b/api.js index 03109611..4c65fdbe 100644 --- a/api.js +++ b/api.js @@ -5,7 +5,7 @@ var util = require('util'); var mkdirp = require('mkdirp'); var optimist = require('optimist'); var config = require('./lib/config.js'); -var index = require('./index'); +var index = require('./connect'); var Migration = require('./lib/migration.js'); var Seeder = require('./lib/seeder.js'); var Migrator = require('./lib/migrator.js'); diff --git a/bin/db-migrate b/bin/db-migrate index 642e2579..ab29a290 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -1,6 +1,23 @@ #!/usr/bin/env node -var DBMigrate = require('../api.js'), - dbmigrate = new DBMigrate(); +var resolve = require( 'resolve' ); -dbmigrate.run(); +process.title = 'db-migrate'; + +resolve( 'db-migrate', { + + basedir: process.cwd() +}, function ( error, localModule ) { + + var DBMigrate, dbmigrate; + + if ( error ) { + DBMigrate = require( '../' ); + } + else { + DBMigrate = require( localModule ); + } + + dbmigrate = new DBMigrate(); + dbmigrate.run(); +} ); diff --git a/connect.js b/connect.js new file mode 100644 index 00000000..93188c54 --- /dev/null +++ b/connect.js @@ -0,0 +1,136 @@ +var recursive = require('final-fs').readdirRecursive; +var fs = require('fs'); +var driver = require('./lib/driver'); +var path = require('path'); +var log = require('./lib/log'); + +exports.dataType = require('./lib/data_type'); +exports.config = require('./lib/config'); + +var internals = {}; + +exports.connect = function(config, passedClass, callback) { + driver.connect(config, internals, function(err, db) { + if (err) { callback(err); return; } + + if(internals.migrationMode) + { + var dirPath = path.resolve(config['migrations-dir'] || 'migrations'); + + if(internals.migrationMode !== 'all') + { + var switched = false, + newConf; + + try { + newConf = require(path.resolve(config['migrations-dir'] || 'migrations', internals.migrationMode) + '/config.json'); + log.info('loaded extra config for migration subfolder: "' + internals.migrationMode + '/config.json"'); + switched = true; + } catch(e) {} + + if(switched) { + + db.switchDatabase(newConf, function() + { + internals.locTitle = internals.migrationMode; + callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); + }); + } + else + { + internals.locTitle = internals.migrationMode; + callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); + } + } + else + { + recursive(dirPath, false, config['migrations-dir'] || 'migrations') + .then(function(files) { + var oldClose = db.close; + + files = files.filter(function (file) { + return file !== 'migrations' && fs.statSync(file).isDirectory(); + }); + + files.push(''); + + db.close = function(cb) { migrationFiles(files, callback, config, passedClass, db, oldClose, cb); }; + + db.close(); + }); + } + } + else + callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); + + }); +}; + +exports.driver = function(config, callback) { + + driver.connect(config, internals, callback); +}; + +function migrationFiles(files, callback, config, passedClass, db, close, cb) { + var file, + switched = false, + newConf; + + if(files.length === 1) + { + db.close = close; + } + + file = files.pop(); + + if(file !== '') + { + + try { + newConf = require(path.resolve(file + '/config.json')); + log.info('loaded extra config for migration subfolder: "' + file + '/config.json"'); + switched = true; + } catch(e) {} + } + + db.switchDatabase((switched) ? newConf : config.database, function() + { + internals.matching = file.substr(file.indexOf(config['migrations-dir'] || 'migrations') + + (config['migrations-dir'] || 'migrations').length + 1); + + if(internals.matching.length === 0) + internals.matching = ''; + + + internals.locTitle = internals.matching; + callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); + + if(typeof(cb) === 'function') + cb(); + + }); +} + +exports.createMigration = function(migration, callback) { + + migration.write(function(err) { + + if (err) { + + callback(err); + return; + } + + callback(null, migration); + }); +}; + +exports.exportInternals = function( intern ) { + + internals = intern; +}; + +exports.importInternals = function() { + + return internals; +}; \ No newline at end of file diff --git a/index.js b/index.js index 93188c54..75974552 100644 --- a/index.js +++ b/index.js @@ -1,136 +1 @@ -var recursive = require('final-fs').readdirRecursive; -var fs = require('fs'); -var driver = require('./lib/driver'); -var path = require('path'); -var log = require('./lib/log'); - -exports.dataType = require('./lib/data_type'); -exports.config = require('./lib/config'); - -var internals = {}; - -exports.connect = function(config, passedClass, callback) { - driver.connect(config, internals, function(err, db) { - if (err) { callback(err); return; } - - if(internals.migrationMode) - { - var dirPath = path.resolve(config['migrations-dir'] || 'migrations'); - - if(internals.migrationMode !== 'all') - { - var switched = false, - newConf; - - try { - newConf = require(path.resolve(config['migrations-dir'] || 'migrations', internals.migrationMode) + '/config.json'); - log.info('loaded extra config for migration subfolder: "' + internals.migrationMode + '/config.json"'); - switched = true; - } catch(e) {} - - if(switched) { - - db.switchDatabase(newConf, function() - { - internals.locTitle = internals.migrationMode; - callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); - }); - } - else - { - internals.locTitle = internals.migrationMode; - callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); - } - } - else - { - recursive(dirPath, false, config['migrations-dir'] || 'migrations') - .then(function(files) { - var oldClose = db.close; - - files = files.filter(function (file) { - return file !== 'migrations' && fs.statSync(file).isDirectory(); - }); - - files.push(''); - - db.close = function(cb) { migrationFiles(files, callback, config, passedClass, db, oldClose, cb); }; - - db.close(); - }); - } - } - else - callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); - - }); -}; - -exports.driver = function(config, callback) { - - driver.connect(config, internals, callback); -}; - -function migrationFiles(files, callback, config, passedClass, db, close, cb) { - var file, - switched = false, - newConf; - - if(files.length === 1) - { - db.close = close; - } - - file = files.pop(); - - if(file !== '') - { - - try { - newConf = require(path.resolve(file + '/config.json')); - log.info('loaded extra config for migration subfolder: "' + file + '/config.json"'); - switched = true; - } catch(e) {} - } - - db.switchDatabase((switched) ? newConf : config.database, function() - { - internals.matching = file.substr(file.indexOf(config['migrations-dir'] || 'migrations') + - (config['migrations-dir'] || 'migrations').length + 1); - - if(internals.matching.length === 0) - internals.matching = ''; - - - internals.locTitle = internals.matching; - callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); - - if(typeof(cb) === 'function') - cb(); - - }); -} - -exports.createMigration = function(migration, callback) { - - migration.write(function(err) { - - if (err) { - - callback(err); - return; - } - - callback(null, migration); - }); -}; - -exports.exportInternals = function( intern ) { - - internals = intern; -}; - -exports.importInternals = function() { - - return internals; -}; \ No newline at end of file +module.exports = require( './api.js' ); \ No newline at end of file diff --git a/package.json b/package.json index f5302bc3..487714c7 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "pg": "~4.3.0", "pg-native": "^1.8.0", "pkginfo": "~0.3.0", + "resolve": "^1.1.6", "semver": "~4.3.0", "sqlite3": "~3.0.4", "tunnel-ssh": "^1.0.0" From a4e9419dae1e6d78cbd8206cf65123fdcd7f6630 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 1 Apr 2015 18:28:50 +0200 Subject: [PATCH 009/412] update dependency and silence dotenv --- api.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api.js b/api.js index 4c65fdbe..4131bad8 100644 --- a/api.js +++ b/api.js @@ -25,7 +25,7 @@ function dbmigrate(isModule, callback) { if(typeof(callback) === 'function') internals.onComplete = callback; - dotenv.load(); + dotenv.load({ silent: true }); registerEvents(); if(typeof(isModule) === 'function') diff --git a/package.json b/package.json index 487714c7..bfdb1c5d 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "dependencies": { "async": "~0.9.0", "bluebird": "^2.9.12", - "dotenv": "~1.0.0", + "dotenv": "~1.1.0", "final-fs": "^1.6.0", "mkdirp": "~0.5.0", "moment": "~2.9.0", From 8bc6c2ceed1d58bc05409bdb24ccf10f3761f592 Mon Sep 17 00:00:00 2001 From: Axel Duch Date: Thu, 2 Apr 2015 15:27:46 +0200 Subject: [PATCH 010/412] Handle defaultValue NULL for MySQL driver (with unit test) --- lib/driver/mysql.js | 2 ++ test/driver/mysql_test.js | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 43c89b93..fee85f57 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -135,6 +135,8 @@ var MysqlDriver = Base.extend({ if (typeof spec.defaultValue === 'string'){ constraint.push("'" + spec.defaultValue + "'"); + } else if (spec.defaultValue === null) { + constraint.push('NULL'); } else { constraint.push(spec.defaultValue); } diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index 5d442217..f4a3bfbb 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -18,6 +18,7 @@ driver.connect(config, internals, function(err, db) { db.createTable('event', { id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, str: { type: dataType.STRING, unique: true, defaultValue: 'foo' }, + strDefaultNull: { type: dataType.STRING, defaultValue: null }, txt: { type: dataType.TEXT, notNull: true }, intg: dataType.INTEGER, rel: dataType.REAL, @@ -58,9 +59,9 @@ driver.connect(config, internals, function(err, db) { }.bind(this)); }, - 'with 9 columns': function(err, columns) { + 'with 10 columns': function(err, columns) { assert.isNotNull(columns); - assert.equal(columns.length, 9); + assert.equal(columns.length, 10); }, 'that has integer id column that is primary key, non-nullable, and auto increments': function(err, columns) { @@ -78,6 +79,11 @@ driver.connect(config, internals, function(err, db) { // assert.equal(column.isUnique(), true); }, + 'that has text strDefaultNull column that has a default null value': function(err, columns) { + var column = findByName(columns, 'strDefaultNull'); + assert.equal(column.getDefaultValue(), null); + }, + 'that has text txt column that is non-nullable': function(err, columns) { var column = findByName(columns, 'txt'); assert.equal(column.getDataType(), 'TEXT'); @@ -119,7 +125,7 @@ driver.connect(config, internals, function(err, db) { assert.equal(column.getDataType(), 'TINYINT'); assert.equal(column.isNullable(), true); assert.equal(column.getDefaultValue(), 0); - } + }, } } }).addBatch({ From 63cd055e6f41ca551fa594479d2fa8d877a2966f Mon Sep 17 00:00:00 2001 From: Axel Duch Date: Thu, 2 Apr 2015 16:36:49 +0200 Subject: [PATCH 011/412] Remove extra comma in object literal (oversight) --- test/driver/mysql_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index f4a3bfbb..600704c2 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -125,7 +125,7 @@ driver.connect(config, internals, function(err, db) { assert.equal(column.getDataType(), 'TINYINT'); assert.equal(column.isNullable(), true); assert.equal(column.getDefaultValue(), 0); - }, + } } } }).addBatch({ From 18988221fe2e5c328f794c746f129f5476213cd6 Mon Sep 17 00:00:00 2001 From: Axel Duch Date: Thu, 2 Apr 2015 15:27:46 +0200 Subject: [PATCH 012/412] Handle defaultValue NULL for MySQL driver (with unit test) --- lib/driver/mysql.js | 2 ++ test/driver/mysql_test.js | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 633b0e0e..5e762aa7 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -98,6 +98,8 @@ var MysqlDriver = Base.extend({ if (typeof spec.defaultValue === 'string'){ constraint.push("'" + spec.defaultValue + "'"); + } else if (spec.defaultValue === null) { + constraint.push('NULL'); } else { constraint.push(spec.defaultValue); } diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index 6170a26c..7b5f82c6 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -17,6 +17,7 @@ driver.connect(config, function(err, db) { db.createTable('event', { id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, str: { type: dataType.STRING, unique: true, defaultValue: 'foo' }, + strDefaultNull: { type: dataType.STRING, defaultValue: null }, txt: { type: dataType.TEXT, notNull: true }, intg: dataType.INTEGER, rel: dataType.REAL, @@ -57,9 +58,9 @@ driver.connect(config, function(err, db) { }.bind(this)); }, - 'with 9 columns': function(err, columns) { + 'with 10 columns': function(err, columns) { assert.isNotNull(columns); - assert.equal(columns.length, 9); + assert.equal(columns.length, 10); }, 'that has integer id column that is primary key, non-nullable, and auto increments': function(err, columns) { @@ -77,6 +78,11 @@ driver.connect(config, function(err, db) { // assert.equal(column.isUnique(), true); }, + 'that has text strDefaultNull column that has a default null value': function(err, columns) { + var column = findByName(columns, 'strDefaultNull'); + assert.equal(column.getDefaultValue(), null); + }, + 'that has text txt column that is non-nullable': function(err, columns) { var column = findByName(columns, 'txt'); assert.equal(column.getDataType(), 'TEXT'); @@ -118,7 +124,7 @@ driver.connect(config, function(err, db) { assert.equal(column.getDataType(), 'TINYINT'); assert.equal(column.isNullable(), true); assert.equal(column.getDefaultValue(), 0); - } + }, } } }).addBatch({ From 555c1b27736002b5fca7dfff9abab83f922aca82 Mon Sep 17 00:00:00 2001 From: Axel Duch Date: Thu, 2 Apr 2015 16:36:49 +0200 Subject: [PATCH 013/412] Remove extra comma in object literal (oversight) --- test/driver/mysql_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index 7b5f82c6..a72ff008 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -124,7 +124,7 @@ driver.connect(config, function(err, db) { assert.equal(column.getDataType(), 'TINYINT'); assert.equal(column.isNullable(), true); assert.equal(column.getDefaultValue(), 0); - }, + } } } }).addBatch({ From 05d34c7d736d1c861cd71ea6dc11415eace4281f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 2 Apr 2015 23:49:55 +0200 Subject: [PATCH 014/412] 0.9.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da7b837d..44d6833e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "sqlite", "mysql" ], - "version": "0.9.11", + "version": "0.9.12", "engines": { "node": ">=0.6.0" }, From dce25e902f4c8702d4dab6cc77962c7d59b6db7d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 3 Apr 2015 17:18:05 +0200 Subject: [PATCH 015/412] several structural changes and one bugfix --- .gitignore | 3 ++- .npmignore | 3 ++- api.js | 8 +++++--- connect.js | 3 --- index.js | 5 ++++- lib/driver/base.js | 2 +- lib/migrator.js | 13 ++++++++----- lib/skeleton.js | 4 ++++ 8 files changed, 26 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index caedbc7f..47eb09c1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ Seeder/ test/db.config.json database.json *.sublime-project -*.sublime-workspace \ No newline at end of file +*.sublime-workspace +archive diff --git a/.npmignore b/.npmignore index 65003c3d..0e6e098f 100644 --- a/.npmignore +++ b/.npmignore @@ -6,4 +6,5 @@ node_modules *.db database.json *.sublime-project -*.sublime-workspace \ No newline at end of file +*.sublime-workspace +archive diff --git a/api.js b/api.js index 4131bad8..6f246240 100644 --- a/api.js +++ b/api.js @@ -13,11 +13,11 @@ var log = require('./lib/log'); var pkginfo = require('pkginfo')(module, 'version'); var dotenv = require('dotenv'); + //global declaration for detection like it's done in umigrate dbm = require( './' ); //deprecated async = require( 'async' ); //deprecated - var internals = {}; function dbmigrate(isModule, callback) { @@ -25,6 +25,8 @@ function dbmigrate(isModule, callback) { if(typeof(callback) === 'function') internals.onComplete = callback; + this.dataType = dbm.dataType; + this.version = dbm.version; dotenv.load({ silent: true }); registerEvents(); @@ -342,7 +344,7 @@ function setDefaultArgv(isModule) { .argv; if (internals.argv.version) { - console.log(module.exports.version); + console.log(dbm.version); process.exit(0); } @@ -650,4 +652,4 @@ function run() { } -module.exports = dbmigrate; \ No newline at end of file +module.exports = dbmigrate; diff --git a/connect.js b/connect.js index 93188c54..5f5b1887 100644 --- a/connect.js +++ b/connect.js @@ -4,9 +4,6 @@ var driver = require('./lib/driver'); var path = require('path'); var log = require('./lib/log'); -exports.dataType = require('./lib/data_type'); -exports.config = require('./lib/config'); - var internals = {}; exports.connect = function(config, passedClass, callback) { diff --git a/index.js b/index.js index 75974552..0c49c37c 100644 --- a/index.js +++ b/index.js @@ -1 +1,4 @@ -module.exports = require( './api.js' ); \ No newline at end of file +var pkginfo = require('pkginfo')(module, 'version'); + +exports.dataType = require('./lib/data_type'); +module.exports = require( './api.js' ); diff --git a/lib/driver/base.js b/lib/driver/base.js index ce7198a9..d200de24 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -201,7 +201,7 @@ module.exports = Base = Class.extend({ addColumn: function(tableName, columnName, columnSpec, callback) { - var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec, tableName)); + var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), {}, tableName); var sql = util.format('ALTER TABLE "%s" ADD COLUMN %s', tableName, def.constraints); this.runSql(sql, function() diff --git a/lib/migrator.js b/lib/migrator.js index 0fb69cc9..be1f8750 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -92,8 +92,10 @@ Migrator.prototype = { .catch(callback) .then(function() { - if(typeof(migration.setup) === 'function') - migration.setup(internals.migrationOptions); + var setup = migration.setup(); + + if(typeof(setup) === 'function') + setup(internals.migrationOptions); self.up(migration.up.bind(migration), function(err) { if (err) { callback(err); return; } @@ -121,11 +123,12 @@ Migrator.prototype = { async.forEachSeries(toRun, function(migration, next) { log.verbose('preparing to run down migration:', migration.name); - if(typeof(migration.setup) === 'function') - migration.setup(internals.migrationOptions); + var setup = migration.setup(); - self.driver.startMigration() + if(typeof(setup) === 'function') + setup(internals.migrationOptions); + self.driver.startMigration() .then(function() { self.down(migration.down.bind(migration), function(err) { if (err) { diff --git a/lib/skeleton.js b/lib/skeleton.js index 99682831..564bb956 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -68,6 +68,10 @@ var Skeleton = Class.extend({ this._down(db, callback); }, + setup: function() { + return require(this.path).setup; + }, + parseName: function(path) { var match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); return match[1]; From faa55cad348d2968582cfd5811c9f540f9e58696 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 3 Apr 2015 17:26:16 +0200 Subject: [PATCH 016/412] [Bugfix] addColumn missing defaultOptionalities Fixes #255 --- lib/driver/base.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 8da193af..ec237de6 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -190,7 +190,7 @@ module.exports = Base = Class.extend({ addColumn: function(tableName, columnName, columnSpec, callback) { - var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec, tableName)); + var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), {}, tableName); var sql = util.format('ALTER TABLE "%s" ADD COLUMN %s', tableName, def.constraints); this.runSql(sql, function() From 1c6b6b8fc490edb891c3527503ba71e4fc5f9de0 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 3 Apr 2015 18:29:56 +0200 Subject: [PATCH 017/412] add addcolumn test to postgres driver --- lib/driver/base.js | 5 +-- lib/driver/pg.js | 2 ++ test/driver/pg_test.js | 76 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index d200de24..5f23aec9 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -83,9 +83,10 @@ module.exports = Base = Class.extend({ var self = this; if (foreignKeys.length > 0) - (foreignKeys.pop())(function() { self.recurseCallbackArray(foreignKeys, callback); } ); + return Promise.resolve((foreignKeys.pop())(function() { self.recurseCallbackArray(foreignKeys, callback); } )) + .nodeify(callback); else - callback(); + return Promise.resolve().nodeify(callback); }, bindForeignKey: function(tableName, columnName, fkOptions) { diff --git a/lib/driver/pg.js b/lib/driver/pg.js index bca44e0e..4bebe4fe 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -363,6 +363,8 @@ var PgDriver = Base.extend({ }); +Promise.promisify(PgDriver); + exports.connect = function(config, intern, callback) { internals = intern; diff --git a/test/driver/pg_test.js b/test/driver/pg_test.js index ac308d29..fde22d38 100644 --- a/test/driver/pg_test.js +++ b/test/driver/pg_test.js @@ -495,6 +495,82 @@ driver.connect(config, internals, function(err, db) { } } } + }).addBatch({ + 'addForeign by addcolumn with spec': { + topic: function() { + db.createTable('event', { + id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, + event_id: { type: dataType.INTEGER, notNull: true }, + title: { type: dataType.STRING } + }, function() { + db.createTable('event_type', { + id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, + title: { type: dataType.STRING } + }, function () { + db.addColumn('event_type', 'event_id', { + type: dataType.INTEGER, + notNull: true, + foreignKey: { + name: 'primary_event_id_fk', + table: 'event', + rules: { + onDelete: 'CASCADE', + onUpdate: 'RESTRICT' + }, + mapping: 'id' + } + }, this.callback.bind(this, null)); + }.bind(this)); + }.bind(this)); + }, + + teardown: function() { + db.dropTable('event_type'); + db.dropTable('event', this.callback); + }, + + 'sets usage and constraints': { + topic: function() { + var metaQuery = ['SELECT', + ' tc.table_schema, tc.table_name as ortn, kcu.column_name orcn, ccu.table_name,', + ' ccu.column_name,', + ' cstr.update_rule,', + ' cstr.delete_rule', + 'FROM', + ' information_schema.table_constraints AS tc', + 'JOIN information_schema.key_column_usage AS kcu', + ' ON tc.constraint_name = kcu.constraint_name', + 'JOIN information_schema.constraint_column_usage AS ccu', + ' ON ccu.constraint_name = tc.constraint_name', + 'JOIN information_schema.referential_constraints AS cstr', + ' ON cstr.constraint_schema = tc.table_schema', + ' AND cstr.constraint_name = tc.constraint_name', + 'WHERE', + ' tc.table_schema = ?', + ' AND tc.table_name = ?', + ' AND kcu.column_name = ?'].join('\n'); + db.runSql(metaQuery, ['public', 'event_type', 'event_id'], this.callback); + }, + + 'with correct references': function(err, result) { + var rows = result.rows; + assert.isNotNull(rows); + assert.equal(rows.length, 1); + var row = rows[0]; + assert.equal(row.table_name, 'event'); + assert.equal(row.column_name, 'id'); + }, + + 'and correct rules': function(err, result) { + var rows = result.rows; + assert.isNotNull(rows); + assert.equal(rows.length, 1); + var row = rows[0]; + assert.equal(row.update_rule, 'RESTRICT'); + assert.equal(row.delete_rule, 'CASCADE'); + } + } + } }).addBatch({ 'insert': { topic: function() { From bed4e5a680b21b728b6cc22e63ba0993e78a9d3b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 3 Apr 2015 19:43:51 +0200 Subject: [PATCH 018/412] updated dependencies and fix promise on old recursion for foreignkeys --- lib/driver/base.js | 12 ++++----- package.json | 2 +- test/driver/mysql_test.js | 51 +++++++++++++++++++++++++++++---------- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 5f23aec9..3e63d019 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -80,13 +80,13 @@ module.exports = Base = Class.extend({ recurseCallbackArray: function(foreignKeys, callback) { - var self = this; + var self = this, fkFunc, + promises = []; - if (foreignKeys.length > 0) - return Promise.resolve((foreignKeys.pop())(function() { self.recurseCallbackArray(foreignKeys, callback); } )) - .nodeify(callback); - else - return Promise.resolve().nodeify(callback); + while((fkFunc = foreignKeys.pop())) + promises.push(Promise.resolve(fkFunc())); + + return Promise.all(promises).nodeify(callback); }, bindForeignKey: function(tableName, columnName, fkOptions) { diff --git a/package.json b/package.json index 1f445103..011a63a4 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "pg-native": "^1.8.0", "pkginfo": "~0.3.0", "resolve": "^1.1.6", - "semver": "~4.3.0", + "semver": "~4.3.3", "sqlite3": "~3.0.4", "tunnel-ssh": "^1.0.0" }, diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index 600704c2..7f002669 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -486,15 +486,26 @@ driver.connect(config, internals, function(err, db) { type: dataType.INTEGER, notNull: true, foreignKey: { - name: 'fk_event_event_type', - table: 'event_type', - mapping: { - event_id: 'id' - }, - rules: { - onDelete: 'CASCADE' - }, - } }, + name: 'fk_event_event_type', + table: 'event_type', + mapping: 'id', + rules: { + onDelete: 'CASCADE' + }, + } + }, + event_id2: { + type: dataType.INTEGER, + notNull: true, + foreignKey: { + name: 'fk_event_event2_type', + table: 'event_type', + mapping: 'id', + rules: { + onDelete: 'CASCADE' + }, + } + }, title: { type: dataType.STRING } @@ -523,24 +534,38 @@ driver.connect(config, internals, function(err, db) { 'WHERE', ' usg.TABLE_SCHEMA = ?', ' AND usg.TABLE_NAME = ?', - ' AND usg.COLUMN_NAME = ?'].join('\n'); - db.runSql(metaQuery, dbName, 'event', 'event_id', this.callback); + ' AND ( usg.COLUMN_NAME = ? OR usg.COLUMN_NAME = ? )'].join('\n'); + db.runSql(metaQuery, dbName, 'event', 'event_id', 'event_id2', this.callback); }, 'with correct references': function(err, rows) { assert.isNotNull(rows); - assert.equal(rows.length, 1); + assert.equal(rows.length, 2); var row = rows[0]; assert.equal(row.REFERENCED_TABLE_NAME, 'event_type'); assert.equal(row.REFERENCED_COLUMN_NAME, 'id'); + + var row = rows[1]; + assert.equal(row.REFERENCED_TABLE_NAME, 'event_type'); + assert.equal(row.REFERENCED_COLUMN_NAME, 'id'); + var row = rows[1]; + assert.equal(row.UPDATE_RULE, 'NO ACTION'); + assert.equal(row.DELETE_RULE, 'CASCADE'); }, 'and correct rules': function(err, rows) { assert.isNotNull(rows); - assert.equal(rows.length, 1); + assert.equal(rows.length, 2); var row = rows[0]; assert.equal(row.UPDATE_RULE, 'NO ACTION'); assert.equal(row.DELETE_RULE, 'CASCADE'); + + var row = rows[1]; + assert.equal(row.REFERENCED_TABLE_NAME, 'event_type'); + assert.equal(row.REFERENCED_COLUMN_NAME, 'id'); + var row = rows[1]; + assert.equal(row.UPDATE_RULE, 'NO ACTION'); + assert.equal(row.DELETE_RULE, 'CASCADE'); } } } From e2537f334ad18ce106764d560016fa88cf850fbe Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 3 Apr 2015 20:03:21 +0200 Subject: [PATCH 019/412] fix behavior of mongodb test --- lib/driver/mongodb.js | 2 +- test/driver/mongodb_test.js | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/driver/mongodb.js b/lib/driver/mongodb.js index a846e768..49ecb6a7 100644 --- a/lib/driver/mongodb.js +++ b/lib/driver/mongodb.js @@ -229,7 +229,7 @@ var MongodbDriver = Base.extend({ * @param command - The command to run against mongo * @param collection - The collection to run the command on * @param options - An object of options to be used based on the command - * @arapm callback - A callback to return the results + * @param callback - A callback to return the results */ _run: function(command, collection, options, callback) { diff --git a/test/driver/mongodb_test.js b/test/driver/mongodb_test.js index df60d372..f1b58dab 100644 --- a/test/driver/mongodb_test.js +++ b/test/driver/mongodb_test.js @@ -81,9 +81,14 @@ driver.connect(config, internals, function(err, db) { }, 'containing the functions table': function(err, tables) { + var index = 0; assert.isNotNull(tables); assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - assert.equal(tables[1].collectionName, 'functions'); + + if( tables[0].collectionName === 'system.indexes' ) + index = 1; + + assert.equal(tables[index].collectionName, 'functions'); } } } @@ -110,9 +115,14 @@ driver.connect(config, internals, function(err, db) { }, 'of the functions original table': function(err, tables) { + var index = 0; assert.isNotNull(tables); assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - assert.equal(tables[1].collectionName, 'event'); + + if( tables[0].collectionName === 'system.indexes' ) + index = 1; + + assert.equal(tables[index].collectionName, 'event'); } }, @@ -248,10 +258,14 @@ driver.connect(config, internals, function(err, db) { }, 'has migrations table' : function(err, tables) { + var index = 0; assert.isNull(err); assert.isNotNull(tables); assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - assert.equal(tables[1].collectionName, 'migrations'); + if( tables[0].collectionName === 'system.indexes' ) + index = 1; + + assert.equal(tables[index].collectionName, 'migrations'); } } } @@ -313,10 +327,15 @@ driver.connect(config, internals, function(err, db) { }, 'has migrations table' : function(err, tables) { + var index = 0; assert.isNull(err); assert.isNotNull(tables); assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - assert.equal(tables[1].collectionName, 'migrations'); + + if( tables[0].collectionName === 'system.indexes' ) + index = 1; + + assert.equal(tables[index].collectionName, 'migrations'); } } } From 2b35dc0cd6c2d994e4fbd209d855a13badf02e75 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Apr 2015 00:03:04 +0200 Subject: [PATCH 020/412] add promise functionality to some methods in mysql and pg driver --- lib/driver/mysql.js | 29 ++++++++++++++-------- lib/driver/pg.js | 40 ++++++++++++++++++++++-------- lib/interface/migratorInterface.js | 6 ++--- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index fee85f57..522cc731 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -213,7 +213,7 @@ var MysqlDriver = Base.extend({ }, addColumn: function(tableName, columnName, columnSpec, callback) { - var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), tableName); + var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), {}, tableName); var sql = util.format('ALTER TABLE `%s` ADD COLUMN %s', tableName, def.constraints); this.runSql(sql, function() { @@ -389,28 +389,29 @@ var MysqlDriver = Base.extend({ var sql = util.format('ALTER TABLE `%s` ADD CONSTRAINT `%s` FOREIGN KEY (%s) REFERENCES `%s` (%s) ON DELETE %s ON UPDATE %s', tableName, keyName, this.tableQuoteArr( columns ), referencedTableName, this.tableQuoteArr( referencedColumns ), rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); - this.runSql(sql, callback); + + return this.runSql(sql).nodeify(callback); }, removeForeignKey: function(tableName, keyName, options, callback) { var sql = util.format('ALTER TABLE `%s` DROP FOREIGN KEY `%s`', tableName, keyName); - this.runSql(sql, function () { + + return this.runSql(sql) + .then(function () { if( typeof(options) === 'function' ) { - options(); + return Promise.resolve().nodeify(options); } else if(options.dropIndex === true) { sql = util.format('ALTER TABLE `%s` DROP INDEX `%s`', tableName, keyName); - this.runSql(sql, function () { - callback(); - }); + return this.runSql(sql); } else - callback(); + return Promise.resolve().nodeify(callback); - }.bind(this)); + }.bind(this)).nodeify(callback); }, tableQuoteArr: function(arr) { @@ -425,10 +426,14 @@ var MysqlDriver = Base.extend({ var self = this; var args = this._makeParamArgs(arguments); - var callback = args.pop(); + var callback; + + if(typeof(args[args.length-1]) === 'function') + callback = args.pop(); + log.sql.apply(null, arguments); if(internals.dryRun) { - return callback(); + return Promise.resolve().nodeify(callback); } return new Promise(function(resolve, reject) { @@ -483,6 +488,8 @@ var MysqlDriver = Base.extend({ }); +Promise.promisifyAll(MysqlDriver); + exports.connect = function(config, intern, callback) { var db; diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 4bebe4fe..7eef5ca9 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -233,17 +233,18 @@ var PgDriver = Base.extend({ renameTable: function(tableName, newTableName, callback) { var sql = util.format('ALTER TABLE "%s" RENAME TO "%s"', tableName, newTableName); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, removeColumn: function(tableName, columnName, callback) { var sql = util.format('ALTER TABLE "%s" DROP COLUMN "%s"', tableName, columnName); - this.runSql(sql, callback); + + return this.runSql(sql).nodeify(callback); }, renameColumn: function(tableName, oldColumnName, newColumnName, callback) { var sql = util.format('ALTER TABLE "%s" RENAME COLUMN "%s" TO "%s"', tableName, oldColumnName, newColumnName); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, changeColumn: function(tableName, columnName, columnSpec, callback) { @@ -306,12 +307,12 @@ var PgDriver = Base.extend({ var referencedColumns = columns.map(function (key) { return '"' + fieldMapping[key] + '"'; }); var sql = util.format('ALTER TABLE "%s" ADD CONSTRAINT "%s" FOREIGN KEY (%s) REFERENCES "%s" (%s) ON DELETE %s ON UPDATE %s', tableName, keyName, this.quoteArr(columns), referencedTableName, referencedColumns, rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, removeForeignKey: function(tableName, keyName, callback) { var sql = util.format('ALTER TABLE "%s" DROP CONSTRAINT "%s"', tableName, keyName); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, insert: function(tableName, columnNameArray, valueArray, callback) { @@ -327,10 +328,17 @@ var PgDriver = Base.extend({ }, runSql: function() { - var callback = arguments[arguments.length - 1]; + var callback, + minLength = 1; + + if(typeof(arguments[arguments.length - 1]) === 'function') + { + minLength = 2; + callback = arguments[arguments.length - 1]; + } params = arguments; - if (params.length > 2){ + if (params.length > minLength){ // We have parameters, but db-migrate uses "?" for param substitutions. // PG uses "$1", "$2", etc so fix up the "?" into "$1", etc var param = params[0].split('?'), @@ -344,9 +352,21 @@ var PgDriver = Base.extend({ log.sql.apply(null, params); if(internals.dryRun) { - return callback(); + return Promise.resolve().nodeify(callback); } - this.connection.query.apply(this.connection, params); + + return new Promise(function(resolve, reject) { + var prCB = function(err, data) { + return (err ? reject(err) : resolve(data)); + }; + + if( minLength === 2 ) + params[params.length - 1] = prCB; + else + params[params.length++] = prCB; + + this.connection.query.apply(this.connection, params); + }.bind(this)).nodeify(callback); }, all: function() { @@ -363,7 +383,7 @@ var PgDriver = Base.extend({ }); -Promise.promisify(PgDriver); +Promise.promisifyAll(PgDriver); exports.connect = function(config, intern, callback) { diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 7b7b9f47..876088df 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -98,7 +98,7 @@ MigratorInterface.prototype = { }; -exports.extending = { +module.exports.MigratorInterface = MigratorInterface; +module.exports.deprecated = {}; +module.exports.extending = { }; - -exports.MigratorInterface = MigratorInterface; From 95b58c1a81561e6d94261a3e124eb82d86a9e72d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Apr 2015 00:12:32 +0200 Subject: [PATCH 021/412] fix mysql runsql --- lib/driver/mysql.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 522cc731..24d00d7f 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -426,11 +426,8 @@ var MysqlDriver = Base.extend({ var self = this; var args = this._makeParamArgs(arguments); - var callback; - - if(typeof(args[args.length-1]) === 'function') - callback = args.pop(); + var callback = args.pop(); log.sql.apply(null, arguments); if(internals.dryRun) { return Promise.resolve().nodeify(callback); From bf5f1db88982b3d64b11967937829a09349b0181 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Apr 2015 00:24:58 +0200 Subject: [PATCH 022/412] promisify runSql of sqlite3 --- lib/driver/sqlite3.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/driver/sqlite3.js b/lib/driver/sqlite3.js index b031954a..cfda1d73 100644 --- a/lib/driver/sqlite3.js +++ b/lib/driver/sqlite3.js @@ -3,6 +3,7 @@ var sqlite3 = require('sqlite3').verbose(); var Base = require('./base'); var log = require('../log'); var type = require('../data_type'); +var Promise = require('bluebird'); var defaultMode = sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, internals = {}; @@ -105,15 +106,29 @@ var Sqlite3Driver = Base.extend({ runSql: function() { var callback = arguments[arguments.length - 1]; + var params = arguments; + log.sql.apply(null, arguments); if(internals.dryRun) { - return callback(); + return Promise.resolve().nodeify(callback); } - if(typeof(arguments[1]) === 'function') - this.connection.exec.apply(this.connection, arguments); - else - this.connection.run.apply(this.connection, arguments); + return new Promise(function(resolve, reject) { + var prCB = function(err, data) { + return (err ? reject(err) : resolve(data)); + }; + + if( typeof(params[params.length - 1]) === 'function' ) + params[params.length - 1] = prCB; + else + params[params.length++] = prCB; + + + if(params.length === 1 || (callback && typeof(params[1]) === 'function')) + this.connection.exec.apply(this.connection, params); + else + this.connection.run.apply(this.connection, params); + }.bind(this)).nodeify(callback); }, all: function() { @@ -127,6 +142,8 @@ var Sqlite3Driver = Base.extend({ }); +Promise.promisifyAll(Sqlite3Driver); + exports.connect = function(config, intern, callback) { var mode = config.mode || defaultMode; From 0369910fbf82aa4da0d34b908eb0392d1c10a52c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Apr 2015 00:50:59 +0200 Subject: [PATCH 023/412] promisify several functions --- lib/driver/base.js | 21 +++++++++++++++------ lib/driver/mongodb.js | 15 ++++++++++++--- lib/driver/mysql.js | 34 ++++++++++++++++++++++------------ lib/driver/pg.js | 19 ++++++++++--------- lib/driver/sqlite3.js | 2 +- 5 files changed, 60 insertions(+), 31 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 3e63d019..20d35c7c 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -98,8 +98,16 @@ module.exports = Base = Class.extend({ else mapping = fkOptions.mapping; - return function (callback) { self.addForeignKey(tableName, fkOptions.table, - fkOptions.name, mapping, fkOptions.rules, callback); }; + return function (callback) { + + if (typeof(callback) === 'function') + self.addForeignKey(tableName, fkOptions.table, + fkOptions.name, mapping, fkOptions.rules, callback); + else + return self.addForeignKey(tableName, fkOptions.table, + fkOptions.name, mapping, fkOptions.rules); + + }; }, createColumnDef: function(name, spec, options) { @@ -205,13 +213,14 @@ module.exports = Base = Class.extend({ var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), {}, tableName); var sql = util.format('ALTER TABLE "%s" ADD COLUMN %s', tableName, def.constraints); - this.runSql(sql, function() + return this.runSql(sql) + .then(function() { if(def.foreignKey) - def.foreignKey(callback); + return def.foreignKey(); else - callback(); - }); + return Promise.resolve(); + }).nodeify(callback); }, removeColumn: function(tableName, columnName, callback) { diff --git a/lib/driver/mongodb.js b/lib/driver/mongodb.js index 49ecb6a7..aef0626f 100644 --- a/lib/driver/mongodb.js +++ b/lib/driver/mongodb.js @@ -5,6 +5,7 @@ var Server = require('mongodb').Server; var Base = require('./base'); var type = require('../data_type'); var log = require('../log'); +var Promise = require('bluebird'); var connectionString, internals = {}; @@ -71,7 +72,7 @@ var MongodbDriver = Base.extend({ this._run('use', options, null, callback); } else - callback(null); + return Promise.resolve().nodeify(callback); }, createDatabase: function(dbName, options, callback) { @@ -79,7 +80,7 @@ var MongodbDriver = Base.extend({ if(typeof(options) === 'function') callback = options; - callback(null); + return Promise.resolve().nodeify(callback); }, dropDatabase: function(dbName, options, callback) { @@ -363,10 +364,18 @@ var MongodbDriver = Base.extend({ * Closes the connection to mongodb */ close: function(callback) { - this.connection.close(callback); + return new Promise(function(resolve, reject) { + var cb = (function(err, data) { + return (err ? reject(err) : resolve(data)); + }); + + this.connection.close(cb); + }.bind(this)).nodeify(callback); } }); +Promise.promisifyAll(MongodbDriver); + /** * Gets a connection to mongo * diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 24d00d7f..4ef11d2c 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -209,19 +209,20 @@ var MysqlDriver = Base.extend({ renameTable: function(tableName, newTableName, callback) { var sql = util.format('RENAME TABLE `%s` TO `%s`', tableName, newTableName); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, addColumn: function(tableName, columnName, columnSpec, callback) { var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), {}, tableName); var sql = util.format('ALTER TABLE `%s` ADD COLUMN %s', tableName, def.constraints); - this.runSql(sql, function() + this.runSql(sql) + .then(function() { if(def.foreignKey) - def.foreignKey(callback); + return def.foreignKey(); else - callback(); - }); + return Promise.resolve(); + }).nodeify(callback); }, createDatabase: function(dbName, options, callback) { @@ -270,7 +271,8 @@ var MysqlDriver = Base.extend({ removeColumn: function(tableName, columnName, callback) { var sql = util.format('ALTER TABLE `%s` DROP COLUMN `%s`', tableName, columnName); - this.runSql(sql, callback); + + return this.runSql(sql).nodeify(callback); }, addIndex: function(tableName, indexName, columns, unique, callback) { @@ -283,7 +285,7 @@ var MysqlDriver = Base.extend({ columns = [columns]; } var sql = util.format('ALTER TABLE `%s` ADD %s INDEX `%s` (`%s`)', tableName, (unique ? 'UNIQUE ' : ''), indexName, columns.join('`, `')); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, insert: function(tableName, columnNameArray, valueArray, callback) { @@ -311,7 +313,7 @@ var MysqlDriver = Base.extend({ } sql += columnNames + ') '+ values + ');'; - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, removeIndex: function(tableName, indexName, callback) { @@ -326,7 +328,8 @@ var MysqlDriver = Base.extend({ } var sql = util.format('DROP INDEX `%s` ON `%s`', indexName, tableName); - this.runSql(sql, callback); + + return this.runSql(sql).nodeify(callback); }, dropTable: function(tableName, options, callback) { @@ -340,13 +343,14 @@ var MysqlDriver = Base.extend({ ifExistsSql = 'IF EXISTS'; } var sql = util.format('DROP TABLE %s `%s`', ifExistsSql, tableName); - this.runSql(sql, callback); + + return this.runSql(sql).nodeify(callback); }, renameColumn: function(tableName, oldColumnName, newColumnName, callback) { var self = this, columnTypeSql = util.format("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s' AND COLUMN_NAME = '%s'", tableName, oldColumnName); - this.all(columnTypeSql, function(err, result) { + this.runSql(columnTypeSql, function(err, result) { var columnType = result[0].COLUMN_TYPE; var alterSql = util.format("ALTER TABLE `%s` CHANGE `%s` `%s` %s", tableName, oldColumnName, newColumnName, columnType); self.runSql(alterSql, callback); @@ -480,7 +484,13 @@ var MysqlDriver = Base.extend({ }, close: function(callback) { - this.connection.end(callback); + return new Promise(function(resolve, reject) { + var cb = (function(err, data) { + return (err ? reject(err) : resolve(data)); + }); + + this.connection.end(cb); + }.bind(this)).nodeify(callback); } }); diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 7eef5ca9..9a38a69b 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -248,17 +248,18 @@ var PgDriver = Base.extend({ }, changeColumn: function(tableName, columnName, columnSpec, callback) { - setNotNull.call(this); + return setNotNull.call(this); function setNotNull() { var setOrDrop = columnSpec.notNull === true ? 'SET' : 'DROP'; var sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" %s NOT NULL', tableName, columnName, setOrDrop); - this.runSql(sql, setUnique.bind(this)); + + return this.runSql(sql).nodeify(setUnique.bind(this)); } function setUnique(err) { if (err) { - callback(err); + return Promise.reject(err); } var sql; @@ -266,18 +267,18 @@ var PgDriver = Base.extend({ if (columnSpec.unique === true) { sql = util.format('ALTER TABLE "%s" ADD CONSTRAINT "%s" UNIQUE ("%s")', tableName, constraintName, columnName); - this.runSql(sql, setDefaultValue.bind(this)); + return this.runSql(sql).nodeify(setDefaultValue.bind(this)); } else if (columnSpec.unique === false) { sql = util.format('ALTER TABLE "%s" DROP CONSTRAINT "%s"', tableName, constraintName); - this.runSql(sql, setDefaultValue.bind(this)); + return this.runSql(sql).nodeify(setDefaultValue.bind(this)); } else { - setDefaultValue.call(this); + return setDefaultValue.call(this); } } function setDefaultValue(err) { if (err) { - return callback(err); + return Promise.reject(err).nodeify(callback); } var sql; @@ -294,7 +295,7 @@ var PgDriver = Base.extend({ sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" DROP DEFAULT', tableName, columnName); } - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); } }, @@ -378,7 +379,7 @@ var PgDriver = Base.extend({ close: function(callback) { this.connection.end(); - callback(null); + return Promise.resolve().nodeify(callback); } }); diff --git a/lib/driver/sqlite3.js b/lib/driver/sqlite3.js index cfda1d73..31f88ca9 100644 --- a/lib/driver/sqlite3.js +++ b/lib/driver/sqlite3.js @@ -137,7 +137,7 @@ var Sqlite3Driver = Base.extend({ close: function(callback) { this.connection.close(); - callback(null); + return Promise.resolve().nodeify(callback); } }); From c66d1a9d36fa3abb49055495c148ad073dc4c090 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Apr 2015 12:38:41 +0200 Subject: [PATCH 024/412] fix exit code behavior and sqlite close behavior on promisification --- api.js | 6 ++++++ lib/driver/sqlite3.js | 6 +++++- lib/migrator.js | 5 ++--- test/integration/create_test.js | 3 ++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/api.js b/api.js index 6f246240..a17a8824 100644 --- a/api.js +++ b/api.js @@ -52,6 +52,11 @@ function registerEvents() { log.error(err.stack); process.exit(1); }); + + process.on("unhandledRejection", function(reason, promise) { + log.error(err.stack); + process.exit(1); + }); } dbmigrate.prototype = { @@ -578,6 +583,7 @@ function executeSeed() { internals.onComplete = onComplete; function onComplete(migrator, originalErr) { + migrator.driver.close(function(err) { assert.ifError(originalErr); assert.ifError(err); diff --git a/lib/driver/sqlite3.js b/lib/driver/sqlite3.js index 31f88ca9..24579a21 100644 --- a/lib/driver/sqlite3.js +++ b/lib/driver/sqlite3.js @@ -137,7 +137,11 @@ var Sqlite3Driver = Base.extend({ close: function(callback) { this.connection.close(); - return Promise.resolve().nodeify(callback); + + if(typeof(callback) === 'function') + callback(null); + else + return Promise.resolve(); } }); diff --git a/lib/migrator.js b/lib/migrator.js index be1f8750..3f70c1d7 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -89,7 +89,6 @@ Migrator.prototype = { async.forEachSeries(toRun, function(migration, next) { log.verbose('preparing to run up migration:', migration.name); self.driver.startMigration() - .catch(callback) .then(function() { var setup = migration.setup(); @@ -101,7 +100,7 @@ Migrator.prototype = { if (err) { callback(err); return; } self.writeMigrationRecord(migration, function() { self.driver.endMigration(next); }); }); - }); + }).catch(next); }, callback); }); }); @@ -145,7 +144,7 @@ Migrator.prototype = { self.driver.endMigration(next); }); }); - }); + }).catch(next); }, callback); }); } diff --git a/test/integration/create_test.js b/test/integration/create_test.js index 5e59973f..56eb72c3 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -174,6 +174,7 @@ vows.describe('create').addBatch({ }.bind(this)); }, 'does cause an error': function(error, code) { + console.log(arguments); assert.equal(error, 1); }, 'did create the new migration': function(error, code) { @@ -186,7 +187,7 @@ vows.describe('create').addBatch({ } }, teardown: function() { - cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); + //cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); } } }).export(module); From 54e1cb05500093de1ec633fbeac81ca69ab0bfed Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Apr 2015 12:39:33 +0200 Subject: [PATCH 025/412] enable teardown again --- test/integration/create_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/create_test.js b/test/integration/create_test.js index 56eb72c3..ff15dc83 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -187,7 +187,7 @@ vows.describe('create').addBatch({ } }, teardown: function() { - //cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); + cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); } } }).export(module); From 6657af01e54c9b6f6b907523a7fd86d135b0273f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Apr 2015 23:36:42 +0200 Subject: [PATCH 026/412] nearly about finishing promisification of drivers --- lib/driver/mongodb.js | 186 ++++++++++++++++++++++++------------------ lib/driver/mysql.js | 29 ++++--- lib/driver/pg.js | 27 +++--- lib/driver/sqlite3.js | 3 +- 4 files changed, 135 insertions(+), 110 deletions(-) diff --git a/lib/driver/mongodb.js b/lib/driver/mongodb.js index aef0626f..f46bda13 100644 --- a/lib/driver/mongodb.js +++ b/lib/driver/mongodb.js @@ -23,7 +23,8 @@ var MongodbDriver = Base.extend({ * @param callback */ _createMigrationsCollection: function(callback) { - this._run('createCollection', internals.migrationTable, null, callback); + return this._run('createCollection', internals.migrationTable, null) + .nodeify(callback); }, @@ -33,7 +34,8 @@ var MongodbDriver = Base.extend({ * @param callback */ _createSeedsCollection: function(callback) { - this._run('createCollection', internals.seedsTable, null, callback); + return this._run('createCollection', internals.seedsTable, null) + .nodeify(callback); }, /** @@ -57,7 +59,8 @@ var MongodbDriver = Base.extend({ * @param callback */ createCollection: function(collectionName, callback) { - this._run('createCollection', collectionName, null, callback); + return this._run('createCollection', collectionName, null) + .nodeify(callback); }, switchDatabase: function(options, callback) { @@ -65,11 +68,13 @@ var MongodbDriver = Base.extend({ if(typeof(options) === 'object') { if(typeof(options.database) === 'string') - this._run('use', options, null, callback); + return this._run('use', options, null) + .nodeify(callback); } else if(typeof(options) === 'string') { - this._run('use', options, null, callback); + return this._run('use', options, null) + .nodeify(callback); } else return Promise.resolve().nodeify(callback); @@ -88,7 +93,8 @@ var MongodbDriver = Base.extend({ if(typeof(options) === 'function') callback = options; - this._run('dropDatabase', dbName, null, callback); + return this._run('dropDatabase', dbName, null) + .nodeify(callback); }, /** @@ -108,7 +114,8 @@ var MongodbDriver = Base.extend({ * @param callback */ dropCollection: function(collectionName, callback) { - this._run('dropCollection', collectionName, null, callback); + return this._run('dropCollection', collectionName, null) + .nodeify(callback); }, /** @@ -129,7 +136,8 @@ var MongodbDriver = Base.extend({ * @param callback */ renameCollection: function(collectionName, newCollectionName, callback) { - this._run('renameCollection', collectionName, {newCollection: newCollectionName}, callback); + return this._run('renameCollection', collectionName, {newCollection: newCollectionName}) + .nodeify(callback); }, /** @@ -140,7 +148,8 @@ var MongodbDriver = Base.extend({ * @param callback */ renameTable: function(collectionName, newCollectionName, callback) { - this.renameCollection(collectionName, newCollectionName, callback); + return this.renameCollection(collectionName, newCollectionName) + .nodeify(callback); }, /** @@ -159,7 +168,8 @@ var MongodbDriver = Base.extend({ unique: unique }; - this._run('createIndex', collectionName, options, callback); + return this._run('createIndex', collectionName, options) + .nodeify(callback); }, /** @@ -170,7 +180,8 @@ var MongodbDriver = Base.extend({ * @param columns */ removeIndex: function(collectionName, indexName, callback) { - this._run('dropIndex', collectionName, {indexName: indexName}, callback); + return this._run('dropIndex', collectionName, {indexName: indexName}) + .nodeify(callback); }, /** @@ -181,7 +192,8 @@ var MongodbDriver = Base.extend({ * @param callback */ insert: function(collectionName, toInsert, callback) { - this._run('insert', collectionName, toInsert, callback); + return this._run('insert', collectionName, toInsert) + .nodeify(callback); }, /** @@ -191,7 +203,8 @@ var MongodbDriver = Base.extend({ * @param callback */ addMigrationRecord: function (name, callback) { - this._run('insert', internals.migrationTable, {name: name, run_on: new Date}, callback); + return this._run('insert', internals.migrationTable, {name: name, run_on: new Date}) + .nodeify(callback); }, /** @@ -202,7 +215,8 @@ var MongodbDriver = Base.extend({ * @param callback */ _find: function(collectionName, query, callback) { - this._run('find', collectionName, query, callback); + return this._run('find', collectionName, query) + .nodeify(callback); }, /** @@ -211,7 +225,8 @@ var MongodbDriver = Base.extend({ * @param callback - The callback to call with the collection names */ _getCollectionNames: function(callback) { - this._run('collections', null, null, callback); + return this._run('collections', null, null) + .nodeify(callback); }, /** @@ -221,7 +236,8 @@ var MongodbDriver = Base.extend({ * @param callback - The callback to call with the collection names */ _getIndexes: function(collectionName, callback) { - this._run('indexInformation', collectionName, null, callback); + return this._run('indexInformation', collectionName, null) + .nodeify(callback); }, /** @@ -247,78 +263,84 @@ var MongodbDriver = Base.extend({ } if(internals.dryRun) { - return callback(); + return Promise.resolve().nodeify(callback); } - // Get a connection to mongo - this.connection.connect(connectionString, function(err, db) { - - if(err) { - return callback(err); - } + return new Promise(function(resolve, reject) { + var prCB = function(err, data) { + return (err ? reject(err) : resolve(data)); + }; - // Callback function to return mongo records - var callbackFunction = function(err, data) { + // Get a connection to mongo + this.connection.connect(connectionString, function(err, db) { if(err) { - return callback(err); + prCB(err); } - callback(null, data); - db.close(); - }; - - // Depending on the command, we need to use different mongo methods - switch(command) { - case 'find': + // Callback function to return mongo records + var callbackFunction = function(err, data) { - if(sort) { - db.collection(collection)[command](options.query).sort(sort).toArray(callbackFunction); - } - else { - db.collection(collection)[command](options).toArray(callbackFunction); + if(err) { + prCB(err); } - break; - case 'renameCollection': - db[command](collection, options.newCollection, callbackFunction); - break; - case 'createIndex': - db[command](collection, options.columns, {name: options.indexName, unique: options.unique}, callbackFunction); - break; - case 'dropIndex': - db.collection(collection)[command](options.indexName, callbackFunction); - break; - case 'insert': - // options is the records to insert in this case - if(util.isArray(options)) - db.collection(collection).insertMany(options, {}, callbackFunction); - else - db.collection(collection).insertOne(options, {}, callbackFunction); - break; - case 'remove': - // options is the records to insert in this case - if(util.isArray(options)) - db.collection(collection).deleteMany(options, callbackFunction); - else - db.collection(collection).deleteOne(options, callbackFunction); - break; - case 'collections': - db.collections(callbackFunction); - break; - case 'indexInformation': - db.indexInformation(collection, callbackFunction); - break; - case 'dropDatabase': - db.dropDatabase(callbackFunction); - break; - case 'use': - db.db(collection, callbackFunction); - break; - default: - db[command](collection, callbackFunction); - break; - } - }); + + prCB(null, data); + db.close(); + }; + + // Depending on the command, we need to use different mongo methods + switch(command) { + case 'find': + + if(sort) { + db.collection(collection)[command](options.query).sort(sort).toArray(callbackFunction); + } + else { + db.collection(collection)[command](options).toArray(callbackFunction); + } + break; + case 'renameCollection': + db[command](collection, options.newCollection, callbackFunction); + break; + case 'createIndex': + db[command](collection, options.columns, {name: options.indexName, unique: options.unique}, callbackFunction); + break; + case 'dropIndex': + db.collection(collection)[command](options.indexName, callbackFunction); + break; + case 'insert': + // options is the records to insert in this case + if(util.isArray(options)) + db.collection(collection).insertMany(options, {}, callbackFunction); + else + db.collection(collection).insertOne(options, {}, callbackFunction); + break; + case 'remove': + // options is the records to insert in this case + if(util.isArray(options)) + db.collection(collection).deleteMany(options, callbackFunction); + else + db.collection(collection).deleteOne(options, callbackFunction); + break; + case 'collections': + db.collections(callbackFunction); + break; + case 'indexInformation': + db.indexInformation(collection, callbackFunction); + break; + case 'dropDatabase': + db.dropDatabase(callbackFunction); + break; + case 'use': + db.db(collection, callbackFunction); + break; + default: + db[command](collection, callbackFunction); + break; + } + }); + }.bind(this)).nodeify(callback); }, _makeParamArgs: function(args) { @@ -347,7 +369,8 @@ var MongodbDriver = Base.extend({ * @param callback */ allLoadedMigrations: function(callback) { - this._run('find', internals.migrationTable, { sort: { run_on: -1 } }, callback); + return this._run('find', internals.migrationTable, { sort: { run_on: -1 } }) + .nodeify(callback); }, /** @@ -357,7 +380,8 @@ var MongodbDriver = Base.extend({ * @param callback */ deleteMigration: function(migrationName, callback) { - this._run('remove', internals.migrationTable, {name: migrationName}, callback); + return this._run('remove', internals.migrationTable, {name: migrationName}) + .nodeify(callback); }, /** diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 4ef11d2c..f2646f0b 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -200,11 +200,12 @@ var MysqlDriver = Base.extend({ var sql = util.format('CREATE TABLE %s `%s` (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql); - this.runSql(sql, function() + return this.runSql(sql) + .then(function() { - this.recurseCallbackArray(foreignKeys, callback); - }.bind(this)); + return this.recurseCallbackArray(foreignKeys); + }.bind(this)).nodeify(callback); }, renameTable: function(tableName, newTableName, callback) { @@ -350,11 +351,13 @@ var MysqlDriver = Base.extend({ renameColumn: function(tableName, oldColumnName, newColumnName, callback) { var self = this, columnTypeSql = util.format("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s' AND COLUMN_NAME = '%s'", tableName, oldColumnName); - this.runSql(columnTypeSql, function(err, result) { + return this.runSql(columnTypeSql) + .then(function(result) { var columnType = result[0].COLUMN_TYPE; var alterSql = util.format("ALTER TABLE `%s` CHANGE `%s` `%s` %s", tableName, oldColumnName, newColumnName, columnType); - self.runSql(alterSql, callback); - }); + + return self.runSql(alterSql); + }).nodeify(callback); }, changeColumn: function(tableName, columnName, columnSpec, callback) { @@ -363,19 +366,21 @@ var MysqlDriver = Base.extend({ var exec = function() { - this.runSql(sql, function() + return this.runSql(sql) + .then(function() { if(constraint.foreignKey) - constraint.foreignKey(callback); + return constraint.foreignKey(); else - callback(); - }); + return Promise.resolve(); + }).nodeify(callback); }.bind(this); if(columnSpec.unique === false) - this.removeIndex(tableName, columnName, exec); + return this.removeIndex(tableName, columnName) + .then(exec); else - exec(); + return exec(); }, addMigrationRecord: function (name, callback) { diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 9a38a69b..443ea02e 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -147,10 +147,8 @@ var PgDriver = Base.extend({ ifNotExists: false }; - this.runSql('select version() as version', function(err, result) { - if (err) { - return callback(err); - } + return this.runSql('select version() as version') + .then(function(result) { if (result && result.rows && result.rows.length > 0 && result.rows[0].version) { var version = result.rows[0].version; @@ -162,10 +160,8 @@ var PgDriver = Base.extend({ // Get the current search path so we can change the current schema // if necessary - this.runSql("SHOW search_path", function(err, result) { - if (err) { - return callback(err); - } + return this.runSql("SHOW search_path") + .then(function(result) { var searchPath; @@ -178,21 +174,20 @@ var PgDriver = Base.extend({ searchPath = this.schema + ',' + result.rows[0].search_path; } - this.runSql('SET search_path TO ' + searchPath, function() { - this.runSql("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.migrationTable + "'", function(err, result) { - if (err) { - return callback(err); - } + return this.runSql('SET search_path TO ' + searchPath) + .then(function() { + return this.runSql("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.migrationTable + "'") + .then(function(result) { if (result && result.rows && result.rows.length < 1) { - this.createTable(internals.migrationTable, options, callback); + return this.createTable(internals.migrationTable, options); } else { - callback(); + return Promise.resolve(); } }.bind(this)); }.bind(this)); }.bind(this)); - }.bind(this)); + }.bind(this)).nodeify(callback); }, createColumnConstraint: function(spec, options, tableName, columnName) { diff --git a/lib/driver/sqlite3.js b/lib/driver/sqlite3.js index 24579a21..7c7d0fef 100644 --- a/lib/driver/sqlite3.js +++ b/lib/driver/sqlite3.js @@ -92,7 +92,8 @@ var Sqlite3Driver = Base.extend({ renameTable: function(tableName, newTableName, callback) { var sql = util.format('ALTER TABLE %s RENAME TO %s', tableName, newTableName); - this.runSql(sql, callback); + + return this.runSql(sql).nodeify(callback); }, //removeColumn: function(tableName, columnName, callback) { From bb7d290c964d8f289b7d6a1cfedb244ad69e419f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Apr 2015 23:41:37 +0200 Subject: [PATCH 027/412] remove observation --- test/integration/create_test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/integration/create_test.js b/test/integration/create_test.js index ff15dc83..5e59973f 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -174,7 +174,6 @@ vows.describe('create').addBatch({ }.bind(this)); }, 'does cause an error': function(error, code) { - console.log(arguments); assert.equal(error, 1); }, 'did create the new migration': function(error, code) { From c4c187af117b7948749dbb0845c4d702c2435987 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 5 Apr 2015 00:37:53 +0200 Subject: [PATCH 028/412] promification of createMigrationsTable --- lib/driver/base.js | 10 +++++---- lib/driver/pg.js | 51 +++++++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 20d35c7c..431af8ec 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -182,11 +182,11 @@ module.exports = Base = Class.extend({ var sql = util.format('CREATE TABLE %s "%s" (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql); - this.runSql(sql, function() + return this.runSql(sql) + .then(function() { - - this.recurseCallbackArray(foreignKeys, callback); - }.bind(this)); + return this.recurseCallbackArray(foreignKeys); + }.bind(this)).nodeify(callback); }, dropTable: function(tableName, options, callback) { @@ -354,3 +354,5 @@ module.exports = Base = Class.extend({ return str.replace(/'/g, "''"); } }); + +Promise.promisifyAll(Base); diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 443ea02e..5fa494bd 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -160,34 +160,35 @@ var PgDriver = Base.extend({ // Get the current search path so we can change the current schema // if necessary - return this.runSql("SHOW search_path") - .then(function(result) { + return this.runSql("SHOW search_path"); + }.bind(this)) + .then(function(result) { - var searchPath; + var searchPath; - // if the user specified a different schema, prepend it to the - // search path. This will make all DDL/DML/SQL operate on the specified - // schema. - if (this.schema === 'public') { - searchPath = result.rows[0].search_path; - } else { - searchPath = this.schema + ',' + result.rows[0].search_path; - } + // if the user specified a different schema, prepend it to the + // search path. This will make all DDL/DML/SQL operate on the specified + // schema. + if (this.schema === 'public') { + searchPath = result.rows[0].search_path; + } else { + searchPath = this.schema + ',' + result.rows[0].search_path; + } - return this.runSql('SET search_path TO ' + searchPath) - .then(function() { - return this.runSql("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.migrationTable + "'") - .then(function(result) { - - if (result && result.rows && result.rows.length < 1) { - return this.createTable(internals.migrationTable, options); - } else { - return Promise.resolve(); - } - }.bind(this)); - }.bind(this)); - }.bind(this)); - }.bind(this)).nodeify(callback); + return this.runSql('SET search_path TO ' + searchPath); + }.bind(this)) + .then(function() { + + return this.runSql("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.migrationTable + "'"); + }.bind(this)) + .then(function(result) { + + if (result && result.rows && result.rows.length < 1) { + return this.createTable(internals.migrationTable, options); + } else { + return Promise.resolve(); + } + }.bind(this)).nodeify(callback); }, createColumnConstraint: function(spec, options, tableName, columnName) { From 1c300fb8d2ca57f8ddca60f20f5643ad5dcef30f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 5 Apr 2015 00:45:22 +0200 Subject: [PATCH 029/412] test strange behavior --- lib/driver/pg.js | 59 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 5fa494bd..4229bdcd 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -184,13 +184,70 @@ var PgDriver = Base.extend({ .then(function(result) { if (result && result.rows && result.rows.length < 1) { - return this.createTable(internals.migrationTable, options); + return this.testTable(internals.migrationTable, options); } else { return Promise.resolve(); } }.bind(this)).nodeify(callback); }, + testTable: function(tableName, options, callback) { + log.verbose('creating table:', tableName); + var columnSpecs = options; + var tableOptions = {}; + + if (options.columns !== undefined) { + columnSpecs = options.columns; + delete options.columns; + tableOptions = options; + } + + var ifNotExistsSql = ""; + if(tableOptions.ifNotExists) { + ifNotExistsSql = "IF NOT EXISTS"; + } + + var primaryKeyColumns = []; + var columnDefOptions = { + emitPrimaryKey: false + }; + + for (var columnName in columnSpecs) { + var columnSpec = this.normalizeColumnSpec(columnSpecs[columnName]); + columnSpecs[columnName] = columnSpec; + if (columnSpec.primaryKey) { + primaryKeyColumns.push(columnName); + } + } + + var pkSql = ''; + if (primaryKeyColumns.length > 1) { + pkSql = util.format(', PRIMARY KEY (%s)', this.quoteArr(primaryKeyColumns).join(', ')); + } else { + columnDefOptions.emitPrimaryKey = true; + } + + var columnDefs = []; + var foreignKeys = []; + + for (var columnName in columnSpecs) { + var columnSpec = columnSpecs[columnName]; + var constraint = this.createColumnDef(columnName, columnSpec, columnDefOptions, tableName); + + columnDefs.push(constraint.constraints); + if (constraint.foreignKey) + foreignKeys.push(constraint.foreignKey); + } + + var sql = util.format('CREATE TABLE %s "%s" (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql); + + return this.runSql(sql) + .then(function() + { + return this.recurseCallbackArray(foreignKeys); + }.bind(this)).nodeify(callback); + }, + createColumnConstraint: function(spec, options, tableName, columnName) { var constraint = [], cb; From 901614200dbb75ff833445a132aa1a1e74e459f5 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 5 Apr 2015 00:54:33 +0200 Subject: [PATCH 030/412] fix bug appeared together with promises in shadow driver --- lib/driver/pg.js | 59 +------------------------------------------- lib/driver/shadow.js | 3 ++- 2 files changed, 3 insertions(+), 59 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 4229bdcd..5fa494bd 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -184,70 +184,13 @@ var PgDriver = Base.extend({ .then(function(result) { if (result && result.rows && result.rows.length < 1) { - return this.testTable(internals.migrationTable, options); + return this.createTable(internals.migrationTable, options); } else { return Promise.resolve(); } }.bind(this)).nodeify(callback); }, - testTable: function(tableName, options, callback) { - log.verbose('creating table:', tableName); - var columnSpecs = options; - var tableOptions = {}; - - if (options.columns !== undefined) { - columnSpecs = options.columns; - delete options.columns; - tableOptions = options; - } - - var ifNotExistsSql = ""; - if(tableOptions.ifNotExists) { - ifNotExistsSql = "IF NOT EXISTS"; - } - - var primaryKeyColumns = []; - var columnDefOptions = { - emitPrimaryKey: false - }; - - for (var columnName in columnSpecs) { - var columnSpec = this.normalizeColumnSpec(columnSpecs[columnName]); - columnSpecs[columnName] = columnSpec; - if (columnSpec.primaryKey) { - primaryKeyColumns.push(columnName); - } - } - - var pkSql = ''; - if (primaryKeyColumns.length > 1) { - pkSql = util.format(', PRIMARY KEY (%s)', this.quoteArr(primaryKeyColumns).join(', ')); - } else { - columnDefOptions.emitPrimaryKey = true; - } - - var columnDefs = []; - var foreignKeys = []; - - for (var columnName in columnSpecs) { - var columnSpec = columnSpecs[columnName]; - var constraint = this.createColumnDef(columnName, columnSpec, columnDefOptions, tableName); - - columnDefs.push(constraint.constraints); - if (constraint.foreignKey) - foreignKeys.push(constraint.foreignKey); - } - - var sql = util.format('CREATE TABLE %s "%s" (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql); - - return this.runSql(sql) - .then(function() - { - return this.recurseCallbackArray(foreignKeys); - }.bind(this)).nodeify(callback); - }, - createColumnConstraint: function(spec, options, tableName, columnName) { var constraint = [], cb; diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 5b41529f..05a8dd86 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -8,6 +8,7 @@ * In our case, it records the execution of methods. */ + var internals = {}; function Shadow(db) { @@ -43,7 +44,7 @@ exports.infect = function(db, intern) { (function(property) { - db[property] = function() { this._shadowsHost[property].apply(this, arguments); }; + db[property] = function() { return this._shadowsHost[property].apply(this, arguments); }; }(prop)); } } From 296e1d553dacf9257b2911587fc2e615919dd0fc Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 5 Apr 2015 00:59:18 +0200 Subject: [PATCH 031/412] fix config of tests --- test/integration/database.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/database.json b/test/integration/database.json index cbb84032..f790e9c0 100644 --- a/test/integration/database.json +++ b/test/integration/database.json @@ -1,6 +1,6 @@ { "dev": { "driver": "sqlite3", - "filename": "memory" + "filename": ":memory:" } } From e9ee0558b57a4dc494d3547572c980fdc64219a4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 9 Apr 2015 13:30:34 +0200 Subject: [PATCH 032/412] update dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 011a63a4..8097bab8 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "dotenv": "~1.1.0", "final-fs": "^1.6.0", "mkdirp": "~0.5.0", - "moment": "~2.9.0", + "moment": "~2.10.2", "mongodb": "^2.0.23", "mysql": "~2.6.0", "optimist": "~0.6.1", From 85397aa4653c7597d2f2f2ce461bcf3def0f2bc3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 14 Apr 2015 23:42:09 +0200 Subject: [PATCH 033/412] allow user and username in config for user convienience --- lib/driver/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/driver/index.js b/lib/driver/index.js index 50731cf9..dcaf7dbe 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -15,6 +15,9 @@ exports.connect = function (config, intern, callback) { internals = intern; internals.mod = mod; + if ( !config.user && config.username ) + config.user = config.username; + if (config.driver === undefined) { throw new Error( 'config must include a driver key specifing which driver to use'); From 0e45239c1bfea698da714f33ed1923033ffec16b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 18 Apr 2015 13:42:54 +0200 Subject: [PATCH 034/412] [bugfix] createMigrationTable crashes on pg while dryRun is active CreateMigrationsTable used runSql instead of all, thus it could not execute the necessary functionality while the dryRun, also this is needed to proceed. runSql was replaced by all and all was also promisified to work properly. the access from row was removed while replacing runSql with all. fixes #259 --- lib/driver/pg.js | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 5fa494bd..3622f55f 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -147,11 +147,11 @@ var PgDriver = Base.extend({ ifNotExists: false }; - return this.runSql('select version() as version') + return this.all('select version() as version') .then(function(result) { - if (result && result.rows && result.rows.length > 0 && result.rows[0].version) { - var version = result.rows[0].version; + if (result && result && result.length > 0 && result[0].version) { + var version = result[0].version; var match = version.match(/\d+\.\d+\.\d+/); if (match && match[0] && semver.gte(match[0], '9.1.0')) { options.ifNotExists = true; @@ -160,7 +160,7 @@ var PgDriver = Base.extend({ // Get the current search path so we can change the current schema // if necessary - return this.runSql("SHOW search_path"); + return this.all("SHOW search_path"); }.bind(this)) .then(function(result) { @@ -170,20 +170,20 @@ var PgDriver = Base.extend({ // search path. This will make all DDL/DML/SQL operate on the specified // schema. if (this.schema === 'public') { - searchPath = result.rows[0].search_path; + searchPath = result[0].search_path; } else { - searchPath = this.schema + ',' + result.rows[0].search_path; + searchPath = this.schema + ',' + result[0].search_path; } - return this.runSql('SET search_path TO ' + searchPath); + return this.all('SET search_path TO ' + searchPath); }.bind(this)) .then(function() { - return this.runSql("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.migrationTable + "'"); + return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.migrationTable + "'"); }.bind(this)) .then(function(result) { - if (result && result.rows && result.rows.length < 1) { + if (result && result && result.length < 1) { return this.createTable(internals.migrationTable, options); } else { return Promise.resolve(); @@ -368,9 +368,16 @@ var PgDriver = Base.extend({ all: function() { params = arguments; - this.connection.query.apply(this.connection, [params[0], function(err, result){ - params[1](err, result.rows); - }]); + return new Promise(function(resolve, reject) { + var prCB = function(err, data) { + return (err ? reject(err) : resolve(data)); + }; + + this.connection.query.apply(this.connection, [params[0], function(err, result){ + prCB(err, result.rows); + }]); + + }.bind(this)).nodeify(params[1]); }, close: function(callback) { From 19b9c61616bc0626f095a74dfb4db385d006e233 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 18 Apr 2015 13:44:50 +0200 Subject: [PATCH 035/412] change module loading --- bin/db-migrate | 2 +- index.js | 54 ++++++++++++++++++++++++++++++++++++++++++- lib/driver/mongodb.js | 2 +- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/bin/db-migrate b/bin/db-migrate index ab29a290..601935ea 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -18,6 +18,6 @@ resolve( 'db-migrate', { DBMigrate = require( localModule ); } - dbmigrate = new DBMigrate(); + dbmigrate = DBMigrate.getInstance(); dbmigrate.run(); } ); diff --git a/index.js b/index.js index 0c49c37c..3a638f5d 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,56 @@ var pkginfo = require('pkginfo')(module, 'version'); exports.dataType = require('./lib/data_type'); -module.exports = require( './api.js' ); + + +/** + * Removes a module from the cache + */ +uncache = function (moduleName) { + // Run over the cache looking for the files + // loaded by the specified module name + searchCache(moduleName, function (mod) { + delete require.cache[mod.id]; + }); + + // Remove cached paths to the module. + // Thanks to @bentael for pointing this out. + Object.keys(module.constructor._pathCache).forEach(function(cacheKey) { + if (cacheKey.indexOf(moduleName)>0) { + delete module.constructor._pathCache[cacheKey]; + } + }); +}; + +/** + * Runs over the cache to search for all the cached + * files + */ +searchCache = function (moduleName, callback) { + // Resolve the module identified by the specified name + var mod = require.resolve(moduleName); + + // Check if the module has been resolved and found within + // the cache + if (mod && ((mod = require.cache[mod]) !== undefined)) { + // Recursively go over the results + (function run(mod) { + // Go over each of the module's children and + // run over it + mod.children.forEach(function (child) { + run(child); + }); + + // Call the specified callback providing the + // found module + callback(mod); + })(mod); + } +}; + +module.exports.getInstance = function(isModule, callback) { + + uncache('./api.js'); + var mod = require( './api.js' ); + return new mod(isModule, callback); +}; diff --git a/lib/driver/mongodb.js b/lib/driver/mongodb.js index f46bda13..81b47d14 100644 --- a/lib/driver/mongodb.js +++ b/lib/driver/mongodb.js @@ -4,7 +4,7 @@ var MongoClient = require('mongodb').MongoClient; var Server = require('mongodb').Server; var Base = require('./base'); var type = require('../data_type'); -var log = require('../log'); +var log = require('../log.js'); var Promise = require('bluebird'); var connectionString, internals = {}; From 7ba00f1fada7165e5358aa3e4ca3171300f51f06 Mon Sep 17 00:00:00 2001 From: Fyodor Wolf Date: Thu, 30 Apr 2015 13:47:44 -0400 Subject: [PATCH 036/412] Added postgres changeColumn TYPE support --- lib/driver/pg.js | 15 ++++++++++++++- test/driver/pg_test.js | 19 ++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 3622f55f..6c882e98 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -290,8 +290,21 @@ var PgDriver = Base.extend({ } else { sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" DROP DEFAULT', tableName, columnName); } + return this.runSql(sql).nodeify(setType.bind(this)); + } - return this.runSql(sql).nodeify(callback); + function setType(err) { + if (err) { + return Promise.reject(err).nodeify(callback); + } + if (columnSpec.type != undefined){ + var using = columnSpec.using != undefined ? + columnSpec.using : util.format("USING %s::%s", columnName, this.mapDataType(columnSpec.type)) + var sql = util.format('ALTER TABLE %s ALTER COLUMN "%s" TYPE %s %s', tableName, columnName, this.mapDataType(columnSpec.type), using); + return this.runSql(sql).nodeify(callback); + } + //should this have explicit else? + return callback.call(this); } }, diff --git a/test/driver/pg_test.js b/test/driver/pg_test.js index fde22d38..fea255e9 100644 --- a/test/driver/pg_test.js +++ b/test/driver/pg_test.js @@ -1,3 +1,4 @@ +var util = require('util'); var vows = require('vows'); var assert = require('assert'); var dbmeta = require('db-meta'); @@ -292,17 +293,20 @@ driver.connect(config, internals, function(err, db) { db.createTable('event', { id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, txt: { type: dataType.TEXT, notNull: true, unique: true, defaultValue: "foo" }, - keep_id: { type: dataType.INTEGER, notNull: true, unique: true } + keep_id: { type: dataType.INTEGER, notNull: true, unique: true }, + type_test: {type:dataType.BLOB, notNull:true} }, function() { var spec = { notNull: false, defaultValue: "foo2", unique: false }, - spec2 = { notNull: true, unsigned: true }; + spec2 = { notNull: true, unsigned: true}, + spec3 = { type:dataType.INTEGER, using:util.format('USING CAST(CAST("type_test" AS %s) AS %s)', dataType.TEXT, dataType.INTEGER) }; db.changeColumn('event', 'txt', spec, function() { - db.changeColumn('event', 'keep_id', spec2, this.callback.bind(this, null)); + db.changeColumn('event', 'keep_id', spec2, function(){ + db.changeColumn('event', 'type_test', spec3, this.callback.bind(this, null)); + }.bind(this)); }.bind(this)); }.bind(this)); }, - 'has column metadata': { topic: function() { dbmeta('pg', { connection:db.connection}, function (err, meta) { @@ -315,7 +319,8 @@ driver.connect(config, internals, function(err, db) { 'with changed title column': function(err, columns) { assert.isNotNull(columns); - assert.equal(columns.length, 3); + assert.equal(columns.length, 4); + var column = findByName(columns, 'txt'); assert.equal(column.getName(), 'txt'); assert.equal(column.isNullable(), true); @@ -326,6 +331,10 @@ driver.connect(config, internals, function(err, db) { assert.equal(column.getName(), 'keep_id'); assert.equal(column.isNullable(), false); assert.equal(column.isUnique(), true); + + column = findByName(columns, 'type_test'); + assert.equal(column.getName(), 'type_test'); + assert.equal(dataType[column.getDataType()], dataType.INTEGER); } }, From 197e407ee4ce9d27d97625e4f7d55bc5ccbcf2b9 Mon Sep 17 00:00:00 2001 From: Fyodor Wolf Date: Fri, 1 May 2015 13:14:13 -0400 Subject: [PATCH 037/412] fixed setType: typesafe operators, promise, and escaping. --- lib/driver/pg.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 6c882e98..b91bb64e 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -290,21 +290,18 @@ var PgDriver = Base.extend({ } else { sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" DROP DEFAULT', tableName, columnName); } - return this.runSql(sql).nodeify(setType.bind(this)); + return this.runSql(sql).then( + setType.bind(this) + ).nodeify(callback); } - function setType(err) { - if (err) { - return Promise.reject(err).nodeify(callback); - } - if (columnSpec.type != undefined){ - var using = columnSpec.using != undefined ? - columnSpec.using : util.format("USING %s::%s", columnName, this.mapDataType(columnSpec.type)) + function setType() { + if (columnSpec.type !== undefined){ + var using = columnSpec.using !== undefined ? + columnSpec.using : util.format('USING "%s"::%s', columnName, this.mapDataType(columnSpec.type)) var sql = util.format('ALTER TABLE %s ALTER COLUMN "%s" TYPE %s %s', tableName, columnName, this.mapDataType(columnSpec.type), using); - return this.runSql(sql).nodeify(callback); + return this.runSql(sql); } - //should this have explicit else? - return callback.call(this); } }, From 5d500aa2702cde5922f4be3a101b1b6cbcdad15e Mon Sep 17 00:00:00 2001 From: Fyodor Wolf Date: Fri, 1 May 2015 15:29:59 -0400 Subject: [PATCH 038/412] added quotes to tableName --- lib/driver/pg.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index b91bb64e..a39b10ab 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -299,7 +299,7 @@ var PgDriver = Base.extend({ if (columnSpec.type !== undefined){ var using = columnSpec.using !== undefined ? columnSpec.using : util.format('USING "%s"::%s', columnName, this.mapDataType(columnSpec.type)) - var sql = util.format('ALTER TABLE %s ALTER COLUMN "%s" TYPE %s %s', tableName, columnName, this.mapDataType(columnSpec.type), using); + var sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" TYPE %s %s', tableName, columnName, this.mapDataType(columnSpec.type), using); return this.runSql(sql); } } From 64034d4bd3f35653cb0b908ff7d5fc2e1c075cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Willian=20R=2E=20Sabi=C3=A3o?= Date: Thu, 7 May 2015 17:16:19 -0300 Subject: [PATCH 039/412] Change position of force-exit call --- api.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api.js b/api.js index a17a8824..f3e0a732 100644 --- a/api.js +++ b/api.js @@ -266,10 +266,6 @@ dbmigrate.prototype = { run(); - if (internals.argv['force-exit']) { - log.verbose('Forcing exit'); - process.exit(0); - } } }; @@ -588,6 +584,11 @@ function onComplete(migrator, originalErr) { assert.ifError(originalErr); assert.ifError(err); log.info('Done'); + + if (internals.argv['force-exit']) { + log.verbose('Forcing exit'); + process.exit(0); + } }); } From 9e538e7a57bdff4e2de4a1dbb4854e1bbb2ddae6 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 3 May 2015 17:06:48 +0200 Subject: [PATCH 040/412] begin promisification on uptoby --- lib/migrator.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/migrator.js b/lib/migrator.js index 3f70c1d7..407280e7 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -86,6 +86,13 @@ Migrator.prototype = { return; } + return Promise.resolve(toRun).each(function(migration) { + + log.verbose('preparing to run up migration:', migration.name); + + return self.driver.startMigration() + .then() + async.forEachSeries(toRun, function(migration, next) { log.verbose('preparing to run up migration:', migration.name); self.driver.startMigration() From 13905191bd980baf42b2029b7f0bfb2ebda0e68d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 4 May 2015 02:34:23 +0200 Subject: [PATCH 041/412] promisified uptoby --- lib/migrator.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 407280e7..7fc25be3 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -91,11 +91,7 @@ Migrator.prototype = { log.verbose('preparing to run up migration:', migration.name); return self.driver.startMigration() - .then() - - async.forEachSeries(toRun, function(migration, next) { - log.verbose('preparing to run up migration:', migration.name); - self.driver.startMigration() + .catch(callback) .then(function() { var setup = migration.setup(); @@ -103,12 +99,19 @@ Migrator.prototype = { if(typeof(setup) === 'function') setup(internals.migrationOptions); - self.up(migration.up.bind(migration), function(err) { - if (err) { callback(err); return; } - self.writeMigrationRecord(migration, function() { self.driver.endMigration(next); }); - }); - }).catch(next); - }, callback); + return (Promise.promisify(self.up.bind(self)))(migration.up.bind(migration)); + }) + .catch(callback) + .then(function() { + + return (Promise.promisify(self.writeMigrationRecord.bind(self)))(migration); + }) + .catch(callback) + .then(self.driver.endMigration.bind(self.driver)); + }) + .catch(callback) + .nodeify(callback); + }); }); }, From 52090af24820be088b80dfd924470fd0b44efa19 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 5 May 2015 02:56:49 +0200 Subject: [PATCH 042/412] improve error handling of promisified uptoby --- lib/migrator.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 7fc25be3..ae8fdce5 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -101,15 +101,20 @@ Migrator.prototype = { return (Promise.promisify(self.up.bind(self)))(migration.up.bind(migration)); }) - .catch(callback) + .catch(function(e) { + + throw e; + }) .then(function() { return (Promise.promisify(self.writeMigrationRecord.bind(self)))(migration); }) - .catch(callback) .then(self.driver.endMigration.bind(self.driver)); }) - .catch(callback) + .catch(function(e) { + + throw e; + }) .nodeify(callback); }); From 0d82b92a05eeb883f0ad8355dc4abca577dffec6 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 6 May 2015 02:03:55 +0200 Subject: [PATCH 043/412] begin promisification of downtoby --- lib/migrator.js | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index ae8fdce5..7365e71a 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -91,7 +91,6 @@ Migrator.prototype = { log.verbose('preparing to run up migration:', migration.name); return self.driver.startMigration() - .catch(callback) .then(function() { var setup = migration.setup(); @@ -101,10 +100,6 @@ Migrator.prototype = { return (Promise.promisify(self.up.bind(self)))(migration.up.bind(migration)); }) - .catch(function(e) { - - throw e; - }) .then(function() { return (Promise.promisify(self.writeMigrationRecord.bind(self)))(migration); @@ -134,9 +129,29 @@ Migrator.prototype = { return; } - async.forEachSeries(toRun, function(migration, next) { + return Promise.resolve(toRun).each(function(migration) { + log.verbose('preparing to run down migration:', migration.name); + self.driver.startMigration() + .then(function() { + var setup = migration.setup(); + + if(typeof(setup) === 'function') + setup(internals.migrationOptions); + + return (Promise.promisify(self.down.bind(self)))(migration.up.bind(migration)); + }) + }) + .catch(function(e) { + + throw e; + }) + .nodeify(callback); + + async.forEachSeries(toRun, function(migration, next) { + + var setup = migration.setup(); if(typeof(setup) === 'function') From c46192c889eea3bd8b99ee63d8450514a0c0789f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 7 May 2015 00:11:57 +0200 Subject: [PATCH 044/412] promisified downToBy, removed async dependency from migrator --- lib/migrator.js | 37 ++++++------------------------------- lib/seeder.js | 4 ++-- 2 files changed, 8 insertions(+), 33 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 7365e71a..5f34cbc1 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -1,4 +1,3 @@ -var async = require('async'); var dbmUtil = require('./util'); var Migration = require('./migration'); var log = require('./log'); @@ -133,49 +132,25 @@ Migrator.prototype = { log.verbose('preparing to run down migration:', migration.name); - self.driver.startMigration() + return self.driver.startMigration() .then(function() { var setup = migration.setup(); if(typeof(setup) === 'function') setup(internals.migrationOptions); - return (Promise.promisify(self.down.bind(self)))(migration.up.bind(migration)); + return (Promise.promisify(self.down.bind(self)))(migration.down.bind(migration)); }) + .then(function() { + return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); + }) + .then(self.driver.endMigration.bind(self.driver)); }) .catch(function(e) { throw e; }) .nodeify(callback); - - async.forEachSeries(toRun, function(migration, next) { - - - var setup = migration.setup(); - - if(typeof(setup) === 'function') - setup(internals.migrationOptions); - - self.driver.startMigration() - .then(function() { - self.down(migration.down.bind(migration), function(err) { - if (err) { - - callback(err); - return; - } - self.deleteMigrationRecord(migration, function(err) { - if(err) { - - return callback(err); - } - - self.driver.endMigration(next); - }); - }); - }).catch(next); - }, callback); }); } }; diff --git a/lib/seeder.js b/lib/seeder.js index c090b887..cbc8d551 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -98,7 +98,7 @@ Seeder.prototype = { var self = this; - return Migration.loadFromFilesystem(self.seedDir, function(err, allMigrations) { + return Seed.loadFromFilesystem(self.seedDir, function(err, allMigrations) { if (err) { callback(err); return; } @@ -134,7 +134,7 @@ Seeder.prototype = { downToBy: function(count, callback) { var self = this; - Migration.loadFromDatabase(self.seedDir, self.driver, function(err, completedMigrations) { + Seed.loadFromDatabase(self.seedDir, self.driver, function(err, completedMigrations) { if (err) { return callback(err); } var toRun = dbmUtil.filterDown(completedMigrations, count); From 731e2c66d7ce5a50088ce8c4eae4be95da2662ae Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 8 May 2015 04:18:44 +0200 Subject: [PATCH 045/412] improved error handling of seeders --- api.js | 1 + lib/seeder.js | 32 ++++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/api.js b/api.js index a17a8824..19bd0418 100644 --- a/api.js +++ b/api.js @@ -43,6 +43,7 @@ function dbmigrate(isModule, callback) { internals.dbm = dbm; global.dbm = dbm; //deprecated internals.migrationOptions = { dbmigrate: internals.dbm }; + internals.seederOptions = { dbmigrate: internals.dbm }; } diff --git a/lib/seeder.js b/lib/seeder.js index cbc8d551..247f4ac3 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -118,14 +118,20 @@ Seeder.prototype = { log.verbose('preparing to run up seeder:', seeder.name); return self.driver.startMigration() - .catch(callback) .then(function() { + var setup = seeder.setup(); + + if(typeof(setup) === 'function') + setup(internals.seederOptions); + return (Promise.promisify(self.up.bind(self)))(seeder.up.bind(seeder)); - }); + }) + .then(self.driver.endMigration.bind(self.driver)); + }) + .catch(function(e) { + + throw e; }) - .catch(callback) - .then(self.driver.endMigration.bind(self.driver)) - .catch(callback) .nodeify(callback); }); @@ -150,15 +156,21 @@ Seeder.prototype = { log.verbose('preparing to run down seeder:', seeder.name); return self.driver.startMigration() - .catch(callback) .then(function() { + + var setup = seeder.setup(); + + if(typeof(setup) === 'function') + setup(internals.seederOptions); + return (Promise.promisify(self.down.bind(self)))(seeder.down.bind(seeder)); - }); + }) + .then(self.driver.endMigration.bind(self.driver)); }) - .catch(callback) - .then(self.driver.endMigration.bind(self.driver)) - .catch(callback) + .catch(function(e) { + throw e; + }) .nodeify(callback); }); } From 871407cbb6efbef79eae4c83c834f897b47cc1d1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 9 May 2015 16:30:33 +0200 Subject: [PATCH 046/412] add seed table creation methods to drivers --- lib/driver/base.js | 36 +++++++++++++++++++++++++++++ lib/driver/mongodb.js | 47 +++++++++++++++++++++++++++++++++++-- lib/driver/mysql.js | 26 +++++++++++++++++++++ lib/driver/pg.js | 54 +++++++++++++++++++++++++++++++++++++++++++ lib/seed.js | 2 +- 5 files changed, 162 insertions(+), 3 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 431af8ec..47f0fb5b 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -132,6 +132,18 @@ module.exports = Base = Class.extend({ this.createTable(internals.migrationTable, options, callback); }, + createSeedsTable: function(callback) { + var options = { + columns: { + 'id': { type: type.INTEGER, notNull: true, primaryKey: true, autoIncrement: true }, + 'name': { type: type.STRING, length: 255, notNull: true}, + 'run_on': { type: type.DATE_TIME, notNull: true} + }, + ifNotExists: true + }; + this.createTable(internals.seedTable, options, callback); + }, + createTable: function(tableName, options, callback) { log.verbose('creating table:', tableName); var columnSpecs = options; @@ -318,6 +330,10 @@ module.exports = Base = Class.extend({ this.runSql('INSERT INTO "' + internals.migrationTable + '" (name, run_on) VALUES (?, ?)', [name, new Date()], callback); }, + addSeedRecord: function (name, callback) { + this.runSql('INSERT INTO "' + internals.seedTable + '" (name, run_on) VALUES (?, ?)', [name, new Date()], callback); + }, + startMigration: function(cb){ return Promise.resolve().nodeify(cb); }, endMigration: function(cb){ return Promise.resolve().nodeify(cb); }, // sql, params, callback @@ -336,6 +352,16 @@ module.exports = Base = Class.extend({ return this.all(sql, callback); }, + /** + * Queries the seeds table + * + * @param callback + */ + allLoadedSeeds: function(callback) { + var sql = 'SELECT * FROM "' + internals.seedTable + '" ORDER BY run_on DESC, name DESC'; + return this.all(sql, callback); + }, + /** * Deletes a migration * @@ -346,6 +372,16 @@ module.exports = Base = Class.extend({ this.runSql(sql, [migrationName], callback); }, + /** + * Deletes a seed + * + * @param seedName - The name of the seed to be deleted + */ + deleteSeed: function(seedName, callback) { + var sql = 'DELETE FROM "' + internals.seedTable + '" WHERE name = ?'; + this.runSql(sql, [seedName], callback); + }, + all: function(sql, params, callback) { throw new Error('not implemented'); }, diff --git a/lib/driver/mongodb.js b/lib/driver/mongodb.js index 81b47d14..082440e8 100644 --- a/lib/driver/mongodb.js +++ b/lib/driver/mongodb.js @@ -28,13 +28,24 @@ var MongodbDriver = Base.extend({ }, + /** + * Creates the seed collection + * + * @param callback + */ + _createSeedsCollection: function(callback) { + return this._run('createCollection', internals.seedTable, null) + .nodeify(callback); + }, + + /** * Creates the seeder collection * * @param callback */ _createSeedsCollection: function(callback) { - return this._run('createCollection', internals.seedsTable, null) + return this._run('createCollection', internals.seedTable, null) .nodeify(callback); }, @@ -49,7 +60,7 @@ var MongodbDriver = Base.extend({ * An alias for _createSeederCollection */ createSeedsTable: function(callback) { - this._createMigrationsCollection(callback); + this._createSeedsCollection(callback); }, /** @@ -207,6 +218,17 @@ var MongodbDriver = Base.extend({ .nodeify(callback); }, + /** + * Inserts a seeder record into the seeder collection + * + * @param name - The name of the seed being run + * @param callback + */ + addSeedRecord: function (name, callback) { + return this._run('insert', internals.seedTable, {name: name, run_on: new Date}) + .nodeify(callback); + }, + /** * Runs a query * @@ -373,6 +395,16 @@ var MongodbDriver = Base.extend({ .nodeify(callback); }, + /** + * Queries the seed collection + * + * @param callback + */ + allLoadedSeeds: function(callback) { + return this._run('find', internals.seedTable, { sort: { run_on: -1 } }) + .nodeify(callback); + }, + /** * Deletes a migration * @@ -384,6 +416,17 @@ var MongodbDriver = Base.extend({ .nodeify(callback); }, + /** + * Deletes a migration + * + * @param migrationName - The name of the migration to be deleted + * @param callback + */ + deleteSeed: function(migrationName, callback) { + return this._run('remove', internals.seedTable, {name: migrationName}) + .nodeify(callback); + }, + /** * Closes the connection to mongodb */ diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index f2646f0b..36a09ea9 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -388,6 +388,11 @@ var MysqlDriver = Base.extend({ this.runSql('INSERT INTO `' + internals.migrationTable + '` (`name`, `run_on`) VALUES (?, ?)', [name, formattedDate], callback); }, + addSeedRecord: function (name, callback) { + var formattedDate = moment(new Date()).format('YYYY-MM-DD HH:mm:ss'); + this.runSql('INSERT INTO `' + internals.seedTable + '` (`name`, `run_on`) VALUES (?, ?)', [name, formattedDate], callback); + }, + addForeignKey: function(tableName, referencedTableName, keyName, fieldMapping, rules, callback) { if(arguments.length === 5 && typeof(rules) === 'function') { callback = rules; @@ -488,6 +493,27 @@ var MysqlDriver = Base.extend({ this.runSql(sql, [migrationName], callback); }, + /** + * Queries the seeds table + * + * @param callback + */ + allLoadedSeeds: function(callback) { + var sql = 'SELECT * FROM `' + internals.seedTable + '` ORDER BY run_on DESC, name DESC'; + this.all(sql, callback); + }, + + /** + * Deletes a seed + * + * @param seedName - The name of the seed to be deleted + * @param callback + */ + deleteSeed: function(seedName, callback) { + var sql = 'DELETE FROM `' + internals.seedTable + '` WHERE name = ?'; + this.runSql(sql, [seedName], callback); + }, + close: function(callback) { return new Promise(function(resolve, reject) { var cb = (function(err, data) { diff --git a/lib/driver/pg.js b/lib/driver/pg.js index a39b10ab..25fd9ecb 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -191,6 +191,60 @@ var PgDriver = Base.extend({ }.bind(this)).nodeify(callback); }, + createSeedsTable: function(callback) { + var options = { + columns: { + 'id': { type: type.INTEGER, notNull: true, primaryKey: true, autoIncrement: true }, + 'name': { type: type.STRING, length: 255, notNull: true}, + 'run_on': { type: type.DATE_TIME, notNull: true} + }, + ifNotExists: false + }; + + return this.all('select version() as version') + .then(function(result) { + + if (result && result && result.length > 0 && result[0].version) { + var version = result[0].version; + var match = version.match(/\d+\.\d+\.\d+/); + if (match && match[0] && semver.gte(match[0], '9.1.0')) { + options.ifNotExists = true; + } + } + + // Get the current search path so we can change the current schema + // if necessary + return this.all("SHOW search_path"); + }.bind(this)) + .then(function(result) { + + var searchPath; + + // if the user specified a different schema, prepend it to the + // search path. This will make all DDL/DML/SQL operate on the specified + // schema. + if (this.schema === 'public') { + searchPath = result[0].search_path; + } else { + searchPath = this.schema + ',' + result[0].search_path; + } + + return this.all('SET search_path TO ' + searchPath); + }.bind(this)) + .then(function() { + + return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.seedTable + "'"); + }.bind(this)) + .then(function(result) { + + if (result && result && result.length < 1) { + return this.createTable(internals.seedTable, options); + } else { + return Promise.resolve(); + } + }.bind(this)).nodeify(callback); + }, + createColumnConstraint: function(spec, options, tableName, columnName) { var constraint = [], cb; diff --git a/lib/seed.js b/lib/seed.js index f5cfc928..05541678 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -120,7 +120,7 @@ Seed.loadFromFilesystem = function(dir, callback) { Seed.loadFromDatabase = function(dir, driver, callback) { log.verbose('loading seeds from database'); - driver.allLoadedseeds(function(err, dbResults) { + driver.allLoadedSeeds(function(err, dbResults) { if (err && !internals.dryRun) { callback(err); return; } else if (err && internals.dryRun) { dbResults = []; From 43ee4c62ebe3af117ad912956b5189e28dd2eecb Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 9 May 2015 16:42:37 +0200 Subject: [PATCH 047/412] add travis webhook --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3d472d24..b392970c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,12 @@ notifications: email: recipients: - magic@wizardtales.com + webhooks: + urls: + - https://webhooks.gitter.im/e/509c88551a18006fe93f + on_success: change + on_failure: always + on_start: false services: - mongodb From 06d59e03927ed08adba5ac293c6f8fda0ad61230 Mon Sep 17 00:00:00 2001 From: Michael A Anderson Date: Sun, 10 May 2015 11:21:02 -0500 Subject: [PATCH 048/412] semicolon removed example code does not work with it there (syntax error) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9817b103..76d3ce10 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ exports.up = function (db, callback) { db.createTable.bind(db, 'owners', { id: { type: 'int', primaryKey: true }, name: 'string' - }); + }) ], callback); }; From db6a8ae22fab91d398758ba487f6baaddf854cee Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 11 May 2015 03:02:44 +0200 Subject: [PATCH 049/412] edited shadow, to execute the infected first --- lib/driver/index.js | 9 ++++++++- lib/driver/shadow.js | 18 +++++++----------- lib/interface/migratorInterface.js | 13 +++++++------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index dcaf7dbe..e9722948 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -8,6 +8,13 @@ var Shadow = require('./shadow'); var log = internals.mod.log; var tunnel = require('tunnel-ssh'); +var ShadowProto = { + + createTable: function() { return Promise.resolve(); }, + addForeignKey: function() { return Promise.resolve(); }, + createCollection: function() { return Promise.resolve(); } +}; + exports.connect = function (config, intern, callback) { var driver, req; @@ -66,7 +73,7 @@ exports.connect = function (config, intern, callback) { log.verbose('connected'); if (!global.immunity) - db = Shadow.infect(db); + db = Shadow.infect(db, internals, ShadowProto); callback(null, db); }); diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 05a8dd86..760858ff 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -17,19 +17,10 @@ function Shadow(db) { } -var ShadowProto = { - - createTable: function() {}, - addForeignKey: function() {}, - createCollection: function() {} - -}; - - /** * 'Infect' the original class */ -exports.infect = function(db, intern) { +exports.infect = function(db, intern, ShadowProto) { internals = intern; @@ -44,7 +35,12 @@ exports.infect = function(db, intern) { (function(property) { - db[property] = function() { return this._shadowsHost[property].apply(this, arguments); }; + db[property] = function() { + var self = this; + + return ShadowProto[prop].apply(self, arguments) + .then( self._shadowsHost[property].apply(self, arguments) ) + }; }(prop)); } } diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 876088df..c0af289e 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -71,11 +71,6 @@ MigratorInterface.prototype = { arguments[arguments.length - 1]('not implemented'); }, - insert: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - removeIndex: function() { arguments[arguments.length - 1]('not implemented'); @@ -99,6 +94,12 @@ MigratorInterface.prototype = { module.exports.MigratorInterface = MigratorInterface; -module.exports.deprecated = {}; +module.exports.deprecated = { + + insert: function() { + + arguments[arguments.length - 1]('not implemented'); + }, +}; module.exports.extending = { }; From fe82dd71bea4e0941380e6bee170b68a0f5bfe62 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 12 May 2015 02:34:16 +0200 Subject: [PATCH 050/412] add basic dummies, fix typo from migrator interface. going to create the interfaces plus documentation of them. --- lib/interface/migratorInterface.js | 2 +- lib/interface/seederInterface.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index c0af289e..cb9bc65a 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -99,7 +99,7 @@ module.exports.deprecated = { insert: function() { arguments[arguments.length - 1]('not implemented'); - }, + } }; module.exports.extending = { }; diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index f22c67f3..852103aa 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -42,6 +42,14 @@ function insert(table, options, callback) { .nodeify(callback); } +function remove() { + +} + +function get() { + +} + function lookup(options, i, callback) { var lookups = []; From 19198fbf445cc43f769fb60d907fe1da126c4506 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 13 May 2015 03:37:36 +0200 Subject: [PATCH 051/412] add partial remove to base driver --- lib/driver/base.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/lib/driver/base.js b/lib/driver/base.js index 47f0fb5b..7c9b6414 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -372,6 +372,39 @@ module.exports = Base = Class.extend({ this.runSql(sql, [migrationName], callback); }, + /** + * Removes the specified keys from the database + * + * @param table - The table in which the to be deleted values are located + * @param ids - array or object + * id array - arrayof the to be deleted ids + * id object - { table: "name of the table to resolve the ids from", + * column: [ + { + name: "name of column", //defaults to id if unset + operator: ">", //defaults to = if unset + searchValue: "12" + } + ] + } + */ + remove: function(table, ids, callback) { + + var sql = 'DELETE FROM "' + table + '"'; + + if( util.isArray(ids) ) { + + sql += 'WHERE id IN (' + ids.join(',') + ')'; + } + else { + + + } + + return this.runSql(sql).nodeify(callback); + }, + + /** * Deletes a seed * From 45e88367970fea2555cf103bf07e713a3e2a4abd Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 14 May 2015 04:34:16 +0200 Subject: [PATCH 052/412] promisified base driver --- lib/driver/base.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 7c9b6414..214db74e 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -213,7 +213,8 @@ module.exports = Base = Class.extend({ ifExistsSql = 'IF EXISTS'; } var sql = util.format('DROP TABLE %s "%s"', ifExistsSql, tableName); - this.runSql(sql, callback); + + return this.runSql(sql).nodeify(callback); }, renameTable: function(tableName, newTableName, callback) { @@ -267,7 +268,7 @@ module.exports = Base = Class.extend({ var sql = util.format('CREATE %s INDEX "%s" ON "%s" (%s)', (unique ? 'UNIQUE' : ''), indexName, tableName, this.quoteArr(columns).join(', ')); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, insert: function(tableName, columnNameArray, valueArray, callback) { @@ -295,7 +296,7 @@ module.exports = Base = Class.extend({ } sql += columnNames + ') '+ values + ');'; - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, removeIndex: function(tableName, indexName, callback) { @@ -307,7 +308,7 @@ module.exports = Base = Class.extend({ } var sql = util.format('DROP INDEX "%s"', indexName); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, addForeignKey: function() { From 1196d017f4a334241e5c4f2bb67d9ae762c600fe Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 15 May 2015 03:53:17 +0200 Subject: [PATCH 053/412] fix functionality of shadow driver --- lib/driver/base.js | 6 +++--- lib/driver/shadow.js | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 214db74e..32adb8ab 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -393,13 +393,13 @@ module.exports = Base = Class.extend({ var sql = 'DELETE FROM "' + table + '"'; - if( util.isArray(ids) ) { + if( util.isArray(ids) && typeof(ids[0]) !== 'object' ) { sql += 'WHERE id IN (' + ids.join(',') + ')'; } - else { - + else if( util.isArray(ids) && typeof(ids[0]) === 'object' ){ + } return this.runSql(sql).nodeify(callback); diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 760858ff..29cc835a 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -25,6 +25,7 @@ exports.infect = function(db, intern, ShadowProto) { internals = intern; db._shadowsHost = {}; + db._shadowProto = {}; for(var prop in db) { @@ -32,13 +33,14 @@ exports.infect = function(db, intern, ShadowProto) { typeof db[prop] === "function") { db._shadowsHost[prop] = db[prop]; + db._shadowProto[prop] = ShadowProto[prop]; (function(property) { db[property] = function() { var self = this; - return ShadowProto[prop].apply(self, arguments) + return self._shadowProto[property].apply(self, arguments) .then( self._shadowsHost[property].apply(self, arguments) ) }; }(prop)); From e02333986763dfbe808e2f3c1ccd214993584dd3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 16 May 2015 04:24:30 +0200 Subject: [PATCH 054/412] add remove method to base --- lib/driver/base.js | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 32adb8ab..a1546515 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -384,7 +384,10 @@ module.exports = Base = Class.extend({ { name: "name of column", //defaults to id if unset operator: ">", //defaults to = if unset - searchValue: "12" + searchValue: "12", + searchValue: { table: "source" }, + link: "AND", //defaults to AND if unset + selector: "id" //defaults to id if from searchvalue is a table } ] } @@ -392,17 +395,45 @@ module.exports = Base = Class.extend({ remove: function(table, ids, callback) { var sql = 'DELETE FROM "' + table + '"'; + var searchClause = ''; - if( util.isArray(ids) && typeof(ids[0]) !== 'object' ) { + if (util.isArray(ids) && typeof(ids[0]) !== 'object') { sql += 'WHERE id IN (' + ids.join(',') + ')'; } - else if( util.isArray(ids) && typeof(ids[0]) === 'object' ){ + else if (util.isArray(ids) && typeof(ids[0]) === 'object'){ + var preLink = '' + searchClause = ' WHERE '; + + for (var column in ids) { + column.name = column.name || 'id', + column.operator = column.operator || '=', + column.link = column.link || 'AND', + column.selector = column.selector || 'id'; + + if (!column.searchValue) { + + return Promise.reject('column ' + column.name + ' was entered without a searchValue.'); + } + + searchClause += ' ' + preLink + ' "' + column.name + '" ' + column.operator; + + if(typeof(searchValue === 'object' && typeof(searchValue.table) === 'string') { + + searchClause += ' (' + column.searchValue.table + ')'; + } + else { + + searchClause += ' (' + column.searchValue + ')'; + } + + preLink = column.link; + } } - return this.runSql(sql).nodeify(callback); + return this.runSql(sql + searchClause).nodeify(callback); }, From 74da6ca1d74b2186b327fc2e0fbbcd64dc25a2b8 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 17 May 2015 01:43:07 +0200 Subject: [PATCH 055/412] simple relation getter/setter --- lib/relation.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/lib/relation.js b/lib/relation.js index e69de29b..91c8b5dd 100644 --- a/lib/relation.js +++ b/lib/relation.js @@ -0,0 +1,48 @@ +var fs = require('fs'), + log = require('./log'); + + +var relations = {}; + +function Relation() { + +} + +Relation.prototype = { + + addRelation: function(table, column, relatedTable, relatedColumn) { + + relations[table] = relations[table] || {}; + relations[table][column] = relatedColumn; + + }, + + getRelation: function(table, column) { + + return relations[table][column]; + }, + + fromJson: function(file) { + + Relation = require(file); + + log.info( "Read Relations from file " + file ); + }. + + toJson: function(file) { + + fs.writeFile(file, JSON.stringify(relations), function(err) { + + if(err) { + throw err; + } + + log.info( "Wrote Relations to file " + file ); + }); + }, + + clearRelations: function() { + + relations = {}; + } +}; From 31b3ce133907c49de7d01e1aa97a702d03ba58f1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 03:45:59 +0200 Subject: [PATCH 056/412] corrected syntax and set uncaught rejection to use reason instead of err --- api.js | 2 +- lib/driver/base.js | 2 +- lib/relation.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api.js b/api.js index 19bd0418..0897ef6d 100644 --- a/api.js +++ b/api.js @@ -55,7 +55,7 @@ function registerEvents() { }); process.on("unhandledRejection", function(reason, promise) { - log.error(err.stack); + log.error(reason); process.exit(1); }); } diff --git a/lib/driver/base.js b/lib/driver/base.js index a1546515..cb6f790f 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -420,7 +420,7 @@ module.exports = Base = Class.extend({ searchClause += ' ' + preLink + ' "' + column.name + '" ' + column.operator; - if(typeof(searchValue === 'object' && typeof(searchValue.table) === 'string') { + if (typeof(searchValue) === 'object' && typeof(searchValue.table) === 'string') { searchClause += ' (' + column.searchValue.table + ')'; } diff --git a/lib/relation.js b/lib/relation.js index 91c8b5dd..b6c25541 100644 --- a/lib/relation.js +++ b/lib/relation.js @@ -27,7 +27,7 @@ Relation.prototype = { Relation = require(file); log.info( "Read Relations from file " + file ); - }. + }, toJson: function(file) { From 9d977a94fab5eec152042e9ec264aa4c9455b7ea Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 10:50:22 +0200 Subject: [PATCH 057/412] revert promisification --- lib/driver/base.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index cb6f790f..424751a1 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -213,8 +213,7 @@ module.exports = Base = Class.extend({ ifExistsSql = 'IF EXISTS'; } var sql = util.format('DROP TABLE %s "%s"', ifExistsSql, tableName); - - return this.runSql(sql).nodeify(callback); + this.runSql(sql, callback); }, renameTable: function(tableName, newTableName, callback) { @@ -268,7 +267,7 @@ module.exports = Base = Class.extend({ var sql = util.format('CREATE %s INDEX "%s" ON "%s" (%s)', (unique ? 'UNIQUE' : ''), indexName, tableName, this.quoteArr(columns).join(', ')); - return this.runSql(sql).nodeify(callback); + this.runSql(sql, callback); }, insert: function(tableName, columnNameArray, valueArray, callback) { @@ -296,7 +295,7 @@ module.exports = Base = Class.extend({ } sql += columnNames + ') '+ values + ');'; - return this.runSql(sql).nodeify(callback); + this.runSql(sql, callback); }, removeIndex: function(tableName, indexName, callback) { @@ -308,7 +307,7 @@ module.exports = Base = Class.extend({ } var sql = util.format('DROP INDEX "%s"', indexName); - return this.runSql(sql).nodeify(callback); + this.runSql(sql, callback); }, addForeignKey: function() { @@ -436,7 +435,6 @@ module.exports = Base = Class.extend({ return this.runSql(sql + searchClause).nodeify(callback); }, - /** * Deletes a seed * From 675815a68be2a33fd8911e0d2b895ba09a167f46 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 10:59:46 +0200 Subject: [PATCH 058/412] add missing dependency to drivers index.js --- lib/driver/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index e9722948..dacd188f 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -6,7 +6,8 @@ internals.mod.type = require('../data_type'); internals.mod.Class = require('../class'); var Shadow = require('./shadow'); var log = internals.mod.log; -var tunnel = require('tunnel-ssh'); +var tunnel = require('tunnel-ssh'), + Promise = require('bluebird'); var ShadowProto = { From 47ffc7513bb2db6e3774ec73d3dd1d8231dbf359 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 11:03:10 +0200 Subject: [PATCH 059/412] add promisification --- lib/driver/base.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 424751a1..cb6f790f 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -213,7 +213,8 @@ module.exports = Base = Class.extend({ ifExistsSql = 'IF EXISTS'; } var sql = util.format('DROP TABLE %s "%s"', ifExistsSql, tableName); - this.runSql(sql, callback); + + return this.runSql(sql).nodeify(callback); }, renameTable: function(tableName, newTableName, callback) { @@ -267,7 +268,7 @@ module.exports = Base = Class.extend({ var sql = util.format('CREATE %s INDEX "%s" ON "%s" (%s)', (unique ? 'UNIQUE' : ''), indexName, tableName, this.quoteArr(columns).join(', ')); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, insert: function(tableName, columnNameArray, valueArray, callback) { @@ -295,7 +296,7 @@ module.exports = Base = Class.extend({ } sql += columnNames + ') '+ values + ');'; - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, removeIndex: function(tableName, indexName, callback) { @@ -307,7 +308,7 @@ module.exports = Base = Class.extend({ } var sql = util.format('DROP INDEX "%s"', indexName); - this.runSql(sql, callback); + return this.runSql(sql).nodeify(callback); }, addForeignKey: function() { @@ -435,6 +436,7 @@ module.exports = Base = Class.extend({ return this.runSql(sql + searchClause).nodeify(callback); }, + /** * Deletes a seed * From 6c1002f50336927f8902cb5d3c8071de702cf285 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 11:19:18 +0200 Subject: [PATCH 060/412] fixed bug in shadow driver when wrong arguments were passed --- lib/driver/shadow.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 29cc835a..70f06e79 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -39,9 +39,10 @@ exports.infect = function(db, intern, ShadowProto) { db[property] = function() { var self = this; + var params = arguments; - return self._shadowProto[property].apply(self, arguments) - .then( self._shadowsHost[property].apply(self, arguments) ) + return self._shadowProto[property].apply(self, params) + .then( self._shadowsHost[property].apply(self, params) ) }; }(prop)); } From ac67a8caba64980d72803ff9af66c63eac2dedf2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 11:49:18 +0200 Subject: [PATCH 061/412] move shadowHost call into closure --- lib/driver/shadow.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 70f06e79..cbc8824b 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -38,11 +38,13 @@ exports.infect = function(db, intern, ShadowProto) { (function(property) { db[property] = function() { - var self = this; - var params = arguments; + var params = arguments, + callback; - return self._shadowProto[property].apply(self, params) - .then( self._shadowsHost[property].apply(self, params) ) + return this._shadowProto[property].apply(this, params) + .then( function() { + return this._shadowsHost[property].apply(this, params); + }.bind(this)); }; }(prop)); } From c8920bba109cccba172da0dd4536f4472837490c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 12:35:13 +0200 Subject: [PATCH 062/412] move functionality into generic buildWhereClause --- lib/driver/base.js | 64 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index cb6f790f..9d808690 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -381,22 +381,53 @@ module.exports = Base = Class.extend({ * id array - arrayof the to be deleted ids * id object - { table: "name of the table to resolve the ids from", * column: [ - { - name: "name of column", //defaults to id if unset - operator: ">", //defaults to = if unset - searchValue: "12", - searchValue: { table: "source" }, - link: "AND", //defaults to AND if unset - selector: "id" //defaults to id if from searchvalue is a table - } - ] - } + * { + * name: "name of column", //defaults to id if unset + * operator: ">", //defaults to = if unset + * searchValue: "12", + * searchValue: { table: "source", column: [...] }, + * //recursion with objects possible + * link: "AND" //defaults to AND if unset + * } + * ] + * } + * + * @return Promise(runSql) */ remove: function(table, ids, callback) { var sql = 'DELETE FROM "' + table + '"'; var searchClause = ''; + + + return this.runSql(sql + buildWhereClause(ids)).nodeify(callback); + }, + + /** + * Builds a where clause out of column objects. + * + * @param ids - array or object + * id array - arrayof the to be deleted ids + * id object - { table: "name of the table to resolve the ids from", + * column: [ + * { + * name: "name of column", //defaults to id if unset + * operator: ">", //defaults to = if unset + * searchValue: "12", + * searchValue: { table: "source", column: [...] }, + * //recursion with objects possible + * link: "AND" //defaults to AND if unset + * } + * ] + * } + * + * @return string + */ + buildWhereClause: function(ids) { + + var searchClause = ''; + if (util.isArray(ids) && typeof(ids[0]) !== 'object') { sql += 'WHERE id IN (' + ids.join(',') + ')'; @@ -410,8 +441,7 @@ module.exports = Base = Class.extend({ for (var column in ids) { column.name = column.name || 'id', column.operator = column.operator || '=', - column.link = column.link || 'AND', - column.selector = column.selector || 'id'; + column.link = column.link || 'AND'; if (!column.searchValue) { @@ -420,9 +450,13 @@ module.exports = Base = Class.extend({ searchClause += ' ' + preLink + ' "' + column.name + '" ' + column.operator; - if (typeof(searchValue) === 'object' && typeof(searchValue.table) === 'string') { + if (typeof(searchValue) === 'object' && + typeof(searchValue.table) === 'string' && + typeof(searchValue.columns) === 'object') { - searchClause += ' (' + column.searchValue.table + ')'; + searchClause += ' (SELECT ' + column.selector + ' FROM ' + + column.searchValue.table + + buildWhereClause(column.searchValue.column) + ')'; } else { @@ -433,7 +467,7 @@ module.exports = Base = Class.extend({ } } - return this.runSql(sql + searchClause).nodeify(callback); + return searchClause; }, From 1a28b5d6ba0ecbfae5a18daae312585c039761e0 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 12:38:19 +0200 Subject: [PATCH 063/412] add missing automatic quoting --- lib/driver/base.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 9d808690..370ecfa6 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -454,8 +454,8 @@ module.exports = Base = Class.extend({ typeof(searchValue.table) === 'string' && typeof(searchValue.columns) === 'object') { - searchClause += ' (SELECT ' + column.selector + ' FROM ' + - column.searchValue.table + + searchClause += ' (SELECT "' + column.selector + '" FROM "' + + column.searchValue.table + '"' + buildWhereClause(column.searchValue.column) + ')'; } else { From 9086ed6ba2887a4fba1a76060d3a7cc0ecf0c291 Mon Sep 17 00:00:00 2001 From: Mike Atkins Date: Sun, 10 May 2015 20:31:08 -0400 Subject: [PATCH 064/412] Create client as topic --- test/driver/pg_schema_test.js | 53 ++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js index 7270b242..0844dec2 100644 --- a/test/driver/pg_schema_test.js +++ b/test/driver/pg_schema_test.js @@ -11,39 +11,52 @@ var internals = {}; internals.migrationTable = 'migrations'; vows.describe('pg').addBatch({ - 'create schema and connect': { - topic: function() { + 'connect to database': { + topic: function () { var callback = this.callback; - client.connect(function(err) { + client.connect(function (err) { + callback(err, client); + }); + }, + + teardown: function () { + client.end(); + this.callback(); + }, + + 'create schema and connect': { + topic: function() { + var callback = this.callback; + client.query('CREATE SCHEMA test_schema', function(err) { driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, internals, function(err, db) { callback(null, db); }); }); - }); - }, + }, - 'migrations table': { - topic: function(db) { - var callback = this.callback; + 'migrations table': { + topic: function(db) { + var callback = this.callback; - db.createMigrationsTable(function() { - client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", function(err, result) { - callback(err, result); + db.createMigrationsTable(function() { + client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", function(err, result) { + callback(err, result); + }); }); - }); + }, + + 'is in test_schema': function(err, result) { + assert.isNull(err); + assert.isNotNull(result); + assert.equal(result.rowCount, 1); + } }, - 'is in test_schema': function(err, result) { - assert.isNull(err); - assert.isNotNull(result); - assert.equal(result.rowCount, 1); + teardown: function() { + client.query('DROP SCHEMA test_schema CASCADE', this.callback); } - }, - - teardown: function() { - client.query('DROP SCHEMA test_schema CASCADE', this.callback); } } }).export(module); From 9ca944baec4a01129e87a788d63f78511cffb383 Mon Sep 17 00:00:00 2001 From: Mike Atkins Date: Sun, 10 May 2015 20:43:22 -0400 Subject: [PATCH 065/412] Add test for schema escaping --- test/driver/pg_schema_test.js | 96 ++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js index 0844dec2..3ea9e50d 100644 --- a/test/driver/pg_schema_test.js +++ b/test/driver/pg_schema_test.js @@ -5,58 +5,96 @@ var pg = require('pg'); var dataType = require('../../lib/data_type'); var driver = require('../../lib/driver'); -var client = new pg.Client('postgres://localhost/db_migrate_test'); +var databaseUrl = 'postgres://localhost/db_migrate_test'; var internals = {}; internals.migrationTable = 'migrations'; vows.describe('pg').addBatch({ - 'connect to database': { - topic: function () { + 'create schema which needs escaping and connect': { + topic: function() { var callback = this.callback; + var client = new pg.Client(databaseUrl); client.connect(function (err) { - callback(err, client); + if (err) { return callback(err); } + client.query('CREATE SCHEMA "test-schema"', function(err) { + driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test-schema' }, function(err, db) { + callback(err, db, client); + }); + }); }); }, - teardown: function () { - client.end(); - this.callback(); - }, - - 'create schema and connect': { - topic: function() { + 'migrations': { + topic: function(db, client) { var callback = this.callback; - client.query('CREATE SCHEMA test_schema', function(err) { - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, internals, function(err, db) { - callback(null, db); + db.createMigrationsTable(function() { + client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test-schema' AND table_name = 'migrations'", function(err, result) { + callback(err, result); }); }); }, - 'migrations table': { - topic: function(db) { - var callback = this.callback; + 'is in test-schema': function(err, result) { + assert.isNull(err); + assert.isNotNull(result); + assert.equal(result.rowCount, 1); + } + }, + + teardown: function(db, client) { + var callback = this.callback; + client.query('DROP SCHEMA "test-schema" CASCADE', function (err) { + if (err) { return callback(err); } + client.end(); + callback(); + }); + } + } +}) +.addBatch({ + 'create schema and connect': { + topic: function() { + var callback = this.callback; + var client = new pg.Client(databaseUrl); - db.createMigrationsTable(function() { - client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", function(err, result) { - callback(err, result); - }); + client.connect(function (err) { + if (err) { return callback(err); } + client.query('CREATE SCHEMA test_schema', function(err) { + driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, function(err, db) { + callback(err, db, client); }); - }, + }); + }); + }, + + 'migrations table': { + topic: function(db, client) { + var callback = this.callback; - 'is in test_schema': function(err, result) { - assert.isNull(err); - assert.isNotNull(result); - assert.equal(result.rowCount, 1); - } + db.createMigrationsTable(function() { + client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", function(err, result) { + callback(err, result); + }); + }); }, - teardown: function() { - client.query('DROP SCHEMA test_schema CASCADE', this.callback); + 'is in test_schema': function(err, result) { + assert.isNull(err); + assert.isNotNull(result); + assert.equal(result.rowCount, 1); } + }, + + teardown: function(db, client) { + var callback = this.callback; + client.query('DROP SCHEMA test_schema CASCADE', function (err) { + if (err) { return callback(err); } + client.end(); + callback(); + }); } } }).export(module); From 49c8d82ee699b9ae8d0e85e52c083620cc7b8e8f Mon Sep 17 00:00:00 2001 From: Mike Atkins Date: Mon, 11 May 2015 07:51:10 -0400 Subject: [PATCH 066/412] Ignore vim swap files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 47eb09c1..374cb87e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ database.json *.sublime-project *.sublime-workspace archive + +# Vim swap files +.*.sw[a-z] From b88875d968ec24672e4b6b95f26c2df10a55cdeb Mon Sep 17 00:00:00 2001 From: Mike Atkins Date: Fri, 8 May 2015 12:26:28 -0400 Subject: [PATCH 067/412] Escape schema for postgres If the name chosen for a schema contains certain characters, it must be surrounded in quotes. This ensures those quotes are added when choosing the schema by setting the `search_path`. --- lib/driver/pg.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 25fd9ecb..bd3eabeb 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -220,14 +220,14 @@ var PgDriver = Base.extend({ var searchPath; - // if the user specified a different schema, prepend it to the - // search path. This will make all DDL/DML/SQL operate on the specified - // schema. - if (this.schema === 'public') { - searchPath = result[0].search_path; - } else { - searchPath = this.schema + ',' + result[0].search_path; - } + // if the user specified a different schema, prepend it to the + // search path. This will make all DDL/DML/SQL operate on the specified + // schema. + if (this.schema === 'public') { + searchPath = result[0].search_path; + } else { + searchPath = '"' + this.schema + '",' + result[0].search_path; + } return this.all('SET search_path TO ' + searchPath); }.bind(this)) From 08ce8d99d5495cfda0bbc51552c2fd0c0b17930e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 18 May 2015 13:06:37 +0200 Subject: [PATCH 068/412] add fix to cherry picked pull request --- lib/driver/pg.js | 2 +- test/driver/pg_schema_test.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index bd3eabeb..e84934dc 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -172,7 +172,7 @@ var PgDriver = Base.extend({ if (this.schema === 'public') { searchPath = result[0].search_path; } else { - searchPath = this.schema + ',' + result[0].search_path; + searchPath = '"' + this.schema + '",' + result[0].search_path; } return this.all('SET search_path TO ' + searchPath); diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js index 3ea9e50d..79fd8e24 100644 --- a/test/driver/pg_schema_test.js +++ b/test/driver/pg_schema_test.js @@ -19,7 +19,7 @@ vows.describe('pg').addBatch({ client.connect(function (err) { if (err) { return callback(err); } client.query('CREATE SCHEMA "test-schema"', function(err) { - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test-schema' }, function(err, db) { + driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test-schema' }, internals, function(err, db) { callback(err, db, client); }); }); @@ -63,7 +63,7 @@ vows.describe('pg').addBatch({ client.connect(function (err) { if (err) { return callback(err); } client.query('CREATE SCHEMA test_schema', function(err) { - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, function(err, db) { + driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, internals, function(err, db) { callback(err, db, client); }); }); From 10d82b629998ab97b2c97e60d01d5d756af1bd7b Mon Sep 17 00:00:00 2001 From: nguyenchr Date: Tue, 19 May 2015 10:19:27 +1000 Subject: [PATCH 069/412] Add support for creating a coffeescript sql loader --- api.js | 4 +++- lib/migration.js | 39 ++++++++++++++++++++++++++++++++++++++- test/migration_test.js | 10 ++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/api.js b/api.js index 0897ef6d..2e91e9a0 100644 --- a/api.js +++ b/api.js @@ -431,7 +431,9 @@ function executeCreate() { } var templateType = Migration.TemplateType.DEFAULT_JS; - if (shouldCreateSqlFiles()) { + if (shouldCreateSqlFiles() && shouldCreateCoffeeFile()) { + templateType = Migration.TemplateType.COFFEE_SQL_FILE_LOADER; + } else if (shouldCreateSqlFiles()) { templateType = Migration.TemplateType.SQL_FILE_LOADER; } else if (shouldCreateCoffeeFile()) { templateType = Migration.TemplateType.DEFAULT_COFFEE; diff --git a/lib/migration.js b/lib/migration.js index a647814f..70e39013 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -137,11 +137,46 @@ Migration.prototype.sqlFileLoaderTemplate = function() { ].join("\n"); }; +Migration.prototype.coffeeSqlFileLoaderTemplate = function() { + return [ + "dbm = undefined", + "type = 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) ->", + " dbm = options.dbmigrate", + " type = dbm.dataType", + "", + "", + "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 + DEFAULT_COFFEE: 3, + COFFEE_SQL_FILE_LOADER: 4 }; Migration.prototype.getTemplate = function() { @@ -152,6 +187,8 @@ Migration.prototype.getTemplate = function() { return this.sqlFileLoaderTemplate(); case Migration.TemplateType.DEFAULT_COFFEE: return this.defaultCoffeeTemplate(); + case Migration.TemplateType.COFFEE_SQL_FILE_LOADER: + return this.coffeeSqlFileLoaderTemplate(); case Migration.TemplateType.DEFAULT_JS: default: return this.defaultJsTemplate(); diff --git a/test/migration_test.js b/test/migration_test.js index b640bd49..71bac3d4 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -123,6 +123,16 @@ vows.describe('migration').addBatch({ assert.equal(actual, migration.defaultCoffeeTemplate()); } }, + 'as coffee sql loader' : { + topic: function() { + var migration = new Migration(fileName, dirName, date, Migration.TemplateType.COFFEE_SQL_FILE_LOADER, internals); + return migration; + }, + 'should return default coffee template': function(migration) { + var actual = migration.getTemplate(); + assert.equal(actual, migration.coffeeSqlFileLoaderTemplate()); + } + }, 'as default javascript' : { topic: function() { var migration = new Migration(fileName, dirName, date, Migration.TemplateType.DEFAULT_JS, internals); From a028db9cd407c8c1f8fadf434156a078a9b58517 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 20 May 2015 04:43:09 +0200 Subject: [PATCH 070/412] add explanation to seeder interface --- lib/interface/seederInterface.js | 83 ++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index 852103aa..b55ed3bb 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -1,5 +1,47 @@ +/** + * The seeder interface provides the ability to handle all operations, that + * are not DDL specific and thus not a migration. + * + * These operations are currently, but not limited to: + * + * inserting data + * removing data + * searching data + * truncating whole tables + * + * This functionality is provided in two ways to the user. First there are + * traditional seeder. You can call them whenever you want, and how often + * you want. This results into a use case, that make seeders might only used + * for development and not to use them in a deployment process. + * + * Here the second way of usage steps in, the version controlled seeders, in + * short VC Seeds. + * There is technically no big difference between them, except the following + * details: + * + * A VC Seed can be called from a migration, via seed.execute and seed.link. A + * normal seeder can not. Also A VC Seeder has a down and up function, like + * the way the migrations work, the static instead has a truncate function, + * which gets called before the seed function. As a seeder often wants to + * truncate tables or just delete data from a table. + * And last but not least, a VC Seed can not be executed if it was executed + * before, you need to roll back it first, it's in short handled like + * migrations are. A normal seed can be executed just as often as you want + * without rollback your data at any time. + * + * To note: If you rollback a migration, linked to a seeder, db-migrate will + * also rollback the seed. This is also a reason why you can't rollback a + * specific migration, you would going to break that much, you probably loose + * a bunch of valueable time. + */ + var Promise = require('bluebird'); +function _l( field ) { + + return { type: 'lookup', field: field }; +} + function insert(table, options, callback) { var foreignLinkage = this.foreignLinkage[table]; @@ -10,16 +52,16 @@ function insert(table, options, callback) { for(var i = 0; i < option.length; ++i) { - if (typeof(options[option]) === 'object') { + if (typeof(options[option[i]]) === 'object') { - if (options[option].type === 'lookup') { + if (options[option[i]].type === 'lookup') { - if (!options[option].table) { + if (!options[option[i]].table) { - if (foreignLinkage[option]) { + if (foreignLinkage[option[i]]) { - options[option].table = foreignLinkage[option].table; - options[option].field = foreignLinkage[option].field; + options[option[i]].table = foreignLinkage[option[i]].table; + options[option[i]].field = foreignLinkage[option[i]].field; } else { @@ -32,27 +74,22 @@ function insert(table, options, callback) { } } - return lookup(options, 0) - .catch(callback) + return lookup(options) .then(function(){ return this.driver.massInsert(options); }) - .catch(callback) - .nodeify(callback); -} - -function remove() { - -} + .catch(function(e) { -function get() { - + throw e; + }) + .nodeify(callback); } -function lookup(options, i, callback) { +function lookup(options) { - var lookups = []; + var lookups = [], + i = 0; for(var o = 0; o < options.length; ++o) { @@ -67,16 +104,12 @@ function lookup(options, i, callback) { lookups.push(this.driver.lookup(options[option]) .catch(function(err) { - console.log(err); - }) - .then(function() { - - return loockup(options, i); + throw err; })); } } } } - return Promise.all(lookups).nodeify(callback); + return Promise.settle(lookups); } From 104e906fdbd819024fb3d1c4996285ea1eb4ab7f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 21 May 2015 05:08:50 +0200 Subject: [PATCH 071/412] add methods to drivers and change behavior Drivers now define the escape char for DDLs and Strings in the constructor. Minimizing the size of SQL Standardized driver. Functions like dropTable and other which only differnce is the escapeChar can be removed from this and are fullfilled correctly by setting the correct escape char --- lib/driver/base.js | 33 ++++++++++++++++++++------------- lib/driver/mysql.js | 2 ++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 370ecfa6..dc9feb14 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -9,6 +9,8 @@ var internals = {}; module.exports = Base = Class.extend({ init: function(intern) { + this._escapeDDL = this._escapeDDL || '"'; + this._escapeString = this._escapeString || '"'; internals = intern; this.eventEmmiter = new events.EventEmitter(); for(var n in events.EventEmitter.prototype) { @@ -57,6 +59,11 @@ module.exports = Base = Class.extend({ } }, + truncate: function(tableName, callback) { + + return this.runSql('TRUNCATE ' + this._escapeDDL + tableName + this._escapeDDL).nodeify(callback); + }, + checkDBMS: function(dbms, callback) { if( this.dbms === dbms ) @@ -213,7 +220,7 @@ module.exports = Base = Class.extend({ ifExistsSql = 'IF EXISTS'; } var sql = util.format('DROP TABLE %s "%s"', ifExistsSql, tableName); - + return this.runSql(sql).nodeify(callback); }, @@ -379,7 +386,7 @@ module.exports = Base = Class.extend({ * @param table - The table in which the to be deleted values are located * @param ids - array or object * id array - arrayof the to be deleted ids - * id object - { table: "name of the table to resolve the ids from", + * id object - { table: "name of the table to resolve the ids from", * column: [ * { * name: "name of column", //defaults to id if unset @@ -396,11 +403,9 @@ module.exports = Base = Class.extend({ */ remove: function(table, ids, callback) { - var sql = 'DELETE FROM "' + table + '"'; + var sql = 'DELETE FROM ' + this._escapeDDL + table + + this._escapeDDL; var searchClause = ''; - - return this.runSql(sql + buildWhereClause(ids)).nodeify(callback); }, @@ -409,7 +414,7 @@ module.exports = Base = Class.extend({ * * @param ids - array or object * id array - arrayof the to be deleted ids - * id object - { table: "name of the table to resolve the ids from", + * id object - { table: "name of the table to resolve the ids from", * column: [ * { * name: "name of column", //defaults to id if unset @@ -430,11 +435,11 @@ module.exports = Base = Class.extend({ if (util.isArray(ids) && typeof(ids[0]) !== 'object') { - sql += 'WHERE id IN (' + ids.join(',') + ')'; + sql += 'WHERE id IN (' + ids.join(this._escapeString + ',' + this._escapeString) + ')'; } else if (util.isArray(ids) && typeof(ids[0]) === 'object'){ - + var preLink = '' searchClause = ' WHERE '; @@ -448,19 +453,21 @@ module.exports = Base = Class.extend({ return Promise.reject('column ' + column.name + ' was entered without a searchValue.'); } - searchClause += ' ' + preLink + ' "' + column.name + '" ' + column.operator; + searchClause += ' ' + preLink + ' ' + this._escapeDDL + + column.name + this._escapeDDL + ' ' + column.operator; - if (typeof(searchValue) === 'object' && + if (typeof(searchValue) === 'object' && typeof(searchValue.table) === 'string' && typeof(searchValue.columns) === 'object') { - searchClause += ' (SELECT "' + column.selector + '" FROM "' + - column.searchValue.table + '"' + + searchClause += ' (SELECT ' + this._escapeDDL + column.selector + + this._escapeDDL + ' FROM ' + this._escapeDDL + + column.searchValue.table + this._escapeDDL + buildWhereClause(column.searchValue.column) + ')'; } else { - searchClause += ' (' + column.searchValue + ')'; + searchClause += ' (' + this._escapeString + column.searchValue + this._escapeString + ')'; } preLink = column.link; diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 36a09ea9..f66d2f7b 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -10,6 +10,8 @@ var internals = {}; var MysqlDriver = Base.extend({ init: function(connection) { + this._escapeDDL = '`'; + this._escapeString = '\''; this._super(internals); this.connection = connection; }, From 59508cbf8039685b1cb8bc90b69737871acb6dd2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 22 May 2015 02:17:18 +0200 Subject: [PATCH 072/412] continue converting automtic quote handling and driver definition to new behavior --- lib/driver/base.js | 24 +++++++++++++------- lib/driver/mysql.js | 54 ++------------------------------------------- 2 files changed, 18 insertions(+), 60 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index dc9feb14..4476ad3c 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -118,7 +118,7 @@ module.exports = Base = Class.extend({ }, createColumnDef: function(name, spec, options) { - name = '"' + name + '"'; + name = this._escapeDDL + name + this._escapeDDL; var type = this.mapDataType(spec.type); var len = spec.length ? util.format('(%s)', spec.length) : ''; var constraint = this.createColumnConstraint(spec, options); @@ -182,7 +182,7 @@ module.exports = Base = Class.extend({ var pkSql = ''; if (primaryKeyColumns.length > 1) { - pkSql = util.format(', PRIMARY KEY (%s)', this.quoteArr(primaryKeyColumns).join(', ')); + pkSql = util.format(', PRIMARY KEY (%s)', this.quoteDDLArr(primaryKeyColumns).join(', ')); } else { columnDefOptions.emitPrimaryKey = true; } @@ -255,10 +255,18 @@ module.exports = Base = Class.extend({ throw new Error('not yet implemented'); }, + quoteDDLArr: function(arr) { + + for(var i = 0; i < arr.length; ++i) + arr[i] = this._escapeDDL + arr[i] + this._escapeDDL; + + return arr; + }, + quoteArr: function(arr) { for(var i = 0; i < arr.length; ++i) - arr[i] = '"' + arr[i] + '"'; + arr[i] = this._escapeString + arr[i] + this._escapeString; return arr; }, @@ -273,7 +281,7 @@ module.exports = Base = Class.extend({ columns = [columns]; } var sql = util.format('CREATE %s INDEX "%s" ON "%s" (%s)', (unique ? 'UNIQUE' : ''), - indexName, tableName, this.quoteArr(columns).join(', ')); + indexName, tableName, this.quoteDDLArr(columns).join(', ')); return this.runSql(sql).nodeify(callback); }, @@ -356,7 +364,7 @@ module.exports = Base = Class.extend({ * @param callback */ allLoadedMigrations: function(callback) { - var sql = 'SELECT * FROM "' + internals.migrationTable + '" ORDER BY run_on DESC, name DESC'; + var sql = 'SELECT * FROM ' + this._escapeDDL + internals.migrationTable + this._escapeDDL + ' ORDER BY run_on DESC, name DESC'; return this.all(sql, callback); }, @@ -366,7 +374,7 @@ module.exports = Base = Class.extend({ * @param callback */ allLoadedSeeds: function(callback) { - var sql = 'SELECT * FROM "' + internals.seedTable + '" ORDER BY run_on DESC, name DESC'; + var sql = 'SELECT * FROM ' + this._escapeDDL + internals.seedTable + this._escapeDDL + ' ORDER BY run_on DESC, name DESC'; return this.all(sql, callback); }, @@ -376,7 +384,7 @@ module.exports = Base = Class.extend({ * @param migrationName - The name of the migration to be deleted */ deleteMigration: function(migrationName, callback) { - var sql = 'DELETE FROM "' + internals.migrationTable + '" WHERE name = ?'; + var sql = 'DELETE FROM ' + this._escapeDDL + internals.migrationTable + this._escapeDDL + ' WHERE name = ?'; this.runSql(sql, [migrationName], callback); }, @@ -484,7 +492,7 @@ module.exports = Base = Class.extend({ * @param seedName - The name of the seed to be deleted */ deleteSeed: function(seedName, callback) { - var sql = 'DELETE FROM "' + internals.seedTable + '" WHERE name = ?'; + var sql = 'DELETE FROM ' + this._escapeDDL + internals.seedTable + this._escapeDDL + ' WHERE name = ?'; this.runSql(sql, [seedName], callback); }, diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index f66d2f7b..f4ffa677 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -403,8 +403,8 @@ var MysqlDriver = Base.extend({ var columns = Object.keys(fieldMapping); var referencedColumns = columns.map(function (key) { return fieldMapping[key]; }); var sql = util.format('ALTER TABLE `%s` ADD CONSTRAINT `%s` FOREIGN KEY (%s) REFERENCES `%s` (%s) ON DELETE %s ON UPDATE %s', - tableName, keyName, this.tableQuoteArr( columns ), referencedTableName, - this.tableQuoteArr( referencedColumns ), rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); + tableName, keyName, this.quoteArr( columns ), referencedTableName, + this.quoteArr( referencedColumns ), rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); return this.runSql(sql).nodeify(callback); }, @@ -430,14 +430,6 @@ var MysqlDriver = Base.extend({ }.bind(this)).nodeify(callback); }, - tableQuoteArr: function(arr) { - - for(var i = 0; i < arr.length; ++i) - arr[i] = '`' + arr[i] + '`'; - - return arr; - }, - runSql: function() { var self = this; @@ -474,48 +466,6 @@ var MysqlDriver = Base.extend({ return this.connection.query.apply(this.connection, args); }, - /** - * Queries the migrations table - * - * @param callback - */ - allLoadedMigrations: function(callback) { - var sql = 'SELECT * FROM `' + internals.migrationTable + '` ORDER BY run_on DESC, name DESC'; - this.all(sql, callback); - }, - - /** - * Deletes a migration - * - * @param migrationName - The name of the migration to be deleted - * @param callback - */ - deleteMigration: function(migrationName, callback) { - var sql = 'DELETE FROM `' + internals.migrationTable + '` WHERE name = ?'; - this.runSql(sql, [migrationName], callback); - }, - - /** - * Queries the seeds table - * - * @param callback - */ - allLoadedSeeds: function(callback) { - var sql = 'SELECT * FROM `' + internals.seedTable + '` ORDER BY run_on DESC, name DESC'; - this.all(sql, callback); - }, - - /** - * Deletes a seed - * - * @param seedName - The name of the seed to be deleted - * @param callback - */ - deleteSeed: function(seedName, callback) { - var sql = 'DELETE FROM `' + internals.seedTable + '` WHERE name = ?'; - this.runSql(sql, [seedName], callback); - }, - close: function(callback) { return new Promise(function(resolve, reject) { var cb = (function(err, data) { From 7c2a2524083633e12f718164ef419bbe237e97b0 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 23 May 2015 12:24:11 +0200 Subject: [PATCH 073/412] fix wrong quoting resulted from wrong quotationFunction --- lib/driver/mysql.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index f4ffa677..1e878bcb 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -403,8 +403,8 @@ var MysqlDriver = Base.extend({ var columns = Object.keys(fieldMapping); var referencedColumns = columns.map(function (key) { return fieldMapping[key]; }); var sql = util.format('ALTER TABLE `%s` ADD CONSTRAINT `%s` FOREIGN KEY (%s) REFERENCES `%s` (%s) ON DELETE %s ON UPDATE %s', - tableName, keyName, this.quoteArr( columns ), referencedTableName, - this.quoteArr( referencedColumns ), rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); + tableName, keyName, this.quoteDDLArr( columns ), referencedTableName, + this.quoteDDLArr( referencedColumns ), rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); return this.runSql(sql).nodeify(callback); }, From 65b24418cab3e470af175bd4e2faccf4fa3d4204 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 24 May 2015 14:40:11 +0200 Subject: [PATCH 074/412] update async, going to remove it soon. async can not be removed yet, as it is a breaking change --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 8097bab8..a9e9ead2 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "url": "https://github.com/kunklejr/node-db-migrate.git" }, "dependencies": { - "async": "~0.9.0", "bluebird": "^2.9.12", "dotenv": "~1.1.0", "final-fs": "^1.6.0", From ea341cea79708339736c9aac8d2f5161aca96edb Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 25 May 2015 16:19:46 +0200 Subject: [PATCH 075/412] add missing async again --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index a9e9ead2..059f3355 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "url": "https://github.com/kunklejr/node-db-migrate.git" }, "dependencies": { + "async": "^1.0.0", "bluebird": "^2.9.12", "dotenv": "~1.1.0", "final-fs": "^1.6.0", From e2737fe84dfbf20cdf06e7ec5c5d09b2a2ae63f5 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 26 May 2015 04:26:02 +0200 Subject: [PATCH 076/412] complete functionality of reduceToInterface --- lib/interface/migratorInterface.js | 4 ++-- lib/util.js | 28 +++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index cb9bc65a..bab01ba4 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -93,9 +93,9 @@ MigratorInterface.prototype = { }; -module.exports.MigratorInterface = MigratorInterface; +module.exports = MigratorInterface; module.exports.deprecated = { - + insert: function() { arguments[arguments.length - 1]('not implemented'); diff --git a/lib/util.js b/lib/util.js index b63d00e4..3f76afd7 100644 --- a/lib/util.js +++ b/lib/util.js @@ -49,13 +49,39 @@ exports.reduceToInterface = function(db, originInterface) { } else if(typeof Interface[prop] === "function") { - Interface._original[prop] = originInterface[prop]; + Interface[property] = originInterface[prop]; + } + } + + for(var prop in originInterface.deprecated) { + + if (typeof Interface[prop] === "function" && + typeof db[prop] === "function") { + + Interface._original[prop] = db[prop]; (function(property) { Interface[property] = function() { this._original[property].apply(this, arguments); }; }(prop)); } + else if(typeof Interface[prop] === "function") + { + Interface[property] = originInterface[prop]; + } + } + + for(var prop in originInterface.extend) { + + if (typeof Interface[prop] === "function" && + typeof db[prop] === "function") { + + Interface[property] = originInterface[prop]; + } + else if(typeof Interface[prop] === "function") + { + Interface[property] = originInterface[prop]; + } } return Interface; From d5a1952c94f57b60bc4328edd3d533147ac86d8a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 27 May 2015 04:36:20 +0200 Subject: [PATCH 077/412] add deprecation notice --- lib/interface/migratorInterface.js | 4 +++- lib/util.js | 30 +++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index bab01ba4..bfbc8dea 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -99,7 +99,9 @@ module.exports.deprecated = { insert: function() { arguments[arguments.length - 1]('not implemented'); - } + }, + + insert_deprecation: 'is completely removed, use version controlled seeds instead.'; }; module.exports.extending = { }; diff --git a/lib/util.js b/lib/util.js index 3f76afd7..2e614c57 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,3 +1,4 @@ +var log = require('./log'); function isIncludedInUp(migration, destination) { if(!destination) { @@ -49,7 +50,7 @@ exports.reduceToInterface = function(db, originInterface) { } else if(typeof Interface[prop] === "function") { - Interface[property] = originInterface[prop]; + Interface[prop] = originInterface[prop]; } } @@ -62,12 +63,31 @@ exports.reduceToInterface = function(db, originInterface) { (function(property) { - Interface[property] = function() { this._original[property].apply(this, arguments); }; + Interface[property] = function() { + + log.warn('This function "' + property + + '" is deprecated.' + "\n" + + originInterface.deprecated[property + '_deprecation'] ); + + this._original[property].apply(this, arguments); + }; }(prop)); } else if(typeof Interface[prop] === "function") { - Interface[property] = originInterface[prop]; + Interface._original[prop] = originInterface[prop]; + + (function(property) { + + Interface[property] = function() { + + log.warn('This function "' + property + + '" is deprecated.' + "\n" + + originInterface.deprecated[property + '_deprecation'] ); + + this._original[property].apply(this, arguments); + }; + }(prop)); } } @@ -76,11 +96,11 @@ exports.reduceToInterface = function(db, originInterface) { if (typeof Interface[prop] === "function" && typeof db[prop] === "function") { - Interface[property] = originInterface[prop]; + Interface[prop] = originInterface[prop]; } else if(typeof Interface[prop] === "function") { - Interface[property] = originInterface[prop]; + Interface[prop] = originInterface[prop]; } } From 1390e5cd856e05db74b8029eefd1f22581299d31 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 28 May 2015 01:37:22 +0200 Subject: [PATCH 078/412] add missing extend property --- lib/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index 2e614c57..8a93393c 100644 --- a/lib/util.js +++ b/lib/util.js @@ -96,11 +96,11 @@ exports.reduceToInterface = function(db, originInterface) { if (typeof Interface[prop] === "function" && typeof db[prop] === "function") { - Interface[prop] = originInterface[prop]; + Interface[prop] = originInterface.extend[prop]; } else if(typeof Interface[prop] === "function") { - Interface[prop] = originInterface[prop]; + Interface[prop] = originInterface.extend[prop]; } } From 9d696e49b9ed4463a54f077a238566a7f25b1ec1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 29 May 2015 05:41:41 +0200 Subject: [PATCH 079/412] fix behavior of reduceToInterface --- lib/util.js | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/lib/util.js b/lib/util.js index 8a93393c..ebbdee62 100644 --- a/lib/util.js +++ b/lib/util.js @@ -38,26 +38,20 @@ exports.reduceToInterface = function(db, originInterface) { for(var prop in db) { - if (typeof Interface[prop] === "function" && - typeof db[prop] === "function") { + if (typeof db[prop] === "function") { - Interface._original[prop] = db[prop]; - - (function(property) { - - Interface[property] = function() { this._original[property].apply(this, arguments); }; - }(prop)); + Interface.[prop] = db[prop]; } - else if(typeof Interface[prop] === "function") - { + else if(typeof originInterface[prop] === "function") { + Interface[prop] = originInterface[prop]; } } for(var prop in originInterface.deprecated) { - if (typeof Interface[prop] === "function" && - typeof db[prop] === "function") { + if (typeof db[prop] === "function" && + typeof originInterface.deprecated[prop] === "function") { Interface._original[prop] = db[prop]; @@ -73,8 +67,8 @@ exports.reduceToInterface = function(db, originInterface) { }; }(prop)); } - else if(typeof Interface[prop] === "function") - { + else if(typeof originInterface[prop] === "function") { + Interface._original[prop] = originInterface[prop]; (function(property) { @@ -93,13 +87,13 @@ exports.reduceToInterface = function(db, originInterface) { for(var prop in originInterface.extend) { - if (typeof Interface[prop] === "function" && - typeof db[prop] === "function") { + if (typeof db[prop] === "function" && + typeof originInterface.extend[prop] === "function") { Interface[prop] = originInterface.extend[prop]; } - else if(typeof Interface[prop] === "function") - { + else if(typeof originInterface[prop] === "function") { + Interface[prop] = originInterface.extend[prop]; } } From 03a494d81fb264a3005d5a862e81f31ae9b6db6b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 30 May 2015 22:42:29 +0200 Subject: [PATCH 080/412] revert DST fix and apply working fix to UTCMonth by swapping day and month order --- lib/skeleton.js | 4 ++-- test/migration_test.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/skeleton.js b/lib/skeleton.js index 564bb956..b1a7803c 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -16,7 +16,7 @@ function formatName(title, date) { function formatDate(date) { return [ date.getUTCFullYear(), - lpad(date.getMonth(), '0', 2), + lpad(date.getUTCMonth() + 1, '0', 2), lpad(date.getUTCDate(), '0', 2), lpad(date.getUTCHours(), '0', 2), lpad(date.getUTCMinutes(), '0', 2), @@ -32,8 +32,8 @@ 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.setMonth(match[2]); date.setUTCDate(match[3]); + date.setUTCMonth(match[2] - 1); date.setUTCHours(match[4]); date.setUTCMinutes(match[5]); date.setUTCSeconds(match[6]); diff --git a/test/migration_test.js b/test/migration_test.js index 71bac3d4..94402edc 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -151,8 +151,8 @@ vows.describe('migration').addBatch({ function createDateForTest() { var date = new Date(); date.setUTCFullYear(2014); - date.setMonth('02'); date.setUTCDate('20'); + date.setUTCMonth('01'); date.setUTCHours('14'); date.setUTCMinutes('30'); date.setUTCSeconds('50'); From 1870c35b0ca647c1719dc13c91dfaeaf846bd426 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 31 May 2015 10:48:38 +0200 Subject: [PATCH 081/412] update dependencies --- lib/util.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index ebbdee62..ff939cec 100644 --- a/lib/util.js +++ b/lib/util.js @@ -40,7 +40,7 @@ exports.reduceToInterface = function(db, originInterface) { if (typeof db[prop] === "function") { - Interface.[prop] = db[prop]; + Interface[prop] = db[prop]; } else if(typeof originInterface[prop] === "function") { diff --git a/package.json b/package.json index 059f3355..a6ae94f0 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "mkdirp": "~0.5.0", "moment": "~2.10.2", "mongodb": "^2.0.23", - "mysql": "~2.6.0", + "mysql": "~2.7.0", "optimist": "~0.6.1", "parse-database-url": "~0.2.2", "pg": "~4.3.0", From a5b0d8b966f91612156479b50e52683ad697fd06 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 31 May 2015 15:57:12 +0200 Subject: [PATCH 082/412] promisify deprecated function wrapper --- lib/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index ff939cec..9a06083b 100644 --- a/lib/util.js +++ b/lib/util.js @@ -63,7 +63,7 @@ exports.reduceToInterface = function(db, originInterface) { + '" is deprecated.' + "\n" + originInterface.deprecated[property + '_deprecation'] ); - this._original[property].apply(this, arguments); + return this._original[property].apply(this, arguments); }; }(prop)); } @@ -79,7 +79,7 @@ exports.reduceToInterface = function(db, originInterface) { + '" is deprecated.' + "\n" + originInterface.deprecated[property + '_deprecation'] ); - this._original[property].apply(this, arguments); + return this._original[property].apply(this, arguments); }; }(prop)); } From 5e5d2481943a377a04eb57f18724f726f08c8f53 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 1 Jun 2015 20:14:04 +0200 Subject: [PATCH 083/412] add failing test for force-exit api method --- api.js | 36 +++++++++++++++--- index.js | 4 +- test/config_test.js | 4 ++ test/integration/api_test.js | 73 ++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 test/integration/api_test.js diff --git a/api.js b/api.js index 2e91e9a0..c37c0752 100644 --- a/api.js +++ b/api.js @@ -20,16 +20,32 @@ async = require( 'async' ); //deprecated var internals = {}; -function dbmigrate(isModule, callback) { +function dbmigrate(isModule, options, callback) { if(typeof(callback) === 'function') internals.onComplete = callback; + else if(typeof(options) === 'function') + internals.onComplete = options; this.dataType = dbm.dataType; this.version = dbm.version; dotenv.load({ silent: true }); registerEvents(); + + if(typeof(options) === 'object') { + + if(typeof(options.config) === 'string') + internals.configFile = options.string; + + if(typeof(options.cwd) === 'string') + internals.cwd = options.cwd; + else + internals.cwd = process.cwd(); + } + else + internals.cwd = process.cwd(); + if(typeof(isModule) === 'function') { internals.onComplete = isModule; @@ -185,6 +201,14 @@ dbmigrate.prototype = { executeDown(); }, + /** + * Silence the log output completely. + */ + silence: function(isSilent) { + + return log.silence(isSilent); + }, + /** * Creates a correctly formatted migration */ @@ -224,7 +248,7 @@ dbmigrate.prototype = { */ setConfigParam: function(param, value) { - return (argv[param] = value); + return (internals.argv[param] = value); }, @@ -285,10 +309,10 @@ function setDefaultArgv(isModule) { 'force-exit': false, 'sql-file': false, 'no-transactions': false, - config: process.cwd() + '/database.json', - 'migrations-dir': process.cwd() + '/migrations', - 'vcseeder-dir': process.cwd() + '/VCSeeder', - 'staticseeder-dir': process.cwd() + '/Seeder'}) + config: internals.configFile || internals.cwd + '/database.json', + 'migrations-dir': internals.cwd + '/migrations', + 'vcseeder-dir': internals.cwd + '/VCSeeder', + 'staticseeder-dir': internals.cwd + '/Seeder'}) .usage('Usage: db-migrate [up|down|reset|create|db] [[dbname/]migrationName|all] [options]') .describe('env', 'The environment to run the migrations under (dev, test, prod).') diff --git a/index.js b/index.js index 3a638f5d..58276907 100644 --- a/index.js +++ b/index.js @@ -48,9 +48,9 @@ searchCache = function (moduleName, callback) { } }; -module.exports.getInstance = function(isModule, callback) { +module.exports.getInstance = function(isModule, options, callback) { uncache('./api.js'); var mod = require( './api.js' ); - return new mod(isModule, callback); + return new mod(isModule, options, callback); }; diff --git a/test/config_test.js b/test/config_test.js index 1a33a88e..6d9bac1b 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -143,6 +143,10 @@ vows.describe('config').addBatch({ 'should something': function(err) { assert.isNull(err); + }, + + teardown: function() { + delete require.cache[require.resolve('../lib/config')]; } } }).export(module); diff --git a/test/integration/api_test.js b/test/integration/api_test.js new file mode 100644 index 00000000..14ce9698 --- /dev/null +++ b/test/integration/api_test.js @@ -0,0 +1,73 @@ +var vows = require('vows'); +var assert = require('assert'); +var fs = require('fs'); +var dbmUtil = require('../../lib/util'); +var DBMigrate = require('../../'); +var path = require('path'); +var cp = require('child_process'); + + +var process_exit = process.exit, + argv = process.argv; + +function restore() { + + process.exit = process_exit; + process.argv = argv; +} + +vows.describe('api').addBatch({ + 'force process exit': { + topic: function() { + + process.argv = [ 'node', 'script' ]; + var called = false, + self = this, + config = { cwd: process.cwd() + '/test/integration' }; + + var api = DBMigrate.getInstance(true, config); + api.create('test'); + + process.argv.push('up'); + + process.exit = function(err) { + + var ret = called; + called = true; + + process.exit = process_exit; + + if(err) + process.exit.apply(arguments); + + if(!ret) + this.callback(false); + }.bind(this); + + var dbmigrate = DBMigrate.getInstance(true, config, function() { + + var ret = called; + called = true; + + if(!ret) + this.callback(true); + }.bind(this)); + + dbmigrate.setConfigParam('force-exit', true); + dbmigrate.silence(true); + + + dbmigrate.run(); + }, + + teardown: function() { + + restore(); + cp.exec('rm -r ' + path.join(__dirname, 'migrations'), function() { this.callback.apply(this, arguments) }.bind(this)); + }, + + 'process exited after migrations have been run': function(called) { + assert.isTrue(called); + } + } +}).export(module); From 034413717f67db286f6fa607fe25b38afb990afa Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 1 Jun 2015 21:03:12 +0200 Subject: [PATCH 084/412] change callback of remove migrations --- test/integration/api_test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 14ce9698..31e690f6 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -49,6 +49,8 @@ vows.describe('api').addBatch({ var ret = called; called = true; + process.exit = process_exit; + if(!ret) this.callback(true); }.bind(this)); @@ -63,10 +65,11 @@ vows.describe('api').addBatch({ teardown: function() { restore(); - cp.exec('rm -r ' + path.join(__dirname, 'migrations'), function() { this.callback.apply(this, arguments) }.bind(this)); + cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); }, 'process exited after migrations have been run': function(called) { + assert.isTrue(called); } } From c341d66d4b63c3a1167f80e40a22f16d086ae6e3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 7 Jun 2015 23:12:02 +0200 Subject: [PATCH 085/412] add driver.close to test --- test/integration/api_test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 31e690f6..18368a00 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -44,11 +44,15 @@ vows.describe('api').addBatch({ this.callback(false); }.bind(this); - var dbmigrate = DBMigrate.getInstance(true, config, function() { + var dbmigrate = DBMigrate.getInstance(true, config, function(migrator) { var ret = called; called = true; + migrator.driver.close(function(err) { + delete migrator.driver; + }); + process.exit = process_exit; if(!ret) From de66b9aaea1c4fb031036ea2408ac34b84894c11 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 7 Jun 2015 23:12:46 +0200 Subject: [PATCH 086/412] update dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a6ae94f0..fec8fb0c 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "mysql": "~2.7.0", "optimist": "~0.6.1", "parse-database-url": "~0.2.2", - "pg": "~4.3.0", + "pg": "~4.4.0", "pg-native": "^1.8.0", "pkginfo": "~0.3.0", "resolve": "^1.1.6", @@ -47,7 +47,7 @@ "db-meta": "~0.4.1", "lab": "^5.2.1", "proxyquire": "^1.4.0", - "rimraf": "~2.3.2", + "rimraf": "~2.4.0", "sinon": "^1.14.1", "vows": "0.8.0" }, From 1c0130cc5a112663fcdb02461132d963c4ec5e91 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 7 Jun 2015 23:28:41 +0200 Subject: [PATCH 087/412] add update method, change some escapings, fix some settings --- lib/driver/base.js | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 4476ad3c..b8e7402c 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -291,7 +291,7 @@ module.exports = Base = Class.extend({ return callback(new Error('The number of columns does not match the number of values.')); } - var sql = util.format('INSERT INTO "%s" ', tableName); + var sql = util.format('INSERT INTO ' + this._escapeDDL + '%s' + this._escapeDDL + ' ', tableName); var columnNames = '('; var values = 'VALUES ('; @@ -299,7 +299,7 @@ module.exports = Base = Class.extend({ columnNames += columnNameArray[index]; if (typeof(valueArray[index]) === 'string') { - values += "'" + this.escape(valueArray[index]) + "'"; + values += this._escapeString + this.escape(valueArray[index]) + this._escapeString; } else { values += valueArray[index]; } @@ -314,6 +314,32 @@ module.exports = Base = Class.extend({ return this.runSql(sql).nodeify(callback); }, + update: function(tableName, columnNameArray, valueArray, ids, callback) { + + if (columnNameArray.length !== valueArray.length) { + return callback(new Error('The number of columns does not match the number of values.')); + } + + var sql = util.format('UPDATE ' + this._escapeDDL + '%s' + this._escapeDDL + ' SET ', tableName ); + + for (var index in columnNameArray) { + sql += columnNameArray[index] + '='; + + if (typeof(valueArray[index]) === 'string') { + sql += this._escapeString + this.escape(valueArray[index]) + this._escapeString; + } else { + sql += valueArray[index]; + } + + if (index != columnNameArray.length - 1) { + sql += ", "; + } + } + + sql += ' ' + buildWhereClause(ids); + return this.runSql(sql).nodeify(callback); + }, + removeIndex: function(tableName, indexName, callback) { if (arguments.length === 2 && typeof(indexName) === 'function') { callback = indexName; @@ -501,7 +527,7 @@ module.exports = Base = Class.extend({ }, escape: function(str) { - return str.replace(/'/g, "''"); + return str.replace(/"/g, '""'); } }); From 39c140080683ebc14c472716b126ce07df4755f7 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jun 2015 00:01:04 +0200 Subject: [PATCH 088/412] fix behavior of automatic quotinggg while updating some automatic quoting --- lib/driver/base.js | 17 +++++++++++++++-- lib/driver/pg.js | 5 +++-- lib/driver/sqlite3.js | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index b8e7402c..6cb68995 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -10,7 +10,7 @@ var internals = {}; module.exports = Base = Class.extend({ init: function(intern) { this._escapeDDL = this._escapeDDL || '"'; - this._escapeString = this._escapeString || '"'; + this._escapeString = this._escapeString || '\''; internals = intern; this.eventEmmiter = new events.EventEmitter(); for(var n in events.EventEmitter.prototype) { @@ -527,7 +527,20 @@ module.exports = Base = Class.extend({ }, escape: function(str) { - return str.replace(/"/g, '""'); + if(this._escapeString === '\'') + return str.replace(/'/g, "''"); + else + return str.replace(/"/g, '"'); + }, + + escapeString: function(str) { + + return this._escapeString + this.escape(str) + this._escapeString: + }, + + escapeDDL: function(str) { + + return this._escapeDDL + this.escape(str) + this._escapeDDL: } }); diff --git a/lib/driver/pg.js b/lib/driver/pg.js index e84934dc..46d324fa 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -10,6 +10,7 @@ var internals = {}; var PgDriver = Base.extend({ init: function(connection, schema) { + this._escapeString = '\''; this._super(internals); this.connection = connection; this.schema = schema || "public"; @@ -351,7 +352,7 @@ var PgDriver = Base.extend({ function setType() { if (columnSpec.type !== undefined){ - var using = columnSpec.using !== undefined ? + var using = columnSpec.using !== undefined ? columnSpec.using : util.format('USING "%s"::%s', columnName, this.mapDataType(columnSpec.type)) var sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" TYPE %s %s', tableName, columnName, this.mapDataType(columnSpec.type), using); return this.runSql(sql); @@ -367,7 +368,7 @@ var PgDriver = Base.extend({ var columns = Object.keys(fieldMapping); var referencedColumns = columns.map(function (key) { return '"' + fieldMapping[key] + '"'; }); var sql = util.format('ALTER TABLE "%s" ADD CONSTRAINT "%s" FOREIGN KEY (%s) REFERENCES "%s" (%s) ON DELETE %s ON UPDATE %s', - tableName, keyName, this.quoteArr(columns), referencedTableName, referencedColumns, rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); + tableName, keyName, this.quoteDDLArr(columns), referencedTableName, referencedColumns, rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); return this.runSql(sql).nodeify(callback); }, diff --git a/lib/driver/sqlite3.js b/lib/driver/sqlite3.js index 7c7d0fef..d0bf1a2c 100644 --- a/lib/driver/sqlite3.js +++ b/lib/driver/sqlite3.js @@ -10,6 +10,7 @@ var defaultMode = sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, var Sqlite3Driver = Base.extend({ init: function(connection) { + this._escapeString = '"'; this._super(internals); this.connection = connection; }, From 7c8d09ee33493e21d4ce782a54797dbf1e312f64 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jun 2015 00:09:43 +0200 Subject: [PATCH 089/412] fix typo --- lib/driver/base.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 6cb68995..93c7839f 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -535,7 +535,7 @@ module.exports = Base = Class.extend({ escapeString: function(str) { - return this._escapeString + this.escape(str) + this._escapeString: + return this._escapeString + this.escape(str) + this._escapeString; }, escapeDDL: function(str) { From 6a1ff104c511ab17c3091fdb29669899925545cc Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jun 2015 00:16:03 +0200 Subject: [PATCH 090/412] add partial notice to migrator interface --- lib/driver/base.js | 2 +- lib/interface/migratorInterface.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index 93c7839f..8b09f767 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -540,7 +540,7 @@ module.exports = Base = Class.extend({ escapeDDL: function(str) { - return this._escapeDDL + this.escape(str) + this._escapeDDL: + return this._escapeDDL + this.escape(str) + this._escapeDDL; } }); diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index bfbc8dea..ca977bac 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -1,3 +1,8 @@ +/** + * The migrator interface provides the ability to handle all abilities which + * are needed to successfully modify the DD of your tables. + * This includes all DDL methods provided by SQL naturally. + */ function MigratorInterface() { From d5153283695a30809799ceb909857be376d614cd Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 9 Jun 2015 18:16:55 +0200 Subject: [PATCH 091/412] correct deprecatoin message --- lib/interface/migratorInterface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index ca977bac..5e369b78 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -106,7 +106,7 @@ module.exports.deprecated = { arguments[arguments.length - 1]('not implemented'); }, - insert_deprecation: 'is completely removed, use version controlled seeds instead.'; + insert_deprecation: 'is going to be completely removed, use version controlled seeds instead.'; }; module.exports.extending = { }; From 6e4d98f414560aacd86e088a8d37ae4f7100d35d Mon Sep 17 00:00:00 2001 From: besuhoff Date: Sat, 13 Jun 2015 20:34:15 +0300 Subject: [PATCH 092/412] Advise to set multipleStatements in DATABASE_URL I've spent quite a bunch of time crawling the web for solution how to pass multipleStatements=true to db-migrated within automated process (grunt-db-migrate). --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 76d3ce10..4a9af065 100644 --- a/README.md +++ b/README.md @@ -244,6 +244,10 @@ If you use MySQL, to be able to use multiple statements in your sql file, you ha } ``` +You can also place it as a query string parameter into DATABASE_URL variable, as https://github.com/pwnall/node-parse-database-url allows passing them into config: + + $ DATABASE_URL="mysql://DB_USER:DB_PASS@localhost/database-name?multipleStatements=true" db-migrate up + ## Running Migrations When first running the migrations, all will be executed in sequence. A table named `migrations` will also be created in your database to track which migrations have been applied. From e797dfa3fbcb88cacb49b0b2f8e2f4399e18e3a1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 15 Jun 2015 03:43:12 +0200 Subject: [PATCH 093/412] add functions and basic interface --- lib/interface/seederInterface.js | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index b55ed3bb..8144c37e 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -113,3 +113,38 @@ function lookup(options) { return Promise.settle(lookups); } + +var SeederInterface = { + + lookup: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + insert: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + delete: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + runSql: function() { + + arguments[arguments.length - 1]('not implemented'); + }, +}; + +module.exports = SeederInterface; +module.exports.deprecated = { + +}; +module.exports.extending = { + + _l: function( field ) { + + return { type: 'lookup', field: field }; + } +}; From 2eac000bf00050df2e11bfb2918418bab069be2a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 16 Jun 2015 04:46:57 +0200 Subject: [PATCH 094/412] add interfaces to internals --- lib/driver/index.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index dacd188f..7e8fbdf6 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -7,7 +7,8 @@ internals.mod.Class = require('../class'); var Shadow = require('./shadow'); var log = internals.mod.log; var tunnel = require('tunnel-ssh'), - Promise = require('bluebird'); + Promise = require('bluebird'), + SeederInterface = require('../interface/seederInterface.js'); var ShadowProto = { @@ -22,6 +23,10 @@ exports.connect = function (config, intern, callback) { var mod = internals.mod; internals = intern; internals.mod = mod; + internals.interfaces = { + + SeederInterface: SeederInterface; + }; if ( !config.user && config.username ) config.user = config.username; From a089d5057f654a8fa272d4e8e103c1d8f015a114 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 17 Jun 2015 06:54:17 +0200 Subject: [PATCH 095/412] change behavior of config.js, replace uncache and add Interface to internals Config.js now do not remove the loadurl and other methods anymore, as we now may reconfigure while a running instance. The uncache was replaced to only unload api.js and specific modules, which change their behavior after they have been first loaded --- index.js | 3 ++- lib/config.js | 8 ++++---- lib/driver/index.js | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 58276907..c9a3f84a 100644 --- a/index.js +++ b/index.js @@ -50,7 +50,8 @@ searchCache = function (moduleName, callback) { module.exports.getInstance = function(isModule, options, callback) { - uncache('./api.js'); + delete require.cache[require.resolve('./api.js')]; + delete require.cache[require.resolve('optimist')]; var mod = require( './api.js' ); return new mod(isModule, options, callback); }; diff --git a/lib/config.js b/lib/config.js index d50d1faa..8456a79a 100644 --- a/lib/config.js +++ b/lib/config.js @@ -49,8 +49,8 @@ exports.load = function(fileName, currentEnv) { setCurrent(['dev', 'development']); } - delete exports.load; - delete exports.loadUrl; + // delete exports.load; + // delete exports.loadUrl; }; exports.loadUrl = function(databaseUrl, currentEnv) { @@ -63,8 +63,8 @@ exports.loadUrl = function(databaseUrl, currentEnv) { setCurrent('urlConfig'); } - delete exports.load; - delete exports.loadUrl; + // delete exports.load; + // delete exports.loadUrl; } var setCurrent = exports.setCurrent = function (env) { diff --git a/lib/driver/index.js b/lib/driver/index.js index 7e8fbdf6..d273dc88 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -25,7 +25,7 @@ exports.connect = function (config, intern, callback) { internals.mod = mod; internals.interfaces = { - SeederInterface: SeederInterface; + SeederInterface: SeederInterface }; if ( !config.user && config.username ) From 660e62e0c8f7522590be1504d83d8eccd0b3ce80 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 17 Jun 2015 11:00:40 +0200 Subject: [PATCH 096/412] fix tests --- test/config_test.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/test/config_test.js b/test/config_test.js index 6d9bac1b..360375c8 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -16,14 +16,6 @@ vows.describe('config').addBatch({ return config; }, - 'should remove the load function': function (config) { - assert.isUndefined(config.load); - }, - - 'should remove the loadUrl function': function (config) { - assert.isUndefined(config.loadUrl); - }, - 'should export all environment settings': function (config) { assert.isDefined(config.dev); assert.isDefined(config.test); @@ -104,14 +96,6 @@ vows.describe('config').addBatch({ return config; }, - 'should remove the load function': function (config) { - assert.isUndefined(config.load); - }, - - 'should remove the loadUrl function': function (config) { - assert.isUndefined(config.loadUrl); - }, - 'should export the settings as the current environment': function (config) { assert.isDefined(config.dev); }, From c21ab3ce3c1e3e12537c74d8f71b4a4f752f72c4 Mon Sep 17 00:00:00 2001 From: Shane Niu Date: Thu, 18 Jun 2015 14:44:42 +1000 Subject: [PATCH 097/412] fix indent in sql loader template --- lib/migration.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 70e39013..a8eb91ec 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -112,7 +112,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { " var filePath = path.join(__dirname + '/sqls/"+this.name.replace('.js', '')+"-up.sql');", " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", " if (err) return callback(err);", - " console.log('received data: ' + data);", + " console.log('received data: ' + data);", "", " db.runSql(data, function(err) {", " if (err) return callback(err);", @@ -125,7 +125,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { " var filePath = path.join(__dirname + '/sqls/"+this.name.replace('.js', '')+"-down.sql');", " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", " if (err) return callback(err);", - " console.log('received data: ' + data);", + " console.log('received data: ' + data);", "", " db.runSql(data, function(err) {", " if (err) return callback(err);", From 095631438a393548109fbaed2ec97c37b447dc96 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 21 Jun 2015 22:22:58 +0200 Subject: [PATCH 098/412] add migrator interface to internals --- lib/driver/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index d273dc88..6045a405 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -8,7 +8,8 @@ var Shadow = require('./shadow'); var log = internals.mod.log; var tunnel = require('tunnel-ssh'), Promise = require('bluebird'), - SeederInterface = require('../interface/seederInterface.js'); + SeederInterface = require('../interface/seederInterface.js'), + MigratorInterface = require('../interface/migratorInterface.js'); var ShadowProto = { @@ -25,7 +26,8 @@ exports.connect = function (config, intern, callback) { internals.mod = mod; internals.interfaces = { - SeederInterface: SeederInterface + SeederInterface: SeederInterface, + MigratorInterface: MigratorInterface }; if ( !config.user && config.username ) @@ -112,4 +114,4 @@ exports.connect = function (config, intern, callback) { else { connect(config); } -}; \ No newline at end of file +}; From c897aa5b098ee69ddae21e34eed6f379d702fd67 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 22 Jun 2015 21:23:51 +0200 Subject: [PATCH 099/412] add logging to all function and remove semicolon from object --- lib/driver/mysql.js | 3 +++ lib/driver/pg.js | 3 +++ lib/driver/sqlite3.js | 3 +++ lib/interface/migratorInterface.js | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 1e878bcb..e74f8d0f 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -463,6 +463,9 @@ var MysqlDriver = Base.extend({ all: function() { var args = this._makeParamArgs(arguments); + + log.sql.apply(null, arguments); + return this.connection.query.apply(this.connection, args); }, diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 46d324fa..8d05ca7e 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -433,6 +433,9 @@ var PgDriver = Base.extend({ all: function() { params = arguments; + + log.sql.apply(null, params); + return new Promise(function(resolve, reject) { var prCB = function(err, data) { return (err ? reject(err) : resolve(data)); diff --git a/lib/driver/sqlite3.js b/lib/driver/sqlite3.js index d0bf1a2c..56f7959d 100644 --- a/lib/driver/sqlite3.js +++ b/lib/driver/sqlite3.js @@ -134,6 +134,9 @@ var Sqlite3Driver = Base.extend({ }, all: function() { + + log.sql.apply(null, arguments); + this.connection.all.apply(this.connection, arguments); }, diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 5e369b78..546736af 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -106,7 +106,7 @@ module.exports.deprecated = { arguments[arguments.length - 1]('not implemented'); }, - insert_deprecation: 'is going to be completely removed, use version controlled seeds instead.'; + insert_deprecation: 'is going to be completely removed, use version controlled seeds instead.' }; module.exports.extending = { }; From 6786385277f059b3d50e45d918b549e7fc7ac7af Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 22 Jun 2015 21:26:11 +0200 Subject: [PATCH 100/412] [bugfix] Redshift fails on executing set search_path TO because of non quoted response quoting the response of show search_path adding logging to all function pass error instead of reading emtpy row on error in all function fixes #277 --- lib/driver/pg.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 8d05ca7e..046f88a0 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -165,7 +165,16 @@ var PgDriver = Base.extend({ }.bind(this)) .then(function(result) { - var searchPath; + var searchPath, + search_pathes = result[0].search_path.split(','); + + for (var i = 0; i < search_pathes.length; ++i) { + if (search_pathes[i].indexOf('"') !== 0) { + search_pathes[i] = '"' + search_pathes[i] + '"'; + } + } + + result[0].search_path = search_pathes.join(','); // if the user specified a different schema, prepend it to the // search path. This will make all DDL/DML/SQL operate on the specified From 632b1ef253e62261f1cab35604e90d5330534b02 Mon Sep 17 00:00:00 2001 From: Samuel Bolduc Date: Tue, 23 Jun 2015 09:51:51 -0400 Subject: [PATCH 101/412] Added 'use strict' instructions at the beginning of generated JS files --- lib/migration.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/migration.js b/lib/migration.js index a8eb91ec..59841a09 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -44,6 +44,8 @@ var Migration = Skeleton.extend({ Migration.prototype.defaultCoffeeTemplate = function() { return [ + "'use strict';", + "", "dbm = undefined", "type = undefined", "", @@ -64,6 +66,8 @@ Migration.prototype.defaultCoffeeTemplate = function() { Migration.prototype.defaultJsTemplate = function() { return [ + "'use strict';", + "", "var dbm;", "var type;", "", @@ -94,6 +98,8 @@ Migration.prototype.defaultSqlTemplate = function() { Migration.prototype.sqlFileLoaderTemplate = function() { return [ + "'use strict';", + "", "var dbm;", "var type;", "var fs = require('fs');", @@ -139,6 +145,8 @@ Migration.prototype.sqlFileLoaderTemplate = function() { Migration.prototype.coffeeSqlFileLoaderTemplate = function() { return [ + "'use strict';", + "", "dbm = undefined", "type = undefined", "fs = require 'fs'", From ca367dbea11fd48e4c42a55a8c91eca5ed9da540 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 24 Jun 2015 00:03:48 +0200 Subject: [PATCH 102/412] changed interfaces pointer to extension only, modify the reduction function --- lib/driver/index.js | 6 ++++-- lib/util.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index 6045a405..03a3a63c 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -24,10 +24,12 @@ exports.connect = function (config, intern, callback) { var mod = internals.mod; internals = intern; internals.mod = mod; + + //add interface extensions to allow drivers to add new methods internals.interfaces = { - SeederInterface: SeederInterface, - MigratorInterface: MigratorInterface + SeederInterface: SeederInterface.extending, + MigratorInterface: MigratorInterface.extending }; if ( !config.user && config.username ) diff --git a/lib/util.js b/lib/util.js index 9a06083b..6da80d25 100644 --- a/lib/util.js +++ b/lib/util.js @@ -90,7 +90,7 @@ exports.reduceToInterface = function(db, originInterface) { if (typeof db[prop] === "function" && typeof originInterface.extend[prop] === "function") { - Interface[prop] = originInterface.extend[prop]; + Interface[prop] = db[prop]; } else if(typeof originInterface[prop] === "function") { From 9f8a3de8ec2541c755c8c5d08486cdcd97e8187b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 25 Jun 2015 19:57:27 +0200 Subject: [PATCH 103/412] update dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fec8fb0c..1ddf0520 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "dependencies": { "async": "^1.0.0", "bluebird": "^2.9.12", - "dotenv": "~1.1.0", + "dotenv": "~1.2.0", "final-fs": "^1.6.0", "mkdirp": "~0.5.0", "moment": "~2.10.2", From a10e1773690fb3f9927ca67cf8eda65b47180e79 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 28 Jun 2015 14:07:19 +0200 Subject: [PATCH 104/412] add log-level, sql query formatting, fix some typos, ignoring completed migrations Adds the ability to use db-migrate to generate sql files, by adding a log level and the ability to ignore already executed migrations. If the log-level is set to sql only we automatically going to format the sql queries. The default syntax of: ? and are currently supported. --- api.js | 23 +++++++++-- lib/driver/mysql.js | 2 +- lib/driver/pg.js | 2 +- lib/driver/sqlite3.js | 2 +- lib/log.js | 88 ++++++++++++++++++++++++++++++++++++++++--- lib/migration.js | 34 ++++++++++------- 6 files changed, 126 insertions(+), 25 deletions(-) diff --git a/api.js b/api.js index 257cece0..623b3315 100644 --- a/api.js +++ b/api.js @@ -308,7 +308,8 @@ function setDefaultArgv(isModule) { config: internals.configFile || internals.cwd + '/database.json', 'migrations-dir': internals.cwd + '/migrations', 'vcseeder-dir': internals.cwd + '/VCSeeder', - 'staticseeder-dir': internals.cwd + '/Seeder'}) + 'staticseeder-dir': internals.cwd + '/Seeder', + 'ignore-completed-migrations': false}) .usage('Usage: db-migrate [up|down|reset|create|db] [[dbname/]migrationName|all] [options]') .describe('env', 'The environment to run the migrations under (dev, test, prod).') @@ -364,8 +365,14 @@ function setDefaultArgv(isModule) { .describe('staticseeder-dir', 'Set the path to the Seeder directory.') .string('staticseeder-dir') - .describe('no-transactions', 'Explicitly disable transactions') - .boolean('no-transactions') + .describe('non-transactional', 'Explicitly disable transactions') + .boolean('non-transactional') + + .describe('ignore-completed-migrations', 'Begin execution from the first migration.') + .boolean('ignore-completed-migrations') + + .describe('log-level', 'Define the log-level, for example sql|warn') + .string('log-level') .argv; @@ -379,13 +386,21 @@ function setDefaultArgv(isModule) { process.exit(1); } + if(internals.argv['log-level']) { + + log.setLogLevel(internals.argv['log-level']); + } + + internals.ignoreCompleted = internals.argv['ignore-completed-migrations']; internals.migrationTable = internals.argv.table; internals.seedsTable = internals.argv['seeds-table']; internals.matching = ''; internals.verbose = internals.argv.verbose; global.verbose = internals.verbose; - internals.notransactions = internals.argv['no-transactions'] + internals.notransactions = internals.argv['non-transactional']; internals.dryRun = internals.argv['dry-run']; + global.dryRun = internals.argv['dry-run']; + if(internals.dryRun) { log.info('dry run'); } diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index e74f8d0f..17576db1 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -20,7 +20,7 @@ var MysqlDriver = Base.extend({ var self = this; - if(!internals.notansactions) { + if(!internals.notransactions) { return this.runSql('SET AUTOCOMMIT=0;') .then(function() { diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 046f88a0..393bf32a 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -19,7 +19,7 @@ var PgDriver = Base.extend({ startMigration: function(cb){ - if(!internals.notansactions) { + if(!internals.notransactions) { return Promise.promisify(this.runSql.bind(this))('BEGIN;').nodeify(cb); } diff --git a/lib/driver/sqlite3.js b/lib/driver/sqlite3.js index 56f7959d..d4ca1019 100644 --- a/lib/driver/sqlite3.js +++ b/lib/driver/sqlite3.js @@ -17,7 +17,7 @@ var Sqlite3Driver = Base.extend({ startMigration: function(cb){ - if(!internals.notansactions) { + if(!internals.notransactions) { return Promise.promisify(this.runSql.bind(this))('BEGIN TRANSACTION;').nodeify(cb); } diff --git a/lib/log.js b/lib/log.js index f88cbcfc..0a853c5a 100644 --- a/lib/log.js +++ b/lib/log.js @@ -1,28 +1,73 @@ this.isSilent = false; +var logLevel = 15, + escape = '"', + level = { + sql: 8, + error: 4, + warn: 2, + info: 1 + }; + +exports.setLogLevel = function( log ) { + + if( typeof(log) === 'object' ) { + + logLevel = 0; + + var keys = Object.keys(log); + + for( var i = 0; i < keys.length; ++i ) { + + logLevel = logLevel | (level[keys[i]] || 0); + } + } + else if( typeof(log) === 'string' ) { + + logLevel = 0; + log.split( '|' ).map( function (key) { + + logLevel = logLevel | (level[key] || 0); + }); + } + +}; + +exports.setEscape = function( escapeChar ) { + + if(typeof(escape) === 'string') { + + escape = escapeChar; + } +}; + exports.silence = function (isSilent) { return this.isSilent = isSilent; }; exports.info = function () { - if (!this.isSilent || global.verbose) { + if ((!this.isSilent || global.verbose) && + logLevel & level.info) { Array.prototype.unshift.call(arguments, '[INFO]'); console.info.apply(console, arguments); } }; exports.warn = function () { - if (!this.isSilent || global.verbose) { + if ((!this.isSilent || global.verbose) && + logLevel & level.warn) { var args = Array.prototype.unshift.call(arguments, '[WARN]'); console.warn.apply(console, arguments); } }; exports.error = function () { - if (!this.isSilent || global.verbose) { + if ((!this.isSilent || global.verbose) && + logLevel & level.error) { var args = Array.prototype.unshift.call(arguments, '[ERROR]'); console.error.apply(console, arguments); } }; exports.sql = function(sql) { - if (!this.isSilent && (global.dryRun || global.verbose)) { + if ((!this.isSilent && (global.dryRun || global.verbose)) && + logLevel & level.sql) { var args = Array.prototype.slice.call(arguments).slice(1); args = args.slice(0, args.length - 1); if(global.verbose) { @@ -34,7 +79,40 @@ exports.sql = function(sql) { } if (global.dryRun) { if(args.length > 0) { - console.log(sql, args); + if (logLevel === level.sql) { + + if( sql.indexOf('?') !== -1 ) { + + var split = sql.split('?'); + var logSql = split[0]; + + for (var i = 1; i < split.length; ++i) { + + logSql += escape + args[0][i - 1] + escape + split[i]; + } + + console.log( logSql ); + } + else if( sql.indexOf('$1') !== -1 ) { + + var logSql = sql; + + for( var i = 0; i < args[0].length; ++i ) { + + logSql = logSql.replace( '$' + (i + 1), escape + args[0][i] + escape ); + } + + console.log( logSql ); + } + else { + + console.log(sql, args); + } + } + else { + + console.log(sql, args); + } } else { console.log(sql); } diff --git a/lib/migration.js b/lib/migration.js index 59841a09..006bda9b 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -227,20 +227,28 @@ Migration.loadFromFilesystem = function(dir, callback) { }; Migration.loadFromDatabase = function(dir, driver, callback) { - 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); - }); + 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); + }); + } }; Migration.exportInternals = function(intern) { From 750aeb40105e29ddb9590b294296292d68522463 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 28 Jun 2015 14:22:03 +0200 Subject: [PATCH 105/412] add api methods --- api.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/api.js b/api.js index 623b3315..96f4b17d 100644 --- a/api.js +++ b/api.js @@ -66,7 +66,7 @@ function dbmigrate(isModule, options, callback) { function registerEvents() { process.on('uncaughtException', function(err) { - log.error(err.stack); + log.error(err); process.exit(1); }); @@ -304,7 +304,7 @@ function setDefaultArgv(isModule) { 'seeds-table': 'seeds', 'force-exit': false, 'sql-file': false, - 'no-transactions': false, + 'non-transactional': false, config: internals.configFile || internals.cwd + '/database.json', 'migrations-dir': internals.cwd + '/migrations', 'vcseeder-dir': internals.cwd + '/VCSeeder', @@ -368,10 +368,10 @@ function setDefaultArgv(isModule) { .describe('non-transactional', 'Explicitly disable transactions') .boolean('non-transactional') - .describe('ignore-completed-migrations', 'Begin execution from the first migration.') + .describe('ignore-completed-migrations', 'Start at the first migration') .boolean('ignore-completed-migrations') - .describe('log-level', 'Define the log-level, for example sql|warn') + .describe('log-level', 'Set the log-level, for example sql|warn') .string('log-level') .argv; @@ -386,9 +386,9 @@ function setDefaultArgv(isModule) { process.exit(1); } - if(internals.argv['log-level']) { + if( internals.argv['log-level'] ) { - log.setLogLevel(internals.argv['log-level']); + log.setLogLevel( internals.argv['log-level'] ); } internals.ignoreCompleted = internals.argv['ignore-completed-migrations']; @@ -397,9 +397,9 @@ function setDefaultArgv(isModule) { internals.matching = ''; internals.verbose = internals.argv.verbose; global.verbose = internals.verbose; - internals.notransactions = internals.argv['non-transactional']; + internals.notransactions = internals.argv['non-transactional'] internals.dryRun = internals.argv['dry-run']; - global.dryRun = internals.argv['dry-run']; + global.dryRun = internals.dryRun; if(internals.dryRun) { log.info('dry run'); From 2fc726dec3b5f94ff9c6c5cce1381348908eba1d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 29 Jun 2015 03:09:27 +0200 Subject: [PATCH 106/412] add semicolon to statements --- lib/log.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/log.js b/lib/log.js index 0a853c5a..1e818862 100644 --- a/lib/log.js +++ b/lib/log.js @@ -88,10 +88,15 @@ exports.sql = function(sql) { for (var i = 1; i < split.length; ++i) { - logSql += escape + args[0][i - 1] + escape + split[i]; + if( typeof(args[i - 1]) === 'string' ) { + logSql += escape + args[i - 1] + escape + split[i]; + } + else { + logSql += escape + args[0][i - 1] + escape + split[i]; + } } - console.log( logSql ); + console.log( logSql + ';' ); } else if( sql.indexOf('$1') !== -1 ) { @@ -102,7 +107,7 @@ exports.sql = function(sql) { logSql = logSql.replace( '$' + (i + 1), escape + args[0][i] + escape ); } - console.log( logSql ); + console.log( logSql + ';' ); } else { @@ -114,7 +119,7 @@ exports.sql = function(sql) { console.log(sql, args); } } else { - console.log(sql); + console.log(sql + ';'); } } } From 3b11d789f1b1987fbfde2494d3c4dd2693025240 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 30 Jun 2015 01:13:36 +0200 Subject: [PATCH 107/412] use object based reference --- api.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api.js b/api.js index 96f4b17d..3d7bd6a4 100644 --- a/api.js +++ b/api.js @@ -22,6 +22,9 @@ var internals = {}; function dbmigrate(isModule, options, callback) { + this.internals = {}; + internals = this.internals; + if(typeof(callback) === 'function') internals.onComplete = callback; else if(typeof(options) === 'function') From 9714ed2c5878658352bb6e9c542e345a95c14073 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 30 Jun 2015 01:13:36 +0200 Subject: [PATCH 108/412] use object based reference --- api.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api.js b/api.js index 257cece0..9b564570 100644 --- a/api.js +++ b/api.js @@ -22,6 +22,9 @@ var internals = {}; function dbmigrate(isModule, options, callback) { + this.internals = {}; + internals = this.internals; + if(typeof(callback) === 'function') internals.onComplete = callback; else if(typeof(options) === 'function') From 77a58e1098dc5111098ae434e57e3b721c6d735e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 1 Jul 2015 03:28:08 +0200 Subject: [PATCH 109/412] exclude methods from NoSQL driver --- lib/driver/mongodb.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/driver/mongodb.js b/lib/driver/mongodb.js index 082440e8..b57c500e 100644 --- a/lib/driver/mongodb.js +++ b/lib/driver/mongodb.js @@ -438,6 +438,16 @@ var MongodbDriver = Base.extend({ this.connection.close(cb); }.bind(this)).nodeify(callback); + }, + + buildWhereClause: function() { + + return Promise.reject('There is no NoSQL implementation yet!'); + }, + + update: function() { + + return Promise.reject('There is no NoSQL implementation yet!'); } }); From c1c5d122c247d1138a8d85c0db9c257947576027 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 4 Jul 2015 11:54:06 +0200 Subject: [PATCH 110/412] add lookup fix missing oncomplete function --- api.js | 11 +++++++---- lib/driver/base.js | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/api.js b/api.js index 9b564570..429232b4 100644 --- a/api.js +++ b/api.js @@ -22,13 +22,16 @@ var internals = {}; function dbmigrate(isModule, options, callback) { - this.internals = {}; + this.internals = { + + onComplete: internals.onComplete + }; internals = this.internals; if(typeof(callback) === 'function') - internals.onComplete = callback; + this.internals.onComplete = callback; else if(typeof(options) === 'function') - internals.onComplete = options; + this.internals.onComplete = options; this.dataType = dbm.dataType; this.version = dbm.version; @@ -51,7 +54,7 @@ function dbmigrate(isModule, options, callback) { if(typeof(isModule) === 'function') { - internals.onComplete = isModule; + this.internals.onComplete = isModule; setDefaultArgv(); } else diff --git a/lib/driver/base.js b/lib/driver/base.js index 8b09f767..18fa439c 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -340,6 +340,17 @@ module.exports = Base = Class.extend({ return this.runSql(sql).nodeify(callback); }, + lookup: function(tableName, column, id, callback) { + + var sql = 'SELECT ' + this.escapeDDL(column) + ' FROM ' + + this.escapeDDL(tableName) + ' ' + buildWhereClause(id); + + return this.runSql(sql) + .then(function(row) { + return row[0]; + }); + }, + removeIndex: function(tableName, indexName, callback) { if (arguments.length === 2 && typeof(indexName) === 'function') { callback = indexName; @@ -467,9 +478,13 @@ module.exports = Base = Class.extend({ var searchClause = ''; - if (util.isArray(ids) && typeof(ids[0]) !== 'object') { + if (util.isArray(ids) && typeof(ids[0]) !== 'object' && ids.length > 1) { - sql += 'WHERE id IN (' + ids.join(this._escapeString + ',' + this._escapeString) + ')'; + searchClause += 'WHERE id IN (' + ids.join(this._escapeString + ',' + this._escapeString) + ')'; + } + else if(typeof(ids) === 'string' || ids.length === 1) { + var id = (util.isArray(ids)) ? ids[0] : ids; + searchClause += 'WHERE id = ' + id; } else if (util.isArray(ids) && typeof(ids[0]) === 'object'){ From da16e9d21656b7d27aee93d84b9b92cca6dc8d42 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 5 Jul 2015 12:32:08 +0200 Subject: [PATCH 111/412] move methods to object space --- api.js | 15 ++++++++++++--- connect.js | 23 ++++++++++++++++++++++- lib/migration.js | 3 +-- lib/migrator.js | 20 +++++++++----------- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/api.js b/api.js index 9e166d21..37fa29fd 100644 --- a/api.js +++ b/api.js @@ -527,7 +527,10 @@ function executeUp() { internals.argv.count = Number.MAX_VALUE; } - index.connect(config.getCurrent().settings, Migrator, function(err, migrator) { + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, Migrator, function(err, migrator) { assert.ifError(err); if(internals.locTitle) @@ -550,7 +553,10 @@ function executeDown() { internals.argv.count = 1; } - index.connect(config.getCurrent().settings, Migrator, function(err, migrator) { + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, Migrator, function(err, migrator) { assert.ifError(err); migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); @@ -615,7 +621,10 @@ function executeSeed() { internals.argv.destination = internals.argv._.shift().toString(); } - index.connect(config.getCurrent().settings, Seeder, function(err, seeder) + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, Seeder, function(err, seeder) { assert.ifError(err); diff --git a/connect.js b/connect.js index 5f5b1887..c6065676 100644 --- a/connect.js +++ b/connect.js @@ -7,6 +7,13 @@ var log = require('./lib/log'); var internals = {}; exports.connect = function(config, passedClass, callback) { + var internals = {}; + var _config = config; + if( config.config ) { + internals = config.internals; + config = config.config; + } + driver.connect(config, internals, function(err, db) { if (err) { callback(err); return; } @@ -65,6 +72,13 @@ exports.connect = function(config, passedClass, callback) { exports.driver = function(config, callback) { + var internals = {}; + var _config = config; + if( config.config ) { + internals = config.internals; + config = config.config; + } + driver.connect(config, internals, callback); }; @@ -73,6 +87,13 @@ function migrationFiles(files, callback, config, passedClass, db, close, cb) { switched = false, newConf; + var internals = {}; + var _config = config; + if( config.config ) { + internals = config.internals; + config = config.config; + } + if(files.length === 1) { db.close = close; @@ -130,4 +151,4 @@ exports.exportInternals = function( intern ) { exports.importInternals = function() { return internals; -}; \ No newline at end of file +}; diff --git a/lib/migration.js b/lib/migration.js index 006bda9b..5de39a84 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -226,8 +226,7 @@ Migration.loadFromFilesystem = function(dir, callback) { }); }; -Migration.loadFromDatabase = function(dir, driver, callback) { - +Migration.loadFromDatabase = function(dir, driver, internals, callback) { if (internals.ignoreCompleted) { callback(null, []); diff --git a/lib/migrator.js b/lib/migrator.js index 5f34cbc1..e137e78b 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -3,14 +3,12 @@ var Migration = require('./migration'); var log = require('./log'); var Promise = require('bluebird'); -var internals = {}; - Migrator = function(driver, migrationsDir, empty, intern) { this.driver = driver; this.migrationsDir = migrationsDir; - internals = intern; + this.internals = intern; - internals.migrationOptions.relation = require('./relation'); + this.internals.migrationOptions.relation = require('./relation'); Migration.exportInternals(intern); }; @@ -29,7 +27,7 @@ Migrator.prototype = { } callback(err); } - this.driver.addMigrationRecord(internals.matching + '/' + migration.name, onComplete); + this.driver.addMigrationRecord(this.internals.matching + '/' + migration.name, onComplete); }, deleteMigrationRecord: function(migration, callback) { @@ -41,9 +39,9 @@ Migrator.prototype = { } callback(err); } - this.driver.deleteMigration(internals.matching + '/' + migration.name, function(err) { + this.driver.deleteMigration(this.internals.matching + '/' + migration.name, function(err) { - if(!internals.matching) { + if(!this.internals.matching) { this.driver.deleteMigration(migration.name, onComplete); } @@ -75,7 +73,7 @@ Migrator.prototype = { Migration.loadFromFilesystem(self.migrationsDir, function(err, allMigrations) { if (err) { callback(err); return; } - Migration.loadFromDatabase(self.migrationsDir, self.driver, function(err, completedMigrations) { + Migration.loadFromDatabase(self.migrationsDir, self.driver, self.internals, function(err, completedMigrations) { if (err) { callback(err); return; } var toRun = dbmUtil.filterUp(allMigrations, completedMigrations, partialName, count); @@ -95,7 +93,7 @@ Migrator.prototype = { var setup = migration.setup(); if(typeof(setup) === 'function') - setup(internals.migrationOptions); + setup(self.internals.migrationOptions); return (Promise.promisify(self.up.bind(self)))(migration.up.bind(migration)); }) @@ -117,7 +115,7 @@ Migrator.prototype = { downToBy: function(count, callback) { var self = this; - Migration.loadFromDatabase(self.migrationsDir, self.driver, function(err, completedMigrations) { + Migration.loadFromDatabase(self.migrationsDir, self.driver, self.internals, function(err, completedMigrations) { if (err) { return callback(err); } var toRun = dbmUtil.filterDown(completedMigrations, count); @@ -137,7 +135,7 @@ Migrator.prototype = { var setup = migration.setup(); if(typeof(setup) === 'function') - setup(internals.migrationOptions); + setup(self.internals.migrationOptions); return (Promise.promisify(self.down.bind(self)))(migration.down.bind(migration)); }) From 61400f640b26a0a9fd6a72d43e0e33983ffb256d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 6 Jul 2015 03:24:08 +0200 Subject: [PATCH 112/412] add on update current_timestamp to mysql driver --- lib/driver/mysql.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 17576db1..4a4ff342 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -128,6 +128,10 @@ var MysqlDriver = Base.extend({ constraint.push('ROW_FORMAT=\'' + spec.rowFormat + '\'') } + if (spec.onUpdate && spec.onUpdate === 'CURRENT_TIMESTAMP') { + constraint.push('ON UPDATE CURRENT_TIMESTAMP') + } + if (spec.null || spec.notNull === false) { constraint.push('NULL'); } @@ -136,7 +140,12 @@ var MysqlDriver = Base.extend({ constraint.push('DEFAULT'); if (typeof spec.defaultValue === 'string'){ - constraint.push("'" + spec.defaultValue + "'"); + if(spec.defaultValue === 'CURRENT_TIMESTAMP') { + constraint.push(spec.defaultValue); + } + else { + constraint.push("'" + spec.defaultValue + "'"); + } } else if (spec.defaultValue === null) { constraint.push('NULL'); } else { From f1d4b884ab4dc08f9998d8c8fa78ed8000781ef1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 8 Jul 2015 06:47:57 +0200 Subject: [PATCH 113/412] add bulk insert to insert function --- lib/driver/mysql.js | 50 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 4a4ff342..db751934 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -307,24 +307,56 @@ var MysqlDriver = Base.extend({ var sql = util.format('INSERT INTO `%s` ', tableName); var columnNames = '('; - var values = 'VALUES ('; + var values = 'VALUES '; + var values_part = []; for (var index in columnNameArray) { columnNames += '`' + columnNameArray[index] + '`'; - if (typeof(valueArray[index]) === 'string') { - values += "'" + this.escape(valueArray[index]) + "'"; - } else { - values += valueArray[index]; + if( util.isArray(valueArray) ) { + + for( var i = 0; i < valuearray.length; ++i ) { + + values_part[i] = values_part[i] || ''; + + if (typeof(valueArray[i][index]) === 'string') { + values_part[i] += "'" + this.escape(valueArray[i][index]) + "'"; + } else { + values_part[i] += valueArray[i][index]; + } + } } + else { - if (index != columnNameArray.length - 1) { - columnNames += ","; - values += ","; + if (typeof(valueArray[index]) === 'string') { + values_part += "'" + this.escape(valueArray[index]) + "'"; + } else { + values_part += valueArray[index]; + } + + values_part += ","; } + + columnNames += ","; + } + + + if( util.isArray(valueArray) ) { + + for( var i = 0; i < values_part.length; ++i ) { + + values += '(' + values_part[i].slice(0, -1) + '),'; + } + + values = values.slice(0, -1); + } + else { + + values += '(' + values_part.slice(0, -1) + ')'; } - sql += columnNames + ') '+ values + ');'; + sql += columnNames.slice(0, -1) + ') ' + + values + ';'; return this.runSql(sql).nodeify(callback); }, From 5f9aabb81ee10186a31203ab30a5ae6c400bfe2b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 8 Jul 2015 15:32:57 +0200 Subject: [PATCH 114/412] define new and deprecate old call convention of insert --- lib/driver/mysql.js | 32 +++++++++++++++++++++++++++++--- lib/interface/seederInterface.js | 2 +- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index db751934..cc21ee66 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -300,7 +300,33 @@ var MysqlDriver = Base.extend({ return this.runSql(sql).nodeify(callback); }, - insert: function(tableName, columnNameArray, valueArray, callback) { + insert: function(tableName, valueArray, callback) { + + var columnNameArray; + + if( arguments.length > 3 ) { + + log.warn( 'This calling convention of insert is deprecated' ); + columnNameArray = valueArray; + valueArray = callback; + callback = arguments[3]; + } + else { + + var names; + if( util.isArray(valueArray) ) { + names = Object.keys(valueArray[0]); + } + else { + names = Object.keys(valueArray); + } + + for( var i = 0; i < names.length; ++i ) { + + columnNameArray[names[i]] = names[i]; + } + } + if (columnNameArray.length !== valueArray.length) { return callback(new Error('The number of columns does not match the number of values.')); } @@ -313,9 +339,9 @@ var MysqlDriver = Base.extend({ for (var index in columnNameArray) { columnNames += '`' + columnNameArray[index] + '`'; - if( util.isArray(valueArray) ) { + if( util.isArray(valueArray) && typeof(valueArray[0]) === 'object') { - for( var i = 0; i < valuearray.length; ++i ) { + for( var i = 0; i < valueArray.length; ++i ) { values_part[i] = values_part[i] || ''; diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index 8144c37e..4d39c995 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -77,7 +77,7 @@ function insert(table, options, callback) { return lookup(options) .then(function(){ - return this.driver.massInsert(options); + return this.driver.insert(options); }) .catch(function(e) { From 959e5e8db887bdb538991065ba8f7270401cc33c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 8 Jul 2015 15:47:44 +0200 Subject: [PATCH 115/412] fix breaking tests --- lib/driver/mysql.js | 2 +- test/driver/mysql_test.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index cc21ee66..1b2c15f2 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -367,7 +367,7 @@ var MysqlDriver = Base.extend({ } - if( util.isArray(valueArray) ) { + if( util.isArray(valueArray) && typeof(valueArray[0]) === 'object' ) { for( var i = 0; i < values_part.length; ++i ) { diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index 7f002669..c2b341bf 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -3,11 +3,13 @@ var assert = require('assert'); var dbmeta = require('db-meta'); var dataType = require('../../lib/data_type'); var driver = require('../../lib/driver'); +var log = require('../..//lib/log.js'); var config = require('../db.config.json').mysql; var internals = {}; internals.migrationTable = 'migrations'; +log.silence(true); var dbName = config.database; driver.connect(config, internals, function(err, db) { From 8759e96274f715d337543cd90a4878561610b62b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 9 Jul 2015 03:48:59 +0200 Subject: [PATCH 116/412] update reduce to interface function --- lib/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index 6da80d25..3400a633 100644 --- a/lib/util.js +++ b/lib/util.js @@ -36,7 +36,7 @@ exports.reduceToInterface = function(db, originInterface) { var Interface = {}; Interface._original = {}; - for(var prop in db) { + for(var prop in originInterface) { if (typeof db[prop] === "function") { @@ -60,7 +60,7 @@ exports.reduceToInterface = function(db, originInterface) { Interface[property] = function() { log.warn('This function "' + property - + '" is deprecated.' + "\n" + + '" is deprecated and ' + originInterface.deprecated[property + '_deprecation'] ); return this._original[property].apply(this, arguments); From e2e4f8bc1cb521563fc14bac64696b155aa520af Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 10 Jul 2015 04:55:45 +0200 Subject: [PATCH 117/412] update dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ddf0520..e5ec74bd 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "mkdirp": "~0.5.0", "moment": "~2.10.2", "mongodb": "^2.0.23", - "mysql": "~2.7.0", + "mysql": "~2.8.0", "optimist": "~0.6.1", "parse-database-url": "~0.2.2", "pg": "~4.4.0", From 0d1c64598844c8edc685937396781e76470a4010 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 11 Jul 2015 23:44:07 +0200 Subject: [PATCH 118/412] update dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e5ec74bd..e6ae01b4 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "pg-native": "^1.8.0", "pkginfo": "~0.3.0", "resolve": "^1.1.6", - "semver": "~4.3.3", + "semver": "~5.0.1", "sqlite3": "~3.0.4", "tunnel-ssh": "^1.0.0" }, From 8fab91d47118518e3343c2c85366b5eb4654a1ba Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 12 Jul 2015 00:48:10 +0200 Subject: [PATCH 119/412] add needed functions to seeder interface --- lib/interface/seederInterface.js | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index 4d39c995..23917144 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -135,6 +135,42 @@ var SeederInterface = { arguments[arguments.length - 1]('not implemented'); }, + + buildWhereClause: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + quoteDDLArr: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + quoteArr: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + escapeString: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + escape: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + escapeDDL: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + checkDBMS: function() { + + arguments[arguments.length - 1]('not implemented'); + } + }; module.exports = SeederInterface; From dd45fd3350640f33b75e095f60192a1722d7cdd5 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 13 Jul 2015 23:36:56 +0200 Subject: [PATCH 120/412] add missing functions to interface --- lib/interface/seederInterface.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index 23917144..a3f21976 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -168,6 +168,21 @@ var SeederInterface = { checkDBMS: function() { + arguments[arguments.length - 1]('not implemented'); + }, + + update: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + truncate: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + switchDatabase: function() { + arguments[arguments.length - 1]('not implemented'); } From 2ddc2fc6a734d23fba90e61227a8f73f1375b1dd Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 15 Jul 2015 17:45:04 +0200 Subject: [PATCH 121/412] partial build of interface --- api.js | 4 ++-- lib/driver/shadow.js | 9 +++++---- lib/interface/migratorInterface.js | 16 ++++++++++++++++ lib/log.js | 1 + lib/migrator.js | 4 +++- lib/util.js | 15 ++++++++++++--- 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/api.js b/api.js index 37fa29fd..c5e26690 100644 --- a/api.js +++ b/api.js @@ -72,12 +72,12 @@ function dbmigrate(isModule, options, callback) { function registerEvents() { process.on('uncaughtException', function(err) { - log.error(err); + log.error(err.stack); process.exit(1); }); process.on("unhandledRejection", function(reason, promise) { - log.error(reason); + log.error(reason.stack); process.exit(1); }); } diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index cbc8824b..9c17fa21 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -37,13 +37,14 @@ exports.infect = function(db, intern, ShadowProto) { (function(property) { - db[property] = function() { + db[property] = function() { var params = arguments, + self = this, callback; - return this._shadowProto[property].apply(this, params) - .then( function() { - return this._shadowsHost[property].apply(this, params); + return self._shadowProto[property].apply(self, params) + .then( function() { + return self._shadowsHost[property].apply(self, params); }.bind(this)); }; }(prop)); diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 546736af..451338fd 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -91,6 +91,22 @@ MigratorInterface.prototype = { arguments[arguments.length - 1]('not implemented'); }, + createMigrationsTable: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + createSeedsTable: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + normalizeColumnSpec: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + runSql: function() { arguments[arguments.length - 1]('not implemented'); diff --git a/lib/log.js b/lib/log.js index 1e818862..23c0fa3f 100644 --- a/lib/log.js +++ b/lib/log.js @@ -62,6 +62,7 @@ exports.error = function () { if ((!this.isSilent || global.verbose) && logLevel & level.error) { var args = Array.prototype.unshift.call(arguments, '[ERROR]'); + console.trace( 'Trace from error log' ); console.error.apply(console, arguments); } }; diff --git a/lib/migrator.js b/lib/migrator.js index e137e78b..e02ea56a 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -2,9 +2,11 @@ var dbmUtil = require('./util'); var Migration = require('./migration'); var log = require('./log'); var Promise = require('bluebird'); +var MigratorInterface = require( './interface/migratorInterface.js'); Migrator = function(driver, migrationsDir, empty, intern) { - this.driver = driver; + this.driver = dbmUtil.reduceToInterface( driver, MigratorInterface ); + console.log( this.driver ); this.migrationsDir = migrationsDir; this.internals = intern; diff --git a/lib/util.js b/lib/util.js index 3400a633..8e97080e 100644 --- a/lib/util.js +++ b/lib/util.js @@ -36,15 +36,24 @@ exports.reduceToInterface = function(db, originInterface) { var Interface = {}; Interface._original = {}; - for(var prop in originInterface) { + if( db._shadowsHost ) { + + Interface._shadowsHost = db._shadowsHost; + Interface._shadowProto = db._shadowProto; + } + + var origin = (typeof(originInterface) === 'function') ? + originInterface.prototype : originInterface; + + for(var prop in origin) { if (typeof db[prop] === "function") { Interface[prop] = db[prop]; } - else if(typeof originInterface[prop] === "function") { + else if(typeof origin[prop] === "function") { - Interface[prop] = originInterface[prop]; + Interface[prop] = origin[prop]; } } From fcfc99d92df9738d712ef0250335c2ee65dabd15 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 16 Jul 2015 02:21:31 +0200 Subject: [PATCH 122/412] add reducteToInterface to seeder --- lib/seeder.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/seeder.js b/lib/seeder.js index 247f4ac3..53aed745 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -2,11 +2,12 @@ var Seed = require('./seed'); var log = require('./log'); var dbmUtil = require('./util'); var Promise = require('bluebird'); +var SeederInterface = require( './interface/seederInterface.js'); var internals = {}; Seeder = function (driver, seedsDir, versionControlled, intern) { - this.driver = driver; + this.driver = dbmUtil.reduceToInterface( driver, SeederInterface ); this.seedDir = seedsDir; this.isVC = versionControlled; internals = intern; From 88f2b056eb1599b9f2241ad386a957f2d9522944 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 17 Jul 2015 23:12:42 +0200 Subject: [PATCH 123/412] add all not function props to object --- lib/util.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/util.js b/lib/util.js index 8e97080e..33a91484 100644 --- a/lib/util.js +++ b/lib/util.js @@ -45,6 +45,14 @@ exports.reduceToInterface = function(db, originInterface) { var origin = (typeof(originInterface) === 'function') ? originInterface.prototype : originInterface; + for(var prop in db) { + + if( typeof(db[prop]) !== "function" ) { + + Interface[prop] = db[prop]; + } + } + for(var prop in origin) { if (typeof db[prop] === "function") { From cf7b4cf6a9b773fc20244e992a32238040239482 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 18 Jul 2015 00:07:17 +0200 Subject: [PATCH 124/412] add possibility to exclude non function props --- lib/util.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/util.js b/lib/util.js index 33a91484..9ec888b5 100644 --- a/lib/util.js +++ b/lib/util.js @@ -47,7 +47,8 @@ exports.reduceToInterface = function(db, originInterface) { for(var prop in db) { - if( typeof(db[prop]) !== "function" ) { + if( typeof(db[prop]) !== "function" && + originInterface.exclude[prop] === undefined ) { Interface[prop] = db[prop]; } From a9c544dc6bd09658935f1ec49b88d7349dddf729 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 19 Jul 2015 23:16:37 +0200 Subject: [PATCH 125/412] add missing functions to migrator interface --- lib/interface/migratorInterface.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 451338fd..832e194a 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -106,11 +106,20 @@ MigratorInterface.prototype = { arguments[arguments.length - 1]('not implemented'); }, - runSql: function() { arguments[arguments.length - 1]('not implemented'); - } + }, + + createColumnDef: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + mapDataType: function() { + + arguments[arguments.length - 1]('not implemented'); + }, }; From e2e929eee9595fda748d0b54ae3413f4b4ca74c0 Mon Sep 17 00:00:00 2001 From: Samuel Bolduc Date: Mon, 20 Jul 2015 11:06:29 -0400 Subject: [PATCH 126/412] Logging --- lib/driver/pg.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 393bf32a..0f3bb264 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -180,10 +180,13 @@ var PgDriver = Base.extend({ // search path. This will make all DDL/DML/SQL operate on the specified // schema. if (this.schema === 'public') { + console.log('inside if branch'); searchPath = result[0].search_path; } else { + console.log('inside else branch'); searchPath = '"' + this.schema + '",' + result[0].search_path; } + console.log('searchPath: %s', searchPath); return this.all('SET search_path TO ' + searchPath); }.bind(this)) From 89021ff3112c263968bb52bd1a1f00ab4fefd20e Mon Sep 17 00:00:00 2001 From: Samuel Bolduc Date: Mon, 20 Jul 2015 11:09:55 -0400 Subject: [PATCH 127/412] logging --- lib/driver/pg.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 0f3bb264..4967eb76 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -181,9 +181,10 @@ var PgDriver = Base.extend({ // schema. if (this.schema === 'public') { console.log('inside if branch'); + console.log(result); + console.log(result[0]); searchPath = result[0].search_path; } else { - console.log('inside else branch'); searchPath = '"' + this.schema + '",' + result[0].search_path; } console.log('searchPath: %s', searchPath); From e558814b4743430197028e6799edb7a2cd34288f Mon Sep 17 00:00:00 2001 From: Samuel Bolduc Date: Mon, 20 Jul 2015 11:14:39 -0400 Subject: [PATCH 128/412] Added trim to search_path splitted values --- lib/driver/pg.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 4967eb76..4c34bdfb 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -170,7 +170,7 @@ var PgDriver = Base.extend({ for (var i = 0; i < search_pathes.length; ++i) { if (search_pathes[i].indexOf('"') !== 0) { - search_pathes[i] = '"' + search_pathes[i] + '"'; + search_pathes[i] = '"' + search_pathes[i].trim() + '"'; } } @@ -180,9 +180,6 @@ var PgDriver = Base.extend({ // search path. This will make all DDL/DML/SQL operate on the specified // schema. if (this.schema === 'public') { - console.log('inside if branch'); - console.log(result); - console.log(result[0]); searchPath = result[0].search_path; } else { searchPath = '"' + this.schema + '",' + result[0].search_path; From c976284cd746f28645b45e844809f3d1cdeba9d5 Mon Sep 17 00:00:00 2001 From: Samuel Bolduc Date: Mon, 20 Jul 2015 11:16:11 -0400 Subject: [PATCH 129/412] Remove debugging logs --- lib/driver/pg.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 4c34bdfb..e9611f06 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -184,7 +184,6 @@ var PgDriver = Base.extend({ } else { searchPath = '"' + this.schema + '",' + result[0].search_path; } - console.log('searchPath: %s', searchPath); return this.all('SET search_path TO ' + searchPath); }.bind(this)) From 98a46c33a26e0cec1345b87a12bbd3a8c11fa4a7 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 20 Jul 2015 23:56:40 +0200 Subject: [PATCH 130/412] make excludes optional --- lib/util.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/util.js b/lib/util.js index 9ec888b5..5d68b791 100644 --- a/lib/util.js +++ b/lib/util.js @@ -36,6 +36,9 @@ exports.reduceToInterface = function(db, originInterface) { var Interface = {}; Interface._original = {}; + //set to make it optional + originInterface.exclude = originInterface.exclude || {}; + if( db._shadowsHost ) { Interface._shadowsHost = db._shadowsHost; From f37b57da79f868ab4bdbe9b088ebfac30fdefd56 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 21 Jul 2015 00:04:18 +0200 Subject: [PATCH 131/412] add some missing methods to migrator interface good night commit... --- lib/interface/migratorInterface.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 832e194a..fcd8bdc3 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -120,6 +120,12 @@ MigratorInterface.prototype = { arguments[arguments.length - 1]('not implemented'); }, + + createColumnConstraint: function() { + + arguments[arguments.length - 1]('not implemented'); + } + }; @@ -133,5 +139,10 @@ module.exports.deprecated = { insert_deprecation: 'is going to be completely removed, use version controlled seeds instead.' }; + module.exports.extending = { }; + +module.exports.exclude = { + +}; From 84ec7b08c99e8ddc9813348b6eaf5eebe8dd964d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 21 Jul 2015 21:05:54 +0200 Subject: [PATCH 132/412] added all necessary methods to migratorInterface? go through checklist next! --- lib/interface/migratorInterface.js | 52 +++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index fcd8bdc3..18925396 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -123,9 +123,59 @@ MigratorInterface.prototype = { createColumnConstraint: function() { + arguments[arguments.length - 1]('not implemented'); + }, + + _makeParamArgs: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + recurseCallbackArray: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + allLoadedMigrations: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + allLoadedSeeds: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + addSeedRecord: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + startMigration: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + endMigration: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + addMigrationRecord: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + all: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + close: function() { + arguments[arguments.length - 1]('not implemented'); } - + }; From 42c5802b61b9db8fc87f444043c171dc7cc572eb Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 21 Jul 2015 21:48:26 +0200 Subject: [PATCH 133/412] remove logging --- lib/migrator.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/migrator.js b/lib/migrator.js index e02ea56a..f094b701 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -6,7 +6,6 @@ var MigratorInterface = require( './interface/migratorInterface.js'); Migrator = function(driver, migrationsDir, empty, intern) { this.driver = dbmUtil.reduceToInterface( driver, MigratorInterface ); - console.log( this.driver ); this.migrationsDir = migrationsDir; this.internals = intern; From 0e79de948818478a3b8c647d6ffc6294056c2f31 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 21 Jul 2015 23:00:48 +0200 Subject: [PATCH 134/412] add missing functions to interface, make use of the real driver for adding and deleting migration records --- lib/interface/migratorInterface.js | 40 ++++++++++++++++++++++++++++++ lib/migrator.js | 13 +++++----- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 18925396..ad56d4cd 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -166,6 +166,46 @@ MigratorInterface.prototype = { arguments[arguments.length - 1]('not implemented'); }, + deleteMigration: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + deleteSeed: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + quoteDDLArr: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + quoteArr: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + escapeString: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + escape: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + escapeDDL: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + + checkDBMS: function() { + + arguments[arguments.length - 1]('not implemented'); + }, + all: function() { arguments[arguments.length - 1]('not implemented'); diff --git a/lib/migrator.js b/lib/migrator.js index f094b701..47a38715 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -6,6 +6,7 @@ var MigratorInterface = require( './interface/migratorInterface.js'); Migrator = function(driver, migrationsDir, empty, intern) { this.driver = dbmUtil.reduceToInterface( driver, MigratorInterface ); + this._driver = driver; this.migrationsDir = migrationsDir; this.internals = intern; @@ -16,7 +17,7 @@ Migrator = function(driver, migrationsDir, empty, intern) { Migrator.prototype = { createMigrationTable: function(callback) { - this.driver.createMigrationTable(callback); + this._driver.createMigrationTable(callback); }, writeMigrationRecord: function(migration, callback) { @@ -28,7 +29,7 @@ Migrator.prototype = { } callback(err); } - this.driver.addMigrationRecord(this.internals.matching + '/' + migration.name, onComplete); + this._driver.addMigrationRecord(this.internals.matching + '/' + migration.name, onComplete); }, deleteMigrationRecord: function(migration, callback) { @@ -40,11 +41,11 @@ Migrator.prototype = { } callback(err); } - this.driver.deleteMigration(this.internals.matching + '/' + migration.name, function(err) { + this._driver.deleteMigration(this.internals.matching + '/' + migration.name, function(err) { if(!this.internals.matching) { - this.driver.deleteMigration(migration.name, onComplete); + this._driver.deleteMigration(migration.name, onComplete); } else { @@ -74,7 +75,7 @@ Migrator.prototype = { Migration.loadFromFilesystem(self.migrationsDir, function(err, allMigrations) { if (err) { callback(err); return; } - Migration.loadFromDatabase(self.migrationsDir, self.driver, self.internals, function(err, completedMigrations) { + Migration.loadFromDatabase(self.migrationsDir, self._driver, self.internals, function(err, completedMigrations) { if (err) { callback(err); return; } var toRun = dbmUtil.filterUp(allMigrations, completedMigrations, partialName, count); @@ -116,7 +117,7 @@ Migrator.prototype = { downToBy: function(count, callback) { var self = this; - Migration.loadFromDatabase(self.migrationsDir, self.driver, self.internals, function(err, completedMigrations) { + Migration.loadFromDatabase(self.migrationsDir, self._driver, self.internals, function(err, completedMigrations) { if (err) { return callback(err); } var toRun = dbmUtil.filterDown(completedMigrations, count); From c30044e22b58877872c40d481a9d0b20ad6f2fb4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 21 Jul 2015 23:03:21 +0200 Subject: [PATCH 135/412] make use of the real driver for adding and deleting migration records --- lib/seeder.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/seeder.js b/lib/seeder.js index 53aed745..c86fbace 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -8,6 +8,7 @@ var internals = {}; Seeder = function (driver, seedsDir, versionControlled, intern) { this.driver = dbmUtil.reduceToInterface( driver, SeederInterface ); + this._driver = driver; this.seedDir = seedsDir; this.isVC = versionControlled; internals = intern; @@ -103,7 +104,7 @@ Seeder.prototype = { if (err) { callback(err); return; } - return Migration.loadFromDatabase(self.seedDir, self.driver, function(err, completedMigrations) { + return Migration.loadFromDatabase(self.seedDir, self._driver, function(err, completedMigrations) { if (err) { callback(err); return; } var toRun = dbmUtil.filterUp(allMigrations, completedMigrations, partialName, count); @@ -141,7 +142,7 @@ Seeder.prototype = { downToBy: function(count, callback) { var self = this; - Seed.loadFromDatabase(self.seedDir, self.driver, function(err, completedMigrations) { + Seed.loadFromDatabase(self.seedDir, self._driver, function(err, completedMigrations) { if (err) { return callback(err); } var toRun = dbmUtil.filterDown(completedMigrations, count); From 61b23c2d3f15ae377963577e701811e830474c6c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 21 Jul 2015 23:10:07 +0200 Subject: [PATCH 136/412] add component for controlling vc seeder --- lib/seeder.js | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/seeder.js b/lib/seeder.js index c86fbace..6efbb622 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -96,6 +96,28 @@ Seeder.prototype = { }); }, + deleteMigrationRecord: 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; @@ -104,10 +126,10 @@ Seeder.prototype = { if (err) { callback(err); return; } - return Migration.loadFromDatabase(self.seedDir, self._driver, function(err, completedMigrations) { + return Seed.loadFromDatabase(self.seedDir, self._driver, function(err, completedSeeds) { if (err) { callback(err); return; } - var toRun = dbmUtil.filterUp(allMigrations, completedMigrations, partialName, count); + var toRun = dbmUtil.filterUp(allMigrations, completedSeeds, partialName, count); if (toRun.length === 0) { log.info('No seeds to run'); @@ -142,10 +164,10 @@ Seeder.prototype = { downToBy: function(count, callback) { var self = this; - Seed.loadFromDatabase(self.seedDir, self._driver, function(err, completedMigrations) { + Seed.loadFromDatabase(self.seedDir, self._driver, function(err, completedSeeds) { if (err) { return callback(err); } - var toRun = dbmUtil.filterDown(completedMigrations, count); + var toRun = dbmUtil.filterDown(completedSeeds, count); if (toRun.length === 0) { log.info('No migrations to run'); From 89529d55272ba6af070b3a6249fe7062a82038ee Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 21 Jul 2015 23:14:01 +0200 Subject: [PATCH 137/412] add api options, switch to object t property within object --- api.js | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/api.js b/api.js index c5e26690..8b8c5a5b 100644 --- a/api.js +++ b/api.js @@ -111,21 +111,21 @@ dbmigrate.prototype = { addConfiguration: function(description, args, type) { var name = args.shift(); - internals.argv.describe(name, description); + this.internals.argv.describe(name, description); for(var i = 0; i < args.length; ++i) { - internals.argv.alias(args[i], name); + this.internals.argv.alias(args[i], name); } switch(type) { case 'string': - internals.argv.string(name); + this.internals.argv.string(name); break; case 'boolean': - internals.argv.boolean(name); + this.internals.argv.boolean(name); break; default: @@ -140,7 +140,7 @@ dbmigrate.prototype = { * Resets and sets argv to a specified new argv. */ resetConfiguration: function(argv) { - internals.argv = argv; + this.internals.argv = argv; }, /** @@ -154,16 +154,16 @@ dbmigrate.prototype = { { if(typeof(specification) === 'string') { - internals.argv.destination = specification; + this.internals.argv.destination = specification; } else if(typeof(specification) === 'number') { - internals.argv.count = specification; + this.internals.argv.count = specification; } if(scope) { - internals.migrationMode = scope; + this.internals.migrationMode = scope; } } @@ -181,12 +181,12 @@ dbmigrate.prototype = { { if(typeof(arguments[0]) === 'number') { - internals.argv.count = arguments[0]; + this.internals.argv.count = arguments[0]; } if(scope) { - internals.migrationMode = scope; + this.internals.migrationMode = scope; } } @@ -200,10 +200,10 @@ dbmigrate.prototype = { if(scope) { - internals.migrationMode = scope; + this.internals.migrationMode = scope; } - internals.argv.count = Number.MAX_VALUE; + this.internals.argv.count = Number.MAX_VALUE; executeDown(); }, @@ -222,10 +222,10 @@ dbmigrate.prototype = { if(scope) { - internals.migrationMode = scope; + this.internals.migrationMode = scope; } - internals.argv._.push(migrationName); + this.internals.argv._.push(migrationName); executeCreate(); }, @@ -234,8 +234,8 @@ dbmigrate.prototype = { */ createDatabase: function(dbname) { - internals.argv._.push(dbname); - internals.mode = 'create'; + this.internals.argv._.push(dbname); + this.internals.mode = 'create'; }, /** @@ -243,8 +243,8 @@ dbmigrate.prototype = { */ dropDatabase: function(dbname) { - internals.argv._.push(dbname); - internals.mode = 'drop'; + this.internals.argv._.push(dbname); + this.internals.mode = 'drop'; }, /** @@ -254,7 +254,7 @@ dbmigrate.prototype = { */ setConfigParam: function(param, value) { - return (internals.argv[param] = value); + return (this.internals.argv[param] = value); }, @@ -263,7 +263,7 @@ dbmigrate.prototype = { */ setDefaultCallback: function() { - internals.onComplete = onComplete; + this.internals.onComplete = onComplete; }, /** @@ -272,7 +272,7 @@ dbmigrate.prototype = { */ setCustomCallback: function(callback) { - internals.onComplete = callback; + this.internals.onComplete = callback; }, /** @@ -283,10 +283,10 @@ dbmigrate.prototype = { if(scope) { - internals.migrationMode = scope; + this.internals.migrationMode = scope; } - internals.mode = mode || 'vc'; + this.internals.mode = mode || 'vc'; executeSeed(); }, @@ -316,7 +316,7 @@ function setDefaultArgv(isModule) { 'vcseeder-dir': internals.cwd + '/VCSeeder', 'staticseeder-dir': internals.cwd + '/Seeder', 'ignore-completed-migrations': false}) - .usage('Usage: db-migrate [up|down|reset|create|db] [[dbname/]migrationName|all] [options]') + .usage('Usage: db-migrate [up|down|reset|create|db|seed] [[dbname/]migrationName|all] [options]') .describe('env', 'The environment to run the migrations under (dev, test, prod).') .alias('e', 'env') From 46107aef5a33adebe452ad69819532756f5429ef Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Jul 2015 04:30:05 +0200 Subject: [PATCH 138/412] add recording to seeder --- lib/seeder.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/seeder.js b/lib/seeder.js index 6efbb622..d304548d 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -96,7 +96,19 @@ Seeder.prototype = { }); }, - deleteMigrationRecord: function(seed, callback) { + 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.addMigrationRecord(this.internals.matching + '/' + seed.name, onComplete); + }, + + deleteSeedRecord: function(seed, callback) { function onComplete(err) { if (err) { log.error(seed.name, err); @@ -150,6 +162,10 @@ Seeder.prototype = { return (Promise.promisify(self.up.bind(self)))(seeder.up.bind(seeder)); }) + .then(function() { + + return (Promise.promisify(self.writeSeedRecord.bind(self)))(migration); + }) .then(self.driver.endMigration.bind(self.driver)); }) .catch(function(e) { @@ -189,6 +205,10 @@ Seeder.prototype = { return (Promise.promisify(self.down.bind(self)))(seeder.down.bind(seeder)); }) + .then(function() { + + return (Promise.promisify(self.deleteSeedRecord.bind(self)))(migration); + }) .then(self.driver.endMigration.bind(self.driver)); }) From 53326f8114bddf48fefd50150f89229cb52bc60f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 23 Jul 2015 04:42:11 +0200 Subject: [PATCH 139/412] add close method to interface, change scope of internals, begin finishing api specs --- api.js | 26 ++++++++++++++------------ lib/interface/seederInterface.js | 5 +++++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/api.js b/api.js index 8b8c5a5b..7e6284d1 100644 --- a/api.js +++ b/api.js @@ -167,7 +167,7 @@ dbmigrate.prototype = { } } - executeUp(); + executeUp( this.internals ); }, /** @@ -190,7 +190,7 @@ dbmigrate.prototype = { } } - executeDown(); + executeDown( this.internals ); }, /** @@ -204,7 +204,7 @@ dbmigrate.prototype = { } this.internals.argv.count = Number.MAX_VALUE; - executeDown(); + executeDown( this.internals ); }, /** @@ -226,7 +226,7 @@ dbmigrate.prototype = { } this.internals.argv._.push(migrationName); - executeCreate(); + executeCreate( this.internals ); }, /** @@ -236,6 +236,7 @@ dbmigrate.prototype = { this.internals.argv._.push(dbname); this.internals.mode = 'create'; + executeDB( this.internals ); }, /** @@ -245,6 +246,7 @@ dbmigrate.prototype = { this.internals.argv._.push(dbname); this.internals.mode = 'drop'; + executeDB( this.internals ); }, /** @@ -295,7 +297,7 @@ dbmigrate.prototype = { */ run: function() { - run(); + run( this.internals ); } @@ -440,7 +442,7 @@ function loadConfig() { } } -function executeCreate() { +function executeCreate( internals ) { var folder, path; if(internals.argv._.length === 0) { @@ -649,7 +651,7 @@ function onComplete(migrator, originalErr) { }); } -function run() { +function run( internals ) { var action = internals.argv._.shift(), folder = action.split(':'); @@ -657,7 +659,7 @@ function run() { switch(action) { case 'create': - executeCreate(); + executeCreate( internals ); break; case 'up': case 'down': @@ -682,9 +684,9 @@ function run() { } if(action == 'up') { - executeUp(); + executeUp( internals ); } else { - executeDown(); + executeDown( internals ); } break; @@ -697,14 +699,14 @@ function run() { else { internals.mode = folder[1]; - executeDB(); + executeDB( internals ); } break; case 'seed': internals.mode = folder[1] || 'vc'; internals.migrationMode = folder[2]; - executeSeed(); + executeSeed( internals ); break; default: diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index a3f21976..47ba6ded 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -183,6 +183,11 @@ var SeederInterface = { switchDatabase: function() { + arguments[arguments.length - 1]('not implemented'); + }, + + close: function() { + arguments[arguments.length - 1]('not implemented'); } From d4f70a55a555b6756446d007076e0f3b802c7f48 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 24 Jul 2015 23:49:35 +0200 Subject: [PATCH 140/412] add missing parameters and fix some cs --- api.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api.js b/api.js index 7e6284d1..0f47aef7 100644 --- a/api.js +++ b/api.js @@ -76,7 +76,7 @@ function registerEvents() { process.exit(1); }); - process.on("unhandledRejection", function(reason, promise) { + process.on('unhandledRejection', function(reason, promise) { log.error(reason.stack); process.exit(1); }); @@ -289,7 +289,7 @@ dbmigrate.prototype = { } this.internals.mode = mode || 'vc'; - executeSeed(); + executeSeed( this.internals ); }, /** @@ -405,7 +405,7 @@ function setDefaultArgv(isModule) { internals.matching = ''; internals.verbose = internals.argv.verbose; global.verbose = internals.verbose; - internals.notransactions = internals.argv['non-transactional'] + internals.notransactions = internals.argv['non-transactional']; internals.dryRun = internals.argv['dry-run']; global.dryRun = internals.dryRun; @@ -523,7 +523,7 @@ function createSqlFiles() { }); } -function executeUp() { +function executeUp( internals ) { if(!internals.argv.count) { internals.argv.count = Number.MAX_VALUE; @@ -548,7 +548,7 @@ function executeUp() { }); } -function executeDown() { +function executeDown( internals ) { if(!internals.argv.count) { log.info('Defaulting to running 1 down migration.'); @@ -570,7 +570,7 @@ function executeDown() { }); } -function executeDB() { +function executeDB( internals ) { if(internals.argv._.length > 0) { internals.argv.dbname = internals.argv._.shift().toString(); @@ -617,7 +617,7 @@ function executeDB() { } -function executeSeed() { +function executeSeed( internals ) { if(internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); From 2100eaa702e704a78d185de41bbb1a3f33912cba Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 25 Jul 2015 00:13:47 +0200 Subject: [PATCH 141/412] rename executeCreate to executeCreateMigration --- api.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api.js b/api.js index 0f47aef7..a753934d 100644 --- a/api.js +++ b/api.js @@ -226,7 +226,7 @@ dbmigrate.prototype = { } this.internals.argv._.push(migrationName); - executeCreate( this.internals ); + executeCreateMigration( this.internals ); }, /** @@ -442,7 +442,7 @@ function loadConfig() { } } -function executeCreate( internals ) { +function executeCreateMigration( internals ) { var folder, path; if(internals.argv._.length === 0) { @@ -659,7 +659,7 @@ function run( internals ) { switch(action) { case 'create': - executeCreate( internals ); + executeCreateMigration( internals ); break; case 'up': case 'down': From c5383756dfc6b73f2302bb8b61a1930faa96cd20 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 26 Jul 2015 17:10:06 +0200 Subject: [PATCH 142/412] add callback to createmigration api method --- api.js | 62 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/api.js b/api.js index a753934d..704713ea 100644 --- a/api.js +++ b/api.js @@ -442,7 +442,7 @@ function loadConfig() { } } -function executeCreateMigration( internals ) { +function executeCreateMigration( internals, callback ) { var folder, path; if(internals.argv._.length === 0) { @@ -483,13 +483,15 @@ function executeCreateMigration( internals ) { } var migration = new Migration(internals.argv.title + (shouldCreateCoffeeFile() ? '.coffee' : '.js'), path, new Date(), templateType); index.createMigration(migration, function(err, migration) { - assert.ifError(err); - log.info(util.format('Created migration at %s', migration.path)); + if ( _assert( err, callback ) ) { + + log.info(util.format('Created migration at %s', migration.path)); + } }); }); - if (shouldCreateSqlFiles()) { - createSqlFiles(); + if (shouldCreateSqlFiles( internals )) { + createSqlFiles( internals, callback ); } } @@ -501,28 +503,60 @@ function shouldCreateCoffeeFile() { return internals.argv['coffee-file'] || config['coffee-file']; } -function createSqlFiles() { +function createSqlFiles( internals, callback ) { var sqlDir = internals.argv['migrations-dir'] + '/sqls'; createMigrationDir(sqlDir, function(err) { if (err) { log.error('Failed to create migration directory at ', sqlDir, err); - process.exit(1); + + if( typeof(callback) !== 'function' ) { + + process.exit(1); + } + else { + + return callback( err ); + } } var templateTypeDefaultSQL = Migration.TemplateType.DEFAULT_SQL; var migrationUpSQL = new Migration(internals.argv.title + '-up.sql', sqlDir, new Date(), templateTypeDefaultSQL); index.createMigration(migrationUpSQL, function(err, migration) { - assert.ifError(err); - log.info(util.format('Created migration up sql file at %s', migration.path)); - }); - var migrationDownSQL = new Migration(internals.argv.title + '-down.sql', sqlDir, new Date(), templateTypeDefaultSQL); - index.createMigration(migrationDownSQL, function(err, migration) { - assert.ifError(err); - log.info(util.format('Created migration down sql file at %s', migration.path)); + if( _assert( err, callback ) ) { + + log.info(util.format('Created migration up sql file at %s', migration.path)); + + var migrationDownSQL = new Migration(internals.argv.title + '-down.sql', sqlDir, new Date(), templateTypeDefaultSQL); + index.createMigration(migrationDownSQL, function(err, migration) { + if( _assert( err, callback ) ) { + + log.info(util.format('Created migration down sql file at %s', migration.path)); + callback(); + } + }); + } }); }); } +function _assert( err, callback ) { + if ( err ) { + + if (typeof(callback) === 'function') { + + callback(err); + return false; + } + else { + + assert.ifError(err); + return false; + } + } + + return true; +} + function executeUp( internals ) { if(!internals.argv.count) { From d7ca78c8ba83ad4a929b966262bf90a7f9fb3213 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 27 Jul 2015 02:59:09 +0200 Subject: [PATCH 143/412] change oncomplete function to handle optional callback --- api.js | 43 ++++++++++++++++++++++++++++++++++++------- lib/seeder.js | 4 ++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/api.js b/api.js index 704713ea..69f9204a 100644 --- a/api.js +++ b/api.js @@ -14,7 +14,7 @@ var pkginfo = require('pkginfo')(module, 'version'); var dotenv = require('dotenv'); -//global declaration for detection like it's done in umigrate +//global declaration for detection like it's done in umigrate //deprecated dbm = require( './' ); //deprecated async = require( 'async' ); //deprecated @@ -651,7 +651,7 @@ function executeDB( internals ) { } -function executeSeed( internals ) { +function executeSeed( internals, callback ) { if(internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); @@ -665,23 +665,52 @@ function executeSeed( internals ) { assert.ifError(err); seeder.seedDir = path.resolve(internals.argv[(internals.mode !== 'static') ? 'vcseeder-dir': 'staticseeder-dir']); - seeder.seed(internals.argv, internals.onComplete.bind(this, seeder)); + + if(internals.mode !== 'static') { + + seeder.seed(internals.argv, internals.onComplete.bind(this, seeder)); + } + else { + + seeder.driver.createMigrationsTable(function(err) { + if( _assert( err, callback ) ) { + + seeder.seed(internals.argv, internals.onComplete.bind(this, seeder, callback)); + } + }); + } }); } internals.onComplete = onComplete; -function onComplete(migrator, originalErr) { +function onComplete(migrator, callback, originalErr) { + + if( typeof(callback) !== 'function' ) { + originalErr = callback; + } migrator.driver.close(function(err) { - assert.ifError(originalErr); - assert.ifError(err); - log.info('Done'); + if( ( err || originalErr ) && typeof(callback) === 'function' ) { + + callback({ err: err, originalErr: originalErr }); + return; + } + else { + + assert.ifError(originalErr); + assert.ifError(err); + log.info('Done'); + } if (internals.argv['force-exit']) { log.verbose('Forcing exit'); process.exit(0); } + + if( typeof( callback ) === 'function' ) { + callback(); + } }); } diff --git a/lib/seeder.js b/lib/seeder.js index d304548d..c0fd905e 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -16,6 +16,10 @@ Seeder = function (driver, seedsDir, versionControlled, intern) { Seeder.prototype = { + createSeedTable: function(callback) { + this._driver.createSeedTable(callback); + }, + seed: function (argv, callback) { if (this.isVC) From 1d48bca160189b3bec77779faca21942546c6050 Mon Sep 17 00:00:00 2001 From: Sergei Besedkov Date: Tue, 28 Jul 2015 18:06:41 +0300 Subject: [PATCH 144/412] Added index length support for MySQL --- lib/driver/mysql.js | 21 ++++++++++++++++++++- test/driver/mysql_test.js | 15 ++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 1b2c15f2..6789f12b 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -296,7 +296,26 @@ var MysqlDriver = Base.extend({ if (!Array.isArray(columns)) { columns = [columns]; } - var sql = util.format('ALTER TABLE `%s` ADD %s INDEX `%s` (`%s`)', tableName, (unique ? 'UNIQUE ' : ''), indexName, columns.join('`, `')); + + var columnsList = []; + for (var columnIndex in columns) { + var column = columns[columnIndex]; + var columnSpec = ''; + + if (typeof(column) === 'object' && column.name) { + columnSpec = util.format('`%s`%s', + column.name, + (column.length ? util.format('(%s)', parseInt(column.length)) : '') + ); + } else if (typeof(column) === 'string') { + columnSpec = util.format('`%s`', column); + } else + return callback(new Error('Invalid column specification')); + + columnsList.push(columnSpec); + } + + var sql = util.format('ALTER TABLE `%s` ADD %s INDEX `%s` (%s)', tableName, (unique ? 'UNIQUE ' : ''), indexName, columnsList.join(', ')); return this.runSql(sql).nodeify(callback); }, diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index c2b341bf..fe29af1a 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -349,7 +349,9 @@ driver.connect(config, internals, function(err, db) { id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, title: { type: dataType.STRING } }, function() { - db.addIndex('event', 'event_title', 'title', this.callback.bind(this, null)); + db.addIndex('event', 'event_title', 'title', function() { + db.addIndex('event', 'event_title_sub_part', { name: 'title', length: 8 }, this.callback.bind(this, null)); + }.bind(this)); }.bind(this)); }, @@ -384,13 +386,20 @@ driver.connect(config, internals, function(err, db) { }.bind(this)); }, - 'with additional index': function(err, indexes) { + 'with additional indexes': function(err, indexes) { assert.isNotNull(indexes); - assert.equal(indexes.length, 2); + assert.equal(indexes.length, 3); + var index = findByName(indexes, 'event_title'); assert.equal(index.getName(), 'event_title'); assert.equal(index.getTableName(), 'event'); assert.equal(index.getColumnName(), 'title'); + + var indexSubpart = findByName(indexes, 'event_title_sub_part'); + assert.equal(indexSubpart.getName(), 'event_title_sub_part'); + assert.equal(indexSubpart.getTableName(), 'event'); + assert.equal(indexSubpart.getColumnName(), 'title'); + assert.equal(indexSubpart.meta.sub_part, '8'); } } } From 519179baeca94bf1b8b622a292b46a1dd5a0b94c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 28 Jul 2015 23:31:21 +0200 Subject: [PATCH 145/412] add creation of seeder table and callbacks --- api.js | 7 +++---- lib/migrator.js | 4 ++-- lib/seeder.js | 6 +++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/api.js b/api.js index 69f9204a..44077968 100644 --- a/api.js +++ b/api.js @@ -401,7 +401,7 @@ function setDefaultArgv(isModule) { internals.ignoreCompleted = internals.argv['ignore-completed-migrations']; internals.migrationTable = internals.argv.table; - internals.seedsTable = internals.argv['seeds-table']; + internals.seedTable = internals.argv['seeds-table']; internals.matching = ''; internals.verbose = internals.argv.verbose; global.verbose = internals.verbose; @@ -666,13 +666,12 @@ function executeSeed( internals, callback ) { seeder.seedDir = path.resolve(internals.argv[(internals.mode !== 'static') ? 'vcseeder-dir': 'staticseeder-dir']); - if(internals.mode !== 'static') { + if(internals.mode === 'static') { seeder.seed(internals.argv, internals.onComplete.bind(this, seeder)); } else { - - seeder.driver.createMigrationsTable(function(err) { + seeder.createSeedsTable(function(err) { if( _assert( err, callback ) ) { seeder.seed(internals.argv, internals.onComplete.bind(this, seeder, callback)); diff --git a/lib/migrator.js b/lib/migrator.js index 47a38715..76dad364 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -16,8 +16,8 @@ Migrator = function(driver, migrationsDir, empty, intern) { }; Migrator.prototype = { - createMigrationTable: function(callback) { - this._driver.createMigrationTable(callback); + createMigrationsTable: function(callback) { + this._driver.createMigrationsTable(callback); }, writeMigrationRecord: function(migration, callback) { diff --git a/lib/seeder.js b/lib/seeder.js index c0fd905e..736ab455 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -16,8 +16,8 @@ Seeder = function (driver, seedsDir, versionControlled, intern) { Seeder.prototype = { - createSeedTable: function(callback) { - this._driver.createSeedTable(callback); + createSeedsTable: function(callback) { + this._driver.createSeedsTable(callback); }, seed: function (argv, callback) { @@ -154,7 +154,7 @@ Seeder.prototype = { } return Promise.resolve(toRun).each(function(seeder) { - +console.log('hello') log.verbose('preparing to run up seeder:', seeder.name); return self.driver.startMigration() From ef64c0454b854d8f14d01f0abac6063e7e6c8440 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 29 Jul 2015 00:56:54 +0200 Subject: [PATCH 146/412] delete and add seeds --- api.js | 2 +- lib/migration.js | 2 +- lib/migrator.js | 2 +- lib/seed.js | 8 ++++---- lib/seeder.js | 27 ++++++++++++++------------- lib/skeleton.js | 4 ++-- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/api.js b/api.js index 44077968..9b7afa91 100644 --- a/api.js +++ b/api.js @@ -686,7 +686,7 @@ internals.onComplete = onComplete; function onComplete(migrator, callback, originalErr) { if( typeof(callback) !== 'function' ) { - originalErr = callback; + originalErr = originalErr || callback; } migrator.driver.close(function(err) { diff --git a/lib/migration.js b/lib/migration.js index 5de39a84..b62118a3 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -207,7 +207,7 @@ Migration.prototype.write = function(callback) { fs.writeFile(this.path, this.getTemplate(), callback); }; -Migration.loadFromFilesystem = function(dir, 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; } diff --git a/lib/migrator.js b/lib/migrator.js index 76dad364..fe64e17f 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -72,7 +72,7 @@ Migrator.prototype = { upToBy: function(partialName, count, callback) { var self = this; - Migration.loadFromFilesystem(self.migrationsDir, function(err, allMigrations) { + 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) { diff --git a/lib/seed.js b/lib/seed.js index 05541678..83af03c3 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -99,7 +99,7 @@ var Seed = Skeleton.extend({ } }); -Seed.loadFromFilesystem = function(dir, callback) { +Seed.loadFromFilesystem = function(dir, internals, callback) { log.verbose('loading seeds from dir', dir); fs.readdir(dir, function(err, files) { if (err) { callback(err); return; } @@ -112,13 +112,13 @@ Seed.loadFromFilesystem = function(dir, callback) { return filesRegEx.test(file); }); var seeds = files.sort().map(function(file) { - return new Seed(path.join(dir, file)); + return new Seed(path.join(dir, file), internals); }); callback(null, seeds); }); }; -Seed.loadFromDatabase = function(dir, driver, callback) { +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; } @@ -128,7 +128,7 @@ Seed.loadFromDatabase = function(dir, driver, callback) { 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)); + return new Seed(path.join(dir, result.name), internals); }); callback(null, seeds); diff --git a/lib/seeder.js b/lib/seeder.js index 736ab455..e583b591 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -12,6 +12,7 @@ Seeder = function (driver, seedsDir, versionControlled, intern) { this.seedDir = seedsDir; this.isVC = versionControlled; internals = intern; + this.internals = intern; }; Seeder.prototype = { @@ -67,7 +68,7 @@ Seeder.prototype = { var self = this; - return Seed.loadFromFilesystem(self.seedDir, function(err, allSeeds) { + return Seed.loadFromFilesystem(self.seedDir, self.internals, function(err, allSeeds) { if (err) { @@ -109,7 +110,7 @@ Seeder.prototype = { } callback(err); } - this._driver.addMigrationRecord(this.internals.matching + '/' + seed.name, onComplete); + this._driver.addSeedRecord(this.internals.matching + '/' + seed.name, onComplete); }, deleteSeedRecord: function(seed, callback) { @@ -138,11 +139,11 @@ Seeder.prototype = { var self = this; - return Seed.loadFromFilesystem(self.seedDir, function(err, allMigrations) { + return Seed.loadFromFilesystem(self.seedDir, self.internals, function(err, allMigrations) { if (err) { callback(err); return; } - return Seed.loadFromDatabase(self.seedDir, self._driver, function(err, completedSeeds) { + 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); @@ -154,13 +155,13 @@ Seeder.prototype = { } return Promise.resolve(toRun).each(function(seeder) { -console.log('hello') + log.verbose('preparing to run up seeder:', seeder.name); - return self.driver.startMigration() + return self._driver.startMigration() .then(function() { - var setup = seeder.setup(); + var setup = seeder.setup(); if(typeof(setup) === 'function') setup(internals.seederOptions); @@ -168,9 +169,9 @@ console.log('hello') }) .then(function() { - return (Promise.promisify(self.writeSeedRecord.bind(self)))(migration); + return (Promise.promisify(self.writeSeedRecord.bind(self)))(seeder); }) - .then(self.driver.endMigration.bind(self.driver)); + .then(self._driver.endMigration.bind(self.driver)); }) .catch(function(e) { @@ -184,7 +185,7 @@ console.log('hello') downToBy: function(count, callback) { var self = this; - Seed.loadFromDatabase(self.seedDir, self._driver, function(err, completedSeeds) { + Seed.loadFromDatabase(self.seedDir, self._driver, self.internals, function(err, completedSeeds) { if (err) { return callback(err); } var toRun = dbmUtil.filterDown(completedSeeds, count); @@ -199,7 +200,7 @@ console.log('hello') log.verbose('preparing to run down seeder:', seeder.name); - return self.driver.startMigration() + return self._driver.startMigration() .then(function() { var setup = seeder.setup(); @@ -211,9 +212,9 @@ console.log('hello') }) .then(function() { - return (Promise.promisify(self.deleteSeedRecord.bind(self)))(migration); + return (Promise.promisify(self.deleteSeedRecord.bind(self)))(seeder); }) - .then(self.driver.endMigration.bind(self.driver)); + .then(self._driver.endMigration.bind(self.driver)); }) .catch(function(e) { diff --git a/lib/skeleton.js b/lib/skeleton.js index b1a7803c..4a545937 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -73,8 +73,8 @@ var Skeleton = Class.extend({ }, parseName: function(path) { - var match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); - return match[1]; + var match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); + return match[1]; }, parseTitle: parseTitle, From b923a8fdc39c2fa177fb4714bee87cccd91ba57e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 30 Jul 2015 22:11:19 +0200 Subject: [PATCH 147/412] fix typo and add extending to driver --- lib/driver/mysql.js | 7 + lib/interface/migratorInterface.js | 211 +++++++---------------------- lib/seeder.js | 2 + lib/util.js | 8 +- 4 files changed, 59 insertions(+), 169 deletions(-) diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index 1b2c15f2..312749c1 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -550,11 +550,18 @@ var MysqlDriver = Base.extend({ Promise.promisifyAll(MysqlDriver); +function dummy() { + + arguments[arguments.length - 1]('not implemented'); +} + exports.connect = function(config, intern, callback) { var db; internals = intern; + internals.interfaces.SeederInterface._makeParamArgs = dummy; + if (typeof(mysql.createConnection) === 'undefined') { db = config.db || new mysql.createClient(config); } else { diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index ad56d4cd..aec98adb 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -4,217 +4,98 @@ * This includes all DDL methods provided by SQL naturally. */ -function MigratorInterface() { +function dummy() { + arguments[arguments.length - 1]('not implemented'); } -MigratorInterface.prototype = { - - checkDBMS: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - - createDatabase: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - switchDatabase: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - dropDatabase: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - bindForeignKey: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - createTable: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - dropTable: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - renameTable: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - addColumn: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - removeColumn: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - renameColumn: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - changeColumn: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - addIndex: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - removeIndex: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - addForeignKey: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - removeForeignKey: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - createMigrationsTable: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - createSeedsTable: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - normalizeColumnSpec: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - runSql: function() { +function MigratorInterface() { - arguments[arguments.length - 1]('not implemented'); - }, +} - createColumnDef: function() { +MigratorInterface.prototype = { - arguments[arguments.length - 1]('not implemented'); - }, + checkDBMS: dummy, - mapDataType: function() { + createDatabase: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + switchDatabase: dummy, - createColumnConstraint: function() { + dropDatabase: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + bindForeignKey: dummy, - _makeParamArgs: function() { + createTable: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + dropTable: dummy, - recurseCallbackArray: function() { + renameTable: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + addColumn: dummy, - allLoadedMigrations: function() { + removeColumn: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + renameColumn: dummy, - allLoadedSeeds: function() { + changeColumn: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + addIndex: dummy, - addSeedRecord: function() { + removeIndex: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + addForeignKey: dummy, - startMigration: function() { + removeForeignKey: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + createMigrationsTable: dummy, - endMigration: function() { + createSeedsTable: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + normalizeColumnSpec: dummy, - addMigrationRecord: function() { + runSql: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + createColumnDef: dummy, - deleteMigration: function() { + mapDataType: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + createColumnConstraint: dummy, - deleteSeed: function() { + _makeParamArgs: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + recurseCallbackArray: dummy, - quoteDDLArr: function() { + allLoadedMigrations: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + allLoadedSeeds: dummy, - quoteArr: function() { + addSeedRecord: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + startMigration: dummy, - escapeString: function() { + endMigration: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + addMigrationRecord: dummy, - escape: function() { + deleteMigration: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + deleteSeed: dummy, - escapeDDL: function() { + quoteDDLArr: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + quoteArr: dummy, - checkDBMS: function() { + escapeString: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + escape: dummy, - all: function() { + escapeDDL: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + checkDBMS: dummy, - close: function() { + all: dummy, - arguments[arguments.length - 1]('not implemented'); - } + close: dummy }; diff --git a/lib/seeder.js b/lib/seeder.js index e583b591..348af5f3 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -7,7 +7,9 @@ var SeederInterface = require( './interface/seederInterface.js'); var internals = {}; Seeder = function (driver, seedsDir, versionControlled, intern) { + SeederInterface.extending = intern.interfaces.SeederInterface; this.driver = dbmUtil.reduceToInterface( driver, SeederInterface ); + console.log(this.driver); this._driver = driver; this.seedDir = seedsDir; this.isVC = versionControlled; diff --git a/lib/util.js b/lib/util.js index 5d68b791..30ea79a1 100644 --- a/lib/util.js +++ b/lib/util.js @@ -106,14 +106,14 @@ exports.reduceToInterface = function(db, originInterface) { } } - for(var prop in originInterface.extend) { + for(var prop in originInterface.extending) { - if (typeof db[prop] === "function" && - typeof originInterface.extend[prop] === "function") { + if (typeof db[prop] === 'function' && + typeof originInterface.extending[prop] === 'function') { Interface[prop] = db[prop]; } - else if(typeof originInterface[prop] === "function") { + else if(typeof originInterface[prop] === 'function') { Interface[prop] = originInterface.extend[prop]; } From b59921e18117819bfbcd9f2ccc9d3a3990c95537 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 31 Jul 2015 15:23:57 +0200 Subject: [PATCH 148/412] only call callback if defined --- api.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api.js b/api.js index 9b7afa91..8215b001 100644 --- a/api.js +++ b/api.js @@ -531,7 +531,8 @@ function createSqlFiles( internals, callback ) { if( _assert( err, callback ) ) { log.info(util.format('Created migration down sql file at %s', migration.path)); - callback(); + if( typeof( callback ) === 'function' ) + callback(); } }); } From 0d3d89181d98d188ac066783d6598704f6082dc4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 1 Aug 2015 15:13:43 +0200 Subject: [PATCH 149/412] edit test to use new callback and d fix the currently sporadically appearing race conditions within the test --- api.js | 13 +++++++--- test/integration/api_test.js | 50 ++++++++++++++++++------------------ 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/api.js b/api.js index 8215b001..06275ef2 100644 --- a/api.js +++ b/api.js @@ -218,15 +218,19 @@ dbmigrate.prototype = { /** * Creates a correctly formatted migration */ - create: function(migrationName, scope) { + create: function(migrationName, scope, callback) { - if(scope) { + if( typeof( scope ) === 'function' ) { + + callback = scope; + } + else if(scope) { this.internals.migrationMode = scope; } this.internals.argv._.push(migrationName); - executeCreateMigration( this.internals ); + executeCreateMigration( this.internals, callback ); }, /** @@ -493,6 +497,9 @@ function executeCreateMigration( internals, callback ) { if (shouldCreateSqlFiles( internals )) { createSqlFiles( internals, callback ); } + else { + callback(); + } } function shouldCreateSqlFiles() { diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 18368a00..66abaef3 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -26,44 +26,44 @@ vows.describe('api').addBatch({ config = { cwd: process.cwd() + '/test/integration' }; var api = DBMigrate.getInstance(true, config); - api.create('test'); + api.create( 'test', function( err ) { + process.argv.push('up'); - process.argv.push('up'); + process.exit = function(err) { - process.exit = function(err) { + var ret = called; + called = true; - var ret = called; - called = true; + process.exit = process_exit; - process.exit = process_exit; + if(err) + process.exit.apply(arguments); - if(err) - process.exit.apply(arguments); + if(!ret) + this.callback(false); + }.bind(this); - if(!ret) - this.callback(false); - }.bind(this); + var dbmigrate = DBMigrate.getInstance(true, config, function(migrator) { - var dbmigrate = DBMigrate.getInstance(true, config, function(migrator) { + var ret = called; + called = true; - var ret = called; - called = true; + migrator.driver.close(function(err) { + delete migrator.driver; + }); - migrator.driver.close(function(err) { - delete migrator.driver; - }); + process.exit = process_exit; - process.exit = process_exit; + if(!ret) + this.callback(true); + }.bind(this)); - if(!ret) - this.callback(true); - }.bind(this)); + dbmigrate.setConfigParam('force-exit', true); + dbmigrate.silence(true); - dbmigrate.setConfigParam('force-exit', true); - dbmigrate.silence(true); - - dbmigrate.run(); + dbmigrate.run(); + }.bind( this ) ); }, teardown: function() { From 818ec9332a94e6efa185b1cf2e95987ed1a8e8ec Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 1 Aug 2015 15:52:44 +0200 Subject: [PATCH 150/412] add dummy functionality to api, remove method from driver and generalized it --- api.js | 35 ++++++++++++++++++++++++++-- lib/driver/base.js | 9 ++++--- lib/driver/mysql.js | 57 --------------------------------------------- lib/migrator.js | 9 ++----- lib/seeder.js | 1 - 5 files changed, 41 insertions(+), 70 deletions(-) diff --git a/api.js b/api.js index 06275ef2..02f420ae 100644 --- a/api.js +++ b/api.js @@ -72,7 +72,7 @@ function dbmigrate(isModule, options, callback) { function registerEvents() { process.on('uncaughtException', function(err) { - log.error(err.stack); + log.error(err.stack, err); process.exit(1); }); @@ -296,6 +296,29 @@ dbmigrate.prototype = { executeSeed( this.internals ); }, + /** + * Execute the down function of currently executed seeds. + */ + undoSeed: function( specification, scope ) { + + if(arguments.length > 0) + { + if(typeof(specification) === 'number') { + + this.internals.argv.count = specification; + + if(scope) { + + this.internals.migrationMode = scope; + } + } + else if( typeof(specification) === 'string' ) { + + this.internals.migrationMode = scope; + } + } + }, + /** * Executes the default routine. */ @@ -776,7 +799,15 @@ function run( internals ) { internals.mode = folder[1] || 'vc'; internals.migrationMode = folder[2]; - executeSeed( internals ); + + if( internals.argv._[0] === 'down' ) { + + internals.argv._.shift(); + } + else { + + executeSeed( internals ); + } break; default: diff --git a/lib/driver/base.js b/lib/driver/base.js index 18fa439c..0e6a9ba5 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -182,7 +182,9 @@ module.exports = Base = Class.extend({ var pkSql = ''; if (primaryKeyColumns.length > 1) { - pkSql = util.format(', PRIMARY KEY (%s)', this.quoteDDLArr(primaryKeyColumns).join(', ')); + pkSql = util.format(', PRIMARY KEY (%s)', + this.quoteDDLArr(primaryKeyColumns).join(', ')); + } else { columnDefOptions.emitPrimaryKey = true; } @@ -199,7 +201,8 @@ module.exports = Base = Class.extend({ foreignKeys.push(constraint.foreignKey); } - var sql = util.format('CREATE TABLE %s "%s" (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql); + var sql = util.format('CREATE TABLE %s %s (%s%s)', ifNotExistsSql, + this.escapeDDL(tableName), columnDefs.join(', '), pkSql); return this.runSql(sql) .then(function() @@ -555,7 +558,7 @@ module.exports = Base = Class.extend({ escapeDDL: function(str) { - return this._escapeDDL + this.escape(str) + this._escapeDDL; + return this._escapeDDL + str + this._escapeDDL; } }); diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index cb56a50b..af17c2ec 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -161,63 +161,6 @@ var MysqlDriver = Base.extend({ return { foreignKey: cb, constraints: constraint.join(' ') }; }, - createTable: function(tableName, options, callback) { - log.verbose('creating table:', tableName); - var columnSpecs = options, - tableOptions = {}; - - if (options.columns !== undefined) { - columnSpecs = options.columns; - delete options.columns; - tableOptions = options; - } - - var ifNotExistsSql = ""; - if(tableOptions.ifNotExists) { - ifNotExistsSql = "IF NOT EXISTS"; - } - - var primaryKeyColumns = []; - var columnDefOptions = { - emitPrimaryKey: false - }; - - for (var columnName in columnSpecs) { - var columnSpec = this.normalizeColumnSpec(columnSpecs[columnName]); - columnSpecs[columnName] = columnSpec; - if (columnSpec.primaryKey) { - primaryKeyColumns.push(columnName); - } - } - - var pkSql = ''; - if (primaryKeyColumns.length > 1) { - pkSql = util.format(', PRIMARY KEY (`%s`)', primaryKeyColumns.join('`, `')); - } else { - columnDefOptions.emitPrimaryKey = true; - } - - var columnDefs = []; - var foreignKeys = []; - - for (var columnName in columnSpecs) { - var columnSpec = columnSpecs[columnName]; - var constraint = this.createColumnDef(columnName, columnSpec, columnDefOptions, tableName); - - columnDefs.push(constraint.constraints); - if (constraint.foreignKey) - foreignKeys.push(constraint.foreignKey); - } - - var sql = util.format('CREATE TABLE %s `%s` (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql); - - return this.runSql(sql) - .then(function() - { - - return this.recurseCallbackArray(foreignKeys); - }.bind(this)).nodeify(callback); - }, renameTable: function(tableName, newTableName, callback) { var sql = util.format('RENAME TABLE `%s` TO `%s`', tableName, newTableName); diff --git a/lib/migrator.js b/lib/migrator.js index fe64e17f..3868731b 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -132,7 +132,7 @@ Migrator.prototype = { log.verbose('preparing to run down migration:', migration.name); - return self.driver.startMigration() + return self._driver.startMigration() .then(function() { var setup = migration.setup(); @@ -144,13 +144,8 @@ Migrator.prototype = { .then(function() { return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); }) - .then(self.driver.endMigration.bind(self.driver)); + .then(self._driver.endMigration.bind(self.driver)); }) - .catch(function(e) { - - throw e; - }) - .nodeify(callback); }); } }; diff --git a/lib/seeder.js b/lib/seeder.js index 348af5f3..c0f3d7df 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -9,7 +9,6 @@ var internals = {}; Seeder = function (driver, seedsDir, versionControlled, intern) { SeederInterface.extending = intern.interfaces.SeederInterface; this.driver = dbmUtil.reduceToInterface( driver, SeederInterface ); - console.log(this.driver); this._driver = driver; this.seedDir = seedsDir; this.isVC = versionControlled; From 6eef04caf4a67fbe00e2934aaf74f890a9d1cb1f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 1 Aug 2015 15:57:59 +0200 Subject: [PATCH 151/412] fix functionality of promise each --- lib/migrator.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 3868731b..e6b79868 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -105,11 +105,13 @@ Migrator.prototype = { }) .then(self.driver.endMigration.bind(self.driver)); }) + .then(function() { + callback(); + }) .catch(function(e) { throw e; - }) - .nodeify(callback); + }); }); }); @@ -130,9 +132,11 @@ Migrator.prototype = { return Promise.resolve(toRun).each(function(migration) { + console.log('again'); + log.verbose('preparing to run down migration:', migration.name); - return self._driver.startMigration() + return self.driver.startMigration() .then(function() { var setup = migration.setup(); @@ -144,7 +148,14 @@ Migrator.prototype = { .then(function() { return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); }) - .then(self._driver.endMigration.bind(self.driver)); + .then(self.driver.endMigration.bind(self.driver)) + }) + .then(function() { + callback(); + }) + .catch(function(e) { + + throw e; }) }); } From 300771be747d8cdfd182113f2ed865dff14b83f3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 1 Aug 2015 16:01:42 +0200 Subject: [PATCH 152/412] change pg transaction functions to real promises --- lib/driver/pg.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index e9611f06..baac228d 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -21,7 +21,7 @@ var PgDriver = Base.extend({ if(!internals.notransactions) { - return Promise.promisify(this.runSql.bind(this))('BEGIN;').nodeify(cb); + return this.runSql('BEGIN;').nodeify(cb); } else return Promise.resolve().nodeify(cb); @@ -31,7 +31,7 @@ var PgDriver = Base.extend({ if(!internals.notransactions) { - return Promise.promisify(this.runSql.bind(this))('COMMIT;').nodeify(cb); + return this.runSql('COMMIT;').nodeify(cb); } else return Promise.resolve(null).nodeify(cb); From 37a3176ad0e7d33c38b05732e93100a711e3be43 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 1 Aug 2015 16:49:34 +0200 Subject: [PATCH 153/412] move insert from mysql to base driver, generalized quote usage and minimize needed standard functions fixes #272 --- api.js | 8 +-- lib/driver/base.js | 100 ++++++++++++++++++++++++++++++------ lib/driver/mysql.js | 114 ----------------------------------------- lib/driver/pg.js | 16 +++--- test/driver/pg_test.js | 3 +- 5 files changed, 100 insertions(+), 141 deletions(-) diff --git a/api.js b/api.js index 02f420ae..bccaee31 100644 --- a/api.js +++ b/api.js @@ -68,11 +68,10 @@ function dbmigrate(isModule, options, callback) { internals.seederOptions = { dbmigrate: internals.dbm }; } - function registerEvents() { process.on('uncaughtException', function(err) { - log.error(err.stack, err); + log.error(err.stack); process.exit(1); }); @@ -521,7 +520,10 @@ function executeCreateMigration( internals, callback ) { createSqlFiles( internals, callback ); } else { - callback(); + if( typeof(callback) === 'function' ) { + + callback(); + } } } diff --git a/lib/driver/base.js b/lib/driver/base.js index 0e6a9ba5..ac13bef6 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -222,7 +222,8 @@ module.exports = Base = Class.extend({ if (options.ifExists) { ifExistsSql = 'IF EXISTS'; } - var sql = util.format('DROP TABLE %s "%s"', ifExistsSql, tableName); + var sql = util.format('DROP TABLE %s %s', ifExistsSql, + this.escapeDDL(tableName)); return this.runSql(sql).nodeify(callback); }, @@ -233,8 +234,10 @@ module.exports = Base = Class.extend({ addColumn: function(tableName, columnName, columnSpec, callback) { - var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), {}, tableName); - var sql = util.format('ALTER TABLE "%s" ADD COLUMN %s', tableName, def.constraints); + var def = this.createColumnDef(columnName, + this.normalizeColumnSpec(columnSpec), {}, tableName); + var sql = util.format('ALTER TABLE %s ADD COLUMN %s', + this.escapeDDL(tableName), def.constraints); return this.runSql(sql) .then(function() @@ -289,31 +292,90 @@ module.exports = Base = Class.extend({ return this.runSql(sql).nodeify(callback); }, - insert: function(tableName, columnNameArray, valueArray, callback) { + insert: function(tableName, valueArray, callback) { + + var columnNameArray; + + if( arguments.length > 3 ) { + + log.warn( 'This calling convention of insert is deprecated' ); + columnNameArray = valueArray; + valueArray = callback; + callback = arguments[3]; + } + else { + + var names; + if( util.isArray(valueArray) ) { + names = Object.keys(valueArray[0]); + } + else { + names = Object.keys(valueArray); + } + + for( var i = 0; i < names.length; ++i ) { + + columnNameArray[names[i]] = names[i]; + } + } + if (columnNameArray.length !== valueArray.length) { return callback(new Error('The number of columns does not match the number of values.')); } - var sql = util.format('INSERT INTO ' + this._escapeDDL + '%s' + this._escapeDDL + ' ', tableName); + var sql = util.format('INSERT INTO %s ', this.escapeDDL(tableName)); var columnNames = '('; - var values = 'VALUES ('; + var values = 'VALUES '; + var values_part = []; for (var index in columnNameArray) { - columnNames += columnNameArray[index]; + columnNames += this.escapeDDL(columnNameArray[index]); - if (typeof(valueArray[index]) === 'string') { - values += this._escapeString + this.escape(valueArray[index]) + this._escapeString; - } else { - values += valueArray[index]; + if( util.isArray(valueArray) && typeof(valueArray[0]) === 'object') { + + for( var i = 0; i < valueArray.length; ++i ) { + + values_part[i] = values_part[i] || ''; + + if (typeof(valueArray[i][index]) === 'string') { + values_part[i] += this.escapeString(valueArray[i][index]); + } else { + values_part[i] += valueArray[i][index]; + } + } } + else { - if (index != columnNameArray.length - 1) { - columnNames += ","; - values += ","; + if (typeof(valueArray[index]) === 'string') { + values_part += this.escapeString(valueArray[index]); + } else { + values_part += valueArray[index]; + } + + values_part += ","; + } + + columnNames += ","; + } + + + if( util.isArray(valueArray) && typeof(valueArray[0]) === 'object' ) { + + for( var i = 0; i < values_part.length; ++i ) { + + values += '(' + values_part[i].slice(0, -1) + '),'; } + + values = values.slice(0, -1); + } + else { + + values += '(' + values_part.slice(0, -1) + ')'; } - sql += columnNames + ') '+ values + ');'; + sql += columnNames.slice(0, -1) + ') ' + + values + ';'; + return this.runSql(sql).nodeify(callback); }, @@ -383,11 +445,15 @@ module.exports = Base = Class.extend({ }, addMigrationRecord: function (name, callback) { - this.runSql('INSERT INTO "' + internals.migrationTable + '" (name, run_on) VALUES (?, ?)', [name, new Date()], callback); + this.runSql('INSERT INTO ' + this.escapeDDL(internals.migrationTable) + + ' (' + this.escapeDDL('name') + ', ' + this.escapeDDL('run_on') + + ') VALUES (?, ?)', [name, new Date()], callback); }, addSeedRecord: function (name, callback) { - this.runSql('INSERT INTO "' + internals.seedTable + '" (name, run_on) VALUES (?, ?)', [name, new Date()], callback); + this.runSql('INSERT INTO ' + this.escapeDDL(internals.seedTable) + + ' (' + this.escapeDDL('name') + ', ' + this.escapeDDL('run_on') + + ') VALUES (?, ?)', [name, new Date()], callback); }, startMigration: function(cb){ return Promise.resolve().nodeify(cb); }, diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js index af17c2ec..a429301f 100644 --- a/lib/driver/mysql.js +++ b/lib/driver/mysql.js @@ -167,19 +167,6 @@ var MysqlDriver = Base.extend({ return this.runSql(sql).nodeify(callback); }, - addColumn: function(tableName, columnName, columnSpec, callback) { - var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), {}, tableName); - var sql = util.format('ALTER TABLE `%s` ADD COLUMN %s', tableName, def.constraints); - this.runSql(sql) - .then(function() - { - if(def.foreignKey) - return def.foreignKey(); - else - return Promise.resolve(); - }).nodeify(callback); - }, - createDatabase: function(dbName, options, callback) { var spec = '', @@ -262,92 +249,6 @@ var MysqlDriver = Base.extend({ return this.runSql(sql).nodeify(callback); }, - insert: function(tableName, valueArray, callback) { - - var columnNameArray; - - if( arguments.length > 3 ) { - - log.warn( 'This calling convention of insert is deprecated' ); - columnNameArray = valueArray; - valueArray = callback; - callback = arguments[3]; - } - else { - - var names; - if( util.isArray(valueArray) ) { - names = Object.keys(valueArray[0]); - } - else { - names = Object.keys(valueArray); - } - - for( var i = 0; i < names.length; ++i ) { - - columnNameArray[names[i]] = names[i]; - } - } - - if (columnNameArray.length !== valueArray.length) { - return callback(new Error('The number of columns does not match the number of values.')); - } - - var sql = util.format('INSERT INTO `%s` ', tableName); - var columnNames = '('; - var values = 'VALUES '; - var values_part = []; - - for (var index in columnNameArray) { - columnNames += '`' + columnNameArray[index] + '`'; - - if( util.isArray(valueArray) && typeof(valueArray[0]) === 'object') { - - for( var i = 0; i < valueArray.length; ++i ) { - - values_part[i] = values_part[i] || ''; - - if (typeof(valueArray[i][index]) === 'string') { - values_part[i] += "'" + this.escape(valueArray[i][index]) + "'"; - } else { - values_part[i] += valueArray[i][index]; - } - } - } - else { - - if (typeof(valueArray[index]) === 'string') { - values_part += "'" + this.escape(valueArray[index]) + "'"; - } else { - values_part += valueArray[index]; - } - - values_part += ","; - } - - columnNames += ","; - } - - - if( util.isArray(valueArray) && typeof(valueArray[0]) === 'object' ) { - - for( var i = 0; i < values_part.length; ++i ) { - - values += '(' + values_part[i].slice(0, -1) + '),'; - } - - values = values.slice(0, -1); - } - else { - - values += '(' + values_part.slice(0, -1) + ')'; - } - - sql += columnNames.slice(0, -1) + ') ' + - values + ';'; - return this.runSql(sql).nodeify(callback); - }, - removeIndex: function(tableName, indexName, callback) { // tableName is optional for other drivers, but required for mySql. So, check the args to ensure they are valid if (arguments.length === 2 && typeof(indexName) === 'function') { @@ -364,21 +265,6 @@ var MysqlDriver = Base.extend({ return this.runSql(sql).nodeify(callback); }, - dropTable: function(tableName, options, callback) { - if (arguments.length < 3) { - callback = options; - options = {}; - } - - var ifExistsSql = ''; - if (options.ifExists) { - ifExistsSql = 'IF EXISTS'; - } - var sql = util.format('DROP TABLE %s `%s`', ifExistsSql, tableName); - - return this.runSql(sql).nodeify(callback); - }, - renameColumn: function(tableName, oldColumnName, newColumnName, callback) { var self = this, columnTypeSql = util.format("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s' AND COLUMN_NAME = '%s'", tableName, oldColumnName); diff --git a/lib/driver/pg.js b/lib/driver/pg.js index baac228d..9a253dca 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -386,16 +386,20 @@ var PgDriver = Base.extend({ return this.runSql(sql).nodeify(callback); }, - insert: function(tableName, columnNameArray, valueArray, callback) { - columnNameArray = columnNameArray.map(function(columnName) { - return (columnName.charAt(0) != '"') ? '"' + columnName + '"' : columnName; - }); + insert: function() { + + var index = 1; + + if( arguments.length > 3 ) { + + index = 2; + } - valueArray = valueArray.map(function(value) { + arguments[index] = arguments[index].map(function(value) { return 'string' === typeof value ? value : JSON.stringify(value); }); - return this._super(tableName, columnNameArray, valueArray, callback); + return this._super.apply(this, arguments); }, runSql: function() { diff --git a/test/driver/pg_test.js b/test/driver/pg_test.js index fea255e9..55b60ba8 100644 --- a/test/driver/pg_test.js +++ b/test/driver/pg_test.js @@ -4,11 +4,13 @@ var assert = require('assert'); var dbmeta = require('db-meta'); var dataType = require('../../lib/data_type'); var driver = require('../../lib/driver'); +var log = require('../..//lib/log.js'); var config = require('../db.config.json').pg; var internals = {}; internals.migrationTable = 'migrations'; +log.silence(true); driver.connect(config, internals, function(err, db) { vows.describe('pg').addBatch({ @@ -718,4 +720,3 @@ function findByName(columns, name) { } return null; } - From f4c794f1009e4bcd108bc5384f5498231c9efd4e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 1 Aug 2015 16:50:06 +0200 Subject: [PATCH 154/412] remove debug messages --- lib/migrator.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index e6b79868..f3ad9782 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -132,8 +132,6 @@ Migrator.prototype = { return Promise.resolve(toRun).each(function(migration) { - console.log('again'); - log.verbose('preparing to run down migration:', migration.name); return self.driver.startMigration() From e71497128a748348ee5f521516e1bd54aa0c84fa Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 1 Aug 2015 18:26:20 +0200 Subject: [PATCH 155/412] add correct function while extending --- lib/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index 30ea79a1..172d17ab 100644 --- a/lib/util.js +++ b/lib/util.js @@ -113,9 +113,9 @@ exports.reduceToInterface = function(db, originInterface) { Interface[prop] = db[prop]; } - else if(typeof originInterface[prop] === 'function') { + else if(typeof originInterface.extending[prop] === 'function') { - Interface[prop] = originInterface.extend[prop]; + Interface[prop] = originInterface.extending[prop]; } } From b3c04211c37a6aaecc3a0e39d8df18af23f40514 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 1 Aug 2015 20:22:23 +0200 Subject: [PATCH 156/412] handle promise on latest require level --- lib/driver/base.js | 2 +- lib/migrator.js | 4 ++-- lib/seed.js | 8 +++++-- lib/seeder.js | 4 ++-- lib/skeleton.js | 53 ++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 58 insertions(+), 13 deletions(-) diff --git a/lib/driver/base.js b/lib/driver/base.js index ac13bef6..47424bb2 100644 --- a/lib/driver/base.js +++ b/lib/driver/base.js @@ -294,7 +294,7 @@ module.exports = Base = Class.extend({ insert: function(tableName, valueArray, callback) { - var columnNameArray; + var columnNameArray = {}; if( arguments.length > 3 ) { diff --git a/lib/migrator.js b/lib/migrator.js index f3ad9782..99710125 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -56,7 +56,7 @@ Migrator.prototype = { up: function(funcOrOpts, callback) { if (dbmUtil.isFunction(funcOrOpts)) { - funcOrOpts(this.driver, callback); + return funcOrOpts(this.driver, callback); } else { this.upToBy(funcOrOpts.destination, funcOrOpts.count, callback); } @@ -64,7 +64,7 @@ Migrator.prototype = { down: function(funcOrOpts, callback) { if (dbmUtil.isFunction(funcOrOpts)) { - funcOrOpts(this.driver, callback); + return funcOrOpts(this.driver, callback); } else { this.downToBy(funcOrOpts.count, callback); } diff --git a/lib/seed.js b/lib/seed.js index 83af03c3..eefc6789 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -69,7 +69,9 @@ var Seed = Skeleton.extend({ } else { - this._up(db, callback); + return Promise.resolve(this._up(db, callback)).then(function() { + callback(); + }); } }, @@ -94,7 +96,9 @@ var Seed = Skeleton.extend({ } else { - this._down(db, callback); + return Promise.resolve(this._up(db, callback)).then(function() { + callback(); + }); } } }); diff --git a/lib/seeder.js b/lib/seeder.js index c0f3d7df..00ce8a04 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -32,7 +32,7 @@ Seeder.prototype = { up: function(funcOrOpts, callback) { if (dbmUtil.isFunction(funcOrOpts)) { - funcOrOpts(this.driver, false, callback); + return funcOrOpts(this.driver, false, callback); } else { this.upToBy(funcOrOpts.destination, funcOrOpts.count, callback); } @@ -40,7 +40,7 @@ Seeder.prototype = { down: function(funcOrOpts, callback) { if (dbmUtil.isFunction(funcOrOpts)) { - funcOrOpts(this.driver, callback); + return funcOrOpts(this.driver, callback); } else { this.downToBy(funcOrOpts.count, callback); } diff --git a/lib/skeleton.js b/lib/skeleton.js index 4a545937..8e5d092c 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -1,5 +1,6 @@ var path = require('path'); var inflection = require('./inflection'); +var Promise = require('bluebird'); var lpad = require('./util').lpad; var Class = require('./class'); @@ -53,19 +54,59 @@ var Skeleton = Class.extend({ }, _up: function() { - return require(this.path).up.apply(this, arguments); + var params = arguments; + + return new Promise(function(resolve, reject) { + var r = function( err ) { + if( err ) + reject( err ); + else + resolve(); + }; + + params[ params.length ] = r; + + Promise.resolve(require(this.path).up.apply(this, params)) + .then(function( Promise ) { + if( Promise !== undefined ) { + resolve(); + } + }).catch(function(err) { + reject( err ); + }); + }.bind(this)); }, _down: function() { - return require(this.path).down.apply(this, arguments); + var params = arguments; + + return new Promise(function(resolve, reject) { + var r = function( err ) { + if( err ) + reject( err ); + else + resolve(); + }; + + params[ params.length ] = r; + + Promise.resolve(require(this.path).down.apply(this, params)) + .then(function( Promise ) { + if( Promise !== undefined ) { + resolve(); + } + }).catch(function(err) { + reject( err ); + }); + }.bind(this)); }, - up: function(db, callback) { - this._up(db, callback); + up: function(db) { + return this._up(db); }, - down: function(db, callback) { - this._down(db, callback); + down: function(db) { + return this._down(db); }, setup: function() { From 50b0b3a28b0b02d003b4870d2833766d560cfb1e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 2 Aug 2015 14:18:52 +0200 Subject: [PATCH 157/412] switch internal handling to promisises and finish global handling of promises and keeping callback backward compatibility resolves #239 --- lib/migrator.js | 4 +-- lib/seed.js | 95 ++++++++++++++++++++++++++++++------------------- lib/seeder.js | 56 +++++++++++++++++------------ lib/skeleton.js | 56 +++++++++++++++++++++-------- 4 files changed, 136 insertions(+), 75 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 99710125..78a850ab 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -97,7 +97,7 @@ Migrator.prototype = { if(typeof(setup) === 'function') setup(self.internals.migrationOptions); - return (Promise.promisify(self.up.bind(self)))(migration.up.bind(migration)); + return self.up(migration.up.bind(migration)); }) .then(function() { @@ -141,7 +141,7 @@ Migrator.prototype = { if(typeof(setup) === 'function') setup(self.internals.migrationOptions); - return (Promise.promisify(self.down.bind(self)))(migration.down.bind(migration)); + return self.down(migration.down.bind(migration)); }) .then(function() { return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); diff --git a/lib/seed.js b/lib/seed.js index eefc6789..7ce5e10d 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -42,64 +42,87 @@ var Seed = Skeleton.extend({ if(static) { var seed = require(this.path); + var cb_executed = false; - seed.truncate(db, function(err) { + return new Promise(function(resolve, reject) { + var r = function( err ) { + if ( cb_executed === false ) { - if(err) { + cb_executed = true; - console.log('Error while truncating static seed.'); - callback(err); - } - else { + if( err ) { - seed.seed(db, function(err) { + log.error('Error while truncating static seed.'); + reject( err ); + } + else + resolve(); + } + }; - if(err) { + Promise.resolve(seed.truncate.apply(this, [ db, r ])) + .then(function( Promise ) { + if( Promise !== undefined && cb_executed === false ) { - console.log('Error while seeding static seed.'); - callback(err); + cb_executed = true + resolve(); } - else { + }).catch(function(err) { + + if ( cb_executed === false ) { - callback(null); + cb_executed = true; + reject( err ); } }); - } - }); - } - else { - return Promise.resolve(this._up(db, callback)).then(function() { - callback(); - }); - } - }, + }.bind(this)).then(function() { - down: function(db, static, callback) { + var seed_executed = false; - if(static) { + return new Promise(function(resolve, reject) { + var r = function( err ) { + if ( seed_executed === false ) { - var seed = require(this.path); + seed_executed = true; + + if( err ) { - seed.truncate(db, function(err) { + log.error('Error while seeding static seed.'); + reject( err ); + } + else + resolve(); + } + }; - if(err) { + Promise.resolve(seed.seed.apply( this, [ db, r ] )) + .then(function( Promise ) { + if( Promise !== undefined && seed_executed === false ) { - console.log('Error while truncating static seed.'); - callback(err); - } - else { + seed_executed = true + resolve(); + } + }).catch(function(err) { - callback(null); - } - }); + if ( seed_executed === false ) { + + seed_executed = true; + reject( err ); + } + }); + }); + }.bind(this)); } else { - return Promise.resolve(this._up(db, callback)).then(function() { - callback(); - }); + return this._up(db); } + }, + + down: function(db, static, callback) { + + return this._down(db); } }); diff --git a/lib/seeder.js b/lib/seeder.js index 00ce8a04..a527790d 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -88,17 +88,25 @@ Seeder.prototype = { return Promise.resolve(toRun).each(function(seeder) { log.verbose('preparing to run up seeder:', seeder.name); - return self.driver.startMigration() + var setup = seeder.setup(); + if(typeof(setup) === 'function') + setup(self.internals.seederOptions); + + return self._driver.startMigration() .catch(callback) .then(function() { - return (Promise.promisify(seeder.up.bind(seeder)))(self.driver, true); + return seeder.up(self.driver, true); }); }) - .catch(callback) - .then(self.driver.endMigration.bind(self.driver)) - .catch(callback) - .nodeify(callback); + .then(self._driver.endMigration.bind(self.driver)) + .then(function() { + callback(); + }) + .catch(function(e) { + + throw e; + }) }); }, @@ -164,21 +172,23 @@ Seeder.prototype = { var setup = seeder.setup(); if(typeof(setup) === 'function') - setup(internals.seederOptions); + setup(self.internals.seederOptions); - return (Promise.promisify(self.up.bind(self)))(seeder.up.bind(seeder)); + return self.up(seeder.up.bind(seeder)); }) .then(function() { return (Promise.promisify(self.writeSeedRecord.bind(self)))(seeder); }) - .then(self._driver.endMigration.bind(self.driver)); - }) - .catch(function(e) { + .then(self._driver.endMigration.bind(self.driver)) + .then(function() { + callback(); + }) + .catch(function(e) { - throw e; - }) - .nodeify(callback); + throw e; + }); + }); }); }); @@ -207,21 +217,23 @@ Seeder.prototype = { var setup = seeder.setup(); if(typeof(setup) === 'function') - setup(internals.seederOptions); + setup(self.internals.seederOptions); - return (Promise.promisify(self.down.bind(self)))(seeder.down.bind(seeder)); + return self.down(seeder.down.bind(seeder)); }) .then(function() { return (Promise.promisify(self.deleteSeedRecord.bind(self)))(seeder); }) - .then(self._driver.endMigration.bind(self.driver)); + .then(self._driver.endMigration.bind(self.driver)) + .then(function() { + callback(); + }) + .catch(function(e) { - }) - .catch(function(e) { - throw e; - }) - .nodeify(callback); + throw e; + }); + }); }); } }; diff --git a/lib/skeleton.js b/lib/skeleton.js index 8e5d092c..2f8f5912 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -56,47 +56,73 @@ var Skeleton = Class.extend({ _up: function() { var params = arguments; + var cb_executed = false; + return new Promise(function(resolve, reject) { var r = function( err ) { - if( err ) - reject( err ); - else - resolve(); + if ( cb_executed === false ) { + + cb_executed = true; + + if( err ) + reject( err ); + else + resolve(); + } }; - params[ params.length ] = r; + params[ params.length++ ] = r; Promise.resolve(require(this.path).up.apply(this, params)) .then(function( Promise ) { - if( Promise !== undefined ) { + if( Promise !== undefined && cb_executed === false ) { + + cb_executed = true; resolve(); } }).catch(function(err) { - reject( err ); + + if ( cb_executed === false ) { + + cb_executed = true; + reject( err ); + } }); }.bind(this)); }, _down: function() { var params = arguments; + var cb_executed = false; return new Promise(function(resolve, reject) { var r = function( err ) { - if( err ) - reject( err ); - else - resolve(); - }; + if ( cb_executed === false ) { - params[ params.length ] = r; + cb_executed = true; + + if( err ) + reject( err ); + else + resolve(); + } + }; + params[ params.length++ ] = r; Promise.resolve(require(this.path).down.apply(this, params)) .then(function( Promise ) { - if( Promise !== undefined ) { + if( Promise !== undefined && cb_executed === false ) { + + cb_executed = true resolve(); } }).catch(function(err) { - reject( err ); + + if ( cb_executed === false ) { + + cb_executed = true; + reject( err ); + } }); }.bind(this)); }, From 1091d467dbf75abd0019bc0ebad05b1b9e1548f4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 2 Aug 2015 22:04:03 +0200 Subject: [PATCH 158/412] change scope --- lib/migration.js | 6 +++--- lib/relation.js | 15 ++++++--------- lib/seed.js | 6 +++--- lib/skeleton.js | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index b62118a3..5514b8c9 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -29,16 +29,16 @@ var Migration = Skeleton.extend({ this.name = this.formatName(this.title, this.date); this.path = this.formatPath(arguments[1], this.name); this.templateType = arguments[3]; - internals = arguments[4]; + 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); - internals = arguments[1]; + this.internals = arguments[1]; } - this._super(internals); + this._super(this.internals); } }); diff --git a/lib/relation.js b/lib/relation.js index b6c25541..45b94c34 100644 --- a/lib/relation.js +++ b/lib/relation.js @@ -1,25 +1,22 @@ var fs = require('fs'), log = require('./log'); - -var relations = {}; - function Relation() { - + this.relations = {}; } Relation.prototype = { addRelation: function(table, column, relatedTable, relatedColumn) { - relations[table] = relations[table] || {}; - relations[table][column] = relatedColumn; + this.relations[table] = this.relations[table] || {}; + this.relations[table][column] = relatedColumn; }, getRelation: function(table, column) { - return relations[table][column]; + return this.relations[table][column]; }, fromJson: function(file) { @@ -31,7 +28,7 @@ Relation.prototype = { toJson: function(file) { - fs.writeFile(file, JSON.stringify(relations), function(err) { + fs.writeFile(file, JSON.stringify(this.relations), function(err) { if(err) { throw err; @@ -43,6 +40,6 @@ Relation.prototype = { clearRelations: function() { - relations = {}; + this.relations = {}; } }; diff --git a/lib/seed.js b/lib/seed.js index 7ce5e10d..54a7bec6 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -25,16 +25,16 @@ var Seed = Skeleton.extend({ this.name = this.formatName(this.title, this.date); this.path = this.formatPath(arguments[1], this.name); this.templateType = arguments[3]; - internals = arguments[4]; + 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); - internals = arguments[1]; + this.internals = arguments[1]; } - this._super(internals); + this._super(this.internals); }, up: function(db, static, callback) { diff --git a/lib/skeleton.js b/lib/skeleton.js index 2f8f5912..c10d83ac 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -50,7 +50,7 @@ function parseTitle(name) { var Skeleton = Class.extend({ init: function(intern) { - internals = intern; + this.internals = intern; }, _up: function() { From a3db821f737b012ddcbbd486eccaae37cbfea656 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 5 Aug 2015 01:11:33 +0200 Subject: [PATCH 159/412] update keywords and add remove to seederinterface, use dummy instead of function body --- LICENSE | 1 + README.md | 1 + lib/interface/seederInterface.js | 78 ++++++++------------------------ package.json | 28 ++++++++++-- 4 files changed, 46 insertions(+), 62 deletions(-) diff --git a/LICENSE b/LICENSE index db39a866..6e52d1bd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,4 @@ +Copyright (c) 2015 Tobias Gurtzick Copyright (c) 2013 Jeff Kunkle Permission is hereby granted, free of charge, to any person obtaining diff --git a/README.md b/README.md index 4a9af065..8f287a22 100644 --- a/README.md +++ b/README.md @@ -817,6 +817,7 @@ and adjust appropriate to setup configuration for your database instances. (The MIT License) +Copyright (c) 2015 Tobias Gurtzick Copyright (c) 2013 Jeff Kunkle Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index 47ba6ded..7ca290ae 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -114,82 +114,44 @@ function lookup(options) { return Promise.settle(lookups); } -var SeederInterface = { - - lookup: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - insert: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - delete: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - runSql: function() { +function dummy() { - arguments[arguments.length - 1]('not implemented'); - }, - - buildWhereClause: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - quoteDDLArr: function() { - - arguments[arguments.length - 1]('not implemented'); - }, - - quoteArr: function() { + arguments[arguments.length - 1]('not implemented'); +} - arguments[arguments.length - 1]('not implemented'); - }, +var SeederInterface = { - escapeString: function() { + lookup: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + insert: dummy, - escape: function() { + delete: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + runSql: dummy, - escapeDDL: function() { + buildWhereClause: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + quoteDDLArr: dummy, - checkDBMS: function() { + quoteArr: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + escapeString: dummy, - update: function() { + escape: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + escapeDDL: dummy, - truncate: function() { + checkDBMS: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + update: dummy, - switchDatabase: function() { + truncate: dummy, - arguments[arguments.length - 1]('not implemented'); - }, + switchDatabase: dummy, - close: function() { + remove: dummy, - arguments[arguments.length - 1]('not implemented'); - } + close: dummy }; diff --git a/package.json b/package.json index e6ae01b4..11faf4c5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "db-migrate", "description": "Database migration framework for node.js", - "author": "Jeff Kunkle", + "author": "Tobias Gurtick", "bin": "./bin/db-migrate", "keywords": [ "database", @@ -9,19 +9,39 @@ "migrate", "migration", "sqlite", - "mysql" + "mysql", + "pg", + "postgre", + "sql", + "migrations", + "db-migrate", + "postgresql", + "extensible", + "expandable", + "nosql", + "coffee", + "coffescript", + "mongo", + "mongodb", + "seed", + "seeds", + "seeder", + "migrator", + "programatic", + "programable", + "api" ], "version": "0.9.12", "engines": { "node": ">=0.6.0" }, "bugs": { - "url": "https://github.com/kunklejr/node-db-migrate/issues" + "url": "https://github.com/db-migrate/node-db-migrate/issues" }, "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/kunklejr/node-db-migrate.git" + "url": "https://github.com/db-migrate/node-db-migrate.git" }, "dependencies": { "async": "^1.0.0", From 368aea3f4afd098d68bce3689b310a483d2617c7 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 5 Aug 2015 17:46:53 +0200 Subject: [PATCH 160/412] move to travis container structure --- .travis.yml | 17 +++++++++++------ LICENSE | 1 + README.md | 1 + 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index b392970c..b4f0d463 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,17 @@ notifications: services: - mongodb +sudo: false + +cache: npm + +addons: + apt: + sources: + - mariadb-10.0 + packages: + - mariadb-server + env: - DB=mysql - DB=mariadb @@ -27,12 +38,6 @@ env: before_script: - until nc -z localhost 27017 ; do echo Waiting for MongoDB; sleep 1; done - - sh -c "if [ '$DB' = 'mariadb' ]; then sudo apt-get install python-software-properties; fi" - - sh -c "if [ '$DB' = 'mariadb' ]; then sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db; fi" - - sh -c "if [ '$DB' = 'mariadb' ]; then sudo add-apt-repository 'deb http://ftp.osuosl.org/pub/mariadb/repo/10.0/ubuntu precise main'; fi" - - sh -c "if [ '$DB' = 'mariadb' ]; then sudo apt-get update; fi" - - sh -c "if [ '$DB' = 'mariadb' ]; then sudo apt-get purge mysql*; fi" - - sh -c "if [ '$DB' = 'mariadb' ]; then sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install mariadb-server-10.0 -y; fi" - sh -c "if [ '$DB' = 'postgres92' ]; then sudo /etc/init.d/postgresql stop && sudo /etc/init.d/postgresql start 9.2; fi" - sh -c "if [ '$DB' = 'postgres93' ]; then sudo /etc/init.d/postgresql stop && sudo /etc/init.d/postgresql start 9.3; fi" - mysql -e "create database db_migrate_test;" diff --git a/LICENSE b/LICENSE index 6e52d1bd..93ccf176 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,5 @@ Copyright (c) 2015 Tobias Gurtzick + Copyright (c) 2013 Jeff Kunkle Permission is hereby granted, free of charge, to any person obtaining diff --git a/README.md b/README.md index 8f287a22..bdd95866 100644 --- a/README.md +++ b/README.md @@ -818,6 +818,7 @@ and adjust appropriate to setup configuration for your database instances. (The MIT License) Copyright (c) 2015 Tobias Gurtzick + Copyright (c) 2013 Jeff Kunkle Permission is hereby granted, free of charge, to any person obtaining From 62c021af38df859d7029722c9b1a119fcaf1894f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 5 Aug 2015 17:48:29 +0200 Subject: [PATCH 161/412] remove custom builds for postgre --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b4f0d463..9d7eb670 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,13 +33,9 @@ addons: env: - DB=mysql - DB=mariadb - - DB=postgres92 - - DB=postgres93 before_script: - until nc -z localhost 27017 ; do echo Waiting for MongoDB; sleep 1; done - - sh -c "if [ '$DB' = 'postgres92' ]; then sudo /etc/init.d/postgresql stop && sudo /etc/init.d/postgresql start 9.2; fi" - - sh -c "if [ '$DB' = 'postgres93' ]; then sudo /etc/init.d/postgresql stop && sudo /etc/init.d/postgresql start 9.3; fi" - mysql -e "create database db_migrate_test;" - createdb db_migrate_test - cp test/db.config.ci test/db.config.json From d619b9653e7d51c3701c1ef6bdcaf3ca663eb70d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 5 Aug 2015 17:56:36 +0200 Subject: [PATCH 162/412] new mariadb addon --- .travis.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9d7eb670..b24757d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,15 +24,7 @@ sudo: false cache: npm addons: - apt: - sources: - - mariadb-10.0 - packages: - - mariadb-server - -env: - - DB=mysql - - DB=mariadb + mariadb: "10.0" before_script: - until nc -z localhost 27017 ; do echo Waiting for MongoDB; sleep 1; done From fbc34cabf77281633faa01acec1032466efe1eec Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 5 Aug 2015 18:01:20 +0200 Subject: [PATCH 163/412] remove pg-native from dependencies --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 11faf4c5..bb7455d2 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "optimist": "~0.6.1", "parse-database-url": "~0.2.2", "pg": "~4.4.0", - "pg-native": "^1.8.0", "pkginfo": "~0.3.0", "resolve": "^1.1.6", "semver": "~5.0.1", From 94c6f3b16753ba23e2edf04b74ab7ad7792091c9 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 5 Aug 2015 18:26:28 +0200 Subject: [PATCH 164/412] run on all io.js versions --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index b24757d8..c99ed709 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,9 @@ language: node_js node_js: - 0.10 - 0.12 + - "iojs-1" + - "iojs-2" + - "iojs-3" - io.js notifications: From 47a5319e2788acc71146827939326a878a37e4c7 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 5 Aug 2015 18:37:00 +0200 Subject: [PATCH 165/412] activate caching --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c99ed709..e35cf933 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,10 @@ services: sudo: false -cache: npm +cache: + npm: true + directories: + - node_modules addons: mariadb: "10.0" From 7886106dea433df5b30b3858d89ee5e4574a1696 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 5 Aug 2015 19:10:53 +0200 Subject: [PATCH 166/412] remove io.js 3 for now, come back on this later --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e35cf933..a266cc0d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,6 @@ node_js: - 0.12 - "iojs-1" - "iojs-2" - - "iojs-3" - - io.js notifications: email: From 8b52c07426a5f65c3249df3b2296bdc4733e6585 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 6 Aug 2015 20:47:39 +0200 Subject: [PATCH 167/412] add example for indexes with length --- README.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bdd95866..2ccff4b4 100644 --- a/README.md +++ b/README.md @@ -617,10 +617,35 @@ __Arguments__ * tableName - table to add the index too * indexName - the name of the index -* columns - an array of column names contained in the index +* columns - an array of column names contained in the index, or as an object +definition * unique - whether the index is unique (optional, default false) * callback(err) - callback that will be invoked after adding the index +Column Object: +* name - the column name +* length - the length of index + +Adding a column with defined index length (MySQL/MariaDB only): + +```javascript +exports.up = function (db) { + return db.addIndex('pets', 'cats', [ + { name: 'color', length: 9}, + { name: 'gender', length: 1}, + 'is_insane' + ]); +} +``` + +Adding new keys to columns: + +```javascript +exports.up = function (db) { + return db.addIndex('pets', 'cats', ['color', 'gender', 'columnC']); +} +``` + ### addForeignKey Adds a foreign Key From 741aeb1ba95ff131594f297fea784501833c4e0b Mon Sep 17 00:00:00 2001 From: Mike Atkins Date: Thu, 6 Aug 2015 17:48:16 -0400 Subject: [PATCH 168/412] port changes from merge request #287 --- lib/driver/pg.js | 13 ++++++-- test/driver/pg_schema_test.js | 63 ++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 9a253dca..9009068a 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -189,7 +189,11 @@ var PgDriver = Base.extend({ }.bind(this)) .then(function() { - return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.migrationTable + "'"); + return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + + internals.migrationTable + "'" + + ((this.schema) ? + " AND table_schema = '" + this.schema + "'" : + '')); }.bind(this)) .then(function(result) { @@ -242,8 +246,11 @@ var PgDriver = Base.extend({ return this.all('SET search_path TO ' + searchPath); }.bind(this)) .then(function() { - - return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.seedTable + "'"); + return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + + internals.seedTable + "'" + + ((this.schema) ? + " AND table_schema = '" + this.schema + "'" : + '')); }.bind(this)) .then(function(result) { diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js index 79fd8e24..700bcc5b 100644 --- a/test/driver/pg_schema_test.js +++ b/test/driver/pg_schema_test.js @@ -1,4 +1,5 @@ var vows = require('vows'); +var Promise = require('bluebird'); var assert = require('assert'); var dbmeta = require('db-meta'); var pg = require('pg'); @@ -54,6 +55,67 @@ vows.describe('pg').addBatch({ } } }) +.addBatch({ + 'create schema and a public.migrations table and connect': { + topic: function() { + var callback = this.callback; + var client = new pg.Client(databaseUrl); + var query = Promise.promisify( client.query ).bind(client); + + client.connect(function (err) { + if (err) { return callback(err) }; + Promise.all([ + query('CREATE SCHEMA test_schema'), + query('CREATE TABLE migrations ()') + ]) + .then( function() { + + driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, internals, function(err, db) { + callback(err, db, client); + }); + }) + .catch( function(err) { + callback(err); + }); + }); + }, + + 'migrations table': { + topic: function(db, client) { + var callback = this.callback; + + db.createMigrationsTable(function() { + client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", function(err, result) { + callback(err, result); + }); + }); + }, + + 'is in test_schema': function(err, result) { + assert.isNull(err); + assert.isNotNull(result); + assert.equal(result.rowCount, 1); + } + }, + + teardown: function(db, client) { + var callback = this.callback; + var query = Promise.promisify(client.query).bind(client); + + Promise.all([ + query('DROP SCHEMA test_schema CASCADE'), + query('DROP TABLE migrations') + ]) + .then(function (err) { + client.end(); + callback(); + }) + .catch(function (err) { + callback(err); + }); + } + } +}) .addBatch({ 'create schema and connect': { topic: function() { @@ -98,4 +160,3 @@ vows.describe('pg').addBatch({ } } }).export(module); - From 006d883b19613c6b956b67ef04d2e8eb5185b51b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 7 Aug 2015 18:13:55 +0200 Subject: [PATCH 169/412] add missing whitespace --- lib/driver/pg.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/driver/pg.js b/lib/driver/pg.js index 9009068a..b7006790 100644 --- a/lib/driver/pg.js +++ b/lib/driver/pg.js @@ -246,6 +246,7 @@ var PgDriver = Base.extend({ return this.all('SET search_path TO ' + searchPath); }.bind(this)) .then(function() { + return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + internals.seedTable + "'" + ((this.schema) ? From ea5e90572c0d3a2fc5a43509ffbfc5129ad70a07 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 8 Aug 2015 22:16:11 +0200 Subject: [PATCH 170/412] readd iojs builds to travis yml, add osx and allow failure on iojs builds --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.travis.yml b/.travis.yml index a266cc0d..9365c43b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ node_js: - 0.12 - "iojs-1" - "iojs-2" + - "iojs-3" + - "iojs" notifications: email: @@ -17,6 +19,16 @@ notifications: on_failure: always on_start: false +os: + - linux + - osx + +matrix: + fast_finish: true + allow_failures: + - node_js: "iojs-3" + - node_js: "iojs" + services: - mongodb From eea68b75e53c9cd976e8d8406b8e3c655a654e16 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 13 Aug 2015 19:09:45 +0200 Subject: [PATCH 171/412] rewrite details of seederInterface Description. --- lib/interface/seederInterface.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index 7ca290ae..244c98f5 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -11,23 +11,25 @@ * * This functionality is provided in two ways to the user. First there are * traditional seeder. You can call them whenever you want, and how often - * you want. This results into a use case, that make seeders might only used - * for development and not to use them in a deployment process. + * you want. This might be handy when initializing a new development + * environment, but not if you want to use it for the production environment. * - * Here the second way of usage steps in, the version controlled seeders, in - * short VC Seeds. + * The second seeder type, the version controlled seeders, short VC Seeds, + * is targeting the production environment and development environment. * There is technically no big difference between them, except the following * details: * * A VC Seed can be called from a migration, via seed.execute and seed.link. A * normal seeder can not. Also A VC Seeder has a down and up function, like - * the way the migrations work, the static instead has a truncate function, - * which gets called before the seed function. As a seeder often wants to - * truncate tables or just delete data from a table. - * And last but not least, a VC Seed can not be executed if it was executed - * before, you need to roll back it first, it's in short handled like - * migrations are. A normal seed can be executed just as often as you want - * without rollback your data at any time. + * the way the migrations work, the static has a truncate function instead, + * which gets called before the seed function. This is because a seeder is + * mostly used to initialize something, a VC Seeder instead is used to + * populate changes made to the dataset and to have a clear separation of + * DDL and Data Maniupulations. + * And last but not least, a VC Seed can not be executed if it was already + * executed. You will need to roll back it first, it just acts pretty similar + * to migrations. A normal seed can be executed just as often as you want + * without the need to rollback your data. * * To note: If you rollback a migration, linked to a seeder, db-migrate will * also rollback the seed. This is also a reason why you can't rollback a From c28ab0a541cf684bf7d63c622d50f47d23ed6c02 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 15 Aug 2015 15:29:59 +0200 Subject: [PATCH 172/412] dummy object for seeder linking --- lib/migrator.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/migrator.js b/lib/migrator.js index 78a850ab..fcdbd981 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -4,6 +4,17 @@ var log = require('./log'); var Promise = require('bluebird'); var MigratorInterface = require( './interface/migratorInterface.js'); +var seed = { + + seed: function( partialName ) { + + }, + + link: function( partialName ) { + + } +}; + Migrator = function(driver, migrationsDir, empty, intern) { this.driver = dbmUtil.reduceToInterface( driver, MigratorInterface ); this._driver = driver; @@ -11,6 +22,7 @@ Migrator = function(driver, migrationsDir, empty, intern) { this.internals = intern; this.internals.migrationOptions.relation = require('./relation'); + this.internals.migrationOptions.seed = seed; Migration.exportInternals(intern); }; From 5118dced13a4594ae29d7cb365620b2a1a3777e8 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 16 Aug 2015 15:11:24 +0200 Subject: [PATCH 173/412] send a new instance of SeedLink to setup method, extending functionality of setup --- lib/migrator.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index fcdbd981..2302534f 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -4,7 +4,9 @@ var log = require('./log'); var Promise = require('bluebird'); var MigratorInterface = require( './interface/migratorInterface.js'); -var seed = { + +function SeedLink(); +var SeedLink = { seed: function( partialName ) { @@ -12,6 +14,7 @@ var seed = { link: function( partialName ) { + } }; @@ -22,7 +25,6 @@ Migrator = function(driver, migrationsDir, empty, intern) { this.internals = intern; this.internals.migrationOptions.relation = require('./relation'); - this.internals.migrationOptions.seed = seed; Migration.exportInternals(intern); }; @@ -104,10 +106,10 @@ Migrator.prototype = { return self.driver.startMigration() .then(function() { - var setup = migration.setup(); + var setup = migration.setup; if(typeof(setup) === 'function') - setup(self.internals.migrationOptions); + setup(self.internals.migrationOptions, new SeedLink()); return self.up(migration.up.bind(migration)); }) @@ -148,10 +150,10 @@ Migrator.prototype = { return self.driver.startMigration() .then(function() { - var setup = migration.setup(); + var setup = migration.setup; if(typeof(setup) === 'function') - setup(self.internals.migrationOptions); + setup(self.internals.migrationOptions, new SeedLink()); return self.down(migration.down.bind(migration)); }) From cfdd0f0c3869b503de9db2911f2d7f41f76d4c66 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 17 Aug 2015 16:05:08 +0200 Subject: [PATCH 174/412] edit templates to include extended functionality of setup function --- lib/migration.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 5514b8c9..763647bb 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -48,10 +48,12 @@ Migration.prototype.defaultCoffeeTemplate = function() { "", "dbm = undefined", "type = undefined", + "seed = undefined", "", - "exports.setup = (options) ->", + "exports.setup = (options, seedLink) ->", " dbm = options.dbmigrate;", " type = dbm.dataType;", + " seed = seedLink;", " return", "", "exports.up = (db, callback) ->", @@ -70,14 +72,16 @@ Migration.prototype.defaultJsTemplate = function() { "", "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) {", + "exports.setup = function(options, seedLink) {", " dbm = options.dbmigrate;", " type = dbm.dataType;", + " seed = seedLink;", "};", "", "exports.up = function(db, callback) {", @@ -102,6 +106,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { "", "var dbm;", "var type;", + "var seed;", "var fs = require('fs');", "var path = require('path');", "", @@ -109,9 +114,10 @@ Migration.prototype.sqlFileLoaderTemplate = function() { " * We receive the dbmigrate dependency from dbmigrate initially.", " * This enables us to not have to rely on NODE_PATH.", " */", - "exports.setup = function(options) {", + "exports.setup = function(options, seedLink) {", " dbm = options.dbmigrate;", " type = dbm.dataType;", + " seed = seedLink;", "};", "", "exports.up = function(db, callback) {", From a001ea2371cccb7d5b3bc6d0cf59f99d964669d6 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 18 Aug 2015 13:08:27 +0200 Subject: [PATCH 175/412] add missing seedLink to coffee sql template --- lib/migration.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/migration.js b/lib/migration.js index 763647bb..152bbf90 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -155,6 +155,7 @@ Migration.prototype.coffeeSqlFileLoaderTemplate = function() { "", "dbm = undefined", "type = undefined", + "seed = undefined", "fs = require 'fs'", "path = require 'path'", "", @@ -162,9 +163,10 @@ Migration.prototype.coffeeSqlFileLoaderTemplate = function() { "# We receive the dbmigrate dependency from dbmigrate initially.", "# This enables us to not have to rely on NODE_PATH.", "#", - "exports.setup = (options) ->", + "exports.setup = (options, seedLink) ->", " dbm = options.dbmigrate", " type = dbm.dataType", + " seed = seedLink", "", "", "exports.up = (db, callback) ->", From b6a3f7ba6d8ed09ae6a07e2d0daa4aa981705a7e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 18 Aug 2015 13:55:29 +0200 Subject: [PATCH 176/412] [bugfix] apply scope to create migration functionality --- api.js | 30 ++++++++++++++++++++++++++---- lib/migrator.js | 2 +- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/api.js b/api.js index bccaee31..14484674 100644 --- a/api.js +++ b/api.js @@ -469,6 +469,14 @@ function loadConfig() { } function executeCreateMigration( internals, callback ) { + var migrationsDir = internals.argv['migrations-dir'] + + if( internals.migrationMode && internals.migrationMode !== 'all' ) { + + migrationsDir = internals.argv['migrations-dir'] + '/' + + internals.migrationMode; + } + var folder, path; if(internals.argv._.length === 0) { @@ -477,9 +485,9 @@ function executeCreateMigration( internals, callback ) { process.exit(1); } - createMigrationDir(internals.argv['migrations-dir'], function(err) { + createMigrationDir(migrationsDir, function(err) { if (err) { - log.error('Failed to create migration directory at ', internals.argv['migrations-dir'], err); + log.error('Failed to create migration directory at ', migrationsDir, err); process.exit(1); } @@ -487,7 +495,7 @@ function executeCreateMigration( internals, callback ) { folder = internals.argv.title.split('/'); internals.argv.title = folder[folder.length - 2] || folder[0]; - path = internals.argv['migrations-dir']; + path = migrationsDir; if(folder.length > 1) { @@ -536,7 +544,15 @@ function shouldCreateCoffeeFile() { } function createSqlFiles( internals, callback ) { - var sqlDir = internals.argv['migrations-dir'] + '/sqls'; + var migrationsDir = internals.argv['migrations-dir'] + + if( internals.migrationMode && internals.migrationMode !== 'all' ) { + + migrationsDir = internals.argv['migrations-dir'] + '/' + + internals.migrationMode; + } + + var sqlDir = migrationsDir + '/sqls'; createMigrationDir(sqlDir, function(err) { if (err) { log.error('Failed to create migration directory at ', sqlDir, err); @@ -754,6 +770,12 @@ function run( internals ) { switch(action) { case 'create': + + if(folder[1]) + { + internals.matching = folder[1]; + internals.migrationMode = folder[1]; + } executeCreateMigration( internals ); break; case 'up': diff --git a/lib/migrator.js b/lib/migrator.js index 2302534f..c911f172 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -5,7 +5,7 @@ var Promise = require('bluebird'); var MigratorInterface = require( './interface/migratorInterface.js'); -function SeedLink(); +function SeedLink() {} var SeedLink = { seed: function( partialName ) { From 3291c635e55bb8df312f8892b80c20d3e4013052 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 18 Aug 2015 14:07:39 +0200 Subject: [PATCH 177/412] fix issue with setup function --- lib/migrator.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index c911f172..4f62f48d 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -6,7 +6,7 @@ var MigratorInterface = require( './interface/migratorInterface.js'); function SeedLink() {} -var SeedLink = { +SeedLink.prototype = { seed: function( partialName ) { @@ -106,7 +106,7 @@ Migrator.prototype = { return self.driver.startMigration() .then(function() { - var setup = migration.setup; + var setup = migration.setup(); if(typeof(setup) === 'function') setup(self.internals.migrationOptions, new SeedLink()); @@ -150,7 +150,7 @@ Migrator.prototype = { return self.driver.startMigration() .then(function() { - var setup = migration.setup; + var setup = migration.setup(); if(typeof(setup) === 'function') setup(self.internals.migrationOptions, new SeedLink()); From d71208f7cf7275c8cbcf156b2ba87307c0cb2ef5 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 19 Aug 2015 11:56:09 +0200 Subject: [PATCH 178/412] update some documentation Updating some information, which caused confusion or were left overs from the past. Updated Parts: * Creating Migrations, there have been a left over indicating that you can use a migration together with a specified dbname in way like dbname/migrationname. This is a relict from the first and never released version of migration scopes. * Scoping, rewrote parts of the description, to make it better understandable. Resolves #294 --- README.md | 40 +++++++++++++++++++++++++++++++++------- lib/log.js | 10 ++++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 2ccff4b4..b3f57dd2 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ DB-Migrate is now available to you via: ## Usage ``` -Usage: db-migrate [up|down|reset|create|db] [[dbname/]migrationName|all] [options] +Usage: db-migrate [up|down|reset|create|db] [dbname|migrationName] [options] Down migrations are run in reverse run order, so migrationName is ignored for down migrations. Use the --count option to control how many down migrations are run (default is 1). @@ -60,6 +60,25 @@ Options: ## Creating Migrations +DB-Migrate can be used to create migration boilerplates from templates. +Currently there are only basic templates available, which may change in some +future versions. + +#### Parameters + +* migration name +* flags + +#### Flags + +* coffee-file +* sql-file + +The flags --coffee-file and --sql-file can be combined to create sql-file +migrations in coffee script. + +### Examples + To create a migration, execute `db-migrate create` with a title. `node-db-migrate` will create a node module within `./migrations/` which contains the following two exports: ```javascript @@ -357,7 +376,8 @@ file settings. This is helpful for use with Heroku. ## Multiple migration scopes -You can have multiple migration scopes, which are subfolders within your migrations folder. A scope gets called like the following: +You can have multiple configurable migration scopes, which are subfolders within +your migrations folder. A scope gets called like the following: $ db-migrate up:myScope @@ -371,13 +391,19 @@ Obviously this means you **CAN'T** create scope which is named all. #### Scope Configuration -You can also configure the scope to specify a sub configuration. Currently you can only define database and schema within this config. +You can also configure the scope to specify a sub configuration. Currently you +can only define a database and schema which you want to switch to within this +config. -This config file is used to tell db-migrate to switch to the `database` or -`schema`. Databases is used for most databases, except **postgres** -which needs the schema variable. +This config file tells db-migrate to switch to the specified `database` or +`schema`. The `database` option switches to the specified database, this is what +you want most of the time. The `schema` option switches to the specified schema, +which is a concept that is related to special databases like **postgres**. +Therefor you can't use schema with any other db than **postgres**. -It's currently also not possible to switch the database over this config with **postgres**. +**Note:** It's currently only possible to switch a schema when using +**postgres**, as switching to a database means to create a complete new +connection for **postgres**. ```json { diff --git a/lib/log.js b/lib/log.js index 23c0fa3f..b2a9cd81 100644 --- a/lib/log.js +++ b/lib/log.js @@ -17,7 +17,7 @@ exports.setLogLevel = function( log ) { var keys = Object.keys(log); - for( var i = 0; i < keys.length; ++i ) { + for( var i = 0, len = keys.length; i < len ; ++i ) { logLevel = logLevel | (level[keys[i]] || 0); } @@ -87,7 +87,7 @@ exports.sql = function(sql) { var split = sql.split('?'); var logSql = split[0]; - for (var i = 1; i < split.length; ++i) { + for (var i = 1, len = split.length; i < len; ++i) { if( typeof(args[i - 1]) === 'string' ) { logSql += escape + args[i - 1] + escape + split[i]; @@ -103,9 +103,10 @@ exports.sql = function(sql) { var logSql = sql; - for( var i = 0; i < args[0].length; ++i ) { + for( var i = 0, len = args[0].length; i < len; ++i ) { - logSql = logSql.replace( '$' + (i + 1), escape + args[0][i] + escape ); + logSql = logSql.replace( '$' + (i + 1), escape + + args[0][i] + escape ); } console.log( logSql + ';' ); @@ -125,6 +126,7 @@ exports.sql = function(sql) { } } }; + exports.verbose = function() { if (global.verbose) { Array.prototype.unshift.call(arguments, '[INFO]'); From 1f76aac03a1612c09fbb849a37717bc8bb806721 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 20 Aug 2015 12:33:09 +0200 Subject: [PATCH 179/412] update dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bb7455d2..c57d00c5 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "mkdirp": "~0.5.0", "moment": "~2.10.2", "mongodb": "^2.0.23", - "mysql": "~2.8.0", + "mysql": "~2.9.0", "optimist": "~0.6.1", "parse-database-url": "~0.2.2", "pg": "~4.4.0", From 787baa09074164a8b8c3a421b691d7d254bc6ff6 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 21 Aug 2015 15:56:35 +0200 Subject: [PATCH 180/412] add callbacks to relevant api functions --- api.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/api.js b/api.js index 14484674..e9281211 100644 --- a/api.js +++ b/api.js @@ -147,7 +147,7 @@ dbmigrate.prototype = { * * Defaults to up all migrations if no count is given. */ - up: function(specification, scope) { + up: function(specification, scope, callback) { if(arguments.length > 0) { @@ -166,7 +166,7 @@ dbmigrate.prototype = { } } - executeUp( this.internals ); + executeUp( this.internals, callback ); }, /** @@ -174,7 +174,7 @@ dbmigrate.prototype = { * * Defaults to up all migrations if no count is given. */ - down: function(specification, scope) { + down: function(specification, scope, callback) { if(arguments.length > 0) { @@ -189,13 +189,13 @@ dbmigrate.prototype = { } } - executeDown( this.internals ); + executeDown( this.internals, callback ); }, /** * Executes down for all currently migrated migrations. */ - reset: function(scope) { + reset: function(scope, callback) { if(scope) { @@ -203,7 +203,7 @@ dbmigrate.prototype = { } this.internals.argv.count = Number.MAX_VALUE; - executeDown( this.internals ); + executeDown( this.internals, callback ); }, /** @@ -235,21 +235,21 @@ dbmigrate.prototype = { /** * Creates a database of the given dbname. */ - createDatabase: function(dbname) { + createDatabase: function(dbname, callback) { this.internals.argv._.push(dbname); this.internals.mode = 'create'; - executeDB( this.internals ); + executeDB( this.internals, callback ); }, /** * Drops a database of the given dbname. */ - dropDatabase: function(dbname) { + dropDatabase: function(dbname, callback) { this.internals.argv._.push(dbname); this.internals.mode = 'drop'; - executeDB( this.internals ); + executeDB( this.internals, callback ); }, /** @@ -284,7 +284,7 @@ dbmigrate.prototype = { * Seeds either the static or version controlled seeders, controlled by * the passed mode. */ - seed: function(mode, scope) { + seed: function(mode, scope, callback) { if(scope) { @@ -292,13 +292,13 @@ dbmigrate.prototype = { } this.internals.mode = mode || 'vc'; - executeSeed( this.internals ); + executeSeed( this.internals, callback ); }, /** * Execute the down function of currently executed seeds. */ - undoSeed: function( specification, scope ) { + undoSeed: function( specification, scope, callback ) { if(arguments.length > 0) { From a587be1302ba2c3cbef2ce5d71609884a6c0a450 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 22 Aug 2015 15:11:41 +0200 Subject: [PATCH 181/412] add some callbacks to api, change scope of argument initialization --- api.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/api.js b/api.js index e9281211..6de9cec0 100644 --- a/api.js +++ b/api.js @@ -55,10 +55,10 @@ function dbmigrate(isModule, options, callback) { if(typeof(isModule) === 'function') { this.internals.onComplete = isModule; - setDefaultArgv(); + setDefaultArgv(this.internals); } else - setDefaultArgv(isModule); + setDefaultArgv(this.internals, isModule); loadConfig(); index.exportInternals(internals); @@ -329,7 +329,7 @@ dbmigrate.prototype = { }; -function setDefaultArgv(isModule) { +function setDefaultArgv(internals, isModule) { internals.argv = optimist .default({ @@ -544,12 +544,12 @@ function shouldCreateCoffeeFile() { } function createSqlFiles( internals, callback ) { - var migrationsDir = internals.argv['migrations-dir'] + var migrationsDir = internals.argv['migrations-dir']; if( internals.migrationMode && internals.migrationMode !== 'all' ) { - migrationsDir = internals.argv['migrations-dir'] + '/' - + internals.migrationMode; + migrationsDir = internals.argv['migrations-dir'] + '/' + + internals.migrationMode; } var sqlDir = migrationsDir + '/sqls'; @@ -606,7 +606,7 @@ function _assert( err, callback ) { return true; } -function executeUp( internals ) { +function executeUp( internals, callback ) { if(!internals.argv.count) { internals.argv.count = Number.MAX_VALUE; @@ -626,12 +626,12 @@ function executeUp( internals ) { migrator.driver.createMigrationsTable(function(err) { assert.ifError(err); log.verbose('migration table created'); - migrator.up(internals.argv, internals.onComplete.bind(this, migrator)); + migrator.up(internals.argv, internals.onComplete.bind(this, migrator, callback)); }); }); } -function executeDown( internals ) { +function executeDown( internals, callback ) { if(!internals.argv.count) { log.info('Defaulting to running 1 down migration.'); @@ -648,12 +648,12 @@ function executeDown( internals ) { migrator.driver.createMigrationsTable(function(err) { assert.ifError(err); - migrator.down(internals.argv, internals.onComplete.bind(this, migrator)); + migrator.down(internals.argv, internals.onComplete.bind(this, migrator, callback)); }); }); } -function executeDB( internals ) { +function executeDB( internals, callback ) { if(internals.argv._.length > 0) { internals.argv.dbname = internals.argv._.shift().toString(); @@ -678,6 +678,7 @@ function executeDB( internals ) { } db.close(); + callback(); }); } else if(internals.mode === 'drop') @@ -692,6 +693,7 @@ function executeDB( internals ) { } db.close(); + callback(); }); } else @@ -717,7 +719,7 @@ function executeSeed( internals, callback ) { if(internals.mode === 'static') { - seeder.seed(internals.argv, internals.onComplete.bind(this, seeder)); + seeder.seed(internals.argv, internals.onComplete.bind(this, seeder, callback)); } else { seeder.createSeedsTable(function(err) { From 1d395bec03fa6bb04255fa397ab6f448abe4e2aa Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 23 Aug 2015 01:13:53 +0200 Subject: [PATCH 182/412] fix some formatting --- api.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api.js b/api.js index 6de9cec0..455d5bad 100644 --- a/api.js +++ b/api.js @@ -469,12 +469,12 @@ function loadConfig() { } function executeCreateMigration( internals, callback ) { - var migrationsDir = internals.argv['migrations-dir'] + var migrationsDir = internals.argv['migrations-dir']; if( internals.migrationMode && internals.migrationMode !== 'all' ) { - migrationsDir = internals.argv['migrations-dir'] + '/' - + internals.migrationMode; + migrationsDir = internals.argv['migrations-dir'] + '/' + + internals.migrationMode; } var folder, path; From 64b7b2742d7a01445f576388d4ea1ed1d1455278 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 31 Aug 2015 14:27:15 +0200 Subject: [PATCH 183/412] define linking methods --- lib/migrator.js | 19 ++++++++++++++----- lib/seeder.js | 25 ++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 4f62f48d..4f944d69 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -5,7 +5,10 @@ var Promise = require('bluebird'); var MigratorInterface = require( './interface/migratorInterface.js'); -function SeedLink() {} +function SeedLink() { + + this.links = []; +} SeedLink.prototype = { seed: function( partialName ) { @@ -14,7 +17,12 @@ SeedLink.prototype = { link: function( partialName ) { + this.links.push( partialName ); + }, + + clear: function() { + this.links = []; } }; @@ -23,6 +31,7 @@ Migrator = function(driver, migrationsDir, empty, intern) { this._driver = driver; this.migrationsDir = migrationsDir; this.internals = intern; + this.seedLink = new SeedLink(); this.internals.migrationOptions.relation = require('./relation'); @@ -109,7 +118,7 @@ Migrator.prototype = { var setup = migration.setup(); if(typeof(setup) === 'function') - setup(self.internals.migrationOptions, new SeedLink()); + setup(self.internals.migrationOptions, self.seedLink); return self.up(migration.up.bind(migration)); }) @@ -153,14 +162,14 @@ Migrator.prototype = { var setup = migration.setup(); if(typeof(setup) === 'function') - setup(self.internals.migrationOptions, new SeedLink()); + setup(self.internals.migrationOptions, self.seedLink); return self.down(migration.down.bind(migration)); }) .then(function() { return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); }) - .then(self.driver.endMigration.bind(self.driver)) + .then(self.driver.endMigration.bind(self.driver)); }) .then(function() { callback(); @@ -168,7 +177,7 @@ Migrator.prototype = { .catch(function(e) { throw e; - }) + }); }); } }; diff --git a/lib/seeder.js b/lib/seeder.js index a527790d..9a61b909 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -6,12 +6,35 @@ var SeederInterface = require( './interface/seederInterface.js'); var internals = {}; +function MigrationLink() { + + this.links = []; +} + +SeedLink.prototype = { + + migrate: function( partialName ) { + + }, + + link: function( partialName ) { + + this.links.push( partialName ); + }, + + clear: function() { + + this.links = []; + } +}; + 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; + this.migrationLink = new MigrationLink(); internals = intern; this.internals = intern; }; @@ -106,7 +129,7 @@ Seeder.prototype = { .catch(function(e) { throw e; - }) + }); }); }, From c5782d57325bfcb6479d09daf7074c60c9e9336c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 31 Aug 2015 18:27:17 +0200 Subject: [PATCH 184/412] update seeder --- lib/seeder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/seeder.js b/lib/seeder.js index 9a61b909..151a34e2 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -11,7 +11,7 @@ function MigrationLink() { this.links = []; } -SeedLink.prototype = { +MigrationLink.prototype = { migrate: function( partialName ) { From edb81def46822f09bd3abd19b0624c9422489305 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 31 Aug 2015 20:42:21 +0200 Subject: [PATCH 185/412] exclude osx from build for now --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9365c43b..6b1bd5ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,6 @@ notifications: os: - linux - - osx matrix: fast_finish: true From b6791f76c1dd063c16ba32ae18bc0080eede0df2 Mon Sep 17 00:00:00 2001 From: "guy.doulberg" Date: Wed, 2 Sep 2015 12:21:13 +0300 Subject: [PATCH 186/412] adding the feature "ignore-on-it" In this commit on create of SQL files, the user can create out of templates of files that if a ignore_on_init is set to true on db-migrate up the content of the SQL file will be ignored --- api.js | 588 ++++++++++++++++++++++++----------------------- lib/migration.js | 98 ++++++-- 2 files changed, 389 insertions(+), 297 deletions(-) diff --git a/api.js b/api.js index 455d5bad..ebe16b8b 100644 --- a/api.js +++ b/api.js @@ -15,8 +15,8 @@ var dotenv = require('dotenv'); //global declaration for detection like it's done in umigrate //deprecated -dbm = require( './' ); //deprecated -async = require( 'async' ); //deprecated +dbm = require('./'); //deprecated +async = require('async'); //deprecated var internals = {}; @@ -28,44 +28,47 @@ function dbmigrate(isModule, options, callback) { }; internals = this.internals; - if(typeof(callback) === 'function') + if (typeof(callback) === 'function') this.internals.onComplete = callback; - else if(typeof(options) === 'function') + else if (typeof(options) === 'function') this.internals.onComplete = options; this.dataType = dbm.dataType; this.version = dbm.version; - dotenv.load({ silent: true }); + dotenv.load({ + silent: true + }); registerEvents(); - if(typeof(options) === 'object') { + if (typeof(options) === 'object') { - if(typeof(options.config) === 'string') + if (typeof(options.config) === 'string') internals.configFile = options.string; - if(typeof(options.cwd) === 'string') + if (typeof(options.cwd) === 'string') internals.cwd = options.cwd; else internals.cwd = process.cwd(); - } - else + } else internals.cwd = process.cwd(); - if(typeof(isModule) === 'function') - { + if (typeof(isModule) === 'function') { this.internals.onComplete = isModule; setDefaultArgv(this.internals); - } - else + } else setDefaultArgv(this.internals, isModule); loadConfig(); index.exportInternals(internals); internals.dbm = dbm; global.dbm = dbm; //deprecated - internals.migrationOptions = { dbmigrate: internals.dbm }; - internals.seederOptions = { dbmigrate: internals.dbm }; + internals.migrationOptions = { + dbmigrate: internals.dbm + }; + internals.seederOptions = { + dbmigrate: internals.dbm + }; } function registerEvents() { @@ -84,16 +87,16 @@ function registerEvents() { dbmigrate.prototype = { /** - * Add a global defined variable to db-migrate, to enable access from - * local migrations without configuring pathes. - * - * @return boolean - */ + * Add a global defined variable to db-migrate, to enable access from + * local migrations without configuring pathes. + * + * @return boolean + */ addGlobal: function(library) { try { require(library); - } catch(e) { + } catch (e) { return false; } @@ -103,21 +106,21 @@ dbmigrate.prototype = { _internals: internals, /** - * Add a configuration option to dbmigrate. - * - * @return boolean - */ + * Add a configuration option to dbmigrate. + * + * @return boolean + */ addConfiguration: function(description, args, type) { var name = args.shift(); this.internals.argv.describe(name, description); - for(var i = 0; i < args.length; ++i) { + for (var i = 0; i < args.length; ++i) { this.internals.argv.alias(args[i], name); } - switch(type) { + switch (type) { case 'string': this.internals.argv.string(name); @@ -136,127 +139,123 @@ dbmigrate.prototype = { /** - * Resets and sets argv to a specified new argv. - */ + * Resets and sets argv to a specified new argv. + */ resetConfiguration: function(argv) { this.internals.argv = argv; }, /** - * Executes up a given number of migrations or a specific one. - * - * Defaults to up all migrations if no count is given. - */ + * Executes up a given number of migrations or a specific one. + * + * Defaults to up all migrations if no count is given. + */ up: function(specification, scope, callback) { - if(arguments.length > 0) - { - if(typeof(specification) === 'string') { + if (arguments.length > 0) { + if (typeof(specification) === 'string') { this.internals.argv.destination = specification; - } - else if(typeof(specification) === 'number') { + } else if (typeof(specification) === 'number') { this.internals.argv.count = specification; } - if(scope) { + if (scope) { this.internals.migrationMode = scope; } } - executeUp( this.internals, callback ); + executeUp(this.internals, callback); }, /** - * Executes up a given number of migrations or a specific one. - * - * Defaults to up all migrations if no count is given. - */ + * Executes up a given number of migrations or a specific one. + * + * Defaults to up all migrations if no count is given. + */ down: function(specification, scope, callback) { - if(arguments.length > 0) - { - if(typeof(arguments[0]) === 'number') { + if (arguments.length > 0) { + if (typeof(arguments[0]) === 'number') { this.internals.argv.count = arguments[0]; } - if(scope) { + if (scope) { this.internals.migrationMode = scope; } } - executeDown( this.internals, callback ); + executeDown(this.internals, callback); }, /** - * Executes down for all currently migrated migrations. - */ + * Executes down for all currently migrated migrations. + */ reset: function(scope, callback) { - if(scope) { + if (scope) { this.internals.migrationMode = scope; } this.internals.argv.count = Number.MAX_VALUE; - executeDown( this.internals, callback ); + executeDown(this.internals, callback); }, /** - * Silence the log output completely. - */ + * Silence the log output completely. + */ silence: function(isSilent) { return log.silence(isSilent); }, /** - * Creates a correctly formatted migration - */ + * Creates a correctly formatted migration + */ create: function(migrationName, scope, callback) { - if( typeof( scope ) === 'function' ) { + if (typeof(scope) === 'function') { callback = scope; - } - else if(scope) { + } else if (scope) { this.internals.migrationMode = scope; } this.internals.argv._.push(migrationName); - executeCreateMigration( this.internals, callback ); + executeCreateMigration(this.internals, callback); }, /** - * Creates a database of the given dbname. - */ + * Creates a database of the given dbname. + */ createDatabase: function(dbname, callback) { this.internals.argv._.push(dbname); this.internals.mode = 'create'; - executeDB( this.internals, callback ); + executeDB(this.internals, callback); }, /** - * Drops a database of the given dbname. - */ + * Drops a database of the given dbname. + */ dropDatabase: function(dbname, callback) { this.internals.argv._.push(dbname); this.internals.mode = 'drop'; - executeDB( this.internals, callback ); + executeDB(this.internals, callback); }, /** - * Sets a config variable to the given value. - * - * @return value - */ + * Sets a config variable to the given value. + * + * @return value + */ setConfigParam: function(param, value) { return (this.internals.argv[param] = value); @@ -264,54 +263,52 @@ dbmigrate.prototype = { /** - * Sets the callback to the default onComplete - */ + * Sets the callback to the default onComplete + */ setDefaultCallback: function() { this.internals.onComplete = onComplete; }, /** - * Let's the user customize the callback, which gets called after all - * migrations have been done. - */ + * Let's the user customize the callback, which gets called after all + * migrations have been done. + */ setCustomCallback: function(callback) { this.internals.onComplete = callback; }, /** - * Seeds either the static or version controlled seeders, controlled by - * the passed mode. - */ + * Seeds either the static or version controlled seeders, controlled by + * the passed mode. + */ seed: function(mode, scope, callback) { - if(scope) { + if (scope) { this.internals.migrationMode = scope; } this.internals.mode = mode || 'vc'; - executeSeed( this.internals, callback ); + executeSeed(this.internals, callback); }, /** - * Execute the down function of currently executed seeds. - */ - undoSeed: function( specification, scope, callback ) { + * Execute the down function of currently executed seeds. + */ + undoSeed: function(specification, scope, callback) { - if(arguments.length > 0) - { - if(typeof(specification) === 'number') { + if (arguments.length > 0) { + if (typeof(specification) === 'number') { this.internals.argv.count = specification; - if(scope) { + if (scope) { this.internals.migrationMode = scope; } - } - else if( typeof(specification) === 'string' ) { + } else if (typeof(specification) === 'string') { this.internals.migrationMode = scope; } @@ -319,11 +316,11 @@ dbmigrate.prototype = { }, /** - * Executes the default routine. - */ + * Executes the default routine. + */ run: function() { - run( this.internals ); + run(this.internals); } @@ -332,83 +329,96 @@ dbmigrate.prototype = { function setDefaultArgv(internals, isModule) { internals.argv = optimist - .default({ - verbose: false, - table: 'migrations', - 'seeds-table': 'seeds', - 'force-exit': false, - 'sql-file': false, - 'non-transactional': false, - config: internals.configFile || internals.cwd + '/database.json', - 'migrations-dir': internals.cwd + '/migrations', - 'vcseeder-dir': internals.cwd + '/VCSeeder', - 'staticseeder-dir': internals.cwd + '/Seeder', - 'ignore-completed-migrations': false}) - .usage('Usage: db-migrate [up|down|reset|create|db|seed] [[dbname/]migrationName|all] [options]') - - .describe('env', 'The environment to run the migrations under (dev, test, prod).') - .alias('e', 'env') - .string('e') - - .describe('migrations-dir', 'The directory containing your migration files.') - .alias('m', 'migrations-dir') - .string('m') - - .describe('count', 'Max number of migrations to run.') - .alias('c', 'count') - .string('c') - - .describe('dry-run', 'Prints the SQL but doesn\'t run it.') - .boolean('dry-run') - - .describe('force-exit', 'Forcibly exit the migration process on completion.') - .boolean('force-exit') - - .describe('verbose', 'Verbose mode.') - .alias('v', 'verbose') - .boolean('v') - - .alias('h', 'help') - .alias('h', '?') - .boolean('h') - - .describe('version', 'Print version info.') - .alias('i', 'version') - .boolean('version') - - .describe('config', 'Location of the database.json file.') - .string('config') - - .describe('sql-file', 'Automatically create two sql files for up and down statements in /sqls and generate the javascript code that loads them.') - .boolean('sql-file') - - .describe('coffee-file', 'Create a coffeescript migration file') - .boolean('coffee-file') - - .describe('migration-table', 'Set the name of the migration table, which stores the migration history.') - .alias('table', 'migration-table') - .alias('t', 'table') - .string('t') - - .describe('seeds-table', 'Set the name of the seeds table, which stores the seed history.') - .string('seeds-table') - - .describe('vcseeder-dir', 'Set the path to the Version Controlled Seeder directory.') - .string('vcseeder-dir') - - .describe('staticseeder-dir', 'Set the path to the Seeder directory.') - .string('staticseeder-dir') - - .describe('non-transactional', 'Explicitly disable transactions') - .boolean('non-transactional') - - .describe('ignore-completed-migrations', 'Start at the first migration') - .boolean('ignore-completed-migrations') - - .describe('log-level', 'Set the log-level, for example sql|warn') - .string('log-level') - - .argv; + .default({ + verbose: false, + table: 'migrations', + 'seeds-table': 'seeds', + 'force-exit': false, + 'sql-file': false, + 'non-transactional': false, + config: internals.configFile || internals.cwd + '/database.json', + 'migrations-dir': internals.cwd + '/migrations', + 'vcseeder-dir': internals.cwd + '/VCSeeder', + 'staticseeder-dir': internals.cwd + '/Seeder', + 'ignore-completed-migrations': false + }) + .usage( + 'Usage: db-migrate [up|down|reset|create|db|seed] [[dbname/]migrationName|all] [options]' + ) + + .describe('env', + 'The environment to run the migrations under (dev, test, prod).') + .alias('e', 'env') + .string('e') + + .describe('migrations-dir', 'The directory containing your migration files.') + .alias('m', 'migrations-dir') + .string('m') + + .describe('count', 'Max number of migrations to run.') + .alias('c', 'count') + .string('c') + + .describe('dry-run', 'Prints the SQL but doesn\'t run it.') + .boolean('dry-run') + + .describe('force-exit', 'Forcibly exit the migration process on completion.') + .boolean('force-exit') + + .describe('verbose', 'Verbose mode.') + .alias('v', 'verbose') + .boolean('v') + + .alias('h', 'help') + .alias('h', '?') + .boolean('h') + + .describe('version', 'Print version info.') + .alias('i', 'version') + .boolean('version') + + .describe('config', 'Location of the database.json file.') + .string('config') + + .describe('sql-file', + 'Automatically create two sql files for up and down statements in /sqls and generate the javascript code that loads them.' + ) + .boolean('sql-file') + + .describe('coffee-file', 'Create a coffeescript migration file') + .boolean('coffee-file') + .describe('ignore-on-init', + 'Create files that will run only if ignore-on-init in the env is set to false (currently works onlt with SQL)' + ).boolean('ignore-on-init') + + .describe('migration-table', + 'Set the name of the migration table, which stores the migration history.' + ) + .alias('table', 'migration-table') + .alias('t', 'table') + .string('t') + + .describe('seeds-table', + 'Set the name of the seeds table, which stores the seed history.') + .string('seeds-table') + + .describe('vcseeder-dir', + 'Set the path to the Version Controlled Seeder directory.') + .string('vcseeder-dir') + + .describe('staticseeder-dir', 'Set the path to the Seeder directory.') + .string('staticseeder-dir') + + .describe('non-transactional', 'Explicitly disable transactions') + .boolean('non-transactional') + + .describe('ignore-completed-migrations', 'Start at the first migration') + .boolean('ignore-completed-migrations') + + .describe('log-level', 'Set the log-level, for example sql|warn') + .string('log-level') + + .argv; if (internals.argv.version) { console.log(dbm.version); @@ -420,9 +430,9 @@ function setDefaultArgv(internals, isModule) { process.exit(1); } - if( internals.argv['log-level'] ) { + if (internals.argv['log-level']) { - log.setLogLevel( internals.argv['log-level'] ); + log.setLogLevel(internals.argv['log-level']); } internals.ignoreCompleted = internals.argv['ignore-completed-migrations']; @@ -435,7 +445,7 @@ function setDefaultArgv(internals, isModule) { internals.dryRun = internals.argv['dry-run']; global.dryRun = internals.dryRun; - if(internals.dryRun) { + if (internals.dryRun) { log.info('dry run'); } @@ -457,7 +467,7 @@ function loadConfig() { } else { config.load(internals.argv.config, internals.argv.env); } - if(internals.verbose) { + if (internals.verbose) { var current = config.getCurrent(); var s = JSON.parse(JSON.stringify(current.settings)); @@ -468,10 +478,10 @@ function loadConfig() { } } -function executeCreateMigration( internals, callback ) { +function executeCreateMigration(internals, callback) { var migrationsDir = internals.argv['migrations-dir']; - if( internals.migrationMode && internals.migrationMode !== 'all' ) { + if (internals.migrationMode && internals.migrationMode !== 'all') { migrationsDir = internals.argv['migrations-dir'] + '/' + internals.migrationMode; @@ -479,7 +489,7 @@ function executeCreateMigration( internals, callback ) { var folder, path; - if(internals.argv._.length === 0) { + if (internals.argv._.length === 0) { log.error('\'migrationName\' is required.'); optimist.showHelp(); process.exit(1); @@ -487,7 +497,8 @@ function executeCreateMigration( internals, callback ) { createMigrationDir(migrationsDir, function(err) { if (err) { - log.error('Failed to create migration directory at ', migrationsDir, err); + log.error('Failed to create migration directory at ', migrationsDir, + err); process.exit(1); } @@ -497,11 +508,11 @@ function executeCreateMigration( internals, callback ) { internals.argv.title = folder[folder.length - 2] || folder[0]; path = migrationsDir; - if(folder.length > 1) { + if (folder.length > 1) { path += '/'; - for(var i = 0; i < folder.length - 1; ++i) { + for (var i = 0; i < folder.length - 1; ++i) { path += folder[i] + '/'; } @@ -510,25 +521,28 @@ function executeCreateMigration( internals, callback ) { var templateType = Migration.TemplateType.DEFAULT_JS; if (shouldCreateSqlFiles() && shouldCreateCoffeeFile()) { templateType = Migration.TemplateType.COFFEE_SQL_FILE_LOADER; + } else if (shouldCreateSqlFiles() && shouldIgnoreOnInitFiles()) { + templateType = Migration.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT; } else if (shouldCreateSqlFiles()) { templateType = Migration.TemplateType.SQL_FILE_LOADER; } else if (shouldCreateCoffeeFile()) { templateType = Migration.TemplateType.DEFAULT_COFFEE; } - var migration = new Migration(internals.argv.title + (shouldCreateCoffeeFile() ? '.coffee' : '.js'), path, new Date(), templateType); + var migration = new Migration(internals.argv.title + ( + shouldCreateCoffeeFile() ? '.coffee' : '.js'), path, new Date(), + templateType); index.createMigration(migration, function(err, migration) { - if ( _assert( err, callback ) ) { + if (_assert(err, callback)) { log.info(util.format('Created migration at %s', migration.path)); } }); }); - if (shouldCreateSqlFiles( internals )) { - createSqlFiles( internals, callback ); - } - else { - if( typeof(callback) === 'function' ) { + if (shouldCreateSqlFiles(internals)) { + createSqlFiles(internals, callback); + } else { + if (typeof(callback) === 'function') { callback(); } @@ -539,14 +553,19 @@ function shouldCreateSqlFiles() { return internals.argv['sql-file'] || config['sql-file']; } +function shouldIgnoreOnInitFiles() { + return internals.argv['ignore-on-init'] || config[ + 'ignore-on-init']; +} + function shouldCreateCoffeeFile() { return internals.argv['coffee-file'] || config['coffee-file']; } -function createSqlFiles( internals, callback ) { +function createSqlFiles(internals, callback) { var migrationsDir = internals.argv['migrations-dir']; - if( internals.migrationMode && internals.migrationMode !== 'all' ) { + if (internals.migrationMode && internals.migrationMode !== 'all') { migrationsDir = internals.argv['migrations-dir'] + '/' + internals.migrationMode; @@ -557,29 +576,33 @@ function createSqlFiles( internals, callback ) { if (err) { log.error('Failed to create migration directory at ', sqlDir, err); - if( typeof(callback) !== 'function' ) { + if (typeof(callback) !== 'function') { process.exit(1); - } - else { + } else { - return callback( err ); + return callback(err); } } var templateTypeDefaultSQL = Migration.TemplateType.DEFAULT_SQL; - var migrationUpSQL = new Migration(internals.argv.title + '-up.sql', sqlDir, new Date(), templateTypeDefaultSQL); + var migrationUpSQL = new Migration(internals.argv.title + '-up.sql', + sqlDir, new Date(), templateTypeDefaultSQL); index.createMigration(migrationUpSQL, function(err, migration) { - if( _assert( err, callback ) ) { + if (_assert(err, callback)) { - log.info(util.format('Created migration up sql file at %s', migration.path)); + log.info(util.format('Created migration up sql file at %s', + migration.path)); - var migrationDownSQL = new Migration(internals.argv.title + '-down.sql', sqlDir, new Date(), templateTypeDefaultSQL); + var migrationDownSQL = new Migration(internals.argv.title + + '-down.sql', sqlDir, new Date(), templateTypeDefaultSQL); index.createMigration(migrationDownSQL, function(err, migration) { - if( _assert( err, callback ) ) { + if (_assert(err, callback)) { - log.info(util.format('Created migration down sql file at %s', migration.path)); - if( typeof( callback ) === 'function' ) + log.info(util.format( + 'Created migration down sql file at %s', + migration.path)); + if (typeof(callback) === 'function') callback(); } }); @@ -588,15 +611,14 @@ function createSqlFiles( internals, callback ) { }); } -function _assert( err, callback ) { - if ( err ) { +function _assert(err, callback) { + if (err) { if (typeof(callback) === 'function') { callback(err); return false; - } - else { + } else { assert.ifError(err); return false; @@ -606,126 +628,124 @@ function _assert( err, callback ) { return true; } -function executeUp( internals, callback ) { +function executeUp(internals, callback) { - if(!internals.argv.count) { + if (!internals.argv.count) { internals.argv.count = Number.MAX_VALUE; } index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Migrator, function(err, migrator) { + config: config.getCurrent().settings, + internals: internals + }, Migrator, function(err, migrator) { assert.ifError(err); - if(internals.locTitle) - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], internals.locTitle); + if (internals.locTitle) + migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], + internals.locTitle); else migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); migrator.driver.createMigrationsTable(function(err) { assert.ifError(err); log.verbose('migration table created'); - migrator.up(internals.argv, internals.onComplete.bind(this, migrator, callback)); + migrator.up(internals.argv, internals.onComplete.bind(this, + migrator, callback)); }); }); } -function executeDown( internals, callback ) { +function executeDown(internals, callback) { - if(!internals.argv.count) { + if (!internals.argv.count) { log.info('Defaulting to running 1 down migration.'); internals.argv.count = 1; } index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Migrator, function(err, migrator) { + config: config.getCurrent().settings, + internals: internals + }, Migrator, function(err, migrator) { assert.ifError(err); migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); migrator.driver.createMigrationsTable(function(err) { assert.ifError(err); - migrator.down(internals.argv, internals.onComplete.bind(this, migrator, callback)); + migrator.down(internals.argv, internals.onComplete.bind(this, + migrator, callback)); }); }); } -function executeDB( internals, callback ) { +function executeDB(internals, callback) { - if(internals.argv._.length > 0) { + if (internals.argv._.length > 0) { internals.argv.dbname = internals.argv._.shift().toString(); - } - else { + } else { log.info('Error: You must enter a database name!'); return; } - index.driver(config.getCurrent().settings, function(err, db) - { - if(internals.mode === 'create') - { - db.createDatabase(internals.argv.dbname, { ifNotExists: true }, function() - { - if(err) { + index.driver(config.getCurrent().settings, function(err, db) { + if (internals.mode === 'create') { + db.createDatabase(internals.argv.dbname, { + ifNotExists: true + }, function() { + if (err) { log.info('Error: Failed to create database!'); - } - else { + } else { log.info('Created database "' + internals.argv.dbname + '"'); } db.close(); callback(); }); - } - else if(internals.mode === 'drop') - { - db.dropDatabase(internals.argv.dbname, { ifExists: true }, function() - { - if(err) { + } else if (internals.mode === 'drop') { + db.dropDatabase(internals.argv.dbname, { + ifExists: true + }, function() { + if (err) { log.info('Error: Failed to drop database!'); - } - else { + } else { log.info('Deleted database "' + internals.argv.dbname + '"'); } db.close(); callback(); }); - } - else + } else return; }); } -function executeSeed( internals, callback ) { +function executeSeed(internals, callback) { - if(internals.argv._.length > 0) { + if (internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); } index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Seeder, function(err, seeder) - { + config: config.getCurrent().settings, + internals: internals + }, Seeder, function(err, seeder) { assert.ifError(err); - seeder.seedDir = path.resolve(internals.argv[(internals.mode !== 'static') ? 'vcseeder-dir': 'staticseeder-dir']); + seeder.seedDir = path.resolve(internals.argv[(internals.mode !== + 'static') ? 'vcseeder-dir' : 'staticseeder-dir']); - if(internals.mode === 'static') { + if (internals.mode === 'static') { - seeder.seed(internals.argv, internals.onComplete.bind(this, seeder, callback)); - } - else { + seeder.seed(internals.argv, internals.onComplete.bind(this, seeder, + callback)); + } else { seeder.createSeedsTable(function(err) { - if( _assert( err, callback ) ) { + if (_assert(err, callback)) { - seeder.seed(internals.argv, internals.onComplete.bind(this, seeder, callback)); + seeder.seed(internals.argv, internals.onComplete.bind(this, + seeder, callback)); } }); } @@ -736,17 +756,19 @@ internals.onComplete = onComplete; function onComplete(migrator, callback, originalErr) { - if( typeof(callback) !== 'function' ) { + if (typeof(callback) !== 'function') { originalErr = originalErr || callback; } migrator.driver.close(function(err) { - if( ( err || originalErr ) && typeof(callback) === 'function' ) { + if ((err || originalErr) && typeof(callback) === 'function') { - callback({ err: err, originalErr: originalErr }); + callback({ + err: err, + originalErr: originalErr + }); return; - } - else { + } else { assert.ifError(originalErr); assert.ifError(err); @@ -758,67 +780,66 @@ function onComplete(migrator, callback, originalErr) { process.exit(0); } - if( typeof( callback ) === 'function' ) { + if (typeof(callback) === 'function') { callback(); } }); } -function run( internals ) { +function run(internals) { var action = internals.argv._.shift(), - folder = action.split(':'); + folder = action.split(':'); action = folder[0]; - switch(action) { + switch (action) { case 'create': - if(folder[1]) - { + if (folder[1]) { internals.matching = folder[1]; internals.migrationMode = folder[1]; } - executeCreateMigration( internals ); + executeCreateMigration(internals); break; case 'up': case 'down': case 'reset': - if(action === 'reset') + if (action === 'reset') internals.argv.count = Number.MAX_VALUE; - if(internals.argv._.length > 0) { + if (internals.argv._.length > 0) { if (action === 'down') { - log.info('Ignoring migration name for down migrations. Use --count to control how many down migrations are run.'); + log.info( + 'Ignoring migration name for down migrations. Use --count to control how many down migrations are run.' + ); internals.argv.destination = null; } else { internals.argv.destination = internals.argv._.shift().toString(); } } - if(folder[1]) - { + if (folder[1]) { internals.matching = folder[1]; internals.migrationMode = folder[1]; } - if(action == 'up') { - executeUp( internals ); + if (action == 'up') { + executeUp(internals); } else { - executeDown( internals ); + executeDown(internals); } break; case 'db': - if(folder.length < 1) { + if (folder.length < 1) { log.info('Please enter a valid command, i.e. db:create|db:drop'); - } - else { + } else { internals.mode = folder[1]; - executeDB( internals ); + executeDB(internals); } break; case 'seed': @@ -826,13 +847,12 @@ function run( internals ) { internals.mode = folder[1] || 'vc'; internals.migrationMode = folder[2]; - if( internals.argv._[0] === 'down' ) { + if (internals.argv._[0] === 'down') { - internals.argv._.shift(); - } - else { + internals.argv._.shift(); + } else { - executeSeed( internals ); + executeSeed(internals); } break; diff --git a/lib/migration.js b/lib/migration.js index 152bbf90..0c22215a 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -17,12 +17,13 @@ try { var internals = {}; function writeMigrationRecord(db, migration, callback) { - db._runSql('INSERT INTO ' + internals.migrationTable + ' (name, run_on) VALUES (?, ?)', [migration.name, new Date()], callback); + db._runSql('INSERT INTO ' + internals.migrationTable + + ' (name, run_on) VALUES (?, ?)', [migration.name, new Date()], callback); } var Migration = Skeleton.extend({ - init: function() { + init: function() { if (arguments.length >= 3) { this.title = arguments[0]; this.date = arguments[2]; @@ -121,7 +122,8 @@ Migration.prototype.sqlFileLoaderTemplate = function() { "};", "", "exports.up = function(db, callback) {", - " var filePath = path.join(__dirname + '/sqls/"+this.name.replace('.js', '')+"-up.sql');", + " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( + '.js', '') + "-up.sql');", " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", " if (err) return callback(err);", " console.log('received data: ' + data);", @@ -134,7 +136,67 @@ Migration.prototype.sqlFileLoaderTemplate = function() { "};", "", "exports.down = function(db, callback) {", - " var filePath = path.join(__dirname + '/sqls/"+this.name.replace('.js', '')+"-down.sql');", + " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( + '.js', '') + "-down.sql');", + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", + " if (err) return callback(err);", + " console.log('received data: ' + data);", + "", + " db.runSql(data, function(err) {", + " if (err) return callback(err);", + " callback();", + " });", + " });", + "};", + "" + ].join("\n"); +}; + +Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { + return [ + "'use strict';", + "", + "var dbm;", + "var type;", + "var seed;", + "var fs = require('fs');", + "var path = require('path');", + + + "", + "/**", + " * 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, callback) {", + " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( + '.js', '') + "-up.sql');", + " if (!dbm.ignoreInit) {", + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", + " if (err) return callback(err);", + " console.log('received data: ' + data);", + "", + " db.runSql(data, function(err) {", + " if (err) return callback(err);", + " callback();", + " });", + " });", + " }", + " else {", + " console.log('ignoring on init: ' + filePath)", + " callback();", + "}", + "};", + "", + "exports.down = function(db, callback) {", + " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( + '.js', '') + "-down.sql');", " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", " if (err) return callback(err);", " console.log('received data: ' + data);", @@ -170,14 +232,16 @@ Migration.prototype.coffeeSqlFileLoaderTemplate = function() { "", "", "exports.up = (db, callback) ->", - " filePath = path.join \"#{__dirname}/sqls/"+this.name.replace('.coffee', '')+"-up.sql\"", + " 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\"", + " filePath = path.join \"#{__dirname}/sqls/" + this.name.replace( + '.coffee', '') + "-down.sql\"", " fs.readFile filePath, {encoding: 'utf-8'}, (err,data) ->", " return callback err if err", @@ -192,7 +256,8 @@ Migration.TemplateType = { DEFAULT_SQL: 1, SQL_FILE_LOADER: 2, DEFAULT_COFFEE: 3, - COFFEE_SQL_FILE_LOADER: 4 + COFFEE_SQL_FILE_LOADER: 4, + SQL_FILE_LOADER_IGNORE_ON_INIT: 5 }; Migration.prototype.getTemplate = function() { @@ -205,6 +270,8 @@ Migration.prototype.getTemplate = function() { 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: default: return this.defaultJsTemplate(); @@ -218,7 +285,10 @@ Migration.prototype.write = function(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; } + if (err) { + callback(err); + return; + } var coffeeWarn = true; files = files.filter(function(file) { if (coffeeWarn && !coffeeSupported && /\.coffee$/.test(file)) { @@ -238,17 +308,19 @@ Migration.loadFromDatabase = function(dir, driver, internals, callback) { if (internals.ignoreCompleted) { callback(null, []); - } - else { + } else { log.verbose('loading migrations from database'); driver.allLoadedMigrations(function(err, dbResults) { - if (err && !internals.dryRun) { callback(err); return; } - else if (err && internals.dryRun) { + 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; + return result.name.substr(0, result.name.lastIndexOf('/')) === + internals.matching; }).map(function(result) { return new Migration(path.join(dir, result.name), internals); }); From 49d8664514404bf82e2ae3a1c090091a265bfcb6 Mon Sep 17 00:00:00 2001 From: "guy.doulberg" Date: Wed, 2 Sep 2015 14:40:22 +0300 Subject: [PATCH 187/412] Activaitng the --ignore-on-init also on the up operation --- lib/migration.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/migration.js b/lib/migration.js index 0c22215a..de2b174a 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -161,6 +161,7 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { "var seed;", "var fs = require('fs');", "var path = require('path');", + "var ignoreOnInit = false;", "", @@ -170,6 +171,7 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { " */", "exports.setup = function(options, seedLink) {", " dbm = options.dbmigrate;", + " ignoreOnInit = dbm.getInstance().internals.argv['ignore-on-init']", " type = dbm.dataType;", " seed = seedLink;", "};", @@ -177,7 +179,7 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { "exports.up = function(db, callback) {", " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( '.js', '') + "-up.sql');", - " if (!dbm.ignoreInit) {", + " if (!ignoreOnInit) {", " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", " if (err) return callback(err);", " console.log('received data: ' + data);", From 837fcc38008ddf9d4c65849a5d40829a513450f6 Mon Sep 17 00:00:00 2001 From: "guy.doulberg" Date: Thu, 3 Sep 2015 09:11:56 +0300 Subject: [PATCH 188/412] putting the config to ignoreOnInit to the options in api instead of loading the DBM framework on every run --- api.js | 3 ++- lib/migration.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api.js b/api.js index ebe16b8b..da18a4f8 100644 --- a/api.js +++ b/api.js @@ -64,7 +64,8 @@ function dbmigrate(isModule, options, callback) { internals.dbm = dbm; global.dbm = dbm; //deprecated internals.migrationOptions = { - dbmigrate: internals.dbm + dbmigrate: internals.dbm, + ignoreOnInit: internals['argv']['ignore-on-init'] }; internals.seederOptions = { dbmigrate: internals.dbm diff --git a/lib/migration.js b/lib/migration.js index de2b174a..2db3ebda 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -171,7 +171,7 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { " */", "exports.setup = function(options, seedLink) {", " dbm = options.dbmigrate;", - " ignoreOnInit = dbm.getInstance().internals.argv['ignore-on-init']", + " ignoreOnInit = options.ignoreOnInit", " type = dbm.dataType;", " seed = seedLink;", "};", From a622cd8b7f6721d8f2472fc934c6a1eda655e071 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Sep 2015 22:53:31 +0200 Subject: [PATCH 189/412] throw exception and give the user a hint to install the missing driver via npm --- lib/driver/index.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index 03a3a63c..d763193b 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -63,10 +63,19 @@ exports.connect = function (config, intern, callback) { } catch (Exception) { - //Fallback to internal drivers, while moving drivers to new repos - req = './' + config.driver; - log.verbose('require:', req); - driver = require(req); + try { + + //Fallback to internal drivers, while moving drivers to new repos + req = './' + config.driver; + log.verbose('require:', req); + driver = require(req); + } + catch (Exception) { + + log.error( 'No such driver found, please try to install it via ' + + 'npm install db-migrate-' + config.driver + ' or ' + + 'npm install -g db-migrate-' + config.driver ); + } } } From ef54a576e0cb4a0496642cba0a0297c4118a881f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Sep 2015 23:33:34 +0200 Subject: [PATCH 190/412] only one side should link, unless we love our stack overflow --- api.js | 2 ++ lib/migrator.js | 31 +++++++++++++++++++++++++++++-- lib/seeder.js | 23 ++++++++++++++++++++--- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/api.js b/api.js index 455d5bad..17b1b10b 100644 --- a/api.js +++ b/api.js @@ -623,6 +623,8 @@ function executeUp( internals, callback ) { else migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); + internals.migrationsDir = migrator.migrationsDir; + migrator.driver.createMigrationsTable(function(err) { assert.ifError(err); log.verbose('migration table created'); diff --git a/lib/migrator.js b/lib/migrator.js index 4f944d69..a8616f61 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -3,10 +3,14 @@ var Migration = require('./migration'); var log = require('./log'); var Promise = require('bluebird'); var MigratorInterface = require( './interface/migratorInterface.js'); +var path = require('path'); +function SeedLink(driver, internals) { -function SeedLink() { + this.seeder = require('./seeder.js')( + driver, internals.argv['vcseeder-dir'], true, internals + ); this.links = []; } SeedLink.prototype = { @@ -20,6 +24,11 @@ SeedLink.prototype = { this.links.push( partialName ); }, + process: function() { + + this.clear(); + }, + clear: function() { this.links = []; @@ -31,7 +40,15 @@ Migrator = function(driver, migrationsDir, empty, intern) { this._driver = driver; this.migrationsDir = migrationsDir; this.internals = intern; - this.seedLink = new SeedLink(); + + if(intern.linked === true) { + + this.seedLink = new SeedLink(driver, intern); + } + else { + + intern.linked = true; + } this.internals.migrationOptions.relation = require('./relation'); @@ -122,6 +139,16 @@ Migrator.prototype = { 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(); + } + + return; + }) .then(function() { return (Promise.promisify(self.writeMigrationRecord.bind(self)))(migration); diff --git a/lib/seeder.js b/lib/seeder.js index 151a34e2..e4ca92a3 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -4,10 +4,14 @@ var dbmUtil = require('./util'); var Promise = require('bluebird'); var SeederInterface = require( './interface/seederInterface.js'); + var internals = {}; -function MigrationLink() { +function MigrationLink(driver, internals) { + this.migrator = require('./migrator.js')( + driver, internals.migrationsDir, null, internals + ); this.links = []; } @@ -22,6 +26,11 @@ MigrationLink.prototype = { this.links.push( partialName ); }, + process: function() { + + this.clear(); + }, + clear: function() { this.links = []; @@ -34,7 +43,16 @@ Seeder = function (driver, seedsDir, versionControlled, intern) { this._driver = driver; this.seedDir = seedsDir; this.isVC = versionControlled; - this.migrationLink = new MigrationLink(); + + if(intern.linked === true) { + + this.migrationLink = new MigrationLink(driver, intern); + } + else { + + intern.linked = true; + } + internals = intern; this.internals = intern; }; @@ -260,5 +278,4 @@ Seeder.prototype = { }); } }; - module.exports = Seeder; From b863eed321d70e99ab705184fe1899ad99d9925d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Sep 2015 23:49:16 +0200 Subject: [PATCH 191/412] iterate through links --- lib/seeder.js | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/lib/seeder.js b/lib/seeder.js index e4ca92a3..1ec83cac 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -17,10 +17,6 @@ function MigrationLink(driver, internals) { MigrationLink.prototype = { - migrate: function( partialName ) { - - }, - link: function( partialName ) { this.links.push( partialName ); @@ -28,7 +24,37 @@ MigrationLink.prototype = { process: function() { - this.clear(); + return new Promise(function(resolve, reject) { + + var keys = Object.keys( this.links ), + i = 0; + + + var migrate = function(i, cb) { + + if(i < keys.length) { + + resolve(); + this.clear(); + } + + this.migrator.up( { + destination: this.links[ keys[ i ] ] + }, function( err ) { + + if( err ) { + + reject( err ); + } + else { + + cb(++i, migrate); + } + } ); + }.bind(this); + + migrate(i, migrate); + }.bind(this)); }, clear: function() { @@ -43,7 +69,7 @@ Seeder = function (driver, seedsDir, versionControlled, intern) { this._driver = driver; this.seedDir = seedsDir; this.isVC = versionControlled; - + if(intern.linked === true) { this.migrationLink = new MigrationLink(driver, intern); From 4438187ea69dae49c779c46bcb7e374121b7cdb6 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 6 Sep 2015 10:13:23 +0200 Subject: [PATCH 192/412] cs fixes --- lib/log.js | 4 ++-- lib/relation.js | 6 +++--- lib/seed.js | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/log.js b/lib/log.js index b2a9cd81..8796a7b8 100644 --- a/lib/log.js +++ b/lib/log.js @@ -105,8 +105,8 @@ exports.sql = function(sql) { for( var i = 0, len = args[0].length; i < len; ++i ) { - logSql = logSql.replace( '$' + (i + 1), escape - + args[0][i] + escape ); + logSql = logSql.replace( '$' + (i + 1), escape + + args[0][i] + escape ); } console.log( logSql + ';' ); diff --git a/lib/relation.js b/lib/relation.js index 45b94c34..20f74905 100644 --- a/lib/relation.js +++ b/lib/relation.js @@ -21,9 +21,9 @@ Relation.prototype = { fromJson: function(file) { - Relation = require(file); + //Relation = require(file); - log.info( "Read Relations from file " + file ); + log.info( 'Read Relations from file ' + file ); }, toJson: function(file) { @@ -34,7 +34,7 @@ Relation.prototype = { throw err; } - log.info( "Wrote Relations to file " + file ); + log.info( 'Wrote Relations to file ' + file ); }); }, diff --git a/lib/seed.js b/lib/seed.js index 54a7bec6..87d96cbb 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -64,7 +64,7 @@ var Seed = Skeleton.extend({ .then(function( Promise ) { if( Promise !== undefined && cb_executed === false ) { - cb_executed = true + cb_executed = true; resolve(); } }).catch(function(err) { @@ -100,7 +100,7 @@ var Seed = Skeleton.extend({ .then(function( Promise ) { if( Promise !== undefined && seed_executed === false ) { - seed_executed = true + seed_executed = true; resolve(); } }).catch(function(err) { From baf87150dfdcfa47a08b36afe85f5922f59c72c4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 7 Sep 2015 01:17:39 +0200 Subject: [PATCH 193/412] add concepting to comments --- lib/interface/migratorInterface.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index aec98adb..a4eb0b3b 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -2,6 +2,27 @@ * The migrator interface provides the ability to handle all abilities which * are needed to successfully modify the DD of your tables. * This includes all DDL methods provided by SQL naturally. + * + * Considering the zero downtime deployment we are handling migrations like + * the following: + * + * ## Data manipulation, the flow: + * + * *) The very first step is always a full dump, for the sake of security + * + * - all operations that are deleting a currently existing column, e.g. renaming a column: + * - 1. duplicate the column + * - if renamed: + * - 1. create a trigger to update both columns + * - 2. disable/delete trigger after successful deployment + * - if deleted: + * - 1. apply steps from the renaming process + * - 2. create a backup of this column (+PK)/table and delete it afterwards (after the successful deployment) + * - all operations that modify content + * - 1. Retrieve data to be applied + * - 2. Extract PKs of to be updated rows + * - 3. Create backup of to be updated rows + * - 4. Apply changes */ function dummy() { From fd4102863c8da31f35c02e50d27ccdf261a6ecc5 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 8 Sep 2015 20:49:41 +0200 Subject: [PATCH 194/412] fix driver inclusion --- lib/driver/index.js | 19 +++- lib/driver/sqlite3.js | 174 ----------------------------- lib/interface/migratorInterface.js | 6 +- lib/log.js | 2 +- package.json | 1 + 5 files changed, 19 insertions(+), 183 deletions(-) delete mode 100644 lib/driver/sqlite3.js diff --git a/lib/driver/index.js b/lib/driver/index.js index d763193b..dfb560d3 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -3,7 +3,6 @@ var internals = {}; internals.mod = internals.mod || {}; internals.mod.log = require('../log'); internals.mod.type = require('../data_type'); -internals.mod.Class = require('../class'); var Shadow = require('./shadow'); var log = internals.mod.log; var tunnel = require('tunnel-ssh'), @@ -47,6 +46,18 @@ exports.connect = function (config, intern, callback) { } else { + + switch(config.driver) { + case 'sqlite3': + config.driver = 'sqlite'; + break; + + case 'postgres': + case 'postgresql': + config.driver = 'pg'; + break; + } + try { req = 'db-migrate-' + config.driver; @@ -57,7 +68,7 @@ exports.connect = function (config, intern, callback) { driver = require(req); } catch (Exception) { - +console.log(Exception) driver = require('../../../' + req); } } @@ -72,9 +83,9 @@ exports.connect = function (config, intern, callback) { } catch (Exception) { - log.error( 'No such driver found, please try to install it via ' + + return callback( { stack: 'No such driver found, please try to install it via ' + 'npm install db-migrate-' + config.driver + ' or ' + - 'npm install -g db-migrate-' + config.driver ); + 'npm install -g db-migrate-' + config.driver } ); } } } diff --git a/lib/driver/sqlite3.js b/lib/driver/sqlite3.js deleted file mode 100644 index d4ca1019..00000000 --- a/lib/driver/sqlite3.js +++ /dev/null @@ -1,174 +0,0 @@ -var util = require('util'); -var sqlite3 = require('sqlite3').verbose(); -var Base = require('./base'); -var log = require('../log'); -var type = require('../data_type'); -var Promise = require('bluebird'); - -var defaultMode = sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, - internals = {}; - -var Sqlite3Driver = Base.extend({ - init: function(connection) { - this._escapeString = '"'; - this._super(internals); - this.connection = connection; - }, - - startMigration: function(cb){ - - if(!internals.notransactions) { - - return Promise.promisify(this.runSql.bind(this))('BEGIN TRANSACTION;').nodeify(cb); - } - else - return Promise.resolve().nodeify(cb); - }, - - endMigration: function(cb){ - - if(!internals.notransactions) { - - return Promise.promisify(this.runSql.bind(this))('COMMIT;').nodeify(cb); - } - else - return Promise.resolve(null).nodeify(cb); - }, - - mapDataType: function(str) { - switch(str) { - case type.DATE_TIME: - return 'datetime'; - case type.TIME: - return 'time'; - } - return this._super(str); - }, - - switchDatabase: function(options, callback) { - callback(null); - }, - - createColumnDef: function(name, spec, options) { - name = '"' + name + '"'; - var dType = this.mapDataType(spec.type); - var len = spec.length ? util.format('(%s)', spec.length) : ''; - var constraint = this.createColumnConstraint(spec, options); - - if(spec.type === type.INTEGER) - len = ''; - - return { foreignKey: null, - constraints: [name, dType, len, constraint].join(' ') }; - }, - - createColumnConstraint: function(spec, options) { - var constraint = []; - if (spec.primaryKey && options.emitPrimaryKey) { - constraint.push('PRIMARY KEY'); - if (spec.autoIncrement) { - constraint.push('AUTOINCREMENT'); - } - } - - if (spec.notNull === true) { - constraint.push('NOT NULL'); - } - - if (spec.unique) { - constraint.push('UNIQUE'); - } - - if (spec.defaultValue) { - constraint.push('DEFAULT'); - - if(typeof(spec.defaultValue) === 'string') - constraint.push('"' + spec.defaultValue + '"'); - else - constraint.push(spec.defaultValue); - } - - return constraint.join(' '); - }, - - renameTable: function(tableName, newTableName, callback) { - var sql = util.format('ALTER TABLE %s RENAME TO %s', tableName, newTableName); - - return this.runSql(sql).nodeify(callback); - }, - - //removeColumn: function(tableName, columnName, callback) { - //}, - - //renameColumn: function(tableName, oldColumnName, newColumnName, callback) { - //}; - - //changeColumn: function(tableName, columnName, columnSpec, callback) { - //}, - - runSql: function() { - var callback = arguments[arguments.length - 1]; - var params = arguments; - - log.sql.apply(null, arguments); - if(internals.dryRun) { - return Promise.resolve().nodeify(callback); - } - - return new Promise(function(resolve, reject) { - var prCB = function(err, data) { - return (err ? reject(err) : resolve(data)); - }; - - if( typeof(params[params.length - 1]) === 'function' ) - params[params.length - 1] = prCB; - else - params[params.length++] = prCB; - - - if(params.length === 1 || (callback && typeof(params[1]) === 'function')) - this.connection.exec.apply(this.connection, params); - else - this.connection.run.apply(this.connection, params); - }.bind(this)).nodeify(callback); - }, - - all: function() { - - log.sql.apply(null, arguments); - - this.connection.all.apply(this.connection, arguments); - }, - - close: function(callback) { - this.connection.close(); - - if(typeof(callback) === 'function') - callback(null); - else - return Promise.resolve(); - } - -}); - -Promise.promisifyAll(Sqlite3Driver); - -exports.connect = function(config, intern, callback) { - var mode = config.mode || defaultMode; - - internals = intern; - - if (config.db) { - callback(null, new Sqlite3Driver(config.db)); - } else { - if (typeof(config.filename) === 'undefined') { - console.error('filename is required in database.json'); - return; - } - var db = new sqlite3.Database(config.filename, mode); - db.on("error", callback); - db.on("open", function() { - callback(null, new Sqlite3Driver(db)); - }); - } -}; diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index a4eb0b3b..33d28ad1 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -6,7 +6,7 @@ * Considering the zero downtime deployment we are handling migrations like * the following: * - * ## Data manipulation, the flow: + * Zero Downtime notes * * *) The very first step is always a full dump, for the sake of security * @@ -22,7 +22,7 @@ * - 1. Retrieve data to be applied * - 2. Extract PKs of to be updated rows * - 3. Create backup of to be updated rows - * - 4. Apply changes + * - 4. Apply changes */ function dummy() { @@ -112,8 +112,6 @@ MigratorInterface.prototype = { escapeDDL: dummy, - checkDBMS: dummy, - all: dummy, close: dummy diff --git a/lib/log.js b/lib/log.js index 8796a7b8..8532333a 100644 --- a/lib/log.js +++ b/lib/log.js @@ -62,7 +62,7 @@ exports.error = function () { if ((!this.isSilent || global.verbose) && logLevel & level.error) { var args = Array.prototype.unshift.call(arguments, '[ERROR]'); - console.trace( 'Trace from error log' ); + //console.trace( 'Trace from error log' ); console.error.apply(console, arguments); } }; diff --git a/package.json b/package.json index c57d00c5..ab74ab88 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "devDependencies": { "code": "^1.3.0", "db-meta": "~0.4.1", + "db-migrate-sqlite": "^0.1.1", "lab": "^5.2.1", "proxyquire": "^1.4.0", "rimraf": "~2.4.0", From d105ea0cdb0af530f0164efca616056311fdf224 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 8 Sep 2015 21:08:47 +0200 Subject: [PATCH 195/412] remove sqlite dependency, add sqlite to devdependencies and outsource driver --- lib/driver/index.js | 6 +++--- package.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index dfb560d3..d7b8f48c 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -48,8 +48,8 @@ exports.connect = function (config, intern, callback) { else { switch(config.driver) { - case 'sqlite3': - config.driver = 'sqlite'; + case 'sqlite': + config.driver = 'sqlite3'; break; case 'postgres': @@ -68,7 +68,7 @@ exports.connect = function (config, intern, callback) { driver = require(req); } catch (Exception) { -console.log(Exception) + driver = require('../../../' + req); } } diff --git a/package.json b/package.json index ab74ab88..41f5721a 100644 --- a/package.json +++ b/package.json @@ -58,17 +58,17 @@ "pkginfo": "~0.3.0", "resolve": "^1.1.6", "semver": "~5.0.1", - "sqlite3": "~3.0.4", "tunnel-ssh": "^1.0.0" }, "devDependencies": { "code": "^1.3.0", "db-meta": "~0.4.1", - "db-migrate-sqlite": "^0.1.1", + "db-migrate-sqlite3": "^0.1.2", "lab": "^5.2.1", "proxyquire": "^1.4.0", "rimraf": "~2.4.0", "sinon": "^1.14.1", + "sqlite3": "^3.0.10", "vows": "0.8.0" }, "scripts": { From fa64f2df43af8a2984dbe76e437c7096117b8b7c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 8 Sep 2015 21:13:57 +0200 Subject: [PATCH 196/412] remove unnecessary files --- lib/driver/postgres.js | 1 - lib/driver/postgresql.js | 1 - 2 files changed, 2 deletions(-) delete mode 100644 lib/driver/postgres.js delete mode 100644 lib/driver/postgresql.js diff --git a/lib/driver/postgres.js b/lib/driver/postgres.js deleted file mode 100644 index a0e5ea61..00000000 --- a/lib/driver/postgres.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./pg'); diff --git a/lib/driver/postgresql.js b/lib/driver/postgresql.js deleted file mode 100644 index a0e5ea61..00000000 --- a/lib/driver/postgresql.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./pg'); From cedc8b7dca0a1213cd4329d5b09e02bc44a52972 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 8 Sep 2015 21:21:26 +0200 Subject: [PATCH 197/412] remove mongodb dependency, outsource mongodb driver --- lib/driver/mongodb.js | 496 ------------------------------------------ package.json | 2 +- 2 files changed, 1 insertion(+), 497 deletions(-) delete mode 100644 lib/driver/mongodb.js diff --git a/lib/driver/mongodb.js b/lib/driver/mongodb.js deleted file mode 100644 index b57c500e..00000000 --- a/lib/driver/mongodb.js +++ /dev/null @@ -1,496 +0,0 @@ -var util = require('util'); -var moment = require('moment'); -var MongoClient = require('mongodb').MongoClient; -var Server = require('mongodb').Server; -var Base = require('./base'); -var type = require('../data_type'); -var log = require('../log.js'); -var Promise = require('bluebird'); - -var connectionString, internals = {}; - -var MongodbDriver = Base.extend({ - - init: function(connection, mongoString) { - this._super(internals); - this.connection = connection; - connectionString = mongoString; - }, - - /** - * Creates the migrations collection - * - * @param callback - */ - _createMigrationsCollection: function(callback) { - return this._run('createCollection', internals.migrationTable, null) - .nodeify(callback); - }, - - - /** - * Creates the seed collection - * - * @param callback - */ - _createSeedsCollection: function(callback) { - return this._run('createCollection', internals.seedTable, null) - .nodeify(callback); - }, - - - /** - * Creates the seeder collection - * - * @param callback - */ - _createSeedsCollection: function(callback) { - return this._run('createCollection', internals.seedTable, null) - .nodeify(callback); - }, - - /** - * An alias for _createMigrationsCollection - */ - createMigrationsTable: function(callback) { - this._createMigrationsCollection(callback); - }, - - /** - * An alias for _createSeederCollection - */ - createSeedsTable: function(callback) { - this._createSeedsCollection(callback); - }, - - /** - * Creates a collection - * - * @param collectionName - The name of the collection to be created - * @param callback - */ - createCollection: function(collectionName, callback) { - return this._run('createCollection', collectionName, null) - .nodeify(callback); - }, - - switchDatabase: function(options, callback) { - - if(typeof(options) === 'object') - { - if(typeof(options.database) === 'string') - return this._run('use', options, null) - .nodeify(callback); - } - else if(typeof(options) === 'string') - { - return this._run('use', options, null) - .nodeify(callback); - } - else - return Promise.resolve().nodeify(callback); - }, - - createDatabase: function(dbName, options, callback) { - //Don't care at all, MongoDB auto creates databases - if(typeof(options) === 'function') - callback = options; - - return Promise.resolve().nodeify(callback); - }, - - dropDatabase: function(dbName, options, callback) { - - if(typeof(options) === 'function') - callback = options; - - return this._run('dropDatabase', dbName, null) - .nodeify(callback); - }, - - /** - * An alias for createCollection - * - * @param collectionName - The name of the collection to be created - * @param callback - */ - createTable: function(collectionName, callback) { - this.createCollection(collectionName, callback); - }, - - /** - * Drops a collection - * - * @param collectionName - The name of the collection to be dropped - * @param callback - */ - dropCollection: function(collectionName, callback) { - return this._run('dropCollection', collectionName, null) - .nodeify(callback); - }, - - /** - * An alias for dropCollection - * - * @param collectionName - The name of the collection to be dropped - * @param callback - */ - dropTable: function(collectionName, callback) { - this.dropCollection(collectionName, callback); - }, - - /** - * Renames a collection - * - * @param collectionName - The name of the existing collection to be renamed - * @param newCollectionName - The new name of the collection - * @param callback - */ - renameCollection: function(collectionName, newCollectionName, callback) { - return this._run('renameCollection', collectionName, {newCollection: newCollectionName}) - .nodeify(callback); - }, - - /** - * An alias for renameCollection - * - * @param collectionName - The name of the existing collection to be renamed - * @param newCollectionName - The new name of the collection - * @param callback - */ - renameTable: function(collectionName, newCollectionName, callback) { - return this.renameCollection(collectionName, newCollectionName) - .nodeify(callback); - }, - - /** - * Adds an index to a collection - * - * @param collectionName - The collection to add the index to - * @param indexName - The name of the index to add - * @param columns - The columns to add an index on - * @param unique - A boolean whether this creates a unique index - */ - addIndex: function(collectionName, indexName, columns, unique, callback) { - - var options = { - indexName: indexName, - columns: columns, - unique: unique - }; - - return this._run('createIndex', collectionName, options) - .nodeify(callback); - }, - - /** - * Removes an index from a collection - * - * @param collectionName - The collection to remove the index - * @param indexName - The name of the index to remove - * @param columns - */ - removeIndex: function(collectionName, indexName, callback) { - return this._run('dropIndex', collectionName, {indexName: indexName}) - .nodeify(callback); - }, - - /** - * Inserts a record(s) into a collection - * - * @param collectionName - The collection to insert into - * @param toInsert - The record(s) to insert - * @param callback - */ - insert: function(collectionName, toInsert, callback) { - return this._run('insert', collectionName, toInsert) - .nodeify(callback); - }, - - /** - * Inserts a migration record into the migration collection - * - * @param name - The name of the migration being run - * @param callback - */ - addMigrationRecord: function (name, callback) { - return this._run('insert', internals.migrationTable, {name: name, run_on: new Date}) - .nodeify(callback); - }, - - /** - * Inserts a seeder record into the seeder collection - * - * @param name - The name of the seed being run - * @param callback - */ - addSeedRecord: function (name, callback) { - return this._run('insert', internals.seedTable, {name: name, run_on: new Date}) - .nodeify(callback); - }, - - /** - * Runs a query - * - * @param collectionName - The collection to query on - * @param query - The query to run - * @param callback - */ - _find: function(collectionName, query, callback) { - return this._run('find', collectionName, query) - .nodeify(callback); - }, - - /** - * Gets all the collection names in mongo - * - * @param callback - The callback to call with the collection names - */ - _getCollectionNames: function(callback) { - return this._run('collections', null, null) - .nodeify(callback); - }, - - /** - * Gets all the indexes for a specific collection - * - * @param collectionName - The name of the collection to get the indexes for - * @param callback - The callback to call with the collection names - */ - _getIndexes: function(collectionName, callback) { - return this._run('indexInformation', collectionName, null) - .nodeify(callback); - }, - - /** - * Gets a connection and runs a mongo command and returns the results - * - * @param command - The command to run against mongo - * @param collection - The collection to run the command on - * @param options - An object of options to be used based on the command - * @param callback - A callback to return the results - */ - _run: function(command, collection, options, callback) { - - var args = this._makeParamArgs(arguments), - sort = null, - callback = args[2]; - - log.sql.apply(null, arguments); - - if(options && typeof(options) === 'object') { - - if(options.sort) - sort = options.sort; - } - - if(internals.dryRun) { - return Promise.resolve().nodeify(callback); - } - - return new Promise(function(resolve, reject) { - var prCB = function(err, data) { - return (err ? reject(err) : resolve(data)); - }; - - // Get a connection to mongo - this.connection.connect(connectionString, function(err, db) { - - if(err) { - prCB(err); - } - - // Callback function to return mongo records - var callbackFunction = function(err, data) { - - if(err) { - prCB(err); - } - - prCB(null, data); - db.close(); - }; - - // Depending on the command, we need to use different mongo methods - switch(command) { - case 'find': - - if(sort) { - db.collection(collection)[command](options.query).sort(sort).toArray(callbackFunction); - } - else { - db.collection(collection)[command](options).toArray(callbackFunction); - } - break; - case 'renameCollection': - db[command](collection, options.newCollection, callbackFunction); - break; - case 'createIndex': - db[command](collection, options.columns, {name: options.indexName, unique: options.unique}, callbackFunction); - break; - case 'dropIndex': - db.collection(collection)[command](options.indexName, callbackFunction); - break; - case 'insert': - // options is the records to insert in this case - if(util.isArray(options)) - db.collection(collection).insertMany(options, {}, callbackFunction); - else - db.collection(collection).insertOne(options, {}, callbackFunction); - break; - case 'remove': - // options is the records to insert in this case - if(util.isArray(options)) - db.collection(collection).deleteMany(options, callbackFunction); - else - db.collection(collection).deleteOne(options, callbackFunction); - break; - case 'collections': - db.collections(callbackFunction); - break; - case 'indexInformation': - db.indexInformation(collection, callbackFunction); - break; - case 'dropDatabase': - db.dropDatabase(callbackFunction); - break; - case 'use': - db.db(collection, callbackFunction); - break; - default: - db[command](collection, callbackFunction); - break; - } - }); - }.bind(this)).nodeify(callback); - }, - - _makeParamArgs: function(args) { - var params = Array.prototype.slice.call(args); - var sql = params.shift(); - var callback = params.pop(); - - if (params.length > 0 && Array.isArray(params[0])) { - params = params[0]; - } - - return [sql, params, callback]; - }, - - /** - * Runs a NoSQL command regardless of the dry-run param - */ - _all: function() { - var args = this._makeParamArgs(arguments); - return this.connection.query.apply(this.connection, args); - }, - - /** - * Queries the migrations collection - * - * @param callback - */ - allLoadedMigrations: function(callback) { - return this._run('find', internals.migrationTable, { sort: { run_on: -1 } }) - .nodeify(callback); - }, - - /** - * Queries the seed collection - * - * @param callback - */ - allLoadedSeeds: function(callback) { - return this._run('find', internals.seedTable, { sort: { run_on: -1 } }) - .nodeify(callback); - }, - - /** - * Deletes a migration - * - * @param migrationName - The name of the migration to be deleted - * @param callback - */ - deleteMigration: function(migrationName, callback) { - return this._run('remove', internals.migrationTable, {name: migrationName}) - .nodeify(callback); - }, - - /** - * Deletes a migration - * - * @param migrationName - The name of the migration to be deleted - * @param callback - */ - deleteSeed: function(migrationName, callback) { - return this._run('remove', internals.seedTable, {name: migrationName}) - .nodeify(callback); - }, - - /** - * Closes the connection to mongodb - */ - close: function(callback) { - return new Promise(function(resolve, reject) { - var cb = (function(err, data) { - return (err ? reject(err) : resolve(data)); - }); - - this.connection.close(cb); - }.bind(this)).nodeify(callback); - }, - - buildWhereClause: function() { - - return Promise.reject('There is no NoSQL implementation yet!'); - }, - - update: function() { - - return Promise.reject('There is no NoSQL implementation yet!'); - } -}); - -Promise.promisifyAll(MongodbDriver); - -/** - * Gets a connection to mongo - * - * @param config - The config to connect to mongo - * @param callback - The callback to call with a MongodbDriver object - */ -exports.connect = function(config, intern, callback) { - var db; - var port; - var host; - - internals = intern; - - // Make sure the database is defined - if(config.database === undefined) { - throw new Error('database must be defined in database.json'); - } - - if(config.host === undefined) { - host = 'localhost'; - } else { - host = config.host; - } - - if(config.port === undefined) { - port = 27017; - } else { - port = config.port; - } - - var mongoString = 'mongodb://'; - - if(config.user !== undefined && config.password !== undefined) { - mongoString += config.user + ':' + config.password + '@'; - } - - mongoString += host + ':' + port + '/' + config.database; - - db = config.db || new MongoClient(new Server(host, port)); - callback(null, new MongodbDriver(db, mongoString)); -}; diff --git a/package.json b/package.json index 41f5721a..3e5e0465 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "final-fs": "^1.6.0", "mkdirp": "~0.5.0", "moment": "~2.10.2", - "mongodb": "^2.0.23", "mysql": "~2.9.0", "optimist": "~0.6.1", "parse-database-url": "~0.2.2", @@ -63,6 +62,7 @@ "devDependencies": { "code": "^1.3.0", "db-meta": "~0.4.1", + "db-migrate-mongodb": "^1.0.1", "db-migrate-sqlite3": "^0.1.2", "lab": "^5.2.1", "proxyquire": "^1.4.0", From 251d8fab2aba9a0936b66c841e1cb9e6366360a4 Mon Sep 17 00:00:00 2001 From: Samuel Bolduc Date: Wed, 9 Sep 2015 20:38:41 -0400 Subject: [PATCH 198/412] Bump sqlite3 package version to fix issue with node 4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3e5e0465..a269db58 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "proxyquire": "^1.4.0", "rimraf": "~2.4.0", "sinon": "^1.14.1", - "sqlite3": "^3.0.10", + "sqlite3": "^3.0.11", "vows": "0.8.0" }, "scripts": { From e578d8080f8e9c5e178528679cade27c490b3863 Mon Sep 17 00:00:00 2001 From: Samuel Bolduc Date: Wed, 9 Sep 2015 20:38:55 -0400 Subject: [PATCH 199/412] Bump sqlite3 package version to fix issue with node 4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a269db58..c822a2da 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "proxyquire": "^1.4.0", "rimraf": "~2.4.0", "sinon": "^1.14.1", - "sqlite3": "^3.0.11", + "sqlite3": "^3.1.0", "vows": "0.8.0" }, "scripts": { From 0a01fe7ba8c8ae19a306903c14ea77c0e489afc3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 13:05:34 +0200 Subject: [PATCH 200/412] add node version 4.0, remove iojs allowed build failures --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6b1bd5ea..3ad9af51 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: node_js node_js: - 0.10 - 0.12 + - 4.0 - "iojs-1" - "iojs-2" - "iojs-3" @@ -24,9 +25,6 @@ os: matrix: fast_finish: true - allow_failures: - - node_js: "iojs-3" - - node_js: "iojs" services: - mongodb From 37ecd3a69584aa845c4d20dfdc448cd28259b2e6 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 14:19:57 +0200 Subject: [PATCH 201/412] remove mysql dependency and add to dev for testing purposes --- lib/driver/mysql.js | 419 -------------------------------------------- package.json | 2 +- 2 files changed, 1 insertion(+), 420 deletions(-) delete mode 100644 lib/driver/mysql.js diff --git a/lib/driver/mysql.js b/lib/driver/mysql.js deleted file mode 100644 index a429301f..00000000 --- a/lib/driver/mysql.js +++ /dev/null @@ -1,419 +0,0 @@ -var util = require('util'); -var moment = require('moment'); -var mysql = require('mysql'); -var Base = require('./base'); -var type = require('../data_type'); -var log = require('../log'); -var Promise = require('bluebird'); - -var internals = {}; - -var MysqlDriver = Base.extend({ - init: function(connection) { - this._escapeDDL = '`'; - this._escapeString = '\''; - this._super(internals); - this.connection = connection; - }, - - startMigration: function(cb){ - - var self = this; - - if(!internals.notransactions) { - - return this.runSql('SET AUTOCOMMIT=0;') - .then(function() { - return self.runSql('START TRANSACTION;'); - }) - .nodeify(cb); - } - else - return Promise.resolve().nodeify(cb); - }, - - endMigration: function(cb){ - - if(!internals.notransactions) { - - return this.runSql('COMMIT;').nodeify(cb); - } - else - return Promise.resolve(null).nodeify(cb); - }, - - mapDataType: function(spec) { - var len; - switch(spec.type) { - case type.TEXT: - len = parseInt(spec.length, 10) || 1000; - if(len > 16777216) { - return 'LONGTEXT'; - } - if(len > 65536) { - return 'MEDIUMTEXT'; - } - if(len > 256) { - return 'TEXT'; - } - return 'TINYTEXT'; - case type.DATE_TIME: - return 'DATETIME'; - case type.BLOB: - len = parseInt(spec.length, 10) || 1000; - if(len > 16777216) { - return 'LONGBLOB'; - } - if(len > 65536) { - return 'MEDIUMBLOB'; - } - if(len > 256) { - return 'BLOB'; - } - return 'TINYBLOB'; - case type.BOOLEAN: - return 'TINYINT(1)'; - } - return this._super(spec.type); - }, - - createColumnDef: function(name, spec, options, tableName) { - var escapedName = util.format('`%s`', name), - t = this.mapDataType(spec), - len; - if(spec.type !== type.TEXT && spec.type !== type.BLOB) { - len = spec.length ? util.format('(%s)', spec.length) : ''; - if (t === 'VARCHAR' && len === '') { - len = '(255)'; - } - } - var constraint = this.createColumnConstraint(spec, options, tableName, name); - return { foreignKey: constraint.foreignKey, - constraints: [escapedName, t, len, constraint.constraints].join(' ') }; - }, - - createColumnConstraint: function(spec, options, tableName, columnName) { - var constraint = []; - var cb; - - if (spec.unsigned) { - constraint.push('UNSIGNED'); - } - - if (spec.primaryKey) { - if (!options || options.emitPrimaryKey) { - constraint.push('PRIMARY KEY'); - } - } - - if(spec.primaryKey || spec.unique) { - if (spec.autoIncrement) { - constraint.push('AUTO_INCREMENT'); - } - } - - if (spec.notNull === true) { - constraint.push('NOT NULL'); - } - - if (spec.unique) { - constraint.push('UNIQUE'); - } - - if (spec.engine && typeof(spec.engine) === 'string') { - constraint.push('ENGINE=\'' + spec.engine + '\'') - } - - if (spec.rowFormat && typeof(spec.rowFormat) === 'string') { - constraint.push('ROW_FORMAT=\'' + spec.rowFormat + '\'') - } - - if (spec.onUpdate && spec.onUpdate === 'CURRENT_TIMESTAMP') { - constraint.push('ON UPDATE CURRENT_TIMESTAMP') - } - - if (spec.null || spec.notNull === false) { - constraint.push('NULL'); - } - - if (spec.defaultValue !== undefined) { - constraint.push('DEFAULT'); - - if (typeof spec.defaultValue === 'string'){ - if(spec.defaultValue === 'CURRENT_TIMESTAMP') { - constraint.push(spec.defaultValue); - } - else { - constraint.push("'" + spec.defaultValue + "'"); - } - } else if (spec.defaultValue === null) { - constraint.push('NULL'); - } else { - constraint.push(spec.defaultValue); - } - } - - if (spec.foreignKey) { - - cb = this.bindForeignKey(tableName, columnName, spec.foreignKey); - } - - return { foreignKey: cb, constraints: constraint.join(' ') }; - }, - - - renameTable: function(tableName, newTableName, callback) { - var sql = util.format('RENAME TABLE `%s` TO `%s`', tableName, newTableName); - return this.runSql(sql).nodeify(callback); - }, - - createDatabase: function(dbName, options, callback) { - - var spec = '', - ifNotExists = ''; - - if(typeof(options) === 'function') - callback = options; - else - { - ifNotExists = (options.ifNotExists === true) ? 'IF NOT EXISTS' : ''; - } - - this.runSql(util.format('CREATE DATABASE %s `%s` %s', ifNotExists, dbName, spec), callback); - }, - - switchDatabase: function(options, callback) { - - if(typeof(options) === 'object') - { - if(typeof(options.database) === 'string') - this.runSql(util.format('USE `%s`', options.database), callback); - } - else if(typeof(options) === 'string') - { - this.runSql(util.format('USE `%s`', options), callback); - } - else - callback(null); - }, - - dropDatabase: function(dbName, options, callback) { - - var ifExists = ''; - - if(typeof(options) === 'function') - callback = options; - else - { - ifExists = (options.ifExists === true) ? 'IF EXISTS' : ''; - } - - this.runSql(util.format('DROP DATABASE %s `%s`', ifExists, dbName), callback); - }, - - removeColumn: function(tableName, columnName, callback) { - var sql = util.format('ALTER TABLE `%s` DROP COLUMN `%s`', tableName, columnName); - - return this.runSql(sql).nodeify(callback); - }, - - addIndex: function(tableName, indexName, columns, unique, callback) { - if (typeof(unique) === 'function') { - callback = unique; - unique = false; - } - - if (!Array.isArray(columns)) { - columns = [columns]; - } - - var columnsList = []; - for (var columnIndex in columns) { - var column = columns[columnIndex]; - var columnSpec = ''; - - if (typeof(column) === 'object' && column.name) { - columnSpec = util.format('`%s`%s', - column.name, - (column.length ? util.format('(%s)', parseInt(column.length)) : '') - ); - } else if (typeof(column) === 'string') { - columnSpec = util.format('`%s`', column); - } else - return callback(new Error('Invalid column specification')); - - columnsList.push(columnSpec); - } - - var sql = util.format('ALTER TABLE `%s` ADD %s INDEX `%s` (%s)', tableName, (unique ? 'UNIQUE ' : ''), indexName, columnsList.join(', ')); - return this.runSql(sql).nodeify(callback); - }, - - removeIndex: function(tableName, indexName, callback) { - // tableName is optional for other drivers, but required for mySql. So, check the args to ensure they are valid - if (arguments.length === 2 && typeof(indexName) === 'function') { - callback = indexName; - process.nextTick(function () { - callback(new Error('Illegal arguments, must provide "tableName" and "indexName"')); - }); - - return; - } - - var sql = util.format('DROP INDEX `%s` ON `%s`', indexName, tableName); - - return this.runSql(sql).nodeify(callback); - }, - - renameColumn: function(tableName, oldColumnName, newColumnName, callback) { - var self = this, columnTypeSql = util.format("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s' AND COLUMN_NAME = '%s'", tableName, oldColumnName); - - return this.runSql(columnTypeSql) - .then(function(result) { - var columnType = result[0].COLUMN_TYPE; - var alterSql = util.format("ALTER TABLE `%s` CHANGE `%s` `%s` %s", tableName, oldColumnName, newColumnName, columnType); - - return self.runSql(alterSql); - }).nodeify(callback); - }, - - changeColumn: function(tableName, columnName, columnSpec, callback) { - var constraint = this.createColumnDef(columnName, columnSpec); - var sql = util.format('ALTER TABLE `%s` CHANGE COLUMN `%s` %s', tableName, columnName, constraint.constraints); - - var exec = function() { - - return this.runSql(sql) - .then(function() - { - if(constraint.foreignKey) - return constraint.foreignKey(); - else - return Promise.resolve(); - }).nodeify(callback); - }.bind(this); - - if(columnSpec.unique === false) - return this.removeIndex(tableName, columnName) - .then(exec); - else - return exec(); - }, - - addMigrationRecord: function (name, callback) { - var formattedDate = moment(new Date()).format('YYYY-MM-DD HH:mm:ss'); - this.runSql('INSERT INTO `' + internals.migrationTable + '` (`name`, `run_on`) VALUES (?, ?)', [name, formattedDate], callback); - }, - - addSeedRecord: function (name, callback) { - var formattedDate = moment(new Date()).format('YYYY-MM-DD HH:mm:ss'); - this.runSql('INSERT INTO `' + internals.seedTable + '` (`name`, `run_on`) VALUES (?, ?)', [name, formattedDate], callback); - }, - - addForeignKey: function(tableName, referencedTableName, keyName, fieldMapping, rules, callback) { - if(arguments.length === 5 && typeof(rules) === 'function') { - callback = rules; - rules = {}; - } - var columns = Object.keys(fieldMapping); - var referencedColumns = columns.map(function (key) { return fieldMapping[key]; }); - var sql = util.format('ALTER TABLE `%s` ADD CONSTRAINT `%s` FOREIGN KEY (%s) REFERENCES `%s` (%s) ON DELETE %s ON UPDATE %s', - tableName, keyName, this.quoteDDLArr( columns ), referencedTableName, - this.quoteDDLArr( referencedColumns ), rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); - - return this.runSql(sql).nodeify(callback); - }, - - removeForeignKey: function(tableName, keyName, options, callback) { - var sql = util.format('ALTER TABLE `%s` DROP FOREIGN KEY `%s`', tableName, keyName); - - return this.runSql(sql) - .then(function () { - - if( typeof(options) === 'function' ) { - - return Promise.resolve().nodeify(options); - } - else if(options.dropIndex === true) { - - sql = util.format('ALTER TABLE `%s` DROP INDEX `%s`', tableName, keyName); - return this.runSql(sql); - } - else - return Promise.resolve().nodeify(callback); - - }.bind(this)).nodeify(callback); - }, - - runSql: function() { - - var self = this; - var args = this._makeParamArgs(arguments); - - var callback = args.pop(); - log.sql.apply(null, arguments); - if(internals.dryRun) { - return Promise.resolve().nodeify(callback); - } - - return new Promise(function(resolve, reject) { - args.push(function(err, data) { - return (err ? reject(err) : resolve(data)); - }); - - self.connection.query.apply(self.connection, args); - }).nodeify(callback); - }, - - _makeParamArgs: function(args) { - var params = Array.prototype.slice.call(args); - var sql = params.shift(); - var callback = params.pop(); - - if (params.length > 0 && Array.isArray(params[0])) { - params = params[0]; - } - return [sql, params, callback]; - }, - - all: function() { - var args = this._makeParamArgs(arguments); - - log.sql.apply(null, arguments); - - return this.connection.query.apply(this.connection, args); - }, - - close: function(callback) { - return new Promise(function(resolve, reject) { - var cb = (function(err, data) { - return (err ? reject(err) : resolve(data)); - }); - - this.connection.end(cb); - }.bind(this)).nodeify(callback); - } - -}); - -Promise.promisifyAll(MysqlDriver); - -function dummy() { - - arguments[arguments.length - 1]('not implemented'); -} - -exports.connect = function(config, intern, callback) { - var db; - - internals = intern; - - internals.interfaces.SeederInterface._makeParamArgs = dummy; - - if (typeof(mysql.createConnection) === 'undefined') { - db = config.db || new mysql.createClient(config); - } else { - db = config.db || new mysql.createConnection(config); - } - callback(null, new MysqlDriver(db)); -}; diff --git a/package.json b/package.json index c822a2da..d3e0e2ca 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "final-fs": "^1.6.0", "mkdirp": "~0.5.0", "moment": "~2.10.2", - "mysql": "~2.9.0", "optimist": "~0.6.1", "parse-database-url": "~0.2.2", "pg": "~4.4.0", @@ -63,6 +62,7 @@ "code": "^1.3.0", "db-meta": "~0.4.1", "db-migrate-mongodb": "^1.0.1", + "db-migrate-mysql": "^1.1.2", "db-migrate-sqlite3": "^0.1.2", "lab": "^5.2.1", "proxyquire": "^1.4.0", From 0fded99b27389b6485c99e05f77d2e740349f8c7 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 14:23:39 +0200 Subject: [PATCH 202/412] fix index_test tests --- test/driver/index_test.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/driver/index_test.js b/test/driver/index_test.js index 3ce511b6..f2b817d0 100644 --- a/test/driver/index_test.js +++ b/test/driver/index_test.js @@ -23,21 +23,21 @@ var indexConnectCallback = function(self, tunnelStub, driverSpy) { db.close(function() { self.callback(err, db, tunnelStub, driverSpy); }); - } + }; }; vows.describe('index').addBatch({ 'a connection with ssh tunnel': { topic: function() { // Ensure that require gets a new copy of the module for each test - delete require.cache[require.resolve('../../lib/driver/mysql')]; - var driver = require('../../lib/driver/mysql'); + delete require.cache[require.resolve('db-migrate-mysql')]; + var driver = require('db-migrate-mysql'); // Set up stubs/spies to verify correct flow var driverSpy = sinon.spy(driver, 'connect'); var tunnelStub = sinon.stub().callsArg(1); - var index = proxyquire('../../lib/driver/index', { + var index = proxyquire('db-migrate-index', { 'tunnel-ssh': tunnelStub, './mysql': driver }); @@ -78,14 +78,14 @@ vows.describe('index').addBatch({ 'a failed tunnel connection': { topic: function() { // Ensure that require gets a new copy of the module for each test - delete require.cache[require.resolve('../../lib/driver/mysql')]; - var driver = require('../../lib/driver/mysql'); + delete require.cache[require.resolve('db-migrate-mysql')]; + var driver = require('db-migrate-mysql'); // Set up stubs/spies to verify correct flow - var tunnelStub = sinon.stub().callsArgWith(1, new Error("error")); + var tunnelStub = sinon.stub().callsArgWith(1, new Error('error')); var driverSpy = sinon.spy(driver, 'connect'); - var index = proxyquire('../../lib/driver/index', { + var index = proxyquire('db-migrate-index', { 'tunnel-ssh': tunnelStub, './mysql': driver }); @@ -93,12 +93,12 @@ vows.describe('index').addBatch({ index.connect(validDbConfigWithTunnel, {}, indexConnectCallback(this, tunnelStub, driverSpy)); }, 'should pass the error to the callback': function (err, db) { - assert(err, "err should be non-null"); - assert(!db, "driver should be null or undefined"); + assert(err, 'err should be non-null'); + assert(!db, 'driver should be null or undefined'); }, 'should call tunnel, but not driver.connect': function (err, db, tunnelStub, driverSpy) { - assert(tunnelStub.calledOnce, "tunnel should be called once"); - assert(driverSpy.notCalled, "driver.connect should not be called"); + assert(tunnelStub.calledOnce, 'tunnel should be called once'); + assert(driverSpy.notCalled, 'driver.connect should not be called'); } } -}).export(module); \ No newline at end of file +}).export(module); From 9e0cb13c2ad25c8616b33eee5cb3ae1867a3df36 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 14:31:48 +0200 Subject: [PATCH 203/412] change base test to extern base --- package.json | 1 + test/driver/base_test.js | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d3e0e2ca..82317b7a 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "devDependencies": { "code": "^1.3.0", "db-meta": "~0.4.1", + "db-migrate-base": "^1.2.1", "db-migrate-mongodb": "^1.0.1", "db-migrate-mysql": "^1.1.2", "db-migrate-sqlite3": "^0.1.2", diff --git a/test/driver/base_test.js b/test/driver/base_test.js index 080f0750..6a0d0d4c 100644 --- a/test/driver/base_test.js +++ b/test/driver/base_test.js @@ -1,9 +1,14 @@ var vows = require('vows'); var assert = require('assert'); -var Base = require('../../lib/driver/base'); +var Base = require('db-migrate-base'); -var internals = {}; -internals.migrationTable = 'migrations'; +var internals = { + migrationTable: 'migrations', + mod: { + log: require('../../lib/log.js'), + type: require('../../lib/data_type.js') + } +}; vows.describe('base').addBatch({ 'default implementation': { @@ -77,4 +82,3 @@ vows.describe('base').addBatch({ } } }).export(module); - From a0943168a16668da27f04ec4be38f1e15461003e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 15:29:09 +0200 Subject: [PATCH 204/412] fix index test --- package.json | 1 + test/driver/index_test.js | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 82317b7a..401a00e9 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "db-migrate-mysql": "^1.1.2", "db-migrate-sqlite3": "^0.1.2", "lab": "^5.2.1", + "mysql": "^2.9.0", "proxyquire": "^1.4.0", "rimraf": "~2.4.0", "sinon": "^1.14.1", diff --git a/test/driver/index_test.js b/test/driver/index_test.js index f2b817d0..1e6cff5d 100644 --- a/test/driver/index_test.js +++ b/test/driver/index_test.js @@ -14,6 +14,10 @@ var validDbConfigWithTunnel = { } }; +var internals = { + migrationTable: 'migrations' +}; + var indexConnectCallback = function(self, tunnelStub, driverSpy) { return function(err, db) { if (err) { @@ -37,7 +41,7 @@ vows.describe('index').addBatch({ var driverSpy = sinon.spy(driver, 'connect'); var tunnelStub = sinon.stub().callsArg(1); - var index = proxyquire('db-migrate-index', { + var index = proxyquire('../../lib/driver/index', { 'tunnel-ssh': tunnelStub, './mysql': driver }); @@ -85,7 +89,7 @@ vows.describe('index').addBatch({ var tunnelStub = sinon.stub().callsArgWith(1, new Error('error')); var driverSpy = sinon.spy(driver, 'connect'); - var index = proxyquire('db-migrate-index', { + var index = proxyquire('../../lib/driver/index', { 'tunnel-ssh': tunnelStub, './mysql': driver }); From 8fb700e0bd084c5529e6205d0c13475b00d18e10 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 15:38:30 +0200 Subject: [PATCH 205/412] remove last driver dependencies resolves #227 --- lib/driver/base.js | 631 --------------------------------------------- lib/driver/pg.js | 488 ----------------------------------- package.json | 2 +- 3 files changed, 1 insertion(+), 1120 deletions(-) delete mode 100644 lib/driver/base.js delete mode 100644 lib/driver/pg.js diff --git a/lib/driver/base.js b/lib/driver/base.js deleted file mode 100644 index 47424bb2..00000000 --- a/lib/driver/base.js +++ /dev/null @@ -1,631 +0,0 @@ -var util = require('util'); -var events = require('events'); -var type = require('../data_type'); -var log = require('../log'); -var Class = require('../class'); -var Promise = require('bluebird'); - -var internals = {}; - -module.exports = Base = Class.extend({ - init: function(intern) { - this._escapeDDL = this._escapeDDL || '"'; - this._escapeString = this._escapeString || '\''; - internals = intern; - this.eventEmmiter = new events.EventEmitter(); - for(var n in events.EventEmitter.prototype) { - this[n] = events.EventEmitter.prototype[n]; - } - }, - - close: function() { - throw new Error('not yet implemented'); - }, - - mapDataType: function(str) { - switch(str) { - case type.STRING: - return 'VARCHAR'; - case type.TEXT: - return 'TEXT'; - case type.INTEGER: - return 'INTEGER'; - case type.BIG_INTEGER: - return 'BIGINT'; - case type.DATE_TIME: - return 'INTEGER'; - case type.REAL: - return 'REAL'; - case type.BLOB: - return 'BLOB'; - case type.TIMESTAMP: - return 'TIMESTAMP'; - case type.BINARY: - return 'BINARY'; - case type.BOOLEAN: - return 'BOOLEAN'; - case type.DECIMAL: - return 'DECIMAL'; - case type.CHAR: - return 'CHAR'; - case type.DATE: - return 'DATE'; - case type.SMALLINT: - return 'SMALLINT'; - default: - var unknownType = str.toUpperCase(); - log.warn('Using unknown data type', unknownType); - return unknownType; - } - }, - - truncate: function(tableName, callback) { - - return this.runSql('TRUNCATE ' + this._escapeDDL + tableName + this._escapeDDL).nodeify(callback); - }, - - checkDBMS: function(dbms, callback) { - - if( this.dbms === dbms ) - return Promise.resolve(dbms).nodeify(callback); - else - return Promise.reject('dbms does not match'); - }, - - createDatabase: function() { - - throw new Error('not implemented'); - }, - - switchDatabase: function() { - throw new Error('not implemented'); - }, - - dropDatabase: function() { - throw new Error('not implemented'); - }, - - recurseCallbackArray: function(foreignKeys, callback) - { - var self = this, fkFunc, - promises = []; - - while((fkFunc = foreignKeys.pop())) - promises.push(Promise.resolve(fkFunc())); - - return Promise.all(promises).nodeify(callback); - }, - - bindForeignKey: function(tableName, columnName, fkOptions) { - var self = this, - mapping = {}; - - if(typeof(fkOptions.mapping) === 'string') - mapping[columnName] = fkOptions.mapping; - else - mapping = fkOptions.mapping; - - return function (callback) { - - if (typeof(callback) === 'function') - self.addForeignKey(tableName, fkOptions.table, - fkOptions.name, mapping, fkOptions.rules, callback); - else - return self.addForeignKey(tableName, fkOptions.table, - fkOptions.name, mapping, fkOptions.rules); - - }; - }, - - createColumnDef: function(name, spec, options) { - name = this._escapeDDL + name + this._escapeDDL; - var type = this.mapDataType(spec.type); - var len = spec.length ? util.format('(%s)', spec.length) : ''; - var constraint = this.createColumnConstraint(spec, options); - - return { foreignKey: null, - constraints: [name, type, len, constraint].join(' ') }; - }, - - createMigrationsTable: function(callback) { - var options = { - columns: { - 'id': { type: type.INTEGER, notNull: true, primaryKey: true, autoIncrement: true }, - 'name': { type: type.STRING, length: 255, notNull: true}, - 'run_on': { type: type.DATE_TIME, notNull: true} - }, - ifNotExists: true - }; - this.createTable(internals.migrationTable, options, callback); - }, - - createSeedsTable: function(callback) { - var options = { - columns: { - 'id': { type: type.INTEGER, notNull: true, primaryKey: true, autoIncrement: true }, - 'name': { type: type.STRING, length: 255, notNull: true}, - 'run_on': { type: type.DATE_TIME, notNull: true} - }, - ifNotExists: true - }; - this.createTable(internals.seedTable, options, callback); - }, - - createTable: function(tableName, options, callback) { - log.verbose('creating table:', tableName); - var columnSpecs = options; - var tableOptions = {}; - - if (options.columns !== undefined) { - columnSpecs = options.columns; - delete options.columns; - tableOptions = options; - } - - var ifNotExistsSql = ""; - if(tableOptions.ifNotExists) { - ifNotExistsSql = "IF NOT EXISTS"; - } - - var primaryKeyColumns = []; - var columnDefOptions = { - emitPrimaryKey: false - }; - - for (var columnName in columnSpecs) { - var columnSpec = this.normalizeColumnSpec(columnSpecs[columnName]); - columnSpecs[columnName] = columnSpec; - if (columnSpec.primaryKey) { - primaryKeyColumns.push(columnName); - } - } - - var pkSql = ''; - if (primaryKeyColumns.length > 1) { - pkSql = util.format(', PRIMARY KEY (%s)', - this.quoteDDLArr(primaryKeyColumns).join(', ')); - - } else { - columnDefOptions.emitPrimaryKey = true; - } - - var columnDefs = []; - var foreignKeys = []; - - for (var columnName in columnSpecs) { - var columnSpec = columnSpecs[columnName]; - var constraint = this.createColumnDef(columnName, columnSpec, columnDefOptions, tableName); - - columnDefs.push(constraint.constraints); - if (constraint.foreignKey) - foreignKeys.push(constraint.foreignKey); - } - - var sql = util.format('CREATE TABLE %s %s (%s%s)', ifNotExistsSql, - this.escapeDDL(tableName), columnDefs.join(', '), pkSql); - - return this.runSql(sql) - .then(function() - { - return this.recurseCallbackArray(foreignKeys); - }.bind(this)).nodeify(callback); - }, - - dropTable: function(tableName, options, callback) { - - if (arguments.length < 3) { - callback = options; - options = {}; - } - - var ifExistsSql = ''; - if (options.ifExists) { - ifExistsSql = 'IF EXISTS'; - } - var sql = util.format('DROP TABLE %s %s', ifExistsSql, - this.escapeDDL(tableName)); - - return this.runSql(sql).nodeify(callback); - }, - - renameTable: function(tableName, newTableName, callback) { - throw new Error('not yet implemented'); - }, - - addColumn: function(tableName, columnName, columnSpec, callback) { - - var def = this.createColumnDef(columnName, - this.normalizeColumnSpec(columnSpec), {}, tableName); - var sql = util.format('ALTER TABLE %s ADD COLUMN %s', - this.escapeDDL(tableName), def.constraints); - - return this.runSql(sql) - .then(function() - { - if(def.foreignKey) - return def.foreignKey(); - else - return Promise.resolve(); - }).nodeify(callback); - }, - - removeColumn: function(tableName, columnName, callback) { - throw new Error('not yet implemented'); - }, - - renameColumn: function(tableName, oldColumnName, newColumnName, callback) { - throw new Error('not yet implemented'); - }, - - changeColumn: function(tableName, columnName, columnSpec, callback) { - throw new Error('not yet implemented'); - }, - - quoteDDLArr: function(arr) { - - for(var i = 0; i < arr.length; ++i) - arr[i] = this._escapeDDL + arr[i] + this._escapeDDL; - - return arr; - }, - - quoteArr: function(arr) { - - for(var i = 0; i < arr.length; ++i) - arr[i] = this._escapeString + arr[i] + this._escapeString; - - return arr; - }, - - addIndex: function(tableName, indexName, columns, unique, callback) { - if (typeof(unique) === 'function') { - callback = unique; - unique = false; - } - - if (!Array.isArray(columns)) { - columns = [columns]; - } - var sql = util.format('CREATE %s INDEX "%s" ON "%s" (%s)', (unique ? 'UNIQUE' : ''), - indexName, tableName, this.quoteDDLArr(columns).join(', ')); - - return this.runSql(sql).nodeify(callback); - }, - - insert: function(tableName, valueArray, callback) { - - var columnNameArray = {}; - - if( arguments.length > 3 ) { - - log.warn( 'This calling convention of insert is deprecated' ); - columnNameArray = valueArray; - valueArray = callback; - callback = arguments[3]; - } - else { - - var names; - if( util.isArray(valueArray) ) { - names = Object.keys(valueArray[0]); - } - else { - names = Object.keys(valueArray); - } - - for( var i = 0; i < names.length; ++i ) { - - columnNameArray[names[i]] = names[i]; - } - } - - if (columnNameArray.length !== valueArray.length) { - return callback(new Error('The number of columns does not match the number of values.')); - } - - var sql = util.format('INSERT INTO %s ', this.escapeDDL(tableName)); - var columnNames = '('; - var values = 'VALUES '; - var values_part = []; - - for (var index in columnNameArray) { - columnNames += this.escapeDDL(columnNameArray[index]); - - if( util.isArray(valueArray) && typeof(valueArray[0]) === 'object') { - - for( var i = 0; i < valueArray.length; ++i ) { - - values_part[i] = values_part[i] || ''; - - if (typeof(valueArray[i][index]) === 'string') { - values_part[i] += this.escapeString(valueArray[i][index]); - } else { - values_part[i] += valueArray[i][index]; - } - } - } - else { - - if (typeof(valueArray[index]) === 'string') { - values_part += this.escapeString(valueArray[index]); - } else { - values_part += valueArray[index]; - } - - values_part += ","; - } - - columnNames += ","; - } - - - if( util.isArray(valueArray) && typeof(valueArray[0]) === 'object' ) { - - for( var i = 0; i < values_part.length; ++i ) { - - values += '(' + values_part[i].slice(0, -1) + '),'; - } - - values = values.slice(0, -1); - } - else { - - values += '(' + values_part.slice(0, -1) + ')'; - } - - sql += columnNames.slice(0, -1) + ') ' + - values + ';'; - - return this.runSql(sql).nodeify(callback); - }, - - update: function(tableName, columnNameArray, valueArray, ids, callback) { - - if (columnNameArray.length !== valueArray.length) { - return callback(new Error('The number of columns does not match the number of values.')); - } - - var sql = util.format('UPDATE ' + this._escapeDDL + '%s' + this._escapeDDL + ' SET ', tableName ); - - for (var index in columnNameArray) { - sql += columnNameArray[index] + '='; - - if (typeof(valueArray[index]) === 'string') { - sql += this._escapeString + this.escape(valueArray[index]) + this._escapeString; - } else { - sql += valueArray[index]; - } - - if (index != columnNameArray.length - 1) { - sql += ", "; - } - } - - sql += ' ' + buildWhereClause(ids); - return this.runSql(sql).nodeify(callback); - }, - - lookup: function(tableName, column, id, callback) { - - var sql = 'SELECT ' + this.escapeDDL(column) + ' FROM ' + - this.escapeDDL(tableName) + ' ' + buildWhereClause(id); - - return this.runSql(sql) - .then(function(row) { - return row[0]; - }); - }, - - removeIndex: function(tableName, indexName, callback) { - if (arguments.length === 2 && typeof(indexName) === 'function') { - callback = indexName; - indexName = tableName; - } else if (arguments.length === 1 && typeof(tableName) === 'string') { - indexName = tableName; - } - - var sql = util.format('DROP INDEX "%s"', indexName); - return this.runSql(sql).nodeify(callback); - }, - - addForeignKey: function() { - throw new Error('not implemented'); - }, - - removeForeignKey: function() { - throw new Error('not implemented'); - }, - - normalizeColumnSpec: function(obj) { - if (typeof(obj) === 'string') { - return { type: obj }; - } else { - return obj; - } - }, - - addMigrationRecord: function (name, callback) { - this.runSql('INSERT INTO ' + this.escapeDDL(internals.migrationTable) + - ' (' + this.escapeDDL('name') + ', ' + this.escapeDDL('run_on') + - ') VALUES (?, ?)', [name, new Date()], callback); - }, - - addSeedRecord: function (name, callback) { - this.runSql('INSERT INTO ' + this.escapeDDL(internals.seedTable) + - ' (' + this.escapeDDL('name') + ', ' + this.escapeDDL('run_on') + - ') VALUES (?, ?)', [name, new Date()], callback); - }, - - startMigration: function(cb){ return Promise.resolve().nodeify(cb); }, - endMigration: function(cb){ return Promise.resolve().nodeify(cb); }, - // sql, params, callback - // sql, callback - runSql: function() { - throw new Error('not implemented'); - }, - - /** - * Queries the migrations table - * - * @param callback - */ - allLoadedMigrations: function(callback) { - var sql = 'SELECT * FROM ' + this._escapeDDL + internals.migrationTable + this._escapeDDL + ' ORDER BY run_on DESC, name DESC'; - return this.all(sql, callback); - }, - - /** - * Queries the seeds table - * - * @param callback - */ - allLoadedSeeds: function(callback) { - var sql = 'SELECT * FROM ' + this._escapeDDL + internals.seedTable + this._escapeDDL + ' ORDER BY run_on DESC, name DESC'; - return this.all(sql, callback); - }, - - /** - * Deletes a migration - * - * @param migrationName - The name of the migration to be deleted - */ - deleteMigration: function(migrationName, callback) { - var sql = 'DELETE FROM ' + this._escapeDDL + internals.migrationTable + this._escapeDDL + ' WHERE name = ?'; - this.runSql(sql, [migrationName], callback); - }, - - /** - * Removes the specified keys from the database - * - * @param table - The table in which the to be deleted values are located - * @param ids - array or object - * id array - arrayof the to be deleted ids - * id object - { table: "name of the table to resolve the ids from", - * column: [ - * { - * name: "name of column", //defaults to id if unset - * operator: ">", //defaults to = if unset - * searchValue: "12", - * searchValue: { table: "source", column: [...] }, - * //recursion with objects possible - * link: "AND" //defaults to AND if unset - * } - * ] - * } - * - * @return Promise(runSql) - */ - remove: function(table, ids, callback) { - - var sql = 'DELETE FROM ' + this._escapeDDL + table + + this._escapeDDL; - var searchClause = ''; - - return this.runSql(sql + buildWhereClause(ids)).nodeify(callback); - }, - - /** - * Builds a where clause out of column objects. - * - * @param ids - array or object - * id array - arrayof the to be deleted ids - * id object - { table: "name of the table to resolve the ids from", - * column: [ - * { - * name: "name of column", //defaults to id if unset - * operator: ">", //defaults to = if unset - * searchValue: "12", - * searchValue: { table: "source", column: [...] }, - * //recursion with objects possible - * link: "AND" //defaults to AND if unset - * } - * ] - * } - * - * @return string - */ - buildWhereClause: function(ids) { - - var searchClause = ''; - - if (util.isArray(ids) && typeof(ids[0]) !== 'object' && ids.length > 1) { - - searchClause += 'WHERE id IN (' + ids.join(this._escapeString + ',' + this._escapeString) + ')'; - } - else if(typeof(ids) === 'string' || ids.length === 1) { - var id = (util.isArray(ids)) ? ids[0] : ids; - searchClause += 'WHERE id = ' + id; - } - else if (util.isArray(ids) && typeof(ids[0]) === 'object'){ - - - var preLink = '' - searchClause = ' WHERE '; - - for (var column in ids) { - column.name = column.name || 'id', - column.operator = column.operator || '=', - column.link = column.link || 'AND'; - - if (!column.searchValue) { - - return Promise.reject('column ' + column.name + ' was entered without a searchValue.'); - } - - searchClause += ' ' + preLink + ' ' + this._escapeDDL + - column.name + this._escapeDDL + ' ' + column.operator; - - if (typeof(searchValue) === 'object' && - typeof(searchValue.table) === 'string' && - typeof(searchValue.columns) === 'object') { - - searchClause += ' (SELECT ' + this._escapeDDL + column.selector + - this._escapeDDL + ' FROM ' + this._escapeDDL + - column.searchValue.table + this._escapeDDL + - buildWhereClause(column.searchValue.column) + ')'; - } - else { - - searchClause += ' (' + this._escapeString + column.searchValue + this._escapeString + ')'; - } - - preLink = column.link; - } - } - - return searchClause; - }, - - - /** - * Deletes a seed - * - * @param seedName - The name of the seed to be deleted - */ - deleteSeed: function(seedName, callback) { - var sql = 'DELETE FROM ' + this._escapeDDL + internals.seedTable + this._escapeDDL + ' WHERE name = ?'; - this.runSql(sql, [seedName], callback); - }, - - all: function(sql, params, callback) { - throw new Error('not implemented'); - }, - - escape: function(str) { - if(this._escapeString === '\'') - return str.replace(/'/g, "''"); - else - return str.replace(/"/g, '"'); - }, - - escapeString: function(str) { - - return this._escapeString + this.escape(str) + this._escapeString; - }, - - escapeDDL: function(str) { - - return this._escapeDDL + str + this._escapeDDL; - } -}); - -Promise.promisifyAll(Base); diff --git a/lib/driver/pg.js b/lib/driver/pg.js deleted file mode 100644 index b7006790..00000000 --- a/lib/driver/pg.js +++ /dev/null @@ -1,488 +0,0 @@ -var util = require('util'); -var pg = require('pg'); -var semver = require('semver'); -var Base = require('./base'); -var type = require('../data_type'); -var log = require('../log'); -var Promise = require('bluebird'); - -var internals = {}; - -var PgDriver = Base.extend({ - init: function(connection, schema) { - this._escapeString = '\''; - this._super(internals); - this.connection = connection; - this.schema = schema || "public"; - this.connection.connect(); - }, - - startMigration: function(cb){ - - if(!internals.notransactions) { - - return this.runSql('BEGIN;').nodeify(cb); - } - else - return Promise.resolve().nodeify(cb); - }, - - endMigration: function(cb){ - - if(!internals.notransactions) { - - return this.runSql('COMMIT;').nodeify(cb); - } - else - return Promise.resolve(null).nodeify(cb); - }, - - createColumnDef: function(name, spec, options, tableName) { - var type = spec.autoIncrement ? '' : this.mapDataType(spec.type); - var len = spec.length ? util.format('(%s)', spec.length) : ''; - var constraint = this.createColumnConstraint(spec, options, tableName, name); - if (name.charAt(0) != '"') { - name = '"' + name + '"'; - } - - return { foreignKey: constraint.foreignKey, - constraints: [name, type, len, constraint.constraints].join(' ') }; - }, - - mapDataType: function(str) { - switch(str) { - case type.STRING: - return 'VARCHAR'; - case type.DATE_TIME: - return 'TIMESTAMP'; - case type.BLOB: - return 'BYTEA'; - } - return this._super(str); - }, - - createDatabase: function(dbName, options, callback) { - - var spec = ''; - - if(typeof(options) === 'function') - callback = options; - - this.runSql(util.format('CREATE DATABASE `%s` %s', dbName, spec), callback); - }, - - dropDatabase: function(dbName, options, callback) { - - var ifExists = ''; - - if(typeof(options) === 'function') - callback = options; - else - { - ifExists = (options.ifExists === true) ? 'IF EXISTS' : ''; - } - - this.runSql(util.format('DROP DATABASE %s `%s`', ifExists, dbName), callback); - }, - - createSequence: function(sqName, options, callback) { - - var spec = '', - temp = ''; - - if(typeof(options) === 'function') - callback = options; - else - { - temp = (options.temp === true) ? 'TEMP' : ''; - } - - this.runSql(util.format('CREATE %s SEQUENCE `%s` %s', temp, sqName, spec), callback); - }, - - switchDatabase: function(options, callback) { - - if(typeof(options) === 'object') - { - if(typeof(options.database) === 'string') - { - log.info('Ignore database option, not available with postgres. Use schema instead!'); - this.runSql(util.format('SET search_path TO `%s`', options.database), callback); - } - } - else if(typeof(options) === 'string') - { - this.runSql(util.format('SET search_path TO `%s`', options), callback); - } - else - callback(null); - }, - - dropSequence: function(dbName, options, callback) { - - var ifExists = '', - rule = ''; - - if(typeof(options) === 'function') - callback = options; - else - { - ifExists = (options.ifExists === true) ? 'IF EXISTS' : ''; - - if(options.cascade === true) - rule = 'CASCADE'; - else if(options.restrict === true) - rule = 'RESTRICT'; - } - - this.runSql(util.format('DROP SEQUENCE %s `%s` %s', ifExists, dbName, rule), callback); - }, - - createMigrationsTable: function(callback) { - var options = { - columns: { - 'id': { type: type.INTEGER, notNull: true, primaryKey: true, autoIncrement: true }, - 'name': { type: type.STRING, length: 255, notNull: true}, - 'run_on': { type: type.DATE_TIME, notNull: true} - }, - ifNotExists: false - }; - - return this.all('select version() as version') - .then(function(result) { - - if (result && result && result.length > 0 && result[0].version) { - var version = result[0].version; - var match = version.match(/\d+\.\d+\.\d+/); - if (match && match[0] && semver.gte(match[0], '9.1.0')) { - options.ifNotExists = true; - } - } - - // Get the current search path so we can change the current schema - // if necessary - return this.all("SHOW search_path"); - }.bind(this)) - .then(function(result) { - - var searchPath, - search_pathes = result[0].search_path.split(','); - - for (var i = 0; i < search_pathes.length; ++i) { - if (search_pathes[i].indexOf('"') !== 0) { - search_pathes[i] = '"' + search_pathes[i].trim() + '"'; - } - } - - result[0].search_path = search_pathes.join(','); - - // if the user specified a different schema, prepend it to the - // search path. This will make all DDL/DML/SQL operate on the specified - // schema. - if (this.schema === 'public') { - searchPath = result[0].search_path; - } else { - searchPath = '"' + this.schema + '",' + result[0].search_path; - } - - return this.all('SET search_path TO ' + searchPath); - }.bind(this)) - .then(function() { - - return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + - internals.migrationTable + "'" + - ((this.schema) ? - " AND table_schema = '" + this.schema + "'" : - '')); - }.bind(this)) - .then(function(result) { - - if (result && result && result.length < 1) { - return this.createTable(internals.migrationTable, options); - } else { - return Promise.resolve(); - } - }.bind(this)).nodeify(callback); - }, - - createSeedsTable: function(callback) { - var options = { - columns: { - 'id': { type: type.INTEGER, notNull: true, primaryKey: true, autoIncrement: true }, - 'name': { type: type.STRING, length: 255, notNull: true}, - 'run_on': { type: type.DATE_TIME, notNull: true} - }, - ifNotExists: false - }; - - return this.all('select version() as version') - .then(function(result) { - - if (result && result && result.length > 0 && result[0].version) { - var version = result[0].version; - var match = version.match(/\d+\.\d+\.\d+/); - if (match && match[0] && semver.gte(match[0], '9.1.0')) { - options.ifNotExists = true; - } - } - - // Get the current search path so we can change the current schema - // if necessary - return this.all("SHOW search_path"); - }.bind(this)) - .then(function(result) { - - var searchPath; - - // if the user specified a different schema, prepend it to the - // search path. This will make all DDL/DML/SQL operate on the specified - // schema. - if (this.schema === 'public') { - searchPath = result[0].search_path; - } else { - searchPath = '"' + this.schema + '",' + result[0].search_path; - } - - return this.all('SET search_path TO ' + searchPath); - }.bind(this)) - .then(function() { - - return this.all("SELECT table_name FROM information_schema.tables WHERE table_name = '" + - internals.seedTable + "'" + - ((this.schema) ? - " AND table_schema = '" + this.schema + "'" : - '')); - }.bind(this)) - .then(function(result) { - - if (result && result && result.length < 1) { - return this.createTable(internals.seedTable, options); - } else { - return Promise.resolve(); - } - }.bind(this)).nodeify(callback); - }, - - createColumnConstraint: function(spec, options, tableName, columnName) { - var constraint = [], - cb; - - if (spec.primaryKey && options.emitPrimaryKey) { - if (spec.autoIncrement) { - constraint.push('SERIAL'); - } - constraint.push('PRIMARY KEY'); - } - - if (spec.notNull === true) { - constraint.push('NOT NULL'); - } - - if (spec.unique) { - constraint.push('UNIQUE'); - } - - if (typeof spec.defaultValue != 'undefined') { - constraint.push('DEFAULT'); - if (typeof spec.defaultValue == 'string'){ - constraint.push("'" + spec.defaultValue + "'"); - } else { - constraint.push(spec.defaultValue); - } - } - - if (spec.foreignKey) { - - cb = this.bindForeignKey(tableName, columnName, spec.foreignKey); - } - - return { foreignKey: cb, constraints: constraint.join(' ') }; - }, - - renameTable: function(tableName, newTableName, callback) { - var sql = util.format('ALTER TABLE "%s" RENAME TO "%s"', tableName, newTableName); - return this.runSql(sql).nodeify(callback); - }, - - removeColumn: function(tableName, columnName, callback) { - var sql = util.format('ALTER TABLE "%s" DROP COLUMN "%s"', tableName, columnName); - - return this.runSql(sql).nodeify(callback); - }, - - renameColumn: function(tableName, oldColumnName, newColumnName, callback) { - var sql = util.format('ALTER TABLE "%s" RENAME COLUMN "%s" TO "%s"', tableName, oldColumnName, newColumnName); - return this.runSql(sql).nodeify(callback); - }, - - changeColumn: function(tableName, columnName, columnSpec, callback) { - return setNotNull.call(this); - - function setNotNull() { - var setOrDrop = columnSpec.notNull === true ? 'SET' : 'DROP'; - var sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" %s NOT NULL', tableName, columnName, setOrDrop); - - return this.runSql(sql).nodeify(setUnique.bind(this)); - } - - function setUnique(err) { - if (err) { - return Promise.reject(err); - } - - var sql; - var constraintName = tableName + '_' + columnName + '_key'; - - if (columnSpec.unique === true) { - sql = util.format('ALTER TABLE "%s" ADD CONSTRAINT "%s" UNIQUE ("%s")', tableName, constraintName, columnName); - return this.runSql(sql).nodeify(setDefaultValue.bind(this)); - } else if (columnSpec.unique === false) { - sql = util.format('ALTER TABLE "%s" DROP CONSTRAINT "%s"', tableName, constraintName); - return this.runSql(sql).nodeify(setDefaultValue.bind(this)); - } else { - return setDefaultValue.call(this); - } - } - - function setDefaultValue(err) { - if (err) { - return Promise.reject(err).nodeify(callback); - } - - var sql; - - if (columnSpec.defaultValue !== undefined) { - var defaultValue = null; - if (typeof columnSpec.defaultValue == 'string'){ - defaultValue = "'" + columnSpec.defaultValue + "'"; - } else { - defaultValue = columnSpec.defaultValue; - } - sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" SET DEFAULT %s', tableName, columnName, defaultValue); - } else { - sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" DROP DEFAULT', tableName, columnName); - } - return this.runSql(sql).then( - setType.bind(this) - ).nodeify(callback); - } - - function setType() { - if (columnSpec.type !== undefined){ - var using = columnSpec.using !== undefined ? - columnSpec.using : util.format('USING "%s"::%s', columnName, this.mapDataType(columnSpec.type)) - var sql = util.format('ALTER TABLE "%s" ALTER COLUMN "%s" TYPE %s %s', tableName, columnName, this.mapDataType(columnSpec.type), using); - return this.runSql(sql); - } - } - }, - - addForeignKey: function(tableName, referencedTableName, keyName, fieldMapping, rules, callback) { - if(arguments.length === 5 && typeof(rules) === 'function') { - callback = rules; - rules = {}; - } - var columns = Object.keys(fieldMapping); - var referencedColumns = columns.map(function (key) { return '"' + fieldMapping[key] + '"'; }); - var sql = util.format('ALTER TABLE "%s" ADD CONSTRAINT "%s" FOREIGN KEY (%s) REFERENCES "%s" (%s) ON DELETE %s ON UPDATE %s', - tableName, keyName, this.quoteDDLArr(columns), referencedTableName, referencedColumns, rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION'); - return this.runSql(sql).nodeify(callback); - }, - - removeForeignKey: function(tableName, keyName, callback) { - var sql = util.format('ALTER TABLE "%s" DROP CONSTRAINT "%s"', tableName, keyName); - return this.runSql(sql).nodeify(callback); - }, - - insert: function() { - - var index = 1; - - if( arguments.length > 3 ) { - - index = 2; - } - - arguments[index] = arguments[index].map(function(value) { - return 'string' === typeof value ? value : JSON.stringify(value); - }); - - return this._super.apply(this, arguments); - }, - - runSql: function() { - var callback, - minLength = 1; - - if(typeof(arguments[arguments.length - 1]) === 'function') - { - minLength = 2; - callback = arguments[arguments.length - 1]; - } - - params = arguments; - if (params.length > minLength){ - // We have parameters, but db-migrate uses "?" for param substitutions. - // PG uses "$1", "$2", etc so fix up the "?" into "$1", etc - var param = params[0].split('?'), - new_param = []; - for (var i = 0; i < param.length-1; i++){ - new_param.push(param[i], "$" + (i+1)); - } - new_param.push(param[param.length-1]); - params[0] = new_param.join(''); - } - - log.sql.apply(null, params); - if(internals.dryRun) { - return Promise.resolve().nodeify(callback); - } - - return new Promise(function(resolve, reject) { - var prCB = function(err, data) { - return (err ? reject(err) : resolve(data)); - }; - - if( minLength === 2 ) - params[params.length - 1] = prCB; - else - params[params.length++] = prCB; - - this.connection.query.apply(this.connection, params); - }.bind(this)).nodeify(callback); - }, - - all: function() { - params = arguments; - - log.sql.apply(null, params); - - return new Promise(function(resolve, reject) { - var prCB = function(err, data) { - return (err ? reject(err) : resolve(data)); - }; - - this.connection.query.apply(this.connection, [params[0], function(err, result){ - prCB(err, result.rows); - }]); - - }.bind(this)).nodeify(params[1]); - }, - - close: function(callback) { - this.connection.end(); - return Promise.resolve().nodeify(callback); - } - -}); - -Promise.promisifyAll(PgDriver); - -exports.connect = function(config, intern, callback) { - - internals = intern; - - if (config.native) { pg = pg.native; } - var db = config.db || new pg.Client(config); - callback(null, new PgDriver(db, config.schema)); -}; diff --git a/package.json b/package.json index 401a00e9..33554a45 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,6 @@ "moment": "~2.10.2", "optimist": "~0.6.1", "parse-database-url": "~0.2.2", - "pg": "~4.4.0", "pkginfo": "~0.3.0", "resolve": "^1.1.6", "semver": "~5.0.1", @@ -64,6 +63,7 @@ "db-migrate-base": "^1.2.1", "db-migrate-mongodb": "^1.0.1", "db-migrate-mysql": "^1.1.2", + "db-migrate-pg": "^0.1.2", "db-migrate-sqlite3": "^0.1.2", "lab": "^5.2.1", "mysql": "^2.9.0", From 9dc969b07a8c00c754baeaddea12ad5bcc6daa67 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 15:40:28 +0200 Subject: [PATCH 206/412] add pg to dev dependencies --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 33554a45..431d441c 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "db-migrate-sqlite3": "^0.1.2", "lab": "^5.2.1", "mysql": "^2.9.0", + "pg": "^4.4.1", "proxyquire": "^1.4.0", "rimraf": "~2.4.0", "sinon": "^1.14.1", From e8092539af8eb65aef044950f01a9ae545705170 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 16:00:00 +0200 Subject: [PATCH 207/412] ? --- test/driver/pg_schema_test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js index 700bcc5b..a719fab8 100644 --- a/test/driver/pg_schema_test.js +++ b/test/driver/pg_schema_test.js @@ -18,6 +18,7 @@ vows.describe('pg').addBatch({ var client = new pg.Client(databaseUrl); client.connect(function (err) { + console.log('hello', err) if (err) { return callback(err); } client.query('CREATE SCHEMA "test-schema"', function(err) { driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test-schema' }, internals, function(err, db) { From 4040c47f19ff4c4e3212def2c052620e828fb599 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 17:47:23 +0200 Subject: [PATCH 208/412] updated fixed pg driver --- package.json | 2 +- test/driver/pg_schema_test.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 431d441c..7ea307a6 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "db-migrate-base": "^1.2.1", "db-migrate-mongodb": "^1.0.1", "db-migrate-mysql": "^1.1.2", - "db-migrate-pg": "^0.1.2", + "db-migrate-pg": "^0.1.3", "db-migrate-sqlite3": "^0.1.2", "lab": "^5.2.1", "mysql": "^2.9.0", diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js index a719fab8..700bcc5b 100644 --- a/test/driver/pg_schema_test.js +++ b/test/driver/pg_schema_test.js @@ -18,7 +18,6 @@ vows.describe('pg').addBatch({ var client = new pg.Client(databaseUrl); client.connect(function (err) { - console.log('hello', err) if (err) { return callback(err); } client.query('CREATE SCHEMA "test-schema"', function(err) { driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test-schema' }, internals, function(err, db) { From a11f652d0bf7391254d845d0eb845c296b82fb9c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 22:22:07 +0200 Subject: [PATCH 209/412] add error message to executeDB and handle callback --- api.js | 14 ++++++++------ package.json | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/api.js b/api.js index bda40db0..8ac0b778 100644 --- a/api.js +++ b/api.js @@ -695,28 +695,30 @@ function executeDB(internals, callback) { if (internals.mode === 'create') { db.createDatabase(internals.argv.dbname, { ifNotExists: true - }, function() { + }, function(err) { if (err) { - log.info('Error: Failed to create database!'); + log.info('Error: Failed to create database!', err.error); } else { log.info('Created database "' + internals.argv.dbname + '"'); } db.close(); - callback(); + if( typeof(callback) === 'function' ) + callback(); }); } else if (internals.mode === 'drop') { db.dropDatabase(internals.argv.dbname, { ifExists: true - }, function() { + }, function(err) { if (err) { - log.info('Error: Failed to drop database!'); + log.info('Error: Failed to drop database!', err.error); } else { log.info('Deleted database "' + internals.argv.dbname + '"'); } db.close(); - callback(); + if( typeof(callback) === 'function' ) + callback(); }); } else return; diff --git a/package.json b/package.json index 7ea307a6..346d0fe7 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "db-migrate-base": "^1.2.1", "db-migrate-mongodb": "^1.0.1", "db-migrate-mysql": "^1.1.2", - "db-migrate-pg": "^0.1.3", + "db-migrate-pg": "^0.1.4", "db-migrate-sqlite3": "^0.1.2", "lab": "^5.2.1", "mysql": "^2.9.0", From f0b7d314f0ffd10f6e805a59b4275fa2667024ca Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 10 Sep 2015 22:24:41 +0200 Subject: [PATCH 210/412] return error message if available or the object/message directly passed through --- api.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/api.js b/api.js index 8ac0b778..1988315d 100644 --- a/api.js +++ b/api.js @@ -697,7 +697,9 @@ function executeDB(internals, callback) { ifNotExists: true }, function(err) { if (err) { - log.info('Error: Failed to create database!', err.error); + if( err.error ) + err = err.error; + log.info('Error: Failed to create database!', err); } else { log.info('Created database "' + internals.argv.dbname + '"'); } @@ -711,7 +713,9 @@ function executeDB(internals, callback) { ifExists: true }, function(err) { if (err) { - log.info('Error: Failed to drop database!', err.error); + if( err.error ) + err = err.error; + log.info('Error: Failed to drop database!', err); } else { log.info('Deleted database "' + internals.argv.dbname + '"'); } From 8248b09cabe708a2aea75ef60631e679d5c04b4a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 14 Sep 2015 23:54:26 +0200 Subject: [PATCH 211/412] fix some cs issues --- test/driver/pg_schema_test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js index 700bcc5b..a6b19b92 100644 --- a/test/driver/pg_schema_test.js +++ b/test/driver/pg_schema_test.js @@ -32,7 +32,7 @@ vows.describe('pg').addBatch({ var callback = this.callback; db.createMigrationsTable(function() { - client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test-schema' AND table_name = 'migrations'", function(err, result) { + client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test-schema\' AND table_name = \'migrations\'', function(err, result) { callback(err, result); }); }); @@ -63,7 +63,7 @@ vows.describe('pg').addBatch({ var query = Promise.promisify( client.query ).bind(client); client.connect(function (err) { - if (err) { return callback(err) }; + if (err) { return callback(err); } Promise.all([ query('CREATE SCHEMA test_schema'), query('CREATE TABLE migrations ()') @@ -85,7 +85,7 @@ vows.describe('pg').addBatch({ var callback = this.callback; db.createMigrationsTable(function() { - client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", function(err, result) { + client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test_schema\' AND table_name = \'migrations\'', function(err, result) { callback(err, result); }); }); @@ -137,7 +137,7 @@ vows.describe('pg').addBatch({ var callback = this.callback; db.createMigrationsTable(function() { - client.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", function(err, result) { + client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test_schema\' AND table_name = \'migrations\'', function(err, result) { callback(err, result); }); }); From 2145e08303112b39a8bca851ae5a0dc740a61f28 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 16 Sep 2015 19:13:17 +0200 Subject: [PATCH 212/412] add missing nosql methods to interface --- lib/interface/migratorInterface.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 33d28ad1..5a6b9b16 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -36,6 +36,12 @@ function MigratorInterface() { MigratorInterface.prototype = { + renameCollection: dummy, + + dropCollection: dummy, + + createCollection: dummy, + checkDBMS: dummy, createDatabase: dummy, From 158c7188f2ee0f3caf9c87131986b03e6aa4ea6c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 16 Sep 2015 22:16:12 +0200 Subject: [PATCH 213/412] do not strip private functions from driver removed unnecessary entries from migrator interface do not strip any `_function` unless it is explicitly defined via exclude --- lib/interface/migratorInterface.js | 2 -- lib/util.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 5a6b9b16..ba8a1cbd 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -88,8 +88,6 @@ MigratorInterface.prototype = { createColumnConstraint: dummy, - _makeParamArgs: dummy, - recurseCallbackArray: dummy, allLoadedMigrations: dummy, diff --git a/lib/util.js b/lib/util.js index 172d17ab..768b372a 100644 --- a/lib/util.js +++ b/lib/util.js @@ -50,7 +50,7 @@ exports.reduceToInterface = function(db, originInterface) { for(var prop in db) { - if( typeof(db[prop]) !== "function" && + if( ( prop[0] === '_' || typeof(db[prop]) !== "function") && originInterface.exclude[prop] === undefined ) { Interface[prop] = db[prop]; From 9fc1745f980194a2f7927d5ac699ecfe1009c933 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 18 Sep 2015 18:08:45 +0200 Subject: [PATCH 214/412] change config to internal scope --- api.js | 59 ++++++++++++++++++++------------------ connect.js | 2 +- lib/config.js | 79 ++++++++++++++++++++++++++++----------------------- 3 files changed, 75 insertions(+), 65 deletions(-) diff --git a/api.js b/api.js index 1988315d..9f711370 100644 --- a/api.js +++ b/api.js @@ -4,7 +4,6 @@ var path = require('path'); var util = require('util'); var mkdirp = require('mkdirp'); var optimist = require('optimist'); -var config = require('./lib/config.js'); var index = require('./connect'); var Migration = require('./lib/migration.js'); var Seeder = require('./lib/seeder.js'); @@ -59,16 +58,17 @@ function dbmigrate(isModule, options, callback) { } else setDefaultArgv(this.internals, isModule); - loadConfig(); + this.config = loadConfig( require('./lib/config.js'), this.internals ); + index.exportInternals(internals); - internals.dbm = dbm; + this.internals.dbm = dbm; global.dbm = dbm; //deprecated - internals.migrationOptions = { - dbmigrate: internals.dbm, - ignoreOnInit: internals['argv']['ignore-on-init'] + this.internals.migrationOptions = { + dbmigrate: this.internals.dbm, + ignoreOnInit: this.internals['argv']['ignore-on-init'] }; - internals.seederOptions = { - dbmigrate: internals.dbm + this.internals.seederOptions = { + dbmigrate: this.internals.dbm }; } @@ -168,7 +168,7 @@ dbmigrate.prototype = { } } - executeUp(this.internals, callback); + executeUp(this.internals, this.config, callback); }, /** @@ -190,7 +190,7 @@ dbmigrate.prototype = { } } - executeDown(this.internals, callback); + executeDown(this.internals, this.config, callback); }, /** @@ -204,7 +204,7 @@ dbmigrate.prototype = { } this.internals.argv.count = Number.MAX_VALUE; - executeDown(this.internals, callback); + executeDown(this.internals, this.config, callback); }, /** @@ -239,7 +239,7 @@ dbmigrate.prototype = { this.internals.argv._.push(dbname); this.internals.mode = 'create'; - executeDB(this.internals, callback); + executeDB(this.internals, this.config, callback); }, /** @@ -249,7 +249,7 @@ dbmigrate.prototype = { this.internals.argv._.push(dbname); this.internals.mode = 'drop'; - executeDB(this.internals, callback); + executeDB(this.internals, this.config, callback); }, /** @@ -292,7 +292,7 @@ dbmigrate.prototype = { } this.internals.mode = mode || 'vc'; - executeSeed(this.internals, callback); + executeSeed(this.internals, this.config, callback); }, /** @@ -321,7 +321,7 @@ dbmigrate.prototype = { */ run: function() { - run(this.internals); + run(this.internals, this.config); } @@ -462,14 +462,15 @@ function createMigrationDir(dir, callback) { }); } -function loadConfig() { +function loadConfig( config, internals ) { + var out; if (process.env.DATABASE_URL) { - config.loadUrl(process.env.DATABASE_URL, internals.argv.env); + out = config.loadUrl(process.env.DATABASE_URL, internals.argv.env); } else { - config.load(internals.argv.config, internals.argv.env); + out = config.load(internals.argv.config, internals.argv.env); } if (internals.verbose) { - var current = config.getCurrent(); + var current = out.getCurrent(); var s = JSON.parse(JSON.stringify(current.settings)); if (s.password) @@ -477,6 +478,8 @@ function loadConfig() { log.info('Using', current.env, 'settings:', s); } + + return out; } function executeCreateMigration(internals, callback) { @@ -629,7 +632,7 @@ function _assert(err, callback) { return true; } -function executeUp(internals, callback) { +function executeUp(internals, config, callback) { if (!internals.argv.count) { internals.argv.count = Number.MAX_VALUE; @@ -658,7 +661,7 @@ function executeUp(internals, callback) { }); } -function executeDown(internals, callback) { +function executeDown(internals, config, callback) { if (!internals.argv.count) { log.info('Defaulting to running 1 down migration.'); @@ -681,7 +684,7 @@ function executeDown(internals, callback) { }); } -function executeDB(internals, callback) { +function executeDB(internals, config, callback) { if (internals.argv._.length > 0) { internals.argv.dbname = internals.argv._.shift().toString(); @@ -730,7 +733,7 @@ function executeDB(internals, callback) { } -function executeSeed(internals, callback) { +function executeSeed(internals, config, callback) { if (internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); @@ -795,7 +798,7 @@ function onComplete(migrator, callback, originalErr) { }); } -function run(internals) { +function run(internals, config) { var action = internals.argv._.shift(), folder = action.split(':'); @@ -834,9 +837,9 @@ function run(internals) { } if (action == 'up') { - executeUp(internals); + executeUp(internals, config); } else { - executeDown(internals); + executeDown(internals, config); } break; @@ -848,7 +851,7 @@ function run(internals) { } else { internals.mode = folder[1]; - executeDB(internals); + executeDB(internals, config); } break; case 'seed': @@ -861,7 +864,7 @@ function run(internals) { internals.argv._.shift(); } else { - executeSeed(internals); + executeSeed(internals, config); } break; diff --git a/connect.js b/connect.js index c6065676..0ab1c3ca 100644 --- a/connect.js +++ b/connect.js @@ -103,8 +103,8 @@ function migrationFiles(files, callback, config, passedClass, db, close, cb) { if(file !== '') { - try { + fs.statSync(path.resolve(file + '/config.json')); newConf = require(path.resolve(file + '/config.json')); log.info('loaded extra config for migration subfolder: "' + file + '/config.json"'); switched = true; diff --git a/lib/config.js b/lib/config.js index 8456a79a..65f56ac9 100644 --- a/lib/config.js +++ b/lib/config.js @@ -3,13 +3,39 @@ var path = require('path'); var parseDatabaseUrl = require('parse-database-url'); var dbmUtil = require('./util'); +var setCurrent = exports.setCurrent = function (env) { + env = dbmUtil.isArray(env) ? env : [env]; + env.forEach(function (current) { + if (dbmUtil.isString(current) && this[current]) { + this.getCurrent = function () { + return { + env: current, + settings: this[current] + }; + }; + } + }.bind(this)); + + if (!this.getCurrent) { + throw new Error("Environment(s) '" + env.join(', ') + "' not found."); + } +}; + +function Config() { +} + +Config.prototype = { + setCurrent: setCurrent +}; + exports.load = function(fileName, currentEnv) { try { fs.statSync(fileName); } catch(e) { throw new Error("Could not find database config file '" + fileName + "'"); } - var config; + var config, + out = new Config(); try { config = require(fileName); @@ -24,9 +50,9 @@ exports.load = function(fileName, currentEnv) { for (var env in config) { if (config[env].ENV) { - exports[env] = parseDatabaseUrl(process.env[config[env].ENV]); + out[env] = parseDatabaseUrl(process.env[config[env].ENV]); } else if (typeof(config[env]) === 'string') { - exports[env] = parseDatabaseUrl(config[env]); + out[env] = parseDatabaseUrl(config[env]); } else { //Check config entry's for ENV objects //which will tell us to grab configuration from the environment @@ -35,53 +61,34 @@ exports.load = function(fileName, currentEnv) { config[env][configEntry] = process.env[config[env][configEntry].ENV]; } } - exports[env] = config[env]; + out[env] = config[env]; } } if(currentEnv) { - setCurrent(currentEnv); + out.setCurrent(currentEnv); } else if(config['default']) { - setCurrent(config['default']); + out.setCurrent(config['default']); } else if(config.env) { - setCurrent(config.env); + out.setCurrent(config.env); } else { - setCurrent(['dev', 'development']); + out.setCurrent(['dev', 'development']); } - // delete exports.load; - // delete exports.loadUrl; + return out; }; exports.loadUrl = function(databaseUrl, currentEnv) { - var config = parseDatabaseUrl(databaseUrl); + var config = parseDatabaseUrl(databaseUrl), + out = new Config(); + if (currentEnv) { - exports[currentEnv] = config; - setCurrent(currentEnv); + out[currentEnv] = config; + out.setCurrent(currentEnv); } else { - exports.urlConfig = config; - setCurrent('urlConfig'); + out.urlConfig = config; + out.setCurrent('urlConfig'); } - // delete exports.load; - // delete exports.loadUrl; + return out; } - -var setCurrent = exports.setCurrent = function (env) { - env = dbmUtil.isArray(env) ? env : [env]; - - env.forEach(function (current) { - if (dbmUtil.isString(current) && exports[current]) { - exports.getCurrent = function () { - return { - env: current, - settings: exports[current] - }; - }; - } - }); - - if (!exports.getCurrent) { - throw new Error("Environment(s) '" + env.join(', ') + "' not found."); - } -}; From d1c0aa663208e07cb3cb3a8e5f0959a8359cb2b5 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 19 Sep 2015 01:09:36 +0200 Subject: [PATCH 215/412] fix test for new internal config --- test/config_test.js | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/test/config_test.js b/test/config_test.js index 360375c8..7c4ce41f 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -10,10 +10,7 @@ vows.describe('config').addBatch({ 'loading from a file': { topic: function() { var configPath = path.join(__dirname, 'database.json'); - config.load = _configLoad; - config.loadUrl = _configLoadUrl; - config.load(configPath, 'dev'); - return config; + return config.load(configPath, 'dev'); }, 'should export all environment settings': function (config) { @@ -34,8 +31,6 @@ vows.describe('config').addBatch({ 'loading from a broken config file': { topic: function() { var configPath = path.join(__dirname, 'database_with_syntax_error.json'); - config.load = _configLoad; - config.loadUrl = _configLoadUrl; try { config.load(configPath, 'dev'); } catch (e) { @@ -54,10 +49,7 @@ vows.describe('config').addBatch({ topic: function() { process.env['DB_MIGRATE_TEST_VAR'] = 'username_from_env'; var configPath = path.join(__dirname, 'database_with_env.json'); - config.load = _configLoad; - config.loadUrl = _configLoadUrl; - config.load(configPath, 'prod'); - return config; + return config.load(configPath, 'prod'); }, 'should load a value from the environments': function (config) { @@ -70,10 +62,7 @@ vows.describe('config').addBatch({ topic: function() { process.env['DB_MIGRATE_TEST_VAR'] = 'postgres://uname:pw@server.com/dbname'; var configPath = path.join(__dirname, 'database_with_env_url.json'); - config.load = _configLoad; - config.loadUrl = _configLoadUrl; - config.load(configPath, 'prod'); - return config; + return config.load(configPath, 'prod'); }, 'should load a value from the environments': function (config) { @@ -90,10 +79,7 @@ vows.describe('config').addBatch({ 'loading from an URL': { topic: function() { var databaseUrl = 'postgres://uname:pw@server.com/dbname'; - config.load = _configLoad; - config.loadUrl = _configLoadUrl; - config.loadUrl(databaseUrl, 'dev'); - return config; + return config.loadUrl(databaseUrl, 'dev'); }, 'should export the settings as the current environment': function (config) { From e2bca146d99411cf8febcb0337484964ae69c742 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 20 Sep 2015 13:34:03 +0200 Subject: [PATCH 216/412] fix last details to move config i into internal scope --- api.js | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/api.js b/api.js index 9f711370..c17135ab 100644 --- a/api.js +++ b/api.js @@ -76,6 +76,7 @@ function registerEvents() { process.on('uncaughtException', function(err) { log.error(err.stack); +console.log(err.stack); process.exit(1); }); @@ -229,7 +230,7 @@ dbmigrate.prototype = { } this.internals.argv._.push(migrationName); - executeCreateMigration(this.internals, callback); + executeCreateMigration(this.internals, this.config, callback); }, /** @@ -482,7 +483,7 @@ function loadConfig( config, internals ) { return out; } -function executeCreateMigration(internals, callback) { +function executeCreateMigration(internals, config, callback) { var migrationsDir = internals.argv['migrations-dir']; if (internals.migrationMode && internals.migrationMode !== 'all') { @@ -523,17 +524,23 @@ function executeCreateMigration(internals, callback) { } var templateType = Migration.TemplateType.DEFAULT_JS; - if (shouldCreateSqlFiles() && shouldCreateCoffeeFile()) { + if (shouldCreateSqlFiles( internals, config ) && + shouldCreateCoffeeFile( internals, config )) { + templateType = Migration.TemplateType.COFFEE_SQL_FILE_LOADER; - } else if (shouldCreateSqlFiles() && shouldIgnoreOnInitFiles()) { + } else if (shouldCreateSqlFiles( internals, config ) && + shouldIgnoreOnInitFiles( internals, config )) { + templateType = Migration.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT; - } else if (shouldCreateSqlFiles()) { + } else if (shouldCreateSqlFiles( internals, config )) { + templateType = Migration.TemplateType.SQL_FILE_LOADER; - } else if (shouldCreateCoffeeFile()) { + } else if (shouldCreateCoffeeFile( internals, config )) { + templateType = Migration.TemplateType.DEFAULT_COFFEE; } var migration = new Migration(internals.argv.title + ( - shouldCreateCoffeeFile() ? '.coffee' : '.js'), path, new Date(), + shouldCreateCoffeeFile( internals, config ) ? '.coffee' : '.js'), path, new Date(), templateType); index.createMigration(migration, function(err, migration) { if (_assert(err, callback)) { @@ -543,8 +550,8 @@ function executeCreateMigration(internals, callback) { }); }); - if (shouldCreateSqlFiles(internals)) { - createSqlFiles(internals, callback); + if (shouldCreateSqlFiles(internals, config)) { + createSqlFiles(internals, config, callback); } else { if (typeof(callback) === 'function') { @@ -553,20 +560,20 @@ function executeCreateMigration(internals, callback) { } } -function shouldCreateSqlFiles() { +function shouldCreateSqlFiles( internals, config ) { return internals.argv['sql-file'] || config['sql-file']; } -function shouldIgnoreOnInitFiles() { +function shouldIgnoreOnInitFiles( internals, config ) { return internals.argv['ignore-on-init'] || config[ 'ignore-on-init']; } -function shouldCreateCoffeeFile() { +function shouldCreateCoffeeFile( intenrals, config ) { return internals.argv['coffee-file'] || config['coffee-file']; } -function createSqlFiles(internals, callback) { +function createSqlFiles(internals, config, callback) { var migrationsDir = internals.argv['migrations-dir']; if (internals.migrationMode && internals.migrationMode !== 'all') { @@ -811,7 +818,7 @@ function run(internals, config) { internals.matching = folder[1]; internals.migrationMode = folder[1]; } - executeCreateMigration(internals); + executeCreateMigration(internals, config); break; case 'up': case 'down': From 771520685cdc215afa354ac3139671c7ff9ab3b0 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 20 Sep 2015 13:40:57 +0200 Subject: [PATCH 217/412] remove debug message --- api.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api.js b/api.js index c17135ab..16e07c3e 100644 --- a/api.js +++ b/api.js @@ -76,7 +76,6 @@ function registerEvents() { process.on('uncaughtException', function(err) { log.error(err.stack); -console.log(err.stack); process.exit(1); }); @@ -536,7 +535,7 @@ function executeCreateMigration(internals, config, callback) { templateType = Migration.TemplateType.SQL_FILE_LOADER; } else if (shouldCreateCoffeeFile( internals, config )) { - + templateType = Migration.TemplateType.DEFAULT_COFFEE; } var migration = new Migration(internals.argv.title + ( From 03b77a5706aec551407c9341da2e401b6b0bd6a3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 22 Sep 2015 01:26:29 +0200 Subject: [PATCH 218/412] remove es5 from jshint rules, fix one cs --- .jshintrc | 1 - api.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.jshintrc b/.jshintrc index 4d91c6d0..b8794ae7 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,5 +1,4 @@ { - "es5": true, "expr": true, "-W092": false, "quotmark": true diff --git a/api.js b/api.js index 16e07c3e..c8dd2e74 100644 --- a/api.js +++ b/api.js @@ -65,7 +65,7 @@ function dbmigrate(isModule, options, callback) { global.dbm = dbm; //deprecated this.internals.migrationOptions = { dbmigrate: this.internals.dbm, - ignoreOnInit: this.internals['argv']['ignore-on-init'] + ignoreOnInit: this.internals.argv.ignore-on-init }; this.internals.seederOptions = { dbmigrate: this.internals.dbm From 36c1110d1a92a07cdd3d00a35b00b6d25c915e40 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 23 Sep 2015 23:28:45 +0200 Subject: [PATCH 219/412] add rules to jshint --- .jshintrc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.jshintrc b/.jshintrc index b8794ae7..4a0d06c8 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,5 +1,8 @@ { "expr": true, "-W092": false, - "quotmark": true + "quotmark": true, + "curly": false, + "bitwise": false, + "eqeqeq": true } From e9fd4a26ee90b161a6cf3bfc0a7a8ba9deb9679b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 24 Sep 2015 00:35:07 +0200 Subject: [PATCH 220/412] fix some cs issues and adjust rules --- .jshintrc | 4 +++- api.js | 4 ++-- lib/class.js | 4 ++-- lib/config.js | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.jshintrc b/.jshintrc index 4a0d06c8..37e7d63b 100644 --- a/.jshintrc +++ b/.jshintrc @@ -4,5 +4,7 @@ "quotmark": true, "curly": false, "bitwise": false, - "eqeqeq": true + "eqeqeq": true, + "funcscope": true, + "futurehostile": true } diff --git a/api.js b/api.js index c8dd2e74..1a8b2762 100644 --- a/api.js +++ b/api.js @@ -14,8 +14,8 @@ var dotenv = require('dotenv'); //global declaration for detection like it's done in umigrate //deprecated -dbm = require('./'); //deprecated -async = require('async'); //deprecated +global.dbm = require('./'); //deprecated +global.async = require('async'); //deprecated var internals = {}; diff --git a/lib/class.js b/lib/class.js index 5dd9eae1..9aea5864 100644 --- a/lib/class.js +++ b/lib/class.js @@ -21,8 +21,8 @@ Class.extend = function(prop) { // Copy the properties over onto the new prototype for (var name in prop) { // Check if we're overwriting an existing function - prototype[name] = typeof prop[name] == "function" && - typeof _super[name] == "function" && fnTest.test(prop[name]) ? + prototype[name] = typeof prop[name] === "function" && + typeof _super[name] === "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; diff --git a/lib/config.js b/lib/config.js index 65f56ac9..059bd175 100644 --- a/lib/config.js +++ b/lib/config.js @@ -17,7 +17,7 @@ var setCurrent = exports.setCurrent = function (env) { }.bind(this)); if (!this.getCurrent) { - throw new Error("Environment(s) '" + env.join(', ') + "' not found."); + throw new Error('Environment(s) \'' + env.join(', ') + '\' not found.'); } }; @@ -32,7 +32,7 @@ exports.load = function(fileName, currentEnv) { try { fs.statSync(fileName); } catch(e) { - throw new Error("Could not find database config file '" + fileName + "'"); + throw new Error('Could not find database config file \'' + fileName + '\''); } var config, out = new Config(); @@ -91,4 +91,4 @@ exports.loadUrl = function(databaseUrl, currentEnv) { } return out; -} +}; From b2dc3cbce2a18696e2a864a62de0870db60c7712 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 25 Sep 2015 23:41:13 +0200 Subject: [PATCH 221/412] adjust some settings and add jscs already --- .jshintrc | 5 ++++- package.json | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.jshintrc b/.jshintrc index 37e7d63b..820fd6ed 100644 --- a/.jshintrc +++ b/.jshintrc @@ -6,5 +6,8 @@ "bitwise": false, "eqeqeq": true, "funcscope": true, - "futurehostile": true + "futurehostile": true, + "nonew": true, + "unused": true, + "loopfunc": true } diff --git a/package.json b/package.json index 346d0fe7..87c82a9c 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "db-migrate-mysql": "^1.1.2", "db-migrate-pg": "^0.1.4", "db-migrate-sqlite3": "^0.1.2", + "jscs": "^2.1.1", "lab": "^5.2.1", "mysql": "^2.9.0", "pg": "^4.4.1", From 407b96e31fe9df743ba8f78c99f07d8df5ca7449 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 26 Sep 2015 01:13:48 +0200 Subject: [PATCH 222/412] [cs] fixed some issues and do some cleanup --- .jscsrc | 0 .jshintignore | 3 +- .jshintrc | 1 + api.js | 4 +- connect.js | 1 - index.js | 2 +- lib/log.js | 6 +- lib/migration.js | 374 +++++++++++++++++++++++------------------------ lib/migrator.js | 1 - lib/seed.js | 9 +- lib/skeleton.js | 2 - lib/util.js | 30 ++-- 12 files changed, 214 insertions(+), 219 deletions(-) create mode 100644 .jscsrc diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 00000000..e69de29b diff --git a/.jshintignore b/.jshintignore index b512c09d..998bc454 100644 --- a/.jshintignore +++ b/.jshintignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules +lib/inflection.js diff --git a/.jshintrc b/.jshintrc index 820fd6ed..12884343 100644 --- a/.jshintrc +++ b/.jshintrc @@ -9,5 +9,6 @@ "futurehostile": true, "nonew": true, "unused": true, + "shadow": true, "loopfunc": true } diff --git a/api.js b/api.js index 1a8b2762..7f5d9923 100644 --- a/api.js +++ b/api.js @@ -9,7 +9,7 @@ var Migration = require('./lib/migration.js'); var Seeder = require('./lib/seeder.js'); var Migrator = require('./lib/migrator.js'); var log = require('./lib/log'); -var pkginfo = require('pkginfo')(module, 'version'); +var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line var dotenv = require('dotenv'); @@ -65,7 +65,7 @@ function dbmigrate(isModule, options, callback) { global.dbm = dbm; //deprecated this.internals.migrationOptions = { dbmigrate: this.internals.dbm, - ignoreOnInit: this.internals.argv.ignore-on-init + ignoreOnInit: this.internals.argv['ignore-on-init'] }; this.internals.seederOptions = { dbmigrate: this.internals.dbm diff --git a/connect.js b/connect.js index 0ab1c3ca..ec3fb9fa 100644 --- a/connect.js +++ b/connect.js @@ -8,7 +8,6 @@ var internals = {}; exports.connect = function(config, passedClass, callback) { var internals = {}; - var _config = config; if( config.config ) { internals = config.internals; config = config.config; diff --git a/index.js b/index.js index c9a3f84a..959f882e 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -var pkginfo = require('pkginfo')(module, 'version'); +var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line exports.dataType = require('./lib/data_type'); diff --git a/lib/log.js b/lib/log.js index 8532333a..6d770e3c 100644 --- a/lib/log.js +++ b/lib/log.js @@ -42,7 +42,7 @@ exports.setEscape = function( escapeChar ) { }; exports.silence = function (isSilent) { - return this.isSilent = isSilent; + return ( this.isSilent = isSilent ); }; exports.info = function () { if ((!this.isSilent || global.verbose) && @@ -54,14 +54,14 @@ exports.info = function () { exports.warn = function () { if ((!this.isSilent || global.verbose) && logLevel & level.warn) { - var args = Array.prototype.unshift.call(arguments, '[WARN]'); + Array.prototype.unshift.call(arguments, '[WARN]'); console.warn.apply(console, arguments); } }; exports.error = function () { if ((!this.isSilent || global.verbose) && logLevel & level.error) { - var args = Array.prototype.unshift.call(arguments, '[ERROR]'); + Array.prototype.unshift.call(arguments, '[ERROR]'); //console.trace( 'Trace from error log' ); console.error.apply(console, arguments); } diff --git a/lib/migration.js b/lib/migration.js index 2db3ebda..d55830d7 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -1,6 +1,5 @@ var fs = require('fs'); var path = require('path'); -var config = require('./config'); var log = require('./log'); var Skeleton = require('./skeleton'); @@ -31,7 +30,7 @@ var Migration = Skeleton.extend({ this.path = this.formatPath(arguments[1], this.name); this.templateType = arguments[3]; this.internals = arguments[4]; - } else if (arguments.length == 2) { + } else if (arguments.length === 2) { this.path = arguments[0]; this.name = this.parseName(this.path); this.date = this.parseDate(this.name); @@ -45,212 +44,212 @@ var Migration = Skeleton.extend({ 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;", - " return", - "", - "exports.up = (db, callback) ->", - "", - "", - "exports.down = (db, callback) ->", - "", - "", - "" - ].join("\n"); + '\'use strict\';', + '', + 'dbm = undefined', + 'type = undefined', + 'seed = undefined', + '', + 'exports.setup = (options, seedLink) ->', + ' dbm = options.dbmigrate;', + ' type = dbm.dataType;', + ' seed = seedLink;', + ' return', + '', + 'exports.up = (db, callback) ->', + '', + '', + 'exports.down = (db, callback) ->', + '', + '', + '' + ].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, callback) {", - " callback();", - "};", - "", - "exports.down = function(db, callback) {", - " callback();", - "};", - "" - ].join("\n"); + '\'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, callback) {', + ' callback();', + '};', + '', + 'exports.down = function(db, callback) {', + ' callback();', + '};', + '' + ].join('\n'); }; Migration.prototype.defaultSqlTemplate = function() { - return "/* Replace with your SQL commands */"; + 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');", - "", - "/**", - " * 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, callback) {", - " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( - '.js', '') + "-up.sql');", - " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", - " if (err) return callback(err);", - " console.log('received data: ' + data);", - "", - " db.runSql(data, function(err) {", - " if (err) return callback(err);", - " callback();", - " });", - " });", - "};", - "", - "exports.down = function(db, callback) {", - " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( - '.js', '') + "-down.sql');", - " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", - " if (err) return callback(err);", - " console.log('received data: ' + data);", - "", - " db.runSql(data, function(err) {", - " if (err) return callback(err);", - " callback();", - " });", - " });", - "};", - "" - ].join("\n"); + '\'use strict\';', + '', + 'var dbm;', + 'var type;', + 'var seed;', + 'var fs = require(\'fs\');', + 'var path = require(\'path\');', + '', + '/**', + ' * 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, callback) {', + ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( + '.js', '') + '-up.sql\');', + ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', + ' if (err) return callback(err);', + ' console.log(\'received data: \' + data);', + '', + ' db.runSql(data, function(err) {', + ' if (err) return callback(err);', + ' callback();', + ' });', + ' });', + '};', + '', + 'exports.down = function(db, callback) {', + ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( + '.js', '') + '-down.sql\');', + ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', + ' if (err) return callback(err);', + ' console.log(\'received data: \' + data);', + '', + ' db.runSql(data, function(err) {', + ' if (err) return callback(err);', + ' callback();', + ' });', + ' });', + '};', + '' + ].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;", + '\'use strict\';', + '', + 'var dbm;', + 'var type;', + 'var seed;', + 'var fs = require(\'fs\');', + 'var path = require(\'path\');', + 'var ignoreOnInit = false;', - "", - "/**", - " * 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;", - "};", - "", - "exports.up = function(db, callback) {", - " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( - '.js', '') + "-up.sql');", - " if (!ignoreOnInit) {", - " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", - " if (err) return callback(err);", - " console.log('received data: ' + data);", - "", - " db.runSql(data, function(err) {", - " if (err) return callback(err);", - " callback();", - " });", - " });", - " }", - " else {", - " console.log('ignoring on init: ' + filePath)", - " callback();", - "}", - "};", - "", - "exports.down = function(db, callback) {", - " var filePath = path.join(__dirname + '/sqls/" + this.name.replace( - '.js', '') + "-down.sql');", - " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", - " if (err) return callback(err);", - " console.log('received data: ' + data);", - "", - " db.runSql(data, function(err) {", - " if (err) return callback(err);", - " callback();", - " });", - " });", - "};", - "" - ].join("\n"); + '', + '/**', + ' * 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;', + '};', + '', + 'exports.up = function(db, callback) {', + ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( + '.js', '') + '-up.sql\');', + ' if (!ignoreOnInit) {', + ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', + ' if (err) return callback(err);', + ' console.log(\'received data: \' + data);', + '', + ' db.runSql(data, function(err) {', + ' if (err) return callback(err);', + ' callback();', + ' });', + ' });', + ' }', + ' else {', + ' console.log(\'ignoring on init: \' + filePath)', + ' callback();', + '}', + '};', + '', + 'exports.down = function(db, callback) {', + ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( + '.js', '') + '-down.sql\');', + ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', + ' if (err) return callback(err);', + ' console.log(\'received data: \' + data);', + '', + ' db.runSql(data, function(err) {', + ' if (err) return callback(err);', + ' callback();', + ' });', + ' });', + '};', + '' + ].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\"", + '\'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"); + ' fs.readFile filePath, {encoding: \'utf-8\'}, (err,data) ->', + ' return callback err if err', + '', + ' db.runSql data, callback', + '' + ].join('\n'); }; Migration.TemplateType = { @@ -275,6 +274,7 @@ Migration.prototype.getTemplate = function() { case Migration.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT: return this.sqlFileLoaderIgnoreOnInitTemplate(); case Migration.TemplateType.DEFAULT_JS: + /* falls through */ default: return this.defaultJsTemplate(); } @@ -318,7 +318,7 @@ Migration.loadFromDatabase = function(dir, driver, internals, callback) { callback(err); return; } else if (err && internals.dryRun) { - dbResults = [] + dbResults = []; } var migrations = dbResults.filter(function(result) { return result.name.substr(0, result.name.lastIndexOf('/')) === @@ -335,6 +335,6 @@ Migration.loadFromDatabase = function(dir, driver, internals, callback) { Migration.exportInternals = function(intern) { internals = intern; -} +}; module.exports = Migration; diff --git a/lib/migrator.js b/lib/migrator.js index a8616f61..a406f3d4 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -3,7 +3,6 @@ var Migration = require('./migration'); var log = require('./log'); var Promise = require('bluebird'); var MigratorInterface = require( './interface/migratorInterface.js'); -var path = require('path'); function SeedLink(driver, internals) { diff --git a/lib/seed.js b/lib/seed.js index 87d96cbb..13775531 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -1,6 +1,5 @@ var fs = require('fs'); var path = require('path'); -var config = require('./config'); var log = require('./log'); var Skeleton = require('./skeleton'); @@ -14,8 +13,6 @@ try { filesRegEx = /\.(js|coffee)$/; } catch (e) {} -var internals = {}; - var Seed = Skeleton.extend({ init: function() { @@ -26,7 +23,7 @@ var Seed = Skeleton.extend({ this.path = this.formatPath(arguments[1], this.name); this.templateType = arguments[3]; this.internals = arguments[4]; - } else if (arguments.length == 2) { + } else if (arguments.length === 2) { this.path = arguments[0]; this.name = this.parseName(this.path); this.date = this.parseDate(this.name); @@ -37,7 +34,7 @@ var Seed = Skeleton.extend({ this._super(this.internals); }, - up: function(db, static, callback) { + up: function(db, static) { if(static) { @@ -120,7 +117,7 @@ var Seed = Skeleton.extend({ } }, - down: function(db, static, callback) { + down: function(db) { return this._down(db); } diff --git a/lib/skeleton.js b/lib/skeleton.js index c10d83ac..1ba7d3ea 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -4,8 +4,6 @@ var Promise = require('bluebird'); var lpad = require('./util').lpad; var Class = require('./class'); -var internals = {}; - function formatPath(dir, name) { return path.join(dir, name); } diff --git a/lib/util.js b/lib/util.js index 768b372a..2d12055f 100644 --- a/lib/util.js +++ b/lib/util.js @@ -50,7 +50,7 @@ exports.reduceToInterface = function(db, originInterface) { for(var prop in db) { - if( ( prop[0] === '_' || typeof(db[prop]) !== "function") && + if( ( prop[0] === '_' || typeof(db[prop]) !== 'function') && originInterface.exclude[prop] === undefined ) { Interface[prop] = db[prop]; @@ -59,11 +59,11 @@ exports.reduceToInterface = function(db, originInterface) { for(var prop in origin) { - if (typeof db[prop] === "function") { + if (typeof db[prop] === 'function') { Interface[prop] = db[prop]; } - else if(typeof origin[prop] === "function") { + else if(typeof origin[prop] === 'function') { Interface[prop] = origin[prop]; } @@ -71,8 +71,8 @@ exports.reduceToInterface = function(db, originInterface) { for(var prop in originInterface.deprecated) { - if (typeof db[prop] === "function" && - typeof originInterface.deprecated[prop] === "function") { + if (typeof db[prop] === 'function' && + typeof originInterface.deprecated[prop] === 'function') { Interface._original[prop] = db[prop]; @@ -80,15 +80,15 @@ exports.reduceToInterface = function(db, originInterface) { Interface[property] = function() { - log.warn('This function "' + property - + '" is deprecated and ' - + originInterface.deprecated[property + '_deprecation'] ); + log.warn('This function "' + property + + '" is deprecated and ' + + originInterface.deprecated[property + '_deprecation'] ); return this._original[property].apply(this, arguments); }; }(prop)); } - else if(typeof originInterface[prop] === "function") { + else if(typeof originInterface[prop] === 'function') { Interface._original[prop] = originInterface[prop]; @@ -96,9 +96,9 @@ exports.reduceToInterface = function(db, originInterface) { Interface[property] = function() { - log.warn('This function "' + property - + '" is deprecated.' + "\n" - + originInterface.deprecated[property + '_deprecation'] ); + log.warn('This function "' + property + + '" is deprecated.' + '\n' + + originInterface.deprecated[property + '_deprecation'] ); return this._original[property].apply(this, arguments); }; @@ -153,13 +153,13 @@ exports.toArray = function(obj) { }; exports.isArray = function(obj) { - return Object.prototype.toString.call(obj) == '[object Array]'; + return Object.prototype.toString.call(obj) === '[object Array]'; }; exports.isFunction = function(obj) { - return typeof(obj) == 'function'; + return typeof(obj) === 'function'; }; exports.isString = function(obj) { - return typeof(obj) == 'string'; + return typeof(obj) === 'string'; }; From 952198ef758733e21e479fb44256ed988f76cd0b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 29 Sep 2015 22:16:42 +0200 Subject: [PATCH 223/412] update lab --- lib/skeleton.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/skeleton.js b/lib/skeleton.js index 1ba7d3ea..3501f524 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -111,7 +111,7 @@ var Skeleton = Class.extend({ .then(function( Promise ) { if( Promise !== undefined && cb_executed === false ) { - cb_executed = true + cb_executed = true; resolve(); } }).catch(function(err) { diff --git a/package.json b/package.json index 87c82a9c..ea6bc090 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "db-migrate-pg": "^0.1.4", "db-migrate-sqlite3": "^0.1.2", "jscs": "^2.1.1", - "lab": "^5.2.1", + "lab": "^6.1.0", "mysql": "^2.9.0", "pg": "^4.4.1", "proxyquire": "^1.4.0", From b8a7a90c82be46189ff62175ddd9abaa17ea46e1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 1 Oct 2015 23:56:00 +0200 Subject: [PATCH 224/412] update dependency and check --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea6bc090..77fdd032 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "pkginfo": "~0.3.0", "resolve": "^1.1.6", "semver": "~5.0.1", - "tunnel-ssh": "^1.0.0" + "tunnel-ssh": "^2.0.0" }, "devDependencies": { "code": "^1.3.0", From a5f3b8b68431c8e637b2760fb2ad377e786a9312 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Oct 2015 00:03:23 +0200 Subject: [PATCH 225/412] add 4.1 to travis ci --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3ad9af51..18576274 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ node_js: - 0.10 - 0.12 - 4.0 + - 4.1 - "iojs-1" - "iojs-2" - "iojs-3" From 5eb2b6d633d18e4fead8d61875e0075a057f59fa Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 9 Oct 2015 23:59:14 +0200 Subject: [PATCH 226/412] change couple of templates --- lib/migration.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index d55830d7..1fe01437 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -56,11 +56,11 @@ Migration.prototype.defaultCoffeeTemplate = function() { ' seed = seedLink;', ' return', '', - 'exports.up = (db, callback) ->', - '', - '', - 'exports.down = (db, callback) ->', + 'exports.up = (db) ->', + ' return null', '', + 'exports.down = (db) ->', + ' return null', '', '' ].join('\n'); @@ -84,12 +84,12 @@ Migration.prototype.defaultJsTemplate = function() { ' seed = seedLink;', '};', '', - 'exports.up = function(db, callback) {', - ' callback();', + 'exports.up = function(db) {', + ' return null;', '};', '', - 'exports.down = function(db, callback) {', - ' callback();', + 'exports.down = function(db) {', + ' return null;', '};', '' ].join('\n'); From 092cd795430e2d73a2da7a91e53bb87b85db2ecf Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 10 Oct 2015 00:09:19 +0200 Subject: [PATCH 227/412] update sql templates --- api.js | 7 +++-- lib/migration.js | 68 +++++++++++++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/api.js b/api.js index 7f5d9923..b9378f65 100644 --- a/api.js +++ b/api.js @@ -11,6 +11,7 @@ var Migrator = require('./lib/migrator.js'); var log = require('./lib/log'); var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line var dotenv = require('dotenv'); +var Promise = require('bluebird'); //global declaration for detection like it's done in umigrate //deprecated @@ -65,10 +66,12 @@ function dbmigrate(isModule, options, callback) { global.dbm = dbm; //deprecated this.internals.migrationOptions = { dbmigrate: this.internals.dbm, - ignoreOnInit: this.internals.argv['ignore-on-init'] + ignoreOnInit: this.internals.argv['ignore-on-init'], + Promise: Promise }; this.internals.seederOptions = { - dbmigrate: this.internals.dbm + dbmigrate: this.internals.dbm, + Promise: Promise }; } diff --git a/lib/migration.js b/lib/migration.js index 1fe01437..6eef5794 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -109,6 +109,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { 'var seed;', 'var fs = require(\'fs\');', 'var path = require(\'path\');', + 'var Promise;', '', '/**', ' * We receive the dbmigrate dependency from dbmigrate initially.', @@ -118,18 +119,21 @@ Migration.prototype.sqlFileLoaderTemplate = function() { ' dbm = options.dbmigrate;', ' type = dbm.dataType;', ' seed = seedLink;', + ' Promise = options.Promise;', '};', '', - 'exports.up = function(db, callback) {', + 'exports.up = function(db) {', ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( '.js', '') + '-up.sql\');', - ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', - ' if (err) return callback(err);', - ' console.log(\'received data: \' + data);', + ' 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);', '', - ' db.runSql(data, function(err) {', - ' if (err) return callback(err);', - ' callback();', + ' db.runSql(data, function(err) {', + ' if (err) return reject(err);', + ' resolve();', + ' });', ' });', ' });', '};', @@ -137,13 +141,15 @@ Migration.prototype.sqlFileLoaderTemplate = function() { 'exports.down = function(db, callback) {', ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( '.js', '') + '-down.sql\');', - ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', - ' if (err) return callback(err);', - ' console.log(\'received data: \' + data);', + ' 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);', '', - ' db.runSql(data, function(err) {', - ' if (err) return callback(err);', - ' callback();', + ' db.runSql(data, function(err) {', + ' if (err) return reject(err);', + ' resolve();', + ' });', ' });', ' });', '};', @@ -161,8 +167,7 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { 'var fs = require(\'fs\');', 'var path = require(\'path\');', 'var ignoreOnInit = false;', - - + 'var Promise;', '', '/**', ' * We receive the dbmigrate dependency from dbmigrate initially.', @@ -173,20 +178,23 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { ' 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) {', - ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', - ' if (err) return callback(err);', - ' console.log(\'received data: \' + data);', + ' return new Promise( function( resolve, reject ) {', + ' if (!ignoreOnInit) {', + ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', + ' if (err) return reject(err);', + ' console.log(\'received data: \' + data);', '', - ' db.runSql(data, function(err) {', - ' if (err) return callback(err);', - ' callback();', - ' });', + ' db.runSql(data, function(err) {', + ' if (err) return reject(err);', + ' resolve();', + ' });', + ' });', ' });', ' }', ' else {', @@ -198,13 +206,15 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { 'exports.down = function(db, callback) {', ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( '.js', '') + '-down.sql\');', - ' fs.readFile(filePath, {encoding: \'utf-8\'}, function(err,data){', - ' if (err) return callback(err);', - ' console.log(\'received data: \' + data);', + ' 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);', '', - ' db.runSql(data, function(err) {', - ' if (err) return callback(err);', - ' callback();', + ' db.runSql(data, function(err) {', + ' if (err) return reject(err);', + ' resolve();', + ' });', ' });', ' });', '};', From a1757ef1c251319129947f8379d49c24829a27f9 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 11 Oct 2015 23:50:30 +0200 Subject: [PATCH 228/412] add undo seed function to api --- api.js | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/api.js b/api.js index b9378f65..a5a87f10 100644 --- a/api.js +++ b/api.js @@ -317,6 +317,8 @@ dbmigrate.prototype = { this.internals.migrationMode = scope; } } + + executeUndoSeed(this.internals, this.config, callback); }, /** @@ -773,6 +775,37 @@ function executeSeed(internals, config, callback) { }); } +function executeUndoSeed(internals, config, callback) { + + if (internals.argv._.length > 0) { + internals.argv.destination = internals.argv._.shift().toString(); + } + + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, Seeder, function(err, seeder) { + assert.ifError(err); + + seeder.seedDir = path.resolve(internals.argv[(internals.mode !== + 'static') ? 'vcseeder-dir' : 'staticseeder-dir']); + + if (internals.mode === 'static') { + + internals.onComplete( seeder, callback, + { stack: 'Static seeders can\'t be undone. Use VC Seeders instead!' } ); + } else { + seeder.createSeedsTable(function(err) { + if (_assert(err, callback)) { + + seeder.down(internals.argv, internals.onComplete.bind(this, + seeder, callback)); + } + }); + } + }); +} + internals.onComplete = onComplete; function onComplete(migrator, callback, originalErr) { @@ -845,7 +878,7 @@ function run(internals, config) { internals.migrationMode = folder[1]; } - if (action == 'up') { + if (action === 'up') { executeUp(internals, config); } else { executeDown(internals, config); @@ -871,6 +904,7 @@ function run(internals, config) { if (internals.argv._[0] === 'down') { internals.argv._.shift(); + executeUndoSeed(internals, config); } else { executeSeed(internals, config); From b25ccb05e177daf4b74cbd3116c97dfd2321b3b2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 12 Oct 2015 00:04:37 +0200 Subject: [PATCH 229/412] fix bug on up/down of seeders --- lib/seeder.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/seeder.js b/lib/seeder.js index 1ec83cac..99ea0fb3 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -248,15 +248,14 @@ Seeder.prototype = { return (Promise.promisify(self.writeSeedRecord.bind(self)))(seeder); }) .then(self._driver.endMigration.bind(self.driver)) - .then(function() { - callback(); - }) .catch(function(e) { throw e; }); + }) + .then(function() { + callback(); }); - }); }); }, @@ -293,13 +292,13 @@ Seeder.prototype = { return (Promise.promisify(self.deleteSeedRecord.bind(self)))(seeder); }) .then(self._driver.endMigration.bind(self.driver)) - .then(function() { - callback(); - }) .catch(function(e) { throw e; }); + }) + .then(function() { + callback(); }); }); } From fbc7bd5892c3749cbbbf8204fff5831462885ba3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 13 Oct 2015 00:15:49 +0200 Subject: [PATCH 230/412] add reset method and limit down methods of seeds --- api.js | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/api.js b/api.js index a5a87f10..b02d83c8 100644 --- a/api.js +++ b/api.js @@ -321,6 +321,30 @@ dbmigrate.prototype = { executeUndoSeed(this.internals, this.config, callback); }, + /** + * Execute the reset function of currently executed seeds. + */ + resetSeed: function(specification, scope, callback) { + + if (arguments.length > 0) { + if (typeof(specification) === 'number') { + + this.internals.argv.count = specification; + + if (scope) { + + this.internals.migrationMode = scope; + } + } else if (typeof(specification) === 'string') { + + this.internals.migrationMode = scope; + } + } + + this.internals.argv.count = Number.MAX_VALUE; + executeUndoSeed(this.internals, this.config, callback); + }, + /** * Executes the default routine. */ @@ -776,6 +800,10 @@ function executeSeed(internals, config, callback) { } function executeUndoSeed(internals, config, callback) { + if (!internals.argv.count) { + log.info('Defaulting to running 1 down seed.'); + internals.argv.count = 1; + } if (internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); @@ -901,7 +929,10 @@ function run(internals, config) { internals.mode = folder[1] || 'vc'; internals.migrationMode = folder[2]; - if (internals.argv._[0] === 'down') { + if (internals.argv._[0] === 'down' || internals.argv._[0] === 'reset') { + + if (internals.argv._[0] === 'reset') + internals.argv.count = Number.MAX_VALUE; internals.argv._.shift(); executeUndoSeed(internals, config); From c4e1103e958d0903fd77deb618976e6a988c9872 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 14 Oct 2015 23:52:28 +0200 Subject: [PATCH 231/412] add dummy calls to linked seeders and migrations --- lib/migrator.js | 10 ++++++++++ lib/seeder.js | 24 ++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index a406f3d4..46eed75e 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -192,6 +192,16 @@ Migrator.prototype = { 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(); + } + + return; + }) .then(function() { return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); }) diff --git a/lib/seeder.js b/lib/seeder.js index 99ea0fb3..073047e2 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -239,10 +239,20 @@ Seeder.prototype = { var setup = seeder.setup(); if(typeof(setup) === 'function') - setup(self.internals.seederOptions); + 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(); + } + + return; + }) .then(function() { return (Promise.promisify(self.writeSeedRecord.bind(self)))(seeder); @@ -283,10 +293,20 @@ Seeder.prototype = { var setup = seeder.setup(); if(typeof(setup) === 'function') - setup(self.internals.seederOptions); + 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(); + } + + return; + }) .then(function() { return (Promise.promisify(self.deleteSeedRecord.bind(self)))(seeder); From 36282875be7b43179b21fee75bd2360e08811dc6 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 18 Oct 2015 00:29:12 +0200 Subject: [PATCH 232/412] link to read the docs and remove readme documentation --- README.md | 834 +----------------------------------------------------- 1 file changed, 7 insertions(+), 827 deletions(-) diff --git a/README.md b/README.md index b3f57dd2..32c4c7e9 100644 --- a/README.md +++ b/README.md @@ -29,840 +29,20 @@ DB-Migrate is now available to you via: $ node node_modules/db-migrate/bin/db-migrate -## Supported Databases +## Officially Supported Databases * Mysql (https://github.com/felixge/node-mysql) +https://github.com/db-migrate/mysql * PostgreSQL (https://github.com/brianc/node-postgres) +https://github.com/db-migrate/pg * sqlite3 (https://github.com/developmentseed/node-sqlite3) +https://github.com/db-migrate/sqlite * Mongodb (https://github.com/mongodb/node-mongodb-native) +https://github.com/db-migrate/mongodb -## Usage +## Resources -``` -Usage: db-migrate [up|down|reset|create|db] [dbname|migrationName] [options] - -Down migrations are run in reverse run order, so migrationName is ignored for down migrations. -Use the --count option to control how many down migrations are run (default is 1). - -Options: - --env, -e The environment to run the migrations under. [default: "dev"] - --migrations-dir, -m The directory containing your migration files. [default: "./migrations"] - --count, -c Max number of migrations to run. - --dry-run Prints the SQL but doesn't run it. [boolean] - --verbose, -v Verbose mode. [default: false] - --config Location of the database.json file. [default: "./database.json"] - --force-exit Call system.exit() after migration run [default: false] - --sql-file Create sql files for up and down. [default: false] - --coffee-file Create a coffeescript migration file [default: false] - --migration-table Set the name of the migration table. - --table, --migration-table [default: "migrations"] -``` - -## Creating Migrations - -DB-Migrate can be used to create migration boilerplates from templates. -Currently there are only basic templates available, which may change in some -future versions. - -#### Parameters - -* migration name -* flags - -#### Flags - -* coffee-file -* sql-file - -The flags --coffee-file and --sql-file can be combined to create sql-file -migrations in coffee script. - -### Examples - -To create a migration, execute `db-migrate create` with a title. `node-db-migrate` will create a node module within `./migrations/` which contains the following two exports: - -```javascript -exports.up = function (db, callback) { - callback(); -}; - -exports.down = function (db, callback) { - callback(); -}; -``` - -All you have to do is populate these, invoking `callback()` when complete, and you are ready to migrate! - -For example: - - $ db-migrate create add-pets - $ db-migrate create add-owners - -The first call creates `./migrations/20111219120000-add-pets.js`, which we can populate: - -```javascript -exports.up = function (db, callback) { - db.createTable('pets', { - id: { type: 'int', primaryKey: true }, - name: 'string' - }, callback); -}; - -exports.down = function (db, callback) { - db.dropTable('pets', callback); -}; -``` - -The second creates `./migrations/20111219120005-add-owners.js`, which we can populate: - -```javascript -exports.up = function (db, callback) { - db.createTable('owners', { - id: { type: 'int', primaryKey: true }, - name: 'string' - }, callback); -}; - -exports.down = function (db, callback) { - db.dropTable('owners', callback); -}; -``` - -Executing multiple statements against the database within a single migration requires a bit more care. You can either nest the migrations like: - -```javascript -exports.up = function (db, callback) { - db.createTable('pets', { - id: { type: 'int', primaryKey: true }, - name: 'string' - }, createOwners); - - function createOwners(err) { - if (err) { callback(err); return; } - db.createTable('owners', { - id: { type: 'int', primaryKey: true }, - name: 'string' - }, callback); - } -}; - -exports.down = function (db, callback) { - db.dropTable('pets', function(err) { - if (err) { callback(err); return; } - db.dropTable('owners', callback); - }); -}; -``` - -or use the async library to simplify things a bit, such as: - -```javascript -var async = require('async'); - -exports.up = function (db, callback) { - async.series([ - db.createTable.bind(db, 'pets', { - id: { type: 'int', primaryKey: true }, - name: 'string' - }), - db.createTable.bind(db, 'owners', { - id: { type: 'int', primaryKey: true }, - name: 'string' - }) - ], callback); -}; - -exports.down = function (db, callback) { - async.series([ - db.dropTable.bind(db, 'pets'), - db.dropTable.bind(db, 'owners') - ], callback); -}; -``` - -### Using files for sqls - -If you prefer to use sql files for your up and down statements, you can use the `--sql-file` option to automatically generate these files and the javascript code that load them. - -For example: - - $ db-migrate create add-people --sql-file - -This call creates 3 files: - -``` -./migrations/20111219120000-add-people.js -./migrations/sqls/20111219120000-add-people-up.sql -./migrations/sqls/20111219120000-add-people-down.sql -``` - -The sql files will have the following content: -```sql -/* Replace with your SQL commands */ -``` - -And the javascript file with the following code that load these sql files: - -```javascript -dbm = dbm || require('db-migrate'); -var type = dbm.dataType; -var fs = require('fs'); -var path = require('path'); - -exports.up = function(db, callback) { - var filePath = path.join(__dirname + '/sqls/20111219120000-add-people-up.sql'); - fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){ - if (err) return console.log(err); - db.runSql(data, function(err) { - if (err) return console.log(err); - callback(); - }); - }); -}; - -exports.down = function(db, callback) { - var filePath = path.join(__dirname + '/sqls/20111219120000-add-people-down.sql'); - fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){ - if (err) return console.log(err); - db.runSql(data, function(err) { - if (err) return console.log(err); - callback(); - }); - }); -}; -``` - -** Making it as default ** - -To not need to always specify the `sql-file` option in your `db-migrate create` commands, you can set a property in your `database.json` as follows: - -``` -{ - "dev": { - "host": "localhost", - ... - }, - "sql-file" : true -} -``` - -** Important - For MySQL users ** - -If you use MySQL, to be able to use multiple statements in your sql file, you have to set the property `multiple-statements: true` when creating the connection object. You can set it in your `database.json` as follows: - -``` -{ - "dev": { - "host": "localhost", - "user": { "ENV" : "DB_USER" }, - "password" : { "ENV" : "DB_PASS" }, - "database": "database-name", - "driver": "mysql", - "multipleStatements": true - } -} -``` - -You can also place it as a query string parameter into DATABASE_URL variable, as https://github.com/pwnall/node-parse-database-url allows passing them into config: - - $ DATABASE_URL="mysql://DB_USER:DB_PASS@localhost/database-name?multipleStatements=true" db-migrate up - -## Running Migrations - -When first running the migrations, all will be executed in sequence. A table named `migrations` will also be created in your database to track which migrations have been applied. - - $ db-migrate up - [INFO] Processed migration 20111219120000-add-pets - [INFO] Processed migration 20111219120005-add-owners - [INFO] Done - -Subsequent attempts to run these migrations will result in the following output - - $ db-migrate up - [INFO] No migrations to run - [INFO] Done - -If we were to create another migration using `db-migrate create`, and then execute migrations again, we would execute only those not previously executed: - - $ db-migrate up - [INFO] Processed migration 20111220120210-add-kennels - [INFO] Done - -You can also run migrations incrementally by specifying a date substring. The example below will run all migrations created on or before December 19, 2011: - - $ db-migrate up 20111219 - [INFO] Processed migration 20111219120000-add-pets - [INFO] Processed migration 20111219120005-add-owners - [INFO] Done - -You can also run a specific number of migrations with the -c option: - - $ db-migrate up -c 1 - [INFO] Processed migration 20111219120000-add-pets - [INFO] Done - -All of the down migrations work identically to the up migrations by substituting the word `down` for `up`. - -## Configuration - -db-migrate supports the concept of environments. For example, you might have a dev, test, and prod environment where you need to run the migrations at different times. Environment settings are loaded from a database.json file like the one shown below: - -```javascript -{ - "dev": { - "driver": "sqlite3", - "filename": "~/dev.db" - }, - - "test": { - "driver": "sqlite3", - "filename": ":memory:" - }, - - "prod": { - "driver": "mysql", - "user": "root", - "password": "root" - }, - - "pg": { - "driver": "pg", - "user": "test", - "password": "test", - "host": "localhost", - "database": "mydb", - "schema": "my_schema" - }, - - "mongo": { - "driver": "mongodb", - "database": "my_db", - "host": "localhost" - }, - - "other": "postgres://uname:pw@server.com/dbname" -} -``` - -You can also specify environment variables in your config file by using a special notation. Here is an example: -```javascript -{ - "prod": { - "driver": "mysql", - "user": {"ENV": "PRODUCTION_USERNAME"}, - "password": {"ENV": "PRODUCTION_PASSWORD"} - }, -} -``` -In this case, db-migrate will search your environment for variables -called `PRODUCTION_USERNAME` and `PRODUCTION_PASSWORD`, and use those values for the corresponding configuration entry. - -Note that if the settings for an environment are represented by a single string that string will be parsed as a database URL. You can also provide a database URL through environmental variable like this: -```javascript -{ - "prod": {"ENV": "PRODUCTION_URL"} -} -``` - -You can pass the -e or --env option to db-migrate to select the environment you want to run migrations against. The --config option can be used to specify the path to your database.json file if it's not in the current working directory. - - db-migrate up --config config/database.json -e prod - -The above will run all migrations that haven't yet been run in the prod environment, grabbing the settings from config/database.json. - -Alternatively, you can specify a DATABASE_URL -environment variable that will be used in place of the configuration -file settings. This is helpful for use with Heroku. - -## Multiple migration scopes - -You can have multiple configurable migration scopes, which are subfolders within -your migrations folder. A scope gets called like the following: - - $ db-migrate up:myScope - -#### Executing all scopes together - -If you want to execute all scopes with one command, you can execute the following: - - $ db-migrate up:all - -Obviously this means you **CAN'T** create scope which is named all. - -#### Scope Configuration - -You can also configure the scope to specify a sub configuration. Currently you -can only define a database and schema which you want to switch to within this -config. - -This config file tells db-migrate to switch to the specified `database` or -`schema`. The `database` option switches to the specified database, this is what -you want most of the time. The `schema` option switches to the specified schema, -which is a concept that is related to special databases like **postgres**. -Therefor you can't use schema with any other db than **postgres**. - -**Note:** It's currently only possible to switch a schema when using -**postgres**, as switching to a database means to create a complete new -connection for **postgres**. - -```json -{ - "database": "test", - "schema": "test" -} -``` - -## Connecting through an SSH tunnel - -If you need to connect to the database through an SSH tunnel, you can set the `tunnel` config: - -```json -{ - "tunnel": { - "localPort" : 33333, - "host": "ssh-machine.example.com", - "username": "sshuser", - "privateKeyPath": "/home/sshuser/privatekey.pem" - } -} -``` - -One common use case for this is when the remote DB does not accept connections from the host that will be running db-migrate. For example, a database within an AWS -[Virtual Private Cloud (VPC)](http://aws.amazon.com/vpc) that is only open to [EC2](http://aws.amazon.com/ec2) hosts within the same VPC. By pointing the tunnel sshConfig to a host within the DB's -VPC, you can run your migrations from any host. - -### Tunnel configuration properties - -The `tunnel` config must specify the `localPort` in addition to any configuration necessary to connect to the SSH tunnel. Please see the [https://github.com/Finanzchef24-GmbH/tunnel-ssh](tunnel-ssh) -documentation for more details about what properties to set on the tunnel config. The only addition to that config is the `privateKeyPath` property. If the connection to your SSH host -requires a private key file, you can specify its path using this property. - -## Defaults - -## Generic Datatypes - -There is currently a small list of generic Datatypes you can use, to make your -migrations more database independent. - -Find the list of supported types [here](https://github.com/kunklejr/node-db-migrate/blob/master/lib/data_type.js). - -## Migrations API - SQL - -Below are examples of all the different migrations supported by db-migrate. Please note that not all migrations are supported by all databases. For example, SQLite does not support dropping columns. - -### createTable(tableName, columnSpec, callback) - -Creates a new table with the specified columns. - -__Arguments__ - -* tableName - the name of the table to create -* columnSpec - a hash of column definitions -* callback(err) - callback that will be invoked after table creation - -__Examples__ - -```javascript -// with no table options -exports.up = function (db, callback) { - db.createTable('pets', { - id: { type: 'int', primaryKey: true, autoIncrement: true }, - name: 'string' // shorthand notation - }, callback); -} - -// with table options -exports.up = function (db, callback) { - db.createTable('pets', { - columns: { - id: { type: 'int', primaryKey: true, autoIncrement: true }, - name: 'string' // shorthand notation - }, - ifNotExists: true - }, callback); -} -``` - -__Column Specs__ - -The following options are available on column specs - -* type - the column data type. Supported types can be found in lib/data_type.js -* length - the column data length, where supported -* primaryKey - true to set the column as a primary key. Compound primary keys are supported by setting the `primaryKey` option to true on multiple columns -* autoIncrement - true to mark the column as auto incrementing -* notNull - true to mark the column as non-nullable, omit it archive database default behavior and false to mark explicitly as nullable -* unique - true to add unique constraint to the column -* defaultValue - set the column default value -* foreignKey - set a foreign key to the column - -__Column ForeignKey Spec Examples__ - -```javascript -exports.up = function(db, callback) { - - //automatic mapping, the mapping key resolves to the column - db.createTable( 'product_variant', - { - id: - { - type: 'int', - unsigned: true, - notNull: true, - primaryKey: true, - autoIncrement: true, - length: 10 - }, - product_id: - { - type: 'int', - unsigned: true, - length: 10, - notNull: true, - foreignKey: { - name: 'product_variant_product_id_fk', - table: 'product', - rules: { - onDelete: 'CASCADE', - onUpdate: 'RESTRICT' - }, - mapping: 'id' - } - }, - }, callback ); -}; - -exports.up = function(db, callback) { - - //explicit mapping - db.createTable( 'product_variant', - { - id: - { - type: 'int', - unsigned: true, - notNull: true, - primaryKey: true, - autoIncrement: true, - length: 10 - }, - product_id: - { - type: 'int', - unsigned: true, - length: 10, - notNull: true, - foreignKey: { - name: 'product_variant_product_id_fk', - table: 'product', - rules: { - onDelete: 'CASCADE', - onUpdate: 'RESTRICT' - }, - mapping: { - product_id: 'id' - } - } - }, - }, callback ); -}; -``` - -### dropTable(tableName, [options,] callback) - -Drop a database table - -__Arguments__ - -* tableName - name of the table to drop -* options - table options -* callback(err) - callback that will be invoked after dropping the table - -__Table Options__ - -* ifExists - Only drop the table if it already exists - -### renameTable(tableName, newTableName, callback) - -Rename a database table - -__Arguments__ - -* tableName - existing table name -* options - new table name -* callback(err) - callback that will be invoked after renaming the table - -### addColumn(tableName, columnName, columnSpec, callback) - -Add a column to a database table - -__Arguments__ - -* tableName - name of table to add a column to -* columnName - name of the column to add -* columnSpec - a hash of column definitions -* callback(err) - callback that will be invoked after adding the column - -Column spec is the same as that described in createTable - -### removeColumn(tableName, columnName, callback) - -Remove a column from an existing database table - -* tableName - name of table to remove a column from -* columnName - name of the column to remove -* callback(err) - callback that will be invoked after removing the column - -### renameColumn(tableName, oldColumnName, newColumnName, callback) - -Rename a column - -__Arguments__ - -* tableName - table containing column to rename -* oldColumnName - existing column name -* newColumnName - new name of the column -* callback(err) - callback that will be invoked after renaming the column - -### changeColumn(tableName, columnName, columnSpec, callback) - -Change the definition of a column - -__Arguments__ - -* tableName - table containing column to change -* columnName - existing column name -* columnSpec - a hash containing the column spec -* callback(err) - callback that will be invoked after changing the column - -### addIndex(tableName, indexName, columns, [unique], callback) - -Add an index - -__Arguments__ - -* tableName - table to add the index too -* indexName - the name of the index -* columns - an array of column names contained in the index, or as an object -definition -* unique - whether the index is unique (optional, default false) -* callback(err) - callback that will be invoked after adding the index - -Column Object: -* name - the column name -* length - the length of index - -Adding a column with defined index length (MySQL/MariaDB only): - -```javascript -exports.up = function (db) { - return db.addIndex('pets', 'cats', [ - { name: 'color', length: 9}, - { name: 'gender', length: 1}, - 'is_insane' - ]); -} -``` - -Adding new keys to columns: - -```javascript -exports.up = function (db) { - return db.addIndex('pets', 'cats', ['color', 'gender', 'columnC']); -} -``` - -### addForeignKey - -Adds a foreign Key - -__Arguments__ - -* tableName - table on which the foreign key gets applied -* referencedTableName - table where the referenced key is located -* keyName - name of the foreign key -* fieldMapping - mapping of the foreign key to referenced key -* rules - ondelete, onupdate constraints -* callback(err) - callback that will be invoked after adding the foreign key - -__Example__ - -```javascript -exports.up = function (db, callback) -{ - db.addForeignKey('module_user', 'modules', 'module_user_module_id_foreign', - { - 'module_id': 'id' - }, - { - onDelete: 'CASCADE', - onUpdate: 'RESTRICT' - }, callback); -}; -``` - -### removeForeignKey - -__Arguments__ - -* tableName - table in which the foreign key should be deleted -* keyName - the name of the foreign key -* options - object of options, see below -* callback - callback that will be invoked once the foreign key was deleted - -__Options__ - -* dropIndex (default: false) - deletes the index with the same name as the foreign key - -__Examples__ - -```javascript -//without options object -exports.down = function (db, callback) -{ - db.removeForeignKey('module_user', 'module_user_module_id_foreign', callback); -}; - -//with options object -exports.down = function (db, callback) -{ - db.removeForeignKey('module_user', 'module_user_module_id_foreign', - { - dropIndex: true, - }, callback); -}; -``` - -### insert(tableName, columnNameArray, valueArray, callback) - -Insert an item into a given column - -__Arguments__ - -* tableName - table to insert the item into -* columnNameArray - the array existing column names for each item being inserted -* valueArray - the array of values to be inserted into the associated column -* callback(err) - callback that will be invoked once the insert has been completed. - -### removeIndex([tableName], indexName, callback) - -Remove an index - -__Arguments__ - -* tableName - name of the table that has the index (Required for mySql) -* indexName - the name of the index -* callback(err) - callback that will be invoked after removing the index - -### runSql(sql, [params,] callback) - -Run arbitrary SQL - -__Arguments__ - -* sql - the SQL query string, possibly with ? replacement parameters -* params - zero or more ? replacement parameters -* callback(err) - callback that will be invoked after executing the SQL - -### all(sql, [params,] callback) - -Execute a select statement - -__Arguments__ - -* sql - the SQL query string, possibly with ? replacement parameters -* params - zero or more ? replacement parameters -* callback(err, results) - callback that will be invoked after executing the SQL - -## Migrations API - NoSQL - -Below are examples of all the different migrations supported by db-migrate for NoSQL databases. - -### createCollection(collectionName, callback) - -Creates a new collection. - -__Arguments__ - -* collectionName - the name of the collection to create -* callback(err) - callback that will be invoked after table creation - -__Examples__ - -```javascript -exports.up = function (db, callback) { - db.createCollection('pets', callback); -} -``` - -### dropCollection(collectionName, callback) - -Drop a database collection - -__Arguments__ - -* collectionName - name of the collection to drop -* callback(err) - callback that will be invoked after dropping the collection - -### renameCollection(collectionName, newCollectionName, callback) - -Rename a database table - -__Arguments__ - -* collectionName - existing collection name -* newCollectionName - new collection name -* callback(err) - callback that will be invoked after renaming the collection - -### addIndex(collectionName, indexName, columns, unique, callback) - -Add an index - -__Arguments__ - -* collectionName - collection to add the index too -* indexName - the name of the index -* columns - an array of column names contained in the index -* unique - whether the index is unique -* callback(err) - callback that will be invoked after adding the index - -### removeIndex(collectionName, indexName, callback) - -Remove an index - -__Arguments__ - -* collectionName - name of the collection that has the index -* indexName - the name of the index -* callback(err) - callback that will be invoked after removing the index - -### insert(collectionName, toInsert, callback) - -Insert an item into a given collection - -__Arguments__ - -* collectionName - collection to insert the item into -* toInsert - an object or array of objects to be inserted into the associated collection -* callback(err) - callback that will be invoked once the insert has been completed. - -## Development - -The following command runs the vows tests. - -```bash -npm test -``` - -Running the tests requires a one-time setup of the **MySQL**, **MongoDB** and **Postgres** databases. - -```bash -mysql -u root -e "CREATE DATABASE db_migrate_test;" -createdb db_migrate_test -``` - -You will also need to copy `test/db.config.example.json` to `test/db.config.json` -and adjust appropriate to setup configuration for your database instances. +Documentation: https://readthedocs.org/projects/db-migrate/?badge=latest ## License From f424e9e96e70c973ba0da9fae7ab44c80fff2654 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 18 Oct 2015 00:34:18 +0200 Subject: [PATCH 233/412] 0.10.0-beta.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77fdd032..fe0e8d80 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.9.12", + "version": "0.10.0-beta.1", "engines": { "node": ">=0.6.0" }, From 477fe25152caf7bd3f02fdf309859c03449b1c77 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 18 Oct 2015 00:55:01 +0200 Subject: [PATCH 234/412] remove the badge ending from the documentation url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 32c4c7e9..6fdefe13 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ https://github.com/db-migrate/mongodb ## Resources -Documentation: https://readthedocs.org/projects/db-migrate/?badge=latest +Documentation: https://readthedocs.org/projects/db-migrate ## License From c063049ffed64e9200968ee628a74bf313b09d61 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 18 Oct 2015 03:09:40 +0200 Subject: [PATCH 235/412] make entry in readme more clear to be also a user manual --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fdefe13..89108794 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,10 @@ https://github.com/db-migrate/sqlite * Mongodb (https://github.com/mongodb/node-mongodb-native) https://github.com/db-migrate/mongodb -## Resources +## Resources and usage instructions + +Please follow the link below, for usage instructions examples and the full +documentation of db-migrate. Documentation: https://readthedocs.org/projects/db-migrate From 3c51af0e22b73abff8881b8eb3549774b8547320 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 19 Oct 2015 23:14:49 +0200 Subject: [PATCH 236/412] Extend startup with logging and failure handling on 0.9.x versions Before this patch users may ran into a local installation older than 0.9.x, this patch ensures that the version is compatible to be preffered over the global version. If the local version is to old (<0.10.0) the global version will be used instead. If this is the case a warn message gets displayed to the user. Additionally added informational logging within the verbose mode if a local version gets preferred. solves #317 --- bin/db-migrate | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/bin/db-migrate b/bin/db-migrate index 601935ea..106004a7 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -1,23 +1,36 @@ #!/usr/bin/env node var resolve = require( 'resolve' ); +var log = require( '../lib/log.js' ); process.title = 'db-migrate'; +if ( process.argv.indexOf( '--verbose' ) !== -1 || process.argv.indexOf( '-v' ) !== -1 ) + global.verbose = true; + resolve( 'db-migrate', { - basedir: process.cwd() +basedir: process.cwd() }, function ( error, localModule ) { - var DBMigrate, dbmigrate; +var DBMigrate, dbmigrate; + +if ( error ) { + DBMigrate = require( '../' ); +} +else { + DBMigrate = require( localModule ); + log.verbose( 'Detected and using the projects local version of db-migrate. ' + + '\'' + localModule + '\''); +} + +if ( typeof( DBMigrate.getInstance ) !== 'function' ) { + DBMigrate = require( '../' ); - if ( error ) { - DBMigrate = require( '../' ); - } - else { - DBMigrate = require( localModule ); - } + log.warn( 'Using global instead of local detected version as you have a ' + + 'version older than 0.10.0 in your projects package.json!' ); +} - dbmigrate = DBMigrate.getInstance(); - dbmigrate.run(); +dbmigrate = DBMigrate.getInstance(); +dbmigrate.run(); } ); From b067864b8e13abc22bc3c5e841db0c01269f5889 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 19 Oct 2015 23:15:40 +0200 Subject: [PATCH 237/412] 0.10.0-beta.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fe0e8d80..11f1dab0 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0-beta.1", + "version": "0.10.0-beta.2", "engines": { "node": ">=0.6.0" }, From 315ce805d07ef58908abe1a2e98012de8b507b24 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 19 Oct 2015 23:20:34 +0200 Subject: [PATCH 238/412] add lts node.js version to travis tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 18576274..0b6f34f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ node_js: - 0.12 - 4.0 - 4.1 + - 4.2 - "iojs-1" - "iojs-2" - "iojs-3" From bd21f85c2795307171180c1df7f66d2330af1606 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 19 Oct 2015 23:54:09 +0200 Subject: [PATCH 239/412] Resolve driver from local projects Fixes #318 --- lib/driver/index.js | 64 +++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index d7b8f48c..a24e29c5 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -8,7 +8,8 @@ var log = internals.mod.log; var tunnel = require('tunnel-ssh'), Promise = require('bluebird'), SeederInterface = require('../interface/seederInterface.js'), - MigratorInterface = require('../interface/migratorInterface.js'); + MigratorInterface = require('../interface/migratorInterface.js'), + resolve = require( 'resolve' ); var ShadowProto = { @@ -44,6 +45,7 @@ exports.connect = function (config, intern, callback) { log.verbose('require:', config.driver.require); driver = require(config.driver.require); + _connect(); } else { @@ -58,37 +60,54 @@ exports.connect = function (config, intern, callback) { break; } - try { + req = 'db-migrate-' + config.driver; + log.verbose('require:', req); - req = 'db-migrate-' + config.driver; - log.verbose('require:', req); + resolve(req, { - try { + basedir: process.cwd() + }, function (error, localModule) { - driver = require(req); + try { + if ( error ) { + try { + + driver = require(req); + } + catch (Exception) { + + driver = require('../../../' + req); + } + } + else { + driver = require( localModule ); + } } catch (Exception) { - driver = require('../../../' + req); + try { + + //Fallback to internal drivers, while moving drivers to new repos + req = './' + config.driver; + log.verbose('require:', req); + driver = require(req); + } + catch (exception) { + + return callback( { + stack: 'No such driver found, please try to install it via ' + + 'npm install db-migrate-' + config.driver + ' or ' + + 'npm install -g db-migrate-' + config.driver + } ); + } } - } - catch (Exception) { - try { + _connect(); + }); + } - //Fallback to internal drivers, while moving drivers to new repos - req = './' + config.driver; - log.verbose('require:', req); - driver = require(req); - } - catch (Exception) { - return callback( { stack: 'No such driver found, please try to install it via ' + - 'npm install db-migrate-' + config.driver + ' or ' + - 'npm install -g db-migrate-' + config.driver } ); - } - } - } +function _connect() { log.verbose('connecting'); @@ -136,4 +155,5 @@ exports.connect = function (config, intern, callback) { else { connect(config); } +} }; From 73ce1bc92ae06e23c696a8b62d26e297d296ba82 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 20 Oct 2015 01:04:15 +0200 Subject: [PATCH 240/412] use synchronized variant of resolve for drivers --- lib/driver/index.js | 59 ++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index a24e29c5..adb336ec 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -45,7 +45,6 @@ exports.connect = function (config, intern, callback) { log.verbose('require:', config.driver.require); driver = require(config.driver.require); - _connect(); } else { @@ -60,54 +59,45 @@ exports.connect = function (config, intern, callback) { break; } - req = 'db-migrate-' + config.driver; - log.verbose('require:', req); - - resolve(req, { - - basedir: process.cwd() - }, function (error, localModule) { + try { + req = 'db-migrate-' + config.driver; + log.verbose('require:', req); try { - if ( error ) { - try { - driver = require(req); - } - catch (Exception) { - - driver = require('../../../' + req); - } - } - else { - driver = require( localModule ); - } + driver = require( + resolve.sync(req, { basedir: process.cwd() }) + ); } - catch (Exception) { + catch(e1) { try { - //Fallback to internal drivers, while moving drivers to new repos - req = './' + config.driver; - log.verbose('require:', req); driver = require(req); } - catch (exception) { + catch (e2) { - return callback( { - stack: 'No such driver found, please try to install it via ' + - 'npm install db-migrate-' + config.driver + ' or ' + - 'npm install -g db-migrate-' + config.driver - } ); + driver = require('../../../' + req); } } + } + catch (e3) { - _connect(); - }); - } + try { + //Fallback to internal drivers, while moving drivers to new repos + req = './' + config.driver; + log.verbose('require:', req); + driver = require(req); + } + catch (e4) { -function _connect() { + return callback( { stack: 'No such driver found, please try to install it via ' + + 'npm install db-migrate-' + config.driver + ' or ' + + 'npm install -g db-migrate-' + config.driver } ); + } + } + } log.verbose('connecting'); @@ -155,5 +145,4 @@ function _connect() { else { connect(config); } -} }; From 6264db11d1553daacb93ab900888e5d78b07c18c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 20 Oct 2015 01:07:52 +0200 Subject: [PATCH 241/412] 0.10.0-beta.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 11f1dab0..16a831ad 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0-beta.2", + "version": "0.10.0-beta.3", "engines": { "node": ">=0.6.0" }, From caf429e15bf32381af5c79f0d32bf0eed3a65430 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 20 Oct 2015 18:57:32 +0200 Subject: [PATCH 242/412] fix sql templates to work with 0.10.x again --- lib/migration.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 6eef5794..6fd677cb 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -130,15 +130,15 @@ Migration.prototype.sqlFileLoaderTemplate = function() { ' if (err) return reject(err);', ' console.log(\'received data: \' + data);', '', - ' db.runSql(data, function(err) {', - ' if (err) return reject(err);', - ' resolve();', - ' });', + ' resolve(data);', ' });', + ' })', + ' .then(function(data) {', + ' return db.runSql(data);', ' });', '};', '', - 'exports.down = function(db, callback) {', + 'exports.down = function(db) {', ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( '.js', '') + '-down.sql\');', ' return new Promise( function( resolve, reject ) {', @@ -146,11 +146,11 @@ Migration.prototype.sqlFileLoaderTemplate = function() { ' if (err) return reject(err);', ' console.log(\'received data: \' + data);', '', - ' db.runSql(data, function(err) {', - ' if (err) return reject(err);', - ' resolve();', - ' });', + ' resolve(data);', ' });', + ' })', + ' .then(function(data) {', + ' return db.runSql(data);', ' });', '};', '' From f97a8f71f6d4a40c44734d584a8b9f52988df1fc Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 20 Oct 2015 19:05:07 +0200 Subject: [PATCH 243/412] ignore on init formatting --- lib/migration.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 6fd677cb..864282cd 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -175,7 +175,7 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { ' */', 'exports.setup = function(options, seedLink) {', ' dbm = options.dbmigrate;', - ' ignoreOnInit = options.ignoreOnInit', + ' ignoreOnInit = options.ignoreOnInit;', ' type = dbm.dataType;', ' seed = seedLink;', ' Promise = options.Promise;', @@ -184,23 +184,23 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { 'exports.up = function(db, callback) {', ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( '.js', '') + '-up.sql\');', - ' return new Promise( function( resolve, reject ) {', - ' if (!ignoreOnInit) {', + ' 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);', '', - ' db.runSql(data, function(err) {', - ' if (err) return reject(err);', - ' resolve();', + ' resolve(data);', ' });', - ' });', - ' });', + ' })', + ' .then(function(data) {', + ' return db.runSql(data);', + ' });', ' }', ' else {', ' console.log(\'ignoring on init: \' + filePath)', - ' callback();', - '}', + ' return null;', + ' }', '};', '', 'exports.down = function(db, callback) {', @@ -211,11 +211,11 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { ' if (err) return reject(err);', ' console.log(\'received data: \' + data);', '', - ' db.runSql(data, function(err) {', - ' if (err) return reject(err);', - ' resolve();', - ' });', + ' resolve(data);', ' });', + ' })', + ' .then(function(data) {', + ' return db.runSql(data);', ' });', '};', '' From c2ef3b9d8ba8d83a52989ad41183fdd752342d50 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 20 Oct 2015 19:06:44 +0200 Subject: [PATCH 244/412] 0.10.0-beta.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16a831ad..56901f08 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0-beta.3", + "version": "0.10.0-beta.4", "engines": { "node": ">=0.6.0" }, From a0d5a6c96ce9328cc6974e383afbf8576fe44028 Mon Sep 17 00:00:00 2001 From: Sanketh Katta Date: Thu, 5 Nov 2015 15:30:18 -0800 Subject: [PATCH 245/412] Support setting default environment via ENV variable. --- lib/config.js | 8 ++++-- test/config_test.js | 28 ++++++++++++++++++++ test/database_with_default_env.json | 7 +++++ test/database_with_default_env_from_env.json | 7 +++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 test/database_with_default_env.json create mode 100644 test/database_with_default_env_from_env.json diff --git a/lib/config.js b/lib/config.js index 059bd175..ec43af3e 100644 --- a/lib/config.js +++ b/lib/config.js @@ -69,8 +69,12 @@ exports.load = function(fileName, currentEnv) { out.setCurrent(currentEnv); } else if(config['default']) { out.setCurrent(config['default']); - } else if(config.env) { - out.setCurrent(config.env); + } else if(config.defaultEnv) { + if (config.defaultEnv.ENV) { + out.setCurrent(process.env[config.defaultEnv.ENV]); + } else { + out.setCurrent(config.defaultEnv); + } } else { out.setCurrent(['dev', 'development']); } diff --git a/test/config_test.js b/test/config_test.js index 7c4ce41f..0d02e04e 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -44,6 +44,34 @@ vows.describe('config').addBatch({ assert.ok(error instanceof SyntaxError, "Expected broken file to produce syntax error"); } } +}).addBatch({ + 'loading from a file with default env option': { + topic: function() { + var configPath = path.join(__dirname, 'database_with_default_env.json'); + return config.load(configPath); + }, + + 'should load a value from the default env': function (config) { + var current = config.getCurrent(); + assert.equal(current.env, 'local'); + assert.equal(current.settings.driver, 'sqlite3'); + assert.equal(current.settings.filename, ':memory:'); + }, + } +}).addBatch({ + 'loading from a file with default env option in ENV variable': { + topic: function() { + process.env['NODE_ENV'] = 'local'; + var configPath = path.join(__dirname, 'database_with_default_env_from_env.json'); + return config.load(configPath); + }, + + 'should load a value from the env set in NODE_ENV': function (config) { + var current = config.getCurrent(); + assert.equal(current.settings.driver, 'sqlite3'); + assert.equal(current.settings.filename, ':memory:'); + }, + } }).addBatch({ 'loading from a file with ENV vars': { topic: function() { diff --git a/test/database_with_default_env.json b/test/database_with_default_env.json new file mode 100644 index 00000000..1c03578e --- /dev/null +++ b/test/database_with_default_env.json @@ -0,0 +1,7 @@ +{ + "defaultEnv": "local", + "local": { + "driver": "sqlite3", + "filename": ":memory:" + } +} diff --git a/test/database_with_default_env_from_env.json b/test/database_with_default_env_from_env.json new file mode 100644 index 00000000..12100ca0 --- /dev/null +++ b/test/database_with_default_env_from_env.json @@ -0,0 +1,7 @@ +{ + "defaultEnv": {"ENV": "NODE_ENV"}, + "local": { + "driver": "sqlite3", + "filename": ":memory:" + } +} From 81abf8e1e4b8d2abf81d054b7aea99aecb5e839e Mon Sep 17 00:00:00 2001 From: Sanketh Katta Date: Thu, 5 Nov 2015 15:30:18 -0800 Subject: [PATCH 246/412] Support setting default environment via ENV variable. --- lib/config.js | 8 ++++-- test/config_test.js | 28 ++++++++++++++++++++ test/database_with_default_env.json | 7 +++++ test/database_with_default_env_from_env.json | 7 +++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 test/database_with_default_env.json create mode 100644 test/database_with_default_env_from_env.json diff --git a/lib/config.js b/lib/config.js index 059bd175..ec43af3e 100644 --- a/lib/config.js +++ b/lib/config.js @@ -69,8 +69,12 @@ exports.load = function(fileName, currentEnv) { out.setCurrent(currentEnv); } else if(config['default']) { out.setCurrent(config['default']); - } else if(config.env) { - out.setCurrent(config.env); + } else if(config.defaultEnv) { + if (config.defaultEnv.ENV) { + out.setCurrent(process.env[config.defaultEnv.ENV]); + } else { + out.setCurrent(config.defaultEnv); + } } else { out.setCurrent(['dev', 'development']); } diff --git a/test/config_test.js b/test/config_test.js index 7c4ce41f..0d02e04e 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -44,6 +44,34 @@ vows.describe('config').addBatch({ assert.ok(error instanceof SyntaxError, "Expected broken file to produce syntax error"); } } +}).addBatch({ + 'loading from a file with default env option': { + topic: function() { + var configPath = path.join(__dirname, 'database_with_default_env.json'); + return config.load(configPath); + }, + + 'should load a value from the default env': function (config) { + var current = config.getCurrent(); + assert.equal(current.env, 'local'); + assert.equal(current.settings.driver, 'sqlite3'); + assert.equal(current.settings.filename, ':memory:'); + }, + } +}).addBatch({ + 'loading from a file with default env option in ENV variable': { + topic: function() { + process.env['NODE_ENV'] = 'local'; + var configPath = path.join(__dirname, 'database_with_default_env_from_env.json'); + return config.load(configPath); + }, + + 'should load a value from the env set in NODE_ENV': function (config) { + var current = config.getCurrent(); + assert.equal(current.settings.driver, 'sqlite3'); + assert.equal(current.settings.filename, ':memory:'); + }, + } }).addBatch({ 'loading from a file with ENV vars': { topic: function() { diff --git a/test/database_with_default_env.json b/test/database_with_default_env.json new file mode 100644 index 00000000..1c03578e --- /dev/null +++ b/test/database_with_default_env.json @@ -0,0 +1,7 @@ +{ + "defaultEnv": "local", + "local": { + "driver": "sqlite3", + "filename": ":memory:" + } +} diff --git a/test/database_with_default_env_from_env.json b/test/database_with_default_env_from_env.json new file mode 100644 index 00000000..12100ca0 --- /dev/null +++ b/test/database_with_default_env_from_env.json @@ -0,0 +1,7 @@ +{ + "defaultEnv": {"ENV": "NODE_ENV"}, + "local": { + "driver": "sqlite3", + "filename": ":memory:" + } +} From 6c703754bf0d5f83a134c721c45ad2593d2ecba6 Mon Sep 17 00:00:00 2001 From: Luiz Freneda Date: Wed, 18 Nov 2015 18:20:57 -0200 Subject: [PATCH 247/412] coffeescript template refactory coffeescript template refactory by default coffeescript always returns the last line/variable, so there is no need to use the ~return~ keyword, there is not need for ; also. --- lib/migration.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 864282cd..d581ffac 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -51,16 +51,15 @@ Migration.prototype.defaultCoffeeTemplate = function() { 'seed = undefined', '', 'exports.setup = (options, seedLink) ->', - ' dbm = options.dbmigrate;', - ' type = dbm.dataType;', - ' seed = seedLink;', - ' return', + ' dbm = options.dbmigrate', + ' type = dbm.dataType', + ' seed = seedLink', '', 'exports.up = (db) ->', - ' return null', + ' null', '', 'exports.down = (db) ->', - ' return null', + ' null', '', '' ].join('\n'); From cc32cfdff965c858ca7baa1d7db80b827a994ec3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Dec 2015 17:58:45 +0100 Subject: [PATCH 248/412] add scope logging --- connect.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/connect.js b/connect.js index ec3fb9fa..e93d8311 100644 --- a/connect.js +++ b/connect.js @@ -7,7 +7,9 @@ var log = require('./lib/log'); var internals = {}; exports.connect = function(config, passedClass, callback) { - var internals = {}; + var internals = {}, + _config = config; + if( config.config ) { internals = config.internals; config = config.config; @@ -57,7 +59,7 @@ exports.connect = function(config, passedClass, callback) { files.push(''); - db.close = function(cb) { migrationFiles(files, callback, config, passedClass, db, oldClose, cb); }; + db.close = function(cb) { migrationFiles(files, callback, _config, passedClass, db, oldClose, cb); }; db.close(); }); @@ -99,6 +101,7 @@ function migrationFiles(files, callback, config, passedClass, db, close, cb) { } file = files.pop(); + log.info( 'Enter scope "' + ((file !== '') ? file : '/') + '"' ); if(file !== '') { From d8e25f32e78d64ff0a4209c55e397acedb9bd733 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Dec 2015 18:04:01 +0100 Subject: [PATCH 249/412] [bugfix] internal linking causes infinite loop fixes #329 --- connect.js | 17 ++++++----------- lib/migrator.js | 5 +---- lib/seeder.js | 7 ++----- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/connect.js b/connect.js index e93d8311..1dc46748 100644 --- a/connect.js +++ b/connect.js @@ -7,8 +7,7 @@ var log = require('./lib/log'); var internals = {}; exports.connect = function(config, passedClass, callback) { - var internals = {}, - _config = config; + var internals = {}; if( config.config ) { internals = config.internals; @@ -59,7 +58,8 @@ exports.connect = function(config, passedClass, callback) { files.push(''); - db.close = function(cb) { migrationFiles(files, callback, _config, passedClass, db, oldClose, cb); }; + db.close = function(cb) { migrationFiles(files, callback, config, + internals, passedClass, db, oldClose, cb); }; db.close(); }); @@ -83,18 +83,12 @@ exports.driver = function(config, callback) { driver.connect(config, internals, callback); }; -function migrationFiles(files, callback, config, passedClass, db, close, cb) { +function migrationFiles(files, callback, config, internals, + passedClass, db, close, cb) { var file, switched = false, newConf; - var internals = {}; - var _config = config; - if( config.config ) { - internals = config.internals; - config = config.config; - } - if(files.length === 1) { db.close = close; @@ -102,6 +96,7 @@ function migrationFiles(files, callback, config, passedClass, db, close, cb) { file = files.pop(); log.info( 'Enter scope "' + ((file !== '') ? file : '/') + '"' ); + console.log(internals) if(file !== '') { diff --git a/lib/migrator.js b/lib/migrator.js index 46eed75e..9dc3d0f2 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -40,12 +40,9 @@ Migrator = function(driver, migrationsDir, empty, intern) { this.migrationsDir = migrationsDir; this.internals = intern; - if(intern.linked === true) { + if(intern.linked === false) { this.seedLink = new SeedLink(driver, intern); - } - else { - intern.linked = true; } diff --git a/lib/seeder.js b/lib/seeder.js index 073047e2..0a206146 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -70,13 +70,10 @@ Seeder = function (driver, seedsDir, versionControlled, intern) { this.seedDir = seedsDir; this.isVC = versionControlled; - if(intern.linked === true) { - - this.migrationLink = new MigrationLink(driver, intern); - } - else { + if(intern.linked === false) { intern.linked = true; + this.migrationLink = new MigrationLink(driver, intern); } internals = intern; From 9fd09d70f2e737b4c08022dee4aa71cce33f5c38 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Dec 2015 17:58:45 +0100 Subject: [PATCH 250/412] add scope logging --- connect.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/connect.js b/connect.js index ec3fb9fa..e93d8311 100644 --- a/connect.js +++ b/connect.js @@ -7,7 +7,9 @@ var log = require('./lib/log'); var internals = {}; exports.connect = function(config, passedClass, callback) { - var internals = {}; + var internals = {}, + _config = config; + if( config.config ) { internals = config.internals; config = config.config; @@ -57,7 +59,7 @@ exports.connect = function(config, passedClass, callback) { files.push(''); - db.close = function(cb) { migrationFiles(files, callback, config, passedClass, db, oldClose, cb); }; + db.close = function(cb) { migrationFiles(files, callback, _config, passedClass, db, oldClose, cb); }; db.close(); }); @@ -99,6 +101,7 @@ function migrationFiles(files, callback, config, passedClass, db, close, cb) { } file = files.pop(); + log.info( 'Enter scope "' + ((file !== '') ? file : '/') + '"' ); if(file !== '') { From c0fb2ae164e9b95641af2147f06d9f88778cbf90 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Dec 2015 18:04:01 +0100 Subject: [PATCH 251/412] [bugfix] internal linking causes infinite loop fixes #329 --- connect.js | 17 ++++++----------- lib/migrator.js | 5 +---- lib/seeder.js | 7 ++----- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/connect.js b/connect.js index e93d8311..1dc46748 100644 --- a/connect.js +++ b/connect.js @@ -7,8 +7,7 @@ var log = require('./lib/log'); var internals = {}; exports.connect = function(config, passedClass, callback) { - var internals = {}, - _config = config; + var internals = {}; if( config.config ) { internals = config.internals; @@ -59,7 +58,8 @@ exports.connect = function(config, passedClass, callback) { files.push(''); - db.close = function(cb) { migrationFiles(files, callback, _config, passedClass, db, oldClose, cb); }; + db.close = function(cb) { migrationFiles(files, callback, config, + internals, passedClass, db, oldClose, cb); }; db.close(); }); @@ -83,18 +83,12 @@ exports.driver = function(config, callback) { driver.connect(config, internals, callback); }; -function migrationFiles(files, callback, config, passedClass, db, close, cb) { +function migrationFiles(files, callback, config, internals, + passedClass, db, close, cb) { var file, switched = false, newConf; - var internals = {}; - var _config = config; - if( config.config ) { - internals = config.internals; - config = config.config; - } - if(files.length === 1) { db.close = close; @@ -102,6 +96,7 @@ function migrationFiles(files, callback, config, passedClass, db, close, cb) { file = files.pop(); log.info( 'Enter scope "' + ((file !== '') ? file : '/') + '"' ); + console.log(internals) if(file !== '') { diff --git a/lib/migrator.js b/lib/migrator.js index 46eed75e..9dc3d0f2 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -40,12 +40,9 @@ Migrator = function(driver, migrationsDir, empty, intern) { this.migrationsDir = migrationsDir; this.internals = intern; - if(intern.linked === true) { + if(intern.linked === false) { this.seedLink = new SeedLink(driver, intern); - } - else { - intern.linked = true; } diff --git a/lib/seeder.js b/lib/seeder.js index 073047e2..0a206146 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -70,13 +70,10 @@ Seeder = function (driver, seedsDir, versionControlled, intern) { this.seedDir = seedsDir; this.isVC = versionControlled; - if(intern.linked === true) { - - this.migrationLink = new MigrationLink(driver, intern); - } - else { + if(intern.linked === false) { intern.linked = true; + this.migrationLink = new MigrationLink(driver, intern); } internals = intern; From 45a0c70abaf754636318ef0a448e86f373d636eb Mon Sep 17 00:00:00 2001 From: Luiz Freneda Date: Wed, 18 Nov 2015 18:20:57 -0200 Subject: [PATCH 252/412] coffeescript template refactory coffeescript template refactory by default coffeescript always returns the last line/variable, so there is no need to use the ~return~ keyword, there is not need for ; also. --- lib/migration.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 864282cd..d581ffac 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -51,16 +51,15 @@ Migration.prototype.defaultCoffeeTemplate = function() { 'seed = undefined', '', 'exports.setup = (options, seedLink) ->', - ' dbm = options.dbmigrate;', - ' type = dbm.dataType;', - ' seed = seedLink;', - ' return', + ' dbm = options.dbmigrate', + ' type = dbm.dataType', + ' seed = seedLink', '', 'exports.up = (db) ->', - ' return null', + ' null', '', 'exports.down = (db) ->', - ' return null', + ' null', '', '' ].join('\n'); From 45327573173122b09ca4f07f6cca662fbd046976 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Dec 2015 18:09:05 +0100 Subject: [PATCH 253/412] 0.10.0-beta.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56901f08..31739979 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0-beta.4", + "version": "0.10.0-beta.5", "engines": { "node": ">=0.6.0" }, From f235bf1e4580eb5d4c924e3dc8cb884fcccb393c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Dec 2015 18:32:52 +0100 Subject: [PATCH 254/412] remove debug message --- connect.js | 1 - 1 file changed, 1 deletion(-) diff --git a/connect.js b/connect.js index 1dc46748..22c0234a 100644 --- a/connect.js +++ b/connect.js @@ -96,7 +96,6 @@ function migrationFiles(files, callback, config, internals, file = files.pop(); log.info( 'Enter scope "' + ((file !== '') ? file : '/') + '"' ); - console.log(internals) if(file !== '') { From fe83b9be0b8a365c22904c08e2567a9fee79de6f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 3 Dec 2015 18:33:01 +0100 Subject: [PATCH 255/412] 0.10.0-beta.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 31739979..b68c7891 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0-beta.5", + "version": "0.10.0-beta.6", "engines": { "node": ">=0.6.0" }, From 2d3bf037b2036707fd342cb249ef8a43cbc01bf8 Mon Sep 17 00:00:00 2001 From: Maximilian Fellner Date: Fri, 1 Jan 2016 01:59:45 +0100 Subject: [PATCH 256/412] allow configuration through options object --- api.js | 15 ++++++++++++--- lib/config.js | 20 +++++++++++++++++--- test/integration/api_test.js | 27 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/api.js b/api.js index b02d83c8..9eecbf3d 100644 --- a/api.js +++ b/api.js @@ -45,6 +45,11 @@ function dbmigrate(isModule, options, callback) { if (typeof(options.config) === 'string') internals.configFile = options.string; + else if (typeof(options.config) === 'object') + internals.configObject = options.config; + + if (typeof(options.env) === 'string') + internals.currentEnv = options.env; if (typeof(options.cwd) === 'string') internals.cwd = options.cwd; @@ -492,11 +497,15 @@ function createMigrationDir(dir, callback) { } function loadConfig( config, internals ) { - var out; + var out, + currentEnv = internals.currentEnv || internals.argv.env; + if (process.env.DATABASE_URL) { - out = config.loadUrl(process.env.DATABASE_URL, internals.argv.env); + out = config.loadUrl(process.env.DATABASE_URL, currentEnv); + } else if (internals.configObject) { + out = config.loadObject(internals.configObject, currentEnv); } else { - out = config.load(internals.argv.config, internals.argv.env); + out = config.loadFile(internals.argv.config, currentEnv); } if (internals.verbose) { var current = out.getCurrent(); diff --git a/lib/config.js b/lib/config.js index ec43af3e..f723adfe 100644 --- a/lib/config.js +++ b/lib/config.js @@ -28,14 +28,22 @@ Config.prototype = { setCurrent: setCurrent }; -exports.load = function(fileName, currentEnv) { +exports.load = function(config, currentEnv) { + if (typeof(config) === 'object') { + return exports.loadObject(config, currentEnv); + } else { + return exports.loadFile(config, currentEnv); + } +}; + +exports.loadFile = function(fileName, currentEnv) { + var config; + try { fs.statSync(fileName); } catch(e) { throw new Error('Could not find database config file \'' + fileName + '\''); } - var config, - out = new Config(); try { config = require(fileName); @@ -48,6 +56,12 @@ exports.load = function(fileName, currentEnv) { config = require(path.join(process.cwd(), fileName)); } + return exports.loadObject(config, currentEnv); +}; + +exports.loadObject = function(config, currentEnv) { + var out = new Config(); + for (var env in config) { if (config[env].ENV) { out[env] = parseDatabaseUrl(process.env[config[env].ENV]); diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 66abaef3..58662b8c 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -77,4 +77,31 @@ vows.describe('api').addBatch({ assert.isTrue(called); } } +}).addBatch({ + 'load config from parameter': { + topic: function() { + var options = { + env: 'dev', + cwd: process.cwd() + '/test/integration', + config: { + dev: { + driver: 'sqlite3', + filename: ':memory:' + }, + pg: { + driver: 'pg', + database: 'db_api_test' + } + } + }; + var api = DBMigrate.getInstance(true, options); + return {options: options, api: api}; + }, + 'should load config from parameter': function(topic) { + var actual = topic.api.config; + var expected = topic.options.config; + expected.getCurrent = actual.getCurrent; + assert.deepEqual(actual, expected); + } + } }).export(module); From 7a262e1e4b8a0e7defeb860e0429cba4b3aea71c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 21 Oct 2015 03:50:47 +0200 Subject: [PATCH 257/412] adjust test --- test/integration/api_test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 58662b8c..dc87661f 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -26,7 +26,7 @@ vows.describe('api').addBatch({ config = { cwd: process.cwd() + '/test/integration' }; var api = DBMigrate.getInstance(true, config); - api.create( 'test', function( err ) { + api.create( 'test', function() { process.argv.push('up'); process.exit = function(err) { @@ -48,7 +48,7 @@ vows.describe('api').addBatch({ var ret = called; called = true; - migrator.driver.close(function(err) { + migrator.driver.close(function() { delete migrator.driver; }); From bae76721710dc7e5f82e9ec1b51c87981e7e0f64 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 23 Oct 2015 00:51:58 +0200 Subject: [PATCH 258/412] add direct execution of seeders and migrator links --- lib/migrator.js | 17 +++++++++++++++++ lib/seeder.js | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/migrator.js b/lib/migrator.js index 9dc3d0f2..16227cab 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -16,6 +16,23 @@ SeedLink.prototype = { seed: function( partialName ) { + var reset = !internals.notransactions; + + internals.notransactions = true; + + return new Promise( function( resolve, reject ) { + + this.seeder.up( partialName, function( err ) { + + if( reset ) + internals.notransactions = false; + + if ( err ) + reject( err ); + else + resolve( err ); + } ); + } ); }, link: function( partialName ) { diff --git a/lib/seeder.js b/lib/seeder.js index 0a206146..15980530 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -22,8 +22,33 @@ MigrationLink.prototype = { 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 ), @@ -34,6 +59,9 @@ MigrationLink.prototype = { if(i < keys.length) { + if ( reset ) + internals.notransactions = false; + resolve(); this.clear(); } @@ -44,6 +72,9 @@ MigrationLink.prototype = { if( err ) { + if ( reset ) + internals.notransactions = false; + reject( err ); } else { @@ -245,7 +276,7 @@ Seeder.prototype = { if( self.seedLink && self.seedLink.links.length ) { log.info('Calling linked migrations'); - return self.seedLink.process(); + return self.seedLink.process( self.migrationLink ); } return; From b6b111baa7e2808bf7cad649dc96ee623ca5df04 Mon Sep 17 00:00:00 2001 From: Sanketh Katta Date: Thu, 7 Jan 2016 18:50:29 -0800 Subject: [PATCH 259/412] Fix config file setting. --- api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.js b/api.js index 9eecbf3d..1ddf9b16 100644 --- a/api.js +++ b/api.js @@ -44,7 +44,7 @@ function dbmigrate(isModule, options, callback) { if (typeof(options) === 'object') { if (typeof(options.config) === 'string') - internals.configFile = options.string; + internals.configFile = options.config; else if (typeof(options.config) === 'object') internals.configObject = options.config; From 01c556071f1d895cbe62285404f78554c3785dce Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 12 Jan 2016 21:15:44 +0100 Subject: [PATCH 260/412] update parse db-url to 0.3.0 Introduces mongodb uri support --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b68c7891..f8ece617 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "mkdirp": "~0.5.0", "moment": "~2.10.2", "optimist": "~0.6.1", - "parse-database-url": "~0.2.2", + "parse-database-url": "~0.3.0", "pkginfo": "~0.3.0", "resolve": "^1.1.6", "semver": "~5.0.1", From 5ba0984774f7c2ad65663b8d4d704b7763be4900 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 13 Jan 2016 00:13:38 +0100 Subject: [PATCH 261/412] update some dependencies --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index f8ece617..b5bee1ca 100644 --- a/package.json +++ b/package.json @@ -45,16 +45,16 @@ }, "dependencies": { "async": "^1.0.0", - "bluebird": "^2.9.12", + "bluebird": "^3.1.1", "dotenv": "~1.2.0", "final-fs": "^1.6.0", "mkdirp": "~0.5.0", - "moment": "~2.10.2", + "moment": "~2.11.1", "optimist": "~0.6.1", "parse-database-url": "~0.3.0", "pkginfo": "~0.3.0", "resolve": "^1.1.6", - "semver": "~5.0.1", + "semver": "~5.1.0", "tunnel-ssh": "^2.0.0" }, "devDependencies": { @@ -70,7 +70,7 @@ "mysql": "^2.9.0", "pg": "^4.4.1", "proxyquire": "^1.4.0", - "rimraf": "~2.4.0", + "rimraf": "~2.5.0", "sinon": "^1.14.1", "sqlite3": "^3.1.0", "vows": "0.8.0" From ed0bb83f7df7487ea1189593e6be5c6bda83c790 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 25 Jan 2016 14:33:59 +0100 Subject: [PATCH 262/412] fix(migration): A promise is not properly identified and returning an empty resolve ends up in db-migrate hanging up forever. Fixes #343 --- lib/skeleton.js | 96 +++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/lib/skeleton.js b/lib/skeleton.js index 3501f524..b6a96635 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -57,35 +57,41 @@ var Skeleton = Class.extend({ var cb_executed = false; return new Promise(function(resolve, reject) { - var r = function( err ) { - if ( cb_executed === false ) { + var migration, + r = function( err ) { + if ( cb_executed === false ) { - cb_executed = true; + cb_executed = true; - if( err ) - reject( err ); - else - resolve(); - } - }; + if( err ) + reject( err ); + else + resolve(); + } + }; params[ params.length++ ] = r; - Promise.resolve(require(this.path).up.apply(this, params)) - .then(function( Promise ) { - if( Promise !== undefined && cb_executed === false ) { + migration = require(this.path).up.apply(this, params); + + if( migration instanceof Promise ) { - cb_executed = true; - resolve(); - } - }).catch(function(err) { + migration + .then(function() { + if( cb_executed === false ) { - if ( cb_executed === false ) { + cb_executed = true; + resolve(); + } + }).catch(function(err) { + + if ( cb_executed === false ) { - cb_executed = true; - reject( err ); - } - }); + cb_executed = true; + reject( err ); + } + }); + } }.bind(this)); }, @@ -94,34 +100,40 @@ var Skeleton = Class.extend({ var cb_executed = false; return new Promise(function(resolve, reject) { - var r = function( err ) { - if ( cb_executed === false ) { + var migration, + r = function( err ) { + if ( cb_executed === false ) { - cb_executed = true; + cb_executed = true; + + if( err ) + reject( err ); + else + resolve(); + } + }; - if( err ) - reject( err ); - else - resolve(); - } - }; params[ params.length++ ] = r; + migration = require(this.path).down.apply(this, params); - Promise.resolve(require(this.path).down.apply(this, params)) - .then(function( Promise ) { - if( Promise !== undefined && cb_executed === false ) { + if( migration instanceof Promise ) { - cb_executed = true; - resolve(); - } - }).catch(function(err) { + migration + .then(function( Promise ) { + if( Promise !== undefined && cb_executed === false ) { - if ( cb_executed === false ) { + cb_executed = true; + resolve(); + } + }).catch(function(err) { + + if ( cb_executed === false ) { - cb_executed = true; - reject( err ); - } - }); + cb_executed = true; + reject( err ); + } + }); + } }.bind(this)); }, From 68f4d89ee5cfb6cca1cf6aa5379d70b58697e908 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 25 Jan 2016 15:32:16 +0100 Subject: [PATCH 263/412] fix(api): callback not called on run If db-mgirate is run via any run method (except directly from console), the callback was not available to the migration functions anymore. --- api.js | 15 ++++++++++++++- lib/skeleton.js | 2 ++ test/integration/api_test.js | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/api.js b/api.js index 1ddf9b16..0cc2a0ba 100644 --- a/api.js +++ b/api.js @@ -521,6 +521,7 @@ function loadConfig( config, internals ) { } function executeCreateMigration(internals, config, callback) { + var migrationsDir = internals.argv['migrations-dir']; if (internals.migrationMode && internals.migrationMode !== 'all') { @@ -611,6 +612,7 @@ function shouldCreateCoffeeFile( intenrals, config ) { } function createSqlFiles(internals, config, callback) { + var migrationsDir = internals.argv['migrations-dir']; if (internals.migrationMode && internals.migrationMode !== 'all') { @@ -678,10 +680,11 @@ function _assert(err, callback) { function executeUp(internals, config, callback) { + var callback = callback || internals.onComplete; + if (!internals.argv.count) { internals.argv.count = Number.MAX_VALUE; } - index.connect({ config: config.getCurrent().settings, internals: internals @@ -699,6 +702,7 @@ function executeUp(internals, config, callback) { migrator.driver.createMigrationsTable(function(err) { assert.ifError(err); log.verbose('migration table created'); + migrator.up(internals.argv, internals.onComplete.bind(this, migrator, callback)); }); @@ -707,6 +711,8 @@ function executeUp(internals, config, callback) { function executeDown(internals, config, callback) { + var callback = callback || internals.onComplete; + if (!internals.argv.count) { log.info('Defaulting to running 1 down migration.'); internals.argv.count = 1; @@ -730,6 +736,8 @@ function executeDown(internals, config, callback) { function executeDB(internals, config, callback) { + var callback = callback || internals.onComplete; + if (internals.argv._.length > 0) { internals.argv.dbname = internals.argv._.shift().toString(); } else { @@ -779,6 +787,8 @@ function executeDB(internals, config, callback) { function executeSeed(internals, config, callback) { + var callback = callback || internals.onComplete; + if (internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); } @@ -809,6 +819,9 @@ function executeSeed(internals, config, callback) { } function executeUndoSeed(internals, config, callback) { + + var callback = callback || internals.onComplete; + if (!internals.argv.count) { log.info('Defaulting to running 1 down seed.'); internals.argv.count = 1; diff --git a/lib/skeleton.js b/lib/skeleton.js index b6a96635..00fcbce9 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -74,6 +74,7 @@ var Skeleton = Class.extend({ migration = require(this.path).up.apply(this, params); + if( migration === null ) migration = Promise.resolve(); if( migration instanceof Promise ) { migration @@ -116,6 +117,7 @@ var Skeleton = Class.extend({ params[ params.length++ ] = r; migration = require(this.path).down.apply(this, params); + if( migration === null ) migration = Promise.resolve(); if( migration instanceof Promise ) { migration diff --git a/test/integration/api_test.js b/test/integration/api_test.js index dc87661f..772d9c87 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -28,9 +28,9 @@ vows.describe('api').addBatch({ var api = DBMigrate.getInstance(true, config); api.create( 'test', function() { process.argv.push('up'); - process.exit = function(err) { + var ret = called; called = true; From 67ac66af80c78b89e754a50309fa0ee3f3a51a6d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 25 Jan 2016 19:01:32 +0100 Subject: [PATCH 264/412] fix(api): callback called twice Revert the change to add the callback if it is undefined. Fixes #343 --- api.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/api.js b/api.js index 0cc2a0ba..b60c2ff6 100644 --- a/api.js +++ b/api.js @@ -680,8 +680,6 @@ function _assert(err, callback) { function executeUp(internals, config, callback) { - var callback = callback || internals.onComplete; - if (!internals.argv.count) { internals.argv.count = Number.MAX_VALUE; } @@ -711,8 +709,6 @@ function executeUp(internals, config, callback) { function executeDown(internals, config, callback) { - var callback = callback || internals.onComplete; - if (!internals.argv.count) { log.info('Defaulting to running 1 down migration.'); internals.argv.count = 1; @@ -736,8 +732,6 @@ function executeDown(internals, config, callback) { function executeDB(internals, config, callback) { - var callback = callback || internals.onComplete; - if (internals.argv._.length > 0) { internals.argv.dbname = internals.argv._.shift().toString(); } else { @@ -787,8 +781,6 @@ function executeDB(internals, config, callback) { function executeSeed(internals, config, callback) { - var callback = callback || internals.onComplete; - if (internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); } @@ -820,8 +812,6 @@ function executeSeed(internals, config, callback) { function executeUndoSeed(internals, config, callback) { - var callback = callback || internals.onComplete; - if (!internals.argv.count) { log.info('Defaulting to running 1 down seed.'); internals.argv.count = 1; From 39e0b88871be066f7bc1bf35ead8c8f00d2d098f Mon Sep 17 00:00:00 2001 From: Sanketh Katta Date: Mon, 25 Jan 2016 11:57:28 -0800 Subject: [PATCH 265/412] Fix promise issue for down migrations. --- lib/skeleton.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/skeleton.js b/lib/skeleton.js index 00fcbce9..109bf1ce 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -121,8 +121,8 @@ var Skeleton = Class.extend({ if( migration instanceof Promise ) { migration - .then(function( Promise ) { - if( Promise !== undefined && cb_executed === false ) { + .then(function() { + if( cb_executed === false ) { cb_executed = true; resolve(); From e6df315ee87138a08aa75b5fcfdce504d5a0aa4c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 28 Jan 2016 00:22:44 +0100 Subject: [PATCH 266/412] refactor(migration): Make check for promise more reliable --- lib/skeleton.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/skeleton.js b/lib/skeleton.js index 109bf1ce..9bb64241 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -4,6 +4,12 @@ var Promise = require('bluebird'); var lpad = require('./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); } @@ -75,7 +81,7 @@ var Skeleton = Class.extend({ migration = require(this.path).up.apply(this, params); if( migration === null ) migration = Promise.resolve(); - if( migration instanceof Promise ) { + if( isPromise( migration ) ) { migration .then(function() { @@ -118,7 +124,7 @@ var Skeleton = Class.extend({ migration = require(this.path).down.apply(this, params); if( migration === null ) migration = Promise.resolve(); - if( migration instanceof Promise ) { + if( isPromise( migration ) ) { migration .then(function() { From 8d1b9789cf5b894be3c2ce11771dcb4cb72d0719 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 3 Feb 2016 23:50:29 +0100 Subject: [PATCH 267/412] fix(test): Stub MySQL connect method instead of calling the original The MySQL driver now connects directly to the driver, instead on the first query. This caused some trouble with the ssh tunnel test, this functionality was stubbed. Fixes #348 --- test/driver/index_test.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/driver/index_test.js b/test/driver/index_test.js index 1e6cff5d..17e2f787 100644 --- a/test/driver/index_test.js +++ b/test/driver/index_test.js @@ -24,9 +24,8 @@ var indexConnectCallback = function(self, tunnelStub, driverSpy) { self.callback(err, db, tunnelStub, driverSpy); return; } - db.close(function() { - self.callback(err, db, tunnelStub, driverSpy); - }); + + self.callback(err, db, tunnelStub, driverSpy); }; }; @@ -38,7 +37,7 @@ vows.describe('index').addBatch({ var driver = require('db-migrate-mysql'); // Set up stubs/spies to verify correct flow - var driverSpy = sinon.spy(driver, 'connect'); + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); var tunnelStub = sinon.stub().callsArg(1); var index = proxyquire('../../lib/driver/index', { @@ -87,7 +86,7 @@ vows.describe('index').addBatch({ // Set up stubs/spies to verify correct flow var tunnelStub = sinon.stub().callsArgWith(1, new Error('error')); - var driverSpy = sinon.spy(driver, 'connect'); + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); var index = proxyquire('../../lib/driver/index', { 'tunnel-ssh': tunnelStub, From 3c4f90604e94f8a40e27634f0b272b0305551712 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 5 Feb 2016 18:23:34 +0100 Subject: [PATCH 268/412] chore(security): Bump dependency because of security vulnerability --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b5bee1ca..288de9aa 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "dotenv": "~1.2.0", "final-fs": "^1.6.0", "mkdirp": "~0.5.0", - "moment": "~2.11.1", + "moment": "~2.11.2", "optimist": "~0.6.1", "parse-database-url": "~0.3.0", "pkginfo": "~0.3.0", From eb0e3c608d61cc0c151be4b87b5a3c865984a9a3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 5 Feb 2016 18:33:45 +0100 Subject: [PATCH 269/412] pull down package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 288de9aa..ca6f52d2 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0-beta.6", + "version": "0.10.0-beta.11", "engines": { "node": ">=0.6.0" }, From 30b9119b5e8d3ceb5cc2b955fb959f39a0d7e427 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 5 Feb 2016 19:08:47 +0100 Subject: [PATCH 270/412] chore(dependencies): update and remove unneeded dependencies --- package.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index ca6f52d2..67916aeb 100644 --- a/package.json +++ b/package.json @@ -60,19 +60,19 @@ "devDependencies": { "code": "^1.3.0", "db-meta": "~0.4.1", - "db-migrate-base": "^1.2.1", - "db-migrate-mongodb": "^1.0.1", - "db-migrate-mysql": "^1.1.2", - "db-migrate-pg": "^0.1.4", - "db-migrate-sqlite3": "^0.1.2", - "jscs": "^2.1.1", + "db-migrate-base": "^1.2.5", + "db-migrate-mongodb": "^1.1.4", + "db-migrate-mysql": "^1.1.6", + "db-migrate-pg": "^0.1.9", + "db-migrate-sqlite3": "^0.1.5", + "jscs": "^2.9.0", "lab": "^6.1.0", - "mysql": "^2.9.0", - "pg": "^4.4.1", + "mysql": "^2.10.2", + "pg": "^4.4.4", "proxyquire": "^1.4.0", "rimraf": "~2.5.0", - "sinon": "^1.14.1", - "sqlite3": "^3.1.0", + "sinon": "^1.17.3", + "sqlite3": "^3.1.1", "vows": "0.8.0" }, "scripts": { From 0addd6040f6cfecb7944e39c920eca533befe96e Mon Sep 17 00:00:00 2001 From: Ian Reis Date: Thu, 24 Mar 2016 13:03:17 -0400 Subject: [PATCH 271/412] Update data_type.js For consistency :-) --- lib/data_type.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/data_type.js b/lib/data_type.js index 5f8f1222..f365a34a 100644 --- a/lib/data_type.js +++ b/lib/data_type.js @@ -3,7 +3,9 @@ module.exports = { STRING: 'string', TEXT: 'text', SMALLINT: 'smallint', + BIGINT: 'bigint', INTEGER: 'int', + SMALL_INTEGER: 'smallint', BIG_INTEGER: 'bigint', REAL: 'real', DATE: 'date', From c55cae21244c5c838ab77d88dd362a490604e709 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 17 Apr 2016 11:12:00 +0200 Subject: [PATCH 272/412] chore(travis): change travis config to use modern compiler --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0b6f34f6..3e10ab2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,8 +39,16 @@ cache: - node_modules addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 mariadb: "10.0" +before_install: + - export CXX=g++-4.8; export CC=gcc-4.8; + before_script: - until nc -z localhost 27017 ; do echo Waiting for MongoDB; sleep 1; done - mysql -e "create database db_migrate_test;" From 57cc05a79e0b4422a34a4f931c8b9cf7731b40ac Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 17 Apr 2016 11:17:51 +0200 Subject: [PATCH 273/412] chore(travis): add node 5 to ci builds --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3e10ab2d..cafe8ebe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ node_js: - 4.0 - 4.1 - 4.2 + - 5 - "iojs-1" - "iojs-2" - "iojs-3" From d281bf16d0ba0aece97091ffb19002894c808569 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 17 Apr 2016 11:26:17 +0200 Subject: [PATCH 274/412] chore(travis): remove obsolete node 4.1 Keep 4.2 lts and node 4 in the build which is usually enough. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cafe8ebe..9aae96ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ node_js: - 0.10 - 0.12 - 4.0 - - 4.1 - 4.2 - 5 - "iojs-1" From 28afd405b777e543ca687407a3f2f943771532de Mon Sep 17 00:00:00 2001 From: "David M. Lee" Date: Mon, 11 Apr 2016 13:58:45 -0500 Subject: [PATCH 275/412] Avoid warning in promise/callback bridge code When Bluebird detects when a promise is created within a promise handler, but is not returned, it [emits a warning][warn] 'a promise was created in a handler but was not returned from it'. This happens if the `callback()` function is implemented using Promises, but uses `nodeify()` to make it callback compatible. By using nodeify here, it handles the returned Promise (if any) and avoids the warning. [warn]: https://github.com/petkaantonov/bluebird/blob/master/docs/docs/warning-explanations.md --- lib/migrator.js | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/lib/migrator.js b/lib/migrator.js index 16227cab..ee5caad0 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -168,14 +168,7 @@ Migrator.prototype = { }) .then(self.driver.endMigration.bind(self.driver)); }) - .then(function() { - callback(); - }) - .catch(function(e) { - - throw e; - }); - + .nodeify(callback); }); }); }, @@ -221,13 +214,7 @@ Migrator.prototype = { }) .then(self.driver.endMigration.bind(self.driver)); }) - .then(function() { - callback(); - }) - .catch(function(e) { - - throw e; - }); + .nodeify(callback); }); } }; From 931795c7b4ac14e166ff6b2f1f558e054d53bfca Mon Sep 17 00:00:00 2001 From: Srikanth AD Date: Mon, 9 May 2016 15:12:56 -0400 Subject: [PATCH 276/412] Updated documentation link in README Current documentation link points to a 404 page, updated it with a working version. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 89108794..49de3025 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ https://github.com/db-migrate/mongodb Please follow the link below, for usage instructions examples and the full documentation of db-migrate. -Documentation: https://readthedocs.org/projects/db-migrate +Documentation: https://db-migrate.readthedocs.io/en/latest/ ## License From baabd7e77693afdd62356e4473365df16419e418 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 12 May 2016 21:09:41 +0200 Subject: [PATCH 277/412] chore(travis): add node 6 --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9aae96ba..43239a7a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ node_js: - 4.0 - 4.2 - 5 + - 6 - "iojs-1" - "iojs-2" - "iojs-3" @@ -27,6 +28,8 @@ os: matrix: fast_finish: true + allow_failures: + - node_js: 6 services: - mongodb From 67a0f611a30eadba149c843abaee4f1f775c7ae6 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 17 May 2016 20:55:49 +0200 Subject: [PATCH 278/412] fix(api): fix race condition on create migration A callback was placed not inside but after the callback which it belongs to. This resulted in a very rarely occuring race condition when creating migrations without an existing migration directory. Fixes #376 --- api.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/api.js b/api.js index b60c2ff6..96be2ed5 100644 --- a/api.js +++ b/api.js @@ -584,18 +584,16 @@ function executeCreateMigration(internals, config, callback) { if (_assert(err, callback)) { log.info(util.format('Created migration at %s', migration.path)); + if (shouldCreateSqlFiles(internals, config)) { + createSqlFiles(internals, config, callback); + } else { + if (typeof(callback) === 'function') { + callback(); + } + } } }); }); - - if (shouldCreateSqlFiles(internals, config)) { - createSqlFiles(internals, config, callback); - } else { - if (typeof(callback) === 'function') { - - callback(); - } - } } function shouldCreateSqlFiles( internals, config ) { From 651fa91d9aa04078df0877fe531046046dc80031 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 17 May 2016 21:06:16 +0200 Subject: [PATCH 279/412] 0.10.0-beta.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 67916aeb..d403d71a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0-beta.11", + "version": "0.10.0-beta.12", "engines": { "node": ">=0.6.0" }, From 9a051f0f6038a022d98859bd85572a5d2b055589 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 26 May 2016 10:11:53 +0200 Subject: [PATCH 280/412] chore(compatibility): update dependencies --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d403d71a..d9d66826 100644 --- a/package.json +++ b/package.json @@ -62,9 +62,9 @@ "db-meta": "~0.4.1", "db-migrate-base": "^1.2.5", "db-migrate-mongodb": "^1.1.4", - "db-migrate-mysql": "^1.1.6", - "db-migrate-pg": "^0.1.9", - "db-migrate-sqlite3": "^0.1.5", + "db-migrate-mysql": "^1.1.7", + "db-migrate-pg": "^0.1.10", + "db-migrate-sqlite3": "^0.1.6", "jscs": "^2.9.0", "lab": "^6.1.0", "mysql": "^2.10.2", From cea543c17618256f6ff11f8c24ca368f5a8887ac Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Jun 2016 22:53:04 +0200 Subject: [PATCH 281/412] chore(dev): add .tern file to project --- .tern-project | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .tern-project diff --git a/.tern-project b/.tern-project new file mode 100644 index 00000000..352ae8be --- /dev/null +++ b/.tern-project @@ -0,0 +1,7 @@ +{ + "plugins": { + "node": {}, + "lint": {}, + "node-extension": {} + } +} From 0fb8ab41eb39f9fb6632a0fbe25867ea406d0d4d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Jun 2016 23:00:54 +0200 Subject: [PATCH 282/412] refactor(log): move log into new extern lib Refers to #382 --- api.js | 2 +- bin/db-migrate | 2 +- connect.js | 2 +- lib/driver/index.js | 2 +- lib/migration.js | 2 +- lib/migrator.js | 2 +- lib/relation.js | 2 +- lib/seed.js | 2 +- lib/seeder.js | 2 +- lib/util.js | 2 +- package.json | 1 + test/driver/base_test.js | 2 +- test/driver/mysql_test.js | 2 +- test/driver/pg_test.js | 2 +- 14 files changed, 14 insertions(+), 13 deletions(-) diff --git a/api.js b/api.js index 96be2ed5..e7470b3b 100644 --- a/api.js +++ b/api.js @@ -8,7 +8,7 @@ var index = require('./connect'); var Migration = require('./lib/migration.js'); var Seeder = require('./lib/seeder.js'); var Migrator = require('./lib/migrator.js'); -var log = require('./lib/log'); +var log = require('db-migrate-shared').log; var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line var dotenv = require('dotenv'); var Promise = require('bluebird'); diff --git a/bin/db-migrate b/bin/db-migrate index 106004a7..33c4d2de 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -1,7 +1,7 @@ #!/usr/bin/env node var resolve = require( 'resolve' ); -var log = require( '../lib/log.js' ); +var log = require('db-migrate-shared').log; process.title = 'db-migrate'; diff --git a/connect.js b/connect.js index 22c0234a..8ee73de4 100644 --- a/connect.js +++ b/connect.js @@ -2,7 +2,7 @@ var recursive = require('final-fs').readdirRecursive; var fs = require('fs'); var driver = require('./lib/driver'); var path = require('path'); -var log = require('./lib/log'); +var log = require('db-migrate-shared').log; var internals = {}; diff --git a/lib/driver/index.js b/lib/driver/index.js index adb336ec..6f6f54cd 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -1,7 +1,7 @@ var internals = {}; internals.mod = internals.mod || {}; -internals.mod.log = require('../log'); +internals.mod.log = require('db-migrate-shared').log; internals.mod.type = require('../data_type'); var Shadow = require('./shadow'); var log = internals.mod.log; diff --git a/lib/migration.js b/lib/migration.js index d581ffac..eecfdd92 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -1,6 +1,6 @@ var fs = require('fs'); var path = require('path'); -var log = require('./log'); +var log = require('db-migrate-shared').log; var Skeleton = require('./skeleton'); var filesRegEx = /\.js$/; diff --git a/lib/migrator.js b/lib/migrator.js index ee5caad0..ff554f1a 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -1,6 +1,6 @@ var dbmUtil = require('./util'); var Migration = require('./migration'); -var log = require('./log'); +var log = require('db-migrate-shared').log; var Promise = require('bluebird'); var MigratorInterface = require( './interface/migratorInterface.js'); diff --git a/lib/relation.js b/lib/relation.js index 20f74905..01ae1cb9 100644 --- a/lib/relation.js +++ b/lib/relation.js @@ -1,5 +1,5 @@ var fs = require('fs'), - log = require('./log'); + log = require('db-migrate-shared').log; function Relation() { this.relations = {}; diff --git a/lib/seed.js b/lib/seed.js index 13775531..f0a3fd96 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -1,6 +1,6 @@ var fs = require('fs'); var path = require('path'); -var log = require('./log'); +var log = require('db-migrate-shared').log; var Skeleton = require('./skeleton'); var filesRegEx = /\.js$/; diff --git a/lib/seeder.js b/lib/seeder.js index 15980530..d84d0fde 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -1,5 +1,5 @@ var Seed = require('./seed'); -var log = require('./log'); +var log = require('db-migrate-shared').log; var dbmUtil = require('./util'); var Promise = require('bluebird'); var SeederInterface = require( './interface/seederInterface.js'); diff --git a/lib/util.js b/lib/util.js index 2d12055f..c8a31353 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,4 +1,4 @@ -var log = require('./log'); +var log = require('db-migrate-shared').log; function isIncludedInUp(migration, destination) { if(!destination) { diff --git a/package.json b/package.json index d9d66826..b5201aeb 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "dependencies": { "async": "^1.0.0", "bluebird": "^3.1.1", + "db-migrate-shared": "^1.0.2", "dotenv": "~1.2.0", "final-fs": "^1.6.0", "mkdirp": "~0.5.0", diff --git a/test/driver/base_test.js b/test/driver/base_test.js index 6a0d0d4c..d5badb19 100644 --- a/test/driver/base_test.js +++ b/test/driver/base_test.js @@ -5,7 +5,7 @@ var Base = require('db-migrate-base'); var internals = { migrationTable: 'migrations', mod: { - log: require('../../lib/log.js'), + log: require('db-migrate-shared').log, type: require('../../lib/data_type.js') } }; diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index fe29af1a..13500e80 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -3,7 +3,7 @@ var assert = require('assert'); var dbmeta = require('db-meta'); var dataType = require('../../lib/data_type'); var driver = require('../../lib/driver'); -var log = require('../..//lib/log.js'); +var log = require('db-migrate-shared').log; var config = require('../db.config.json').mysql; diff --git a/test/driver/pg_test.js b/test/driver/pg_test.js index 55b60ba8..d284270c 100644 --- a/test/driver/pg_test.js +++ b/test/driver/pg_test.js @@ -4,7 +4,7 @@ var assert = require('assert'); var dbmeta = require('db-meta'); var dataType = require('../../lib/data_type'); var driver = require('../../lib/driver'); -var log = require('../..//lib/log.js'); +var log = require('db-migrate-shared').log; var config = require('../db.config.json').pg; From a087d3a5673753a8ab9d1597d5ba20705e2355bc Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Jun 2016 23:06:08 +0200 Subject: [PATCH 283/412] refactor(datatype): move dataType into new extern lib Refers to #382 --- index.js | 2 +- lib/driver/index.js | 2 +- test/driver/base_test.js | 2 +- test/driver/mongodb_test.js | 3 +-- test/driver/mysql_test.js | 2 +- test/driver/pg_schema_test.js | 2 +- test/driver/pg_test.js | 2 +- test/driver/sqlite3_test.js | 2 +- 8 files changed, 8 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 959f882e..5ff47107 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line -exports.dataType = require('./lib/data_type'); +exports.dataType = require('db-migrate-shared').dataType; /** diff --git a/lib/driver/index.js b/lib/driver/index.js index 6f6f54cd..8b1fa797 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -2,7 +2,7 @@ var internals = {}; internals.mod = internals.mod || {}; internals.mod.log = require('db-migrate-shared').log; -internals.mod.type = require('../data_type'); +internals.mod.type = require('db-migrate-shared').dataType; var Shadow = require('./shadow'); var log = internals.mod.log; var tunnel = require('tunnel-ssh'), diff --git a/test/driver/base_test.js b/test/driver/base_test.js index d5badb19..3c5abd1f 100644 --- a/test/driver/base_test.js +++ b/test/driver/base_test.js @@ -6,7 +6,7 @@ var internals = { migrationTable: 'migrations', mod: { log: require('db-migrate-shared').log, - type: require('../../lib/data_type.js') + type: require('db-migrate-shared').dataType } }; diff --git a/test/driver/mongodb_test.js b/test/driver/mongodb_test.js index f1b58dab..8556c008 100644 --- a/test/driver/mongodb_test.js +++ b/test/driver/mongodb_test.js @@ -1,7 +1,7 @@ var vows = require('vows'); var assert = require('assert'); var dbmeta = require('db-meta'); -var dataType = require('../../lib/data_type'); +var dataType = require('db-migrate-shared').dataType; var driver = require('../../lib/driver'); var config = require('../db.config.json').mongodb; @@ -342,4 +342,3 @@ driver.connect(config, internals, function(err, db) { }) .export(module); }); - diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js index 13500e80..0755f2d2 100644 --- a/test/driver/mysql_test.js +++ b/test/driver/mysql_test.js @@ -1,7 +1,7 @@ var vows = require('vows'); var assert = require('assert'); var dbmeta = require('db-meta'); -var dataType = require('../../lib/data_type'); +var dataType = require('db-migrate-shared').dataType; var driver = require('../../lib/driver'); var log = require('db-migrate-shared').log; diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js index a6b19b92..2fd5f6ec 100644 --- a/test/driver/pg_schema_test.js +++ b/test/driver/pg_schema_test.js @@ -3,7 +3,7 @@ var Promise = require('bluebird'); var assert = require('assert'); var dbmeta = require('db-meta'); var pg = require('pg'); -var dataType = require('../../lib/data_type'); +var dataType = require('db-migrate-shared').dataType; var driver = require('../../lib/driver'); var databaseUrl = 'postgres://localhost/db_migrate_test'; diff --git a/test/driver/pg_test.js b/test/driver/pg_test.js index d284270c..22542a6e 100644 --- a/test/driver/pg_test.js +++ b/test/driver/pg_test.js @@ -2,7 +2,7 @@ var util = require('util'); var vows = require('vows'); var assert = require('assert'); var dbmeta = require('db-meta'); -var dataType = require('../../lib/data_type'); +var dataType = require('db-migrate-shared').dataType; var driver = require('../../lib/driver'); var log = require('db-migrate-shared').log; diff --git a/test/driver/sqlite3_test.js b/test/driver/sqlite3_test.js index a553452e..f84ca0c7 100644 --- a/test/driver/sqlite3_test.js +++ b/test/driver/sqlite3_test.js @@ -2,7 +2,7 @@ var fs = require('fs'); var vows = require('vows'); var assert = require('assert'); var dbmeta = require('db-meta'); -var dataType = require('../../lib/data_type'); +var dataType = require('db-migrate-shared').dataType; var driver = require('../../lib/driver'); var config = require('../db.config.json').sqlite3; From 3af5161da823d4e25c1d0d065521f49f151dca6d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Jun 2016 23:08:22 +0200 Subject: [PATCH 284/412] refactor(remove): remove log and dataType artifacts Refers to #382 --- lib/data_type.js | 19 ------- lib/log.js | 135 ----------------------------------------------- 2 files changed, 154 deletions(-) delete mode 100644 lib/data_type.js delete mode 100644 lib/log.js diff --git a/lib/data_type.js b/lib/data_type.js deleted file mode 100644 index f365a34a..00000000 --- a/lib/data_type.js +++ /dev/null @@ -1,19 +0,0 @@ -module.exports = { - CHAR: 'char', - STRING: 'string', - TEXT: 'text', - SMALLINT: 'smallint', - BIGINT: 'bigint', - INTEGER: 'int', - SMALL_INTEGER: 'smallint', - BIG_INTEGER: 'bigint', - REAL: 'real', - DATE: 'date', - DATE_TIME: 'datetime', - TIME: 'time', - BLOB: 'blob', - TIMESTAMP: 'timestamp', - BINARY: 'binary', - BOOLEAN: 'boolean', - DECIMAL: 'decimal' -}; diff --git a/lib/log.js b/lib/log.js deleted file mode 100644 index 6d770e3c..00000000 --- a/lib/log.js +++ /dev/null @@ -1,135 +0,0 @@ -this.isSilent = false; - -var logLevel = 15, - escape = '"', - level = { - sql: 8, - error: 4, - warn: 2, - info: 1 - }; - -exports.setLogLevel = function( log ) { - - if( typeof(log) === 'object' ) { - - logLevel = 0; - - var keys = Object.keys(log); - - for( var i = 0, len = keys.length; i < len ; ++i ) { - - logLevel = logLevel | (level[keys[i]] || 0); - } - } - else if( typeof(log) === 'string' ) { - - logLevel = 0; - log.split( '|' ).map( function (key) { - - logLevel = logLevel | (level[key] || 0); - }); - } - -}; - -exports.setEscape = function( escapeChar ) { - - if(typeof(escape) === 'string') { - - escape = escapeChar; - } -}; - -exports.silence = function (isSilent) { - return ( this.isSilent = isSilent ); -}; -exports.info = function () { - if ((!this.isSilent || global.verbose) && - logLevel & level.info) { - Array.prototype.unshift.call(arguments, '[INFO]'); - console.info.apply(console, arguments); - } -}; -exports.warn = function () { - if ((!this.isSilent || global.verbose) && - logLevel & level.warn) { - Array.prototype.unshift.call(arguments, '[WARN]'); - console.warn.apply(console, arguments); - } -}; -exports.error = function () { - if ((!this.isSilent || global.verbose) && - logLevel & level.error) { - Array.prototype.unshift.call(arguments, '[ERROR]'); - //console.trace( 'Trace from error log' ); - console.error.apply(console, arguments); - } -}; -exports.sql = function(sql) { - if ((!this.isSilent && (global.dryRun || global.verbose)) && - logLevel & level.sql) { - var args = Array.prototype.slice.call(arguments).slice(1); - args = args.slice(0, args.length - 1); - if(global.verbose) { - if(args.length > 0) { - console.log('[SQL]', sql, args); - } else { - console.log('[SQL]', sql); - } - } - if (global.dryRun) { - if(args.length > 0) { - if (logLevel === level.sql) { - - if( sql.indexOf('?') !== -1 ) { - - var split = sql.split('?'); - var logSql = split[0]; - - for (var i = 1, len = split.length; i < len; ++i) { - - if( typeof(args[i - 1]) === 'string' ) { - logSql += escape + args[i - 1] + escape + split[i]; - } - else { - logSql += escape + args[0][i - 1] + escape + split[i]; - } - } - - console.log( logSql + ';' ); - } - else if( sql.indexOf('$1') !== -1 ) { - - var logSql = sql; - - for( var i = 0, len = args[0].length; i < len; ++i ) { - - logSql = logSql.replace( '$' + (i + 1), escape + - args[0][i] + escape ); - } - - console.log( logSql + ';' ); - } - else { - - console.log(sql, args); - } - } - else { - - console.log(sql, args); - } - } else { - console.log(sql + ';'); - } - } - } -}; - -exports.verbose = function() { - if (global.verbose) { - Array.prototype.unshift.call(arguments, '[INFO]'); - console.log.apply(console, arguments); - } -}; From 6c51f8c69b82c5b42e1c6f14521f10475a59085c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Jun 2016 23:12:58 +0200 Subject: [PATCH 285/412] refactor(util): remove util artifact Resolves #382 --- lib/config.js | 2 +- lib/migrator.js | 2 +- lib/seeder.js | 2 +- lib/skeleton.js | 4 +- lib/util.js | 165 -------------------------------- test/integration/api_test.js | 2 +- test/integration/create_test.js | 2 +- test/util_test.js | 2 +- 8 files changed, 8 insertions(+), 173 deletions(-) delete mode 100644 lib/util.js diff --git a/lib/config.js b/lib/config.js index f723adfe..dda2b5d5 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,7 +1,7 @@ var fs = require('fs'); var path = require('path'); var parseDatabaseUrl = require('parse-database-url'); -var dbmUtil = require('./util'); +var dbmUtil = require('db-migrate-shared').util; var setCurrent = exports.setCurrent = function (env) { env = dbmUtil.isArray(env) ? env : [env]; diff --git a/lib/migrator.js b/lib/migrator.js index ff554f1a..e6b19120 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -1,4 +1,4 @@ -var dbmUtil = require('./util'); +var dbmUtil = require('db-migrate-shared').util; var Migration = require('./migration'); var log = require('db-migrate-shared').log; var Promise = require('bluebird'); diff --git a/lib/seeder.js b/lib/seeder.js index d84d0fde..c4c8581b 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -1,6 +1,6 @@ var Seed = require('./seed'); var log = require('db-migrate-shared').log; -var dbmUtil = require('./util'); +var dbmUtil = require('db-migrate-shared').util; var Promise = require('bluebird'); var SeederInterface = require( './interface/seederInterface.js'); diff --git a/lib/skeleton.js b/lib/skeleton.js index 9bb64241..f0f497ec 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -1,13 +1,13 @@ var path = require('path'); var inflection = require('./inflection'); var Promise = require('bluebird'); -var lpad = require('./util').lpad; +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' ); + probe.constructor && probe.constructor.name === 'Promise' ); } function formatPath(dir, name) { diff --git a/lib/util.js b/lib/util.js deleted file mode 100644 index c8a31353..00000000 --- a/lib/util.js +++ /dev/null @@ -1,165 +0,0 @@ -var log = require('db-migrate-shared').log; - -function isIncludedInUp(migration, destination) { - if(!destination) { - return true; - } - var migrationTest = migration.name.substring(0, Math.min(migration.name.length, destination.length)); - var destinationTest = destination.substring(0, Math.min(migration.name.length, destination.length)); - return migrationTest <= destinationTest; -} - -exports.filterUp = function(allMigrations, completedMigrations, destination, count) { - var sortFn = function(a, b) { - return a.name.slice(0, a.name.indexOf('-')) - b.name.slice(0, b.name.indexOf('-')); - }; - - return allMigrations.sort(sortFn) - .filter(function(migration) { - var hasRun = completedMigrations.some(function(completedMigration) { - return completedMigration.name === migration.name; - }); - return !hasRun; - }) - .filter(function(migration) { - return isIncludedInUp(migration, destination); - }) - .slice(0, count); -}; - -/** - * Similar to the shadow driver, but we reduce to a subset of an existing - * driver. - */ -exports.reduceToInterface = function(db, originInterface) { - - var Interface = {}; - Interface._original = {}; - - //set to make it optional - originInterface.exclude = originInterface.exclude || {}; - - if( db._shadowsHost ) { - - Interface._shadowsHost = db._shadowsHost; - Interface._shadowProto = db._shadowProto; - } - - var origin = (typeof(originInterface) === 'function') ? - originInterface.prototype : originInterface; - - for(var prop in db) { - - if( ( prop[0] === '_' || typeof(db[prop]) !== 'function') && - originInterface.exclude[prop] === undefined ) { - - Interface[prop] = db[prop]; - } - } - - for(var prop in origin) { - - if (typeof db[prop] === 'function') { - - Interface[prop] = db[prop]; - } - else if(typeof origin[prop] === 'function') { - - Interface[prop] = origin[prop]; - } - } - - for(var prop in originInterface.deprecated) { - - if (typeof db[prop] === 'function' && - typeof originInterface.deprecated[prop] === 'function') { - - Interface._original[prop] = db[prop]; - - (function(property) { - - Interface[property] = function() { - - log.warn('This function "' + property + - '" is deprecated and ' + - originInterface.deprecated[property + '_deprecation'] ); - - return this._original[property].apply(this, arguments); - }; - }(prop)); - } - else if(typeof originInterface[prop] === 'function') { - - Interface._original[prop] = originInterface[prop]; - - (function(property) { - - Interface[property] = function() { - - log.warn('This function "' + property + - '" is deprecated.' + '\n' + - originInterface.deprecated[property + '_deprecation'] ); - - return this._original[property].apply(this, arguments); - }; - }(prop)); - } - } - - for(var prop in originInterface.extending) { - - if (typeof db[prop] === 'function' && - typeof originInterface.extending[prop] === 'function') { - - Interface[prop] = db[prop]; - } - else if(typeof originInterface.extending[prop] === 'function') { - - Interface[prop] = originInterface.extending[prop]; - } - } - - return Interface; -}; - -exports.filterDown = function(completedMigrations, count) { - return completedMigrations.slice(0, count); -}; - - -exports.lpad = function(str, padChar, totalLength) { - str = str.toString(); - var neededPadding = totalLength - str.length; - for (var i = 0; i < neededPadding; i++) { - str = padChar + str; - } - return str; -}; - -exports.shallowCopy = function(obj) { - var newObj = {}; - for (var prop in obj) { - newObj[prop] = obj[prop]; - } - return newObj; -}; - -exports.toArray = function(obj) { - var arr = []; - for (var prop in obj) { - arr[prop] = obj[prop]; - } - return arr; -}; - -exports.isArray = function(obj) { - return Object.prototype.toString.call(obj) === '[object Array]'; -}; - -exports.isFunction = function(obj) { - return typeof(obj) === 'function'; -}; - -exports.isString = function(obj) { - return typeof(obj) === 'string'; -}; diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 772d9c87..97d23094 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -1,7 +1,7 @@ var vows = require('vows'); var assert = require('assert'); var fs = require('fs'); -var dbmUtil = require('../../lib/util'); +var dbmUtil = require('db-migrate-shared').util; var DBMigrate = require('../../'); var path = require('path'); var cp = require('child_process'); diff --git a/test/integration/create_test.js b/test/integration/create_test.js index 5e59973f..43a985e4 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -3,7 +3,7 @@ var assert = require('assert'); var fs = require('fs'); var path = require('path'); var cp = require('child_process'); -var dbmUtil = require('../../lib/util'); +var dbmUtil = require('db-migrate-shared').util; var rmdir = require('rimraf'); diff --git a/test/util_test.js b/test/util_test.js index 8c8ec073..10d7e9c7 100644 --- a/test/util_test.js +++ b/test/util_test.js @@ -1,6 +1,6 @@ var vows = require('vows'); var assert = require('assert'); -var util = require('../lib/util'); +var util = require('db-migrate-shared').util; vows.describe('util').addBatch({ 'lpad': { From 9a0a65f802a7559ca8a0e33a04b5a334ff3d1e02 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 11 Jul 2016 19:30:19 +0200 Subject: [PATCH 286/412] detect real callback for several api functions --- api.js | 38 +++++++++++++++++++++++++++++--------- lib/driver/shadow.js | 3 +-- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/api.js b/api.js index e7470b3b..c5b983b7 100644 --- a/api.js +++ b/api.js @@ -87,7 +87,7 @@ function registerEvents() { process.exit(1); }); - process.on('unhandledRejection', function(reason, promise) { + process.on('unhandledRejection', function(reason) { log.error(reason.stack); process.exit(1); }); @@ -159,7 +159,7 @@ dbmigrate.prototype = { * * Defaults to up all migrations if no count is given. */ - up: function(specification, scope, callback) { + up: function(specification, opts, callback) { if (arguments.length > 0) { if (typeof(specification) === 'string') { @@ -169,10 +169,18 @@ dbmigrate.prototype = { this.internals.argv.count = specification; } + else if (typeof(specification) === 'function') { - if (scope) { + callback = specification; + } - this.internals.migrationMode = scope; + if (typeof(opts) === 'string') { + + this.internals.migrationMode = opts; + } + else if (typeof(opts) === 'function') { + + callback = opts; } } @@ -184,17 +192,25 @@ dbmigrate.prototype = { * * Defaults to up all migrations if no count is given. */ - down: function(specification, scope, callback) { + down: function(specification, opts, callback) { if (arguments.length > 0) { - if (typeof(arguments[0]) === 'number') { + if (typeof(specification) === 'number') { this.internals.argv.count = arguments[0]; } + else if (typeof(specification) === 'function') { - if (scope) { + callback = specification; + } - this.internals.migrationMode = scope; + if (typeof(opts) === 'string') { + + this.internals.migrationMode = opts; + } + else if (typeof(opts) === 'function') { + + callback = opts; } } @@ -206,10 +222,14 @@ dbmigrate.prototype = { */ reset: function(scope, callback) { - if (scope) { + if (typeof(scope) === 'string') { this.internals.migrationMode = scope; } + else if(typeof(scope) === 'function') { + + callback = scope; + } this.internals.argv.count = Number.MAX_VALUE; executeDown(this.internals, this.config, callback); diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 9c17fa21..4328883c 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -39,8 +39,7 @@ exports.infect = function(db, intern, ShadowProto) { db[property] = function() { var params = arguments, - self = this, - callback; + self = this; return self._shadowProto[property].apply(self, params) .then( function() { From 3fca5102a893bde43b5de749278728b906486595 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 11 Jul 2016 19:54:24 +0200 Subject: [PATCH 287/412] feat(api): promisify all current api methods --- api.js | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/api.js b/api.js index c5b983b7..05eb6773 100644 --- a/api.js +++ b/api.js @@ -184,7 +184,10 @@ dbmigrate.prototype = { } } - executeUp(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeUp(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** @@ -214,7 +217,10 @@ dbmigrate.prototype = { } } - executeDown(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeDown(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** @@ -232,7 +238,10 @@ dbmigrate.prototype = { } this.internals.argv.count = Number.MAX_VALUE; - executeDown(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeDown(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** @@ -257,7 +266,10 @@ dbmigrate.prototype = { } this.internals.argv._.push(migrationName); - executeCreateMigration(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeCreateMigration(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** @@ -267,7 +279,10 @@ dbmigrate.prototype = { this.internals.argv._.push(dbname); this.internals.mode = 'create'; - executeDB(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeDB(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** @@ -277,7 +292,10 @@ dbmigrate.prototype = { this.internals.argv._.push(dbname); this.internals.mode = 'drop'; - executeDB(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeDB(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** @@ -320,7 +338,10 @@ dbmigrate.prototype = { } this.internals.mode = mode || 'vc'; - executeSeed(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeSeed(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** @@ -343,7 +364,10 @@ dbmigrate.prototype = { } } - executeUndoSeed(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeUndoSeed(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** @@ -367,7 +391,10 @@ dbmigrate.prototype = { } this.internals.argv.count = Number.MAX_VALUE; - executeUndoSeed(this.internals, this.config, callback); + return Promise.fromCallback(function(callback) { + + executeUndoSeed(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); }, /** From 47b72fab371b9976feb1bbcaa043f2e176b39596 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 15 Jul 2016 21:35:17 +0200 Subject: [PATCH 288/412] refactor(ssh): delay loading of tunnel-ssh and improve load time This improves the loadtime of db-migrate by 47%. To be exact from ~22ms to ~15ms. Resolves #387 --- lib/driver/index.js | 5 ++--- package.json | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/driver/index.js b/lib/driver/index.js index 8b1fa797..adda2298 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -5,8 +5,7 @@ internals.mod.log = require('db-migrate-shared').log; internals.mod.type = require('db-migrate-shared').dataType; var Shadow = require('./shadow'); var log = internals.mod.log; -var tunnel = require('tunnel-ssh'), - Promise = require('bluebird'), +var Promise = require('bluebird'), SeederInterface = require('../interface/seederInterface.js'), MigratorInterface = require('../interface/migratorInterface.js'), resolve = require( 'resolve' ); @@ -119,6 +118,7 @@ exports.connect = function (config, intern, callback) { }; if (config.tunnel) { + var tunnel = require('tunnel-ssh'); var tunnelConfig = JSON.parse(JSON.stringify(config.tunnel)); tunnelConfig.dstHost = config.host; tunnelConfig.dstPort = config.port; @@ -132,7 +132,6 @@ exports.connect = function (config, intern, callback) { config.port = tunnelConfig.localPort; tunnel(tunnelConfig, function (err) { - if (err) { callback(err); return; diff --git a/package.json b/package.json index b5201aeb..9c37bbed 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "pkginfo": "~0.3.0", "resolve": "^1.1.6", "semver": "~5.1.0", - "tunnel-ssh": "^2.0.0" + "tunnel-ssh": "^4.0.0" }, "devDependencies": { "code": "^1.3.0", From d538186346dafa99f7c29592bc811f32d0a3662d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 26 Jul 2016 21:23:44 +0200 Subject: [PATCH 289/412] refactor(modularize): require inflection from npm instead --- lib/driver/shadow.js | 11 +- lib/inflection.js | 512 ------------------------------------------- lib/skeleton.js | 2 +- package.json | 2 + 4 files changed, 4 insertions(+), 523 deletions(-) delete mode 100644 lib/inflection.js diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 4328883c..a71f5ff9 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -8,21 +8,12 @@ * In our case, it records the execution of methods. */ - -var internals = {}; - -function Shadow(db) { - - this.db = db; -} - - /** * 'Infect' the original class */ exports.infect = function(db, intern, ShadowProto) { - internals = intern; + var internals = intern; db._shadowsHost = {}; db._shadowProto = {}; diff --git a/lib/inflection.js b/lib/inflection.js deleted file mode 100644 index 6d4a20b4..00000000 --- a/lib/inflection.js +++ /dev/null @@ -1,512 +0,0 @@ -/* -Copyright (c) 2010 Ryan Schuft (ryan.schuft@gmail.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* - This code is based in part on the work done in Ruby to support - infection as part of Ruby on Rails in the ActiveSupport's Inflector - and Inflections classes. It was initally ported to Javascript by - Ryan Schuft (ryan.schuft@gmail.com) in 2007. It has since been modified - to not alter the String prototype. - - Currently implemented functions: - - pluralize(str, plural) == String - renders a singular English language noun into its plural form - normal results can be overridden by passing in an alternative - - singularize(str, singular) == String - renders a plural English language noun into its singular form - normal results can be overridden by passing in an alterative - - camelize(str, lowFirstLetter) == String - renders a lower case underscored word into camel case - the first letter of the result will be upper case unless you pass true - also translates "/" into "::" (underscore does the opposite) - - underscore(str) == String - renders a camel cased word into words seperated by underscores - also translates "::" back into "/" (camelize does the opposite) - - humanize(str, lowFirstLetter) == String - renders a lower case and underscored word into human readable form - defaults to making the first letter capitalized unless you pass true - - capitalize(str) == String - renders all characters to lower case and then makes the first upper - - dasherize(str) == String - renders all underbars and spaces as dashes - - titleize(str) == String - renders words into title casing (as for book titles) - - demodulize(str) == String - renders class names that are prepended by modules into just the class - - tableize(str) == String - renders camel cased singular words into their underscored plural form - - classify(str) == String - renders an underscored plural word into its camel cased singular form - - foreignKey(str, dropIdUbar) == String - renders a class name (camel cased singular noun) into a foreign key - defaults to seperating the class from the id with an underbar unless - you pass true - - ordinalize(str) == String - renders all numbers found in the string into their sequence like "22nd" -*/ - -/* - This is a list of nouns that use the same form for both singular and plural. - This list should remain entirely in lower case to correctly match Strings. -*/ -var uncountableWords = [ - 'equipment', 'information', 'rice', 'money', 'species', 'series', - 'fish', 'sheep', 'moose', 'deer', 'news' -]; - -/* - These rules translate from the singular form of a noun to its plural form. -*/ -var pluralRules = [ - [new RegExp('(m)an$', 'gi'), '$1en'], - [new RegExp('(pe)rson$', 'gi'), '$1ople'], - [new RegExp('(child)$', 'gi'), '$1ren'], - [new RegExp('^(ox)$', 'gi'), '$1en'], - [new RegExp('(ax|test)is$', 'gi'), '$1es'], - [new RegExp('(octop|vir)us$', 'gi'), '$1i'], - [new RegExp('(alias|status)$', 'gi'), '$1es'], - [new RegExp('(bu)s$', 'gi'), '$1ses'], - [new RegExp('(buffal|tomat|potat)o$', 'gi'), '$1oes'], - [new RegExp('([ti])um$', 'gi'), '$1a'], - [new RegExp('sis$', 'gi'), 'ses'], - [new RegExp('(?:([^f])fe|([lr])f)$', 'gi'), '$1$2ves'], - [new RegExp('(hive)$', 'gi'), '$1s'], - [new RegExp('([^aeiouy]|qu)y$', 'gi'), '$1ies'], - [new RegExp('(x|ch|ss|sh)$', 'gi'), '$1es'], - [new RegExp('(matr|vert|ind)ix|ex$', 'gi'), '$1ices'], - [new RegExp('([m|l])ouse$', 'gi'), '$1ice'], - [new RegExp('(quiz)$', 'gi'), '$1zes'], - [new RegExp('s$', 'gi'), 's'], - [new RegExp('$', 'gi'), 's'] -]; - -/* - These rules translate from the plural form of a noun to its singular form. -*/ -var singularRules = [ - [new RegExp('(m)en$', 'gi'), '$1an'], - [new RegExp('(pe)ople$', 'gi'), '$1rson'], - [new RegExp('(child)ren$', 'gi'), '$1'], - [new RegExp('([ti])a$', 'gi'), '$1um'], - [new RegExp('((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$','gi'), '$1$2sis'], - [new RegExp('(hive)s$', 'gi'), '$1'], - [new RegExp('(tive)s$', 'gi'), '$1'], - [new RegExp('(curve)s$', 'gi'), '$1'], - [new RegExp('([lr])ves$', 'gi'), '$1f'], - [new RegExp('([^fo])ves$', 'gi'), '$1fe'], - [new RegExp('([^aeiouy]|qu)ies$', 'gi'), '$1y'], - [new RegExp('(s)eries$', 'gi'), '$1eries'], - [new RegExp('(m)ovies$', 'gi'), '$1ovie'], - [new RegExp('(x|ch|ss|sh)es$', 'gi'), '$1'], - [new RegExp('([m|l])ice$', 'gi'), '$1ouse'], - [new RegExp('(bus)es$', 'gi'), '$1'], - [new RegExp('(o)es$', 'gi'), '$1'], - [new RegExp('(shoe)s$', 'gi'), '$1'], - [new RegExp('(cris|ax|test)es$', 'gi'), '$1is'], - [new RegExp('(octop|vir)i$', 'gi'), '$1us'], - [new RegExp('(alias|status)es$', 'gi'), '$1'], - [new RegExp('^(ox)en', 'gi'), '$1'], - [new RegExp('(vert|ind)ices$', 'gi'), '$1ex'], - [new RegExp('(matr)ices$', 'gi'), '$1ix'], - [new RegExp('(quiz)zes$', 'gi'), '$1'], - [new RegExp('s$', 'gi'), ''] -]; - -/* - This is a list of words that should not be capitalized for title case -*/ -var nonTitlecasedWords = [ - 'and', 'or', 'nor', 'a', 'an', 'the', 'so', 'but', 'to', 'of', 'at', - 'by', 'from', 'into', 'on', 'onto', 'off', 'out', 'in', 'over', - 'with', 'for' -]; - -/* - These are regular expressions used for converting between String formats -*/ -var idSuffix = new RegExp('(_ids|_id)$', 'g'); -var underbar = new RegExp('_', 'g'); -var spaceOrUnderbar = new RegExp('[ _]', 'g'); -var dashOrUnderbar = new RegExp('[-_]', 'g'); -var uppercase = new RegExp('([A-Z])', 'g'); -var underbarPrefix = new RegExp('^_'); - -/* - This is a helper method that applies rules based replacement to a String - Signature: - applyRules(str, rules, skip, override) == String - Arguments: - str - String - String to modify and return based on the passed rules - rules - Array: [RegExp, String] - Regexp to match paired with String to use for replacement - skip - Array: [String] - Strings to skip if they match - override - String (optional) - String to return as though this method succeeded (used to conform to APIs) - Returns: - String - passed String modified by passed rules - Examples: - applyRules("cows", InflectionJs.singularRules) === 'cow' -*/ -var applyRules = function(str, rules, skip, override) { - if (override) { - str = override; - } else { - var ignore = (skip.indexOf(str.toLowerCase()) > -1); - if (!ignore) { - for (var x = 0; x < rules.length; x++) { - if (str.match(rules[x][0])) { - str = str.replace(rules[x][0], rules[x][1]); - break; - } - } - } - } - return str; -}; - -/* - This lets us detect if an Array contains a given element - Signature: - indexOf(array, item, fromIndex, compareFunc) == Integer - Arguments: - array - Array - array to find object in - item - Object - object to locate in the Array - fromIndex - Integer (optional) - starts checking from this position in the Array - compareFunc - Function (optional) - function used to compare Array item vs passed item - Returns: - Integer - index position in the Array of the passed item - Examples: - ['hi','there'].indexOf("guys") === -1 - ['hi','there'].indexOf("hi") === 0 -*/ -exports.indexOf = function(array, item, fromIndex, compareFunc) { - if (!fromIndex) { - fromIndex = -1; - } - var index = -1; - for (var i = fromIndex; i < array.length; i++) { - if (array[i] === item || compareFunc && compareFunc(array[i], item)) { - index = i; - break; - } - } - return index; -}; - -/* - This function adds plurilization support to every String object - Signature: - pluralize(str, plural) == String - Arguments: - str - String - string to apply inflection on - plural - String (optional) - overrides normal output with said String - Returns: - String - singular English language nouns are returned in plural form - Examples: - "person".pluralize() == "people" - "octopus".pluralize() == "octopi" - "Hat".pluralize() == "Hats" - "person".pluralize("guys") == "guys" -*/ -exports.pluralize = function(str, plural) { - return applyRules(str, pluralRules, uncountableWords, plural); -}; - -/* - This function adds singularization support to every String object - Signature: - singularize(str, singular) == String - Arguments: - str - String - string to apply inflection on - singular - String (optional) - overrides normal output with said String - Returns: - String - plural English language nouns are returned in singular form - Examples: - "people".singularize() == "person" - "octopi".singularize() == "octopus" - "Hats".singularize() == "Hat" - "guys".singularize("person") == "person" -*/ -exports.singularize = function(str, singular) { - return applyRules(str, singularRules, uncountableWords, singular); -}; - -/* - This function adds camelization support to every String object - Signature: - camelize(str, lowFirstLetter) == String - Arguments: - str - String - string to apply inflection on - lowFirstLetter - boolean (optional) - default is to capitalize the first - letter of the results... passing true will lowercase it - Returns: - String - lower case underscored words will be returned in camel case - additionally '/' is translated to '::' - Examples: - "message_properties".camelize() == "MessageProperties" - "message_properties".camelize(true) == "messageProperties" -*/ -exports.camelize = function(str, lowFirstLetter) { - str = str.toLowerCase(); - var str_path = str.split('/'); - for (var i = 0; i < str_path.length; i++) { - var str_arr = str_path[i].split('_'); - var initX = ((lowFirstLetter && i + 1 === str_path.length) ? (1) : (0)); - for (var x = initX; x < str_arr.length; x++) { - str_arr[x] = str_arr[x].charAt(0).toUpperCase() + str_arr[x].substring(1); - } - str_path[i] = str_arr.join(''); - } - str = str_path.join('::'); - return str; -}; - -/* - This function adds underscore support to every String object - Signature: - underscore(str) == String - Arguments: - str - String - string to apply inflection on - Returns: - String - camel cased words are returned as lower cased and underscored - additionally '::' is translated to '/' - Examples: - "MessageProperties".camelize() == "message_properties" - "messageProperties".underscore() == "message_properties" -*/ -exports.underscore = function(str) { - var str_path = str.split('::'); - for (var i = 0; i < str_path.length; i++) { - str_path[i] = str_path[i].replace(uppercase, '_$1'); - str_path[i] = str_path[i].replace(underbarPrefix, ''); - } - str = str_path.join('/').toLowerCase(); - return str; -}; - -/* - This function adds humanize support to every String object - Signature: - humanize(str, lowFirstLetter) == String - Arguments: - str - String - string to apply inflection on - lowFirstLetter - boolean (optional) - default is to capitalize the first - letter of the results... passing true will lowercase it - Returns: - String - lower case underscored words will be returned in humanized form - Examples: - "message_properties".humanize() == "Message properties" - "message_properties".humanize(true) == "message properties" -*/ -exports.humanize = function(str, lowFirstLetter) { - str = str.toLowerCase(); - str = str.replace(idSuffix, ''); - str = str.replace(dashOrUnderbar, ' '); - if (!lowFirstLetter) { - str = exports.capitalize(str); - } - return str; -}; - -/* - This function adds capitalization support to every String object - Signature: - capitalize(str) == String - Arguments: - str - String - string to apply inflection on - Returns: - String - all characters will be lower case and the first will be upper - Examples: - "message_properties".capitalize() == "Message_properties" - "message properties".capitalize() == "Message properties" -*/ -exports.capitalize = function(str) { - str = str.toLowerCase(); - str = str.substring(0, 1).toUpperCase() + str.substring(1); - return str; -}; - -/* - This function adds dasherization support to every String object - Signature: - dasherize(str) == String - Arguments: - str - String - string to apply inflection on - Returns: - String - replaces all spaces or underbars with dashes - Examples: - "message_properties".capitalize() == "message-properties" - "Message Properties".capitalize() == "Message-Properties" -*/ -exports.dasherize = function(str) { - str = str.replace(spaceOrUnderbar, '-'); - return str; -}; - -/* - This function adds titleize support to every String object - Signature: - titleize(str) == String - Arguments: - str - String - string to apply inflection on - Returns: - String - capitalizes words as you would for a book title - Examples: - "message_properties".titleize() == "Message Properties" - "message properties to keep".titleize() == "Message Properties to Keep" -*/ -exports.titleize = function(str) { - str = str.toLowerCase(); - str = str.replace(underbar, ' '); - var str_arr = str.split(' '); - for (var x = 0; x < str_arr.length; x++) { - var d = str_arr[x].split('-'); - for (var i = 0; i < d.length; i++) { - if (nonTitlecasedWords.indexOf(d[i].toLowerCase()) < 0) { - d[i] = exports.capitalize(d[i]); - } - } - str_arr[x] = d.join('-'); - } - str = str_arr.join(' '); - str = str.substring(0, 1).toUpperCase() + str.substring(1); - return str; -}; - -/* - This function adds demodulize support to every String object - Signature: - demodulize(str) == String - Arguments: - str - String - string to apply inflection on - Returns: - String - removes module names leaving only class names (Ruby style) - Examples: - "Message::Bus::Properties".demodulize() == "Properties" -*/ -exports.demodulize = function(str) { - var str_arr = str.split('::'); - str = str_arr[str_arr.length - 1]; - return str; -}; - -/* - This function adds tableize support to every String object - Signature: - tableize(str) == String - Arguments: - str - String - string to apply inflection on - Returns: - String - renders camel cased words into their underscored plural form - Examples: - "MessageBusProperty".tableize() == "message_bus_properties" -*/ -exports.tableize = function(str) { - str = exports.underscore(str); - str = exports.pluralize(str); - return str; -}; - -/* - This function adds classification support to every String object - Signature: - classify(str) == String - Arguments: - str - String - string to apply inflection on - Returns: - String - underscored plural nouns become the camel cased singular form - Examples: - "message_bus_properties".classify() == "MessageBusProperty" -*/ -exports.classify = function(str) { - str = exports.camelize(str); - str = exports.singularize(str); - return str; -}; - -/* - This function adds foreign key support to every String object - Signature: - foreignKey(str, dropIdUbar) == String - Arguments: - str - String - string to apply inflection on - dropIdUbar - boolean (optional) - default is to seperate id with an - underbar at the end of the class name, you can pass true to skip it - Returns: - String - camel cased singular class names become underscored with id - Examples: - "MessageBusProperty".foreign_key() == "message_bus_property_id" - "MessageBusProperty".foreign_key(true) == "message_bus_propertyid" -*/ -exports.foreignKey = function(str, dropIdUbar) { - str = exports.demodulize(str); - str = exports.underscore(str); - str = str + ((dropIdUbar) ? ('') : ('_')) + 'id'; - return str; -}; - -/* - This function adds ordinalize support to every String object - Signature: - ordinalize(str) == String - Arguments: - str - String - string to apply inflection on - Returns: - String - renders all found numbers their sequence like "22nd" - Examples: - "the 1 pitch".ordinalize() == "the 1st pitch" -*/ -exports.ordinalize = function(str) { - var str_arr = str.split(' '); - for (var x = 0; x < str_arr.length; x++) { - var i = parseInt(str_arr[x], 10); - if (isNan(i)) { - var ltd = str_arr[x].substring(str_arr[x].length - 2); - var ld = str_arr[x].substring(str_arr[x].length - 1); - var suf = "th"; - if (ltd != "11" && ltd != "12" && ltd != "13") { - if (ld === "1") { - suf = "st"; - } else if (ld === "2") { - suf = "nd"; - } else if (ld === "3") { - suf = "rd"; - } - } - str_arr[x] += suf; - } - } - str = str_arr.join(' '); - return str; -}; - diff --git a/lib/skeleton.js b/lib/skeleton.js index f0f497ec..2cb629e8 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -1,5 +1,5 @@ var path = require('path'); -var inflection = require('./inflection'); +var inflection = require('inflection'); var Promise = require('bluebird'); var lpad = require('db-migrate-shared').util.lpad; var Class = require('./class'); diff --git a/package.json b/package.json index 9c37bbed..911cf199 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "db-migrate-shared": "^1.0.2", "dotenv": "~1.2.0", "final-fs": "^1.6.0", + "inflection": "^1.10.0", "mkdirp": "~0.5.0", "moment": "~2.11.2", "optimist": "~0.6.1", @@ -73,6 +74,7 @@ "proxyquire": "^1.4.0", "rimraf": "~2.5.0", "sinon": "^1.17.3", + "sinon-as-promised": "^3.0.1", "sqlite3": "^3.1.1", "vows": "0.8.0" }, From 03226f3737636715ab3040745dec902566e9f293 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 27 Jul 2016 15:51:28 +0200 Subject: [PATCH 290/412] refactor(tests): added shadow test and rewrite api test --- new/driver/shadow_test.js | 25 +++++ new/integration/api_test.js | 100 ++++++++++++++++++ new/integration/database.json | 6 ++ .../database_with_coffee_file.json | 7 ++ new/integration/database_with_sql_file.json | 7 ++ package.json | 4 +- 6 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 new/driver/shadow_test.js create mode 100644 new/integration/api_test.js create mode 100644 new/integration/database.json create mode 100644 new/integration/database_with_coffee_file.json create mode 100644 new/integration/database_with_sql_file.json diff --git a/new/driver/shadow_test.js b/new/driver/shadow_test.js new file mode 100644 index 00000000..7325162a --- /dev/null +++ b/new/driver/shadow_test.js @@ -0,0 +1,25 @@ +var Code = require('code'); // assertion library +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); +var sinon = require('sinon'); +var Bluebird = require('bluebird'); +var shadow = require('../../lib/driver/shadow.js'); +require('sinon-as-promised')(Bluebird); + +lab.test('shadow function and original function get called in serial', + function(done) { + + var stub = sinon.stub().callsArg(0); + var shadowStub = sinon.stub().resolves(); + var infected = shadow.infect({ + test: stub + }, {}, { + test: shadowStub + }); + + infected.test(function() { + Code.expect(shadowStub.calledOnce).to.equal(true); + Code.expect(stub.calledOnce).to.equal(true); + done(); + }); +}); diff --git a/new/integration/api_test.js b/new/integration/api_test.js new file mode 100644 index 00000000..e837e316 --- /dev/null +++ b/new/integration/api_test.js @@ -0,0 +1,100 @@ +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); +var DBMigrate = require('../../'); +var path = require('path'); +var cp = require('child_process'); + +lab.experiment('api', function() { + + lab.test('force process exit after migrations have been run', + function(done, onCleanup) { + + var process_exit = process.exit, + argv = process.argv; + + var called = false, + config = { cwd: __dirname }; + + onCleanup(teardown); + + createMigration(function() { + + var dbmigrate = DBMigrate.getInstance(true, config); + + dbmigrate.setConfigParam('force-exit', true); + dbmigrate.silence(true); + + dbmigrate.up(); + }); + + function validate() { + + Code.expect(called).to.equal(true); + done(); + } + + /** + * Create a migration with the programatic API and overwrite process.exit. + */ + function createMigration(callback) { + + var api = DBMigrate.getInstance(true, config); + api.silence(true); + + api.create( 'test', function() { + process.exit = function(err) { + + var ret = called; + called = true; + + process.exit = process_exit; + + if(err) + process.exit.apply(arguments); + + Code.expect(ret).to.equal(false); + validate(); + }; + + callback(); + } ); + } + + function teardown(next) { + + process.exit = process_exit; + process.argv = argv; + cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); + return next(); + } + }); + + lab.test('should load config from parameter', function(done) { + + var options = { + env: 'dev', + cwd: process.cwd() + '/test/integration', + config: { + dev: { + driver: 'sqlite3', + filename: ':memory:' + }, + pg: { + driver: 'pg', + database: 'db_api_test' + } + } + }; + + var api = DBMigrate.getInstance(true, options); + var actual = api.config; + var expected = options.config; + + delete expected.getCurrent; + delete actual.getCurrent; + + Code.expect(actual).to.equal(expected); + done(); + }); +}); diff --git a/new/integration/database.json b/new/integration/database.json new file mode 100644 index 00000000..f790e9c0 --- /dev/null +++ b/new/integration/database.json @@ -0,0 +1,6 @@ +{ + "dev": { + "driver": "sqlite3", + "filename": ":memory:" + } +} diff --git a/new/integration/database_with_coffee_file.json b/new/integration/database_with_coffee_file.json new file mode 100644 index 00000000..6ea53068 --- /dev/null +++ b/new/integration/database_with_coffee_file.json @@ -0,0 +1,7 @@ +{ + "dev": { + "driver": "sqlite3", + "filename": "memory" + }, + "coffee-file": true +} diff --git a/new/integration/database_with_sql_file.json b/new/integration/database_with_sql_file.json new file mode 100644 index 00000000..e2eb7f25 --- /dev/null +++ b/new/integration/database_with_sql_file.json @@ -0,0 +1,7 @@ +{ + "dev": { + "driver": "sqlite3", + "filename": "memory" + }, + "sql-file": true +} diff --git a/package.json b/package.json index 911cf199..26abb01a 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "tunnel-ssh": "^4.0.0" }, "devDependencies": { - "code": "^1.3.0", + "code": "^3.0.1", "db-meta": "~0.4.1", "db-migrate-base": "^1.2.5", "db-migrate-mongodb": "^1.1.4", @@ -68,7 +68,7 @@ "db-migrate-pg": "^0.1.10", "db-migrate-sqlite3": "^0.1.6", "jscs": "^2.9.0", - "lab": "^6.1.0", + "lab": "^10.9.0", "mysql": "^2.10.2", "pg": "^4.4.4", "proxyquire": "^1.4.0", From 4949f2ef2e3cfbc0a3ffbf3ed2df0cbf419039cd Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 27 Jul 2016 16:00:16 +0200 Subject: [PATCH 291/412] chore(comments): add some notes to the api tests --- new/integration/api_test.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/new/integration/api_test.js b/new/integration/api_test.js index e837e316..289a3452 100644 --- a/new/integration/api_test.js +++ b/new/integration/api_test.js @@ -11,13 +11,12 @@ lab.experiment('api', function() { function(done, onCleanup) { var process_exit = process.exit, - argv = process.argv; - - var called = false, + argv = process.argv, + called = false, config = { cwd: __dirname }; + // register cleanup method and start preparing the test onCleanup(teardown); - createMigration(function() { var dbmigrate = DBMigrate.getInstance(true, config); @@ -25,9 +24,19 @@ lab.experiment('api', function() { dbmigrate.setConfigParam('force-exit', true); dbmigrate.silence(true); + /** + * We have set force-exit above, this should end up in db-migrate + * executing process.exit on the final callback. + * Process.exit has been overwritten and will finally call validate. + * + * The test validation takes place in validate() + */ dbmigrate.up(); }); + /** + * Final validation after process.exit should have been called. + */ function validate() { Code.expect(called).to.equal(true); From 2d9037f670840f52015919f5d98cf9832f6d3847 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 27 Jul 2016 17:54:19 +0200 Subject: [PATCH 292/412] refactor(globals): remove several globals, this might break things There are several things that are exposed as global. For example Migrator, Seeder, Class, or the async and dbm globals. Most probably finally removing async and dbm which have been marked deprecated, will end up for some people in a breaking change. But we need to remove all those globals, to not interfere with projects using db-migrate. DB-Migrate is not just a cli module anymore though. In this step we now also finally removed internals completely from the API, and needed to adjust the onComplete callback to actually do this. This change could also lead to a breaking change and should thus be communicated All in all this is a big clean up and also two not necessary functions were removed. --- api.js | 39 +++++++++++++++------------------------ index.js | 46 ---------------------------------------------- lib/class.js | 6 +++--- lib/migrator.js | 2 +- lib/seeder.js | 2 +- 5 files changed, 20 insertions(+), 75 deletions(-) diff --git a/api.js b/api.js index 05eb6773..cb6e7a9b 100644 --- a/api.js +++ b/api.js @@ -13,28 +13,22 @@ var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line var dotenv = require('dotenv'); var Promise = require('bluebird'); - -//global declaration for detection like it's done in umigrate //deprecated -global.dbm = require('./'); //deprecated -global.async = require('async'); //deprecated - -var internals = {}; - function dbmigrate(isModule, options, callback) { this.internals = { - onComplete: internals.onComplete + onComplete: onComplete }; - internals = this.internals; + var internals = this.internals; if (typeof(callback) === 'function') this.internals.onComplete = callback; else if (typeof(options) === 'function') this.internals.onComplete = options; - this.dataType = dbm.dataType; - this.version = dbm.version; + this.internals.dbm = require('./'); + this.dataType = this.internals.dbm.dataType; + this.version = this.internals.dbm.version; dotenv.load({ silent: true }); @@ -67,8 +61,7 @@ function dbmigrate(isModule, options, callback) { this.config = loadConfig( require('./lib/config.js'), this.internals ); index.exportInternals(internals); - this.internals.dbm = dbm; - global.dbm = dbm; //deprecated + this.internals.migrationOptions = { dbmigrate: this.internals.dbm, ignoreOnInit: this.internals.argv['ignore-on-init'], @@ -112,7 +105,7 @@ dbmigrate.prototype = { return true; }, - _internals: internals, + _internals: this.internals, /** * Add a configuration option to dbmigrate. @@ -503,7 +496,7 @@ function setDefaultArgv(internals, isModule) { .argv; if (internals.argv.version) { - console.log(dbm.version); + console.log(internals.dbm.version); process.exit(0); } @@ -652,7 +645,7 @@ function shouldIgnoreOnInitFiles( internals, config ) { 'ignore-on-init']; } -function shouldCreateCoffeeFile( intenrals, config ) { +function shouldCreateCoffeeFile( internals, config ) { return internals.argv['coffee-file'] || config['coffee-file']; } @@ -747,7 +740,7 @@ function executeUp(internals, config, callback) { log.verbose('migration table created'); migrator.up(internals.argv, internals.onComplete.bind(this, - migrator, callback)); + migrator, internals, callback)); }); }); } @@ -770,7 +763,7 @@ function executeDown(internals, config, callback) { migrator.driver.createMigrationsTable(function(err) { assert.ifError(err); migrator.down(internals.argv, internals.onComplete.bind(this, - migrator, callback)); + migrator, internals, callback)); }); }); } @@ -842,13 +835,13 @@ function executeSeed(internals, config, callback) { if (internals.mode === 'static') { seeder.seed(internals.argv, internals.onComplete.bind(this, seeder, - callback)); + internals, callback)); } else { seeder.createSeedsTable(function(err) { if (_assert(err, callback)) { seeder.seed(internals.argv, internals.onComplete.bind(this, - seeder, callback)); + seeder, internals, callback)); } }); } @@ -884,16 +877,14 @@ function executeUndoSeed(internals, config, callback) { if (_assert(err, callback)) { seeder.down(internals.argv, internals.onComplete.bind(this, - seeder, callback)); + seeder, internals, callback)); } }); } }); } -internals.onComplete = onComplete; - -function onComplete(migrator, callback, originalErr) { +function onComplete(migrator, internals, callback, originalErr) { if (typeof(callback) !== 'function') { originalErr = originalErr || callback; diff --git a/index.js b/index.js index 5ff47107..72cbdcc8 100644 --- a/index.js +++ b/index.js @@ -2,52 +2,6 @@ var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line exports.dataType = require('db-migrate-shared').dataType; - -/** - * Removes a module from the cache - */ -uncache = function (moduleName) { - // Run over the cache looking for the files - // loaded by the specified module name - searchCache(moduleName, function (mod) { - delete require.cache[mod.id]; - }); - - // Remove cached paths to the module. - // Thanks to @bentael for pointing this out. - Object.keys(module.constructor._pathCache).forEach(function(cacheKey) { - if (cacheKey.indexOf(moduleName)>0) { - delete module.constructor._pathCache[cacheKey]; - } - }); -}; - -/** - * Runs over the cache to search for all the cached - * files - */ -searchCache = function (moduleName, callback) { - // Resolve the module identified by the specified name - var mod = require.resolve(moduleName); - - // Check if the module has been resolved and found within - // the cache - if (mod && ((mod = require.cache[mod]) !== undefined)) { - // Recursively go over the results - (function run(mod) { - // Go over each of the module's children and - // run over it - mod.children.forEach(function (child) { - run(child); - }); - - // Call the specified callback providing the - // found module - callback(mod); - })(mod); - } -}; - module.exports.getInstance = function(isModule, options, callback) { delete require.cache[require.resolve('./api.js')]; diff --git a/lib/class.js b/lib/class.js index 9aea5864..155c7774 100644 --- a/lib/class.js +++ b/lib/class.js @@ -6,10 +6,10 @@ var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; // The base Class implementation (does nothing) -Class = function(){}; +var Class = function(){}; // Create a new Class that inherits from this class -Class.extend = function(prop) { +Class.extend = function ext(prop) { var _super = this.prototype; // Instantiate a base class (but only create the instance, @@ -56,7 +56,7 @@ Class.extend = function(prop) { Class.prototype.constructor = Class; // And make this class extendable - Class.extend = arguments.callee; + Class.extend = ext; return Class; }; diff --git a/lib/migrator.js b/lib/migrator.js index e6b19120..a8ffbd71 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -51,7 +51,7 @@ SeedLink.prototype = { } }; -Migrator = function(driver, migrationsDir, empty, intern) { +var Migrator = function(driver, migrationsDir, empty, intern) { this.driver = dbmUtil.reduceToInterface( driver, MigratorInterface ); this._driver = driver; this.migrationsDir = migrationsDir; diff --git a/lib/seeder.js b/lib/seeder.js index c4c8581b..3c7d94a1 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -94,7 +94,7 @@ MigrationLink.prototype = { } }; -Seeder = function (driver, seedsDir, versionControlled, intern) { +var Seeder = function (driver, seedsDir, versionControlled, intern) { SeederInterface.extending = intern.interfaces.SeederInterface; this.driver = dbmUtil.reduceToInterface( driver, SeederInterface ); this._driver = driver; From f71600092d1e7c8ff61d72e6ebc56622228f6b67 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 27 Jul 2016 23:08:17 +0200 Subject: [PATCH 293/412] chore(parallelize): parallelize non interferring api tests --- new/integration/api_test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/new/integration/api_test.js b/new/integration/api_test.js index 289a3452..6c4096a3 100644 --- a/new/integration/api_test.js +++ b/new/integration/api_test.js @@ -8,7 +8,7 @@ var cp = require('child_process'); lab.experiment('api', function() { lab.test('force process exit after migrations have been run', - function(done, onCleanup) { + { parallel : true}, function(done, onCleanup) { var process_exit = process.exit, argv = process.argv, @@ -79,7 +79,8 @@ lab.experiment('api', function() { } }); - lab.test('should load config from parameter', function(done) { + lab.test('should load config from parameter', { parallel : true}, + function(done) { var options = { env: 'dev', From b6c9365454c48229e5b43eaa29fdbe13c6c7ffcc Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 3 Aug 2016 17:12:06 +0200 Subject: [PATCH 294/412] refactor(tests): add index tests and some configs --- new/database.json | 16 +++ new/database_with_default_env.json | 7 + new/database_with_default_env_from_env.json | 7 + new/database_with_env.json | 7 + new/database_with_env_url.json | 3 + new/database_with_null_values.json | 16 +++ new/database_with_syntax_error.json | 1 + new/db.config.example.json | 20 +++ new/db.config.json | 22 +++ new/driver/index_test.js | 140 ++++++++++++++++++++ new/driver/shadow_test.js | 5 +- 11 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 new/database.json create mode 100644 new/database_with_default_env.json create mode 100644 new/database_with_default_env_from_env.json create mode 100644 new/database_with_env.json create mode 100644 new/database_with_env_url.json create mode 100644 new/database_with_null_values.json create mode 100644 new/database_with_syntax_error.json create mode 100644 new/db.config.example.json create mode 100644 new/db.config.json create mode 100644 new/driver/index_test.js diff --git a/new/database.json b/new/database.json new file mode 100644 index 00000000..7bea8191 --- /dev/null +++ b/new/database.json @@ -0,0 +1,16 @@ +{ + "dev": { + "driver": "sqlite3", + "filename": ":memory:" + }, + + "test": { + "driver": "sqlite3", + "filename": ":memory:" + }, + + "prod": { + "driver": "sqlite3", + "filename": "prod.db" + } +} diff --git a/new/database_with_default_env.json b/new/database_with_default_env.json new file mode 100644 index 00000000..1c03578e --- /dev/null +++ b/new/database_with_default_env.json @@ -0,0 +1,7 @@ +{ + "defaultEnv": "local", + "local": { + "driver": "sqlite3", + "filename": ":memory:" + } +} diff --git a/new/database_with_default_env_from_env.json b/new/database_with_default_env_from_env.json new file mode 100644 index 00000000..12100ca0 --- /dev/null +++ b/new/database_with_default_env_from_env.json @@ -0,0 +1,7 @@ +{ + "defaultEnv": {"ENV": "NODE_ENV"}, + "local": { + "driver": "sqlite3", + "filename": ":memory:" + } +} diff --git a/new/database_with_env.json b/new/database_with_env.json new file mode 100644 index 00000000..6f2d5fc7 --- /dev/null +++ b/new/database_with_env.json @@ -0,0 +1,7 @@ +{ + "prod": { + "driver": "sqlite3", + "filename": "prod.db", + "username": {"ENV": "DB_MIGRATE_TEST_VAR"} + } +} diff --git a/new/database_with_env_url.json b/new/database_with_env_url.json new file mode 100644 index 00000000..cf993432 --- /dev/null +++ b/new/database_with_env_url.json @@ -0,0 +1,3 @@ +{ + "prod": {"ENV": "DB_MIGRATE_TEST_VAR"} +} diff --git a/new/database_with_null_values.json b/new/database_with_null_values.json new file mode 100644 index 00000000..d936f22b --- /dev/null +++ b/new/database_with_null_values.json @@ -0,0 +1,16 @@ +{ + "dev": { + "driver": null, + "filename": ":memory:" + }, + + "test": { + "driver": null, + "filename": ":memory:" + }, + + "prod": { + "driver": null, + "filename": "prod.db" + } +} diff --git a/new/database_with_syntax_error.json b/new/database_with_syntax_error.json new file mode 100644 index 00000000..a5778498 --- /dev/null +++ b/new/database_with_syntax_error.json @@ -0,0 +1 @@ +{this:'is' not:'valid' json} \ No newline at end of file diff --git a/new/db.config.example.json b/new/db.config.example.json new file mode 100644 index 00000000..10d6a915 --- /dev/null +++ b/new/db.config.example.json @@ -0,0 +1,20 @@ +{ + "mysql": { + "database": "db_migrate_test", + "user": "root", + "driver": "mysql" + }, + "pg": { + "driver": "pg", + "database": "db_migrate_test" + }, + "sqlite3": { + "driver": "sqlite3", + "filename": "test.db" + }, + "mongodb": { + "driver": "mongodb", + "host": "localhost", + "database": "db_migrate_test" + } +} diff --git a/new/db.config.json b/new/db.config.json new file mode 100644 index 00000000..b3a41b94 --- /dev/null +++ b/new/db.config.json @@ -0,0 +1,22 @@ +{ + "mysql": { + "database": "db_migrate_test", + "user": "root", + "password": "12345678", + "driver": "mysql" + }, + "pg": { + "driver": "pg", + "database": "db_migrate_test", + "username": "postgres" + }, + "sqlite3": { + "driver": "sqlite3", + "filename": "test.db" + }, + "mongodb": { + "driver": "mongodb", + "host": "localhost", + "database": "db_migrate_test" + } +} diff --git a/new/driver/index_test.js b/new/driver/index_test.js new file mode 100644 index 00000000..9694520c --- /dev/null +++ b/new/driver/index_test.js @@ -0,0 +1,140 @@ +var proxyquire = require('proxyquire'); +var sinon = require('sinon'); +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); +var validDbConfigWithTunnel = { + driver: 'mysql', + host: 'dbHost', + port: 'dbPort', + tunnel: { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort' + } +}; + +var internals = { + migrationTable: 'migrations' +}; + +var indexConnectCallback = function(tunnelStub, driverSpy, callback) { + return function(err, db) { + if (err) { + callback(err, db, tunnelStub, driverSpy); + return; + } + + callback(err, db, tunnelStub, driverSpy); + }; +}; + +lab.experiment('index', function() { + + lab.test('a successful connection with ssh tunnel with expected parameters', + function(done, cleanup) { + + // Ensure that require gets a new copy of the module for each test + delete require.cache[require.resolve('db-migrate-mysql')]; + var driver = require('db-migrate-mysql'); + + // Set up stubs/spies to verify correct flow + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); + var tunnelStub = sinon.stub().callsArg(1); + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + './mysql': driver + }); + //register clean up + cleanup(function(next) { + + driverSpy.restore(); + delete require.cache[require.resolve('tunnel-ssh')]; + delete require.cache[require.resolve('db-migrate-mysql')]; + next(); + }); + + index.connect( + validDbConfigWithTunnel, + {}, + indexConnectCallback(tunnelStub, driverSpy, validate) + ); + + function validate(err, db, tunnelStub, driverSpy) { + var expectedTunnelConfig = { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort', + dstHost: 'dbHost', + dstPort: 'dbPort' + }; + var expectedDbConfig = { + driver: 'mysql', + host: '127.0.0.1', + port: 'localPort', + tunnel: { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort' + } + }; + + + Code.expect(err).to.be.null(); + Code.expect(db).to.not.be.null(); + Code.expect( + tunnelStub.withArgs(expectedTunnelConfig).calledOnce + ).to.equal(true); + Code.expect( + driverSpy.withArgs(expectedDbConfig).calledOnce + ).to.equal(true); + + done(); + } + }); + + lab.test('a failed connection with ssh tunnel', function(done, cleanup) { + + // Ensure that require gets a new copy of the module for each test + delete require.cache[require.resolve('db-migrate-mysql')]; + var driver = require('db-migrate-mysql'); + + // Set up stubs/spies to verify correct flow + var tunnelStub = sinon.stub().callsArgWith(1, new Error('error')); + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + './mysql': driver + }); + + index.connect( + validDbConfigWithTunnel, + {}, + indexConnectCallback(tunnelStub, driverSpy, validate) + ); + + //register clean up + cleanup(function(next) { + + driverSpy.restore(); + delete require.cache[require.resolve('tunnel-ssh')]; + delete require.cache[require.resolve('db-migrate-mysql')]; + next(); + }); + + function validate(err, db, tunnelStub, driverSpy) { + + Code.expect(err, 'err should be non-null') + .to.exists(); + Code.expect(db, 'driver should be null or undefined') + .to.not.exists(); + + Code.expect(tunnelStub.calledOnce, 'tunnel should be called once') + .to.equal(true); + Code.expect(driverSpy.notCalled, 'driver.connect should not be called') + .to.equal(true); + + done(); + } + }); +}); diff --git a/new/driver/shadow_test.js b/new/driver/shadow_test.js index 7325162a..a40920d1 100644 --- a/new/driver/shadow_test.js +++ b/new/driver/shadow_test.js @@ -6,7 +6,9 @@ var Bluebird = require('bluebird'); var shadow = require('../../lib/driver/shadow.js'); require('sinon-as-promised')(Bluebird); -lab.test('shadow function and original function get called in serial', +lab.experiment('shadow', function() { + + lab.test('shadow function and original function get called in serial', function(done) { var stub = sinon.stub().callsArg(0); @@ -22,4 +24,5 @@ lab.test('shadow function and original function get called in serial', Code.expect(stub.calledOnce).to.equal(true); done(); }); + }); }); From a7e5de7cce6d751f4189a121d1930468d9bf6d9b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 3 Aug 2016 18:59:15 +0200 Subject: [PATCH 295/412] refactor(tests): refactored util_tests --- new/util_test.js | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 new/util_test.js diff --git a/new/util_test.js b/new/util_test.js new file mode 100644 index 00000000..03654f86 --- /dev/null +++ b/new/util_test.js @@ -0,0 +1,57 @@ +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); +var util = require('db-migrate-shared').util; + +lab.experiment('util', { parallel: true }, function() { + + lab.experiment('lpad', { parallel: true }, lpad); +}); + +function lpad() { + + lab.test('should left pad the number of characters to equal the total length', + { parallel: true }, function(done) { + + var actual = util.lpad('prompt', '>', 8); + Code.expect(actual).to.equal('>>prompt'); + + done(); + }); + + lab.test('should apply no left padding if already equal to the total length', + { parallel: true }, function(done) { + + var actual = util.lpad('>>prompt', '>', 8); + Code.expect(actual).to.equal('>>prompt'); + + done(); + }); + + lab.test('should apply no left padding if already greater than the total ' + + 'length', { parallel: true }, function(done) { + + var actual = util.lpad('>>>prompt', '>', 8); + Code.expect(actual).to.equal('>>>prompt'); + + done(); + }); + + lab.test('should be apple to pad numbers', + { parallel: true }, function(done) { + + var actual = util.lpad(12, '>', 4); + Code.expect(actual).to.equal('>>12'); + + done(); + }); + + lab.test('should be apple to pad using numbers', + { parallel: true }, function(done) { + + var actual = util.lpad(12, 0, 4); + Code.expect(actual).to.equal('0012'); + + done(); + }); +} From 4152b41e6525c3029a073a00698c377e75323538 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 3 Aug 2016 22:47:23 +0200 Subject: [PATCH 296/412] refactor(tests): refactored migration tests --- new/driver/index_test.js | 8 +- new/driver/shadow_test.js | 4 +- new/integration/api_test.js | 4 +- new/migration_test.js | 252 ++++++++++++++++++++++++++++++++++++ 4 files changed, 260 insertions(+), 8 deletions(-) create mode 100644 new/migration_test.js diff --git a/new/driver/index_test.js b/new/driver/index_test.js index 9694520c..530ab6ad 100644 --- a/new/driver/index_test.js +++ b/new/driver/index_test.js @@ -84,10 +84,10 @@ lab.experiment('index', function() { Code.expect(db).to.not.be.null(); Code.expect( tunnelStub.withArgs(expectedTunnelConfig).calledOnce - ).to.equal(true); + ).to.be.true(); Code.expect( driverSpy.withArgs(expectedDbConfig).calledOnce - ).to.equal(true); + ).to.be.true(); done(); } @@ -130,9 +130,9 @@ lab.experiment('index', function() { .to.not.exists(); Code.expect(tunnelStub.calledOnce, 'tunnel should be called once') - .to.equal(true); + .to.be.true(); Code.expect(driverSpy.notCalled, 'driver.connect should not be called') - .to.equal(true); + .to.be.true(); done(); } diff --git a/new/driver/shadow_test.js b/new/driver/shadow_test.js index a40920d1..279c2613 100644 --- a/new/driver/shadow_test.js +++ b/new/driver/shadow_test.js @@ -20,8 +20,8 @@ lab.experiment('shadow', function() { }); infected.test(function() { - Code.expect(shadowStub.calledOnce).to.equal(true); - Code.expect(stub.calledOnce).to.equal(true); + Code.expect(shadowStub.calledOnce).to.be.true(); + Code.expect(stub.calledOnce).to.be.true(); done(); }); }); diff --git a/new/integration/api_test.js b/new/integration/api_test.js index 6c4096a3..bb7f6caa 100644 --- a/new/integration/api_test.js +++ b/new/integration/api_test.js @@ -39,7 +39,7 @@ lab.experiment('api', function() { */ function validate() { - Code.expect(called).to.equal(true); + Code.expect(called).to.be.true(); done(); } @@ -62,7 +62,7 @@ lab.experiment('api', function() { if(err) process.exit.apply(arguments); - Code.expect(ret).to.equal(false); + Code.expect(ret).to.be.false(); validate(); }; diff --git a/new/migration_test.js b/new/migration_test.js new file mode 100644 index 00000000..683a9e39 --- /dev/null +++ b/new/migration_test.js @@ -0,0 +1,252 @@ +var Code = require('code'); +var Lab = require('lab'); +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 = {}; +internals.migrationTable = 'migrations'; + +lab.experiment('migration', { parallel: true }, function() { + + lab.experiment('when creating a new migration object', { parallel: true }, + newMigrationObject); + + lab.experiment('get template', { parallel: true }, + getTemplate); +}); + +function newMigrationObject() { + + lab.experiment('with 2 parameters as the complete filepath', + { parallel: true }, function() { + + var migration = new Migration(dirName + dateString+'-'+fileName, internals); + + lab.test('should have title set without file extension', { parallel: true }, + function(done) { + + Code.expect(migration.title).to.equal(fileNameNoExtension); + done(); + }); + + lab.test('should have date set', { parallel: true }, + function(done) { + + migration.date.setMilliseconds(0); + date.setMilliseconds(0); + Code.expect(migration.date.getTime()).to.equal(date.getTime()); + done(); + }); + + lab.test('should have name set without file extension', { parallel: true }, + function(done) { + + Code.expect(migration.name).to.equal(dateString+'-'+fileNameNoExtension); + done(); + }); + + lab.test('should have path set', { parallel: true }, + function(done) { + + Code.expect(migration.path).to.equal(dirName+dateString+'-'+fileName); + done(); + }); + + lab.test('should have templateType not set', { parallel: true }, + function(done) { + + Code.expect(migration.templateType).to.be.undefined(); + done(); + }); + }); + + lab.experiment('with 3 parameters', { parallel: true }, function() { + + var migration = new Migration(fileName, dirName, date); + + lab.test('should have title set', { parallel: true }, + function(done) { + + Code.expect(migration.title).to.equal(fileName); + done(); + }); + + lab.test('should have date set with month', { parallel: true }, + function(done) { + + Code.expect(migration.date).to.equal(date); + done(); + }); + + lab.test('should have name set', { parallel: true }, + function(done) { + + Code.expect(migration.name).to.equal(dateString+'-'+fileName); + done(); + }); + + lab.test('should have path set', { parallel: true }, + function(done) { + + Code.expect(migration.path).to.equal(dirName+dateString+'-'+fileName); + done(); + }); + + lab.test('should have templateType not set', { parallel: true }, + function(done) { + + Code.expect(migration.templateType).to.be.undefined(); + done(); + }); + }); + + lab.experiment('with 5 parameters', { parallel: true }, function() { + + var migration = new Migration(fileName, dirName, date, templateType, + internals); + + lab.test('should have title set', { parallel: true }, + function(done) { + + Code.expect(migration.title).to.equal(fileName); + done(); + }); + + lab.test('should have date set', { parallel: true }, + function(done) { + + Code.expect(migration.date).to.equal(date); + done(); + }); + + lab.test('should have name set', { parallel: true }, + function(done) { + + Code.expect(migration.name).to.equal(dateString+'-'+fileName); + done(); + }); + + lab.test('should have path set', { parallel: true }, + function(done) { + + Code.expect(migration.path).to.equal(dirName+dateString+'-'+fileName); + done(); + }); + + lab.test('should have templateType set', { parallel: true }, + function(done) { + + Code.expect(migration.templateType).to.equal(templateType); + done(); + }); + }); +} + +function getTemplate() { + + lab.experiment('when template type is not set', { parallel: true }, + function() { + + var migration = new Migration(fileName, dirName, date, internals); + + lab.test('should return default javascript template', { parallel: true }, + function(done) { + + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.defaultJsTemplate()); + done(); + }); + }); + + lab.experiment('when template type is set', { parallel: true }, + function() { + + lab.experiment('as sql file loader', { parallel: true }, function() { + + var migration = new Migration(fileName, dirName, date, + Migration.TemplateType.SQL_FILE_LOADER, internals); + + lab.test('should return sql file loader template', { parallel: true }, + function(done) { + + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.sqlFileLoaderTemplate()); + done(); + }); + }); + + lab.experiment('as default sql', { parallel: true }, function() { + + var migration = new Migration(fileName, dirName, date, + Migration.TemplateType.DEFAULT_SQL, internals); + + lab.test('should return default sql template', { parallel: true }, + function(done) { + + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.defaultSqlTemplate()); + done(); + }); + }); + + lab.experiment('as default coffee', { parallel: true }, function() { + + var migration = new Migration(fileName, dirName, date, + Migration.TemplateType.DEFAULT_COFFEE, internals); + + lab.test('should return default coffee template', { parallel: true }, + function(done) { + + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.defaultCoffeeTemplate()); + done(); + }); + }); + + lab.experiment('as coffee sql loader', { parallel: true }, function() { + + var migration = new Migration(fileName, dirName, date, + Migration.TemplateType.COFFEE_SQL_FILE_LOADER, internals); + + lab.test('should return default coffee template', { parallel: true }, + function(done) { + + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.coffeeSqlFileLoaderTemplate()); + done(); + }); + }); + + lab.experiment('as default javascript', { parallel: true }, function() { + + var migration = new Migration(fileName, dirName, date, + Migration.TemplateType.DEFAULT_JS, internals); + + lab.test('should return default sql template', { parallel: true }, + function(done) { + + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.defaultJsTemplate()); + done(); + }); + }); + }); +} + +function createDateForTest() { + var date = new Date(); + date.setUTCFullYear(2014); + date.setUTCDate('20'); + date.setUTCMonth('01'); + date.setUTCHours('14'); + date.setUTCMinutes('30'); + date.setUTCSeconds('50'); + return date; +} From 555866feb7a46ff8d09f2769335b07e1812f466e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 3 Aug 2016 23:28:40 +0200 Subject: [PATCH 297/412] refactor(tests): refactored config tests --- new/config_test.js | 177 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 new/config_test.js diff --git a/new/config_test.js b/new/config_test.js new file mode 100644 index 00000000..a73638dd --- /dev/null +++ b/new/config_test.js @@ -0,0 +1,177 @@ +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); +var config = require('../lib/config'); +var path = require('path'); + +var _configLoad = config.load; +var _configLoadUrl = config.loadUrl; + +lab.experiment('config', function() { + + lab.experiment('loading from a file', { parallel: true }, + function() { + + var configPath = path.join(__dirname, 'database.json'); + var _config = config.load(configPath, 'dev'); + + lab.test('should export all environment settings', { parallel: true }, + function (done) { + + Code.expect(_config.dev).to.exists(); + Code.expect(_config.test).to.exists(); + Code.expect(_config.prod).to.exists(); + done(); + }); + + lab.test('should export a getCurrent function with all current ' + + 'environment settings', { parallel: true }, function (done) { + + var current; + Code.expect(_config.getCurrent).to.exists(); + current = _config.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); + }); + + lab.experiment('loading from a broken config file', { parallel: true }, + function() { + + var configPath = path.join(__dirname, 'database_with_syntax_error.json'); + + lab.test('should throw a syntax error', { parallel: true }, + function (done) { + + Code.expect( + config.load.bind(this, configPath, 'dev'), + 'Expected broken file to produce syntax error' + ).to.throw(SyntaxError); + done(); + }); + }); + + lab.experiment('loading from a file with default env option', + { parallel: true }, function() { + + var configPath = path.join(__dirname, 'database_with_default_env.json'); + var _config = config.load(configPath); + + lab.test('should load a value from the default env', { parallel: true }, + function (done) { + + var current = _config.getCurrent(); + Code.expect(current.env).to.equal('local'); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); + }); + + lab.experiment('loading from a file with default env option in ENV variable', + { parallel: true }, function() { + + process.env.NODE_ENV = 'local'; + var configPath = path.join( + __dirname, + 'database_with_default_env_from_env.json' + ); + var _config = config.load(configPath); + + lab.test('should load a value from the env set in NODE_ENV', + { parallel: true }, function (done) { + + var current = _config.getCurrent(); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); + }); + + lab.experiment('loading from a file with ENV vars', { parallel: true }, + function() { + + process.env.DB_MIGRATE_TEST_VAR = 'username_from_env'; + var configPath = path.join(__dirname, 'database_with_env.json'); + var _config = config.load(configPath, 'prod'); + + lab.test('should load a value from the environments', { parallel: true }, + function (done) { + + Code.expect(_config.prod.username).to.equal('username_from_env'); + done(); + }); + }); + + lab.experiment('loading from a file with ENV URL', { parallel: true }, + function() { + + process.env.DB_MIGRATE_TEST_VAR = 'postgres://uname:pw@server.com/dbname'; + var configPath = path.join(__dirname, 'database_with_env_url.json'); + var _config = config.load(configPath, 'prod'); + + lab.test('should load a value from the environments', { parallel: true }, + function (done) { + + var current = _config.getCurrent(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host, ').to.equal(rver.com'); + Code.expect(current.settings.database).to.equal('dbname'); + done(); + }); + }); + + lab.experiment('loading from an URL', { parallel: true }, + function() { + + var databaseUrl = 'postgres://uname:pw@server.com/dbname'; + var _config = config.loadUrl(databaseUrl, 'dev'); + + lab.test('should export the settings as the current environment', + { parallel: true }, function (done) { + + Code.expect(_config.dev).to.exists(); + done(); + }); + + lab.test('should export a getCurrent function with all current ' + + 'environment settings', { parallel: true }, function (done) { + + var current; + Code.expect(_config.getCurrent).to.exists(); + current = _config.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + done(); + }); + }); + + lab.experiment('loading a config with null values', function() { + + var configPath = path.join(__dirname, 'database_with_null_values.json'); + config.load = _configLoad; + config.loadUrl = _configLoadUrl; + + lab.test('should something', function(done, cleanup) { + + cleanup(function(next) { + + delete require.cache[require.resolve('../lib/config')]; + next(); + }); + + Code.expect( + config.load.bind(this, configPath, 'dev') + ).to.not.throw; + done(); + }); + }); +}); From 7f4a6256139bfa071e983cd74f734bf32dfc1491 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 3 Aug 2016 23:45:41 +0200 Subject: [PATCH 298/412] refactor(tests): refactored base tests --- new/driver/base_test.js | 96 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 new/driver/base_test.js diff --git a/new/driver/base_test.js b/new/driver/base_test.js new file mode 100644 index 00000000..8fa25779 --- /dev/null +++ b/new/driver/base_test.js @@ -0,0 +1,96 @@ +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); +var Base = require('db-migrate-base'); + +var internals = { + migrationTable: 'migrations', + mod: { + log: require('db-migrate-shared').log, + type: require('db-migrate-shared').dataType + } +}; + +lab.experiment('base', { parallel: true }, function() { + + lab.experiment('default implementation', { parallel: true }, function() { + + var base = new Base(internals); + + lab.test('inherits from EventEmitter', { parallel: true }, function(done) { + + Code.expect(base.on).to.be.not.null(); + Code.expect(base.emit).to.be.not.null(); + done(); + }); + + lab.test('throws errors for all API methods', { parallel: true }, + function(done) { + + Code.expect(function() { + base.createTable(); + }).to.throw(Error); + + Code.expect(function() { + base.dropTable(); + }).to.throw(Error); + + Code.expect(function() { + base.addColumn(); + }).to.throw(Error); + + Code.expect(function() { + base.removeColumn(); + }).to.throw(Error); + + Code.expect(function() { + base.renameColumn(); + }).to.throw(Error); + + Code.expect(function() { + base.changeColumn(); + }).to.throw(Error); + + Code.expect(function() { + base.addIndex(); + }).to.throw(Error); + + Code.expect(function() { + base.insert(); + }).to.throw(Error); + + Code.expect(function() { + base.removeIndex(); + }).to.throw(Error); + + Code.expect(function() { + base.addAssociation(); + }).to.throw(Error); + + Code.expect(function() { + base.removeAssociation(); + }).to.throw(Error); + + Code.expect(function() { + base.addForeignKey(); + }).to.throw(Error); + + Code.expect(function() { + base.removeForeignKey(); + }).to.throw(Error); + + Code.expect(function() { + base.runSql(); + }).to.throw(Error); + + done(); + }); + + lab.test('escapes single quotes', { parallel: true }, function(done) { + + Code.expect('Bill\'\'s Mother\'\'s House') + .to.equal(base.escape('Bill\'s Mother\'s House')); + done(); + }); + }); +}); From 687035f7397ddcb613141d6d4f080c0a9273c384 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 4 Aug 2016 16:45:14 +0200 Subject: [PATCH 299/412] refactor(tests): add create tests and remove sample shadows --- lib/driver/index.js | 6 +- new/integration/create_test.js | 340 +++++++++++++++++++++++++++++++++ 2 files changed, 342 insertions(+), 4 deletions(-) create mode 100644 new/integration/create_test.js diff --git a/lib/driver/index.js b/lib/driver/index.js index adda2298..45302a30 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -1,6 +1,6 @@ var internals = {}; -internals.mod = internals.mod || {}; +internals.mod = {}; internals.mod.log = require('db-migrate-shared').log; internals.mod.type = require('db-migrate-shared').dataType; var Shadow = require('./shadow'); @@ -12,9 +12,7 @@ var Promise = require('bluebird'), var ShadowProto = { - createTable: function() { return Promise.resolve(); }, - addForeignKey: function() { return Promise.resolve(); }, - createCollection: function() { return Promise.resolve(); } + createTable: function() { return Promise.resolve(); } }; exports.connect = function (config, intern, callback) { diff --git a/new/integration/create_test.js b/new/integration/create_test.js new file mode 100644 index 00000000..c8fbed87 --- /dev/null +++ b/new/integration/create_test.js @@ -0,0 +1,340 @@ +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; + +var rmdir = require('rimraf'); + + +function wipeMigrations(callback) { + var dir = path.join(__dirname, 'migrations'); + rmdir(dir, callback); +} + +function dbMigrate() { + var args = dbmUtil.toArray(arguments); + var 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; + + lab.before(function(done) { + wipeMigrations(function(err) { + + Code.expect(err).to.be.null(); + dbMigrate('create', 'first migration').on('exit', + function(code) { + + exitCode = code; + done(); + }); + }); + }); + + lab.test('does not cause an error', { parallel: true }, + function(done) { + + Code.expect(exitCode).to.equal(0); + done(); + }); + + lab.test('will create a new migration directory', { parallel: true }, + function(done) { + + var stats = fs.statSync(path.join(__dirname, 'migrations')); + Code.expect(stats.isDirectory()).to.be.true(); + done(); + }); + + lab.test('will create a new migration', { parallel: true }, + function(done) { + + var files = fs.readdirSync(path.join(__dirname, 'migrations')); + Code.expect(files.length).to.equal(1); + var file = files[0]; + Code.expect(file).to.match(/first-migration\.js$/); + done(); + }); + }); + + lab.experiment('with sql-file option set to true from config file', + function() { + + var exitCode; + + lab.before(function(done) { + + var configOption = path.join('--config=', __dirname, + 'database_with_sql_file.json'); + + wipeMigrations(function(err) { + + Code.expect(err).to.not.exist(); + dbMigrate( 'create', 'second migration', configOption).on('exit', + function(code) { + + exitCode = code; + done(); + }); + }); + }); + + lab.test('does not cause an error', { parallel: true }, function(done) { + + Code.expect(exitCode).to.equal(0); + done(); + }); + + lab.test('will create a new migration', { parallel: true }, + function(done) { + + var files = fs.readdirSync(path.join(__dirname, 'migrations')); + + for (var i = 0; i Date: Wed, 10 Aug 2016 17:53:19 +0200 Subject: [PATCH 300/412] chore(ci,dep): update ci and dependencies --- .travis.yml | 7 ------- package.json | 7 +++---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 43239a7a..ae387b02 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,9 +31,6 @@ matrix: allow_failures: - node_js: 6 -services: - - mongodb - sudo: false cache: @@ -47,13 +44,9 @@ addons: - ubuntu-toolchain-r-test packages: - g++-4.8 - mariadb: "10.0" before_install: - export CXX=g++-4.8; export CC=gcc-4.8; before_script: - - until nc -z localhost 27017 ; do echo Waiting for MongoDB; sleep 1; done - - mysql -e "create database db_migrate_test;" - - createdb db_migrate_test - cp test/db.config.ci test/db.config.json diff --git a/package.json b/package.json index 26abb01a..dcd3288a 100644 --- a/package.json +++ b/package.json @@ -44,19 +44,18 @@ "url": "https://github.com/db-migrate/node-db-migrate.git" }, "dependencies": { - "async": "^1.0.0", "bluebird": "^3.1.1", "db-migrate-shared": "^1.0.2", "dotenv": "~1.2.0", "final-fs": "^1.6.0", "inflection": "^1.10.0", "mkdirp": "~0.5.0", - "moment": "~2.11.2", + "moment": "^2.14.1", "optimist": "~0.6.1", "parse-database-url": "~0.3.0", "pkginfo": "~0.3.0", "resolve": "^1.1.6", - "semver": "~5.1.0", + "semver": "^5.3.0", "tunnel-ssh": "^4.0.0" }, "devDependencies": { @@ -79,6 +78,6 @@ "vows": "0.8.0" }, "scripts": { - "test": "node node_modules/.bin/vows" + "test": "lab -t 75 new" } } From 1c8a308c3f4312939b8f7f623e948830b20b2886 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 10 Aug 2016 18:06:33 +0200 Subject: [PATCH 301/412] chore(test): create Makefile for tests and edit ci config Removing 0.10 and 0.12 from tests --- .travis.yml | 2 -- Makefile | 8 ++++++++ package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 Makefile diff --git a/.travis.yml b/.travis.yml index ae387b02..954a318a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: node_js node_js: - - 0.10 - - 0.12 - 4.0 - 4.2 - 5 diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..cbfe3337 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +test: + @node node_modules/lab/bin/lab new -I verbose,dryRun +test-cov: + @node node_modules/lab/bin/lab new -t 75 -I verbose,dryRun +test-cov-html: + @node node_modules/lab/bin/lab new -r html -o coverage.html -I verbose,dryRun + +.PHONY: test test-cov test-cov-html diff --git a/package.json b/package.json index dcd3288a..959fef41 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,6 @@ "vows": "0.8.0" }, "scripts": { - "test": "lab -t 75 new" + "test": "make test-cov" } } From bf878018663e406c544abfe0411f453577be31ff Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 10 Aug 2016 18:16:33 +0200 Subject: [PATCH 302/412] chore(ci): clean up ci config --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 954a318a..5b9b2d82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,6 @@ node_js: - 4.2 - 5 - 6 - - "iojs-1" - - "iojs-2" - - "iojs-3" - - "iojs" notifications: email: @@ -26,8 +22,6 @@ os: matrix: fast_finish: true - allow_failures: - - node_js: 6 sudo: false From 0028a659165e66c6900e34cbe10665c4cea2c89b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 12 Aug 2016 10:00:20 +0200 Subject: [PATCH 303/412] chore(dependencies): upgrade dotenv and pkginfo --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 959fef41..96c63caa 100644 --- a/package.json +++ b/package.json @@ -46,14 +46,14 @@ "dependencies": { "bluebird": "^3.1.1", "db-migrate-shared": "^1.0.2", - "dotenv": "~1.2.0", + "dotenv": "^2.0.0", "final-fs": "^1.6.0", "inflection": "^1.10.0", "mkdirp": "~0.5.0", "moment": "^2.14.1", "optimist": "~0.6.1", "parse-database-url": "~0.3.0", - "pkginfo": "~0.3.0", + "pkginfo": "^0.4.0", "resolve": "^1.1.6", "semver": "^5.3.0", "tunnel-ssh": "^4.0.0" From 7d53893a34a39165c98cd464d9936ebbc967ba51 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 12 Aug 2016 10:03:16 +0200 Subject: [PATCH 304/412] chore(devdep): update and remove some devDependencies --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 96c63caa..cae79971 100644 --- a/package.json +++ b/package.json @@ -66,14 +66,13 @@ "db-migrate-mysql": "^1.1.7", "db-migrate-pg": "^0.1.10", "db-migrate-sqlite3": "^0.1.6", - "jscs": "^2.9.0", "lab": "^10.9.0", "mysql": "^2.10.2", - "pg": "^4.4.4", + "pg": "^6.1.0", "proxyquire": "^1.4.0", "rimraf": "~2.5.0", "sinon": "^1.17.3", - "sinon-as-promised": "^3.0.1", + "sinon-as-promised": "^4.0.2", "sqlite3": "^3.1.1", "vows": "0.8.0" }, From 6fb6b976a71f1413cc616e1cae86a57c8ce63f15 Mon Sep 17 00:00:00 2001 From: Thomas Reggi Date: Mon, 15 Aug 2016 13:32:28 -0400 Subject: [PATCH 305/412] use path.join (#353) refactor(template): use path.join as it is intended to be used --- lib/migration.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index eecfdd92..90720747 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -122,7 +122,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { '};', '', 'exports.up = function(db) {', - ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( + ' 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){', @@ -138,7 +138,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { '};', '', 'exports.down = function(db) {', - ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( + ' 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){', From 3480e7ab8d02a3899051aa838ba5beb9d0082fe8 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 16 Aug 2016 18:59:43 +0200 Subject: [PATCH 306/412] fix(template): fix unnoticed error introduced in the last merge request Wrong migrations have been generated --- lib/migration.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 90720747..021f9d32 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -122,7 +122,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { '};', '', 'exports.up = function(db) {', - ' var filePath = path.join(__dirname, \'sqls', this.name.replace( + ' 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){', @@ -138,7 +138,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { '};', '', 'exports.down = function(db) {', - ' var filePath = path.join(__dirname, \'sqls', this.name.replace( + ' 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){', From 2ad22b1cef457155772daaef6d7b9ffc8d2edfb0 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 22 Aug 2016 22:48:21 +0200 Subject: [PATCH 307/412] feat(plugins): add basic support for plugins and improve performance Some libraries have been changed to be delay loaded. DB-Migrate is back to the minimal load time possible again, if no command at all is entered. Basic plugin support and the first hook, in this case of the type overwrite has been added. An functional example of a yaml config plugin has been published. Also some old functions have been cleaned up which are not necessary any more. refers to #397 --- api.js | 89 ++++++++++++++++++++++++++++++++++++++++++++------ bin/db-migrate | 39 +++++++++++----------- connect.js | 10 ------ index.js | 63 +++++++++++++++++++++++++++++++++-- lib/config.js | 28 ++++++++++++++-- package.json | 1 + 6 files changed, 187 insertions(+), 43 deletions(-) diff --git a/api.js b/api.js index cb6e7a9b..b071bd40 100644 --- a/api.js +++ b/api.js @@ -4,16 +4,61 @@ var path = require('path'); var util = require('util'); var mkdirp = require('mkdirp'); var optimist = require('optimist'); -var index = require('./connect'); -var Migration = require('./lib/migration.js'); -var Seeder = require('./lib/seeder.js'); -var Migrator = require('./lib/migrator.js'); var log = require('db-migrate-shared').log; var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line var dotenv = require('dotenv'); -var Promise = require('bluebird'); +var Promise = Promise; -function dbmigrate(isModule, options, callback) { +function registerPluginLoader(plugins) { + + return { + + overwrite: function(name) { + + if(plugins[name] && plugins[name].length) { + + var plugin = plugins[name]; + + if(plugin.length !== 1) { + log.warn( + 'Attention, multiple overwrites registered for %s, we are ' + + 'only loading the first plugin %s!', + name, + plugin.name + ); + } + + plugin = plugin[0]; + if(typeof(plugin.loadPlugin) === 'function') + plugin.loadPlugin(); + + return plugin; + } + + return false; + }, + + hook: function(name) { + + if(plugins[name] && plugins[name].length) { + + var plugin = plugins[name]; + + plugin.map(function(plugin) { + + if(typeof(plugin.loadPlugin) === 'function') + plugin.loadPlugin(); + }); + + return plugin; + } + + return false; + } + }; +} + +function dbmigrate(plugins, isModule, options, callback) { this.internals = { @@ -21,6 +66,8 @@ function dbmigrate(isModule, options, callback) { }; var internals = this.internals; + this.internals.plugins = registerPluginLoader(plugins); + if (typeof(callback) === 'function') this.internals.onComplete = callback; else if (typeof(options) === 'function') @@ -60,8 +107,8 @@ function dbmigrate(isModule, options, callback) { this.config = loadConfig( require('./lib/config.js'), this.internals ); - index.exportInternals(internals); - + //delayed loading of bluebird + Promise = require('bluebird'); this.internals.migrationOptions = { dbmigrate: this.internals.dbm, ignoreOnInit: this.internals.argv['ignore-on-init'], @@ -411,7 +458,7 @@ function setDefaultArgv(internals, isModule) { 'force-exit': false, 'sql-file': false, 'non-transactional': false, - config: internals.configFile || internals.cwd + '/database.json', + config: internals.configFile || 'database.json', 'migrations-dir': internals.cwd + '/migrations', 'vcseeder-dir': internals.cwd + '/VCSeeder', 'staticseeder-dir': internals.cwd + '/Seeder', @@ -545,7 +592,7 @@ function loadConfig( config, internals ) { } else if (internals.configObject) { out = config.loadObject(internals.configObject, currentEnv); } else { - out = config.loadFile(internals.argv.config, currentEnv); + out = config.loadFile(internals.argv.config, currentEnv, internals.plugins); } if (internals.verbose) { var current = out.getCurrent(); @@ -579,6 +626,10 @@ function executeCreateMigration(internals, config, callback) { } createMigrationDir(migrationsDir, function(err) { + + var index = require('./connect'); + var Migration = require('./lib/migration.js'); + if (err) { log.error('Failed to create migration directory at ', migrationsDir, err); @@ -661,6 +712,10 @@ function createSqlFiles(internals, config, callback) { var sqlDir = migrationsDir + '/sqls'; createMigrationDir(sqlDir, function(err) { + + var index = require('./connect'); + var Migration = require('./lib/migration.js'); + if (err) { log.error('Failed to create migration directory at ', sqlDir, err); @@ -718,6 +773,9 @@ function _assert(err, callback) { function executeUp(internals, config, callback) { + var Migrator = require('./lib/migrator.js'); + var index = require('./connect'); + if (!internals.argv.count) { internals.argv.count = Number.MAX_VALUE; } @@ -747,6 +805,9 @@ function executeUp(internals, config, callback) { function executeDown(internals, config, callback) { + var Migrator = require('./lib/migrator.js'); + var index = require('./connect'); + if (!internals.argv.count) { log.info('Defaulting to running 1 down migration.'); internals.argv.count = 1; @@ -770,6 +831,8 @@ function executeDown(internals, config, callback) { function executeDB(internals, config, callback) { + var index = require('./connect'); + if (internals.argv._.length > 0) { internals.argv.dbname = internals.argv._.shift().toString(); } else { @@ -819,6 +882,9 @@ function executeDB(internals, config, callback) { function executeSeed(internals, config, callback) { + var index = require('./connect'); + var Seeder = require('./lib/seeder.js'); + if (internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); } @@ -850,6 +916,9 @@ function executeSeed(internals, config, callback) { function executeUndoSeed(internals, config, callback) { + var index = require('./connect'); + var Seeder = require('./lib/seeder.js'); + if (!internals.argv.count) { log.info('Defaulting to running 1 down seed.'); internals.argv.count = 1; diff --git a/bin/db-migrate b/bin/db-migrate index 33c4d2de..f749c59d 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -4,33 +4,34 @@ var resolve = require( 'resolve' ); var log = require('db-migrate-shared').log; process.title = 'db-migrate'; - -if ( process.argv.indexOf( '--verbose' ) !== -1 || process.argv.indexOf( '-v' ) !== -1 ) +if ( process.argv.indexOf( '--verbose' ) !== -1 || + process.argv.indexOf( '-v' ) !== -1 + ) global.verbose = true; resolve( 'db-migrate', { -basedir: process.cwd() + basedir: process.cwd() }, function ( error, localModule ) { -var DBMigrate, dbmigrate; + var DBMigrate, dbmigrate; -if ( error ) { - DBMigrate = require( '../' ); -} -else { - DBMigrate = require( localModule ); - log.verbose( 'Detected and using the projects local version of db-migrate. ' + - '\'' + localModule + '\''); -} + if ( error ) { + DBMigrate = require( '../' ); + } + else { + DBMigrate = require( localModule ); + log.verbose( 'Detected and using the projects local version of db-migrate. ' + + '\'' + localModule + '\''); + } -if ( typeof( DBMigrate.getInstance ) !== 'function' ) { - DBMigrate = require( '../' ); + if ( typeof( DBMigrate.getInstance ) !== 'function' ) { + DBMigrate = require( '../' ); - log.warn( 'Using global instead of local detected version as you have a ' + - 'version older than 0.10.0 in your projects package.json!' ); -} + log.warn( 'Using global instead of local detected version as you have a ' + + 'version older than 0.10.0 in your projects package.json!' ); + } -dbmigrate = DBMigrate.getInstance(); -dbmigrate.run(); + dbmigrate = DBMigrate.getInstance(); + dbmigrate.run(); } ); diff --git a/connect.js b/connect.js index 8ee73de4..b4a67e20 100644 --- a/connect.js +++ b/connect.js @@ -138,13 +138,3 @@ exports.createMigration = function(migration, callback) { callback(null, migration); }); }; - -exports.exportInternals = function( intern ) { - - internals = intern; -}; - -exports.importInternals = function() { - - return internals; -}; diff --git a/index.js b/index.js index 72cbdcc8..2e6d6fcd 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,70 @@ var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line +var fs = require('fs'); +var path = require('path'); exports.dataType = require('db-migrate-shared').dataType; +function loadPluginList() { + + var plugins = JSON.parse(fs.readFileSync( + path.join(process.cwd(), 'package.json'), + 'utf-8' + ) + ), + targets = []; + + plugins = Object.assign(plugins.dependencies, plugins.devDependencies); + + for(var plugin in plugins) { + + if(plugin.startsWith('db-migrate-plugin')) + targets.push(plugin); + } + + return targets; +} + +function loadPlugins() { + + var plugins = loadPluginList(), + i = 0, + length = plugins.length, + hooks = {}; + + for(; i < length; ++i) { + + var plugin = require(plugins[i]); + if(typeof(plugin.name) !== 'string' || !plugin.hooks || !plugin.loadPlugin) + continue; + + plugin.hooks.map(function(hook) { + + hooks[hook] = hooks[hook] || []; + hooks[hook].push(plugin); + }); + } + + return hooks; +} + module.exports.getInstance = function(isModule, options, callback) { delete require.cache[require.resolve('./api.js')]; delete require.cache[require.resolve('optimist')]; - var mod = require( './api.js' ); - return new mod(isModule, options, callback); + var mod = require('./api.js'), + plugins = {}; + + try { + + if(!options || !options.noPlugins) + plugins = loadPlugins(); + } + catch(ex) {} + + if(options && options.plugins) { + + plugins = Object.assign(plugins, options.plugins); + } + + return new mod(plugins, isModule, options, callback); }; diff --git a/lib/config.js b/lib/config.js index dda2b5d5..bec1a7bd 100644 --- a/lib/config.js +++ b/lib/config.js @@ -2,6 +2,7 @@ var fs = require('fs'); var path = require('path'); var parseDatabaseUrl = require('parse-database-url'); var dbmUtil = require('db-migrate-shared').util; +var log = require('db-migrate-shared').log; var setCurrent = exports.setCurrent = function (env) { env = dbmUtil.isArray(env) ? env : [env]; @@ -36,7 +37,7 @@ exports.load = function(config, currentEnv) { } }; -exports.loadFile = function(fileName, currentEnv) { +exports.loadFile = function(fileName, currentEnv, plugins) { var config; try { @@ -46,7 +47,30 @@ exports.loadFile = function(fileName, currentEnv) { } try { - config = require(fileName); + + var plugin = false; + + if(plugins) + plugin = plugins.overwrite('init:config:overwrite:require'); + + if(plugin !== false) { + + try { + + config = plugin['init:config:overwrite:require'](fileName); + } + catch(ex) { + + log.warn('Plugin failure "' + plugin.name + + '", falling back to default behavior!'); + log.verbose(ex); + + config = require(fileName); + } + } + else + config = require(fileName); + } catch(e) { // distinguish broken files from missing ones if (e instanceof SyntaxError){ diff --git a/package.json b/package.json index cae79971..55207ff0 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "url": "https://github.com/db-migrate/node-db-migrate.git" }, "dependencies": { + "db-migrate-plugin-test": "1.0.0", "bluebird": "^3.1.1", "db-migrate-shared": "^1.0.2", "dotenv": "^2.0.0", From bbf9c3c40746d5fede060ce6c517025ed7b9d95e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 22 Aug 2016 22:50:23 +0200 Subject: [PATCH 308/412] chore(leftover): remove example plugin leftover from package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 55207ff0..cae79971 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "url": "https://github.com/db-migrate/node-db-migrate.git" }, "dependencies": { - "db-migrate-plugin-test": "1.0.0", "bluebird": "^3.1.1", "db-migrate-shared": "^1.0.2", "dotenv": "^2.0.0", From 9df704e838c198b5eff355d2374369c16945d5d9 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 22 Aug 2016 23:01:37 +0200 Subject: [PATCH 309/412] fix(api): fix introduced undefined behavior of specified configs internal.cwd added again, which is needed. --- api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.js b/api.js index b071bd40..379b2916 100644 --- a/api.js +++ b/api.js @@ -458,7 +458,7 @@ function setDefaultArgv(internals, isModule) { 'force-exit': false, 'sql-file': false, 'non-transactional': false, - config: internals.configFile || 'database.json', + config: internals.configFile || internals.cwd + '/database.json', 'migrations-dir': internals.cwd + '/migrations', 'vcseeder-dir': internals.cwd + '/VCSeeder', 'staticseeder-dir': internals.cwd + '/Seeder', From d6cf5d4194c4680c6172e5f19f0410866f4c7a1a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 5 Sep 2016 09:02:19 +0200 Subject: [PATCH 310/412] fix(api): fix scoping The api was missing the matching internal, which resulted in a missing prefix when executing scope migrations. fixes #409 --- api.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/api.js b/api.js index 379b2916..910f7f7c 100644 --- a/api.js +++ b/api.js @@ -217,6 +217,7 @@ dbmigrate.prototype = { if (typeof(opts) === 'string') { this.internals.migrationMode = opts; + this.internals.matching = opts; } else if (typeof(opts) === 'function') { @@ -250,6 +251,7 @@ dbmigrate.prototype = { if (typeof(opts) === 'string') { this.internals.migrationMode = opts; + this.internals.matching = opts; } else if (typeof(opts) === 'function') { @@ -271,6 +273,7 @@ dbmigrate.prototype = { if (typeof(scope) === 'string') { this.internals.migrationMode = scope; + this.internals.matching = scope; } else if(typeof(scope) === 'function') { @@ -303,6 +306,7 @@ dbmigrate.prototype = { } else if (scope) { this.internals.migrationMode = scope; + this.internals.matching = scope; } this.internals.argv._.push(migrationName); @@ -375,6 +379,7 @@ dbmigrate.prototype = { if (scope) { this.internals.migrationMode = scope; + this.internals.matching = scope; } this.internals.mode = mode || 'vc'; @@ -397,10 +402,12 @@ dbmigrate.prototype = { if (scope) { this.internals.migrationMode = scope; + this.internals.matching = scope; } } else if (typeof(specification) === 'string') { this.internals.migrationMode = scope; + this.internals.matching = scope; } } @@ -423,10 +430,12 @@ dbmigrate.prototype = { if (scope) { this.internals.migrationMode = scope; + this.internals.matching = scope; } } else if (typeof(specification) === 'string') { this.internals.migrationMode = scope; + this.internals.matching = scope; } } From a6b3a4571aab4cbcda6ab079b5d062f8b49dc0b3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 14 Sep 2016 15:41:39 +0200 Subject: [PATCH 311/412] most of the first protocol transition and the transition helper is implemented already. Just the logic to actually call the helper is currently missing. --- Makefile | 6 +-- lib/transitions/1.js | 0 lib/transitions/ask.js | 27 ++++++++++ lib/transitions/snippets/setup.sjs | 8 +++ lib/transitions/transitioner.js | 61 ++++++++++++++++++++++ lib/transitions/try-require.js | 82 ++++++++++++++++++++++++++++++ lib/transitions/update-version.js | 44 ++++++++++++++++ package.json | 2 + 8 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 lib/transitions/1.js create mode 100644 lib/transitions/ask.js create mode 100644 lib/transitions/snippets/setup.sjs create mode 100644 lib/transitions/transitioner.js create mode 100644 lib/transitions/try-require.js create mode 100644 lib/transitions/update-version.js diff --git a/Makefile b/Makefile index cbfe3337..b37f6777 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ test: - @node node_modules/lab/bin/lab new -I verbose,dryRun + @node node_modules/lab/bin/lab new -I verbose,dryRun --coverage-exclude lib/transitions test-cov: - @node node_modules/lab/bin/lab new -t 75 -I verbose,dryRun + @node node_modules/lab/bin/lab new -t 75 -I verbose,dryRun --coverage-exclude lib/transitions test-cov-html: - @node node_modules/lab/bin/lab new -r html -o coverage.html -I verbose,dryRun + @node node_modules/lab/bin/lab new -r html -o coverage.html -I verbose,dryRun --coverage-exclude lib/transitions .PHONY: test test-cov test-cov-html diff --git a/lib/transitions/1.js b/lib/transitions/1.js new file mode 100644 index 00000000..e69de29b diff --git a/lib/transitions/ask.js b/lib/transitions/ask.js new file mode 100644 index 00000000..e2f0b341 --- /dev/null +++ b/lib/transitions/ask.js @@ -0,0 +1,27 @@ +var prompt = require('prompt'); + +function ask(schema, callback) { + + console.log('Starting transition helper...\n'); + + prompt.start(); + + prompt.get(schema, function(err, result) { + + if(err) { + return callback(err); + } + + if(result.safe === 'n') { + + console.log('Aborted transition helper!'); + callback(new Error('Aborted transition.')); + } + else { + + callback(null, result); + } + }); +} + +module.exports = ask; diff --git a/lib/transitions/snippets/setup.sjs b/lib/transitions/snippets/setup.sjs new file mode 100644 index 00000000..03d5700a --- /dev/null +++ b/lib/transitions/snippets/setup.sjs @@ -0,0 +1,8 @@ +/** + * 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; +}; diff --git a/lib/transitions/transitioner.js b/lib/transitions/transitioner.js new file mode 100644 index 00000000..77417b6b --- /dev/null +++ b/lib/transitions/transitioner.js @@ -0,0 +1,61 @@ +var Migration = require('../migration.js'); +var tryRequire = require('./try-require.js'); +var updateVersion = require('./update-version.js'); +var ask = require('./ask.js'); +var log = require('db-migrate-shared').log; + +var internals = { + migrationProtcol: 1, + cwd: process.cwd() +}; + +ask( + { + properties: { + safe: { + description: 'This process is going to alter your migrations. We ' + + 'highly recommend you to backup your migrations or even better safe ' + + 'the current state with git versioning.\nPlease make sure you don\'t ' + + 'blow up yourself.\n\nDo you want to continue? [y/n]', + message: 'Invalid answer! Do you want to continue? [y/n]', + type: 'string', + default: 'n', + conform: function(value) { + + return value === 'y' || value === 'n'; + } + } + } + }, function(err) { + + if(err) + return; + + Migration.loadFromFilesystem('migrations/', internals, + function(err, migrations) { + + migrations.forEach(function(migration) { + + var required = tryRequire(migration, internals); + var version = (required._meta && required._meta.version) ? + required._meta.version + : 0; + + if(version !== internals.migrationProtcol) { + + var i; + + for(i = 0; i < internals.migrationProtocol; ++i) { + + var transition = require('./' + i + 1); + updateVersion(required, migration, internals, i + 1); + } + } + else { + + log.info(migration.name, 'was already transitioned to version ' + + internals.migrationProtcol + '.'); + } + }); + }); +}); diff --git a/lib/transitions/try-require.js b/lib/transitions/try-require.js new file mode 100644 index 00000000..fd174be8 --- /dev/null +++ b/lib/transitions/try-require.js @@ -0,0 +1,82 @@ +var log = require('db-migrate-shared').log; +var fs = require('fs'); + +var handled = false; +var removedGlobals = { + 'dbm is not defined': globalHandler, + 'async is not defined': globalHandler +}; + +function globalHandler(migration, retry) { + + var data = fs.readFileSync(migration, 'utf8'); + data = data.replace( + /^dbm = dbm \|\| require\(\s+'db-migrate'\s+\)/m, + 'var dbm' + ); + data = data.replace( + /^async = async \|\| require\(\s+'async'\s+\)/m, + 'var async = require( \'async\' )' + ); + data = data.replace( + /^var type = dbm.dataType/m, + 'var type' + ); + + if(data.indexOf('exports.setup = ') === -1) { + + var snippet = fs.readFileSync(__dirname + '/snippets/setup.sjs', 'utf8'); + data = data.replace(/exports.up/, snippet + '\nexports.up'); + } + + fs.writeFileSync(migration, data, 'utf8'); + + return retry(); +} + +function tryRequire(migration) { + + try { + + if(handled) { + + //require(migration.internals.cwd + 'package.json') + //cp npm install --save async + } + + return require(migration.internals.cwd + '/' + migration.path); + } + catch(ex) { + if(ex instanceof ReferenceError) { + + if(removedGlobals[ex.message]) { + + handled = true; + log.info(ex.message, 'Initiating removal of old globals...'); + return removedGlobals[ex.message]( + migration.path, + tryRequire.bind(this, migration) + ); + } + else { + + log.error( + ex.stack, + 'Unknown failure, please check your file', + migration + ); + + throw new Error('Unhandled ReferenceError while transition. Please ' + + 'fix the issues and rerun the transitioner again.'); + } + } + else { + + log.error(ex.stack, migration); + throw new Error('Unhandled Error while transition. Please ' + + 'fix the issues and rerun the transitioner again.'); + } + } +} + +module.exports = tryRequire; diff --git a/lib/transitions/update-version.js b/lib/transitions/update-version.js new file mode 100644 index 00000000..baf0e4dc --- /dev/null +++ b/lib/transitions/update-version.js @@ -0,0 +1,44 @@ +var balanced = require('balanced-match'); +var fs = require('fs'); + +function updateVersion(required, migration, internals, version) { + + var data = fs.readFileSync(migration.path, 'utf8'); + var searchString = 'exports.down'; + var balance; + var metaIndex; + var plus = 1; + + if(required._meta) + searchString = 'exports._meta'; + + metaIndex = data.indexOf(searchString); + sub = data.substring(metaIndex); + balance = balanced('{', '}', sub); + + if(sub[balance.end + 1] === ';') + ++plus; + + sub = sub.substring(0, balanced.end); + + if(required._meta) { + + required._meta.version = version; + + data = data.substring(0, metaIndex) + sub.replace( + sub.substring(balance.start, balance.end + 1), + JSON.stringify(required._meta, null, 2) + ) + data.substring(metaIndex + balance.end + plus); + } + else { + + data = data.substring(0, metaIndex + balance.end + plus) + + '\n\nexports._meta = ' + + JSON.stringify({ version: version }, null, 2) + ';' + + data.substring(metaIndex + balance.end + plus); + } + + fs.writeFileSync(migration.path, data, 'utf8'); +} + +module.exports = updateVersion; diff --git a/package.json b/package.json index cae79971..9738393a 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "url": "https://github.com/db-migrate/node-db-migrate.git" }, "dependencies": { + "balanced-match": "^0.4.2", "bluebird": "^3.1.1", "db-migrate-shared": "^1.0.2", "dotenv": "^2.0.0", @@ -54,6 +55,7 @@ "optimist": "~0.6.1", "parse-database-url": "~0.3.0", "pkginfo": "^0.4.0", + "prompt": "^1.0.0", "resolve": "^1.1.6", "semver": "^5.3.0", "tunnel-ssh": "^4.0.0" From cd23b42359272624b3e122c9750f6769d594bf9b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 28 Sep 2016 16:08:53 +0200 Subject: [PATCH 312/412] feat(transitioner): add transitioner to easen the process of protocol changes Resolves #403 --- lib/transitions/1.js | 34 +++++++++++++ lib/transitions/transitioner.js | 86 ++++++++++++++++++--------------- lib/transitions/try-require.js | 53 ++++++++++++++++---- 3 files changed, 124 insertions(+), 49 deletions(-) diff --git a/lib/transitions/1.js b/lib/transitions/1.js index e69de29b..7006e83f 100644 --- a/lib/transitions/1.js +++ b/lib/transitions/1.js @@ -0,0 +1,34 @@ + +/** + * Our first transition is actually the removal of globals and + * introducing the setup routine. + * Thus the body of this transition is just an empty function, but displays + * as all transitions an explanation to the user. + */ +module.exports = { + + transition: function() { + + }, + + message: function() { + + console.log('Congratulations!\n\n' + + 'You just migrated from protocol 0 to 1!\n' + + 'What does that mean for you?\n' + + 'Quite simple, from 0 to 1 we introduced the setup function and we' + + 'deprecated some globals, like async or dbm. What this transition does is' + + ' grabbing your migrations, replacing the async and dbm definitions and ' + + 'inserting the setup body if not present.\n' + + 'It might be possible, that you still run into errors, for example if ' + + 'you already have had a setup body, it wont be replaced and you might ' + + 'be missing the default routine of the setup, which provides for example ' + + 'the dataTypes to your migration.\n\n' + + 'What do I need to do now?\n' + + 'Try to rexecute all of your migrations and watch if you run into any ' + + 'Errors, if you encounter any, you need to manually fix those ' + + 'problems. But don\'t worry, this protocol transitions happen very ' + + 'rarely!\n' + ); + } +}; diff --git a/lib/transitions/transitioner.js b/lib/transitions/transitioner.js index 77417b6b..2433457f 100644 --- a/lib/transitions/transitioner.js +++ b/lib/transitions/transitioner.js @@ -4,58 +4,66 @@ var updateVersion = require('./update-version.js'); var ask = require('./ask.js'); var log = require('db-migrate-shared').log; -var internals = { - migrationProtcol: 1, - cwd: process.cwd() -}; +module.exports = function(internals) { + + ask( + { + properties: { + safe: { + description: 'This process is going to alter your migrations. We ' + + 'highly recommend you to backup your migrations or even better safe ' + + 'the current state with git versioning.\nPlease make sure you don\'t ' + + 'blow up yourself.\n\nDo you want to continue? [y/n]', + message: 'Invalid answer! Do you want to continue? [y/n]', + type: 'string', + default: 'n', + conform: function(value) { -ask( - { - properties: { - safe: { - description: 'This process is going to alter your migrations. We ' + - 'highly recommend you to backup your migrations or even better safe ' + - 'the current state with git versioning.\nPlease make sure you don\'t ' + - 'blow up yourself.\n\nDo you want to continue? [y/n]', - message: 'Invalid answer! Do you want to continue? [y/n]', - type: 'string', - default: 'n', - conform: function(value) { - - return value === 'y' || value === 'n'; + return value === 'y' || value === 'n'; + } } } - } - }, function(err) { + }, function(err) { - if(err) - return; + if(err) + return; - Migration.loadFromFilesystem('migrations/', internals, + Migration.loadFromFilesystem('migrations/', internals, function(err, migrations) { - migrations.forEach(function(migration) { + var messages = []; + + migrations.forEach(function(migration) { - var required = tryRequire(migration, internals); - var version = (required._meta && required._meta.version) ? - required._meta.version - : 0; + var required = tryRequire(migration, internals); + var version = (required._meta && required._meta.version) ? + required._meta.version + : 0; - if(version !== internals.migrationProtcol) { + if(version !== internals.migrationProtocol) { - var i; + var i; - for(i = 0; i < internals.migrationProtocol; ++i) { + for(i = 0; i < internals.migrationProtocol; ++i) { - var transition = require('./' + i + 1); - updateVersion(required, migration, internals, i + 1); + var transition = require('./' + (i + 1)); + transition.transition(); + messages[i + 1] = transition.message; + + updateVersion(required, migration, internals, i + 1); + log.info('Transitioned ' + migration.name + '.'); + } } - } - else { + else { - log.info(migration.name, 'was already transitioned to version ' + - internals.migrationProtcol + '.'); - } + log.verbose(migration.name, 'was already transitioned to version ' + + internals.migrationProtocol + '.'); + } + }); + + messages.forEach(function(message) { + message(); + }); }); }); -}); +}; diff --git a/lib/transitions/try-require.js b/lib/transitions/try-require.js index fd174be8..f4fd309b 100644 --- a/lib/transitions/try-require.js +++ b/lib/transitions/try-require.js @@ -1,12 +1,33 @@ var log = require('db-migrate-shared').log; var fs = require('fs'); +var cp = require('child_process'); var handled = false; +var installed = false; var removedGlobals = { 'dbm is not defined': globalHandler, - 'async is not defined': globalHandler + 'async is not defined': globalHandler, + 'Cannot find module \'async\'': installAsync }; +function installAsync(migration, retry) { + + var cmd = [ 'install', '--save', 'async' ]; + + if(installed) + retry(); + else + installed = true; + + log.info('Installing async...'); + cp.spawnSync('npm', cmd, { + cwd: migration.internals.cwd, + stdio: 'inherit' + }); + + return retry(); +} + function globalHandler(migration, retry) { var data = fs.readFileSync(migration, 'utf8'); @@ -14,10 +35,15 @@ function globalHandler(migration, retry) { /^dbm = dbm \|\| require\(\s+'db-migrate'\s+\)/m, 'var dbm' ); - data = data.replace( - /^async = async \|\| require\(\s+'async'\s+\)/m, - 'var async = require( \'async\' )' - ); + + if(data.indexOf('async = async || require') !== -1) { + + handled = true; + data = data.replace( + /^async = async \|\| require\(\s+'async'\s+\)/m, + 'var async = require( \'async\' )' + ); + } data = data.replace( /^var type = dbm.dataType/m, 'var type' @@ -38,20 +64,20 @@ function tryRequire(migration) { try { - if(handled) { + if(handled && !installed) { - //require(migration.internals.cwd + 'package.json') - //cp npm install --save async + return installAsync( + migration, + tryRequire.bind(this, migration) + ); } return require(migration.internals.cwd + '/' + migration.path); } catch(ex) { if(ex instanceof ReferenceError) { - if(removedGlobals[ex.message]) { - handled = true; log.info(ex.message, 'Initiating removal of old globals...'); return removedGlobals[ex.message]( migration.path, @@ -70,6 +96,13 @@ function tryRequire(migration) { 'fix the issues and rerun the transitioner again.'); } } + else if(removedGlobals[ex.message]) { + + return removedGlobals[ex.message]( + migration, + tryRequire.bind(this, migration) + ); + } else { log.error(ex.stack, migration); From a924436c79c534422b8d14e77d9a4d08c5be38cf Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 28 Sep 2016 16:13:37 +0200 Subject: [PATCH 313/412] feat(hook): parser hook and transitioner api Added a hook for parsers and added the API endpoints for the transitioner. Refers to #403 Refers to #397 --- api.js | 110 ++++++++++++++++++++++++++++++----------------- lib/migration.js | 49 +++++++++++++++------ lib/seed.js | 17 +------- 3 files changed, 108 insertions(+), 68 deletions(-) diff --git a/api.js b/api.js index 910f7f7c..b270b7a6 100644 --- a/api.js +++ b/api.js @@ -62,7 +62,8 @@ function dbmigrate(plugins, isModule, options, callback) { this.internals = { - onComplete: onComplete + onComplete: onComplete, + migrationProtocol: 1 }; var internals = this.internals; @@ -295,6 +296,14 @@ dbmigrate.prototype = { return log.silence(isSilent); }, + /** + * Transition migrations to the latest defined protocol. + */ + transition: function() { + + transition(this.internals); + }, + /** * Creates a correctly formatted migration */ @@ -474,7 +483,7 @@ function setDefaultArgv(internals, isModule) { 'ignore-completed-migrations': false }) .usage( - 'Usage: db-migrate [up|down|reset|create|db|seed] [[dbname/]migrationName|all] [options]' + 'Usage: db-migrate [up|down|reset|create|db|seed|transition] [[dbname/]migrationName|all] [options]' ) .describe('env', @@ -780,61 +789,75 @@ function _assert(err, callback) { return true; } +function migrationHook(internals) { + + var Migration = require('./lib/migration.js'); + return Migration.registerHook(internals.plugins, internals); +} + function executeUp(internals, config, callback) { - var Migrator = require('./lib/migrator.js'); - var index = require('./connect'); + migrationHook(internals) + .then(function() { - if (!internals.argv.count) { - internals.argv.count = Number.MAX_VALUE; - } - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Migrator, function(err, migrator) { - assert.ifError(err); + var Migrator = require('./lib/migrator.js'); + var index = require('./connect'); + + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, Migrator, function(err, migrator) { + assert.ifError(err); - if (internals.locTitle) + if (internals.locTitle) migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], - internals.locTitle); - else + internals.locTitle); + else migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); - internals.migrationsDir = migrator.migrationsDir; + internals.migrationsDir = migrator.migrationsDir; - migrator.driver.createMigrationsTable(function(err) { - assert.ifError(err); - log.verbose('migration table created'); + migrator.driver.createMigrationsTable(function(err) { + assert.ifError(err); + 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)); + }); + }); }); } function executeDown(internals, config, callback) { - var Migrator = require('./lib/migrator.js'); - var index = require('./connect'); - - if (!internals.argv.count) { - log.info('Defaulting to running 1 down migration.'); - internals.argv.count = 1; - } + migrationHook(internals) + .then(function() { - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Migrator, function(err, migrator) { - assert.ifError(err); + var Migrator = require('./lib/migrator.js'); + var index = require('./connect'); - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); + if (!internals.argv.count) { + log.info('Defaulting to running 1 down migration.'); + internals.argv.count = 1; + } - migrator.driver.createMigrationsTable(function(err) { + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, Migrator, function(err, migrator) { assert.ifError(err); - migrator.down(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); - }); + + migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); + + migrator.driver.createMigrationsTable(function(err) { + assert.ifError(err); + migrator.down(internals.argv, internals.onComplete.bind(this, + migrator, internals, callback)); + }); + }); }); } @@ -994,6 +1017,11 @@ function onComplete(migrator, internals, callback, originalErr) { }); } +function transition(internals) { + + require('./lib/transitions/transitioner.js')(internals); +} + function run(internals, config) { var action = internals.argv._.shift(), folder = action.split(':'); @@ -1001,6 +1029,10 @@ function run(internals, config) { action = folder[0]; switch (action) { + case 'transition': + + transition(internals); + break; case 'create': if (folder[1]) { diff --git a/lib/migration.js b/lib/migration.js index 021f9d32..10901d74 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -2,17 +2,9 @@ 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 coffeeSupported = false; -var coffeeModule = null; -try { - coffeeModule = require('coffee-script'); - if (coffeeModule && coffeeModule.register) coffeeModule.register(); - coffeeSupported = true; - filesRegEx = /\.(js|coffee)$/; -} catch (e) {} - var internals = {}; function writeMigrationRecord(db, migration, callback) { @@ -42,6 +34,38 @@ var Migration = Skeleton.extend({ } }); +Migration.registerHook = function(plugin, internals) { + + var plugin = plugin.hook('migrator:migration:hook:require'); + internals.parser = internals.parse || { + 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) { + + 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\';', @@ -302,11 +326,8 @@ Migration.loadFromFilesystem = function(dir, internals, callback) { } var coffeeWarn = true; files = files.filter(function(file) { - if (coffeeWarn && !coffeeSupported && /\.coffee$/.test(file)) { - log.warn('CoffeeScript not installed'); - coffeeWarn = false; - } - return filesRegEx.test(file); + + return internals.parser.filesRegEx.test(file); }); var migrations = files.sort().map(function(file) { return new Migration(path.join(dir, file), internals); diff --git a/lib/seed.js b/lib/seed.js index f0a3fd96..86682eea 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -3,16 +3,6 @@ var path = require('path'); var log = require('db-migrate-shared').log; var Skeleton = require('./skeleton'); -var filesRegEx = /\.js$/; -var coffeeSupported = false; -var coffeeModule = null; -try { - coffeeModule = require('coffee-script'); - if (coffeeModule && coffeeModule.register) coffeeModule.register(); - coffeeSupported = true; - filesRegEx = /\.(js|coffee)$/; -} catch (e) {} - var Seed = Skeleton.extend({ init: function() { @@ -129,11 +119,8 @@ Seed.loadFromFilesystem = function(dir, internals, callback) { if (err) { callback(err); return; } var coffeeWarn = true; files = files.filter(function(file) { - if (coffeeWarn && !coffeeSupported && /\.coffee$/.test(file)) { - log.warn('CoffeeScript not installed'); - coffeeWarn = false; - } - return filesRegEx.test(file); + + return internals.parser.filesRegEx.test(file); }); var seeds = files.sort().map(function(file) { return new Seed(path.join(dir, file), internals); From c9c49d09fa5030f11bd3b551fc8265149ecdcce4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 28 Sep 2016 16:20:28 +0200 Subject: [PATCH 314/412] fix(config): Don't throw if environment variable is empty Fixes #411 --- lib/config.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/config.js b/lib/config.js index bec1a7bd..2c9124fc 100644 --- a/lib/config.js +++ b/lib/config.js @@ -88,7 +88,10 @@ exports.loadObject = function(config, currentEnv) { for (var env in config) { if (config[env].ENV) { - out[env] = parseDatabaseUrl(process.env[config[env].ENV]); + if(!process.env[config[env].ENV]) + log.verbose('Environment variable ' + config[env].ENV + 'is empty!'); + else + out[env] = parseDatabaseUrl(process.env[config[env].ENV]); } else if (typeof(config[env]) === 'string') { out[env] = parseDatabaseUrl(config[env]); } else { @@ -96,6 +99,13 @@ exports.loadObject = function(config, currentEnv) { //which will tell us to grab configuration from the environment for (var configEntry in config[env]) { if (config[env][configEntry] && config[env][configEntry].ENV){ + + if(!process.env[config[env][configEntry].ENV]) { + + log.verbose('Environment variable ' + config[env][configEntry].ENV + + 'is empty!'); + } + config[env][configEntry] = process.env[config[env][configEntry].ENV]; } } From 72942cbdc7839c5d3e1543bb82ea67b7432a53f2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 28 Sep 2016 16:34:04 +0200 Subject: [PATCH 315/412] chore(hook): allow also to hook without adding any extension --- lib/migration.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 10901d74..bb59bdab 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -37,7 +37,7 @@ var Migration = Skeleton.extend({ Migration.registerHook = function(plugin, internals) { var plugin = plugin.hook('migrator:migration:hook:require'); - internals.parser = internals.parse || { + internals.parser = internals.parser || { filesRegEx: filesRegEx, extensions: 'js' }; @@ -52,8 +52,9 @@ Migration.registerHook = function(plugin, internals) { }) .each(function(parser) { - internals.parser.extensions = internals.parser.extensions + '|' + - parser.extensions; + if(parser && parser.extensions) + internals.parser.extensions = internals.parser.extensions + '|' + + parser.extensions; }) .then(function() { internals.parser.filesRegEx = new RegExp( From a26b6fd545480dac70c40b4b1d7d7ff36590d89a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 28 Sep 2016 17:28:43 +0200 Subject: [PATCH 316/412] fix(transitioner): add new parser internal to transitioner --- lib/transitions/transitioner.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/transitions/transitioner.js b/lib/transitions/transitioner.js index 2433457f..afd6c308 100644 --- a/lib/transitions/transitioner.js +++ b/lib/transitions/transitioner.js @@ -28,6 +28,10 @@ module.exports = function(internals) { if(err) return; + internals.parser = { + filesRegEx: /\.js$/ + }; + Migration.loadFromFilesystem('migrations/', internals, function(err, migrations) { From 18eb4a63b37223bbf4bb6b5a00a08d167d3ed813 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 28 Sep 2016 17:46:36 +0200 Subject: [PATCH 317/412] fix(transitioner): catch whitespaces properly --- lib/transitions/try-require.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/transitions/try-require.js b/lib/transitions/try-require.js index f4fd309b..a4bf4040 100644 --- a/lib/transitions/try-require.js +++ b/lib/transitions/try-require.js @@ -7,9 +7,15 @@ var installed = false; var removedGlobals = { 'dbm is not defined': globalHandler, 'async is not defined': globalHandler, + 'Cannot find module \'db-migrate\'': missingDBMigrate, 'Cannot find module \'async\'': installAsync }; +function missingDBMigrate(migration, retry) { + + return globalHandler(migration.path, retry); +} + function installAsync(migration, retry) { var cmd = [ 'install', '--save', 'async' ]; @@ -29,10 +35,14 @@ function installAsync(migration, retry) { } function globalHandler(migration, retry) { - var data = fs.readFileSync(migration, 'utf8'); data = data.replace( - /^dbm = dbm \|\| require\(\s+'db-migrate'\s+\)/m, + /^dbm = dbm \|\| require\((?!\s)?'db-migrate'(?!\s)?\)/m, + 'var dbm' + ); + + data = data.replace( + /^var dbm = global\.dbm \|\| require\((?!\s)?'db-migrate'(?!\s)?\)/m, 'var dbm' ); @@ -40,7 +50,7 @@ function globalHandler(migration, retry) { handled = true; data = data.replace( - /^async = async \|\| require\(\s+'async'\s+\)/m, + /^async = async \|\| require\((?!\s)?'async'(?!\s)?\)/m, 'var async = require( \'async\' )' ); } From 688b89f0bd5d3729b28abf05c1002a089e13efd9 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 28 Sep 2016 17:49:07 +0200 Subject: [PATCH 318/412] chore(templates): add meta protocol v1 to already aligned migration templates --- lib/migration.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/migration.js b/lib/migration.js index bb59bdab..443dccf6 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -115,6 +115,10 @@ Migration.prototype.defaultJsTemplate = function() { 'exports.down = function(db) {', ' return null;', '};', + '', + 'exports._meta = {', + ' "version": 1', + '};', '' ].join('\n'); }; @@ -177,6 +181,10 @@ Migration.prototype.sqlFileLoaderTemplate = function() { ' return db.runSql(data);', ' });', '};', + '', + 'exports._meta = {', + ' "version": 1', + '};', '' ].join('\n'); }; @@ -242,6 +250,10 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { ' return db.runSql(data);', ' });', '};', + '', + 'exports._meta = {', + ' "version": 1', + '};', '' ].join('\n'); }; From 1d2ee9e9f974596cbd26a4637d5e94450af6424c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 29 Sep 2016 13:36:51 +0200 Subject: [PATCH 319/412] feat(plugin): add basic plugin support Added basic plugin support, enabling to inject at multiple targets of the API, config and register pre compiler. Resolves #397 Refers #396 --- api.js | 76 ++++++++++++++++++++++++++++++++++++++++++++++---- bin/db-migrate | 6 +++- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/api.js b/api.js index b270b7a6..2075f13c 100644 --- a/api.js +++ b/api.js @@ -58,6 +58,18 @@ function registerPluginLoader(plugins) { }; } +var APIHooks = { + 'init:api:addfunction:hook': function(name, fn) { + + this[name] = fn; + return; + }, + 'init:api:accessapi:hook': function(cb) { + + return cb(this); + } +}; + function dbmigrate(plugins, isModule, options, callback) { this.internals = { @@ -153,6 +165,31 @@ dbmigrate.prototype = { return true; }, + registerAPIHook: function(callback) { + + var plugins = this.internals.plugins; + var self = this; + + return Promise.resolve(Object.keys(APIHooks)) + .each(function(hook) { + + var plugin = plugins.hook(hook); + if(!plugin) return; + + var APIHook = APIHooks[hook].bind(self); + + return Promise.resolve(plugin) + .map(function(plugin) { + + return plugin[hook](); + }) + .each(function(args) { + + return APIHook.apply(self, args); + }); + }).asCallback(callback); + }, + _internals: this.internals, /** @@ -556,9 +593,24 @@ function setDefaultArgv(internals, isModule) { .boolean('ignore-completed-migrations') .describe('log-level', 'Set the log-level, for example sql|warn') - .string('log-level') + .string('log-level'); + + + var plugins = internals.plugins; + var plugin = plugins.hook('init:cli:config:hook'); + if(plugin) { - .argv; + plugin.forEach(function(plugin) { + + var configs = plugin['init:cli:config:hook'](); + if(!configs) return; + + //hook not yet used, we look into migrating away from optimist first + return; + }); + } + + internals.argv = internals.argv.argv; if (internals.argv.version) { console.log(internals.dbm.version); @@ -592,7 +644,7 @@ function setDefaultArgv(internals, isModule) { } function createMigrationDir(dir, callback) { - fs.stat(dir, function(err, stat) { + fs.stat(dir, function(err) { if (err) { mkdirp(dir, callback); } else { @@ -1101,9 +1153,21 @@ function run(internals, config) { break; default: - log.error('Invalid Action: Must be [up|down|create|reset|seed|db].'); - optimist.showHelp(); - process.exit(1); + var plugins = internals.plugins; + var plugin = plugins.overwrite( + 'run:default:action:' + action + ':overwrite' + ); + if(plugin) { + + plugin['run:default:action:' + action + ':overwrite'] + (internals, config); + } + else { + + log.error('Invalid Action: Must be [up|down|create|reset|seed|db].'); + optimist.showHelp(); + process.exit(1); + } break; } } diff --git a/bin/db-migrate b/bin/db-migrate index f749c59d..53ef2bef 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -33,5 +33,9 @@ resolve( 'db-migrate', { } dbmigrate = DBMigrate.getInstance(); - dbmigrate.run(); + dbmigrate.registerAPIHook() + .then(function() { + + dbmigrate.run(); + }); } ); From f8039f33fa0d48a329eb74c4cecf59388dead775 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 29 Sep 2016 14:09:38 +0200 Subject: [PATCH 320/412] fix(plugin): use correct path to include plugins --- bin/db-migrate | 4 ++-- index.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/db-migrate b/bin/db-migrate index 53ef2bef..403cb68e 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -34,8 +34,8 @@ resolve( 'db-migrate', { dbmigrate = DBMigrate.getInstance(); dbmigrate.registerAPIHook() - .then(function() { + .then( function() { dbmigrate.run(); - }); + } ); } ); diff --git a/index.js b/index.js index 2e6d6fcd..897728ae 100644 --- a/index.js +++ b/index.js @@ -33,7 +33,8 @@ function loadPlugins() { for(; i < length; ++i) { - var plugin = require(plugins[i]); + var plugin = require(path.join(process.cwd(), 'node_modules', plugins[i])); + if(typeof(plugin.name) !== 'string' || !plugin.hooks || !plugin.loadPlugin) continue; From 376fdc3183bcc3f81364e7bfd282d782ff6d597a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 29 Sep 2016 22:07:12 +0200 Subject: [PATCH 321/412] fix(errorhandling): Add missing error assertion in executeDB fixes #381 --- api.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api.js b/api.js index 2075f13c..1f213bf9 100644 --- a/api.js +++ b/api.js @@ -926,6 +926,8 @@ function executeDB(internals, config, callback) { } index.driver(config.getCurrent().settings, function(err, db) { + assert.ifError(err); + if (internals.mode === 'create') { db.createDatabase(internals.argv.dbname, { ifNotExists: true From fa1a1611880a877d9b57060d035af7f0e5d91443 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 30 Sep 2016 12:01:14 +0200 Subject: [PATCH 322/412] feat(sync): add sync mode Refers to #383 Resolves #313 Refers to #222 --- api.js | 103 ++++++++++++++++++++++++++++++++++++++++++++---- lib/migrator.js | 31 +++++++++++++-- package.json | 2 +- 3 files changed, 124 insertions(+), 12 deletions(-) diff --git a/api.js b/api.js index 1f213bf9..e66a1cdc 100644 --- a/api.js +++ b/api.js @@ -303,6 +303,36 @@ dbmigrate.prototype = { }.bind(this)).asCallback(callback); }, + /** + * Executes up a given number of migrations or a specific one. + * + * Defaults to up all migrations if no count is given. + */ + sync: function(specification, opts, callback) { + + if (arguments.length > 0) { + if (typeof(specification) === 'string') { + + this.internals.argv.destination = specification; + } + + if (typeof(opts) === 'string') { + + this.internals.migrationMode = opts; + this.internals.matching = opts; + } + else if (typeof(opts) === 'function') { + + callback = opts; + } + } + + return Promise.fromCallback(function(callback) { + + executeSync(this.internals, this.config, callback); + }.bind(this)).asCallback(callback); + }, + /** * Executes down for all currently migrated migrations. */ @@ -520,7 +550,8 @@ function setDefaultArgv(internals, isModule) { 'ignore-completed-migrations': false }) .usage( - 'Usage: db-migrate [up|down|reset|create|db|seed|transition] [[dbname/]migrationName|all] [options]' + 'Usage: db-migrate [up|down|reset|sync|create|db|seed|transition] ' + + '[[dbname/]migrationName|all] [options]' ) .describe('env', @@ -558,14 +589,16 @@ function setDefaultArgv(internals, isModule) { .string('config') .describe('sql-file', - 'Automatically create two sql files for up and down statements in /sqls and generate the javascript code that loads them.' + 'Automatically create two sql files for up and down statements in ' + + '/sqls and generate the javascript code that loads them.' ) .boolean('sql-file') .describe('coffee-file', 'Create a coffeescript migration file') .boolean('coffee-file') .describe('ignore-on-init', - 'Create files that will run only if ignore-on-init in the env is set to false (currently works onlt with SQL)' + 'Create files that will run only if ignore-on-init in the env is set ' + + 'to false (currently works onlt with SQL)' ).boolean('ignore-on-init') .describe('migration-table', @@ -883,6 +916,42 @@ function executeUp(internals, config, callback) { }); } +function executeSync(internals, config, callback) { + + migrationHook(internals) + .then(function() { + + var Migrator = require('./lib/migrator.js'); + var index = require('./connect'); + + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, Migrator, function(err, migrator) { + assert.ifError(err); + + if (internals.locTitle) + migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], + internals.locTitle); + else + migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); + + internals.migrationsDir = migrator.migrationsDir; + + migrator.driver.createMigrationsTable(function(err) { + assert.ifError(err); + log.verbose('migration table created'); + + migrator.sync(internals.argv, internals.onComplete.bind(this, + migrator, internals, callback)); + }); + }); + }); +} + function executeDown(internals, config, callback) { migrationHook(internals) @@ -1095,6 +1164,24 @@ function run(internals, config) { } executeCreateMigration(internals, config); break; + case 'sync': + + if (internals.argv._.length === 0) { + + log.error('Missing sync destination!'); + process.exit(1); + } + + internals.argv.count = Number.MAX_VALUE; + internals.argv.destination = internals.argv._.shift().toString(); + + if (folder[1]) { + internals.matching = folder[1]; + internals.migrationMode = folder[1]; + } + + executeSync(internals, config); + break; case 'up': case 'down': case 'reset': @@ -1104,10 +1191,9 @@ function run(internals, config) { if (internals.argv._.length > 0) { if (action === 'down') { - log.info( - 'Ignoring migration name for down migrations. Use --count to control how many down migrations are run.' - ); - internals.argv.destination = null; + + internals.argv.count = internals.argv.count || Number.MAX_VALUE; + internals.argv.destination = internals.argv._.shift().toString(); } else { internals.argv.destination = internals.argv._.shift().toString(); } @@ -1166,7 +1252,8 @@ function run(internals, config) { } else { - log.error('Invalid Action: Must be [up|down|create|reset|seed|db].'); + log.error('Invalid Action: Must be [up|down|create|reset|sync|seed|' + + 'db|transition].'); optimist.showHelp(); process.exit(1); } diff --git a/lib/migrator.js b/lib/migrator.js index a8ffbd71..a3ceb829 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -119,10 +119,35 @@ Migrator.prototype = { if (dbmUtil.isFunction(funcOrOpts)) { return funcOrOpts(this.driver, callback); } else { - this.downToBy(funcOrOpts.count, callback); + this.downToBy(funcOrOpts.destination, funcOrOpts.count, callback); } }, + 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) { @@ -173,12 +198,12 @@ Migrator.prototype = { }); }, - downToBy: function(count, 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, count); + var toRun = dbmUtil.filterDown(completedMigrations, partialName, count); if (toRun.length === 0) { log.info('No migrations to run'); diff --git a/package.json b/package.json index 9738393a..c3767be1 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "dependencies": { "balanced-match": "^0.4.2", "bluebird": "^3.1.1", - "db-migrate-shared": "^1.0.2", + "db-migrate-shared": "^1.1.2", "dotenv": "^2.0.0", "final-fs": "^1.6.0", "inflection": "^1.10.0", From 26cf00d2471ce3507d64029d5d1b16c4ddd9b9f3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 30 Sep 2016 18:36:19 +0200 Subject: [PATCH 323/412] refactor(tests): remove tests from main repo Tests have been moved to their driver repo. Resolves #399 --- new/config_test.js | 177 ---- new/database.json | 16 - new/database_with_default_env.json | 7 - new/database_with_default_env_from_env.json | 7 - new/database_with_env.json | 7 - new/database_with_env_url.json | 3 - new/database_with_null_values.json | 16 - new/database_with_syntax_error.json | 1 - new/db.config.example.json | 20 - new/db.config.json | 22 - new/driver/base_test.js | 96 -- new/driver/index_test.js | 140 --- new/integration/api_test.js | 110 --- new/integration/create_test.js | 340 ------- new/integration/database.json | 6 - .../database_with_coffee_file.json | 7 - new/integration/database_with_sql_file.json | 7 - new/migration_test.js | 252 ----- new/util_test.js | 57 -- test/config_test.js | 315 ++++--- test/db.config.ci | 21 - test/driver/base_test.js | 100 +- test/driver/index_test.js | 149 +-- test/driver/mongodb_test.js | 344 ------- test/driver/mysql_test.js | 880 ------------------ test/driver/pg_schema_test.js | 162 ---- test/driver/pg_test.js | 722 -------------- {new => test}/driver/shadow_test.js | 0 test/driver/sqlite3_test.js | 455 --------- test/integration/api_test.js | 161 ++-- test/integration/create_test.js | 376 +++++--- test/migration_test.js | 362 ++++--- test/util_test.js | 85 +- 33 files changed, 944 insertions(+), 4479 deletions(-) delete mode 100644 new/config_test.js delete mode 100644 new/database.json delete mode 100644 new/database_with_default_env.json delete mode 100644 new/database_with_default_env_from_env.json delete mode 100644 new/database_with_env.json delete mode 100644 new/database_with_env_url.json delete mode 100644 new/database_with_null_values.json delete mode 100644 new/database_with_syntax_error.json delete mode 100644 new/db.config.example.json delete mode 100644 new/db.config.json delete mode 100644 new/driver/base_test.js delete mode 100644 new/driver/index_test.js delete mode 100644 new/integration/api_test.js delete mode 100644 new/integration/create_test.js delete mode 100644 new/integration/database.json delete mode 100644 new/integration/database_with_coffee_file.json delete mode 100644 new/integration/database_with_sql_file.json delete mode 100644 new/migration_test.js delete mode 100644 new/util_test.js delete mode 100644 test/db.config.ci delete mode 100644 test/driver/mongodb_test.js delete mode 100644 test/driver/mysql_test.js delete mode 100644 test/driver/pg_schema_test.js delete mode 100644 test/driver/pg_test.js rename {new => test}/driver/shadow_test.js (100%) delete mode 100644 test/driver/sqlite3_test.js diff --git a/new/config_test.js b/new/config_test.js deleted file mode 100644 index a73638dd..00000000 --- a/new/config_test.js +++ /dev/null @@ -1,177 +0,0 @@ -var Code = require('code'); -var Lab = require('lab'); -var lab = exports.lab = Lab.script(); -var config = require('../lib/config'); -var path = require('path'); - -var _configLoad = config.load; -var _configLoadUrl = config.loadUrl; - -lab.experiment('config', function() { - - lab.experiment('loading from a file', { parallel: true }, - function() { - - var configPath = path.join(__dirname, 'database.json'); - var _config = config.load(configPath, 'dev'); - - lab.test('should export all environment settings', { parallel: true }, - function (done) { - - Code.expect(_config.dev).to.exists(); - Code.expect(_config.test).to.exists(); - Code.expect(_config.prod).to.exists(); - done(); - }); - - lab.test('should export a getCurrent function with all current ' + - 'environment settings', { parallel: true }, function (done) { - - var current; - Code.expect(_config.getCurrent).to.exists(); - current = _config.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.driver).to.equal('sqlite3'); - Code.expect(current.settings.filename).to.equal(':memory:'); - done(); - }); - }); - - lab.experiment('loading from a broken config file', { parallel: true }, - function() { - - var configPath = path.join(__dirname, 'database_with_syntax_error.json'); - - lab.test('should throw a syntax error', { parallel: true }, - function (done) { - - Code.expect( - config.load.bind(this, configPath, 'dev'), - 'Expected broken file to produce syntax error' - ).to.throw(SyntaxError); - done(); - }); - }); - - lab.experiment('loading from a file with default env option', - { parallel: true }, function() { - - var configPath = path.join(__dirname, 'database_with_default_env.json'); - var _config = config.load(configPath); - - lab.test('should load a value from the default env', { parallel: true }, - function (done) { - - var current = _config.getCurrent(); - Code.expect(current.env).to.equal('local'); - Code.expect(current.settings.driver).to.equal('sqlite3'); - Code.expect(current.settings.filename).to.equal(':memory:'); - done(); - }); - }); - - lab.experiment('loading from a file with default env option in ENV variable', - { parallel: true }, function() { - - process.env.NODE_ENV = 'local'; - var configPath = path.join( - __dirname, - 'database_with_default_env_from_env.json' - ); - var _config = config.load(configPath); - - lab.test('should load a value from the env set in NODE_ENV', - { parallel: true }, function (done) { - - var current = _config.getCurrent(); - Code.expect(current.settings.driver).to.equal('sqlite3'); - Code.expect(current.settings.filename).to.equal(':memory:'); - done(); - }); - }); - - lab.experiment('loading from a file with ENV vars', { parallel: true }, - function() { - - process.env.DB_MIGRATE_TEST_VAR = 'username_from_env'; - var configPath = path.join(__dirname, 'database_with_env.json'); - var _config = config.load(configPath, 'prod'); - - lab.test('should load a value from the environments', { parallel: true }, - function (done) { - - Code.expect(_config.prod.username).to.equal('username_from_env'); - done(); - }); - }); - - lab.experiment('loading from a file with ENV URL', { parallel: true }, - function() { - - process.env.DB_MIGRATE_TEST_VAR = 'postgres://uname:pw@server.com/dbname'; - var configPath = path.join(__dirname, 'database_with_env_url.json'); - var _config = config.load(configPath, 'prod'); - - lab.test('should load a value from the environments', { parallel: true }, - function (done) { - - var current = _config.getCurrent(); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host, ').to.equal(rver.com'); - Code.expect(current.settings.database).to.equal('dbname'); - done(); - }); - }); - - lab.experiment('loading from an URL', { parallel: true }, - function() { - - var databaseUrl = 'postgres://uname:pw@server.com/dbname'; - var _config = config.loadUrl(databaseUrl, 'dev'); - - lab.test('should export the settings as the current environment', - { parallel: true }, function (done) { - - Code.expect(_config.dev).to.exists(); - done(); - }); - - lab.test('should export a getCurrent function with all current ' + - 'environment settings', { parallel: true }, function (done) { - - var current; - Code.expect(_config.getCurrent).to.exists(); - current = _config.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host).to.equal('server.com'); - Code.expect(current.settings.database).to.equal('dbname'); - done(); - }); - }); - - lab.experiment('loading a config with null values', function() { - - var configPath = path.join(__dirname, 'database_with_null_values.json'); - config.load = _configLoad; - config.loadUrl = _configLoadUrl; - - lab.test('should something', function(done, cleanup) { - - cleanup(function(next) { - - delete require.cache[require.resolve('../lib/config')]; - next(); - }); - - Code.expect( - config.load.bind(this, configPath, 'dev') - ).to.not.throw; - done(); - }); - }); -}); diff --git a/new/database.json b/new/database.json deleted file mode 100644 index 7bea8191..00000000 --- a/new/database.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "dev": { - "driver": "sqlite3", - "filename": ":memory:" - }, - - "test": { - "driver": "sqlite3", - "filename": ":memory:" - }, - - "prod": { - "driver": "sqlite3", - "filename": "prod.db" - } -} diff --git a/new/database_with_default_env.json b/new/database_with_default_env.json deleted file mode 100644 index 1c03578e..00000000 --- a/new/database_with_default_env.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "defaultEnv": "local", - "local": { - "driver": "sqlite3", - "filename": ":memory:" - } -} diff --git a/new/database_with_default_env_from_env.json b/new/database_with_default_env_from_env.json deleted file mode 100644 index 12100ca0..00000000 --- a/new/database_with_default_env_from_env.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "defaultEnv": {"ENV": "NODE_ENV"}, - "local": { - "driver": "sqlite3", - "filename": ":memory:" - } -} diff --git a/new/database_with_env.json b/new/database_with_env.json deleted file mode 100644 index 6f2d5fc7..00000000 --- a/new/database_with_env.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "prod": { - "driver": "sqlite3", - "filename": "prod.db", - "username": {"ENV": "DB_MIGRATE_TEST_VAR"} - } -} diff --git a/new/database_with_env_url.json b/new/database_with_env_url.json deleted file mode 100644 index cf993432..00000000 --- a/new/database_with_env_url.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "prod": {"ENV": "DB_MIGRATE_TEST_VAR"} -} diff --git a/new/database_with_null_values.json b/new/database_with_null_values.json deleted file mode 100644 index d936f22b..00000000 --- a/new/database_with_null_values.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "dev": { - "driver": null, - "filename": ":memory:" - }, - - "test": { - "driver": null, - "filename": ":memory:" - }, - - "prod": { - "driver": null, - "filename": "prod.db" - } -} diff --git a/new/database_with_syntax_error.json b/new/database_with_syntax_error.json deleted file mode 100644 index a5778498..00000000 --- a/new/database_with_syntax_error.json +++ /dev/null @@ -1 +0,0 @@ -{this:'is' not:'valid' json} \ No newline at end of file diff --git a/new/db.config.example.json b/new/db.config.example.json deleted file mode 100644 index 10d6a915..00000000 --- a/new/db.config.example.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "mysql": { - "database": "db_migrate_test", - "user": "root", - "driver": "mysql" - }, - "pg": { - "driver": "pg", - "database": "db_migrate_test" - }, - "sqlite3": { - "driver": "sqlite3", - "filename": "test.db" - }, - "mongodb": { - "driver": "mongodb", - "host": "localhost", - "database": "db_migrate_test" - } -} diff --git a/new/db.config.json b/new/db.config.json deleted file mode 100644 index b3a41b94..00000000 --- a/new/db.config.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "mysql": { - "database": "db_migrate_test", - "user": "root", - "password": "12345678", - "driver": "mysql" - }, - "pg": { - "driver": "pg", - "database": "db_migrate_test", - "username": "postgres" - }, - "sqlite3": { - "driver": "sqlite3", - "filename": "test.db" - }, - "mongodb": { - "driver": "mongodb", - "host": "localhost", - "database": "db_migrate_test" - } -} diff --git a/new/driver/base_test.js b/new/driver/base_test.js deleted file mode 100644 index 8fa25779..00000000 --- a/new/driver/base_test.js +++ /dev/null @@ -1,96 +0,0 @@ -var Code = require('code'); -var Lab = require('lab'); -var lab = exports.lab = Lab.script(); -var Base = require('db-migrate-base'); - -var internals = { - migrationTable: 'migrations', - mod: { - log: require('db-migrate-shared').log, - type: require('db-migrate-shared').dataType - } -}; - -lab.experiment('base', { parallel: true }, function() { - - lab.experiment('default implementation', { parallel: true }, function() { - - var base = new Base(internals); - - lab.test('inherits from EventEmitter', { parallel: true }, function(done) { - - Code.expect(base.on).to.be.not.null(); - Code.expect(base.emit).to.be.not.null(); - done(); - }); - - lab.test('throws errors for all API methods', { parallel: true }, - function(done) { - - Code.expect(function() { - base.createTable(); - }).to.throw(Error); - - Code.expect(function() { - base.dropTable(); - }).to.throw(Error); - - Code.expect(function() { - base.addColumn(); - }).to.throw(Error); - - Code.expect(function() { - base.removeColumn(); - }).to.throw(Error); - - Code.expect(function() { - base.renameColumn(); - }).to.throw(Error); - - Code.expect(function() { - base.changeColumn(); - }).to.throw(Error); - - Code.expect(function() { - base.addIndex(); - }).to.throw(Error); - - Code.expect(function() { - base.insert(); - }).to.throw(Error); - - Code.expect(function() { - base.removeIndex(); - }).to.throw(Error); - - Code.expect(function() { - base.addAssociation(); - }).to.throw(Error); - - Code.expect(function() { - base.removeAssociation(); - }).to.throw(Error); - - Code.expect(function() { - base.addForeignKey(); - }).to.throw(Error); - - Code.expect(function() { - base.removeForeignKey(); - }).to.throw(Error); - - Code.expect(function() { - base.runSql(); - }).to.throw(Error); - - done(); - }); - - lab.test('escapes single quotes', { parallel: true }, function(done) { - - Code.expect('Bill\'\'s Mother\'\'s House') - .to.equal(base.escape('Bill\'s Mother\'s House')); - done(); - }); - }); -}); diff --git a/new/driver/index_test.js b/new/driver/index_test.js deleted file mode 100644 index 530ab6ad..00000000 --- a/new/driver/index_test.js +++ /dev/null @@ -1,140 +0,0 @@ -var proxyquire = require('proxyquire'); -var sinon = require('sinon'); -var Code = require('code'); -var Lab = require('lab'); -var lab = exports.lab = Lab.script(); -var validDbConfigWithTunnel = { - driver: 'mysql', - host: 'dbHost', - port: 'dbPort', - tunnel: { - localPort: 'localPort', - host: 'sshHost', - port: 'sshPort' - } -}; - -var internals = { - migrationTable: 'migrations' -}; - -var indexConnectCallback = function(tunnelStub, driverSpy, callback) { - return function(err, db) { - if (err) { - callback(err, db, tunnelStub, driverSpy); - return; - } - - callback(err, db, tunnelStub, driverSpy); - }; -}; - -lab.experiment('index', function() { - - lab.test('a successful connection with ssh tunnel with expected parameters', - function(done, cleanup) { - - // Ensure that require gets a new copy of the module for each test - delete require.cache[require.resolve('db-migrate-mysql')]; - var driver = require('db-migrate-mysql'); - - // Set up stubs/spies to verify correct flow - var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); - var tunnelStub = sinon.stub().callsArg(1); - var index = proxyquire('../../lib/driver/index', { - 'tunnel-ssh': tunnelStub, - './mysql': driver - }); - //register clean up - cleanup(function(next) { - - driverSpy.restore(); - delete require.cache[require.resolve('tunnel-ssh')]; - delete require.cache[require.resolve('db-migrate-mysql')]; - next(); - }); - - index.connect( - validDbConfigWithTunnel, - {}, - indexConnectCallback(tunnelStub, driverSpy, validate) - ); - - function validate(err, db, tunnelStub, driverSpy) { - var expectedTunnelConfig = { - localPort: 'localPort', - host: 'sshHost', - port: 'sshPort', - dstHost: 'dbHost', - dstPort: 'dbPort' - }; - var expectedDbConfig = { - driver: 'mysql', - host: '127.0.0.1', - port: 'localPort', - tunnel: { - localPort: 'localPort', - host: 'sshHost', - port: 'sshPort' - } - }; - - - Code.expect(err).to.be.null(); - Code.expect(db).to.not.be.null(); - Code.expect( - tunnelStub.withArgs(expectedTunnelConfig).calledOnce - ).to.be.true(); - Code.expect( - driverSpy.withArgs(expectedDbConfig).calledOnce - ).to.be.true(); - - done(); - } - }); - - lab.test('a failed connection with ssh tunnel', function(done, cleanup) { - - // Ensure that require gets a new copy of the module for each test - delete require.cache[require.resolve('db-migrate-mysql')]; - var driver = require('db-migrate-mysql'); - - // Set up stubs/spies to verify correct flow - var tunnelStub = sinon.stub().callsArgWith(1, new Error('error')); - var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); - var index = proxyquire('../../lib/driver/index', { - 'tunnel-ssh': tunnelStub, - './mysql': driver - }); - - index.connect( - validDbConfigWithTunnel, - {}, - indexConnectCallback(tunnelStub, driverSpy, validate) - ); - - //register clean up - cleanup(function(next) { - - driverSpy.restore(); - delete require.cache[require.resolve('tunnel-ssh')]; - delete require.cache[require.resolve('db-migrate-mysql')]; - next(); - }); - - function validate(err, db, tunnelStub, driverSpy) { - - Code.expect(err, 'err should be non-null') - .to.exists(); - Code.expect(db, 'driver should be null or undefined') - .to.not.exists(); - - Code.expect(tunnelStub.calledOnce, 'tunnel should be called once') - .to.be.true(); - Code.expect(driverSpy.notCalled, 'driver.connect should not be called') - .to.be.true(); - - done(); - } - }); -}); diff --git a/new/integration/api_test.js b/new/integration/api_test.js deleted file mode 100644 index bb7f6caa..00000000 --- a/new/integration/api_test.js +++ /dev/null @@ -1,110 +0,0 @@ -var Code = require('code'); -var Lab = require('lab'); -var lab = exports.lab = Lab.script(); -var DBMigrate = require('../../'); -var path = require('path'); -var cp = require('child_process'); - -lab.experiment('api', function() { - - lab.test('force process exit after migrations have been run', - { parallel : true}, function(done, onCleanup) { - - var process_exit = process.exit, - argv = process.argv, - called = false, - config = { cwd: __dirname }; - - // register cleanup method and start preparing the test - onCleanup(teardown); - createMigration(function() { - - var dbmigrate = DBMigrate.getInstance(true, config); - - dbmigrate.setConfigParam('force-exit', true); - dbmigrate.silence(true); - - /** - * We have set force-exit above, this should end up in db-migrate - * executing process.exit on the final callback. - * Process.exit has been overwritten and will finally call validate. - * - * The test validation takes place in validate() - */ - dbmigrate.up(); - }); - - /** - * Final validation after process.exit should have been called. - */ - function validate() { - - Code.expect(called).to.be.true(); - done(); - } - - /** - * Create a migration with the programatic API and overwrite process.exit. - */ - function createMigration(callback) { - - var api = DBMigrate.getInstance(true, config); - api.silence(true); - - api.create( 'test', function() { - process.exit = function(err) { - - var ret = called; - called = true; - - process.exit = process_exit; - - if(err) - process.exit.apply(arguments); - - Code.expect(ret).to.be.false(); - validate(); - }; - - callback(); - } ); - } - - function teardown(next) { - - process.exit = process_exit; - process.argv = argv; - cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); - return next(); - } - }); - - lab.test('should load config from parameter', { parallel : true}, - function(done) { - - var options = { - env: 'dev', - cwd: process.cwd() + '/test/integration', - config: { - dev: { - driver: 'sqlite3', - filename: ':memory:' - }, - pg: { - driver: 'pg', - database: 'db_api_test' - } - } - }; - - var api = DBMigrate.getInstance(true, options); - var actual = api.config; - var expected = options.config; - - delete expected.getCurrent; - delete actual.getCurrent; - - Code.expect(actual).to.equal(expected); - done(); - }); -}); diff --git a/new/integration/create_test.js b/new/integration/create_test.js deleted file mode 100644 index c8fbed87..00000000 --- a/new/integration/create_test.js +++ /dev/null @@ -1,340 +0,0 @@ -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; - -var rmdir = require('rimraf'); - - -function wipeMigrations(callback) { - var dir = path.join(__dirname, 'migrations'); - rmdir(dir, callback); -} - -function dbMigrate() { - var args = dbmUtil.toArray(arguments); - var 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; - - lab.before(function(done) { - wipeMigrations(function(err) { - - Code.expect(err).to.be.null(); - dbMigrate('create', 'first migration').on('exit', - function(code) { - - exitCode = code; - done(); - }); - }); - }); - - lab.test('does not cause an error', { parallel: true }, - function(done) { - - Code.expect(exitCode).to.equal(0); - done(); - }); - - lab.test('will create a new migration directory', { parallel: true }, - function(done) { - - var stats = fs.statSync(path.join(__dirname, 'migrations')); - Code.expect(stats.isDirectory()).to.be.true(); - done(); - }); - - lab.test('will create a new migration', { parallel: true }, - function(done) { - - var files = fs.readdirSync(path.join(__dirname, 'migrations')); - Code.expect(files.length).to.equal(1); - var file = files[0]; - Code.expect(file).to.match(/first-migration\.js$/); - done(); - }); - }); - - lab.experiment('with sql-file option set to true from config file', - function() { - - var exitCode; - - lab.before(function(done) { - - var configOption = path.join('--config=', __dirname, - 'database_with_sql_file.json'); - - wipeMigrations(function(err) { - - Code.expect(err).to.not.exist(); - dbMigrate( 'create', 'second migration', configOption).on('exit', - function(code) { - - exitCode = code; - done(); - }); - }); - }); - - lab.test('does not cause an error', { parallel: true }, function(done) { - - Code.expect(exitCode).to.equal(0); - done(); - }); - - lab.test('will create a new migration', { parallel: true }, - function(done) { - - var files = fs.readdirSync(path.join(__dirname, 'migrations')); - - for (var i = 0; i', 8); - Code.expect(actual).to.equal('>>prompt'); - - done(); - }); - - lab.test('should apply no left padding if already equal to the total length', - { parallel: true }, function(done) { - - var actual = util.lpad('>>prompt', '>', 8); - Code.expect(actual).to.equal('>>prompt'); - - done(); - }); - - lab.test('should apply no left padding if already greater than the total ' + - 'length', { parallel: true }, function(done) { - - var actual = util.lpad('>>>prompt', '>', 8); - Code.expect(actual).to.equal('>>>prompt'); - - done(); - }); - - lab.test('should be apple to pad numbers', - { parallel: true }, function(done) { - - var actual = util.lpad(12, '>', 4); - Code.expect(actual).to.equal('>>12'); - - done(); - }); - - lab.test('should be apple to pad using numbers', - { parallel: true }, function(done) { - - var actual = util.lpad(12, 0, 4); - Code.expect(actual).to.equal('0012'); - - done(); - }); -} diff --git a/test/config_test.js b/test/config_test.js index 0d02e04e..a73638dd 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -1,150 +1,177 @@ -var vows = require('vows'); -var assert = require('assert'); +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); var config = require('../lib/config'); var path = require('path'); var _configLoad = config.load; var _configLoadUrl = config.loadUrl; -vows.describe('config').addBatch({ - 'loading from a file': { - topic: function() { - var configPath = path.join(__dirname, 'database.json'); - return config.load(configPath, 'dev'); - }, - - 'should export all environment settings': function (config) { - assert.isDefined(config.dev); - assert.isDefined(config.test); - assert.isDefined(config.prod); - }, - - 'should export a getCurrent function with all current environment settings': function (config) { - assert.isDefined(config.getCurrent); - var current = config.getCurrent(); - assert.equal(current.env, 'dev'); - assert.equal(current.settings.driver, 'sqlite3'); - assert.equal(current.settings.filename, ':memory:'); - } - }, -}).addBatch({ - 'loading from a broken config file': { - topic: function() { - var configPath = path.join(__dirname, 'database_with_syntax_error.json'); - try { - config.load(configPath, 'dev'); - } catch (e) { - return e; - } - return; - }, - - 'should throw a syntax error': function (error) { - assert.isDefined(error); - assert.ok(error instanceof SyntaxError, "Expected broken file to produce syntax error"); - } - } -}).addBatch({ - 'loading from a file with default env option': { - topic: function() { - var configPath = path.join(__dirname, 'database_with_default_env.json'); - return config.load(configPath); - }, - - 'should load a value from the default env': function (config) { - var current = config.getCurrent(); - assert.equal(current.env, 'local'); - assert.equal(current.settings.driver, 'sqlite3'); - assert.equal(current.settings.filename, ':memory:'); - }, - } -}).addBatch({ - 'loading from a file with default env option in ENV variable': { - topic: function() { - process.env['NODE_ENV'] = 'local'; - var configPath = path.join(__dirname, 'database_with_default_env_from_env.json'); - return config.load(configPath); - }, - - 'should load a value from the env set in NODE_ENV': function (config) { - var current = config.getCurrent(); - assert.equal(current.settings.driver, 'sqlite3'); - assert.equal(current.settings.filename, ':memory:'); - }, - } -}).addBatch({ - 'loading from a file with ENV vars': { - topic: function() { - process.env['DB_MIGRATE_TEST_VAR'] = 'username_from_env'; - var configPath = path.join(__dirname, 'database_with_env.json'); - return config.load(configPath, 'prod'); - }, - - 'should load a value from the environments': function (config) { - assert.equal(config.prod.username, 'username_from_env'); - }, -} - -}).addBatch({ - 'loading from a file with ENV URL': { - topic: function() { - process.env['DB_MIGRATE_TEST_VAR'] = 'postgres://uname:pw@server.com/dbname'; - var configPath = path.join(__dirname, 'database_with_env_url.json'); - return config.load(configPath, 'prod'); - }, - - 'should load a value from the environments': function (config) { - var current = config.getCurrent(); - assert.equal(current.settings.driver, 'postgres'); - assert.equal(current.settings.user, 'uname'); - assert.equal(current.settings.password, 'pw'); - assert.equal(current.settings.host, 'server.com'); - assert.equal(current.settings.database, 'dbname'); - }, -} - -}).addBatch({ - 'loading from an URL': { - topic: function() { - var databaseUrl = 'postgres://uname:pw@server.com/dbname'; - return config.loadUrl(databaseUrl, 'dev'); - }, - - 'should export the settings as the current environment': function (config) { - assert.isDefined(config.dev); - }, - - 'should export a getCurrent function with all current environment settings': function (config) { - assert.isDefined(config.getCurrent); - var current = config.getCurrent(); - assert.equal(current.env, 'dev'); - assert.equal(current.settings.driver, 'postgres'); - assert.equal(current.settings.user, 'uname'); - assert.equal(current.settings.password, 'pw'); - assert.equal(current.settings.host, 'server.com'); - assert.equal(current.settings.database, 'dbname'); - } - } -}).addBatch({ - 'loading a config with null values': { - topic: function() { - var configPath = path.join(__dirname, 'database_with_null_values.json'); - config.load = _configLoad; - config.loadUrl = _configLoadUrl; - try { - config.load(configPath, 'dev'); - }catch(e) { - return e; - } - return null; - }, - - 'should something': function(err) { - assert.isNull(err); - }, - - teardown: function() { - delete require.cache[require.resolve('../lib/config')]; - } - } -}).export(module); +lab.experiment('config', function() { + + lab.experiment('loading from a file', { parallel: true }, + function() { + + var configPath = path.join(__dirname, 'database.json'); + var _config = config.load(configPath, 'dev'); + + lab.test('should export all environment settings', { parallel: true }, + function (done) { + + Code.expect(_config.dev).to.exists(); + Code.expect(_config.test).to.exists(); + Code.expect(_config.prod).to.exists(); + done(); + }); + + lab.test('should export a getCurrent function with all current ' + + 'environment settings', { parallel: true }, function (done) { + + var current; + Code.expect(_config.getCurrent).to.exists(); + current = _config.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); + }); + + lab.experiment('loading from a broken config file', { parallel: true }, + function() { + + var configPath = path.join(__dirname, 'database_with_syntax_error.json'); + + lab.test('should throw a syntax error', { parallel: true }, + function (done) { + + Code.expect( + config.load.bind(this, configPath, 'dev'), + 'Expected broken file to produce syntax error' + ).to.throw(SyntaxError); + done(); + }); + }); + + lab.experiment('loading from a file with default env option', + { parallel: true }, function() { + + var configPath = path.join(__dirname, 'database_with_default_env.json'); + var _config = config.load(configPath); + + lab.test('should load a value from the default env', { parallel: true }, + function (done) { + + var current = _config.getCurrent(); + Code.expect(current.env).to.equal('local'); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); + }); + + lab.experiment('loading from a file with default env option in ENV variable', + { parallel: true }, function() { + + process.env.NODE_ENV = 'local'; + var configPath = path.join( + __dirname, + 'database_with_default_env_from_env.json' + ); + var _config = config.load(configPath); + + lab.test('should load a value from the env set in NODE_ENV', + { parallel: true }, function (done) { + + var current = _config.getCurrent(); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); + }); + + lab.experiment('loading from a file with ENV vars', { parallel: true }, + function() { + + process.env.DB_MIGRATE_TEST_VAR = 'username_from_env'; + var configPath = path.join(__dirname, 'database_with_env.json'); + var _config = config.load(configPath, 'prod'); + + lab.test('should load a value from the environments', { parallel: true }, + function (done) { + + Code.expect(_config.prod.username).to.equal('username_from_env'); + done(); + }); + }); + + lab.experiment('loading from a file with ENV URL', { parallel: true }, + function() { + + process.env.DB_MIGRATE_TEST_VAR = 'postgres://uname:pw@server.com/dbname'; + var configPath = path.join(__dirname, 'database_with_env_url.json'); + var _config = config.load(configPath, 'prod'); + + lab.test('should load a value from the environments', { parallel: true }, + function (done) { + + var current = _config.getCurrent(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host, ').to.equal(rver.com'); + Code.expect(current.settings.database).to.equal('dbname'); + done(); + }); + }); + + lab.experiment('loading from an URL', { parallel: true }, + function() { + + var databaseUrl = 'postgres://uname:pw@server.com/dbname'; + var _config = config.loadUrl(databaseUrl, 'dev'); + + lab.test('should export the settings as the current environment', + { parallel: true }, function (done) { + + Code.expect(_config.dev).to.exists(); + done(); + }); + + lab.test('should export a getCurrent function with all current ' + + 'environment settings', { parallel: true }, function (done) { + + var current; + Code.expect(_config.getCurrent).to.exists(); + current = _config.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + done(); + }); + }); + + lab.experiment('loading a config with null values', function() { + + var configPath = path.join(__dirname, 'database_with_null_values.json'); + config.load = _configLoad; + config.loadUrl = _configLoadUrl; + + lab.test('should something', function(done, cleanup) { + + cleanup(function(next) { + + delete require.cache[require.resolve('../lib/config')]; + next(); + }); + + Code.expect( + config.load.bind(this, configPath, 'dev') + ).to.not.throw; + done(); + }); + }); +}); diff --git a/test/db.config.ci b/test/db.config.ci deleted file mode 100644 index 3a6cc4fc..00000000 --- a/test/db.config.ci +++ /dev/null @@ -1,21 +0,0 @@ -{ - "mysql": { - "database": "db_migrate_test", - "user": "root", - "driver": "mysql" - }, - "pg": { - "driver": "pg", - "database": "db_migrate_test", - "username": "postgres" - }, - "sqlite3": { - "driver": "sqlite3", - "filename": "test.db" - }, - "mongodb": { - "driver": "mongodb", - "host": "localhost", - "database": "db_migrate_test" - } -} diff --git a/test/driver/base_test.js b/test/driver/base_test.js index 3c5abd1f..8fa25779 100644 --- a/test/driver/base_test.js +++ b/test/driver/base_test.js @@ -1,5 +1,6 @@ -var vows = require('vows'); -var assert = require('assert'); +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); var Base = require('db-migrate-base'); var internals = { @@ -10,75 +11,86 @@ var internals = { } }; -vows.describe('base').addBatch({ - 'default implementation': { - topic: new Base(internals), +lab.experiment('base', { parallel: true }, function() { - 'inherits from EventEmitter': function(base) { - assert.isNotNull(base.on); - assert.isNotNull(base.emit); - }, + lab.experiment('default implementation', { parallel: true }, function() { - 'throws errors for all API methods': function(base) { - assert.throws(function() { + var base = new Base(internals); + + lab.test('inherits from EventEmitter', { parallel: true }, function(done) { + + Code.expect(base.on).to.be.not.null(); + Code.expect(base.emit).to.be.not.null(); + done(); + }); + + lab.test('throws errors for all API methods', { parallel: true }, + function(done) { + + Code.expect(function() { base.createTable(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.dropTable(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.addColumn(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.removeColumn(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.renameColumn(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.changeColumn(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.addIndex(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.insert(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.removeIndex(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.addAssociation(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.removeAssociation(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.addForeignKey(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.removeForeignKey(); - }, Error); + }).to.throw(Error); - assert.throws(function() { + Code.expect(function() { base.runSql(); - }, Error); - }, + }).to.throw(Error); - 'escapes single quotes': function(base) { - assert.equal("Bill''s Mother''s House", base.escape("Bill's Mother's House")); - } - } -}).export(module); + done(); + }); + + lab.test('escapes single quotes', { parallel: true }, function(done) { + + Code.expect('Bill\'\'s Mother\'\'s House') + .to.equal(base.escape('Bill\'s Mother\'s House')); + done(); + }); + }); +}); diff --git a/test/driver/index_test.js b/test/driver/index_test.js index 17e2f787..530ab6ad 100644 --- a/test/driver/index_test.js +++ b/test/driver/index_test.js @@ -1,8 +1,8 @@ -var vows = require('vows'); -var assert = require('assert'); var proxyquire = require('proxyquire'); var sinon = require('sinon'); - +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); var validDbConfigWithTunnel = { driver: 'mysql', host: 'dbHost', @@ -18,36 +18,49 @@ var internals = { migrationTable: 'migrations' }; -var indexConnectCallback = function(self, tunnelStub, driverSpy) { +var indexConnectCallback = function(tunnelStub, driverSpy, callback) { return function(err, db) { if (err) { - self.callback(err, db, tunnelStub, driverSpy); + callback(err, db, tunnelStub, driverSpy); return; } - self.callback(err, db, tunnelStub, driverSpy); + callback(err, db, tunnelStub, driverSpy); }; }; -vows.describe('index').addBatch({ - 'a connection with ssh tunnel': { - topic: function() { - // Ensure that require gets a new copy of the module for each test - delete require.cache[require.resolve('db-migrate-mysql')]; - var driver = require('db-migrate-mysql'); +lab.experiment('index', function() { + + lab.test('a successful connection with ssh tunnel with expected parameters', + function(done, cleanup) { - // Set up stubs/spies to verify correct flow - var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); - var tunnelStub = sinon.stub().callsArg(1); + // Ensure that require gets a new copy of the module for each test + delete require.cache[require.resolve('db-migrate-mysql')]; + var driver = require('db-migrate-mysql'); + + // Set up stubs/spies to verify correct flow + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); + var tunnelStub = sinon.stub().callsArg(1); + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + './mysql': driver + }); + //register clean up + cleanup(function(next) { + + driverSpy.restore(); + delete require.cache[require.resolve('tunnel-ssh')]; + delete require.cache[require.resolve('db-migrate-mysql')]; + next(); + }); - var index = proxyquire('../../lib/driver/index', { - 'tunnel-ssh': tunnelStub, - './mysql': driver - }); + index.connect( + validDbConfigWithTunnel, + {}, + indexConnectCallback(tunnelStub, driverSpy, validate) + ); - index.connect(validDbConfigWithTunnel, {}, indexConnectCallback(this, tunnelStub, driverSpy)); - }, - 'should call tunnel once with db config properties added': function(err, db, tunnelStub) { + function validate(err, db, tunnelStub, driverSpy) { var expectedTunnelConfig = { localPort: 'localPort', host: 'sshHost', @@ -55,12 +68,6 @@ vows.describe('index').addBatch({ dstHost: 'dbHost', dstPort: 'dbPort' }; - - assert.isNull(err); - assert.isNotNull(db); - assert(tunnelStub.withArgs(expectedTunnelConfig).calledOnce); - }, - 'should replace the db host and port with localhost and the tunnel localPort': function(err, db, tunnelStub, driverSpy) { var expectedDbConfig = { driver: 'mysql', host: '127.0.0.1', @@ -72,36 +79,62 @@ vows.describe('index').addBatch({ } }; - assert(driverSpy.withArgs(expectedDbConfig).calledOnce); - }, - teardown: function(db, tunnelStub, driverSpy) { - driverSpy.restore(); + + Code.expect(err).to.be.null(); + Code.expect(db).to.not.be.null(); + Code.expect( + tunnelStub.withArgs(expectedTunnelConfig).calledOnce + ).to.be.true(); + Code.expect( + driverSpy.withArgs(expectedDbConfig).calledOnce + ).to.be.true(); + + done(); } - }, - 'a failed tunnel connection': { - topic: function() { - // Ensure that require gets a new copy of the module for each test + }); + + lab.test('a failed connection with ssh tunnel', function(done, cleanup) { + + // Ensure that require gets a new copy of the module for each test + delete require.cache[require.resolve('db-migrate-mysql')]; + var driver = require('db-migrate-mysql'); + + // Set up stubs/spies to verify correct flow + var tunnelStub = sinon.stub().callsArgWith(1, new Error('error')); + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + './mysql': driver + }); + + index.connect( + validDbConfigWithTunnel, + {}, + indexConnectCallback(tunnelStub, driverSpy, validate) + ); + + //register clean up + cleanup(function(next) { + + driverSpy.restore(); + delete require.cache[require.resolve('tunnel-ssh')]; delete require.cache[require.resolve('db-migrate-mysql')]; - var driver = require('db-migrate-mysql'); - - // Set up stubs/spies to verify correct flow - var tunnelStub = sinon.stub().callsArgWith(1, new Error('error')); - var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); - - var index = proxyquire('../../lib/driver/index', { - 'tunnel-ssh': tunnelStub, - './mysql': driver - }); - - index.connect(validDbConfigWithTunnel, {}, indexConnectCallback(this, tunnelStub, driverSpy)); - }, - 'should pass the error to the callback': function (err, db) { - assert(err, 'err should be non-null'); - assert(!db, 'driver should be null or undefined'); - }, - 'should call tunnel, but not driver.connect': function (err, db, tunnelStub, driverSpy) { - assert(tunnelStub.calledOnce, 'tunnel should be called once'); - assert(driverSpy.notCalled, 'driver.connect should not be called'); + next(); + }); + + function validate(err, db, tunnelStub, driverSpy) { + + Code.expect(err, 'err should be non-null') + .to.exists(); + Code.expect(db, 'driver should be null or undefined') + .to.not.exists(); + + Code.expect(tunnelStub.calledOnce, 'tunnel should be called once') + .to.be.true(); + Code.expect(driverSpy.notCalled, 'driver.connect should not be called') + .to.be.true(); + + done(); } - } -}).export(module); + }); +}); diff --git a/test/driver/mongodb_test.js b/test/driver/mongodb_test.js deleted file mode 100644 index 8556c008..00000000 --- a/test/driver/mongodb_test.js +++ /dev/null @@ -1,344 +0,0 @@ -var vows = require('vows'); -var assert = require('assert'); -var dbmeta = require('db-meta'); -var dataType = require('db-migrate-shared').dataType; -var driver = require('../../lib/driver'); - -var config = require('../db.config.json').mongodb; - -var internals = {}; -internals.migrationTable = 'migrations'; - -var dbName = config.database; -driver.connect(config, internals, function(err, db) { - assert.isNull(err); - vows.describe('mongodb') - .addBatch({ - 'createCollection': { - topic: function() { - db.createCollection('event', this.callback); - }, - - teardown: function() { - db.dropCollection('event', this.callback); - }, - - 'has table metadata': { - topic: function() { - db._getCollectionNames(this.callback); - }, - - 'containing the event table': function(err, tables) { - assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - } - } - } - }) - .addBatch({ - 'dropCollection': { - topic: function() { - db.createCollection('event', function(err, collection) { - if(err) { - return this.callback(err); - } - - db.dropCollection('event', this.callback); - }.bind(this)); - }, - - 'has table metadata': { - topic: function() { - db._getCollectionNames(this.callback); - }, - - 'containing no tables': function(err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 1); // Should be 1 b/c of the system collection - } - } - } - }) - .addBatch({ - 'renameCollection': { - topic: function() { - db.createCollection('event', function(err, collection) { - if(err) { - return this.callback(err); - } - - db.renameCollection('event', 'functions', this.callback); - }.bind(this)); - }, - - teardown: function() { - db.dropCollection('functions', this.callback); - }, - - - 'has table metadata': { - topic: function() { - db._getCollectionNames(this.callback); - }, - - 'containing the functions table': function(err, tables) { - var index = 0; - assert.isNotNull(tables); - assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - - if( tables[0].collectionName === 'system.indexes' ) - index = 1; - - assert.equal(tables[index].collectionName, 'functions'); - } - } - } - }) - .addBatch({ - 'addIndex': { - topic: function() { - db.createCollection('event', function(err, collection) { - if(err) { - return this.callback(err); - } - - db.addIndex('event', 'event_title', 'title', false, this.callback); - }.bind(this)); - }, - - teardown: function() { - db.dropCollection('event', this.callback); - }, - - 'preserves case': { - topic: function() { - db._getCollectionNames(this.callback); - }, - - 'of the functions original table': function(err, tables) { - var index = 0; - assert.isNotNull(tables); - assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - - if( tables[0].collectionName === 'system.indexes' ) - index = 1; - - assert.equal(tables[index].collectionName, 'event'); - } - }, - - 'has resulting index metadata': { - topic: function() { - db._getIndexes('event', this.callback); - }, - - 'with additional index': function(err, indexes) { - assert.isDefined(indexes); - assert.isNotNull(indexes); - assert.include(indexes, 'event_title'); - } - } - } - }) - .addBatch({ - 'insertOne': { - topic: function() { - db.createCollection('event', function(err, collection) { - if(err) { - return this.callback(err); - } - db.insert('event', {id: 2, title: 'title'}, function(err) { - - if(err) { - - return this.callback(err); - } - - db._find('event', {title: 'title'}, this.callback); - - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropCollection('event', this.callback); - }, - - 'with additional row' : function(err, data) { - - assert.equal(data.length, 1); - } - } - }) - .addBatch({ - 'insertMany': { - topic: function() { - db.createCollection('event', function(err, collection) { - if(err) { - return this.callback(err); - } - db.insert('event', [{id: 2, title: 'title'}, - {id: 3, title: 'lol'}, - {id: 4, title: 'title'}], function(err) { - - if(err) { - - return this.callback(err); - } - - db._find('event', {title: 'title'}, this.callback); - - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropCollection('event', this.callback); - }, - - 'with additional row' : function(err, data) { - - assert.equal(data.length, 2); - } - } - }) - .addBatch({ - 'removeIndex': { - topic: function() { - db.createCollection('event', function(err, collection) { - if(err) { - return this.callback(err); - } - - db.addIndex('event', 'event_title', 'title', false, function(err, data) { - - if(err) { - return this.callback(err); - } - - db.removeIndex('event', 'event_title', this.callback); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropCollection('event', this.callback); - }, - - - 'has resulting index metadata': { - topic: function() { - db._getIndexes('event', this.callback); - }, - - 'without index': function(err, indexes) { - if(err) { - return this.callback(err); - } - - assert.isDefined(indexes); - assert.isNotNull(indexes); - assert.notInclude(indexes, 'event_title'); - } - } - } - }) - .addBatch({ - 'createMigrationsTable': { - topic: function() { - db._createMigrationsCollection(this.callback); - }, - - teardown: function() { - db.dropCollection('migrations', this.callback); - }, - - 'has migrations table': { - topic: function() { - db._getCollectionNames(this.callback); - }, - - 'has migrations table' : function(err, tables) { - var index = 0; - assert.isNull(err); - assert.isNotNull(tables); - assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - if( tables[0].collectionName === 'system.indexes' ) - index = 1; - - assert.equal(tables[index].collectionName, 'migrations'); - } - } - } - }) - .addBatch({ - 'removeIndex': { - topic: function() { - db.createCollection('event', function(err, collection) { - if(err) { - return this.callback(err); - } - - db.addIndex('event', 'event_title', 'title', false, function(err, data) { - - if(err) { - return this.callback(err); - } - - db.removeIndex('event', 'event_title', this.callback); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropCollection('event', this.callback); - }, - - - 'has resulting index metadata': { - topic: function() { - db._getIndexes('event', this.callback); - }, - - 'without index': function(err, indexes) { - if(err) { - return this.callback(err); - } - - assert.isDefined(indexes); - assert.isNotNull(indexes); - assert.notInclude(indexes, 'event_title'); - } - } - } - }) - .addBatch({ - 'createMigrationsTable': { - topic: function() { - db._createMigrationsCollection(this.callback); - }, - - teardown: function() { - db.dropCollection('migrations', this.callback); - }, - - 'has migrations table': { - topic: function() { - db._getCollectionNames(this.callback); - }, - - 'has migrations table' : function(err, tables) { - var index = 0; - assert.isNull(err); - assert.isNotNull(tables); - assert.equal(tables.length, 2); // Should be 2 b/c of the system collection - - if( tables[0].collectionName === 'system.indexes' ) - index = 1; - - assert.equal(tables[index].collectionName, 'migrations'); - } - } - } - }) - .export(module); -}); diff --git a/test/driver/mysql_test.js b/test/driver/mysql_test.js deleted file mode 100644 index 0755f2d2..00000000 --- a/test/driver/mysql_test.js +++ /dev/null @@ -1,880 +0,0 @@ -var vows = require('vows'); -var assert = require('assert'); -var dbmeta = require('db-meta'); -var dataType = require('db-migrate-shared').dataType; -var driver = require('../../lib/driver'); -var log = require('db-migrate-shared').log; - -var config = require('../db.config.json').mysql; - -var internals = {}; -internals.migrationTable = 'migrations'; -log.silence(true); - -var dbName = config.database; -driver.connect(config, internals, function(err, db) { - assert.isNull(err); - vows.describe('mysql').addBatch({ - 'createTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - str: { type: dataType.STRING, unique: true, defaultValue: 'foo' }, - strDefaultNull: { type: dataType.STRING, defaultValue: null }, - txt: { type: dataType.TEXT, notNull: true }, - intg: dataType.INTEGER, - rel: dataType.REAL, - dt: dataType.DATE_TIME, - ts: dataType.TIMESTAMP, - bin: dataType.BINARY, - bl: { type: dataType.BOOLEAN, defaultValue: false } - }, this.callback); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'has table metadata': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing the event table': function(err, tables) { - assert.equal(tables.length, 1); - assert.equal(tables[0].getName(), 'event'); - } - }, - - 'has column metadata for the event table': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with 10 columns': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 10); - }, - - 'that has integer id column that is primary key, non-nullable, and auto increments': function(err, columns) { - var column = findByName(columns, 'id'); - assert.equal(column.getDataType(), 'INT'); - assert.equal(column.isPrimaryKey(), true); - assert.equal(column.isNullable(), false); - // assert.equal(column.isAutoIncrementing(), true); - }, - - 'that has text str column that is unique and has a default value': function(err, columns) { - var column = findByName(columns, 'str'); - assert.equal(column.getDataType(), 'VARCHAR'); - assert.equal(column.getDefaultValue(), 'foo'); - // assert.equal(column.isUnique(), true); - }, - - 'that has text strDefaultNull column that has a default null value': function(err, columns) { - var column = findByName(columns, 'strDefaultNull'); - assert.equal(column.getDefaultValue(), null); - }, - - 'that has text txt column that is non-nullable': function(err, columns) { - var column = findByName(columns, 'txt'); - assert.equal(column.getDataType(), 'TEXT'); - assert.equal(column.isNullable(), false); - }, - - 'that has integer intg column': function(err, columns) { - var column = findByName(columns, 'intg'); - assert.equal(column.getDataType(), 'INT'); - assert.equal(column.isNullable(), true); - }, - - 'that has real rel column': function(err, columns) { - var column = findByName(columns, 'rel'); - assert.equal(column.getDataType(), 'DOUBLE'); - assert.equal(column.isNullable(), true); - }, - - 'that has datetime dt column': function(err, columns) { - var column = findByName(columns, 'dt'); - assert.equal(column.getDataType(), 'DATETIME'); - assert.equal(column.isNullable(), true); - }, - - 'that has timestamp ts column': function(err, columns) { - var column = findByName(columns, 'ts'); - assert.equal(column.getDataType(), 'TIMESTAMP'); - assert.equal(column.isNullable(), false); - }, - - 'that has binary bin column': function(err, columns) { - var column = findByName(columns, 'bin'); - assert.equal(column.getDataType(), 'BINARY'); - assert.equal(column.isNullable(), true); - }, - - 'that has boolean bl column with a default value': function(err, columns) { - var column = findByName(columns, 'bl'); - assert.equal(column.getDataType(), 'TINYINT'); - assert.equal(column.isNullable(), true); - assert.equal(column.getDefaultValue(), 0); - } - } - } - }).addBatch({ - 'dropTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function(err) { - if (err) { - return this.callback(err); - } - db.dropTable('event', this.callback.bind(this, null)); - }.bind(this)); - }, - - 'has table metadata': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing no tables': function(err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 0); - } - } - } - }).addBatch({ - 'renameTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.renameTable('event', 'functions', this.callback.bind(this, null)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('functions', this.callback); - }, - - 'has table metadata': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing the functions table': function(err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 1); - assert.equal(tables[0].getName(), 'functions'); - } - } - } - }).addBatch({ - 'addColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addColumn('event', 'title', 'string', this.callback.bind(this, null)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'has column metadata': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with additional title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 2); - var column = findByName(columns, 'title'); - assert.equal(column.getName(), 'title'); - assert.equal(column.getDataType(), 'VARCHAR'); - } - } - } - }).addBatch({ - 'removeColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addColumn('event', 'title', 'string', function(err) { - db.removeColumn('event', 'title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'has column metadata': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'without title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 1); - assert.notEqual(columns[0].getName(), 'title'); - } - } - } - }).addBatch({ - 'renameColumn': { - topic: function() { - driver.connect(config, internals, function(err) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: dataType.STRING - }, function() { - db.renameColumn('event', 'title', 'new_title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'has column metadata': { - topic: function() { - dbmeta('mysql', { connection: db.connection }, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with renamed title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 2); - var column = findByName(columns, 'new_title'); - assert.isNotNull(column); - assert.equal(column.getName(), 'new_title'); - } - } - } - }).addBatch({ - 'changeColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - txt: { type: dataType.STRING, notNull: true, defaultValue: "foo", unique: true }, - keep_id: { type: dataType.INTEGER, notNull: false, unique: true } - }, function(err) { - if (err) { - return this.callback(err); - } - var spec = { type: dataType.STRING, notNull: false, unique: false, defaultValue: 'foo2' }, - spec2 = { type: dataType.INTEGER, notNull: true, unsigned: true }; - - db.changeColumn('event', 'txt', spec, function() { - db.changeColumn('event', 'keep_id', spec2, this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'has column metadata': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with changed title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 3); - var column = findByName(columns, 'txt'); - assert.equal(column.getName(), 'txt'); - assert.equal(column.isNullable(), true); - assert.equal(column.getDefaultValue(), "foo2"); - assert.equal(column.isUnique(), false); - - column = findByName(columns, 'keep_id'); - assert.equal(column.getName(), 'keep_id'); - assert.equal(column.isNullable(), false); - assert.equal(column.isUnique(), true); - } - } - } - }).addBatch({ - 'addIndex': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - db.addIndex('event', 'event_title', 'title', function() { - db.addIndex('event', 'event_title_sub_part', { name: 'title', length: 8 }, this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'preserves case': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'of the functions original table': function(err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 1); - assert.equal(tables[0].getName(), 'event'); - } - }, - - 'has resulting index metadata': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); - }, - - 'with additional indexes': function(err, indexes) { - assert.isNotNull(indexes); - assert.equal(indexes.length, 3); - - var index = findByName(indexes, 'event_title'); - assert.equal(index.getName(), 'event_title'); - assert.equal(index.getTableName(), 'event'); - assert.equal(index.getColumnName(), 'title'); - - var indexSubpart = findByName(indexes, 'event_title_sub_part'); - assert.equal(indexSubpart.getName(), 'event_title_sub_part'); - assert.equal(indexSubpart.getTableName(), 'event'); - assert.equal(indexSubpart.getColumnName(), 'title'); - assert.equal(indexSubpart.meta.sub_part, '8'); - } - } - } - }).addBatch({ - 'columnForeignKeySpec': { - topic: function() { - db.createTable('event_type', { - - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - - db.createTable('event', { - id: { - type: dataType.INTEGER, - primaryKey: true, - autoIncrement: true - }, - event_id: { - type: dataType.INTEGER, - notNull: true, - foreignKey: { - name: 'fk_event_event_type', - table: 'event_type', - mapping: 'id', - rules: { - onDelete: 'CASCADE' - }, - } }, - title: { - type: dataType.STRING - } - }, this.callback.bind(this, null)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event'); - db.dropTable('event_type', this.callback); - }, - - 'sets usage and constraints': { - topic: function() { - var metaQuery = ['SELECT', - ' usg.REFERENCED_TABLE_NAME,', - ' usg.REFERENCED_COLUMN_NAME,', - ' cstr.UPDATE_RULE,', - ' cstr.DELETE_RULE', - 'FROM', - ' `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` AS usg', - 'INNER JOIN', - ' `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS` AS cstr', - ' ON cstr.CONSTRAINT_SCHEMA = usg.TABLE_SCHEMA', - ' AND cstr.CONSTRAINT_NAME = usg.CONSTRAINT_NAME', - 'WHERE', - ' usg.TABLE_SCHEMA = ?', - ' AND usg.TABLE_NAME = ?', - ' AND usg.COLUMN_NAME = ?'].join('\n'); - db.runSql(metaQuery, dbName, 'event', 'event_id', this.callback); - }, - - 'with correct references': function(err, rows) { - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.REFERENCED_TABLE_NAME, 'event_type'); - assert.equal(row.REFERENCED_COLUMN_NAME, 'id'); - }, - - 'and correct rules': function(err, rows) { - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.UPDATE_RULE, 'NO ACTION'); - assert.equal(row.DELETE_RULE, 'CASCADE'); - } - } - } - }).addBatch({ - 'explicitColumnForeignKeySpec': { - topic: function() { - db.createTable('event_type', { - - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - - db.createTable('event', { - id: { - type: dataType.INTEGER, - primaryKey: true, - autoIncrement: true - }, - event_id: { - type: dataType.INTEGER, - notNull: true, - foreignKey: { - name: 'fk_event_event_type', - table: 'event_type', - mapping: 'id', - rules: { - onDelete: 'CASCADE' - }, - } - }, - event_id2: { - type: dataType.INTEGER, - notNull: true, - foreignKey: { - name: 'fk_event_event2_type', - table: 'event_type', - mapping: 'id', - rules: { - onDelete: 'CASCADE' - }, - } - }, - title: { - type: dataType.STRING - } - }, this.callback.bind(this, null)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event'); - db.dropTable('event_type', this.callback); - }, - - 'sets usage and constraints': { - topic: function() { - var metaQuery = ['SELECT', - ' usg.REFERENCED_TABLE_NAME,', - ' usg.REFERENCED_COLUMN_NAME,', - ' cstr.UPDATE_RULE,', - ' cstr.DELETE_RULE', - 'FROM', - ' `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` AS usg', - 'INNER JOIN', - ' `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS` AS cstr', - ' ON cstr.CONSTRAINT_SCHEMA = usg.TABLE_SCHEMA', - ' AND cstr.CONSTRAINT_NAME = usg.CONSTRAINT_NAME', - 'WHERE', - ' usg.TABLE_SCHEMA = ?', - ' AND usg.TABLE_NAME = ?', - ' AND ( usg.COLUMN_NAME = ? OR usg.COLUMN_NAME = ? )'].join('\n'); - db.runSql(metaQuery, dbName, 'event', 'event_id', 'event_id2', this.callback); - }, - - 'with correct references': function(err, rows) { - assert.isNotNull(rows); - assert.equal(rows.length, 2); - var row = rows[0]; - assert.equal(row.REFERENCED_TABLE_NAME, 'event_type'); - assert.equal(row.REFERENCED_COLUMN_NAME, 'id'); - - var row = rows[1]; - assert.equal(row.REFERENCED_TABLE_NAME, 'event_type'); - assert.equal(row.REFERENCED_COLUMN_NAME, 'id'); - var row = rows[1]; - assert.equal(row.UPDATE_RULE, 'NO ACTION'); - assert.equal(row.DELETE_RULE, 'CASCADE'); - }, - - 'and correct rules': function(err, rows) { - assert.isNotNull(rows); - assert.equal(rows.length, 2); - var row = rows[0]; - assert.equal(row.UPDATE_RULE, 'NO ACTION'); - assert.equal(row.DELETE_RULE, 'CASCADE'); - - var row = rows[1]; - assert.equal(row.REFERENCED_TABLE_NAME, 'event_type'); - assert.equal(row.REFERENCED_COLUMN_NAME, 'id'); - var row = rows[1]; - assert.equal(row.UPDATE_RULE, 'NO ACTION'); - assert.equal(row.DELETE_RULE, 'CASCADE'); - } - } - } - }).addBatch({ - 'addForeignKey': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - event_id: { type: dataType.INTEGER, notNull: true }, - title: { type: dataType.STRING } - }, function() { - db.createTable('event_type', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.addForeignKey('event', 'event_type', 'fk_event_event_type', { - 'event_id': 'id' - }, { - onDelete: 'CASCADE' - }, this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event'); - db.dropTable('event_type', this.callback); - }, - - 'sets usage and constraints': { - topic: function() { - var metaQuery = ['SELECT', - ' usg.REFERENCED_TABLE_NAME,', - ' usg.REFERENCED_COLUMN_NAME,', - ' cstr.UPDATE_RULE,', - ' cstr.DELETE_RULE', - 'FROM', - ' `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` AS usg', - 'INNER JOIN', - ' `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS` AS cstr', - ' ON cstr.CONSTRAINT_SCHEMA = usg.TABLE_SCHEMA', - ' AND cstr.CONSTRAINT_NAME = usg.CONSTRAINT_NAME', - 'WHERE', - ' usg.TABLE_SCHEMA = ?', - ' AND usg.TABLE_NAME = ?', - ' AND usg.COLUMN_NAME = ?'].join('\n'); - db.runSql(metaQuery, dbName, 'event', 'event_id', this.callback); - }, - - 'with correct references': function(err, rows) { - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.REFERENCED_TABLE_NAME, 'event_type'); - assert.equal(row.REFERENCED_COLUMN_NAME, 'id'); - }, - - 'and correct rules': function(err, rows) { - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.UPDATE_RULE, 'NO ACTION'); - assert.equal(row.DELETE_RULE, 'CASCADE'); - } - } - } - }).addBatch({ - 'removeForeignKey': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - event_id: { type: dataType.INTEGER, notNull: true }, - title: { type: dataType.STRING } - }, function() { - db.createTable('event_type', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.addForeignKey('event', 'event_type', 'fk_event_event_type', { - 'event_id': 'id' - }, { - onDelete: 'CASCADE' - }, function () { - db.removeForeignKey('event', 'fk_event_event_type', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event'); - db.dropTable('event_type', this.callback); - }, - }, - - 'removes usage and constraints': { - topic: function() { - var metaQuery = ['SELECT', - ' usg.REFERENCED_TABLE_NAME,', - ' usg.REFERENCED_COLUMN_NAME,', - ' cstr.UPDATE_RULE,', - ' cstr.DELETE_RULE', - 'FROM', - ' `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` AS usg', - 'INNER JOIN', - ' `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS` AS cstr', - ' ON cstr.CONSTRAINT_SCHEMA = usg.TABLE_SCHEMA', - ' AND cstr.CONSTRAINT_NAME = usg.CONSTRAINT_NAME', - 'WHERE', - ' usg.TABLE_SCHEMA = ?', - ' AND usg.TABLE_NAME = ?', - ' AND usg.COLUMN_NAME = ?'].join('\n'); - db.runSql(metaQuery, dbName, 'event', 'event_id', this.callback); - }, - - 'completely': function(err, rows) { - assert.isNotNull(rows); - assert.equal(rows.length, 0); - } - } - }).addBatch({ - 'runSql': { - 'accepts vararg parameters': function() { - db.runSql("SELECT 1 = ?, 2 = ?", 1, 2, function(err, data) { - assert.equal(data.length, 1); - }); - }, - 'accepts array parameters': function() { - db.runSql("SELECT 1 = ?, 2 = ?", [1, 2], function(err, data) { - assert.equal(data.length, 1); - }); - } - } - }).addBatch({ - 'all': { - 'accepts vararg parameters': function() { - db.all("SELECT 1 = ?, 2 = ?", 1, 2, function(err, data) { - assert.equal(data.length, 1); - }); - } - } - }).addBatch({ - 'insert': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - db.insert('event', ['id','title'], [2,'title'], this.callback.bind(this, null)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'with additional row' : function() { - db.runSql("SELECT * from event", function(err, data) { - assert.equal(data.length, 1); - }); - } - } - }).addBatch({ - 'insertWithSingleQuotes': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - db.insert('event', ['id','title'], [2,"Bill's Mother's House"], this.callback.bind(this, null)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'with additional row' : function() { - db.runSql("SELECT * from event", function(err, data) { - assert.equal(data.length, 1); - }); - } - } - }).addBatch({ - 'removeIndex': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - db.addIndex('event', 'event_title', 'title', function(err) { - db.removeIndex('event', 'event_title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event', this.callback); - }, - - 'has resulting index metadata': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); - }, - - 'without index': function(err, indexes) { - assert.isNotNull(indexes); - assert.equal(indexes.length, 1); // first index is primary key - } - } - } - }).addBatch({ - 'removeIndexInvalidArgs': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - db.addIndex('event', 'event_title', 'title', function(err) { - db.removeIndex('event_title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - 'removeIndex has errored': function (err) { - assert.isNotNull(err); - assert.equal(err.message, 'Illegal arguments, must provide "tableName" and "indexName"'); - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'createMigrationsTable': { - topic: function() { - db.createMigrationsTable(this.callback.bind(this, null)); - }, - - teardown: function() { - db.dropTable('migrations', this.callback); - }, - - 'has migrations table': { - topic: function() { - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'has migrations table' : function(err, tables) { - assert.isNull(err); - assert.isNotNull(tables); - assert.equal(tables.length,1); - assert.equal(tables[0].getName(), 'migrations'); - }, - - 'that has columns':{ - topic:function(){ - dbmeta('mysql', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('migrations',this.callback); - }.bind(this)); - }, - - 'with names': function(err, columns){ - assert.isNotNull(columns); - assert.equal(columns.length, 3); - var column = findByName(columns, 'id'); - assert.equal(column.getName(), 'id'); - assert.equal(column.getDataType(), 'INT'); - column = findByName(columns, 'name'); - assert.equal(column.getName(), 'name'); - assert.equal(column.getDataType(), 'VARCHAR'); - column = findByName(columns, 'run_on'); - assert.equal(column.getName(), 'run_on'); - assert.equal(column.getDataType(), 'DATETIME'); - } - } - } - } - }).export(module); -}); -function findByName(columns, name) { - for (var i = 0; i < columns.length; i++) { - if (columns[i].getName() === name) { - return columns[i]; - } - } - return null; -} diff --git a/test/driver/pg_schema_test.js b/test/driver/pg_schema_test.js deleted file mode 100644 index 2fd5f6ec..00000000 --- a/test/driver/pg_schema_test.js +++ /dev/null @@ -1,162 +0,0 @@ -var vows = require('vows'); -var Promise = require('bluebird'); -var assert = require('assert'); -var dbmeta = require('db-meta'); -var pg = require('pg'); -var dataType = require('db-migrate-shared').dataType; -var driver = require('../../lib/driver'); - -var databaseUrl = 'postgres://localhost/db_migrate_test'; - -var internals = {}; -internals.migrationTable = 'migrations'; - -vows.describe('pg').addBatch({ - 'create schema which needs escaping and connect': { - topic: function() { - var callback = this.callback; - var client = new pg.Client(databaseUrl); - - client.connect(function (err) { - if (err) { return callback(err); } - client.query('CREATE SCHEMA "test-schema"', function(err) { - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test-schema' }, internals, function(err, db) { - callback(err, db, client); - }); - }); - }); - }, - - 'migrations': { - topic: function(db, client) { - var callback = this.callback; - - db.createMigrationsTable(function() { - client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test-schema\' AND table_name = \'migrations\'', function(err, result) { - callback(err, result); - }); - }); - }, - - 'is in test-schema': function(err, result) { - assert.isNull(err); - assert.isNotNull(result); - assert.equal(result.rowCount, 1); - } - }, - - teardown: function(db, client) { - var callback = this.callback; - client.query('DROP SCHEMA "test-schema" CASCADE', function (err) { - if (err) { return callback(err); } - client.end(); - callback(); - }); - } - } -}) -.addBatch({ - 'create schema and a public.migrations table and connect': { - topic: function() { - var callback = this.callback; - var client = new pg.Client(databaseUrl); - var query = Promise.promisify( client.query ).bind(client); - - client.connect(function (err) { - if (err) { return callback(err); } - Promise.all([ - query('CREATE SCHEMA test_schema'), - query('CREATE TABLE migrations ()') - ]) - .then( function() { - - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, internals, function(err, db) { - callback(err, db, client); - }); - }) - .catch( function(err) { - callback(err); - }); - }); - }, - - 'migrations table': { - topic: function(db, client) { - var callback = this.callback; - - db.createMigrationsTable(function() { - client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test_schema\' AND table_name = \'migrations\'', function(err, result) { - callback(err, result); - }); - }); - }, - - 'is in test_schema': function(err, result) { - assert.isNull(err); - assert.isNotNull(result); - assert.equal(result.rowCount, 1); - } - }, - - teardown: function(db, client) { - var callback = this.callback; - var query = Promise.promisify(client.query).bind(client); - - Promise.all([ - query('DROP SCHEMA test_schema CASCADE'), - query('DROP TABLE migrations') - ]) - .then(function (err) { - client.end(); - callback(); - }) - .catch(function (err) { - callback(err); - }); - } - } -}) -.addBatch({ - 'create schema and connect': { - topic: function() { - var callback = this.callback; - var client = new pg.Client(databaseUrl); - - client.connect(function (err) { - if (err) { return callback(err); } - client.query('CREATE SCHEMA test_schema', function(err) { - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, internals, function(err, db) { - callback(err, db, client); - }); - }); - }); - }, - - 'migrations table': { - topic: function(db, client) { - var callback = this.callback; - - db.createMigrationsTable(function() { - client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test_schema\' AND table_name = \'migrations\'', function(err, result) { - callback(err, result); - }); - }); - }, - - 'is in test_schema': function(err, result) { - assert.isNull(err); - assert.isNotNull(result); - assert.equal(result.rowCount, 1); - } - }, - - teardown: function(db, client) { - var callback = this.callback; - client.query('DROP SCHEMA test_schema CASCADE', function (err) { - if (err) { return callback(err); } - client.end(); - callback(); - }); - } - } -}).export(module); diff --git a/test/driver/pg_test.js b/test/driver/pg_test.js deleted file mode 100644 index 22542a6e..00000000 --- a/test/driver/pg_test.js +++ /dev/null @@ -1,722 +0,0 @@ -var util = require('util'); -var vows = require('vows'); -var assert = require('assert'); -var dbmeta = require('db-meta'); -var dataType = require('db-migrate-shared').dataType; -var driver = require('../../lib/driver'); -var log = require('db-migrate-shared').log; - -var config = require('../db.config.json').pg; - -var internals = {}; -internals.migrationTable = 'migrations'; -log.silence(true); - -driver.connect(config, internals, function(err, db) { - vows.describe('pg').addBatch({ - 'createTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - str: { type: dataType.STRING, unique: true }, - txt: { type: dataType.TEXT, notNull: true, defaultValue: "foo" }, - chr: dataType.CHAR, - intg: dataType.INTEGER, - rel: dataType.REAL, - smalint: dataType.SMALLINT, - dt: dataType.DATE, - dti: dataType.DATE_TIME, - bl: dataType.BOOLEAN - }, this.callback.bind(this)); - }, - - 'has table metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing the event table': function(err, tables) { - assert.equal(tables.length, 1); - assert.equal(tables[0].getName(), 'event'); - } - }, - - 'has column metadata for the event table': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with 10 columns': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 10); - }, - - 'that has integer id column that is primary key, non-nullable, and auto increments': function(err, columns) { - var column = findByName(columns, 'id'); - assert.equal(column.getDataType(), 'INTEGER'); - assert.equal(column.isPrimaryKey(), true); - assert.equal(column.isNullable(), false); - assert.equal(column.isAutoIncrementing(), true); - }, - - 'that has text str column that is unique': function(err, columns) { - var column = findByName(columns, 'str'); - assert.equal(column.getDataType(), 'CHARACTER VARYING'); - assert.equal(column.isUnique(), true); - }, - - 'that has text txt column that is non-nullable': function(err, columns) { - var column = findByName(columns, 'txt'); - assert.equal(column.getDataType(), 'TEXT'); - assert.equal(column.isNullable(), false); - // assert.equal(column.getDefaultValue(), 'foo'); - }, - - 'that has integer intg column': function(err, columns) { - var column = findByName(columns, 'intg'); - assert.equal(column.getDataType(), 'INTEGER'); - assert.equal(column.isNullable(), true); - }, - - 'that has real rel column': function(err, columns) { - var column = findByName(columns, 'rel'); - assert.equal(column.getDataType(), 'REAL'); - assert.equal(column.isNullable(), true); - }, - - 'that has integer dt column': function(err, columns) { - var column = findByName(columns, 'dt'); - assert.equal(column.getDataType(), 'DATE'); - assert.equal(column.isNullable(), true); - }, - - 'that has integer dti column': function(err, columns) { - var column = findByName(columns, 'dti'); - assert.equal(column.getDataType(), 'TIMESTAMP WITHOUT TIME ZONE'); - assert.equal(column.isNullable(), true); - }, - - 'that has boolean bl column': function(err, columns) { - var column = findByName(columns, 'bl'); - assert.equal(column.getDataType(), 'BOOLEAN'); - assert.equal(column.isNullable(), true); - }, - - 'that has character chr column': function(err, columns) { - var column = findByName(columns, 'chr'); - assert.equal(column.getDataType(), 'CHARACTER'); - assert.equal(column.isNullable(), true); - }, - - 'that has small integer smalint column': function(err, columns) { - var column = findByName(columns, 'smalint'); - assert.equal(column.getDataType(), 'SMALLINT'); - assert.equal(column.isNullable(), true); - } - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'dropTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function(err) { - if (err) { - return this.callback(err); - } - db.dropTable('event', this.callback.bind(this, null)); - }.bind(this)); - }, - - 'has table metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing no tables': function(err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 0); - } - } - } - }).addBatch({ - 'renameTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.renameTable('event', 'functions', this.callback.bind(this, null)); - }.bind(this)); - }, - - 'has table metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing the functions table': function(err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 1); - assert.equal(tables[0].getName(), 'functions'); - } - }, - - teardown: function() { - db.dropTable('functions', this.callback); - } - } - }).addBatch({ - 'addColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addColumn('event', 'title', 'string', this.callback.bind(this, null)); - }.bind(this)); - }, - - 'has column metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with additional title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 2); - var column = findByName(columns, 'title'); - assert.equal(column.getName(), 'title'); - assert.equal(column.getDataType(), 'CHARACTER VARYING'); - } - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'removeColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addColumn('event', 'title', 'string', function(err) { - db.removeColumn('event', 'title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - 'has column metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'without title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 1); - assert.notEqual(columns[0].getName(), 'title'); - } - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'renameColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addColumn('event', 'title', 'string', function(err) { - db.renameColumn('event', 'title', 'new_title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - 'has column metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with renamed title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 2); - var column = findByName(columns, 'new_title'); - assert.equal(column.getName(), 'new_title'); - } - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'changeColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - txt: { type: dataType.TEXT, notNull: true, unique: true, defaultValue: "foo" }, - keep_id: { type: dataType.INTEGER, notNull: true, unique: true }, - type_test: {type:dataType.BLOB, notNull:true} - }, function() { - var spec = { notNull: false, defaultValue: "foo2", unique: false }, - spec2 = { notNull: true, unsigned: true}, - spec3 = { type:dataType.INTEGER, using:util.format('USING CAST(CAST("type_test" AS %s) AS %s)', dataType.TEXT, dataType.INTEGER) }; - - db.changeColumn('event', 'txt', spec, function() { - db.changeColumn('event', 'keep_id', spec2, function(){ - db.changeColumn('event', 'type_test', spec3, this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }, - 'has column metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with changed title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 4); - - var column = findByName(columns, 'txt'); - assert.equal(column.getName(), 'txt'); - assert.equal(column.isNullable(), true); - assert.equal(column.getDefaultValue(), "'foo2'::text"); - assert.equal(column.isUnique(), false); - - column = findByName(columns, 'keep_id'); - assert.equal(column.getName(), 'keep_id'); - assert.equal(column.isNullable(), false); - assert.equal(column.isUnique(), true); - - column = findByName(columns, 'type_test'); - assert.equal(column.getName(), 'type_test'); - assert.equal(dataType[column.getDataType()], dataType.INTEGER); - } - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'addIndex': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - db.addIndex('event', 'event_title', 'title', this.callback.bind(this, null)); - }.bind(this)); - }, - - 'has resulting index metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); - }, - - 'with additional index': function(err, indexes) { - assert.isNotNull(indexes); - assert.equal(indexes.length, 2); - var index = findByName(indexes, 'event_title'); - assert.equal(index.getName(), 'event_title'); - assert.equal(index.getTableName(), 'event'); - assert.equal(index.getColumnName(), 'title'); - } - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'addForeignKey': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - event_id: { type: dataType.INTEGER, notNull: true }, - title: { type: dataType.STRING } - }, function() { - db.createTable('event_type', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - // lowercase table names because they are quoted in the function - // and pg uses lowercase internally - db.addForeignKey('event', 'event_type', 'fk_event_event_type', { - 'event_id': 'id' - }, { - onDelete: 'CASCADE' - }, this.callback); - }.bind(this)); - }.bind(this)); - }, - - 'sets usage and constraints': { - topic: function() { - var metaQuery = ['SELECT', - ' tc.table_schema, tc.table_name as ortn, kcu.column_name orcn, ccu.table_name,', - ' ccu.column_name,', - ' cstr.update_rule,', - ' cstr.delete_rule', - 'FROM', - ' information_schema.table_constraints AS tc', - 'JOIN information_schema.key_column_usage AS kcu', - ' ON tc.constraint_name = kcu.constraint_name', - 'JOIN information_schema.constraint_column_usage AS ccu', - ' ON ccu.constraint_name = tc.constraint_name', - 'JOIN information_schema.referential_constraints AS cstr', - ' ON cstr.constraint_schema = tc.table_schema', - ' AND cstr.constraint_name = tc.constraint_name', - 'WHERE', - ' tc.table_schema = ?', - ' AND tc.table_name = ?', - ' AND kcu.column_name = ?'].join('\n'); - db.runSql(metaQuery, ['public', 'event', 'event_id'], this.callback); - }, - - 'with correct references': function(err, result) { - var rows = result.rows; - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.table_name, 'event_type'); - assert.equal(row.column_name, 'id'); - }, - - 'and correct rules': function(err, result) { - var rows = result.rows; - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.update_rule, 'NO ACTION'); - assert.equal(row.delete_rule, 'CASCADE'); - } - }, - - teardown: function() { - db.dropTable('event'); - db.dropTable('event_type', this.callback); - } - } - }).addBatch({ - 'removeForeignKey': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - event_id: { type: dataType.INTEGER, notNull: true }, - title: { type: dataType.STRING } - }, function() { - db.createTable('event_type', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.addForeignKey('event', 'event_type', 'fk_event_event_type', { - 'event_id': 'id' - }, { - onDelete: 'CASCADE' - }, function () { - db.removeForeignKey('event', 'fk_event_event_type', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event'); - db.dropTable('event_type', this.callback); - }, - - 'removes usage and constraints': { - topic: function() { - var metaQuery = ['SELECT', - ' tc.table_schema, tc.table_name as ortn, kcu.column_name orcn, ccu.table_name,', - ' ccu.column_name,', - ' cstr.update_rule,', - ' cstr.delete_rule', - 'FROM', - ' information_schema.table_constraints AS tc', - 'JOIN information_schema.key_column_usage AS kcu', - ' ON tc.constraint_name = kcu.constraint_name', - 'JOIN information_schema.constraint_column_usage AS ccu', - ' ON ccu.constraint_name = tc.constraint_name', - 'JOIN information_schema.referential_constraints AS cstr', - ' ON cstr.constraint_schema = tc.table_schema', - ' AND cstr.constraint_name = tc.constraint_name', - 'WHERE', - ' tc.table_schema = ?', - ' AND tc.table_name = ?', - ' AND kcu.column_name = ?'].join('\n'); - db.runSql(metaQuery, ['public', 'event', 'event_id'], this.callback); - }, - - 'completely': function(err, result) { - assert.isNotNull(result.rows); - assert.equal(result.rows.length, 0); - } - } - } - }).addBatch({ - 'addForeign by addcolumn with spec': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - event_id: { type: dataType.INTEGER, notNull: true }, - title: { type: dataType.STRING } - }, function() { - db.createTable('event_type', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.addColumn('event_type', 'event_id', { - type: dataType.INTEGER, - notNull: true, - foreignKey: { - name: 'primary_event_id_fk', - table: 'event', - rules: { - onDelete: 'CASCADE', - onUpdate: 'RESTRICT' - }, - mapping: 'id' - } - }, this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event_type'); - db.dropTable('event', this.callback); - }, - - 'sets usage and constraints': { - topic: function() { - var metaQuery = ['SELECT', - ' tc.table_schema, tc.table_name as ortn, kcu.column_name orcn, ccu.table_name,', - ' ccu.column_name,', - ' cstr.update_rule,', - ' cstr.delete_rule', - 'FROM', - ' information_schema.table_constraints AS tc', - 'JOIN information_schema.key_column_usage AS kcu', - ' ON tc.constraint_name = kcu.constraint_name', - 'JOIN information_schema.constraint_column_usage AS ccu', - ' ON ccu.constraint_name = tc.constraint_name', - 'JOIN information_schema.referential_constraints AS cstr', - ' ON cstr.constraint_schema = tc.table_schema', - ' AND cstr.constraint_name = tc.constraint_name', - 'WHERE', - ' tc.table_schema = ?', - ' AND tc.table_name = ?', - ' AND kcu.column_name = ?'].join('\n'); - db.runSql(metaQuery, ['public', 'event_type', 'event_id'], this.callback); - }, - - 'with correct references': function(err, result) { - var rows = result.rows; - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.table_name, 'event'); - assert.equal(row.column_name, 'id'); - }, - - 'and correct rules': function(err, result) { - var rows = result.rows; - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.update_rule, 'RESTRICT'); - assert.equal(row.delete_rule, 'CASCADE'); - } - } - } - }).addBatch({ - 'insert': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function(err) { - db.insert('event', ['id','title'], [2,'title'], this.callback.bind(this, null)); - }.bind(this)); - }, - - 'with additional row' : function() { - db.runSql("SELECT * from event", function(err, data) { - assert.equal(data.rowCount, 1); - }); - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'insertWithSingleQuotes': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function(err) { - db.insert('event', ['id','title'], [2,"Bill's Mother's House"], this.callback.bind(this, null)); - }.bind(this)); - }, - - 'with additional row' : function() { - db.runSql("SELECT * from event", function(err, data) { - assert.equal(data.rowCount, 1); - }); - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'removeIndex': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addIndex('event', 'event_title', 'title', function(err) { - db.removeIndex('event_title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - 'has resulting index metadata': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); - }, - - 'without index': function(err, indexes) { - assert.isNotNull(indexes); - assert.equal(indexes.length, 1); // first index is primary key - } - }, - - teardown: function() { - db.dropTable('event', this.callback); - } - } - }).addBatch({ - 'createMigrationsTable': { - topic: function() { - db.createMigrationsTable(this.callback.bind(this, null)); - }, - - 'has migrations table': { - topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'has migrations table' : function(err, tables) { - assert.isNull(err); - assert.isNotNull(tables); - assert.equal(tables.length,1); - assert.equal(tables[0].getName(), 'migrations'); - }, - - 'that has columns':{ - topic:function(){ - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('migrations', this.callback); - }.bind(this)); - }, - - 'with names': function(err, columns){ - assert.isNotNull(columns); - assert.equal(columns.length, 3); - var column = findByName(columns, 'id'); - assert.equal(column.getName(), 'id'); - assert.equal(column.getDataType(), 'INTEGER'); - column = findByName(columns, 'name'); - assert.equal(column.getName(), 'name'); - assert.equal(column.getDataType(), 'CHARACTER VARYING'); - column = findByName(columns, 'run_on'); - assert.equal(column.getName(), 'run_on'); - assert.equal(column.getDataType(), 'TIMESTAMP WITHOUT TIME ZONE'); - } - } - }, - - teardown: function() { - db.dropTable('migrations', this.callback); - } - } - }).export(module); -}); - -function findByName(columns, name) { - for (var i = 0; i < columns.length; i++) { - if (columns[i].getName() === name) { - return columns[i]; - } - } - return null; -} diff --git a/new/driver/shadow_test.js b/test/driver/shadow_test.js similarity index 100% rename from new/driver/shadow_test.js rename to test/driver/shadow_test.js diff --git a/test/driver/sqlite3_test.js b/test/driver/sqlite3_test.js deleted file mode 100644 index f84ca0c7..00000000 --- a/test/driver/sqlite3_test.js +++ /dev/null @@ -1,455 +0,0 @@ -var fs = require('fs'); -var vows = require('vows'); -var assert = require('assert'); -var dbmeta = require('db-meta'); -var dataType = require('db-migrate-shared').dataType; -var driver = require('../../lib/driver'); - -var config = require('../db.config.json').sqlite3; - -var internals = {}; -internals.migrationTable = 'migrations'; - -vows.describe('sqlite3').addBatch({ - 'createTable': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true, notNull: true }, - str: { type: dataType.STRING, unique: true }, - txt: { type: dataType.TEXT, notNull: true, defaultValue: "foo" }, - intg: dataType.INTEGER, - rel: dataType.REAL, - dt: dataType.DATE_TIME, - bl: dataType.BOOLEAN - }, this.callback.bind(this, null, db)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'has resulting table metadata': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing the event table': function (err, tables) { - assert.isNull(err); - var table = findByName(tables, 'event'); - assert.isNotNull(table); - assert.equal(table.getName(), 'event'); - } - }, - - 'has column metadata for the event table': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with 7 columns': function (err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 7); - }, - - 'that has integer id column that is primary key, non-nullable, and auto increments': function (err, columns) { - var column = findByName(columns, 'id'); - assert.equal(column.getDataType(), 'INTEGER'); - assert.equal(column.isPrimaryKey(), true); - assert.equal(column.isNullable(), false); - assert.equal(column.isAutoIncrementing(), true); - }, - - 'that has text str column that is unique': function (err, columns) { - var column = findByName(columns, 'str'); - assert.equal(column.getDataType(), 'VARCHAR'); - assert.equal(column.isUnique(), true); - }, - - 'that has text txt column that is non-nullable': function (err, columns) { - var column = findByName(columns, 'txt'); - assert.equal(column.getDataType(), 'TEXT'); - assert.equal(column.isNullable(), false); -// assert.equal(column.getDefaultValue(), 'foo'); - }, - - 'that has integer intg column': function (err, columns) { - var column = findByName(columns, 'intg'); - assert.equal(column.getDataType(), 'INTEGER'); - assert.equal(column.isNullable(), true); - }, - - 'that has real rel column': function (err, columns) { - var column = findByName(columns, 'rel'); - assert.equal(column.getDataType(), 'REAL'); - assert.equal(column.isNullable(), true); - }, - - 'that has integer dt column': function (err, columns) { - var column = findByName(columns, 'dt'); - assert.equal(column.getDataType(), 'DATETIME'); - assert.equal(column.isNullable(), true); - }, - - 'that has boolean bl column': function (err, columns) { - var column = findByName(columns, 'bl'); - assert.equal(column.getDataType(), 'BOOLEAN'); - assert.equal(column.isNullable(), true); - } - } - } -}).addBatch({ - 'dropTable': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function (err) { - if (err) { - return this.callback(err); - } - db.dropTable('event', this.callback.bind(this, null, db)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'has table metadata': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing no tables': function (err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 1); - } - } - } - }).addBatch({ - 'renameTable': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function () { - db.renameTable('event', 'functions', this.callback.bind(this, null, db)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'has table metadata': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); - }, - - 'containing the functions table': function (err, tables) { - assert.isNotNull(tables); - var table = findByName(tables, 'functions'); - assert.equal(table.getName(), 'functions'); - assert.isNull(findByName(tables, 'event')); - } - } - } - }).addBatch({ - 'addColumn': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function () { - db.addColumn('event', 'title', 'string', this.callback.bind(this, null, db)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'has column metadata': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); - }, - - 'with additional title column': function (err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 2); - var column = findByName(columns, 'title'); - assert.equal(column.getName(), 'title'); - assert.equal(column.getDataType(), 'VARCHAR'); - } - } - } -// removeColumn -// renameColumn -// changeColumn - }).addBatch({ - 'addIndex': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.addIndex('event', 'event_title', 'title', this.callback.bind(this, null, db)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'has resulting index metadata': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); - }, - - 'with additional index': function (err, indexes) { - assert.isNotNull(indexes); - var index = findByName(indexes, 'event_title'); - assert.equal(index.getName(), 'event_title'); - assert.equal(index.getTableName(), 'event'); - assert.equal(index.getColumnName(), 'title'); - } - } - } - }).addBatch({ - 'insert': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.insert('event', ['id', 'title'], [2, 'title'], this.callback.bind(this, null, db)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'with additional row': function (db) { - db.all("SELECT * from event;", function (err, data) { - assert.equal(data.length, 1); - }); - } - } - }).addBatch({ - 'insertWithSingleQuotes': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.insert('event', ['id', 'title'], [2, "Bill's Mother's House"], this.callback.bind(this, null, db)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'with additional row': function (db) { - db.all("SELECT * from event;", function (err, data) { - assert.equal(data.length, 1); - }); - } - } - }).addBatch({ - 'removeIndex': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function (err) { - db.addIndex('event', 'event_title', 'title', function (err) { - db.removeIndex('event_title', this.callback.bind(this, null, db)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'has resulting index metadata': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); - }, - - 'without index': function (err, indexes) { - assert.isNotNull(indexes); - assert.equal(indexes.length, 0); - } - } - } - }).addBatch({ - 'removeIndexWithTableName': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function (err) { - db.addIndex('event', 'event_title', 'title', function (err) { - db.removeIndex('event', 'event_title', this.callback.bind(this, null, db)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'has resulting index metadata': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); - }, - - 'without index': function (err, indexes) { - assert.isNotNull(indexes); - assert.equal(indexes.length, 0); - } - } - } - }).addBatch({ - 'createMigrationsTable': { - topic: function () { - driver.connect(config, internals, function (err, db) { - db.createMigrationsTable(this.callback.bind(this, null, db)); - }.bind(this)); - }, - - teardown: function (db) { - db.close(function (err) { - fs.unlink(config.filename, this.callback); - }); - }, - - 'has migrations table': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback.bind(this)); - }.bind(this)); - }, - - 'has migrations table': function (err, tables) { - assert.isNull(err); - assert.isNotNull(tables); - assert.equal(tables.length, 2); - assert.equal(tables[0].getName(), 'migrations'); - }, - }, - - 'that has columns': { - topic: function (db) { - dbmeta('sqlite3', {connection: db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('migrations', this.callback); - }.bind(this)); - }, - - 'with names': function (err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 3); - var column = findByName(columns, 'id'); - assert.equal(column.getName(), 'id'); - assert.equal(column.getDataType(), 'INTEGER'); - column = findByName(columns, 'name'); - assert.equal(column.getName(), 'name'); - assert.equal(column.getDataType(), 'VARCHAR (255)'); - column = findByName(columns, 'run_on'); - assert.equal(column.getName(), 'run_on'); - assert.equal(column.getDataType(), 'DATETIME'); - } - } - } - }).export(module); - -function findByName(columns, name) { - for (var i = 0; i < columns.length; i++) { - if (columns[i].getName() === name) { - return columns[i]; - } - } - return null; -} diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 97d23094..bb7f6caa 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -1,107 +1,110 @@ -var vows = require('vows'); -var assert = require('assert'); -var fs = require('fs'); -var dbmUtil = require('db-migrate-shared').util; +var Code = require('code'); +var Lab = require('lab'); +var lab = exports.lab = Lab.script(); var DBMigrate = require('../../'); var path = require('path'); var cp = require('child_process'); +lab.experiment('api', function() { -var process_exit = process.exit, - argv = process.argv; + lab.test('force process exit after migrations have been run', + { parallel : true}, function(done, onCleanup) { -function restore() { + var process_exit = process.exit, + argv = process.argv, + called = false, + config = { cwd: __dirname }; - process.exit = process_exit; - process.argv = argv; -} + // register cleanup method and start preparing the test + onCleanup(teardown); + createMigration(function() { -vows.describe('api').addBatch({ - 'force process exit': { - topic: function() { + var dbmigrate = DBMigrate.getInstance(true, config); - process.argv = [ 'node', 'script' ]; - var called = false, - self = this, - config = { cwd: process.cwd() + '/test/integration' }; + dbmigrate.setConfigParam('force-exit', true); + dbmigrate.silence(true); - var api = DBMigrate.getInstance(true, config); - api.create( 'test', function() { - process.argv.push('up'); - process.exit = function(err) { + /** + * We have set force-exit above, this should end up in db-migrate + * executing process.exit on the final callback. + * Process.exit has been overwritten and will finally call validate. + * + * The test validation takes place in validate() + */ + dbmigrate.up(); + }); + /** + * Final validation after process.exit should have been called. + */ + function validate() { - var ret = called; - called = true; - - process.exit = process_exit; + Code.expect(called).to.be.true(); + done(); + } - if(err) - process.exit.apply(arguments); + /** + * Create a migration with the programatic API and overwrite process.exit. + */ + function createMigration(callback) { - if(!ret) - this.callback(false); - }.bind(this); + var api = DBMigrate.getInstance(true, config); + api.silence(true); - var dbmigrate = DBMigrate.getInstance(true, config, function(migrator) { + api.create( 'test', function() { + process.exit = function(err) { var ret = called; called = true; - migrator.driver.close(function() { - delete migrator.driver; - }); - process.exit = process_exit; - if(!ret) - this.callback(true); - }.bind(this)); - - dbmigrate.setConfigParam('force-exit', true); - dbmigrate.silence(true); + if(err) + process.exit.apply(arguments); + Code.expect(ret).to.be.false(); + validate(); + }; - dbmigrate.run(); - }.bind( this ) ); - }, + callback(); + } ); + } - teardown: function() { + function teardown(next) { - restore(); + process.exit = process_exit; + process.argv = argv; cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); - }, - - 'process exited after migrations have been run': function(called) { - - assert.isTrue(called); + return next(); } - } -}).addBatch({ - 'load config from parameter': { - topic: function() { - var options = { - env: 'dev', - cwd: process.cwd() + '/test/integration', - config: { - dev: { - driver: 'sqlite3', - filename: ':memory:' - }, - pg: { - driver: 'pg', - database: 'db_api_test' - } + }); + + lab.test('should load config from parameter', { parallel : true}, + function(done) { + + var options = { + env: 'dev', + cwd: process.cwd() + '/test/integration', + config: { + dev: { + driver: 'sqlite3', + filename: ':memory:' + }, + pg: { + driver: 'pg', + database: 'db_api_test' } - }; - var api = DBMigrate.getInstance(true, options); - return {options: options, api: api}; - }, - 'should load config from parameter': function(topic) { - var actual = topic.api.config; - var expected = topic.options.config; - expected.getCurrent = actual.getCurrent; - assert.deepEqual(actual, expected); - } - } -}).export(module); + } + }; + + var api = DBMigrate.getInstance(true, options); + var actual = api.config; + var expected = options.config; + + delete expected.getCurrent; + delete actual.getCurrent; + + Code.expect(actual).to.equal(expected); + done(); + }); +}); diff --git a/test/integration/create_test.js b/test/integration/create_test.js index 43a985e4..c8fbed87 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -1,5 +1,6 @@ -var vows = require('vows'); -var assert = require('assert'); +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'); @@ -20,173 +21,320 @@ function dbMigrate() { return cp.spawn('node', args, { cwd: __dirname }); } -vows.describe('create').addBatch({ - 'without a migration directory': { - topic: function() { +lab.experiment('create', function() { + + lab.experiment('without a migration directory', function() { + + var exitCode; + + lab.before(function(done) { wipeMigrations(function(err) { - assert.isNull(err); - dbMigrate('create', 'first migration').on('exit', this.callback); - }.bind(this)); - }, - 'does not cause an error': function(code) { - assert.isNull(code); - }, + Code.expect(err).to.be.null(); + dbMigrate('create', 'first migration').on('exit', + function(code) { + + exitCode = code; + done(); + }); + }); + }); + + lab.test('does not cause an error', { parallel: true }, + function(done) { + + Code.expect(exitCode).to.equal(0); + done(); + }); + + lab.test('will create a new migration directory', { parallel: true }, + function(done) { - 'will create a new migration directory': function(code) { var stats = fs.statSync(path.join(__dirname, 'migrations')); - assert.isTrue(stats.isDirectory()); - }, + Code.expect(stats.isDirectory()).to.be.true(); + done(); + }); + + lab.test('will create a new migration', { parallel: true }, + function(done) { - 'will create a new migration': function(code) { var files = fs.readdirSync(path.join(__dirname, 'migrations')); - assert.equal(files.length, 1); + Code.expect(files.length).to.equal(1); var file = files[0]; - assert.match(file, /first-migration\.js$/); - } - } -}).addBatch({ - 'with sql-file option set to true from config file' : { - topic: function() { - var configOption = path.join("--config=", __dirname, 'database_with_sql_file.json'); + Code.expect(file).to.match(/first-migration\.js$/); + done(); + }); + }); + + lab.experiment('with sql-file option set to true from config file', + function() { + + var exitCode; + + lab.before(function(done) { + + var configOption = path.join('--config=', __dirname, + 'database_with_sql_file.json'); + wipeMigrations(function(err) { - assert.isNull(err); - dbMigrate( 'create', 'second migration', configOption).on('exit', this.callback); - }.bind(this)); - }, - 'does not cause an error': function(code) { - assert.isNull(code); - }, - 'will create a new migration': function(code) { + + Code.expect(err).to.not.exist(); + dbMigrate( 'create', 'second migration', configOption).on('exit', + function(code) { + + exitCode = code; + done(); + }); + }); + }); + + lab.test('does not cause an error', { parallel: true }, function(done) { + + Code.expect(exitCode).to.equal(0); + done(); + }); + + lab.test('will create a new migration', { parallel: true }, + function(done) { + var files = fs.readdirSync(path.join(__dirname, 'migrations')); for (var i = 0; i', 8); - assert.equal(actual, '>>prompt'); - }, - - 'should apply no left padding if already equal to the total length': function() { - var actual = util.lpad('>>prompt', '>', 8); - assert.equal(actual, '>>prompt'); - }, - - 'should apply no left padding if already greater than the total length': function() { - var actual = util.lpad('>>>prompt', '>', 8); - assert.equal(actual, '>>>prompt'); - }, - - 'should be apple to pad numbers': function() { - var actual = util.lpad(12, '>', 4); - assert.equal(actual, '>>12'); - }, - - 'should be apple to pad using numbers': function() { - var actual = util.lpad(12, 0, 4); - assert.equal(actual, '0012'); - } - } -}).export(module); +lab.experiment('util', { parallel: true }, function() { + + lab.experiment('lpad', { parallel: true }, lpad); +}); + +function lpad() { + + lab.test('should left pad the number of characters to equal the total length', + { parallel: true }, function(done) { + + var actual = util.lpad('prompt', '>', 8); + Code.expect(actual).to.equal('>>prompt'); + + done(); + }); + + lab.test('should apply no left padding if already equal to the total length', + { parallel: true }, function(done) { + + var actual = util.lpad('>>prompt', '>', 8); + Code.expect(actual).to.equal('>>prompt'); + + done(); + }); + + lab.test('should apply no left padding if already greater than the total ' + + 'length', { parallel: true }, function(done) { + + var actual = util.lpad('>>>prompt', '>', 8); + Code.expect(actual).to.equal('>>>prompt'); + + done(); + }); + + lab.test('should be apple to pad numbers', + { parallel: true }, function(done) { + + var actual = util.lpad(12, '>', 4); + Code.expect(actual).to.equal('>>12'); + + done(); + }); + + lab.test('should be apple to pad using numbers', + { parallel: true }, function(done) { + + var actual = util.lpad(12, 0, 4); + Code.expect(actual).to.equal('0012'); + + done(); + }); +} From 7ed971aa8727610e01ea5f310ba228f477934963 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 30 Sep 2016 18:47:57 +0200 Subject: [PATCH 324/412] refactor(cleanup): cleanup package.json and add db.config.ci back --- Makefile | 6 +++--- package.json | 15 +++------------ test/db.config.ci | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 test/db.config.ci diff --git a/Makefile b/Makefile index b37f6777..df4c14fd 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ test: - @node node_modules/lab/bin/lab new -I verbose,dryRun --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -I verbose,dryRun --coverage-exclude lib/transitions test-cov: - @node node_modules/lab/bin/lab new -t 75 -I verbose,dryRun --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -t 75 -I verbose,dryRun --coverage-exclude lib/transitions test-cov-html: - @node node_modules/lab/bin/lab new -r html -o coverage.html -I verbose,dryRun --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -r html -o coverage.html -I verbose,dryRun --coverage-exclude lib/transitions .PHONY: test test-cov test-cov-html diff --git a/package.json b/package.json index c3767be1..1089c286 100644 --- a/package.json +++ b/package.json @@ -61,22 +61,13 @@ "tunnel-ssh": "^4.0.0" }, "devDependencies": { - "code": "^3.0.1", - "db-meta": "~0.4.1", + "code": "^4.0.0", "db-migrate-base": "^1.2.5", - "db-migrate-mongodb": "^1.1.4", - "db-migrate-mysql": "^1.1.7", - "db-migrate-pg": "^0.1.10", - "db-migrate-sqlite3": "^0.1.6", - "lab": "^10.9.0", - "mysql": "^2.10.2", - "pg": "^6.1.0", + "lab": "^11.1.0", "proxyquire": "^1.4.0", "rimraf": "~2.5.0", "sinon": "^1.17.3", - "sinon-as-promised": "^4.0.2", - "sqlite3": "^3.1.1", - "vows": "0.8.0" + "sinon-as-promised": "^4.0.2" }, "scripts": { "test": "make test-cov" diff --git a/test/db.config.ci b/test/db.config.ci new file mode 100644 index 00000000..3a6cc4fc --- /dev/null +++ b/test/db.config.ci @@ -0,0 +1,21 @@ +{ + "mysql": { + "database": "db_migrate_test", + "user": "root", + "driver": "mysql" + }, + "pg": { + "driver": "pg", + "database": "db_migrate_test", + "username": "postgres" + }, + "sqlite3": { + "driver": "sqlite3", + "filename": "test.db" + }, + "mongodb": { + "driver": "mongodb", + "host": "localhost", + "database": "db_migrate_test" + } +} From 5756da82e4052923980c03a4d55318cf9f0dbe2b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 30 Sep 2016 18:52:48 +0200 Subject: [PATCH 325/412] chore(ci): exclude interfaces --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index df4c14fd..33ba11ab 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ test: - @node node_modules/lab/bin/lab -I verbose,dryRun --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions test-cov: - @node node_modules/lab/bin/lab -t 75 -I verbose,dryRun --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -t 70 -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions test-cov-html: - @node node_modules/lab/bin/lab -r html -o coverage.html -I verbose,dryRun --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -r html -o coverage.html -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions .PHONY: test test-cov test-cov-html From 7fc8e5aa9cd7ad9ecdec2fea7660a106b07a7027 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 30 Sep 2016 19:03:00 +0200 Subject: [PATCH 326/412] chore(ci): Readd missing dependencies --- Makefile | 2 +- package.json | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 33ba11ab..2dde1658 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ test: @node node_modules/lab/bin/lab -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions test-cov: - @node node_modules/lab/bin/lab -t 70 -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -t 66 -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions test-cov-html: @node node_modules/lab/bin/lab -r html -o coverage.html -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions diff --git a/package.json b/package.json index 1089c286..2e20d50d 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,8 @@ "devDependencies": { "code": "^4.0.0", "db-migrate-base": "^1.2.5", + "db-migrate-mysql": "^1.1.7", + "db-migrate-sqlite3": "^0.1.9", "lab": "^11.1.0", "proxyquire": "^1.4.0", "rimraf": "~2.5.0", From 68de8447b33a410b461e7fb13c1ef22ac004dc95 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 4 Oct 2016 15:14:42 +0200 Subject: [PATCH 327/412] chore(test): Add Test for privateKey param on shh tunnel --- test/driver/index_test.js | 79 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/test/driver/index_test.js b/test/driver/index_test.js index 530ab6ad..d2c7876d 100644 --- a/test/driver/index_test.js +++ b/test/driver/index_test.js @@ -1,4 +1,4 @@ -var proxyquire = require('proxyquire'); +var proxyquire = require('proxyquire').noPreserveCache(); var sinon = require('sinon'); var Code = require('code'); var Lab = require('lab'); @@ -41,6 +41,7 @@ lab.experiment('index', function() { // Set up stubs/spies to verify correct flow var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); var tunnelStub = sinon.stub().callsArg(1); + var index = proxyquire('../../lib/driver/index', { 'tunnel-ssh': tunnelStub, './mysql': driver @@ -137,4 +138,80 @@ lab.experiment('index', function() { done(); } }); + + lab.test('privateKey gets set as expected', + function(done, cleanup) { + + // Ensure that require gets a new copy of the module for each test + delete require.cache[require.resolve('db-migrate-mysql')]; + var driver = require('db-migrate-mysql'); + var fs = { readFileSync: sinon.stub().returns('sshkey') }; + + // Set up stubs/spies to verify correct flow + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); + var tunnelStub = sinon.stub().callsArg(1); + + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + 'fs': fs, + './mysql': driver, + }); + + //register clean up + cleanup(function(next) { + + driverSpy.restore(); + + delete require.cache[require.resolve('tunnel-ssh')]; + delete require.cache[require.resolve('db-migrate-mysql')]; + next(); + }); + + validDbConfigWithTunnel.tunnel.privateKeyPath = '/test/key'; + + index.connect( + validDbConfigWithTunnel, + {}, + indexConnectCallback(tunnelStub, driverSpy, validate) + ); + + function validate(err, db, tunnelStub, driverSpy) { + var expectedTunnelConfig = { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort', + privateKeyPath: '/test/key', + dstHost: '127.0.0.1', + dstPort: 'localPort', + privateKey: 'sshkey' + }; + var expectedDbConfig = { + driver: 'mysql', + host: '127.0.0.1', + port: 'localPort', + tunnel: { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort', + privateKeyPath: '/test/key' + } + }; + + + Code.expect(err).to.be.null(); + Code.expect(db).to.not.be.null(); + Code.expect( + fs.readFileSync.withArgs(validDbConfigWithTunnel.tunnel.privateKeyPath) + .calledOnce + ).to.be.true(); + Code.expect( + tunnelStub.withArgs(expectedTunnelConfig).calledOnce + ).to.be.true(); + Code.expect( + driverSpy.withArgs(expectedDbConfig).calledOnce + ).to.be.true(); + + done(); + } + }); }); From b681257cefe2c35e743d5173d3afc95c610b0f0a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 10 Oct 2016 14:17:28 +0200 Subject: [PATCH 328/412] fix(resolve): Check if resolved version has plugin support fix #425 --- bin/db-migrate | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bin/db-migrate b/bin/db-migrate index 403cb68e..39e880e2 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -33,9 +33,12 @@ resolve( 'db-migrate', { } dbmigrate = DBMigrate.getInstance(); - dbmigrate.registerAPIHook() - .then( function() { + if(dbmigrate.registerAPIHook) + dbmigrate.registerAPIHook() + .then( function() { + dbmigrate.run(); + } ); + else dbmigrate.run(); - } ); } ); From 43c4ca22c584d9c10e6a0509ee5613ddd402bc4b Mon Sep 17 00:00:00 2001 From: stafford Date: Mon, 21 Nov 2016 13:37:44 +1100 Subject: [PATCH 329/412] log error on undefined stack --- api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.js b/api.js index e66a1cdc..7fff31d5 100644 --- a/api.js +++ b/api.js @@ -136,7 +136,7 @@ function dbmigrate(plugins, isModule, options, callback) { function registerEvents() { process.on('uncaughtException', function(err) { - log.error(err.stack); + log.error(err.stack || err); process.exit(1); }); From 3e06b1c3f5d14bbcb0beaa1cecb8aa512ec9e68a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 30 Nov 2016 15:55:43 +0100 Subject: [PATCH 330/412] refactor(api): cleanup information and added commentary --- api.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api.js b/api.js index 7fff31d5..ed3e079d 100644 --- a/api.js +++ b/api.js @@ -165,6 +165,11 @@ dbmigrate.prototype = { return true; }, + /** + * Registers and initializes hooks. + * + * @returns Promise + */ registerAPIHook: function(callback) { var plugins = this.internals.plugins; @@ -550,7 +555,7 @@ function setDefaultArgv(internals, isModule) { 'ignore-completed-migrations': false }) .usage( - 'Usage: db-migrate [up|down|reset|sync|create|db|seed|transition] ' + + 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + '[[dbname/]migrationName|all] [options]' ) From b5e7c80a833c4e8eb0ef24838d810d393015a2c9 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 30 Nov 2016 16:53:48 +0100 Subject: [PATCH 331/412] feat(config): add rc style configs fixes #308 fixes #406 --- .gitignore | 1 + .npmignore | 1 + api.js | 10 ++++++++-- package.json | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 374cb87e..a9a6cc35 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ database.json *.sublime-project *.sublime-workspace archive +.db-migraterc # Vim swap files .*.sw[a-z] diff --git a/.npmignore b/.npmignore index 0e6e098f..726ac2d3 100644 --- a/.npmignore +++ b/.npmignore @@ -8,3 +8,4 @@ database.json *.sublime-project *.sublime-workspace archive +.db-migraterc diff --git a/api.js b/api.js index ed3e079d..9f485631 100644 --- a/api.js +++ b/api.js @@ -540,6 +540,9 @@ dbmigrate.prototype = { function setDefaultArgv(internals, isModule) { + var rc = require('rc'); + var deepExtend = require('deep-extend'); + internals.argv = optimist .default({ verbose: false, @@ -558,7 +561,6 @@ function setDefaultArgv(internals, isModule) { 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + '[[dbname/]migrationName|all] [options]' ) - .describe('env', 'The environment to run the migrations under (dev, test, prod).') .alias('e', 'env') @@ -636,6 +638,8 @@ function setDefaultArgv(internals, isModule) { var plugins = internals.plugins; var plugin = plugins.hook('init:cli:config:hook'); + var _config = internals.argv.argv.config; + if(plugin) { plugin.forEach(function(plugin) { @@ -648,7 +652,9 @@ function setDefaultArgv(internals, isModule) { }); } - internals.argv = internals.argv.argv; + internals.argv = deepExtend(internals.argv.argv, rc('db-migrate', {})); + internals.argv.rcconfig = internals.argv.config; + internals.argv.config = _config; if (internals.argv.version) { console.log(internals.dbm.version); diff --git a/package.json b/package.json index 2e20d50d..f2af0f62 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "balanced-match": "^0.4.2", "bluebird": "^3.1.1", "db-migrate-shared": "^1.1.2", + "deep-extend": "^0.4.1", "dotenv": "^2.0.0", "final-fs": "^1.6.0", "inflection": "^1.10.0", @@ -56,6 +57,7 @@ "parse-database-url": "~0.3.0", "pkginfo": "^0.4.0", "prompt": "^1.0.0", + "rc": "^1.1.6", "resolve": "^1.1.6", "semver": "^5.3.0", "tunnel-ssh": "^4.0.0" From d1c81c6f6fdd5055dab79d0d2f6ac67ea3cf0367 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 30 Nov 2016 18:59:27 +0100 Subject: [PATCH 332/412] refactor(api): refactor tests and make api.js more modular --- api.js | 258 ++------------------------ lib/commands/down.js | 34 ++++ lib/commands/helper/assert.js | 17 ++ lib/commands/helper/migration-hook.js | 6 + lib/commands/on-complete.js | 34 ++++ lib/commands/set-default-argv.js | 151 +++++++++++++++ lib/commands/sync.js | 40 ++++ lib/commands/up.js | 40 ++++ test/integration/api_test.js | 81 ++++---- 9 files changed, 379 insertions(+), 282 deletions(-) create mode 100644 lib/commands/down.js create mode 100644 lib/commands/helper/assert.js create mode 100644 lib/commands/helper/migration-hook.js create mode 100644 lib/commands/on-complete.js create mode 100644 lib/commands/set-default-argv.js create mode 100644 lib/commands/sync.js create mode 100644 lib/commands/up.js diff --git a/api.js b/api.js index 9f485631..b5c44213 100644 --- a/api.js +++ b/api.js @@ -8,6 +8,7 @@ var log = require('db-migrate-shared').log; var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line var dotenv = require('dotenv'); var Promise = Promise; +var onComplete = require('./lib/commands/on-complete.js'); function registerPluginLoader(plugins) { @@ -72,6 +73,8 @@ var APIHooks = { function dbmigrate(plugins, isModule, options, callback) { + var setDefaultArgv = require('./lib/commands/set-default-argv.js'); + this.internals = { onComplete: onComplete, @@ -244,6 +247,8 @@ dbmigrate.prototype = { */ up: function(specification, opts, callback) { + var executeUp = require('./lib/commands/up.js'); + if (arguments.length > 0) { if (typeof(specification) === 'string') { @@ -281,6 +286,8 @@ dbmigrate.prototype = { */ down: function(specification, opts, callback) { + var executeDown = require('./lib/commands/down.js'); + if (arguments.length > 0) { if (typeof(specification) === 'number') { @@ -538,155 +545,6 @@ dbmigrate.prototype = { }; -function setDefaultArgv(internals, isModule) { - - var rc = require('rc'); - var deepExtend = require('deep-extend'); - - internals.argv = optimist - .default({ - verbose: false, - table: 'migrations', - 'seeds-table': 'seeds', - 'force-exit': false, - 'sql-file': false, - 'non-transactional': false, - config: internals.configFile || internals.cwd + '/database.json', - 'migrations-dir': internals.cwd + '/migrations', - 'vcseeder-dir': internals.cwd + '/VCSeeder', - 'staticseeder-dir': internals.cwd + '/Seeder', - 'ignore-completed-migrations': false - }) - .usage( - 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + - '[[dbname/]migrationName|all] [options]' - ) - .describe('env', - 'The environment to run the migrations under (dev, test, prod).') - .alias('e', 'env') - .string('e') - - .describe('migrations-dir', 'The directory containing your migration files.') - .alias('m', 'migrations-dir') - .string('m') - - .describe('count', 'Max number of migrations to run.') - .alias('c', 'count') - .string('c') - - .describe('dry-run', 'Prints the SQL but doesn\'t run it.') - .boolean('dry-run') - - .describe('force-exit', 'Forcibly exit the migration process on completion.') - .boolean('force-exit') - - .describe('verbose', 'Verbose mode.') - .alias('v', 'verbose') - .boolean('v') - - .alias('h', 'help') - .alias('h', '?') - .boolean('h') - - .describe('version', 'Print version info.') - .alias('i', 'version') - .boolean('version') - - .describe('config', 'Location of the database.json file.') - .string('config') - - .describe('sql-file', - 'Automatically create two sql files for up and down statements in ' + - '/sqls and generate the javascript code that loads them.' - ) - .boolean('sql-file') - - .describe('coffee-file', 'Create a coffeescript migration file') - .boolean('coffee-file') - .describe('ignore-on-init', - 'Create files that will run only if ignore-on-init in the env is set ' + - 'to false (currently works onlt with SQL)' - ).boolean('ignore-on-init') - - .describe('migration-table', - 'Set the name of the migration table, which stores the migration history.' - ) - .alias('table', 'migration-table') - .alias('t', 'table') - .string('t') - - .describe('seeds-table', - 'Set the name of the seeds table, which stores the seed history.') - .string('seeds-table') - - .describe('vcseeder-dir', - 'Set the path to the Version Controlled Seeder directory.') - .string('vcseeder-dir') - - .describe('staticseeder-dir', 'Set the path to the Seeder directory.') - .string('staticseeder-dir') - - .describe('non-transactional', 'Explicitly disable transactions') - .boolean('non-transactional') - - .describe('ignore-completed-migrations', 'Start at the first migration') - .boolean('ignore-completed-migrations') - - .describe('log-level', 'Set the log-level, for example sql|warn') - .string('log-level'); - - - var plugins = internals.plugins; - var plugin = plugins.hook('init:cli:config:hook'); - var _config = internals.argv.argv.config; - - if(plugin) { - - plugin.forEach(function(plugin) { - - var configs = plugin['init:cli:config:hook'](); - if(!configs) return; - - //hook not yet used, we look into migrating away from optimist first - return; - }); - } - - internals.argv = deepExtend(internals.argv.argv, rc('db-migrate', {})); - internals.argv.rcconfig = internals.argv.config; - internals.argv.config = _config; - - if (internals.argv.version) { - console.log(internals.dbm.version); - process.exit(0); - } - - if (!isModule && (internals.argv.help || internals.argv._.length === 0)) { - optimist.showHelp(); - process.exit(1); - } - - if (internals.argv['log-level']) { - - log.setLogLevel(internals.argv['log-level']); - } - - internals.ignoreCompleted = internals.argv['ignore-completed-migrations']; - internals.migrationTable = internals.argv.table; - internals.seedTable = internals.argv['seeds-table']; - internals.matching = ''; - internals.verbose = internals.argv.verbose; - global.verbose = internals.verbose; - internals.notransactions = internals.argv['non-transactional']; - internals.dryRun = internals.argv['dry-run']; - global.dryRun = internals.dryRun; - - if (internals.dryRun) { - log.info('dry run'); - } - -} - function createMigrationDir(dir, callback) { fs.stat(dir, function(err) { if (err) { @@ -891,42 +749,6 @@ function migrationHook(internals) { return Migration.registerHook(internals.plugins, internals); } -function executeUp(internals, config, callback) { - - migrationHook(internals) - .then(function() { - - var Migrator = require('./lib/migrator.js'); - var index = require('./connect'); - - if (!internals.argv.count) { - internals.argv.count = Number.MAX_VALUE; - } - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Migrator, function(err, migrator) { - assert.ifError(err); - - if (internals.locTitle) - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], - internals.locTitle); - else - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); - - internals.migrationsDir = migrator.migrationsDir; - - migrator.driver.createMigrationsTable(function(err) { - assert.ifError(err); - log.verbose('migration table created'); - - migrator.up(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); - }); - }); - }); -} - function executeSync(internals, config, callback) { migrationHook(internals) @@ -963,36 +785,6 @@ function executeSync(internals, config, callback) { }); } -function executeDown(internals, config, callback) { - - migrationHook(internals) - .then(function() { - - var Migrator = require('./lib/migrator.js'); - var index = require('./connect'); - - if (!internals.argv.count) { - log.info('Defaulting to running 1 down migration.'); - internals.argv.count = 1; - } - - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Migrator, function(err, migrator) { - assert.ifError(err); - - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); - - migrator.driver.createMigrationsTable(function(err) { - assert.ifError(err); - migrator.down(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); - }); - }); - }); -} - function executeDB(internals, config, callback) { var index = require('./connect'); @@ -1119,38 +911,6 @@ function executeUndoSeed(internals, config, callback) { }); } -function onComplete(migrator, internals, callback, originalErr) { - - if (typeof(callback) !== 'function') { - originalErr = originalErr || callback; - } - - migrator.driver.close(function(err) { - if ((err || originalErr) && typeof(callback) === 'function') { - - callback({ - err: err, - originalErr: originalErr - }); - return; - } else { - - assert.ifError(originalErr); - assert.ifError(err); - log.info('Done'); - } - - if (internals.argv['force-exit']) { - log.verbose('Forcing exit'); - process.exit(0); - } - - if (typeof(callback) === 'function') { - callback(); - } - }); -} - function transition(internals) { require('./lib/transitions/transitioner.js')(internals); @@ -1216,8 +976,12 @@ function run(internals, config) { } if (action === 'up') { + + var executeUp = require('./lib/commands/up.js'); executeUp(internals, config); } else { + + var executeDown = require('./lib/commands/down.js'); executeDown(internals, config); } break; diff --git a/lib/commands/down.js b/lib/commands/down.js new file mode 100644 index 00000000..dbe3f657 --- /dev/null +++ b/lib/commands/down.js @@ -0,0 +1,34 @@ +var path = require('path'); +var log = require('db-migrate-shared').log; +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'); + + if (!internals.argv.count) { + log.info('Defaulting to running 1 down migration.'); + internals.argv.count = 1; + } + + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, 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)); + }); + }); + }); +}; diff --git a/lib/commands/helper/assert.js b/lib/commands/helper/assert.js new file mode 100644 index 00000000..ce648c67 --- /dev/null +++ b/lib/commands/helper/assert.js @@ -0,0 +1,17 @@ + +module.exports = function(err, callback) { + if (err) { + + if (typeof(callback) === 'function') { + + callback(err); + return false; + } else { + + assert.ifError(err); + return false; + } + } + + return true; +}; diff --git a/lib/commands/helper/migration-hook.js b/lib/commands/helper/migration-hook.js new file mode 100644 index 00000000..f9ed96ff --- /dev/null +++ b/lib/commands/helper/migration-hook.js @@ -0,0 +1,6 @@ + +module.exports = function(internals) { + + var Migration = require('../../migration.js'); + return Migration.registerHook(internals.plugins, internals); +}; diff --git a/lib/commands/on-complete.js b/lib/commands/on-complete.js new file mode 100644 index 00000000..b064231a --- /dev/null +++ b/lib/commands/on-complete.js @@ -0,0 +1,34 @@ +var assert = require('assert'); +var log = require('db-migrate-shared').log; + +module.exports = function(migrator, internals, callback, originalErr) { + if (typeof(callback) !== 'function') { + originalErr = originalErr || callback; + } + + migrator.driver.close(function(err) { + + if ((err || originalErr) && typeof(callback) === 'function') { + + callback({ + err: err, + originalErr: originalErr + }); + return; + } else { + + assert.ifError(originalErr); + assert.ifError(err); + log.info('Done'); + } + + if (internals.argv['force-exit']) { + log.verbose('Forcing exit'); + return process.exit(0); + } + + if (typeof(callback) === 'function') { + callback(); + } + }); +}; diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js new file mode 100644 index 00000000..bf45b635 --- /dev/null +++ b/lib/commands/set-default-argv.js @@ -0,0 +1,151 @@ +var optimist = require('optimist'); +var log = require('db-migrate-shared').log; + +module.exports = function(internals, isModule) { + + var rc = require('rc'); + var deepExtend = require('deep-extend'); + + internals.argv = optimist + .default({ + verbose: false, + table: 'migrations', + 'seeds-table': 'seeds', + 'force-exit': false, + 'sql-file': false, + 'non-transactional': false, + config: internals.configFile || internals.cwd + '/database.json', + 'migrations-dir': internals.cwd + '/migrations', + 'vcseeder-dir': internals.cwd + '/VCSeeder', + 'staticseeder-dir': internals.cwd + '/Seeder', + 'ignore-completed-migrations': false + }) + .usage( + 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + + '[[dbname/]migrationName|all] [options]' + ) + .describe('env', + 'The environment to run the migrations under (dev, test, prod).') + .alias('e', 'env') + .string('e') + + .describe('migrations-dir', 'The directory containing your migration files.') + .alias('m', 'migrations-dir') + .string('m') + + .describe('count', 'Max number of migrations to run.') + .alias('c', 'count') + .string('c') + + .describe('dry-run', 'Prints the SQL but doesn\'t run it.') + .boolean('dry-run') + + .describe('force-exit', 'Forcibly exit the migration process on completion.') + .boolean('force-exit') + + .describe('verbose', 'Verbose mode.') + .alias('v', 'verbose') + .boolean('v') + + .alias('h', 'help') + .alias('h', '?') + .boolean('h') + + .describe('version', 'Print version info.') + .alias('i', 'version') + .boolean('version') + + .describe('config', 'Location of the database.json file.') + .string('config') + + .describe('sql-file', + 'Automatically create two sql files for up and down statements in ' + + '/sqls and generate the javascript code that loads them.' + ) + .boolean('sql-file') + + .describe('coffee-file', 'Create a coffeescript migration file') + .boolean('coffee-file') + .describe('ignore-on-init', + 'Create files that will run only if ignore-on-init in the env is set ' + + 'to false (currently works onlt with SQL)' + ).boolean('ignore-on-init') + + .describe('migration-table', + 'Set the name of the migration table, which stores the migration history.' + ) + .alias('table', 'migration-table') + .alias('t', 'table') + .string('t') + + .describe('seeds-table', + 'Set the name of the seeds table, which stores the seed history.') + .string('seeds-table') + + .describe('vcseeder-dir', + 'Set the path to the Version Controlled Seeder directory.') + .string('vcseeder-dir') + + .describe('staticseeder-dir', 'Set the path to the Seeder directory.') + .string('staticseeder-dir') + + .describe('non-transactional', 'Explicitly disable transactions') + .boolean('non-transactional') + + .describe('ignore-completed-migrations', 'Start at the first migration') + .boolean('ignore-completed-migrations') + + .describe('log-level', 'Set the log-level, for example sql|warn') + .string('log-level'); + + + var plugins = internals.plugins; + var plugin = plugins.hook('init:cli:config:hook'); + var _config = internals.argv.argv.config; + + if(plugin) { + + plugin.forEach(function(plugin) { + + var configs = plugin['init:cli:config:hook'](); + if(!configs) return; + + //hook not yet used, we look into migrating away from optimist first + return; + }); + } + + internals.argv = deepExtend(internals.argv.argv, rc('db-migrate', {})); + internals.argv.rcconfig = internals.argv.config; + internals.argv.config = _config; + + if (internals.argv.version) { + console.log(internals.dbm.version); + process.exit(0); + } + + if (!isModule && (internals.argv.help || internals.argv._.length === 0)) { + optimist.showHelp(); + process.exit(1); + } + + if (internals.argv['log-level']) { + + log.setLogLevel(internals.argv['log-level']); + } + + internals.ignoreCompleted = internals.argv['ignore-completed-migrations']; + internals.migrationTable = internals.argv.table; + internals.seedTable = internals.argv['seeds-table']; + internals.matching = ''; + internals.verbose = internals.argv.verbose; + global.verbose = internals.verbose; + internals.notransactions = internals.argv['non-transactional']; + internals.dryRun = internals.argv['dry-run']; + global.dryRun = internals.dryRun; + + if (internals.dryRun) { + log.info('dry run'); + } + +}; diff --git a/lib/commands/sync.js b/lib/commands/sync.js new file mode 100644 index 00000000..81740b0d --- /dev/null +++ b/lib/commands/sync.js @@ -0,0 +1,40 @@ +var path = require('path'); +var log = require('db-migrate-shared').log; +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'); + + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, 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']); + + internals.migrationsDir = migrator.migrationsDir; + + migrator.driver.createMigrationsTable(function(err) { + if(!assert(err)) return; + log.verbose('migration table created'); + + migrator.sync(internals.argv, internals.onComplete.bind(this, + migrator, internals, callback)); + }); + }); + }); +}; diff --git a/lib/commands/up.js b/lib/commands/up.js new file mode 100644 index 00000000..8854d5f6 --- /dev/null +++ b/lib/commands/up.js @@ -0,0 +1,40 @@ +var path = require('path'); +var log = require('db-migrate-shared').log; +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'); + + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, 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']); + + internals.migrationsDir = migrator.migrationsDir; + + migrator.driver.createMigrationsTable(function(err) { + if(!assert(err, callback)) return; + log.verbose('migration table created'); + + migrator.up(internals.argv, internals.onComplete.bind(this, + migrator, internals, callback)); + }); + }); + }); +}; diff --git a/test/integration/api_test.js b/test/integration/api_test.js index bb7f6caa..1314e995 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -1,9 +1,8 @@ var Code = require('code'); var Lab = require('lab'); var lab = exports.lab = Lab.script(); -var DBMigrate = require('../../'); -var path = require('path'); -var cp = require('child_process'); +var sinon = require('sinon'); +var proxyquire = require('proxyquire').noPreserveCache(); lab.experiment('api', function() { @@ -17,22 +16,23 @@ lab.experiment('api', function() { // register cleanup method and start preparing the test onCleanup(teardown); - createMigration(function() { + overwriteExit(); - var dbmigrate = DBMigrate.getInstance(true, config); + var dbmigrate = stubApiInstance(true, { + './lib/commands/up.js': upStub + }, config); - dbmigrate.setConfigParam('force-exit', true); - dbmigrate.silence(true); + dbmigrate.setConfigParam('force-exit', true); + dbmigrate.silence(true); - /** - * We have set force-exit above, this should end up in db-migrate - * executing process.exit on the final callback. - * Process.exit has been overwritten and will finally call validate. - * - * The test validation takes place in validate() - */ - dbmigrate.up(); - }); + /** + * We have set force-exit above, this should end up in db-migrate + * executing process.exit on the final callback. + * Process.exit has been overwritten and will finally call validate. + * + * The test validation takes place in validate() + */ + dbmigrate.up(); /** * Final validation after process.exit should have been called. @@ -43,38 +43,39 @@ lab.experiment('api', function() { done(); } + function upStub(internals) { + + internals.onComplete({ + driver: { + close: sinon.stub().callsArg(0) + } + }, internals); + } + /** * Create a migration with the programatic API and overwrite process.exit. */ - function createMigration(callback) { + function overwriteExit() { - var api = DBMigrate.getInstance(true, config); - api.silence(true); + process.exit = function(err) { - api.create( 'test', function() { - process.exit = function(err) { + var ret = called; + called = true; - var ret = called; - called = true; + process.exit = process_exit; - process.exit = process_exit; + if(err) + process.exit.apply(arguments); - if(err) - process.exit.apply(arguments); - - Code.expect(ret).to.be.false(); - validate(); - }; - - callback(); - } ); + Code.expect(ret).to.be.false(); + validate(); + }; } function teardown(next) { process.exit = process_exit; process.argv = argv; - cp.exec('rm -r ' + path.join(__dirname, 'migrations'), this.callback); return next(); } }); @@ -97,7 +98,7 @@ lab.experiment('api', function() { } }; - var api = DBMigrate.getInstance(true, options); + var api = stubApiInstance(true, {}, options); var actual = api.config; var expected = options.config; @@ -108,3 +109,13 @@ lab.experiment('api', function() { done(); }); }); + +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), + plugins = {}; + + return new mod(plugins, isModule, options, callback); +}; From a2522a2c8a6a9517cd582dce994913f32f59f1b4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 30 Nov 2016 19:02:13 +0100 Subject: [PATCH 333/412] fix(api): add missing reference to sync --- api.js | 40 ++++------------------------------------ 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/api.js b/api.js index b5c44213..ee321d75 100644 --- a/api.js +++ b/api.js @@ -322,6 +322,8 @@ dbmigrate.prototype = { */ sync: function(specification, opts, callback) { + var executeSync = require('./lib/commands/sync.js'); + if (arguments.length > 0) { if (typeof(specification) === 'string') { @@ -749,42 +751,6 @@ function migrationHook(internals) { return Migration.registerHook(internals.plugins, internals); } -function executeSync(internals, config, callback) { - - migrationHook(internals) - .then(function() { - - var Migrator = require('./lib/migrator.js'); - var index = require('./connect'); - - if (!internals.argv.count) { - internals.argv.count = Number.MAX_VALUE; - } - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Migrator, function(err, migrator) { - assert.ifError(err); - - if (internals.locTitle) - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'], - internals.locTitle); - else - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); - - internals.migrationsDir = migrator.migrationsDir; - - migrator.driver.createMigrationsTable(function(err) { - assert.ifError(err); - log.verbose('migration table created'); - - migrator.sync(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); - }); - }); - }); -} - function executeDB(internals, config, callback) { var index = require('./connect'); @@ -937,6 +903,8 @@ function run(internals, config) { break; case 'sync': + var executeSync = require('./lib/commands/sync.js'); + if (internals.argv._.length === 0) { log.error('Missing sync destination!'); From 11fef2912e8bd8f0962f86d63711e2ae465101a2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 30 Nov 2016 19:07:46 +0100 Subject: [PATCH 334/412] refactor(api): remove last output of postponed seeders --- api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.js b/api.js index ee321d75..e17930dc 100644 --- a/api.js +++ b/api.js @@ -995,7 +995,7 @@ function run(internals, config) { } else { - log.error('Invalid Action: Must be [up|down|create|reset|sync|seed|' + + log.error('Invalid Action: Must be [up|down|create|reset|sync|' + 'db|transition].'); optimist.showHelp(); process.exit(1); From 3f0bd0796f4b481c11f7fd0a7f9e0425c2e06317 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 30 Nov 2016 19:21:00 +0100 Subject: [PATCH 335/412] add test dummies for api --- test/integration/api_test.js | 44 +++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 1314e995..729f43db 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -4,7 +4,7 @@ var lab = exports.lab = Lab.script(); var sinon = require('sinon'); var proxyquire = require('proxyquire').noPreserveCache(); -lab.experiment('api', function() { +lab.experiment('api', { parallel: true }, function() { lab.test('force process exit after migrations have been run', { parallel : true}, function(done, onCleanup) { @@ -108,6 +108,48 @@ lab.experiment('api', function() { Code.expect(actual).to.equal(expected); done(); }); + + lab.test.skip('should do something', { parallel: true }, function(done) { + + var api = stubApiInstance(true, { + './lib/commands/up.js': upStub + }); + + api.up(); + + function upStub() { + + done(); + } + }); + + lab.test.skip('should do something', { parallel: true }, function(done) { + + var api = stubApiInstance(true, { + './lib/commands/down.js': downStub + }); + + api.down(); + + function downStub() { + + done(); + } + }); + + lab.test.skip('should do something', { parallel: true }, function(done) { + + var api = stubApiInstance(true, { + './lib/commands/sync.js': syncStub + }); + + api.sync(); + + function syncStub() { + + done(); + } + }); }); function stubApiInstance(isModule, stubs, options, callback) { From 85bde6de71a609449ffb8937eba6917b34582fa7 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 30 Nov 2016 23:14:20 +0100 Subject: [PATCH 336/412] add first programable api tests --- api.js | 7 +- test/integration/api_test.js | 126 +++++++++++++++++++++++++++-------- 2 files changed, 104 insertions(+), 29 deletions(-) diff --git a/api.js b/api.js index e17930dc..373b6a0f 100644 --- a/api.js +++ b/api.js @@ -95,8 +95,11 @@ function dbmigrate(plugins, isModule, options, callback) { dotenv.load({ silent: true }); - registerEvents(); + /* $lab:coverage:off$ */ + if(options && !options.throwUncatched) + registerEvents(); + /* $lab:coverage:on$ */ if (typeof(options) === 'object') { @@ -352,6 +355,8 @@ dbmigrate.prototype = { */ reset: function(scope, callback) { + var executeDown = require('./lib/commands/down.js'); + if (typeof(scope) === 'string') { this.internals.migrationMode = scope; diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 729f43db..2a60bffb 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -3,6 +3,7 @@ var Lab = require('lab'); var lab = exports.lab = Lab.script(); var sinon = require('sinon'); var proxyquire = require('proxyquire').noPreserveCache(); +var Promise = require('bluebird'); lab.experiment('api', { parallel: true }, function() { @@ -109,48 +110,112 @@ lab.experiment('api', { parallel: true }, function() { done(); }); - lab.test.skip('should do something', { parallel: true }, function(done) { - - var api = stubApiInstance(true, { - './lib/commands/up.js': upStub - }); + lab.test('should handle all up parameter variations properly', + { parallel: true }, function(done) { + + Promise.resolve([ + [], // promise + [sinon.spy()], + ['nameatargetmigration', sinon.spy()], // targeted migration + ['nameatargetmigration'], // promise targeted migration + [1, sinon.spy()], // targeted migration + [1], // promise targeted migration + ['nameatargetmigration', 'testscope', sinon.spy()], // scoped target + ['nameatargetmigration', 'testscope'], // promise scope target + [1, 'testscope', sinon.spy()], // scoped target + [1, 'testscope'] // promise scope target + ]) + .each(defaultExecParams('up')) + .each(spyCallback) + .asCallback(done); + }); - api.up(); + lab.test('should handle all down parameter variations properly', + { parallel: true }, function(done) { + + Promise.resolve([ + [], // promise + [sinon.spy()], + [1, sinon.spy()], // targeted migration + [1], // promise targeted migration + [1, 'testscope', sinon.spy()], // scoped target + [1, 'testscope'] // promise scope target + ]) + .each(defaultExecParams('down')) + .each(spyCallback) + .asCallback(done); + }); - function upStub() { + lab.test('should handle all reset parameter variations properly', + { parallel: true }, function(done) { + + Promise.resolve([ + [], // promise + [sinon.spy()], + ['testscope', sinon.spy()], // scoped target + ['testscope'] // promise scope target + ]) + .each(defaultExecParams('reset')) + .each(spyCallback) + .asCallback(done); + }); - done(); - } + lab.test('should handle all sync parameter variations properly', + { parallel: true }, function(done) { + + Promise.resolve([ + [], + ['nameatargetmigration', sinon.spy()], // targeted migration + ['nameatargetmigration'], // promise targeted migration + ['nameatargetmigration', 'testscope', sinon.spy()], // scoped target + ['nameatargetmigration', 'testscope'], // promise scope target + ]) + .each(defaultExecParams('sync')) + .each(spyCallback) + .asCallback(done); }); +}); - lab.test.skip('should do something', { parallel: true }, function(done) { +function defaultExecParams(method) { - var api = stubApiInstance(true, { - './lib/commands/down.js': downStub - }); + return function(args, index) { - api.down(); + var stubs = {}; + stubs['./lib/commands/' + method + '.js'] = stub; - function downStub() { + var api = stubApiInstance(true, stubs); - done(); - } - }); + return [ api[method].apply(api, args), args ]; - lab.test.skip('should do something', { parallel: true }, function(done) { + function stub(internals, config, callback) { - var api = stubApiInstance(true, { - './lib/commands/sync.js': syncStub - }); + if(typeof(args[0]) === 'string') { - api.sync(); + Code.expect(internals.argv.destination).to.equal(args[0]); + } else if(typeof(args[0]) === 'number') { - function syncStub() { + Code.expect(internals.argv.count).to.equal(args[0]); + } - done(); + if(typeof(args[1]) === 'string') { + + Code.expect(internals.migrationMode).to.equal(args[1]); + Code.expect(internals.matching).to.equal(args[1]); + } + + callback(); } - }); -}); + }; +} + +function spyCallback(api, args) { + + if(typeof(args[args.length - 1]) === 'function') { + + var spy = args[args.length - 1]; + Code.expect(spy.called).to.be.true(); + } +} function stubApiInstance(isModule, stubs, options, callback) { @@ -158,6 +223,11 @@ function stubApiInstance(isModule, stubs, options, callback) { delete require.cache[require.resolve('optimist')]; var mod = proxyquire('../../api.js', stubs), plugins = {}; + options = options || {}; + + options = Object.assign(options, { + throwUncatched: true + }); return new mod(plugins, isModule, options, callback); -}; +} From ecae49bab668e4dcf580dbe39660b7b5c58949c1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 30 Nov 2016 23:23:44 +0100 Subject: [PATCH 337/412] directly use promises in tests --- test/integration/api_test.js | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 2a60bffb..73c851fc 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -111,9 +111,9 @@ lab.experiment('api', { parallel: true }, function() { }); lab.test('should handle all up parameter variations properly', - { parallel: true }, function(done) { + { parallel: true }, function() { - Promise.resolve([ + return Promise.resolve([ [], // promise [sinon.spy()], ['nameatargetmigration', sinon.spy()], // targeted migration @@ -126,14 +126,13 @@ lab.experiment('api', { parallel: true }, function() { [1, 'testscope'] // promise scope target ]) .each(defaultExecParams('up')) - .each(spyCallback) - .asCallback(done); + .each(spyCallback); }); lab.test('should handle all down parameter variations properly', - { parallel: true }, function(done) { + { parallel: true }, function() { - Promise.resolve([ + return Promise.resolve([ [], // promise [sinon.spy()], [1, sinon.spy()], // targeted migration @@ -142,28 +141,26 @@ lab.experiment('api', { parallel: true }, function() { [1, 'testscope'] // promise scope target ]) .each(defaultExecParams('down')) - .each(spyCallback) - .asCallback(done); + .each(spyCallback); }); lab.test('should handle all reset parameter variations properly', - { parallel: true }, function(done) { + { parallel: true }, function() { - Promise.resolve([ + return Promise.resolve([ [], // promise [sinon.spy()], ['testscope', sinon.spy()], // scoped target ['testscope'] // promise scope target ]) .each(defaultExecParams('reset')) - .each(spyCallback) - .asCallback(done); + .each(spyCallback); }); lab.test('should handle all sync parameter variations properly', - { parallel: true }, function(done) { + { parallel: true }, function() { - Promise.resolve([ + return Promise.resolve([ [], ['nameatargetmigration', sinon.spy()], // targeted migration ['nameatargetmigration'], // promise targeted migration @@ -171,8 +168,7 @@ lab.experiment('api', { parallel: true }, function() { ['nameatargetmigration', 'testscope'], // promise scope target ]) .each(defaultExecParams('sync')) - .each(spyCallback) - .asCallback(done); + .each(spyCallback); }); }); From 369bf8528c78ec74993dd2780d7bd203d84cad7d Mon Sep 17 00:00:00 2001 From: ZReichert Date: Thu, 15 Jun 2017 13:10:30 -0400 Subject: [PATCH 338/412] Double quoting interpolated file name for coffee --- lib/migration.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 443dccf6..f326f6e6 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -279,16 +279,16 @@ Migration.prototype.coffeeSqlFileLoaderTemplate = function() { '', '', 'exports.up = (db, callback) ->', - ' filePath = path.join \'#{__dirname}/sqls/' + this.name.replace( - '.coffee', '') + '-up.sql\'', + ' 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\'', + ' filePath = path.join "#{__dirname}/sqls/' + this.name.replace( + '.coffee', '') + '-down.sql"', ' fs.readFile filePath, {encoding: \'utf-8\'}, (err,data) ->', ' return callback err if err', From f7c28c133607a0d5c1ae767a7fd4f01f3c78d4c4 Mon Sep 17 00:00:00 2001 From: Gonzalo Manrique Date: Sun, 9 Jul 2017 17:36:19 -0300 Subject: [PATCH 339/412] fix(create): use same timestamp in every created file --- api.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/api.js b/api.js index 373b6a0f..54e9fac0 100644 --- a/api.js +++ b/api.js @@ -648,7 +648,7 @@ function executeCreateMigration(internals, config, callback) { templateType = Migration.TemplateType.DEFAULT_COFFEE; } var migration = new Migration(internals.argv.title + ( - shouldCreateCoffeeFile( internals, config ) ? '.coffee' : '.js'), path, new Date(), + shouldCreateCoffeeFile( internals, config ) ? '.coffee' : '.js'), path, internals.runTimestamp, templateType); index.createMigration(migration, function(err, migration) { if (_assert(err, callback)) { @@ -709,7 +709,7 @@ function createSqlFiles(internals, config, callback) { var templateTypeDefaultSQL = Migration.TemplateType.DEFAULT_SQL; var migrationUpSQL = new Migration(internals.argv.title + '-up.sql', - sqlDir, new Date(), templateTypeDefaultSQL); + sqlDir, internals.runTimestamp, templateTypeDefaultSQL); index.createMigration(migrationUpSQL, function(err, migration) { if (_assert(err, callback)) { @@ -717,7 +717,7 @@ function createSqlFiles(internals, config, callback) { migration.path)); var migrationDownSQL = new Migration(internals.argv.title + - '-down.sql', sqlDir, new Date(), templateTypeDefaultSQL); + '-down.sql', sqlDir, internals.runTimestamp, templateTypeDefaultSQL); index.createMigration(migrationDownSQL, function(err, migration) { if (_assert(err, callback)) { @@ -891,6 +891,8 @@ function run(internals, config) { var action = internals.argv._.shift(), folder = action.split(':'); + internals.runTimestamp = new Date(); + action = folder[0]; switch (action) { From ec24db40943c92e40f67ecc3cb0e39446cd85537 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 14 Dec 2016 17:35:12 +0100 Subject: [PATCH 340/412] fix(args): dont parse when called as module fixes #449 --- lib/commands/set-default-argv.js | 194 ++++++++++++++++--------------- 1 file changed, 103 insertions(+), 91 deletions(-) diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index bf45b635..3af0804f 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -5,99 +5,111 @@ module.exports = function(internals, isModule) { var rc = require('rc'); var deepExtend = require('deep-extend'); + var defaultConfig = { + verbose: false, + table: 'migrations', + 'seeds-table': 'seeds', + 'force-exit': false, + 'sql-file': false, + 'non-transactional': false, + config: internals.configFile || internals.cwd + '/database.json', + 'migrations-dir': internals.cwd + '/migrations', + 'vcseeder-dir': internals.cwd + '/VCSeeder', + 'staticseeder-dir': internals.cwd + '/Seeder', + 'ignore-completed-migrations': false + }; + + if(!isModule) { + + internals.argv = optimist + .default(defaultConfig) + .usage( + 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + + '[[dbname/]migrationName|all] [options]' + ) + .describe('env', + 'The environment to run the migrations under (dev, test, prod).') + .alias('e', 'env') + .string('e') + + .describe('migrations-dir', 'The directory containing your migration files.') + .alias('m', 'migrations-dir') + .string('m') + + .describe('count', 'Max number of migrations to run.') + .alias('c', 'count') + .string('c') + + .describe('dry-run', 'Prints the SQL but doesn\'t run it.') + .boolean('dry-run') + + .describe('force-exit', 'Forcibly exit the migration process on completion.') + .boolean('force-exit') + + .describe('verbose', 'Verbose mode.') + .alias('v', 'verbose') + .boolean('v') + + .alias('h', 'help') + .alias('h', '?') + .boolean('h') + + .describe('version', 'Print version info.') + .alias('i', 'version') + .boolean('version') + + .describe('config', 'Location of the database.json file.') + .string('config') + + .describe('sql-file', + 'Automatically create two sql files for up and down statements in ' + + '/sqls and generate the javascript code that loads them.' + ) + .boolean('sql-file') + + .describe('coffee-file', 'Create a coffeescript migration file') + .boolean('coffee-file') + .describe('ignore-on-init', + 'Create files that will run only if ignore-on-init in the env is set ' + + 'to false (currently works onlt with SQL)' + ).boolean('ignore-on-init') + + .describe('migration-table', + 'Set the name of the migration table, which stores the migration history.' + ) + .alias('table', 'migration-table') + .alias('t', 'table') + .string('t') + + .describe('seeds-table', + 'Set the name of the seeds table, which stores the seed history.') + .string('seeds-table') + + .describe('vcseeder-dir', + 'Set the path to the Version Controlled Seeder directory.') + .string('vcseeder-dir') + + .describe('staticseeder-dir', 'Set the path to the Seeder directory.') + .string('staticseeder-dir') + + .describe('non-transactional', 'Explicitly disable transactions') + .boolean('non-transactional') + + .describe('ignore-completed-migrations', 'Start at the first migration') + .boolean('ignore-completed-migrations') + + .describe('log-level', 'Set the log-level, for example sql|warn') + .string('log-level'); + } + else { - internals.argv = optimist - .default({ - verbose: false, - table: 'migrations', - 'seeds-table': 'seeds', - 'force-exit': false, - 'sql-file': false, - 'non-transactional': false, - config: internals.configFile || internals.cwd + '/database.json', - 'migrations-dir': internals.cwd + '/migrations', - 'vcseeder-dir': internals.cwd + '/VCSeeder', - 'staticseeder-dir': internals.cwd + '/Seeder', - 'ignore-completed-migrations': false - }) - .usage( - 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + - '[[dbname/]migrationName|all] [options]' - ) - .describe('env', - 'The environment to run the migrations under (dev, test, prod).') - .alias('e', 'env') - .string('e') - - .describe('migrations-dir', 'The directory containing your migration files.') - .alias('m', 'migrations-dir') - .string('m') - - .describe('count', 'Max number of migrations to run.') - .alias('c', 'count') - .string('c') - - .describe('dry-run', 'Prints the SQL but doesn\'t run it.') - .boolean('dry-run') - - .describe('force-exit', 'Forcibly exit the migration process on completion.') - .boolean('force-exit') - - .describe('verbose', 'Verbose mode.') - .alias('v', 'verbose') - .boolean('v') - - .alias('h', 'help') - .alias('h', '?') - .boolean('h') - - .describe('version', 'Print version info.') - .alias('i', 'version') - .boolean('version') - - .describe('config', 'Location of the database.json file.') - .string('config') - - .describe('sql-file', - 'Automatically create two sql files for up and down statements in ' + - '/sqls and generate the javascript code that loads them.' - ) - .boolean('sql-file') - - .describe('coffee-file', 'Create a coffeescript migration file') - .boolean('coffee-file') - .describe('ignore-on-init', - 'Create files that will run only if ignore-on-init in the env is set ' + - 'to false (currently works onlt with SQL)' - ).boolean('ignore-on-init') - - .describe('migration-table', - 'Set the name of the migration table, which stores the migration history.' - ) - .alias('table', 'migration-table') - .alias('t', 'table') - .string('t') - - .describe('seeds-table', - 'Set the name of the seeds table, which stores the seed history.') - .string('seeds-table') - - .describe('vcseeder-dir', - 'Set the path to the Version Controlled Seeder directory.') - .string('vcseeder-dir') - - .describe('staticseeder-dir', 'Set the path to the Seeder directory.') - .string('staticseeder-dir') - - .describe('non-transactional', 'Explicitly disable transactions') - .boolean('non-transactional') - - .describe('ignore-completed-migrations', 'Start at the first migration') - .boolean('ignore-completed-migrations') - - .describe('log-level', 'Set the log-level, for example sql|warn') - .string('log-level'); + internals.argv = { + get argv() { + return defaultConfig; + } + }; + } var plugins = internals.plugins; var plugin = plugins.hook('init:cli:config:hook'); From b0837d55151115fbf6697941034abd341fb7c305 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 11 Jul 2017 13:09:16 +0200 Subject: [PATCH 341/412] fix deep config replacements fixes #473 --- lib/config.js | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/config.js b/lib/config.js index 2c9124fc..e6ddc6f9 100644 --- a/lib/config.js +++ b/lib/config.js @@ -83,13 +83,35 @@ exports.loadFile = function(fileName, currentEnv, plugins) { return exports.loadObject(config, currentEnv); }; +function walkConfig(level) { + + for (var configEntry in level) { + if (level[configEntry] && level[configEntry].ENV){ + + if(!process.env[level[configEntry].ENV]) { + + log.verbose('Environment variable ' + level[configEntry].ENV + + ' is empty!'); + } + + level[configEntry] = process.env[level[configEntry].ENV]; + } + else if(level[configEntry] && typeof(level[configEntry]) === 'object') { + + level[configEntry] = walkConfig(level[configEntry]); + } + } + + return level; +} + exports.loadObject = function(config, currentEnv) { var out = new Config(); for (var env in config) { if (config[env].ENV) { if(!process.env[config[env].ENV]) - log.verbose('Environment variable ' + config[env].ENV + 'is empty!'); + log.verbose('Environment variable ' + config[env].ENV + ' is empty!'); else out[env] = parseDatabaseUrl(process.env[config[env].ENV]); } else if (typeof(config[env]) === 'string') { @@ -97,18 +119,7 @@ exports.loadObject = function(config, currentEnv) { } else { //Check config entry's for ENV objects //which will tell us to grab configuration from the environment - for (var configEntry in config[env]) { - if (config[env][configEntry] && config[env][configEntry].ENV){ - - if(!process.env[config[env][configEntry].ENV]) { - - log.verbose('Environment variable ' + config[env][configEntry].ENV + - 'is empty!'); - } - - config[env][configEntry] = process.env[config[env][configEntry].ENV]; - } - } + config[env] = walkConfig(config[env]); out[env] = config[env]; } } From 8be9215786e278ba9f29d3b8244545cd890a8cfd Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 13 Aug 2017 17:26:26 +0200 Subject: [PATCH 342/412] feat(config): helper to overwrite and extend configuration This allows to parse a url from an url property and as well to overwrite and extend variables as needed. To pass in url as normal value an object is needed like the following: { url: { value: "http://example.com } }. Fixes #349 Fixes db-migrate/pg#8 Fixes #488 Fixes #463 --- lib/config.js | 42 +++++++++- test/config_test.js | 181 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 215 insertions(+), 8 deletions(-) diff --git a/lib/config.js b/lib/config.js index e6ddc6f9..0269f82f 100644 --- a/lib/config.js +++ b/lib/config.js @@ -105,10 +105,14 @@ function walkConfig(level) { return level; } -exports.loadObject = function(config, currentEnv) { +exports.loadObject = function(_config, currentEnv) { var out = new Config(); + // do not overwrite the users config + var config = JSON.parse(JSON.stringify(_config)); for (var env in config) { + + if (config[env].ENV) { if(!process.env[config[env].ENV]) log.verbose('Environment variable ' + config[env].ENV + ' is empty!'); @@ -122,6 +126,42 @@ exports.loadObject = function(config, currentEnv) { config[env] = walkConfig(config[env]); out[env] = config[env]; } + + if(typeof(config[env].url) === 'string') { + + config[env] = Object.assign( + config[env], + exports.loadUrl(config[env].url, env)[env] + ); + delete config[env].url; + } + else if(config[env].url && config[env].url.value) { + + config[env].url = config[env].url.value; + } + + if(config[env].overwrite || config[env].addIfNotExists) { + + var overwrite = config[env].overwrite || {}; + + if(config[env].addIfNotExists) { + + var addIfNotExists = config[env].addIfNotExists; + Object.keys(addIfNotExists).filter(function(key) { + return !overwrite[key] && !config[env][key]; + }).forEach(function(key) { + config[env][key] = addIfNotExists[key]; + }); + + delete config[env].addIfNotExists; + } + + Object.keys(overwrite).forEach(function(key) { + config[env][key] = overwrite[key]; + }); + + delete config[env].overwrite; + } } if(currentEnv) { diff --git a/test/config_test.js b/test/config_test.js index a73638dd..6abbde1a 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -3,6 +3,7 @@ var Lab = require('lab'); var lab = exports.lab = Lab.script(); var config = require('../lib/config'); var path = require('path'); +var sinon = require('sinon'); var _configLoad = config.load; var _configLoadUrl = config.loadUrl; @@ -160,13 +161,7 @@ lab.experiment('config', function() { config.load = _configLoad; config.loadUrl = _configLoadUrl; - lab.test('should something', function(done, cleanup) { - - cleanup(function(next) { - - delete require.cache[require.resolve('../lib/config')]; - next(); - }); + lab.test('should something', function(done) { Code.expect( config.load.bind(this, configPath, 'dev') @@ -174,4 +169,176 @@ lab.experiment('config', function() { done(); }); }); + + lab.experiment('loading a url from url property', function() { + + + lab.test('should export a valid config', + function(done) { + + var databaseUrl = { + 'dev': { + 'url': 'postgres://uname:pw@server.com/dbname' + } + }; + var cfg = config.loadObject(databaseUrl, 'dev'); + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + + done(); + }); + + lab.test('should export the value if specified in suboject', + function(done) { + + var databaseUrl = { + 'dev': { + 'url': { + 'value': 'http://example.com' + } + } + }; + var cfg = config.loadObject(databaseUrl, 'dev'); + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.equal('http://example.com'); + + done(); + }); + }); + + lab.experiment('loading from an URL and overwriting it', function() { + + var databaseUrl = { + 'dev': { + 'url': 'postgres://uname:pw@server.com/dbname', + 'overwrite': { + 'ssl': true + } + } + }; + + var cfg = config.loadObject(databaseUrl, 'dev'); + + lab.test('should export the settings as the current environment', function(done) { + + Code.expect(cfg.dev).to.exists(); + done(); + }); + + lab.test('should export a getCurrent function with all current environment settings', + function(done) { + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.overwrite).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + Code.expect(current.settings.ssl).to.equal(true); + + done(); + }); + }); + + lab.experiment('loading from an ENV URL within the object and overwriting it', + function() { + + lab.test('should export a getCurrent function with all current environment settings', + function(done, cleanup) { + + process.env.DATABASE_URL = 'postgres://uname:pw@server.com/dbname'; + var databaseUrl = { + 'dev': { + 'url': { 'ENV': 'DATABASE_URL' }, + 'overwrite': { + 'ssl': true + } + } + }; + var cfg = config.loadObject(databaseUrl, 'dev'); + + cleanup(function(next) { + delete process.env.DATABASE_URL; + next(); + }); + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.overwrite).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + Code.expect(current.settings.ssl).to.equal(true); + + done(); + }); + }); + + lab.experiment('loading from an ENV URL within the object and extending it from the ENV', + function() { + + lab.test('', function(done, cleanup) { + + process.env.DATABASE_URL = 'postgres://uname:pw@server.com/dbname?ssl=false&testing=false'; + var databaseUrl = { + 'dev': { + 'url': { + 'ENV': 'DATABASE_URL', + }, + 'overwrite': { + 'ssl': true, + 'cache': false + }, + 'addIfNotExists': { + 'native': true, // this on is new + 'cache': true, // overwrite should have higher priority + 'testing': true // already in config do not overwrite + } + } + }; + var cfg = config.loadObject(databaseUrl, 'dev'); + + cleanup(function(next) { + delete process.env.DATABASE_URL; + next(); + }); + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.overwrite).to.not.exists(); + Code.expect(current.settings.addIfNotExists).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + Code.expect(current.settings.native).to.equal(true); + Code.expect(current.settings.testing).to.equal('false'); + Code.expect(current.settings.cache).to.equal(false); + Code.expect(current.settings.ssl).to.equal(true); + + done(); + }); + }); }); From 335dea1f10d915fbed8d849bca0f38c0e48e3da3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 13 Aug 2017 17:41:40 +0200 Subject: [PATCH 343/412] fix(tests): fix breaking tests --- lib/commands/set-default-argv.js | 1 - test/integration/api_test.js | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index 3af0804f..91f5855e 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -2,7 +2,6 @@ var optimist = require('optimist'); var log = require('db-migrate-shared').log; module.exports = function(internals, isModule) { - var rc = require('rc'); var deepExtend = require('deep-extend'); var defaultConfig = { diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 73c851fc..3b952c3e 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -13,7 +13,7 @@ lab.experiment('api', { parallel: true }, function() { var process_exit = process.exit, argv = process.argv, called = false, - config = { cwd: __dirname }; + config = {}; // register cleanup method and start preparing the test onCleanup(teardown); @@ -222,7 +222,8 @@ function stubApiInstance(isModule, stubs, options, callback) { options = options || {}; options = Object.assign(options, { - throwUncatched: true + throwUncatched: true, + cwd: __dirname }); return new mod(plugins, isModule, options, callback); From a793f4487cd295ba85e7351a901b99e6cdd62daa Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 13 Aug 2017 18:15:34 +0200 Subject: [PATCH 344/412] refactor(config): do not just interpret database.json also check for either a passed config object OR a config file exists --- api.js | 4 +--- lib/commands/helper/assert.js | 1 + lib/config.js | 40 ++++++++++++++++++++++++++++------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/api.js b/api.js index 54e9fac0..0ede7a44 100644 --- a/api.js +++ b/api.js @@ -566,9 +566,7 @@ function loadConfig( config, internals ) { var out, currentEnv = internals.currentEnv || internals.argv.env; - if (process.env.DATABASE_URL) { - out = config.loadUrl(process.env.DATABASE_URL, currentEnv); - } else if (internals.configObject) { + if (internals.configObject) { out = config.loadObject(internals.configObject, currentEnv); } else { out = config.loadFile(internals.argv.config, currentEnv, internals.plugins); diff --git a/lib/commands/helper/assert.js b/lib/commands/helper/assert.js index ce648c67..4bd6f442 100644 --- a/lib/commands/helper/assert.js +++ b/lib/commands/helper/assert.js @@ -1,3 +1,4 @@ +var assert = require('assert'); module.exports = function(err, callback) { if (err) { diff --git a/lib/config.js b/lib/config.js index 0269f82f..c80a78fe 100644 --- a/lib/config.js +++ b/lib/config.js @@ -43,7 +43,12 @@ exports.loadFile = function(fileName, currentEnv, plugins) { try { fs.statSync(fileName); } catch(e) { - throw new Error('Could not find database config file \'' + fileName + '\''); + if(!process.env.DATABASE_URL) { + throw new Error('Could not find database config file \'' + fileName + '\''); + } + else { + return exports.loadUrl(process.env.DATABASE_URL, currentEnv); + } } try { @@ -77,7 +82,18 @@ exports.loadFile = function(fileName, currentEnv, plugins) { throw e; } - config = require(path.join(process.cwd(), fileName)); + try { + config = require(path.join(process.cwd(), fileName)); + } + catch(e) { + + if(!process.env.DATABASE_URL) { + throw e; + } + else { + return exports.loadUrl(process.env.DATABASE_URL, currentEnv); + } + } } return exports.loadObject(config, currentEnv); @@ -106,13 +122,13 @@ function walkConfig(level) { } exports.loadObject = function(_config, currentEnv) { + var out = new Config(); // do not overwrite the users config var config = JSON.parse(JSON.stringify(_config)); for (var env in config) { - if (config[env].ENV) { if(!process.env[config[env].ENV]) log.verbose('Environment variable ' + config[env].ENV + ' is empty!'); @@ -127,12 +143,20 @@ exports.loadObject = function(_config, currentEnv) { out[env] = config[env]; } - if(typeof(config[env].url) === 'string') { + if(typeof(config[env].url) === 'string' || process.env.DATABASE_URL) { - config[env] = Object.assign( - config[env], - exports.loadUrl(config[env].url, env)[env] - ); + if(typeof(config[env].url) !== 'string') { + config[env] = Object.assign( + config[env], + parseDatabaseUrl(process.env.DATABASE_URL) + ); + } + else { + config[env] = Object.assign( + config[env], + parseDatabaseUrl(config[env].url) + ); + } delete config[env].url; } else if(config[env].url && config[env].url.value) { From 28290589cee61efca6613080d7a6896257cd1a5d Mon Sep 17 00:00:00 2001 From: Gonzalo Manrique Date: Sat, 9 Sep 2017 19:11:13 -0300 Subject: [PATCH 345/412] fix(create): Fix create when using db-migrate as module Bug introduced on #485 Fixes: #493 --- api.js | 4 ++-- test/migration_test.js | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/api.js b/api.js index 0ede7a44..f8a14691 100644 --- a/api.js +++ b/api.js @@ -588,6 +588,8 @@ function executeCreateMigration(internals, config, callback) { var migrationsDir = internals.argv['migrations-dir']; + internals.runTimestamp = new Date(); + if (internals.migrationMode && internals.migrationMode !== 'all') { migrationsDir = internals.argv['migrations-dir'] + '/' + @@ -889,8 +891,6 @@ function run(internals, config) { var action = internals.argv._.shift(), folder = action.split(':'); - internals.runTimestamp = new Date(); - action = folder[0]; switch (action) { diff --git a/test/migration_test.js b/test/migration_test.js index 683a9e39..d00630e9 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -2,6 +2,7 @@ var Code = require('code'); var Lab = require('lab'); var lab = exports.lab = Lab.script(); var Migration = require('../lib/migration.js'); +var DBMigrate = require('../index'); var date = createDateForTest(); var dateString = '20140220143050'; @@ -20,8 +21,21 @@ lab.experiment('migration', { parallel: true }, function() { lab.experiment('get template', { parallel: true }, getTemplate); + + lab.experiment('when using db-migrate as module', { parallel: true }, + asModule); }); +function asModule() { + lab.test('should create migration', function (done) { + + var dbmigrate = DBMigrate.getInstance(true); + dbmigrate.setConfigParam('_',[]); + + dbmigrate.create('migrationName').then(done); + }); +} + function newMigrationObject() { lab.experiment('with 2 parameters as the complete filepath', From 8fb4a1bb8add5e377fa797979a04831b92954ec5 Mon Sep 17 00:00:00 2001 From: Gonzalo Manrique Date: Tue, 12 Sep 2017 23:58:43 -0300 Subject: [PATCH 346/412] test(create): Fix testing as module when no database.json on root --- test/migration_test.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/test/migration_test.js b/test/migration_test.js index d00630e9..3f6dea68 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -1,8 +1,8 @@ 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 DBMigrate = require('../index'); var date = createDateForTest(); var dateString = '20140220143050'; @@ -29,7 +29,7 @@ lab.experiment('migration', { parallel: true }, function() { function asModule() { lab.test('should create migration', function (done) { - var dbmigrate = DBMigrate.getInstance(true); + var dbmigrate = stubApiInstance(true, {}, {}); dbmigrate.setConfigParam('_',[]); dbmigrate.create('migrationName').then(done); @@ -254,6 +254,22 @@ 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), + plugins = {}; + options = options || {}; + + options = Object.assign(options, { + throwUncatched: true, + cwd: __dirname + }); + + return new mod(plugins, isModule, options, callback); +} + function createDateForTest() { var date = new Date(); date.setUTCFullYear(2014); From c4f0eed38fb43ce2c0afa18676bde430f6ccc6b9 Mon Sep 17 00:00:00 2001 From: philipyoo Date: Fri, 15 Sep 2017 10:58:54 -0700 Subject: [PATCH 347/412] fix small typo in cli help menu --- lib/commands/set-default-argv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index 91f5855e..19a617e6 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -70,7 +70,7 @@ module.exports = function(internals, isModule) { .boolean('coffee-file') .describe('ignore-on-init', 'Create files that will run only if ignore-on-init in the env is set ' + - 'to false (currently works onlt with SQL)' + 'to false (currently works only with SQL)' ).boolean('ignore-on-init') .describe('migration-table', From 93679a5fed342d301d8b0e6b2d8e11884123c5af Mon Sep 17 00:00:00 2001 From: Jordan Amos Date: Fri, 22 Sep 2017 09:53:06 -0700 Subject: [PATCH 348/412] allow rc file to contain location of config file --- lib/commands/set-default-argv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index 19a617e6..2afdf727 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -128,7 +128,7 @@ module.exports = function(internals, isModule) { internals.argv = deepExtend(internals.argv.argv, rc('db-migrate', {})); internals.argv.rcconfig = internals.argv.config; - internals.argv.config = _config; + internals.argv.config = internals.argv.configFile || _config; if (internals.argv.version) { console.log(internals.dbm.version); From 876f512f6aca5fedf25afdf5030ffe46da4dff94 Mon Sep 17 00:00:00 2001 From: junchao Date: Tue, 26 Sep 2017 23:08:07 +0800 Subject: [PATCH 349/412] print the reason in unhandledRejection evnet if reason.stack does not exist --- api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.js b/api.js index f8a14691..af4f0ce1 100644 --- a/api.js +++ b/api.js @@ -147,7 +147,7 @@ function registerEvents() { }); process.on('unhandledRejection', function(reason) { - log.error(reason.stack); + log.error(reason.stack || reason); process.exit(1); }); } From 489d498bbfc75e0f4f533782f30584e25eba75db Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sun, 29 Oct 2017 23:59:46 +0100 Subject: [PATCH 350/412] complete refactor of api js --- .eslintrc | 8 + .prettierrc | 3 + .tern-port | 1 + api.js | 805 ++++--------------------- index.js | 43 +- lib/commands/create-migration.js | 168 ++++++ lib/commands/db.js | 56 ++ lib/commands/fn/plugin.js | 45 ++ lib/commands/helper/load-config.js | 24 + lib/commands/helper/register-events.js | 15 + lib/commands/index.js | 9 + lib/commands/run.js | 111 ++++ lib/commands/seed.js | 48 ++ lib/commands/undo-seed.js | 52 ++ 14 files changed, 673 insertions(+), 715 deletions(-) create mode 100644 .eslintrc create mode 100644 .prettierrc create mode 100644 .tern-port create mode 100644 lib/commands/create-migration.js create mode 100644 lib/commands/db.js create mode 100644 lib/commands/fn/plugin.js create mode 100644 lib/commands/helper/load-config.js create mode 100644 lib/commands/helper/register-events.js create mode 100644 lib/commands/index.js create mode 100644 lib/commands/run.js create mode 100644 lib/commands/seed.js create mode 100644 lib/commands/undo-seed.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..7728755f --- /dev/null +++ b/.eslintrc @@ -0,0 +1,8 @@ +{ + "extends": "standard", + "rules": { + "semi": ["error", "always"], + "no-unused-vars": "warn" + "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }] + } +} diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..544138be --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/.tern-port b/.tern-port new file mode 100644 index 00000000..ecc7cc84 --- /dev/null +++ b/.tern-port @@ -0,0 +1 @@ +45175 \ No newline at end of file diff --git a/api.js b/api.js index af4f0ce1..dfcad86b 100644 --- a/api.js +++ b/api.js @@ -1,93 +1,36 @@ -var assert = require('assert'); -var fs = require('fs'); -var path = require('path'); -var util = require('util'); -var mkdirp = require('mkdirp'); -var optimist = require('optimist'); +'use strict'; + +var load = require('./lib/commands'); var log = require('db-migrate-shared').log; var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line -var dotenv = require('dotenv'); var Promise = Promise; -var onComplete = require('./lib/commands/on-complete.js'); - -function registerPluginLoader(plugins) { - - return { - - overwrite: function(name) { - - if(plugins[name] && plugins[name].length) { - - var plugin = plugins[name]; - - if(plugin.length !== 1) { - log.warn( - 'Attention, multiple overwrites registered for %s, we are ' + - 'only loading the first plugin %s!', - name, - plugin.name - ); - } - - plugin = plugin[0]; - if(typeof(plugin.loadPlugin) === 'function') - plugin.loadPlugin(); - - return plugin; - } - - return false; - }, - - hook: function(name) { - - if(plugins[name] && plugins[name].length) { - - var plugin = plugins[name]; - - plugin.map(function(plugin) { - - if(typeof(plugin.loadPlugin) === 'function') - plugin.loadPlugin(); - }); - - return plugin; - } - - return false; - } - }; -} +var onComplete = load('on-complete'); +// constant hooks for this file var APIHooks = { 'init:api:addfunction:hook': function(name, fn) { - this[name] = fn; return; }, 'init:api:accessapi:hook': function(cb) { - return cb(this); } }; function dbmigrate(plugins, isModule, options, callback) { - - var setDefaultArgv = require('./lib/commands/set-default-argv.js'); + var dotenv = require('dotenv'); + var setDefaultArgv = load('set-default-argv'); this.internals = { - onComplete: onComplete, migrationProtocol: 1 }; var internals = this.internals; - this.internals.plugins = registerPluginLoader(plugins); + this.internals.plugins = load('fn/plugin')(plugins); - if (typeof(callback) === 'function') - this.internals.onComplete = callback; - else if (typeof(options) === 'function') - this.internals.onComplete = options; + if (typeof callback === 'function') this.internals.onComplete = callback; + else if (typeof options === 'function') this.internals.onComplete = options; this.internals.dbm = require('./'); this.dataType = this.internals.dbm.dataType; @@ -97,34 +40,30 @@ function dbmigrate(plugins, isModule, options, callback) { }); /* $lab:coverage:off$ */ - if(options && !options.throwUncatched) - registerEvents(); + if (options && !options.throwUncatched) load('helper/register-events')(); /* $lab:coverage:on$ */ - if (typeof(options) === 'object') { - - if (typeof(options.config) === 'string') + if (typeof options === 'object') { + if (typeof options.config === 'string') internals.configFile = options.config; - else if (typeof(options.config) === 'object') + else if (typeof options.config === 'object') internals.configObject = options.config; - if (typeof(options.env) === 'string') - internals.currentEnv = options.env; + if (typeof options.env === 'string') internals.currentEnv = options.env; - if (typeof(options.cwd) === 'string') - internals.cwd = options.cwd; - else - internals.cwd = process.cwd(); - } else - internals.cwd = process.cwd(); + if (typeof options.cwd === 'string') internals.cwd = options.cwd; + else internals.cwd = process.cwd(); + } else internals.cwd = process.cwd(); - if (typeof(isModule) === 'function') { + if (typeof isModule === 'function') { this.internals.onComplete = isModule; setDefaultArgv(this.internals); - } else - setDefaultArgv(this.internals, isModule); + } else setDefaultArgv(this.internals, isModule); - this.config = loadConfig( require('./lib/config.js'), this.internals ); + this.config = load('helper/load-config')( + require('./lib/config.js'), + this.internals + ); //delayed loading of bluebird Promise = require('bluebird'); @@ -139,21 +78,7 @@ function dbmigrate(plugins, isModule, options, callback) { }; } -function registerEvents() { - - process.on('uncaughtException', function(err) { - log.error(err.stack || err); - process.exit(1); - }); - - process.on('unhandledRejection', function(reason) { - log.error(reason.stack || reason); - process.exit(1); - }); -} - dbmigrate.prototype = { - /** * Add a global defined variable to db-migrate, to enable access from * local migrations without configuring pathes. @@ -161,7 +86,6 @@ dbmigrate.prototype = { * @return boolean */ addGlobal: function(library) { - try { require(library); } catch (e) { @@ -177,28 +101,25 @@ dbmigrate.prototype = { * @returns Promise */ registerAPIHook: function(callback) { - var plugins = this.internals.plugins; var self = this; return Promise.resolve(Object.keys(APIHooks)) - .each(function(hook) { - - var plugin = plugins.hook(hook); - if(!plugin) return; - - var APIHook = APIHooks[hook].bind(self); - - return Promise.resolve(plugin) - .map(function(plugin) { - - return plugin[hook](); + .each(function(hook) { + var plugin = plugins.hook(hook); + if (!plugin) return; + + var APIHook = APIHooks[hook].bind(self); + + return Promise.resolve(plugin) + .map(function(plugin) { + return plugin[hook](); + }) + .each(function(args) { + return APIHook.apply(self, args); + }); }) - .each(function(args) { - - return APIHook.apply(self, args); - }); - }).asCallback(callback); + .asCallback(callback); }, _internals: this.internals, @@ -209,17 +130,14 @@ dbmigrate.prototype = { * @return boolean */ addConfiguration: function(description, args, type) { - var name = args.shift(); this.internals.argv.describe(name, description); for (var i = 0; i < args.length; ++i) { - this.internals.argv.alias(args[i], name); } switch (type) { - case 'string': this.internals.argv.string(name); break; @@ -235,7 +153,6 @@ dbmigrate.prototype = { return true; }, - /** * Resets and sets argv to a specified new argv. */ @@ -249,37 +166,30 @@ dbmigrate.prototype = { * Defaults to up all migrations if no count is given. */ up: function(specification, opts, callback) { - - var executeUp = require('./lib/commands/up.js'); + var executeUp = load('up'); if (arguments.length > 0) { - if (typeof(specification) === 'string') { - + if (typeof specification === 'string') { this.internals.argv.destination = specification; - } else if (typeof(specification) === 'number') { - + } else if (typeof specification === 'number') { this.internals.argv.count = specification; - } - else if (typeof(specification) === 'function') { - + } else if (typeof specification === 'function') { callback = specification; } - if (typeof(opts) === 'string') { - + if (typeof opts === 'string') { this.internals.migrationMode = opts; this.internals.matching = opts; - } - else if (typeof(opts) === 'function') { - + } else if (typeof opts === 'function') { callback = opts; } } - return Promise.fromCallback(function(callback) { - - executeUp(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeUp(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** @@ -288,34 +198,28 @@ dbmigrate.prototype = { * Defaults to up all migrations if no count is given. */ down: function(specification, opts, callback) { - - var executeDown = require('./lib/commands/down.js'); + var executeDown = load('down'); if (arguments.length > 0) { - if (typeof(specification) === 'number') { - + if (typeof specification === 'number') { this.internals.argv.count = arguments[0]; - } - else if (typeof(specification) === 'function') { - + } else if (typeof specification === 'function') { callback = specification; } - if (typeof(opts) === 'string') { - + if (typeof opts === 'string') { this.internals.migrationMode = opts; this.internals.matching = opts; - } - else if (typeof(opts) === 'function') { - + } else if (typeof opts === 'function') { callback = opts; } } - return Promise.fromCallback(function(callback) { - - executeDown(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeDown(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** @@ -324,61 +228,53 @@ dbmigrate.prototype = { * Defaults to up all migrations if no count is given. */ sync: function(specification, opts, callback) { - - var executeSync = require('./lib/commands/sync.js'); + var executeSync = load('sync'); if (arguments.length > 0) { - if (typeof(specification) === 'string') { - + if (typeof specification === 'string') { this.internals.argv.destination = specification; } - if (typeof(opts) === 'string') { - + if (typeof opts === 'string') { this.internals.migrationMode = opts; this.internals.matching = opts; - } - else if (typeof(opts) === 'function') { - + } else if (typeof opts === 'function') { callback = opts; } } - return Promise.fromCallback(function(callback) { - - executeSync(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeSync(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** * Executes down for all currently migrated migrations. */ reset: function(scope, callback) { + var executeDown = load('down'); - var executeDown = require('./lib/commands/down.js'); - - if (typeof(scope) === 'string') { - + if (typeof scope === 'string') { this.internals.migrationMode = scope; this.internals.matching = scope; - } - else if(typeof(scope) === 'function') { - + } else if (typeof scope === 'function') { callback = scope; } this.internals.argv.count = Number.MAX_VALUE; - return Promise.fromCallback(function(callback) { - - executeDown(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeDown(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** * Silence the log output completely. */ silence: function(isSilent) { - return log.silence(isSilent); }, @@ -386,7 +282,6 @@ dbmigrate.prototype = { * Transition migrations to the latest defined protocol. */ transition: function() { - transition(this.internals); }, @@ -394,47 +289,48 @@ dbmigrate.prototype = { * Creates a correctly formatted migration */ create: function(migrationName, scope, callback) { - - if (typeof(scope) === 'function') { - + var executeCreateMigration = load('create-migration'); + if (typeof scope === 'function') { callback = scope; } else if (scope) { - this.internals.migrationMode = scope; this.internals.matching = scope; } this.internals.argv._.push(migrationName); - return Promise.fromCallback(function(callback) { - - executeCreateMigration(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeCreateMigration(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** * Creates a database of the given dbname. */ createDatabase: function(dbname, callback) { - + var executeDB = load('db'); this.internals.argv._.push(dbname); this.internals.mode = 'create'; - return Promise.fromCallback(function(callback) { - - executeDB(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeDB(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** * Drops a database of the given dbname. */ dropDatabase: function(dbname, callback) { - + var executeDB = load('db'); this.internals.argv._.push(dbname); this.internals.mode = 'drop'; - return Promise.fromCallback(function(callback) { - - executeDB(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeDB(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** @@ -443,16 +339,13 @@ dbmigrate.prototype = { * @return value */ setConfigParam: function(param, value) { - return (this.internals.argv[param] = value); }, - /** * Sets the callback to the default onComplete */ setDefaultCallback: function() { - this.internals.onComplete = onComplete; }, @@ -461,7 +354,6 @@ dbmigrate.prototype = { * migrations have been done. */ setCustomCallback: function(callback) { - this.internals.onComplete = callback; }, @@ -470,544 +362,83 @@ dbmigrate.prototype = { * the passed mode. */ seed: function(mode, scope, callback) { - + var executeSeed = load('seed'); if (scope) { - this.internals.migrationMode = scope; this.internals.matching = scope; } this.internals.mode = mode || 'vc'; - return Promise.fromCallback(function(callback) { - - executeSeed(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeSeed(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** * Execute the down function of currently executed seeds. */ undoSeed: function(specification, scope, callback) { - + var executeUndoSeed = load('undo-seed'); if (arguments.length > 0) { - if (typeof(specification) === 'number') { - + if (typeof specification === 'number') { this.internals.argv.count = specification; if (scope) { - this.internals.migrationMode = scope; this.internals.matching = scope; } - } else if (typeof(specification) === 'string') { - + } else if (typeof specification === 'string') { this.internals.migrationMode = scope; this.internals.matching = scope; } } - return Promise.fromCallback(function(callback) { - - executeUndoSeed(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeUndoSeed(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** * Execute the reset function of currently executed seeds. */ resetSeed: function(specification, scope, callback) { - + var executeUndoSeed = load('undo-seed'); if (arguments.length > 0) { - if (typeof(specification) === 'number') { - + if (typeof specification === 'number') { this.internals.argv.count = specification; if (scope) { - this.internals.migrationMode = scope; this.internals.matching = scope; } - } else if (typeof(specification) === 'string') { - + } else if (typeof specification === 'string') { this.internals.migrationMode = scope; this.internals.matching = scope; } } this.internals.argv.count = Number.MAX_VALUE; - return Promise.fromCallback(function(callback) { - - executeUndoSeed(this.internals, this.config, callback); - }.bind(this)).asCallback(callback); + return Promise.fromCallback( + function(callback) { + executeUndoSeed(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); }, /** * Executes the default routine. */ run: function() { - - run(this.internals, this.config); - + load('run')(this.internals, this.config); } - }; -function createMigrationDir(dir, callback) { - fs.stat(dir, function(err) { - if (err) { - mkdirp(dir, callback); - } else { - callback(); - } - }); -} - -function loadConfig( config, internals ) { - var out, - currentEnv = internals.currentEnv || internals.argv.env; - - if (internals.configObject) { - out = config.loadObject(internals.configObject, currentEnv); - } else { - out = config.loadFile(internals.argv.config, currentEnv, internals.plugins); - } - if (internals.verbose) { - var current = out.getCurrent(); - var s = JSON.parse(JSON.stringify(current.settings)); - - if (s.password) - s.password = '******'; - - log.info('Using', current.env, 'settings:', s); - } - - return out; -} - -function executeCreateMigration(internals, config, callback) { - - var migrationsDir = internals.argv['migrations-dir']; - - internals.runTimestamp = new Date(); - - if (internals.migrationMode && internals.migrationMode !== 'all') { - - migrationsDir = internals.argv['migrations-dir'] + '/' + - internals.migrationMode; - } - - var folder, path; - - if (internals.argv._.length === 0) { - log.error('\'migrationName\' is required.'); - optimist.showHelp(); - process.exit(1); - } - - createMigrationDir(migrationsDir, function(err) { - - var index = require('./connect'); - var Migration = require('./lib/migration.js'); - - if (err) { - log.error('Failed to create migration directory at ', migrationsDir, - err); - process.exit(1); - } - - internals.argv.title = internals.argv._.shift(); - folder = internals.argv.title.split('/'); - - internals.argv.title = folder[folder.length - 2] || folder[0]; - path = migrationsDir; - - if (folder.length > 1) { - - path += '/'; - - for (var i = 0; i < folder.length - 1; ++i) { - - path += folder[i] + '/'; - } - } - - var templateType = Migration.TemplateType.DEFAULT_JS; - if (shouldCreateSqlFiles( internals, config ) && - shouldCreateCoffeeFile( internals, config )) { - - templateType = Migration.TemplateType.COFFEE_SQL_FILE_LOADER; - } else if (shouldCreateSqlFiles( internals, config ) && - shouldIgnoreOnInitFiles( internals, config )) { - - templateType = Migration.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT; - } else if (shouldCreateSqlFiles( internals, config )) { - - templateType = Migration.TemplateType.SQL_FILE_LOADER; - } else if (shouldCreateCoffeeFile( internals, config )) { - - templateType = Migration.TemplateType.DEFAULT_COFFEE; - } - var migration = new Migration(internals.argv.title + ( - shouldCreateCoffeeFile( internals, config ) ? '.coffee' : '.js'), path, internals.runTimestamp, - templateType); - index.createMigration(migration, function(err, migration) { - if (_assert(err, callback)) { - - log.info(util.format('Created migration at %s', migration.path)); - if (shouldCreateSqlFiles(internals, config)) { - createSqlFiles(internals, config, callback); - } else { - if (typeof(callback) === 'function') { - callback(); - } - } - } - }); - }); -} - -function shouldCreateSqlFiles( internals, config ) { - return internals.argv['sql-file'] || config['sql-file']; -} - -function shouldIgnoreOnInitFiles( internals, config ) { - return internals.argv['ignore-on-init'] || config[ - 'ignore-on-init']; -} - -function shouldCreateCoffeeFile( internals, config ) { - return internals.argv['coffee-file'] || config['coffee-file']; -} - -function createSqlFiles(internals, config, callback) { - - var migrationsDir = internals.argv['migrations-dir']; - - if (internals.migrationMode && internals.migrationMode !== 'all') { - - migrationsDir = internals.argv['migrations-dir'] + '/' + - internals.migrationMode; - } - - var sqlDir = migrationsDir + '/sqls'; - createMigrationDir(sqlDir, function(err) { - - var index = require('./connect'); - var Migration = require('./lib/migration.js'); - - if (err) { - log.error('Failed to create migration directory at ', sqlDir, err); - - if (typeof(callback) !== 'function') { - - process.exit(1); - } else { - - return callback(err); - } - } - - var templateTypeDefaultSQL = Migration.TemplateType.DEFAULT_SQL; - var migrationUpSQL = new Migration(internals.argv.title + '-up.sql', - sqlDir, internals.runTimestamp, templateTypeDefaultSQL); - index.createMigration(migrationUpSQL, function(err, migration) { - if (_assert(err, callback)) { - - log.info(util.format('Created migration up sql file at %s', - migration.path)); - - var migrationDownSQL = new Migration(internals.argv.title + - '-down.sql', sqlDir, internals.runTimestamp, templateTypeDefaultSQL); - index.createMigration(migrationDownSQL, function(err, migration) { - if (_assert(err, callback)) { - - log.info(util.format( - 'Created migration down sql file at %s', - migration.path)); - if (typeof(callback) === 'function') - callback(); - } - }); - } - }); - }); -} - -function _assert(err, callback) { - if (err) { - - if (typeof(callback) === 'function') { - - callback(err); - return false; - } else { - - assert.ifError(err); - return false; - } - } - - return true; -} - -function migrationHook(internals) { - - var Migration = require('./lib/migration.js'); - return Migration.registerHook(internals.plugins, internals); -} - -function executeDB(internals, config, callback) { - - var index = require('./connect'); - - if (internals.argv._.length > 0) { - internals.argv.dbname = internals.argv._.shift().toString(); - } else { - - log.info('Error: You must enter a database name!'); - return; - } - - index.driver(config.getCurrent().settings, function(err, db) { - assert.ifError(err); - - if (internals.mode === 'create') { - db.createDatabase(internals.argv.dbname, { - ifNotExists: true - }, function(err) { - if (err) { - if( err.error ) - err = err.error; - log.info('Error: Failed to create database!', err); - } else { - log.info('Created database "' + internals.argv.dbname + '"'); - } - - db.close(); - if( typeof(callback) === 'function' ) - callback(); - }); - } else if (internals.mode === 'drop') { - db.dropDatabase(internals.argv.dbname, { - ifExists: true - }, function(err) { - if (err) { - if( err.error ) - err = err.error; - log.info('Error: Failed to drop database!', err); - } else { - log.info('Deleted database "' + internals.argv.dbname + '"'); - } - - db.close(); - if( typeof(callback) === 'function' ) - callback(); - }); - } else - return; - }); - -} - -function executeSeed(internals, config, callback) { - - var index = require('./connect'); - var Seeder = require('./lib/seeder.js'); - - if (internals.argv._.length > 0) { - internals.argv.destination = internals.argv._.shift().toString(); - } - - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Seeder, function(err, seeder) { - assert.ifError(err); - - seeder.seedDir = path.resolve(internals.argv[(internals.mode !== - 'static') ? 'vcseeder-dir' : 'staticseeder-dir']); - - if (internals.mode === 'static') { - - seeder.seed(internals.argv, internals.onComplete.bind(this, seeder, - internals, callback)); - } else { - seeder.createSeedsTable(function(err) { - if (_assert(err, callback)) { - - seeder.seed(internals.argv, internals.onComplete.bind(this, - seeder, internals, callback)); - } - }); - } - }); -} - -function executeUndoSeed(internals, config, callback) { - - var index = require('./connect'); - var Seeder = require('./lib/seeder.js'); - - if (!internals.argv.count) { - log.info('Defaulting to running 1 down seed.'); - internals.argv.count = 1; - } - - if (internals.argv._.length > 0) { - internals.argv.destination = internals.argv._.shift().toString(); - } - - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, Seeder, function(err, seeder) { - assert.ifError(err); - - seeder.seedDir = path.resolve(internals.argv[(internals.mode !== - 'static') ? 'vcseeder-dir' : 'staticseeder-dir']); - - if (internals.mode === 'static') { - - internals.onComplete( seeder, callback, - { stack: 'Static seeders can\'t be undone. Use VC Seeders instead!' } ); - } else { - seeder.createSeedsTable(function(err) { - if (_assert(err, callback)) { - - seeder.down(internals.argv, internals.onComplete.bind(this, - seeder, internals, callback)); - } - }); - } - }); -} - function transition(internals) { - require('./lib/transitions/transitioner.js')(internals); } -function run(internals, config) { - var action = internals.argv._.shift(), - folder = action.split(':'); - - action = folder[0]; - - switch (action) { - case 'transition': - - transition(internals); - break; - case 'create': - - if (folder[1]) { - internals.matching = folder[1]; - internals.migrationMode = folder[1]; - } - executeCreateMigration(internals, config); - break; - case 'sync': - - var executeSync = require('./lib/commands/sync.js'); - - if (internals.argv._.length === 0) { - - log.error('Missing sync destination!'); - process.exit(1); - } - - internals.argv.count = Number.MAX_VALUE; - internals.argv.destination = internals.argv._.shift().toString(); - - if (folder[1]) { - internals.matching = folder[1]; - internals.migrationMode = folder[1]; - } - - executeSync(internals, config); - break; - case 'up': - case 'down': - case 'reset': - - if (action === 'reset') - internals.argv.count = Number.MAX_VALUE; - - if (internals.argv._.length > 0) { - if (action === 'down') { - - internals.argv.count = internals.argv.count || Number.MAX_VALUE; - internals.argv.destination = internals.argv._.shift().toString(); - } else { - internals.argv.destination = internals.argv._.shift().toString(); - } - } - - if (folder[1]) { - internals.matching = folder[1]; - internals.migrationMode = folder[1]; - } - - if (action === 'up') { - - var executeUp = require('./lib/commands/up.js'); - executeUp(internals, config); - } else { - - var executeDown = require('./lib/commands/down.js'); - executeDown(internals, config); - } - break; - - case 'db': - - if (folder.length < 1) { - - log.info('Please enter a valid command, i.e. db:create|db:drop'); - } else { - - internals.mode = folder[1]; - executeDB(internals, config); - } - break; - case 'seed': - - internals.mode = folder[1] || 'vc'; - internals.migrationMode = folder[2]; - - if (internals.argv._[0] === 'down' || internals.argv._[0] === 'reset') { - - if (internals.argv._[0] === 'reset') - internals.argv.count = Number.MAX_VALUE; - - internals.argv._.shift(); - executeUndoSeed(internals, config); - } else { - - executeSeed(internals, config); - } - break; - - default: - var plugins = internals.plugins; - var plugin = plugins.overwrite( - 'run:default:action:' + action + ':overwrite' - ); - if(plugin) { - - plugin['run:default:action:' + action + ':overwrite'] - (internals, config); - } - else { - - log.error('Invalid Action: Must be [up|down|create|reset|sync|' + - 'db|transition].'); - optimist.showHelp(); - process.exit(1); - } - break; - } -} - - module.exports = dbmigrate; diff --git a/index.js b/index.js index 897728ae..30279a08 100644 --- a/index.js +++ b/index.js @@ -5,41 +5,33 @@ var path = require('path'); exports.dataType = require('db-migrate-shared').dataType; function loadPluginList() { - - var plugins = JSON.parse(fs.readFileSync( - path.join(process.cwd(), 'package.json'), - 'utf-8' - ) - ), - targets = []; + var plugins = JSON.parse( + fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8') + ), + targets = []; plugins = Object.assign(plugins.dependencies, plugins.devDependencies); - for(var plugin in plugins) { - - if(plugin.startsWith('db-migrate-plugin')) - targets.push(plugin); + for (var plugin in plugins) { + if (plugin.startsWith('db-migrate-plugin')) targets.push(plugin); } return targets; } function loadPlugins() { - var plugins = loadPluginList(), - i = 0, - length = plugins.length, - hooks = {}; - - for(; i < length; ++i) { + i = 0, + length = plugins.length, + hooks = {}; + for (; i < length; ++i) { var plugin = require(path.join(process.cwd(), 'node_modules', plugins[i])); - if(typeof(plugin.name) !== 'string' || !plugin.hooks || !plugin.loadPlugin) + if (typeof plugin.name !== 'string' || !plugin.hooks || !plugin.loadPlugin) continue; plugin.hooks.map(function(hook) { - hooks[hook] = hooks[hook] || []; hooks[hook].push(plugin); }); @@ -49,21 +41,16 @@ function loadPlugins() { } module.exports.getInstance = function(isModule, options, callback) { - delete require.cache[require.resolve('./api.js')]; delete require.cache[require.resolve('optimist')]; var mod = require('./api.js'), - plugins = {}; + plugins = {}; try { + if (!options || !options.noPlugins) plugins = loadPlugins(); + } catch (ex) {} - if(!options || !options.noPlugins) - plugins = loadPlugins(); - } - catch(ex) {} - - if(options && options.plugins) { - + if (options && options.plugins) { plugins = Object.assign(plugins, options.plugins); } diff --git a/lib/commands/create-migration.js b/lib/commands/create-migration.js new file mode 100644 index 00000000..492a4b26 --- /dev/null +++ b/lib/commands/create-migration.js @@ -0,0 +1,168 @@ +'use strict'; + +var assert = require('../helper/assert'); +var log = require('db-migrate-shared').log; +var mkdirp = require('mkdirp'); +var fs = require('fs'); +var util = require('util'); + +function createMigrationDir(dir, callback) { + fs.stat(dir, function(err) { + if (err) { + mkdirp(dir, callback); + } else { + callback(); + } + }); +} + +function executeCreateMigration(internals, config, callback) { + var migrationsDir = internals.argv['migrations-dir']; + + internals.runTimestamp = new Date(); + + if (internals.migrationMode && internals.migrationMode !== 'all') { + migrationsDir = + internals.argv['migrations-dir'] + '/' + internals.migrationMode; + } + + var folder, path; + + if (internals.argv._.length === 0) { + log.error("'migrationName' is required."); + optimist.showHelp(); + process.exit(1); + } + + createMigrationDir(migrationsDir, function(err) { + var index = require('./connect'); + var Migration = require('./lib/migration.js'); + + if (err) { + log.error('Failed to create migration directory at ', migrationsDir, err); + process.exit(1); + } + + internals.argv.title = internals.argv._.shift(); + folder = internals.argv.title.split('/'); + + internals.argv.title = folder[folder.length - 2] || folder[0]; + path = migrationsDir; + + if (folder.length > 1) { + path += '/'; + + for (var i = 0; i < folder.length - 1; ++i) { + path += folder[i] + '/'; + } + } + + var templateType = Migration.TemplateType.DEFAULT_JS; + if ( + shouldCreateSqlFiles(internals, config) && + shouldCreateCoffeeFile(internals, config) + ) { + templateType = Migration.TemplateType.COFFEE_SQL_FILE_LOADER; + } else if ( + shouldCreateSqlFiles(internals, config) && + shouldIgnoreOnInitFiles(internals, config) + ) { + templateType = Migration.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT; + } else if (shouldCreateSqlFiles(internals, config)) { + templateType = Migration.TemplateType.SQL_FILE_LOADER; + } else if (shouldCreateCoffeeFile(internals, config)) { + templateType = Migration.TemplateType.DEFAULT_COFFEE; + } + var migration = new Migration( + internals.argv.title + + (shouldCreateCoffeeFile(internals, config) ? '.coffee' : '.js'), + path, + internals.runTimestamp, + templateType + ); + index.createMigration(migration, function(err, migration) { + if (_assert(err, callback)) { + log.info(util.format('Created migration at %s', migration.path)); + if (shouldCreateSqlFiles(internals, config)) { + createSqlFiles(internals, config, callback); + } else { + if (typeof callback === 'function') { + callback(); + } + } + } + }); + }); +} + +function shouldCreateSqlFiles(internals, config) { + return internals.argv['sql-file'] || config['sql-file']; +} + +function shouldIgnoreOnInitFiles(internals, config) { + return internals.argv['ignore-on-init'] || config['ignore-on-init']; +} + +function shouldCreateCoffeeFile(internals, config) { + return internals.argv['coffee-file'] || config['coffee-file']; +} + +function createSqlFiles(internals, config, callback) { + var migrationsDir = internals.argv['migrations-dir']; + + if (internals.migrationMode && internals.migrationMode !== 'all') { + migrationsDir = + internals.argv['migrations-dir'] + '/' + internals.migrationMode; + } + + var sqlDir = migrationsDir + '/sqls'; + createMigrationDir(sqlDir, function(err) { + var index = require('./connect'); + var Migration = require('./lib/migration.js'); + + if (err) { + log.error('Failed to create migration directory at ', sqlDir, err); + + if (typeof callback !== 'function') { + process.exit(1); + } else { + return callback(err); + } + } + + var templateTypeDefaultSQL = Migration.TemplateType.DEFAULT_SQL; + var migrationUpSQL = new Migration( + internals.argv.title + '-up.sql', + sqlDir, + internals.runTimestamp, + templateTypeDefaultSQL + ); + index.createMigration(migrationUpSQL, function(err, migration) { + if (_assert(err, callback)) { + log.info( + util.format('Created migration up sql file at %s', migration.path) + ); + + var migrationDownSQL = new Migration( + internals.argv.title + '-down.sql', + sqlDir, + internals.runTimestamp, + templateTypeDefaultSQL + ); + index.createMigration(migrationDownSQL, function(err, migration) { + if (_assert(err, callback)) { + log.info( + util.format( + 'Created migration down sql file at %s', + migration.path + ) + ); + if (typeof callback === 'function') callback(); + } + }); + } + }); + }); +} + +module.exports = executeCreateMigration; diff --git a/lib/commands/db.js b/lib/commands/db.js new file mode 100644 index 00000000..9e645322 --- /dev/null +++ b/lib/commands/db.js @@ -0,0 +1,56 @@ +'use strict'; + +function executeDB(internals, config, callback) { + var index = require('./connect'); + + if (internals.argv._.length > 0) { + internals.argv.dbname = internals.argv._.shift().toString(); + } else { + log.info('Error: You must enter a database name!'); + return; + } + + index.driver(config.getCurrent().settings, function(err, db) { + assert.ifError(err); + + if (internals.mode === 'create') { + db.createDatabase( + internals.argv.dbname, + { + ifNotExists: true + }, + function(err) { + if (err) { + if (err.error) err = err.error; + log.info('Error: Failed to create database!', err); + } else { + log.info('Created database "' + internals.argv.dbname + '"'); + } + + db.close(); + if (typeof callback === 'function') callback(); + } + ); + } else if (internals.mode === 'drop') { + db.dropDatabase( + internals.argv.dbname, + { + ifExists: true + }, + function(err) { + if (err) { + if (err.error) err = err.error; + log.info('Error: Failed to drop database!', err); + } else { + log.info('Deleted database "' + internals.argv.dbname + '"'); + } + + db.close(); + if (typeof callback === 'function') callback(); + } + ); + } else return; + }); +} + +module.exports = executeDB; diff --git a/lib/commands/fn/plugin.js b/lib/commands/fn/plugin.js new file mode 100644 index 00000000..24c604ed --- /dev/null +++ b/lib/commands/fn/plugin.js @@ -0,0 +1,45 @@ +'use strict'; + +const log = require('db-migrate-shared').log; + +function registerPluginLoader(plugins) { + return { + overwrite: function(name) { + if (plugins[name] && plugins[name].length) { + var plugin = plugins[name]; + + if (plugin.length !== 1) { + log.warn( + 'Attention, multiple overwrites registered for %s, we are ' + + 'only loading the first plugin %s!', + name, + plugin.name + ); + } + + plugin = plugin[0]; + if (typeof plugin.loadPlugin === 'function') plugin.loadPlugin(); + + return plugin; + } + + return false; + }, + + hook: function(name) { + if (plugins[name] && plugins[name].length) { + var plugin = plugins[name]; + + plugin.map(function(plugin) { + if (typeof plugin.loadPlugin === 'function') plugin.loadPlugin(); + }); + + return plugin; + } + + return false; + } + }; +} + +module.exports = registerPluginLoader; diff --git a/lib/commands/helper/load-config.js b/lib/commands/helper/load-config.js new file mode 100644 index 00000000..b26063f2 --- /dev/null +++ b/lib/commands/helper/load-config.js @@ -0,0 +1,24 @@ +'use strict'; + +function loadConfig(config, internals) { + var out, + currentEnv = internals.currentEnv || internals.argv.env; + + if (internals.configObject) { + out = config.loadObject(internals.configObject, currentEnv); + } else { + out = config.loadFile(internals.argv.config, currentEnv, internals.plugins); + } + if (internals.verbose) { + var current = out.getCurrent(); + var s = JSON.parse(JSON.stringify(current.settings)); + + if (s.password) s.password = '******'; + + log.info('Using', current.env, 'settings:', s); + } + + return out; +} + +module.exports = loadConfig; diff --git a/lib/commands/helper/register-events.js b/lib/commands/helper/register-events.js new file mode 100644 index 00000000..fd7f521b --- /dev/null +++ b/lib/commands/helper/register-events.js @@ -0,0 +1,15 @@ +'use strict'; + +function registerEvents() { + process.on('uncaughtException', function(err) { + log.error(err.stack || err); + process.exit(1); + }); + + process.on('unhandledRejection', function(reason) { + log.error(reason.stack || reason); + process.exit(1); + }); +} + +module.exports = registerEvents; diff --git a/lib/commands/index.js b/lib/commands/index.js new file mode 100644 index 00000000..633018f7 --- /dev/null +++ b/lib/commands/index.js @@ -0,0 +1,9 @@ +'use strict'; + +var path = require('path'); + +function register(module) { + return require(path.resolve(__dirname, module)); +} + +module.exports = register; diff --git a/lib/commands/run.js b/lib/commands/run.js new file mode 100644 index 00000000..d1a3e17b --- /dev/null +++ b/lib/commands/run.js @@ -0,0 +1,111 @@ +'use strict'; + +function run(internals, config) { + var action = internals.argv._.shift(), + folder = action.split(':'); + + action = folder[0]; + + switch (action) { + case 'transition': + transition(internals); + break; + case 'create': + if (folder[1]) { + internals.matching = folder[1]; + internals.migrationMode = folder[1]; + } + executeCreateMigration(internals, config); + break; + case 'sync': + var executeSync = load('sync'); + + if (internals.argv._.length === 0) { + log.error('Missing sync destination!'); + process.exit(1); + } + + internals.argv.count = Number.MAX_VALUE; + internals.argv.destination = internals.argv._.shift().toString(); + + if (folder[1]) { + internals.matching = folder[1]; + internals.migrationMode = folder[1]; + } + + executeSync(internals, config); + break; + case 'up': + case 'down': + case 'reset': + if (action === 'reset') internals.argv.count = Number.MAX_VALUE; + + if (internals.argv._.length > 0) { + if (action === 'down') { + internals.argv.count = internals.argv.count || Number.MAX_VALUE; + internals.argv.destination = internals.argv._.shift().toString(); + } else { + internals.argv.destination = internals.argv._.shift().toString(); + } + } + + if (folder[1]) { + internals.matching = folder[1]; + internals.migrationMode = folder[1]; + } + + if (action === 'up') { + var executeUp = load('up'); + executeUp(internals, config); + } else { + var executeDown = load('down'); + executeDown(internals, config); + } + break; + + case 'db': + if (folder.length < 1) { + log.info('Please enter a valid command, i.e. db:create|db:drop'); + } else { + internals.mode = folder[1]; + executeDB(internals, config); + } + break; + case 'seed': + internals.mode = folder[1] || 'vc'; + internals.migrationMode = folder[2]; + + if (internals.argv._[0] === 'down' || internals.argv._[0] === 'reset') { + if (internals.argv._[0] === 'reset') + internals.argv.count = Number.MAX_VALUE; + + internals.argv._.shift(); + executeUndoSeed(internals, config); + } else { + executeSeed(internals, config); + } + break; + + default: + var plugins = internals.plugins; + var plugin = plugins.overwrite( + 'run:default:action:' + action + ':overwrite' + ); + if (plugin) { + plugin['run:default:action:' + action + ':overwrite']( + internals, + config + ); + } else { + log.error( + 'Invalid Action: Must be [up|down|create|reset|sync|' + + 'db|transition].' + ); + optimist.showHelp(); + process.exit(1); + } + break; + } +} + +module.exports = run; diff --git a/lib/commands/seed.js b/lib/commands/seed.js new file mode 100644 index 00000000..248b9cfd --- /dev/null +++ b/lib/commands/seed.js @@ -0,0 +1,48 @@ +'use strict'; + +var assert = require('assert'); +var _assert = require('../helper/assert'); + +function executeSeed(internals, config, callback) { + var index = require('./connect'); + var Seeder = require('./lib/seeder.js'); + + if (internals.argv._.length > 0) { + internals.argv.destination = internals.argv._.shift().toString(); + } + + index.connect( + { + config: config.getCurrent().settings, + internals: internals + }, + Seeder, + function(err, seeder) { + assert.ifError(err); + + seeder.seedDir = path.resolve( + internals.argv[ + internals.mode !== 'static' ? 'vcseeder-dir' : 'staticseeder-dir' + ] + ); + + if (internals.mode === 'static') { + seeder.seed( + internals.argv, + internals.onComplete.bind(this, seeder, internals, callback) + ); + } else { + seeder.createSeedsTable(function(err) { + if (_assert(err, callback)) { + seeder.seed( + internals.argv, + internals.onComplete.bind(this, seeder, internals, callback) + ); + } + }); + } + } + ); +} + +module.exports = executeSeed; diff --git a/lib/commands/undo-seed.js b/lib/commands/undo-seed.js new file mode 100644 index 00000000..05dd464a --- /dev/null +++ b/lib/commands/undo-seed.js @@ -0,0 +1,52 @@ +'use strict'; + +var assert = require('assert'); +var _assert = require('../helper/assert'); + +function executeUndoSeed(internals, config, callback) { + var index = require('./connect'); + var Seeder = require('./lib/seeder.js'); + + if (!internals.argv.count) { + log.info('Defaulting to running 1 down seed.'); + internals.argv.count = 1; + } + + if (internals.argv._.length > 0) { + internals.argv.destination = internals.argv._.shift().toString(); + } + + index.connect( + { + config: config.getCurrent().settings, + internals: internals + }, + Seeder, + function(err, seeder) { + assert.ifError(err); + + seeder.seedDir = path.resolve( + internals.argv[ + internals.mode !== 'static' ? 'vcseeder-dir' : 'staticseeder-dir' + ] + ); + + if (internals.mode === 'static') { + internals.onComplete(seeder, callback, { + stack: "Static seeders can't be undone. Use VC Seeders instead!" + }); + } else { + seeder.createSeedsTable(function(err) { + if (_assert(err, callback)) { + seeder.down( + internals.argv, + internals.onComplete.bind(this, seeder, internals, callback) + ); + } + }); + } + } + ); +} + +module.exports = executeUndoSeed; From 388facf896a17251d3688b5275270d342127a0f7 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 30 Oct 2017 00:04:52 +0100 Subject: [PATCH 351/412] add eslint to dependencies --- package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package.json b/package.json index f2af0f62..b0361467 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,11 @@ "db-migrate-base": "^1.2.5", "db-migrate-mysql": "^1.1.7", "db-migrate-sqlite3": "^0.1.9", + "eslint": "^4.10.0", + "eslint-plugin-import": "^2.8.0", + "eslint-plugin-node": "^5.2.1", + "eslint-plugin-promise": "^3.6.0", + "eslint-plugin-standard": "^3.0.1", "lab": "^11.1.0", "proxyquire": "^1.4.0", "rimraf": "~2.5.0", From d5a688e2724f247ea7a24cd46305136ab693e920 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 30 Oct 2017 01:19:00 +0100 Subject: [PATCH 352/412] fix a few bugs and update tests --- .tern-port | 2 +- api.js | 4 - lib/commands/create-migration.js | 10 +- lib/commands/helper/register-events.js | 2 + lib/commands/run.js | 16 +- lib/commands/seed.js | 2 +- lib/commands/undo-seed.js | 2 +- test/integration/api_test.js | 239 +++++++++++++------------ 8 files changed, 149 insertions(+), 128 deletions(-) diff --git a/.tern-port b/.tern-port index ecc7cc84..84a49b77 100644 --- a/.tern-port +++ b/.tern-port @@ -1 +1 @@ -45175 \ No newline at end of file +39355 \ No newline at end of file diff --git a/api.js b/api.js index dfcad86b..3794eb10 100644 --- a/api.js +++ b/api.js @@ -437,8 +437,4 @@ dbmigrate.prototype = { } }; -function transition(internals) { - require('./lib/transitions/transitioner.js')(internals); -} - module.exports = dbmigrate; diff --git a/lib/commands/create-migration.js b/lib/commands/create-migration.js index 492a4b26..7341a4c4 100644 --- a/lib/commands/create-migration.js +++ b/lib/commands/create-migration.js @@ -1,6 +1,6 @@ 'use strict'; -var assert = require('../helper/assert'); +var _assert = require('./helper/assert'); var log = require('db-migrate-shared').log; var mkdirp = require('mkdirp'); var fs = require('fs'); @@ -35,8 +35,8 @@ function executeCreateMigration(internals, config, callback) { } createMigrationDir(migrationsDir, function(err) { - var index = require('./connect'); - var Migration = require('./lib/migration.js'); + var index = require('../../connect'); + var Migration = require('../migration.js'); if (err) { log.error('Failed to create migration directory at ', migrationsDir, err); @@ -117,8 +117,8 @@ function createSqlFiles(internals, config, callback) { var sqlDir = migrationsDir + '/sqls'; createMigrationDir(sqlDir, function(err) { - var index = require('./connect'); - var Migration = require('./lib/migration.js'); + var index = require('../../connect'); + var Migration = require('../migration.js'); if (err) { log.error('Failed to create migration directory at ', sqlDir, err); diff --git a/lib/commands/helper/register-events.js b/lib/commands/helper/register-events.js index fd7f521b..f5517b17 100644 --- a/lib/commands/helper/register-events.js +++ b/lib/commands/helper/register-events.js @@ -1,5 +1,7 @@ 'use strict'; +var log = require('db-migrate-shared').log; + function registerEvents() { process.on('uncaughtException', function(err) { log.error(err.stack || err); diff --git a/lib/commands/run.js b/lib/commands/run.js index d1a3e17b..ad2de2e7 100644 --- a/lib/commands/run.js +++ b/lib/commands/run.js @@ -1,5 +1,13 @@ 'use strict'; +var log = require('db-migrate-shared').log; +var optimist = require('optimist'); +var load = require('./'); + +function transition(internals) { + require('../transitions/transitioner.js')(internals); +} + function run(internals, config) { var action = internals.argv._.shift(), folder = action.split(':'); @@ -15,7 +23,7 @@ function run(internals, config) { internals.matching = folder[1]; internals.migrationMode = folder[1]; } - executeCreateMigration(internals, config); + load('create-migration')(internals, config); break; case 'sync': var executeSync = load('sync'); @@ -68,7 +76,7 @@ function run(internals, config) { log.info('Please enter a valid command, i.e. db:create|db:drop'); } else { internals.mode = folder[1]; - executeDB(internals, config); + load('db')(internals, config); } break; case 'seed': @@ -80,9 +88,9 @@ function run(internals, config) { internals.argv.count = Number.MAX_VALUE; internals.argv._.shift(); - executeUndoSeed(internals, config); + load('undo-seed')(internals, config); } else { - executeSeed(internals, config); + load('seed')(internals, config); } break; diff --git a/lib/commands/seed.js b/lib/commands/seed.js index 248b9cfd..e269df38 100644 --- a/lib/commands/seed.js +++ b/lib/commands/seed.js @@ -1,7 +1,7 @@ 'use strict'; var assert = require('assert'); -var _assert = require('../helper/assert'); +var _assert = require('./helper/assert'); function executeSeed(internals, config, callback) { var index = require('./connect'); diff --git a/lib/commands/undo-seed.js b/lib/commands/undo-seed.js index 05dd464a..2ca1b471 100644 --- a/lib/commands/undo-seed.js +++ b/lib/commands/undo-seed.js @@ -1,7 +1,7 @@ 'use strict'; var assert = require('assert'); -var _assert = require('../helper/assert'); +var _assert = require('./helper/assert'); function executeUndoSeed(internals, config, callback) { var index = require('./connect'); diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 3b952c3e..65f9c26a 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -1,89 +1,91 @@ var Code = require('code'); var Lab = require('lab'); -var lab = exports.lab = Lab.script(); +var lab = (exports.lab = Lab.script()); var sinon = require('sinon'); var proxyquire = require('proxyquire').noPreserveCache(); var Promise = require('bluebird'); lab.experiment('api', { parallel: true }, function() { - - lab.test('force process exit after migrations have been run', - { parallel : true}, function(done, onCleanup) { - - var process_exit = process.exit, + lab.test( + 'force process exit after migrations have been run', + { parallel: true }, + function(done, onCleanup) { + var process_exit = process.exit, argv = process.argv, called = false, config = {}; - // register cleanup method and start preparing the test - onCleanup(teardown); - overwriteExit(); + // register cleanup method and start preparing the test + onCleanup(teardown); + overwriteExit(); - var dbmigrate = stubApiInstance(true, { - './lib/commands/up.js': upStub - }, config); + var dbmigrate = stubApiInstance( + true, + { + up: upStub + }, + config + ); - dbmigrate.setConfigParam('force-exit', true); - dbmigrate.silence(true); + dbmigrate.setConfigParam('force-exit', true); + dbmigrate.silence(true); - /** + /** * We have set force-exit above, this should end up in db-migrate * executing process.exit on the final callback. * Process.exit has been overwritten and will finally call validate. * * The test validation takes place in validate() */ - dbmigrate.up(); + dbmigrate.up(); - /** + /** * Final validation after process.exit should have been called. */ - function validate() { - - Code.expect(called).to.be.true(); - done(); - } - - function upStub(internals) { + function validate() { + Code.expect(called).to.be.true(); + done(); + } - internals.onComplete({ - driver: { - close: sinon.stub().callsArg(0) - } - }, internals); - } + function upStub(internals) { + internals.onComplete( + { + driver: { + close: sinon.stub().callsArg(0) + } + }, + internals + ); + } - /** + /** * Create a migration with the programatic API and overwrite process.exit. */ - function overwriteExit() { + function overwriteExit() { + process.exit = function(err) { + var ret = called; + called = true; - process.exit = function(err) { + process.exit = process_exit; - var ret = called; - called = true; + if (err) process.exit.apply(arguments); - process.exit = process_exit; - - if(err) - process.exit.apply(arguments); - - Code.expect(ret).to.be.false(); - validate(); - }; - } - - function teardown(next) { + Code.expect(ret).to.be.false(); + validate(); + }; + } - process.exit = process_exit; - process.argv = argv; - return next(); + function teardown(next) { + process.exit = process_exit; + process.argv = argv; + return next(); + } } - }); - - lab.test('should load config from parameter', { parallel : true}, - function(done) { + ); + lab.test('should load config from parameter', { parallel: true }, function( + done + ) { var options = { env: 'dev', cwd: process.cwd() + '/test/integration', @@ -110,91 +112,93 @@ lab.experiment('api', { parallel: true }, function() { done(); }); - lab.test('should handle all up parameter variations properly', - { parallel: true }, function() { - - return Promise.resolve([ - [], // promise - [sinon.spy()], - ['nameatargetmigration', sinon.spy()], // targeted migration - ['nameatargetmigration'], // promise targeted migration - [1, sinon.spy()], // targeted migration - [1], // promise targeted migration - ['nameatargetmigration', 'testscope', sinon.spy()], // scoped target - ['nameatargetmigration', 'testscope'], // promise scope target - [1, 'testscope', sinon.spy()], // scoped target - [1, 'testscope'] // promise scope target - ]) - .each(defaultExecParams('up')) - .each(spyCallback); - }); - - lab.test('should handle all down parameter variations properly', - { parallel: true }, function() { - + lab.test( + 'should handle all up parameter variations properly', + { parallel: true }, + function() { return Promise.resolve([ [], // promise [sinon.spy()], + ['nameatargetmigration', sinon.spy()], // targeted migration + ['nameatargetmigration'], // promise targeted migration [1, sinon.spy()], // targeted migration [1], // promise targeted migration + ['nameatargetmigration', 'testscope', sinon.spy()], // scoped target + ['nameatargetmigration', 'testscope'], // promise scope target [1, 'testscope', sinon.spy()], // scoped target [1, 'testscope'] // promise scope target ]) - .each(defaultExecParams('down')) - .each(spyCallback); - }); + .each(defaultExecParams('up')) + .each(spyCallback); + } + ); - lab.test('should handle all reset parameter variations properly', - { parallel: true }, function() { + lab.test( + 'should handle all down parameter variations properly', + { parallel: true }, + function() { + return Promise.resolve([ + [], // promise + [sinon.spy()], + [1, sinon.spy()], // targeted migration + [1], // promise targeted migration + [1, 'testscope', sinon.spy()], // scoped target + [1, 'testscope'] // promise scope target + ]) + .each(defaultExecParams('down')) + .each(spyCallback); + } + ); + lab.test( + 'should handle all reset parameter variations properly', + { parallel: true }, + function() { return Promise.resolve([ [], // promise [sinon.spy()], ['testscope', sinon.spy()], // scoped target ['testscope'] // promise scope target ]) - .each(defaultExecParams('reset')) - .each(spyCallback); - }); + .each(defaultExecParams('reset')) + .each(spyCallback); + } + ); - lab.test('should handle all sync parameter variations properly', - { parallel: true }, function() { - - return Promise.resolve([ - [], - ['nameatargetmigration', sinon.spy()], // targeted migration - ['nameatargetmigration'], // promise targeted migration - ['nameatargetmigration', 'testscope', sinon.spy()], // scoped target - ['nameatargetmigration', 'testscope'], // promise scope target - ]) - .each(defaultExecParams('sync')) - .each(spyCallback); - }); + lab.test( + 'should handle all sync parameter variations properly', + { parallel: true }, + function() { + return Promise.resolve([ + [], + ['nameatargetmigration', sinon.spy()], // targeted migration + ['nameatargetmigration'], // promise targeted migration + ['nameatargetmigration', 'testscope', sinon.spy()], // scoped target + ['nameatargetmigration', 'testscope'] // promise scope target + ]) + .each(defaultExecParams('sync')) + .each(spyCallback); + } + ); }); function defaultExecParams(method) { - return function(args, index) { - var stubs = {}; stubs['./lib/commands/' + method + '.js'] = stub; var api = stubApiInstance(true, stubs); - return [ api[method].apply(api, args), args ]; + return [api[method].apply(api, args), args]; function stub(internals, config, callback) { - - if(typeof(args[0]) === 'string') { - + if (typeof args[0] === 'string') { Code.expect(internals.argv.destination).to.equal(args[0]); - } else if(typeof(args[0]) === 'number') { - + } else if (typeof args[0] === 'number') { Code.expect(internals.argv.count).to.equal(args[0]); } - if(typeof(args[1]) === 'string') { - + if (typeof args[1] === 'string') { Code.expect(internals.migrationMode).to.equal(args[1]); Code.expect(internals.matching).to.equal(args[1]); } @@ -205,20 +209,31 @@ function defaultExecParams(method) { } function spyCallback(api, args) { - - if(typeof(args[args.length - 1]) === 'function') { - + if (typeof args[args.length - 1] === 'function') { var spy = args[args.length - 1]; Code.expect(spy.called).to.be.true(); } } -function stubApiInstance(isModule, stubs, options, callback) { +function loader(stubs) { + var load = require('../../lib/commands'); + var keys = Object.keys(stubs); + return function(module) { + var index = keys.indexOf(module); + if (index !== -1) { + return stubs[keys[index]]; + } + return load(module); + }; +} +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), - plugins = {}; + var mod = proxyquire('../../api.js', { + './lib/commands': loader(stubs) + }), + plugins = {}; options = options || {}; options = Object.assign(options, { From d811fae894eb0dd7221cb57c6a99c4b9016342bf Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 30 Oct 2017 01:23:57 +0100 Subject: [PATCH 353/412] fix last tests --- test/integration/api_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 65f9c26a..3868db65 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -185,7 +185,7 @@ lab.experiment('api', { parallel: true }, function() { function defaultExecParams(method) { return function(args, index) { var stubs = {}; - stubs['./lib/commands/' + method + '.js'] = stub; + stubs[method] = stub; var api = stubApiInstance(true, stubs); From 9e71c2a66093de44a60815441fea37e802d931a0 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 11 Nov 2017 17:54:56 +0100 Subject: [PATCH 354/412] adjust to cs --- .eslintrc | 2 +- .tern-port | 1 - api.js | 80 ++-- bin/db-migrate | 47 +-- connect.js | 102 ++--- index.js | 11 +- lib/class.js | 23 +- lib/commands/create-migration.js | 24 +- lib/commands/db.js | 8 +- lib/commands/down.js | 40 +- lib/commands/fn/plugin.js | 8 +- lib/commands/helper/assert.js | 7 +- lib/commands/helper/load-config.js | 2 +- lib/commands/helper/migration-hook.js | 3 +- lib/commands/helper/register-events.js | 6 +- lib/commands/index.js | 2 +- lib/commands/on-complete.js | 13 +- lib/commands/run.js | 7 +- lib/commands/seed.js | 6 +- lib/commands/set-default-argv.js | 60 ++- lib/commands/sync.js | 59 ++- lib/commands/undo-seed.js | 6 +- lib/commands/up.js | 59 ++- lib/config.js | 109 ++---- lib/driver/index.js | 61 +-- lib/driver/shadow.js | 28 +- lib/interface/migratorInterface.js | 15 +- lib/interface/seederInterface.js | 108 +++--- lib/migration.js | 78 ++-- lib/migrator.js | 198 ++++------ lib/relation.js | 55 ++- lib/seeder.js | 234 +++++------ lib/skeleton.js | 123 +++--- lib/transitions/1.js | 5 +- lib/transitions/ask.js | 15 +- lib/transitions/transitioner.js | 86 ++--- lib/transitions/try-require.js | 46 +-- lib/transitions/update-version.js | 16 +- package.json | 1 + test/config_test.js | 512 ++++++++++++------------- test/driver/base_test.js | 103 +++-- test/driver/index_test.js | 264 ++++++------- test/driver/shadow_test.js | 32 +- test/integration/api_test.js | 38 +- test/integration/create_test.js | 463 ++++++++++------------ test/migration_test.js | 318 +++++++-------- test/util_test.js | 53 ++- 47 files changed, 1553 insertions(+), 1984 deletions(-) delete mode 100644 .tern-port diff --git a/.eslintrc b/.eslintrc index 7728755f..657d4a56 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,7 +2,7 @@ "extends": "standard", "rules": { "semi": ["error", "always"], - "no-unused-vars": "warn" + "no-unused-vars": "warn", "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }] } } diff --git a/.tern-port b/.tern-port deleted file mode 100644 index 84a49b77..00000000 --- a/.tern-port +++ /dev/null @@ -1 +0,0 @@ -39355 \ No newline at end of file diff --git a/api.js b/api.js index 3794eb10..3d76a5a7 100644 --- a/api.js +++ b/api.js @@ -8,16 +8,15 @@ var onComplete = load('on-complete'); // constant hooks for this file var APIHooks = { - 'init:api:addfunction:hook': function(name, fn) { + 'init:api:addfunction:hook': function (name, fn) { this[name] = fn; - return; }, - 'init:api:accessapi:hook': function(cb) { + 'init:api:accessapi:hook': function (cb) { return cb(this); } }; -function dbmigrate(plugins, isModule, options, callback) { +function dbmigrate (plugins, isModule, options, callback) { var dotenv = require('dotenv'); var setDefaultArgv = load('set-default-argv'); @@ -44,10 +43,7 @@ function dbmigrate(plugins, isModule, options, callback) { /* $lab:coverage:on$ */ if (typeof options === 'object') { - if (typeof options.config === 'string') - internals.configFile = options.config; - else if (typeof options.config === 'object') - internals.configObject = options.config; + if (typeof options.config === 'string') { internals.configFile = options.config; } else if (typeof options.config === 'object') { internals.configObject = options.config; } if (typeof options.env === 'string') internals.currentEnv = options.env; @@ -65,7 +61,7 @@ function dbmigrate(plugins, isModule, options, callback) { this.internals ); - //delayed loading of bluebird + // delayed loading of bluebird Promise = require('bluebird'); this.internals.migrationOptions = { dbmigrate: this.internals.dbm, @@ -85,7 +81,7 @@ dbmigrate.prototype = { * * @return boolean */ - addGlobal: function(library) { + addGlobal: function (library) { try { require(library); } catch (e) { @@ -100,22 +96,22 @@ dbmigrate.prototype = { * * @returns Promise */ - registerAPIHook: function(callback) { + registerAPIHook: function (callback) { var plugins = this.internals.plugins; var self = this; return Promise.resolve(Object.keys(APIHooks)) - .each(function(hook) { + .each(function (hook) { var plugin = plugins.hook(hook); if (!plugin) return; var APIHook = APIHooks[hook].bind(self); return Promise.resolve(plugin) - .map(function(plugin) { + .map(function (plugin) { return plugin[hook](); }) - .each(function(args) { + .each(function (args) { return APIHook.apply(self, args); }); }) @@ -129,7 +125,7 @@ dbmigrate.prototype = { * * @return boolean */ - addConfiguration: function(description, args, type) { + addConfiguration: function (description, args, type) { var name = args.shift(); this.internals.argv.describe(name, description); @@ -156,7 +152,7 @@ dbmigrate.prototype = { /** * Resets and sets argv to a specified new argv. */ - resetConfiguration: function(argv) { + resetConfiguration: function (argv) { this.internals.argv = argv; }, @@ -165,7 +161,7 @@ dbmigrate.prototype = { * * Defaults to up all migrations if no count is given. */ - up: function(specification, opts, callback) { + up: function (specification, opts, callback) { var executeUp = load('up'); if (arguments.length > 0) { @@ -186,7 +182,7 @@ dbmigrate.prototype = { } return Promise.fromCallback( - function(callback) { + function (callback) { executeUp(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -197,7 +193,7 @@ dbmigrate.prototype = { * * Defaults to up all migrations if no count is given. */ - down: function(specification, opts, callback) { + down: function (specification, opts, callback) { var executeDown = load('down'); if (arguments.length > 0) { @@ -216,7 +212,7 @@ dbmigrate.prototype = { } return Promise.fromCallback( - function(callback) { + function (callback) { executeDown(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -227,7 +223,7 @@ dbmigrate.prototype = { * * Defaults to up all migrations if no count is given. */ - sync: function(specification, opts, callback) { + sync: function (specification, opts, callback) { var executeSync = load('sync'); if (arguments.length > 0) { @@ -244,7 +240,7 @@ dbmigrate.prototype = { } return Promise.fromCallback( - function(callback) { + function (callback) { executeSync(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -253,7 +249,7 @@ dbmigrate.prototype = { /** * Executes down for all currently migrated migrations. */ - reset: function(scope, callback) { + reset: function (scope, callback) { var executeDown = load('down'); if (typeof scope === 'string') { @@ -265,7 +261,7 @@ dbmigrate.prototype = { this.internals.argv.count = Number.MAX_VALUE; return Promise.fromCallback( - function(callback) { + function (callback) { executeDown(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -274,21 +270,21 @@ dbmigrate.prototype = { /** * Silence the log output completely. */ - silence: function(isSilent) { + silence: function (isSilent) { return log.silence(isSilent); }, /** * Transition migrations to the latest defined protocol. */ - transition: function() { + transition: function () { transition(this.internals); }, /** * Creates a correctly formatted migration */ - create: function(migrationName, scope, callback) { + create: function (migrationName, scope, callback) { var executeCreateMigration = load('create-migration'); if (typeof scope === 'function') { callback = scope; @@ -299,7 +295,7 @@ dbmigrate.prototype = { this.internals.argv._.push(migrationName); return Promise.fromCallback( - function(callback) { + function (callback) { executeCreateMigration(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -308,12 +304,12 @@ dbmigrate.prototype = { /** * Creates a database of the given dbname. */ - createDatabase: function(dbname, callback) { + createDatabase: function (dbname, callback) { var executeDB = load('db'); this.internals.argv._.push(dbname); this.internals.mode = 'create'; return Promise.fromCallback( - function(callback) { + function (callback) { executeDB(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -322,12 +318,12 @@ dbmigrate.prototype = { /** * Drops a database of the given dbname. */ - dropDatabase: function(dbname, callback) { + dropDatabase: function (dbname, callback) { var executeDB = load('db'); this.internals.argv._.push(dbname); this.internals.mode = 'drop'; return Promise.fromCallback( - function(callback) { + function (callback) { executeDB(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -338,14 +334,14 @@ dbmigrate.prototype = { * * @return value */ - setConfigParam: function(param, value) { + setConfigParam: function (param, value) { return (this.internals.argv[param] = value); }, /** * Sets the callback to the default onComplete */ - setDefaultCallback: function() { + setDefaultCallback: function () { this.internals.onComplete = onComplete; }, @@ -353,7 +349,7 @@ dbmigrate.prototype = { * Let's the user customize the callback, which gets called after all * migrations have been done. */ - setCustomCallback: function(callback) { + setCustomCallback: function (callback) { this.internals.onComplete = callback; }, @@ -361,7 +357,7 @@ dbmigrate.prototype = { * Seeds either the static or version controlled seeders, controlled by * the passed mode. */ - seed: function(mode, scope, callback) { + seed: function (mode, scope, callback) { var executeSeed = load('seed'); if (scope) { this.internals.migrationMode = scope; @@ -370,7 +366,7 @@ dbmigrate.prototype = { this.internals.mode = mode || 'vc'; return Promise.fromCallback( - function(callback) { + function (callback) { executeSeed(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -379,7 +375,7 @@ dbmigrate.prototype = { /** * Execute the down function of currently executed seeds. */ - undoSeed: function(specification, scope, callback) { + undoSeed: function (specification, scope, callback) { var executeUndoSeed = load('undo-seed'); if (arguments.length > 0) { if (typeof specification === 'number') { @@ -396,7 +392,7 @@ dbmigrate.prototype = { } return Promise.fromCallback( - function(callback) { + function (callback) { executeUndoSeed(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -405,7 +401,7 @@ dbmigrate.prototype = { /** * Execute the reset function of currently executed seeds. */ - resetSeed: function(specification, scope, callback) { + resetSeed: function (specification, scope, callback) { var executeUndoSeed = load('undo-seed'); if (arguments.length > 0) { if (typeof specification === 'number') { @@ -423,7 +419,7 @@ dbmigrate.prototype = { this.internals.argv.count = Number.MAX_VALUE; return Promise.fromCallback( - function(callback) { + function (callback) { executeUndoSeed(this.internals, this.config, callback); }.bind(this) ).asCallback(callback); @@ -432,7 +428,7 @@ dbmigrate.prototype = { /** * Executes the default routine. */ - run: function() { + run: function () { load('run')(this.internals, this.config); } }; diff --git a/bin/db-migrate b/bin/db-migrate index 39e880e2..65f41f9e 100755 --- a/bin/db-migrate +++ b/bin/db-migrate @@ -1,44 +1,39 @@ #!/usr/bin/env node -var resolve = require( 'resolve' ); +var resolve = require('resolve'); var log = require('db-migrate-shared').log; process.title = 'db-migrate'; -if ( process.argv.indexOf( '--verbose' ) !== -1 || - process.argv.indexOf( '-v' ) !== -1 - ) - global.verbose = true; +if (process.argv.indexOf('--verbose') !== -1 || + process.argv.indexOf('-v') !== -1 +) { global.verbose = true; } -resolve( 'db-migrate', { +resolve('db-migrate', { basedir: process.cwd() -}, function ( error, localModule ) { - +}, function (error, localModule) { var DBMigrate, dbmigrate; - if ( error ) { - DBMigrate = require( '../' ); - } - else { - DBMigrate = require( localModule ); - log.verbose( 'Detected and using the projects local version of db-migrate. ' + + if (error) { + DBMigrate = require('../'); + } else { + DBMigrate = require(localModule); + log.verbose('Detected and using the projects local version of db-migrate. ' + '\'' + localModule + '\''); } - if ( typeof( DBMigrate.getInstance ) !== 'function' ) { - DBMigrate = require( '../' ); + if (typeof (DBMigrate.getInstance) !== 'function') { + DBMigrate = require('../'); - log.warn( 'Using global instead of local detected version as you have a ' + - 'version older than 0.10.0 in your projects package.json!' ); + log.warn('Using global instead of local detected version as you have a ' + + 'version older than 0.10.0 in your projects package.json!'); } dbmigrate = DBMigrate.getInstance(); - if(dbmigrate.registerAPIHook) + if (dbmigrate.registerAPIHook) { dbmigrate.registerAPIHook() - .then( function() { - - dbmigrate.run(); - } ); - else - dbmigrate.run(); -} ); + .then(function () { + dbmigrate.run(); + }); + } else { dbmigrate.run(); } +}); diff --git a/connect.js b/connect.js index b4a67e20..a362b119 100644 --- a/connect.js +++ b/connect.js @@ -6,76 +6,66 @@ var log = require('db-migrate-shared').log; var internals = {}; -exports.connect = function(config, passedClass, callback) { +exports.connect = function (config, passedClass, callback) { var internals = {}; - if( config.config ) { + if (config.config) { internals = config.internals; config = config.config; } - driver.connect(config, internals, function(err, db) { + driver.connect(config, internals, function (err, db) { if (err) { callback(err); return; } - if(internals.migrationMode) - { + if (internals.migrationMode) { var dirPath = path.resolve(config['migrations-dir'] || 'migrations'); - if(internals.migrationMode !== 'all') - { + if (internals.migrationMode !== 'all') { var switched = false, - newConf; + newConf; try { newConf = require(path.resolve(config['migrations-dir'] || 'migrations', internals.migrationMode) + '/config.json'); log.info('loaded extra config for migration subfolder: "' + internals.migrationMode + '/config.json"'); switched = true; - } catch(e) {} + } catch (e) {} - if(switched) { - - db.switchDatabase(newConf, function() - { + if (switched) { + db.switchDatabase(newConf, function () { internals.locTitle = internals.migrationMode; callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); }); - } - else - { + } else { internals.locTitle = internals.migrationMode; callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); } - } - else - { - recursive(dirPath, false, config['migrations-dir'] || 'migrations') - .then(function(files) { - var oldClose = db.close; - - files = files.filter(function (file) { - return file !== 'migrations' && fs.statSync(file).isDirectory(); - }); + } else { + recursive(dirPath, false, config['migrations-dir'] || 'migrations') + .then(function (files) { + var oldClose = db.close; - files.push(''); + files = files.filter(function (file) { + return file !== 'migrations' && fs.statSync(file).isDirectory(); + }); - db.close = function(cb) { migrationFiles(files, callback, config, - internals, passedClass, db, oldClose, cb); }; + files.push(''); - db.close(); - }); - } - } - else - callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); + db.close = function (cb) { + migrationFiles(files, callback, config, + internals, passedClass, db, oldClose, cb); + }; + db.close(); + }); + } + } else { callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); } }); }; -exports.driver = function(config, callback) { - +exports.driver = function (config, callback) { var internals = {}; var _config = config; - if( config.config ) { + if (config.config) { internals = config.internals; config = config.config; } @@ -83,54 +73,44 @@ exports.driver = function(config, callback) { driver.connect(config, internals, callback); }; -function migrationFiles(files, callback, config, internals, - passedClass, db, close, cb) { +function migrationFiles (files, callback, config, internals, + passedClass, db, close, cb) { var file, - switched = false, - newConf; + switched = false, + newConf; - if(files.length === 1) - { + if (files.length === 1) { db.close = close; } file = files.pop(); - log.info( 'Enter scope "' + ((file !== '') ? file : '/') + '"' ); + log.info('Enter scope "' + ((file !== '') ? file : '/') + '"'); - if(file !== '') - { + if (file !== '') { try { fs.statSync(path.resolve(file + '/config.json')); newConf = require(path.resolve(file + '/config.json')); log.info('loaded extra config for migration subfolder: "' + file + '/config.json"'); switched = true; - } catch(e) {} + } catch (e) {} } - db.switchDatabase((switched) ? newConf : config.database, function() - { + db.switchDatabase((switched) ? newConf : config.database, function () { internals.matching = file.substr(file.indexOf(config['migrations-dir'] || 'migrations') + (config['migrations-dir'] || 'migrations').length + 1); - if(internals.matching.length === 0) - internals.matching = ''; - + if (internals.matching.length === 0) { internals.matching = ''; } internals.locTitle = internals.matching; callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); - if(typeof(cb) === 'function') - cb(); - + if (typeof (cb) === 'function') { cb(); } }); } -exports.createMigration = function(migration, callback) { - - migration.write(function(err) { - +exports.createMigration = function (migration, callback) { + migration.write(function (err) { if (err) { - callback(err); return; } diff --git a/index.js b/index.js index 30279a08..d8cdae33 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,7 @@ var path = require('path'); exports.dataType = require('db-migrate-shared').dataType; -function loadPluginList() { +function loadPluginList () { var plugins = JSON.parse( fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8') ), @@ -19,7 +19,7 @@ function loadPluginList() { return targets; } -function loadPlugins() { +function loadPlugins () { var plugins = loadPluginList(), i = 0, length = plugins.length, @@ -28,10 +28,9 @@ function loadPlugins() { for (; i < length; ++i) { var plugin = require(path.join(process.cwd(), 'node_modules', plugins[i])); - if (typeof plugin.name !== 'string' || !plugin.hooks || !plugin.loadPlugin) - continue; + if (typeof plugin.name !== 'string' || !plugin.hooks || !plugin.loadPlugin) { continue; } - plugin.hooks.map(function(hook) { + plugin.hooks.map(function (hook) { hooks[hook] = hooks[hook] || []; hooks[hook].push(plugin); }); @@ -40,7 +39,7 @@ function loadPlugins() { return hooks; } -module.exports.getInstance = function(isModule, options, callback) { +module.exports.getInstance = function (isModule, options, callback) { delete require.cache[require.resolve('./api.js')]; delete require.cache[require.resolve('optimist')]; var mod = require('./api.js'), diff --git a/lib/class.js b/lib/class.js index 155c7774..105163af 100644 --- a/lib/class.js +++ b/lib/class.js @@ -3,13 +3,13 @@ * MIT Licensed. */ // Inspired by base2 and Prototype -var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; +var initializing = false, fnTest = /xyz/.test(function () { xyz; }) ? /\b_super\b/ : /.*/; // The base Class implementation (does nothing) -var Class = function(){}; +var Class = function () {}; // Create a new Class that inherits from this class -Class.extend = function ext(prop) { +Class.extend = function ext (prop) { var _super = this.prototype; // Instantiate a base class (but only create the instance, @@ -21,10 +21,10 @@ Class.extend = function ext(prop) { // Copy the properties over onto the new prototype for (var name in prop) { // Check if we're overwriting an existing function - prototype[name] = typeof prop[name] === "function" && - typeof _super[name] === "function" && fnTest.test(prop[name]) ? - (function(name, fn){ - return function() { + prototype[name] = typeof prop[name] === 'function' && + typeof _super[name] === 'function' && fnTest.test(prop[name]) + ? (function (name, fn) { + return function () { var tmp = this._super; // Add a new ._super() method that is the same method @@ -38,15 +38,14 @@ Class.extend = function ext(prop) { return ret; }; - })(name, prop[name]) : - prop[name]; + })(name, prop[name]) + : prop[name]; } // The dummy class constructor - function Class() { + function Class () { // All construction is actually done in the init method - if ( !initializing && this.init ) - this.init.apply(this, arguments); + if (!initializing && this.init) { this.init.apply(this, arguments); } } // Populate our constructed prototype object diff --git a/lib/commands/create-migration.js b/lib/commands/create-migration.js index 7341a4c4..d778372c 100644 --- a/lib/commands/create-migration.js +++ b/lib/commands/create-migration.js @@ -6,8 +6,8 @@ var mkdirp = require('mkdirp'); var fs = require('fs'); var util = require('util'); -function createMigrationDir(dir, callback) { - fs.stat(dir, function(err) { +function createMigrationDir (dir, callback) { + fs.stat(dir, function (err) { if (err) { mkdirp(dir, callback); } else { @@ -16,7 +16,7 @@ function createMigrationDir(dir, callback) { }); } -function executeCreateMigration(internals, config, callback) { +function executeCreateMigration (internals, config, callback) { var migrationsDir = internals.argv['migrations-dir']; internals.runTimestamp = new Date(); @@ -34,7 +34,7 @@ function executeCreateMigration(internals, config, callback) { process.exit(1); } - createMigrationDir(migrationsDir, function(err) { + createMigrationDir(migrationsDir, function (err) { var index = require('../../connect'); var Migration = require('../migration.js'); @@ -80,7 +80,7 @@ function executeCreateMigration(internals, config, callback) { internals.runTimestamp, templateType ); - index.createMigration(migration, function(err, migration) { + index.createMigration(migration, function (err, migration) { if (_assert(err, callback)) { log.info(util.format('Created migration at %s', migration.path)); if (shouldCreateSqlFiles(internals, config)) { @@ -95,19 +95,19 @@ function executeCreateMigration(internals, config, callback) { }); } -function shouldCreateSqlFiles(internals, config) { +function shouldCreateSqlFiles (internals, config) { return internals.argv['sql-file'] || config['sql-file']; } -function shouldIgnoreOnInitFiles(internals, config) { +function shouldIgnoreOnInitFiles (internals, config) { return internals.argv['ignore-on-init'] || config['ignore-on-init']; } -function shouldCreateCoffeeFile(internals, config) { +function shouldCreateCoffeeFile (internals, config) { return internals.argv['coffee-file'] || config['coffee-file']; } -function createSqlFiles(internals, config, callback) { +function createSqlFiles (internals, config, callback) { var migrationsDir = internals.argv['migrations-dir']; if (internals.migrationMode && internals.migrationMode !== 'all') { @@ -116,7 +116,7 @@ function createSqlFiles(internals, config, callback) { } var sqlDir = migrationsDir + '/sqls'; - createMigrationDir(sqlDir, function(err) { + createMigrationDir(sqlDir, function (err) { var index = require('../../connect'); var Migration = require('../migration.js'); @@ -137,7 +137,7 @@ function createSqlFiles(internals, config, callback) { internals.runTimestamp, templateTypeDefaultSQL ); - index.createMigration(migrationUpSQL, function(err, migration) { + index.createMigration(migrationUpSQL, function (err, migration) { if (_assert(err, callback)) { log.info( util.format('Created migration up sql file at %s', migration.path) @@ -149,7 +149,7 @@ function createSqlFiles(internals, config, callback) { internals.runTimestamp, templateTypeDefaultSQL ); - index.createMigration(migrationDownSQL, function(err, migration) { + index.createMigration(migrationDownSQL, function (err, migration) { if (_assert(err, callback)) { log.info( util.format( diff --git a/lib/commands/db.js b/lib/commands/db.js index 9e645322..eb22e83e 100644 --- a/lib/commands/db.js +++ b/lib/commands/db.js @@ -1,6 +1,6 @@ 'use strict'; -function executeDB(internals, config, callback) { +function executeDB (internals, config, callback) { var index = require('./connect'); if (internals.argv._.length > 0) { @@ -10,7 +10,7 @@ function executeDB(internals, config, callback) { return; } - index.driver(config.getCurrent().settings, function(err, db) { + index.driver(config.getCurrent().settings, function (err, db) { assert.ifError(err); if (internals.mode === 'create') { @@ -19,7 +19,7 @@ function executeDB(internals, config, callback) { { ifNotExists: true }, - function(err) { + function (err) { if (err) { if (err.error) err = err.error; log.info('Error: Failed to create database!', err); @@ -37,7 +37,7 @@ function executeDB(internals, config, callback) { { ifExists: true }, - function(err) { + function (err) { if (err) { if (err.error) err = err.error; log.info('Error: Failed to drop database!', err); diff --git a/lib/commands/down.js b/lib/commands/down.js index dbe3f657..4454f1ed 100644 --- a/lib/commands/down.js +++ b/lib/commands/down.js @@ -3,32 +3,30 @@ var log = require('db-migrate-shared').log; var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); -module.exports = function(internals, config, callback) { - +module.exports = function (internals, config, callback) { migrationHook(internals) - .then(function() { - - var Migrator = require('../migrator.js'); - var index = require('../../connect'); + .then(function () { + var Migrator = require('../migrator.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({ - config: config.getCurrent().settings, - internals: internals - }, Migrator, function(err, migrator) { - if(!assert(err)) return; + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, Migrator, function (err, migrator) { + if (!assert(err)) return; - migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); + 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.driver.createMigrationsTable(function (err) { + if (!assert(err)) return; + migrator.down(internals.argv, internals.onComplete.bind(this, + migrator, internals, callback)); }); }); - }); + }); }; diff --git a/lib/commands/fn/plugin.js b/lib/commands/fn/plugin.js index 24c604ed..a581c7fe 100644 --- a/lib/commands/fn/plugin.js +++ b/lib/commands/fn/plugin.js @@ -2,9 +2,9 @@ const log = require('db-migrate-shared').log; -function registerPluginLoader(plugins) { +function registerPluginLoader (plugins) { return { - overwrite: function(name) { + overwrite: function (name) { if (plugins[name] && plugins[name].length) { var plugin = plugins[name]; @@ -26,11 +26,11 @@ function registerPluginLoader(plugins) { return false; }, - hook: function(name) { + hook: function (name) { if (plugins[name] && plugins[name].length) { var plugin = plugins[name]; - plugin.map(function(plugin) { + plugin.map(function (plugin) { if (typeof plugin.loadPlugin === 'function') plugin.loadPlugin(); }); diff --git a/lib/commands/helper/assert.js b/lib/commands/helper/assert.js index 4bd6f442..ad9d0888 100644 --- a/lib/commands/helper/assert.js +++ b/lib/commands/helper/assert.js @@ -1,14 +1,11 @@ var assert = require('assert'); -module.exports = function(err, callback) { +module.exports = function (err, callback) { if (err) { - - if (typeof(callback) === 'function') { - + if (typeof (callback) === 'function') { callback(err); return false; } else { - assert.ifError(err); return false; } diff --git a/lib/commands/helper/load-config.js b/lib/commands/helper/load-config.js index b26063f2..2327223f 100644 --- a/lib/commands/helper/load-config.js +++ b/lib/commands/helper/load-config.js @@ -1,6 +1,6 @@ 'use strict'; -function loadConfig(config, internals) { +function loadConfig (config, internals) { var out, currentEnv = internals.currentEnv || internals.argv.env; diff --git a/lib/commands/helper/migration-hook.js b/lib/commands/helper/migration-hook.js index f9ed96ff..cb69a90e 100644 --- a/lib/commands/helper/migration-hook.js +++ b/lib/commands/helper/migration-hook.js @@ -1,6 +1,5 @@ -module.exports = function(internals) { - +module.exports = function (internals) { var Migration = require('../../migration.js'); return Migration.registerHook(internals.plugins, internals); }; diff --git a/lib/commands/helper/register-events.js b/lib/commands/helper/register-events.js index f5517b17..5a4a0eb2 100644 --- a/lib/commands/helper/register-events.js +++ b/lib/commands/helper/register-events.js @@ -2,13 +2,13 @@ var log = require('db-migrate-shared').log; -function registerEvents() { - process.on('uncaughtException', function(err) { +function registerEvents () { + process.on('uncaughtException', function (err) { log.error(err.stack || err); process.exit(1); }); - process.on('unhandledRejection', function(reason) { + process.on('unhandledRejection', function (reason) { log.error(reason.stack || reason); process.exit(1); }); diff --git a/lib/commands/index.js b/lib/commands/index.js index 633018f7..e00162ef 100644 --- a/lib/commands/index.js +++ b/lib/commands/index.js @@ -2,7 +2,7 @@ var path = require('path'); -function register(module) { +function register (module) { return require(path.resolve(__dirname, module)); } diff --git a/lib/commands/on-complete.js b/lib/commands/on-complete.js index b064231a..724a2b09 100644 --- a/lib/commands/on-complete.js +++ b/lib/commands/on-complete.js @@ -1,22 +1,19 @@ var assert = require('assert'); var log = require('db-migrate-shared').log; -module.exports = function(migrator, internals, callback, originalErr) { - if (typeof(callback) !== 'function') { +module.exports = function (migrator, internals, callback, originalErr) { + if (typeof (callback) !== 'function') { originalErr = originalErr || callback; } - migrator.driver.close(function(err) { - - if ((err || originalErr) && typeof(callback) === 'function') { - + migrator.driver.close(function (err) { + if ((err || originalErr) && typeof (callback) === 'function') { callback({ err: err, originalErr: originalErr }); return; } else { - assert.ifError(originalErr); assert.ifError(err); log.info('Done'); @@ -27,7 +24,7 @@ module.exports = function(migrator, internals, callback, originalErr) { return process.exit(0); } - if (typeof(callback) === 'function') { + if (typeof (callback) === 'function') { callback(); } }); diff --git a/lib/commands/run.js b/lib/commands/run.js index ad2de2e7..7f26439a 100644 --- a/lib/commands/run.js +++ b/lib/commands/run.js @@ -4,11 +4,11 @@ var log = require('db-migrate-shared').log; var optimist = require('optimist'); var load = require('./'); -function transition(internals) { +function transition (internals) { require('../transitions/transitioner.js')(internals); } -function run(internals, config) { +function run (internals, config) { var action = internals.argv._.shift(), folder = action.split(':'); @@ -84,8 +84,7 @@ function run(internals, config) { internals.migrationMode = folder[2]; if (internals.argv._[0] === 'down' || internals.argv._[0] === 'reset') { - if (internals.argv._[0] === 'reset') - internals.argv.count = Number.MAX_VALUE; + if (internals.argv._[0] === 'reset') { internals.argv.count = Number.MAX_VALUE; } internals.argv._.shift(); load('undo-seed')(internals, config); diff --git a/lib/commands/seed.js b/lib/commands/seed.js index e269df38..f8a6326c 100644 --- a/lib/commands/seed.js +++ b/lib/commands/seed.js @@ -3,7 +3,7 @@ var assert = require('assert'); var _assert = require('./helper/assert'); -function executeSeed(internals, config, callback) { +function executeSeed (internals, config, callback) { var index = require('./connect'); var Seeder = require('./lib/seeder.js'); @@ -17,7 +17,7 @@ function executeSeed(internals, config, callback) { internals: internals }, Seeder, - function(err, seeder) { + function (err, seeder) { assert.ifError(err); seeder.seedDir = path.resolve( @@ -32,7 +32,7 @@ function executeSeed(internals, config, callback) { internals.onComplete.bind(this, seeder, internals, callback) ); } else { - seeder.createSeedsTable(function(err) { + seeder.createSeedsTable(function (err) { if (_assert(err, callback)) { seeder.seed( internals.argv, diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index 19a617e6..4599099a 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -1,7 +1,7 @@ var optimist = require('optimist'); var log = require('db-migrate-shared').log; -module.exports = function(internals, isModule) { +module.exports = function (internals, isModule) { var rc = require('rc'); var deepExtend = require('deep-extend'); var defaultConfig = { @@ -18,93 +18,90 @@ module.exports = function(internals, isModule) { 'ignore-completed-migrations': false }; - if(!isModule) { - + if (!isModule) { internals.argv = optimist .default(defaultConfig) .usage( 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + '[[dbname/]migrationName|all] [options]' ) - .describe('env', + .describe('env', 'The environment to run the migrations under (dev, test, prod).') .alias('e', 'env') .string('e') - .describe('migrations-dir', 'The directory containing your migration files.') + .describe('migrations-dir', 'The directory containing your migration files.') .alias('m', 'migrations-dir') .string('m') - .describe('count', 'Max number of migrations to run.') + .describe('count', 'Max number of migrations to run.') .alias('c', 'count') .string('c') - .describe('dry-run', 'Prints the SQL but doesn\'t run it.') + .describe('dry-run', 'Prints the SQL but doesn\'t run it.') .boolean('dry-run') - .describe('force-exit', 'Forcibly exit the migration process on completion.') + .describe('force-exit', 'Forcibly exit the migration process on completion.') .boolean('force-exit') - .describe('verbose', 'Verbose mode.') + .describe('verbose', 'Verbose mode.') .alias('v', 'verbose') .boolean('v') - .alias('h', 'help') + .alias('h', 'help') .alias('h', '?') .boolean('h') - .describe('version', 'Print version info.') + .describe('version', 'Print version info.') .alias('i', 'version') .boolean('version') - .describe('config', 'Location of the database.json file.') + .describe('config', 'Location of the database.json file.') .string('config') - .describe('sql-file', + .describe('sql-file', 'Automatically create two sql files for up and down statements in ' + '/sqls and generate the javascript code that loads them.' ) .boolean('sql-file') - .describe('coffee-file', 'Create a coffeescript migration file') + .describe('coffee-file', 'Create a coffeescript migration file') .boolean('coffee-file') .describe('ignore-on-init', 'Create files that will run only if ignore-on-init in the env is set ' + 'to false (currently works only with SQL)' ).boolean('ignore-on-init') - .describe('migration-table', + .describe('migration-table', 'Set the name of the migration table, which stores the migration history.' ) .alias('table', 'migration-table') .alias('t', 'table') .string('t') - .describe('seeds-table', + .describe('seeds-table', 'Set the name of the seeds table, which stores the seed history.') .string('seeds-table') - .describe('vcseeder-dir', + .describe('vcseeder-dir', 'Set the path to the Version Controlled Seeder directory.') .string('vcseeder-dir') - .describe('staticseeder-dir', 'Set the path to the Seeder directory.') + .describe('staticseeder-dir', 'Set the path to the Seeder directory.') .string('staticseeder-dir') - .describe('non-transactional', 'Explicitly disable transactions') + .describe('non-transactional', 'Explicitly disable transactions') .boolean('non-transactional') - .describe('ignore-completed-migrations', 'Start at the first migration') + .describe('ignore-completed-migrations', 'Start at the first migration') .boolean('ignore-completed-migrations') - .describe('log-level', 'Set the log-level, for example sql|warn') + .describe('log-level', 'Set the log-level, for example sql|warn') .string('log-level'); - } - else { - + } else { internals.argv = { - get argv() { + get argv () { return defaultConfig; } }; @@ -114,15 +111,12 @@ module.exports = function(internals, isModule) { var plugin = plugins.hook('init:cli:config:hook'); var _config = internals.argv.argv.config; - if(plugin) { - - plugin.forEach(function(plugin) { - + if (plugin) { + plugin.forEach(function (plugin) { var configs = plugin['init:cli:config:hook'](); - if(!configs) return; + if (!configs) return; - //hook not yet used, we look into migrating away from optimist first - return; + // hook not yet used, we look into migrating away from optimist first }); } @@ -141,7 +135,6 @@ module.exports = function(internals, isModule) { } if (internals.argv['log-level']) { - log.setLogLevel(internals.argv['log-level']); } @@ -158,5 +151,4 @@ module.exports = function(internals, isModule) { if (internals.dryRun) { log.info('dry run'); } - }; diff --git a/lib/commands/sync.js b/lib/commands/sync.js index 81740b0d..ed1d3fc0 100644 --- a/lib/commands/sync.js +++ b/lib/commands/sync.js @@ -3,38 +3,35 @@ var log = require('db-migrate-shared').log; var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); -module.exports = function(internals, config, callback) { - +module.exports = function (internals, config, callback) { migrationHook(internals) - .then(function() { - - var Migrator = require('../migrator.js'); - var index = require('../../connect'); - - if (!internals.argv.count) { - internals.argv.count = Number.MAX_VALUE; - } - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, 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']); - - internals.migrationsDir = migrator.migrationsDir; - - migrator.driver.createMigrationsTable(function(err) { - if(!assert(err)) return; - log.verbose('migration table created'); - - migrator.sync(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); + .then(function () { + var Migrator = require('../migrator.js'); + var index = require('../../connect'); + + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, 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']); } + + internals.migrationsDir = migrator.migrationsDir; + + migrator.driver.createMigrationsTable(function (err) { + if (!assert(err)) return; + log.verbose('migration table created'); + + migrator.sync(internals.argv, internals.onComplete.bind(this, + migrator, internals, callback)); }); }); - }); + }); }; diff --git a/lib/commands/undo-seed.js b/lib/commands/undo-seed.js index 2ca1b471..b42b41ed 100644 --- a/lib/commands/undo-seed.js +++ b/lib/commands/undo-seed.js @@ -3,7 +3,7 @@ var assert = require('assert'); var _assert = require('./helper/assert'); -function executeUndoSeed(internals, config, callback) { +function executeUndoSeed (internals, config, callback) { var index = require('./connect'); var Seeder = require('./lib/seeder.js'); @@ -22,7 +22,7 @@ function executeUndoSeed(internals, config, callback) { internals: internals }, Seeder, - function(err, seeder) { + function (err, seeder) { assert.ifError(err); seeder.seedDir = path.resolve( @@ -36,7 +36,7 @@ function executeUndoSeed(internals, config, callback) { stack: "Static seeders can't be undone. Use VC Seeders instead!" }); } else { - seeder.createSeedsTable(function(err) { + seeder.createSeedsTable(function (err) { if (_assert(err, callback)) { seeder.down( internals.argv, diff --git a/lib/commands/up.js b/lib/commands/up.js index 8854d5f6..fccd9348 100644 --- a/lib/commands/up.js +++ b/lib/commands/up.js @@ -3,38 +3,35 @@ var log = require('db-migrate-shared').log; var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); -module.exports = function(internals, config, callback) { - +module.exports = function (internals, config, callback) { migrationHook(internals) - .then(function() { - - var Migrator = require('../migrator.js'); - var index = require('../../connect'); - - if (!internals.argv.count) { - internals.argv.count = Number.MAX_VALUE; - } - index.connect({ - config: config.getCurrent().settings, - internals: internals - }, 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']); - - internals.migrationsDir = migrator.migrationsDir; - - migrator.driver.createMigrationsTable(function(err) { - if(!assert(err, callback)) return; - log.verbose('migration table created'); - - migrator.up(internals.argv, internals.onComplete.bind(this, - migrator, internals, callback)); + .then(function () { + var Migrator = require('../migrator.js'); + var index = require('../../connect'); + + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, 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']); } + + internals.migrationsDir = migrator.migrationsDir; + + migrator.driver.createMigrationsTable(function (err) { + if (!assert(err, callback)) return; + log.verbose('migration table created'); + + migrator.up(internals.argv, internals.onComplete.bind(this, + migrator, internals, callback)); }); }); - }); + }); }; diff --git a/lib/config.js b/lib/config.js index c80a78fe..8f70ca27 100644 --- a/lib/config.js +++ b/lib/config.js @@ -22,75 +22,62 @@ var setCurrent = exports.setCurrent = function (env) { } }; -function Config() { +function Config () { } Config.prototype = { setCurrent: setCurrent }; -exports.load = function(config, currentEnv) { - if (typeof(config) === 'object') { +exports.load = function (config, currentEnv) { + if (typeof (config) === 'object') { return exports.loadObject(config, currentEnv); } else { return exports.loadFile(config, currentEnv); } }; -exports.loadFile = function(fileName, currentEnv, plugins) { +exports.loadFile = function (fileName, currentEnv, plugins) { var config; try { fs.statSync(fileName); - } catch(e) { - if(!process.env.DATABASE_URL) { + } catch (e) { + if (!process.env.DATABASE_URL) { throw new Error('Could not find database config file \'' + fileName + '\''); - } - else { + } else { return exports.loadUrl(process.env.DATABASE_URL, currentEnv); } } try { - var plugin = false; - if(plugins) - plugin = plugins.overwrite('init:config:overwrite:require'); - - if(plugin !== false) { + if (plugins) { plugin = plugins.overwrite('init:config:overwrite:require'); } + if (plugin !== false) { try { - config = plugin['init:config:overwrite:require'](fileName); - } - catch(ex) { - + } catch (ex) { log.warn('Plugin failure "' + plugin.name + '", falling back to default behavior!'); log.verbose(ex); config = require(fileName); } - } - else - config = require(fileName); - - } catch(e) { + } else { config = require(fileName); } + } catch (e) { // distinguish broken files from missing ones - if (e instanceof SyntaxError){ + if (e instanceof SyntaxError) { throw e; } try { config = require(path.join(process.cwd(), fileName)); - } - catch(e) { - - if(!process.env.DATABASE_URL) { + } catch (e) { + if (!process.env.DATABASE_URL) { throw e; - } - else { + } else { return exports.loadUrl(process.env.DATABASE_URL, currentEnv); } } @@ -99,21 +86,16 @@ exports.loadFile = function(fileName, currentEnv, plugins) { return exports.loadObject(config, currentEnv); }; -function walkConfig(level) { - +function walkConfig (level) { for (var configEntry in level) { - if (level[configEntry] && level[configEntry].ENV){ - - if(!process.env[level[configEntry].ENV]) { - + if (level[configEntry] && level[configEntry].ENV) { + if (!process.env[level[configEntry].ENV]) { log.verbose('Environment variable ' + level[configEntry].ENV + ' is empty!'); } - level[configEntry] = process.env[level[configEntry].ENV]; - } - else if(level[configEntry] && typeof(level[configEntry]) === 'object') { - + level[configEntry] = process.env[level[configEntry].ENV]; + } else if (level[configEntry] && typeof (level[configEntry]) === 'object') { level[configEntry] = walkConfig(level[configEntry]); } } @@ -121,66 +103,55 @@ function walkConfig(level) { return level; } -exports.loadObject = function(_config, currentEnv) { - +exports.loadObject = function (_config, currentEnv) { var out = new Config(); // do not overwrite the users config var config = JSON.parse(JSON.stringify(_config)); for (var env in config) { - if (config[env].ENV) { - if(!process.env[config[env].ENV]) - log.verbose('Environment variable ' + config[env].ENV + ' is empty!'); - else - out[env] = parseDatabaseUrl(process.env[config[env].ENV]); - } else if (typeof(config[env]) === 'string') { + if (!process.env[config[env].ENV]) { log.verbose('Environment variable ' + config[env].ENV + ' is empty!'); } else { out[env] = parseDatabaseUrl(process.env[config[env].ENV]); } + } else if (typeof (config[env]) === 'string') { out[env] = parseDatabaseUrl(config[env]); } else { - //Check config entry's for ENV objects - //which will tell us to grab configuration from the environment + // Check config entry's for ENV objects + // which will tell us to grab configuration from the environment config[env] = walkConfig(config[env]); out[env] = config[env]; } - if(typeof(config[env].url) === 'string' || process.env.DATABASE_URL) { - - if(typeof(config[env].url) !== 'string') { + if (typeof (config[env].url) === 'string' || process.env.DATABASE_URL) { + if (typeof (config[env].url) !== 'string') { config[env] = Object.assign( config[env], parseDatabaseUrl(process.env.DATABASE_URL) ); - } - else { + } else { config[env] = Object.assign( config[env], parseDatabaseUrl(config[env].url) ); } delete config[env].url; - } - else if(config[env].url && config[env].url.value) { - + } else if (config[env].url && config[env].url.value) { config[env].url = config[env].url.value; } - if(config[env].overwrite || config[env].addIfNotExists) { - + if (config[env].overwrite || config[env].addIfNotExists) { var overwrite = config[env].overwrite || {}; - if(config[env].addIfNotExists) { - + if (config[env].addIfNotExists) { var addIfNotExists = config[env].addIfNotExists; - Object.keys(addIfNotExists).filter(function(key) { + Object.keys(addIfNotExists).filter(function (key) { return !overwrite[key] && !config[env][key]; - }).forEach(function(key) { + }).forEach(function (key) { config[env][key] = addIfNotExists[key]; }); delete config[env].addIfNotExists; } - Object.keys(overwrite).forEach(function(key) { + Object.keys(overwrite).forEach(function (key) { config[env][key] = overwrite[key]; }); @@ -188,11 +159,11 @@ exports.loadObject = function(_config, currentEnv) { } } - if(currentEnv) { + if (currentEnv) { out.setCurrent(currentEnv); - } else if(config['default']) { + } else if (config['default']) { out.setCurrent(config['default']); - } else if(config.defaultEnv) { + } else if (config.defaultEnv) { if (config.defaultEnv.ENV) { out.setCurrent(process.env[config.defaultEnv.ENV]); } else { @@ -205,9 +176,9 @@ exports.loadObject = function(_config, currentEnv) { return out; }; -exports.loadUrl = function(databaseUrl, currentEnv) { +exports.loadUrl = function (databaseUrl, currentEnv) { var config = parseDatabaseUrl(databaseUrl), - out = new Config(); + out = new Config(); if (currentEnv) { out[currentEnv] = config; diff --git a/lib/driver/index.js b/lib/driver/index.js index 45302a30..bf10c28d 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -6,13 +6,13 @@ internals.mod.type = require('db-migrate-shared').dataType; var Shadow = require('./shadow'); var log = internals.mod.log; var Promise = require('bluebird'), - SeederInterface = require('../interface/seederInterface.js'), - MigratorInterface = require('../interface/migratorInterface.js'), - resolve = require( 'resolve' ); + SeederInterface = require('../interface/seederInterface.js'), + MigratorInterface = require('../interface/migratorInterface.js'), + resolve = require('resolve'); var ShadowProto = { - createTable: function() { return Promise.resolve(); } + createTable: function () { return Promise.resolve(); } }; exports.connect = function (config, intern, callback) { @@ -22,15 +22,14 @@ exports.connect = function (config, intern, callback) { internals = intern; internals.mod = mod; - //add interface extensions to allow drivers to add new methods + // add interface extensions to allow drivers to add new methods internals.interfaces = { SeederInterface: SeederInterface.extending, MigratorInterface: MigratorInterface.extending }; - if ( !config.user && config.username ) - config.user = config.username; + if (!config.user && config.username) { config.user = config.username; } if (config.driver === undefined) { throw new Error( @@ -38,78 +37,59 @@ exports.connect = function (config, intern, callback) { } if (config.driver && typeof (config.driver) === 'object') { - log.verbose('require:', config.driver.require); driver = require(config.driver.require); - - } - else { - - switch(config.driver) { + } else { + switch (config.driver) { case 'sqlite': config.driver = 'sqlite3'; - break; + break; case 'postgres': case 'postgresql': config.driver = 'pg'; - break; + break; } try { - req = 'db-migrate-' + config.driver; log.verbose('require:', req); try { - driver = require( resolve.sync(req, { basedir: process.cwd() }) ); - } - catch(e1) { - + } catch (e1) { try { - driver = require(req); - } - catch (e2) { - + } catch (e2) { driver = require('../../../' + req); } } - } - catch (e3) { - + } catch (e3) { try { - - //Fallback to internal drivers, while moving drivers to new repos + // Fallback to internal drivers, while moving drivers to new repos req = './' + config.driver; log.verbose('require:', req); driver = require(req); - } - catch (e4) { - - return callback( { stack: 'No such driver found, please try to install it via ' + + } catch (e4) { + return callback({ stack: 'No such driver found, please try to install it via ' + 'npm install db-migrate-' + config.driver + ' or ' + - 'npm install -g db-migrate-' + config.driver } ); + 'npm install -g db-migrate-' + config.driver }); } } } log.verbose('connecting'); - var connect = function(config) { + var connect = function (config) { driver.connect(config, intern, function (err, db) { - if (err) { - callback(err); return; } log.verbose('connected'); - if (!global.immunity) - db = Shadow.infect(db, internals, ShadowProto); + if (!global.immunity) { db = Shadow.infect(db, internals, ShadowProto); } callback(null, db); }); @@ -138,8 +118,7 @@ exports.connect = function (config, intern, callback) { connect(config); }); - } - else { + } else { connect(config); } }; diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index a71f5ff9..65e592f7 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -11,31 +11,27 @@ /** * 'Infect' the original class */ -exports.infect = function(db, intern, ShadowProto) { - +exports.infect = function (db, intern, ShadowProto) { var internals = intern; db._shadowsHost = {}; db._shadowProto = {}; - for(var prop in db) { - - if (typeof ShadowProto[prop] === "function" && - typeof db[prop] === "function") { - + for (var prop in db) { + if (typeof ShadowProto[prop] === 'function' && + typeof db[prop] === 'function') { db._shadowsHost[prop] = db[prop]; db._shadowProto[prop] = ShadowProto[prop]; - (function(property) { - - db[property] = function() { - var params = arguments, - self = this; + (function (property) { + db[property] = function () { + var params = arguments, + self = this; - return self._shadowProto[property].apply(self, params) - .then( function() { - return self._shadowsHost[property].apply(self, params); - }.bind(this)); + return self._shadowProto[property].apply(self, params) + .then(function () { + return self._shadowsHost[property].apply(self, params); + }); }; }(prop)); } diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index ba8a1cbd..e05e9035 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -25,12 +25,11 @@ * - 4. Apply changes */ -function dummy() { - +function dummy () { arguments[arguments.length - 1]('not implemented'); } -function MigratorInterface() { +function MigratorInterface () { } @@ -122,16 +121,14 @@ MigratorInterface.prototype = { }; - module.exports = MigratorInterface; module.exports.deprecated = { - insert: function() { - - arguments[arguments.length - 1]('not implemented'); - }, + insert: function () { + arguments[arguments.length - 1]('not implemented'); + }, - insert_deprecation: 'is going to be completely removed, use version controlled seeds instead.' + insert_deprecation: 'is going to be completely removed, use version controlled seeds instead.' }; module.exports.extending = { diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index 244c98f5..41a0a25d 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -39,36 +39,26 @@ var Promise = require('bluebird'); -function _l( field ) { - +function _l (field) { return { type: 'lookup', field: field }; } -function insert(table, options, callback) { - +function insert (table, options, callback) { var foreignLinkage = this.foreignLinkage[table]; - for(var o = 0; o < options.length; ++o) - { + for (var o = 0; o < options.length; ++o) { var option = Object.keys(options[o]); - for(var i = 0; i < option.length; ++i) { - - if (typeof(options[option[i]]) === 'object') { - + for (var i = 0; i < option.length; ++i) { + if (typeof (options[option[i]]) === 'object') { if (options[option[i]].type === 'lookup') { - if (!options[option[i]].table) { - if (foreignLinkage[option[i]]) { - options[option[i]].table = foreignLinkage[option[i]].table; options[option[i]].field = foreignLinkage[option[i]].field; - } - else { - - return Promise.reject('missing foreign key linkage!'). - nodeify(callback); + } else { + return Promise.reject('missing foreign key linkage!') + .nodeify(callback); } } } @@ -77,37 +67,29 @@ function insert(table, options, callback) { } return lookup(options) - .then(function(){ - - return this.driver.insert(options); - }) - .catch(function(e) { - - throw e; - }) - .nodeify(callback); + .then(function () { + return this.driver.insert(options); + }) + .catch(function (e) { + throw e; + }) + .nodeify(callback); } -function lookup(options) { - +function lookup (options) { var lookups = [], - i = 0; + i = 0; - for(var o = 0; o < options.length; ++o) - { + for (var o = 0; o < options.length; ++o) { var option = Object.keys(options[o]); - for(; i < option.length; ++i) { - - if (typeof(options[option]) === 'object') { - + for (; i < option.length; ++i) { + if (typeof (options[option]) === 'object') { if (options[option].type === 'lookup') { - lookups.push(this.driver.lookup(options[option]) - .catch(function(err) { - - throw err; - })); + .catch(function (err) { + throw err; + })); } } } @@ -116,44 +98,43 @@ function lookup(options) { return Promise.settle(lookups); } -function dummy() { - - arguments[arguments.length - 1]('not implemented'); +function dummy () { + arguments[arguments.length - 1]('not implemented'); } var SeederInterface = { - lookup: dummy, + lookup: dummy, - insert: dummy, + insert: dummy, - delete: dummy, + delete: dummy, - runSql: dummy, + runSql: dummy, - buildWhereClause: dummy, + buildWhereClause: dummy, - quoteDDLArr: dummy, + quoteDDLArr: dummy, - quoteArr: dummy, + quoteArr: dummy, - escapeString: dummy, + escapeString: dummy, - escape: dummy, + escape: dummy, - escapeDDL: dummy, + escapeDDL: dummy, - checkDBMS: dummy, + checkDBMS: dummy, - update: dummy, + update: dummy, - truncate: dummy, + truncate: dummy, - switchDatabase: dummy, + switchDatabase: dummy, - remove: dummy, + remove: dummy, - close: dummy + close: dummy }; @@ -163,8 +144,7 @@ module.exports.deprecated = { }; module.exports.extending = { - _l: function( field ) { - - return { type: 'lookup', field: field }; - } + _l: function (field) { + return { type: 'lookup', field: field }; + } }; diff --git a/lib/migration.js b/lib/migration.js index f326f6e6..bfad38f5 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -7,14 +7,14 @@ var Promise = require('bluebird'); var filesRegEx = /\.js$/; var internals = {}; -function writeMigrationRecord(db, migration, callback) { +function writeMigrationRecord (db, migration, callback) { db._runSql('INSERT INTO ' + internals.migrationTable + ' (name, run_on) VALUES (?, ?)', [migration.name, new Date()], callback); } var Migration = Skeleton.extend({ - init: function() { + init: function () { if (arguments.length >= 3) { this.title = arguments[0]; this.date = arguments[2]; @@ -34,40 +34,37 @@ var Migration = Skeleton.extend({ } }); -Migration.registerHook = function(plugin, internals) { - +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); + 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 + '|' + + .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( - '\\.(' + + } + }) + .then(function () { + internals.parser.filesRegEx = new RegExp( + '\\.(' + internals.parser.extensions + ')$' - ); + ); - return internals.parser; - }); + return internals.parser; + }); }; -Migration.prototype.defaultCoffeeTemplate = function() { +Migration.prototype.defaultCoffeeTemplate = function () { return [ '\'use strict\';', '', @@ -90,7 +87,7 @@ Migration.prototype.defaultCoffeeTemplate = function() { ].join('\n'); }; -Migration.prototype.defaultJsTemplate = function() { +Migration.prototype.defaultJsTemplate = function () { return [ '\'use strict\';', '', @@ -123,12 +120,11 @@ Migration.prototype.defaultJsTemplate = function() { ].join('\n'); }; -Migration.prototype.defaultSqlTemplate = function() { +Migration.prototype.defaultSqlTemplate = function () { return '/* Replace with your SQL commands */'; }; - -Migration.prototype.sqlFileLoaderTemplate = function() { +Migration.prototype.sqlFileLoaderTemplate = function () { return [ '\'use strict\';', '', @@ -189,7 +185,7 @@ Migration.prototype.sqlFileLoaderTemplate = function() { ].join('\n'); }; -Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { +Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function () { return [ '\'use strict\';', '', @@ -258,7 +254,7 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function() { ].join('\n'); }; -Migration.prototype.coffeeSqlFileLoaderTemplate = function() { +Migration.prototype.coffeeSqlFileLoaderTemplate = function () { return [ '\'use strict\';', '', @@ -307,7 +303,7 @@ Migration.TemplateType = { SQL_FILE_LOADER_IGNORE_ON_INIT: 5 }; -Migration.prototype.getTemplate = function() { +Migration.prototype.getTemplate = function () { switch (this.templateType) { case Migration.TemplateType.DEFAULT_SQL: return this.defaultSqlTemplate(); @@ -326,47 +322,44 @@ Migration.prototype.getTemplate = function() { } }; -Migration.prototype.write = function(callback) { +Migration.prototype.write = function (callback) { fs.writeFile(this.path, this.getTemplate(), callback); }; -Migration.loadFromFilesystem = function(dir, internals, callback) { +Migration.loadFromFilesystem = function (dir, internals, callback) { log.verbose('loading migrations from dir', dir); - fs.readdir(dir, function(err, files) { + fs.readdir(dir, function (err, files) { if (err) { callback(err); return; } var coffeeWarn = true; - files = files.filter(function(file) { - + files = files.filter(function (file) { return internals.parser.filesRegEx.test(file); }); - var migrations = files.sort().map(function(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) { +Migration.loadFromDatabase = function (dir, driver, internals, callback) { if (internals.ignoreCompleted) { - callback(null, []); } else { - log.verbose('loading migrations from database'); - driver.allLoadedMigrations(function(err, dbResults) { + driver.allLoadedMigrations(function (err, dbResults) { if (err && !internals.dryRun) { callback(err); return; } else if (err && internals.dryRun) { dbResults = []; } - var migrations = dbResults.filter(function(result) { + var migrations = dbResults.filter(function (result) { return result.name.substr(0, result.name.lastIndexOf('/')) === internals.matching; - }).map(function(result) { + }).map(function (result) { return new Migration(path.join(dir, result.name), internals); }); @@ -375,8 +368,7 @@ Migration.loadFromDatabase = function(dir, driver, internals, callback) { } }; -Migration.exportInternals = function(intern) { - +Migration.exportInternals = function (intern) { internals = intern; }; diff --git a/lib/migrator.js b/lib/migrator.js index a3ceb829..c7610780 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -2,10 +2,9 @@ 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) { +var MigratorInterface = require('./interface/migratorInterface.js'); +function SeedLink (driver, internals) { this.seeder = require('./seeder.js')( driver, internals.argv['vcseeder-dir'], true, internals @@ -14,51 +13,40 @@ function SeedLink(driver, internals) { } SeedLink.prototype = { - seed: function( partialName ) { - + seed: function (partialName) { var reset = !internals.notransactions; internals.notransactions = true; - return new Promise( function( resolve, reject ) { - - this.seeder.up( partialName, function( err ) { - - if( reset ) - internals.notransactions = false; + return new Promise(function (resolve, reject) { + this.seeder.up(partialName, function (err) { + if (reset) { internals.notransactions = false; } - if ( err ) - reject( err ); - else - resolve( err ); - } ); - } ); + if (err) { reject(err); } else { resolve(err); } + }); + }); }, - link: function( partialName ) { - - this.links.push( partialName ); + link: function (partialName) { + this.links.push(partialName); }, - process: function() { - + process: function () { this.clear(); }, - clear: function() { - + clear: function () { this.links = []; } }; -var Migrator = function(driver, migrationsDir, empty, intern) { - this.driver = dbmUtil.reduceToInterface( driver, MigratorInterface ); +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) { - + if (intern.linked === false) { this.seedLink = new SeedLink(driver, intern); intern.linked = true; } @@ -69,12 +57,12 @@ var Migrator = function(driver, migrationsDir, empty, intern) { }; Migrator.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(migration.name, err); } else { @@ -85,8 +73,8 @@ Migrator.prototype = { this._driver.addMigrationRecord(this.internals.matching + '/' + migration.name, onComplete); }, - deleteMigrationRecord: function(migration, callback) { - function onComplete(err) { + deleteMigrationRecord: function (migration, callback) { + function onComplete (err) { if (err) { log.error(migration.name, err); } else { @@ -94,20 +82,16 @@ Migrator.prototype = { } callback(err); } - this._driver.deleteMigration(this.internals.matching + '/' + migration.name, function(err) { - - if(!this.internals.matching) { - + this._driver.deleteMigration(this.internals.matching + '/' + migration.name, function (err) { + if (!this.internals.matching) { this._driver.deleteMigration(migration.name, onComplete); - } - else { - + } else { onComplete.apply(err); } }.bind(this)); }, - up: function(funcOrOpts, callback) { + up: function (funcOrOpts, callback) { if (dbmUtil.isFunction(funcOrOpts)) { return funcOrOpts(this.driver, callback); } else { @@ -115,7 +99,7 @@ Migrator.prototype = { } }, - down: function(funcOrOpts, callback) { + down: function (funcOrOpts, callback) { if (dbmUtil.isFunction(funcOrOpts)) { return funcOrOpts(this.driver, callback); } else { @@ -123,37 +107,33 @@ Migrator.prototype = { } }, - sync: function(funcOrOpts, callback) { - + 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 { + self.internals, function (err, completedMigrations) { + if (err) { callback(err); return; } - log.info('Syncing downwards.'); - self.down(funcOrOpts, callback); - } - }); + 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) { + upToBy: function (partialName, count, callback) { var self = this; - Migration.loadFromFilesystem(self.migrationsDir, self.internals, function(err, allMigrations) { + 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) { + Migration.loadFromDatabase(self.migrationsDir, self._driver, self.internals, function (err, completedMigrations) { if (err) { callback(err); return; } var toRun = dbmUtil.filterUp(allMigrations, completedMigrations, partialName, count); @@ -163,44 +143,37 @@ Migrator.prototype = { return; } - return Promise.resolve(toRun).each(function(migration) { - + 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(); - } - - return; - }) - .then(function() { - - return (Promise.promisify(self.writeMigrationRecord.bind(self)))(migration); - }) - .then(self.driver.endMigration.bind(self.driver)); + .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); + .nodeify(callback); }); }); }, - downToBy: function(partialName, count, callback) { + downToBy: function (partialName, count, callback) { var self = this; - Migration.loadFromDatabase(self.migrationsDir, self._driver, self.internals, function(err, completedMigrations) { + Migration.loadFromDatabase(self.migrationsDir, self._driver, self.internals, function (err, completedMigrations) { if (err) { return callback(err); } var toRun = dbmUtil.filterDown(completedMigrations, partialName, count); @@ -211,35 +184,30 @@ Migrator.prototype = { return; } - return Promise.resolve(toRun).each(function(migration) { - + 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() { + .then(function () { + var setup = migration.setup(); - if( self.seedLink && self.seedLink.links.length ) { - log.info('Calling linked seeds'); + if (typeof (setup) === 'function') { setup(self.internals.migrationOptions, self.seedLink); } - return self.seedLink.process(); - } + return self.down(migration.down.bind(migration)); + }) + .then(function () { + if (self.seedLink && self.seedLink.links.length) { + log.info('Calling linked seeds'); - return; - }) - .then(function() { - return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); - }) - .then(self.driver.endMigration.bind(self.driver)); + return self.seedLink.process(); + } + }) + .then(function () { + return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); + }) + .then(self.driver.endMigration.bind(self.driver)); }) - .nodeify(callback); + .nodeify(callback); }); } }; diff --git a/lib/relation.js b/lib/relation.js index 01ae1cb9..a292f318 100644 --- a/lib/relation.js +++ b/lib/relation.js @@ -1,45 +1,38 @@ var fs = require('fs'), - log = require('db-migrate-shared').log; + log = require('db-migrate-shared').log; -function Relation() { +function Relation () { this.relations = {}; } Relation.prototype = { - addRelation: function(table, column, relatedTable, relatedColumn) { + addRelation: function (table, column, relatedTable, relatedColumn) { + this.relations[table] = this.relations[table] || {}; + this.relations[table][column] = relatedColumn; + }, - this.relations[table] = this.relations[table] || {}; - this.relations[table][column] = relatedColumn; + getRelation: function (table, column) { + return this.relations[table][column]; + }, - }, + fromJson: function (file) { + // Relation = require(file); - getRelation: function(table, column) { + log.info('Read Relations from file ' + file); + }, - return this.relations[table][column]; - }, + toJson: function (file) { + fs.writeFile(file, JSON.stringify(this.relations), function (err) { + if (err) { + throw err; + } - fromJson: function(file) { + log.info('Wrote Relations to file ' + file); + }); + }, - //Relation = require(file); - - log.info( 'Read Relations from file ' + file ); - }, - - toJson: function(file) { - - fs.writeFile(file, JSON.stringify(this.relations), function(err) { - - if(err) { - throw err; - } - - log.info( 'Wrote Relations to file ' + file ); - }); - }, - - clearRelations: function() { - - this.relations = {}; - } + clearRelations: function () { + this.relations = {}; + } }; diff --git a/lib/seeder.js b/lib/seeder.js index 3c7d94a1..f4b4c1c3 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -2,13 +2,11 @@ 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 SeederInterface = require('./interface/seederInterface.js'); var internals = {}; -function MigrationLink(driver, internals) { - +function MigrationLink (driver, internals) { this.migrator = require('./migrator.js')( driver, internals.migrationsDir, null, internals ); @@ -17,92 +15,71 @@ function MigrationLink(driver, internals) { MigrationLink.prototype = { - link: function( partialName ) { - - this.links.push( partialName ); + link: function (partialName) { + this.links.push(partialName); }, - migrate: function( partialName ) { - + migrate: function (partialName) { var reset = !internals.notransactions; internals.notransactions = true; - return new Promise( function( resolve, reject ) { - - this.migrator.up( partialName, function( err ) { + return new Promise(function (resolve, reject) { + this.migrator.up(partialName, function (err) { + if (reset) { internals.notransactions = false; } - if( reset ) - internals.notransactions = false; - - if ( err ) - reject( err ); - else - resolve( err ); - } ); - } ); + if (err) { reject(err); } else { resolve(err); } + }); + }); }, - process: function() { - + process: function () { var reset = !internals.notransactions; internals.notransactions = true; - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { + var keys = Object.keys(this.links), + i = 0; - var keys = Object.keys( this.links ), - i = 0; - - - var migrate = function(i, cb) { - - if(i < keys.length) { - - if ( reset ) - internals.notransactions = false; + var migrate = function (i, cb) { + if (i < keys.length) { + if (reset) { internals.notransactions = false; } resolve(); this.clear(); } - this.migrator.up( { + this.migrator.up({ destination: this.links[ keys[ i ] ] - }, function( err ) { - - if( err ) { - - if ( reset ) - internals.notransactions = false; - - reject( err ); - } - else { + }, function (err) { + if (err) { + if (reset) { internals.notransactions = false; } + reject(err); + } else { cb(++i, migrate); } - } ); + }); }.bind(this); migrate(i, migrate); }.bind(this)); }, - clear: function() { - + clear: function () { this.links = []; } }; var Seeder = function (driver, seedsDir, versionControlled, intern) { SeederInterface.extending = intern.interfaces.SeederInterface; - this.driver = dbmUtil.reduceToInterface( driver, SeederInterface ); + this.driver = dbmUtil.reduceToInterface(driver, SeederInterface); this._driver = driver; this.seedDir = seedsDir; this.isVC = versionControlled; - if(intern.linked === false) { - + if (intern.linked === false) { intern.linked = true; this.migrationLink = new MigrationLink(driver, intern); } @@ -113,19 +90,15 @@ var Seeder = function (driver, seedsDir, versionControlled, intern) { Seeder.prototype = { - createSeedsTable: function(callback) { + createSeedsTable: function (callback) { this._driver.createSeedsTable(callback); }, seed: function (argv, callback) { - - if (this.isVC) - this.up(argv, callback); - else - this._staticSeed(argv.destination, callback); + if (this.isVC) { this.up(argv, callback); } else { this._staticSeed(argv.destination, callback); } }, - up: function(funcOrOpts, callback) { + up: function (funcOrOpts, callback) { if (dbmUtil.isFunction(funcOrOpts)) { return funcOrOpts(this.driver, false, callback); } else { @@ -133,7 +106,7 @@ Seeder.prototype = { } }, - down: function(funcOrOpts, callback) { + down: function (funcOrOpts, callback) { if (dbmUtil.isFunction(funcOrOpts)) { return funcOrOpts(this.driver, callback); } else { @@ -161,13 +134,10 @@ Seeder.prototype = { * */ _staticSeed: function (partialName, callback) { - var self = this; - return Seed.loadFromFilesystem(self.seedDir, self.internals, function(err, allSeeds) { - + return Seed.loadFromFilesystem(self.seedDir, self.internals, function (err, allSeeds) { if (err) { - callback(err); return; } @@ -180,33 +150,30 @@ Seeder.prototype = { return; } - return Promise.resolve(toRun).each(function(seeder) { + 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); + if (typeof (setup) === 'function') { setup(self.internals.seederOptions); } return self._driver.startMigration() .catch(callback) - .then(function() { - + .then(function () { return seeder.up(self.driver, true); }); }) - .then(self._driver.endMigration.bind(self.driver)) - .then(function() { - callback(); - }) - .catch(function(e) { - - throw e; - }); + .then(self._driver.endMigration.bind(self.driver)) + .then(function () { + callback(); + }) + .catch(function (e) { + throw e; + }); }); }, - writeSeedRecord: function(seed, callback) { - function onComplete(err) { + writeSeedRecord: function (seed, callback) { + function onComplete (err) { if (err) { log.error(seed.name, err); } else { @@ -217,8 +184,8 @@ Seeder.prototype = { this._driver.addSeedRecord(this.internals.matching + '/' + seed.name, onComplete); }, - deleteSeedRecord: function(seed, callback) { - function onComplete(err) { + deleteSeedRecord: function (seed, callback) { + function onComplete (err) { if (err) { log.error(seed.name, err); } else { @@ -226,29 +193,22 @@ Seeder.prototype = { } callback(err); } - this._driver.deleteSeed(this.internals.matching + '/' + seed.name, function(err) { - - if(!this.internals.matching) { - + this._driver.deleteSeed(this.internals.matching + '/' + seed.name, function (err) { + if (!this.internals.matching) { this._driver.deleteSeed(seed.name, onComplete); - } - else { - + } else { onComplete.apply(err); } }.bind(this)); }, - upToBy: function(partialName, count, callback) { - + upToBy: function (partialName, count, callback) { var self = this; - return Seed.loadFromFilesystem(self.seedDir, self.internals, function(err, allMigrations) { - + 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) { - + 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); @@ -258,49 +218,41 @@ Seeder.prototype = { return; } - return Promise.resolve(toRun).each(function(seeder) { - + 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 ); - } - - return; - }) - .then(function() { - - return (Promise.promisify(self.writeSeedRecord.bind(self)))(seeder); - }) - .then(self._driver.endMigration.bind(self.driver)) - .catch(function(e) { - - throw e; - }); + .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(); - }); + .then(function () { + callback(); + }); }); }); }, - downToBy: function(count, callback) { + downToBy: function (count, callback) { var self = this; - Seed.loadFromDatabase(self.seedDir, self._driver, self.internals, function(err, completedSeeds) { + Seed.loadFromDatabase(self.seedDir, self._driver, self.internals, function (err, completedSeeds) { if (err) { return callback(err); } var toRun = dbmUtil.filterDown(completedSeeds, count); @@ -311,43 +263,35 @@ Seeder.prototype = { return; } - return Promise.resolve(toRun).each(function(seeder) { - + return Promise.resolve(toRun).each(function (seeder) { log.verbose('preparing to run down seeder:', seeder.name); return self._driver.startMigration() - .then(function() { - + .then(function () { var setup = seeder.setup(); - if(typeof(setup) === 'function') - setup(self.internals.seederOptions, self.migrationLink); + 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 ) { + .then(function () { + if (self.seedLink && self.seedLink.links.length) { log.info('Calling linked migrations'); return self.seedLink.process(); } - - return; }) - .then(function() { - + .then(function () { return (Promise.promisify(self.deleteSeedRecord.bind(self)))(seeder); }) .then(self._driver.endMigration.bind(self.driver)) - .catch(function(e) { - + .catch(function (e) { throw e; }); }) - .then(function() { - callback(); - }); + .then(function () { + callback(); + }); }); } }; diff --git a/lib/skeleton.js b/lib/skeleton.js index 2cb629e8..48dfb484 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -4,21 +4,20 @@ 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 isPromise (probe) { + return probe instanceof Promise || (probe && probe.then && + probe.constructor && probe.constructor.name === 'Promise'); } -function formatPath(dir, name) { +function formatPath (dir, name) { return path.join(dir, name); } -function formatName(title, date) { +function formatName (title, date) { return formatDate(date) + '-' + formatTitle(title); } -function formatDate(date) { +function formatDate (date) { return [ date.getUTCFullYear(), lpad(date.getUTCMonth() + 1, '0', 2), @@ -29,11 +28,11 @@ function formatDate(date) { ].join(''); } -function formatTitle(title) { +function formatTitle (title) { return inflection.dasherize(title); } -function parseDate(name) { +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]); @@ -45,7 +44,7 @@ function parseDate(name) { return date; } -function parseTitle(name) { +function parseTitle (name) { var match = name.match(/\d{14}-([^\.]+)/); var dashed = match[1]; return inflection.humanize(dashed, true); @@ -53,26 +52,22 @@ function parseTitle(name) { var Skeleton = Class.extend({ - init: function(intern) { + init: function (intern) { this.internals = intern; }, - _up: function() { + _up: function () { var params = arguments; var cb_executed = false; - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { var migration, - r = function( err ) { - if ( cb_executed === false ) { - + r = function (err) { + if (cb_executed === false) { cb_executed = true; - if( err ) - reject( err ); - else - resolve(); + if (err) { reject(err); } else { resolve(); } } }; @@ -80,84 +75,72 @@ var Skeleton = Class.extend({ migration = require(this.path).up.apply(this, params); - if( migration === null ) migration = Promise.resolve(); - if( isPromise( migration ) ) { - + if (migration === null) migration = Promise.resolve(); + if (isPromise(migration)) { migration - .then(function() { - if( cb_executed === false ) { - - cb_executed = true; - resolve(); - } - }).catch(function(err) { - - if ( cb_executed === false ) { - - cb_executed = true; - reject( err ); - } - }); + .then(function () { + if (cb_executed === false) { + cb_executed = true; + resolve(); + } + }).catch(function (err) { + if (cb_executed === false) { + cb_executed = true; + reject(err); + } + }); } }.bind(this)); }, - _down: function() { + _down: function () { var params = arguments; var cb_executed = false; - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { var migration, - r = function( err ) { - if ( cb_executed === false ) { - - cb_executed = true; + r = function (err) { + if (cb_executed === false) { + cb_executed = true; - if( err ) - reject( err ); - else - resolve(); - } - }; + 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 ) ) { - + if (migration === null) migration = Promise.resolve(); + if (isPromise(migration)) { migration - .then(function() { - if( cb_executed === false ) { - - cb_executed = true; - resolve(); - } - }).catch(function(err) { - - if ( cb_executed === false ) { - - cb_executed = true; - reject( err ); - } - }); + .then(function () { + if (cb_executed === false) { + cb_executed = true; + resolve(); + } + }).catch(function (err) { + if (cb_executed === false) { + cb_executed = true; + reject(err); + } + }); } }.bind(this)); }, - up: function(db) { + up: function (db) { return this._up(db); }, - down: function(db) { + down: function (db) { return this._down(db); }, - setup: function() { + setup: function () { return require(this.path).setup; }, - parseName: function(path) { + parseName: function (path) { var match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/); return match[1]; }, diff --git a/lib/transitions/1.js b/lib/transitions/1.js index 7006e83f..3da3e43a 100644 --- a/lib/transitions/1.js +++ b/lib/transitions/1.js @@ -7,12 +7,11 @@ */ module.exports = { - transition: function() { + transition: function () { }, - message: function() { - + message: function () { console.log('Congratulations!\n\n' + 'You just migrated from protocol 0 to 1!\n' + 'What does that mean for you?\n' + diff --git a/lib/transitions/ask.js b/lib/transitions/ask.js index e2f0b341..9098eca5 100644 --- a/lib/transitions/ask.js +++ b/lib/transitions/ask.js @@ -1,24 +1,19 @@ var prompt = require('prompt'); -function ask(schema, callback) { - +function ask (schema, callback) { console.log('Starting transition helper...\n'); prompt.start(); - prompt.get(schema, function(err, result) { - - if(err) { + prompt.get(schema, function (err, result) { + if (err) { return callback(err); } - if(result.safe === 'n') { - + if (result.safe === 'n') { console.log('Aborted transition helper!'); callback(new Error('Aborted transition.')); - } - else { - + } else { callback(null, result); } }); diff --git a/lib/transitions/transitioner.js b/lib/transitions/transitioner.js index afd6c308..ab8bc50b 100644 --- a/lib/transitions/transitioner.js +++ b/lib/transitions/transitioner.js @@ -4,8 +4,7 @@ var updateVersion = require('./update-version.js'); var ask = require('./ask.js'); var log = require('db-migrate-shared').log; -module.exports = function(internals) { - +module.exports = function (internals) { ask( { properties: { @@ -17,57 +16,48 @@ module.exports = function(internals) { message: 'Invalid answer! Do you want to continue? [y/n]', type: 'string', default: 'n', - conform: function(value) { - + conform: function (value) { return value === 'y' || value === 'n'; } } } - }, function(err) { - - if(err) - return; - - internals.parser = { - filesRegEx: /\.js$/ - }; - - Migration.loadFromFilesystem('migrations/', internals, - function(err, migrations) { - - var messages = []; - - migrations.forEach(function(migration) { - - var required = tryRequire(migration, internals); - var version = (required._meta && required._meta.version) ? - required._meta.version - : 0; - - if(version !== internals.migrationProtocol) { - - var i; - - for(i = 0; i < internals.migrationProtocol; ++i) { - - var transition = require('./' + (i + 1)); - transition.transition(); - messages[i + 1] = transition.message; - - updateVersion(required, migration, internals, i + 1); - log.info('Transitioned ' + migration.name + '.'); - } - } - else { - - log.verbose(migration.name, 'was already transitioned to version ' + + }, function (err) { + if (err) { return; } + + internals.parser = { + filesRegEx: /\.js$/ + }; + + Migration.loadFromFilesystem('migrations/', internals, + function (err, migrations) { + var messages = []; + + migrations.forEach(function (migration) { + var required = tryRequire(migration, internals); + var version = (required._meta && required._meta.version) + ? required._meta.version + : 0; + + if (version !== internals.migrationProtocol) { + var i; + + for (i = 0; i < internals.migrationProtocol; ++i) { + var transition = require('./' + (i + 1)); + transition.transition(); + messages[i + 1] = transition.message; + + updateVersion(required, migration, internals, i + 1); + log.info('Transitioned ' + migration.name + '.'); + } + } else { + log.verbose(migration.name, 'was already transitioned to version ' + internals.migrationProtocol + '.'); - } - }); + } + }); - messages.forEach(function(message) { - message(); - }); + messages.forEach(function (message) { + message(); + }); + }); }); - }); }; diff --git a/lib/transitions/try-require.js b/lib/transitions/try-require.js index a4bf4040..fcaea5d8 100644 --- a/lib/transitions/try-require.js +++ b/lib/transitions/try-require.js @@ -11,19 +11,14 @@ var removedGlobals = { 'Cannot find module \'async\'': installAsync }; -function missingDBMigrate(migration, retry) { - +function missingDBMigrate (migration, retry) { return globalHandler(migration.path, retry); } -function installAsync(migration, retry) { - +function installAsync (migration, retry) { var cmd = [ 'install', '--save', 'async' ]; - if(installed) - retry(); - else - installed = true; + if (installed) { retry(); } else { installed = true; } log.info('Installing async...'); cp.spawnSync('npm', cmd, { @@ -34,7 +29,7 @@ function installAsync(migration, retry) { return retry(); } -function globalHandler(migration, retry) { +function globalHandler (migration, retry) { var data = fs.readFileSync(migration, 'utf8'); data = data.replace( /^dbm = dbm \|\| require\((?!\s)?'db-migrate'(?!\s)?\)/m, @@ -46,8 +41,7 @@ function globalHandler(migration, retry) { 'var dbm' ); - if(data.indexOf('async = async || require') !== -1) { - + if (data.indexOf('async = async || require') !== -1) { handled = true; data = data.replace( /^async = async \|\| require\((?!\s)?'async'(?!\s)?\)/m, @@ -59,8 +53,7 @@ function globalHandler(migration, retry) { 'var type' ); - if(data.indexOf('exports.setup = ') === -1) { - + if (data.indexOf('exports.setup = ') === -1) { var snippet = fs.readFileSync(__dirname + '/snippets/setup.sjs', 'utf8'); data = data.replace(/exports.up/, snippet + '\nexports.up'); } @@ -70,12 +63,9 @@ function globalHandler(migration, retry) { return retry(); } -function tryRequire(migration) { - +function tryRequire (migration) { try { - - if(handled && !installed) { - + if (handled && !installed) { return installAsync( migration, tryRequire.bind(this, migration) @@ -83,19 +73,15 @@ function tryRequire(migration) { } return require(migration.internals.cwd + '/' + migration.path); - } - catch(ex) { - if(ex instanceof ReferenceError) { - if(removedGlobals[ex.message]) { - + } catch (ex) { + if (ex instanceof ReferenceError) { + if (removedGlobals[ex.message]) { log.info(ex.message, 'Initiating removal of old globals...'); return removedGlobals[ex.message]( migration.path, tryRequire.bind(this, migration) ); - } - else { - + } else { log.error( ex.stack, 'Unknown failure, please check your file', @@ -105,16 +91,12 @@ function tryRequire(migration) { throw new Error('Unhandled ReferenceError while transition. Please ' + 'fix the issues and rerun the transitioner again.'); } - } - else if(removedGlobals[ex.message]) { - + } else if (removedGlobals[ex.message]) { return removedGlobals[ex.message]( migration, tryRequire.bind(this, migration) ); - } - else { - + } else { log.error(ex.stack, migration); throw new Error('Unhandled Error while transition. Please ' + 'fix the issues and rerun the transitioner again.'); diff --git a/lib/transitions/update-version.js b/lib/transitions/update-version.js index baf0e4dc..4535948c 100644 --- a/lib/transitions/update-version.js +++ b/lib/transitions/update-version.js @@ -1,37 +1,31 @@ var balanced = require('balanced-match'); var fs = require('fs'); -function updateVersion(required, migration, internals, version) { - +function updateVersion (required, migration, internals, version) { var data = fs.readFileSync(migration.path, 'utf8'); var searchString = 'exports.down'; var balance; var metaIndex; var plus = 1; - if(required._meta) - searchString = 'exports._meta'; + if (required._meta) { searchString = 'exports._meta'; } metaIndex = data.indexOf(searchString); sub = data.substring(metaIndex); balance = balanced('{', '}', sub); - if(sub[balance.end + 1] === ';') - ++plus; + if (sub[balance.end + 1] === ';') { ++plus; } sub = sub.substring(0, balanced.end); - if(required._meta) { - + if (required._meta) { required._meta.version = version; data = data.substring(0, metaIndex) + sub.replace( sub.substring(balance.start, balance.end + 1), JSON.stringify(required._meta, null, 2) ) + data.substring(metaIndex + balance.end + plus); - } - else { - + } else { data = data.substring(0, metaIndex + balance.end + plus) + '\n\nexports._meta = ' + JSON.stringify({ version: version }, null, 2) + ';' + diff --git a/package.json b/package.json index b0361467..58c4374d 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "db-migrate-mysql": "^1.1.7", "db-migrate-sqlite3": "^0.1.9", "eslint": "^4.10.0", + "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.8.0", "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.6.0", diff --git a/test/config_test.js b/test/config_test.js index 6abbde1a..108aae54 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -8,337 +8,307 @@ var sinon = require('sinon'); var _configLoad = config.load; var _configLoadUrl = config.loadUrl; -lab.experiment('config', function() { - +lab.experiment('config', function () { lab.experiment('loading from a file', { parallel: true }, - function() { - - var configPath = path.join(__dirname, 'database.json'); - var _config = config.load(configPath, 'dev'); - - lab.test('should export all environment settings', { parallel: true }, - function (done) { - - Code.expect(_config.dev).to.exists(); - Code.expect(_config.test).to.exists(); - Code.expect(_config.prod).to.exists(); - done(); - }); - - lab.test('should export a getCurrent function with all current ' + + function () { + var configPath = path.join(__dirname, 'database.json'); + var _config = config.load(configPath, 'dev'); + + lab.test('should export all environment settings', { parallel: true }, + function (done) { + Code.expect(_config.dev).to.exists(); + Code.expect(_config.test).to.exists(); + Code.expect(_config.prod).to.exists(); + done(); + }); + + lab.test('should export a getCurrent function with all current ' + 'environment settings', { parallel: true }, function (done) { - - var current; - Code.expect(_config.getCurrent).to.exists(); - current = _config.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.driver).to.equal('sqlite3'); - Code.expect(current.settings.filename).to.equal(':memory:'); - done(); + var current; + Code.expect(_config.getCurrent).to.exists(); + current = _config.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); }); - }); lab.experiment('loading from a broken config file', { parallel: true }, - function() { - - var configPath = path.join(__dirname, 'database_with_syntax_error.json'); - - lab.test('should throw a syntax error', { parallel: true }, - function (done) { - - Code.expect( - config.load.bind(this, configPath, 'dev'), - 'Expected broken file to produce syntax error' - ).to.throw(SyntaxError); - done(); + function () { + var configPath = path.join(__dirname, 'database_with_syntax_error.json'); + + lab.test('should throw a syntax error', { parallel: true }, + function (done) { + Code.expect( + config.load.bind(this, configPath, 'dev'), + 'Expected broken file to produce syntax error' + ).to.throw(SyntaxError); + done(); + }); }); - }); lab.experiment('loading from a file with default env option', - { parallel: true }, function() { - - var configPath = path.join(__dirname, 'database_with_default_env.json'); - var _config = config.load(configPath); - - lab.test('should load a value from the default env', { parallel: true }, - function (done) { - - var current = _config.getCurrent(); - Code.expect(current.env).to.equal('local'); - Code.expect(current.settings.driver).to.equal('sqlite3'); - Code.expect(current.settings.filename).to.equal(':memory:'); - done(); + { parallel: true }, function () { + var configPath = path.join(__dirname, 'database_with_default_env.json'); + var _config = config.load(configPath); + + lab.test('should load a value from the default env', { parallel: true }, + function (done) { + var current = _config.getCurrent(); + Code.expect(current.env).to.equal('local'); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); }); - }); lab.experiment('loading from a file with default env option in ENV variable', - { parallel: true }, function() { - - process.env.NODE_ENV = 'local'; - var configPath = path.join( - __dirname, - 'database_with_default_env_from_env.json' - ); - var _config = config.load(configPath); - - lab.test('should load a value from the env set in NODE_ENV', - { parallel: true }, function (done) { - - var current = _config.getCurrent(); - Code.expect(current.settings.driver).to.equal('sqlite3'); - Code.expect(current.settings.filename).to.equal(':memory:'); - done(); + { parallel: true }, function () { + process.env.NODE_ENV = 'local'; + var configPath = path.join( + __dirname, + 'database_with_default_env_from_env.json' + ); + var _config = config.load(configPath); + + lab.test('should load a value from the env set in NODE_ENV', + { parallel: true }, function (done) { + var current = _config.getCurrent(); + Code.expect(current.settings.driver).to.equal('sqlite3'); + Code.expect(current.settings.filename).to.equal(':memory:'); + done(); + }); }); - }); lab.experiment('loading from a file with ENV vars', { parallel: true }, - function() { - - process.env.DB_MIGRATE_TEST_VAR = 'username_from_env'; - var configPath = path.join(__dirname, 'database_with_env.json'); - var _config = config.load(configPath, 'prod'); - - lab.test('should load a value from the environments', { parallel: true }, - function (done) { - - Code.expect(_config.prod.username).to.equal('username_from_env'); - done(); + function () { + process.env.DB_MIGRATE_TEST_VAR = 'username_from_env'; + var configPath = path.join(__dirname, 'database_with_env.json'); + var _config = config.load(configPath, 'prod'); + + lab.test('should load a value from the environments', { parallel: true }, + function (done) { + Code.expect(_config.prod.username).to.equal('username_from_env'); + done(); + }); }); - }); lab.experiment('loading from a file with ENV URL', { parallel: true }, - function() { - - process.env.DB_MIGRATE_TEST_VAR = 'postgres://uname:pw@server.com/dbname'; - var configPath = path.join(__dirname, 'database_with_env_url.json'); - var _config = config.load(configPath, 'prod'); - - lab.test('should load a value from the environments', { parallel: true }, - function (done) { - - var current = _config.getCurrent(); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host, ').to.equal(rver.com'); - Code.expect(current.settings.database).to.equal('dbname'); - done(); + function () { + process.env.DB_MIGRATE_TEST_VAR = 'postgres://uname:pw@server.com/dbname'; + var configPath = path.join(__dirname, 'database_with_env_url.json'); + var _config = config.load(configPath, 'prod'); + + lab.test('should load a value from the environments', { parallel: true }, + function (done) { + var current = _config.getCurrent(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host, ').to.equal(rver.com'); + Code.expect(current.settings.database).to.equal('dbname'); + done(); + }); }); - }); lab.experiment('loading from an URL', { parallel: true }, - function() { - - var databaseUrl = 'postgres://uname:pw@server.com/dbname'; - var _config = config.loadUrl(databaseUrl, 'dev'); + function () { + var databaseUrl = 'postgres://uname:pw@server.com/dbname'; + var _config = config.loadUrl(databaseUrl, 'dev'); - lab.test('should export the settings as the current environment', - { parallel: true }, function (done) { + lab.test('should export the settings as the current environment', + { parallel: true }, function (done) { + Code.expect(_config.dev).to.exists(); + done(); + }); - Code.expect(_config.dev).to.exists(); - done(); - }); - - lab.test('should export a getCurrent function with all current ' + + lab.test('should export a getCurrent function with all current ' + 'environment settings', { parallel: true }, function (done) { - - var current; - Code.expect(_config.getCurrent).to.exists(); - current = _config.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host).to.equal('server.com'); - Code.expect(current.settings.database).to.equal('dbname'); - done(); + var current; + Code.expect(_config.getCurrent).to.exists(); + current = _config.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + done(); + }); }); - }); - - lab.experiment('loading a config with null values', function() { + lab.experiment('loading a config with null values', function () { var configPath = path.join(__dirname, 'database_with_null_values.json'); config.load = _configLoad; config.loadUrl = _configLoadUrl; - lab.test('should something', function(done) { - - Code.expect( - config.load.bind(this, configPath, 'dev') - ).to.not.throw; - done(); + lab.test('should something', function (done) { + Code.expect( + config.load.bind(this, configPath, 'dev') + ).to.not.throw; + done(); }); }); - lab.experiment('loading a url from url property', function() { - - + lab.experiment('loading a url from url property', function () { lab.test('should export a valid config', - function(done) { - - var databaseUrl = { - 'dev': { - 'url': 'postgres://uname:pw@server.com/dbname' - } - }; - var cfg = config.loadObject(databaseUrl, 'dev'); - - Code.expect(cfg.getCurrent).to.exists(); - var current = cfg.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.url).to.not.exists(); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host).to.equal('server.com'); - Code.expect(current.settings.database).to.equal('dbname'); + function (done) { + var databaseUrl = { + 'dev': { + 'url': 'postgres://uname:pw@server.com/dbname' + } + }; + var cfg = config.loadObject(databaseUrl, 'dev'); + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); - done(); - }); + done(); + }); lab.test('should export the value if specified in suboject', - function(done) { - - var databaseUrl = { - 'dev': { - 'url': { - 'value': 'http://example.com' + function (done) { + var databaseUrl = { + 'dev': { + 'url': { + 'value': 'http://example.com' + } } - } - }; - var cfg = config.loadObject(databaseUrl, 'dev'); + }; + var cfg = config.loadObject(databaseUrl, 'dev'); - Code.expect(cfg.getCurrent).to.exists(); - var current = cfg.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.url).to.equal('http://example.com'); + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.equal('http://example.com'); - done(); - }); + done(); + }); }); - lab.experiment('loading from an URL and overwriting it', function() { - + lab.experiment('loading from an URL and overwriting it', function () { var databaseUrl = { - 'dev': { - 'url': 'postgres://uname:pw@server.com/dbname', - 'overwrite': { - 'ssl': true - } - } - }; + 'dev': { + 'url': 'postgres://uname:pw@server.com/dbname', + 'overwrite': { + 'ssl': true + } + } + }; var cfg = config.loadObject(databaseUrl, 'dev'); - lab.test('should export the settings as the current environment', function(done) { - + lab.test('should export the settings as the current environment', function (done) { Code.expect(cfg.dev).to.exists(); done(); }); lab.test('should export a getCurrent function with all current environment settings', - function(done) { - - Code.expect(cfg.getCurrent).to.exists(); - var current = cfg.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.url).to.not.exists(); - Code.expect(current.settings.overwrite).to.not.exists(); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host).to.equal('server.com'); - Code.expect(current.settings.database).to.equal('dbname'); - Code.expect(current.settings.ssl).to.equal(true); + function (done) { + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.overwrite).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + Code.expect(current.settings.ssl).to.equal(true); - done(); - }); + done(); + }); }); lab.experiment('loading from an ENV URL within the object and overwriting it', - function() { - - lab.test('should export a getCurrent function with all current environment settings', - function(done, cleanup) { - - process.env.DATABASE_URL = 'postgres://uname:pw@server.com/dbname'; - var databaseUrl = { - 'dev': { - 'url': { 'ENV': 'DATABASE_URL' }, - 'overwrite': { - 'ssl': true + function () { + lab.test('should export a getCurrent function with all current environment settings', + function (done, cleanup) { + process.env.DATABASE_URL = 'postgres://uname:pw@server.com/dbname'; + var databaseUrl = { + 'dev': { + 'url': { 'ENV': 'DATABASE_URL' }, + 'overwrite': { + 'ssl': true + } } - } - }; - var cfg = config.loadObject(databaseUrl, 'dev'); - - cleanup(function(next) { - delete process.env.DATABASE_URL; - next(); - }); - - Code.expect(cfg.getCurrent).to.exists(); - var current = cfg.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.url).to.not.exists(); - Code.expect(current.settings.overwrite).to.not.exists(); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host).to.equal('server.com'); - Code.expect(current.settings.database).to.equal('dbname'); - Code.expect(current.settings.ssl).to.equal(true); - - done(); + }; + var cfg = config.loadObject(databaseUrl, 'dev'); + + cleanup(function (next) { + delete process.env.DATABASE_URL; + next(); + }); + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.overwrite).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + Code.expect(current.settings.ssl).to.equal(true); + + done(); + }); }); - }); lab.experiment('loading from an ENV URL within the object and extending it from the ENV', - function() { - - lab.test('', function(done, cleanup) { - - process.env.DATABASE_URL = 'postgres://uname:pw@server.com/dbname?ssl=false&testing=false'; - var databaseUrl = { - 'dev': { - 'url': { - 'ENV': 'DATABASE_URL', - }, - 'overwrite': { - 'ssl': true, - 'cache': false - }, - 'addIfNotExists': { - 'native': true, // this on is new - 'cache': true, // overwrite should have higher priority - 'testing': true // already in config do not overwrite + function () { + lab.test('', function (done, cleanup) { + process.env.DATABASE_URL = 'postgres://uname:pw@server.com/dbname?ssl=false&testing=false'; + var databaseUrl = { + 'dev': { + 'url': { + 'ENV': 'DATABASE_URL' + }, + 'overwrite': { + 'ssl': true, + 'cache': false + }, + 'addIfNotExists': { + 'native': true, // this on is new + 'cache': true, // overwrite should have higher priority + 'testing': true // already in config do not overwrite + } } - } - }; - var cfg = config.loadObject(databaseUrl, 'dev'); + }; + var cfg = config.loadObject(databaseUrl, 'dev'); + + cleanup(function (next) { + delete process.env.DATABASE_URL; + next(); + }); + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.overwrite).to.not.exists(); + Code.expect(current.settings.addIfNotExists).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); + Code.expect(current.settings.native).to.equal(true); + Code.expect(current.settings.testing).to.equal('false'); + Code.expect(current.settings.cache).to.equal(false); + Code.expect(current.settings.ssl).to.equal(true); - cleanup(function(next) { - delete process.env.DATABASE_URL; - next(); + done(); }); - - Code.expect(cfg.getCurrent).to.exists(); - var current = cfg.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.url).to.not.exists(); - Code.expect(current.settings.overwrite).to.not.exists(); - Code.expect(current.settings.addIfNotExists).to.not.exists(); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host).to.equal('server.com'); - Code.expect(current.settings.database).to.equal('dbname'); - Code.expect(current.settings.native).to.equal(true); - Code.expect(current.settings.testing).to.equal('false'); - Code.expect(current.settings.cache).to.equal(false); - Code.expect(current.settings.ssl).to.equal(true); - - done(); }); - }); }); diff --git a/test/driver/base_test.js b/test/driver/base_test.js index 8fa25779..778038c7 100644 --- a/test/driver/base_test.js +++ b/test/driver/base_test.js @@ -11,83 +11,78 @@ var internals = { } }; -lab.experiment('base', { parallel: true }, function() { - - lab.experiment('default implementation', { parallel: true }, function() { - +lab.experiment('base', { parallel: true }, function () { + lab.experiment('default implementation', { parallel: true }, function () { var base = new Base(internals); - lab.test('inherits from EventEmitter', { parallel: true }, function(done) { - + lab.test('inherits from EventEmitter', { parallel: true }, function (done) { Code.expect(base.on).to.be.not.null(); Code.expect(base.emit).to.be.not.null(); done(); }); lab.test('throws errors for all API methods', { parallel: true }, - function(done) { - - Code.expect(function() { - base.createTable(); - }).to.throw(Error); + function (done) { + Code.expect(function () { + base.createTable(); + }).to.throw(Error); - Code.expect(function() { - base.dropTable(); - }).to.throw(Error); + Code.expect(function () { + base.dropTable(); + }).to.throw(Error); - Code.expect(function() { - base.addColumn(); - }).to.throw(Error); + Code.expect(function () { + base.addColumn(); + }).to.throw(Error); - Code.expect(function() { - base.removeColumn(); - }).to.throw(Error); + Code.expect(function () { + base.removeColumn(); + }).to.throw(Error); - Code.expect(function() { - base.renameColumn(); - }).to.throw(Error); + Code.expect(function () { + base.renameColumn(); + }).to.throw(Error); - Code.expect(function() { - base.changeColumn(); - }).to.throw(Error); + Code.expect(function () { + base.changeColumn(); + }).to.throw(Error); - Code.expect(function() { - base.addIndex(); - }).to.throw(Error); + Code.expect(function () { + base.addIndex(); + }).to.throw(Error); - Code.expect(function() { - base.insert(); - }).to.throw(Error); + Code.expect(function () { + base.insert(); + }).to.throw(Error); - Code.expect(function() { - base.removeIndex(); - }).to.throw(Error); + Code.expect(function () { + base.removeIndex(); + }).to.throw(Error); - Code.expect(function() { - base.addAssociation(); - }).to.throw(Error); + Code.expect(function () { + base.addAssociation(); + }).to.throw(Error); - Code.expect(function() { - base.removeAssociation(); - }).to.throw(Error); + Code.expect(function () { + base.removeAssociation(); + }).to.throw(Error); - Code.expect(function() { - base.addForeignKey(); - }).to.throw(Error); + Code.expect(function () { + base.addForeignKey(); + }).to.throw(Error); - Code.expect(function() { - base.removeForeignKey(); - }).to.throw(Error); + Code.expect(function () { + base.removeForeignKey(); + }).to.throw(Error); - Code.expect(function() { - base.runSql(); - }).to.throw(Error); - - done(); - }); + Code.expect(function () { + base.runSql(); + }).to.throw(Error); - lab.test('escapes single quotes', { parallel: true }, function(done) { + done(); + }); + lab.test('escapes single quotes', { parallel: true }, function (done) { Code.expect('Bill\'\'s Mother\'\'s House') .to.equal(base.escape('Bill\'s Mother\'s House')); done(); diff --git a/test/driver/index_test.js b/test/driver/index_test.js index d2c7876d..a5ccc2b8 100644 --- a/test/driver/index_test.js +++ b/test/driver/index_test.js @@ -18,8 +18,8 @@ var internals = { migrationTable: 'migrations' }; -var indexConnectCallback = function(tunnelStub, driverSpy, callback) { - return function(err, db) { +var indexConnectCallback = function (tunnelStub, driverSpy, callback) { + return function (err, db) { if (err) { callback(err, db, tunnelStub, driverSpy); return; @@ -29,73 +29,68 @@ var indexConnectCallback = function(tunnelStub, driverSpy, callback) { }; }; -lab.experiment('index', function() { - +lab.experiment('index', function () { lab.test('a successful connection with ssh tunnel with expected parameters', - function(done, cleanup) { - + function (done, cleanup) { // Ensure that require gets a new copy of the module for each test - delete require.cache[require.resolve('db-migrate-mysql')]; - var driver = require('db-migrate-mysql'); - - // Set up stubs/spies to verify correct flow - var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); - var tunnelStub = sinon.stub().callsArg(1); - - var index = proxyquire('../../lib/driver/index', { - 'tunnel-ssh': tunnelStub, - './mysql': driver - }); - //register clean up - cleanup(function(next) { - - driverSpy.restore(); - delete require.cache[require.resolve('tunnel-ssh')]; delete require.cache[require.resolve('db-migrate-mysql')]; - next(); - }); - - index.connect( - validDbConfigWithTunnel, - {}, - indexConnectCallback(tunnelStub, driverSpy, validate) - ); - - function validate(err, db, tunnelStub, driverSpy) { - var expectedTunnelConfig = { - localPort: 'localPort', - host: 'sshHost', - port: 'sshPort', - dstHost: 'dbHost', - dstPort: 'dbPort' - }; - var expectedDbConfig = { - driver: 'mysql', - host: '127.0.0.1', - port: 'localPort', - tunnel: { + var driver = require('db-migrate-mysql'); + + // Set up stubs/spies to verify correct flow + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); + var tunnelStub = sinon.stub().callsArg(1); + + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + './mysql': driver + }); + // register clean up + cleanup(function (next) { + driverSpy.restore(); + delete require.cache[require.resolve('tunnel-ssh')]; + delete require.cache[require.resolve('db-migrate-mysql')]; + next(); + }); + + index.connect( + validDbConfigWithTunnel, + {}, + indexConnectCallback(tunnelStub, driverSpy, validate) + ); + + function validate (err, db, tunnelStub, driverSpy) { + var expectedTunnelConfig = { localPort: 'localPort', host: 'sshHost', - port: 'sshPort' - } - }; - - - Code.expect(err).to.be.null(); - Code.expect(db).to.not.be.null(); - Code.expect( - tunnelStub.withArgs(expectedTunnelConfig).calledOnce - ).to.be.true(); - Code.expect( - driverSpy.withArgs(expectedDbConfig).calledOnce - ).to.be.true(); - - done(); - } - }); - - lab.test('a failed connection with ssh tunnel', function(done, cleanup) { + port: 'sshPort', + dstHost: 'dbHost', + dstPort: 'dbPort' + }; + var expectedDbConfig = { + driver: 'mysql', + host: '127.0.0.1', + port: 'localPort', + tunnel: { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort' + } + }; + + Code.expect(err).to.be.null(); + Code.expect(db).to.not.be.null(); + Code.expect( + tunnelStub.withArgs(expectedTunnelConfig).calledOnce + ).to.be.true(); + Code.expect( + driverSpy.withArgs(expectedDbConfig).calledOnce + ).to.be.true(); + + done(); + } + }); + lab.test('a failed connection with ssh tunnel', function (done, cleanup) { // Ensure that require gets a new copy of the module for each test delete require.cache[require.resolve('db-migrate-mysql')]; var driver = require('db-migrate-mysql'); @@ -114,17 +109,15 @@ lab.experiment('index', function() { indexConnectCallback(tunnelStub, driverSpy, validate) ); - //register clean up - cleanup(function(next) { - + // register clean up + cleanup(function (next) { driverSpy.restore(); delete require.cache[require.resolve('tunnel-ssh')]; delete require.cache[require.resolve('db-migrate-mysql')]; next(); }); - function validate(err, db, tunnelStub, driverSpy) { - + function validate (err, db, tunnelStub, driverSpy) { Code.expect(err, 'err should be non-null') .to.exists(); Code.expect(db, 'driver should be null or undefined') @@ -140,78 +133,75 @@ lab.experiment('index', function() { }); lab.test('privateKey gets set as expected', - function(done, cleanup) { - + function (done, cleanup) { // Ensure that require gets a new copy of the module for each test - delete require.cache[require.resolve('db-migrate-mysql')]; - var driver = require('db-migrate-mysql'); - var fs = { readFileSync: sinon.stub().returns('sshkey') }; - - // Set up stubs/spies to verify correct flow - var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); - var tunnelStub = sinon.stub().callsArg(1); - - var index = proxyquire('../../lib/driver/index', { - 'tunnel-ssh': tunnelStub, - 'fs': fs, - './mysql': driver, - }); - - //register clean up - cleanup(function(next) { - - driverSpy.restore(); - - delete require.cache[require.resolve('tunnel-ssh')]; delete require.cache[require.resolve('db-migrate-mysql')]; - next(); - }); - - validDbConfigWithTunnel.tunnel.privateKeyPath = '/test/key'; - - index.connect( - validDbConfigWithTunnel, - {}, - indexConnectCallback(tunnelStub, driverSpy, validate) - ); - - function validate(err, db, tunnelStub, driverSpy) { - var expectedTunnelConfig = { - localPort: 'localPort', - host: 'sshHost', - port: 'sshPort', - privateKeyPath: '/test/key', - dstHost: '127.0.0.1', - dstPort: 'localPort', - privateKey: 'sshkey' - }; - var expectedDbConfig = { - driver: 'mysql', - host: '127.0.0.1', - port: 'localPort', - tunnel: { + var driver = require('db-migrate-mysql'); + var fs = { readFileSync: sinon.stub().returns('sshkey') }; + + // Set up stubs/spies to verify correct flow + var driverSpy = sinon.stub(driver, 'connect').yields(null, {}); + var tunnelStub = sinon.stub().callsArg(1); + + var index = proxyquire('../../lib/driver/index', { + 'tunnel-ssh': tunnelStub, + 'fs': fs, + './mysql': driver + }); + + // register clean up + cleanup(function (next) { + driverSpy.restore(); + + delete require.cache[require.resolve('tunnel-ssh')]; + delete require.cache[require.resolve('db-migrate-mysql')]; + next(); + }); + + validDbConfigWithTunnel.tunnel.privateKeyPath = '/test/key'; + + index.connect( + validDbConfigWithTunnel, + {}, + indexConnectCallback(tunnelStub, driverSpy, validate) + ); + + function validate (err, db, tunnelStub, driverSpy) { + var expectedTunnelConfig = { localPort: 'localPort', host: 'sshHost', port: 'sshPort', - privateKeyPath: '/test/key' - } - }; - - - Code.expect(err).to.be.null(); - Code.expect(db).to.not.be.null(); - Code.expect( - fs.readFileSync.withArgs(validDbConfigWithTunnel.tunnel.privateKeyPath) - .calledOnce - ).to.be.true(); - Code.expect( - tunnelStub.withArgs(expectedTunnelConfig).calledOnce - ).to.be.true(); - Code.expect( - driverSpy.withArgs(expectedDbConfig).calledOnce - ).to.be.true(); - - done(); - } - }); + privateKeyPath: '/test/key', + dstHost: '127.0.0.1', + dstPort: 'localPort', + privateKey: 'sshkey' + }; + var expectedDbConfig = { + driver: 'mysql', + host: '127.0.0.1', + port: 'localPort', + tunnel: { + localPort: 'localPort', + host: 'sshHost', + port: 'sshPort', + privateKeyPath: '/test/key' + } + }; + + Code.expect(err).to.be.null(); + Code.expect(db).to.not.be.null(); + Code.expect( + fs.readFileSync.withArgs(validDbConfigWithTunnel.tunnel.privateKeyPath) + .calledOnce + ).to.be.true(); + Code.expect( + tunnelStub.withArgs(expectedTunnelConfig).calledOnce + ).to.be.true(); + Code.expect( + driverSpy.withArgs(expectedDbConfig).calledOnce + ).to.be.true(); + + done(); + } + }); }); diff --git a/test/driver/shadow_test.js b/test/driver/shadow_test.js index 279c2613..95e1e304 100644 --- a/test/driver/shadow_test.js +++ b/test/driver/shadow_test.js @@ -1,4 +1,4 @@ -var Code = require('code'); // assertion library +var Code = require('code'); // assertion library var Lab = require('lab'); var lab = exports.lab = Lab.script(); var sinon = require('sinon'); @@ -6,23 +6,21 @@ var Bluebird = require('bluebird'); var shadow = require('../../lib/driver/shadow.js'); require('sinon-as-promised')(Bluebird); -lab.experiment('shadow', function() { - +lab.experiment('shadow', function () { lab.test('shadow function and original function get called in serial', - function(done) { - - var stub = sinon.stub().callsArg(0); - var shadowStub = sinon.stub().resolves(); - var infected = shadow.infect({ - test: stub - }, {}, { - test: shadowStub - }); + function (done) { + var stub = sinon.stub().callsArg(0); + var shadowStub = sinon.stub().resolves(); + var infected = shadow.infect({ + test: stub + }, {}, { + test: shadowStub + }); - infected.test(function() { - Code.expect(shadowStub.calledOnce).to.be.true(); - Code.expect(stub.calledOnce).to.be.true(); - done(); + infected.test(function () { + Code.expect(shadowStub.calledOnce).to.be.true(); + Code.expect(stub.calledOnce).to.be.true(); + done(); + }); }); - }); }); diff --git a/test/integration/api_test.js b/test/integration/api_test.js index 3868db65..dc551d25 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -5,11 +5,11 @@ var sinon = require('sinon'); var proxyquire = require('proxyquire').noPreserveCache(); var Promise = require('bluebird'); -lab.experiment('api', { parallel: true }, function() { +lab.experiment('api', { parallel: true }, function () { lab.test( 'force process exit after migrations have been run', { parallel: true }, - function(done, onCleanup) { + function (done, onCleanup) { var process_exit = process.exit, argv = process.argv, called = false, @@ -42,12 +42,12 @@ lab.experiment('api', { parallel: true }, function() { /** * Final validation after process.exit should have been called. */ - function validate() { + function validate () { Code.expect(called).to.be.true(); done(); } - function upStub(internals) { + function upStub (internals) { internals.onComplete( { driver: { @@ -61,8 +61,8 @@ lab.experiment('api', { parallel: true }, function() { /** * Create a migration with the programatic API and overwrite process.exit. */ - function overwriteExit() { - process.exit = function(err) { + function overwriteExit () { + process.exit = function (err) { var ret = called; called = true; @@ -75,7 +75,7 @@ lab.experiment('api', { parallel: true }, function() { }; } - function teardown(next) { + function teardown (next) { process.exit = process_exit; process.argv = argv; return next(); @@ -83,7 +83,7 @@ lab.experiment('api', { parallel: true }, function() { } ); - lab.test('should load config from parameter', { parallel: true }, function( + lab.test('should load config from parameter', { parallel: true }, function ( done ) { var options = { @@ -115,7 +115,7 @@ lab.experiment('api', { parallel: true }, function() { lab.test( 'should handle all up parameter variations properly', { parallel: true }, - function() { + function () { return Promise.resolve([ [], // promise [sinon.spy()], @@ -136,7 +136,7 @@ lab.experiment('api', { parallel: true }, function() { lab.test( 'should handle all down parameter variations properly', { parallel: true }, - function() { + function () { return Promise.resolve([ [], // promise [sinon.spy()], @@ -153,7 +153,7 @@ lab.experiment('api', { parallel: true }, function() { lab.test( 'should handle all reset parameter variations properly', { parallel: true }, - function() { + function () { return Promise.resolve([ [], // promise [sinon.spy()], @@ -168,7 +168,7 @@ lab.experiment('api', { parallel: true }, function() { lab.test( 'should handle all sync parameter variations properly', { parallel: true }, - function() { + function () { return Promise.resolve([ [], ['nameatargetmigration', sinon.spy()], // targeted migration @@ -182,8 +182,8 @@ lab.experiment('api', { parallel: true }, function() { ); }); -function defaultExecParams(method) { - return function(args, index) { +function defaultExecParams (method) { + return function (args, index) { var stubs = {}; stubs[method] = stub; @@ -191,7 +191,7 @@ function defaultExecParams(method) { return [api[method].apply(api, args), args]; - function stub(internals, config, callback) { + function stub (internals, config, callback) { if (typeof args[0] === 'string') { Code.expect(internals.argv.destination).to.equal(args[0]); } else if (typeof args[0] === 'number') { @@ -208,17 +208,17 @@ function defaultExecParams(method) { }; } -function spyCallback(api, args) { +function spyCallback (api, args) { if (typeof args[args.length - 1] === 'function') { var spy = args[args.length - 1]; Code.expect(spy.called).to.be.true(); } } -function loader(stubs) { +function loader (stubs) { var load = require('../../lib/commands'); var keys = Object.keys(stubs); - return function(module) { + return function (module) { var index = keys.indexOf(module); if (index !== -1) { return stubs[keys[index]]; @@ -227,7 +227,7 @@ function loader(stubs) { }; } -function stubApiInstance(isModule, stubs, options, callback) { +function stubApiInstance (isModule, stubs, options, callback) { delete require.cache[require.resolve('../../api.js')]; delete require.cache[require.resolve('optimist')]; var mod = proxyquire('../../api.js', { diff --git a/test/integration/create_test.js b/test/integration/create_test.js index c8fbed87..46f51431 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -8,333 +8,284 @@ var dbmUtil = require('db-migrate-shared').util; var rmdir = require('rimraf'); - -function wipeMigrations(callback) { +function wipeMigrations (callback) { var dir = path.join(__dirname, 'migrations'); rmdir(dir, callback); } -function dbMigrate() { +function dbMigrate () { var args = dbmUtil.toArray(arguments); var 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() { - +lab.experiment('create', function () { + lab.experiment('without a migration directory', function () { var exitCode; - lab.before(function(done) { - wipeMigrations(function(err) { - + lab.before(function (done) { + wipeMigrations(function (err) { Code.expect(err).to.be.null(); dbMigrate('create', 'first migration').on('exit', - function(code) { - - exitCode = code; - done(); - }); + function (code) { + exitCode = code; + done(); + }); }); }); lab.test('does not cause an error', { parallel: true }, - function(done) { - - Code.expect(exitCode).to.equal(0); - done(); - }); + function (done) { + Code.expect(exitCode).to.equal(0); + done(); + }); lab.test('will create a new migration directory', { parallel: true }, - function(done) { - - var stats = fs.statSync(path.join(__dirname, 'migrations')); - Code.expect(stats.isDirectory()).to.be.true(); - done(); - }); + function (done) { + var stats = fs.statSync(path.join(__dirname, 'migrations')); + Code.expect(stats.isDirectory()).to.be.true(); + done(); + }); lab.test('will create a new migration', { parallel: true }, - function(done) { - - var files = fs.readdirSync(path.join(__dirname, 'migrations')); - Code.expect(files.length).to.equal(1); - var file = files[0]; - Code.expect(file).to.match(/first-migration\.js$/); - done(); - }); + function (done) { + var files = fs.readdirSync(path.join(__dirname, 'migrations')); + Code.expect(files.length).to.equal(1); + var file = files[0]; + Code.expect(file).to.match(/first-migration\.js$/); + done(); + }); }); lab.experiment('with sql-file option set to true from config file', - function() { - - var exitCode; - - lab.before(function(done) { - - var configOption = path.join('--config=', __dirname, - 'database_with_sql_file.json'); - - wipeMigrations(function(err) { - - Code.expect(err).to.not.exist(); - dbMigrate( 'create', 'second migration', configOption).on('exit', - function(code) { - - exitCode = code; - done(); + function () { + var exitCode; + + lab.before(function (done) { + var configOption = path.join('--config=', __dirname, + 'database_with_sql_file.json'); + + wipeMigrations(function (err) { + Code.expect(err).to.not.exist(); + dbMigrate('create', 'second migration', configOption).on('exit', + function (code) { + exitCode = code; + done(); + }); }); }); - }); - - lab.test('does not cause an error', { parallel: true }, function(done) { - - Code.expect(exitCode).to.equal(0); - done(); - }); - - lab.test('will create a new migration', { parallel: true }, - function(done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); - - for (var i = 0; i', 8); + Code.expect(actual).to.equal('>>prompt'); - var actual = util.lpad('prompt', '>', 8); - Code.expect(actual).to.equal('>>prompt'); - - done(); - }); + done(); + }); lab.test('should apply no left padding if already equal to the total length', - { parallel: true }, function(done) { - - var actual = util.lpad('>>prompt', '>', 8); - Code.expect(actual).to.equal('>>prompt'); + { parallel: true }, function (done) { + var actual = util.lpad('>>prompt', '>', 8); + Code.expect(actual).to.equal('>>prompt'); - done(); - }); + done(); + }); lab.test('should apply no left padding if already greater than the total ' + - 'length', { parallel: true }, function(done) { - + 'length', { parallel: true }, function (done) { var actual = util.lpad('>>>prompt', '>', 8); Code.expect(actual).to.equal('>>>prompt'); @@ -38,20 +33,18 @@ function lpad() { }); lab.test('should be apple to pad numbers', - { parallel: true }, function(done) { - - var actual = util.lpad(12, '>', 4); - Code.expect(actual).to.equal('>>12'); + { parallel: true }, function (done) { + var actual = util.lpad(12, '>', 4); + Code.expect(actual).to.equal('>>12'); - done(); - }); + done(); + }); lab.test('should be apple to pad using numbers', - { parallel: true }, function(done) { + { parallel: true }, function (done) { + var actual = util.lpad(12, 0, 4); + Code.expect(actual).to.equal('0012'); - var actual = util.lpad(12, 0, 4); - Code.expect(actual).to.equal('0012'); - - done(); - }); + done(); + }); } From 4de822b8d420148f1c661de9f816585831bc5f84 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 11 Nov 2017 19:25:46 +0100 Subject: [PATCH 355/412] adjust manual changes for cs --- api.js | 14 +- connect.js | 155 ++++++++---- index.js | 30 ++- lib/class.js | 54 +++-- lib/commands/create-migration.js | 1 + lib/commands/db.js | 5 +- lib/commands/helper/load-config.js | 6 +- lib/commands/on-complete.js | 16 +- lib/commands/run.js | 13 +- lib/commands/seed.js | 9 +- lib/commands/set-default-argv.js | 65 +++-- lib/commands/transition.js | 5 + lib/commands/undo-seed.js | 11 +- lib/config.js | 83 ++++--- lib/driver/index.js | 49 ++-- lib/driver/shadow.js | 17 +- lib/interface/seederInterface.js | 35 ++- lib/migration.js | 120 +++++---- lib/migrator.js | 235 +++++++++++------- lib/relation.js | 5 +- lib/seed.js | 170 ++++++------- lib/seeder.js | 287 +++++++++++++--------- lib/skeleton.js | 135 ++++++----- lib/transitions/transitioner.js | 73 +++--- lib/transitions/try-require.js | 42 ++-- lib/transitions/update-version.js | 26 +- test/config_test.js | 298 +++++++++++++---------- test/integration/api_test.js | 22 +- test/migration_test.js | 376 +++++++++++++++++------------ 29 files changed, 1381 insertions(+), 976 deletions(-) create mode 100644 lib/commands/transition.js diff --git a/api.js b/api.js index 3d76a5a7..5282c7f8 100644 --- a/api.js +++ b/api.js @@ -2,8 +2,8 @@ var load = require('./lib/commands'); var log = require('db-migrate-shared').log; -var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line -var Promise = Promise; +require('pkginfo')(module, 'version'); // jshint ignore:line +var Promise; var onComplete = load('on-complete'); // constant hooks for this file @@ -12,7 +12,7 @@ var APIHooks = { this[name] = fn; }, 'init:api:accessapi:hook': function (cb) { - return cb(this); + return this; } }; @@ -43,7 +43,11 @@ function dbmigrate (plugins, isModule, options, callback) { /* $lab:coverage:on$ */ if (typeof options === 'object') { - if (typeof options.config === 'string') { internals.configFile = options.config; } else if (typeof options.config === 'object') { internals.configObject = options.config; } + if (typeof options.config === 'string') { + internals.configFile = options.config; + } else if (typeof options.config === 'object') { + internals.configObject = options.config; + } if (typeof options.env === 'string') internals.currentEnv = options.env; @@ -278,7 +282,7 @@ dbmigrate.prototype = { * Transition migrations to the latest defined protocol. */ transition: function () { - transition(this.internals); + load('transition')(this.internals); }, /** diff --git a/connect.js b/connect.js index a362b119..2d2ae894 100644 --- a/connect.js +++ b/connect.js @@ -4,9 +4,7 @@ var driver = require('./lib/driver'); var path = require('path'); var log = require('db-migrate-shared').log; -var internals = {}; - -exports.connect = function (config, passedClass, callback) { +exports.connect = function (config, PassedClass, callback) { var internals = {}; if (config.config) { @@ -15,56 +13,102 @@ exports.connect = function (config, passedClass, callback) { } driver.connect(config, internals, function (err, db) { - if (err) { callback(err); return; } + if (err) { + callback(err); + return; + } if (internals.migrationMode) { var dirPath = path.resolve(config['migrations-dir'] || 'migrations'); if (internals.migrationMode !== 'all') { - var switched = false, - newConf; + var switched = false; + var newConf; try { - newConf = require(path.resolve(config['migrations-dir'] || 'migrations', internals.migrationMode) + '/config.json'); - log.info('loaded extra config for migration subfolder: "' + internals.migrationMode + '/config.json"'); + newConf = require(path.resolve( + config['migrations-dir'] || 'migrations', + internals.migrationMode + ) + '/config.json'); + log.info( + 'loaded extra config for migration subfolder: "' + + internals.migrationMode + + '/config.json"' + ); switched = true; } catch (e) {} if (switched) { db.switchDatabase(newConf, function () { internals.locTitle = internals.migrationMode; - callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); + callback( + null, + new PassedClass( + db, + config['migrations-dir'], + internals.mode !== 'static', + internals + ) + ); }); } else { internals.locTitle = internals.migrationMode; - callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); + callback( + null, + new PassedClass( + db, + config['migrations-dir'], + internals.mode !== 'static', + internals + ) + ); } } else { - recursive(dirPath, false, config['migrations-dir'] || 'migrations') - .then(function (files) { - var oldClose = db.close; - - files = files.filter(function (file) { - return file !== 'migrations' && fs.statSync(file).isDirectory(); - }); - - files.push(''); - - db.close = function (cb) { - migrationFiles(files, callback, config, - internals, passedClass, db, oldClose, cb); - }; - - db.close(); + recursive( + dirPath, + false, + config['migrations-dir'] || 'migrations' + ).then(function (files) { + var oldClose = db.close; + + files = files.filter(function (file) { + return file !== 'migrations' && fs.statSync(file).isDirectory(); }); + + files.push(''); + + db.close = function (cb) { + migrationFiles( + files, + callback, + config, + internals, + PassedClass, + db, + oldClose, + cb + ); + }; + + db.close(); + }); } - } else { callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); } + } else { + callback( + null, + new PassedClass( + db, + config['migrations-dir'], + internals.mode !== 'static', + internals + ) + ); + } }); }; exports.driver = function (config, callback) { var internals = {}; - var _config = config; if (config.config) { internals = config.internals; config = config.config; @@ -73,38 +117,65 @@ exports.driver = function (config, callback) { driver.connect(config, internals, callback); }; -function migrationFiles (files, callback, config, internals, - passedClass, db, close, cb) { - var file, - switched = false, - newConf; +function migrationFiles ( + files, + callback, + config, + internals, + PassedClass, + db, + close, + cb +) { + var file; + var switched = false; + var newConf; if (files.length === 1) { db.close = close; } file = files.pop(); - log.info('Enter scope "' + ((file !== '') ? file : '/') + '"'); + log.info('Enter scope "' + (file !== '' ? file : '/') + '"'); if (file !== '') { try { fs.statSync(path.resolve(file + '/config.json')); newConf = require(path.resolve(file + '/config.json')); - log.info('loaded extra config for migration subfolder: "' + file + '/config.json"'); + log.info( + 'loaded extra config for migration subfolder: "' + + file + + '/config.json"' + ); switched = true; } catch (e) {} } - db.switchDatabase((switched) ? newConf : config.database, function () { - internals.matching = file.substr(file.indexOf(config['migrations-dir'] || 'migrations') + - (config['migrations-dir'] || 'migrations').length + 1); + db.switchDatabase(switched ? newConf : config.database, function () { + internals.matching = file.substr( + file.indexOf(config['migrations-dir'] || 'migrations') + + (config['migrations-dir'] || 'migrations').length + + 1 + ); - if (internals.matching.length === 0) { internals.matching = ''; } + if (internals.matching.length === 0) { + internals.matching = ''; + } internals.locTitle = internals.matching; - callback(null, new passedClass(db, config['migrations-dir'], internals.mode !== 'static', internals)); - - if (typeof (cb) === 'function') { cb(); } + callback( + null, + new PassedClass( + db, + config['migrations-dir'], + internals.mode !== 'static', + internals + ) + ); + + if (typeof cb === 'function') { + cb(); + } }); } diff --git a/index.js b/index.js index d8cdae33..f2eee0fe 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -var pkginfo = require('pkginfo')(module, 'version'); // jshint ignore:line +require('pkginfo')(module, 'version'); // jshint ignore:line var fs = require('fs'); var path = require('path'); @@ -6,9 +6,9 @@ exports.dataType = require('db-migrate-shared').dataType; function loadPluginList () { var plugins = JSON.parse( - fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8') - ), - targets = []; + fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8') + ); + var targets = []; plugins = Object.assign(plugins.dependencies, plugins.devDependencies); @@ -20,15 +20,21 @@ function loadPluginList () { } function loadPlugins () { - var plugins = loadPluginList(), - i = 0, - length = plugins.length, - hooks = {}; + var plugins = loadPluginList(); + var i = 0; + var length = plugins.length; + var hooks = {}; for (; i < length; ++i) { var plugin = require(path.join(process.cwd(), 'node_modules', plugins[i])); - if (typeof plugin.name !== 'string' || !plugin.hooks || !plugin.loadPlugin) { continue; } + if ( + typeof plugin.name !== 'string' || + !plugin.hooks || + !plugin.loadPlugin + ) { + continue; + } plugin.hooks.map(function (hook) { hooks[hook] = hooks[hook] || []; @@ -42,8 +48,8 @@ function loadPlugins () { module.exports.getInstance = function (isModule, options, callback) { delete require.cache[require.resolve('./api.js')]; delete require.cache[require.resolve('optimist')]; - var mod = require('./api.js'), - plugins = {}; + var Mod = require('./api.js'); + var plugins = {}; try { if (!options || !options.noPlugins) plugins = loadPlugins(); @@ -53,5 +59,5 @@ module.exports.getInstance = function (isModule, options, callback) { plugins = Object.assign(plugins, options.plugins); } - return new mod(plugins, isModule, options, callback); + return new Mod(plugins, isModule, options, callback); }; diff --git a/lib/class.js b/lib/class.js index 105163af..a534f940 100644 --- a/lib/class.js +++ b/lib/class.js @@ -3,7 +3,15 @@ * MIT Licensed. */ // Inspired by base2 and Prototype -var initializing = false, fnTest = /xyz/.test(function () { xyz; }) ? /\b_super\b/ : /.*/; +var initializing = false; + +/*eslint-disable */ +var fnTest = /xyz/.test(function() { + xyz; +}) + ? /\b_super\b/ + : /.*/; +/* eslint-enable */ // The base Class implementation (does nothing) var Class = function () {}; @@ -21,31 +29,35 @@ Class.extend = function ext (prop) { // Copy the properties over onto the new prototype for (var name in prop) { // Check if we're overwriting an existing function - prototype[name] = typeof prop[name] === 'function' && - typeof _super[name] === 'function' && fnTest.test(prop[name]) - ? (function (name, fn) { - return function () { - var tmp = this._super; - - // Add a new ._super() method that is the same method - // but on the super-class - this._super = _super[name]; - - // The method only need to be bound temporarily, so we - // remove it when we're done executing - var ret = fn.apply(this, arguments); - this._super = tmp; - - return ret; - }; - })(name, prop[name]) - : prop[name]; + prototype[name] = + typeof prop[name] === 'function' && + typeof _super[name] === 'function' && + fnTest.test(prop[name]) + ? (function (name, fn) { + return function () { + var tmp = this._super; + + // Add a new ._super() method that is the same method + // but on the super-class + this._super = _super[name]; + + // The method only need to be bound temporarily, so we + // remove it when we're done executing + var ret = fn.apply(this, arguments); + this._super = tmp; + + return ret; + }; + })(name, prop[name]) + : prop[name]; } // The dummy class constructor function Class () { // All construction is actually done in the init method - if (!initializing && this.init) { this.init.apply(this, arguments); } + if (!initializing && this.init) { + this.init.apply(this, arguments); + } } // Populate our constructed prototype object diff --git a/lib/commands/create-migration.js b/lib/commands/create-migration.js index d778372c..6cf38eed 100644 --- a/lib/commands/create-migration.js +++ b/lib/commands/create-migration.js @@ -4,6 +4,7 @@ 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'); function createMigrationDir (dir, callback) { diff --git a/lib/commands/db.js b/lib/commands/db.js index eb22e83e..43200ac6 100644 --- a/lib/commands/db.js +++ b/lib/commands/db.js @@ -1,5 +1,8 @@ 'use strict'; +var log = require('db-migrate-shared').log; +var assert = require('assert'); + function executeDB (internals, config, callback) { var index = require('./connect'); @@ -49,7 +52,7 @@ function executeDB (internals, config, callback) { if (typeof callback === 'function') callback(); } ); - } else return; + } }); } diff --git a/lib/commands/helper/load-config.js b/lib/commands/helper/load-config.js index 2327223f..1ddbeed3 100644 --- a/lib/commands/helper/load-config.js +++ b/lib/commands/helper/load-config.js @@ -1,8 +1,10 @@ 'use strict'; +var log = require('db-migrate-shared').log; + function loadConfig (config, internals) { - var out, - currentEnv = internals.currentEnv || internals.argv.env; + var out; + var currentEnv = internals.currentEnv || internals.argv.env; if (internals.configObject) { out = config.loadObject(internals.configObject, currentEnv); diff --git a/lib/commands/on-complete.js b/lib/commands/on-complete.js index 724a2b09..3df484a5 100644 --- a/lib/commands/on-complete.js +++ b/lib/commands/on-complete.js @@ -2,16 +2,18 @@ var assert = require('assert'); var log = require('db-migrate-shared').log; module.exports = function (migrator, internals, callback, originalErr) { - if (typeof (callback) !== 'function') { + if (typeof callback !== 'function') { originalErr = originalErr || callback; } migrator.driver.close(function (err) { - if ((err || originalErr) && typeof (callback) === 'function') { - callback({ - err: err, - originalErr: originalErr - }); + if ((err || originalErr) && typeof callback === 'function') { + callback( + new Error({ + err: err, + originalErr: originalErr + }) + ); return; } else { assert.ifError(originalErr); @@ -24,7 +26,7 @@ module.exports = function (migrator, internals, callback, originalErr) { return process.exit(0); } - if (typeof (callback) === 'function') { + if (typeof callback === 'function') { callback(); } }); diff --git a/lib/commands/run.js b/lib/commands/run.js index 7f26439a..6d182cc4 100644 --- a/lib/commands/run.js +++ b/lib/commands/run.js @@ -3,14 +3,11 @@ var log = require('db-migrate-shared').log; var optimist = require('optimist'); var load = require('./'); - -function transition (internals) { - require('../transitions/transitioner.js')(internals); -} +var transition = load('transition'); function run (internals, config) { - var action = internals.argv._.shift(), - folder = action.split(':'); + var action = internals.argv._.shift(); + var folder = action.split(':'); action = folder[0]; @@ -84,7 +81,9 @@ function run (internals, config) { internals.migrationMode = folder[2]; if (internals.argv._[0] === 'down' || internals.argv._[0] === 'reset') { - if (internals.argv._[0] === 'reset') { internals.argv.count = Number.MAX_VALUE; } + if (internals.argv._[0] === 'reset') { + internals.argv.count = Number.MAX_VALUE; + } internals.argv._.shift(); load('undo-seed')(internals, config); diff --git a/lib/commands/seed.js b/lib/commands/seed.js index f8a6326c..87558889 100644 --- a/lib/commands/seed.js +++ b/lib/commands/seed.js @@ -1,6 +1,7 @@ 'use strict'; var assert = require('assert'); +var path = require('path'); var _assert = require('./helper/assert'); function executeSeed (internals, config, callback) { @@ -19,12 +20,10 @@ function executeSeed (internals, config, callback) { Seeder, function (err, seeder) { assert.ifError(err); + var seedDir = + internals.mode !== 'static' ? 'vcseeder-dir' : 'staticseeder-dir'; - seeder.seedDir = path.resolve( - internals.argv[ - internals.mode !== 'static' ? 'vcseeder-dir' : 'staticseeder-dir' - ] - ); + seeder.seedDir = path.resolve(internals.argv[seedDir]); if (internals.mode === 'static') { seeder.seed( diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index 4599099a..912801b9 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -25,82 +25,80 @@ module.exports = function (internals, isModule) { 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + '[[dbname/]migrationName|all] [options]' ) - .describe('env', - 'The environment to run the migrations under (dev, test, prod).') + .describe( + 'env', + 'The environment to run the migrations under (dev, test, prod).' + ) .alias('e', 'env') .string('e') - - .describe('migrations-dir', 'The directory containing your migration files.') + .describe( + 'migrations-dir', + 'The directory containing your migration files.' + ) .alias('m', 'migrations-dir') .string('m') - .describe('count', 'Max number of migrations to run.') .alias('c', 'count') .string('c') - - .describe('dry-run', 'Prints the SQL but doesn\'t run it.') + .describe('dry-run', "Prints the SQL but doesn't run it.") .boolean('dry-run') - - .describe('force-exit', 'Forcibly exit the migration process on completion.') + .describe( + 'force-exit', + 'Forcibly exit the migration process on completion.' + ) .boolean('force-exit') - .describe('verbose', 'Verbose mode.') .alias('v', 'verbose') .boolean('v') - .alias('h', 'help') .alias('h', '?') .boolean('h') - .describe('version', 'Print version info.') .alias('i', 'version') .boolean('version') - .describe('config', 'Location of the database.json file.') .string('config') - - .describe('sql-file', + .describe( + 'sql-file', 'Automatically create two sql files for up and down statements in ' + '/sqls and generate the javascript code that loads them.' ) .boolean('sql-file') - .describe('coffee-file', 'Create a coffeescript migration file') .boolean('coffee-file') - .describe('ignore-on-init', + .describe( + 'ignore-on-init', 'Create files that will run only if ignore-on-init in the env is set ' + 'to false (currently works only with SQL)' - ).boolean('ignore-on-init') - - .describe('migration-table', + ) + .boolean('ignore-on-init') + .describe( + 'migration-table', 'Set the name of the migration table, which stores the migration history.' ) .alias('table', 'migration-table') .alias('t', 'table') .string('t') - - .describe('seeds-table', - 'Set the name of the seeds table, which stores the seed history.') + .describe( + 'seeds-table', + 'Set the name of the seeds table, which stores the seed history.' + ) .string('seeds-table') - - .describe('vcseeder-dir', - 'Set the path to the Version Controlled Seeder directory.') + .describe( + 'vcseeder-dir', + 'Set the path to the Version Controlled Seeder directory.' + ) .string('vcseeder-dir') - .describe('staticseeder-dir', 'Set the path to the Seeder directory.') .string('staticseeder-dir') - .describe('non-transactional', 'Explicitly disable transactions') .boolean('non-transactional') - .describe('ignore-completed-migrations', 'Start at the first migration') .boolean('ignore-completed-migrations') - .describe('log-level', 'Set the log-level, for example sql|warn') .string('log-level'); } else { internals.argv = { - get argv () { return defaultConfig; } @@ -113,9 +111,8 @@ module.exports = function (internals, isModule) { if (plugin) { plugin.forEach(function (plugin) { - var configs = plugin['init:cli:config:hook'](); - if (!configs) return; - + // var configs = plugin['init:cli:config:hook'](); + // if (!configs) return; // hook not yet used, we look into migrating away from optimist first }); } diff --git a/lib/commands/transition.js b/lib/commands/transition.js new file mode 100644 index 00000000..5a3814ad --- /dev/null +++ b/lib/commands/transition.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = function (internals) { + require('../transitions/transitioner.js')(internals); +}; diff --git a/lib/commands/undo-seed.js b/lib/commands/undo-seed.js index b42b41ed..6f2cd09f 100644 --- a/lib/commands/undo-seed.js +++ b/lib/commands/undo-seed.js @@ -1,6 +1,8 @@ 'use strict'; var assert = require('assert'); +var path = require('path'); +var log = require('db-migrate-shared').log; var _assert = require('./helper/assert'); function executeUndoSeed (internals, config, callback) { @@ -25,11 +27,10 @@ function executeUndoSeed (internals, config, callback) { function (err, seeder) { assert.ifError(err); - seeder.seedDir = path.resolve( - internals.argv[ - internals.mode !== 'static' ? 'vcseeder-dir' : 'staticseeder-dir' - ] - ); + var seedDir = + internals.mode !== 'static' ? 'vcseeder-dir' : 'staticseeder-dir'; + + seeder.seedDir = path.resolve(internals.argv[seedDir]); if (internals.mode === 'static') { internals.onComplete(seeder, callback, { diff --git a/lib/config.js b/lib/config.js index 8f70ca27..85fc229c 100644 --- a/lib/config.js +++ b/lib/config.js @@ -4,33 +4,34 @@ var parseDatabaseUrl = require('parse-database-url'); var dbmUtil = require('db-migrate-shared').util; var log = require('db-migrate-shared').log; -var setCurrent = exports.setCurrent = function (env) { +var setCurrent = (exports.setCurrent = function (env) { env = dbmUtil.isArray(env) ? env : [env]; - env.forEach(function (current) { - if (dbmUtil.isString(current) && this[current]) { - this.getCurrent = function () { - return { - env: current, - settings: this[current] + env.forEach( + function (current) { + if (dbmUtil.isString(current) && this[current]) { + this.getCurrent = function () { + return { + env: current, + settings: this[current] + }; }; - }; - } - }.bind(this)); + } + }.bind(this) + ); if (!this.getCurrent) { - throw new Error('Environment(s) \'' + env.join(', ') + '\' not found.'); + throw new Error("Environment(s) '" + env.join(', ') + "' not found."); } -}; +}); -function Config () { -} +function Config () {} Config.prototype = { setCurrent: setCurrent }; exports.load = function (config, currentEnv) { - if (typeof (config) === 'object') { + if (typeof config === 'object') { return exports.loadObject(config, currentEnv); } else { return exports.loadFile(config, currentEnv); @@ -44,7 +45,7 @@ exports.loadFile = function (fileName, currentEnv, plugins) { fs.statSync(fileName); } catch (e) { if (!process.env.DATABASE_URL) { - throw new Error('Could not find database config file \'' + fileName + '\''); + throw new Error("Could not find database config file '" + fileName + "'"); } else { return exports.loadUrl(process.env.DATABASE_URL, currentEnv); } @@ -53,19 +54,26 @@ exports.loadFile = function (fileName, currentEnv, plugins) { try { var plugin = false; - if (plugins) { plugin = plugins.overwrite('init:config:overwrite:require'); } + if (plugins) { + plugin = plugins.overwrite('init:config:overwrite:require'); + } if (plugin !== false) { try { config = plugin['init:config:overwrite:require'](fileName); } catch (ex) { - log.warn('Plugin failure "' + plugin.name + - '", falling back to default behavior!'); + log.warn( + 'Plugin failure "' + + plugin.name + + '", falling back to default behavior!' + ); log.verbose(ex); config = require(fileName); } - } else { config = require(fileName); } + } else { + config = require(fileName); + } } catch (e) { // distinguish broken files from missing ones if (e instanceof SyntaxError) { @@ -90,12 +98,13 @@ function walkConfig (level) { for (var configEntry in level) { if (level[configEntry] && level[configEntry].ENV) { if (!process.env[level[configEntry].ENV]) { - log.verbose('Environment variable ' + level[configEntry].ENV + - ' is empty!'); + log.verbose( + 'Environment variable ' + level[configEntry].ENV + ' is empty!' + ); } level[configEntry] = process.env[level[configEntry].ENV]; - } else if (level[configEntry] && typeof (level[configEntry]) === 'object') { + } else if (level[configEntry] && typeof level[configEntry] === 'object') { level[configEntry] = walkConfig(level[configEntry]); } } @@ -110,8 +119,12 @@ exports.loadObject = function (_config, currentEnv) { for (var env in config) { if (config[env].ENV) { - if (!process.env[config[env].ENV]) { log.verbose('Environment variable ' + config[env].ENV + ' is empty!'); } else { out[env] = parseDatabaseUrl(process.env[config[env].ENV]); } - } else if (typeof (config[env]) === 'string') { + if (!process.env[config[env].ENV]) { + log.verbose('Environment variable ' + config[env].ENV + ' is empty!'); + } else { + out[env] = parseDatabaseUrl(process.env[config[env].ENV]); + } + } else if (typeof config[env] === 'string') { out[env] = parseDatabaseUrl(config[env]); } else { // Check config entry's for ENV objects @@ -120,8 +133,8 @@ exports.loadObject = function (_config, currentEnv) { out[env] = config[env]; } - if (typeof (config[env].url) === 'string' || process.env.DATABASE_URL) { - if (typeof (config[env].url) !== 'string') { + if (typeof config[env].url === 'string' || process.env.DATABASE_URL) { + if (typeof config[env].url !== 'string') { config[env] = Object.assign( config[env], parseDatabaseUrl(process.env.DATABASE_URL) @@ -142,11 +155,13 @@ exports.loadObject = function (_config, currentEnv) { if (config[env].addIfNotExists) { var addIfNotExists = config[env].addIfNotExists; - Object.keys(addIfNotExists).filter(function (key) { - return !overwrite[key] && !config[env][key]; - }).forEach(function (key) { - config[env][key] = addIfNotExists[key]; - }); + Object.keys(addIfNotExists) + .filter(function (key) { + return !overwrite[key] && !config[env][key]; + }) + .forEach(function (key) { + config[env][key] = addIfNotExists[key]; + }); delete config[env].addIfNotExists; } @@ -177,8 +192,8 @@ exports.loadObject = function (_config, currentEnv) { }; exports.loadUrl = function (databaseUrl, currentEnv) { - var config = parseDatabaseUrl(databaseUrl), - out = new Config(); + var config = parseDatabaseUrl(databaseUrl); + var out = new Config(); if (currentEnv) { out[currentEnv] = config; diff --git a/lib/driver/index.js b/lib/driver/index.js index bf10c28d..845ec3b7 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -5,14 +5,15 @@ internals.mod.log = require('db-migrate-shared').log; internals.mod.type = require('db-migrate-shared').dataType; var Shadow = require('./shadow'); var log = internals.mod.log; -var Promise = require('bluebird'), - SeederInterface = require('../interface/seederInterface.js'), - MigratorInterface = require('../interface/migratorInterface.js'), - resolve = require('resolve'); +var Promise = require('bluebird'); +var SeederInterface = require('../interface/seederInterface.js'); +var MigratorInterface = require('../interface/migratorInterface.js'); +var resolve = require('resolve'); var ShadowProto = { - - createTable: function () { return Promise.resolve(); } + createTable: function () { + return Promise.resolve(); + } }; exports.connect = function (config, intern, callback) { @@ -24,19 +25,21 @@ exports.connect = function (config, intern, callback) { // add interface extensions to allow drivers to add new methods internals.interfaces = { - SeederInterface: SeederInterface.extending, MigratorInterface: MigratorInterface.extending }; - if (!config.user && config.username) { config.user = config.username; } + if (!config.user && config.username) { + config.user = config.username; + } if (config.driver === undefined) { throw new Error( - 'config must include a driver key specifing which driver to use'); + 'config must include a driver key specifing which driver to use' + ); } - if (config.driver && typeof (config.driver) === 'object') { + if (config.driver && typeof config.driver === 'object') { log.verbose('require:', config.driver.require); driver = require(config.driver.require); } else { @@ -55,9 +58,7 @@ exports.connect = function (config, intern, callback) { req = 'db-migrate-' + config.driver; log.verbose('require:', req); try { - driver = require( - resolve.sync(req, { basedir: process.cwd() }) - ); + driver = require(resolve.sync(req, { basedir: process.cwd() })); } catch (e1) { try { driver = require(req); @@ -72,9 +73,17 @@ exports.connect = function (config, intern, callback) { log.verbose('require:', req); driver = require(req); } catch (e4) { - return callback({ stack: 'No such driver found, please try to install it via ' + - 'npm install db-migrate-' + config.driver + ' or ' + - 'npm install -g db-migrate-' + config.driver }); + return callback( + new Error({ + stack: + 'No such driver found, please try to install it via ' + + 'npm install db-migrate-' + + config.driver + + ' or ' + + 'npm install -g db-migrate-' + + config.driver + }) + ); } } } @@ -89,7 +98,9 @@ exports.connect = function (config, intern, callback) { } log.verbose('connected'); - if (!global.immunity) { db = Shadow.infect(db, internals, ShadowProto); } + if (!global.immunity) { + db = Shadow.infect(db, internals, ShadowProto); + } callback(null, db); }); @@ -102,7 +113,9 @@ exports.connect = function (config, intern, callback) { tunnelConfig.dstPort = config.port; if (tunnelConfig.privateKeyPath) { - tunnelConfig.privateKey = require('fs').readFileSync(tunnelConfig.privateKeyPath); + tunnelConfig.privateKey = require('fs').readFileSync( + tunnelConfig.privateKeyPath + ); } // Reassign the db host/port to point to our local ssh tunnel diff --git a/lib/driver/shadow.js b/lib/driver/shadow.js index 65e592f7..6779aa98 100644 --- a/lib/driver/shadow.js +++ b/lib/driver/shadow.js @@ -12,28 +12,29 @@ * 'Infect' the original class */ exports.infect = function (db, intern, ShadowProto) { - var internals = intern; - db._shadowsHost = {}; db._shadowProto = {}; for (var prop in db) { - if (typeof ShadowProto[prop] === 'function' && - typeof db[prop] === 'function') { + if ( + typeof ShadowProto[prop] === 'function' && + typeof db[prop] === 'function' + ) { db._shadowsHost[prop] = db[prop]; db._shadowProto[prop] = ShadowProto[prop]; (function (property) { db[property] = function () { - var params = arguments, - self = this; + var params = arguments; + var self = this; - return self._shadowProto[property].apply(self, params) + return self._shadowProto[property] + .apply(self, params) .then(function () { return self._shadowsHost[property].apply(self, params); }); }; - }(prop)); + })(prop); } } diff --git a/lib/interface/seederInterface.js b/lib/interface/seederInterface.js index 41a0a25d..d5aa53bc 100644 --- a/lib/interface/seederInterface.js +++ b/lib/interface/seederInterface.js @@ -39,10 +39,6 @@ var Promise = require('bluebird'); -function _l (field) { - return { type: 'lookup', field: field }; -} - function insert (table, options, callback) { var foreignLinkage = this.foreignLinkage[table]; @@ -50,15 +46,16 @@ function insert (table, options, callback) { var option = Object.keys(options[o]); for (var i = 0; i < option.length; ++i) { - if (typeof (options[option[i]]) === 'object') { + if (typeof options[option[i]] === 'object') { if (options[option[i]].type === 'lookup') { if (!options[option[i]].table) { if (foreignLinkage[option[i]]) { options[option[i]].table = foreignLinkage[option[i]].table; options[option[i]].field = foreignLinkage[option[i]].field; } else { - return Promise.reject('missing foreign key linkage!') - .nodeify(callback); + return Promise.reject( + new Error('missing foreign key linkage!') + ).nodeify(callback); } } } @@ -77,19 +74,20 @@ function insert (table, options, callback) { } function lookup (options) { - var lookups = [], - i = 0; + var lookups = []; + var i = 0; for (var o = 0; o < options.length; ++o) { var option = Object.keys(options[o]); for (; i < option.length; ++i) { - if (typeof (options[option]) === 'object') { + if (typeof options[option] === 'object') { if (options[option].type === 'lookup') { - lookups.push(this.driver.lookup(options[option]) - .catch(function (err) { + lookups.push( + this.driver.lookup(options[option]).catch(function (err) { throw err; - })); + }) + ); } } } @@ -103,7 +101,6 @@ function dummy () { } var SeederInterface = { - lookup: dummy, insert: dummy, @@ -135,16 +132,14 @@ var SeederInterface = { remove: dummy, close: dummy - }; module.exports = SeederInterface; -module.exports.deprecated = { - -}; +module.exports.deprecated = {}; module.exports.extending = { - _l: function (field) { return { type: 'lookup', field: field }; - } + }, + __Test__insert: insert, + __Test__lookup: lookup }; diff --git a/lib/migration.js b/lib/migration.js index bfad38f5..d94ae5e2 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -5,15 +5,8 @@ var Skeleton = require('./skeleton'); var Promise = require('bluebird'); var filesRegEx = /\.js$/; -var internals = {}; - -function writeMigrationRecord (db, migration, callback) { - db._runSql('INSERT INTO ' + internals.migrationTable + - ' (name, run_on) VALUES (?, ?)', [migration.name, new Date()], callback); -} var Migration = Skeleton.extend({ - init: function () { if (arguments.length >= 3) { this.title = arguments[0]; @@ -34,14 +27,16 @@ var Migration = Skeleton.extend({ } }); -Migration.registerHook = function (plugin, internals) { - var plugin = plugin.hook('migrator:migration:hook:require'); +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); } + if (!plugin) { + return Promise.resolve(null); + } return Promise.resolve(plugin) .map(function (plugin) { @@ -49,15 +44,13 @@ Migration.registerHook = function (plugin, internals) { }) .each(function (parser) { if (parser && parser.extensions) { - internals.parser.extensions = internals.parser.extensions + '|' + - parser.extensions; + internals.parser.extensions = + internals.parser.extensions + '|' + parser.extensions; } }) .then(function () { internals.parser.filesRegEx = new RegExp( - '\\.(' + - internals.parser.extensions + - ')$' + '\\.(' + internals.parser.extensions + ')$' ); return internals.parser; @@ -66,7 +59,7 @@ Migration.registerHook = function (plugin, internals) { Migration.prototype.defaultCoffeeTemplate = function () { return [ - '\'use strict\';', + "'use strict';", '', 'dbm = undefined', 'type = undefined', @@ -89,7 +82,7 @@ Migration.prototype.defaultCoffeeTemplate = function () { Migration.prototype.defaultJsTemplate = function () { return [ - '\'use strict\';', + "'use strict';", '', 'var dbm;', 'var type;', @@ -126,13 +119,13 @@ Migration.prototype.defaultSqlTemplate = function () { Migration.prototype.sqlFileLoaderTemplate = function () { return [ - '\'use strict\';', + "'use strict';", '', 'var dbm;', 'var type;', 'var seed;', - 'var fs = require(\'fs\');', - 'var path = require(\'path\');', + "var fs = require('fs');", + "var path = require('path');", 'var Promise;', '', '/**', @@ -147,12 +140,13 @@ Migration.prototype.sqlFileLoaderTemplate = function () { '};', '', 'exports.up = function(db) {', - ' var filePath = path.join(__dirname, \'sqls\', \'' + this.name.replace( - '.js', '') + '-up.sql\');', + " 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){', + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", ' if (err) return reject(err);', - ' console.log(\'received data: \' + data);', + " console.log('received data: ' + data);", '', ' resolve(data);', ' });', @@ -163,12 +157,13 @@ Migration.prototype.sqlFileLoaderTemplate = function () { '};', '', 'exports.down = function(db) {', - ' var filePath = path.join(__dirname, \'sqls\', \'' + this.name.replace( - '.js', '') + '-down.sql\');', + " 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){', + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", ' if (err) return reject(err);', - ' console.log(\'received data: \' + data);', + " console.log('received data: ' + data);", '', ' resolve(data);', ' });', @@ -187,13 +182,13 @@ Migration.prototype.sqlFileLoaderTemplate = function () { Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function () { return [ - '\'use strict\';', + "'use strict';", '', 'var dbm;', 'var type;', 'var seed;', - 'var fs = require(\'fs\');', - 'var path = require(\'path\');', + "var fs = require('fs');", + "var path = require('path');", 'var ignoreOnInit = false;', 'var Promise;', '', @@ -210,13 +205,14 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function () { '};', '', 'exports.up = function(db, callback) {', - ' var filePath = path.join(__dirname + \'/sqls/' + this.name.replace( - '.js', '') + '-up.sql\');', + " 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){', + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", ' if (err) return reject(err);', - ' console.log(\'received data: \' + data);', + " console.log('received data: ' + data);", '', ' resolve(data);', ' });', @@ -226,18 +222,19 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function () { ' });', ' }', ' else {', - ' console.log(\'ignoring on init: \' + filePath)', + " 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\');', + " 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){', + " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){", ' if (err) return reject(err);', - ' console.log(\'received data: \' + data);', + " console.log('received data: ' + data);", '', ' resolve(data);', ' });', @@ -256,13 +253,13 @@ Migration.prototype.sqlFileLoaderIgnoreOnInitTemplate = function () { Migration.prototype.coffeeSqlFileLoaderTemplate = function () { return [ - '\'use strict\';', + "'use strict';", '', 'dbm = undefined', 'type = undefined', 'seed = undefined', - 'fs = require \'fs\'', - 'path = require \'path\'', + "fs = require 'fs'", + "path = require 'path'", '', '#', '# We receive the dbmigrate dependency from dbmigrate initially.', @@ -275,18 +272,20 @@ Migration.prototype.coffeeSqlFileLoaderTemplate = function () { '', '', 'exports.up = (db, callback) ->', - ' filePath = path.join "#{__dirname}/sqls/' + this.name.replace( - '.coffee', '') + '-up.sql"', - ' fs.readFile filePath, {encoding: \'utf-8\'}, (err,data) ->', + ' 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"', + ' filePath = path.join "#{__dirname}/sqls/' + + this.name.replace('.coffee', '') + + '-down.sql"', - ' fs.readFile filePath, {encoding: \'utf-8\'}, (err,data) ->', + " fs.readFile filePath, {encoding: 'utf-8'}, (err,data) ->", ' return callback err if err', '', ' db.runSql data, callback', @@ -316,7 +315,7 @@ Migration.prototype.getTemplate = function () { case Migration.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT: return this.sqlFileLoaderIgnoreOnInitTemplate(); case Migration.TemplateType.DEFAULT_JS: - /* falls through */ + /* falls through */ default: return this.defaultJsTemplate(); } @@ -333,7 +332,6 @@ Migration.loadFromFilesystem = function (dir, internals, callback) { callback(err); return; } - var coffeeWarn = true; files = files.filter(function (file) { return internals.parser.filesRegEx.test(file); }); @@ -356,20 +354,20 @@ Migration.loadFromDatabase = function (dir, driver, internals, callback) { } 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); - }); + 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); }); } }; -Migration.exportInternals = function (intern) { - internals = intern; -}; - module.exports = Migration; diff --git a/lib/migrator.js b/lib/migrator.js index c7610780..846440cb 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -6,23 +6,31 @@ var MigratorInterface = require('./interface/migratorInterface.js'); function SeedLink (driver, internals) { this.seeder = require('./seeder.js')( - - driver, internals.argv['vcseeder-dir'], true, internals + driver, + internals.argv['vcseeder-dir'], + true, + internals ); + this.internals = internals; this.links = []; } SeedLink.prototype = { - seed: function (partialName) { - var reset = !internals.notransactions; + var reset = !this.internals.notransactions; - internals.notransactions = true; + this.internals.notransactions = true; return new Promise(function (resolve, reject) { this.seeder.up(partialName, function (err) { - if (reset) { internals.notransactions = false; } + if (reset) { + this.internals.notransactions = false; + } - if (err) { reject(err); } else { resolve(err); } + if (err) { + reject(err); + } else { + resolve(err); + } }); }); }, @@ -52,8 +60,6 @@ var Migrator = function (driver, migrationsDir, empty, intern) { } this.internals.migrationOptions.relation = require('./relation'); - - Migration.exportInternals(intern); }; Migrator.prototype = { @@ -70,7 +76,10 @@ Migrator.prototype = { } callback(err); } - this._driver.addMigrationRecord(this.internals.matching + '/' + migration.name, onComplete); + this._driver.addMigrationRecord( + this.internals.matching + '/' + migration.name, + onComplete + ); }, deleteMigrationRecord: function (migration, callback) { @@ -82,13 +91,16 @@ Migrator.prototype = { } 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)); + 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) { @@ -110,9 +122,15 @@ Migrator.prototype = { sync: function (funcOrOpts, callback) { var self = this; - Migration.loadFromDatabase(self.migrationsDir, self._driver, - self.internals, function (err, completedMigrations) { - if (err) { callback(err); return; } + Migration.loadFromDatabase( + self.migrationsDir, + self._driver, + self.internals, + function (err, completedMigrations) { + if (err) { + callback(err); + return; + } var mode = dbmUtil.syncMode( completedMigrations, @@ -125,90 +143,129 @@ Migrator.prototype = { 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; - } - - 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'); + Migration.loadFromFilesystem(self.migrationsDir, self.internals, function ( + err, + allMigrations + ) { + if (err) { + callback(err); + return; + } - return self.seedLink.process(); - } + 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; + } + + 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)); }) - .then(function () { - return (Promise.promisify(self.writeMigrationRecord.bind(self)))(migration); - }) - .then(self.driver.endMigration.bind(self.driver)); - }) - .nodeify(callback); - }); + .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; - } - - 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(); + Migration.loadFromDatabase( + self.migrationsDir, + self._driver, + self.internals, + function (err, completedMigrations) { + if (err) { + return callback(err); + } - if (typeof (setup) === 'function') { setup(self.internals.migrationOptions, self.seedLink); } + var toRun = dbmUtil.filterDown(completedMigrations, partialName, count); - return self.down(migration.down.bind(migration)); - }) - .then(function () { - if (self.seedLink && self.seedLink.links.length) { - log.info('Calling linked seeds'); + if (toRun.length === 0) { + log.info('No migrations to run'); + callback(null); + return; + } - return self.seedLink.process(); - } - }) - .then(function () { - return (Promise.promisify(self.deleteMigrationRecord.bind(self)))(migration); + 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)); }) - .then(self.driver.endMigration.bind(self.driver)); - }) - .nodeify(callback); - }); + .nodeify(callback); + } + ); } }; diff --git a/lib/relation.js b/lib/relation.js index a292f318..c3a42721 100644 --- a/lib/relation.js +++ b/lib/relation.js @@ -1,12 +1,11 @@ -var fs = require('fs'), - log = require('db-migrate-shared').log; +var fs = require('fs'); +var log = require('db-migrate-shared').log; function Relation () { this.relations = {}; } Relation.prototype = { - addRelation: function (table, column, relatedTable, relatedColumn) { this.relations[table] = this.relations[table] || {}; this.relations[table][column] = relatedColumn; diff --git a/lib/seed.js b/lib/seed.js index 86682eea..5bdbf6fc 100644 --- a/lib/seed.js +++ b/lib/seed.js @@ -4,8 +4,7 @@ var log = require('db-migrate-shared').log; var Skeleton = require('./skeleton'); var Seed = Skeleton.extend({ - - init: function() { + init: function () { if (arguments.length >= 3) { this.title = arguments[0]; this.date = arguments[2]; @@ -24,123 +23,114 @@ var Seed = Skeleton.extend({ this._super(this.internals); }, - up: function(db, static) { - - if(static) { - + up: function (db, isStatic) { + if (isStatic) { var seed = require(this.path); - var cb_executed = false; - - return new Promise(function(resolve, reject) { - var r = function( err ) { - if ( cb_executed === false ) { - - cb_executed = 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 && cb_executed === false ) { - - cb_executed = true; - resolve(); - } - }).catch(function(err) { - - if ( cb_executed === false ) { - - cb_executed = true; - reject( err ); + 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(); } - }); - - }.bind(this)).then(function() { - - var seed_executed = false; - - return new Promise(function(resolve, reject) { - var r = function( err ) { - if ( seed_executed === false ) { + }; - seed_executed = true; - - if( err ) { - - log.error('Error while seeding 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(); } - }; - - Promise.resolve(seed.seed.apply( this, [ db, r ] )) - .then(function( Promise ) { - if( Promise !== undefined && seed_executed === false ) { + }) + .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(); + } + }; - seed_executed = true; + Promise.resolve(seed.seed.apply(this, [db, r])) + .then(function (Promise) { + if (Promise !== undefined && seedExecuted === false) { + seedExecuted = true; resolve(); } - }).catch(function(err) { - - if ( seed_executed === false ) { - - seed_executed = true; - reject( err ); + }) + .catch(function (err) { + if (seedExecuted === false) { + seedExecuted = true; + reject(err); } }); - }); - }.bind(this)); - } - else { - + }); + }); + } else { return this._up(db); } }, - down: function(db) { - + down: function (db) { return this._down(db); } }); -Seed.loadFromFilesystem = function(dir, internals, callback) { +Seed.loadFromFilesystem = function (dir, internals, callback) { log.verbose('loading seeds from dir', dir); - fs.readdir(dir, function(err, files) { - if (err) { callback(err); return; } - var coffeeWarn = true; - files = files.filter(function(file) { - + 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) { + 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) { +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) { + 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); - }); + 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); }); diff --git a/lib/seeder.js b/lib/seeder.js index f4b4c1c3..072fc7ff 100644 --- a/lib/seeder.js +++ b/lib/seeder.js @@ -8,13 +8,15 @@ var internals = {}; function MigrationLink (driver, internals) { this.migrator = require('./migrator.js')( - driver, internals.migrationsDir, null, internals + driver, + internals.migrationsDir, + null, + internals ); this.links = []; } MigrationLink.prototype = { - link: function (partialName) { this.links.push(partialName); }, @@ -26,9 +28,15 @@ MigrationLink.prototype = { return new Promise(function (resolve, reject) { this.migrator.up(partialName, function (err) { - if (reset) { internals.notransactions = false; } + if (reset) { + internals.notransactions = false; + } - if (err) { reject(err); } else { resolve(err); } + if (err) { + reject(err); + } else { + resolve(err); + } }); }); }, @@ -38,33 +46,42 @@ MigrationLink.prototype = { internals.notransactions = true; - return new Promise(function (resolve, reject) { - var keys = Object.keys(this.links), - i = 0; - - var migrate = function (i, cb) { - if (i < keys.length) { - if (reset) { internals.notransactions = false; } + return new Promise( + function (resolve, reject) { + var keys = Object.keys(this.links); + var i = 0; - resolve(); - this.clear(); - } - - this.migrator.up({ - destination: this.links[ keys[ i ] ] - }, function (err) { - if (err) { - if (reset) { internals.notransactions = false; } + var migrate = function (i) { + if (i < keys.length) { + if (reset) { + internals.notransactions = false; + } - reject(err); - } else { - cb(++i, migrate); + resolve(); + this.clear(); } - }); - }.bind(this); - migrate(i, migrate); - }.bind(this)); + 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 () { @@ -89,13 +106,16 @@ var Seeder = function (driver, seedsDir, versionControlled, 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); } + if (this.isVC) { + this.up(argv, callback); + } else { + this._staticSeed(argv.destination, callback); + } }, up: function (funcOrOpts, callback) { @@ -136,7 +156,10 @@ Seeder.prototype = { _staticSeed: function (partialName, callback) { var self = this; - return Seed.loadFromFilesystem(self.seedDir, self.internals, function (err, allSeeds) { + return Seed.loadFromFilesystem(self.seedDir, self.internals, function ( + err, + allSeeds + ) { if (err) { callback(err); return; @@ -150,18 +173,22 @@ Seeder.prototype = { return; } - return Promise.resolve(toRun).each(function (seeder) { - log.verbose('preparing to run up seeder:', seeder.name); + 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); } + 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); - }); - }) + return self._driver + .startMigration() + .catch(callback) + .then(function () { + return seeder.up(self.driver, true); + }); + }) .then(self._driver.endMigration.bind(self.driver)) .then(function () { callback(); @@ -181,7 +208,10 @@ Seeder.prototype = { } callback(err); } - this._driver.addSeedRecord(this.internals.matching + '/' + seed.name, onComplete); + this._driver.addSeedRecord( + this.internals.matching + '/' + seed.name, + onComplete + ); }, deleteSeedRecord: function (seed, callback) { @@ -193,67 +223,100 @@ Seeder.prototype = { } 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)); + 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 Seed.loadFromFilesystem(self.seedDir, self.internals, function ( + err, + allMigrations + ) { + if (err) { + callback(err); + return; + } - return self.up(seeder.up.bind(seeder)); - }) - .then(function () { - if (self.seedLink && self.seedLink.links.length) { - log.info('Calling linked migrations'); + 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 self.seedLink.process(self.migrationLink); - } + 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 () { - return (Promise.promisify(self.writeSeedRecord.bind(self)))(seeder); - }) - .then(self._driver.endMigration.bind(self.driver)) - .catch(function (e) { - throw e; + callback(); }); - }) - .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); } + Seed.loadFromDatabase(self.seedDir, self._driver, self.internals, function ( + err, + completedSeeds + ) { + if (err) { + return callback(err); + } var toRun = dbmUtil.filterDown(completedSeeds, count); @@ -263,32 +326,38 @@ Seeder.prototype = { return; } - return Promise.resolve(toRun).each(function (seeder) { - log.verbose('preparing to run down seeder:', seeder.name); + 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(); + return self._driver + .startMigration() + .then(function () { + var setup = seeder.setup(); - if (typeof (setup) === 'function') { setup(self.internals.seederOptions, self.migrationLink); } + 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.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; - }); - }) + 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(); }); diff --git a/lib/skeleton.js b/lib/skeleton.js index 48dfb484..0adca10b 100644 --- a/lib/skeleton.js +++ b/lib/skeleton.js @@ -5,8 +5,13 @@ 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'); + return ( + probe instanceof Promise || + (probe && + probe.then && + probe.constructor && + probe.constructor.name === 'Promise') + ); } function formatPath (dir, name) { @@ -34,7 +39,7 @@ 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})-[^\.]+/); + 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); @@ -45,13 +50,12 @@ function parseDate (name) { } function parseTitle (name) { - var match = name.match(/\d{14}-([^\.]+)/); + 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; }, @@ -59,73 +63,87 @@ var Skeleton = Class.extend({ _up: function () { var params = arguments; - var cb_executed = false; + var cbExecuted = false; - return new Promise(function (resolve, reject) { - var migration, - r = function (err) { - if (cb_executed === false) { - cb_executed = true; + return new Promise( + function (resolve, reject) { + var migration; + var r = function (err) { + if (cbExecuted === false) { + cbExecuted = true; - if (err) { reject(err); } else { resolve(); } + 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 (cb_executed === false) { - cb_executed = true; - resolve(); - } - }).catch(function (err) { - if (cb_executed === false) { - cb_executed = true; - reject(err); - } - }); - } - }.bind(this)); + 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 cb_executed = false; + var cbExecuted = false; - return new Promise(function (resolve, reject) { - var migration, - r = function (err) { - if (cb_executed === false) { - cb_executed = true; + return new Promise( + function (resolve, reject) { + var migration; + var r = function (err) { + if (cbExecuted === false) { + cbExecuted = true; - if (err) { reject(err); } else { resolve(); } + 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 (cb_executed === false) { - cb_executed = true; - resolve(); - } - }).catch(function (err) { - if (cb_executed === false) { - cb_executed = true; - reject(err); - } - }); - } - }.bind(this)); + 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) { @@ -150,7 +168,6 @@ var Skeleton = Class.extend({ formatTitle: formatTitle, formatPath: formatPath, formatName: formatName - }); module.exports = Skeleton; diff --git a/lib/transitions/transitioner.js b/lib/transitions/transitioner.js index ab8bc50b..ea19caa1 100644 --- a/lib/transitions/transitioner.js +++ b/lib/transitions/transitioner.js @@ -9,10 +9,11 @@ module.exports = function (internals) { { properties: { safe: { - description: 'This process is going to alter your migrations. We ' + - 'highly recommend you to backup your migrations or even better safe ' + - 'the current state with git versioning.\nPlease make sure you don\'t ' + - 'blow up yourself.\n\nDo you want to continue? [y/n]', + description: + 'This process is going to alter your migrations. We ' + + 'highly recommend you to backup your migrations or even better safe ' + + "the current state with git versioning.\nPlease make sure you don't " + + 'blow up yourself.\n\nDo you want to continue? [y/n]', message: 'Invalid answer! Do you want to continue? [y/n]', type: 'string', default: 'n', @@ -21,43 +22,57 @@ module.exports = function (internals) { } } } - }, function (err) { - if (err) { return; } + }, + function (err) { + if (err) { + return; + } internals.parser = { filesRegEx: /\.js$/ }; - Migration.loadFromFilesystem('migrations/', internals, - function (err, migrations) { - var messages = []; + Migration.loadFromFilesystem('migrations/', internals, function ( + err, + migrations + ) { + var messages = []; + if (err) { + return; + } - migrations.forEach(function (migration) { - var required = tryRequire(migration, internals); - var version = (required._meta && required._meta.version) + migrations.forEach(function (migration) { + var required = tryRequire(migration, internals); + var version = + required._meta && required._meta.version ? required._meta.version : 0; - if (version !== internals.migrationProtocol) { - var i; + if (version !== internals.migrationProtocol) { + var i; - for (i = 0; i < internals.migrationProtocol; ++i) { - var transition = require('./' + (i + 1)); - transition.transition(); - messages[i + 1] = transition.message; + for (i = 0; i < internals.migrationProtocol; ++i) { + var transition = require('./' + (i + 1)); + transition.transition(); + messages[i + 1] = transition.message; - updateVersion(required, migration, internals, i + 1); - log.info('Transitioned ' + migration.name + '.'); - } - } else { - log.verbose(migration.name, 'was already transitioned to version ' + - internals.migrationProtocol + '.'); + updateVersion(required, migration, internals, i + 1); + log.info('Transitioned ' + migration.name + '.'); } - }); + } else { + log.verbose( + migration.name, + 'was already transitioned to version ' + + internals.migrationProtocol + + '.' + ); + } + }); - messages.forEach(function (message) { - message(); - }); + messages.forEach(function (message) { + message(); }); - }); + }); + } + ); }; diff --git a/lib/transitions/try-require.js b/lib/transitions/try-require.js index fcaea5d8..eb8f532d 100644 --- a/lib/transitions/try-require.js +++ b/lib/transitions/try-require.js @@ -1,4 +1,5 @@ var log = require('db-migrate-shared').log; +var path = require('path'); var fs = require('fs'); var cp = require('child_process'); @@ -7,8 +8,8 @@ var installed = false; var removedGlobals = { 'dbm is not defined': globalHandler, 'async is not defined': globalHandler, - 'Cannot find module \'db-migrate\'': missingDBMigrate, - 'Cannot find module \'async\'': installAsync + "Cannot find module 'db-migrate'": missingDBMigrate, + "Cannot find module 'async'": installAsync }; function missingDBMigrate (migration, retry) { @@ -16,9 +17,13 @@ function missingDBMigrate (migration, retry) { } function installAsync (migration, retry) { - var cmd = [ 'install', '--save', 'async' ]; + var cmd = ['install', '--save', 'async']; - if (installed) { retry(); } else { installed = true; } + if (installed) { + retry(); + } else { + installed = true; + } log.info('Installing async...'); cp.spawnSync('npm', cmd, { @@ -45,16 +50,16 @@ function globalHandler (migration, retry) { handled = true; data = data.replace( /^async = async \|\| require\((?!\s)?'async'(?!\s)?\)/m, - 'var async = require( \'async\' )' + "var async = require( 'async' )" ); } - data = data.replace( - /^var type = dbm.dataType/m, - 'var type' - ); + data = data.replace(/^var type = dbm.dataType/m, 'var type'); if (data.indexOf('exports.setup = ') === -1) { - var snippet = fs.readFileSync(__dirname + '/snippets/setup.sjs', 'utf8'); + var snippet = fs.readFileSync( + path.join(__dirname, '/snippets/setup.sjs'), + 'utf8' + ); data = data.replace(/exports.up/, snippet + '\nexports.up'); } @@ -66,10 +71,7 @@ function globalHandler (migration, retry) { function tryRequire (migration) { try { if (handled && !installed) { - return installAsync( - migration, - tryRequire.bind(this, migration) - ); + return installAsync(migration, tryRequire.bind(this, migration)); } return require(migration.internals.cwd + '/' + migration.path); @@ -88,8 +90,10 @@ function tryRequire (migration) { migration ); - throw new Error('Unhandled ReferenceError while transition. Please ' + - 'fix the issues and rerun the transitioner again.'); + throw new Error( + 'Unhandled ReferenceError while transition. Please ' + + 'fix the issues and rerun the transitioner again.' + ); } } else if (removedGlobals[ex.message]) { return removedGlobals[ex.message]( @@ -98,8 +102,10 @@ function tryRequire (migration) { ); } else { log.error(ex.stack, migration); - throw new Error('Unhandled Error while transition. Please ' + - 'fix the issues and rerun the transitioner again.'); + throw new Error( + 'Unhandled Error while transition. Please ' + + 'fix the issues and rerun the transitioner again.' + ); } } } diff --git a/lib/transitions/update-version.js b/lib/transitions/update-version.js index 4535948c..e67744b8 100644 --- a/lib/transitions/update-version.js +++ b/lib/transitions/update-version.js @@ -7,28 +7,38 @@ function updateVersion (required, migration, internals, version) { var balance; var metaIndex; var plus = 1; + var sub; - if (required._meta) { searchString = 'exports._meta'; } + if (required._meta) { + searchString = 'exports._meta'; + } metaIndex = data.indexOf(searchString); sub = data.substring(metaIndex); balance = balanced('{', '}', sub); - if (sub[balance.end + 1] === ';') { ++plus; } + if (sub[balance.end + 1] === ';') { + ++plus; + } sub = sub.substring(0, balanced.end); if (required._meta) { required._meta.version = version; - data = data.substring(0, metaIndex) + sub.replace( - sub.substring(balance.start, balance.end + 1), - JSON.stringify(required._meta, null, 2) - ) + data.substring(metaIndex + balance.end + plus); + data = + data.substring(0, metaIndex) + + sub.replace( + sub.substring(balance.start, balance.end + 1), + JSON.stringify(required._meta, null, 2) + ) + + data.substring(metaIndex + balance.end + plus); } else { - data = data.substring(0, metaIndex + balance.end + plus) + + data = + data.substring(0, metaIndex + balance.end + plus) + '\n\nexports._meta = ' + - JSON.stringify({ version: version }, null, 2) + ';' + + JSON.stringify({ version: version }, null, 2) + + ';' + data.substring(metaIndex + balance.end + plus); } diff --git a/test/config_test.js b/test/config_test.js index 108aae54..2d78d485 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -1,29 +1,33 @@ var Code = require('code'); var Lab = require('lab'); -var lab = exports.lab = Lab.script(); +var lab = (exports.lab = Lab.script()); var config = require('../lib/config'); var path = require('path'); -var sinon = require('sinon'); var _configLoad = config.load; var _configLoadUrl = config.loadUrl; lab.experiment('config', function () { - lab.experiment('loading from a file', { parallel: true }, - function () { - var configPath = path.join(__dirname, 'database.json'); - var _config = config.load(configPath, 'dev'); + lab.experiment('loading from a file', { parallel: true }, function () { + var configPath = path.join(__dirname, 'database.json'); + var _config = config.load(configPath, 'dev'); - lab.test('should export all environment settings', { parallel: true }, - function (done) { - Code.expect(_config.dev).to.exists(); - Code.expect(_config.test).to.exists(); - Code.expect(_config.prod).to.exists(); - done(); - }); + lab.test( + 'should export all environment settings', + { parallel: true }, + function (done) { + Code.expect(_config.dev).to.exists(); + Code.expect(_config.test).to.exists(); + Code.expect(_config.prod).to.exists(); + done(); + } + ); - lab.test('should export a getCurrent function with all current ' + - 'environment settings', { parallel: true }, function (done) { + lab.test( + 'should export a getCurrent function with all current ' + + 'environment settings', + { parallel: true }, + function (done) { var current; Code.expect(_config.getCurrent).to.exists(); current = _config.getCurrent(); @@ -31,40 +35,53 @@ lab.experiment('config', function () { Code.expect(current.settings.driver).to.equal('sqlite3'); Code.expect(current.settings.filename).to.equal(':memory:'); done(); - }); - }); + } + ); + }); - lab.experiment('loading from a broken config file', { parallel: true }, + lab.experiment( + 'loading from a broken config file', + { parallel: true }, function () { var configPath = path.join(__dirname, 'database_with_syntax_error.json'); - lab.test('should throw a syntax error', { parallel: true }, - function (done) { - Code.expect( - config.load.bind(this, configPath, 'dev'), - 'Expected broken file to produce syntax error' - ).to.throw(SyntaxError); - done(); - }); - }); + lab.test('should throw a syntax error', { parallel: true }, function ( + done + ) { + Code.expect( + config.load.bind(this, configPath, 'dev'), + 'Expected broken file to produce syntax error' + ).to.throw(SyntaxError); + done(); + }); + } + ); - lab.experiment('loading from a file with default env option', - { parallel: true }, function () { + lab.experiment( + 'loading from a file with default env option', + { parallel: true }, + function () { var configPath = path.join(__dirname, 'database_with_default_env.json'); var _config = config.load(configPath); - lab.test('should load a value from the default env', { parallel: true }, + lab.test( + 'should load a value from the default env', + { parallel: true }, function (done) { var current = _config.getCurrent(); Code.expect(current.env).to.equal('local'); Code.expect(current.settings.driver).to.equal('sqlite3'); Code.expect(current.settings.filename).to.equal(':memory:'); done(); - }); - }); + } + ); + } + ); - lab.experiment('loading from a file with default env option in ENV variable', - { parallel: true }, function () { + lab.experiment( + 'loading from a file with default env option in ENV variable', + { parallel: true }, + function () { process.env.NODE_ENV = 'local'; var configPath = path.join( __dirname, @@ -72,35 +89,49 @@ lab.experiment('config', function () { ); var _config = config.load(configPath); - lab.test('should load a value from the env set in NODE_ENV', - { parallel: true }, function (done) { + lab.test( + 'should load a value from the env set in NODE_ENV', + { parallel: true }, + function (done) { var current = _config.getCurrent(); Code.expect(current.settings.driver).to.equal('sqlite3'); Code.expect(current.settings.filename).to.equal(':memory:'); done(); - }); - }); + } + ); + } + ); - lab.experiment('loading from a file with ENV vars', { parallel: true }, + lab.experiment( + 'loading from a file with ENV vars', + { parallel: true }, function () { process.env.DB_MIGRATE_TEST_VAR = 'username_from_env'; var configPath = path.join(__dirname, 'database_with_env.json'); var _config = config.load(configPath, 'prod'); - lab.test('should load a value from the environments', { parallel: true }, + lab.test( + 'should load a value from the environments', + { parallel: true }, function (done) { Code.expect(_config.prod.username).to.equal('username_from_env'); done(); - }); - }); + } + ); + } + ); - lab.experiment('loading from a file with ENV URL', { parallel: true }, + lab.experiment( + 'loading from a file with ENV URL', + { parallel: true }, function () { process.env.DB_MIGRATE_TEST_VAR = 'postgres://uname:pw@server.com/dbname'; var configPath = path.join(__dirname, 'database_with_env_url.json'); var _config = config.load(configPath, 'prod'); - lab.test('should load a value from the environments', { parallel: true }, + lab.test( + 'should load a value from the environments', + { parallel: true }, function (done) { var current = _config.getCurrent(); Code.expect(current.settings.driver).to.equal('postgres'); @@ -109,22 +140,29 @@ lab.experiment('config', function () { Code.expect(current.settings.host, ').to.equal(rver.com'); Code.expect(current.settings.database).to.equal('dbname'); done(); - }); - }); + } + ); + } + ); - lab.experiment('loading from an URL', { parallel: true }, - function () { - var databaseUrl = 'postgres://uname:pw@server.com/dbname'; - var _config = config.loadUrl(databaseUrl, 'dev'); + lab.experiment('loading from an URL', { parallel: true }, function () { + var databaseUrl = 'postgres://uname:pw@server.com/dbname'; + var _config = config.loadUrl(databaseUrl, 'dev'); - lab.test('should export the settings as the current environment', - { parallel: true }, function (done) { - Code.expect(_config.dev).to.exists(); - done(); - }); + lab.test( + 'should export the settings as the current environment', + { parallel: true }, + function (done) { + Code.expect(_config.dev).to.exists(); + done(); + } + ); - lab.test('should export a getCurrent function with all current ' + - 'environment settings', { parallel: true }, function (done) { + lab.test( + 'should export a getCurrent function with all current ' + + 'environment settings', + { parallel: true }, + function (done) { var current; Code.expect(_config.getCurrent).to.exists(); current = _config.getCurrent(); @@ -135,8 +173,9 @@ lab.experiment('config', function () { Code.expect(current.settings.host).to.equal('server.com'); Code.expect(current.settings.database).to.equal('dbname'); done(); - }); - }); + } + ); + }); lab.experiment('loading a config with null values', function () { var configPath = path.join(__dirname, 'database_with_null_values.json'); @@ -144,74 +183,75 @@ lab.experiment('config', function () { config.loadUrl = _configLoadUrl; lab.test('should something', function (done) { - Code.expect( - config.load.bind(this, configPath, 'dev') - ).to.not.throw; + Code.expect(config.load.bind(this, configPath, 'dev')).to.not.throw(); done(); }); }); lab.experiment('loading a url from url property', function () { - lab.test('should export a valid config', - function (done) { - var databaseUrl = { - 'dev': { - 'url': 'postgres://uname:pw@server.com/dbname' - } - }; - var cfg = config.loadObject(databaseUrl, 'dev'); - - Code.expect(cfg.getCurrent).to.exists(); - var current = cfg.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.url).to.not.exists(); - Code.expect(current.settings.driver).to.equal('postgres'); - Code.expect(current.settings.user).to.equal('uname'); - Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host).to.equal('server.com'); - Code.expect(current.settings.database).to.equal('dbname'); + lab.test('should export a valid config', function (done) { + var databaseUrl = { + dev: { + url: 'postgres://uname:pw@server.com/dbname' + } + }; + var cfg = config.loadObject(databaseUrl, 'dev'); + + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.not.exists(); + Code.expect(current.settings.driver).to.equal('postgres'); + Code.expect(current.settings.user).to.equal('uname'); + Code.expect(current.settings.password).to.equal('pw'); + Code.expect(current.settings.host).to.equal('server.com'); + Code.expect(current.settings.database).to.equal('dbname'); - done(); - }); + done(); + }); - lab.test('should export the value if specified in suboject', - function (done) { - var databaseUrl = { - 'dev': { - 'url': { - 'value': 'http://example.com' - } + lab.test('should export the value if specified in suboject', function ( + done + ) { + var databaseUrl = { + dev: { + url: { + value: 'http://example.com' } - }; - var cfg = config.loadObject(databaseUrl, 'dev'); + } + }; + var cfg = config.loadObject(databaseUrl, 'dev'); - Code.expect(cfg.getCurrent).to.exists(); - var current = cfg.getCurrent(); - Code.expect(current.env).to.equal('dev'); - Code.expect(current.settings.url).to.equal('http://example.com'); + Code.expect(cfg.getCurrent).to.exists(); + var current = cfg.getCurrent(); + Code.expect(current.env).to.equal('dev'); + Code.expect(current.settings.url).to.equal('http://example.com'); - done(); - }); + done(); + }); }); lab.experiment('loading from an URL and overwriting it', function () { var databaseUrl = { - 'dev': { - 'url': 'postgres://uname:pw@server.com/dbname', - 'overwrite': { - 'ssl': true + dev: { + url: 'postgres://uname:pw@server.com/dbname', + overwrite: { + ssl: true } } }; var cfg = config.loadObject(databaseUrl, 'dev'); - lab.test('should export the settings as the current environment', function (done) { + lab.test('should export the settings as the current environment', function ( + done + ) { Code.expect(cfg.dev).to.exists(); done(); }); - lab.test('should export a getCurrent function with all current environment settings', + lab.test( + 'should export a getCurrent function with all current environment settings', function (done) { Code.expect(cfg.getCurrent).to.exists(); var current = cfg.getCurrent(); @@ -226,19 +266,22 @@ lab.experiment('config', function () { Code.expect(current.settings.ssl).to.equal(true); done(); - }); + } + ); }); - lab.experiment('loading from an ENV URL within the object and overwriting it', + lab.experiment( + 'loading from an ENV URL within the object and overwriting it', function () { - lab.test('should export a getCurrent function with all current environment settings', + lab.test( + 'should export a getCurrent function with all current environment settings', function (done, cleanup) { process.env.DATABASE_URL = 'postgres://uname:pw@server.com/dbname'; var databaseUrl = { - 'dev': { - 'url': { 'ENV': 'DATABASE_URL' }, - 'overwrite': { - 'ssl': true + dev: { + url: { ENV: 'DATABASE_URL' }, + overwrite: { + ssl: true } } }; @@ -262,26 +305,30 @@ lab.experiment('config', function () { Code.expect(current.settings.ssl).to.equal(true); done(); - }); - }); + } + ); + } + ); - lab.experiment('loading from an ENV URL within the object and extending it from the ENV', + lab.experiment( + 'loading from an ENV URL within the object and extending it from the ENV', function () { lab.test('', function (done, cleanup) { - process.env.DATABASE_URL = 'postgres://uname:pw@server.com/dbname?ssl=false&testing=false'; + process.env.DATABASE_URL = + 'postgres://uname:pw@server.com/dbname?ssl=false&testing=false'; var databaseUrl = { - 'dev': { - 'url': { - 'ENV': 'DATABASE_URL' + dev: { + url: { + ENV: 'DATABASE_URL' }, - 'overwrite': { - 'ssl': true, - 'cache': false + overwrite: { + ssl: true, + cache: false }, - 'addIfNotExists': { - 'native': true, // this on is new - 'cache': true, // overwrite should have higher priority - 'testing': true // already in config do not overwrite + addIfNotExists: { + native: true, // this on is new + cache: true, // overwrite should have higher priority + testing: true // already in config do not overwrite } } }; @@ -310,5 +357,6 @@ lab.experiment('config', function () { done(); }); - }); + } + ); }); diff --git a/test/integration/api_test.js b/test/integration/api_test.js index dc551d25..a83fe843 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -10,10 +10,10 @@ lab.experiment('api', { parallel: true }, function () { 'force process exit after migrations have been run', { parallel: true }, function (done, onCleanup) { - var process_exit = process.exit, - argv = process.argv, - called = false, - config = {}; + var processExit = process.exit; + var argv = process.argv; + var called = false; + var config = {}; // register cleanup method and start preparing the test onCleanup(teardown); @@ -66,7 +66,7 @@ lab.experiment('api', { parallel: true }, function () { var ret = called; called = true; - process.exit = process_exit; + process.exit = processExit; if (err) process.exit.apply(arguments); @@ -76,7 +76,7 @@ lab.experiment('api', { parallel: true }, function () { } function teardown (next) { - process.exit = process_exit; + process.exit = processExit; process.argv = argv; return next(); } @@ -230,10 +230,10 @@ function loader (stubs) { function stubApiInstance (isModule, stubs, options, callback) { delete require.cache[require.resolve('../../api.js')]; delete require.cache[require.resolve('optimist')]; - var mod = proxyquire('../../api.js', { - './lib/commands': loader(stubs) - }), - plugins = {}; + var Mod = proxyquire('../../api.js', { + './lib/commands': loader(stubs) + }); + var plugins = {}; options = options || {}; options = Object.assign(options, { @@ -241,5 +241,5 @@ function stubApiInstance (isModule, stubs, options, callback) { cwd: __dirname }); - return new mod(plugins, isModule, options, callback); + return new Mod(plugins, isModule, options, callback); } diff --git a/test/migration_test.js b/test/migration_test.js index 330a7575..989cf442 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -1,7 +1,7 @@ var Code = require('code'); var Lab = require('lab'); var proxyquire = require('proxyquire').noPreserveCache(); -var lab = exports.lab = Lab.script(); +var lab = (exports.lab = Lab.script()); var Migration = require('../lib/migration.js'); var date = createDateForTest(); @@ -15,14 +15,19 @@ var internals = {}; internals.migrationTable = 'migrations'; lab.experiment('migration', { parallel: true }, function () { - lab.experiment('when creating a new migration object', { parallel: true }, - newMigrationObject); - - lab.experiment('get template', { parallel: true }, - getTemplate); - - lab.experiment('when using db-migrate as module', { parallel: true }, - asModule); + lab.experiment( + 'when creating a new migration object', + { parallel: true }, + newMigrationObject + ); + + lab.experiment('get template', { parallel: true }, getTemplate); + + lab.experiment( + 'when using db-migrate as module', + { parallel: true }, + asModule + ); }); function asModule () { @@ -35,195 +40,260 @@ function asModule () { } function newMigrationObject () { - lab.experiment('with 2 parameters as the complete filepath', - { parallel: true }, function () { - var migration = new Migration(dirName + dateString + '-' + fileName, internals); - - lab.test('should have title set without file extension', { parallel: true }, + lab.experiment( + 'with 2 parameters as the complete filepath', + { parallel: true }, + function () { + var migration = new Migration( + dirName + dateString + '-' + fileName, + internals + ); + + lab.test( + 'should have title set without file extension', + { parallel: true }, function (done) { Code.expect(migration.title).to.equal(fileNameNoExtension); done(); - }); + } + ); - lab.test('should have date set', { parallel: true }, - function (done) { - migration.date.setMilliseconds(0); - date.setMilliseconds(0); - Code.expect(migration.date.getTime()).to.equal(date.getTime()); - done(); - }); + lab.test('should have date set', { parallel: true }, function (done) { + migration.date.setMilliseconds(0); + date.setMilliseconds(0); + Code.expect(migration.date.getTime()).to.equal(date.getTime()); + done(); + }); - lab.test('should have name set without file extension', { parallel: true }, + lab.test( + 'should have name set without file extension', + { parallel: true }, function (done) { - Code.expect(migration.name).to.equal(dateString + '-' + fileNameNoExtension); + Code.expect(migration.name).to.equal( + dateString + '-' + fileNameNoExtension + ); done(); - }); + } + ); - lab.test('should have path set', { parallel: true }, - function (done) { - Code.expect(migration.path).to.equal(dirName + dateString + '-' + fileName); - done(); - }); + lab.test('should have path set', { parallel: true }, function (done) { + Code.expect(migration.path).to.equal( + dirName + dateString + '-' + fileName + ); + done(); + }); - lab.test('should have templateType not set', { parallel: true }, - function (done) { - Code.expect(migration.templateType).to.be.undefined(); - done(); - }); - }); + lab.test('should have templateType not set', { parallel: true }, function ( + done + ) { + Code.expect(migration.templateType).to.be.undefined(); + done(); + }); + } + ); lab.experiment('with 3 parameters', { parallel: true }, function () { var migration = new Migration(fileName, dirName, date); - lab.test('should have title set', { parallel: true }, - function (done) { - Code.expect(migration.title).to.equal(fileName); - done(); - }); + lab.test('should have title set', { parallel: true }, function (done) { + Code.expect(migration.title).to.equal(fileName); + done(); + }); - lab.test('should have date set with month', { parallel: true }, - function (done) { - Code.expect(migration.date).to.equal(date); - done(); - }); + lab.test('should have date set with month', { parallel: true }, function ( + done + ) { + Code.expect(migration.date).to.equal(date); + done(); + }); - lab.test('should have name set', { parallel: true }, - function (done) { - Code.expect(migration.name).to.equal(dateString + '-' + fileName); - done(); - }); + lab.test('should have name set', { parallel: true }, function (done) { + Code.expect(migration.name).to.equal(dateString + '-' + fileName); + done(); + }); - lab.test('should have path set', { parallel: true }, - function (done) { - Code.expect(migration.path).to.equal(dirName + dateString + '-' + fileName); - done(); - }); + lab.test('should have path set', { parallel: true }, function (done) { + Code.expect(migration.path).to.equal( + dirName + dateString + '-' + fileName + ); + done(); + }); - lab.test('should have templateType not set', { parallel: true }, - function (done) { - Code.expect(migration.templateType).to.be.undefined(); - done(); - }); + lab.test('should have templateType not set', { parallel: true }, function ( + done + ) { + Code.expect(migration.templateType).to.be.undefined(); + done(); + }); }); lab.experiment('with 5 parameters', { parallel: true }, function () { - var migration = new Migration(fileName, dirName, date, templateType, - internals); - - lab.test('should have title set', { parallel: true }, - function (done) { - Code.expect(migration.title).to.equal(fileName); - done(); - }); + var migration = new Migration( + fileName, + dirName, + date, + templateType, + internals + ); + + lab.test('should have title set', { parallel: true }, function (done) { + Code.expect(migration.title).to.equal(fileName); + done(); + }); - lab.test('should have date set', { parallel: true }, - function (done) { - Code.expect(migration.date).to.equal(date); - done(); - }); + lab.test('should have date set', { parallel: true }, function (done) { + Code.expect(migration.date).to.equal(date); + done(); + }); - lab.test('should have name set', { parallel: true }, - function (done) { - Code.expect(migration.name).to.equal(dateString + '-' + fileName); - done(); - }); + lab.test('should have name set', { parallel: true }, function (done) { + Code.expect(migration.name).to.equal(dateString + '-' + fileName); + done(); + }); - lab.test('should have path set', { parallel: true }, - function (done) { - Code.expect(migration.path).to.equal(dirName + dateString + '-' + fileName); - done(); - }); + lab.test('should have path set', { parallel: true }, function (done) { + Code.expect(migration.path).to.equal( + dirName + dateString + '-' + fileName + ); + done(); + }); - lab.test('should have templateType set', { parallel: true }, - function (done) { - Code.expect(migration.templateType).to.equal(templateType); - done(); - }); + lab.test('should have templateType set', { parallel: true }, function ( + done + ) { + Code.expect(migration.templateType).to.equal(templateType); + done(); + }); }); } function getTemplate () { - lab.experiment('when template type is not set', { parallel: true }, + lab.experiment( + 'when template type is not set', + { parallel: true }, function () { var migration = new Migration(fileName, dirName, date, internals); - lab.test('should return default javascript template', { parallel: true }, + lab.test( + 'should return default javascript template', + { parallel: true }, function (done) { var actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultJsTemplate()); done(); - }); + } + ); + } + ); + + lab.experiment('when template type is set', { parallel: true }, function () { + lab.experiment('as sql file loader', { parallel: true }, function () { + var migration = new Migration( + fileName, + dirName, + date, + Migration.TemplateType.SQL_FILE_LOADER, + internals + ); + + lab.test( + 'should return sql file loader template', + { parallel: true }, + function (done) { + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.sqlFileLoaderTemplate()); + done(); + } + ); }); - lab.experiment('when template type is set', { parallel: true }, - function () { - lab.experiment('as sql file loader', { parallel: true }, function () { - var migration = new Migration(fileName, dirName, date, - Migration.TemplateType.SQL_FILE_LOADER, internals); - - lab.test('should return sql file loader template', { parallel: true }, - function (done) { - var actual = migration.getTemplate(); - Code.expect(actual).to.equal(migration.sqlFileLoaderTemplate()); - done(); - }); - }); - - lab.experiment('as default sql', { parallel: true }, function () { - var migration = new Migration(fileName, dirName, date, - Migration.TemplateType.DEFAULT_SQL, internals); - - lab.test('should return default sql template', { parallel: true }, - function (done) { - var actual = migration.getTemplate(); - Code.expect(actual).to.equal(migration.defaultSqlTemplate()); - done(); - }); - }); - - lab.experiment('as default coffee', { parallel: true }, function () { - var migration = new Migration(fileName, dirName, date, - Migration.TemplateType.DEFAULT_COFFEE, internals); - - lab.test('should return default coffee template', { parallel: true }, - function (done) { - var actual = migration.getTemplate(); - Code.expect(actual).to.equal(migration.defaultCoffeeTemplate()); - done(); - }); - }); - - lab.experiment('as coffee sql loader', { parallel: true }, function () { - var migration = new Migration(fileName, dirName, date, - Migration.TemplateType.COFFEE_SQL_FILE_LOADER, internals); + lab.experiment('as default sql', { parallel: true }, function () { + var migration = new Migration( + fileName, + dirName, + date, + Migration.TemplateType.DEFAULT_SQL, + internals + ); + + lab.test( + 'should return default sql template', + { parallel: true }, + function (done) { + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.defaultSqlTemplate()); + done(); + } + ); + }); - lab.test('should return default coffee template', { parallel: true }, - function (done) { - var actual = migration.getTemplate(); - Code.expect(actual).to.equal(migration.coffeeSqlFileLoaderTemplate()); - done(); - }); - }); + lab.experiment('as default coffee', { parallel: true }, function () { + var migration = new Migration( + fileName, + dirName, + date, + Migration.TemplateType.DEFAULT_COFFEE, + internals + ); + + lab.test( + 'should return default coffee template', + { parallel: true }, + function (done) { + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.defaultCoffeeTemplate()); + done(); + } + ); + }); - lab.experiment('as default javascript', { parallel: true }, function () { - var migration = new Migration(fileName, dirName, date, - Migration.TemplateType.DEFAULT_JS, internals); + lab.experiment('as coffee sql loader', { parallel: true }, function () { + var migration = new Migration( + fileName, + dirName, + date, + Migration.TemplateType.COFFEE_SQL_FILE_LOADER, + internals + ); + + lab.test( + 'should return default coffee template', + { parallel: true }, + function (done) { + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.coffeeSqlFileLoaderTemplate()); + done(); + } + ); + }); - lab.test('should return default sql template', { parallel: true }, - function (done) { - var actual = migration.getTemplate(); - Code.expect(actual).to.equal(migration.defaultJsTemplate()); - done(); - }); - }); + lab.experiment('as default javascript', { parallel: true }, function () { + var migration = new Migration( + fileName, + dirName, + date, + Migration.TemplateType.DEFAULT_JS, + internals + ); + + lab.test( + 'should return default sql template', + { parallel: true }, + function (done) { + var actual = migration.getTemplate(); + Code.expect(actual).to.equal(migration.defaultJsTemplate()); + done(); + } + ); }); + }); } 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), - plugins = {}; + var Mod = proxyquire('../api.js', stubs); + var plugins = {}; options = options || {}; options = Object.assign(options, { @@ -231,7 +301,7 @@ function stubApiInstance (isModule, stubs, options, callback) { cwd: __dirname }); - return new mod(plugins, isModule, options, callback); + return new Mod(plugins, isModule, options, callback); } function createDateForTest () { From 18a003283231aaa3eb9a8136034d5e98acc845ca Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 18 Nov 2017 15:01:09 +0100 Subject: [PATCH 356/412] remove process.exit when no callback passed and remove optimist help when in module mode Fixes #516 --- api.js | 3 +++ lib/commands/create-migration.js | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/api.js b/api.js index 5282c7f8..8e980865 100644 --- a/api.js +++ b/api.js @@ -24,6 +24,9 @@ function dbmigrate (plugins, isModule, options, callback) { onComplete: onComplete, migrationProtocol: 1 }; + if (typeof isModule !== 'function') { + this.internals.isModule = isModule; + } var internals = this.internals; this.internals.plugins = load('fn/plugin')(plugins); diff --git a/lib/commands/create-migration.js b/lib/commands/create-migration.js index 6cf38eed..92adc3fb 100644 --- a/lib/commands/create-migration.js +++ b/lib/commands/create-migration.js @@ -31,8 +31,15 @@ function executeCreateMigration (internals, config, callback) { if (internals.argv._.length === 0) { log.error("'migrationName' is required."); - optimist.showHelp(); - process.exit(1); + if (!internals.isModule) { + optimist.showHelp(); + } + + if (typeof callback !== 'function') { + process.exit(1); + } else { + return callback(new Error("'migrationName' is required.")); + } } createMigrationDir(migrationsDir, function (err) { @@ -41,7 +48,11 @@ function executeCreateMigration (internals, config, callback) { if (err) { log.error('Failed to create migration directory at ', migrationsDir, err); - process.exit(1); + if (typeof callback !== 'function') { + process.exit(1); + } else { + return callback(new Error('Failed to create migration directory.')); + } } internals.argv.title = internals.argv._.shift(); @@ -88,7 +99,7 @@ function executeCreateMigration (internals, config, callback) { createSqlFiles(internals, config, callback); } else { if (typeof callback === 'function') { - callback(); + return callback(); } } } From aa25283e88974ce0b06bb14a8f0c8548dbb1f28a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 17:30:45 +0100 Subject: [PATCH 357/412] add changelog and release 0.10.0 --- CHANGELOG.md | 30 + package-lock.json | 3822 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3852 insertions(+) create mode 100644 package-lock.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f1c6596..71786de6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ + +## 0.10.0 + +Note: + +This is a cornerstone release. It provides groundwork for many things to come and has worked +on stability and flexibility, while mostly retaining backwards compatibility. + +This release was a rewrite of nearly the whole module. However backwards compatibility +was mostly preeserved. Bug fixes wont be listed for this release, all subsequent releases +will follow the angular standard to automatically generate changelogs. + +New Features: + - Sync + - Driverless Core + - Plugin Hooks and overwrites + - Adjusted migration schema, to allow specific setup routines + - Version migration schemas itself for future iterations + - Promise style migrations + - Programmatic API + - Restructered major parts of db-migrate + - Transactional migrations + - New configuration options + +Find a full list of features added here: + +https://github.com/db-migrate/node-db-migrate/issues?utf8=%E2%9C%93&q=milestone%3Av0.10.0 + +# Old Changelogs + ## 0.1.0 New Features: diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..72d98811 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3822 @@ +{ + "name": "db-migrate", + "version": "0.10.0-beta.24", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "acorn": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.4.0.tgz", + "integrity": "sha1-MtHPCNvIDEMvQm8S4QslEfa0ZHQ=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + }, + "bignumber.js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.4.tgz", + "integrity": "sha512-LDXpJKVzEx2/OqNbG9mXBNvHuiRL4PzHCGfnANHMJ+fv68Ads3exDVJeGDJws+AoNEuca93bU3q+S0woeUaCdg==", + "dev": true + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "bossy": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/bossy/-/bossy-3.0.4.tgz", + "integrity": "sha1-+a6fJugbQaMY9O4Ng2huSlwlB7k=", + "dev": true, + "requires": { + "hoek": "4.2.0", + "joi": "10.6.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "chardet": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.0.tgz", + "integrity": "sha1-C74TVaxE16PtSpJXB8TvcPgZD2w=", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/code/-/code-4.1.0.tgz", + "integrity": "sha1-IJrRHQWvigwceq9pTZ+k0sfZW4U=", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-thenable": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/create-thenable/-/create-thenable-1.0.2.tgz", + "integrity": "sha1-4gMXIMzJV12M+jH1wUbnYqgMBTQ=", + "dev": true, + "requires": { + "object.omit": "2.0.1", + "unique-concat": "0.2.2" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.35" + } + }, + "db-migrate-base": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/db-migrate-base/-/db-migrate-base-1.5.3.tgz", + "integrity": "sha512-dbJHFVYIY75vSOL3MD4qbpjilcwrYn7ZnTqsdA2AGs6w1mYugspfWEBea+uMgJVH/YsUFxw2AYPKRHCHUjhirw==", + "dev": true, + "requires": { + "bluebird": "3.5.1" + } + }, + "db-migrate-mysql": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/db-migrate-mysql/-/db-migrate-mysql-1.1.10.tgz", + "integrity": "sha1-TB1e8R9ZO1qPHxIkkIO+5xWnzKw=", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "db-migrate-base": "1.5.3", + "moment": "2.19.2", + "mysql": "2.15.0" + } + }, + "db-migrate-shared": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/db-migrate-shared/-/db-migrate-shared-1.1.3.tgz", + "integrity": "sha1-7bPIF7KVAixhmEwYcmdBm7NqLVg=" + }, + "db-migrate-sqlite3": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/db-migrate-sqlite3/-/db-migrate-sqlite3-0.1.9.tgz", + "integrity": "sha1-X1tUIRMZuvxH+Az+LZpSxPl1ud8=", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "db-migrate-base": "1.5.3", + "sqlite3": "3.1.13" + } + }, + "debug": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", + "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", + "requires": { + "ms": "0.7.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "optional": true + }, + "deep-equal": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", + "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=" + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.5.4" + } + }, + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "dev": true + }, + "doctrine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "dotenv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-2.0.0.tgz", + "integrity": "sha1-vXWcNXqqcDZeAclrewvsCKbg2Uk=" + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es5-ext": { + "version": "0.10.35", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.35.tgz", + "integrity": "sha1-GO6FjOajxFx9eekcFfzKnsVoSU8=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.35", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.35", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.35", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.35" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.35", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.11.0.tgz", + "integrity": "sha512-UWbhQpaKlm8h5x/VLwm0S1kheMrDj8jPwhnBMjr/Dlo3qqT7MvcN/UfKAR3E1N4lr4YNtOvS4m3hwsrVc/ky7g==", + "dev": true, + "requires": { + "ajv": "5.4.0", + "babel-code-frame": "6.26.0", + "chalk": "2.3.0", + "concat-stream": "1.6.0", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.0.0", + "eslint-scope": "3.7.1", + "espree": "3.5.2", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-config-hapi": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-hapi/-/eslint-config-hapi-10.1.0.tgz", + "integrity": "sha512-tAUedyvZla1qKt6jhOx7mj5tYDVCwdSyImpEK7wk/A/atKUjg18aHUK6Q6qWWM6rq21I1F/A8JAhIpkk0SvFMQ==", + "dev": true + }, + "eslint-config-standard": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz", + "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==", + "dev": true, + "requires": { + "debug": "2.6.9", + "resolve": "1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "pkg-dir": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-hapi": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-hapi/-/eslint-plugin-hapi-4.1.0.tgz", + "integrity": "sha512-z1yUoSWArx6pXaC0FoWRFpqjbHn8QWonJiTVhJmiC14jOAT7FZKdKWCkhM4jQrgrkEK9YEv3p2HuzSf5dtWmuQ==", + "dev": true, + "requires": { + "hapi-capitalize-modules": "1.1.6", + "hapi-for-you": "1.0.0", + "hapi-no-var": "1.0.1", + "hapi-scope-start": "2.1.1", + "no-arrowception": "1.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", + "dev": true, + "requires": { + "builtin-modules": "1.1.1", + "contains-path": "0.1.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.3.1", + "eslint-module-utils": "2.1.1", + "has": "1.0.1", + "lodash.cond": "4.5.2", + "minimatch": "3.0.4", + "read-pkg-up": "2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "dev": true, + "requires": { + "ignore": "3.3.7", + "minimatch": "3.0.4", + "resolve": "1.5.0", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", + "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "espree": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "dev": true, + "requires": { + "acorn": "5.2.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.35" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "dev": true, + "requires": { + "chardet": "0.4.0", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "dev": true, + "requires": { + "is-object": "1.0.1", + "merge-descriptors": "1.0.1" + } + }, + "final-fs": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/final-fs/-/final-fs-1.6.1.tgz", + "integrity": "sha1-1tzZLvb+T+jAer1WjHE1YQ7eMjY=", + "requires": { + "node-fs": "0.1.7", + "when": "2.0.1" + } + }, + "find-rc": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/find-rc/-/find-rc-3.0.1.tgz", + "integrity": "sha1-VKQXg3DxC8k3H6jRssKAmir6DM4=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "1.1.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "hapi-capitalize-modules": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/hapi-capitalize-modules/-/hapi-capitalize-modules-1.1.6.tgz", + "integrity": "sha1-eZEXFBXhXmqjIx5k3ac8gUZmUxg=", + "dev": true + }, + "hapi-for-you": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hapi-for-you/-/hapi-for-you-1.0.0.tgz", + "integrity": "sha1-02L77o172pwseAHiB+WlzRoLans=", + "dev": true + }, + "hapi-no-var": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hapi-no-var/-/hapi-no-var-1.0.1.tgz", + "integrity": "sha512-kk2xyyTzI+eQ/oA1rO4eVdCpYsrPHVERHa6+mTHD08XXFLaAkkaEs6reMg1VyqGh2o5xPt//DO4EhCacLx/cRA==", + "dev": true + }, + "hapi-scope-start": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/hapi-scope-start/-/hapi-scope-start-2.1.1.tgz", + "integrity": "sha1-dJWnJv5yt7yo3izcwdh82M5qtPI=", + "dev": true + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "i": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", + "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=" + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "interpret": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", + "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isemail": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz", + "integrity": "sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "items": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz", + "integrity": "sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg=", + "dev": true + }, + "joi": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.6.0.tgz", + "integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==", + "dev": true, + "requires": { + "hoek": "4.2.0", + "isemail": "2.2.1", + "items": "2.1.1", + "topo": "2.0.2" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "lab": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lab/-/lab-11.2.2.tgz", + "integrity": "sha1-ASzTGDxcC28cDwIxoOVUNM55OIc=", + "dev": true, + "requires": { + "bossy": "3.0.4", + "diff": "3.4.0", + "eslint": "3.13.1", + "eslint-config-hapi": "10.1.0", + "eslint-plugin-hapi": "4.1.0", + "espree": "3.5.2", + "find-rc": "3.0.1", + "handlebars": "4.0.11", + "hoek": "4.2.0", + "items": "2.1.1", + "json-stable-stringify": "1.0.1", + "json-stringify-safe": "5.0.1", + "mkdirp": "0.5.1", + "seedrandom": "2.4.3", + "source-map-support": "0.4.18" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "eslint": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.13.1.tgz", + "integrity": "sha1-Vk0mRrXv3thd+WmFMy7dkaI7/yU=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.0", + "doctrine": "1.5.0", + "escope": "3.6.0", + "espree": "3.5.2", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "0.12.0", + "is-my-json-valid": "2.16.1", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "shelljs": "0.7.8", + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.4", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.4", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lolex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", + "dev": true + }, + "moment": { + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.2.tgz", + "integrity": "sha512-Rf6jiHPEfxp9+dlzxPTmRHbvoFXsh2L/U8hOupUMpnuecHQmI6cF6lUbJl3QqKPko1u6ujO+FxtcajLVfLpAtA==" + }, + "mongodb-uri": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz", + "integrity": "sha1-D3ca0W9IOuZfQoeWlCjp+8SqYYE=" + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "mysql": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.15.0.tgz", + "integrity": "sha512-C7tjzWtbN5nzkLIV+E8Crnl9bFyc7d3XJcBAvHKEVkjrYjogz3llo22q6s/hw+UcsE4/844pDob9ac+3dVjQSA==", + "dev": true, + "requires": { + "bignumber.js": "4.0.4", + "readable-stream": "2.3.3", + "safe-buffer": "5.1.1", + "sqlstring": "2.3.0" + } + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", + "dev": true + }, + "native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ncp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", + "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=" + }, + "no-arrowception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/no-arrowception/-/no-arrowception-1.0.0.tgz", + "integrity": "sha1-W/PpXrnEG1c4SoBTM9qjtzTuMno=", + "dev": true + }, + "node-fs": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/node-fs/-/node-fs-0.1.7.tgz", + "integrity": "sha1-MjI8zLRsn78PwRgS1FAhzDHTJbs=" + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "parse-database-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/parse-database-url/-/parse-database-url-0.3.0.tgz", + "integrity": "sha1-NpZmMh6SfJreY838Gqr2+zdFPQ0=", + "requires": { + "mongodb-uri": "0.9.7" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + }, + "pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=" + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "prompt": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.0.0.tgz", + "integrity": "sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=", + "requires": { + "colors": "1.1.2", + "pkginfo": "0.4.1", + "read": "1.0.7", + "revalidator": "0.1.8", + "utile": "0.3.0", + "winston": "2.1.1" + } + }, + "proxyquire": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", + "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", + "dev": true, + "requires": { + "fill-keys": "1.0.2", + "module-not-found-error": "1.0.1", + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "rc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz", + "integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=", + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "0.0.7" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.5.0" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "revalidator": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "samsam": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "dev": true + }, + "seedrandom": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz", + "integrity": "sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw=", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.0.4", + "rechoir": "0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": "0.10.3" + } + }, + "sinon-as-promised": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/sinon-as-promised/-/sinon-as-promised-4.0.3.tgz", + "integrity": "sha1-wFRbFoX9gTWIpO1pcBJIftEdFRs=", + "dev": true, + "requires": { + "create-thenable": "1.0.2", + "native-promise-only": "0.8.1" + } + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sqlite3": { + "version": "3.1.13", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-3.1.13.tgz", + "integrity": "sha512-JxXKPJnkZ6NuHRojq+g2WXWBt3M1G9sjZaYiHEWSTGijDM3cwju/0T2XbWqMXFmPqDgw+iB7zKQvnns4bvzXlw==", + "dev": true, + "requires": { + "nan": "2.7.0", + "node-pre-gyp": "0.6.38" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "dev": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node-pre-gyp": { + "version": "0.6.38", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.38.tgz", + "integrity": "sha1-6Sog+DQWQVu0CG9tH7eLPac9ET0=", + "dev": true, + "requires": { + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.4.1", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", + "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } + }, + "sqlstring": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz", + "integrity": "sha1-UluKT9Jtb3GqYegipsr5dtMa0qg=", + "dev": true + }, + "ssh2": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.5.4.tgz", + "integrity": "sha1-G/a2soyW6u8mf01sRqWiUXpZnic=", + "requires": { + "ssh2-streams": "0.1.20" + } + }, + "ssh2-streams": { + "version": "0.1.20", + "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.1.20.tgz", + "integrity": "sha1-URGNFUVV31Rp7h9n4M8efoosDjo=", + "requires": { + "asn1": "0.2.3", + "semver": "5.4.1", + "streamsearch": "0.1.2" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.4.0", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", + "lodash": "4.17.4", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "topo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "tunnel-ssh": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tunnel-ssh/-/tunnel-ssh-4.1.3.tgz", + "integrity": "sha1-kRIWrXnfEAkILFcT/tJkdu0jm60=", + "requires": { + "debug": "2.6.0", + "lodash.defaults": "4.2.0", + "ssh2": "0.5.4" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "unique-concat": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/unique-concat/-/unique-concat-0.2.2.tgz", + "integrity": "sha1-khD5vcqsxeHjkpSQ18AZ35bxhxI=", + "dev": true + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utile": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", + "integrity": "sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo=", + "requires": { + "async": "0.9.2", + "deep-equal": "0.2.2", + "i": "0.3.6", + "mkdirp": "0.5.1", + "ncp": "1.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + } + } + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "when": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/when/-/when-2.0.1.tgz", + "integrity": "sha1-jYcv4V5oQkyRtLck6EjggH2rZkI=" + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "winston": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz", + "integrity": "sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4=", + "requires": { + "async": "1.0.0", + "colors": "1.0.3", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "pkginfo": "0.3.1", + "stack-trace": "0.0.10" + }, + "dependencies": { + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, + "pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" + } + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } +} From 117b0413e02fcde6706705da0ae41e6020ca24b3 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 17:31:56 +0100 Subject: [PATCH 358/412] 0.10.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 72d98811..ed983db7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.10.0-beta.24", + "version": "0.10.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 58c4374d..0c2496ce 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0-beta.12", + "version": "0.10.0", "engines": { "node": ">=0.6.0" }, From 6ad37ca15375ce370bd6f5cf3855c9206b2ce977 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 18:24:20 +0100 Subject: [PATCH 359/412] adjusted tests and updated devDependencies Refers to #518 --- package-lock.json | 493 +++++++++++++++++-------------------- package.json | 11 +- test/config_test.js | 2 +- test/driver/shadow_test.js | 1 - 4 files changed, 230 insertions(+), 277 deletions(-) diff --git a/package-lock.json b/package-lock.json index ed983db7..dc21e5e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -322,12 +322,20 @@ "dev": true }, "code": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/code/-/code-4.1.0.tgz", - "integrity": "sha1-IJrRHQWvigwceq9pTZ+k0sfZW4U=", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/code/-/code-5.1.2.tgz", + "integrity": "sha512-Typ0BuWOKPGNOY9M7hBDY60J9uSPok4Y7hhtTG/3Cpqg0/AhauZSWax0Mb0lZuzm89w1YgVvl8BTrBW/4Sw6sw==", "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "5.0.2" + }, + "dependencies": { + "hoek": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.2.tgz", + "integrity": "sha512-NA10UYP9ufCtY2qYGkZktcQXwVyYK4zK0gkaFSB96xhtlo6V8tKXdQgx8eHolQTRemaW0uLn8BhjhwqrOU+QLQ==", + "dev": true + } } }, "code-point-at": { @@ -446,9 +454,9 @@ "integrity": "sha1-7bPIF7KVAixhmEwYcmdBm7NqLVg=" }, "db-migrate-sqlite3": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/db-migrate-sqlite3/-/db-migrate-sqlite3-0.1.9.tgz", - "integrity": "sha1-X1tUIRMZuvxH+Az+LZpSxPl1ud8=", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/db-migrate-sqlite3/-/db-migrate-sqlite3-0.2.1.tgz", + "integrity": "sha1-ox1nudNtz5lWSymLz9C5hx+2bmc=", "dev": true, "requires": { "bluebird": "3.5.1", @@ -499,7 +507,7 @@ "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1", - "rimraf": "2.5.4" + "rimraf": "2.6.2" } }, "diff": { @@ -1027,12 +1035,12 @@ } }, "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", "dev": true, "requires": { - "samsam": "1.1.2" + "samsam": "1.3.0" } }, "fs.realpath": { @@ -1453,6 +1461,12 @@ "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, + "just-extend": { + "version": "1.1.27", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", + "dev": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -1803,10 +1817,16 @@ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.1.tgz", + "integrity": "sha512-mQuW55GhduF3ppo+ZRUTz1PRjEh1hS5BbqU7d8D0ez2OKxHDod7StPPeAVKisZR5aLkHZjdGWSL42LSONUJsZw==", "dev": true }, "longest": { @@ -1919,6 +1939,27 @@ "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=" }, + "nise": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.2.0.tgz", + "integrity": "sha512-q9jXh3UNsMV28KeqI43ILz5+c3l+RiNW8mhurEwCKckuHQbL+hTJIKKTiUlCPKlgQ/OukFvSnKB/Jk3+sFbkGA==", + "dev": true, + "requires": { + "formatio": "1.2.0", + "just-extend": "1.1.27", + "lolex": "1.6.0", + "path-to-regexp": "1.7.0", + "text-encoding": "0.6.4" + }, + "dependencies": { + "lolex": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", + "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", + "dev": true + } + } + }, "no-arrowception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/no-arrowception/-/no-arrowception-1.0.0.tgz", @@ -2081,6 +2122,23 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", @@ -2353,9 +2411,9 @@ } }, "rimraf": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", - "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { "glob": "7.1.2" @@ -2392,9 +2450,9 @@ "dev": true }, "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, "seedrandom": { @@ -2441,15 +2499,29 @@ "dev": true }, "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.1.2.tgz", + "integrity": "sha512-5uLBZPdCWl59Lpbf45ygKj7Z0LVol+ftBe7RDIXOQV/sF58pcFmbK8raA7bt6eljNuGnvBP+/ZxlicVn0emDjA==", "dev": true, "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": "0.10.3" + "diff": "3.4.0", + "formatio": "1.2.0", + "lodash.get": "4.4.2", + "lolex": "2.3.1", + "nise": "1.2.0", + "supports-color": "4.5.0", + "type-detect": "4.0.5" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } } }, "sinon-as-promised": { @@ -2536,14 +2608,12 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "dev": true }, "ajv": { "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "bundled": true, "dev": true, "requires": { "co": "4.6.0", @@ -2552,20 +2622,17 @@ }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "dev": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "dev": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "bundled": true, "dev": true, "requires": { "delegates": "1.0.0", @@ -2574,44 +2641,37 @@ }, "asn1": { "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "bundled": true, "dev": true }, "assert-plus": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "bundled": true, "dev": true }, "asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "bundled": true, "dev": true }, "aws-sign2": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "bundled": true, "dev": true }, "aws4": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "bundled": true, "dev": true }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "bundled": true, "dev": true }, "bcrypt-pbkdf": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2620,8 +2680,7 @@ }, "block-stream": { "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "bundled": true, "dev": true, "requires": { "inherits": "2.0.3" @@ -2629,8 +2688,7 @@ }, "boom": { "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "bundled": true, "dev": true, "requires": { "hoek": "2.16.3" @@ -2638,8 +2696,7 @@ }, "brace-expansion": { "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "bundled": true, "dev": true, "requires": { "balanced-match": "1.0.0", @@ -2648,26 +2705,22 @@ }, "caseless": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "bundled": true, "dev": true }, "co": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "bundled": true, "dev": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "dev": true }, "combined-stream": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "bundled": true, "dev": true, "requires": { "delayed-stream": "1.0.0" @@ -2675,26 +2728,22 @@ }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "dev": true }, "cryptiles": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "bundled": true, "dev": true, "requires": { "boom": "2.10.1" @@ -2702,8 +2751,7 @@ }, "dashdash": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "bundled": true, "dev": true, "requires": { "assert-plus": "1.0.0" @@ -2711,16 +2759,14 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "bundled": true, "dev": true } } }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "bundled": true, "dev": true, "requires": { "ms": "2.0.0" @@ -2728,26 +2774,22 @@ }, "deep-extend": { "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "bundled": true, "dev": true }, "delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "bundled": true, "dev": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true }, "ecc-jsbn": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2756,26 +2798,22 @@ }, "extend": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "bundled": true, "dev": true }, "extsprintf": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "bundled": true, "dev": true }, "forever-agent": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "bundled": true, "dev": true }, "form-data": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "bundled": true, "dev": true, "requires": { "asynckit": "0.4.0", @@ -2785,14 +2823,12 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "dev": true }, "fstream": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "bundled": true, "dev": true, "requires": { "graceful-fs": "4.1.11", @@ -2803,8 +2839,7 @@ }, "fstream-ignore": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "bundled": true, "dev": true, "requires": { "fstream": "1.0.11", @@ -2814,8 +2849,7 @@ }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, "requires": { "aproba": "1.2.0", @@ -2830,8 +2864,7 @@ }, "getpass": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "bundled": true, "dev": true, "requires": { "assert-plus": "1.0.0" @@ -2839,16 +2872,14 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "bundled": true, "dev": true } } }, "glob": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "bundled": true, "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -2861,20 +2892,17 @@ }, "graceful-fs": { "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "bundled": true, "dev": true }, "har-schema": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "bundled": true, "dev": true }, "har-validator": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "bundled": true, "dev": true, "requires": { "ajv": "4.11.8", @@ -2883,14 +2911,12 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true }, "hawk": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "bundled": true, "dev": true, "requires": { "boom": "2.10.1", @@ -2901,14 +2927,12 @@ }, "hoek": { "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "bundled": true, "dev": true }, "http-signature": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "bundled": true, "dev": true, "requires": { "assert-plus": "0.2.0", @@ -2918,8 +2942,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, "requires": { "once": "1.4.0", @@ -2928,20 +2951,17 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, "dev": true }, "ini": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "bundled": true, "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "dev": true, "requires": { "number-is-nan": "1.0.1" @@ -2949,39 +2969,33 @@ }, "is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "bundled": true, "dev": true }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "dev": true }, "isstream": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "bundled": true, "dev": true }, "jsbn": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "bundled": true, "dev": true, "optional": true }, "json-schema": { "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "bundled": true, "dev": true }, "json-stable-stringify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "bundled": true, "dev": true, "requires": { "jsonify": "0.0.0" @@ -2989,20 +3003,17 @@ }, "json-stringify-safe": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "bundled": true, "dev": true }, "jsonify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "bundled": true, "dev": true }, "jsprim": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "bundled": true, "dev": true, "requires": { "assert-plus": "1.0.0", @@ -3013,22 +3024,19 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "bundled": true, "dev": true } } }, "mime-db": { "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "bundled": true, "dev": true }, "mime-types": { "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "bundled": true, "dev": true, "requires": { "mime-db": "1.30.0" @@ -3036,8 +3044,7 @@ }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -3045,14 +3052,12 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "bundled": true, "dev": true }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "dev": true, "requires": { "minimist": "0.0.8" @@ -3060,14 +3065,12 @@ }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "bundled": true, "dev": true }, "node-pre-gyp": { "version": "0.6.38", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.38.tgz", - "integrity": "sha1-6Sog+DQWQVu0CG9tH7eLPac9ET0=", + "bundled": true, "dev": true, "requires": { "hawk": "3.1.3", @@ -3084,8 +3087,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "dev": true, "requires": { "abbrev": "1.1.1", @@ -3094,8 +3096,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "dev": true, "requires": { "are-we-there-yet": "1.1.4", @@ -3106,26 +3107,22 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "bundled": true, "dev": true }, "oauth-sign": { "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "bundled": true, "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "dev": true, "requires": { "wrappy": "1.0.2" @@ -3133,20 +3130,17 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "bundled": true, "dev": true }, "osenv": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "bundled": true, "dev": true, "requires": { "os-homedir": "1.0.2", @@ -3155,38 +3149,32 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "bundled": true, "dev": true }, "performance-now": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "bundled": true, "dev": true }, "process-nextick-args": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "bundled": true, "dev": true }, "punycode": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "bundled": true, "dev": true }, "qs": { "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "bundled": true, "dev": true }, "rc": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "bundled": true, "dev": true, "requires": { "deep-extend": "0.4.2", @@ -3197,16 +3185,14 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "dev": true } } }, "readable-stream": { "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "bundled": true, "dev": true, "requires": { "core-util-is": "1.0.2", @@ -3220,8 +3206,7 @@ }, "request": { "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "bundled": true, "dev": true, "requires": { "aws-sign2": "0.6.0", @@ -3250,8 +3235,7 @@ }, "rimraf": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "bundled": true, "dev": true, "requires": { "glob": "7.1.2" @@ -3259,32 +3243,27 @@ }, "safe-buffer": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "bundled": true, "dev": true }, "semver": { "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "bundled": true, "dev": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true }, "sntp": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "bundled": true, "dev": true, "requires": { "hoek": "2.16.3" @@ -3292,8 +3271,7 @@ }, "sshpk": { "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "bundled": true, "dev": true, "requires": { "asn1": "0.2.3", @@ -3308,16 +3286,14 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "bundled": true, "dev": true } } }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "dev": true, "requires": { "code-point-at": "1.1.0", @@ -3327,8 +3303,7 @@ }, "string_decoder": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "bundled": true, "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -3336,14 +3311,12 @@ }, "stringstream": { "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "bundled": true, "dev": true }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "dev": true, "requires": { "ansi-regex": "2.1.1" @@ -3351,14 +3324,12 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "bundled": true, "dev": true }, "tar": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "bundled": true, "dev": true, "requires": { "block-stream": "0.0.9", @@ -3368,8 +3339,7 @@ }, "tar-pack": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", - "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", + "bundled": true, "dev": true, "requires": { "debug": "2.6.9", @@ -3384,8 +3354,7 @@ }, "tough-cookie": { "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "bundled": true, "dev": true, "requires": { "punycode": "1.4.1" @@ -3393,8 +3362,7 @@ }, "tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "bundled": true, "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -3402,33 +3370,28 @@ }, "tweetnacl": { "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "bundled": true, "dev": true, "optional": true }, "uid-number": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "bundled": true, "dev": true }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "dev": true }, "uuid": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "bundled": true, "dev": true }, "verror": { "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "bundled": true, "dev": true, "requires": { "assert-plus": "1.0.0", @@ -3438,16 +3401,14 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "bundled": true, "dev": true } } }, "wide-align": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "bundled": true, "dev": true, "requires": { "string-width": "1.0.2" @@ -3455,8 +3416,7 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, "dev": true } } @@ -3562,6 +3522,12 @@ "string-width": "2.1.1" } }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "dev": true + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3617,6 +3583,12 @@ "prelude-ls": "1.1.2" } }, + "type-detect": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz", + "integrity": "sha512-N9IvkQslUGYGC24RkJk1ba99foK6TkwC2FHAEBlQFBP0RxQZS8ZpJuAZcwiY/w9ZJHFQb1aOXBI60OdxhTrwEQ==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -3666,23 +3638,6 @@ "os-homedir": "1.0.2" } }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 0c2496ce..ea4d4d2f 100644 --- a/package.json +++ b/package.json @@ -63,21 +63,20 @@ "tunnel-ssh": "^4.0.0" }, "devDependencies": { - "code": "^4.0.0", + "code": "^4.1.0", "db-migrate-base": "^1.2.5", "db-migrate-mysql": "^1.1.7", - "db-migrate-sqlite3": "^0.1.9", + "db-migrate-sqlite3": "^0.2.1", "eslint": "^4.10.0", "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.8.0", "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.6.0", "eslint-plugin-standard": "^3.0.1", - "lab": "^11.1.0", + "lab": "^14.3.1", "proxyquire": "^1.4.0", - "rimraf": "~2.5.0", - "sinon": "^1.17.3", - "sinon-as-promised": "^4.0.2" + "rimraf": "^2.6.2", + "sinon": "^4.1.2" }, "scripts": { "test": "make test-cov" diff --git a/test/config_test.js b/test/config_test.js index 2d78d485..bd20299c 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -137,7 +137,7 @@ lab.experiment('config', function () { Code.expect(current.settings.driver).to.equal('postgres'); Code.expect(current.settings.user).to.equal('uname'); Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host, ').to.equal(rver.com'); + Code.expect(current.settings.host ).to.equal('server.com'); Code.expect(current.settings.database).to.equal('dbname'); done(); } diff --git a/test/driver/shadow_test.js b/test/driver/shadow_test.js index 95e1e304..79aa7196 100644 --- a/test/driver/shadow_test.js +++ b/test/driver/shadow_test.js @@ -4,7 +4,6 @@ var lab = exports.lab = Lab.script(); var sinon = require('sinon'); var Bluebird = require('bluebird'); var shadow = require('../../lib/driver/shadow.js'); -require('sinon-as-promised')(Bluebird); lab.experiment('shadow', function () { lab.test('shadow function and original function get called in serial', From e44f641342226959f02de9c248261c720caf3572 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 18:28:20 +0100 Subject: [PATCH 360/412] readd pkg-lock --- package-lock.json | 580 +++++----------------------------------------- 1 file changed, 57 insertions(+), 523 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc21e5e6..0bb7268a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -322,28 +322,14 @@ "dev": true }, "code": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/code/-/code-5.1.2.tgz", - "integrity": "sha512-Typ0BuWOKPGNOY9M7hBDY60J9uSPok4Y7hhtTG/3Cpqg0/AhauZSWax0Mb0lZuzm89w1YgVvl8BTrBW/4Sw6sw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/code/-/code-4.1.0.tgz", + "integrity": "sha1-IJrRHQWvigwceq9pTZ+k0sfZW4U=", "dev": true, "requires": { - "hoek": "5.0.2" - }, - "dependencies": { - "hoek": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.2.tgz", - "integrity": "sha512-NA10UYP9ufCtY2qYGkZktcQXwVyYK4zK0gkaFSB96xhtlo6V8tKXdQgx8eHolQTRemaW0uLn8BhjhwqrOU+QLQ==", - "dev": true - } + "hoek": "4.2.0" } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", @@ -392,16 +378,6 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "create-thenable": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/create-thenable/-/create-thenable-1.0.2.tgz", - "integrity": "sha1-4gMXIMzJV12M+jH1wUbnYqgMBTQ=", - "dev": true, - "requires": { - "object.omit": "2.0.1", - "unique-concat": "0.2.2" - } - }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -418,15 +394,6 @@ "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "0.10.35" - } - }, "db-migrate-base": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/db-migrate-base/-/db-migrate-base-1.5.3.tgz", @@ -540,94 +507,12 @@ "is-arrayish": "0.2.1" } }, - "es5-ext": { - "version": "0.10.35", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.35.tgz", - "integrity": "sha1-GO6FjOajxFx9eekcFfzKnsVoSU8=", - "dev": true, - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-symbol": "3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - } - }, "eslint": { "version": "4.11.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.11.0.tgz", @@ -903,22 +788,6 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35" - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, "external-editor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", @@ -1019,21 +888,6 @@ "write": "0.2.1" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, "formatio": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", @@ -1060,21 +914,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -1263,12 +1102,6 @@ "through": "2.3.8" } }, - "interpret": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", - "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -1290,30 +1123,12 @@ "builtin-modules": "1.1.1" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", @@ -1350,12 +1165,6 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, "is-resolvable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", @@ -1455,12 +1264,6 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, "just-extend": { "version": "1.1.27", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", @@ -1477,14 +1280,15 @@ } }, "lab": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/lab/-/lab-11.2.2.tgz", - "integrity": "sha1-ASzTGDxcC28cDwIxoOVUNM55OIc=", + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/lab/-/lab-14.3.1.tgz", + "integrity": "sha512-sN14QhqiRuBGnfrOGo1B9UqiJJarEcZJEna/hGAT5g4uuxcowns4zc/JUBoMgT44jZgWBxbpjKPizBOGt5mYRw==", "dev": true, "requires": { "bossy": "3.0.4", - "diff": "3.4.0", - "eslint": "3.13.1", + "code": "4.1.0", + "diff": "3.3.1", + "eslint": "4.5.0", "eslint-config-hapi": "10.1.0", "eslint-plugin-hapi": "4.1.0", "espree": "3.5.2", @@ -1496,259 +1300,96 @@ "json-stringify-safe": "5.0.1", "mkdirp": "0.5.1", "seedrandom": "2.4.3", - "source-map-support": "0.4.18" + "source-map": "0.5.7", + "source-map-support": "0.4.18", + "supports-color": "4.4.0" }, "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "ms": "2.0.0" } }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "dev": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "1.0.1" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" - } - }, "eslint": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.13.1.tgz", - "integrity": "sha1-Vk0mRrXv3thd+WmFMy7dkaI7/yU=", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.5.0.tgz", + "integrity": "sha1-u3XTuL3pf7XhPvzVOXRGd/6wGcM=", "dev": true, "requires": { + "ajv": "5.4.0", "babel-code-frame": "6.26.0", - "chalk": "1.1.3", + "chalk": "2.3.0", "concat-stream": "1.6.0", - "debug": "2.6.0", - "doctrine": "1.5.0", - "escope": "3.6.0", + "cross-spawn": "5.1.0", + "debug": "2.6.9", + "doctrine": "2.0.0", + "eslint-scope": "3.7.1", "espree": "3.5.2", + "esquery": "1.0.0", "estraverse": "4.2.0", "esutils": "2.0.2", "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", "glob": "7.1.2", "globals": "9.18.0", "ignore": "3.3.7", "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.16.1", + "inquirer": "3.3.0", "is-resolvable": "1.0.0", "js-yaml": "3.10.0", "json-stable-stringify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.4", + "minimatch": "3.0.4", "mkdirp": "0.5.1", "natural-compare": "1.4.0", "optionator": "0.8.2", "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", + "pluralize": "4.0.0", + "progress": "2.0.0", "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", + "semver": "5.4.1", + "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "table": "4.0.2", + "text-table": "0.2.0" } }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.2.0", - "figures": "1.7.0", - "lodash": "4.17.4", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", + "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", "dev": true }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.4", - "slice-ansi": "0.0.4", - "string-width": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } + "has-flag": "2.0.0" } } } @@ -1922,12 +1563,6 @@ "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", "dev": true }, - "native-promise-only": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -1983,28 +1618,12 @@ "validate-npm-package-license": "3.0.1" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2053,12 +1672,6 @@ } } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -2318,43 +1931,6 @@ "util-deprecate": "1.0.2" } }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "mute-stream": "0.0.5" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - } - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.5.0" - } - }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -2481,17 +2057,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, - "requires": { - "glob": "7.1.2", - "interpret": "1.0.4", - "rechoir": "0.6.2" - } - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -2524,16 +2089,6 @@ } } }, - "sinon-as-promised": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/sinon-as-promised/-/sinon-as-promised-4.0.3.tgz", - "integrity": "sha1-wFRbFoX9gTWIpO1pcBJIftEdFRs=", - "dev": true, - "requires": { - "create-thenable": "1.0.2", - "native-promise-only": "0.8.1" - } - }, "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", @@ -3623,21 +3178,6 @@ "dev": true, "optional": true }, - "unique-concat": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/unique-concat/-/unique-concat-0.2.2.tgz", - "integrity": "sha1-khD5vcqsxeHjkpSQ18AZ35bxhxI=", - "dev": true - }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3748,12 +3288,6 @@ "mkdirp": "0.5.1" } }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", From 486fbe23afcb1cbd513e1cfd096b5398189b0a0f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 18:39:23 +0100 Subject: [PATCH 361/412] change tested versions --- .travis.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b9b2d82..ca32bff0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: node_js node_js: - - 4.0 - - 4.2 - - 5 + - 4 - 6 + - 8 + - latest notifications: email: @@ -21,6 +21,8 @@ os: - linux matrix: + allow_failures: + - node_js: latest fast_finish: true sudo: false @@ -41,4 +43,4 @@ before_install: - export CXX=g++-4.8; export CC=gcc-4.8; before_script: - - cp test/db.config.ci test/db.config.json + - cp test/db.config.ci test/db.config.json From 85243af1ea4791a04037c9bf9770edc36b985f51 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 18:43:49 +0100 Subject: [PATCH 362/412] rewrite latest to node --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ca32bff0..f88edef4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ node_js: - 4 - 6 - 8 - - latest + - node notifications: email: @@ -22,7 +22,7 @@ os: matrix: allow_failures: - - node_js: latest + - node_js: node fast_finish: true sudo: false From 759c27081a7a7f4c9cd68793bb1b7d4400cedf5f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 18:53:17 +0100 Subject: [PATCH 363/412] add linting and fix cs on config test --- package.json | 1 + test/config_test.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ea4d4d2f..096fe5ca 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "sinon": "^4.1.2" }, "scripts": { + "pretest": "eslint *.js lib/*.js test/*.js bin/*", "test": "make test-cov" } } diff --git a/test/config_test.js b/test/config_test.js index bd20299c..8574e540 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -137,7 +137,7 @@ lab.experiment('config', function () { Code.expect(current.settings.driver).to.equal('postgres'); Code.expect(current.settings.user).to.equal('uname'); Code.expect(current.settings.password).to.equal('pw'); - Code.expect(current.settings.host ).to.equal('server.com'); + Code.expect(current.settings.host).to.equal('server.com'); Code.expect(current.settings.database).to.equal('dbname'); done(); } From df3ffa8b23a919dcd50416278d93d9136ca56f9f Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 22:34:48 +0100 Subject: [PATCH 364/412] add commitlint --- commitlint.config.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 commitlint.config.js diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..69b18d9f --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +module.exports = { extends: ['@commitlint/config-angular'] }; From 72fce59be67e9259aa5d5bcf4ac5f5a09ad8c817 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 22 Nov 2017 23:50:25 +0100 Subject: [PATCH 365/412] remove parallel: true as it was deprecated --- test/config_test.js | 34 ++-- test/driver/base_test.js | 106 +++++------ test/integration/api_test.js | 16 +- test/integration/create_test.js | 302 +++++++++++++++++--------------- test/migration_test.js | 78 ++++----- test/util_test.js | 59 ++++--- 6 files changed, 302 insertions(+), 293 deletions(-) diff --git a/test/config_test.js b/test/config_test.js index 8574e540..500b3837 100644 --- a/test/config_test.js +++ b/test/config_test.js @@ -8,13 +8,13 @@ var _configLoad = config.load; var _configLoadUrl = config.loadUrl; lab.experiment('config', function () { - lab.experiment('loading from a file', { parallel: true }, function () { + lab.experiment('loading from a file', function () { var configPath = path.join(__dirname, 'database.json'); var _config = config.load(configPath, 'dev'); lab.test( 'should export all environment settings', - { parallel: true }, + function (done) { Code.expect(_config.dev).to.exists(); Code.expect(_config.test).to.exists(); @@ -26,7 +26,7 @@ lab.experiment('config', function () { lab.test( 'should export a getCurrent function with all current ' + 'environment settings', - { parallel: true }, + function (done) { var current; Code.expect(_config.getCurrent).to.exists(); @@ -41,13 +41,11 @@ lab.experiment('config', function () { lab.experiment( 'loading from a broken config file', - { parallel: true }, + function () { var configPath = path.join(__dirname, 'database_with_syntax_error.json'); - lab.test('should throw a syntax error', { parallel: true }, function ( - done - ) { + lab.test('should throw a syntax error', function (done) { Code.expect( config.load.bind(this, configPath, 'dev'), 'Expected broken file to produce syntax error' @@ -59,14 +57,14 @@ lab.experiment('config', function () { lab.experiment( 'loading from a file with default env option', - { parallel: true }, + function () { var configPath = path.join(__dirname, 'database_with_default_env.json'); var _config = config.load(configPath); lab.test( 'should load a value from the default env', - { parallel: true }, + function (done) { var current = _config.getCurrent(); Code.expect(current.env).to.equal('local'); @@ -80,7 +78,7 @@ lab.experiment('config', function () { lab.experiment( 'loading from a file with default env option in ENV variable', - { parallel: true }, + function () { process.env.NODE_ENV = 'local'; var configPath = path.join( @@ -91,7 +89,7 @@ lab.experiment('config', function () { lab.test( 'should load a value from the env set in NODE_ENV', - { parallel: true }, + function (done) { var current = _config.getCurrent(); Code.expect(current.settings.driver).to.equal('sqlite3'); @@ -104,7 +102,7 @@ lab.experiment('config', function () { lab.experiment( 'loading from a file with ENV vars', - { parallel: true }, + function () { process.env.DB_MIGRATE_TEST_VAR = 'username_from_env'; var configPath = path.join(__dirname, 'database_with_env.json'); @@ -112,7 +110,7 @@ lab.experiment('config', function () { lab.test( 'should load a value from the environments', - { parallel: true }, + function (done) { Code.expect(_config.prod.username).to.equal('username_from_env'); done(); @@ -123,7 +121,7 @@ lab.experiment('config', function () { lab.experiment( 'loading from a file with ENV URL', - { parallel: true }, + function () { process.env.DB_MIGRATE_TEST_VAR = 'postgres://uname:pw@server.com/dbname'; var configPath = path.join(__dirname, 'database_with_env_url.json'); @@ -131,7 +129,7 @@ lab.experiment('config', function () { lab.test( 'should load a value from the environments', - { parallel: true }, + function (done) { var current = _config.getCurrent(); Code.expect(current.settings.driver).to.equal('postgres'); @@ -145,13 +143,13 @@ lab.experiment('config', function () { } ); - lab.experiment('loading from an URL', { parallel: true }, function () { + lab.experiment('loading from an URL', function () { var databaseUrl = 'postgres://uname:pw@server.com/dbname'; var _config = config.loadUrl(databaseUrl, 'dev'); lab.test( 'should export the settings as the current environment', - { parallel: true }, + function (done) { Code.expect(_config.dev).to.exists(); done(); @@ -161,7 +159,7 @@ lab.experiment('config', function () { lab.test( 'should export a getCurrent function with all current ' + 'environment settings', - { parallel: true }, + function (done) { var current; Code.expect(_config.getCurrent).to.exists(); diff --git a/test/driver/base_test.js b/test/driver/base_test.js index 778038c7..5c6462f1 100644 --- a/test/driver/base_test.js +++ b/test/driver/base_test.js @@ -1,6 +1,6 @@ var Code = require('code'); var Lab = require('lab'); -var lab = exports.lab = Lab.script(); +var lab = (exports.lab = Lab.script()); var Base = require('db-migrate-base'); var internals = { @@ -11,80 +11,80 @@ var internals = { } }; -lab.experiment('base', { parallel: true }, function () { - lab.experiment('default implementation', { parallel: true }, function () { +lab.experiment('base', function () { + lab.experiment('default implementation', function () { var base = new Base(internals); - lab.test('inherits from EventEmitter', { parallel: true }, function (done) { + lab.test('inherits from EventEmitter', function (done) { Code.expect(base.on).to.be.not.null(); Code.expect(base.emit).to.be.not.null(); done(); }); - lab.test('throws errors for all API methods', { parallel: true }, - function (done) { - Code.expect(function () { - base.createTable(); - }).to.throw(Error); + lab.test('throws errors for all API methods', function (done) { + Code.expect(function () { + base.createTable(); + }).to.throw(Error); - Code.expect(function () { - base.dropTable(); - }).to.throw(Error); + Code.expect(function () { + base.dropTable(); + }).to.throw(Error); - Code.expect(function () { - base.addColumn(); - }).to.throw(Error); + Code.expect(function () { + base.addColumn(); + }).to.throw(Error); - Code.expect(function () { - base.removeColumn(); - }).to.throw(Error); + Code.expect(function () { + base.removeColumn(); + }).to.throw(Error); - Code.expect(function () { - base.renameColumn(); - }).to.throw(Error); + Code.expect(function () { + base.renameColumn(); + }).to.throw(Error); - Code.expect(function () { - base.changeColumn(); - }).to.throw(Error); + Code.expect(function () { + base.changeColumn(); + }).to.throw(Error); - Code.expect(function () { - base.addIndex(); - }).to.throw(Error); + Code.expect(function () { + base.addIndex(); + }).to.throw(Error); - Code.expect(function () { - base.insert(); - }).to.throw(Error); + Code.expect(function () { + base.insert(); + }).to.throw(Error); - Code.expect(function () { - base.removeIndex(); - }).to.throw(Error); + Code.expect(function () { + base.removeIndex(); + }).to.throw(Error); - Code.expect(function () { - base.addAssociation(); - }).to.throw(Error); + Code.expect(function () { + base.addAssociation(); + }).to.throw(Error); - Code.expect(function () { - base.removeAssociation(); - }).to.throw(Error); + Code.expect(function () { + base.removeAssociation(); + }).to.throw(Error); - Code.expect(function () { - base.addForeignKey(); - }).to.throw(Error); + Code.expect(function () { + base.addForeignKey(); + }).to.throw(Error); - Code.expect(function () { - base.removeForeignKey(); - }).to.throw(Error); + Code.expect(function () { + base.removeForeignKey(); + }).to.throw(Error); - Code.expect(function () { - base.runSql(); - }).to.throw(Error); + Code.expect(function () { + base.runSql(); + }).to.throw(Error); - done(); - }); + done(); + }); - lab.test('escapes single quotes', { parallel: true }, function (done) { - Code.expect('Bill\'\'s Mother\'\'s House') - .to.equal(base.escape('Bill\'s Mother\'s House')); + lab.test('escapes single quotes', function (done) { + Code.expect("Bill''s Mother''s House").to.equal( + base.escape("Bill's Mother's House") + ); done(); }); }); diff --git a/test/integration/api_test.js b/test/integration/api_test.js index a83fe843..b5dabaff 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -5,10 +5,10 @@ var sinon = require('sinon'); var proxyquire = require('proxyquire').noPreserveCache(); var Promise = require('bluebird'); -lab.experiment('api', { parallel: true }, function () { +lab.experiment('api', function () { lab.test( 'force process exit after migrations have been run', - { parallel: true }, + function (done, onCleanup) { var processExit = process.exit; var argv = process.argv; @@ -83,9 +83,7 @@ lab.experiment('api', { parallel: true }, function () { } ); - lab.test('should load config from parameter', { parallel: true }, function ( - done - ) { + lab.test('should load config from parameter', function (done) { var options = { env: 'dev', cwd: process.cwd() + '/test/integration', @@ -114,7 +112,7 @@ lab.experiment('api', { parallel: true }, function () { lab.test( 'should handle all up parameter variations properly', - { parallel: true }, + function () { return Promise.resolve([ [], // promise @@ -135,7 +133,7 @@ lab.experiment('api', { parallel: true }, function () { lab.test( 'should handle all down parameter variations properly', - { parallel: true }, + function () { return Promise.resolve([ [], // promise @@ -152,7 +150,7 @@ lab.experiment('api', { parallel: true }, function () { lab.test( 'should handle all reset parameter variations properly', - { parallel: true }, + function () { return Promise.resolve([ [], // promise @@ -167,7 +165,7 @@ lab.experiment('api', { parallel: true }, function () { lab.test( 'should handle all sync parameter variations properly', - { parallel: true }, + function () { return Promise.resolve([ [], diff --git a/test/integration/create_test.js b/test/integration/create_test.js index 46f51431..dd18106c 100644 --- a/test/integration/create_test.js +++ b/test/integration/create_test.js @@ -1,6 +1,6 @@ var Code = require('code'); var Lab = require('lab'); -var lab = exports.lab = Lab.script(); +var lab = (exports.lab = Lab.script()); var fs = require('fs'); var path = require('path'); var cp = require('child_process'); @@ -27,91 +27,92 @@ lab.experiment('create', function () { lab.before(function (done) { wipeMigrations(function (err) { Code.expect(err).to.be.null(); - dbMigrate('create', 'first migration').on('exit', - function (code) { - exitCode = code; - done(); - }); + dbMigrate('create', 'first migration').on('exit', function (code) { + exitCode = code; + done(); + }); }); }); - lab.test('does not cause an error', { parallel: true }, - function (done) { - Code.expect(exitCode).to.equal(0); - done(); - }); + lab.test('does not cause an error', function (done) { + Code.expect(exitCode).to.equal(0); + done(); + }); - lab.test('will create a new migration directory', { parallel: true }, - function (done) { - var stats = fs.statSync(path.join(__dirname, 'migrations')); - Code.expect(stats.isDirectory()).to.be.true(); - done(); - }); + lab.test('will create a new migration directory', function (done) { + var stats = fs.statSync(path.join(__dirname, 'migrations')); + Code.expect(stats.isDirectory()).to.be.true(); + done(); + }); - lab.test('will create a new migration', { parallel: true }, - function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); - Code.expect(files.length).to.equal(1); - var file = files[0]; - Code.expect(file).to.match(/first-migration\.js$/); - done(); - }); + lab.test('will create a new migration', function (done) { + var files = fs.readdirSync(path.join(__dirname, 'migrations')); + Code.expect(files.length).to.equal(1); + var file = files[0]; + Code.expect(file).to.match(/first-migration\.js$/); + done(); + }); }); - lab.experiment('with sql-file option set to true from config file', + lab.experiment( + 'with sql-file option set to true from config file', function () { var exitCode; lab.before(function (done) { - var configOption = path.join('--config=', __dirname, - 'database_with_sql_file.json'); + var configOption = path.join( + '--config=', + __dirname, + 'database_with_sql_file.json' + ); wipeMigrations(function (err) { Code.expect(err).to.not.exist(); - dbMigrate('create', 'second migration', configOption).on('exit', + dbMigrate('create', 'second migration', configOption).on( + 'exit', function (code) { exitCode = code; done(); - }); + } + ); }); }); - lab.test('does not cause an error', { parallel: true }, function (done) { + lab.test('does not cause an error', function (done) { Code.expect(exitCode).to.equal(0); done(); }); - lab.test('will create a new migration', { parallel: true }, - function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + lab.test('will create a new migration', function (done) { + var 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 (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$/); } + } - done(); - }); + done(); + }); - lab.test('will create a new migration/sqls directory', { parallel: true }, - function (done) { - var stats = fs.statSync(path.join(__dirname, 'migrations/sqls')); - Code.expect(stats.isDirectory()).to.be.true(); - done(); - }); + lab.test('will create a new migration/sqls directory', function (done) { + var 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', { parallel: true }, - function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations/sqls')); - Code.expect(files.length).to.equal(2); - var file = files[1]; - Code.expect(file).to.match(/second-migration-up\.sql$/); - done(); - }); - }); + lab.test('will create a new migration sql up file', function (done) { + var files = fs.readdirSync(path.join(__dirname, 'migrations/sqls')); + Code.expect(files.length).to.equal(2); + var file = files[1]; + Code.expect(file).to.match(/second-migration-up\.sql$/); + done(); + }); + } + ); - lab.experiment('with sql-file option set to true as a command parameter', + lab.experiment( + 'with sql-file option set to true as a command parameter', function () { var exitCode; @@ -119,88 +120,95 @@ lab.experiment('create', function () { var configOption = path.join('--sql-file'); wipeMigrations(function (err) { Code.expect(err).to.not.exist(); - dbMigrate('create', 'third migration', configOption).on('exit', + dbMigrate('create', 'third migration', configOption).on( + 'exit', function (code) { exitCode = code; done(); - }); + } + ); }); }); - lab.test('does not cause an error', { parallel: true }, - function (done) { - Code.expect(exitCode).to.equal(0); - done(); - }); + lab.test('does not cause an error', function (done) { + Code.expect(exitCode).to.equal(0); + done(); + }); - lab.test('will create a new migration', { parallel: true }, - function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + lab.test('will create a new migration', function (done) { + var 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$/); - } - done(); - }); + 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$/); } + } + done(); + }); - lab.test('will create a new migration/sqls directory', { parallel: true }, - function (done) { - var stats = fs.statSync(path.join(__dirname, 'migrations/sqls')); - Code.expect(stats.isDirectory()).to.be.true(); - done(); - }); + lab.test('will create a new migration/sqls directory', function (done) { + var 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', { parallel: true }, - function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations/sqls')); - Code.expect(files.length).to.equal(2); - var file = files[1]; - Code.expect(file).to.match(/third-migration-up\.sql$/); - done(); - }); - }); + lab.test('will create a new migration sql up file', function (done) { + var files = fs.readdirSync(path.join(__dirname, 'migrations/sqls')); + Code.expect(files.length).to.equal(2); + var file = files[1]; + Code.expect(file).to.match(/third-migration-up\.sql$/); + done(); + }); + } + ); - lab.experiment('with coffee-file option set to true from config file', + lab.experiment( + 'with coffee-file option set to true from config file', function () { var exitCode; lab.before(function (done) { - var configOption = path.join('--config=', __dirname, - 'database_with_coffee_file.json'); + var configOption = path.join( + '--config=', + __dirname, + 'database_with_coffee_file.json' + ); wipeMigrations(function (err) { Code.expect(err).to.not.exist(); - dbMigrate('create', 'fourth migration', configOption).on('exit', + dbMigrate('create', 'fourth migration', configOption).on( + 'exit', function (code) { exitCode = code; done(); - }); + } + ); }); }); - lab.test('does not cause an error', { parallel: true }, - function (done) { - Code.expect(exitCode).to.equal(0); - done(); - }); + lab.test('does not cause an error', function (done) { + Code.expect(exitCode).to.equal(0); + done(); + }); - lab.test('will create a new coffeescript migration', { parallel: true }, - function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + lab.test('will create a new coffeescript migration', function (done) { + var 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(/fourth-migration\.coffee$/); } + 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(/fourth-migration\.coffee$/); } + } - done(); - }); - }); + done(); + }); + } + ); - lab.experiment('with coffee-file option set to true as a command parameter', + lab.experiment( + 'with coffee-file option set to true as a command parameter', function () { var exitCode; @@ -208,34 +216,38 @@ lab.experiment('create', function () { var configOption = path.join('--coffee-file'); wipeMigrations(function (err) { Code.expect(err).to.not.exist(); - dbMigrate('create', 'fifth migration', configOption).on('exit', + dbMigrate('create', 'fifth migration', configOption).on( + 'exit', function (code) { exitCode = code; done(); - }); + } + ); }); }); - lab.test('does not cause an error', { parallel: true }, - function (done) { - Code.expect(exitCode).to.equal(0); - done(); - }); + lab.test('does not cause an error', function (done) { + Code.expect(exitCode).to.equal(0); + done(); + }); - lab.test('will create a new coffeescript migration', { parallel: true }, - function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + lab.test('will create a new coffeescript migration', function (done) { + var 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(/fifth-migration\.coffee$/); } + 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(/fifth-migration\.coffee$/); } - done(); - }); - }); + } + done(); + }); + } + ); - lab.experiment('with sql-file and a bad migration, causes an exit', + lab.experiment( + 'with sql-file and a bad migration, causes an exit', function () { var exitCode; @@ -243,13 +255,16 @@ lab.experiment('create', function () { var configOption = path.join('--sql-file'); wipeMigrations(function (err) { Code.expect(err).to.not.exist(); - dbMigrate('create', 'sixth migration', configOption).on('exit', + dbMigrate('create', 'sixth migration', configOption).on( + 'exit', function () { var 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)); + var stats = fs.statSync( + path.join(__dirname, 'migrations', file) + ); if (stats.isFile() && file.match(/sixth-migration\.js$/)) { fs.writeFileSync( @@ -262,30 +277,31 @@ lab.experiment('create', function () { }); } } - }); + } + ); }); }); - lab.test('does cause an error', { parallel: true }, function (done) { + lab.test('does cause an error', function (done) { Code.expect(exitCode).to.equal(1); done(); }); - lab.test('did create the new migration', { parallel: true }, - function (done) { - var files = fs.readdirSync(path.join(__dirname, 'migrations')); + lab.test('did create the new migration', function (done) { + var 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 (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$/); } + } - done(); - }); + done(); + }); lab.after(function (done) { cp.exec('rm -r ' + path.join(__dirname, 'migrations'), done); }); - }); + } + ); }); diff --git a/test/migration_test.js b/test/migration_test.js index 989cf442..daac3a68 100644 --- a/test/migration_test.js +++ b/test/migration_test.js @@ -14,18 +14,18 @@ var templateType = Migration.TemplateType.SQL_FILE_LOADER; var internals = {}; internals.migrationTable = 'migrations'; -lab.experiment('migration', { parallel: true }, function () { +lab.experiment('migration', function () { lab.experiment( 'when creating a new migration object', - { parallel: true }, + newMigrationObject ); - lab.experiment('get template', { parallel: true }, getTemplate); + lab.experiment('get template', getTemplate); lab.experiment( 'when using db-migrate as module', - { parallel: true }, + asModule ); }); @@ -42,7 +42,7 @@ function asModule () { function newMigrationObject () { lab.experiment( 'with 2 parameters as the complete filepath', - { parallel: true }, + function () { var migration = new Migration( dirName + dateString + '-' + fileName, @@ -51,14 +51,14 @@ function newMigrationObject () { lab.test( 'should have title set without file extension', - { parallel: true }, + function (done) { Code.expect(migration.title).to.equal(fileNameNoExtension); done(); } ); - lab.test('should have date set', { parallel: true }, function (done) { + lab.test('should have date set', function (done) { migration.date.setMilliseconds(0); date.setMilliseconds(0); Code.expect(migration.date.getTime()).to.equal(date.getTime()); @@ -67,7 +67,7 @@ function newMigrationObject () { lab.test( 'should have name set without file extension', - { parallel: true }, + function (done) { Code.expect(migration.name).to.equal( dateString + '-' + fileNameNoExtension @@ -76,58 +76,52 @@ function newMigrationObject () { } ); - lab.test('should have path set', { parallel: true }, function (done) { + lab.test('should have path set', function (done) { Code.expect(migration.path).to.equal( dirName + dateString + '-' + fileName ); done(); }); - lab.test('should have templateType not set', { parallel: true }, function ( - done - ) { + lab.test('should have templateType not set', function (done) { Code.expect(migration.templateType).to.be.undefined(); done(); }); } ); - lab.experiment('with 3 parameters', { parallel: true }, function () { + lab.experiment('with 3 parameters', function () { var migration = new Migration(fileName, dirName, date); - lab.test('should have title set', { parallel: true }, function (done) { + lab.test('should have title set', function (done) { Code.expect(migration.title).to.equal(fileName); done(); }); - lab.test('should have date set with month', { parallel: true }, function ( - done - ) { + lab.test('should have date set with month', function (done) { Code.expect(migration.date).to.equal(date); done(); }); - lab.test('should have name set', { parallel: true }, function (done) { + lab.test('should have name set', function (done) { Code.expect(migration.name).to.equal(dateString + '-' + fileName); done(); }); - lab.test('should have path set', { parallel: true }, function (done) { + lab.test('should have path set', function (done) { Code.expect(migration.path).to.equal( dirName + dateString + '-' + fileName ); done(); }); - lab.test('should have templateType not set', { parallel: true }, function ( - done - ) { + lab.test('should have templateType not set', function (done) { Code.expect(migration.templateType).to.be.undefined(); done(); }); }); - lab.experiment('with 5 parameters', { parallel: true }, function () { + lab.experiment('with 5 parameters', function () { var migration = new Migration( fileName, dirName, @@ -136,31 +130,29 @@ function newMigrationObject () { internals ); - lab.test('should have title set', { parallel: true }, function (done) { + lab.test('should have title set', function (done) { Code.expect(migration.title).to.equal(fileName); done(); }); - lab.test('should have date set', { parallel: true }, function (done) { + lab.test('should have date set', function (done) { Code.expect(migration.date).to.equal(date); done(); }); - lab.test('should have name set', { parallel: true }, function (done) { + lab.test('should have name set', function (done) { Code.expect(migration.name).to.equal(dateString + '-' + fileName); done(); }); - lab.test('should have path set', { parallel: true }, function (done) { + lab.test('should have path set', function (done) { Code.expect(migration.path).to.equal( dirName + dateString + '-' + fileName ); done(); }); - lab.test('should have templateType set', { parallel: true }, function ( - done - ) { + lab.test('should have templateType set', function (done) { Code.expect(migration.templateType).to.equal(templateType); done(); }); @@ -170,13 +162,13 @@ function newMigrationObject () { function getTemplate () { lab.experiment( 'when template type is not set', - { parallel: true }, + function () { var migration = new Migration(fileName, dirName, date, internals); lab.test( 'should return default javascript template', - { parallel: true }, + function (done) { var actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultJsTemplate()); @@ -186,8 +178,8 @@ function getTemplate () { } ); - lab.experiment('when template type is set', { parallel: true }, function () { - lab.experiment('as sql file loader', { parallel: true }, function () { + lab.experiment('when template type is set', function () { + lab.experiment('as sql file loader', function () { var migration = new Migration( fileName, dirName, @@ -198,7 +190,7 @@ function getTemplate () { lab.test( 'should return sql file loader template', - { parallel: true }, + function (done) { var actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.sqlFileLoaderTemplate()); @@ -207,7 +199,7 @@ function getTemplate () { ); }); - lab.experiment('as default sql', { parallel: true }, function () { + lab.experiment('as default sql', function () { var migration = new Migration( fileName, dirName, @@ -218,7 +210,7 @@ function getTemplate () { lab.test( 'should return default sql template', - { parallel: true }, + function (done) { var actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultSqlTemplate()); @@ -227,7 +219,7 @@ function getTemplate () { ); }); - lab.experiment('as default coffee', { parallel: true }, function () { + lab.experiment('as default coffee', function () { var migration = new Migration( fileName, dirName, @@ -238,7 +230,7 @@ function getTemplate () { lab.test( 'should return default coffee template', - { parallel: true }, + function (done) { var actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultCoffeeTemplate()); @@ -247,7 +239,7 @@ function getTemplate () { ); }); - lab.experiment('as coffee sql loader', { parallel: true }, function () { + lab.experiment('as coffee sql loader', function () { var migration = new Migration( fileName, dirName, @@ -258,7 +250,7 @@ function getTemplate () { lab.test( 'should return default coffee template', - { parallel: true }, + function (done) { var actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.coffeeSqlFileLoaderTemplate()); @@ -267,7 +259,7 @@ function getTemplate () { ); }); - lab.experiment('as default javascript', { parallel: true }, function () { + lab.experiment('as default javascript', function () { var migration = new Migration( fileName, dirName, @@ -278,7 +270,7 @@ function getTemplate () { lab.test( 'should return default sql template', - { parallel: true }, + function (done) { var actual = migration.getTemplate(); Code.expect(actual).to.equal(migration.defaultJsTemplate()); diff --git a/test/util_test.js b/test/util_test.js index 2186b66c..3d4b93b7 100644 --- a/test/util_test.js +++ b/test/util_test.js @@ -1,50 +1,55 @@ var Code = require('code'); var Lab = require('lab'); -var lab = exports.lab = Lab.script(); +var lab = (exports.lab = Lab.script()); var util = require('db-migrate-shared').util; -lab.experiment('util', { parallel: true }, function () { - lab.experiment('lpad', { parallel: true }, lpad); +lab.experiment('util', function () { + lab.experiment('lpad', lpad); }); function lpad () { - lab.test('should left pad the number of characters to equal the total length', - { parallel: true }, function (done) { + lab.test( + 'should left pad the number of characters to equal the total length', + function (done) { var actual = util.lpad('prompt', '>', 8); Code.expect(actual).to.equal('>>prompt'); done(); - }); + } + ); - lab.test('should apply no left padding if already equal to the total length', - { parallel: true }, function (done) { + lab.test( + 'should apply no left padding if already equal to the total length', + function (done) { var actual = util.lpad('>>prompt', '>', 8); Code.expect(actual).to.equal('>>prompt'); done(); - }); + } + ); - lab.test('should apply no left padding if already greater than the total ' + - 'length', { parallel: true }, function (done) { - var actual = util.lpad('>>>prompt', '>', 8); - Code.expect(actual).to.equal('>>>prompt'); + lab.test( + 'should apply no left padding if already greater than the total ' + + 'length', + function (done) { + var actual = util.lpad('>>>prompt', '>', 8); + Code.expect(actual).to.equal('>>>prompt'); - done(); - }); + done(); + } + ); - lab.test('should be apple to pad numbers', - { parallel: true }, function (done) { - var actual = util.lpad(12, '>', 4); - Code.expect(actual).to.equal('>>12'); + lab.test('should be apple to pad numbers', function (done) { + var actual = util.lpad(12, '>', 4); + Code.expect(actual).to.equal('>>12'); - done(); - }); + done(); + }); - lab.test('should be apple to pad using numbers', - { parallel: true }, function (done) { - var actual = util.lpad(12, 0, 4); - Code.expect(actual).to.equal('0012'); + lab.test('should be apple to pad using numbers', function (done) { + var actual = util.lpad(12, 0, 4); + Code.expect(actual).to.equal('0012'); - done(); - }); + done(); + }); } From 0692daa0dd536aa605c913510565bf555be2ac09 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 23 Nov 2017 09:53:47 +0100 Subject: [PATCH 366/412] add stale config --- .github/stale.yml | 23 +++++++++++++++++++++++ .npmignore | 1 + 2 files changed, 24 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000..acdb9cc6 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,23 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 30 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - feature + - Refactoring + - RFC + - bug + - documentation + - bounty + - pinned + - security +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/.npmignore b/.npmignore index 726ac2d3..a8319eaa 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1,4 @@ +.github test migrations VCSeeder From 73904ac162ff72088d5759caeb210719182dc668 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 23 Nov 2017 09:55:00 +0100 Subject: [PATCH 367/412] use more appropiate label --- .github/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/stale.yml b/.github/stale.yml index acdb9cc6..d2e1474e 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -13,7 +13,7 @@ exemptLabels: - pinned - security # Label to use when marking an issue as stale -staleLabel: wontfix +staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had From 5c2201c9e7b861fcd91a8ae88f00ac20f65c7a3b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 28 Nov 2017 00:13:08 +0100 Subject: [PATCH 368/412] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..1eea9489 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at dbmigrate@wizardtales.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ From 991ee7633e9d606f89557c4f3e76e0d5d42349db Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 28 Nov 2017 00:18:09 +0100 Subject: [PATCH 369/412] fix(db): wrong reference to connect causes db:create to fail Fixes #520 --- lib/commands/db.js | 2 +- lib/commands/seed.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/commands/db.js b/lib/commands/db.js index 43200ac6..1ca8b17e 100644 --- a/lib/commands/db.js +++ b/lib/commands/db.js @@ -4,7 +4,7 @@ var log = require('db-migrate-shared').log; var assert = require('assert'); function executeDB (internals, config, callback) { - var index = require('./connect'); + var index = require('../../connect'); if (internals.argv._.length > 0) { internals.argv.dbname = internals.argv._.shift().toString(); diff --git a/lib/commands/seed.js b/lib/commands/seed.js index 87558889..72b18a66 100644 --- a/lib/commands/seed.js +++ b/lib/commands/seed.js @@ -5,8 +5,8 @@ var path = require('path'); var _assert = require('./helper/assert'); function executeSeed (internals, config, callback) { - var index = require('./connect'); - var Seeder = require('./lib/seeder.js'); + var index = require('../../connect'); + var Seeder = require('../seeder.js'); if (internals.argv._.length > 0) { internals.argv.destination = internals.argv._.shift().toString(); From 89c57d1c63228f2274fe8381df022e86616c4c6d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 28 Nov 2017 00:18:17 +0100 Subject: [PATCH 370/412] 0.10.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0bb7268a..180c3dd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.10.0", + "version": "0.10.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 096fe5ca..f3865a49 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.0", + "version": "0.10.1", "engines": { "node": ">=0.6.0" }, From a1bf9e83a66aff0847f6e9fbcb8faa6882401c72 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 28 Nov 2017 00:25:13 +0100 Subject: [PATCH 371/412] add changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71786de6..8e1b9029 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ + +## [0.10.1](https://github.com/db-migrate/node-db-migrate/compare/v0.10.0...v0.10.1) (2017-11-27) + + +### Bug Fixes + +* **db:** wrong reference to connect causes db:create to fail ([56cb75a](https://github.com/db-migrate/node-db-migrate/commit/56cb75a)), closes [#520](https://github.com/db-migrate/node-db-migrate/issues/520) ## 0.10.0 From 16512f60fda4c12923229e377d58eb5cbb084661 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 1 Dec 2017 23:04:32 +0100 Subject: [PATCH 372/412] fix(log): error ended up in unreadable errors Fixes #524 Fixes #521 --- lib/commands/on-complete.js | 7 +------ lib/driver/index.js | 7 +++---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/commands/on-complete.js b/lib/commands/on-complete.js index 3df484a5..a78d921d 100644 --- a/lib/commands/on-complete.js +++ b/lib/commands/on-complete.js @@ -8,12 +8,7 @@ module.exports = function (migrator, internals, callback, originalErr) { migrator.driver.close(function (err) { if ((err || originalErr) && typeof callback === 'function') { - callback( - new Error({ - err: err, - originalErr: originalErr - }) - ); + callback(originalErr || err); return; } else { assert.ifError(originalErr); diff --git a/lib/driver/index.js b/lib/driver/index.js index 845ec3b7..d927a51b 100644 --- a/lib/driver/index.js +++ b/lib/driver/index.js @@ -74,15 +74,14 @@ exports.connect = function (config, intern, callback) { driver = require(req); } catch (e4) { return callback( - new Error({ - stack: - 'No such driver found, please try to install it via ' + + new Error( + 'No such driver found, please try to install it via ' + 'npm install db-migrate-' + config.driver + ' or ' + 'npm install -g db-migrate-' + config.driver - }) + ) ); } } From 31e094ec05fe11a638b837ae4ccfc5fdbc05d6a7 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 1 Dec 2017 23:05:47 +0100 Subject: [PATCH 373/412] add changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e1b9029..3dc7f63b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [0.10.2](https://github.com/db-migrate/node-db-migrate/compare/v0.10.1...v0.10.2) (2017-12-01) + + +### Bug Fixes + +* **log:** error ended up in unreadable errors ([97de65d](https://github.com/db-migrate/node-db-migrate/commit/97de65d)), closes [#524](https://github.com/db-migrate/node-db-migrate/issues/524) [#521](https://github.com/db-migrate/node-db-migrate/issues/521) + + + ## [0.10.1](https://github.com/db-migrate/node-db-migrate/compare/v0.10.0...v0.10.1) (2017-11-27) From a0d251ef9be73cec98540de6a63f50f06e13ee84 Mon Sep 17 00:00:00 2001 From: wtgtybhertgeghgtwtg Date: Tue, 28 Nov 2017 17:00:21 -0700 Subject: [PATCH 374/412] chore: Remove `moment`. Signed-off-by: wtgtybhertgeghgtwtg --- package-lock.json | 3 ++- package.json | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 180c3dd5..5466a6c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1528,7 +1528,8 @@ "moment": { "version": "2.19.2", "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.2.tgz", - "integrity": "sha512-Rf6jiHPEfxp9+dlzxPTmRHbvoFXsh2L/U8hOupUMpnuecHQmI6cF6lUbJl3QqKPko1u6ujO+FxtcajLVfLpAtA==" + "integrity": "sha512-Rf6jiHPEfxp9+dlzxPTmRHbvoFXsh2L/U8hOupUMpnuecHQmI6cF6lUbJl3QqKPko1u6ujO+FxtcajLVfLpAtA==", + "dev": true }, "mongodb-uri": { "version": "0.9.7", diff --git a/package.json b/package.json index f3865a49..f423f0e5 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,6 @@ "final-fs": "^1.6.0", "inflection": "^1.10.0", "mkdirp": "~0.5.0", - "moment": "^2.14.1", "optimist": "~0.6.1", "parse-database-url": "~0.3.0", "pkginfo": "^0.4.0", From 3c0fcbf65f89287ef2431a2c2b7802ca8ffa336b Mon Sep 17 00:00:00 2001 From: BorntraegerMarc Date: Thu, 4 Jan 2018 12:39:34 +0100 Subject: [PATCH 375/412] feat(issuetemplate): added a github issue template Signed-off-by: BorntraegerMarc --- .github/ISSUE_TEMPLATE.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..87e9f27e --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,35 @@ +## I'm submitting a... + +

+[ ] Bug report  
+[ ] Feature request
+
+ +## Current behavior + + + +## Expected behavior + + + +## Minimal reproduction of the problem with instructions + +## What is the motivation / use case for changing the behavior? + + + +## Environment + +

+db-migrate version: X.Y.Z
+plugins with versions: X.Y.Z
+db-migrate driver with versions: 
+
+Additional information:
+- Node version: XX  
+- Platform:  
+
+Others:
+
+
From 3c6fc33683831d7135f60ed6c0e4f7437e29cea1 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Fri, 2 Feb 2018 21:54:57 +0100 Subject: [PATCH 376/412] fix(exitCode): wrong check for existence fixed A wrong check for existence resulted in events not being loaded on version sized like 4.0.0. This resulted in non zero error codes when actually running into errors. Signed-off-by: Tobias Gurtzick --- api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.js b/api.js index 8e980865..aaa636ff 100644 --- a/api.js +++ b/api.js @@ -42,7 +42,7 @@ function dbmigrate (plugins, isModule, options, callback) { }); /* $lab:coverage:off$ */ - if (options && !options.throwUncatched) load('helper/register-events')(); + if (!options || !options.throwUncatched) load('helper/register-events')(); /* $lab:coverage:on$ */ if (typeof options === 'object') { From b1a3869f0cf1727ee5ec9453ef2063245306892b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 14:11:35 +0100 Subject: [PATCH 377/412] refactor(deprecationNotice): remove insert deprecation This temporarily removes the note being displayed to the user when an insert call is being made. This will be removed until seeders really going to be introduced. Refers to #215 Signed-off-by: Tobias Gurtzick --- lib/interface/migratorInterface.js | 72 ++++++++++++------------------ 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index e05e9035..729de6e3 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -1,40 +1,37 @@ /** - * The migrator interface provides the ability to handle all abilities which - * are needed to successfully modify the DD of your tables. - * This includes all DDL methods provided by SQL naturally. - * - * Considering the zero downtime deployment we are handling migrations like - * the following: - * - * Zero Downtime notes - * - * *) The very first step is always a full dump, for the sake of security - * - * - all operations that are deleting a currently existing column, e.g. renaming a column: - * - 1. duplicate the column - * - if renamed: - * - 1. create a trigger to update both columns - * - 2. disable/delete trigger after successful deployment - * - if deleted: - * - 1. apply steps from the renaming process - * - 2. create a backup of this column (+PK)/table and delete it afterwards (after the successful deployment) - * - all operations that modify content - * - 1. Retrieve data to be applied - * - 2. Extract PKs of to be updated rows - * - 3. Create backup of to be updated rows - * - 4. Apply changes - */ + * The migrator interface provides the ability to handle all abilities which + * are needed to successfully modify the DD of your tables. + * This includes all DDL methods provided by SQL naturally. + * + * Considering the zero downtime deployment we are handling migrations like + * the following: + * + * Zero Downtime notes + * + * *) The very first step is always a full dump, for the sake of security + * + * - all operations that are deleting a currently existing column, e.g. renaming a column: + * - 1. duplicate the column + * - if renamed: + * - 1. create a trigger to update both columns + * - 2. disable/delete trigger after successful deployment + * - if deleted: + * - 1. apply steps from the renaming process + * - 2. create a backup of this column (+PK)/table and delete it afterwards (after the successful deployment) + * - all operations that modify content + * - 1. Retrieve data to be applied + * - 2. Extract PKs of to be updated rows + * - 3. Create backup of to be updated rows + * - 4. Apply changes + */ function dummy () { arguments[arguments.length - 1]('not implemented'); } -function MigratorInterface () { - -} +function MigratorInterface () {} MigratorInterface.prototype = { - renameCollection: dummy, dropCollection: dummy, @@ -118,22 +115,11 @@ MigratorInterface.prototype = { all: dummy, close: dummy - }; module.exports = MigratorInterface; -module.exports.deprecated = { - - insert: function () { - arguments[arguments.length - 1]('not implemented'); - }, +module.exports.deprecated = {}; - insert_deprecation: 'is going to be completely removed, use version controlled seeds instead.' -}; - -module.exports.extending = { -}; +module.exports.extending = {}; -module.exports.exclude = { - -}; +module.exports.exclude = {}; From 486cb78bd53a0683ac59f3c53fbc5b0c7a5fc8e4 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 14:28:08 +0100 Subject: [PATCH 378/412] fix(exitCode): wrong exit code on db methods DB Calls always returned an exit code of 0, which leads to an unexpected behavior on the user side. Fixes #534 Signed-off-by: Tobias Gurtzick --- lib/commands/db.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/commands/db.js b/lib/commands/db.js index 1ca8b17e..de0cab86 100644 --- a/lib/commands/db.js +++ b/lib/commands/db.js @@ -25,13 +25,14 @@ function executeDB (internals, config, callback) { function (err) { if (err) { if (err.error) err = err.error; - log.info('Error: Failed to create database!', err); + log.error('Error: Failed to create database!', err); } else { log.info('Created database "' + internals.argv.dbname + '"'); } db.close(); - if (typeof callback === 'function') callback(); + if (typeof callback === 'function') callback(err); + else process.exit(1); } ); } else if (internals.mode === 'drop') { @@ -43,13 +44,14 @@ function executeDB (internals, config, callback) { function (err) { if (err) { if (err.error) err = err.error; - log.info('Error: Failed to drop database!', err); + log.error('Error: Failed to drop database!', err); } else { log.info('Deleted database "' + internals.argv.dbname + '"'); } db.close(); - if (typeof callback === 'function') callback(); + if (typeof callback === 'function') callback(err); + process.exit(1); } ); } From 392d88c5e12d3785f669454dc76729a2455ad147 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 14:47:58 +0100 Subject: [PATCH 379/412] fix(switchDatabase): no error was thrown on scope switch switchDatabase error was unhandled, which resulted in an unhandled scope switch error. Fixes #470 Signed-off-by: Tobias Gurtzick --- connect.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/connect.js b/connect.js index 2d2ae894..590aadc9 100644 --- a/connect.js +++ b/connect.js @@ -39,7 +39,10 @@ exports.connect = function (config, PassedClass, callback) { } catch (e) {} if (switched) { - db.switchDatabase(newConf, function () { + db.switchDatabase(newConf, function (err) { + if (err) { + return callback(err); + } internals.locTitle = internals.migrationMode; callback( null, From 7853c05cc833ed0ea7796fc7788aa034d88e5533 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 14:55:23 +0100 Subject: [PATCH 380/412] 0.10.3 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5466a6c5..1c74096a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.10.1", + "version": "0.10.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f423f0e5..d602384f 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.1", + "version": "0.10.3", "engines": { "node": ">=0.6.0" }, From 467bf2a7ae72a05805015f7595335d5efbacd3ce Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 3 Feb 2018 14:56:51 +0100 Subject: [PATCH 381/412] add changelog --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dc7f63b..95f941ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ + +## [0.10.3](https://github.com/db-migrate/node-db-migrate/compare/v0.10.2...v0.10.3) (2018-02-03) + + +### Bug Fixes + +* **db:** wrong reference to connect causes db:create to fail ([991ee76](https://github.com/db-migrate/node-db-migrate/commit/991ee76)), closes [#520](https://github.com/db-migrate/node-db-migrate/issues/520) +* **exitCode:** wrong check for existence fixed ([3c6fc33](https://github.com/db-migrate/node-db-migrate/commit/3c6fc33)) +* **exitCode:** wrong exit code on db methods ([486cb78](https://github.com/db-migrate/node-db-migrate/commit/486cb78)), closes [#534](https://github.com/db-migrate/node-db-migrate/issues/534) +* **log:** error ended up in unreadable errors ([16512f6](https://github.com/db-migrate/node-db-migrate/commit/16512f6)), closes [#524](https://github.com/db-migrate/node-db-migrate/issues/524) [#521](https://github.com/db-migrate/node-db-migrate/issues/521) +* **switchDatabase:** no error was thrown on scope switch ([392d88c](https://github.com/db-migrate/node-db-migrate/commit/392d88c)), closes [#470](https://github.com/db-migrate/node-db-migrate/issues/470) + + +### Features + +* **issuetemplate:** added a github issue template ([3c0fcbf](https://github.com/db-migrate/node-db-migrate/commit/3c0fcbf)) + + + ## [0.10.2](https://github.com/db-migrate/node-db-migrate/compare/v0.10.1...v0.10.2) (2017-12-01) From 7ca2f56283adf37e7da84cd03c03a7e8f4ea1c02 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 7 Feb 2018 00:09:52 +0100 Subject: [PATCH 382/412] fix(insert): add missing insert entry to interface Fixes #542 Signed-off-by: Tobias Gurtzick --- lib/interface/migratorInterface.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/interface/migratorInterface.js b/lib/interface/migratorInterface.js index 729de6e3..ba5d4a1d 100644 --- a/lib/interface/migratorInterface.js +++ b/lib/interface/migratorInterface.js @@ -114,7 +114,9 @@ MigratorInterface.prototype = { all: dummy, - close: dummy + close: dummy, + + insert: dummy }; module.exports = MigratorInterface; From 5d2c3938bdbc4795e86384cf7a25d14e2e09321c Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 7 Feb 2018 00:10:21 +0100 Subject: [PATCH 383/412] 0.10.4 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1c74096a..67f1ef16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.10.3", + "version": "0.10.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d602384f..2f7646e7 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.3", + "version": "0.10.4", "engines": { "node": ">=0.6.0" }, From e3ba2cea3ce170ba100bd90b94784d7d522664d2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 7 Feb 2018 00:11:01 +0100 Subject: [PATCH 384/412] changelog Signed-off-by: Tobias Gurtzick --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95f941ed..618372be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [0.10.4](https://github.com/db-migrate/node-db-migrate/compare/v0.10.3...v0.10.4) (2018-02-06) + + +### Bug Fixes + +* **insert:** add missing insert entry to interface ([899b8bc](https://github.com/db-migrate/node-db-migrate/commit/899b8bc)), closes [#542](https://github.com/db-migrate/node-db-migrate/issues/542) + + + ## [0.10.3](https://github.com/db-migrate/node-db-migrate/compare/v0.10.2...v0.10.3) (2018-02-03) From 66996cd2d20f9c90b546f426d9b8a9d5606a3708 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 7 Feb 2018 00:17:34 +0100 Subject: [PATCH 385/412] 0.10.5 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 67f1ef16..5c3247ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.10.4", + "version": "0.10.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2f7646e7..a1808ea0 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.4", + "version": "0.10.5", "engines": { "node": ">=0.6.0" }, From a39606eb6bed520a7b3499d5e9e109ead10312ef Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 8 Feb 2018 13:18:49 +0100 Subject: [PATCH 386/412] update to use real checkboxes --- .github/ISSUE_TEMPLATE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 87e9f27e..9f67e5c6 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,9 +1,9 @@ ## I'm submitting a... -

-[ ] Bug report  
-[ ] Feature request
-
+ + - [ ] Bug report + - [ ] Feature request + ## Current behavior From eb93c75172e685d5113519b40adc97c46031d00e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Thu, 8 Feb 2018 13:19:48 +0100 Subject: [PATCH 387/412] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 9f67e5c6..e0da2d98 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -3,6 +3,7 @@ - [ ] Bug report - [ ] Feature request + - [ ] Question ## Current behavior From 2cd0578f20cfee0a1b2b0b311e07f81fb7366e98 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 26 Feb 2018 23:26:37 +0100 Subject: [PATCH 388/412] feat(contribution): enrich contribution instructions Refers to #549 Signed-off-by: Tobias Gurtzick --- CONTRIBUTING.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b0d6553..a4937f21 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,16 +8,21 @@ this project: 2. Copy the test/db.config.example.json to test/db.config.json 3. Run the tests. Pull requests without tests are much less likely to be -merged, and it's great to know you're starting with a clean slate: `npm test`. -Be sure to check the README for setting up your test databases first. + merged, and it's great to know you're starting with a clean slate: `npm test`. + Be sure to check the README for setting up your test databases first. 4. Add a test for your change. Refactoring and documentation changes -require no new tests. If you are adding functionality or fixing a bug, -please include a test. + require no new tests. If you are adding functionality or fixing a bug, + please include a test. 5. Make the test pass. -6. Push to your fork and submit a pull request. +6. Create a commit that complies with our conventions, which you can view + [here](https://github.com/conventional-changelog/conventional-changelog/tree/35e60b5be6027fb2784c5103eee111f6f99b045e/packages/conventional-changelog-angular) + and last but not least also comply to the [DCO](https://github.com/probot/dco#how-it-works). + Which easiest work with just commiting via `git commit -s -m 'your commit message'`. + +7. Push to your fork and submit a pull request. At this point you're waiting on me. In a perfect world I'd commit to responding to your request in some short period of time. Unfortunately, From 5ee386b423e3a91ef25eb294a516552506a441f2 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 26 Feb 2018 23:42:12 +0100 Subject: [PATCH 389/412] feat(contribution): enrich contribution instructions, issues Signed-off-by: Tobias Gurtzick --- CONTRIBUTING.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a4937f21..026d3ac2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,40 @@ +# Contributing by opening an Issue or Discussing + +Whenever you find a bug, which you do not have the time to fix, it is still important +to get your input. Same goes for feature suggestions and everything else that helps +a project to get better. + +Here are a few points to consider before creating an issue or discussing within one: + +1. Make sure you have proper description of your problem or what exactly you want: + +We have issue templates in place that should help you with this one and this is really +important, since we may not just agree with you, if we don't understand your use case. + +2. Be constructive and before you post think once more if this is going to waste the maintainers + time, or if it is going to actually help them. + +Since being constructive, is a big vague, here some simple points that should help you: + +2.1. Just stating something is wrong, is not constructive. + +When you've got the feeling something is wrong, try to understand first if it is really wrong +and if it is make suggestions on how to improve, or even better open a PR and make the open source +world once again even better! + +2.2. "Does not work", is not a proper problem description + +Neither is, "see title". When you follow the issue template and provide all informations asked for +you should be pretty fine, in providing us exactly the information we need to help you. + +2.3. Follow the CoC and contribute, not attack + +An example when you're not contributing, but attacking is, should you just impose you're right +and you should be followed. It is always about the dialogue, that makes the difference. After all +you should be fine, by just using your common sense. + +# Contributing a Pull Request + Without pull requests from generous people like you, this project wouldn't be what it is today. You are planning to contribute aren't you? If so, here's a quick guide to creating a great pull request for From fd8562e4b1369018f6762cd7e999f132c11e4d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Borntr=C3=A4ger?= Date: Tue, 20 Mar 2018 09:45:34 +0100 Subject: [PATCH 390/412] feat(progamableApi): CMD options can be passed programatically now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc Bornträger --- lib/commands/set-default-argv.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index 6b07a4a0..ecd88635 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -98,9 +98,10 @@ module.exports = function (internals, isModule) { .describe('log-level', 'Set the log-level, for example sql|warn') .string('log-level'); } else { + var _internalsArgv = Object.assign(defaultConfig, internals.cmdOptions); internals.argv = { get argv () { - return defaultConfig; + return _internalsArgv; } }; } From 21c3eb9895853a6175654479a60512faec776907 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 20 Mar 2018 11:19:21 +0100 Subject: [PATCH 391/412] fix(ci): add ignores for backported features Signed-off-by: Tobias Gurtzick --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 2dde1658..55155416 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ test: - @node node_modules/lab/bin/lab -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -I verbose,dryRun,SharedArrayBuffer,Atomics --coverage-exclude lib/interface --coverage-exclude lib/transitions test-cov: - @node node_modules/lab/bin/lab -t 66 -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -t 66 -I verbose,dryRun,SharedArrayBuffer,Atomics --coverage-exclude lib/interface --coverage-exclude lib/transitions test-cov-html: - @node node_modules/lab/bin/lab -r html -o coverage.html -I verbose,dryRun --coverage-exclude lib/interface --coverage-exclude lib/transitions + @node node_modules/lab/bin/lab -r html -o coverage.html -I verbose,dryRun,SharedArrayBuffer,Atomics --coverage-exclude lib/interface --coverage-exclude lib/transitions .PHONY: test test-cov test-cov-html From 93afd7d3a8898eba51a66c46fc85039c60629bef Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 20 Mar 2018 11:24:33 +0100 Subject: [PATCH 392/412] chore: update dependencies Signed-off-by: Tobias Gurtzick --- package-lock.json | 19 ++++++++++++------- package.json | 4 ++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5c3247ae..6ca19125 100644 --- a/package-lock.json +++ b/package-lock.json @@ -411,7 +411,7 @@ "requires": { "bluebird": "3.5.1", "db-migrate-base": "1.5.3", - "moment": "2.19.2", + "moment": "2.21.0", "mysql": "2.15.0" } }, @@ -452,9 +452,9 @@ "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=" }, "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.0.tgz", + "integrity": "sha1-bvSgmwX5iw41jW2T1Mo8rsZnKAM=" }, "deep-is": { "version": "0.1.3", @@ -1526,9 +1526,9 @@ "dev": true }, "moment": { - "version": "2.19.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.2.tgz", - "integrity": "sha512-Rf6jiHPEfxp9+dlzxPTmRHbvoFXsh2L/U8hOupUMpnuecHQmI6cF6lUbJl3QqKPko1u6ujO+FxtcajLVfLpAtA==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", + "integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==", "dev": true }, "mongodb-uri": { @@ -1870,6 +1870,11 @@ "strip-json-comments": "2.0.1" }, "dependencies": { + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", diff --git a/package.json b/package.json index a1808ea0..8b29e88b 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "balanced-match": "^0.4.2", "bluebird": "^3.1.1", "db-migrate-shared": "^1.1.2", - "deep-extend": "^0.4.1", + "deep-extend": "^0.5.0", "dotenv": "^2.0.0", "final-fs": "^1.6.0", "inflection": "^1.10.0", @@ -64,7 +64,7 @@ "devDependencies": { "code": "^4.1.0", "db-migrate-base": "^1.2.5", - "db-migrate-mysql": "^1.1.7", + "db-migrate-mysql": "^1.1.10", "db-migrate-sqlite3": "^0.2.1", "eslint": "^4.10.0", "eslint-config-standard": "^10.2.1", From d761ebf53d0a922ee8e98bb308a7911bf37de08d Mon Sep 17 00:00:00 2001 From: BorntraegerMarc Date: Tue, 20 Mar 2018 11:38:46 +0100 Subject: [PATCH 393/412] feat(progamableApi): using const now Signed-off-by: BorntraegerMarc --- lib/commands/set-default-argv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index ecd88635..616750a5 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -98,7 +98,7 @@ module.exports = function (internals, isModule) { .describe('log-level', 'Set the log-level, for example sql|warn') .string('log-level'); } else { - var _internalsArgv = Object.assign(defaultConfig, internals.cmdOptions); + const _internalsArgv = Object.assign(defaultConfig, internals.cmdOptions); internals.argv = { get argv () { return _internalsArgv; From 2a6b0f9137e36bf8569f56f87a9e2b7c7f344391 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 21 Mar 2018 09:53:06 +0100 Subject: [PATCH 394/412] add changelog Signed-off-by: Tobias Gurtzick --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 618372be..2631ab54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ + +## [0.10.6](https://github.com/db-migrate/node-db-migrate/compare/v0.10.5...v0.10.6) (2018-03-21) + + +### Bug Fixes + +* **ci:** add ignores for backported features ([53dedc2](https://github.com/db-migrate/node-db-migrate/commit/53dedc2)) + + +### Features + +* **contribution:** enrich contribution instructions ([93b5cea](https://github.com/db-migrate/node-db-migrate/commit/93b5cea)), closes [#549](https://github.com/db-migrate/node-db-migrate/issues/549) +* **contribution:** enrich contribution instructions, issues ([d87a734](https://github.com/db-migrate/node-db-migrate/commit/d87a734)) +* **progamableApi:** CMD options can be passed programatically now ([69d7605](https://github.com/db-migrate/node-db-migrate/commit/69d7605)) +* **progamableApi:** using const now ([a69e221](https://github.com/db-migrate/node-db-migrate/commit/a69e221)) + + + ## [0.10.4](https://github.com/db-migrate/node-db-migrate/compare/v0.10.3...v0.10.4) (2018-02-06) From efb8f3601fd89b96d18d3c64c8da3eb830b70d70 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 21 Mar 2018 09:49:30 +0100 Subject: [PATCH 395/412] 0.10.6 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6ca19125..09323e14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.10.5", + "version": "0.10.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8b29e88b..aa6cbb8c 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.5", + "version": "0.10.6", "engines": { "node": ">=0.6.0" }, From 6c7dc6702ba072dc8068181f8a06aa50eb0b07a5 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 27 Mar 2018 11:10:56 +0200 Subject: [PATCH 396/412] chore: add test to detect cmdOptions functionality Refers to #560 Refers to #557 Signed-off-by: Tobias Gurtzick --- test/integration/api_test.js | 40 +++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/test/integration/api_test.js b/test/integration/api_test.js index b5dabaff..e997e04d 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -31,17 +31,17 @@ lab.experiment('api', function () { dbmigrate.silence(true); /** - * We have set force-exit above, this should end up in db-migrate - * executing process.exit on the final callback. - * Process.exit has been overwritten and will finally call validate. - * - * The test validation takes place in validate() - */ + * We have set force-exit above, this should end up in db-migrate + * executing process.exit on the final callback. + * Process.exit has been overwritten and will finally call validate. + * + * The test validation takes place in validate() + */ dbmigrate.up(); /** - * Final validation after process.exit should have been called. - */ + * Final validation after process.exit should have been called. + */ function validate () { Code.expect(called).to.be.true(); done(); @@ -59,8 +59,8 @@ lab.experiment('api', function () { } /** - * Create a migration with the programatic API and overwrite process.exit. - */ + * Create a migration with the programatic API and overwrite process.exit. + */ function overwriteExit () { process.exit = function (err) { var ret = called; @@ -110,6 +110,26 @@ lab.experiment('api', function () { done(); }); + lab.test('should load commandline options from options parameter', function ( + done + ) { + var options = { + cmdOptions: { + 'migrations-dir': './test' + } + }; + + var api = stubApiInstance(true, {}, options); + var actual = api.internals.argv['migrations-dir']; + var expected = options.cmdOptions['migrations-dir']; + + delete expected.getCurrent; + delete actual.getCurrent; + + Code.expect(actual).to.equal(expected); + done(); + }); + lab.test( 'should handle all up parameter variations properly', From cb88b5895a89e37baef4a0fbc6d43806e510b531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Borntr=C3=A4ger?= Date: Tue, 27 Mar 2018 10:53:24 +0200 Subject: [PATCH 397/412] fix(progamableApi): cmdOptions get passed into setDefaultArgv now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc Bornträger --- api.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api.js b/api.js index aaa636ff..2576bd4c 100644 --- a/api.js +++ b/api.js @@ -56,6 +56,8 @@ function dbmigrate (plugins, isModule, options, callback) { if (typeof options.cwd === 'string') internals.cwd = options.cwd; else internals.cwd = process.cwd(); + + if (typeof options.cmdOptions === 'object') internals.cmdOptions = options.cmdOptions; } else internals.cwd = process.cwd(); if (typeof isModule === 'function') { From 7cc47b139aee50e3b55b96fde43f4f3044cb0633 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 27 Mar 2018 13:30:42 +0200 Subject: [PATCH 398/412] 0.10.7 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 09323e14..a0ab3acd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.10.6", + "version": "0.10.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index aa6cbb8c..982511ff 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.6", + "version": "0.10.7", "engines": { "node": ">=0.6.0" }, From 96b0bf326b6f65a452e2c59529baf0127a25fcae Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 27 Mar 2018 13:35:50 +0200 Subject: [PATCH 399/412] add changelog Signed-off-by: Tobias Gurtzick --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2631ab54..88cfa5eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [0.10.7](https://github.com/db-migrate/node-db-migrate/compare/v0.10.6...v0.10.7) (2018-03-27) + + +### Bug Fixes + +* **progamableApi:** cmdOptions get passed into setDefaultArgv now ([ebdd75d](https://github.com/db-migrate/node-db-migrate/commit/ebdd75d)) + + + ## [0.10.6](https://github.com/db-migrate/node-db-migrate/compare/v0.10.5...v0.10.6) (2018-03-21) From 387219d4e5c425809dec1984a9cb87bf47b7c83e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 10 Apr 2018 08:17:38 +0200 Subject: [PATCH 400/412] chore: update dependency Signed-off-by: Tobias Gurtzick --- package-lock.json | 722 ++++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 308 insertions(+), 416 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0ab3acd..edf1ce6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,10 +4,19 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "dev": true, + "requires": { + "samsam": "1.3.0" + } + }, "acorn": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", "dev": true }, "acorn-jsx": { @@ -28,13 +37,13 @@ } }, "ajv": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.4.0.tgz", - "integrity": "sha1-MtHPCNvIDEMvQm8S4QslEfa0ZHQ=", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { "co": "4.6.0", - "fast-deep-equal": "1.0.0", + "fast-deep-equal": "1.1.0", "fast-json-stable-stringify": "2.0.0", "json-schema-traverse": "0.3.1" } @@ -63,9 +72,9 @@ "dev": true }, "ansi-escapes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, "ansi-regex": { @@ -81,9 +90,9 @@ "dev": true }, "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "1.0.3" @@ -177,14 +186,14 @@ "integrity": "sha1-+a6fJugbQaMY9O4Ng2huSlwlB7k=", "dev": true, "requires": { - "hoek": "4.2.0", + "hoek": "4.2.1", "joi": "10.6.0" } }, "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -197,6 +206,12 @@ } } }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -237,40 +252,40 @@ } }, "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "supports-color": "5.3.0" }, "dependencies": { "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "1.9.1" } }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "3.0.0" } } } }, "chardet": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.0.tgz", - "integrity": "sha1-C74TVaxE16PtSpJXB8TvcPgZD2w=", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, "circular-json": { @@ -327,7 +342,7 @@ "integrity": "sha1-IJrRHQWvigwceq9pTZ+k0sfZW4U=", "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "color-convert": { @@ -346,9 +361,9 @@ "dev": true }, "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz", + "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==" }, "concat-map": { "version": "0.0.1", @@ -356,11 +371,12 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { + "buffer-from": "1.0.0", "inherits": "2.0.3", "readable-stream": "2.3.3", "typedarray": "0.0.6" @@ -384,7 +400,7 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "shebang-command": "1.2.0", "which": "1.3.0" } @@ -411,7 +427,7 @@ "requires": { "bluebird": "3.5.1", "db-migrate-base": "1.5.3", - "moment": "2.21.0", + "moment": "2.22.0", "mysql": "2.15.0" } }, @@ -432,11 +448,11 @@ } }, "debug": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", - "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } }, "decamelize": { @@ -470,7 +486,7 @@ "requires": { "globby": "5.0.0", "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1", @@ -478,19 +494,18 @@ } }, "diff": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", - "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "doctrine": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", - "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "2.0.2" } }, "dotenv": { @@ -514,35 +529,35 @@ "dev": true }, "eslint": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.11.0.tgz", - "integrity": "sha512-UWbhQpaKlm8h5x/VLwm0S1kheMrDj8jPwhnBMjr/Dlo3qqT7MvcN/UfKAR3E1N4lr4YNtOvS4m3hwsrVc/ky7g==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { - "ajv": "5.4.0", + "ajv": "5.5.2", "babel-code-frame": "6.26.0", - "chalk": "2.3.0", - "concat-stream": "1.6.0", + "chalk": "2.3.2", + "concat-stream": "1.6.2", "cross-spawn": "5.1.0", "debug": "3.1.0", - "doctrine": "2.0.0", + "doctrine": "2.1.0", "eslint-scope": "3.7.1", - "espree": "3.5.2", - "esquery": "1.0.0", - "estraverse": "4.2.0", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.4", + "esquery": "1.0.1", "esutils": "2.0.2", "file-entry-cache": "2.0.0", "functional-red-black-tree": "1.0.1", "glob": "7.1.2", - "globals": "9.18.0", + "globals": "11.4.0", "ignore": "3.3.7", "imurmurhash": "0.1.4", "inquirer": "3.3.0", - "is-resolvable": "1.0.0", - "js-yaml": "3.10.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.11.0", "json-stable-stringify-without-jsonify": "1.0.1", "levn": "0.3.0", - "lodash": "4.17.4", + "lodash": "4.17.5", "minimatch": "3.0.4", "mkdirp": "0.5.1", "natural-compare": "1.4.0", @@ -550,8 +565,9 @@ "path-is-inside": "1.0.2", "pluralize": "7.0.0", "progress": "2.0.0", + "regexpp": "1.1.0", "require-uncached": "1.0.3", - "semver": "5.4.1", + "semver": "5.5.0", "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", "table": "4.0.2", @@ -566,12 +582,6 @@ "requires": { "ms": "2.0.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, @@ -588,57 +598,23 @@ "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz", - "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, "requires": { "debug": "2.6.9", - "resolve": "1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "resolve": "1.7.0" } }, "eslint-module-utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", - "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, "requires": { "debug": "2.6.9", "pkg-dir": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } } }, "eslint-plugin-hapi": { @@ -655,32 +631,23 @@ } }, "eslint-plugin-import": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", - "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.10.0.tgz", + "integrity": "sha1-+gkIPVp1KI35xsfQn+EiVZhWVec=", "dev": true, "requires": { "builtin-modules": "1.1.1", "contains-path": "0.1.0", "debug": "2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "0.3.1", - "eslint-module-utils": "2.1.1", + "eslint-import-resolver-node": "0.3.2", + "eslint-module-utils": "2.2.0", "has": "1.0.1", - "lodash.cond": "4.5.2", + "lodash": "4.17.5", "minimatch": "3.0.4", "read-pkg-up": "2.0.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "doctrine": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", @@ -690,12 +657,6 @@ "esutils": "2.0.2", "isarray": "1.0.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, @@ -707,7 +668,7 @@ "requires": { "ignore": "3.3.7", "minimatch": "3.0.4", - "resolve": "1.5.0", + "resolve": "1.7.0", "semver": "5.3.0" }, "dependencies": { @@ -720,9 +681,9 @@ } }, "eslint-plugin-promise": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", - "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz", + "integrity": "sha512-2WO+ZFh7vxUKRfR0cOIMrWgYKdR6S1AlOezw6pC52B6oYpd5WFghN+QHxvrRdZMtbo8h3dfUZ2o1rWb0UPbKtg==", "dev": true }, "eslint-plugin-standard": { @@ -737,17 +698,23 @@ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "esrecurse": "4.2.0", + "esrecurse": "4.2.1", "estraverse": "4.2.0" } }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, "espree": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", - "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "5.2.1", + "acorn": "5.5.3", "acorn-jsx": "3.0.1" } }, @@ -758,22 +725,21 @@ "dev": true }, "esquery": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { "estraverse": "4.2.0" } }, "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "4.2.0" } }, "estraverse": { @@ -789,13 +755,13 @@ "dev": true }, "external-editor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, "requires": { - "chardet": "0.4.0", - "iconv-lite": "0.4.19", + "chardet": "0.4.2", + "iconv-lite": "0.4.21", "tmp": "0.0.33" } }, @@ -805,9 +771,9 @@ "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { @@ -888,15 +854,6 @@ "write": "0.2.1" } }, - "formatio": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", - "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", - "dev": true, - "requires": { - "samsam": "1.3.0" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -928,9 +885,9 @@ } }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.4.0.tgz", + "integrity": "sha512-Dyzmifil8n/TmSqYDEXbm+C8yitzJQqQIlJQLNRMwa+BOUJpRC19pyVeN12JAjt61xonvXjtff+hJruTRXn5HA==", "dev": true }, "globby": { @@ -970,6 +927,15 @@ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } } } }, @@ -1016,21 +982,21 @@ } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", "dev": true }, "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", "dev": true }, "i": { @@ -1039,10 +1005,13 @@ "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=" }, "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", + "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } }, "ignore": { "version": "3.3.7", @@ -1086,13 +1055,13 @@ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.0", + "ansi-escapes": "3.1.0", + "chalk": "2.3.2", "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "external-editor": "2.1.0", + "external-editor": "2.2.0", "figures": "2.0.0", - "lodash": "4.17.4", + "lodash": "4.17.5", "mute-stream": "0.0.7", "run-async": "2.3.0", "rx-lite": "4.0.8", @@ -1142,18 +1111,18 @@ "dev": true }, "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { "path-is-inside": "1.0.2" @@ -1166,13 +1135,10 @@ "dev": true }, "is-resolvable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true, - "requires": { - "tryit": "1.0.3" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true }, "isarray": { "version": "1.0.0", @@ -1209,7 +1175,7 @@ "integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==", "dev": true, "requires": { - "hoek": "4.2.0", + "hoek": "4.2.1", "isemail": "2.2.1", "items": "2.1.1", "topo": "2.0.2" @@ -1222,12 +1188,12 @@ "dev": true }, "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "dev": true, "requires": { - "argparse": "1.0.9", + "argparse": "1.0.10", "esprima": "4.0.0" } }, @@ -1280,107 +1246,35 @@ } }, "lab": { - "version": "14.3.1", - "resolved": "https://registry.npmjs.org/lab/-/lab-14.3.1.tgz", - "integrity": "sha512-sN14QhqiRuBGnfrOGo1B9UqiJJarEcZJEna/hGAT5g4uuxcowns4zc/JUBoMgT44jZgWBxbpjKPizBOGt5mYRw==", + "version": "14.3.4", + "resolved": "https://registry.npmjs.org/lab/-/lab-14.3.4.tgz", + "integrity": "sha512-IFnuYVRd6CtnFTFgUbjPCFrrCIked5BvGH/dX+/h+6pi3IrQrK21JsKy/J1CshEm6sMe980+oswtK8lZCusHSA==", "dev": true, "requires": { "bossy": "3.0.4", "code": "4.1.0", - "diff": "3.3.1", - "eslint": "4.5.0", + "diff": "3.5.0", + "eslint": "4.19.1", "eslint-config-hapi": "10.1.0", "eslint-plugin-hapi": "4.1.0", - "espree": "3.5.2", + "espree": "3.5.4", "find-rc": "3.0.1", "handlebars": "4.0.11", - "hoek": "4.2.0", + "hoek": "4.2.1", "items": "2.1.1", "json-stable-stringify": "1.0.1", "json-stringify-safe": "5.0.1", "mkdirp": "0.5.1", "seedrandom": "2.4.3", - "source-map": "0.5.7", + "source-map": "0.6.1", "source-map-support": "0.4.18", "supports-color": "4.4.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "eslint": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.5.0.tgz", - "integrity": "sha1-u3XTuL3pf7XhPvzVOXRGd/6wGcM=", - "dev": true, - "requires": { - "ajv": "5.4.0", - "babel-code-frame": "6.26.0", - "chalk": "2.3.0", - "concat-stream": "1.6.0", - "cross-spawn": "5.1.0", - "debug": "2.6.9", - "doctrine": "2.0.0", - "eslint-scope": "3.7.1", - "espree": "3.5.2", - "esquery": "1.0.0", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.7", - "imurmurhash": "0.1.4", - "inquirer": "3.3.0", - "is-resolvable": "1.0.0", - "js-yaml": "3.10.0", - "json-stable-stringify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "4.0.0", - "progress": "2.0.0", - "require-uncached": "1.0.3", - "semver": "5.4.1", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", - "table": "4.0.2", - "text-table": "0.2.0" - } - }, - "ms": { + "has-flag": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "pluralize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", - "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, "supports-color": { @@ -1442,15 +1336,9 @@ } }, "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "lodash.cond": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", - "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", "dev": true }, "lodash.defaults": { @@ -1465,9 +1353,9 @@ "dev": true }, "lolex": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.1.tgz", - "integrity": "sha512-mQuW55GhduF3ppo+ZRUTz1PRjEh1hS5BbqU7d8D0ez2OKxHDod7StPPeAVKisZR5aLkHZjdGWSL42LSONUJsZw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==", "dev": true }, "longest": { @@ -1477,9 +1365,9 @@ "dev": true }, "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", "dev": true, "requires": { "pseudomap": "1.0.2", @@ -1493,9 +1381,9 @@ "dev": true }, "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimatch": { @@ -1503,7 +1391,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -1526,9 +1414,9 @@ "dev": true }, "moment": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", - "integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.0.tgz", + "integrity": "sha512-1muXCh8jb1N/gHRbn9VDUBr0GYb8A/aVcHlII9QSB68a50spqEVLIGN6KVmCOnSvJrUhC0edGgKU5ofnGXdYdg==", "dev": true }, "mongodb-uri": { @@ -1537,9 +1425,9 @@ "integrity": "sha1-D3ca0W9IOuZfQoeWlCjp+8SqYYE=" }, "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mute-stream": { "version": "0.0.7", @@ -1576,24 +1464,16 @@ "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=" }, "nise": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.2.0.tgz", - "integrity": "sha512-q9jXh3UNsMV28KeqI43ILz5+c3l+RiNW8mhurEwCKckuHQbL+hTJIKKTiUlCPKlgQ/OukFvSnKB/Jk3+sFbkGA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.3.2.tgz", + "integrity": "sha512-KPKb+wvETBiwb4eTwtR/OsA2+iijXP+VnlSFYJo3EHjm2yjek1NWxHOUQat3i7xNLm1Bm18UA5j5Wor0yO2GtA==", "dev": true, "requires": { - "formatio": "1.2.0", + "@sinonjs/formatio": "2.0.0", "just-extend": "1.1.27", - "lolex": "1.6.0", + "lolex": "2.3.2", "path-to-regexp": "1.7.0", "text-encoding": "0.6.4" - }, - "dependencies": { - "lolex": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", - "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", - "dev": true - } } }, "no-arrowception": { @@ -1613,10 +1493,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "2.5.0", + "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" } }, "object-assign": { @@ -1639,7 +1519,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "mimic-fn": "1.2.0" } }, "optimist": { @@ -1680,10 +1560,13 @@ "dev": true }, "p-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } }, "p-locate": { "version": "2.0.0", @@ -1691,9 +1574,15 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.1.0" + "p-limit": "1.2.0" } }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, "parse-database-url": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/parse-database-url/-/parse-database-url-0.3.0.tgz", @@ -1826,7 +1715,7 @@ "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.0.0.tgz", "integrity": "sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=", "requires": { - "colors": "1.1.2", + "colors": "1.2.1", "pkginfo": "0.4.1", "read": "1.0.7", "revalidator": "0.1.8", @@ -1860,9 +1749,9 @@ "dev": true }, "rc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz", - "integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz", + "integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=", "requires": { "deep-extend": "0.4.2", "ini": "1.3.5", @@ -1937,6 +1826,12 @@ "util-deprecate": "1.0.2" } }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true + }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -1954,9 +1849,9 @@ } }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.0.tgz", + "integrity": "sha512-QdgZ5bjR1WAlpLaO5yHepFvC+o3rCr6wpfE2tpJNMkXdulf2jKomQBdNRQITF3ZKHNlT71syG98yQP03gasgnA==", "requires": { "path-parse": "1.0.5" } @@ -1996,7 +1891,6 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "requires": { "glob": "7.1.2" } @@ -2031,6 +1925,12 @@ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "samsam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", @@ -2044,9 +1944,9 @@ "dev": true }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "shebang-command": { "version": "1.2.0", @@ -2070,27 +1970,27 @@ "dev": true }, "sinon": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.1.2.tgz", - "integrity": "sha512-5uLBZPdCWl59Lpbf45ygKj7Z0LVol+ftBe7RDIXOQV/sF58pcFmbK8raA7bt6eljNuGnvBP+/ZxlicVn0emDjA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "dev": true, "requires": { - "diff": "3.4.0", - "formatio": "1.2.0", + "@sinonjs/formatio": "2.0.0", + "diff": "3.5.0", "lodash.get": "4.4.2", - "lolex": "2.3.1", - "nise": "1.2.0", - "supports-color": "4.5.0", - "type-detect": "4.0.5" + "lolex": "2.3.2", + "nise": "1.3.2", + "supports-color": "5.3.0", + "type-detect": "4.0.8" }, "dependencies": { "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "3.0.0" } } } @@ -2105,13 +2005,10 @@ } }, "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "source-map-support": { "version": "0.4.18", @@ -2131,24 +2028,35 @@ } }, "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, "sprintf-js": { @@ -3002,7 +2910,7 @@ "integrity": "sha1-URGNFUVV31Rp7h9n4M8efoosDjo=", "requires": { "asn1": "0.2.3", - "semver": "5.4.1", + "semver": "5.5.0", "streamsearch": "0.1.2" } }, @@ -3075,10 +2983,10 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "5.4.0", + "ajv": "5.5.2", "ajv-keywords": "2.1.1", - "chalk": "2.3.0", - "lodash": "4.17.4", + "chalk": "2.3.2", + "lodash": "4.17.5", "slice-ansi": "1.0.0", "string-width": "2.1.1" } @@ -3116,21 +3024,15 @@ "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true - }, "tunnel-ssh": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tunnel-ssh/-/tunnel-ssh-4.1.3.tgz", - "integrity": "sha1-kRIWrXnfEAkILFcT/tJkdu0jm60=", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tunnel-ssh/-/tunnel-ssh-4.1.4.tgz", + "integrity": "sha512-CjBqboGvAbM7iXSX2F95kzoI+c2J81YkrHbyyo4SWNKCzU6w5LfEvXBCHu6PPriYaNvfhMKzD8bFf5Vl14YTtg==", "requires": { - "debug": "2.6.0", + "debug": "2.6.9", "lodash.defaults": "4.2.0", "ssh2": "0.5.4" } @@ -3145,9 +3047,9 @@ } }, "type-detect": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz", - "integrity": "sha512-N9IvkQslUGYGC24RkJk1ba99foK6TkwC2FHAEBlQFBP0RxQZS8ZpJuAZcwiY/w9ZJHFQb1aOXBI60OdxhTrwEQ==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "typedarray": { @@ -3201,26 +3103,16 @@ "mkdirp": "0.5.1", "ncp": "1.0.1", "rimraf": "2.6.2" - }, - "dependencies": { - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "7.1.2" - } - } } }, "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "when": { diff --git a/package.json b/package.json index 982511ff..4b3ad0e1 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "dependencies": { "balanced-match": "^0.4.2", "bluebird": "^3.1.1", - "db-migrate-shared": "^1.1.2", + "db-migrate-shared": "^1.1.3", "deep-extend": "^0.5.0", "dotenv": "^2.0.0", "final-fs": "^1.6.0", From 03659d9b4de54682d34c0e8f6d5d1522e8bc667d Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 10 Apr 2018 08:21:33 +0200 Subject: [PATCH 401/412] chore: update dependency Signed-off-by: Tobias Gurtzick --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index edf1ce6c..0eb1cfcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -432,9 +432,9 @@ } }, "db-migrate-shared": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/db-migrate-shared/-/db-migrate-shared-1.1.3.tgz", - "integrity": "sha1-7bPIF7KVAixhmEwYcmdBm7NqLVg=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/db-migrate-shared/-/db-migrate-shared-1.2.0.tgz", + "integrity": "sha512-65k86bVeHaMxb2L0Gw3y5V+CgZSRwhVQMwDMydmw5MvIpHHwD6SmBciqIwHsZfzJ9yzV/yYhdRefRM6FV5/siw==" }, "db-migrate-sqlite3": { "version": "0.2.1", diff --git a/package.json b/package.json index 4b3ad0e1..99f7a45d 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "dependencies": { "balanced-match": "^0.4.2", "bluebird": "^3.1.1", - "db-migrate-shared": "^1.1.3", + "db-migrate-shared": "^1.2.0", "deep-extend": "^0.5.0", "dotenv": "^2.0.0", "final-fs": "^1.6.0", From 56acdb985e5bd643e18c6ac4248448e6f70892d5 Mon Sep 17 00:00:00 2001 From: RandomSeeded Date: Mon, 19 Mar 2018 11:53:46 +0900 Subject: [PATCH 402/412] feat(check): add check functionality to determine migrations to run Signed-off-by: RandomSeeded --- api.js | 25 +++++++++++++++++ lib/commands/check.js | 37 ++++++++++++++++++++++++ lib/commands/run.js | 8 ++++-- lib/commands/set-default-argv.js | 8 +++++- lib/migrator.js | 48 ++++++++++++++++++++++++++++++++ test/integration/api_test.js | 17 +++++++++++ test/migrator_test.js | 32 +++++++++++++++++++++ 7 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 lib/commands/check.js create mode 100644 test/migrator_test.js diff --git a/api.js b/api.js index 2576bd4c..ccf3e973 100644 --- a/api.js +++ b/api.js @@ -227,6 +227,31 @@ dbmigrate.prototype = { ).asCallback(callback); }, + check: function (specification, opts, callback) { + var executeCheck = load('check'); + + if (arguments.length > 0) { + if (typeof specification === 'number') { + this.internals.argv.count = arguments[0]; + } else if (typeof specification === 'function') { + callback = specification; + } + + if (typeof opts === 'string') { + this.internals.migrationMode = opts; + this.internals.matching = opts; + } else if (typeof opts === 'function') { + callback = opts; + } + } + + return Promise.fromCallback( + function (callback) { + executeCheck(this.internals, this.config, callback); + }.bind(this) + ).asCallback(callback); + }, + /** * Executes up a given number of migrations or a specific one. * diff --git a/lib/commands/check.js b/lib/commands/check.js new file mode 100644 index 00000000..63891ff6 --- /dev/null +++ b/lib/commands/check.js @@ -0,0 +1,37 @@ +var path = require('path'); +var log = require('db-migrate-shared').log; +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'); + + if (!internals.argv.count) { + internals.argv.count = Number.MAX_VALUE; + } + index.connect({ + config: config.getCurrent().settings, + internals: internals + }, 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']); } + + internals.migrationsDir = migrator.migrationsDir; + + migrator.driver.createMigrationsTable(function (err) { + if (!assert(err, callback)) return; + log.verbose('migration table created'); + + migrator.check(internals.argv, internals.onComplete.bind(this, + migrator, internals, callback)); + }); + }); + }); +}; diff --git a/lib/commands/run.js b/lib/commands/run.js index 6d182cc4..40bffeb5 100644 --- a/lib/commands/run.js +++ b/lib/commands/run.js @@ -42,6 +42,7 @@ function run (internals, config) { break; case 'up': case 'down': + case 'check': case 'reset': if (action === 'reset') internals.argv.count = Number.MAX_VALUE; @@ -62,9 +63,12 @@ function run (internals, config) { if (action === 'up') { var executeUp = load('up'); executeUp(internals, config); - } else { + } else if (action === 'down') { var executeDown = load('down'); executeDown(internals, config); + } else { + var executeCheck = load('check'); + executeCheck(internals, config); } break; @@ -104,7 +108,7 @@ function run (internals, config) { ); } else { log.error( - 'Invalid Action: Must be [up|down|create|reset|sync|' + + 'Invalid Action: Must be [up|down|check|create|reset|sync|' + 'db|transition].' ); optimist.showHelp(); diff --git a/lib/commands/set-default-argv.js b/lib/commands/set-default-argv.js index 616750a5..bd89db37 100644 --- a/lib/commands/set-default-argv.js +++ b/lib/commands/set-default-argv.js @@ -22,7 +22,7 @@ module.exports = function (internals, isModule) { internals.argv = optimist .default(defaultConfig) .usage( - 'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' + + 'Usage: db-migrate [up|down|check|reset|sync|create|db|transition] ' + '[[dbname/]migrationName|all] [options]' ) .describe( @@ -42,6 +42,8 @@ module.exports = function (internals, isModule) { .string('c') .describe('dry-run', "Prints the SQL but doesn't run it.") .boolean('dry-run') + .describe('check', 'Prints the migrations to be run without running them.') + .boolean('check') .describe( 'force-exit', 'Forcibly exit the migration process on completion.' @@ -145,8 +147,12 @@ module.exports = function (internals, isModule) { internals.notransactions = internals.argv['non-transactional']; internals.dryRun = internals.argv['dry-run']; global.dryRun = internals.dryRun; + internals.check = internals.argv['check']; if (internals.dryRun) { log.info('dry run'); } + if (internals.check) { + log.info('check'); + } }; diff --git a/lib/migrator.js b/lib/migrator.js index 846440cb..02a62909 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -119,6 +119,40 @@ Migrator.prototype = { } }, + 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; @@ -180,6 +214,13 @@ Migrator.prototype = { 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); @@ -234,6 +275,13 @@ Migrator.prototype = { 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); diff --git a/test/integration/api_test.js b/test/integration/api_test.js index e997e04d..14524e53 100644 --- a/test/integration/api_test.js +++ b/test/integration/api_test.js @@ -168,6 +168,23 @@ lab.experiment('api', function () { } ); + lab.test( + 'should handle all check parameter variations properly', + + function () { + return Promise.resolve([ + [], // promise + [sinon.spy()], + [1, sinon.spy()], // targeted migration + [1], // promise targeted migration + [1, 'testscope', sinon.spy()], // scoped target + [1, 'testscope'] // promise scope target + ]) + .each(defaultExecParams('check')) + .each(spyCallback); + } + ); + lab.test( 'should handle all reset parameter variations properly', diff --git a/test/migrator_test.js b/test/migrator_test.js new file mode 100644 index 00000000..3ac29fc7 --- /dev/null +++ b/test/migrator_test.js @@ -0,0 +1,32 @@ +var Code = require('code'); +var Lab = require('lab'); +var proxyquire = require('proxyquire').noPreserveCache(); +var 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 = { + name: '20180330020329-thisMigrationIsCompleted' + }; + var uncompletedMigration = { + name: '20180330020330-thisMigrationIsNotCompleted' + }; + var Migrator = proxyquire('../lib/migrator.js', { + './migration': { + loadFromFilesystem: (migrationsDir, internals, cb) => { + return cb(null, [completedMigration, uncompletedMigration]); + }, + loadFromDatabase: (migrationsDir, driver, internals, cb) => { + return cb(null, [completedMigration]); + } + } + }); + Migrator.prototype.check(null, function (err, res) { + Code.expect(res.length).to.equal(1); + Code.expect(res[0].name).to.equal(uncompletedMigration.name); + done(err, res); + }); + }); + }); +}); From 0d18ac292aacd2e8c7de79114b0caf5657471f4e Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 10 Apr 2018 20:27:11 +0200 Subject: [PATCH 403/412] 0.11.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0eb1cfcf..1ec83446 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.10.7", + "version": "0.11.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 99f7a45d..fa9fcc29 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.10.7", + "version": "0.11.0", "engines": { "node": ">=0.6.0" }, From f2ea484f422f89e54c3ac28befe928b8b5e086f9 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 10 Apr 2018 20:27:59 +0200 Subject: [PATCH 404/412] add changelog Signed-off-by: Tobias Gurtzick --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88cfa5eb..6648a19b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [0.11.0](https://github.com/db-migrate/node-db-migrate/compare/v0.10.7...v0.11.0) (2018-04-10) + + +### Features + +* **check:** add check functionality to determine migrations to run ([93e9f18](https://github.com/db-migrate/node-db-migrate/commit/93e9f18)) + + + ## [0.10.7](https://github.com/db-migrate/node-db-migrate/compare/v0.10.6...v0.10.7) (2018-03-27) From b94db96ba7366241e65230a4f14227c2fd6edf55 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 11 Apr 2018 01:50:13 +0200 Subject: [PATCH 405/412] 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'); From aeca980e34cb02881296228f7d9715db255d17aa Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 11 Apr 2018 01:51:07 +0200 Subject: [PATCH 406/412] add changelog Signed-off-by: Tobias Gurtzick --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6648a19b..d53609bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [0.11.1](https://github.com/db-migrate/node-db-migrate/compare/v0.11.0...v0.11.1) (2018-04-10) + + +### Bug Fixes + +* **reset:** regression introduced in check functionality ([d8a735d](https://github.com/db-migrate/node-db-migrate/commit/d8a735d)), closes [#552](https://github.com/db-migrate/node-db-migrate/issues/552) + + + # [0.11.0](https://github.com/db-migrate/node-db-migrate/compare/v0.10.7...v0.11.0) (2018-04-10) From 86669d5bb8f7613f5f04d21c77fd407d0960824a Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Wed, 11 Apr 2018 01:50:59 +0200 Subject: [PATCH 407/412] 0.11.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ec83446..01b8fec3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "db-migrate", - "version": "0.11.0", + "version": "0.11.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index fa9fcc29..4a7ad5b5 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "programable", "api" ], - "version": "0.11.0", + "version": "0.11.1", "engines": { "node": ">=0.6.0" }, From b74369687a126062fcef68b57a7098f1cb78434f Mon Sep 17 00:00:00 2001 From: RandomSeeded Date: Wed, 11 Apr 2018 16:32:45 -0700 Subject: [PATCH 408/412] fix(check): fix check via API not passing results to the callback Signed-off-by: RandomSeeded --- lib/commands/on-complete.js | 5 +++-- test/on_complete_test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 test/on_complete_test.js diff --git a/lib/commands/on-complete.js b/lib/commands/on-complete.js index a78d921d..a0d0ad8d 100644 --- a/lib/commands/on-complete.js +++ b/lib/commands/on-complete.js @@ -1,9 +1,10 @@ var assert = require('assert'); var log = require('db-migrate-shared').log; -module.exports = function (migrator, internals, callback, originalErr) { +module.exports = function (migrator, internals, callback, originalErr, results) { if (typeof callback !== 'function') { originalErr = originalErr || callback; + results = results || originalErr; } migrator.driver.close(function (err) { @@ -22,7 +23,7 @@ module.exports = function (migrator, internals, callback, originalErr) { } if (typeof callback === 'function') { - callback(); + callback(null, results); } }); }; diff --git a/test/on_complete_test.js b/test/on_complete_test.js new file mode 100644 index 00000000..38f64b56 --- /dev/null +++ b/test/on_complete_test.js @@ -0,0 +1,27 @@ +var Code = require('code'); +var Lab = require('lab'); +var lab = (exports.lab = Lab.script()); +var onComplete = require('../lib/commands/on-complete'); + +lab.experiment('on-complete', function () { + lab.test('should invoke the callback with the results', function (done) { + var migratorMock = { + driver: { + close: function (cb) { + cb(); + } + } + }; + var internalsMock = { + argv: { } + }; + + var resultsPassedToCallback = 'callback should be invoked with results'; + var testCallback = function (err, res) { + Code.expect(err).to.equal(null); + Code.expect(res).to.equal(resultsPassedToCallback); + done(); + }; + onComplete(migratorMock, internalsMock, testCallback, null, resultsPassedToCallback); + }); +}); From 1b32dc593a553ebbea5ec945982fe5ecb4b6cdcd Mon Sep 17 00:00:00 2001 From: RandomSeeded Date: Mon, 30 Apr 2018 10:54:11 -0400 Subject: [PATCH 409/412] save --- api.js | 1 + index.js | 1 + lib/commands/check.js | 4 ++++ lib/migrator.js | 2 ++ 4 files changed, 8 insertions(+) diff --git a/api.js b/api.js index ccf3e973..fdaa66ae 100644 --- a/api.js +++ b/api.js @@ -228,6 +228,7 @@ dbmigrate.prototype = { }, check: function (specification, opts, callback) { + console.log('api check'); var executeCheck = load('check'); if (arguments.length > 0) { diff --git a/index.js b/index.js index f2eee0fe..8f1d0b2b 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,4 @@ +console.log('index.js'); require('pkginfo')(module, 'version'); // jshint ignore:line var fs = require('fs'); var path = require('path'); diff --git a/lib/commands/check.js b/lib/commands/check.js index 63891ff6..0948871d 100644 --- a/lib/commands/check.js +++ b/lib/commands/check.js @@ -4,6 +4,7 @@ var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); module.exports = function (internals, config, callback) { + console.log('executeCheck check.js'); migrationHook(internals) .then(function () { var Migrator = require('../migrator.js'); @@ -16,6 +17,8 @@ module.exports = function (internals, config, callback) { config: config.getCurrent().settings, internals: internals }, Migrator, function (err, migrator) { + console.log('err', err); + console.log('migrator', migrator); if (!assert(err, callback)) return; if (internals.locTitle) { @@ -29,6 +32,7 @@ module.exports = function (internals, config, callback) { if (!assert(err, callback)) return; log.verbose('migration table created'); + console.log('about to run migrator.check'); migrator.check(internals.argv, internals.onComplete.bind(this, migrator, internals, callback)); }); diff --git a/lib/migrator.js b/lib/migrator.js index 02a62909..27714e51 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -125,6 +125,7 @@ Migrator.prototype = { err, allMigrations ) { + console.log('allMigrations', allMigrations); if (err) { callback(err); return; @@ -135,6 +136,7 @@ Migrator.prototype = { self._driver, self.internals, function (err, completedMigrations) { + console.log('completedMigrations', completedMigrations); if (err) { callback(err); return; From 3e8fa31d10fab5097d8130b856985d032946abfc Mon Sep 17 00:00:00 2001 From: RandomSeeded Date: Mon, 14 May 2018 10:45:15 +0200 Subject: [PATCH 410/412] save --- lib/commands/check.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/commands/check.js b/lib/commands/check.js index 0948871d..17eeae97 100644 --- a/lib/commands/check.js +++ b/lib/commands/check.js @@ -28,6 +28,7 @@ module.exports = function (internals, config, callback) { internals.migrationsDir = migrator.migrationsDir; + console.log('creating migrations table', migrator.driver.createMigrationsTable); migrator.driver.createMigrationsTable(function (err) { if (!assert(err, callback)) return; log.verbose('migration table created'); From 67e53d368439537c52c103d251c036461e7e04c5 Mon Sep 17 00:00:00 2001 From: nate Date: Sun, 20 May 2018 12:15:34 -0400 Subject: [PATCH 411/412] updates --- lib/commands/check.js | 8 +- package-lock.json | 940 +++++++++++++++++++++--------------------- 2 files changed, 474 insertions(+), 474 deletions(-) diff --git a/lib/commands/check.js b/lib/commands/check.js index 17eeae97..18ca0f8e 100644 --- a/lib/commands/check.js +++ b/lib/commands/check.js @@ -17,8 +17,8 @@ module.exports = function (internals, config, callback) { config: config.getCurrent().settings, internals: internals }, Migrator, function (err, migrator) { - console.log('err', err); - console.log('migrator', migrator); + // console.log('err', err); + // console.log('migrator', migrator); if (!assert(err, callback)) return; if (internals.locTitle) { @@ -28,12 +28,12 @@ module.exports = function (internals, config, callback) { internals.migrationsDir = migrator.migrationsDir; - console.log('creating migrations table', migrator.driver.createMigrationsTable); + // console.log('creating migrations table', migrator.driver.createMigrationsTable); migrator.driver.createMigrationsTable(function (err) { if (!assert(err, callback)) return; log.verbose('migration table created'); - console.log('about to run migrator.check'); + // console.log('about to run migrator.check'); migrator.check(internals.argv, internals.onComplete.bind(this, migrator, internals, callback)); }); diff --git a/package-lock.json b/package-lock.json index 01b8fec3..fb6d59ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "^3.0.4" }, "dependencies": { "acorn": { @@ -42,10 +42,10 @@ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "ajv-keywords": { @@ -60,9 +60,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" } }, "amdefine": { @@ -95,7 +95,7 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "array-union": { @@ -104,7 +104,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { @@ -135,9 +135,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" }, "dependencies": { "chalk": { @@ -146,11 +146,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "strip-ansi": { @@ -159,7 +159,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } } } @@ -186,8 +186,8 @@ "integrity": "sha1-+a6fJugbQaMY9O4Ng2huSlwlB7k=", "dev": true, "requires": { - "hoek": "4.2.1", - "joi": "10.6.0" + "hoek": "4.x.x", + "joi": "10.x.x" } }, "brace-expansion": { @@ -195,7 +195,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" }, "dependencies": { @@ -224,7 +224,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "^0.2.0" } }, "callsites": { @@ -247,8 +247,8 @@ "dev": true, "optional": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" } }, "chalk": { @@ -257,9 +257,9 @@ "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.3.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "dependencies": { "ansi-styles": { @@ -268,7 +268,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "supports-color": { @@ -277,7 +277,7 @@ "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -300,7 +300,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "2.0.0" + "restore-cursor": "^2.0.0" } }, "cli-width": { @@ -316,8 +316,8 @@ "dev": true, "optional": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" }, "dependencies": { @@ -342,7 +342,7 @@ "integrity": "sha1-IJrRHQWvigwceq9pTZ+k0sfZW4U=", "dev": true, "requires": { - "hoek": "4.2.1" + "hoek": "4.x.x" } }, "color-convert": { @@ -351,7 +351,7 @@ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.1.1" } }, "color-name": { @@ -376,10 +376,10 @@ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-from": "1.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "contains-path": { @@ -400,9 +400,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.2", - "shebang-command": "1.2.0", - "which": "1.3.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "cycle": { @@ -416,7 +416,7 @@ "integrity": "sha512-dbJHFVYIY75vSOL3MD4qbpjilcwrYn7ZnTqsdA2AGs6w1mYugspfWEBea+uMgJVH/YsUFxw2AYPKRHCHUjhirw==", "dev": true, "requires": { - "bluebird": "3.5.1" + "bluebird": "^3.1.1" } }, "db-migrate-mysql": { @@ -425,10 +425,10 @@ "integrity": "sha1-TB1e8R9ZO1qPHxIkkIO+5xWnzKw=", "dev": true, "requires": { - "bluebird": "3.5.1", - "db-migrate-base": "1.5.3", - "moment": "2.22.0", - "mysql": "2.15.0" + "bluebird": "^3.2.1", + "db-migrate-base": "^1.2.5", + "moment": "^2.11.2", + "mysql": "^2.10.2" } }, "db-migrate-shared": { @@ -442,9 +442,9 @@ "integrity": "sha1-ox1nudNtz5lWSymLz9C5hx+2bmc=", "dev": true, "requires": { - "bluebird": "3.5.1", - "db-migrate-base": "1.5.3", - "sqlite3": "3.1.13" + "bluebird": "^3.1.1", + "db-migrate-base": "^1.2.5", + "sqlite3": "^3.1.4" } }, "debug": { @@ -484,13 +484,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.1", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" } }, "diff": { @@ -505,7 +505,7 @@ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "2.0.2" + "esutils": "^2.0.2" } }, "dotenv": { @@ -519,7 +519,7 @@ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "escape-string-regexp": { @@ -534,44 +534,44 @@ "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { - "ajv": "5.5.2", - "babel-code-frame": "6.26.0", - "chalk": "2.3.2", - "concat-stream": "1.6.2", - "cross-spawn": "5.1.0", - "debug": "3.1.0", - "doctrine": "2.1.0", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "1.0.0", - "espree": "3.5.4", - "esquery": "1.0.1", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.2", - "globals": "11.4.0", - "ignore": "3.3.7", - "imurmurhash": "0.1.4", - "inquirer": "3.3.0", - "is-resolvable": "1.1.0", - "js-yaml": "3.11.0", - "json-stable-stringify-without-jsonify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.5", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "7.0.0", - "progress": "2.0.0", - "regexpp": "1.1.0", - "require-uncached": "1.0.3", - "semver": "5.5.0", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", "table": "4.0.2", - "text-table": "0.2.0" + "text-table": "~0.2.0" }, "dependencies": { "debug": { @@ -603,8 +603,8 @@ "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, "requires": { - "debug": "2.6.9", - "resolve": "1.7.0" + "debug": "^2.6.9", + "resolve": "^1.5.0" } }, "eslint-module-utils": { @@ -613,8 +613,8 @@ "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, "requires": { - "debug": "2.6.9", - "pkg-dir": "1.0.0" + "debug": "^2.6.8", + "pkg-dir": "^1.0.0" } }, "eslint-plugin-hapi": { @@ -623,11 +623,11 @@ "integrity": "sha512-z1yUoSWArx6pXaC0FoWRFpqjbHn8QWonJiTVhJmiC14jOAT7FZKdKWCkhM4jQrgrkEK9YEv3p2HuzSf5dtWmuQ==", "dev": true, "requires": { - "hapi-capitalize-modules": "1.1.6", - "hapi-for-you": "1.0.0", - "hapi-no-var": "1.0.1", - "hapi-scope-start": "2.1.1", - "no-arrowception": "1.0.0" + "hapi-capitalize-modules": "1.x.x", + "hapi-for-you": "1.x.x", + "hapi-no-var": "1.x.x", + "hapi-scope-start": "2.x.x", + "no-arrowception": "1.x.x" } }, "eslint-plugin-import": { @@ -636,16 +636,16 @@ "integrity": "sha1-+gkIPVp1KI35xsfQn+EiVZhWVec=", "dev": true, "requires": { - "builtin-modules": "1.1.1", - "contains-path": "0.1.0", - "debug": "2.6.9", + "builtin-modules": "^1.1.1", + "contains-path": "^0.1.0", + "debug": "^2.6.8", "doctrine": "1.5.0", - "eslint-import-resolver-node": "0.3.2", - "eslint-module-utils": "2.2.0", - "has": "1.0.1", - "lodash": "4.17.5", - "minimatch": "3.0.4", - "read-pkg-up": "2.0.0" + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0" }, "dependencies": { "doctrine": { @@ -654,8 +654,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } } } @@ -666,9 +666,9 @@ "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, "requires": { - "ignore": "3.3.7", - "minimatch": "3.0.4", - "resolve": "1.7.0", + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", "semver": "5.3.0" }, "dependencies": { @@ -698,8 +698,8 @@ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "esrecurse": "4.2.1", - "estraverse": "4.2.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "eslint-visitor-keys": { @@ -714,8 +714,8 @@ "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "5.5.3", - "acorn-jsx": "3.0.1" + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" } }, "esprima": { @@ -730,7 +730,7 @@ "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "^4.0.0" } }, "esrecurse": { @@ -739,7 +739,7 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "^4.1.0" } }, "estraverse": { @@ -760,9 +760,9 @@ "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.21", - "tmp": "0.0.33" + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" } }, "eyes": { @@ -794,7 +794,7 @@ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5" + "escape-string-regexp": "^1.0.5" } }, "file-entry-cache": { @@ -803,8 +803,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, "fill-keys": { @@ -813,8 +813,8 @@ "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", "dev": true, "requires": { - "is-object": "1.0.1", - "merge-descriptors": "1.0.1" + "is-object": "~1.0.1", + "merge-descriptors": "~1.0.0" } }, "final-fs": { @@ -822,8 +822,8 @@ "resolved": "https://registry.npmjs.org/final-fs/-/final-fs-1.6.1.tgz", "integrity": "sha1-1tzZLvb+T+jAer1WjHE1YQ7eMjY=", "requires": { - "node-fs": "0.1.7", - "when": "2.0.1" + "node-fs": "~0.1.5", + "when": "~2.0.1" } }, "find-rc": { @@ -838,8 +838,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "flat-cache": { @@ -848,10 +848,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" } }, "fs.realpath": { @@ -876,12 +876,12 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "globals": { @@ -896,12 +896,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "graceful-fs": { @@ -916,10 +916,10 @@ "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" }, "dependencies": { "async": { @@ -934,7 +934,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -969,7 +969,7 @@ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.0.2" } }, "has-ansi": { @@ -978,7 +978,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-flag": { @@ -1010,7 +1010,7 @@ "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", "dev": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": "^2.1.0" } }, "ignore": { @@ -1035,8 +1035,8 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -1055,20 +1055,20 @@ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "3.1.0", - "chalk": "2.3.2", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.2.0", - "figures": "2.0.0", - "lodash": "4.17.5", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" } }, "is-arrayish": { @@ -1089,7 +1089,7 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, "is-fullwidth-code-point": { @@ -1116,7 +1116,7 @@ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.1" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { @@ -1125,7 +1125,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, "is-promise": { @@ -1175,10 +1175,10 @@ "integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==", "dev": true, "requires": { - "hoek": "4.2.1", - "isemail": "2.2.1", - "items": "2.1.1", - "topo": "2.0.2" + "hoek": "4.x.x", + "isemail": "2.x.x", + "items": "2.x.x", + "topo": "2.x.x" } }, "js-tokens": { @@ -1193,8 +1193,8 @@ "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "json-schema-traverse": { @@ -1209,7 +1209,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json-stable-stringify-without-jsonify": { @@ -1242,7 +1242,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } }, "lab": { @@ -1251,24 +1251,24 @@ "integrity": "sha512-IFnuYVRd6CtnFTFgUbjPCFrrCIked5BvGH/dX+/h+6pi3IrQrK21JsKy/J1CshEm6sMe980+oswtK8lZCusHSA==", "dev": true, "requires": { - "bossy": "3.0.4", - "code": "4.1.0", - "diff": "3.5.0", - "eslint": "4.19.1", - "eslint-config-hapi": "10.1.0", - "eslint-plugin-hapi": "4.1.0", - "espree": "3.5.4", - "find-rc": "3.0.1", - "handlebars": "4.0.11", - "hoek": "4.2.1", - "items": "2.1.1", - "json-stable-stringify": "1.0.1", - "json-stringify-safe": "5.0.1", - "mkdirp": "0.5.1", - "seedrandom": "2.4.3", - "source-map": "0.6.1", - "source-map-support": "0.4.18", - "supports-color": "4.4.0" + "bossy": "3.x.x", + "code": "4.1.x", + "diff": "3.5.x", + "eslint": "4.19.x", + "eslint-config-hapi": "10.x.x", + "eslint-plugin-hapi": "4.x.x", + "espree": "3.5.x", + "find-rc": "3.0.x", + "handlebars": "4.x.x", + "hoek": "4.x.x", + "items": "2.x.x", + "json-stable-stringify": "1.x.x", + "json-stringify-safe": "5.x.x", + "mkdirp": "0.5.x", + "seedrandom": "2.4.x", + "source-map": "0.6.x", + "source-map-support": "0.4.x", + "supports-color": "4.4.x" }, "dependencies": { "has-flag": { @@ -1283,7 +1283,7 @@ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^2.0.0" } } } @@ -1301,8 +1301,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "load-json-file": { @@ -1311,10 +1311,10 @@ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" } }, "locate-path": { @@ -1323,8 +1323,8 @@ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" }, "dependencies": { "path-exists": { @@ -1370,8 +1370,8 @@ "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "merge-descriptors": { @@ -1391,7 +1391,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -1469,11 +1469,11 @@ "integrity": "sha512-KPKb+wvETBiwb4eTwtR/OsA2+iijXP+VnlSFYJo3EHjm2yjek1NWxHOUQat3i7xNLm1Bm18UA5j5Wor0yO2GtA==", "dev": true, "requires": { - "@sinonjs/formatio": "2.0.0", - "just-extend": "1.1.27", - "lolex": "2.3.2", - "path-to-regexp": "1.7.0", - "text-encoding": "0.6.4" + "@sinonjs/formatio": "^2.0.0", + "just-extend": "^1.1.27", + "lolex": "^2.3.2", + "path-to-regexp": "^1.7.0", + "text-encoding": "^0.6.4" } }, "no-arrowception": { @@ -1493,10 +1493,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "2.6.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.3" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "object-assign": { @@ -1510,7 +1510,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -1519,7 +1519,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "^1.0.0" } }, "optimist": { @@ -1527,8 +1527,8 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" } }, "optionator": { @@ -1537,12 +1537,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" }, "dependencies": { "wordwrap": { @@ -1565,7 +1565,7 @@ "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", "dev": true, "requires": { - "p-try": "1.0.0" + "p-try": "^1.0.0" } }, "p-locate": { @@ -1574,7 +1574,7 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.2.0" + "p-limit": "^1.1.0" } }, "p-try": { @@ -1588,7 +1588,7 @@ "resolved": "https://registry.npmjs.org/parse-database-url/-/parse-database-url-0.3.0.tgz", "integrity": "sha1-NpZmMh6SfJreY838Gqr2+zdFPQ0=", "requires": { - "mongodb-uri": "0.9.7" + "mongodb-uri": ">= 0.9.7" } }, "parse-json": { @@ -1597,7 +1597,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.2.0" } }, "path-exists": { @@ -1606,7 +1606,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "^2.0.0" } }, "path-is-absolute": { @@ -1648,7 +1648,7 @@ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "pify": "2.3.0" + "pify": "^2.0.0" } }, "pify": { @@ -1669,7 +1669,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "pkg-dir": { @@ -1678,7 +1678,7 @@ "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { - "find-up": "1.1.2" + "find-up": "^1.0.0" } }, "pkginfo": { @@ -1715,12 +1715,12 @@ "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.0.0.tgz", "integrity": "sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=", "requires": { - "colors": "1.2.1", - "pkginfo": "0.4.1", - "read": "1.0.7", - "revalidator": "0.1.8", - "utile": "0.3.0", - "winston": "2.1.1" + "colors": "^1.1.2", + "pkginfo": "0.x.x", + "read": "1.0.x", + "revalidator": "0.1.x", + "utile": "0.3.x", + "winston": "2.1.x" } }, "proxyquire": { @@ -1729,9 +1729,9 @@ "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", "dev": true, "requires": { - "fill-keys": "1.0.2", - "module-not-found-error": "1.0.1", - "resolve": "1.1.7" + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.0", + "resolve": "~1.1.7" }, "dependencies": { "resolve": { @@ -1753,10 +1753,10 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz", "integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=", "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "deep-extend": { @@ -1776,7 +1776,7 @@ "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", "requires": { - "mute-stream": "0.0.7" + "mute-stream": "~0.0.4" } }, "read-pkg": { @@ -1785,9 +1785,9 @@ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" } }, "read-pkg-up": { @@ -1796,8 +1796,8 @@ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" }, "dependencies": { "find-up": { @@ -1806,7 +1806,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } } } @@ -1817,13 +1817,13 @@ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "regexpp": { @@ -1844,8 +1844,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" } }, "resolve": { @@ -1853,7 +1853,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.0.tgz", "integrity": "sha512-QdgZ5bjR1WAlpLaO5yHepFvC+o3rCr6wpfE2tpJNMkXdulf2jKomQBdNRQITF3ZKHNlT71syG98yQP03gasgnA==", "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "resolve-from": { @@ -1868,8 +1868,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" } }, "revalidator": { @@ -1884,7 +1884,7 @@ "dev": true, "optional": true, "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "rimraf": { @@ -1892,7 +1892,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "run-async": { @@ -1901,7 +1901,7 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "2.1.0" + "is-promise": "^2.1.0" } }, "rx-lite": { @@ -1916,7 +1916,7 @@ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "requires": { - "rx-lite": "4.0.8" + "rx-lite": "*" } }, "safe-buffer": { @@ -1954,7 +1954,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -1975,13 +1975,13 @@ "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "dev": true, "requires": { - "@sinonjs/formatio": "2.0.0", - "diff": "3.5.0", - "lodash.get": "4.4.2", - "lolex": "2.3.2", - "nise": "1.3.2", - "supports-color": "5.3.0", - "type-detect": "4.0.8" + "@sinonjs/formatio": "^2.0.0", + "diff": "^3.1.0", + "lodash.get": "^4.4.2", + "lolex": "^2.2.0", + "nise": "^1.2.0", + "supports-color": "^5.1.0", + "type-detect": "^4.0.5" }, "dependencies": { "supports-color": { @@ -1990,7 +1990,7 @@ "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -2001,7 +2001,7 @@ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0" + "is-fullwidth-code-point": "^2.0.0" } }, "source-map": { @@ -2016,7 +2016,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.6" }, "dependencies": { "source-map": { @@ -2033,8 +2033,8 @@ "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { @@ -2049,8 +2049,8 @@ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { @@ -2071,8 +2071,8 @@ "integrity": "sha512-JxXKPJnkZ6NuHRojq+g2WXWBt3M1G9sjZaYiHEWSTGijDM3cwju/0T2XbWqMXFmPqDgw+iB7zKQvnns4bvzXlw==", "dev": true, "requires": { - "nan": "2.7.0", - "node-pre-gyp": "0.6.38" + "nan": "~2.7.0", + "node-pre-gyp": "~0.6.38" }, "dependencies": { "abbrev": { @@ -2085,8 +2085,8 @@ "bundled": true, "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" } }, "ansi-regex": { @@ -2104,8 +2104,8 @@ "bundled": true, "dev": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.3" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "asn1": { @@ -2144,7 +2144,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "block-stream": { @@ -2152,7 +2152,7 @@ "bundled": true, "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "~2.0.0" } }, "boom": { @@ -2160,7 +2160,7 @@ "bundled": true, "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "brace-expansion": { @@ -2168,7 +2168,7 @@ "bundled": true, "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -2192,7 +2192,7 @@ "bundled": true, "dev": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "concat-map": { @@ -2215,7 +2215,7 @@ "bundled": true, "dev": true, "requires": { - "boom": "2.10.1" + "boom": "2.x.x" } }, "dashdash": { @@ -2223,7 +2223,7 @@ "bundled": true, "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -2262,7 +2262,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "extend": { @@ -2285,9 +2285,9 @@ "bundled": true, "dev": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" } }, "fs.realpath": { @@ -2300,10 +2300,10 @@ "bundled": true, "dev": true, "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" } }, "fstream-ignore": { @@ -2311,9 +2311,9 @@ "bundled": true, "dev": true, "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" + "fstream": "^1.0.0", + "inherits": "2", + "minimatch": "^3.0.0" } }, "gauge": { @@ -2321,14 +2321,14 @@ "bundled": true, "dev": true, "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "getpass": { @@ -2336,7 +2336,7 @@ "bundled": true, "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -2351,12 +2351,12 @@ "bundled": true, "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "graceful-fs": { @@ -2374,8 +2374,8 @@ "bundled": true, "dev": true, "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "ajv": "^4.9.1", + "har-schema": "^1.0.5" } }, "has-unicode": { @@ -2388,10 +2388,10 @@ "bundled": true, "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" } }, "hoek": { @@ -2404,9 +2404,9 @@ "bundled": true, "dev": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "inflight": { @@ -2414,8 +2414,8 @@ "bundled": true, "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -2433,7 +2433,7 @@ "bundled": true, "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-typedarray": { @@ -2467,7 +2467,7 @@ "bundled": true, "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json-stringify-safe": { @@ -2508,7 +2508,7 @@ "bundled": true, "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "~1.30.0" } }, "minimatch": { @@ -2516,7 +2516,7 @@ "bundled": true, "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -2543,15 +2543,15 @@ "dev": true, "requires": { "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.2", - "rc": "1.2.1", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.0.2", + "rc": "^1.1.7", "request": "2.81.0", - "rimraf": "2.6.2", - "semver": "5.4.1", - "tar": "2.2.1", - "tar-pack": "3.4.0" + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^2.2.1", + "tar-pack": "^3.4.0" } }, "nopt": { @@ -2559,8 +2559,8 @@ "bundled": true, "dev": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.4" + "abbrev": "1", + "osenv": "^0.1.4" } }, "npmlog": { @@ -2568,10 +2568,10 @@ "bundled": true, "dev": true, "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "number-is-nan": { @@ -2594,7 +2594,7 @@ "bundled": true, "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "os-homedir": { @@ -2612,8 +2612,8 @@ "bundled": true, "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "path-is-absolute": { @@ -2646,10 +2646,10 @@ "bundled": true, "dev": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { @@ -2664,13 +2664,13 @@ "bundled": true, "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "request": { @@ -2678,28 +2678,28 @@ "bundled": true, "dev": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.1.0" + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" } }, "rimraf": { @@ -2707,7 +2707,7 @@ "bundled": true, "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "safe-buffer": { @@ -2735,7 +2735,7 @@ "bundled": true, "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "sshpk": { @@ -2743,14 +2743,14 @@ "bundled": true, "dev": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" }, "dependencies": { "assert-plus": { @@ -2765,9 +2765,9 @@ "bundled": true, "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -2775,7 +2775,7 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "stringstream": { @@ -2788,7 +2788,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -2801,9 +2801,9 @@ "bundled": true, "dev": true, "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, "tar-pack": { @@ -2811,14 +2811,14 @@ "bundled": true, "dev": true, "requires": { - "debug": "2.6.9", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.3.3", - "rimraf": "2.6.2", - "tar": "2.2.1", - "uid-number": "0.0.6" + "debug": "^2.2.0", + "fstream": "^1.0.10", + "fstream-ignore": "^1.0.5", + "once": "^1.3.3", + "readable-stream": "^2.1.4", + "rimraf": "^2.5.1", + "tar": "^2.2.1", + "uid-number": "^0.0.6" } }, "tough-cookie": { @@ -2826,7 +2826,7 @@ "bundled": true, "dev": true, "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" } }, "tunnel-agent": { @@ -2834,7 +2834,7 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -2863,9 +2863,9 @@ "bundled": true, "dev": true, "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" }, "dependencies": { "assert-plus": { @@ -2880,7 +2880,7 @@ "bundled": true, "dev": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2" } }, "wrappy": { @@ -2901,7 +2901,7 @@ "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.5.4.tgz", "integrity": "sha1-G/a2soyW6u8mf01sRqWiUXpZnic=", "requires": { - "ssh2-streams": "0.1.20" + "ssh2-streams": "~0.1.15" } }, "ssh2-streams": { @@ -2909,9 +2909,9 @@ "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.1.20.tgz", "integrity": "sha1-URGNFUVV31Rp7h9n4M8efoosDjo=", "requires": { - "asn1": "0.2.3", - "semver": "5.5.0", - "streamsearch": "0.1.2" + "asn1": "~0.2.0", + "semver": "^5.1.0", + "streamsearch": "~0.1.2" } }, "stack-trace": { @@ -2930,8 +2930,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "string_decoder": { @@ -2940,7 +2940,7 @@ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -2949,7 +2949,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" }, "dependencies": { "ansi-regex": { @@ -2983,12 +2983,12 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "5.5.2", - "ajv-keywords": "2.1.1", - "chalk": "2.3.2", - "lodash": "4.17.5", + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", "slice-ansi": "1.0.0", - "string-width": "2.1.1" + "string-width": "^2.1.1" } }, "text-encoding": { @@ -3015,7 +3015,7 @@ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.2" } }, "topo": { @@ -3024,7 +3024,7 @@ "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", "dev": true, "requires": { - "hoek": "4.2.1" + "hoek": "4.x.x" } }, "tunnel-ssh": { @@ -3033,7 +3033,7 @@ "integrity": "sha512-CjBqboGvAbM7iXSX2F95kzoI+c2J81YkrHbyyo4SWNKCzU6w5LfEvXBCHu6PPriYaNvfhMKzD8bFf5Vl14YTtg==", "requires": { "debug": "2.6.9", - "lodash.defaults": "4.2.0", + "lodash.defaults": "^4.1.0", "ssh2": "0.5.4" } }, @@ -3043,7 +3043,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-detect": { @@ -3065,9 +3065,9 @@ "dev": true, "optional": true, "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" }, "dependencies": { "source-map": { @@ -3097,12 +3097,12 @@ "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", "integrity": "sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo=", "requires": { - "async": "0.9.2", - "deep-equal": "0.2.2", - "i": "0.3.6", - "mkdirp": "0.5.1", - "ncp": "1.0.1", - "rimraf": "2.6.2" + "async": "~0.9.0", + "deep-equal": "~0.2.1", + "i": "0.3.x", + "mkdirp": "0.x.x", + "ncp": "1.0.x", + "rimraf": "2.x.x" } }, "validate-npm-package-license": { @@ -3111,8 +3111,8 @@ "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "dev": true, "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, "when": { @@ -3126,7 +3126,7 @@ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "window-size": { @@ -3141,13 +3141,13 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz", "integrity": "sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4=", "requires": { - "async": "1.0.0", - "colors": "1.0.3", - "cycle": "1.0.3", - "eyes": "0.1.8", - "isstream": "0.1.2", - "pkginfo": "0.3.1", - "stack-trace": "0.0.10" + "async": "~1.0.0", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "pkginfo": "0.3.x", + "stack-trace": "0.0.x" }, "dependencies": { "async": { @@ -3183,7 +3183,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "yallist": { @@ -3199,9 +3199,9 @@ "dev": true, "optional": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" } } From 88d91266b382c257edc06a5780c570b9bb73eb47 Mon Sep 17 00:00:00 2001 From: nate Date: Mon, 21 May 2018 07:00:57 -0400 Subject: [PATCH 412/412] cleanup --- api.js | 1 - index.js | 1 - lib/commands/check.js | 5 ----- lib/migrator.js | 2 -- 4 files changed, 9 deletions(-) diff --git a/api.js b/api.js index fdaa66ae..ccf3e973 100644 --- a/api.js +++ b/api.js @@ -228,7 +228,6 @@ dbmigrate.prototype = { }, check: function (specification, opts, callback) { - console.log('api check'); var executeCheck = load('check'); if (arguments.length > 0) { diff --git a/index.js b/index.js index 8f1d0b2b..f2eee0fe 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,3 @@ -console.log('index.js'); require('pkginfo')(module, 'version'); // jshint ignore:line var fs = require('fs'); var path = require('path'); diff --git a/lib/commands/check.js b/lib/commands/check.js index 18ca0f8e..63891ff6 100644 --- a/lib/commands/check.js +++ b/lib/commands/check.js @@ -4,7 +4,6 @@ var assert = require('./helper/assert.js'); var migrationHook = require('./helper/migration-hook.js'); module.exports = function (internals, config, callback) { - console.log('executeCheck check.js'); migrationHook(internals) .then(function () { var Migrator = require('../migrator.js'); @@ -17,8 +16,6 @@ module.exports = function (internals, config, callback) { config: config.getCurrent().settings, internals: internals }, Migrator, function (err, migrator) { - // console.log('err', err); - // console.log('migrator', migrator); if (!assert(err, callback)) return; if (internals.locTitle) { @@ -28,12 +25,10 @@ module.exports = function (internals, config, callback) { internals.migrationsDir = migrator.migrationsDir; - // console.log('creating migrations table', migrator.driver.createMigrationsTable); migrator.driver.createMigrationsTable(function (err) { if (!assert(err, callback)) return; log.verbose('migration table created'); - // console.log('about to run migrator.check'); migrator.check(internals.argv, internals.onComplete.bind(this, migrator, internals, callback)); }); diff --git a/lib/migrator.js b/lib/migrator.js index 27714e51..02a62909 100644 --- a/lib/migrator.js +++ b/lib/migrator.js @@ -125,7 +125,6 @@ Migrator.prototype = { err, allMigrations ) { - console.log('allMigrations', allMigrations); if (err) { callback(err); return; @@ -136,7 +135,6 @@ Migrator.prototype = { self._driver, self.internals, function (err, completedMigrations) { - console.log('completedMigrations', completedMigrations); if (err) { callback(err); return;