@naturalcycles/nodejs-lib 13.34.4 → 13.34.6
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/dist/stream/transform/transformThrottle.js +12 -7
- package/dist/util/exec2.d.ts +36 -23
- package/dist/util/exec2.js +114 -82
- package/package.json +1 -1
- package/src/stream/transform/transformThrottle.ts +14 -6
- package/src/util/exec2.ts +129 -96
|
@@ -49,7 +49,7 @@ function transformThrottle(opt) {
|
|
|
49
49
|
// console.log('pausing now after', {item, count})
|
|
50
50
|
paused = (0, js_lib_1.pDefer)();
|
|
51
51
|
if (debug) {
|
|
52
|
-
console.log(`${js_lib_1.localTime.now().toPretty()} transformThrottle activated: ${count} items passed in ${(0, js_lib_1.
|
|
52
|
+
console.log(`${js_lib_1.localTime.now().toPretty()} transformThrottle activated: ${count} items passed in ${(0, js_lib_1._since)(start)}, will pause for ${(0, js_lib_1._ms)(interval * 1000 - (Date.now() - start))}`);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
cb(null, item); // pass the item through
|
|
@@ -60,15 +60,20 @@ function transformThrottle(opt) {
|
|
|
60
60
|
},
|
|
61
61
|
});
|
|
62
62
|
function onInterval(transform) {
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
if (paused) {
|
|
64
|
+
if (debug) {
|
|
65
|
+
console.log(`${js_lib_1.localTime.now().toPretty()} transformThrottle resumed`);
|
|
66
|
+
}
|
|
67
|
+
paused.resolve();
|
|
68
|
+
paused = undefined;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
if (debug) {
|
|
72
|
+
console.log(`${js_lib_1.localTime.now().toPretty()} transformThrottle passed ${count} (of max ${throughput}) items in ${(0, js_lib_1._since)(start)}`);
|
|
73
|
+
}
|
|
67
74
|
}
|
|
68
75
|
count = 0;
|
|
69
76
|
start = Date.now();
|
|
70
77
|
timeout = setTimeout(() => onInterval(transform), interval * 1000);
|
|
71
|
-
paused.resolve();
|
|
72
|
-
paused = undefined;
|
|
73
78
|
}
|
|
74
79
|
}
|
package/dist/util/exec2.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { AnyObject, AppError, NumberOfMilliseconds } from '@naturalcycles/js-lib
|
|
|
8
8
|
*
|
|
9
9
|
* Short-running job, no need to print the output, might want to return the output - use Exec.
|
|
10
10
|
*
|
|
11
|
-
* Need to both print and return the output - use
|
|
11
|
+
* Need to both print and return the output - use SpawnAsyncAndReturn.
|
|
12
12
|
*
|
|
13
13
|
* ***
|
|
14
14
|
*
|
|
@@ -22,33 +22,13 @@ import { AnyObject, AppError, NumberOfMilliseconds } from '@naturalcycles/js-lib
|
|
|
22
22
|
* Exec always uses the shell (there's no option to disable it).
|
|
23
23
|
*/
|
|
24
24
|
declare class Exec2 {
|
|
25
|
-
/**
|
|
26
|
-
* Advanced/async version of Spawn.
|
|
27
|
-
* Consider simpler `spawn` or `exec` first, which are also sync.
|
|
28
|
-
*
|
|
29
|
-
* spawnAsync features:
|
|
30
|
-
*
|
|
31
|
-
* 1. Async
|
|
32
|
-
* 2. Allows to collect the output AND print it while running.
|
|
33
|
-
* 3. Returns SpawnOutput with stdout, stderr and exitCode.
|
|
34
|
-
* 4. Allows to not throw on error, but just return SpawnOutput for further inspection.
|
|
35
|
-
*
|
|
36
|
-
* Defaults:
|
|
37
|
-
*
|
|
38
|
-
* shell: true
|
|
39
|
-
* printWhileRunning: true
|
|
40
|
-
* collectOutputWhileRunning: true
|
|
41
|
-
* throwOnNonZeroCode: true
|
|
42
|
-
* log: true
|
|
43
|
-
*/
|
|
44
|
-
spawnAsync(cmd: string, opt?: SpawnAsyncOptions): Promise<SpawnOutput>;
|
|
45
25
|
/**
|
|
46
26
|
* Reasons to use it:
|
|
47
27
|
* - Sync
|
|
48
28
|
* - Need to print output while running
|
|
49
29
|
*
|
|
50
30
|
* Limitations:
|
|
51
|
-
* - Cannot return stdout/stderr (use exec or
|
|
31
|
+
* - Cannot return stdout/stderr (use exec, execAsync or spawnAsyncAndReturn for that)
|
|
52
32
|
*
|
|
53
33
|
* Defaults:
|
|
54
34
|
*
|
|
@@ -71,7 +51,40 @@ declare class Exec2 {
|
|
|
71
51
|
* log: false
|
|
72
52
|
*/
|
|
73
53
|
exec(cmd: string, opt?: ExecOptions): string;
|
|
74
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Reasons to use it:
|
|
56
|
+
* - Async
|
|
57
|
+
* - Need to print output while running
|
|
58
|
+
*
|
|
59
|
+
* Limitations:
|
|
60
|
+
* - Cannot return stdout/stderr (use execAsync or spawnAsyncAndReturn for that)
|
|
61
|
+
*
|
|
62
|
+
* Defaults:
|
|
63
|
+
*
|
|
64
|
+
* shell: true
|
|
65
|
+
* log: true
|
|
66
|
+
*/
|
|
67
|
+
spawnAsync(cmd: string, opt?: SpawnOptions): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Advanced/async version of Spawn.
|
|
70
|
+
* Consider simpler `spawn` or `exec` first, which are also sync.
|
|
71
|
+
*
|
|
72
|
+
* spawnAsyncAndReturn features:
|
|
73
|
+
*
|
|
74
|
+
* 1. Async
|
|
75
|
+
* 2. Allows to collect the output AND print it while running.
|
|
76
|
+
* 3. Returns SpawnOutput with stdout, stderr and exitCode.
|
|
77
|
+
* 4. Allows to not throw on error, but just return SpawnOutput for further inspection.
|
|
78
|
+
*
|
|
79
|
+
* Defaults:
|
|
80
|
+
*
|
|
81
|
+
* shell: true
|
|
82
|
+
* printWhileRunning: true
|
|
83
|
+
* collectOutputWhileRunning: true
|
|
84
|
+
* throwOnNonZeroCode: true
|
|
85
|
+
* log: true
|
|
86
|
+
*/
|
|
87
|
+
spawnAsyncAndReturn(cmd: string, opt?: SpawnAsyncOptions): Promise<SpawnOutput>;
|
|
75
88
|
private logStart;
|
|
76
89
|
private logFinish;
|
|
77
90
|
}
|
package/dist/util/exec2.js
CHANGED
|
@@ -14,7 +14,7 @@ const colors_1 = require("../colors/colors");
|
|
|
14
14
|
*
|
|
15
15
|
* Short-running job, no need to print the output, might want to return the output - use Exec.
|
|
16
16
|
*
|
|
17
|
-
* Need to both print and return the output - use
|
|
17
|
+
* Need to both print and return the output - use SpawnAsyncAndReturn.
|
|
18
18
|
*
|
|
19
19
|
* ***
|
|
20
20
|
*
|
|
@@ -28,87 +28,13 @@ const colors_1 = require("../colors/colors");
|
|
|
28
28
|
* Exec always uses the shell (there's no option to disable it).
|
|
29
29
|
*/
|
|
30
30
|
class Exec2 {
|
|
31
|
-
/**
|
|
32
|
-
* Advanced/async version of Spawn.
|
|
33
|
-
* Consider simpler `spawn` or `exec` first, which are also sync.
|
|
34
|
-
*
|
|
35
|
-
* spawnAsync features:
|
|
36
|
-
*
|
|
37
|
-
* 1. Async
|
|
38
|
-
* 2. Allows to collect the output AND print it while running.
|
|
39
|
-
* 3. Returns SpawnOutput with stdout, stderr and exitCode.
|
|
40
|
-
* 4. Allows to not throw on error, but just return SpawnOutput for further inspection.
|
|
41
|
-
*
|
|
42
|
-
* Defaults:
|
|
43
|
-
*
|
|
44
|
-
* shell: true
|
|
45
|
-
* printWhileRunning: true
|
|
46
|
-
* collectOutputWhileRunning: true
|
|
47
|
-
* throwOnNonZeroCode: true
|
|
48
|
-
* log: true
|
|
49
|
-
*/
|
|
50
|
-
async spawnAsync(cmd, opt = {}) {
|
|
51
|
-
const { shell = true, printWhileRunning = true, collectOutputWhileRunning = true, throwOnNonZeroCode = true, cwd, env, passProcessEnv = true, forceColor = colors_1.hasColors, } = opt;
|
|
52
|
-
opt.log ??= printWhileRunning; // by default log should be true, as we are printing the output
|
|
53
|
-
opt.logStart ??= opt.log;
|
|
54
|
-
opt.logFinish ??= opt.log;
|
|
55
|
-
const started = Date.now();
|
|
56
|
-
this.logStart(cmd, opt);
|
|
57
|
-
let stdout = '';
|
|
58
|
-
let stderr = '';
|
|
59
|
-
// if (printWhileRunning) console.log('') // 1-line padding before the output
|
|
60
|
-
return await new Promise((resolve, reject) => {
|
|
61
|
-
const p = node_child_process_1.default.spawn(cmd, opt.args || [], {
|
|
62
|
-
shell,
|
|
63
|
-
cwd,
|
|
64
|
-
env: {
|
|
65
|
-
...(passProcessEnv ? process.env : {}),
|
|
66
|
-
...(forceColor ? { FORCE_COLOR: '1' } : {}),
|
|
67
|
-
...env,
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
p.stdout.on('data', data => {
|
|
71
|
-
if (collectOutputWhileRunning) {
|
|
72
|
-
stdout += data.toString();
|
|
73
|
-
// console.log('stdout:', data.toString())
|
|
74
|
-
}
|
|
75
|
-
if (printWhileRunning) {
|
|
76
|
-
process.stdout.write(data);
|
|
77
|
-
// console.log('stderr:', data.toString())
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
p.stderr.on('data', data => {
|
|
81
|
-
if (collectOutputWhileRunning) {
|
|
82
|
-
stderr += data.toString();
|
|
83
|
-
}
|
|
84
|
-
if (printWhileRunning) {
|
|
85
|
-
process.stderr.write(data);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
p.on('close', code => {
|
|
89
|
-
// if (printWhileRunning) console.log('') // 1-line padding after the output
|
|
90
|
-
const isSuccessful = !code;
|
|
91
|
-
this.logFinish(cmd, opt, started, isSuccessful);
|
|
92
|
-
const exitCode = code || 0;
|
|
93
|
-
const o = {
|
|
94
|
-
exitCode,
|
|
95
|
-
stdout: stdout.trim(),
|
|
96
|
-
stderr: stderr.trim(),
|
|
97
|
-
};
|
|
98
|
-
if (throwOnNonZeroCode && code) {
|
|
99
|
-
return reject(new SpawnError(`spawnAsync exited with code ${code}: ${cmd}`, o));
|
|
100
|
-
}
|
|
101
|
-
resolve(o);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
31
|
/**
|
|
106
32
|
* Reasons to use it:
|
|
107
33
|
* - Sync
|
|
108
34
|
* - Need to print output while running
|
|
109
35
|
*
|
|
110
36
|
* Limitations:
|
|
111
|
-
* - Cannot return stdout/stderr (use exec or
|
|
37
|
+
* - Cannot return stdout/stderr (use exec, execAsync or spawnAsyncAndReturn for that)
|
|
112
38
|
*
|
|
113
39
|
* Defaults:
|
|
114
40
|
*
|
|
@@ -122,7 +48,6 @@ class Exec2 {
|
|
|
122
48
|
opt.logFinish ??= opt.log;
|
|
123
49
|
const started = Date.now();
|
|
124
50
|
this.logStart(cmd, opt);
|
|
125
|
-
// console.log('') // 1-line padding before the output
|
|
126
51
|
const r = node_child_process_1.default.spawnSync(cmd, opt.args, {
|
|
127
52
|
encoding: 'utf8',
|
|
128
53
|
stdio: 'inherit',
|
|
@@ -134,7 +59,6 @@ class Exec2 {
|
|
|
134
59
|
...env,
|
|
135
60
|
},
|
|
136
61
|
});
|
|
137
|
-
// console.log('') // 1-line padding after the output
|
|
138
62
|
const isSuccessful = !r.error && !r.status;
|
|
139
63
|
this.logFinish(cmd, opt, started, isSuccessful);
|
|
140
64
|
if (r.error) {
|
|
@@ -195,10 +119,118 @@ class Exec2 {
|
|
|
195
119
|
throw new Error(`exec exited with code ${err.status}: ${cmd}`);
|
|
196
120
|
}
|
|
197
121
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Reasons to use it:
|
|
124
|
+
* - Async
|
|
125
|
+
* - Need to print output while running
|
|
126
|
+
*
|
|
127
|
+
* Limitations:
|
|
128
|
+
* - Cannot return stdout/stderr (use execAsync or spawnAsyncAndReturn for that)
|
|
129
|
+
*
|
|
130
|
+
* Defaults:
|
|
131
|
+
*
|
|
132
|
+
* shell: true
|
|
133
|
+
* log: true
|
|
134
|
+
*/
|
|
135
|
+
async spawnAsync(cmd, opt = {}) {
|
|
136
|
+
const { shell = true, cwd, env, passProcessEnv = true, forceColor = colors_1.hasColors } = opt;
|
|
137
|
+
opt.log ??= true; // by default log should be true, as we are printing the output
|
|
138
|
+
opt.logStart ??= opt.log;
|
|
139
|
+
opt.logFinish ??= opt.log;
|
|
140
|
+
const started = Date.now();
|
|
141
|
+
this.logStart(cmd, opt);
|
|
142
|
+
await new Promise((resolve, reject) => {
|
|
143
|
+
const p = node_child_process_1.default.spawn(cmd, opt.args || [], {
|
|
144
|
+
shell,
|
|
145
|
+
cwd,
|
|
146
|
+
stdio: 'inherit',
|
|
147
|
+
env: {
|
|
148
|
+
...(passProcessEnv ? process.env : {}),
|
|
149
|
+
...(forceColor ? { FORCE_COLOR: '1' } : {}),
|
|
150
|
+
...env,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
p.on('close', code => {
|
|
154
|
+
const isSuccessful = !code;
|
|
155
|
+
this.logFinish(cmd, opt, started, isSuccessful);
|
|
156
|
+
if (code) {
|
|
157
|
+
return reject(new Error(`spawnAsync exited with code ${code}: ${cmd}`));
|
|
158
|
+
}
|
|
159
|
+
resolve();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Advanced/async version of Spawn.
|
|
165
|
+
* Consider simpler `spawn` or `exec` first, which are also sync.
|
|
166
|
+
*
|
|
167
|
+
* spawnAsyncAndReturn features:
|
|
168
|
+
*
|
|
169
|
+
* 1. Async
|
|
170
|
+
* 2. Allows to collect the output AND print it while running.
|
|
171
|
+
* 3. Returns SpawnOutput with stdout, stderr and exitCode.
|
|
172
|
+
* 4. Allows to not throw on error, but just return SpawnOutput for further inspection.
|
|
173
|
+
*
|
|
174
|
+
* Defaults:
|
|
175
|
+
*
|
|
176
|
+
* shell: true
|
|
177
|
+
* printWhileRunning: true
|
|
178
|
+
* collectOutputWhileRunning: true
|
|
179
|
+
* throwOnNonZeroCode: true
|
|
180
|
+
* log: true
|
|
181
|
+
*/
|
|
182
|
+
async spawnAsyncAndReturn(cmd, opt = {}) {
|
|
183
|
+
const { shell = true, printWhileRunning = true, collectOutputWhileRunning = true, throwOnNonZeroCode = true, cwd, env, passProcessEnv = true, forceColor = colors_1.hasColors, } = opt;
|
|
184
|
+
opt.log ??= printWhileRunning; // by default log should be true, as we are printing the output
|
|
185
|
+
opt.logStart ??= opt.log;
|
|
186
|
+
opt.logFinish ??= opt.log;
|
|
187
|
+
const started = Date.now();
|
|
188
|
+
this.logStart(cmd, opt);
|
|
189
|
+
let stdout = '';
|
|
190
|
+
let stderr = '';
|
|
191
|
+
return await new Promise((resolve, reject) => {
|
|
192
|
+
const p = node_child_process_1.default.spawn(cmd, opt.args || [], {
|
|
193
|
+
shell,
|
|
194
|
+
cwd,
|
|
195
|
+
env: {
|
|
196
|
+
...(passProcessEnv ? process.env : {}),
|
|
197
|
+
...(forceColor ? { FORCE_COLOR: '1' } : {}),
|
|
198
|
+
...env,
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
p.stdout.on('data', data => {
|
|
202
|
+
if (collectOutputWhileRunning) {
|
|
203
|
+
stdout += data.toString();
|
|
204
|
+
// console.log('stdout:', data.toString())
|
|
205
|
+
}
|
|
206
|
+
if (printWhileRunning) {
|
|
207
|
+
process.stdout.write(data);
|
|
208
|
+
// console.log('stderr:', data.toString())
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
p.stderr.on('data', data => {
|
|
212
|
+
if (collectOutputWhileRunning) {
|
|
213
|
+
stderr += data.toString();
|
|
214
|
+
}
|
|
215
|
+
if (printWhileRunning) {
|
|
216
|
+
process.stderr.write(data);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
p.on('close', code => {
|
|
220
|
+
const isSuccessful = !code;
|
|
221
|
+
this.logFinish(cmd, opt, started, isSuccessful);
|
|
222
|
+
const exitCode = code || 0;
|
|
223
|
+
const o = {
|
|
224
|
+
exitCode,
|
|
225
|
+
stdout: stdout.trim(),
|
|
226
|
+
stderr: stderr.trim(),
|
|
227
|
+
};
|
|
228
|
+
if (throwOnNonZeroCode && code) {
|
|
229
|
+
return reject(new SpawnError(`spawnAsyncAndReturn exited with code ${code}: ${cmd}`, o));
|
|
230
|
+
}
|
|
231
|
+
resolve(o);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
202
234
|
}
|
|
203
235
|
logStart(cmd, opt) {
|
|
204
236
|
if (!opt.logStart)
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Transform } from 'node:stream'
|
|
2
2
|
import {
|
|
3
3
|
_ms,
|
|
4
|
+
_since,
|
|
4
5
|
DeferredPromise,
|
|
5
6
|
localTime,
|
|
6
7
|
NumberOfMilliseconds,
|
|
@@ -75,7 +76,7 @@ export function transformThrottle<T>(opt: TransformThrottleOptions): TransformTy
|
|
|
75
76
|
paused = pDefer()
|
|
76
77
|
if (debug) {
|
|
77
78
|
console.log(
|
|
78
|
-
`${localTime.now().toPretty()} transformThrottle activated: ${count} items passed in ${
|
|
79
|
+
`${localTime.now().toPretty()} transformThrottle activated: ${count} items passed in ${_since(start)}, will pause for ${_ms(interval * 1000 - (Date.now() - start))}`,
|
|
79
80
|
)
|
|
80
81
|
}
|
|
81
82
|
}
|
|
@@ -89,16 +90,23 @@ export function transformThrottle<T>(opt: TransformThrottleOptions): TransformTy
|
|
|
89
90
|
})
|
|
90
91
|
|
|
91
92
|
function onInterval(transform: Transform): void {
|
|
92
|
-
if (
|
|
93
|
+
if (paused) {
|
|
94
|
+
if (debug) {
|
|
95
|
+
console.log(`${localTime.now().toPretty()} transformThrottle resumed`)
|
|
96
|
+
}
|
|
93
97
|
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
paused.resolve()
|
|
99
|
+
paused = undefined
|
|
100
|
+
} else {
|
|
101
|
+
if (debug) {
|
|
102
|
+
console.log(
|
|
103
|
+
`${localTime.now().toPretty()} transformThrottle passed ${count} (of max ${throughput}) items in ${_since(start)}`,
|
|
104
|
+
)
|
|
105
|
+
}
|
|
96
106
|
}
|
|
97
107
|
|
|
98
108
|
count = 0
|
|
99
109
|
start = Date.now()
|
|
100
110
|
timeout = setTimeout(() => onInterval(transform), interval * 1000)
|
|
101
|
-
paused.resolve()
|
|
102
|
-
paused = undefined
|
|
103
111
|
}
|
|
104
112
|
}
|
package/src/util/exec2.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { dimGrey, dimRed, hasColors, white } from '../colors/colors'
|
|
|
17
17
|
*
|
|
18
18
|
* Short-running job, no need to print the output, might want to return the output - use Exec.
|
|
19
19
|
*
|
|
20
|
-
* Need to both print and return the output - use
|
|
20
|
+
* Need to both print and return the output - use SpawnAsyncAndReturn.
|
|
21
21
|
*
|
|
22
22
|
* ***
|
|
23
23
|
*
|
|
@@ -31,101 +31,13 @@ import { dimGrey, dimRed, hasColors, white } from '../colors/colors'
|
|
|
31
31
|
* Exec always uses the shell (there's no option to disable it).
|
|
32
32
|
*/
|
|
33
33
|
class Exec2 {
|
|
34
|
-
/**
|
|
35
|
-
* Advanced/async version of Spawn.
|
|
36
|
-
* Consider simpler `spawn` or `exec` first, which are also sync.
|
|
37
|
-
*
|
|
38
|
-
* spawnAsync features:
|
|
39
|
-
*
|
|
40
|
-
* 1. Async
|
|
41
|
-
* 2. Allows to collect the output AND print it while running.
|
|
42
|
-
* 3. Returns SpawnOutput with stdout, stderr and exitCode.
|
|
43
|
-
* 4. Allows to not throw on error, but just return SpawnOutput for further inspection.
|
|
44
|
-
*
|
|
45
|
-
* Defaults:
|
|
46
|
-
*
|
|
47
|
-
* shell: true
|
|
48
|
-
* printWhileRunning: true
|
|
49
|
-
* collectOutputWhileRunning: true
|
|
50
|
-
* throwOnNonZeroCode: true
|
|
51
|
-
* log: true
|
|
52
|
-
*/
|
|
53
|
-
async spawnAsync(cmd: string, opt: SpawnAsyncOptions = {}): Promise<SpawnOutput> {
|
|
54
|
-
const {
|
|
55
|
-
shell = true,
|
|
56
|
-
printWhileRunning = true,
|
|
57
|
-
collectOutputWhileRunning = true,
|
|
58
|
-
throwOnNonZeroCode = true,
|
|
59
|
-
cwd,
|
|
60
|
-
env,
|
|
61
|
-
passProcessEnv = true,
|
|
62
|
-
forceColor = hasColors,
|
|
63
|
-
} = opt
|
|
64
|
-
opt.log ??= printWhileRunning // by default log should be true, as we are printing the output
|
|
65
|
-
opt.logStart ??= opt.log
|
|
66
|
-
opt.logFinish ??= opt.log
|
|
67
|
-
const started = Date.now()
|
|
68
|
-
this.logStart(cmd, opt)
|
|
69
|
-
let stdout = ''
|
|
70
|
-
let stderr = ''
|
|
71
|
-
|
|
72
|
-
// if (printWhileRunning) console.log('') // 1-line padding before the output
|
|
73
|
-
|
|
74
|
-
return await new Promise<SpawnOutput>((resolve, reject) => {
|
|
75
|
-
const p = cp.spawn(cmd, opt.args || [], {
|
|
76
|
-
shell,
|
|
77
|
-
cwd,
|
|
78
|
-
env: {
|
|
79
|
-
...(passProcessEnv ? process.env : {}),
|
|
80
|
-
...(forceColor ? { FORCE_COLOR: '1' } : {}),
|
|
81
|
-
...env,
|
|
82
|
-
},
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
p.stdout.on('data', data => {
|
|
86
|
-
if (collectOutputWhileRunning) {
|
|
87
|
-
stdout += data.toString()
|
|
88
|
-
// console.log('stdout:', data.toString())
|
|
89
|
-
}
|
|
90
|
-
if (printWhileRunning) {
|
|
91
|
-
process.stdout.write(data)
|
|
92
|
-
// console.log('stderr:', data.toString())
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
p.stderr.on('data', data => {
|
|
96
|
-
if (collectOutputWhileRunning) {
|
|
97
|
-
stderr += data.toString()
|
|
98
|
-
}
|
|
99
|
-
if (printWhileRunning) {
|
|
100
|
-
process.stderr.write(data)
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
p.on('close', code => {
|
|
105
|
-
// if (printWhileRunning) console.log('') // 1-line padding after the output
|
|
106
|
-
const isSuccessful = !code
|
|
107
|
-
this.logFinish(cmd, opt, started, isSuccessful)
|
|
108
|
-
const exitCode = code || 0
|
|
109
|
-
const o: SpawnOutput = {
|
|
110
|
-
exitCode,
|
|
111
|
-
stdout: stdout.trim(),
|
|
112
|
-
stderr: stderr.trim(),
|
|
113
|
-
}
|
|
114
|
-
if (throwOnNonZeroCode && code) {
|
|
115
|
-
return reject(new SpawnError(`spawnAsync exited with code ${code}: ${cmd}`, o))
|
|
116
|
-
}
|
|
117
|
-
resolve(o)
|
|
118
|
-
})
|
|
119
|
-
})
|
|
120
|
-
}
|
|
121
|
-
|
|
122
34
|
/**
|
|
123
35
|
* Reasons to use it:
|
|
124
36
|
* - Sync
|
|
125
37
|
* - Need to print output while running
|
|
126
38
|
*
|
|
127
39
|
* Limitations:
|
|
128
|
-
* - Cannot return stdout/stderr (use exec or
|
|
40
|
+
* - Cannot return stdout/stderr (use exec, execAsync or spawnAsyncAndReturn for that)
|
|
129
41
|
*
|
|
130
42
|
* Defaults:
|
|
131
43
|
*
|
|
@@ -139,7 +51,6 @@ class Exec2 {
|
|
|
139
51
|
opt.logFinish ??= opt.log
|
|
140
52
|
const started = Date.now()
|
|
141
53
|
this.logStart(cmd, opt)
|
|
142
|
-
// console.log('') // 1-line padding before the output
|
|
143
54
|
|
|
144
55
|
const r = cp.spawnSync(cmd, opt.args, {
|
|
145
56
|
encoding: 'utf8',
|
|
@@ -153,7 +64,6 @@ class Exec2 {
|
|
|
153
64
|
},
|
|
154
65
|
})
|
|
155
66
|
|
|
156
|
-
// console.log('') // 1-line padding after the output
|
|
157
67
|
const isSuccessful = !r.error && !r.status
|
|
158
68
|
this.logFinish(cmd, opt, started, isSuccessful)
|
|
159
69
|
|
|
@@ -218,10 +128,133 @@ class Exec2 {
|
|
|
218
128
|
}
|
|
219
129
|
}
|
|
220
130
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Reasons to use it:
|
|
133
|
+
* - Async
|
|
134
|
+
* - Need to print output while running
|
|
135
|
+
*
|
|
136
|
+
* Limitations:
|
|
137
|
+
* - Cannot return stdout/stderr (use execAsync or spawnAsyncAndReturn for that)
|
|
138
|
+
*
|
|
139
|
+
* Defaults:
|
|
140
|
+
*
|
|
141
|
+
* shell: true
|
|
142
|
+
* log: true
|
|
143
|
+
*/
|
|
144
|
+
async spawnAsync(cmd: string, opt: SpawnOptions = {}): Promise<void> {
|
|
145
|
+
const { shell = true, cwd, env, passProcessEnv = true, forceColor = hasColors } = opt
|
|
146
|
+
opt.log ??= true // by default log should be true, as we are printing the output
|
|
147
|
+
opt.logStart ??= opt.log
|
|
148
|
+
opt.logFinish ??= opt.log
|
|
149
|
+
const started = Date.now()
|
|
150
|
+
this.logStart(cmd, opt)
|
|
151
|
+
|
|
152
|
+
await new Promise<void>((resolve, reject) => {
|
|
153
|
+
const p = cp.spawn(cmd, opt.args || [], {
|
|
154
|
+
shell,
|
|
155
|
+
cwd,
|
|
156
|
+
stdio: 'inherit',
|
|
157
|
+
env: {
|
|
158
|
+
...(passProcessEnv ? process.env : {}),
|
|
159
|
+
...(forceColor ? { FORCE_COLOR: '1' } : {}),
|
|
160
|
+
...env,
|
|
161
|
+
},
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
p.on('close', code => {
|
|
165
|
+
const isSuccessful = !code
|
|
166
|
+
this.logFinish(cmd, opt, started, isSuccessful)
|
|
167
|
+
if (code) {
|
|
168
|
+
return reject(new Error(`spawnAsync exited with code ${code}: ${cmd}`))
|
|
169
|
+
}
|
|
170
|
+
resolve()
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Advanced/async version of Spawn.
|
|
177
|
+
* Consider simpler `spawn` or `exec` first, which are also sync.
|
|
178
|
+
*
|
|
179
|
+
* spawnAsyncAndReturn features:
|
|
180
|
+
*
|
|
181
|
+
* 1. Async
|
|
182
|
+
* 2. Allows to collect the output AND print it while running.
|
|
183
|
+
* 3. Returns SpawnOutput with stdout, stderr and exitCode.
|
|
184
|
+
* 4. Allows to not throw on error, but just return SpawnOutput for further inspection.
|
|
185
|
+
*
|
|
186
|
+
* Defaults:
|
|
187
|
+
*
|
|
188
|
+
* shell: true
|
|
189
|
+
* printWhileRunning: true
|
|
190
|
+
* collectOutputWhileRunning: true
|
|
191
|
+
* throwOnNonZeroCode: true
|
|
192
|
+
* log: true
|
|
193
|
+
*/
|
|
194
|
+
async spawnAsyncAndReturn(cmd: string, opt: SpawnAsyncOptions = {}): Promise<SpawnOutput> {
|
|
195
|
+
const {
|
|
196
|
+
shell = true,
|
|
197
|
+
printWhileRunning = true,
|
|
198
|
+
collectOutputWhileRunning = true,
|
|
199
|
+
throwOnNonZeroCode = true,
|
|
200
|
+
cwd,
|
|
201
|
+
env,
|
|
202
|
+
passProcessEnv = true,
|
|
203
|
+
forceColor = hasColors,
|
|
204
|
+
} = opt
|
|
205
|
+
opt.log ??= printWhileRunning // by default log should be true, as we are printing the output
|
|
206
|
+
opt.logStart ??= opt.log
|
|
207
|
+
opt.logFinish ??= opt.log
|
|
208
|
+
const started = Date.now()
|
|
209
|
+
this.logStart(cmd, opt)
|
|
210
|
+
let stdout = ''
|
|
211
|
+
let stderr = ''
|
|
212
|
+
|
|
213
|
+
return await new Promise<SpawnOutput>((resolve, reject) => {
|
|
214
|
+
const p = cp.spawn(cmd, opt.args || [], {
|
|
215
|
+
shell,
|
|
216
|
+
cwd,
|
|
217
|
+
env: {
|
|
218
|
+
...(passProcessEnv ? process.env : {}),
|
|
219
|
+
...(forceColor ? { FORCE_COLOR: '1' } : {}),
|
|
220
|
+
...env,
|
|
221
|
+
},
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
p.stdout.on('data', data => {
|
|
225
|
+
if (collectOutputWhileRunning) {
|
|
226
|
+
stdout += data.toString()
|
|
227
|
+
// console.log('stdout:', data.toString())
|
|
228
|
+
}
|
|
229
|
+
if (printWhileRunning) {
|
|
230
|
+
process.stdout.write(data)
|
|
231
|
+
// console.log('stderr:', data.toString())
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
p.stderr.on('data', data => {
|
|
235
|
+
if (collectOutputWhileRunning) {
|
|
236
|
+
stderr += data.toString()
|
|
237
|
+
}
|
|
238
|
+
if (printWhileRunning) {
|
|
239
|
+
process.stderr.write(data)
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
p.on('close', code => {
|
|
244
|
+
const isSuccessful = !code
|
|
245
|
+
this.logFinish(cmd, opt, started, isSuccessful)
|
|
246
|
+
const exitCode = code || 0
|
|
247
|
+
const o: SpawnOutput = {
|
|
248
|
+
exitCode,
|
|
249
|
+
stdout: stdout.trim(),
|
|
250
|
+
stderr: stderr.trim(),
|
|
251
|
+
}
|
|
252
|
+
if (throwOnNonZeroCode && code) {
|
|
253
|
+
return reject(new SpawnError(`spawnAsyncAndReturn exited with code ${code}: ${cmd}`, o))
|
|
254
|
+
}
|
|
255
|
+
resolve(o)
|
|
256
|
+
})
|
|
257
|
+
})
|
|
225
258
|
}
|
|
226
259
|
|
|
227
260
|
private logStart(cmd: string, opt: SpawnOptions | ExecOptions): void {
|