knex-migrator 4.0.5 → 4.1.3

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.
Files changed (2) hide show
  1. package/lib/index.js +126 -149
  2. package/package.json +2 -2
package/lib/index.js CHANGED
@@ -155,30 +155,33 @@ KnexMigrator.prototype.init = function init(options) {
155
155
  throw err;
156
156
  }
157
157
 
158
- return database.createTransaction(self.connection, function (transacting) {
158
+ return database.createTransaction(self.connection, async function (transacting) {
159
+ const existingMigrations = await transacting('migrations').select('name');
160
+ const existingMigrationsNames = existingMigrations.map(m => m.name);
161
+ const migrationsToAdd = [];
162
+
159
163
  // CASE: Run over all migration scripts and add the file name to the database.
160
- return Promise.each(versionsToMigrateTo, function (versionToMigrateTo) {
164
+ for (const versionToMigrateTo of versionsToMigrateTo) {
161
165
  let versionPath = path.join(self.migrationPath, self.subfolder, versionToMigrateTo);
162
166
  let filesToMigrateTo = utils.listFiles(versionPath) || [];
163
167
 
164
- return Promise.each(filesToMigrateTo, function (fileToMigrateTo) {
165
- // CASE: check if migration exists, do not insert twice
166
- return transacting('migrations')
167
- .where('name', fileToMigrateTo)
168
- .then(function (migrationExists) {
169
- if (migrationExists.length) {
170
- return Promise.resolve();
171
- }
172
-
173
- return transacting('migrations')
174
- .insert({
175
- name: fileToMigrateTo,
176
- version: versionToMigrateTo,
177
- currentVersion: self.currentVersion
178
- });
179
- });
180
- });
181
- });
168
+ // CASE: check if migration exists, do not insert twice
169
+ for (const name of filesToMigrateTo) {
170
+ if (existingMigrationsNames.includes(name)) {
171
+ continue;
172
+ }
173
+
174
+ migrationsToAdd.push({
175
+ name,
176
+ version: versionToMigrateTo,
177
+ currentVersion: self.currentVersion
178
+ });
179
+ }
180
+ }
181
+
182
+ await self.connection
183
+ .batchInsert('migrations', migrationsToAdd)
184
+ .transacting(transacting);
182
185
  });
183
186
  })
184
187
  .then(function () {
@@ -286,11 +289,10 @@ KnexMigrator.prototype.init = function init(options) {
286
289
  * @param {Object} options - Custom options you can pass in (version, force, init, only, skip)
287
290
  * @returns {Bluebird<any>}
288
291
  */
289
- KnexMigrator.prototype.migrate = function migrate(options) {
292
+ KnexMigrator.prototype.migrate = async function migrate(options) {
290
293
  options = options || {};
291
294
 
292
- let self = this,
293
- onlyVersion = options.version,
295
+ let onlyVersion = options.version,
294
296
  force = options.force,
295
297
  init = options.init,
296
298
  onlyFile = options.only,
@@ -308,14 +310,11 @@ KnexMigrator.prototype.migrate = function migrate(options) {
308
310
 
309
311
  // CASE: `--init` flag is passed. Combo feature.
310
312
  if (init) {
311
- return this.init()
312
- .then(function () {
313
- return self.migrate(_.omit(options, 'init'));
314
- });
313
+ await this.init();
315
314
  }
316
315
 
317
316
  try {
318
- hooks = require(path.join(self.migrationPath, '/hooks/migrate'));
317
+ hooks = require(path.join(this.migrationPath, '/hooks/migrate'));
319
318
  } catch (err) {
320
319
  debug('Hook Error: ' + err.message);
321
320
  debug('No hooks found, no problem.');
@@ -323,152 +322,130 @@ KnexMigrator.prototype.migrate = function migrate(options) {
323
322
 
324
323
  this.connection = database.connect(this.dbConfig);
325
324
 
326
- return database.ensureConnectionWorks(this.connection)
327
- .then(function () {
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
- });
325
+ try {
326
+ await database.ensureConnectionWorks(this.connection);
346
327
 
347
- if (onlyVersion) {
348
- // CASE: filter out versions which should not run
349
- let containsVersion = _.find(result, function (obj, key) {
350
- return key === onlyVersion;
351
- });
328
+ await migrations.run(this.connection);
352
329
 
353
- if (!containsVersion) {
354
- logging.warn('Cannot find requested version: ' + onlyVersion);
355
- }
330
+ await locking.lock(this.connection);
331
+
332
+ const result = await this._integrityCheck({force});
333
+
334
+ _.each(result, function (_value, version) {
335
+ // CASE: Log which versions won't be executed based on the "only" flag
336
+ if (onlyVersion && version !== onlyVersion) {
337
+ debug('Do not execute: ' + version);
338
+ return;
356
339
  }
340
+ });
357
341
 
358
- _.each(result, function (value, version) {
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
- }
342
+ if (onlyVersion) {
343
+ // CASE: filter out versions which should not run
344
+ let containsVersion = _.find(result, function (_obj, key) {
345
+ return key === onlyVersion;
364
346
  });
365
- })
366
- .then(function executeBeforeHook() {
367
- if (!versionsToMigrate.length) {
368
- return;
347
+
348
+ if (!containsVersion) {
349
+ logging.warn('Cannot find requested version: ' + onlyVersion);
369
350
  }
351
+ }
370
352
 
353
+ _.each(result, function (value, version) {
354
+ // CASE: compare files on disk with files in database
355
+ if (value.expected !== value.actual) {
356
+ debug('Need to execute migrations for: ' + version);
357
+ versionsToMigrate.push(version);
358
+ }
359
+ });
360
+
361
+ if (versionsToMigrate.length) {
371
362
  if (hooks.before) {
372
363
  debug('Before hook');
373
- return hooks.before({
374
- connection: self.connection
364
+ await hooks.before({
365
+ connection: this.connection
375
366
  });
376
367
  }
377
- })
378
- .then(function executeMigrations() {
379
- if (!versionsToMigrate.length) {
380
- return;
381
- }
382
368
 
383
- return Promise.each(versionsToMigrate, function (versionToMigrate) {
384
- return self._migrateTo({
385
- version: versionToMigrate,
386
- only: onlyFile,
387
- hooks: hooks
388
- });
389
- });
390
- })
391
- .then(function executeAfterHook() {
392
- if (!versionsToMigrate.length) {
393
- return;
394
- }
369
+ logging.info('Running migrations.');
395
370
 
396
- if (hooks.after) {
397
- debug('After hook');
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;
410
- }
371
+ for (const versionToMigrate of versionsToMigrate) {
372
+ try {
373
+ await this._migrateTo({
374
+ version: versionToMigrate,
375
+ only: onlyFile,
376
+ hooks: hooks
377
+ });
378
+ } catch (err) {
379
+ // CASE: Do not rollback if migrations are locked
380
+ if (err instanceof errors.MigrationsAreLockedError) {
381
+ throw err;
382
+ }
411
383
 
412
- // CASE: Do not rollback migration scripts, if lock error
413
- if (err instanceof errors.LockError) {
414
- throw err;
415
- }
384
+ // CASE: Do not rollback migration scripts, if lock error
385
+ if (err instanceof errors.LockError) {
386
+ throw err;
387
+ }
416
388
 
417
- // CASE: ETIMEDOUT, ENOTFOUND
418
- if (err instanceof errors.DatabaseError) {
419
- throw err;
420
- }
389
+ // CASE: ETIMEDOUT, ENOTFOUND
390
+ if (err instanceof errors.DatabaseError) {
391
+ throw err;
392
+ }
421
393
 
422
- if (err.context && err.context.name) {
423
- debug(`Task failed: ${err.context.name}`);
424
- }
394
+ if (err.context && err.context.name) {
395
+ debug(`Task failed: ${err.context.name}`);
396
+ }
425
397
 
426
- debug(`Rolling back: ${err.message}`);
398
+ logging.info(`Rolling back: ${err.message}.`);
427
399
 
428
- versionsToMigrate.reverse();
400
+ const versionsMigrated = versionsToMigrate.slice(
401
+ 0,
402
+ versionsToMigrate.indexOf(versionToMigrate) + 1
403
+ );
429
404
 
430
- // CASE: rollback in reversed order
431
- return Promise.each(versionsToMigrate, function (version) {
432
- return self._rollback({version: version, task: err.context});
433
- }).then(function () {
434
- throw err;
435
- }).catch(function (innerErr) {
436
- if (errors.utils.isIgnitionError(innerErr)) {
437
- throw err;
438
- }
405
+ versionsMigrated.reverse();
439
406
 
440
- throw new errors.RollbackError({
441
- message: innerErr.message,
442
- err: innerErr,
443
- context: `OuterError: ${err.message}`
444
- });
445
- }).finally(function () {
446
- return locking.unlock(self.connection);
447
- });
448
- }).finally(function () {
449
- let ops = [];
407
+ try {
408
+ for (const versionMigrated of versionsMigrated) {
409
+ await this._rollback({version: versionMigrated, task: err.context});
410
+ }
411
+ logging.info(`Rollback was successful.`);
412
+ throw err;
413
+ } catch (innerErr) {
414
+ if (errors.utils.isIgnitionError(innerErr)) {
415
+ throw err;
416
+ }
417
+
418
+ throw new errors.RollbackError({
419
+ message: innerErr.message,
420
+ err: innerErr,
421
+ context: `OuterError: ${err.message}`
422
+ });
423
+ } finally {
424
+ await locking.unlock(this.connection);
425
+ }
426
+ }
427
+ }
450
428
 
451
- if (hooks.shutdown) {
452
- ops.push(function shutdownHook() {
453
- debug('Shutdown hook');
454
- return hooks.shutdown({
455
- executedFromShell: self.executedFromShell
456
- });
429
+ if (hooks.after) {
430
+ debug('After hook');
431
+ await hooks.after({
432
+ connection: this.connection
457
433
  });
458
434
  }
459
-
460
- ops.push(function destroyConnection() {
461
- debug('Destroy connection');
462
- return self.connection.destroy()
463
- .then(function () {
464
- debug('Destroyed connection');
465
- });
435
+ }
436
+ await locking.unlock(this.connection);
437
+ } finally {
438
+ if (hooks.shutdown) {
439
+ debug('Shutdown hook');
440
+ await hooks.shutdown({
441
+ executedFromShell: this.executedFromShell
466
442
  });
443
+ }
467
444
 
468
- return Promise.each(ops, function (op) {
469
- return op.bind(self)();
470
- });
471
- });
445
+ debug('Destroy connection');
446
+ await this.connection.destroy();
447
+ debug('Destroyed connection');
448
+ }
472
449
  };
473
450
 
474
451
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knex-migrator",
3
- "version": "4.0.5",
3
+ "version": "4.1.3",
4
4
  "description": "Database migrations with knex.",
5
5
  "keywords": [
6
6
  "ghost",
@@ -44,7 +44,7 @@
44
44
  "knex-migrator-rollback": "./bin/knex-migrator-rollback"
45
45
  },
46
46
  "engines": {
47
- "node": "^12.10.0 || ^14.14.0"
47
+ "node": "^12.22.1 || ^14.17.0 || ^16.13.0"
48
48
  },
49
49
  "dependencies": {
50
50
  "bluebird": "3.7.2",