@naturalcycles/nodejs-lib 13.34.3 → 13.34.5
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/util/exec2.d.ts +35 -22
- package/dist/util/exec2.js +122 -84
- package/package.json +1 -1
- package/src/util/exec2.ts +137 -98
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
|
*
|
|
@@ -23,55 +23,68 @@ import { AnyObject, AppError, NumberOfMilliseconds } from '@naturalcycles/js-lib
|
|
|
23
23
|
*/
|
|
24
24
|
declare class Exec2 {
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* spawnAsync features:
|
|
26
|
+
* Reasons to use it:
|
|
27
|
+
* - Sync
|
|
28
|
+
* - Need to print output while running
|
|
30
29
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* 3. Returns SpawnOutput with stdout, stderr and exitCode.
|
|
34
|
-
* 4. Allows to not throw on error, but just return SpawnOutput for further inspection.
|
|
30
|
+
* Limitations:
|
|
31
|
+
* - Cannot return stdout/stderr (use exec, execAsync or spawnAsyncAndReturn for that)
|
|
35
32
|
*
|
|
36
33
|
* Defaults:
|
|
37
34
|
*
|
|
38
35
|
* shell: true
|
|
39
|
-
* printWhileRunning: true
|
|
40
|
-
* collectOutputWhileRunning: true
|
|
41
|
-
* throwOnNonZeroCode: true
|
|
42
36
|
* log: true
|
|
43
37
|
*/
|
|
44
|
-
|
|
38
|
+
spawn(cmd: string, opt?: SpawnOptions): void;
|
|
45
39
|
/**
|
|
46
40
|
* Reasons to use it:
|
|
41
|
+
*
|
|
47
42
|
* - Sync
|
|
43
|
+
* - Need to return output
|
|
44
|
+
*
|
|
45
|
+
* Limitations:
|
|
46
|
+
* - Cannot print while running (use spawn or spawnAsync for that)
|
|
47
|
+
*
|
|
48
|
+
* Defaults:
|
|
49
|
+
*
|
|
50
|
+
* shell: true
|
|
51
|
+
* log: false
|
|
52
|
+
*/
|
|
53
|
+
exec(cmd: string, opt?: ExecOptions): string;
|
|
54
|
+
/**
|
|
55
|
+
* Reasons to use it:
|
|
56
|
+
* - Async
|
|
48
57
|
* - Need to print output while running
|
|
49
58
|
*
|
|
50
59
|
* Limitations:
|
|
51
|
-
* - Cannot return stdout/stderr (use
|
|
60
|
+
* - Cannot return stdout/stderr (use execAsync or spawnAsyncAndReturn for that)
|
|
52
61
|
*
|
|
53
62
|
* Defaults:
|
|
54
63
|
*
|
|
55
64
|
* shell: true
|
|
56
65
|
* log: true
|
|
57
66
|
*/
|
|
58
|
-
|
|
67
|
+
spawnAsync(cmd: string, opt?: SpawnOptions): Promise<void>;
|
|
59
68
|
/**
|
|
60
|
-
*
|
|
69
|
+
* Advanced/async version of Spawn.
|
|
70
|
+
* Consider simpler `spawn` or `exec` first, which are also sync.
|
|
61
71
|
*
|
|
62
|
-
*
|
|
63
|
-
* - Need to return output
|
|
72
|
+
* spawnAsyncAndReturn features:
|
|
64
73
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
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.
|
|
67
78
|
*
|
|
68
79
|
* Defaults:
|
|
69
80
|
*
|
|
70
81
|
* shell: true
|
|
82
|
+
* printWhileRunning: true
|
|
83
|
+
* collectOutputWhileRunning: true
|
|
84
|
+
* throwOnNonZeroCode: true
|
|
71
85
|
* log: true
|
|
72
86
|
*/
|
|
73
|
-
|
|
74
|
-
throwOnNonZeroExitCode(o: SpawnOutput): void;
|
|
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,85 +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
|
-
const started = Date.now();
|
|
54
|
-
this.logStart(cmd, opt);
|
|
55
|
-
let stdout = '';
|
|
56
|
-
let stderr = '';
|
|
57
|
-
// if (printWhileRunning) console.log('') // 1-line padding before the output
|
|
58
|
-
return await new Promise((resolve, reject) => {
|
|
59
|
-
const p = node_child_process_1.default.spawn(cmd, opt.args || [], {
|
|
60
|
-
shell,
|
|
61
|
-
cwd,
|
|
62
|
-
env: {
|
|
63
|
-
...(passProcessEnv ? process.env : {}),
|
|
64
|
-
...(forceColor ? { FORCE_COLOR: '1' } : {}),
|
|
65
|
-
...env,
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
p.stdout.on('data', data => {
|
|
69
|
-
if (collectOutputWhileRunning) {
|
|
70
|
-
stdout += data.toString();
|
|
71
|
-
// console.log('stdout:', data.toString())
|
|
72
|
-
}
|
|
73
|
-
if (printWhileRunning) {
|
|
74
|
-
process.stdout.write(data);
|
|
75
|
-
// console.log('stderr:', data.toString())
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
p.stderr.on('data', data => {
|
|
79
|
-
if (collectOutputWhileRunning) {
|
|
80
|
-
stderr += data.toString();
|
|
81
|
-
}
|
|
82
|
-
if (printWhileRunning) {
|
|
83
|
-
process.stderr.write(data);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
p.on('close', code => {
|
|
87
|
-
// if (printWhileRunning) console.log('') // 1-line padding after the output
|
|
88
|
-
const isSuccessful = !code;
|
|
89
|
-
this.logFinish(cmd, opt, started, isSuccessful);
|
|
90
|
-
const exitCode = code || 0;
|
|
91
|
-
const o = {
|
|
92
|
-
exitCode,
|
|
93
|
-
stdout: stdout.trim(),
|
|
94
|
-
stderr: stderr.trim(),
|
|
95
|
-
};
|
|
96
|
-
if (throwOnNonZeroCode && code) {
|
|
97
|
-
return reject(new SpawnError(`spawnAsync exited with code ${code}: ${cmd}`, o));
|
|
98
|
-
}
|
|
99
|
-
resolve(o);
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
31
|
/**
|
|
104
32
|
* Reasons to use it:
|
|
105
33
|
* - Sync
|
|
106
34
|
* - Need to print output while running
|
|
107
35
|
*
|
|
108
36
|
* Limitations:
|
|
109
|
-
* - Cannot return stdout/stderr (use exec or
|
|
37
|
+
* - Cannot return stdout/stderr (use exec, execAsync or spawnAsyncAndReturn for that)
|
|
110
38
|
*
|
|
111
39
|
* Defaults:
|
|
112
40
|
*
|
|
@@ -116,9 +44,10 @@ class Exec2 {
|
|
|
116
44
|
spawn(cmd, opt = {}) {
|
|
117
45
|
const { shell = true, cwd, env, passProcessEnv = true, forceColor = colors_1.hasColors } = opt;
|
|
118
46
|
opt.log ??= true; // by default log should be true, as we are printing the output
|
|
47
|
+
opt.logStart ??= opt.log;
|
|
48
|
+
opt.logFinish ??= opt.log;
|
|
119
49
|
const started = Date.now();
|
|
120
50
|
this.logStart(cmd, opt);
|
|
121
|
-
// console.log('') // 1-line padding before the output
|
|
122
51
|
const r = node_child_process_1.default.spawnSync(cmd, opt.args, {
|
|
123
52
|
encoding: 'utf8',
|
|
124
53
|
stdio: 'inherit',
|
|
@@ -130,7 +59,6 @@ class Exec2 {
|
|
|
130
59
|
...env,
|
|
131
60
|
},
|
|
132
61
|
});
|
|
133
|
-
// console.log('') // 1-line padding after the output
|
|
134
62
|
const isSuccessful = !r.error && !r.status;
|
|
135
63
|
this.logFinish(cmd, opt, started, isSuccessful);
|
|
136
64
|
if (r.error) {
|
|
@@ -152,12 +80,14 @@ class Exec2 {
|
|
|
152
80
|
* Defaults:
|
|
153
81
|
*
|
|
154
82
|
* shell: true
|
|
155
|
-
* log:
|
|
83
|
+
* log: false
|
|
156
84
|
*/
|
|
157
85
|
exec(cmd, opt = {}) {
|
|
86
|
+
const { cwd, env, passProcessEnv = true, timeout } = opt;
|
|
87
|
+
opt.logStart ??= opt.log ?? false;
|
|
88
|
+
opt.logFinish ??= opt.log ?? false;
|
|
158
89
|
const started = Date.now();
|
|
159
90
|
this.logStart(cmd, opt);
|
|
160
|
-
const { cwd, env, passProcessEnv = true, timeout } = opt;
|
|
161
91
|
try {
|
|
162
92
|
const s = node_child_process_1.default
|
|
163
93
|
.execSync(cmd, {
|
|
@@ -189,13 +119,121 @@ class Exec2 {
|
|
|
189
119
|
throw new Error(`exec exited with code ${err.status}: ${cmd}`);
|
|
190
120
|
}
|
|
191
121
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
+
});
|
|
196
234
|
}
|
|
197
235
|
logStart(cmd, opt) {
|
|
198
|
-
if (!opt.logStart
|
|
236
|
+
if (!opt.logStart)
|
|
199
237
|
return;
|
|
200
238
|
console.log([
|
|
201
239
|
(0, colors_1.dimGrey)(...Object.entries(opt.env || {}).map(([k, v]) => [k, v].join('='))),
|
|
@@ -206,7 +244,7 @@ class Exec2 {
|
|
|
206
244
|
.join(' '));
|
|
207
245
|
}
|
|
208
246
|
logFinish(cmd, opt, started, isSuccessful) {
|
|
209
|
-
if (isSuccessful && !opt.logFinish
|
|
247
|
+
if (isSuccessful && !opt.logFinish)
|
|
210
248
|
return;
|
|
211
249
|
console.log([
|
|
212
250
|
(0, colors_1.white)(opt.name || cmd),
|
package/package.json
CHANGED
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,99 +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
|
-
const started = Date.now()
|
|
66
|
-
this.logStart(cmd, opt)
|
|
67
|
-
let stdout = ''
|
|
68
|
-
let stderr = ''
|
|
69
|
-
|
|
70
|
-
// if (printWhileRunning) console.log('') // 1-line padding before the output
|
|
71
|
-
|
|
72
|
-
return await new Promise<SpawnOutput>((resolve, reject) => {
|
|
73
|
-
const p = cp.spawn(cmd, opt.args || [], {
|
|
74
|
-
shell,
|
|
75
|
-
cwd,
|
|
76
|
-
env: {
|
|
77
|
-
...(passProcessEnv ? process.env : {}),
|
|
78
|
-
...(forceColor ? { FORCE_COLOR: '1' } : {}),
|
|
79
|
-
...env,
|
|
80
|
-
},
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
p.stdout.on('data', data => {
|
|
84
|
-
if (collectOutputWhileRunning) {
|
|
85
|
-
stdout += data.toString()
|
|
86
|
-
// console.log('stdout:', data.toString())
|
|
87
|
-
}
|
|
88
|
-
if (printWhileRunning) {
|
|
89
|
-
process.stdout.write(data)
|
|
90
|
-
// console.log('stderr:', data.toString())
|
|
91
|
-
}
|
|
92
|
-
})
|
|
93
|
-
p.stderr.on('data', data => {
|
|
94
|
-
if (collectOutputWhileRunning) {
|
|
95
|
-
stderr += data.toString()
|
|
96
|
-
}
|
|
97
|
-
if (printWhileRunning) {
|
|
98
|
-
process.stderr.write(data)
|
|
99
|
-
}
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
p.on('close', code => {
|
|
103
|
-
// if (printWhileRunning) console.log('') // 1-line padding after the output
|
|
104
|
-
const isSuccessful = !code
|
|
105
|
-
this.logFinish(cmd, opt, started, isSuccessful)
|
|
106
|
-
const exitCode = code || 0
|
|
107
|
-
const o: SpawnOutput = {
|
|
108
|
-
exitCode,
|
|
109
|
-
stdout: stdout.trim(),
|
|
110
|
-
stderr: stderr.trim(),
|
|
111
|
-
}
|
|
112
|
-
if (throwOnNonZeroCode && code) {
|
|
113
|
-
return reject(new SpawnError(`spawnAsync exited with code ${code}: ${cmd}`, o))
|
|
114
|
-
}
|
|
115
|
-
resolve(o)
|
|
116
|
-
})
|
|
117
|
-
})
|
|
118
|
-
}
|
|
119
|
-
|
|
120
34
|
/**
|
|
121
35
|
* Reasons to use it:
|
|
122
36
|
* - Sync
|
|
123
37
|
* - Need to print output while running
|
|
124
38
|
*
|
|
125
39
|
* Limitations:
|
|
126
|
-
* - Cannot return stdout/stderr (use exec or
|
|
40
|
+
* - Cannot return stdout/stderr (use exec, execAsync or spawnAsyncAndReturn for that)
|
|
127
41
|
*
|
|
128
42
|
* Defaults:
|
|
129
43
|
*
|
|
@@ -133,9 +47,10 @@ class Exec2 {
|
|
|
133
47
|
spawn(cmd: string, opt: SpawnOptions = {}): void {
|
|
134
48
|
const { shell = true, cwd, env, passProcessEnv = true, forceColor = hasColors } = opt
|
|
135
49
|
opt.log ??= true // by default log should be true, as we are printing the output
|
|
50
|
+
opt.logStart ??= opt.log
|
|
51
|
+
opt.logFinish ??= opt.log
|
|
136
52
|
const started = Date.now()
|
|
137
53
|
this.logStart(cmd, opt)
|
|
138
|
-
// console.log('') // 1-line padding before the output
|
|
139
54
|
|
|
140
55
|
const r = cp.spawnSync(cmd, opt.args, {
|
|
141
56
|
encoding: 'utf8',
|
|
@@ -149,7 +64,6 @@ class Exec2 {
|
|
|
149
64
|
},
|
|
150
65
|
})
|
|
151
66
|
|
|
152
|
-
// console.log('') // 1-line padding after the output
|
|
153
67
|
const isSuccessful = !r.error && !r.status
|
|
154
68
|
this.logFinish(cmd, opt, started, isSuccessful)
|
|
155
69
|
|
|
@@ -173,12 +87,14 @@ class Exec2 {
|
|
|
173
87
|
* Defaults:
|
|
174
88
|
*
|
|
175
89
|
* shell: true
|
|
176
|
-
* log:
|
|
90
|
+
* log: false
|
|
177
91
|
*/
|
|
178
92
|
exec(cmd: string, opt: ExecOptions = {}): string {
|
|
93
|
+
const { cwd, env, passProcessEnv = true, timeout } = opt
|
|
94
|
+
opt.logStart ??= opt.log ?? false
|
|
95
|
+
opt.logFinish ??= opt.log ?? false
|
|
179
96
|
const started = Date.now()
|
|
180
97
|
this.logStart(cmd, opt)
|
|
181
|
-
const { cwd, env, passProcessEnv = true, timeout } = opt
|
|
182
98
|
|
|
183
99
|
try {
|
|
184
100
|
const s = cp
|
|
@@ -212,14 +128,137 @@ class Exec2 {
|
|
|
212
128
|
}
|
|
213
129
|
}
|
|
214
130
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
+
})
|
|
219
258
|
}
|
|
220
259
|
|
|
221
260
|
private logStart(cmd: string, opt: SpawnOptions | ExecOptions): void {
|
|
222
|
-
if (!opt.logStart
|
|
261
|
+
if (!opt.logStart) return
|
|
223
262
|
|
|
224
263
|
console.log(
|
|
225
264
|
[
|
|
@@ -238,7 +277,7 @@ class Exec2 {
|
|
|
238
277
|
started: UnixTimestampMillisNumber,
|
|
239
278
|
isSuccessful: boolean,
|
|
240
279
|
): void {
|
|
241
|
-
if (isSuccessful && !opt.logFinish
|
|
280
|
+
if (isSuccessful && !opt.logFinish) return
|
|
242
281
|
|
|
243
282
|
console.log(
|
|
244
283
|
[
|