@@ -41,16 +41,23 @@ import {
41
41
export interface Shell {
42
42
( pieces : TemplateStringsArray , ...args : any [ ] ) : ProcessPromise
43
43
( opts : Partial < Options > ) : Shell
44
+ sync : {
45
+ ( pieces : TemplateStringsArray , ...args : any [ ] ) : ProcessOutput
46
+ ( opts : Partial < Options > ) : Shell
47
+ }
44
48
}
45
49
46
50
const processCwd = Symbol ( 'processCwd' )
51
+ const syncExec = Symbol ( 'syncExec' )
47
52
48
53
export interface Options {
49
54
[ processCwd ] : string
55
+ [ syncExec ] : boolean
50
56
cwd ?: string
51
57
ac ?: AbortController
52
58
input ?: string | Buffer | Readable | ProcessOutput | ProcessPromise
53
59
verbose : boolean
60
+ sync : boolean
54
61
env : NodeJS . ProcessEnv
55
62
shell : string | boolean
56
63
nothrow : boolean
@@ -73,8 +80,10 @@ hook.enable()
73
80
74
81
export const defaults : Options = {
75
82
[ processCwd ] : process . cwd ( ) ,
83
+ [ syncExec ] : false ,
76
84
verbose : true ,
77
85
env : process . env ,
86
+ sync : false ,
78
87
shell : true ,
79
88
nothrow : false ,
80
89
quiet : false ,
@@ -127,18 +136,35 @@ export const $: Shell & Options = new Proxy<Shell & Options>(
127
136
args
128
137
) as string
129
138
130
- promise . _bind ( cmd , from , resolve ! , reject ! , getStore ( ) )
139
+ const snapshot = getStore ( )
140
+ const sync = snapshot [ syncExec ]
141
+ const callback = ( ) => promise . isHalted || promise . run ( )
142
+
143
+ promise . _bind (
144
+ cmd ,
145
+ from ,
146
+ resolve ! ,
147
+ ( v : ProcessOutput ) => {
148
+ reject ! ( v )
149
+ if ( sync ) throw v
150
+ } ,
151
+ snapshot
152
+ )
131
153
// Postpone run to allow promise configuration.
132
- setImmediate ( ( ) => promise . isHalted || promise . run ( ) )
133
- return promise
154
+ sync ? callback ( ) : setImmediate ( callback )
155
+
156
+ return sync ? promise . output : promise
134
157
} as Shell & Options ,
135
158
{
136
159
set ( _ , key , value ) {
137
160
const target = key in Function . prototype ? _ : getStore ( )
138
- Reflect . set ( target , key , value )
161
+ Reflect . set ( target , key === 'sync' ? syncExec : key , value )
162
+
139
163
return true
140
164
} ,
141
165
get ( _ , key ) {
166
+ if ( key === 'sync' ) return $ ( { sync : true } )
167
+
142
168
const target = key in Function . prototype ? _ : getStore ( )
143
169
return Reflect . get ( target , key )
144
170
} ,
@@ -169,7 +195,8 @@ export class ProcessPromise extends Promise<ProcessOutput> {
169
195
private _resolved = false
170
196
private _halted = false
171
197
private _piped = false
172
- private zurk : ReturnType < typeof exec > | null = null
198
+ private _zurk : ReturnType < typeof exec > | null = null
199
+ private _output : ProcessOutput | null = null
173
200
_prerun = noop
174
201
_postrun = noop
175
202
@@ -203,7 +230,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
203
230
verbose : self . isVerbose ( ) ,
204
231
} )
205
232
206
- this . zurk = exec ( {
233
+ this . _zurk = exec ( {
207
234
input,
208
235
cmd : $ . prefix + this . _command ,
209
236
cwd : $ . cwd ?? $ [ processCwd ] ,
@@ -212,7 +239,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
212
239
env : $ . env ,
213
240
spawn : $ . spawn ,
214
241
stdio : this . _stdio as any ,
215
- sync : false ,
242
+ sync : $ [ syncExec ] ,
216
243
detached : ! isWin ,
217
244
run : ( cb ) => cb ( ) ,
218
245
on : {
@@ -241,9 +268,16 @@ export class ProcessPromise extends Promise<ProcessOutput> {
241
268
const message = ProcessOutput . getErrorMessage ( error , self . _from )
242
269
// Should we enable this?
243
270
// (nothrow ? self._resolve : self._reject)(
244
- self . _reject (
245
- new ProcessOutput ( null , null , stdout , stderr , stdall , message )
271
+ const output = new ProcessOutput (
272
+ null ,
273
+ null ,
274
+ stdout ,
275
+ stderr ,
276
+ stdall ,
277
+ message
246
278
)
279
+ self . _output = output
280
+ self . _reject ( output )
247
281
} else {
248
282
const message = ProcessOutput . getExitMessage (
249
283
status ,
@@ -259,6 +293,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
259
293
stdall ,
260
294
message
261
295
)
296
+ self . _output = output
262
297
if ( status === 0 || ( self . _nothrow ?? $ . nothrow ) ) {
263
298
self . _resolve ( output )
264
299
} else {
@@ -275,7 +310,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
275
310
}
276
311
277
312
get child ( ) {
278
- return this . zurk ?. child
313
+ return this . _zurk ?. child
279
314
}
280
315
281
316
get stdin ( ) : Writable {
@@ -366,7 +401,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
366
401
if ( ! this . child )
367
402
throw new Error ( 'Trying to abort a process without creating one.' )
368
403
369
- this . zurk ?. ac . abort ( reason )
404
+ this . _zurk ?. ac . abort ( reason )
370
405
}
371
406
372
407
async kill ( signal = 'SIGTERM' ) : Promise < void > {
@@ -419,6 +454,10 @@ export class ProcessPromise extends Promise<ProcessOutput> {
419
454
get isHalted ( ) : boolean {
420
455
return this . _halted
421
456
}
457
+
458
+ get output ( ) {
459
+ return this . _output
460
+ }
422
461
}
423
462
424
463
export class ProcessOutput extends Error {
0 commit comments