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.
Files changed (51) hide show
  1. package/CHANGELOG.md +487 -0
  2. package/LICENSE +22 -0
  3. package/README.md +100 -0
  4. package/api.js +463 -0
  5. package/bin/db-migrate +39 -0
  6. package/connect.js +198 -0
  7. package/get.js +67 -0
  8. package/index.js +85 -0
  9. package/lib/chain.js +157 -0
  10. package/lib/class.js +75 -0
  11. package/lib/commands/check.js +52 -0
  12. package/lib/commands/create-migration.js +252 -0
  13. package/lib/commands/db.js +63 -0
  14. package/lib/commands/down.js +45 -0
  15. package/lib/commands/dump.js +22 -0
  16. package/lib/commands/fn/plugin.js +45 -0
  17. package/lib/commands/generated.js +32 -0
  18. package/lib/commands/helper/assert.js +15 -0
  19. package/lib/commands/helper/load-config.js +26 -0
  20. package/lib/commands/helper/migration-hook.js +4 -0
  21. package/lib/commands/helper/register-events.js +19 -0
  22. package/lib/commands/index.js +9 -0
  23. package/lib/commands/on-complete.js +28 -0
  24. package/lib/commands/run.js +122 -0
  25. package/lib/commands/seed.js +48 -0
  26. package/lib/commands/set-default-argv.js +169 -0
  27. package/lib/commands/sync.js +52 -0
  28. package/lib/commands/undo-seed.js +54 -0
  29. package/lib/commands/up.js +52 -0
  30. package/lib/config.js +207 -0
  31. package/lib/driver/index.js +156 -0
  32. package/lib/driver/shadow.js +74 -0
  33. package/lib/executors/versioned/v1.js +48 -0
  34. package/lib/executors/versioned/v2.js +78 -0
  35. package/lib/file.js +190 -0
  36. package/lib/interface/migratorInterface.js +127 -0
  37. package/lib/interface/seederInterface.js +145 -0
  38. package/lib/learn.js +369 -0
  39. package/lib/methods/v2/conventions.js +47 -0
  40. package/lib/methods/v2/migrate.js +5 -0
  41. package/lib/methods/v2/statetravel.js +86 -0
  42. package/lib/methods/v2/translatestate.js +117 -0
  43. package/lib/relation.js +37 -0
  44. package/lib/state.js +154 -0
  45. package/lib/template.js +312 -0
  46. package/lib/templates/v2.js +12 -0
  47. package/lib/temputils.js +62 -0
  48. package/lib/walker.js +266 -0
  49. package/package.json +87 -0
  50. package/pnpm-lock.yaml +2574 -0
  51. package/te.js +70 -0
package/lib/state.js ADDED
@@ -0,0 +1,154 @@
1
+ const MSTATE = '__dbmigrate_state__';
2
+ const SSTATE = '__dbmigrate_schema__';
3
+ const log = require('db-migrate-shared').log;
4
+
5
+ module.exports = {
6
+ lockState: async function (driver, state, internals) {
7
+ if (!state) {
8
+ return driver._insertKV(
9
+ internals.migrationState,
10
+ MSTATE,
11
+ JSON.stringify({
12
+ s: {
13
+ step: 0,
14
+ fin: 0,
15
+ date: new Date()
16
+ }
17
+ })
18
+ );
19
+ } else {
20
+ state = state.value;
21
+ state = JSON.parse(state);
22
+ state.s.date = new Date();
23
+ return driver._updateKV(
24
+ internals.migrationState,
25
+ MSTATE,
26
+
27
+ JSON.stringify(state)
28
+ );
29
+ }
30
+ },
31
+
32
+ init: async function (driver, internals) {
33
+ await driver._createKV(internals.migrationState);
34
+ const schema = await driver._getKV(internals.migrationState, SSTATE);
35
+ if (schema) {
36
+ internals.schema = JSON.parse(schema.value);
37
+ } else {
38
+ await driver._insertKV(internals.migrationState, SSTATE, '{}');
39
+ }
40
+
41
+ if (!internals.dryRun) {
42
+ const state = await driver._getKV(internals.migrationState, MSTATE);
43
+ return module.exports.lockState(driver, state, internals);
44
+ }
45
+
46
+ return Promise.resolve();
47
+ },
48
+
49
+ startMigration: async function (driver, file, internals) {
50
+ const state = await driver._getKV(internals.migrationState, MSTATE);
51
+ const mig = await driver._getKV(internals.migrationState, file.name);
52
+
53
+ if (mig && mig.value !== '{}') {
54
+ internals.modSchema = JSON.parse(mig.value);
55
+ }
56
+
57
+ if (internals.dryRun) {
58
+ return Promise.resolve();
59
+ }
60
+
61
+ await module.exports.lockState(driver, state, internals);
62
+
63
+ if (!mig) {
64
+ return driver._insertKV(
65
+ internals.migrationState,
66
+ file.name,
67
+ JSON.stringify({})
68
+ );
69
+ } else {
70
+ return Promise.resolve();
71
+ }
72
+ },
73
+
74
+ update: async function (driver, file, state, internals) {
75
+ log.verbose(`[state] update state`);
76
+ if (internals.dryRun) {
77
+ return Promise.resolve();
78
+ }
79
+
80
+ await driver._updateKV(internals.migrationState, SSTATE, internals.schema);
81
+
82
+ return driver._updateKV(
83
+ internals.migrationState,
84
+ file.name,
85
+ JSON.stringify(state)
86
+ );
87
+ },
88
+
89
+ get: function (driver, file, internals) {
90
+ return driver._getKV(internals.migrationState, file.name);
91
+ },
92
+
93
+ tick: async function (driver, internals) {
94
+ if (internals.dryRun) {
95
+ return Promise.resolve();
96
+ }
97
+
98
+ let { value: state } = await driver._getKV(
99
+ internals.migrationState,
100
+ MSTATE
101
+ );
102
+ state = JSON.parse(state);
103
+ state.s.date = new Date();
104
+ return driver._updateKV(
105
+ internals.migrationState,
106
+ MSTATE,
107
+ JSON.stringify(state)
108
+ );
109
+ },
110
+
111
+ step: async function (driver, step, internals) {
112
+ log.verbose(`[state] proceeded to step ${step}`);
113
+ if (internals.dryRun) {
114
+ return Promise.resolve();
115
+ }
116
+
117
+ let { value: state } = await driver._getKV(
118
+ internals.migrationState,
119
+ MSTATE
120
+ );
121
+ state = JSON.parse(state);
122
+ state.s.date = new Date();
123
+ state.s.step = step;
124
+ return driver._updateKV(
125
+ internals.migrationState,
126
+ MSTATE,
127
+ JSON.stringify(state)
128
+ );
129
+ },
130
+
131
+ deleteState: function (driver, file, internals) {
132
+ return driver._deleteKV(internals.migrationState, file.name);
133
+ },
134
+
135
+ endMigration: async function (driver, file, internals) {
136
+ if (internals.dryRun) {
137
+ return Promise.resolve();
138
+ }
139
+
140
+ let { value: state } = await driver._getKV(
141
+ internals.migrationState,
142
+ MSTATE
143
+ );
144
+ state = JSON.parse(state);
145
+ state.s.date = new Date();
146
+ state.s.fin = 1;
147
+
148
+ return driver._updateKV(
149
+ internals.migrationState,
150
+ MSTATE,
151
+ JSON.stringify(state)
152
+ );
153
+ }
154
+ };
@@ -0,0 +1,312 @@
1
+ 'use strict';
2
+
3
+ const File = require('./file.js');
4
+ const { util: dbmUtil, log } = require('db-migrate-shared');
5
+
6
+ const Template = function () {
7
+ if (arguments[4] && typeof arguments[4].overwrite === 'function') {
8
+ this.plugins = arguments[4];
9
+ arguments[4] = undefined;
10
+ arguments.length--;
11
+ }
12
+ this.templateType = arguments[3];
13
+ // this is a tweak for node 4 this can be translated
14
+ // to ...arguments instead in upcoming node versions
15
+ const Comp = File.bind.apply(File, [null].concat(dbmUtil.toArray(arguments)));
16
+ this.file = new Comp();
17
+ };
18
+
19
+ Template.prototype.defaultCoffeeTemplate = function () {
20
+ return [
21
+ "'use strict';",
22
+ '',
23
+ 'dbm = undefined',
24
+ 'type = undefined',
25
+ 'seed = undefined',
26
+ '',
27
+ 'exports.setup = (options, seedLink) ->',
28
+ ' dbm = options.dbmigrate',
29
+ ' type = dbm.dataType',
30
+ ' seed = seedLink',
31
+ '',
32
+ 'exports.up = (db) ->',
33
+ ' null',
34
+ '',
35
+ 'exports.down = (db) ->',
36
+ ' null',
37
+ '',
38
+ ''
39
+ ].join('\n');
40
+ };
41
+
42
+ Template.prototype.defaultJsTemplate = function () {
43
+ return [
44
+ "'use strict';",
45
+ '',
46
+ 'var dbm;',
47
+ 'var type;',
48
+ 'var seed;',
49
+ '',
50
+ '/**',
51
+ ' * We receive the dbmigrate dependency from dbmigrate initially.',
52
+ ' * This enables us to not have to rely on NODE_PATH.',
53
+ ' */',
54
+ 'exports.setup = function(options, seedLink) {',
55
+ ' dbm = options.dbmigrate;',
56
+ ' type = dbm.dataType;',
57
+ ' seed = seedLink;',
58
+ '};',
59
+ '',
60
+ 'exports.up = function(db) {',
61
+ ' return null;',
62
+ '};',
63
+ '',
64
+ 'exports.down = function(db) {',
65
+ ' return null;',
66
+ '};',
67
+ '',
68
+ 'exports._meta = {',
69
+ ' "version": 1',
70
+ '};',
71
+ ''
72
+ ].join('\n');
73
+ };
74
+
75
+ Template.prototype.defaultSqlTemplate = function () {
76
+ return '/* Replace with your SQL commands */';
77
+ };
78
+
79
+ Template.prototype.sqlFileLoaderTemplate = function () {
80
+ return [
81
+ "'use strict';",
82
+ '',
83
+ 'var dbm;',
84
+ 'var type;',
85
+ 'var seed;',
86
+ "var fs = require('fs');",
87
+ "var path = require('path');",
88
+ 'var Promise;',
89
+ '',
90
+ '/**',
91
+ ' * We receive the dbmigrate dependency from dbmigrate initially.',
92
+ ' * This enables us to not have to rely on NODE_PATH.',
93
+ ' */',
94
+ 'exports.setup = function(options, seedLink) {',
95
+ ' dbm = options.dbmigrate;',
96
+ ' type = dbm.dataType;',
97
+ ' seed = seedLink;',
98
+ ' Promise = options.Promise;',
99
+ '};',
100
+ '',
101
+ 'exports.up = function(db) {',
102
+ " var filePath = path.join(__dirname, 'sqls', '" +
103
+ this.file.name.replace('.js', '') +
104
+ "-up.sql');",
105
+ ' return new Promise( function( resolve, reject ) {',
106
+ " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){",
107
+ ' if (err) return reject(err);',
108
+ " console.log('received data: ' + data);",
109
+ '',
110
+ ' resolve(data);',
111
+ ' });',
112
+ ' })',
113
+ ' .then(function(data) {',
114
+ ' return db.runSql(data);',
115
+ ' });',
116
+ '};',
117
+ '',
118
+ 'exports.down = function(db) {',
119
+ " var filePath = path.join(__dirname, 'sqls', '" +
120
+ this.file.name.replace('.js', '') +
121
+ "-down.sql');",
122
+ ' return new Promise( function( resolve, reject ) {',
123
+ " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){",
124
+ ' if (err) return reject(err);',
125
+ " console.log('received data: ' + data);",
126
+ '',
127
+ ' resolve(data);',
128
+ ' });',
129
+ ' })',
130
+ ' .then(function(data) {',
131
+ ' return db.runSql(data);',
132
+ ' });',
133
+ '};',
134
+ '',
135
+ 'exports._meta = {',
136
+ ' "version": 1',
137
+ '};',
138
+ ''
139
+ ].join('\n');
140
+ };
141
+
142
+ Template.prototype.sqlFileLoaderIgnoreOnInitTemplate = function () {
143
+ return [
144
+ "'use strict';",
145
+ '',
146
+ 'var dbm;',
147
+ 'var type;',
148
+ 'var seed;',
149
+ "var fs = require('fs');",
150
+ "var path = require('path');",
151
+ 'var ignoreOnInit = false;',
152
+ 'var Promise;',
153
+ '',
154
+ '/**',
155
+ ' * We receive the dbmigrate dependency from dbmigrate initially.',
156
+ ' * This enables us to not have to rely on NODE_PATH.',
157
+ ' */',
158
+ 'exports.setup = function(options, seedLink) {',
159
+ ' dbm = options.dbmigrate;',
160
+ ' ignoreOnInit = options.ignoreOnInit;',
161
+ ' type = dbm.dataType;',
162
+ ' seed = seedLink;',
163
+ ' Promise = options.Promise;',
164
+ '};',
165
+ '',
166
+ 'exports.up = function(db, callback) {',
167
+ " var filePath = path.join(__dirname + '/sqls/" +
168
+ this.file.name.replace('.js', '') +
169
+ "-up.sql');",
170
+ ' if (!ignoreOnInit) {',
171
+ ' return new Promise( function( resolve, reject ) {',
172
+ " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){",
173
+ ' if (err) return reject(err);',
174
+ " console.log('received data: ' + data);",
175
+ '',
176
+ ' resolve(data);',
177
+ ' });',
178
+ ' })',
179
+ ' .then(function(data) {',
180
+ ' return db.runSql(data);',
181
+ ' });',
182
+ ' }',
183
+ ' else {',
184
+ " console.log('ignoring on init: ' + filePath)",
185
+ ' return null;',
186
+ ' }',
187
+ '};',
188
+ '',
189
+ 'exports.down = function(db, callback) {',
190
+ " var filePath = path.join(__dirname + '/sqls/" +
191
+ this.file.name.replace('.js', '') +
192
+ "-down.sql');",
193
+ ' return new Promise( function( resolve, reject ) {',
194
+ " fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){",
195
+ ' if (err) return reject(err);',
196
+ " console.log('received data: ' + data);",
197
+ '',
198
+ ' resolve(data);',
199
+ ' });',
200
+ ' })',
201
+ ' .then(function(data) {',
202
+ ' return db.runSql(data);',
203
+ ' });',
204
+ '};',
205
+ '',
206
+ 'exports._meta = {',
207
+ ' "version": 1',
208
+ '};',
209
+ ''
210
+ ].join('\n');
211
+ };
212
+
213
+ Template.prototype.coffeeSqlFileLoaderTemplate = function () {
214
+ return [
215
+ "'use strict';",
216
+ '',
217
+ 'dbm = undefined',
218
+ 'type = undefined',
219
+ 'seed = undefined',
220
+ "fs = require 'fs'",
221
+ "path = require 'path'",
222
+ '',
223
+ '#',
224
+ '# We receive the dbmigrate dependency from dbmigrate initially.',
225
+ '# This enables us to not have to rely on NODE_PATH.',
226
+ '#',
227
+ 'exports.setup = (options, seedLink) ->',
228
+ ' dbm = options.dbmigrate',
229
+ ' type = dbm.dataType',
230
+ ' seed = seedLink',
231
+ '',
232
+ '',
233
+ 'exports.up = (db, callback) ->',
234
+ ' filePath = path.join "#{__dirname}/sqls/' +
235
+ this.file.name.replace('.coffee', '') +
236
+ '-up.sql"',
237
+ " fs.readFile filePath, {encoding: 'utf-8'}, (err,data) ->",
238
+ ' return callback err if err',
239
+ '',
240
+ ' db.runSql data, callback',
241
+ '',
242
+ 'exports.down = (db, callback) ->',
243
+ ' filePath = path.join "#{__dirname}/sqls/' +
244
+ this.file.name.replace('.coffee', '') +
245
+ '-down.sql"',
246
+
247
+ " fs.readFile filePath, {encoding: 'utf-8'}, (err,data) ->",
248
+ ' return callback err if err',
249
+ '',
250
+ ' db.runSql data, callback',
251
+ ''
252
+ ].join('\n');
253
+ };
254
+
255
+ Template.TemplateType = {
256
+ DEFAULT_JS: 0,
257
+ DEFAULT_SQL: 1,
258
+ SQL_FILE_LOADER: 2,
259
+ DEFAULT_COFFEE: 3,
260
+ COFFEE_SQL_FILE_LOADER: 4,
261
+ SQL_FILE_LOADER_IGNORE_ON_INIT: 5,
262
+ V2_DEFAULT: 6
263
+ };
264
+
265
+ Template.prototype.getTemplate = function () {
266
+ let plugin = false;
267
+
268
+ switch (this.templateType) {
269
+ case Template.TemplateType.DEFAULT_SQL:
270
+ return this.defaultSqlTemplate();
271
+ case Template.TemplateType.SQL_FILE_LOADER:
272
+ return this.sqlFileLoaderTemplate();
273
+ case Template.TemplateType.DEFAULT_COFFEE:
274
+ return this.defaultCoffeeTemplate();
275
+ case Template.TemplateType.COFFEE_SQL_FILE_LOADER:
276
+ return this.coffeeSqlFileLoaderTemplate();
277
+ case Template.TemplateType.SQL_FILE_LOADER_IGNORE_ON_INIT:
278
+ return this.sqlFileLoaderIgnoreOnInitTemplate();
279
+ case Template.TemplateType.DEFAULT_JS:
280
+ return this.defaultJsTemplate();
281
+ case Template.TemplateType.V2_DEFAULT:
282
+ return require('./templates/v2.js')();
283
+ default:
284
+ if (this.plugins) {
285
+ plugin = this.plugins.overwrite(
286
+ `template:overwrite:provider:${this.templateType}`
287
+ );
288
+ }
289
+
290
+ if (plugin !== false) {
291
+ try {
292
+ return plugin[`template:overwrite:provider:${this.templateType}`]({
293
+ file: {
294
+ name: this.file.name
295
+ }
296
+ });
297
+ } catch (ex) {
298
+ log.error('Plugin failure "' + plugin.name + '", arborting!');
299
+
300
+ throw ex;
301
+ }
302
+ } else {
303
+ return this.defaultJsTemplate();
304
+ }
305
+ }
306
+ };
307
+
308
+ Template.prototype.write = function (callback) {
309
+ return this.file.write(this.getTemplate()).nodeify(callback);
310
+ };
311
+
312
+ module.exports = Template;
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ module.exports = () => `'use strict';
4
+
5
+ exports.migrate = async (db, opt) => {
6
+ const type = opt.dbm.dataType;
7
+ return null;
8
+ };
9
+
10
+ exports._meta = {
11
+ version: 2
12
+ };`;
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ function isPromise (probe) {
4
+ return (
5
+ probe instanceof Promise ||
6
+ (probe &&
7
+ probe.then &&
8
+ probe.constructor &&
9
+ probe.constructor.name === 'Promise')
10
+ );
11
+ }
12
+
13
+ /**
14
+ * Backwards compatibility function.
15
+ *
16
+ * This ensures old migrations can still be executed by allowing them
17
+ * to still use callbacks or promises. This function ensures that every
18
+ * execution context may be returned only once (since callbacks can be called
19
+ * multiple times) and is basically FI(-only-)FO function.
20
+ */
21
+ function maybePromised (context, action, params) {
22
+ let cbExecuted = false;
23
+
24
+ return new Promise((resolve, reject) => {
25
+ const r = err => {
26
+ if (cbExecuted === false) {
27
+ cbExecuted = true;
28
+
29
+ if (err) {
30
+ reject(err);
31
+ } else {
32
+ resolve();
33
+ }
34
+ }
35
+ };
36
+
37
+ params[params.length++] = r;
38
+
39
+ if (typeof action === 'function') action = action.apply(context, params);
40
+ if (action === null) action = Promise.resolve();
41
+
42
+ if (isPromise(action)) {
43
+ action
44
+ .then(() => {
45
+ if (cbExecuted === false) {
46
+ cbExecuted = true;
47
+ resolve();
48
+ }
49
+ })
50
+ .catch(err => {
51
+ if (cbExecuted === false) {
52
+ cbExecuted = true;
53
+ reject(err);
54
+ }
55
+ });
56
+ }
57
+ });
58
+ }
59
+
60
+ module.exports = {
61
+ maybePromised: maybePromised
62
+ };