db-migrate 1.0.0-beta.22 → 1.0.0-beta.24
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/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/state.js +3 -3
- package/lib/walker.js +63 -4
- package/package.json +1 -1
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({ emptyState: true });
|
|
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/state.js
CHANGED
|
@@ -29,12 +29,12 @@ module.exports = {
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
|
|
32
|
-
init: async function (driver, internals) {
|
|
32
|
+
init: async function (driver, internals, { emptyState }) {
|
|
33
33
|
await driver._createKV(internals.migrationState);
|
|
34
|
-
const schema = await driver._getKV(internals.migrationState, SSTATE);
|
|
34
|
+
const schema = emptyState ? await driver._getKV(internals.migrationState, SSTATE) : null;
|
|
35
35
|
if (schema) {
|
|
36
36
|
internals.schema = JSON.parse(schema.value);
|
|
37
|
-
} else {
|
|
37
|
+
} else if (!emptyState) {
|
|
38
38
|
await driver._insertKV(internals.migrationState, SSTATE, '{}');
|
|
39
39
|
}
|
|
40
40
|
|
package/lib/walker.js
CHANGED
|
@@ -59,12 +59,12 @@ const Walker = function (driver, directory, mode, intern, prefix) {
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
Walker.prototype = {
|
|
62
|
-
createTables: async function () {
|
|
63
|
-
await State.init(this._driver, this.internals);
|
|
62
|
+
createTables: async function (options) {
|
|
63
|
+
await State.init(this._driver, this.internals, options);
|
|
64
64
|
return this._driver._createList(this.internals.migrationTable);
|
|
65
65
|
},
|
|
66
66
|
|
|
67
|
-
createMigrationsTable: function () {
|
|
67
|
+
createMigrationsTable: function (options) {
|
|
68
68
|
if (
|
|
69
69
|
typeof this._driver._createList !== 'function' ||
|
|
70
70
|
typeof this._driver._getList !== 'function' ||
|
|
@@ -85,7 +85,7 @@ Walker.prototype = {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
return this.createTables();
|
|
88
|
+
return this.createTables(options);
|
|
89
89
|
},
|
|
90
90
|
|
|
91
91
|
writeMigrationRecord: function (migration, callback) {
|
|
@@ -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(
|