Skip to content

Commit c6900d9

Browse files
committed
Adding a lot of events and extracting output to separate module
1 parent 894431f commit c6900d9

File tree

6 files changed

+314
-161
lines changed

6 files changed

+314
-161
lines changed

bin/klei-migrate

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#!/usr/bin/env node
22

3-
var cli = require('../lib/cli');
3+
var cli = require('../lib/cli'),
4+
reporter = require('../lib/reporter');
45

5-
cli.init().exec(function () {
6-
console.log(arguments);
7-
process.exit();
8-
});
6+
cli.init().reporter(reporter).exec();

lib/cli.js

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ var options = {
2222
commands = {
2323
run: "Run migrations",
2424
create: "Create a new migration (optional name as [arguments])",
25-
dry: "List what is able to migrate (according to direction and limit)",
26-
help: "Show this usage information",
27-
version: "Show version information"
25+
dry: "List what is able to migrate (according to direction and limit)"
2826
},
2927
aliases = {
3028
status: "dry",
@@ -39,7 +37,13 @@ exports.init = function (args) {
3937
var parsed = nopt(noptions.full, noptions.short, args, args ? 0 : 2),
4038
argv = parsed.argv.remain || [];
4139

42-
this.command(argv.shift());
40+
try {
41+
this.command(argv.shift());
42+
} catch (e) {
43+
this.help();
44+
console.error('\n' + e.message.red + '\n');
45+
process.exit(1);
46+
}
4347
this._showVersion = parsed.version;
4448
this._showHelp = parsed.help || this.command() === 'help';
4549
this.migrate = migrate;
@@ -55,6 +59,19 @@ exports.init = function (args) {
5559
return this;
5660
};
5761

62+
/**
63+
* Set reporter
64+
*
65+
* @param {Function} reporter
66+
*/
67+
exports.reporter = function (reporter) {
68+
if (!this.migrate) {
69+
throw new Error('Initialize the cli with init() first!');
70+
}
71+
this.reporter = reporter(this.migrate);
72+
return this;
73+
};
74+
5875
/**
5976
* Execute current klei-migrate command
6077
*/
@@ -133,6 +150,83 @@ exports.command = function (newCommand) {
133150
return this._newCommand = this._newCommand || 'help';
134151
};
135152

153+
/**
154+
* Set printer/output handler
155+
*
156+
* @param {Function} newPrinter
157+
*/
158+
exports.printer = function (newPrinter) {
159+
if (newPrinter) {
160+
this._printer = newPrinter;
161+
return this;
162+
}
163+
return this._printer = this._printer || function () { /* noop */ };
164+
};
165+
166+
/**
167+
* Log message to printer
168+
*
169+
* @param {String} msg
170+
*/
171+
exports.log = function (msg) {
172+
this.printer()(msg);
173+
return this;
174+
};
175+
176+
/**
177+
* Log info messages
178+
*
179+
* @param {String} msg
180+
*/
181+
exports.info = function (msg) {
182+
return this.log(msg.yellow);
183+
};
184+
185+
/**
186+
* Log debug messages
187+
*
188+
* @param {String} msg
189+
*/
190+
exports.debug = function (msg) {
191+
return this.log(msg.grey);
192+
};
193+
194+
/**
195+
* Log successful messages
196+
*
197+
* @param {String} msg
198+
*/
199+
exports.success = function (msg) {
200+
return this.log(msg.green);
201+
};
202+
203+
/**
204+
* Log bad messages
205+
*
206+
* @param {String} msg
207+
*/
208+
exports.bad = function (msg) {
209+
return this.log(msg.red);
210+
};
211+
212+
/**
213+
* Log errors
214+
*
215+
* @param {Error} err
216+
* @param {String} heading
217+
*/
218+
exports.error = function (err, heading) {
219+
if (heading) {
220+
this.log(heading.bold.red);
221+
}
222+
if (err instanceof Error) {
223+
this.log(err.stack.red);
224+
} else {
225+
this.log(err.toString().red);
226+
}
227+
return this;
228+
};
229+
136230
function getOptionsForNopt () {
137231
var result = {short: {}, full: {}};
138232
Object.keys(options).forEach(function (key) {

lib/migrate.js

Lines changed: 94 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,27 @@ exports.create = function (cb) {
6868
var name = +new Date + '_' + (this.args().join(' ').replace(/[\s\.]+/g, '_') || 'migration') + '.js';
6969

7070
var dir = this.directory();
71+
72+
ee.emit('create:init');
73+
7174
ensureExistingMigrationsDir(dir, function (err) {
7275
if (err) {
73-
cb(err);
76+
error(err, cb);
7477
return;
7578
}
7679
exports.template(function (err, template) {
7780
if (err) {
78-
cb(err);
81+
error(err, cb);
7982
return;
8083
}
84+
ee.emit('create:ready', name, dir);
8185
fs.writeFile(join(dir, name), template, 'utf8', function (err) {
82-
cb(err, name);
86+
if (err) {
87+
error(err, cb);
88+
} else {
89+
ee.emit('create:success', name, dir);
90+
cb && cb(null, name);
91+
}
8392
});
8493
});
8594
});
@@ -170,41 +179,12 @@ exports.directory = function (newDirectory) {
170179
* @param {Function} cb
171180
*/
172181
exports.dry = function (cb) {
173-
var dir = this.directory(),
174-
name = this.args().join(' ');
175-
fs.readdir(dir, function (err, files) {
176-
if (err) {
177-
cb([], {});
178-
return;
179-
}
180-
fs.readJson(join(dir, '.migrated.json'), function (err, migrated) {
181-
if (err || !migrated) {
182-
migrated = {};
183-
}
184-
185-
var down = isDown(exports.direction()),
186-
limit = exports.limit();
187-
188-
var migratable = files.filter(function (file) {
189-
return /^[0-9]{13}_.*\.js$/.test(file)
190-
&& (down && migrated[file] || !down && !migrated[file])
191-
&& (!name || !limit && (down && name <= file || !down && name >= file) || limit && name == file);
192-
});
193-
194-
migratable.sort();
195-
196-
if (down) {
197-
migratable.reverse();
198-
}
199-
200-
if (limit && migratable.length > 1) {
201-
migratable = [migratable.shift()];
202-
}
182+
ee.emit('dry:init');
203183

204-
cb(migratable, migrated);
205-
});
184+
return this.migratables(function (migratable, migrated) {
185+
ee.emit('dry:success', migratable, migrated);
186+
cb && cb(migratable, migrated);
206187
});
207-
return this;
208188
};
209189

210190
/**
@@ -215,11 +195,24 @@ exports.dry = function (cb) {
215195
exports.run = function (cb) {
216196
var self = this;
217197

218-
return this.dry(function (migratable, migrated) {
198+
ee.emit('run:init');
199+
200+
return this.migratables(function (migratable, migrated) {
201+
ee.emit('run:ready', migratable, migrated);
202+
203+
if (!migratable.length) {
204+
cb && cb(null, []);
205+
return;
206+
}
207+
219208
var migratedNow = [];
220209
function next (err, file) {
221-
if (err || !file) {
222-
cb(err, migratedNow);
210+
if (err) {
211+
cb ? cb(err, migratedNow) : ee.emit('error', err);
212+
return;
213+
} else if (!file) {
214+
ee.emit('run:success', migratedNow);
215+
cb && cb(null, migratedNow);
223216
return;
224217
}
225218

@@ -230,6 +223,7 @@ exports.run = function (cb) {
230223
}, self.timeout());
231224

232225
try {
226+
ee.emit('run:migrate:before', file);
233227
var migration = loadMigration(self.directory(), file);
234228
migration[self.direction()](function (err) {
235229
if (hasTimedout) {
@@ -238,12 +232,15 @@ exports.run = function (cb) {
238232
clearTimeout(timeoutId);
239233
if (!err) {
240234
migratedNow.push(file);
235+
ee.emit('run:migrate:after', file);
241236
saveProgress(migrated, file, doNext);
242237
} else {
238+
ee.emit('run:migrate:fail', err, file);
243239
doNext(err);
244240
}
245241
});
246242
} catch (e) {
243+
ee.emit('run:migrate:fail', e, file);
247244
next(e);
248245
}
249246
}
@@ -256,54 +253,68 @@ exports.run = function (cb) {
256253
});
257254
};
258255

259-
/**
260-
* Add event listener for event
261-
*
262-
* @param {String} event
263-
* @param {Function} cb Listener
264-
*/
265-
exports.on = function (event, cb) {
266-
ee.on(event, cb);
267-
};
256+
exports.migratables = function (cb) {
257+
var self = this,
258+
dir = this.directory(),
259+
name = this.args().join(' ');
260+
fs.readdir(dir, function (err, files) {
261+
if (err) {
262+
cb([], {});
263+
return;
264+
}
265+
fs.readJson(join(dir, '.migrated.json'), function (err, migrated) {
266+
if (err || !migrated) {
267+
migrated = {};
268+
}
268269

269-
/**
270-
* Trigger output event (with optional level)
271-
*
272-
* @param {String} msg
273-
* @param {String} level
274-
*/
275-
exports.output = function (msg, level) {
276-
ee.emit('output', msg);
277-
if (level) {
278-
ee.emit('output:' + level, msg);
279-
}
280-
};
270+
var down = isDown(exports.direction()),
271+
limit = exports.limit();
281272

282-
/**
283-
* Trigger output:info event
284-
*
285-
* @param {String} msg
286-
*/
287-
exports.info = function (msg) {
288-
this.output(msg, 'info');
289-
};
273+
var migratable = files.filter(function (file) {
274+
if (!/^[0-9]{13}_.*\.js$/.test(file))
275+
return false;
290276

291-
/**
292-
* Trigger output:debug event
293-
*
294-
* @param {String} msg
295-
*/
296-
exports.debug = function (msg) {
297-
this.output(msg, 'debug');
277+
if (down && !migrated[file] || !down && migrated[file])
278+
return false;
279+
280+
if (limit === 1 && name && name !== file) {
281+
return false;
282+
}
283+
284+
if (name && down && name > file)
285+
return false;
286+
287+
if (name && !down && name < file)
288+
return false;
289+
290+
return true;
291+
});
292+
293+
migratable.sort();
294+
295+
if (down) {
296+
migratable.reverse();
297+
}
298+
299+
if (limit) {
300+
migratable = migratable.slice(0, limit);
301+
}
302+
303+
cb(migratable, migrated);
304+
});
305+
});
306+
return this;
298307
};
299308

300309
/**
301-
* Trigger output:success event
310+
* Add event listener for event
302311
*
303-
* @param {String} msg
312+
* @param {String} event
313+
* @param {Function} cb Listener
304314
*/
305-
exports.success = function (msg) {
306-
this.output(msg, 'success');
315+
exports.on = function (event, cb) {
316+
ee.on(event, cb);
317+
return this;
307318
};
308319

309320
exports.error = function (err, heading) {
@@ -354,3 +365,7 @@ function isDirection (str) {
354365
function isDown (str) {
355366
return str === 'down';
356367
}
368+
369+
function error (err, cb) {
370+
cb ? cb(err) : ee.emit('error', err);
371+
}

0 commit comments

Comments
 (0)