promisify-child-process 4.1.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/index.cjs +92 -123
- package/index.cjs.map +1 -0
- package/index.d.cts +65 -0
- package/index.d.cts.map +1 -0
- package/index.d.ts +63 -66
- package/index.d.ts.map +1 -0
- package/index.js +141 -0
- package/index.js.map +1 -0
- package/package.json +22 -126
- package/src/index.ts +314 -0
- package/index.js.flow +0 -221
- package/index.mjs +0 -6
package/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import child_process from 'child_process';
|
|
2
|
+
function joinChunks(chunks, encoding) {
|
|
3
|
+
if (!chunks) return undefined;
|
|
4
|
+
const buffer = Buffer.concat(chunks);
|
|
5
|
+
return encoding && encoding !== 'buffer' ? buffer.toString(encoding) : buffer;
|
|
6
|
+
}
|
|
7
|
+
export function promisifyChildProcess(child, options) {
|
|
8
|
+
var _promise$finally;
|
|
9
|
+
const promise = new Promise((resolve, reject) => {
|
|
10
|
+
var _child$stdout, _child$stderr;
|
|
11
|
+
const encoding = options === null || options === void 0 ? void 0 : options.encoding;
|
|
12
|
+
const killSignal = options === null || options === void 0 ? void 0 : options.killSignal;
|
|
13
|
+
const captureStdio = encoding != null || (options === null || options === void 0 ? void 0 : options.maxBuffer) != null;
|
|
14
|
+
const maxBuffer = (options === null || options === void 0 ? void 0 : options.maxBuffer) ?? 1024 * 1024;
|
|
15
|
+
let bufferSize = 0;
|
|
16
|
+
let error;
|
|
17
|
+
const stdoutChunks = captureStdio && child.stdout ? [] : undefined;
|
|
18
|
+
const stderrChunks = captureStdio && child.stderr ? [] : undefined;
|
|
19
|
+
const capture = chunks => data => {
|
|
20
|
+
if (typeof data === 'string') data = Buffer.from(data);
|
|
21
|
+
const remaining = Math.max(0, maxBuffer - bufferSize);
|
|
22
|
+
bufferSize += Math.min(remaining, data.length);
|
|
23
|
+
if (data.length > remaining) {
|
|
24
|
+
error = new Error('maxBuffer exceeded');
|
|
25
|
+
child.kill(killSignal ?? 'SIGTERM');
|
|
26
|
+
data = data.subarray(0, remaining);
|
|
27
|
+
}
|
|
28
|
+
chunks.push(data);
|
|
29
|
+
};
|
|
30
|
+
const captureStdout = stdoutChunks ? capture(stdoutChunks) : undefined;
|
|
31
|
+
const captureStderr = stderrChunks ? capture(stderrChunks) : undefined;
|
|
32
|
+
if (captureStdout) (_child$stdout = child.stdout) === null || _child$stdout === void 0 || _child$stdout.on('data', captureStdout);
|
|
33
|
+
if (captureStderr) (_child$stderr = child.stderr) === null || _child$stderr === void 0 || _child$stderr.on('data', captureStderr);
|
|
34
|
+
function onError(err) {
|
|
35
|
+
error = err;
|
|
36
|
+
done();
|
|
37
|
+
}
|
|
38
|
+
child.on('error', onError);
|
|
39
|
+
function done(code = null, signal = null) {
|
|
40
|
+
var _child$stdout2, _child$stderr2;
|
|
41
|
+
child.removeListener('error', onError);
|
|
42
|
+
child.removeListener('close', done);
|
|
43
|
+
if (captureStdout) (_child$stdout2 = child.stdout) === null || _child$stdout2 === void 0 || _child$stdout2.removeListener('data', captureStdout);
|
|
44
|
+
if (captureStderr) (_child$stderr2 = child.stderr) === null || _child$stderr2 === void 0 || _child$stderr2.removeListener('data', captureStderr);
|
|
45
|
+
const stdout = joinChunks(stdoutChunks, encoding);
|
|
46
|
+
const stderr = joinChunks(stderrChunks, encoding);
|
|
47
|
+
if (error || code != null && code != 0 || signal != null) {
|
|
48
|
+
reject(Object.assign(error || new Error(signal != null ? `Process was killed with ${signal}` : `Process exited with code ${code}`), {
|
|
49
|
+
code,
|
|
50
|
+
signal,
|
|
51
|
+
killed: signal != null,
|
|
52
|
+
stdout,
|
|
53
|
+
stderr
|
|
54
|
+
}));
|
|
55
|
+
} else {
|
|
56
|
+
resolve({
|
|
57
|
+
stderr,
|
|
58
|
+
stdout,
|
|
59
|
+
code,
|
|
60
|
+
signal,
|
|
61
|
+
killed: false
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
child.on('close', done);
|
|
66
|
+
});
|
|
67
|
+
return Object.create(child, {
|
|
68
|
+
then: {
|
|
69
|
+
value: promise.then.bind(promise)
|
|
70
|
+
},
|
|
71
|
+
catch: {
|
|
72
|
+
value: promise.catch.bind(promise)
|
|
73
|
+
},
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
75
|
+
finally: {
|
|
76
|
+
value: (_promise$finally = promise.finally) === null || _promise$finally === void 0 ? void 0 : _promise$finally.bind(promise)
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function isArray(t) {
|
|
81
|
+
return Array.isArray(t);
|
|
82
|
+
}
|
|
83
|
+
export function spawn(command, args, options) {
|
|
84
|
+
if (!isArray(args)) {
|
|
85
|
+
options = args;
|
|
86
|
+
args = [];
|
|
87
|
+
}
|
|
88
|
+
return promisifyChildProcess(child_process.spawn(command, args, options), options);
|
|
89
|
+
}
|
|
90
|
+
export function fork(module, args, options) {
|
|
91
|
+
if (!isArray(args)) {
|
|
92
|
+
options = args;
|
|
93
|
+
args = [];
|
|
94
|
+
}
|
|
95
|
+
return promisifyChildProcess(child_process.fork(module, args, options), options);
|
|
96
|
+
}
|
|
97
|
+
function promisifyExecMethod(method) {
|
|
98
|
+
return (...args) => {
|
|
99
|
+
var _promise$finally2;
|
|
100
|
+
let child;
|
|
101
|
+
const promise = new Promise((resolve, reject) => {
|
|
102
|
+
child = method(...args, (err, stdout, stderr) => {
|
|
103
|
+
if (err) {
|
|
104
|
+
reject(Object.assign(err, {
|
|
105
|
+
stdout,
|
|
106
|
+
stderr
|
|
107
|
+
}));
|
|
108
|
+
} else {
|
|
109
|
+
resolve({
|
|
110
|
+
code: 0,
|
|
111
|
+
signal: null,
|
|
112
|
+
killed: false,
|
|
113
|
+
stdout: stdout,
|
|
114
|
+
stderr: stderr
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
if (!child) {
|
|
120
|
+
throw new Error('unexpected error: child has not been initialized');
|
|
121
|
+
}
|
|
122
|
+
return Object.create(child, {
|
|
123
|
+
then: {
|
|
124
|
+
value: promise.then.bind(promise)
|
|
125
|
+
},
|
|
126
|
+
catch: {
|
|
127
|
+
value: promise.catch.bind(promise)
|
|
128
|
+
},
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
130
|
+
finally: {
|
|
131
|
+
value: (_promise$finally2 = promise.finally) === null || _promise$finally2 === void 0 ? void 0 : _promise$finally2.bind(promise)
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export const exec = promisifyExecMethod(child_process.exec);
|
|
137
|
+
export const execFile = promisifyExecMethod(child_process.execFile);
|
|
138
|
+
export function isChildProcessError(error) {
|
|
139
|
+
return error instanceof Error && 'code' in error && 'signal' in error;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["child_process","joinChunks","chunks","encoding","undefined","buffer","Buffer","concat","toString","promisifyChildProcess","child","options","_promise$finally","promise","Promise","resolve","reject","_child$stdout","_child$stderr","killSignal","captureStdio","maxBuffer","bufferSize","error","stdoutChunks","stdout","stderrChunks","stderr","capture","data","from","remaining","Math","max","min","length","Error","kill","subarray","push","captureStdout","captureStderr","on","onError","err","done","code","signal","_child$stdout2","_child$stderr2","removeListener","Object","assign","killed","create","then","value","bind","catch","finally","isArray","t","Array","spawn","command","args","fork","module","promisifyExecMethod","method","_promise$finally2","exec","execFile","isChildProcessError"],"sources":["src/index.ts"],"sourcesContent":[null],"mappings":"AACA,OAAOA,aAAa,MAAM,eAAe;AAyFzC,SAASC,UAAUA,CACjBC,MAA4B,EAC5BC,QAAsD,EACzB;EAC7B,IAAI,CAACD,MAAM,EAAE,OAAOE,SAAS;EAC7B,MAAMC,MAAM,GAAGC,MAAM,CAACC,MAAM,CAACL,MAAM,CAAC;EACpC,OAAOC,QAAQ,IAAIA,QAAQ,KAAK,QAAQ,GAAGE,MAAM,CAACG,QAAQ,CAACL,QAAQ,CAAC,GAAGE,MAAM;AAC/E;AAEA,OAAO,SAASI,qBAAqBA,CAEnCC,KAAmB,EAAEC,OAAiB,EAAgC;EAAA,IAAAC,gBAAA;EACtE,MAAMC,OAAO,GAAG,IAAIC,OAAO,CACzB,CAACC,OAAO,EAAEC,MAAM,KAAK;IAAA,IAAAC,aAAA,EAAAC,aAAA;IACnB,MAAMf,QAAQ,GAAGQ,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAER,QAAQ;IAClC,MAAMgB,UAAU,GAAGR,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEQ,UAAU;IACtC,MAAMC,YAAY,GAAGjB,QAAQ,IAAI,IAAI,IAAI,CAAAQ,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEU,SAAS,KAAI,IAAI;IACnE,MAAMA,SAAS,GAAG,CAAAV,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEU,SAAS,KAAI,IAAI,GAAG,IAAI;IACnD,IAAIC,UAAU,GAAG,CAAC;IAClB,IAAIC,KAAwB;IAC5B,MAAMC,YAAkC,GACtCJ,YAAY,IAAIV,KAAK,CAACe,MAAM,GAAG,EAAE,GAAGrB,SAAS;IAC/C,MAAMsB,YAAkC,GACtCN,YAAY,IAAIV,KAAK,CAACiB,MAAM,GAAG,EAAE,GAAGvB,SAAS;IAC/C,MAAMwB,OAAO,GAAI1B,MAAgB,IAAM2B,IAAqB,IAAK;MAC/D,IAAI,OAAOA,IAAI,KAAK,QAAQ,EAAEA,IAAI,GAAGvB,MAAM,CAACwB,IAAI,CAACD,IAAI,CAAC;MACtD,MAAME,SAAS,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEZ,SAAS,GAAGC,UAAU,CAAC;MACrDA,UAAU,IAAIU,IAAI,CAACE,GAAG,CAACH,SAAS,EAAEF,IAAI,CAACM,MAAM,CAAC;MAC9C,IAAIN,IAAI,CAACM,MAAM,GAAGJ,SAAS,EAAE;QAC3BR,KAAK,GAAG,IAAIa,KAAK,CAAC,oBAAoB,CAAC;QACvC1B,KAAK,CAAC2B,IAAI,CAAClB,UAAU,IAAI,SAAS,CAAC;QACnCU,IAAI,GAAGA,IAAI,CAACS,QAAQ,CAAC,CAAC,EAAEP,SAAS,CAAC;MACpC;MACA7B,MAAM,CAACqC,IAAI,CAACV,IAAI,CAAC;IACnB,CAAC;IACD,MAAMW,aAAa,GAAGhB,YAAY,GAAGI,OAAO,CAACJ,YAAY,CAAC,GAAGpB,SAAS;IACtE,MAAMqC,aAAa,GAAGf,YAAY,GAAGE,OAAO,CAACF,YAAY,CAAC,GAAGtB,SAAS;IACtE,IAAIoC,aAAa,EAAE,CAAAvB,aAAA,GAAAP,KAAK,CAACe,MAAM,cAAAR,aAAA,eAAZA,aAAA,CAAcyB,EAAE,CAAC,MAAM,EAAEF,aAAa,CAAC;IAC1D,IAAIC,aAAa,EAAE,CAAAvB,aAAA,GAAAR,KAAK,CAACiB,MAAM,cAAAT,aAAA,eAAZA,aAAA,CAAcwB,EAAE,CAAC,MAAM,EAAED,aAAa,CAAC;IAC1D,SAASE,OAAOA,CAACC,GAAU,EAAE;MAC3BrB,KAAK,GAAGqB,GAAG;MACXC,IAAI,CAAC,CAAC;IACR;IACAnC,KAAK,CAACgC,EAAE,CAAC,OAAO,EAAEC,OAAO,CAAC;IAC1B,SAASE,IAAIA,CAACC,IAAmB,GAAG,IAAI,EAAEC,MAAqB,GAAG,IAAI,EAAE;MAAA,IAAAC,cAAA,EAAAC,cAAA;MACtEvC,KAAK,CAACwC,cAAc,CAAC,OAAO,EAAEP,OAAO,CAAC;MACtCjC,KAAK,CAACwC,cAAc,CAAC,OAAO,EAAEL,IAAI,CAAC;MACnC,IAAIL,aAAa,EAAE,CAAAQ,cAAA,GAAAtC,KAAK,CAACe,MAAM,cAAAuB,cAAA,eAAZA,cAAA,CAAcE,cAAc,CAAC,MAAM,EAAEV,aAAa,CAAC;MACtE,IAAIC,aAAa,EAAE,CAAAQ,cAAA,GAAAvC,KAAK,CAACiB,MAAM,cAAAsB,cAAA,eAAZA,cAAA,CAAcC,cAAc,CAAC,MAAM,EAAET,aAAa,CAAC;MAEtE,MAAMhB,MAAM,GAAGxB,UAAU,CACvBuB,YAAY,EACZrB,QACF,CAA0C;MAC1C,MAAMwB,MAAM,GAAG1B,UAAU,CACvByB,YAAY,EACZvB,QACF,CAA0C;MAE1C,IAAIoB,KAAK,IAAKuB,IAAI,IAAI,IAAI,IAAIA,IAAI,IAAI,CAAE,IAAIC,MAAM,IAAI,IAAI,EAAE;QAC1D/B,MAAM,CACJmC,MAAM,CAACC,MAAM,CACX7B,KAAK,IACH,IAAIa,KAAK,CACPW,MAAM,IAAI,IAAI,GACZ,2BAA2BA,MAAM,EAAE,GACnC,4BAA4BD,IAAI,EACpC,CAAC,EACH;UACEA,IAAI;UACJC,MAAM;UACNM,MAAM,EAAEN,MAAM,IAAI,IAAI;UACtBtB,MAAM;UACNE;QACF,CACF,CACF,CAAC;MACH,CAAC,MAAM;QACLZ,OAAO,CAAC;UAAEY,MAAM;UAAEF,MAAM;UAAEqB,IAAI;UAAEC,MAAM;UAAEM,MAAM,EAAE;QAAM,CAAC,CAAC;MAC1D;IACF;IACA3C,KAAK,CAACgC,EAAE,CAAC,OAAO,EAAEG,IAAI,CAAC;EACzB,CACF,CAAC;EACD,OAAOM,MAAM,CAACG,MAAM,CAAC5C,KAAK,EAAE;IAC1B6C,IAAI,EAAE;MAAEC,KAAK,EAAE3C,OAAO,CAAC0C,IAAI,CAACE,IAAI,CAAC5C,OAAO;IAAE,CAAC;IAC3C6C,KAAK,EAAE;MAAEF,KAAK,EAAE3C,OAAO,CAAC6C,KAAK,CAACD,IAAI,CAAC5C,OAAO;IAAE,CAAC;IAC7C;IACA8C,OAAO,EAAE;MAAEH,KAAK,GAAA5C,gBAAA,GAAEC,OAAO,CAAC8C,OAAO,cAAA/C,gBAAA,uBAAfA,gBAAA,CAAiB6C,IAAI,CAAC5C,OAAO;IAAE;EACnD,CAAC,CAAC;AACJ;AAOA,SAAS+C,OAAOA,CAACC,CAAU,EAAuC;EAChE,OAAOC,KAAK,CAACF,OAAO,CAACC,CAAC,CAAC;AACzB;AAWA,OAAO,SAASE,KAAKA,CACnBC,OAAe,EACfC,IAAkC,EAClCtD,OAAiB,EACa;EAC9B,IAAI,CAACiD,OAAO,CAACK,IAAI,CAAC,EAAE;IAClBtD,OAAO,GAAGsD,IAAI;IACdA,IAAI,GAAG,EAAE;EACX;EACA,OAAOxD,qBAAqB,CAC1BT,aAAa,CAAC+D,KAAK,CAACC,OAAO,EAAEC,IAAI,EAAEtD,OAAqC,CAAC,EACzEA,OACF,CAAC;AACH;AAgBA,OAAO,SAASuD,IAAIA,CAClBC,MAAc,EACdF,IAA8B,EAC9BtD,OAAiB,EACa;EAC9B,IAAI,CAACiD,OAAO,CAACK,IAAI,CAAC,EAAE;IAClBtD,OAAO,GAAGsD,IAAI;IACdA,IAAI,GAAG,EAAE;EACX;EACA,OAAOxD,qBAAqB,CAC1BT,aAAa,CAACkE,IAAI,CAACC,MAAM,EAAEF,IAAI,EAAEtD,OAAO,CAAC,EACzCA,OACF,CAAC;AACH;AACA,SAASyD,mBAAmBA,CAACC,MAAwC,EAAE;EACrE,OAAO,CAAC,GAAGJ,IAAW,KAA+B;IAAA,IAAAK,iBAAA;IACnD,IAAI5D,KAA+B;IACnC,MAAMG,OAAO,GAAG,IAAIC,OAAO,CAA0B,CAACC,OAAO,EAAEC,MAAM,KAAK;MACxEN,KAAK,GAAG2D,MAAM,CACZ,GAAGJ,IAAI,EACP,CACErB,GAAiB,EACjBnB,MAAuB,EACvBE,MAAuB,KACpB;QACH,IAAIiB,GAAG,EAAE;UACP5B,MAAM,CAACmC,MAAM,CAACC,MAAM,CAACR,GAAG,EAAE;YAAEnB,MAAM;YAAEE;UAAO,CAAC,CAAC,CAAC;QAChD,CAAC,MAAM;UACLZ,OAAO,CAAC;YACN+B,IAAI,EAAE,CAAC;YACPC,MAAM,EAAE,IAAI;YACZM,MAAM,EAAE,KAAK;YACb5B,MAAM,EAAEA,MAAa;YACrBE,MAAM,EAAEA;UACV,CAAC,CAAC;QACJ;MACF,CACF,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAACjB,KAAK,EAAE;MACV,MAAM,IAAI0B,KAAK,CAAC,kDAAkD,CAAC;IACrE;IACA,OAAOe,MAAM,CAACG,MAAM,CAAC5C,KAAK,EAAE;MAC1B6C,IAAI,EAAE;QAAEC,KAAK,EAAE3C,OAAO,CAAC0C,IAAI,CAACE,IAAI,CAAC5C,OAAO;MAAE,CAAC;MAC3C6C,KAAK,EAAE;QAAEF,KAAK,EAAE3C,OAAO,CAAC6C,KAAK,CAACD,IAAI,CAAC5C,OAAO;MAAE,CAAC;MAC7C;MACA8C,OAAO,EAAE;QAAEH,KAAK,GAAAc,iBAAA,GAAEzD,OAAO,CAAC8C,OAAO,cAAAW,iBAAA,uBAAfA,iBAAA,CAAiBb,IAAI,CAAC5C,OAAO;MAAE;IACnD,CAAC,CAAC;EACJ,CAAC;AACH;AAMA,OAAO,MAAM0D,IAGoB,GAAGH,mBAAmB,CAACpE,aAAa,CAACuE,IAAI,CAAC;AAM3E,OAAO,MAAMC,QAUZ,GAAGJ,mBAAmB,CAACpE,aAAa,CAACwE,QAAQ,CAAC;AAE/C,OAAO,SAASC,mBAAmBA,CAAClD,KAAc,EAMhD;EACA,OAAOA,KAAK,YAAYa,KAAK,IAAI,MAAM,IAAIb,KAAK,IAAI,QAAQ,IAAIA,KAAK;AACvE","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,79 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "promisify-child-process",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "seriously like the best async child process library",
|
|
5
5
|
"engines": {
|
|
6
|
-
"node": ">=
|
|
6
|
+
"node": ">=16"
|
|
7
7
|
},
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"import": "./index.mjs",
|
|
11
|
-
"require": "./index.cjs"
|
|
12
|
-
},
|
|
13
|
-
"files": [
|
|
14
|
-
"index.cjs",
|
|
15
|
-
"index.mjs",
|
|
16
|
-
"index.d.ts",
|
|
17
|
-
"index.js.flow"
|
|
18
|
-
],
|
|
8
|
+
"types": "index.d.cts",
|
|
9
|
+
"type": "module",
|
|
19
10
|
"sideEffects": false,
|
|
20
|
-
"scripts": {
|
|
21
|
-
"lint": "eslint src test --cache",
|
|
22
|
-
"lint:fix": "eslint --fix src test --cache",
|
|
23
|
-
"lint:watch": "esw --watch src test --cache",
|
|
24
|
-
"prettier": "prettier --write *.json *.md *.js *.ts '{src,test}/**/*.js'",
|
|
25
|
-
"prettier:check": "prettier --list-different *.json *.md *.js *.ts '{src,test}/**/*.js'",
|
|
26
|
-
"flow": "flow",
|
|
27
|
-
"flow:coverage": "for file in src/**.js test/**.js; do echo $file; flow coverage $file; done",
|
|
28
|
-
"flow:watch": "flow-watch -e js,js.flow,flowconfig --ignore es/ --ignore node_modules/ --watch .flowconfig --watch src/ --watch test/",
|
|
29
|
-
"build": "babel src/index.js -o index.cjs && flow-copy-source -v src/ .",
|
|
30
|
-
"test": "cross-env NODE_ENV=test mocha $npm_package_config_mocha && cross-env NODE_ENV=test BABEL_ENV=coverage nyc --reporter=lcov --reporter=text mocha $npm_package_config_mocha",
|
|
31
|
-
"test:watch": "cross-env NODE_ENV=test BABEL_ENV=test mocha --watch $npm_package_config_mocha",
|
|
32
|
-
"test:debug": "cross-env NODE_ENV=test BABEL_ENV=test mocha --inspect-brk $npm_package_config_mocha",
|
|
33
|
-
"codecov": "nyc report --reporter=text-lcov > coverage.lcov; codecov",
|
|
34
|
-
"prepublishOnly": "npm run prettier:check && npm run lint && flow && tsc && npm test && npm run build",
|
|
35
|
-
"open:coverage": "open coverage/lcov-report/index.html",
|
|
36
|
-
"semantic-release": "semantic-release"
|
|
37
|
-
},
|
|
38
|
-
"husky": {
|
|
39
|
-
"hooks": {
|
|
40
|
-
"pre-commit": "lint-staged && npm run lint && flow && tsc",
|
|
41
|
-
"commit-msg": "commitlint -e $GIT_PARAMS",
|
|
42
|
-
"pre-push": "npm test"
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
"lint-staged": {
|
|
46
|
-
"*.{js,json,css,md,ts}": [
|
|
47
|
-
"prettier --write",
|
|
48
|
-
"git add"
|
|
49
|
-
]
|
|
50
|
-
},
|
|
51
|
-
"commitlint": {
|
|
52
|
-
"extends": [
|
|
53
|
-
"@jedwards1211/commitlint-config"
|
|
54
|
-
]
|
|
55
|
-
},
|
|
56
|
-
"prettier": {
|
|
57
|
-
"semi": false,
|
|
58
|
-
"singleQuote": true,
|
|
59
|
-
"trailingComma": "es5"
|
|
60
|
-
},
|
|
61
|
-
"config": {
|
|
62
|
-
"mocha": "-r @babel/register test/configure.js 'test/**/*.js'",
|
|
63
|
-
"commitizen": {
|
|
64
|
-
"path": "cz-conventional-changelog"
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
"nyc": {
|
|
68
|
-
"include": [
|
|
69
|
-
"src/**/*.js"
|
|
70
|
-
],
|
|
71
|
-
"require": [
|
|
72
|
-
"@babel/register"
|
|
73
|
-
],
|
|
74
|
-
"sourceMap": false,
|
|
75
|
-
"instrument": false
|
|
76
|
-
},
|
|
77
11
|
"repository": {
|
|
78
12
|
"type": "git",
|
|
79
13
|
"url": "https://github.com/jcoreio/promisify-child-process.git"
|
|
@@ -98,62 +32,24 @@
|
|
|
98
32
|
"url": "https://github.com/jcoreio/promisify-child-process/issues"
|
|
99
33
|
},
|
|
100
34
|
"homepage": "https://github.com/jcoreio/promisify-child-process#readme",
|
|
101
|
-
"
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
"@jedwards1211/eslint-config-flow": "^2.0.0",
|
|
113
|
-
"@types/node": "^12.12.17",
|
|
114
|
-
"babel-eslint": "^10.0.1",
|
|
115
|
-
"babel-plugin-istanbul": "^5.1.0",
|
|
116
|
-
"chai": "^4.2.0",
|
|
117
|
-
"codecov": "^3.1.0",
|
|
118
|
-
"copy": "^0.3.2",
|
|
119
|
-
"cross-env": "^5.2.0",
|
|
120
|
-
"eslint": "^5.9.0",
|
|
121
|
-
"eslint-config-prettier": "^3.3.0",
|
|
122
|
-
"eslint-plugin-flowtype": "^3.2.0",
|
|
123
|
-
"eslint-watch": "^4.0.2",
|
|
124
|
-
"flow-bin": "^0.124.0",
|
|
125
|
-
"flow-copy-source": "^2.0.2",
|
|
126
|
-
"flow-watch": "^1.1.4",
|
|
127
|
-
"fs-extra": "^7.0.1",
|
|
128
|
-
"husky": "^1.1.4",
|
|
129
|
-
"istanbul": "^0.4.5",
|
|
130
|
-
"lint-staged": "^8.0.4",
|
|
131
|
-
"mocha": "^6.2.1",
|
|
132
|
-
"nyc": "^13.1.0",
|
|
133
|
-
"prettier": "^1.15.2",
|
|
134
|
-
"prettier-eslint": "^8.8.2",
|
|
135
|
-
"rimraf": "^2.6.0",
|
|
136
|
-
"semantic-release": "^15.13.31",
|
|
137
|
-
"typescript": "^3.7.3",
|
|
138
|
-
"waait": "^1.0.5"
|
|
139
|
-
},
|
|
140
|
-
"dependencies": {},
|
|
141
|
-
"renovate": {
|
|
142
|
-
"extends": [
|
|
143
|
-
":separateMajorReleases",
|
|
144
|
-
":combinePatchMinorReleases",
|
|
145
|
-
":ignoreUnstable",
|
|
146
|
-
":prImmediately",
|
|
147
|
-
":renovatePrefix",
|
|
148
|
-
":updateNotScheduled",
|
|
149
|
-
":preserveSemverRanges",
|
|
150
|
-
":semanticPrefixFixDepsChoreOthers",
|
|
151
|
-
":automergeDisabled",
|
|
152
|
-
"group:monorepos"
|
|
153
|
-
],
|
|
154
|
-
"automerge": true,
|
|
155
|
-
"major": {
|
|
156
|
-
"automerge": false
|
|
35
|
+
"main": "index.cjs",
|
|
36
|
+
"module": "index.js",
|
|
37
|
+
"exports": {
|
|
38
|
+
"./package.json": "./package.json",
|
|
39
|
+
".": {
|
|
40
|
+
"types": {
|
|
41
|
+
"import": "./index.d.ts",
|
|
42
|
+
"default": "./index.d.cts"
|
|
43
|
+
},
|
|
44
|
+
"import": "./index.js",
|
|
45
|
+
"default": "./index.cjs"
|
|
157
46
|
}
|
|
47
|
+
},
|
|
48
|
+
"packageManager": "pnpm@10.6.5",
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@babel/runtime": "^7.26.0"
|
|
51
|
+
},
|
|
52
|
+
"@jcoreio/toolchain": {
|
|
53
|
+
"migratedVersion": "5.8.8"
|
|
158
54
|
}
|
|
159
55
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { ChildProcess, StdioOptions } from 'child_process'
|
|
2
|
+
import child_process from 'child_process'
|
|
3
|
+
import { Pipe, Readable, Writable } from 'stream'
|
|
4
|
+
|
|
5
|
+
interface IOOptions {
|
|
6
|
+
silent?: boolean
|
|
7
|
+
stdio?: StdioOptions
|
|
8
|
+
encoding?: BufferEncoding | 'buffer' | null
|
|
9
|
+
maxBuffer?: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type ChunkTypeHelper<MaxBuffer, Encoding> =
|
|
13
|
+
MaxBuffer extends number ?
|
|
14
|
+
Encoding extends BufferEncoding ?
|
|
15
|
+
string
|
|
16
|
+
: Buffer
|
|
17
|
+
: Encoding extends BufferEncoding ? string
|
|
18
|
+
: Encoding extends 'buffer' ? Buffer
|
|
19
|
+
: undefined
|
|
20
|
+
|
|
21
|
+
type ChunkType<Options extends IOOptions> = ChunkTypeHelper<
|
|
22
|
+
'maxBuffer' extends keyof Options ? Options['maxBuffer'] : undefined,
|
|
23
|
+
'encoding' extends keyof Options ? Options['encoding'] : undefined
|
|
24
|
+
>
|
|
25
|
+
|
|
26
|
+
type IsPipeHelper<Stdio, Silent, Fd extends 0 | 1 | 2> =
|
|
27
|
+
Stdio extends unknown[] ?
|
|
28
|
+
Stdio[Fd] extends infer Value ?
|
|
29
|
+
Value extends 'pipe' | 'overlapped' ?
|
|
30
|
+
true
|
|
31
|
+
: false
|
|
32
|
+
: false
|
|
33
|
+
: Stdio extends null | undefined | 'pipe' | 'overlapped' ? true
|
|
34
|
+
: Stdio extends null | undefined ?
|
|
35
|
+
Silent extends true ?
|
|
36
|
+
false
|
|
37
|
+
: true
|
|
38
|
+
: false
|
|
39
|
+
|
|
40
|
+
type IsPipe<Options extends IOOptions, Fd extends 0 | 1 | 2> = IsPipeHelper<
|
|
41
|
+
'stdio' extends keyof Options ? Options['stdio'] : undefined,
|
|
42
|
+
'silent' extends keyof Options ? Options['silent'] : undefined,
|
|
43
|
+
Fd
|
|
44
|
+
>
|
|
45
|
+
|
|
46
|
+
type Contains<A, T> =
|
|
47
|
+
A extends [infer Head, ...infer Tail] ?
|
|
48
|
+
Head extends T ?
|
|
49
|
+
true
|
|
50
|
+
: Contains<Tail, T>
|
|
51
|
+
: false
|
|
52
|
+
|
|
53
|
+
export interface ChildProcessResult<Options extends IOOptions> {
|
|
54
|
+
stdout: IsPipe<Options, 1> extends true ? ChunkType<Options> : undefined
|
|
55
|
+
stderr: IsPipe<Options, 2> extends true ? ChunkType<Options> : undefined
|
|
56
|
+
code: number | null
|
|
57
|
+
signal: string | null
|
|
58
|
+
killed: boolean
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
type StdioStreams<Stdio> = {
|
|
62
|
+
[K in keyof Stdio]: Stdio[K] extends 'pipe' | 'overlapped' ?
|
|
63
|
+
K extends 0 | '0' ?
|
|
64
|
+
Writable
|
|
65
|
+
: Readable
|
|
66
|
+
: null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ChildProcessPromise<Options extends IOOptions>
|
|
70
|
+
extends ChildProcess, Promise<ChildProcessResult<Options>> {
|
|
71
|
+
stdin: IsPipe<Options, 0> extends true ? Writable : null
|
|
72
|
+
stdout: IsPipe<Options, 1> extends true ? Readable : null
|
|
73
|
+
stderr: IsPipe<Options, 2> extends true ? Readable : null
|
|
74
|
+
readonly channel: Options['stdio'] extends infer Stdio ?
|
|
75
|
+
Contains<Stdio, 'ipc'> extends true ?
|
|
76
|
+
Pipe
|
|
77
|
+
: undefined
|
|
78
|
+
: undefined
|
|
79
|
+
readonly stdio: Options['stdio'] extends infer Stdio ?
|
|
80
|
+
Stdio extends unknown[] ? StdioStreams<Stdio>
|
|
81
|
+
: Stdio extends null | undefined | 'pipe' | 'overlapped' ?
|
|
82
|
+
[Writable, Readable, Readable, undefined, undefined]
|
|
83
|
+
: [null, null, null, undefined, undefined]
|
|
84
|
+
: [null, null, null, undefined, undefined]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface PromisifyChildProcessBaseOptions extends IOOptions {
|
|
88
|
+
killSignal?: NodeJS.Signals | number
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function joinChunks(
|
|
92
|
+
chunks: Buffer[] | undefined,
|
|
93
|
+
encoding: BufferEncoding | 'buffer' | null | undefined
|
|
94
|
+
): string | Buffer | undefined {
|
|
95
|
+
if (!chunks) return undefined
|
|
96
|
+
const buffer = Buffer.concat(chunks)
|
|
97
|
+
return encoding && encoding !== 'buffer' ? buffer.toString(encoding) : buffer
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function promisifyChildProcess<
|
|
101
|
+
Options extends PromisifyChildProcessBaseOptions,
|
|
102
|
+
>(child: ChildProcess, options?: Options): ChildProcessPromise<Options> {
|
|
103
|
+
const promise = new Promise<ChildProcessResult<Options>>(
|
|
104
|
+
(resolve, reject) => {
|
|
105
|
+
const encoding = options?.encoding
|
|
106
|
+
const killSignal = options?.killSignal
|
|
107
|
+
const captureStdio = encoding != null || options?.maxBuffer != null
|
|
108
|
+
const maxBuffer = options?.maxBuffer ?? 1024 * 1024
|
|
109
|
+
let bufferSize = 0
|
|
110
|
+
let error: Error | undefined
|
|
111
|
+
const stdoutChunks: Buffer[] | undefined =
|
|
112
|
+
captureStdio && child.stdout ? [] : undefined
|
|
113
|
+
const stderrChunks: Buffer[] | undefined =
|
|
114
|
+
captureStdio && child.stderr ? [] : undefined
|
|
115
|
+
const capture = (chunks: Buffer[]) => (data: string | Buffer) => {
|
|
116
|
+
if (typeof data === 'string') data = Buffer.from(data)
|
|
117
|
+
const remaining = Math.max(0, maxBuffer - bufferSize)
|
|
118
|
+
bufferSize += Math.min(remaining, data.length)
|
|
119
|
+
if (data.length > remaining) {
|
|
120
|
+
error = new Error('maxBuffer exceeded')
|
|
121
|
+
child.kill(killSignal ?? 'SIGTERM')
|
|
122
|
+
data = data.subarray(0, remaining)
|
|
123
|
+
}
|
|
124
|
+
chunks.push(data)
|
|
125
|
+
}
|
|
126
|
+
const captureStdout = stdoutChunks ? capture(stdoutChunks) : undefined
|
|
127
|
+
const captureStderr = stderrChunks ? capture(stderrChunks) : undefined
|
|
128
|
+
if (captureStdout) child.stdout?.on('data', captureStdout)
|
|
129
|
+
if (captureStderr) child.stderr?.on('data', captureStderr)
|
|
130
|
+
function onError(err: Error) {
|
|
131
|
+
error = err
|
|
132
|
+
done()
|
|
133
|
+
}
|
|
134
|
+
child.on('error', onError)
|
|
135
|
+
function done(code: number | null = null, signal: string | null = null) {
|
|
136
|
+
child.removeListener('error', onError)
|
|
137
|
+
child.removeListener('close', done)
|
|
138
|
+
if (captureStdout) child.stdout?.removeListener('data', captureStdout)
|
|
139
|
+
if (captureStderr) child.stderr?.removeListener('data', captureStderr)
|
|
140
|
+
|
|
141
|
+
const stdout = joinChunks(
|
|
142
|
+
stdoutChunks,
|
|
143
|
+
encoding
|
|
144
|
+
) as ChildProcessResult<Options>['stdout']
|
|
145
|
+
const stderr = joinChunks(
|
|
146
|
+
stderrChunks,
|
|
147
|
+
encoding
|
|
148
|
+
) as ChildProcessResult<Options>['stderr']
|
|
149
|
+
|
|
150
|
+
if (error || (code != null && code != 0) || signal != null) {
|
|
151
|
+
reject(
|
|
152
|
+
Object.assign(
|
|
153
|
+
error ||
|
|
154
|
+
new Error(
|
|
155
|
+
signal != null ?
|
|
156
|
+
`Process was killed with ${signal}`
|
|
157
|
+
: `Process exited with code ${code}`
|
|
158
|
+
),
|
|
159
|
+
{
|
|
160
|
+
code,
|
|
161
|
+
signal,
|
|
162
|
+
killed: signal != null,
|
|
163
|
+
stdout,
|
|
164
|
+
stderr,
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
} else {
|
|
169
|
+
resolve({ stderr, stdout, code, signal, killed: false })
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
child.on('close', done)
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
return Object.create(child, {
|
|
176
|
+
then: { value: promise.then.bind(promise) },
|
|
177
|
+
catch: { value: promise.catch.bind(promise) },
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
179
|
+
finally: { value: promise.finally?.bind(promise) },
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface SpawnOptions extends child_process.SpawnOptions {
|
|
184
|
+
encoding?: BufferEncoding
|
|
185
|
+
maxBuffer?: number
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function isArray(t: unknown): t is unknown[] | readonly unknown[] {
|
|
189
|
+
return Array.isArray(t)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function spawn<Options extends SpawnOptions>(
|
|
193
|
+
command: string,
|
|
194
|
+
args: readonly string[],
|
|
195
|
+
options?: Options
|
|
196
|
+
): ChildProcessPromise<Options>
|
|
197
|
+
export function spawn<Options extends SpawnOptions>(
|
|
198
|
+
command: string,
|
|
199
|
+
options?: Options
|
|
200
|
+
): ChildProcessPromise<Options>
|
|
201
|
+
export function spawn<Options extends SpawnOptions>(
|
|
202
|
+
command: string,
|
|
203
|
+
args?: readonly string[] | Options,
|
|
204
|
+
options?: Options
|
|
205
|
+
): ChildProcessPromise<Options> {
|
|
206
|
+
if (!isArray(args)) {
|
|
207
|
+
options = args
|
|
208
|
+
args = []
|
|
209
|
+
}
|
|
210
|
+
return promisifyChildProcess(
|
|
211
|
+
child_process.spawn(command, args, options as child_process.SpawnOptions),
|
|
212
|
+
options
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface ForkOptions extends child_process.ForkOptions {
|
|
217
|
+
encoding?: BufferEncoding
|
|
218
|
+
maxBuffer?: number
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function fork<Options extends ForkOptions>(
|
|
222
|
+
module: string,
|
|
223
|
+
args: Array<string>,
|
|
224
|
+
options?: Options
|
|
225
|
+
): ChildProcessPromise<Options>
|
|
226
|
+
export function fork<Options extends ForkOptions>(
|
|
227
|
+
module: string,
|
|
228
|
+
options?: Options
|
|
229
|
+
): ChildProcessPromise<Options>
|
|
230
|
+
export function fork<Options extends ForkOptions>(
|
|
231
|
+
module: string,
|
|
232
|
+
args?: Array<string> | Options,
|
|
233
|
+
options?: Options
|
|
234
|
+
): ChildProcessPromise<Options> {
|
|
235
|
+
if (!isArray(args)) {
|
|
236
|
+
options = args
|
|
237
|
+
args = []
|
|
238
|
+
}
|
|
239
|
+
return promisifyChildProcess(
|
|
240
|
+
child_process.fork(module, args, options),
|
|
241
|
+
options
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
function promisifyExecMethod(method: (...args: any[]) => ChildProcess) {
|
|
245
|
+
return (...args: any[]): ChildProcessPromise<any> => {
|
|
246
|
+
let child: ChildProcess | undefined
|
|
247
|
+
const promise = new Promise<ChildProcessResult<any>>((resolve, reject) => {
|
|
248
|
+
child = method(
|
|
249
|
+
...args,
|
|
250
|
+
(
|
|
251
|
+
err: Error | null,
|
|
252
|
+
stdout: string | Buffer,
|
|
253
|
+
stderr: string | Buffer
|
|
254
|
+
) => {
|
|
255
|
+
if (err) {
|
|
256
|
+
reject(Object.assign(err, { stdout, stderr }))
|
|
257
|
+
} else {
|
|
258
|
+
resolve({
|
|
259
|
+
code: 0,
|
|
260
|
+
signal: null,
|
|
261
|
+
killed: false,
|
|
262
|
+
stdout: stdout as any,
|
|
263
|
+
stderr: stderr as any,
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
)
|
|
268
|
+
})
|
|
269
|
+
if (!child) {
|
|
270
|
+
throw new Error('unexpected error: child has not been initialized')
|
|
271
|
+
}
|
|
272
|
+
return Object.create(child, {
|
|
273
|
+
then: { value: promise.then.bind(promise) },
|
|
274
|
+
catch: { value: promise.catch.bind(promise) },
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
276
|
+
finally: { value: promise.finally?.bind(promise) },
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface ExecOptions extends child_process.ExecOptions {
|
|
282
|
+
encoding?: BufferEncoding | 'buffer'
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export const exec: <Options extends ExecOptions>(
|
|
286
|
+
command: string,
|
|
287
|
+
options?: Options
|
|
288
|
+
) => ChildProcessPromise<Options> = promisifyExecMethod(child_process.exec)
|
|
289
|
+
|
|
290
|
+
export interface ExecFileOptions extends child_process.ExecFileOptions {
|
|
291
|
+
encoding?: BufferEncoding | 'buffer'
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export const execFile: {
|
|
295
|
+
<Options extends ExecFileOptions>(
|
|
296
|
+
file: string,
|
|
297
|
+
args: readonly string[],
|
|
298
|
+
options?: Options
|
|
299
|
+
): ChildProcessPromise<Options>
|
|
300
|
+
<Options extends ExecFileOptions>(
|
|
301
|
+
file: string,
|
|
302
|
+
options?: Options
|
|
303
|
+
): ChildProcessPromise<Options>
|
|
304
|
+
} = promisifyExecMethod(child_process.execFile)
|
|
305
|
+
|
|
306
|
+
export function isChildProcessError(error: unknown): error is Error & {
|
|
307
|
+
code: number | null
|
|
308
|
+
signal: NodeJS.Signals | null
|
|
309
|
+
killed: boolean
|
|
310
|
+
stdout?: string | Buffer
|
|
311
|
+
stderr?: string | Buffer
|
|
312
|
+
} {
|
|
313
|
+
return error instanceof Error && 'code' in error && 'signal' in error
|
|
314
|
+
}
|