db-migrate 1.0.0-beta.21 → 1.0.0-beta.23

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 CHANGED
@@ -1,10 +1,6 @@
1
1
  [![Backers on Open Collective](https://opencollective.com/node-db-migrate/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/node-db-migrate/sponsors/badge.svg)](#sponsors)
2
2
  [![Build Status](https://github.com/db-migrate/node-db-migrate/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/db-migrate/node-db-migrate/actions/workflows/ci.yml)
3
- [![Dependency Status](https://david-dm.org/db-migrate/node-db-migrate.svg)](https://david-dm.org/db-migrate/node-db-migrate)
4
- [![devDependency Status](https://david-dm.org/db-migrate/node-db-migrate/dev-status.svg)](https://david-dm.org/db-migrate/node-db-migrate#info=devDependencies)
5
3
  [![Documentation Status](https://readthedocs.org/projects/db-migrate/badge/?version=latest)](https://readthedocs.org/projects/db-migrate/?badge=latest)
6
- [![Code Quality: Javascript](https://img.shields.io/lgtm/grade/javascript/g/db-migrate/node-db-migrate.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/db-migrate/node-db-migrate/context:javascript)
7
- [![Total Alerts](https://img.shields.io/lgtm/alerts/g/db-migrate/node-db-migrate.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/db-migrate/node-db-migrate/alerts)
8
4
 
9
5
  # db-migrate
10
6
 
package/api.js CHANGED
@@ -245,6 +245,31 @@ dbmigrate.prototype = {
245
245
  );
246
246
  },
247
247
 
248
+ fix: function (specification, opts, callback) {
249
+ var executeFix = load('fix');
250
+
251
+ if (arguments.length > 0) {
252
+ if (typeof specification === 'string') {
253
+ this.internals.argv.destination = specification;
254
+ } else if (typeof specification === 'number') {
255
+ this.internals.argv.count = specification;
256
+ } else if (typeof specification === 'function') {
257
+ callback = specification;
258
+ }
259
+
260
+ if (typeof opts === 'string') {
261
+ this.internals.migrationMode = opts;
262
+ this.internals.matching = opts;
263
+ } else if (typeof opts === 'function') {
264
+ callback = opts;
265
+ }
266
+ }
267
+
268
+ return Promise.resolve(executeFix(this.internals, this.config)).nodeify(
269
+ callback
270
+ );
271
+ },
272
+
248
273
  check: function (specification, opts, callback) {
249
274
  var executeCheck = load('check');
250
275
 
@@ -0,0 +1,52 @@
1
+ var path = require('path');
2
+ var log = require('db-migrate-shared').log;
3
+ var migrationHook = require('./helper/migration-hook.js');
4
+
5
+ async function prepare (internals, config) {
6
+ try {
7
+ await migrationHook(internals);
8
+ var Migrator = require('../walker.js');
9
+ var index = require('../../connect');
10
+
11
+ if (!internals.argv.count) {
12
+ internals.argv.count = Number.MAX_VALUE;
13
+ }
14
+ const migrator = await index.connect(
15
+ {
16
+ config: config.getCurrent().settings,
17
+ internals: internals,
18
+ prefix: 'migration'
19
+ },
20
+ Migrator
21
+ );
22
+
23
+ if (internals.locTitle) {
24
+ migrator.directory = path.resolve(
25
+ internals.argv['migrations-dir'],
26
+ internals.locTitle
27
+ );
28
+ } else {
29
+ migrator.directory = path.resolve(internals.argv['migrations-dir']);
30
+ }
31
+
32
+ internals.migrationsDir = migrator.directory;
33
+
34
+ await migrator.createMigrationsTable();
35
+ log.verbose('migration table created');
36
+
37
+ return migrator;
38
+ } catch (err) {
39
+ throw err;
40
+ }
41
+ }
42
+
43
+ module.exports = async function (internals, config) {
44
+ const migrator = await prepare(internals, config);
45
+
46
+ try {
47
+ const res = await migrator.fix(internals.argv);
48
+ return internals.onComplete(migrator, internals, null, res);
49
+ } catch (err) {
50
+ return internals.onComplete(migrator, internals, err);
51
+ }
52
+ };
@@ -9,6 +9,7 @@ const files = {
9
9
  "db": require('./db.js'),
10
10
  "down": require('./down.js'),
11
11
  "dump": require('./dump.js'),
12
+ "fix": require('./fix.js'),
12
13
  "fn/plugin": require('./fn/plugin.js'),
13
14
  "generated": require('./generated.js'),
14
15
  "helper/assert": require('./helper/assert.js'),
@@ -36,6 +36,7 @@ function run (internals, config) {
36
36
 
37
37
  executeSync(internals, config);
38
38
  break;
39
+ case 'fix':
39
40
  case 'up':
40
41
  case 'down':
41
42
  case 'reset':
@@ -58,6 +59,9 @@ function run (internals, config) {
58
59
  if (action === 'up') {
59
60
  var executeUp = load('up');
60
61
  executeUp(internals, config);
62
+ } else if (action === 'fix') {
63
+ var executeFix = load('fix');
64
+ executeFix(internals, config);
61
65
  } else {
62
66
  var executeDown = load('down');
63
67
  executeDown(internals, config);
@@ -9,6 +9,7 @@ const StateTravel = require('../../methods/v2/statetravel');
9
9
  const Migrate = require('../../methods/v2/migrate');
10
10
  const TranslateState = require('../../methods/v2/translatestate');
11
11
  const AddConventions = require('../../methods/v2/conventions');
12
+ const util = require('util');
12
13
 
13
14
  const execUnit = {
14
15
  _extend: (context, type) => {
@@ -65,6 +66,45 @@ const execUnit = {
65
66
  // end migration, same as start migration
66
67
  },
67
68
 
69
+ fix: async function (context, driver, file) {
70
+ const _file = file.get();
71
+ const chain = new Chain(context._driver, file, driver, context.internals);
72
+ if (!_file._meta.noDefaultColumn) {
73
+ chain.addChain(AddConventions);
74
+ }
75
+ chain.addChain(Learn);
76
+ // chain.addChain(StateTravel);
77
+
78
+ await State.startMigration(context._driver, file, context.internals);
79
+ // startMigration - needs secondary instance since we can not afford to
80
+ // loose state and the transaction start will include these for roll back
81
+ // we will disable them probably at all from DDL when the driver does not
82
+ // explicitly signal DDL transaction support (like crdb)
83
+ try {
84
+ await _file.migrate(chain, {
85
+ options: context.internals.safeOptions,
86
+ seedLink: context.seedLink,
87
+ dbm: context.internals.safeOptions.dbmigrate
88
+ });
89
+ } catch (err) {
90
+ context.internals.rollback = true;
91
+
92
+ // transfer last state
93
+ chain.transferInt();
94
+
95
+ log.error(
96
+ 'An error occured. No alternative failure strategy defined. Rolling back!',
97
+ err
98
+ );
99
+ await execUnit.down(context, driver, file);
100
+ throw err;
101
+ }
102
+ await Promise.promisify(context.writeMigrationRecord.bind(context))(file);
103
+ await State.endMigration(context._driver, file, context.internals);
104
+ log.verbose(`[fix] current schema`, util.inspect(context.internals.schema, false, null, true));
105
+ // end migration, same as start migration
106
+ },
107
+
68
108
  down: async function (context, driver, file) {
69
109
  // start migration, see up comments
70
110
  await State.startMigration(context._driver, file, context.internals);
package/lib/learn.js CHANGED
@@ -2,7 +2,7 @@ const Promise = require('bluebird');
2
2
  const Shadow = require('./driver/shadow');
3
3
 
4
4
  class STD {
5
- constructor ({ schema, modSchema: mod }, driver) {
5
+ constructor ({ schema, modSchema: mod, unlearn }, driver) {
6
6
  this.checkColumn = function (t, c) {
7
7
  if (!this.schema[t]) {
8
8
  throw new Error(`There is no ${t} table in schema!`);
@@ -12,6 +12,7 @@ class STD {
12
12
  throw new Error(`There is no ${c} column in schema!`);
13
13
  }
14
14
  };
15
+ this.unlearn = unlearn;
15
16
  this.validations = {};
16
17
  this.driver = driver;
17
18
  this.indizies = schema.i;
@@ -21,10 +22,14 @@ class STD {
21
22
  schema.e = {};
22
23
  }
23
24
  this.extra = schema.e;
25
+ if (unlearn) {
26
+ this.modC = [];
27
+ } else {
28
+ this.modC = mod.s;
29
+ }
24
30
  this.modS = mod.c;
25
31
  this.modI = mod.i;
26
32
  this.modF = mod.f;
27
- this.modC = mod.s;
28
33
  }
29
34
 
30
35
  dropTable (t) {
@@ -124,7 +129,7 @@ class STD {
124
129
  const hasColumns = this.schema[t].columns !== undefined;
125
130
  const columns = hasColumns ? this.schema[t].columns : this.schema[t];
126
131
 
127
- if (columns[c].notNull === true) {
132
+ if (columns[c].notNull === true && !this.unlearn) {
128
133
  if (this.validations.columnStrategies !== true) {
129
134
  if (
130
135
  this.driver._meta &&
@@ -172,7 +177,7 @@ class STD {
172
177
 
173
178
  this.modS[t] = {};
174
179
 
175
- if (columns[c].notNull === true) {
180
+ if (columns[c].notNull === true && !this.unlearn) {
176
181
  switch (o.columnStrategy) {
177
182
  case 'delay':
178
183
  this.modS[t][c] = columns[c];
@@ -196,7 +201,7 @@ class STD {
196
201
  this.modC.push({ t: 1, a: 'addColumn', c: [t, c, o] });
197
202
  break;
198
203
  }
199
- } else {
204
+ } else if (!this.unlearn) {
200
205
  this.modS[t][c] = columns[c];
201
206
 
202
207
  this.modC.push({ t: 1, a: 'addColumn', c: [t, c, o] });
@@ -2,6 +2,7 @@ const Promise = require('bluebird');
2
2
  const State = require('../../state');
3
3
  const Chain = require('../../chain');
4
4
  const Migrate = require('./migrate');
5
+ const Learn = require('../../learn');
5
6
  const log = require('db-migrate-shared').log;
6
7
 
7
8
  const methods = {
@@ -107,7 +108,9 @@ module.exports = async (context, file, driver, internals) => {
107
108
  const mod = internals.modSchema;
108
109
 
109
110
  const chain = new Chain(context, file, driver, internals);
110
- // chain.addChain(Learn);
111
+ internals.unlearn = true;
112
+
113
+ chain.addChain(Learn);
111
114
  chain.addChain(Migrate);
112
115
  await Promise.resolve(mod.s.reverse()).each(args =>
113
116
  processEntry(context, file, chain, internals, args)
package/lib/walker.js CHANGED
@@ -239,6 +239,65 @@ Walker.prototype = {
239
239
  .nodeify(callback);
240
240
  },
241
241
 
242
+ fix: function (options, callback) {
243
+ const partialName = options.destination;
244
+ const count = options.count;
245
+ const sortFn = function (a, b) {
246
+ a = a.name.slice(0, a.name.indexOf('-'));
247
+ b = b.name.slice(0, b.name.indexOf('-'));
248
+
249
+ if (!isNaN(a)) {
250
+ return a - b;
251
+ }
252
+
253
+ return a.localeCompare(b);
254
+ };
255
+
256
+ const files = File.loadFromDatabase(
257
+ this.directory,
258
+ this.prefix,
259
+ this._driver,
260
+ this.internals
261
+ ).then(completedFiles => {
262
+ const toRun = dbmUtil.filterDown(completedFiles, partialName, count).sort(sortFn);
263
+
264
+ if (toRun.length === 0) {
265
+ log.info(this.title + 'Nothing to run');
266
+ }
267
+
268
+ if (this.internals.check) {
269
+ const toRunNames = toRun.map(migration => migration.name);
270
+ log.info(this.title + 'run:', toRunNames);
271
+ return toRunNames;
272
+ }
273
+
274
+ return toRun;
275
+ });
276
+
277
+ if (this.internals.check) {
278
+ return files.nodeify(callback);
279
+ }
280
+
281
+ return files
282
+ .each(file => {
283
+ log.verbose(this.title + 'preparing to run fix:', file.name);
284
+ const _meta = file.get()._meta || {};
285
+ const version = _meta.version || 1;
286
+ if (version < 2) {
287
+ log.warn(`${this.title} skipping "${file.name}" as v1 migrations do not maintain a schema`);
288
+ return Promise.resolve();
289
+ }
290
+
291
+ this.internals.modSchema = { i: {}, c: {}, f: {}, s: [] };
292
+ return require(`./executors/versioned/v${version}`).fix(
293
+ this,
294
+ this.driver,
295
+ file
296
+ );
297
+ })
298
+ .nodeify(callback);
299
+ },
300
+
242
301
  check: function (options, callback) {
243
302
  return Promise.all([
244
303
  File.loadFromDatabase(
package/package.json CHANGED
@@ -31,7 +31,7 @@
31
31
  "programable",
32
32
  "api"
33
33
  ],
34
- "version": "1.0.0-beta.21",
34
+ "version": "1.0.0-beta.23",
35
35
  "engines": {
36
36
  "node": ">=8.0.0"
37
37
  },
@@ -54,7 +54,6 @@
54
54
  "parse-database-url": "~0.3.0",
55
55
  "rc": "^1.2.8",
56
56
  "resolve": "^1.19.0",
57
- "semver": "^5.3.0",
58
57
  "tunnel-ssh": "^4.0.0",
59
58
  "yargs": "^17.5.1"
60
59
  },
@@ -64,8 +63,8 @@
64
63
  "@hapi/eslint-plugin": "^6.0.0",
65
64
  "@hapi/lab": "25.x",
66
65
  "db-migrate-base": "^2.1.1",
67
- "db-migrate-mysql": "^2.1.1",
68
- "db-migrate-sqlite3": "^0.4.0",
66
+ "db-migrate-mysql": "^2.2.0",
67
+ "db-migrate-sqlite3": "^0.5.0",
69
68
  "eslint": "^7.32.0",
70
69
  "eslint-config-standard": "^14.1.1",
71
70
  "eslint-plugin-import": "^2.26.0",