Skip to content

Commit e2d25db

Browse files
author
RandomSeeded
committed
feat(check): add check functionality to determine migrations to run
Signed-off-by: RandomSeeded <[email protected]>
1 parent 5ee386b commit e2d25db

File tree

6 files changed

+140
-3
lines changed

6 files changed

+140
-3
lines changed

api.js

+25
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,31 @@ dbmigrate.prototype = {
225225
).asCallback(callback);
226226
},
227227

228+
check: function (specification, opts, callback) {
229+
var executeCheck = load('check');
230+
231+
if (arguments.length > 0) {
232+
if (typeof specification === 'number') {
233+
this.internals.argv.count = arguments[0];
234+
} else if (typeof specification === 'function') {
235+
callback = specification;
236+
}
237+
238+
if (typeof opts === 'string') {
239+
this.internals.migrationMode = opts;
240+
this.internals.matching = opts;
241+
} else if (typeof opts === 'function') {
242+
callback = opts;
243+
}
244+
}
245+
246+
return Promise.fromCallback(
247+
function (callback) {
248+
executeCheck(this.internals, this.config, callback);
249+
}.bind(this)
250+
).asCallback(callback);
251+
},
252+
228253
/**
229254
* Executes up a given number of migrations or a specific one.
230255
*

lib/commands/check.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
var path = require('path');
2+
var log = require('db-migrate-shared').log;
3+
var assert = require('./helper/assert.js');
4+
var migrationHook = require('./helper/migration-hook.js');
5+
6+
module.exports = function (internals, config, callback) {
7+
migrationHook(internals)
8+
.then(function () {
9+
var Migrator = require('../migrator.js');
10+
var index = require('../../connect');
11+
12+
if (!internals.argv.count) {
13+
internals.argv.count = Number.MAX_VALUE;
14+
}
15+
index.connect({
16+
config: config.getCurrent().settings,
17+
internals: internals
18+
}, Migrator, function (err, migrator) {
19+
if (!assert(err, callback)) return;
20+
21+
if (internals.locTitle) {
22+
migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'],
23+
internals.locTitle);
24+
} else { migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); }
25+
26+
internals.migrationsDir = migrator.migrationsDir;
27+
28+
migrator.driver.createMigrationsTable(function (err) {
29+
if (!assert(err, callback)) return;
30+
log.verbose('migration table created');
31+
32+
migrator.check(internals.argv, internals.onComplete.bind(this,
33+
migrator, internals, callback));
34+
});
35+
});
36+
});
37+
};

lib/commands/run.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function run (internals, config) {
4242
break;
4343
case 'up':
4444
case 'down':
45+
case 'check':
4546
case 'reset':
4647
if (action === 'reset') internals.argv.count = Number.MAX_VALUE;
4748

@@ -62,9 +63,12 @@ function run (internals, config) {
6263
if (action === 'up') {
6364
var executeUp = load('up');
6465
executeUp(internals, config);
65-
} else {
66+
} else if (action === 'down') {
6667
var executeDown = load('down');
6768
executeDown(internals, config);
69+
} else {
70+
var executeCheck = load('check');
71+
executeCheck(internals, config);
6872
}
6973
break;
7074

@@ -104,7 +108,7 @@ function run (internals, config) {
104108
);
105109
} else {
106110
log.error(
107-
'Invalid Action: Must be [up|down|create|reset|sync|' +
111+
'Invalid Action: Must be [up|down|check|create|reset|sync|' +
108112
'db|transition].'
109113
);
110114
optimist.showHelp();

lib/commands/set-default-argv.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module.exports = function (internals, isModule) {
2222
internals.argv = optimist
2323
.default(defaultConfig)
2424
.usage(
25-
'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' +
25+
'Usage: db-migrate [up|down|check|reset|sync|create|db|transition] ' +
2626
'[[dbname/]migrationName|all] [options]'
2727
)
2828
.describe(
@@ -42,6 +42,8 @@ module.exports = function (internals, isModule) {
4242
.string('c')
4343
.describe('dry-run', "Prints the SQL but doesn't run it.")
4444
.boolean('dry-run')
45+
.describe('check', 'Prints the migrations to be run without running them.')
46+
.boolean('check')
4547
.describe(
4648
'force-exit',
4749
'Forcibly exit the migration process on completion.'
@@ -144,8 +146,12 @@ module.exports = function (internals, isModule) {
144146
internals.notransactions = internals.argv['non-transactional'];
145147
internals.dryRun = internals.argv['dry-run'];
146148
global.dryRun = internals.dryRun;
149+
internals.check = internals.argv['check'];
147150

148151
if (internals.dryRun) {
149152
log.info('dry run');
150153
}
154+
if (internals.check) {
155+
log.info('check');
156+
}
151157
};

lib/migrator.js

+48
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,40 @@ Migrator.prototype = {
119119
}
120120
},
121121

122+
check: function (funcOrOpts, callback) {
123+
var self = this;
124+
Migration.loadFromFilesystem(self.migrationsDir, self.internals, function (
125+
err,
126+
allMigrations
127+
) {
128+
if (err) {
129+
callback(err);
130+
return;
131+
}
132+
133+
Migration.loadFromDatabase(
134+
self.migrationsDir,
135+
self._driver,
136+
self.internals,
137+
function (err, completedMigrations) {
138+
if (err) {
139+
callback(err);
140+
return;
141+
}
142+
143+
// Requires pr to export filterCompleted from db-migrate-shared
144+
var toRun = dbmUtil.filterCompleted(
145+
allMigrations,
146+
completedMigrations
147+
);
148+
149+
log.info('Migrations to run:', toRun.map(migration => migration.name));
150+
callback(null, toRun);
151+
}
152+
);
153+
});
154+
},
155+
122156
sync: function (funcOrOpts, callback) {
123157
var self = this;
124158

@@ -180,6 +214,13 @@ Migrator.prototype = {
180214
return;
181215
}
182216

217+
if (self.internals.check) {
218+
var toRunNames = toRun.map(migration => migration.name);
219+
log.info('Migrations to run:', toRunNames);
220+
callback(null, toRunNames);
221+
return;
222+
}
223+
183224
return Promise.resolve(toRun)
184225
.each(function (migration) {
185226
log.verbose('preparing to run up migration:', migration.name);
@@ -234,6 +275,13 @@ Migrator.prototype = {
234275
return;
235276
}
236277

278+
if (self.internals.check) {
279+
var toRunNames = toRun.map(migration => migration.name);
280+
log.info('Migrations to run:', toRunNames);
281+
callback(null, toRunNames);
282+
return;
283+
}
284+
237285
return Promise.resolve(toRun)
238286
.each(function (migration) {
239287
log.verbose('preparing to run down migration:', migration.name);

test/integration/api_test.js

+17
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,23 @@ lab.experiment('api', function () {
148148
}
149149
);
150150

151+
lab.test(
152+
'should handle all check parameter variations properly',
153+
154+
function () {
155+
return Promise.resolve([
156+
[], // promise
157+
[sinon.spy()],
158+
[1, sinon.spy()], // targeted migration
159+
[1], // promise targeted migration
160+
[1, 'testscope', sinon.spy()], // scoped target
161+
[1, 'testscope'] // promise scope target
162+
])
163+
.each(defaultExecParams('check'))
164+
.each(spyCallback);
165+
}
166+
);
167+
151168
lab.test(
152169
'should handle all reset parameter variations properly',
153170

0 commit comments

Comments
 (0)