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 +0 -4
- package/api.js +25 -0
- package/lib/commands/fix.js +52 -0
- package/lib/commands/generated.js +1 -0
- package/lib/commands/run.js +4 -0
- package/lib/executors/versioned/v2.js +40 -0
- package/lib/learn.js +10 -5
- package/lib/methods/v2/translatestate.js +4 -1
- package/lib/walker.js +59 -0
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
[](#backers) [](#sponsors)
|
|
2
2
|
[](https://github.com/db-migrate/node-db-migrate/actions/workflows/ci.yml)
|
|
3
|
-
[](https://david-dm.org/db-migrate/node-db-migrate)
|
|
4
|
-
[](https://david-dm.org/db-migrate/node-db-migrate#info=devDependencies)
|
|
5
3
|
[](https://readthedocs.org/projects/db-migrate/?badge=latest)
|
|
6
|
-
[](https://lgtm.com/projects/g/db-migrate/node-db-migrate/context:javascript)
|
|
7
|
-
[](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'),
|
package/lib/commands/run.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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.
|
|
68
|
-
"db-migrate-sqlite3": "^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",
|