Skip to content

Commit

Permalink
feat(transitioner): add transitioner to easen the process of protocol…
Browse files Browse the repository at this point in the history
… changes

Resolves #403
  • Loading branch information
wzrdtales committed Sep 28, 2016
1 parent 30560a3 commit a704fec
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 49 deletions.
34 changes: 34 additions & 0 deletions lib/transitions/1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

/**
* Our first transition is actually the removal of globals and
* introducing the setup routine.
* Thus the body of this transition is just an empty function, but displays
* as all transitions an explanation to the user.
*/
module.exports = {

transition: function() {

},

message: function() {

console.log('Congratulations!\n\n' +
'You just migrated from protocol 0 to 1!\n' +
'What does that mean for you?\n' +
'Quite simple, from 0 to 1 we introduced the setup function and we' +
'deprecated some globals, like async or dbm. What this transition does is' +
' grabbing your migrations, replacing the async and dbm definitions and ' +
'inserting the setup body if not present.\n' +
'It might be possible, that you still run into errors, for example if ' +
'you already have had a setup body, it wont be replaced and you might ' +
'be missing the default routine of the setup, which provides for example ' +
'the dataTypes to your migration.\n\n' +
'What do I need to do now?\n' +
'Try to rexecute all of your migrations and watch if you run into any ' +
'Errors, if you encounter any, you need to manually fix those ' +
'problems. But don\'t worry, this protocol transitions happen very ' +
'rarely!\n'
);
}
};
86 changes: 47 additions & 39 deletions lib/transitions/transitioner.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,66 @@ var updateVersion = require('./update-version.js');
var ask = require('./ask.js');
var log = require('db-migrate-shared').log;

var internals = {
migrationProtcol: 1,
cwd: process.cwd()
};
module.exports = function(internals) {

ask(
{
properties: {
safe: {
description: 'This process is going to alter your migrations. We ' +
'highly recommend you to backup your migrations or even better safe ' +
'the current state with git versioning.\nPlease make sure you don\'t ' +
'blow up yourself.\n\nDo you want to continue? [y/n]',
message: 'Invalid answer! Do you want to continue? [y/n]',
type: 'string',
default: 'n',
conform: function(value) {

ask(
{
properties: {
safe: {
description: 'This process is going to alter your migrations. We ' +
'highly recommend you to backup your migrations or even better safe ' +
'the current state with git versioning.\nPlease make sure you don\'t ' +
'blow up yourself.\n\nDo you want to continue? [y/n]',
message: 'Invalid answer! Do you want to continue? [y/n]',
type: 'string',
default: 'n',
conform: function(value) {

return value === 'y' || value === 'n';
return value === 'y' || value === 'n';
}
}
}
}
}, function(err) {
}, function(err) {

if(err)
return;
if(err)
return;

Migration.loadFromFilesystem('migrations/', internals,
Migration.loadFromFilesystem('migrations/', internals,
function(err, migrations) {

migrations.forEach(function(migration) {
var messages = [];

migrations.forEach(function(migration) {

var required = tryRequire(migration, internals);
var version = (required._meta && required._meta.version) ?
required._meta.version
: 0;
var required = tryRequire(migration, internals);
var version = (required._meta && required._meta.version) ?
required._meta.version
: 0;

if(version !== internals.migrationProtcol) {
if(version !== internals.migrationProtocol) {

var i;
var i;

for(i = 0; i < internals.migrationProtocol; ++i) {
for(i = 0; i < internals.migrationProtocol; ++i) {

var transition = require('./' + i + 1);
updateVersion(required, migration, internals, i + 1);
var transition = require('./' + (i + 1));
transition.transition();
messages[i + 1] = transition.message;

updateVersion(required, migration, internals, i + 1);
log.info('Transitioned ' + migration.name + '.');
}
}
}
else {
else {

log.info(migration.name, 'was already transitioned to version ' +
internals.migrationProtcol + '.');
}
log.verbose(migration.name, 'was already transitioned to version ' +
internals.migrationProtocol + '.');
}
});

messages.forEach(function(message) {
message();
});
});
});
});
};
53 changes: 43 additions & 10 deletions lib/transitions/try-require.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,49 @@
var log = require('db-migrate-shared').log;
var fs = require('fs');
var cp = require('child_process');

var handled = false;
var installed = false;
var removedGlobals = {
'dbm is not defined': globalHandler,
'async is not defined': globalHandler
'async is not defined': globalHandler,
'Cannot find module \'async\'': installAsync
};

function installAsync(migration, retry) {

var cmd = [ 'install', '--save', 'async' ];

if(installed)
retry();
else
installed = true;

log.info('Installing async...');
cp.spawnSync('npm', cmd, {
cwd: migration.internals.cwd,
stdio: 'inherit'
});

return retry();
}

function globalHandler(migration, retry) {

var data = fs.readFileSync(migration, 'utf8');
data = data.replace(
/^dbm = dbm \|\| require\(\s+'db-migrate'\s+\)/m,
'var dbm'
);
data = data.replace(
/^async = async \|\| require\(\s+'async'\s+\)/m,
'var async = require( \'async\' )'
);

if(data.indexOf('async = async || require') !== -1) {

handled = true;
data = data.replace(
/^async = async \|\| require\(\s+'async'\s+\)/m,
'var async = require( \'async\' )'
);
}
data = data.replace(
/^var type = dbm.dataType/m,
'var type'
Expand All @@ -38,20 +64,20 @@ function tryRequire(migration) {

try {

if(handled) {
if(handled && !installed) {

//require(migration.internals.cwd + 'package.json')
//cp npm install --save async
return installAsync(
migration,
tryRequire.bind(this, migration)
);
}

return require(migration.internals.cwd + '/' + migration.path);
}
catch(ex) {
if(ex instanceof ReferenceError) {

if(removedGlobals[ex.message]) {

handled = true;
log.info(ex.message, 'Initiating removal of old globals...');
return removedGlobals[ex.message](
migration.path,
Expand All @@ -70,6 +96,13 @@ function tryRequire(migration) {
'fix the issues and rerun the transitioner again.');
}
}
else if(removedGlobals[ex.message]) {

return removedGlobals[ex.message](
migration,
tryRequire.bind(this, migration)
);
}
else {

log.error(ex.stack, migration);
Expand Down

0 comments on commit a704fec

Please sign in to comment.