-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
index.js
108 lines (82 loc) · 2.64 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
99
100
101
102
103
104
105
106
107
108
"use strict";
const chalk = require("chalk");
const execa = require("execa");
const logTransformer = require("strong-log-transformer");
// bookkeeping for spawned processes
let children = 0;
// when streaming children are spawned, use this color for prefix
const colorWheel = ["cyan", "magenta", "blue", "yellow", "green", "red"];
const NUM_COLORS = colorWheel.length;
function exec(command, args, opts) {
const options = Object.assign({ stdio: "pipe" }, opts);
const spawned = spawnProcess(command, args, options);
return wrapError(spawned);
}
function execSync(command, args, opts) {
return execa.sync(command, args, opts).stdout;
}
function spawn(command, args, opts) {
const options = Object.assign({}, opts, { stdio: "inherit" });
const spawned = spawnProcess(command, args, options);
return wrapError(spawned);
}
// istanbul ignore next
function spawnStreaming(command, args, opts, prefix) {
const options = Object.assign({}, opts);
options.stdio = ["ignore", "pipe", "pipe"];
const colorName = colorWheel[children % NUM_COLORS];
const color = chalk[colorName];
const spawned = spawnProcess(command, args, options);
const stdoutOpts = {};
const stderrOpts = {}; // mergeMultiline causes escaped newlines :P
if (prefix) {
stdoutOpts.tag = `${color.bold(prefix)}:`;
stderrOpts.tag = `${color(prefix)}:`;
}
// Avoid "Possible EventEmitter memory leak detected" warning due to piped stdio
if (children > process.stdout.listenerCount("close")) {
process.stdout.setMaxListeners(children);
process.stderr.setMaxListeners(children);
}
spawned.stdout.pipe(logTransformer(stdoutOpts)).pipe(process.stdout);
spawned.stderr.pipe(logTransformer(stderrOpts)).pipe(process.stderr);
return wrapError(spawned);
}
function getChildProcessCount() {
return children;
}
function spawnProcess(command, args, opts) {
children += 1;
const child = execa(command, args, opts);
const drain = (code, signal) => {
children -= 1;
// don't run repeatedly if this is the error event
if (signal === undefined) {
child.removeListener("exit", drain);
}
};
child.once("exit", drain);
child.once("error", drain);
if (opts.pkg) {
child.pkg = opts.pkg;
}
return child;
}
function wrapError(spawned) {
if (spawned.pkg) {
return spawned.catch(err => {
// istanbul ignore else
if (err.code) {
// log non-lerna error cleanly
err.pkg = spawned.pkg;
}
throw err;
});
}
return spawned;
}
exports.exec = exec;
exports.execSync = execSync;
exports.spawn = spawn;
exports.spawnStreaming = spawnStreaming;
exports.getChildProcessCount = getChildProcessCount;