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
|
@@ -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.sync(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,54 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var assert = require('assert');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var log = require('db-migrate-shared').log;
|
|
6
|
+
var _assert = require('./helper/assert');
|
|
7
|
+
|
|
8
|
+
function executeUndoSeed (internals, config, callback) {
|
|
9
|
+
var index = require('./connect');
|
|
10
|
+
var Seeder = require('./lib/walker.js');
|
|
11
|
+
|
|
12
|
+
if (!internals.argv.count) {
|
|
13
|
+
log.info('Defaulting to running 1 down seed.');
|
|
14
|
+
internals.argv.count = 1;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (internals.argv._.length > 0) {
|
|
18
|
+
internals.argv.destination = internals.argv._.shift().toString();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
index.connect(
|
|
22
|
+
{
|
|
23
|
+
config: config.getCurrent().settings,
|
|
24
|
+
internals: internals,
|
|
25
|
+
prefix: 'seed'
|
|
26
|
+
},
|
|
27
|
+
Seeder,
|
|
28
|
+
function (err, seeder) {
|
|
29
|
+
assert.ifError(err);
|
|
30
|
+
|
|
31
|
+
var seedDir =
|
|
32
|
+
internals.mode !== 'static' ? 'vcseeder-dir' : 'staticseeder-dir';
|
|
33
|
+
|
|
34
|
+
seeder.seedDir = path.resolve(internals.argv[seedDir]);
|
|
35
|
+
|
|
36
|
+
if (internals.mode === 'static') {
|
|
37
|
+
internals.onComplete(seeder, callback, {
|
|
38
|
+
stack: "Static seeders can't be undone. Use VC Seeders instead!"
|
|
39
|
+
});
|
|
40
|
+
} else {
|
|
41
|
+
seeder.createSeedsTable(function (err) {
|
|
42
|
+
if (_assert(err, callback)) {
|
|
43
|
+
seeder.down(
|
|
44
|
+
internals.argv,
|
|
45
|
+
internals.onComplete.bind(this, seeder, internals, callback)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = executeUndoSeed;
|
|
@@ -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.up(internals.argv);
|
|
48
|
+
return internals.onComplete(migrator, internals, null, res);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
return internals.onComplete(migrator, internals, err);
|
|
51
|
+
}
|
|
52
|
+
};
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
var fs = require('fs');
|
|
2
|
+
var path = require('path');
|
|
3
|
+
var parseDatabaseUrl = require('parse-database-url');
|
|
4
|
+
var dbmUtil = require('db-migrate-shared').util;
|
|
5
|
+
var log = require('db-migrate-shared').log;
|
|
6
|
+
|
|
7
|
+
var setCurrent = (exports.setCurrent = function (env) {
|
|
8
|
+
env = dbmUtil.isArray(env) ? env : [env];
|
|
9
|
+
env.forEach(
|
|
10
|
+
function (current) {
|
|
11
|
+
if (dbmUtil.isString(current) && this[current]) {
|
|
12
|
+
this.getCurrent = function () {
|
|
13
|
+
return {
|
|
14
|
+
env: current,
|
|
15
|
+
settings: this[current]
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}.bind(this)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
if (!this.getCurrent) {
|
|
23
|
+
throw new Error("Environment(s) '" + env.join(', ') + "' not found.");
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
function Config () {}
|
|
28
|
+
|
|
29
|
+
Config.prototype = {
|
|
30
|
+
setCurrent: setCurrent
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
exports.load = function (config, currentEnv) {
|
|
34
|
+
if (typeof config === 'object') {
|
|
35
|
+
return exports.loadObject(config, currentEnv);
|
|
36
|
+
} else {
|
|
37
|
+
return exports.loadFile(config, currentEnv);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
exports.loadFile = function (fileName, currentEnv, plugins) {
|
|
42
|
+
var config;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
fs.statSync(fileName);
|
|
46
|
+
} catch (e) {
|
|
47
|
+
if (!process.env.DATABASE_URL) {
|
|
48
|
+
throw new Error("Could not find database config file '" + fileName + "'");
|
|
49
|
+
} else {
|
|
50
|
+
return exports.loadUrl(process.env.DATABASE_URL, currentEnv);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
var plugin = false;
|
|
56
|
+
|
|
57
|
+
if (plugins) {
|
|
58
|
+
plugin = plugins.overwrite('init:config:overwrite:require');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (plugin !== false) {
|
|
62
|
+
try {
|
|
63
|
+
config = plugin['init:config:overwrite:require'](fileName);
|
|
64
|
+
} catch (ex) {
|
|
65
|
+
log.warn(
|
|
66
|
+
'Plugin failure "' +
|
|
67
|
+
plugin.name +
|
|
68
|
+
'", falling back to default behavior!'
|
|
69
|
+
);
|
|
70
|
+
log.verbose(ex);
|
|
71
|
+
|
|
72
|
+
config = require(fileName);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
config = require(fileName);
|
|
76
|
+
}
|
|
77
|
+
} catch (e) {
|
|
78
|
+
// distinguish broken files from missing ones
|
|
79
|
+
if (e instanceof SyntaxError) {
|
|
80
|
+
throw e;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
config = require(path.join(process.cwd(), fileName));
|
|
85
|
+
} catch (e) {
|
|
86
|
+
if (!process.env.DATABASE_URL) {
|
|
87
|
+
throw e;
|
|
88
|
+
} else {
|
|
89
|
+
return exports.loadUrl(process.env.DATABASE_URL, currentEnv);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return exports.loadObject(config, currentEnv);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
function walkConfig (level) {
|
|
98
|
+
for (var configEntry in level) {
|
|
99
|
+
if (level[configEntry] && level[configEntry].ENV) {
|
|
100
|
+
if (!process.env[level[configEntry].ENV]) {
|
|
101
|
+
log.verbose(
|
|
102
|
+
'Environment variable ' + level[configEntry].ENV + ' is empty!'
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
level[configEntry] = process.env[level[configEntry].ENV];
|
|
107
|
+
} else if (level[configEntry] && typeof level[configEntry] === 'object') {
|
|
108
|
+
level[configEntry] = walkConfig(level[configEntry]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return level;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
exports.loadObject = function (_config, currentEnv) {
|
|
116
|
+
var out = new Config();
|
|
117
|
+
// do not overwrite the users config
|
|
118
|
+
var config = JSON.parse(JSON.stringify(_config));
|
|
119
|
+
|
|
120
|
+
for (var env in config) {
|
|
121
|
+
if (config[env].ENV) {
|
|
122
|
+
if (!process.env[config[env].ENV]) {
|
|
123
|
+
log.verbose('Environment variable ' + config[env].ENV + ' is empty!');
|
|
124
|
+
} else {
|
|
125
|
+
out[env] = parseDatabaseUrl(process.env[config[env].ENV]);
|
|
126
|
+
}
|
|
127
|
+
} else if (typeof config[env] === 'string') {
|
|
128
|
+
out[env] = parseDatabaseUrl(config[env]);
|
|
129
|
+
} else {
|
|
130
|
+
// Check config entry's for ENV objects
|
|
131
|
+
// which will tell us to grab configuration from the environment
|
|
132
|
+
config[env] = walkConfig(config[env]);
|
|
133
|
+
out[env] = config[env];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (typeof config[env].url === 'string' || process.env.DATABASE_URL) {
|
|
137
|
+
if (typeof config[env].url !== 'string') {
|
|
138
|
+
config[env] = Object.assign(
|
|
139
|
+
config[env],
|
|
140
|
+
parseDatabaseUrl(process.env.DATABASE_URL)
|
|
141
|
+
);
|
|
142
|
+
} else {
|
|
143
|
+
config[env] = Object.assign(
|
|
144
|
+
config[env],
|
|
145
|
+
parseDatabaseUrl(config[env].url)
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
delete config[env].url;
|
|
149
|
+
} else if (config[env].url && config[env].url.value) {
|
|
150
|
+
config[env].url = config[env].url.value;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (config[env].overwrite || config[env].addIfNotExists) {
|
|
154
|
+
var overwrite = config[env].overwrite || {};
|
|
155
|
+
|
|
156
|
+
if (config[env].addIfNotExists) {
|
|
157
|
+
var addIfNotExists = config[env].addIfNotExists;
|
|
158
|
+
Object.keys(addIfNotExists)
|
|
159
|
+
.filter(function (key) {
|
|
160
|
+
return !overwrite[key] && !config[env][key];
|
|
161
|
+
})
|
|
162
|
+
.forEach(function (key) {
|
|
163
|
+
config[env][key] = addIfNotExists[key];
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
delete config[env].addIfNotExists;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
Object.keys(overwrite).forEach(function (key) {
|
|
170
|
+
config[env][key] = overwrite[key];
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
delete config[env].overwrite;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (currentEnv) {
|
|
178
|
+
out.setCurrent(currentEnv);
|
|
179
|
+
} else if (config.default) {
|
|
180
|
+
out.setCurrent(config.default);
|
|
181
|
+
} else if (config.defaultEnv) {
|
|
182
|
+
if (config.defaultEnv.ENV) {
|
|
183
|
+
out.setCurrent(process.env[config.defaultEnv.ENV]);
|
|
184
|
+
} else {
|
|
185
|
+
out.setCurrent(config.defaultEnv);
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
out.setCurrent(['dev', 'development']);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return out;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
exports.loadUrl = function (databaseUrl, currentEnv) {
|
|
195
|
+
var config = parseDatabaseUrl(databaseUrl);
|
|
196
|
+
var out = new Config();
|
|
197
|
+
|
|
198
|
+
if (currentEnv) {
|
|
199
|
+
out[currentEnv] = config;
|
|
200
|
+
out.setCurrent(currentEnv);
|
|
201
|
+
} else {
|
|
202
|
+
out.urlConfig = config;
|
|
203
|
+
out.setCurrent('urlConfig');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return out;
|
|
207
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
var internals = {};
|
|
2
|
+
|
|
3
|
+
internals.mod = {};
|
|
4
|
+
internals.mod.log = require('db-migrate-shared').log;
|
|
5
|
+
internals.mod.type = require('db-migrate-shared').dataType;
|
|
6
|
+
var Shadow = require('./shadow');
|
|
7
|
+
var log = internals.mod.log;
|
|
8
|
+
var Promise = require('bluebird');
|
|
9
|
+
var SeederInterface = require('../interface/seederInterface.js');
|
|
10
|
+
var MigratorInterface = require('../interface/migratorInterface.js');
|
|
11
|
+
var resolve = require('resolve');
|
|
12
|
+
|
|
13
|
+
var ShadowProto = {
|
|
14
|
+
createTable: function () {
|
|
15
|
+
return Promise.resolve();
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
exports.connect = function (config, intern, callback) {
|
|
20
|
+
var driver, req;
|
|
21
|
+
let plugin = false;
|
|
22
|
+
const { plugins } = intern;
|
|
23
|
+
|
|
24
|
+
var mod = internals.mod;
|
|
25
|
+
internals = intern;
|
|
26
|
+
internals.mod = mod;
|
|
27
|
+
|
|
28
|
+
// add interface extensions to allow drivers to add new methods
|
|
29
|
+
internals.interfaces = {
|
|
30
|
+
SeederInterface: SeederInterface.extending,
|
|
31
|
+
MigratorInterface: MigratorInterface.extending
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (!config.user && config.username) {
|
|
35
|
+
config.user = config.username;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (config.driver === undefined) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
'config must include a driver key specifing which driver to use'
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (config.driver && typeof config.driver === 'object') {
|
|
45
|
+
log.verbose('require:', config.driver.require);
|
|
46
|
+
driver = require(config.driver.require);
|
|
47
|
+
} else {
|
|
48
|
+
switch (config.driver) {
|
|
49
|
+
case 'sqlite':
|
|
50
|
+
config.driver = 'sqlite3';
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case 'postgres':
|
|
54
|
+
case 'postgresql':
|
|
55
|
+
config.driver = 'pg';
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
req = 'db-migrate-' + config.driver;
|
|
61
|
+
log.verbose('require:', req);
|
|
62
|
+
try {
|
|
63
|
+
driver = require(resolve.sync(req, { basedir: process.cwd() }));
|
|
64
|
+
} catch (e1) {
|
|
65
|
+
try {
|
|
66
|
+
driver = require(req);
|
|
67
|
+
} catch (e2) {
|
|
68
|
+
driver = require('../../../' + req);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} catch (e3) {
|
|
72
|
+
try {
|
|
73
|
+
// Fallback to internal drivers, while moving drivers to new repos
|
|
74
|
+
req = './' + config.driver;
|
|
75
|
+
log.verbose('require:', req);
|
|
76
|
+
driver = require(req);
|
|
77
|
+
} catch (e4) {
|
|
78
|
+
return callback(
|
|
79
|
+
new Error(
|
|
80
|
+
'No such driver found, please try to install it via ' +
|
|
81
|
+
'npm install db-migrate-' +
|
|
82
|
+
config.driver +
|
|
83
|
+
' or ' +
|
|
84
|
+
'npm install -g db-migrate-' +
|
|
85
|
+
config.driver
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
log.verbose('connecting');
|
|
93
|
+
|
|
94
|
+
var connect = function (config) {
|
|
95
|
+
driver.connect(config, intern, function (err, db) {
|
|
96
|
+
if (err) {
|
|
97
|
+
callback(err);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
log.verbose('connected');
|
|
101
|
+
|
|
102
|
+
if (!global.immunity) {
|
|
103
|
+
db = Shadow.infect(db, internals, ShadowProto);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
callback(null, db);
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
if (config.tunnel) {
|
|
111
|
+
var tunnel = require('tunnel-ssh');
|
|
112
|
+
var tunnelConfig = JSON.parse(JSON.stringify(config.tunnel));
|
|
113
|
+
const { tunnelType } = tunnelConfig;
|
|
114
|
+
|
|
115
|
+
if (plugins) {
|
|
116
|
+
plugin = plugins.overwrite(
|
|
117
|
+
`connection:tunnel:${
|
|
118
|
+
tunnelType && tunnelType !== 'ssh' ? tunnelType : 'ssh'
|
|
119
|
+
}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
tunnelConfig.dstHost = config.host;
|
|
124
|
+
tunnelConfig.dstPort = config.port;
|
|
125
|
+
|
|
126
|
+
if (plugin) {
|
|
127
|
+
tunnel = plugin[
|
|
128
|
+
`connection:tunnel:${
|
|
129
|
+
tunnelType && tunnelType !== 'ssh' ? tunnelType : 'ssh'
|
|
130
|
+
}`
|
|
131
|
+
](tunnelConfig);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (tunnelConfig.privateKeyPath) {
|
|
135
|
+
tunnelConfig.privateKey = require('fs').readFileSync(
|
|
136
|
+
tunnelConfig.privateKeyPath
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Reassign the db host/port to point to our local ssh tunnel
|
|
141
|
+
config.host = '127.0.0.1';
|
|
142
|
+
config.port = tunnelConfig.localPort;
|
|
143
|
+
|
|
144
|
+
tunnel(tunnelConfig, function (err) {
|
|
145
|
+
if (err) {
|
|
146
|
+
callback(err);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
log.verbose('SSH tunnel connected on port ', tunnelConfig.localPort);
|
|
150
|
+
|
|
151
|
+
connect(config);
|
|
152
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
connect(config);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shadow driver is basically a MITM object. Or in other words:
|
|
3
|
+
*
|
|
4
|
+
* This shadow is very infectius. It infects other objects and overwrite their
|
|
5
|
+
* behavior. It gets a shadow part of this object and executes various
|
|
6
|
+
* actions.
|
|
7
|
+
*
|
|
8
|
+
* In our case, it records the execution of methods.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 'Infect' the original class
|
|
13
|
+
*/
|
|
14
|
+
exports.infect = function (db, intern, ShadowProto) {
|
|
15
|
+
const newDb = {};
|
|
16
|
+
if (db._shadowsHost || db._shadowProto) {
|
|
17
|
+
throw new Error("Can't shadow a shadow!");
|
|
18
|
+
}
|
|
19
|
+
newDb._shadowsHost = {};
|
|
20
|
+
newDb._shadowProto = {};
|
|
21
|
+
|
|
22
|
+
for (var prop in db) {
|
|
23
|
+
if (
|
|
24
|
+
typeof ShadowProto[prop] === 'function' &&
|
|
25
|
+
typeof db[prop] === 'function'
|
|
26
|
+
) {
|
|
27
|
+
newDb._shadowsHost[prop] = db[prop];
|
|
28
|
+
newDb._shadowProto[prop] = ShadowProto[prop];
|
|
29
|
+
|
|
30
|
+
(function (property) {
|
|
31
|
+
newDb[property] = function () {
|
|
32
|
+
var params = arguments;
|
|
33
|
+
var self = this;
|
|
34
|
+
|
|
35
|
+
return self._shadowProto[property]
|
|
36
|
+
.apply(self, params)
|
|
37
|
+
.then(function () {
|
|
38
|
+
return self._shadowsHost[property].apply(self, params);
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
})(prop);
|
|
42
|
+
} else {
|
|
43
|
+
newDb[prop] = db[prop];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return newDb;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 'Overshadow' the original class
|
|
52
|
+
*
|
|
53
|
+
* This basically overwrites methods existent from the original
|
|
54
|
+
* with a provided replacement. If no replacement was found, it will overwrite
|
|
55
|
+
* with an error instead, which needs to be supplied as a fallback.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
exports.overshadow = function (db, ShadowProto, ShadowError) {
|
|
59
|
+
const newDb = Object.assign({}, ShadowProto);
|
|
60
|
+
newDb.prototype = Object.assign({}, ShadowProto.prototype);
|
|
61
|
+
|
|
62
|
+
for (var prop in db) {
|
|
63
|
+
if (
|
|
64
|
+
typeof ShadowProto[prop] === 'function' &&
|
|
65
|
+
typeof db[prop] === 'function'
|
|
66
|
+
) {
|
|
67
|
+
newDb[prop] = ShadowProto[prop];
|
|
68
|
+
} else if (typeof db[prop] === 'function') {
|
|
69
|
+
newDb[prop] = ShadowError(prop);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return newDb;
|
|
74
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Promise = require('bluebird');
|
|
4
|
+
const maybePromised = require('../../temputils.js').maybePromised;
|
|
5
|
+
|
|
6
|
+
const execUnit = {
|
|
7
|
+
up: function (context, driver, file) {
|
|
8
|
+
return context.driver
|
|
9
|
+
.startMigration()
|
|
10
|
+
.then(() => {
|
|
11
|
+
const _file = file.get();
|
|
12
|
+
|
|
13
|
+
if (typeof _file.setup === 'function') {
|
|
14
|
+
_file.setup(context.internals.safeOptions, context.seedLink);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return maybePromised(file, _file.up, [context.driver]);
|
|
18
|
+
})
|
|
19
|
+
.then(() => {
|
|
20
|
+
return Promise.promisify(context.writeMigrationRecord.bind(context))(
|
|
21
|
+
file
|
|
22
|
+
);
|
|
23
|
+
})
|
|
24
|
+
.then(context.driver.endMigration.bind(context.driver));
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
down: function (context, driver, file) {
|
|
28
|
+
return driver
|
|
29
|
+
.startMigration()
|
|
30
|
+
.then(() => {
|
|
31
|
+
const _file = file.get();
|
|
32
|
+
|
|
33
|
+
if (typeof _file.setup === 'function') {
|
|
34
|
+
_file.setup(context.internals.safeOptions, context.seedLink);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return maybePromised(file, _file.down, [context.driver]);
|
|
38
|
+
})
|
|
39
|
+
.then(() => {
|
|
40
|
+
return Promise.promisify(context.deleteMigrationRecord.bind(context))(
|
|
41
|
+
file
|
|
42
|
+
);
|
|
43
|
+
})
|
|
44
|
+
.then(context.driver.endMigration.bind(context.driver));
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
module.exports = execUnit;
|