/
index.js
71 lines (61 loc) · 2.37 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
"use strict";
const path = require("path");
const yargs = require("yargs/yargs");
const globalOptions = require("@lerna/global-options");
module.exports = commandRunner;
/**
* A higher-order function to help with passing _actual_ yargs-parsed argv
* into command constructors (instead of artificial direct parameters).
*
* @param {Object} commandModule The yargs command exports
* @return {Function} with partially-applied yargs config
*/
function commandRunner(commandModule) {
/* eslint-disable import/no-dynamic-require, global-require */
const cmd = commandModule.command.split(" ")[0];
// prime the pump so slow-as-molasses CI doesn't fail with delayed require()
require(path.resolve(require.main.filename, "../.."));
return cwd => {
// create a _new_ yargs instance every time cwd changes to avoid singleton pollution
const cli = yargs([], cwd)
.strict()
.exitProcess(false)
.detectLocale(false)
.showHelpOnFail(false)
.wrap(null)
.command(commandModule);
globalOptions(cli, { loglevel: "silent", progress: false });
return (...args) =>
new Promise((resolve, reject) => {
const yargsMeta = {};
const context = {
cwd,
lernaVersion: "__TEST_VERSION__",
onResolved: result => {
// success resolves the result, if any, returned from execute()
resolve(Object.assign({}, result, yargsMeta));
},
onRejected: result => {
Object.assign(result, yargsMeta);
// tests expect errors thrown to indicate failure,
// _not_ just non-zero exitCode
reject(result);
},
};
const parseFn = (yargsError, parsedArgv, yargsOutput) => {
// this is synchronous, before the async handlers resolve
Object.assign(yargsMeta, { parsedArgv, yargsOutput });
};
cli
.fail((msg, err) => {
// since yargs 10.1.0, this is the only way to catch handler rejection
// _and_ yargs validation exceptions when using async command handlers
const actual = err || new Error(msg);
// backfill exitCode for test convenience
yargsMeta.exitCode = "exitCode" in actual ? actual.exitCode : 1;
context.onRejected(actual);
})
.parse([cmd, ...args], context, parseFn);
});
};
}