-
Notifications
You must be signed in to change notification settings - Fork 4
/
index.js
98 lines (77 loc) · 2.7 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/* eslint global-require:0 */
'use strict';
const Promise = require('bluebird');
const get = require('lodash/get');
const isPlainObject = require('lodash/isPlainObject');
const run = require('./lib/run');
const promisify = require('./lib/promisify');
const build = require('./lib/build');
function setupReporter(reporter) {
reporter = reporter || 'blocks';
// If it is a string, import built-in reporter
if (typeof reporter === 'string') {
let factory;
try {
factory = require('./reporters/' + reporter);
} catch (err) {
err.message = 'Unknown reporter: ' + reporter;
throw err;
}
reporter = factory();
} else if (!isPlainObject(reporter)) {
throw new TypeError('Reporter must be a string or a plain object');
}
// Finally promisify it
return promisify.reporter(reporter);
}
function onNotification(reporter, node, action) {
const reporterFn = get(reporter, node.type + '.' + action);
const args = Array.from(arguments).slice(3);
args.unshift(node);
return Promise.resolve(reporterFn && reporterFn.apply(null, args));
}
function planify(data) {
const plan = build(data);
return Object.assign(plan, {
getNode() {
return plan.node;
},
run(options, done) {
if (typeof options === 'function') {
done = options;
options = null;
}
options = Object.assign({
reporter: 'blocks',
exit: false,
}, options);
// Setup reporter
const reporter = setupReporter(options.reporter);
// Check if a plan is running
if (global.$planifyRunning) {
throw new Error('A plan is already running');
}
// Run actual plan
global.$planifyRunning = true; // Use global because several versions might be used
return run(plan.node, onNotification.bind(null, reporter))
.finally(() => {
global.$planifyRunning = false;
})
// Exit automatically if options.exit is set to true
.then(() => {
options.exit && process.exit(0);
}, (err) => {
if (!options.exit) {
throw err;
}
process.exit(err.exitCode || 1);
// This is necessary if the `process.exit()` is being mocked. This way it is possible
// to catch the error and assert it accordingly.
throw err;
})
.return(plan.node.data)
.nodeify(done);
},
});
}
module.exports = planify;