knex-migrator 4.0.3 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -12
- package/lib/index.js +170 -194
- package/lib/utils.js +24 -11
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -6,14 +6,14 @@ A database migration tool for [knex.js](https://github.com/tgriesser/knex), whic
|
|
|
6
6
|
|
|
7
7
|
- [x] JS API
|
|
8
8
|
- [x] CLI Tool
|
|
9
|
-
- [x] Differentiation between database
|
|
9
|
+
- [x] Differentiation between database initialization and migration (Support for a database schema, [like we use in Ghost](https://github.com/TryGhost/Ghost/blob/1.16.2/core/server/data/schema/schema.js))
|
|
10
10
|
- [x] Support for database creation
|
|
11
11
|
- [x] Hooks
|
|
12
12
|
- [x] Rollback to latest version
|
|
13
13
|
- [x] Auto-Rollback on error
|
|
14
14
|
- [x] Database health check
|
|
15
15
|
- [x] Supports transactions
|
|
16
|
-
- [x] Full atomic, support for separate DML/DDL scripts (no autocommit)
|
|
16
|
+
- [x] Full atomic, support for separate DML/DDL scripts (no autocommit)
|
|
17
17
|
- [x] Migration lock
|
|
18
18
|
- [x] Full debug & pretty log support
|
|
19
19
|
- [x] Custom migration folder structure
|
|
@@ -36,8 +36,8 @@ Add me to your globals:
|
|
|
36
36
|
|
|
37
37
|
- Replicas are unsupported, because Knex.js [doesn't support them](https://github.com/tgriesser/knex/issues/2253).
|
|
38
38
|
- Sqlite does **not** support read locks by default. Read [here](https://github.com/TryGhost/knex-migrator/issues/87) why.
|
|
39
|
-
- [
|
|
40
|
-
- Don't mix DDL/DML statements in a migration script. In MySQL DDL statements use implicit commits.
|
|
39
|
+
- [Comparison](https://github.com/TryGhost/knex-migrator/issues/119) with other available migration tools.
|
|
40
|
+
- Don't mix DDL/DML statements in a migration script. In MySQL DDL statements use implicit commits.
|
|
41
41
|
- It's highly recommended to write both the `up` and the `down` function to ensure a full rollback.
|
|
42
42
|
- If your process dies while migrations are running, knex-migrator won't be able to release the migration lock.
|
|
43
43
|
To release to lock you can run `knex-migrator rollback`. **But** it's recommended to check your database first to see in which state it is.
|
|
@@ -73,7 +73,7 @@ Please take a look at [this real example](https://github.com/TryGhost/Ghost/blob
|
|
|
73
73
|
|
|
74
74
|
```
|
|
75
75
|
project/
|
|
76
|
-
migrations/
|
|
76
|
+
migrations/
|
|
77
77
|
hooks/
|
|
78
78
|
init/
|
|
79
79
|
index.js
|
|
@@ -88,9 +88,9 @@ project/
|
|
|
88
88
|
versions/
|
|
89
89
|
1.0/
|
|
90
90
|
1-add-events-table.js
|
|
91
|
-
2-normalise-settings.js
|
|
91
|
+
2-normalise-settings.js
|
|
92
92
|
2.0/
|
|
93
|
-
1-add-timestamps-columns.js
|
|
93
|
+
1-add-timestamps-columns.js
|
|
94
94
|
2.1/
|
|
95
95
|
1-remove-empty-strings.js
|
|
96
96
|
2-add-webhooks-table.js
|
|
@@ -199,7 +199,7 @@ Commands:
|
|
|
199
199
|
|
|
200
200
|
#### knex-migrator init
|
|
201
201
|
|
|
202
|
-
-
|
|
202
|
+
- Initializes your database based on your init scripts
|
|
203
203
|
- Creates the database if it was not created yet
|
|
204
204
|
|
|
205
205
|
##### Options
|
|
@@ -223,10 +223,10 @@ Commands:
|
|
|
223
223
|
##### Options
|
|
224
224
|
|
|
225
225
|
```bash
|
|
226
|
-
# The
|
|
226
|
+
# The version you would like to migrate to
|
|
227
227
|
--v
|
|
228
228
|
|
|
229
|
-
# Combo Feature to check whether the database was already
|
|
229
|
+
# Combo Feature to check whether the database was already initialized
|
|
230
230
|
--init
|
|
231
231
|
|
|
232
232
|
# Force the execution no matter which current version you are on
|
|
@@ -312,13 +312,13 @@ knexMigrator.reset
|
|
|
312
312
|
knexMigrator.isDatabaseOK()
|
|
313
313
|
.then(function() {
|
|
314
314
|
// database is OK
|
|
315
|
-
//
|
|
315
|
+
// initialization & migrations are not missing
|
|
316
316
|
})
|
|
317
317
|
.catch(function(err) {
|
|
318
318
|
if (err.code === 'DB_NOT_INITIALISED') {
|
|
319
319
|
return knexMigrator.init();
|
|
320
320
|
}
|
|
321
|
-
|
|
321
|
+
|
|
322
322
|
if (err.code === 'DB_NEEDS_MIGRATION') {
|
|
323
323
|
return knexMigrator.migrate();
|
|
324
324
|
}
|
package/lib/index.js
CHANGED
|
@@ -119,7 +119,7 @@ KnexMigrator.prototype.init = function init(options) {
|
|
|
119
119
|
}
|
|
120
120
|
})
|
|
121
121
|
.then(function () {
|
|
122
|
-
const initTasks = utils.
|
|
122
|
+
const initTasks = utils.listFiles(path.join(self.migrationPath, 'init'));
|
|
123
123
|
|
|
124
124
|
/**
|
|
125
125
|
* CASE 1: You can disable init completion manually
|
|
@@ -159,12 +159,12 @@ KnexMigrator.prototype.init = function init(options) {
|
|
|
159
159
|
// CASE: Run over all migration scripts and add the file name to the database.
|
|
160
160
|
return Promise.each(versionsToMigrateTo, function (versionToMigrateTo) {
|
|
161
161
|
let versionPath = path.join(self.migrationPath, self.subfolder, versionToMigrateTo);
|
|
162
|
-
let filesToMigrateTo = utils.
|
|
162
|
+
let filesToMigrateTo = utils.listFiles(versionPath) || [];
|
|
163
163
|
|
|
164
164
|
return Promise.each(filesToMigrateTo, function (fileToMigrateTo) {
|
|
165
165
|
// CASE: check if migration exists, do not insert twice
|
|
166
166
|
return transacting('migrations')
|
|
167
|
-
.where('name', fileToMigrateTo
|
|
167
|
+
.where('name', fileToMigrateTo)
|
|
168
168
|
.then(function (migrationExists) {
|
|
169
169
|
if (migrationExists.length) {
|
|
170
170
|
return Promise.resolve();
|
|
@@ -172,7 +172,7 @@ KnexMigrator.prototype.init = function init(options) {
|
|
|
172
172
|
|
|
173
173
|
return transacting('migrations')
|
|
174
174
|
.insert({
|
|
175
|
-
name: fileToMigrateTo
|
|
175
|
+
name: fileToMigrateTo,
|
|
176
176
|
version: versionToMigrateTo,
|
|
177
177
|
currentVersion: self.currentVersion
|
|
178
178
|
});
|
|
@@ -286,11 +286,10 @@ KnexMigrator.prototype.init = function init(options) {
|
|
|
286
286
|
* @param {Object} options - Custom options you can pass in (version, force, init, only, skip)
|
|
287
287
|
* @returns {Bluebird<any>}
|
|
288
288
|
*/
|
|
289
|
-
KnexMigrator.prototype.migrate = function migrate(options) {
|
|
289
|
+
KnexMigrator.prototype.migrate = async function migrate(options) {
|
|
290
290
|
options = options || {};
|
|
291
291
|
|
|
292
|
-
let
|
|
293
|
-
onlyVersion = options.version,
|
|
292
|
+
let onlyVersion = options.version,
|
|
294
293
|
force = options.force,
|
|
295
294
|
init = options.init,
|
|
296
295
|
onlyFile = options.only,
|
|
@@ -308,14 +307,11 @@ KnexMigrator.prototype.migrate = function migrate(options) {
|
|
|
308
307
|
|
|
309
308
|
// CASE: `--init` flag is passed. Combo feature.
|
|
310
309
|
if (init) {
|
|
311
|
-
|
|
312
|
-
.then(function () {
|
|
313
|
-
return self.migrate(_.omit(options, 'init'));
|
|
314
|
-
});
|
|
310
|
+
await this.init();
|
|
315
311
|
}
|
|
316
312
|
|
|
317
313
|
try {
|
|
318
|
-
hooks = require(path.join(
|
|
314
|
+
hooks = require(path.join(this.migrationPath, '/hooks/migrate'));
|
|
319
315
|
} catch (err) {
|
|
320
316
|
debug('Hook Error: ' + err.message);
|
|
321
317
|
debug('No hooks found, no problem.');
|
|
@@ -323,152 +319,130 @@ KnexMigrator.prototype.migrate = function migrate(options) {
|
|
|
323
319
|
|
|
324
320
|
this.connection = database.connect(this.dbConfig);
|
|
325
321
|
|
|
326
|
-
|
|
327
|
-
.
|
|
328
|
-
return migrations.run(self.connection);
|
|
329
|
-
})
|
|
330
|
-
.then(function () {
|
|
331
|
-
return locking.lock(self.connection);
|
|
332
|
-
})
|
|
333
|
-
.then(function () {
|
|
334
|
-
return self._integrityCheck({
|
|
335
|
-
force: force
|
|
336
|
-
});
|
|
337
|
-
})
|
|
338
|
-
.then(function (result) {
|
|
339
|
-
_.each(result, function (value, version) {
|
|
340
|
-
// CASE: Log which versions won't be executed based on the "only" flag
|
|
341
|
-
if (onlyVersion && version !== onlyVersion) {
|
|
342
|
-
debug('Do not execute: ' + version);
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
});
|
|
322
|
+
try {
|
|
323
|
+
await database.ensureConnectionWorks(this.connection);
|
|
346
324
|
|
|
347
|
-
|
|
348
|
-
// CASE: filter out versions which should not run
|
|
349
|
-
let containsVersion = _.find(result, function (obj, key) {
|
|
350
|
-
return key === onlyVersion;
|
|
351
|
-
});
|
|
325
|
+
await migrations.run(this.connection);
|
|
352
326
|
|
|
353
|
-
|
|
354
|
-
logging.warn('Cannot find requested version: ' + onlyVersion);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
327
|
+
await locking.lock(this.connection);
|
|
357
328
|
|
|
358
|
-
|
|
359
|
-
// CASE: compare files on disk with files in database
|
|
360
|
-
if (value.expected !== value.actual) {
|
|
361
|
-
debug('Need to execute migrations for: ' + version);
|
|
362
|
-
versionsToMigrate.push(version);
|
|
363
|
-
}
|
|
364
|
-
});
|
|
365
|
-
})
|
|
366
|
-
.then(function executeBeforeHook() {
|
|
367
|
-
if (!versionsToMigrate.length) {
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
329
|
+
const result = await this._integrityCheck({force});
|
|
370
330
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
})
|
|
378
|
-
.then(function executeMigrations() {
|
|
379
|
-
if (!versionsToMigrate.length) {
|
|
331
|
+
_.each(result, function (_value, version) {
|
|
332
|
+
// CASE: Log which versions won't be executed based on the "only" flag
|
|
333
|
+
if (onlyVersion && version !== onlyVersion) {
|
|
334
|
+
debug('Do not execute: ' + version);
|
|
380
335
|
return;
|
|
381
336
|
}
|
|
337
|
+
});
|
|
382
338
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
hooks: hooks
|
|
388
|
-
});
|
|
339
|
+
if (onlyVersion) {
|
|
340
|
+
// CASE: filter out versions which should not run
|
|
341
|
+
let containsVersion = _.find(result, function (_obj, key) {
|
|
342
|
+
return key === onlyVersion;
|
|
389
343
|
});
|
|
390
|
-
})
|
|
391
|
-
.then(function executeAfterHook() {
|
|
392
|
-
if (!versionsToMigrate.length) {
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
344
|
|
|
396
|
-
if (
|
|
397
|
-
|
|
398
|
-
return hooks.after({
|
|
399
|
-
connection: self.connection
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
})
|
|
403
|
-
.then(function () {
|
|
404
|
-
return locking.unlock(self.connection);
|
|
405
|
-
})
|
|
406
|
-
.catch(function (err) {
|
|
407
|
-
// CASE: Do not rollback if migrations are locked
|
|
408
|
-
if (err instanceof errors.MigrationsAreLockedError) {
|
|
409
|
-
throw err;
|
|
345
|
+
if (!containsVersion) {
|
|
346
|
+
logging.warn('Cannot find requested version: ' + onlyVersion);
|
|
410
347
|
}
|
|
348
|
+
}
|
|
411
349
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
350
|
+
_.each(result, function (value, version) {
|
|
351
|
+
// CASE: compare files on disk with files in database
|
|
352
|
+
if (value.expected !== value.actual) {
|
|
353
|
+
debug('Need to execute migrations for: ' + version);
|
|
354
|
+
versionsToMigrate.push(version);
|
|
415
355
|
}
|
|
356
|
+
});
|
|
416
357
|
|
|
417
|
-
|
|
418
|
-
if (
|
|
419
|
-
|
|
358
|
+
if (versionsToMigrate.length) {
|
|
359
|
+
if (hooks.before) {
|
|
360
|
+
debug('Before hook');
|
|
361
|
+
await hooks.before({
|
|
362
|
+
connection: this.connection
|
|
363
|
+
});
|
|
420
364
|
}
|
|
421
365
|
|
|
422
|
-
|
|
423
|
-
debug(`Task failed: ${err.context.name}`);
|
|
424
|
-
}
|
|
366
|
+
logging.info('Running migrations.');
|
|
425
367
|
|
|
426
|
-
|
|
368
|
+
for (const versionToMigrate of versionsToMigrate) {
|
|
369
|
+
try {
|
|
370
|
+
await this._migrateTo({
|
|
371
|
+
version: versionToMigrate,
|
|
372
|
+
only: onlyFile,
|
|
373
|
+
hooks: hooks
|
|
374
|
+
});
|
|
375
|
+
} catch (err) {
|
|
376
|
+
// CASE: Do not rollback if migrations are locked
|
|
377
|
+
if (err instanceof errors.MigrationsAreLockedError) {
|
|
378
|
+
throw err;
|
|
379
|
+
}
|
|
427
380
|
|
|
428
|
-
|
|
381
|
+
// CASE: Do not rollback migration scripts, if lock error
|
|
382
|
+
if (err instanceof errors.LockError) {
|
|
383
|
+
throw err;
|
|
384
|
+
}
|
|
429
385
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
throw err;
|
|
435
|
-
}).catch(function (innerErr) {
|
|
436
|
-
if (errors.utils.isIgnitionError(innerErr)) {
|
|
437
|
-
throw err;
|
|
438
|
-
}
|
|
386
|
+
// CASE: ETIMEDOUT, ENOTFOUND
|
|
387
|
+
if (err instanceof errors.DatabaseError) {
|
|
388
|
+
throw err;
|
|
389
|
+
}
|
|
439
390
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
context: `OuterError: ${err.message}`
|
|
444
|
-
});
|
|
445
|
-
}).finally(function () {
|
|
446
|
-
return locking.unlock(self.connection);
|
|
447
|
-
});
|
|
448
|
-
}).finally(function () {
|
|
449
|
-
let ops = [];
|
|
391
|
+
if (err.context && err.context.name) {
|
|
392
|
+
debug(`Task failed: ${err.context.name}`);
|
|
393
|
+
}
|
|
450
394
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
395
|
+
logging.info(`Rolling back: ${err.message}.`);
|
|
396
|
+
|
|
397
|
+
const versionsMigrated = versionsToMigrate.slice(
|
|
398
|
+
0,
|
|
399
|
+
versionsToMigrate.indexOf(versionToMigrate) + 1
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
versionsMigrated.reverse();
|
|
403
|
+
|
|
404
|
+
try {
|
|
405
|
+
for (const versionMigrated of versionsMigrated) {
|
|
406
|
+
await this._rollback({version: versionMigrated, task: err.context});
|
|
407
|
+
}
|
|
408
|
+
logging.info(`Rollback was successful.`);
|
|
409
|
+
throw err;
|
|
410
|
+
} catch (innerErr) {
|
|
411
|
+
if (errors.utils.isIgnitionError(innerErr)) {
|
|
412
|
+
throw err;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
throw new errors.RollbackError({
|
|
416
|
+
message: innerErr.message,
|
|
417
|
+
err: innerErr,
|
|
418
|
+
context: `OuterError: ${err.message}`
|
|
419
|
+
});
|
|
420
|
+
} finally {
|
|
421
|
+
await locking.unlock(this.connection);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
458
424
|
}
|
|
459
425
|
|
|
460
|
-
|
|
461
|
-
debug('
|
|
462
|
-
|
|
463
|
-
.
|
|
464
|
-
|
|
465
|
-
|
|
426
|
+
if (hooks.after) {
|
|
427
|
+
debug('After hook');
|
|
428
|
+
await hooks.after({
|
|
429
|
+
connection: this.connection
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
await locking.unlock(this.connection);
|
|
434
|
+
} finally {
|
|
435
|
+
if (hooks.shutdown) {
|
|
436
|
+
debug('Shutdown hook');
|
|
437
|
+
await hooks.shutdown({
|
|
438
|
+
executedFromShell: this.executedFromShell
|
|
466
439
|
});
|
|
440
|
+
}
|
|
467
441
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
442
|
+
debug('Destroy connection');
|
|
443
|
+
await this.connection.destroy();
|
|
444
|
+
debug('Destroyed connection');
|
|
445
|
+
}
|
|
472
446
|
};
|
|
473
447
|
|
|
474
448
|
/**
|
|
@@ -1045,8 +1019,8 @@ KnexMigrator.prototype._migrateTo = function _migrateTo(options) {
|
|
|
1045
1019
|
throw new errors.MigrationScriptError({
|
|
1046
1020
|
message: 'Field length of %field% in %table% is too long!'.replace('%field%', field).replace('%table%', table),
|
|
1047
1021
|
context: 'This usually happens if your database encoding is utf8mb4.\n' +
|
|
1048
|
-
|
|
1049
|
-
|
|
1022
|
+
'All unique fields and indexes must be lower than 191 characters.\n' +
|
|
1023
|
+
'Please correct your field length and reset your database with knex-migrator reset.\n',
|
|
1050
1024
|
help: 'Read more here: https://github.com/TryGhost/knex-migrator/issues/51\n',
|
|
1051
1025
|
err: err
|
|
1052
1026
|
});
|
|
@@ -1132,7 +1106,6 @@ KnexMigrator.prototype._integrityCheck = function _integrityCheck(options) {
|
|
|
1132
1106
|
subfolder = this.subfolder,
|
|
1133
1107
|
force = options.force,
|
|
1134
1108
|
folders = [],
|
|
1135
|
-
operations = {},
|
|
1136
1109
|
toReturn = {},
|
|
1137
1110
|
futureVersions = [];
|
|
1138
1111
|
|
|
@@ -1148,29 +1121,69 @@ KnexMigrator.prototype._integrityCheck = function _integrityCheck(options) {
|
|
|
1148
1121
|
// ignore
|
|
1149
1122
|
}
|
|
1150
1123
|
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1124
|
+
return this
|
|
1125
|
+
.connection('migrations')
|
|
1126
|
+
.select('version')
|
|
1127
|
+
.count('version', {as: 'c'})
|
|
1128
|
+
.groupBy('version')
|
|
1129
|
+
.then((dbMigrations) => {
|
|
1130
|
+
_.each(folders, function (folder) {
|
|
1131
|
+
// CASE: versions/1.1-members or versions/2.0-payments
|
|
1132
|
+
if (folder !== 'init') {
|
|
1133
|
+
try {
|
|
1134
|
+
folder = folder.match(/([\d._]+)/)[0];
|
|
1135
|
+
} catch (err) {
|
|
1136
|
+
logging.warn('Cannot parse folder name.');
|
|
1137
|
+
logging.warn('Ignore Folder: ' + folder);
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// CASE:
|
|
1143
|
+
// if your current version is 1.0 and you add migration scripts for the next version 1.1
|
|
1144
|
+
// we won't execute them until your current version changes to 1.1 or until you force KM to migrate to it
|
|
1145
|
+
if (self.currentVersion && !force) {
|
|
1146
|
+
if (utils.isGreaterThanVersion({smallerVersion: self.currentVersion, greaterVersion: folder})) {
|
|
1147
|
+
futureVersions.push(folder);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1162
1150
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1151
|
+
let actual = 0;
|
|
1152
|
+
let expected;
|
|
1153
|
+
|
|
1154
|
+
const migrationCount = dbMigrations.find(m => m.version === folder);
|
|
1155
|
+
if (migrationCount) {
|
|
1156
|
+
actual = migrationCount.c;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
if (folder !== 'init') {
|
|
1160
|
+
expected = utils.listFiles(path.join(self.migrationPath, subfolder, folder)).length;
|
|
1161
|
+
} else {
|
|
1162
|
+
expected = utils.listFiles(path.join(self.migrationPath, folder)).length;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
debug('Version ' + folder + ' expected: ' + expected);
|
|
1166
|
+
debug('Version ' + folder + ' actual: ' + actual);
|
|
1167
|
+
|
|
1168
|
+
toReturn[folder] = {
|
|
1169
|
+
expected: expected,
|
|
1170
|
+
actual: actual
|
|
1171
|
+
};
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1174
|
+
// CASE: ensure that either you have to run `migrate --force` or they ran already
|
|
1175
|
+
if (futureVersions.length) {
|
|
1176
|
+
_.each(futureVersions, function (futureVersion) {
|
|
1177
|
+
if (toReturn[futureVersion].actual !== toReturn[futureVersion].expected) {
|
|
1178
|
+
logging.warn('knex-migrator is skipping ' + futureVersion);
|
|
1179
|
+
logging.warn('Current version in MigratorConfig.js is smaller then requested version, use --force to proceed!');
|
|
1180
|
+
logging.warn('Please run `knex-migrator migrate --v ' + futureVersion + ' --force` to proceed!');
|
|
1181
|
+
delete toReturn[futureVersion];
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1169
1184
|
}
|
|
1170
|
-
}
|
|
1171
1185
|
|
|
1172
|
-
|
|
1173
|
-
version: folder
|
|
1186
|
+
return toReturn;
|
|
1174
1187
|
}).catch(function onMigrationsLookupError(err) {
|
|
1175
1188
|
// CASE: no database selected (database.connection.database="")
|
|
1176
1189
|
if (err.errno === 1046) {
|
|
@@ -1199,43 +1212,6 @@ KnexMigrator.prototype._integrityCheck = function _integrityCheck(options) {
|
|
|
1199
1212
|
|
|
1200
1213
|
throw err;
|
|
1201
1214
|
});
|
|
1202
|
-
});
|
|
1203
|
-
|
|
1204
|
-
return Promise.props(operations)
|
|
1205
|
-
.then(function (result) {
|
|
1206
|
-
_.each(result, function (value, version) {
|
|
1207
|
-
let actual = value.length,
|
|
1208
|
-
expected = actual;
|
|
1209
|
-
|
|
1210
|
-
if (version !== 'init') {
|
|
1211
|
-
expected = utils.readTasks(path.join(self.migrationPath, subfolder, version)).length;
|
|
1212
|
-
} else {
|
|
1213
|
-
expected = utils.readTasks(path.join(self.migrationPath, version)).length;
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
debug('Version ' + version + ' expected: ' + expected);
|
|
1217
|
-
debug('Version ' + version + ' actual: ' + actual);
|
|
1218
|
-
|
|
1219
|
-
toReturn[version] = {
|
|
1220
|
-
expected: expected,
|
|
1221
|
-
actual: actual
|
|
1222
|
-
};
|
|
1223
|
-
});
|
|
1224
|
-
|
|
1225
|
-
// CASE: ensure that either you have to run `migrate --force` or they ran already
|
|
1226
|
-
if (futureVersions.length) {
|
|
1227
|
-
_.each(futureVersions, function (futureVersion) {
|
|
1228
|
-
if (toReturn[futureVersion].actual !== toReturn[futureVersion].expected) {
|
|
1229
|
-
logging.warn('knex-migrator is skipping ' + futureVersion);
|
|
1230
|
-
logging.warn('Current version in MigratorConfig.js is smaller then requested version, use --force to proceed!');
|
|
1231
|
-
logging.warn('Please run `knex-migrator migrate --v ' + futureVersion + ' --force` to proceed!');
|
|
1232
|
-
delete toReturn[futureVersion];
|
|
1233
|
-
}
|
|
1234
|
-
});
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
return toReturn;
|
|
1238
|
-
});
|
|
1239
1215
|
};
|
|
1240
1216
|
|
|
1241
1217
|
module.exports = KnexMigrator;
|
package/lib/utils.js
CHANGED
|
@@ -46,15 +46,13 @@ module.exports.loadConfig = function loadConfig(options) {
|
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
* @description
|
|
50
|
-
* It returns an Array of migration files including it's up/down hooks, config and the name.
|
|
49
|
+
* @description List all migration files from disk based on a path.
|
|
51
50
|
*
|
|
52
51
|
* @param absolutePath
|
|
53
52
|
* @returns {Array}
|
|
54
53
|
*/
|
|
55
|
-
exports.
|
|
56
|
-
let files = []
|
|
57
|
-
tasks = [];
|
|
54
|
+
exports.listFiles = function listFiles(absolutePath) {
|
|
55
|
+
let files = [];
|
|
58
56
|
|
|
59
57
|
try {
|
|
60
58
|
files = fs.readdirSync(absolutePath);
|
|
@@ -65,13 +63,28 @@ exports.readTasks = function readTasks(absolutePath) {
|
|
|
65
63
|
});
|
|
66
64
|
}
|
|
67
65
|
|
|
68
|
-
|
|
66
|
+
files = files.filter(function (file) {
|
|
69
67
|
// CASE: ignore dot files
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
return !file.match(/^\./);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
debug(files);
|
|
72
|
+
return files;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @description Reads all migration files from disk based on a path.
|
|
77
|
+
* It returns an Array of migration files including it's up/down hooks, config and the name.
|
|
78
|
+
*
|
|
79
|
+
* @param absolutePath
|
|
80
|
+
* @returns {Array}
|
|
81
|
+
*/
|
|
82
|
+
exports.readTasks = function readTasks(absolutePath) {
|
|
83
|
+
let tasks = [];
|
|
84
|
+
|
|
85
|
+
const files = exports.listFiles(absolutePath);
|
|
74
86
|
|
|
87
|
+
_.each(files, function (file) {
|
|
75
88
|
let executeFn = require(path.join(absolutePath, file));
|
|
76
89
|
|
|
77
90
|
try {
|
|
@@ -92,7 +105,7 @@ exports.readTasks = function readTasks(absolutePath) {
|
|
|
92
105
|
}
|
|
93
106
|
});
|
|
94
107
|
|
|
95
|
-
debug(
|
|
108
|
+
debug(tasks);
|
|
96
109
|
return tasks;
|
|
97
110
|
};
|
|
98
111
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knex-migrator",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"description": "Database migrations with knex.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ghost",
|
|
@@ -44,18 +44,18 @@
|
|
|
44
44
|
"knex-migrator-rollback": "./bin/knex-migrator-rollback"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|
|
47
|
-
"node": "^
|
|
47
|
+
"node": "^12.22.1 || ^14.17.0 || ^16.13.0"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"bluebird": "3.7.2",
|
|
51
51
|
"commander": "5.1.0",
|
|
52
52
|
"compare-ver": "2.0.2",
|
|
53
|
-
"debug": "4.3.
|
|
54
|
-
"ghost-ignition": "4.6.
|
|
53
|
+
"debug": "4.3.2",
|
|
54
|
+
"ghost-ignition": "4.6.3",
|
|
55
55
|
"knex": "0.21.19",
|
|
56
56
|
"lodash": "4.17.21",
|
|
57
57
|
"moment": "2.24.0",
|
|
58
|
-
"nconf": "0.11.
|
|
58
|
+
"nconf": "0.11.3",
|
|
59
59
|
"resolve": "1.20.0"
|
|
60
60
|
},
|
|
61
61
|
"files": [
|