teen_process 2.1.7 → 2.1.9
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/build/lib/circular-buffer.d.ts +13 -0
- package/build/lib/circular-buffer.d.ts.map +1 -0
- package/build/lib/circular-buffer.js +54 -0
- package/build/lib/circular-buffer.js.map +1 -0
- package/build/lib/exec.d.ts.map +1 -1
- package/build/lib/exec.js +11 -37
- package/build/lib/exec.js.map +1 -1
- package/lib/circular-buffer.ts +60 -0
- package/lib/exec.js +12 -37
- package/package.json +4 -6
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const MAX_BUFFER_SIZE: number;
|
|
2
|
+
export declare class CircularBuffer {
|
|
3
|
+
private _buf;
|
|
4
|
+
private _size;
|
|
5
|
+
private _maxSize;
|
|
6
|
+
constructor(maxSize?: number);
|
|
7
|
+
get size(): number;
|
|
8
|
+
get count(): number;
|
|
9
|
+
add(item: Buffer): this;
|
|
10
|
+
value(): Buffer;
|
|
11
|
+
private _align;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=circular-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circular-buffer.d.ts","sourceRoot":"","sources":["../../lib/circular-buffer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,QAAoB,CAAC;AAGjD,qBAAa,cAAc;IACzB,OAAO,CAAC,IAAI,CAAW;IACvB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,SAAkB;IAMrC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAEM,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAOvB,KAAK,IAAI,MAAM;IAItB,OAAO,CAAC,MAAM;CA0Bf"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CircularBuffer = exports.MAX_BUFFER_SIZE = void 0;
|
|
4
|
+
exports.MAX_BUFFER_SIZE = 100 * 1024 * 1024; // 100 MiB
|
|
5
|
+
const THRESHOLD = 0.15;
|
|
6
|
+
class CircularBuffer {
|
|
7
|
+
constructor(maxSize = exports.MAX_BUFFER_SIZE) {
|
|
8
|
+
this._maxSize = maxSize;
|
|
9
|
+
this._buf = [];
|
|
10
|
+
this._size = 0;
|
|
11
|
+
}
|
|
12
|
+
get size() {
|
|
13
|
+
return this._size;
|
|
14
|
+
}
|
|
15
|
+
get count() {
|
|
16
|
+
return this._buf.length;
|
|
17
|
+
}
|
|
18
|
+
add(item) {
|
|
19
|
+
this._buf.push(item);
|
|
20
|
+
this._size += item.length;
|
|
21
|
+
this._align();
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
value() {
|
|
25
|
+
return Buffer.concat(this._buf);
|
|
26
|
+
}
|
|
27
|
+
_align() {
|
|
28
|
+
if (this._size <= this._maxSize) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
let numberOfItemsToShift = 0;
|
|
32
|
+
// We add the threshold to avoid shifting the array for each `add` call,
|
|
33
|
+
// which reduces the CPU usage
|
|
34
|
+
const expectedSizeToShift = this._size - this._maxSize + Math.trunc(this._maxSize * THRESHOLD);
|
|
35
|
+
let actualShiftedSize = 0;
|
|
36
|
+
while (numberOfItemsToShift < this._buf.length - 1 && actualShiftedSize <= expectedSizeToShift) {
|
|
37
|
+
actualShiftedSize += this._buf[numberOfItemsToShift].length;
|
|
38
|
+
numberOfItemsToShift++;
|
|
39
|
+
}
|
|
40
|
+
if (numberOfItemsToShift > 0) {
|
|
41
|
+
this._buf.splice(0, numberOfItemsToShift);
|
|
42
|
+
this._size -= actualShiftedSize;
|
|
43
|
+
}
|
|
44
|
+
if (actualShiftedSize < expectedSizeToShift) {
|
|
45
|
+
// We have already deleted all buffer items, but one,
|
|
46
|
+
// although the recent item is still too big to fit into the allowed size limit
|
|
47
|
+
const remainderToShift = expectedSizeToShift - actualShiftedSize;
|
|
48
|
+
this._buf[0] = this._buf[0].subarray(remainderToShift);
|
|
49
|
+
this._size -= remainderToShift;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.CircularBuffer = CircularBuffer;
|
|
54
|
+
//# sourceMappingURL=circular-buffer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circular-buffer.js","sourceRoot":"","sources":["../../lib/circular-buffer.ts"],"names":[],"mappings":";;;AAAa,QAAA,eAAe,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,UAAU;AAC5D,MAAM,SAAS,GAAG,IAAI,CAAC;AAEvB,MAAa,cAAc;IAKzB,YAAY,OAAO,GAAG,uBAAe;QACnC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAEM,GAAG,CAAC,IAAY;QACrB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK;QACV,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAEO,MAAM;QACZ,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,OAAO;QACT,CAAC;QAED,IAAI,oBAAoB,GAAG,CAAC,CAAC;QAC7B,wEAAwE;QACxE,8BAA8B;QAC9B,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;QAC/F,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,OAAO,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,iBAAiB,IAAI,mBAAmB,EAAE,CAAC;YAC/F,iBAAiB,IAAI,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,CAAC;YAC5D,oBAAoB,EAAE,CAAC;QACzB,CAAC;QACD,IAAI,oBAAoB,GAAG,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK,IAAI,iBAAiB,CAAC;QAClC,CAAC;QACD,IAAI,iBAAiB,GAAG,mBAAmB,EAAE,CAAC;YAC5C,qDAAqD;YACrD,+EAA+E;YAC/E,MAAM,gBAAgB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;YACjE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YACvD,IAAI,CAAC,KAAK,IAAI,gBAAgB,CAAC;QACjC,CAAC;IACH,CAAC;CACF;AAxDD,wCAwDC"}
|
package/build/lib/exec.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../lib/exec.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../lib/exec.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAqJc,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI;;;;;qCAKzB,OAAO,eAAe,EAAE,YAAY,GAAG,gBAAgB;;;;;;;;YAMtD,MAAM;;;;YACN,MAAM;;;;UACN,MAAM,OAAC;;;;;;;;;YAMP,MAAM;;;;YACN,MAAM;;;;UACN,MAAM,OAAC;;;;;;;;;YAMP,MAAM;;;;YACN,MAAM;;;;UACN,MAAM,OAAC;;;;;mCAKR,KAAK,GAAG,yBAAyB;uBAIV,WAAW,SAAlC;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,IACtB,WAAW,CAAC,UAAU,CAAC;AArLpC;;;;;;;GAOG;AACH,qBANsC,CAAC,SAAzB,sBAAuB,OAC1B,MAAM,8DAGJ,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,2BAA2B,GAAG,2BAA2B,CAAC,CAqH3G"}
|
package/build/lib/exec.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable promise/prefer-await-to-callbacks */
|
|
3
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
4
|
};
|
|
@@ -10,7 +9,7 @@ const shell_quote_1 = require("shell-quote");
|
|
|
10
9
|
const bluebird_1 = __importDefault(require("bluebird"));
|
|
11
10
|
const lodash_1 = __importDefault(require("lodash"));
|
|
12
11
|
const helpers_1 = require("./helpers");
|
|
13
|
-
const
|
|
12
|
+
const circular_buffer_1 = require("./circular-buffer");
|
|
14
13
|
/**
|
|
15
14
|
* Spawns a process
|
|
16
15
|
* @template {TeenProcessExecOptions} T
|
|
@@ -35,8 +34,8 @@ async function exec(cmd, args = [], originalOpts = /** @type {T} */ ({})) {
|
|
|
35
34
|
isBuffer: false,
|
|
36
35
|
shell: undefined,
|
|
37
36
|
logger: undefined,
|
|
38
|
-
maxStdoutBufferSize: MAX_BUFFER_SIZE,
|
|
39
|
-
maxStderrBufferSize: MAX_BUFFER_SIZE,
|
|
37
|
+
maxStdoutBufferSize: circular_buffer_1.MAX_BUFFER_SIZE,
|
|
38
|
+
maxStderrBufferSize: circular_buffer_1.MAX_BUFFER_SIZE,
|
|
40
39
|
}));
|
|
41
40
|
const isBuffer = Boolean(opts.isBuffer);
|
|
42
41
|
// this is an async function, so return a promise
|
|
@@ -44,10 +43,8 @@ async function exec(cmd, args = [], originalOpts = /** @type {T} */ ({})) {
|
|
|
44
43
|
// spawn the child process with options; we don't currently expose any of
|
|
45
44
|
// the other 'spawn' options through the API
|
|
46
45
|
const proc = (0, child_process_1.spawn)(cmd, args, { cwd: opts.cwd, env: opts.env, shell: opts.shell });
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
/** @type {Buffer[]} */
|
|
50
|
-
const stderrArr = [];
|
|
46
|
+
const stdoutBuffer = new circular_buffer_1.CircularBuffer(opts.maxStdoutBufferSize);
|
|
47
|
+
const stderrBuffer = new circular_buffer_1.CircularBuffer(opts.maxStderrBufferSize);
|
|
51
48
|
let timer = null;
|
|
52
49
|
// if the process errors out, reject the promise
|
|
53
50
|
proc.on('error', /** @param {NodeJS.ErrnoException} err */ async (err) => {
|
|
@@ -61,7 +58,7 @@ async function exec(cmd, args = [], originalOpts = /** @type {T} */ ({})) {
|
|
|
61
58
|
reject(new Error(`Standard input '${err.syscall}' error: ${err.stack}`));
|
|
62
59
|
});
|
|
63
60
|
}
|
|
64
|
-
const handleStream = (streamType,
|
|
61
|
+
const handleStream = (/** @type {string} */ streamType, /** @type {CircularBuffer} */ buffer) => {
|
|
65
62
|
if (!proc[streamType]) {
|
|
66
63
|
return;
|
|
67
64
|
}
|
|
@@ -74,46 +71,23 @@ async function exec(cmd, args = [], originalOpts = /** @type {T} */ ({})) {
|
|
|
74
71
|
return;
|
|
75
72
|
}
|
|
76
73
|
// keep track of the stream if we don't want to ignore it
|
|
77
|
-
const { chunks, maxSize } = streamProps;
|
|
78
|
-
let size = 0;
|
|
79
74
|
proc[streamType].on('data', (/** @type {Buffer} */ chunk) => {
|
|
80
|
-
|
|
81
|
-
size += chunk.length;
|
|
82
|
-
while (chunks.length > 1 && size >= maxSize) {
|
|
83
|
-
size -= chunks[0].length;
|
|
84
|
-
chunks.shift();
|
|
85
|
-
}
|
|
75
|
+
buffer.add(chunk);
|
|
86
76
|
if (opts.logger && lodash_1.default.isFunction(opts.logger.debug)) {
|
|
87
77
|
opts.logger.debug(chunk.toString());
|
|
88
78
|
}
|
|
89
79
|
});
|
|
90
80
|
};
|
|
91
|
-
handleStream('stdout',
|
|
92
|
-
|
|
93
|
-
chunks: stdoutArr,
|
|
94
|
-
});
|
|
95
|
-
handleStream('stderr', {
|
|
96
|
-
maxSize: opts.maxStderrBufferSize,
|
|
97
|
-
chunks: stderrArr,
|
|
98
|
-
});
|
|
81
|
+
handleStream('stdout', stdoutBuffer);
|
|
82
|
+
handleStream('stderr', stderrBuffer);
|
|
99
83
|
/**
|
|
100
84
|
* @template {boolean} U
|
|
101
85
|
* @param {U} isBuffer
|
|
102
86
|
* @returns {U extends true ? {stdout: Buffer, stderr: Buffer} : {stdout: string, stderr: string}}
|
|
103
87
|
*/
|
|
104
88
|
function getStdio(isBuffer) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
/** @type {string | Buffer} */
|
|
108
|
-
let stderr;
|
|
109
|
-
if (isBuffer) {
|
|
110
|
-
stdout = Buffer.concat(stdoutArr);
|
|
111
|
-
stderr = Buffer.concat(stderrArr);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
stdout = Buffer.concat(stdoutArr).toString(opts.encoding);
|
|
115
|
-
stderr = Buffer.concat(stderrArr).toString(opts.encoding);
|
|
116
|
-
}
|
|
89
|
+
const stdout = isBuffer ? stdoutBuffer.value() : stdoutBuffer.value().toString(opts.encoding);
|
|
90
|
+
const stderr = isBuffer ? stderrBuffer.value() : stderrBuffer.value().toString(opts.encoding);
|
|
117
91
|
return /** @type {U extends true ? {stdout: Buffer, stderr: Buffer} : {stdout: string, stderr: string}} */ ({ stdout, stderr });
|
|
118
92
|
}
|
|
119
93
|
// if the process ends, either resolve or reject the promise based on the
|
package/build/lib/exec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../lib/exec.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../lib/exec.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const MAX_BUFFER_SIZE = 100 * 1024 * 1024; // 100 MiB
|
|
2
|
+
const THRESHOLD = 0.15;
|
|
3
|
+
|
|
4
|
+
export class CircularBuffer {
|
|
5
|
+
private _buf: Buffer[];
|
|
6
|
+
private _size: number;
|
|
7
|
+
private _maxSize: number;
|
|
8
|
+
|
|
9
|
+
constructor(maxSize = MAX_BUFFER_SIZE) {
|
|
10
|
+
this._maxSize = maxSize;
|
|
11
|
+
this._buf = [];
|
|
12
|
+
this._size = 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get size(): number {
|
|
16
|
+
return this._size;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get count(): number {
|
|
20
|
+
return this._buf.length;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public add(item: Buffer): this {
|
|
24
|
+
this._buf.push(item);
|
|
25
|
+
this._size += item.length;
|
|
26
|
+
this._align();
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public value(): Buffer {
|
|
31
|
+
return Buffer.concat(this._buf);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private _align(): void {
|
|
35
|
+
if (this._size <= this._maxSize) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let numberOfItemsToShift = 0;
|
|
40
|
+
// We add the threshold to avoid shifting the array for each `add` call,
|
|
41
|
+
// which reduces the CPU usage
|
|
42
|
+
const expectedSizeToShift = this._size - this._maxSize + Math.trunc(this._maxSize * THRESHOLD);
|
|
43
|
+
let actualShiftedSize = 0;
|
|
44
|
+
while (numberOfItemsToShift < this._buf.length - 1 && actualShiftedSize <= expectedSizeToShift) {
|
|
45
|
+
actualShiftedSize += this._buf[numberOfItemsToShift].length;
|
|
46
|
+
numberOfItemsToShift++;
|
|
47
|
+
}
|
|
48
|
+
if (numberOfItemsToShift > 0) {
|
|
49
|
+
this._buf.splice(0, numberOfItemsToShift);
|
|
50
|
+
this._size -= actualShiftedSize;
|
|
51
|
+
}
|
|
52
|
+
if (actualShiftedSize < expectedSizeToShift) {
|
|
53
|
+
// We have already deleted all buffer items, but one,
|
|
54
|
+
// although the recent item is still too big to fit into the allowed size limit
|
|
55
|
+
const remainderToShift = expectedSizeToShift - actualShiftedSize;
|
|
56
|
+
this._buf[0] = this._buf[0].subarray(remainderToShift);
|
|
57
|
+
this._size -= remainderToShift;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
package/lib/exec.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
/* eslint-disable promise/prefer-await-to-callbacks */
|
|
2
|
-
|
|
3
1
|
import { spawn } from 'child_process';
|
|
4
2
|
import { quote } from 'shell-quote';
|
|
5
3
|
import B from 'bluebird';
|
|
6
4
|
import _ from 'lodash';
|
|
7
5
|
import { formatEnoent } from './helpers';
|
|
8
|
-
|
|
9
|
-
const MAX_BUFFER_SIZE = 100 * 1024 * 1024;
|
|
6
|
+
import { CircularBuffer, MAX_BUFFER_SIZE } from './circular-buffer';
|
|
10
7
|
|
|
11
8
|
/**
|
|
12
9
|
* Spawns a process
|
|
@@ -44,10 +41,8 @@ async function exec (cmd, args = [], originalOpts = /** @type {T} */({})) {
|
|
|
44
41
|
// spawn the child process with options; we don't currently expose any of
|
|
45
42
|
// the other 'spawn' options through the API
|
|
46
43
|
const proc = spawn(cmd, args, {cwd: opts.cwd, env: opts.env, shell: opts.shell});
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
/** @type {Buffer[]} */
|
|
50
|
-
const stderrArr = [];
|
|
44
|
+
const stdoutBuffer = new CircularBuffer(opts.maxStdoutBufferSize);
|
|
45
|
+
const stderrBuffer = new CircularBuffer(opts.maxStderrBufferSize);
|
|
51
46
|
let timer = null;
|
|
52
47
|
|
|
53
48
|
// if the process errors out, reject the promise
|
|
@@ -62,7 +57,7 @@ async function exec (cmd, args = [], originalOpts = /** @type {T} */({})) {
|
|
|
62
57
|
reject(new Error(`Standard input '${err.syscall}' error: ${err.stack}`));
|
|
63
58
|
});
|
|
64
59
|
}
|
|
65
|
-
const handleStream = (streamType,
|
|
60
|
+
const handleStream = (/** @type {string} */ streamType, /** @type {CircularBuffer} */ buffer) => {
|
|
66
61
|
if (!proc[streamType]) {
|
|
67
62
|
return;
|
|
68
63
|
}
|
|
@@ -78,28 +73,15 @@ async function exec (cmd, args = [], originalOpts = /** @type {T} */({})) {
|
|
|
78
73
|
}
|
|
79
74
|
|
|
80
75
|
// keep track of the stream if we don't want to ignore it
|
|
81
|
-
const {chunks, maxSize} = streamProps;
|
|
82
|
-
let size = 0;
|
|
83
76
|
proc[streamType].on('data', (/** @type {Buffer} */ chunk) => {
|
|
84
|
-
|
|
85
|
-
size += chunk.length;
|
|
86
|
-
while (chunks.length > 1 && size >= maxSize) {
|
|
87
|
-
size -= chunks[0].length;
|
|
88
|
-
chunks.shift();
|
|
89
|
-
}
|
|
77
|
+
buffer.add(chunk);
|
|
90
78
|
if (opts.logger && _.isFunction(opts.logger.debug)) {
|
|
91
79
|
opts.logger.debug(chunk.toString());
|
|
92
80
|
}
|
|
93
81
|
});
|
|
94
82
|
};
|
|
95
|
-
handleStream('stdout',
|
|
96
|
-
|
|
97
|
-
chunks: stdoutArr,
|
|
98
|
-
});
|
|
99
|
-
handleStream('stderr', {
|
|
100
|
-
maxSize: opts.maxStderrBufferSize,
|
|
101
|
-
chunks: stderrArr,
|
|
102
|
-
});
|
|
83
|
+
handleStream('stdout', stdoutBuffer);
|
|
84
|
+
handleStream('stderr', stderrBuffer);
|
|
103
85
|
|
|
104
86
|
/**
|
|
105
87
|
* @template {boolean} U
|
|
@@ -107,18 +89,11 @@ async function exec (cmd, args = [], originalOpts = /** @type {T} */({})) {
|
|
|
107
89
|
* @returns {U extends true ? {stdout: Buffer, stderr: Buffer} : {stdout: string, stderr: string}}
|
|
108
90
|
*/
|
|
109
91
|
function getStdio (isBuffer) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
/** @type {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
stdout = Buffer.concat(stdoutArr);
|
|
116
|
-
stderr = Buffer.concat(stderrArr);
|
|
117
|
-
} else {
|
|
118
|
-
stdout = Buffer.concat(stdoutArr).toString(opts.encoding);
|
|
119
|
-
stderr = Buffer.concat(stderrArr).toString(opts.encoding);
|
|
120
|
-
}
|
|
121
|
-
return /** @type {U extends true ? {stdout: Buffer, stderr: Buffer} : {stdout: string, stderr: string}} */({stdout, stderr});
|
|
92
|
+
const stdout = isBuffer ? stdoutBuffer.value() : stdoutBuffer.value().toString(opts.encoding);
|
|
93
|
+
const stderr = isBuffer ? stderrBuffer.value() : stderrBuffer.value().toString(opts.encoding);
|
|
94
|
+
return /** @type {U extends true ? {stdout: Buffer, stderr: Buffer} : {stdout: string, stderr: string}} */(
|
|
95
|
+
{stdout, stderr}
|
|
96
|
+
);
|
|
122
97
|
}
|
|
123
98
|
|
|
124
99
|
// if the process ends, either resolve or reject the promise based on the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teen_process",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.9",
|
|
4
4
|
"description": "A grown up version of Node's spawn/exec",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"child_process",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
},
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
22
|
"author": "Appium Contributors",
|
|
23
|
-
"main": "
|
|
23
|
+
"main": "index.js",
|
|
24
|
+
"types": "./build/lib/index.d.ts",
|
|
24
25
|
"bin": {},
|
|
25
26
|
"directories": {
|
|
26
27
|
"lib": "lib"
|
|
@@ -53,15 +54,13 @@
|
|
|
53
54
|
"source-map-support": "^0.x"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
|
-
"@appium/eslint-config-appium": "^
|
|
57
|
+
"@appium/eslint-config-appium-ts": "^0.x",
|
|
57
58
|
"@appium/tsconfig": "^0.x",
|
|
58
59
|
"@appium/types": "^0.x",
|
|
59
60
|
"@semantic-release/changelog": "^6.0.3",
|
|
60
61
|
"@semantic-release/git": "^10.0.1",
|
|
61
62
|
"@types/bluebird": "^3.5.42",
|
|
62
|
-
"@types/chai-as-promised": "^7.1.8",
|
|
63
63
|
"@types/lodash": "^4.14.202",
|
|
64
|
-
"@types/mocha": "^10.0.6",
|
|
65
64
|
"@types/node": "^20.10.4",
|
|
66
65
|
"@types/shell-quote": "^1.7.5",
|
|
67
66
|
"@types/source-map-support": "^0.x",
|
|
@@ -72,7 +71,6 @@
|
|
|
72
71
|
"mocha": "^10.2.0",
|
|
73
72
|
"prettier": "^3.1.0",
|
|
74
73
|
"semantic-release": "^24.0.0",
|
|
75
|
-
"sinon": "^18.0.0",
|
|
76
74
|
"typescript": "^5.4.1",
|
|
77
75
|
"ts-node": "^10.9.1"
|
|
78
76
|
},
|