db-migrate 1.0.0-beta.16
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/CHANGELOG.md +487 -0
- package/LICENSE +22 -0
- package/README.md +100 -0
- package/api.js +463 -0
- package/bin/db-migrate +39 -0
- package/connect.js +198 -0
- package/get.js +67 -0
- package/index.js +85 -0
- package/lib/chain.js +157 -0
- package/lib/class.js +75 -0
- package/lib/commands/check.js +52 -0
- package/lib/commands/create-migration.js +252 -0
- package/lib/commands/db.js +63 -0
- package/lib/commands/down.js +45 -0
- package/lib/commands/dump.js +22 -0
- package/lib/commands/fn/plugin.js +45 -0
- package/lib/commands/generated.js +32 -0
- package/lib/commands/helper/assert.js +15 -0
- package/lib/commands/helper/load-config.js +26 -0
- package/lib/commands/helper/migration-hook.js +4 -0
- package/lib/commands/helper/register-events.js +19 -0
- package/lib/commands/index.js +9 -0
- package/lib/commands/on-complete.js +28 -0
- package/lib/commands/run.js +122 -0
- package/lib/commands/seed.js +48 -0
- package/lib/commands/set-default-argv.js +169 -0
- package/lib/commands/sync.js +52 -0
- package/lib/commands/undo-seed.js +54 -0
- package/lib/commands/up.js +52 -0
- package/lib/config.js +207 -0
- package/lib/driver/index.js +156 -0
- package/lib/driver/shadow.js +74 -0
- package/lib/executors/versioned/v1.js +48 -0
- package/lib/executors/versioned/v2.js +78 -0
- package/lib/file.js +190 -0
- package/lib/interface/migratorInterface.js +127 -0
- package/lib/interface/seederInterface.js +145 -0
- package/lib/learn.js +369 -0
- package/lib/methods/v2/conventions.js +47 -0
- package/lib/methods/v2/migrate.js +5 -0
- package/lib/methods/v2/statetravel.js +86 -0
- package/lib/methods/v2/translatestate.js +117 -0
- package/lib/relation.js +37 -0
- package/lib/state.js +154 -0
- package/lib/template.js +312 -0
- package/lib/templates/v2.js +12 -0
- package/lib/temputils.js +62 -0
- package/lib/walker.js +266 -0
- package/package.json +87 -0
- package/pnpm-lock.yaml +2574 -0
- package/te.js +70 -0
package/get.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
exports.migrate = async (db, opt) => {
|
|
2
|
+
await db.get('test', {
|
|
3
|
+
columns: ['column1']
|
|
4
|
+
});
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* columns can be aliased
|
|
8
|
+
*/
|
|
9
|
+
await db.get('test', {
|
|
10
|
+
columns: {
|
|
11
|
+
column1: 'maxima'
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* We avoid tapping into complicated languages to define
|
|
17
|
+
* the where clause. Instead you just use SQL or mongo schema
|
|
18
|
+
* depending on the db you use. If you want to provide genericity we will
|
|
19
|
+
* suggest using helper libraries like sql2mongo or vice versa. This allows
|
|
20
|
+
* flexibility and avoids also the need to learn to many new things and
|
|
21
|
+
* reinventing the weel just for a translation layer in this case.
|
|
22
|
+
*/
|
|
23
|
+
await db.get('test', {
|
|
24
|
+
columns: {
|
|
25
|
+
column1: 'maxima',
|
|
26
|
+
column2: 'something'
|
|
27
|
+
},
|
|
28
|
+
search: 'maxima >= 12'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* However, the most simple operation we will support upfront. Everything
|
|
33
|
+
* else can use tooling. We will provide a plugin hook so this can be in
|
|
34
|
+
* doubt tightly integrated into the migrations.
|
|
35
|
+
*/
|
|
36
|
+
await db.get('test', {
|
|
37
|
+
columns: {
|
|
38
|
+
column1: 'maxima',
|
|
39
|
+
column2: 'something'
|
|
40
|
+
},
|
|
41
|
+
search: {
|
|
42
|
+
maxima: 15
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* when doing more then searching, you want to access it in query mode.
|
|
48
|
+
* You will have to write the whole definition by hand. This guarantees
|
|
49
|
+
* that we still understand what is happening (type of operation), but
|
|
50
|
+
* gives ultimate flexibility.
|
|
51
|
+
*
|
|
52
|
+
* The table param is optional, when using for example SQL it will not be
|
|
53
|
+
* needed, databases like mongodb will need it however, so it might be
|
|
54
|
+
* recommended as a best practice to not omit it, depending on how ultimate
|
|
55
|
+
* the decision of the db is yet.
|
|
56
|
+
*
|
|
57
|
+
* Adding LIMITS yourself is possible, but leave this to db-migrate in doubt.
|
|
58
|
+
*/
|
|
59
|
+
await db.get('test', {
|
|
60
|
+
query: 'DISTINCT value1 FROM test' // select will be forcefully prepended so we always know this will only get data
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
exports._meta = {
|
|
65
|
+
version: 2,
|
|
66
|
+
DML: true
|
|
67
|
+
};
|
package/index.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module.exports.version = require('./package.json').version;
|
|
2
|
+
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var log = require('db-migrate-shared').log;
|
|
6
|
+
|
|
7
|
+
exports.dataType = require('db-migrate-shared').dataType;
|
|
8
|
+
|
|
9
|
+
function loadPluginList (options) {
|
|
10
|
+
try {
|
|
11
|
+
fs.accessSync(path.join(options.cwd, 'package.json'), fs.constants.R_OK);
|
|
12
|
+
} catch (err) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
'There was no package.json found in the current working dir!',
|
|
15
|
+
options.cwd
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
var plugins = JSON.parse(
|
|
21
|
+
fs.readFileSync(path.join(options.cwd, 'package.json'), 'utf-8')
|
|
22
|
+
);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
throw new Error('Error parsing package.json', err);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var targets = [];
|
|
28
|
+
|
|
29
|
+
plugins = Object.assign(
|
|
30
|
+
plugins.dependencies || {},
|
|
31
|
+
plugins.devDependencies || {}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
for (var plugin in plugins) {
|
|
35
|
+
if (plugin.startsWith('db-migrate-plugin')) targets.push(plugin);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return targets;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function loadPlugins (options) {
|
|
42
|
+
var plugins = loadPluginList(options);
|
|
43
|
+
var i = 0;
|
|
44
|
+
var length = plugins.length;
|
|
45
|
+
var hooks = {};
|
|
46
|
+
|
|
47
|
+
for (; i < length; ++i) {
|
|
48
|
+
var plugin = require(path.join(options.cwd, 'node_modules', plugins[i]));
|
|
49
|
+
|
|
50
|
+
if (!plugin.hooks || !plugin.loadPlugin) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// name is now derived from package name
|
|
55
|
+
plugin.name = plugins[i];
|
|
56
|
+
|
|
57
|
+
plugin.hooks.forEach(function (hook) {
|
|
58
|
+
hooks[hook] = hooks[hook] || [];
|
|
59
|
+
hooks[hook].push(plugin);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return hooks;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports.getInstance = function (isModule, options = {}, callback) {
|
|
67
|
+
delete require.cache[require.resolve('./api.js')];
|
|
68
|
+
delete require.cache[require.resolve('yargs')];
|
|
69
|
+
var Mod = require('./api.js');
|
|
70
|
+
var plugins = {};
|
|
71
|
+
options.cwd = options.cwd || process.cwd();
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
if (!options || !options.noPlugins) plugins = loadPlugins(options);
|
|
75
|
+
} catch (ex) {
|
|
76
|
+
log.verbose('No plugin could be loaded!');
|
|
77
|
+
log.verbose(ex);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (options && options.plugins) {
|
|
81
|
+
plugins = Object.assign(plugins, options.plugins);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return new Mod(plugins, isModule, options, callback);
|
|
85
|
+
};
|
package/lib/chain.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
const DEFAULT = [
|
|
2
|
+
'renameCollection',
|
|
3
|
+
'dropCollection',
|
|
4
|
+
'createCollection',
|
|
5
|
+
'createTable',
|
|
6
|
+
'dropTable',
|
|
7
|
+
'renameTable',
|
|
8
|
+
'addColumn',
|
|
9
|
+
'removeColumn',
|
|
10
|
+
'renameColumn',
|
|
11
|
+
'changeColumn',
|
|
12
|
+
'addIndex',
|
|
13
|
+
'removeIndex',
|
|
14
|
+
'addForeignKey',
|
|
15
|
+
'removeForeignKey'
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
let rollbackCounter = 0;
|
|
19
|
+
let rollbackSignal = null;
|
|
20
|
+
let signal = null;
|
|
21
|
+
let counter = 0;
|
|
22
|
+
|
|
23
|
+
const dbmControl = {
|
|
24
|
+
inc: () => {
|
|
25
|
+
++counter;
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
signal: () => {
|
|
29
|
+
signal = true;
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
hasSignaled: () => {
|
|
33
|
+
return signal;
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
previousSignal: () => {
|
|
37
|
+
const r = rollbackSignal;
|
|
38
|
+
// we reset on retrieval and mark as retrieved
|
|
39
|
+
rollbackSignal = rollbackSignal === null ? null : false;
|
|
40
|
+
return r;
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
get: () => {
|
|
44
|
+
return counter;
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
getPrevious: () => {
|
|
48
|
+
const r = rollbackCounter;
|
|
49
|
+
|
|
50
|
+
// we reset on retrieval and mark as retrieved
|
|
51
|
+
rollbackCounter = rollbackCounter > 0 ? false : 0;
|
|
52
|
+
|
|
53
|
+
return r;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
class Chain {
|
|
58
|
+
constructor (context, file, driver, internals) {
|
|
59
|
+
this.file = file;
|
|
60
|
+
this.context = context;
|
|
61
|
+
this.driver = context;
|
|
62
|
+
this.udriver = driver;
|
|
63
|
+
if (this.udriver._dbmControl !== true) {
|
|
64
|
+
this.udriver._counter = dbmControl;
|
|
65
|
+
this.udriver._dbmControl = true;
|
|
66
|
+
const runSql = this.udriver.runSql;
|
|
67
|
+
this.udriver._dbmControlRSQL = runSql;
|
|
68
|
+
|
|
69
|
+
// couple runSql
|
|
70
|
+
this.udriver.runSql = function (...args) {
|
|
71
|
+
return runSql.apply(this, args).then(x => {
|
|
72
|
+
++counter;
|
|
73
|
+
return x;
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
this.internals = internals;
|
|
78
|
+
this.chains = [];
|
|
79
|
+
this.interfaces = [];
|
|
80
|
+
this.it = 0;
|
|
81
|
+
this._step = null;
|
|
82
|
+
this._interface = null;
|
|
83
|
+
|
|
84
|
+
DEFAULT.concat(Object.keys(this.context.learnable || [])).forEach(
|
|
85
|
+
method => {
|
|
86
|
+
this[method] = function (...args) {
|
|
87
|
+
// we don't handle any callbacks here, v2 ultimately deprecates them
|
|
88
|
+
|
|
89
|
+
this.transferInt();
|
|
90
|
+
|
|
91
|
+
return this.exec.apply(this, [method].concat(args));
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
transferInt () {
|
|
98
|
+
rollbackCounter = counter;
|
|
99
|
+
counter = 0;
|
|
100
|
+
rollbackSignal = signal;
|
|
101
|
+
signal = null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
addChain (chain) {
|
|
105
|
+
this.chains.push(chain);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
step () {
|
|
109
|
+
this._step = this.chains[this.it];
|
|
110
|
+
if (!this._step) return null;
|
|
111
|
+
if (!this.interfaces[this.it]) {
|
|
112
|
+
this.interfaces[this.it] = this._step.getInterface(
|
|
113
|
+
this.context,
|
|
114
|
+
this.file,
|
|
115
|
+
this.udriver,
|
|
116
|
+
this.internals
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this._interface = this.interfaces[this.it++];
|
|
121
|
+
return this._step;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
reset () {
|
|
125
|
+
this.it = 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async exec (m, ...args) {
|
|
129
|
+
let ret;
|
|
130
|
+
const stat = [];
|
|
131
|
+
while (this.step()) {
|
|
132
|
+
ret = await this._interface[m].apply(this._interface, args);
|
|
133
|
+
stat.push(ret);
|
|
134
|
+
|
|
135
|
+
if (this._step.hasStateUsage) {
|
|
136
|
+
this._step.useState(ret);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (this._step.hasModification) {
|
|
140
|
+
const ret = this._step.modify(
|
|
141
|
+
this.context,
|
|
142
|
+
this.udriver,
|
|
143
|
+
this.internals
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
if (ret.driver) {
|
|
147
|
+
this.udriver = ret.driver;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.reset();
|
|
153
|
+
return ret;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = Chain;
|
package/lib/class.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* Simple JavaScript Inheritance
|
|
2
|
+
* By John Resig http://ejohn.org/
|
|
3
|
+
* MIT Licensed.
|
|
4
|
+
*/
|
|
5
|
+
// Inspired by base2 and Prototype
|
|
6
|
+
var initializing = false;
|
|
7
|
+
|
|
8
|
+
/*eslint-disable */
|
|
9
|
+
var fnTest = /xyz/.test(function() {
|
|
10
|
+
xyz; // lgtm [js/useless-expression]
|
|
11
|
+
})
|
|
12
|
+
? /\b_super\b/
|
|
13
|
+
: /.*/;
|
|
14
|
+
/* eslint-enable */
|
|
15
|
+
|
|
16
|
+
// The base Class implementation (does nothing)
|
|
17
|
+
var Class = function () {};
|
|
18
|
+
|
|
19
|
+
// Create a new Class that inherits from this class
|
|
20
|
+
Class.extend = function ext (prop) {
|
|
21
|
+
var _super = this.prototype;
|
|
22
|
+
|
|
23
|
+
// Instantiate a base class (but only create the instance,
|
|
24
|
+
// don't run the init constructor)
|
|
25
|
+
initializing = true;
|
|
26
|
+
var prototype = new this();
|
|
27
|
+
initializing = false;
|
|
28
|
+
|
|
29
|
+
// Copy the properties over onto the new prototype
|
|
30
|
+
for (var name in prop) {
|
|
31
|
+
// Check if we're overwriting an existing function
|
|
32
|
+
prototype[name] =
|
|
33
|
+
typeof prop[name] === 'function' &&
|
|
34
|
+
typeof _super[name] === 'function' &&
|
|
35
|
+
fnTest.test(prop[name])
|
|
36
|
+
? (function (name, fn) {
|
|
37
|
+
return function () {
|
|
38
|
+
var tmp = this._super;
|
|
39
|
+
|
|
40
|
+
// Add a new ._super() method that is the same method
|
|
41
|
+
// but on the super-class
|
|
42
|
+
this._super = _super[name];
|
|
43
|
+
|
|
44
|
+
// The method only need to be bound temporarily, so we
|
|
45
|
+
// remove it when we're done executing
|
|
46
|
+
var ret = fn.apply(this, arguments);
|
|
47
|
+
this._super = tmp;
|
|
48
|
+
|
|
49
|
+
return ret;
|
|
50
|
+
};
|
|
51
|
+
})(name, prop[name])
|
|
52
|
+
: prop[name];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The dummy class constructor
|
|
56
|
+
function Class () {
|
|
57
|
+
// All construction is actually done in the init method
|
|
58
|
+
if (!initializing && this.init) {
|
|
59
|
+
this.init.apply(this, arguments);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Populate our constructed prototype object
|
|
64
|
+
Class.prototype = prototype;
|
|
65
|
+
|
|
66
|
+
// Enforce the constructor to be what we expect
|
|
67
|
+
Class.prototype.constructor = Class;
|
|
68
|
+
|
|
69
|
+
// And make this class extendable
|
|
70
|
+
Class.extend = ext;
|
|
71
|
+
|
|
72
|
+
return Class;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
module.exports = Class;
|
|
@@ -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.migrationsDir = path.resolve(
|
|
25
|
+
internals.argv['migrations-dir'],
|
|
26
|
+
internals.locTitle
|
|
27
|
+
);
|
|
28
|
+
} else {
|
|
29
|
+
migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
internals.migrationsDir = migrator.migrationsDir;
|
|
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.check(internals.argv);
|
|
48
|
+
return internals.onComplete(migrator, internals, null, res);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
return internals.onComplete(migrator, internals, err);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Promise = require('bluebird');
|
|
4
|
+
const log = require('db-migrate-shared').log;
|
|
5
|
+
const mkdirp = Promise.promisify(require('mkdirp'));
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const stat = Promise.promisify(fs.stat);
|
|
8
|
+
const writeFile = Promise.promisify(fs.writeFile);
|
|
9
|
+
const yargs = require('yargs');
|
|
10
|
+
const util = require('util');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
async function createMigrationDir (dir) {
|
|
14
|
+
const res = await stat(dir).catch(_ => {
|
|
15
|
+
return { err: true };
|
|
16
|
+
});
|
|
17
|
+
if (res && res.err === true) {
|
|
18
|
+
await mkdirp(dir);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Create migrations/package.json to ensure migration files are
|
|
22
|
+
// executed as CJS and not ESM
|
|
23
|
+
// https://github.com/db-migrate/node-db-migrate/issues/721
|
|
24
|
+
const packageJsonPath = path.resolve(dir, 'package.json');
|
|
25
|
+
|
|
26
|
+
await stat(packageJsonPath).then(
|
|
27
|
+
async () => {
|
|
28
|
+
const packageJson = require(packageJsonPath);
|
|
29
|
+
packageJson.type = 'commonjs';
|
|
30
|
+
const packageJsonStr = JSON.stringify(packageJson, null, 2);
|
|
31
|
+
await writeFile(packageJsonPath, packageJsonStr, 'utf-8');
|
|
32
|
+
},
|
|
33
|
+
async (err) => {
|
|
34
|
+
const packageJson = JSON.stringify({
|
|
35
|
+
type: 'commonjs'
|
|
36
|
+
}, null, 2)
|
|
37
|
+
await writeFile(packageJsonPath, packageJson, 'utf-8');
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function executeCreateMigration (internals, config) {
|
|
43
|
+
let migrationsDir = internals.argv['migrations-dir'];
|
|
44
|
+
let path;
|
|
45
|
+
let hooks = false;
|
|
46
|
+
let pluginTemplate = false;
|
|
47
|
+
let customWrite = false;
|
|
48
|
+
const { plugins } = internals;
|
|
49
|
+
|
|
50
|
+
internals.runTimestamp = new Date();
|
|
51
|
+
|
|
52
|
+
if (internals.migrationMode && internals.migrationMode !== 'all') {
|
|
53
|
+
migrationsDir =
|
|
54
|
+
internals.argv['migrations-dir'] + '/' + internals.migrationMode;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (internals.argv._.length === 0) {
|
|
58
|
+
log.error("'migrationName' is required.");
|
|
59
|
+
if (!internals.isModule) {
|
|
60
|
+
yargs.showHelp();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throw new Error("'migrationName' is required.");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const Migration = require('../template.js');
|
|
67
|
+
|
|
68
|
+
internals.argv.title = internals.argv._.shift();
|
|
69
|
+
const folder = internals.argv.title.toString().split('/');
|
|
70
|
+
|
|
71
|
+
internals.argv.title = folder[folder.length - 1] || folder[0];
|
|
72
|
+
path = migrationsDir;
|
|
73
|
+
|
|
74
|
+
if (folder.length > 1) {
|
|
75
|
+
path += '/';
|
|
76
|
+
|
|
77
|
+
for (let i = 0; i < folder.length - 1; ++i) {
|
|
78
|
+
path += folder[i] + '/';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
internals.argv['migrations-dir'] = path;
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
await createMigrationDir(path);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
log.error('Failed to create migration directory at ', migrationsDir, err);
|
|
87
|
+
throw new Error('Failed to create migration directory.');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let templateType = Migration.TemplateType.DEFAULT_JS;
|
|
91
|
+
if (
|
|
92
|
+
shouldCreateSqlFiles(internals, config) &&
|
|
93
|
+
shouldCreateCoffeeFile(internals, config)
|
|
94
|
+
) {
|
|
95
|
+
templateType = Migration.TemplateType.COFFEE_SQL_FILE_LOADER;
|
|
96
|
+
} else if (
|
|
97
|
+
shouldCreateSqlFiles(internals, config) &&
|
|
98
|
+
shouldIgnoreOnInitFiles(internals, config)
|
|
99
|
+
) {
|
|
100
|
+
templateType = Migration.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT;
|
|
101
|
+
} else if (shouldCreateSqlFiles(internals, config)) {
|
|
102
|
+
templateType = Migration.TemplateType.SQL_FILE_LOADER;
|
|
103
|
+
} else if (shouldCreateCoffeeFile(internals, config)) {
|
|
104
|
+
templateType = Migration.TemplateType.DEFAULT_COFFEE;
|
|
105
|
+
} else if (shouldCreateV2File(internals, config)) {
|
|
106
|
+
templateType = Migration.TemplateType.V2_DEFAULT;
|
|
107
|
+
}
|
|
108
|
+
if (plugins) {
|
|
109
|
+
hooks = plugins.hook('create:template') || [];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (hooks !== false) {
|
|
113
|
+
for (const plugin of hooks) {
|
|
114
|
+
const template = plugin['init:template']();
|
|
115
|
+
|
|
116
|
+
if (internals.argv[template.option] || config[template.option]) {
|
|
117
|
+
pluginTemplate = plugin;
|
|
118
|
+
customWrite = plugin['create:template:custom:write'] === true;
|
|
119
|
+
|
|
120
|
+
if (customWrite) {
|
|
121
|
+
templateType = `${plugin.name}${templateType}`;
|
|
122
|
+
} else {
|
|
123
|
+
templateType = template.type;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// no reason to continue processing here
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!pluginTemplate && !customWrite) {
|
|
133
|
+
const migration = new Migration(
|
|
134
|
+
internals.argv.title +
|
|
135
|
+
(shouldCreateCoffeeFile(internals, config) ? '.coffee' : '.js'),
|
|
136
|
+
path,
|
|
137
|
+
internals.runTimestamp,
|
|
138
|
+
templateType,
|
|
139
|
+
internals.plugins
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
await migration.write();
|
|
143
|
+
log.info(util.format('Created migration at %s', migration.file.path));
|
|
144
|
+
if (shouldCreateSqlFiles(internals, config)) {
|
|
145
|
+
return createSqlFiles(internals, config);
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
const plugin = pluginTemplate;
|
|
149
|
+
|
|
150
|
+
if (typeof plugin['write:template'] !== 'function') {
|
|
151
|
+
log.error(`Plugin ${plugin.name} does not have function write:template`);
|
|
152
|
+
throw new Error(`write:template not existent!`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
await plugin['write:template'](
|
|
156
|
+
{ argv: { ...internals.argv }, config: { ...config } },
|
|
157
|
+
async opts => {
|
|
158
|
+
let title = internals.argv.title;
|
|
159
|
+
let _path = path;
|
|
160
|
+
const extension = opts.extension || '.js';
|
|
161
|
+
|
|
162
|
+
if (opts.suffix) {
|
|
163
|
+
title += opts.suffix;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (opts.pathExtension) {
|
|
167
|
+
_path += opts.pathExtension;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const migration = new Migration(
|
|
171
|
+
title + extension,
|
|
172
|
+
_path,
|
|
173
|
+
internals.runTimestamp,
|
|
174
|
+
opts.type,
|
|
175
|
+
internals.plugins
|
|
176
|
+
);
|
|
177
|
+
await migration.write();
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return Promise.resolve();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function shouldCreateSqlFiles (internals, config) {
|
|
186
|
+
return internals.argv['sql-file'] || config['sql-file'];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function shouldIgnoreOnInitFiles (internals, config) {
|
|
190
|
+
return internals.argv['ignore-on-init'] || config['ignore-on-init'];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function shouldCreateCoffeeFile (internals, config) {
|
|
194
|
+
return internals.argv['coffee-file'] || config['coffee-file'];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function shouldCreateV2File (internals, config) {
|
|
198
|
+
return internals.argv['v2-file'] || config['v2-file'];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function createSqlFiles (internals, config) {
|
|
202
|
+
let migrationsDir = internals.argv['migrations-dir'];
|
|
203
|
+
|
|
204
|
+
if (internals.migrationMode && internals.migrationMode !== 'all') {
|
|
205
|
+
migrationsDir =
|
|
206
|
+
internals.argv['migrations-dir'] + '/' + internals.migrationMode;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const sqlDir = migrationsDir + '/sqls';
|
|
210
|
+
try {
|
|
211
|
+
await createMigrationDir(sqlDir);
|
|
212
|
+
} catch (err) {
|
|
213
|
+
log.error('Failed to create migration directory at ', sqlDir, err);
|
|
214
|
+
|
|
215
|
+
throw err;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const Migration = require('../template.js');
|
|
219
|
+
|
|
220
|
+
const templateTypeDefaultSQL = Migration.TemplateType.DEFAULT_SQL;
|
|
221
|
+
const migrationUpSQL = new Migration(
|
|
222
|
+
internals.argv.title + '-up.sql',
|
|
223
|
+
sqlDir,
|
|
224
|
+
internals.runTimestamp,
|
|
225
|
+
templateTypeDefaultSQL,
|
|
226
|
+
internals.plugins
|
|
227
|
+
);
|
|
228
|
+
await migrationUpSQL.write();
|
|
229
|
+
|
|
230
|
+
log.info(
|
|
231
|
+
util.format('Created migration up sql file at %s', migrationUpSQL.file.path)
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const migrationDownSQL = new Migration(
|
|
235
|
+
internals.argv.title + '-down.sql',
|
|
236
|
+
sqlDir,
|
|
237
|
+
internals.runTimestamp,
|
|
238
|
+
templateTypeDefaultSQL,
|
|
239
|
+
internals.plugins
|
|
240
|
+
);
|
|
241
|
+
migrationDownSQL.write();
|
|
242
|
+
log.info(
|
|
243
|
+
util.format(
|
|
244
|
+
'Created migration down sql file at %s',
|
|
245
|
+
migrationDownSQL.file.path
|
|
246
|
+
)
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
return Promise.resolve();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
module.exports = executeCreateMigration;
|