printable-shell-command 5.1.1 → 5.3.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 +10 -8
- package/dist/lib/printable-shell-command/PrintableShellCommand.d.ts +13 -10
- package/dist/lib/printable-shell-command/index.js +58 -40
- package/dist/lib/printable-shell-command/index.js.map +2 -2
- package/dist/lib/printable-shell-command/spawn.d.ts +13 -11
- package/package.json +10 -7
- package/src/PrintableShellCommand.ts +86 -50
- package/src/spawn.ts +18 -11
package/README.md
CHANGED
|
@@ -21,10 +21,10 @@ Construct a command by providing a command string and a list of argument entries
|
|
|
21
21
|
import { PrintableShellCommand } from "printable-shell-command";
|
|
22
22
|
|
|
23
23
|
export const command = new PrintableShellCommand("ffmpeg", [
|
|
24
|
-
["-i", "./
|
|
24
|
+
["-i", "./example/My video.mov"],
|
|
25
25
|
["-filter:v", "setpts=2.0*PTS"],
|
|
26
26
|
["-filter:a", "atempo=0.5"],
|
|
27
|
-
"./
|
|
27
|
+
"./example/My video (slow-mo).mov",
|
|
28
28
|
]);
|
|
29
29
|
|
|
30
30
|
command.print();
|
|
@@ -34,10 +34,10 @@ This prints:
|
|
|
34
34
|
|
|
35
35
|
```shell
|
|
36
36
|
ffmpeg \
|
|
37
|
-
-i './
|
|
37
|
+
-i './example/My video.mov' \
|
|
38
38
|
-filter:v 'setpts=2.0*PTS' \
|
|
39
39
|
-filter:a atempo=0.5 \
|
|
40
|
-
'./
|
|
40
|
+
'./example/My video (slow-mo).mov'
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
### Spawn a process in `node`
|
|
@@ -47,17 +47,19 @@ import { spawn } from "node:child_process";
|
|
|
47
47
|
import { PrintableShellCommand } from "printable-shell-command";
|
|
48
48
|
|
|
49
49
|
const command = new PrintableShellCommand("ffmpeg", [
|
|
50
|
-
["-i", "./
|
|
50
|
+
["-i", "./example/My video.mov"],
|
|
51
51
|
["-filter:v", "setpts=2.0*PTS"],
|
|
52
52
|
["-filter:a", "atempo=0.5"],
|
|
53
|
-
"
|
|
53
|
+
["-y"], // Overwrite to avoid a prompt for the non-interactive calls
|
|
54
|
+
"./example/My video (slow-mo).mov",
|
|
54
55
|
]);
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
// Spawn with inherited stdio
|
|
58
|
+
await command.shellOut();
|
|
57
59
|
|
|
58
60
|
// Spawn directly
|
|
59
61
|
await command.spawn().success;
|
|
60
|
-
await command.
|
|
62
|
+
await command.spawnPassthrough().success;
|
|
61
63
|
command.spawnDetached();
|
|
62
64
|
|
|
63
65
|
// Or use `node` spawn (note the `...`).
|
|
@@ -3,7 +3,7 @@ import { Readable, Writable } from "node:stream";
|
|
|
3
3
|
import type { WriteStream } from "node:tty";
|
|
4
4
|
import { styleText } from "node:util";
|
|
5
5
|
import { Path } from "path-class";
|
|
6
|
-
import type { NodeWithCwd, spawnType,
|
|
6
|
+
import type { NodeWithCwd, spawnType, WithExitPromises } from "./spawn";
|
|
7
7
|
import { type TrailingNewlineOptions } from "./trimTrailingNewlines";
|
|
8
8
|
type StyleTextFormat = Parameters<typeof styleText>[0];
|
|
9
9
|
type SingleArgument = string | Path;
|
|
@@ -61,6 +61,9 @@ export type StdinSource = {
|
|
|
61
61
|
} | {
|
|
62
62
|
stream: Readable | ReadableStream;
|
|
63
63
|
};
|
|
64
|
+
interface AllowFailureOptions {
|
|
65
|
+
allowFailure?: boolean;
|
|
66
|
+
}
|
|
64
67
|
export declare class PrintableShellCommand {
|
|
65
68
|
#private;
|
|
66
69
|
private args;
|
|
@@ -113,7 +116,9 @@ export declare class PrintableShellCommand {
|
|
|
113
116
|
* then it acts "transparent" and allows user to interact with the subprocess
|
|
114
117
|
* in its stead.
|
|
115
118
|
*/
|
|
116
|
-
|
|
119
|
+
spawnPassthrough(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">>): ChildProcessByStdio<null, null, null> & WithExitPromises;
|
|
120
|
+
/** @deprecated Use `.spawnPassthrough(…)` instead. */
|
|
121
|
+
spawnTransparently: (...args: Parameters<PrintableShellCommand["spawnPassthrough"]>) => ReturnType<PrintableShellCommand["spawnPassthrough"]>;
|
|
117
122
|
/**
|
|
118
123
|
* A wrapper for {@link PrintableShellCommand.spawn | `.spawn(…)`} that:
|
|
119
124
|
*
|
|
@@ -126,10 +131,10 @@ export declare class PrintableShellCommand {
|
|
|
126
131
|
*
|
|
127
132
|
*/
|
|
128
133
|
spawnDetached(options?: NodeWithCwd<Omit<Omit<NodeSpawnOptions, "stdio">, "detached">>): void;
|
|
129
|
-
stdout(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">>): Response & {
|
|
134
|
+
stdout(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> & AllowFailureOptions): Response & {
|
|
130
135
|
text: (options?: TrailingNewlineOptions) => Promise<string>;
|
|
131
136
|
};
|
|
132
|
-
stderr(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">>): Response & {
|
|
137
|
+
stderr(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> & AllowFailureOptions): Response & {
|
|
133
138
|
text: (options?: TrailingNewlineOptions) => Promise<string>;
|
|
134
139
|
};
|
|
135
140
|
/**
|
|
@@ -139,9 +144,7 @@ export declare class PrintableShellCommand {
|
|
|
139
144
|
*
|
|
140
145
|
* This can make some simple invocations easier to read and/or fit on a single line.
|
|
141
146
|
*/
|
|
142
|
-
text(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
143
|
-
trimTrailingNewlines: "single-required" | "single-if-present" | "never";
|
|
144
|
-
}): Promise<string>;
|
|
147
|
+
text(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> & TrailingNewlineOptions & AllowFailureOptions): Promise<string>;
|
|
145
148
|
/**
|
|
146
149
|
* Convenience function for:
|
|
147
150
|
*
|
|
@@ -149,19 +152,19 @@ export declare class PrintableShellCommand {
|
|
|
149
152
|
*
|
|
150
153
|
* This can make some simple invocations easier to read and/or fit on a single line.
|
|
151
154
|
*/
|
|
152
|
-
json<T>(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">>): Promise<T>;
|
|
155
|
+
json<T>(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> & AllowFailureOptions): Promise<T>;
|
|
153
156
|
/**
|
|
154
157
|
* Parse `stdout` into a generator of string values using a NULL delimiter.
|
|
155
158
|
*
|
|
156
159
|
* A trailing NULL delimiter from `stdout` is required and removed.
|
|
157
160
|
*/
|
|
158
|
-
text0(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">>): AsyncGenerator<string>;
|
|
161
|
+
text0(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> & AllowFailureOptions): AsyncGenerator<string>;
|
|
159
162
|
/**
|
|
160
163
|
* Parse `stdout` into a generator of JSON values using a NULL delimiter.
|
|
161
164
|
*
|
|
162
165
|
* A trailing NULL delimiter from `stdout` is required and removed.
|
|
163
166
|
*/
|
|
164
|
-
json0(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">>): AsyncGenerator<any>;
|
|
167
|
+
json0(options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> & AllowFailureOptions): AsyncGenerator<any>;
|
|
165
168
|
/** Equivalent to:
|
|
166
169
|
*
|
|
167
170
|
* ```
|
|
@@ -296,61 +296,73 @@ var PrintableShellCommand = class {
|
|
|
296
296
|
...options,
|
|
297
297
|
cwd
|
|
298
298
|
});
|
|
299
|
-
let
|
|
299
|
+
let cachedExitCode;
|
|
300
|
+
const getCachedExitCode = () => {
|
|
301
|
+
return cachedExitCode ??= // TODO: Use `Promise.withResolvers()` ocne we default to ES2024.
|
|
302
|
+
new Promise((resolve, reject) => {
|
|
303
|
+
if (subprocess.exitCode !== null) {
|
|
304
|
+
resolve(subprocess.exitCode);
|
|
305
|
+
}
|
|
306
|
+
subprocess.addListener(
|
|
307
|
+
"exit",
|
|
308
|
+
/* we only use the first arg */
|
|
309
|
+
resolve
|
|
310
|
+
);
|
|
311
|
+
subprocess.addListener("error", (err) => {
|
|
312
|
+
reject(err);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
};
|
|
300
316
|
Object.defineProperty(subprocess, "success", {
|
|
301
317
|
get() {
|
|
302
|
-
return
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
if (subprocess.exitCode !== null) {
|
|
311
|
-
handle(subprocess.exitCode);
|
|
318
|
+
return (async () => {
|
|
319
|
+
const exitCode = await getCachedExitCode();
|
|
320
|
+
if (exitCode !== 0) {
|
|
321
|
+
throw new Error(
|
|
322
|
+
`Command failed with non-zero exit code: ${exitCode}`
|
|
323
|
+
);
|
|
312
324
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
});
|
|
325
|
+
})();
|
|
326
|
+
},
|
|
327
|
+
enumerable: false
|
|
328
|
+
});
|
|
329
|
+
Object.defineProperty(subprocess, "exited", {
|
|
330
|
+
get() {
|
|
331
|
+
return (async () => {
|
|
332
|
+
await getCachedExitCode();
|
|
333
|
+
})();
|
|
334
|
+
},
|
|
335
|
+
enumerable: false
|
|
336
|
+
});
|
|
337
|
+
Object.defineProperty(subprocess, "exitCodePromise", {
|
|
338
|
+
get() {
|
|
339
|
+
return getCachedExitCode();
|
|
322
340
|
},
|
|
323
341
|
enumerable: false
|
|
324
342
|
});
|
|
325
343
|
if (subprocess.stdout) {
|
|
326
344
|
const s = subprocess;
|
|
327
345
|
let cachedResponse;
|
|
328
|
-
s.stdout.response = () => (
|
|
329
|
-
|
|
330
|
-
cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
331
|
-
new Response(Readable.from(this.#generator(s.stdout, s.success)))
|
|
332
|
-
)
|
|
346
|
+
s.stdout.response = () => cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
347
|
+
new Response(Readable.from(this.#generator(s.stdout, s)))
|
|
333
348
|
);
|
|
334
349
|
s.stdout.text = wrapHandleTrailingNewlinesForResponder(s.stdout);
|
|
335
350
|
const thisCached = this;
|
|
336
351
|
s.stdout.text0 = async function* () {
|
|
337
|
-
yield* thisCached.#split0(thisCached.#generator(s.stdout, s
|
|
352
|
+
yield* thisCached.#split0(thisCached.#generator(s.stdout, s));
|
|
338
353
|
};
|
|
339
354
|
s.stdout.json = () => s.stdout.response().json();
|
|
340
355
|
}
|
|
341
356
|
if (subprocess.stderr) {
|
|
342
357
|
const s = subprocess;
|
|
343
358
|
let cachedResponse;
|
|
344
|
-
s.stderr.response = () => (
|
|
345
|
-
|
|
346
|
-
cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
347
|
-
new Response(Readable.from(this.#generator(s.stderr, s.success)))
|
|
348
|
-
)
|
|
359
|
+
s.stderr.response = () => cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
360
|
+
new Response(Readable.from(this.#generator(s.stderr, s)))
|
|
349
361
|
);
|
|
350
362
|
s.stderr.text = wrapHandleTrailingNewlinesForResponder(s.stderr);
|
|
351
363
|
const thisCached = this;
|
|
352
364
|
s.stderr.text0 = async function* () {
|
|
353
|
-
yield* thisCached.#split0(thisCached.#generator(s.stderr, s
|
|
365
|
+
yield* thisCached.#split0(thisCached.#generator(s.stderr, s));
|
|
354
366
|
};
|
|
355
367
|
s.stderr.json = () => s.stderr.response().json();
|
|
356
368
|
}
|
|
@@ -385,12 +397,14 @@ var PrintableShellCommand = class {
|
|
|
385
397
|
* then it acts "transparent" and allows user to interact with the subprocess
|
|
386
398
|
* in its stead.
|
|
387
399
|
*/
|
|
388
|
-
|
|
400
|
+
spawnPassthrough(options) {
|
|
389
401
|
if (options && "stdio" in options) {
|
|
390
402
|
throw new Error("Unexpected `stdio` field.");
|
|
391
403
|
}
|
|
392
404
|
return this.spawn({ ...options, stdio: "inherit" });
|
|
393
405
|
}
|
|
406
|
+
/** @deprecated Use `.spawnPassthrough(…)` instead. */
|
|
407
|
+
spawnTransparently = (...args) => this.spawnPassthrough(...args);
|
|
394
408
|
/**
|
|
395
409
|
* A wrapper for {@link PrintableShellCommand.spawn | `.spawn(…)`} that:
|
|
396
410
|
*
|
|
@@ -417,12 +431,16 @@ var PrintableShellCommand = class {
|
|
|
417
431
|
});
|
|
418
432
|
childProcess.unref();
|
|
419
433
|
}
|
|
420
|
-
#generator(readable,
|
|
434
|
+
#generator(readable, exiter, options) {
|
|
421
435
|
return (async function* () {
|
|
422
436
|
for await (const chunk of readable) {
|
|
423
437
|
yield chunk;
|
|
424
438
|
}
|
|
425
|
-
|
|
439
|
+
if (options?.allowFailure) {
|
|
440
|
+
await exiter.exited;
|
|
441
|
+
} else {
|
|
442
|
+
await exiter.success;
|
|
443
|
+
}
|
|
426
444
|
})();
|
|
427
445
|
}
|
|
428
446
|
#stdoutSpawnGenerator(options) {
|
|
@@ -433,7 +451,7 @@ var PrintableShellCommand = class {
|
|
|
433
451
|
...options,
|
|
434
452
|
stdio: ["ignore", "pipe", "inherit"]
|
|
435
453
|
});
|
|
436
|
-
return this.#generator(subprocess.stdout, subprocess
|
|
454
|
+
return this.#generator(subprocess.stdout, subprocess, options);
|
|
437
455
|
}
|
|
438
456
|
stdout(options) {
|
|
439
457
|
return wrapHandleTrailingNewlinesForResponse(
|
|
@@ -448,7 +466,7 @@ var PrintableShellCommand = class {
|
|
|
448
466
|
...options,
|
|
449
467
|
stdio: ["ignore", "inherit", "pipe"]
|
|
450
468
|
});
|
|
451
|
-
return this.#generator(subprocess.stderr, subprocess
|
|
469
|
+
return this.#generator(subprocess.stderr, subprocess, options);
|
|
452
470
|
}
|
|
453
471
|
stderr(options) {
|
|
454
472
|
return wrapHandleTrailingNewlinesForResponse(
|
|
@@ -479,9 +497,9 @@ var PrintableShellCommand = class {
|
|
|
479
497
|
async text(options) {
|
|
480
498
|
const {
|
|
481
499
|
trimTrailingNewlines: trimTrailingNewlinesOption,
|
|
482
|
-
...
|
|
500
|
+
...stdoutOptions
|
|
483
501
|
} = options ?? {};
|
|
484
|
-
return handleTrailingNewlines(this.stdout(
|
|
502
|
+
return handleTrailingNewlines(this.stdout(stdoutOptions).text(), {
|
|
485
503
|
trimTrailingNewlines: trimTrailingNewlinesOption
|
|
486
504
|
});
|
|
487
505
|
}
|
|
@@ -532,7 +550,7 @@ var PrintableShellCommand = class {
|
|
|
532
550
|
} else {
|
|
533
551
|
this.print(printOptions);
|
|
534
552
|
}
|
|
535
|
-
await this.
|
|
553
|
+
await this.spawnPassthrough(spawnOptions).success;
|
|
536
554
|
}
|
|
537
555
|
};
|
|
538
556
|
function escapeArg(arg, isMainCommand, options) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/PrintableShellCommand.ts", "../../../src/trimTrailingNewlines.ts"],
|
|
4
|
-
"sourcesContent": ["import assert from \"node:assert\";\nimport type {\n ChildProcessByStdio,\n ChildProcess as NodeChildProcess,\n SpawnOptions as NodeSpawnOptions,\n} from \"node:child_process\";\nimport { createReadStream } from \"node:fs\";\nimport { stderr } from \"node:process\";\nimport { Readable, Writable } from \"node:stream\";\nimport type { WriteStream } from \"node:tty\";\nimport { styleText } from \"node:util\";\nimport { Path, stringifyIfPath } from \"path-class\";\nimport type {\n NodeWithCwd,\n spawnType,\n WithStderrResponse,\n WithStdoutResponse,\n WithSuccess,\n} from \"./spawn\";\nimport {\n handleTrailingNewlines,\n type TrailingNewlineOptions,\n wrapHandleTrailingNewlinesForResponder,\n wrapHandleTrailingNewlinesForResponse,\n} from \"./trimTrailingNewlines\";\n\n// TODO: does this import work?\n/**\n * @import { stdout } from \"node:process\"\n */\n\nconst DEFAULT_MAIN_INDENTATION = \"\";\nconst DEFAULT_ARG_INDENTATION = \" \";\nconst DEFAULT_ARGUMENT_LINE_WRAPPING = \"by-entry\";\n\nconst INLINE_SEPARATOR = \" \";\nconst LINE_WRAP_LINE_END = \" \\\\\\n\";\n\ntype StyleTextFormat = Parameters<typeof styleText>[0];\n\nconst TTY_AUTO_STYLE: StyleTextFormat = [\"gray\", \"bold\"];\n\n// biome-ignore lint/suspicious/noExplicitAny: This is the correct type nere.\nfunction isString(s: any): s is string {\n return typeof s === \"string\";\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: This is the correct type here.\nfunction isValidArgsEntryArray(entries: any[]): entries is SingleArgument[] {\n for (const entry of entries) {\n if (isString(entry)) {\n continue;\n }\n if (entry instanceof Path) {\n continue;\n }\n return false;\n }\n return true;\n}\n\n// TODO: allow `.toString()`ables?\ntype SingleArgument = string | Path;\ntype ArgsEntry = SingleArgument | SingleArgument[];\ntype Args = ArgsEntry[];\n\nconst ARGUMENT_LINE_WRAPPING_VALUES = [\n \"by-entry\",\n \"nested-by-entry\",\n \"by-argument\",\n \"inline\",\n] as const;\ntype ArgumentLineWrapping = (typeof ARGUMENT_LINE_WRAPPING_VALUES)[number];\n\nexport interface PrintOptions {\n /** Defaults to \"\" */\n mainIndentation?: string;\n /** Defaults to \" \" */\n argIndentation?: string;\n /**\n * - `\"auto\"`: Quote only arguments that need it for safety. This tries to be\n * portable and safe across shells, but true safety and portability is hard\n * to guarantee.\n * - `\"extra-safe\"`: Quote all arguments, even ones that don't need it. This is\n * more likely to be safe under all circumstances.\n */\n quoting?: \"auto\" | \"extra-safe\";\n /** Line wrapping to use between arguments. Defaults to `\"by-entry\"`. */\n argumentLineWrapping?: ArgumentLineWrapping;\n /** Include the first arg (or first arg group) on the same line as the command, regardless of the `argumentLineWrapping` setting. */\n skipLineWrapBeforeFirstArg?: true | false;\n /**\n * Style text using `node`'s {@link styleText | `styleText(\u2026)`}.\n *\n * Example usage:\n *\n * ```\n * new PrintableShellCommand(\"echo\", [\"hi\"]).print({\n * style: [\"green\", \"underline\"],\n * });\n * */\n style?: StyleTextFormat;\n}\n\n/**\n * https://no-color.org/\n *\n * > Command-line software which adds ANSI color to its output by default should\n * > check for a NO_COLOR environment variable that, when present and not an\n * > empty string (regardless of its value), prevents the addition of ANSI\n * > color.\n *\n * I think it's a bit silly that `NO_COLOR=false` and `NO_COLOR=0` count as \"no\n * color please\", but \uD83E\uDD37\n *\n */\nfunction NO_COLOR(): boolean {\n const { env } = globalThis.process.getBuiltinModule(\"node:process\");\n // The empty string is falsy, so we can just use `!!`.\n // biome-ignore lint/complexity/useLiteralKeys: TODO: https://github.com/biomejs/biome/discussions/7572\n return !!env[\"NO_COLOR\"];\n}\n\nexport interface StreamPrintOptions extends PrintOptions {\n /**\n * Auto-style the text when:\n *\n * - the output stream is detected to be a TTY\n * - `styleTextFormat` is not specified.\n *\n * The current auto style is: `[\"gray\", \"bold\"]`\n */\n autoStyle?: \"tty\" | \"never\";\n // This would be a `WritableStream` (open web standard), but `WriteStream` allows us to query `.isTTY`.\n stream?: WriteStream | Writable;\n}\n\n// https://mywiki.wooledge.org/BashGuide/SpecialCharacters\nconst SPECIAL_SHELL_CHARACTERS = new Set([\n \" \",\n '\"',\n \"'\",\n \"`\",\n \"|\",\n \"$\",\n \"*\",\n \"?\",\n \">\",\n \"<\",\n \"(\",\n \")\",\n \"[\",\n \"]\",\n \"{\",\n \"}\",\n \"&\",\n \"\\\\\",\n \";\",\n \"#\",\n]);\n\n// https://mywiki.wooledge.org/BashGuide/SpecialCharacters\nconst SPECIAL_SHELL_CHARACTERS_FOR_MAIN_COMMAND =\n // biome-ignore lint/suspicious/noExplicitAny: Workaround to make this package easier to use in a project that otherwise only uses ES2022.)\n (SPECIAL_SHELL_CHARACTERS as unknown as any).union(new Set([\"=\"]));\n\n// TODO: Is there an idiomatic ways to check that all potential fields of\n// `StdinSource` satisfy `(typeof STDIN_SOURCE_KEYS)[number]`, without adding\n// extra indirection for type wrangling?\nconst STDIN_SOURCE_KEYS = [\"text\", \"json\", \"path\", \"stream\"] as const;\nexport type StdinSource =\n | { text: string }\n // biome-ignore lint/suspicious/noExplicitAny: `any` is the correct type for JSON data.\n | { json: any }\n | { path: string | Path }\n | { stream: Readable | ReadableStream };\n\nexport class PrintableShellCommand {\n #commandName: string | Path;\n constructor(\n commandName: string | Path,\n private args: Args = [],\n ) {\n if (!isString(commandName) && !(commandName instanceof Path)) {\n // biome-ignore lint/suspicious/noExplicitAny: We want to print this, no matter what it is.\n throw new Error(\"Command name is not a string:\", commandName as any);\n }\n this.#commandName = commandName;\n if (typeof args === \"undefined\") {\n return;\n }\n if (!Array.isArray(args)) {\n throw new Error(\"Command arguments are not an array\");\n }\n for (let i = 0; i < args.length; i++) {\n const argEntry = args[i];\n if (typeof argEntry === \"string\") {\n continue;\n }\n if (argEntry instanceof Path) {\n continue;\n }\n if (Array.isArray(argEntry) && isValidArgsEntryArray(argEntry)) {\n continue;\n }\n throw new Error(`Invalid arg entry at index: ${i}`);\n }\n }\n\n get commandName(): string {\n return stringifyIfPath(this.#commandName);\n }\n\n /**\n * For use with `node:child_process`\n *\n * Usage example:\n *\n * ```\n * import { PrintableShellCommand } from \"printable-shell-command\";\n * import { spawn } from \"node:child_process\";\n *\n * const command = new PrintableShellCommand( \u2026 );\n * const child_process = spawn(...command.toCommandWithFlatArgs()); // Note the `...`\n * ```\n *\n */\n public toCommandWithFlatArgs(): [string, string[]] {\n return [this.commandName, this.args.flat().map(stringifyIfPath)];\n }\n\n #mainIndentation(options: PrintOptions): string {\n return options?.mainIndentation ?? DEFAULT_MAIN_INDENTATION;\n }\n\n #argIndentation(options: PrintOptions): string {\n return (\n this.#mainIndentation(options) +\n (options?.argIndentation ?? DEFAULT_ARG_INDENTATION)\n );\n }\n\n #lineWrapSeparator(options: PrintOptions): string {\n return LINE_WRAP_LINE_END + this.#argIndentation(options);\n }\n\n #argPairSeparator(options: PrintOptions): string {\n switch (options?.argumentLineWrapping ?? DEFAULT_ARGUMENT_LINE_WRAPPING) {\n case \"by-entry\": {\n return INLINE_SEPARATOR;\n }\n case \"nested-by-entry\": {\n return this.#lineWrapSeparator(options) + this.#argIndentation(options);\n }\n case \"by-argument\": {\n return this.#lineWrapSeparator(options);\n }\n case \"inline\": {\n return INLINE_SEPARATOR;\n }\n default:\n throw new Error(\"Invalid argument line wrapping argument.\");\n }\n }\n\n #intraEntrySeparator(options: PrintOptions): string {\n switch (options?.argumentLineWrapping ?? DEFAULT_ARGUMENT_LINE_WRAPPING) {\n case \"by-entry\":\n case \"nested-by-entry\":\n case \"by-argument\": {\n return LINE_WRAP_LINE_END + this.#argIndentation(options);\n }\n case \"inline\": {\n return INLINE_SEPARATOR;\n }\n default:\n throw new Error(\"Invalid argument line wrapping argument.\");\n }\n }\n\n #separatorAfterCommand(\n options: PrintOptions,\n numFollowingEntries: number,\n ): string {\n if (numFollowingEntries === 0) {\n return \"\";\n }\n if (options.skipLineWrapBeforeFirstArg ?? false) {\n return INLINE_SEPARATOR;\n }\n return this.#intraEntrySeparator(options);\n }\n\n public getPrintableCommand(options?: PrintOptions): string {\n // TODO: Why in the world does TypeScript not give the `options` arg the type of `PrintOptions | undefined`???\n options ??= {};\n const serializedEntries: string[] = [];\n\n for (let i = 0; i < this.args.length; i++) {\n const argsEntry = stringifyIfPath(this.args[i]);\n\n if (isString(argsEntry)) {\n serializedEntries.push(escapeArg(argsEntry, false, options));\n } else {\n serializedEntries.push(\n argsEntry\n .map((part) => escapeArg(stringifyIfPath(part), false, options))\n .join(this.#argPairSeparator(options)),\n );\n }\n }\n\n let text =\n this.#mainIndentation(options) +\n escapeArg(this.commandName, true, options) +\n this.#separatorAfterCommand(options, serializedEntries.length) +\n serializedEntries.join(this.#intraEntrySeparator(options));\n if (options?.style) {\n text = styleText(options.style, text);\n }\n return text;\n }\n\n /**\n * Print the shell command to {@link stderr} (default) or a specified stream.\n *\n * By default, this will be auto-styled (as bold gray) when `.isTTY` is true\n * for the stream. `.isTTY` is populated for the {@link stderr} and\n * {@link stdout} objects. Pass `\"autoStyle\": \"never\"` or an explicit\n * `style` to disable this.\n *\n */\n public print(options?: StreamPrintOptions): PrintableShellCommand {\n const stream = options?.stream ?? stderr;\n // Note: we only need to modify top-level fields, so `structuredClone(\u2026)`\n // would be overkill and can only cause performance issues.\n const optionsCopy = {\n ...options,\n style: this.#styleFromOptions(stream, options),\n };\n const writable =\n stream instanceof Writable ? stream : Writable.fromWeb(stream);\n writable.write(this.getPrintableCommand(optionsCopy));\n writable.write(\"\\n\");\n return this;\n }\n\n #styleFromOptions(\n stream: WriteStream | Writable,\n options?: StreamPrintOptions,\n ): StyleTextFormat | undefined {\n if (options?.autoStyle === \"never\") {\n return;\n }\n if (!(stream as { isTTY?: boolean }).isTTY) {\n return;\n }\n if (NO_COLOR()) {\n return;\n }\n return TTY_AUTO_STYLE;\n }\n\n #stdinSource: StdinSource | undefined;\n /**\n * Send data to `stdin` of the subprocess.\n *\n * Note that this will overwrite:\n *\n * - Any previous value set using {@link PrintableShellCommand.stdin | `.stdin(\u2026)`}.\n * - Any value set for `stdin` using the `\"stdio\"` field of {@link PrintableShellCommand.spawn | `.spawn(\u2026)`}.\n */\n stdin(source: StdinSource): PrintableShellCommand {\n const [key, ...moreKeys] = Object.keys(source);\n assert.equal(moreKeys.length, 0);\n // TODO: validate values?\n assert((STDIN_SOURCE_KEYS as unknown as string[]).includes(key));\n\n this.#stdinSource = source;\n return this;\n }\n\n /**\n * The returned child process includes a `.success` `Promise` field, per https://github.com/oven-sh/bun/issues/8313\n */\n public spawn: typeof spawnType = ((\n options?: Parameters<typeof spawnType>[0],\n ) => {\n const { spawn } = process.getBuiltinModule(\"node:child_process\");\n const cwd = stringifyIfPath(options?.cwd);\n options = { ...options };\n if (this.#stdinSource) {\n options ??= {};\n if (typeof options.stdio === \"undefined\") {\n options.stdio = \"pipe\";\n }\n if (typeof options.stdio === \"string\") {\n options.stdio = new Array(3).fill(options.stdio);\n }\n options.stdio = [\"pipe\", ...options.stdio.slice(1)];\n }\n // biome-ignore lint/suspicious/noTsIgnore: We don't want linting to depend on *broken* type checking.\n // @ts-ignore: The TypeScript checker has trouble reconciling the optional (i.e. potentially `undefined`) `options` with the third argument.\n const subprocess = spawn(...this.toCommandWithFlatArgs(), {\n ...(options as object),\n cwd,\n }) as NodeChildProcess & {\n success: Promise<void>;\n };\n let cachedSuccess: Promise<void> | undefined;\n // TODO: define properties on prototypes instead.\n Object.defineProperty(subprocess, \"success\", {\n get() {\n // biome-ignore lint/suspicious/noAssignInExpressions: TODO: https://github.com/biomejs/biome/discussions/7592\n return (cachedSuccess ??= new Promise<void>((resolve, reject) => {\n function handle(exitCode: number) {\n if (exitCode === 0) {\n resolve();\n } else {\n reject(`Command failed with non-zero exit code: ${exitCode}`);\n }\n }\n if (subprocess.exitCode !== null) {\n handle(subprocess.exitCode);\n }\n this.addListener(\n \"exit\",\n /* we only use the first arg */\n handle,\n );\n // biome-ignore lint/suspicious/noExplicitAny: We don't have the type available.\n this.addListener(\"error\", (err: any) => {\n reject(err);\n });\n }));\n },\n enumerable: false,\n });\n if (subprocess.stdout) {\n // TODO: dedupe\n const s = subprocess as unknown as Readable &\n WithStdoutResponse &\n WithSuccess;\n let cachedResponse: Response | undefined;\n s.stdout.response = () =>\n // biome-ignore lint/suspicious/noAssignInExpressions: TODO: https://github.com/biomejs/biome/discussions/7592\n (cachedResponse ??= wrapHandleTrailingNewlinesForResponse(\n new Response(Readable.from(this.#generator(s.stdout, s.success))),\n ));\n s.stdout.text = wrapHandleTrailingNewlinesForResponder(s.stdout);\n const thisCached = this; // TODO: make this type-check using `.bind(\u2026)`\n s.stdout.text0 = async function* () {\n yield* thisCached.#split0(thisCached.#generator(s.stdout, s.success));\n };\n s.stdout.json = <T>() => s.stdout.response().json() as Promise<T>;\n }\n if (subprocess.stderr) {\n // TODO: dedupe\n const s = subprocess as unknown as Readable &\n WithStderrResponse &\n WithSuccess;\n let cachedResponse: Response | undefined;\n s.stderr.response = () =>\n // biome-ignore lint/suspicious/noAssignInExpressions: TODO: https://github.com/biomejs/biome/discussions/7592\n (cachedResponse ??= wrapHandleTrailingNewlinesForResponse(\n new Response(Readable.from(this.#generator(s.stderr, s.success))),\n ));\n s.stderr.text = wrapHandleTrailingNewlinesForResponder(s.stderr);\n const thisCached = this; // TODO: make this type-check using `.bind(\u2026)`\n s.stderr.text0 = async function* () {\n yield* thisCached.#split0(thisCached.#generator(s.stderr, s.success));\n };\n s.stderr.json = <T>() => s.stderr.response().json() as Promise<T>;\n }\n if (this.#stdinSource) {\n const { stdin } = subprocess;\n assert(stdin);\n if (\"text\" in this.#stdinSource) {\n stdin.write(this.#stdinSource.text);\n stdin.end();\n } else if (\"json\" in this.#stdinSource) {\n stdin.write(JSON.stringify(this.#stdinSource.json));\n stdin.end();\n } else if (\"path\" in this.#stdinSource) {\n createReadStream(stringifyIfPath(this.#stdinSource.path)).pipe(stdin);\n } else if (\"stream\" in this.#stdinSource) {\n const stream = (() => {\n const { stream } = this.#stdinSource;\n return stream instanceof Readable ? stream : Readable.fromWeb(stream);\n })();\n stream.pipe(stdin);\n } else {\n throw new Error(\"Invalid `.stdin(\u2026)` source?\");\n }\n }\n return subprocess;\n // biome-ignore lint/suspicious/noExplicitAny: Type wrangling\n }) as any;\n\n /** A wrapper for `.spawn(\u2026)` that sets stdio to `\"inherit\"` (common for\n * invoking commands from scripts whose output and interaction should be\n * surfaced to the user).\n *\n * If there is no other interaction with the shell from the calling process,\n * then it acts \"transparent\" and allows user to interact with the subprocess\n * in its stead.\n */\n public spawnTransparently(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): ChildProcessByStdio<null, null, null> & WithSuccess {\n if (options && \"stdio\" in options) {\n throw new Error(\"Unexpected `stdio` field.\");\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Type wrangling.\n return this.spawn({ ...options, stdio: \"inherit\" }) as any;\n }\n\n /**\n * A wrapper for {@link PrintableShellCommand.spawn | `.spawn(\u2026)`} that:\n *\n * - sets `detached` to `true`,\n * - sets stdio to `\"inherit\"`,\n * - calls `.unref()`, and\n * - does not wait for the process to exit.\n *\n * This is similar to starting a command in the background and disowning it (in a shell).\n *\n */\n public spawnDetached(\n options?: NodeWithCwd<Omit<Omit<NodeSpawnOptions, \"stdio\">, \"detached\">>,\n ): void {\n if (options) {\n for (const field of [\"stdio\", \"detached\"]) {\n if (field in options) {\n throw new Error(`Unexpected \\`${field}\\` field.`);\n }\n }\n }\n const childProcess = this.spawn({\n stdio: \"ignore\",\n ...options,\n detached: true,\n });\n childProcess.unref();\n }\n\n #generator(\n readable: Readable,\n successPromise: Promise<void>,\n ): AsyncGenerator<string> {\n // TODO: we'd make this a `ReadableStream`, but `ReadableStream.from(\u2026)` is\n // not implemented in `bun`: https://github.com/oven-sh/bun/issues/3700\n return (async function* () {\n for await (const chunk of readable) {\n yield chunk;\n }\n await successPromise;\n })();\n }\n\n #stdoutSpawnGenerator(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): AsyncGenerator<string> {\n if (options && \"stdio\" in options) {\n throw new Error(\"Unexpected `stdio` field.\");\n }\n const subprocess = this.spawn({\n ...options,\n stdio: [\"ignore\", \"pipe\", \"inherit\"],\n });\n return this.#generator(subprocess.stdout, subprocess.success);\n }\n\n public stdout(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): Response & {\n text: (options?: TrailingNewlineOptions) => Promise<string>;\n } {\n // TODO: Use `ReadableStream.from(\u2026)` once `bun` implements it: https://github.com/oven-sh/bun/pull/21269\n return wrapHandleTrailingNewlinesForResponse(\n new Response(Readable.from(this.#stdoutSpawnGenerator(options))),\n );\n }\n\n #stderrSpawnGenerator(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): AsyncGenerator<string> {\n if (options && \"stdio\" in options) {\n throw new Error(\"Unexpected `stdio` field.\");\n }\n const subprocess = this.spawn({\n ...options,\n stdio: [\"ignore\", \"inherit\", \"pipe\"],\n });\n return this.#generator(subprocess.stderr, subprocess.success);\n }\n\n public stderr(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): Response & {\n text: (options?: TrailingNewlineOptions) => Promise<string>;\n } {\n // TODO: Use `ReadableStream.from(\u2026)` once `bun` implements it: https://github.com/oven-sh/bun/pull/21269\n return wrapHandleTrailingNewlinesForResponse(\n new Response(Readable.from(this.#stderrSpawnGenerator(options))),\n );\n }\n\n async *#split0(generator: AsyncGenerator<string>): AsyncGenerator<string> {\n let pending = \"\";\n for await (const chunk of generator) {\n pending += chunk;\n const newChunks = pending.split(\"\\x00\");\n pending = newChunks.splice(-1)[0];\n yield* newChunks;\n }\n if (pending !== \"\") {\n throw new Error(\n \"Missing a trailing NUL character at the end of a NUL-delimited stream.\",\n );\n }\n }\n\n /**\n * Convenience function for:\n *\n * .stdout(options).text()\n *\n * This can make some simple invocations easier to read and/or fit on a single line.\n */\n public async text(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> & {\n trimTrailingNewlines: \"single-required\" | \"single-if-present\" | \"never\";\n },\n ): Promise<string> {\n const {\n trimTrailingNewlines: trimTrailingNewlinesOption,\n ...spawnOptions\n } = options ?? {};\n return handleTrailingNewlines(this.stdout(spawnOptions).text(), {\n trimTrailingNewlines: trimTrailingNewlinesOption,\n });\n }\n\n /**\n * Convenience function for:\n *\n * .stdout(options).json()\n *\n * This can make some simple invocations easier to read and/or fit on a single line.\n */\n public json<T>(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): Promise<T> {\n return this.stdout(options).json() as Promise<T>;\n }\n\n /**\n * Parse `stdout` into a generator of string values using a NULL delimiter.\n *\n * A trailing NULL delimiter from `stdout` is required and removed.\n */\n public async *text0(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): AsyncGenerator<string> {\n yield* this.#split0(this.#stdoutSpawnGenerator(options));\n }\n\n /**\n * Parse `stdout` into a generator of JSON values using a NULL delimiter.\n *\n * A trailing NULL delimiter from `stdout` is required and removed.\n */\n public async *json0(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): // biome-ignore lint/suspicious/noExplicitAny: `any` is the correct type for JSON\n AsyncGenerator<any> {\n for await (const part of this.#split0(\n this.#stdoutSpawnGenerator(options),\n )) {\n yield JSON.parse(part);\n }\n }\n\n /** Equivalent to:\n *\n * ```\n * await this.print(\u2026).spawnTransparently(\u2026).success;\n * ```\n */\n public async shellOut(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> & {\n print?: StreamPrintOptions | ArgumentLineWrapping | boolean;\n },\n ): Promise<void> {\n const { print: printOptions, ...spawnOptions } = options ?? {};\n\n if (typeof printOptions === \"string\") {\n assert(ARGUMENT_LINE_WRAPPING_VALUES.includes(printOptions));\n this.print({ argumentLineWrapping: printOptions });\n } else if (printOptions === true) {\n this.print();\n } else if (printOptions === false) {\n // no-op\n } else {\n this.print(printOptions);\n }\n await this.spawnTransparently(spawnOptions).success;\n }\n}\n\nexport function escapeArg(\n arg: string,\n isMainCommand: boolean,\n options: PrintOptions,\n): string {\n const argCharacters = new Set(arg);\n const specialShellCharacters = isMainCommand\n ? SPECIAL_SHELL_CHARACTERS_FOR_MAIN_COMMAND\n : SPECIAL_SHELL_CHARACTERS;\n if (\n options?.quoting === \"extra-safe\" ||\n // biome-ignore lint/suspicious/noExplicitAny: Workaround to make this package easier to use in a project that otherwise only uses ES2022.)\n (argCharacters as unknown as any).intersection(specialShellCharacters)\n .size > 0\n ) {\n // Use single quote to reduce the need to escape (and therefore reduce the chance for bugs/security issues).\n const escaped = arg.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll(\"'\", \"\\\\'\");\n return `'${escaped}'`;\n }\n return arg;\n}\n", "const DEFAULT_TRIM_TRAILING_NEWLINE_BEHAVIOUR = \"never\";\nexport interface TrailingNewlineOptions {\n trimTrailingNewlines?: \"single-required\" | \"single-if-present\" | \"never\";\n}\n\n// TODO: Handle carriage return?\nexport async function handleTrailingNewlines(\n text: Promise<string>,\n options?: TrailingNewlineOptions,\n): Promise<string> {\n const awaitedText = await text;\n switch (\n options?.trimTrailingNewlines ??\n DEFAULT_TRIM_TRAILING_NEWLINE_BEHAVIOUR\n ) {\n case \"single-required\": {\n if (!awaitedText.endsWith(\"\\n\")) {\n throw new Error(\"Trailing newline required, but not present.\");\n }\n return awaitedText.slice(0, -1);\n }\n case \"single-if-present\": {\n if (awaitedText.endsWith(\"\\n\")) {\n return awaitedText.slice(0, -1);\n } else {\n return awaitedText;\n }\n }\n case \"never\": {\n return awaitedText;\n }\n default:\n throw new Error(\"Invalid value for `trimTrailingNewlines`.\");\n }\n}\n\nfunction wrapHandleTrailingNewlines(\n fn: () => Promise<string>,\n): (options?: TrailingNewlineOptions) => Promise<string> {\n return (options?: TrailingNewlineOptions) =>\n handleTrailingNewlines(fn(), options);\n}\n\nexport function wrapHandleTrailingNewlinesForResponder(v: {\n response(): {\n text: () => Promise<string>;\n };\n}): (options?: TrailingNewlineOptions) => Promise<string> {\n const response = v.response();\n const originalTextFn = response.text.bind(response);\n return wrapHandleTrailingNewlines(originalTextFn);\n}\n\nexport function wrapHandleTrailingNewlinesForResponse(\n response: Response,\n): Response & { text: (options?: TrailingNewlineOptions) => Promise<string> } {\n const textFn = wrapHandleTrailingNewlinesForResponder({\n response: () => response,\n });\n Object.defineProperty(response, \"text\", {\n get: () => {\n return textFn;\n },\n });\n return response;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import assert from \"node:assert\";\nimport type {\n ChildProcessByStdio,\n ChildProcess as NodeChildProcess,\n SpawnOptions as NodeSpawnOptions,\n} from \"node:child_process\";\nimport { createReadStream } from \"node:fs\";\nimport { stderr } from \"node:process\";\nimport { Readable, Writable } from \"node:stream\";\nimport type { WriteStream } from \"node:tty\";\nimport { styleText } from \"node:util\";\nimport { Path, stringifyIfPath } from \"path-class\";\nimport type {\n NodeWithCwd,\n spawnType,\n WithExitPromises,\n WithStderrResponse,\n WithStdoutResponse,\n} from \"./spawn\";\nimport {\n handleTrailingNewlines,\n type TrailingNewlineOptions,\n wrapHandleTrailingNewlinesForResponder,\n wrapHandleTrailingNewlinesForResponse,\n} from \"./trimTrailingNewlines\";\n\nconst DEFAULT_MAIN_INDENTATION = \"\";\nconst DEFAULT_ARG_INDENTATION = \" \";\nconst DEFAULT_ARGUMENT_LINE_WRAPPING = \"by-entry\";\n\nconst INLINE_SEPARATOR = \" \";\nconst LINE_WRAP_LINE_END = \" \\\\\\n\";\n\ntype StyleTextFormat = Parameters<typeof styleText>[0];\n\nconst TTY_AUTO_STYLE: StyleTextFormat = [\"gray\", \"bold\"];\n\n// biome-ignore lint/suspicious/noExplicitAny: This is the correct type nere.\nfunction isString(s: any): s is string {\n return typeof s === \"string\";\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: This is the correct type here.\nfunction isValidArgsEntryArray(entries: any[]): entries is SingleArgument[] {\n for (const entry of entries) {\n if (isString(entry)) {\n continue;\n }\n if (entry instanceof Path) {\n continue;\n }\n return false;\n }\n return true;\n}\n\n// TODO: allow `.toString()`ables?\ntype SingleArgument = string | Path;\ntype ArgsEntry = SingleArgument | SingleArgument[];\ntype Args = ArgsEntry[];\n\nconst ARGUMENT_LINE_WRAPPING_VALUES = [\n \"by-entry\",\n \"nested-by-entry\",\n \"by-argument\",\n \"inline\",\n] as const;\ntype ArgumentLineWrapping = (typeof ARGUMENT_LINE_WRAPPING_VALUES)[number];\n\nexport interface PrintOptions {\n /** Defaults to \"\" */\n mainIndentation?: string;\n /** Defaults to \" \" */\n argIndentation?: string;\n /**\n * - `\"auto\"`: Quote only arguments that need it for safety. This tries to be\n * portable and safe across shells, but true safety and portability is hard\n * to guarantee.\n * - `\"extra-safe\"`: Quote all arguments, even ones that don't need it. This is\n * more likely to be safe under all circumstances.\n */\n quoting?: \"auto\" | \"extra-safe\";\n /** Line wrapping to use between arguments. Defaults to `\"by-entry\"`. */\n argumentLineWrapping?: ArgumentLineWrapping;\n /** Include the first arg (or first arg group) on the same line as the command, regardless of the `argumentLineWrapping` setting. */\n skipLineWrapBeforeFirstArg?: true | false;\n /**\n * Style text using `node`'s {@link styleText | `styleText(\u2026)`}.\n *\n * Example usage:\n *\n * ```\n * new PrintableShellCommand(\"echo\", [\"hi\"]).print({\n * style: [\"green\", \"underline\"],\n * });\n * */\n style?: StyleTextFormat;\n}\n\n/**\n * https://no-color.org/\n *\n * > Command-line software which adds ANSI color to its output by default should\n * > check for a NO_COLOR environment variable that, when present and not an\n * > empty string (regardless of its value), prevents the addition of ANSI\n * > color.\n *\n * I think it's a bit silly that `NO_COLOR=false` and `NO_COLOR=0` count as \"no\n * color please\", but \uD83E\uDD37\n *\n */\nfunction NO_COLOR(): boolean {\n const { env } = globalThis.process.getBuiltinModule(\"node:process\");\n // The empty string is falsy, so we can just use `!!`.\n // biome-ignore lint/complexity/useLiteralKeys: TODO: https://github.com/biomejs/biome/discussions/7572\n return !!env[\"NO_COLOR\"];\n}\n\nexport interface StreamPrintOptions extends PrintOptions {\n /**\n * Auto-style the text when:\n *\n * - the output stream is detected to be a TTY\n * - `styleTextFormat` is not specified.\n *\n * The current auto style is: `[\"gray\", \"bold\"]`\n */\n autoStyle?: \"tty\" | \"never\";\n // This would be a `WritableStream` (open web standard), but `WriteStream` allows us to query `.isTTY`.\n stream?: WriteStream | Writable;\n}\n\n// https://mywiki.wooledge.org/BashGuide/SpecialCharacters\nconst SPECIAL_SHELL_CHARACTERS = new Set([\n \" \",\n '\"',\n \"'\",\n \"`\",\n \"|\",\n \"$\",\n \"*\",\n \"?\",\n \">\",\n \"<\",\n \"(\",\n \")\",\n \"[\",\n \"]\",\n \"{\",\n \"}\",\n \"&\",\n \"\\\\\",\n \";\",\n \"#\",\n]);\n\n// https://mywiki.wooledge.org/BashGuide/SpecialCharacters\nconst SPECIAL_SHELL_CHARACTERS_FOR_MAIN_COMMAND =\n // biome-ignore lint/suspicious/noExplicitAny: Workaround to make this package easier to use in a project that otherwise only uses ES2022.)\n (SPECIAL_SHELL_CHARACTERS as unknown as any).union(new Set([\"=\"]));\n\n// TODO: Is there an idiomatic ways to check that all potential fields of\n// `StdinSource` satisfy `(typeof STDIN_SOURCE_KEYS)[number]`, without adding\n// extra indirection for type wrangling?\nconst STDIN_SOURCE_KEYS = [\"text\", \"json\", \"path\", \"stream\"] as const;\nexport type StdinSource =\n | { text: string }\n // biome-ignore lint/suspicious/noExplicitAny: `any` is the correct type for JSON data.\n | { json: any }\n | { path: string | Path }\n | { stream: Readable | ReadableStream };\n\ninterface AllowFailureOptions {\n allowFailure?: boolean;\n}\n\nexport class PrintableShellCommand {\n #commandName: string | Path;\n constructor(\n commandName: string | Path,\n private args: Args = [],\n ) {\n if (!isString(commandName) && !(commandName instanceof Path)) {\n // biome-ignore lint/suspicious/noExplicitAny: We want to print this, no matter what it is.\n throw new Error(\"Command name is not a string:\", commandName as any);\n }\n this.#commandName = commandName;\n if (typeof args === \"undefined\") {\n return;\n }\n if (!Array.isArray(args)) {\n throw new Error(\"Command arguments are not an array\");\n }\n for (let i = 0; i < args.length; i++) {\n const argEntry = args[i];\n if (typeof argEntry === \"string\") {\n continue;\n }\n if (argEntry instanceof Path) {\n continue;\n }\n if (Array.isArray(argEntry) && isValidArgsEntryArray(argEntry)) {\n continue;\n }\n throw new Error(`Invalid arg entry at index: ${i}`);\n }\n }\n\n get commandName(): string {\n return stringifyIfPath(this.#commandName);\n }\n\n /**\n * For use with `node:child_process`\n *\n * Usage example:\n *\n * ```\n * import { PrintableShellCommand } from \"printable-shell-command\";\n * import { spawn } from \"node:child_process\";\n *\n * const command = new PrintableShellCommand( \u2026 );\n * const child_process = spawn(...command.toCommandWithFlatArgs()); // Note the `...`\n * ```\n *\n */\n public toCommandWithFlatArgs(): [string, string[]] {\n return [this.commandName, this.args.flat().map(stringifyIfPath)];\n }\n\n #mainIndentation(options: PrintOptions): string {\n return options?.mainIndentation ?? DEFAULT_MAIN_INDENTATION;\n }\n\n #argIndentation(options: PrintOptions): string {\n return (\n this.#mainIndentation(options) +\n (options?.argIndentation ?? DEFAULT_ARG_INDENTATION)\n );\n }\n\n #lineWrapSeparator(options: PrintOptions): string {\n return LINE_WRAP_LINE_END + this.#argIndentation(options);\n }\n\n #argPairSeparator(options: PrintOptions): string {\n switch (options?.argumentLineWrapping ?? DEFAULT_ARGUMENT_LINE_WRAPPING) {\n case \"by-entry\": {\n return INLINE_SEPARATOR;\n }\n case \"nested-by-entry\": {\n return this.#lineWrapSeparator(options) + this.#argIndentation(options);\n }\n case \"by-argument\": {\n return this.#lineWrapSeparator(options);\n }\n case \"inline\": {\n return INLINE_SEPARATOR;\n }\n default:\n throw new Error(\"Invalid argument line wrapping argument.\");\n }\n }\n\n #intraEntrySeparator(options: PrintOptions): string {\n switch (options?.argumentLineWrapping ?? DEFAULT_ARGUMENT_LINE_WRAPPING) {\n case \"by-entry\":\n case \"nested-by-entry\":\n case \"by-argument\": {\n return LINE_WRAP_LINE_END + this.#argIndentation(options);\n }\n case \"inline\": {\n return INLINE_SEPARATOR;\n }\n default:\n throw new Error(\"Invalid argument line wrapping argument.\");\n }\n }\n\n #separatorAfterCommand(\n options: PrintOptions,\n numFollowingEntries: number,\n ): string {\n if (numFollowingEntries === 0) {\n return \"\";\n }\n if (options.skipLineWrapBeforeFirstArg ?? false) {\n return INLINE_SEPARATOR;\n }\n return this.#intraEntrySeparator(options);\n }\n\n public getPrintableCommand(options?: PrintOptions): string {\n // TODO: Why in the world does TypeScript not give the `options` arg the type of `PrintOptions | undefined`???\n options ??= {};\n const serializedEntries: string[] = [];\n\n for (let i = 0; i < this.args.length; i++) {\n const argsEntry = stringifyIfPath(this.args[i]);\n\n if (isString(argsEntry)) {\n serializedEntries.push(escapeArg(argsEntry, false, options));\n } else {\n serializedEntries.push(\n argsEntry\n .map((part) => escapeArg(stringifyIfPath(part), false, options))\n .join(this.#argPairSeparator(options)),\n );\n }\n }\n\n let text =\n this.#mainIndentation(options) +\n escapeArg(this.commandName, true, options) +\n this.#separatorAfterCommand(options, serializedEntries.length) +\n serializedEntries.join(this.#intraEntrySeparator(options));\n if (options?.style) {\n text = styleText(options.style, text);\n }\n return text;\n }\n\n /**\n * Print the shell command to {@link stderr} (default) or a specified stream.\n *\n * By default, this will be auto-styled (as bold gray) when `.isTTY` is true\n * for the stream. `.isTTY` is populated for the {@link stderr} and\n * {@link stdout} objects. Pass `\"autoStyle\": \"never\"` or an explicit\n * `style` to disable this.\n *\n */\n public print(options?: StreamPrintOptions): PrintableShellCommand {\n const stream = options?.stream ?? stderr;\n // Note: we only need to modify top-level fields, so `structuredClone(\u2026)`\n // would be overkill and can only cause performance issues.\n const optionsCopy = {\n ...options,\n style: this.#styleFromOptions(stream, options),\n };\n const writable =\n stream instanceof Writable ? stream : Writable.fromWeb(stream);\n writable.write(this.getPrintableCommand(optionsCopy));\n writable.write(\"\\n\");\n return this;\n }\n\n #styleFromOptions(\n stream: WriteStream | Writable,\n options?: StreamPrintOptions,\n ): StyleTextFormat | undefined {\n if (options?.autoStyle === \"never\") {\n return;\n }\n if (!(stream as { isTTY?: boolean }).isTTY) {\n return;\n }\n if (NO_COLOR()) {\n return;\n }\n return TTY_AUTO_STYLE;\n }\n\n #stdinSource: StdinSource | undefined;\n /**\n * Send data to `stdin` of the subprocess.\n *\n * Note that this will overwrite:\n *\n * - Any previous value set using {@link PrintableShellCommand.stdin | `.stdin(\u2026)`}.\n * - Any value set for `stdin` using the `\"stdio\"` field of {@link PrintableShellCommand.spawn | `.spawn(\u2026)`}.\n */\n stdin(source: StdinSource): PrintableShellCommand {\n const [key, ...moreKeys] = Object.keys(source);\n assert.equal(moreKeys.length, 0);\n // TODO: validate values?\n assert((STDIN_SOURCE_KEYS as unknown as string[]).includes(key));\n\n this.#stdinSource = source;\n return this;\n }\n\n /**\n * The returned child process includes a `.success` `Promise` field, per https://github.com/oven-sh/bun/issues/8313\n */\n public spawn: typeof spawnType = ((\n options?: Parameters<typeof spawnType>[0],\n ) => {\n const { spawn } = process.getBuiltinModule(\"node:child_process\");\n const cwd = stringifyIfPath(options?.cwd);\n options = { ...options };\n if (this.#stdinSource) {\n options ??= {};\n if (typeof options.stdio === \"undefined\") {\n options.stdio = \"pipe\";\n }\n if (typeof options.stdio === \"string\") {\n options.stdio = new Array(3).fill(options.stdio);\n }\n options.stdio = [\"pipe\", ...options.stdio.slice(1)];\n }\n // biome-ignore lint/suspicious/noTsIgnore: We don't want linting to depend on *broken* type checking.\n // @ts-ignore: The TypeScript checker has trouble reconciling the optional (i.e. potentially `undefined`) `options` with the third argument.\n const subprocess = spawn(...this.toCommandWithFlatArgs(), {\n ...(options as object),\n cwd,\n }) as NodeChildProcess & {\n success: Promise<void>;\n };\n let cachedExitCode: Promise<number> | undefined;\n const getCachedExitCode = (): Promise<number> => {\n // biome-ignore lint/suspicious/noAssignInExpressions: Caching pattern.\n return (cachedExitCode ??=\n // TODO: Use `Promise.withResolvers()` ocne we default to ES2024.\n new Promise((resolve, reject) => {\n if (subprocess.exitCode !== null) {\n resolve(subprocess.exitCode);\n }\n subprocess.addListener(\n \"exit\",\n /* we only use the first arg */\n resolve,\n );\n // biome-ignore lint/suspicious/noExplicitAny: We don't have the type available.\n subprocess.addListener(\"error\", (err: any) => {\n reject(err);\n });\n }));\n };\n\n // TODO: define properties on prototypes instead.\n Object.defineProperty(subprocess, \"success\", {\n get() {\n return (async () => {\n const exitCode = await getCachedExitCode();\n if (exitCode !== 0) {\n throw new Error(\n `Command failed with non-zero exit code: ${exitCode}`,\n );\n }\n })();\n },\n enumerable: false,\n });\n Object.defineProperty(subprocess, \"exited\", {\n get() {\n return (async () => {\n await getCachedExitCode();\n })();\n },\n enumerable: false,\n });\n Object.defineProperty(subprocess, \"exitCodePromise\", {\n get() {\n return getCachedExitCode();\n },\n enumerable: false,\n });\n\n if (subprocess.stdout) {\n // TODO: dedupe\n const s = subprocess as unknown as Readable &\n WithStdoutResponse &\n WithExitPromises;\n let cachedResponse: Response | undefined;\n s.stdout.response = () =>\n (cachedResponse ??= wrapHandleTrailingNewlinesForResponse(\n new Response(Readable.from(this.#generator(s.stdout, s))),\n ));\n s.stdout.text = wrapHandleTrailingNewlinesForResponder(s.stdout);\n const thisCached = this; // TODO: make this type-check using `.bind(\u2026)`\n s.stdout.text0 = async function* () {\n yield* thisCached.#split0(thisCached.#generator(s.stdout, s));\n };\n s.stdout.json = <T>() => s.stdout.response().json() as Promise<T>;\n }\n if (subprocess.stderr) {\n // TODO: dedupe\n const s = subprocess as unknown as Readable &\n WithStderrResponse &\n WithExitPromises;\n let cachedResponse: Response | undefined;\n s.stderr.response = () =>\n (cachedResponse ??= wrapHandleTrailingNewlinesForResponse(\n new Response(Readable.from(this.#generator(s.stderr, s))),\n ));\n s.stderr.text = wrapHandleTrailingNewlinesForResponder(s.stderr);\n const thisCached = this; // TODO: make this type-check using `.bind(\u2026)`\n s.stderr.text0 = async function* () {\n yield* thisCached.#split0(thisCached.#generator(s.stderr, s));\n };\n s.stderr.json = <T>() => s.stderr.response().json() as Promise<T>;\n }\n if (this.#stdinSource) {\n const { stdin } = subprocess;\n assert(stdin);\n if (\"text\" in this.#stdinSource) {\n stdin.write(this.#stdinSource.text);\n stdin.end();\n } else if (\"json\" in this.#stdinSource) {\n stdin.write(JSON.stringify(this.#stdinSource.json));\n stdin.end();\n } else if (\"path\" in this.#stdinSource) {\n createReadStream(stringifyIfPath(this.#stdinSource.path)).pipe(stdin);\n } else if (\"stream\" in this.#stdinSource) {\n const stream = (() => {\n const { stream } = this.#stdinSource;\n return stream instanceof Readable ? stream : Readable.fromWeb(stream);\n })();\n stream.pipe(stdin);\n } else {\n throw new Error(\"Invalid `.stdin(\u2026)` source?\");\n }\n }\n return subprocess;\n // biome-ignore lint/suspicious/noExplicitAny: Type wrangling\n }) as any;\n\n /** A wrapper for `.spawn(\u2026)` that sets stdio to `\"inherit\"` (common for\n * invoking commands from scripts whose output and interaction should be\n * surfaced to the user).\n *\n * If there is no other interaction with the shell from the calling process,\n * then it acts \"transparent\" and allows user to interact with the subprocess\n * in its stead.\n */\n public spawnPassthrough(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">>,\n ): ChildProcessByStdio<null, null, null> & WithExitPromises {\n if (options && \"stdio\" in options) {\n throw new Error(\"Unexpected `stdio` field.\");\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Type wrangling.\n return this.spawn({ ...options, stdio: \"inherit\" }) as any;\n }\n\n /** @deprecated Use `.spawnPassthrough(\u2026)` instead. */\n spawnTransparently = (\n ...args: Parameters<PrintableShellCommand[\"spawnPassthrough\"]>\n ): ReturnType<PrintableShellCommand[\"spawnPassthrough\"]> =>\n this.spawnPassthrough(...args);\n\n /**\n * A wrapper for {@link PrintableShellCommand.spawn | `.spawn(\u2026)`} that:\n *\n * - sets `detached` to `true`,\n * - sets stdio to `\"inherit\"`,\n * - calls `.unref()`, and\n * - does not wait for the process to exit.\n *\n * This is similar to starting a command in the background and disowning it (in a shell).\n *\n */\n public spawnDetached(\n options?: NodeWithCwd<Omit<Omit<NodeSpawnOptions, \"stdio\">, \"detached\">>,\n ): void {\n if (options) {\n for (const field of [\"stdio\", \"detached\"]) {\n if (field in options) {\n throw new Error(`Unexpected \\`${field}\\` field.`);\n }\n }\n }\n const childProcess = this.spawn({\n stdio: \"ignore\",\n ...options,\n detached: true,\n });\n childProcess.unref();\n }\n\n #generator(\n readable: Readable,\n exiter: WithExitPromises,\n options?: AllowFailureOptions,\n ): AsyncGenerator<string> {\n // TODO: we'd make this a `ReadableStream`, but `ReadableStream.from(\u2026)` is\n // not implemented in `bun`: https://github.com/oven-sh/bun/issues/3700\n return (async function* () {\n for await (const chunk of readable) {\n yield chunk;\n }\n if (options?.allowFailure) {\n await exiter.exited;\n } else {\n await exiter.success;\n }\n })();\n }\n\n #stdoutSpawnGenerator(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> &\n AllowFailureOptions,\n ): AsyncGenerator<string> {\n if (options && \"stdio\" in options) {\n throw new Error(\"Unexpected `stdio` field.\");\n }\n const subprocess = this.spawn({\n ...options,\n stdio: [\"ignore\", \"pipe\", \"inherit\"],\n });\n return this.#generator(subprocess.stdout, subprocess, options);\n }\n\n public stdout(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> &\n AllowFailureOptions,\n ): Response & {\n text: (options?: TrailingNewlineOptions) => Promise<string>;\n } {\n // TODO: Use `ReadableStream.from(\u2026)` once `bun` implements it: https://github.com/oven-sh/bun/pull/21269\n return wrapHandleTrailingNewlinesForResponse(\n new Response(Readable.from(this.#stdoutSpawnGenerator(options))),\n );\n }\n\n #stderrSpawnGenerator(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> &\n AllowFailureOptions,\n ): AsyncGenerator<string> {\n if (options && \"stdio\" in options) {\n throw new Error(\"Unexpected `stdio` field.\");\n }\n const subprocess = this.spawn({\n ...options,\n stdio: [\"ignore\", \"inherit\", \"pipe\"],\n });\n return this.#generator(subprocess.stderr, subprocess, options);\n }\n\n public stderr(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> &\n AllowFailureOptions,\n ): Response & {\n text: (options?: TrailingNewlineOptions) => Promise<string>;\n } {\n // TODO: Use `ReadableStream.from(\u2026)` once `bun` implements it: https://github.com/oven-sh/bun/pull/21269\n return wrapHandleTrailingNewlinesForResponse(\n new Response(Readable.from(this.#stderrSpawnGenerator(options))),\n );\n }\n\n async *#split0(generator: AsyncGenerator<string>): AsyncGenerator<string> {\n let pending = \"\";\n for await (const chunk of generator) {\n pending += chunk;\n const newChunks = pending.split(\"\\x00\");\n pending = newChunks.splice(-1)[0];\n yield* newChunks;\n }\n if (pending !== \"\") {\n throw new Error(\n \"Missing a trailing NUL character at the end of a NUL-delimited stream.\",\n );\n }\n }\n\n /**\n * Convenience function for:\n *\n * .stdout(options).text()\n *\n * This can make some simple invocations easier to read and/or fit on a single line.\n */\n public async text(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> &\n TrailingNewlineOptions &\n AllowFailureOptions,\n ): Promise<string> {\n const {\n trimTrailingNewlines: trimTrailingNewlinesOption,\n ...stdoutOptions\n } = options ?? {};\n return handleTrailingNewlines(this.stdout(stdoutOptions).text(), {\n trimTrailingNewlines: trimTrailingNewlinesOption,\n });\n }\n\n /**\n * Convenience function for:\n *\n * .stdout(options).json()\n *\n * This can make some simple invocations easier to read and/or fit on a single line.\n */\n public json<T>(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> &\n AllowFailureOptions,\n ): Promise<T> {\n return this.stdout(options).json() as Promise<T>;\n }\n\n /**\n * Parse `stdout` into a generator of string values using a NULL delimiter.\n *\n * A trailing NULL delimiter from `stdout` is required and removed.\n */\n public async *text0(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> &\n AllowFailureOptions,\n ): AsyncGenerator<string> {\n yield* this.#split0(this.#stdoutSpawnGenerator(options));\n }\n\n /**\n * Parse `stdout` into a generator of JSON values using a NULL delimiter.\n *\n * A trailing NULL delimiter from `stdout` is required and removed.\n */\n public async *json0(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> &\n AllowFailureOptions,\n ): // biome-ignore lint/suspicious/noExplicitAny: `any` is the correct type for JSON\n AsyncGenerator<any> {\n for await (const part of this.#split0(\n this.#stdoutSpawnGenerator(options),\n )) {\n yield JSON.parse(part);\n }\n }\n\n /** Equivalent to:\n *\n * ```\n * await this.print(\u2026).spawnTransparently(\u2026).success;\n * ```\n */\n public async shellOut(\n options?: NodeWithCwd<Omit<NodeSpawnOptions, \"stdio\">> & {\n print?: StreamPrintOptions | ArgumentLineWrapping | boolean;\n },\n ): Promise<void> {\n const { print: printOptions, ...spawnOptions } = options ?? {};\n\n if (typeof printOptions === \"string\") {\n assert(ARGUMENT_LINE_WRAPPING_VALUES.includes(printOptions));\n this.print({ argumentLineWrapping: printOptions });\n } else if (printOptions === true) {\n this.print();\n } else if (printOptions === false) {\n // no-op\n } else {\n this.print(printOptions);\n }\n await this.spawnPassthrough(spawnOptions).success;\n }\n}\n\nexport function escapeArg(\n arg: string,\n isMainCommand: boolean,\n options: PrintOptions,\n): string {\n const argCharacters = new Set(arg);\n const specialShellCharacters = isMainCommand\n ? SPECIAL_SHELL_CHARACTERS_FOR_MAIN_COMMAND\n : SPECIAL_SHELL_CHARACTERS;\n if (\n options?.quoting === \"extra-safe\" ||\n // biome-ignore lint/suspicious/noExplicitAny: Workaround to make this package easier to use in a project that otherwise only uses ES2022.)\n (argCharacters as unknown as any).intersection(specialShellCharacters)\n .size > 0\n ) {\n // Use single quote to reduce the need to escape (and therefore reduce the chance for bugs/security issues).\n const escaped = arg.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll(\"'\", \"\\\\'\");\n return `'${escaped}'`;\n }\n return arg;\n}\n", "const DEFAULT_TRIM_TRAILING_NEWLINE_BEHAVIOUR = \"never\";\nexport interface TrailingNewlineOptions {\n trimTrailingNewlines?: \"single-required\" | \"single-if-present\" | \"never\";\n}\n\n// TODO: Handle carriage return?\nexport async function handleTrailingNewlines(\n text: Promise<string>,\n options?: TrailingNewlineOptions,\n): Promise<string> {\n const awaitedText = await text;\n switch (\n options?.trimTrailingNewlines ??\n DEFAULT_TRIM_TRAILING_NEWLINE_BEHAVIOUR\n ) {\n case \"single-required\": {\n if (!awaitedText.endsWith(\"\\n\")) {\n throw new Error(\"Trailing newline required, but not present.\");\n }\n return awaitedText.slice(0, -1);\n }\n case \"single-if-present\": {\n if (awaitedText.endsWith(\"\\n\")) {\n return awaitedText.slice(0, -1);\n } else {\n return awaitedText;\n }\n }\n case \"never\": {\n return awaitedText;\n }\n default:\n throw new Error(\"Invalid value for `trimTrailingNewlines`.\");\n }\n}\n\nfunction wrapHandleTrailingNewlines(\n fn: () => Promise<string>,\n): (options?: TrailingNewlineOptions) => Promise<string> {\n return (options?: TrailingNewlineOptions) =>\n handleTrailingNewlines(fn(), options);\n}\n\nexport function wrapHandleTrailingNewlinesForResponder(v: {\n response(): {\n text: () => Promise<string>;\n };\n}): (options?: TrailingNewlineOptions) => Promise<string> {\n const response = v.response();\n const originalTextFn = response.text.bind(response);\n return wrapHandleTrailingNewlines(originalTextFn);\n}\n\nexport function wrapHandleTrailingNewlinesForResponse(\n response: Response,\n): Response & { text: (options?: TrailingNewlineOptions) => Promise<string> } {\n const textFn = wrapHandleTrailingNewlinesForResponder({\n response: () => response,\n });\n Object.defineProperty(response, \"text\", {\n get: () => {\n return textFn;\n },\n });\n return response;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["stream"]
|
|
7
7
|
}
|
|
@@ -8,8 +8,10 @@ export type NodeWithCwd<T extends {
|
|
|
8
8
|
}> = Omit<T, "cwd"> & {
|
|
9
9
|
cwd?: NodeCwd;
|
|
10
10
|
};
|
|
11
|
-
export interface
|
|
11
|
+
export interface WithExitPromises {
|
|
12
12
|
success: Promise<void>;
|
|
13
|
+
exited: Promise<void>;
|
|
14
|
+
exitCodePromise: Promise<number>;
|
|
13
15
|
}
|
|
14
16
|
export interface WithResponse {
|
|
15
17
|
response: () => Response;
|
|
@@ -23,13 +25,13 @@ export interface WithStdoutResponse {
|
|
|
23
25
|
export interface WithStderrResponse {
|
|
24
26
|
stderr: Readable & WithResponse;
|
|
25
27
|
}
|
|
26
|
-
export declare function spawnType(options?: NodeWithCwd<SpawnOptionsWithoutStdio>): ChildProcessWithoutNullStreams &
|
|
27
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioPipe>>): ChildProcessByStdio<Writable, Readable, Readable> &
|
|
28
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioNull>>): ChildProcessByStdio<Writable, Readable, null> &
|
|
29
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioPipe>>): ChildProcessByStdio<Writable, null, Readable> &
|
|
30
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioPipe>>): ChildProcessByStdio<null, Readable, Readable> &
|
|
31
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioNull>>): ChildProcessByStdio<Writable, null, null> &
|
|
32
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioNull>>): ChildProcessByStdio<null, Readable, null> &
|
|
33
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioPipe>>): ChildProcessByStdio<null, null, Readable> &
|
|
34
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioNull>>): ChildProcessByStdio<null, null, null> &
|
|
35
|
-
export declare function spawnType(options: NodeWithCwd<SpawnOptions>): ChildProcess &
|
|
28
|
+
export declare function spawnType(options?: NodeWithCwd<SpawnOptionsWithoutStdio>): ChildProcessWithoutNullStreams & WithExitPromises;
|
|
29
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioPipe>>): ChildProcessByStdio<Writable, Readable, Readable> & WithExitPromises & WithStdoutResponse & WithStderrResponse;
|
|
30
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioNull>>): ChildProcessByStdio<Writable, Readable, null> & WithExitPromises & WithStdoutResponse;
|
|
31
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioPipe>>): ChildProcessByStdio<Writable, null, Readable> & WithExitPromises & WithStderrResponse;
|
|
32
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioPipe>>): ChildProcessByStdio<null, Readable, Readable> & WithExitPromises & WithStdoutResponse & WithStderrResponse;
|
|
33
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioNull>>): ChildProcessByStdio<Writable, null, null> & WithExitPromises;
|
|
34
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioNull>>): ChildProcessByStdio<null, Readable, null> & WithExitPromises & WithStdoutResponse;
|
|
35
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioPipe>>): ChildProcessByStdio<null, null, Readable> & WithExitPromises & WithStderrResponse;
|
|
36
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioNull>>): ChildProcessByStdio<null, null, null> & WithExitPromises;
|
|
37
|
+
export declare function spawnType(options: NodeWithCwd<SpawnOptions>): ChildProcess & WithExitPromises;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "printable-shell-command",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"description": "A helper class to construct shell commands in a way that allows printing them.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Lucas Garron",
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@types/node": ">=25.0.3",
|
|
24
23
|
"path-class": ">=0.12.1"
|
|
25
24
|
},
|
|
26
25
|
"devDependencies": {
|
|
27
|
-
"@biomejs/biome": "2.
|
|
28
|
-
"@cubing/dev-config": ">=0.
|
|
26
|
+
"@biomejs/biome": "^2.4.8",
|
|
27
|
+
"@cubing/dev-config": ">=0.9.4",
|
|
29
28
|
"@lgarron-bin/repo": "^0.14.5",
|
|
30
|
-
"@types/bun": "^1.3.
|
|
29
|
+
"@types/bun": "^1.3.12",
|
|
30
|
+
"@types/node": "^25.6.0",
|
|
31
|
+
"@typescript/native-preview": "^7.0.0-dev.20260413.1",
|
|
31
32
|
"bun-dx": "^0.1.4",
|
|
32
33
|
"clipboardy": "^5.0.2",
|
|
33
34
|
"esbuild": "^0.27.2",
|
|
34
|
-
"readme-cli-help": "^0.4.10"
|
|
35
|
-
"typescript": "^5.9.3"
|
|
35
|
+
"readme-cli-help": "^0.4.10"
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"./dist/",
|
|
@@ -40,5 +40,8 @@
|
|
|
40
40
|
],
|
|
41
41
|
"scripts": {
|
|
42
42
|
"prepublishOnly": "make prepublishOnly"
|
|
43
|
+
},
|
|
44
|
+
"patchedDependencies": {
|
|
45
|
+
"bun-types@1.3.12": "patches/bun-types@1.3.12.patch"
|
|
43
46
|
}
|
|
44
47
|
}
|
|
@@ -13,9 +13,9 @@ import { Path, stringifyIfPath } from "path-class";
|
|
|
13
13
|
import type {
|
|
14
14
|
NodeWithCwd,
|
|
15
15
|
spawnType,
|
|
16
|
+
WithExitPromises,
|
|
16
17
|
WithStderrResponse,
|
|
17
18
|
WithStdoutResponse,
|
|
18
|
-
WithSuccess,
|
|
19
19
|
} from "./spawn";
|
|
20
20
|
import {
|
|
21
21
|
handleTrailingNewlines,
|
|
@@ -24,11 +24,6 @@ import {
|
|
|
24
24
|
wrapHandleTrailingNewlinesForResponse,
|
|
25
25
|
} from "./trimTrailingNewlines";
|
|
26
26
|
|
|
27
|
-
// TODO: does this import work?
|
|
28
|
-
/**
|
|
29
|
-
* @import { stdout } from "node:process"
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
27
|
const DEFAULT_MAIN_INDENTATION = "";
|
|
33
28
|
const DEFAULT_ARG_INDENTATION = " ";
|
|
34
29
|
const DEFAULT_ARGUMENT_LINE_WRAPPING = "by-entry";
|
|
@@ -175,6 +170,10 @@ export type StdinSource =
|
|
|
175
170
|
| { path: string | Path }
|
|
176
171
|
| { stream: Readable | ReadableStream };
|
|
177
172
|
|
|
173
|
+
interface AllowFailureOptions {
|
|
174
|
+
allowFailure?: boolean;
|
|
175
|
+
}
|
|
176
|
+
|
|
178
177
|
export class PrintableShellCommand {
|
|
179
178
|
#commandName: string | Path;
|
|
180
179
|
constructor(
|
|
@@ -407,50 +406,70 @@ export class PrintableShellCommand {
|
|
|
407
406
|
}) as NodeChildProcess & {
|
|
408
407
|
success: Promise<void>;
|
|
409
408
|
};
|
|
410
|
-
let
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
//
|
|
415
|
-
|
|
416
|
-
function handle(exitCode: number) {
|
|
417
|
-
if (exitCode === 0) {
|
|
418
|
-
resolve();
|
|
419
|
-
} else {
|
|
420
|
-
reject(`Command failed with non-zero exit code: ${exitCode}`);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
409
|
+
let cachedExitCode: Promise<number> | undefined;
|
|
410
|
+
const getCachedExitCode = (): Promise<number> => {
|
|
411
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: Caching pattern.
|
|
412
|
+
return (cachedExitCode ??=
|
|
413
|
+
// TODO: Use `Promise.withResolvers()` ocne we default to ES2024.
|
|
414
|
+
new Promise((resolve, reject) => {
|
|
423
415
|
if (subprocess.exitCode !== null) {
|
|
424
|
-
|
|
416
|
+
resolve(subprocess.exitCode);
|
|
425
417
|
}
|
|
426
|
-
|
|
418
|
+
subprocess.addListener(
|
|
427
419
|
"exit",
|
|
428
420
|
/* we only use the first arg */
|
|
429
|
-
|
|
421
|
+
resolve,
|
|
430
422
|
);
|
|
431
423
|
// biome-ignore lint/suspicious/noExplicitAny: We don't have the type available.
|
|
432
|
-
|
|
424
|
+
subprocess.addListener("error", (err: any) => {
|
|
433
425
|
reject(err);
|
|
434
426
|
});
|
|
435
427
|
}));
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
// TODO: define properties on prototypes instead.
|
|
431
|
+
Object.defineProperty(subprocess, "success", {
|
|
432
|
+
get() {
|
|
433
|
+
return (async () => {
|
|
434
|
+
const exitCode = await getCachedExitCode();
|
|
435
|
+
if (exitCode !== 0) {
|
|
436
|
+
throw new Error(
|
|
437
|
+
`Command failed with non-zero exit code: ${exitCode}`,
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
})();
|
|
441
|
+
},
|
|
442
|
+
enumerable: false,
|
|
443
|
+
});
|
|
444
|
+
Object.defineProperty(subprocess, "exited", {
|
|
445
|
+
get() {
|
|
446
|
+
return (async () => {
|
|
447
|
+
await getCachedExitCode();
|
|
448
|
+
})();
|
|
449
|
+
},
|
|
450
|
+
enumerable: false,
|
|
451
|
+
});
|
|
452
|
+
Object.defineProperty(subprocess, "exitCodePromise", {
|
|
453
|
+
get() {
|
|
454
|
+
return getCachedExitCode();
|
|
436
455
|
},
|
|
437
456
|
enumerable: false,
|
|
438
457
|
});
|
|
458
|
+
|
|
439
459
|
if (subprocess.stdout) {
|
|
440
460
|
// TODO: dedupe
|
|
441
461
|
const s = subprocess as unknown as Readable &
|
|
442
462
|
WithStdoutResponse &
|
|
443
|
-
|
|
463
|
+
WithExitPromises;
|
|
444
464
|
let cachedResponse: Response | undefined;
|
|
445
465
|
s.stdout.response = () =>
|
|
446
|
-
// biome-ignore lint/suspicious/noAssignInExpressions: TODO: https://github.com/biomejs/biome/discussions/7592
|
|
447
466
|
(cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
448
|
-
new Response(Readable.from(this.#generator(s.stdout, s
|
|
467
|
+
new Response(Readable.from(this.#generator(s.stdout, s))),
|
|
449
468
|
));
|
|
450
469
|
s.stdout.text = wrapHandleTrailingNewlinesForResponder(s.stdout);
|
|
451
470
|
const thisCached = this; // TODO: make this type-check using `.bind(…)`
|
|
452
471
|
s.stdout.text0 = async function* () {
|
|
453
|
-
yield* thisCached.#split0(thisCached.#generator(s.stdout, s
|
|
472
|
+
yield* thisCached.#split0(thisCached.#generator(s.stdout, s));
|
|
454
473
|
};
|
|
455
474
|
s.stdout.json = <T>() => s.stdout.response().json() as Promise<T>;
|
|
456
475
|
}
|
|
@@ -458,17 +477,16 @@ export class PrintableShellCommand {
|
|
|
458
477
|
// TODO: dedupe
|
|
459
478
|
const s = subprocess as unknown as Readable &
|
|
460
479
|
WithStderrResponse &
|
|
461
|
-
|
|
480
|
+
WithExitPromises;
|
|
462
481
|
let cachedResponse: Response | undefined;
|
|
463
482
|
s.stderr.response = () =>
|
|
464
|
-
// biome-ignore lint/suspicious/noAssignInExpressions: TODO: https://github.com/biomejs/biome/discussions/7592
|
|
465
483
|
(cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
466
|
-
new Response(Readable.from(this.#generator(s.stderr, s
|
|
484
|
+
new Response(Readable.from(this.#generator(s.stderr, s))),
|
|
467
485
|
));
|
|
468
486
|
s.stderr.text = wrapHandleTrailingNewlinesForResponder(s.stderr);
|
|
469
487
|
const thisCached = this; // TODO: make this type-check using `.bind(…)`
|
|
470
488
|
s.stderr.text0 = async function* () {
|
|
471
|
-
yield* thisCached.#split0(thisCached.#generator(s.stderr, s
|
|
489
|
+
yield* thisCached.#split0(thisCached.#generator(s.stderr, s));
|
|
472
490
|
};
|
|
473
491
|
s.stderr.json = <T>() => s.stderr.response().json() as Promise<T>;
|
|
474
492
|
}
|
|
@@ -505,9 +523,9 @@ export class PrintableShellCommand {
|
|
|
505
523
|
* then it acts "transparent" and allows user to interact with the subprocess
|
|
506
524
|
* in its stead.
|
|
507
525
|
*/
|
|
508
|
-
public
|
|
526
|
+
public spawnPassthrough(
|
|
509
527
|
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">>,
|
|
510
|
-
): ChildProcessByStdio<null, null, null> &
|
|
528
|
+
): ChildProcessByStdio<null, null, null> & WithExitPromises {
|
|
511
529
|
if (options && "stdio" in options) {
|
|
512
530
|
throw new Error("Unexpected `stdio` field.");
|
|
513
531
|
}
|
|
@@ -516,6 +534,12 @@ export class PrintableShellCommand {
|
|
|
516
534
|
return this.spawn({ ...options, stdio: "inherit" }) as any;
|
|
517
535
|
}
|
|
518
536
|
|
|
537
|
+
/** @deprecated Use `.spawnPassthrough(…)` instead. */
|
|
538
|
+
spawnTransparently = (
|
|
539
|
+
...args: Parameters<PrintableShellCommand["spawnPassthrough"]>
|
|
540
|
+
): ReturnType<PrintableShellCommand["spawnPassthrough"]> =>
|
|
541
|
+
this.spawnPassthrough(...args);
|
|
542
|
+
|
|
519
543
|
/**
|
|
520
544
|
* A wrapper for {@link PrintableShellCommand.spawn | `.spawn(…)`} that:
|
|
521
545
|
*
|
|
@@ -547,7 +571,8 @@ export class PrintableShellCommand {
|
|
|
547
571
|
|
|
548
572
|
#generator(
|
|
549
573
|
readable: Readable,
|
|
550
|
-
|
|
574
|
+
exiter: WithExitPromises,
|
|
575
|
+
options?: AllowFailureOptions,
|
|
551
576
|
): AsyncGenerator<string> {
|
|
552
577
|
// TODO: we'd make this a `ReadableStream`, but `ReadableStream.from(…)` is
|
|
553
578
|
// not implemented in `bun`: https://github.com/oven-sh/bun/issues/3700
|
|
@@ -555,12 +580,17 @@ export class PrintableShellCommand {
|
|
|
555
580
|
for await (const chunk of readable) {
|
|
556
581
|
yield chunk;
|
|
557
582
|
}
|
|
558
|
-
|
|
583
|
+
if (options?.allowFailure) {
|
|
584
|
+
await exiter.exited;
|
|
585
|
+
} else {
|
|
586
|
+
await exiter.success;
|
|
587
|
+
}
|
|
559
588
|
})();
|
|
560
589
|
}
|
|
561
590
|
|
|
562
591
|
#stdoutSpawnGenerator(
|
|
563
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
592
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
593
|
+
AllowFailureOptions,
|
|
564
594
|
): AsyncGenerator<string> {
|
|
565
595
|
if (options && "stdio" in options) {
|
|
566
596
|
throw new Error("Unexpected `stdio` field.");
|
|
@@ -569,11 +599,12 @@ export class PrintableShellCommand {
|
|
|
569
599
|
...options,
|
|
570
600
|
stdio: ["ignore", "pipe", "inherit"],
|
|
571
601
|
});
|
|
572
|
-
return this.#generator(subprocess.stdout, subprocess
|
|
602
|
+
return this.#generator(subprocess.stdout, subprocess, options);
|
|
573
603
|
}
|
|
574
604
|
|
|
575
605
|
public stdout(
|
|
576
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
606
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
607
|
+
AllowFailureOptions,
|
|
577
608
|
): Response & {
|
|
578
609
|
text: (options?: TrailingNewlineOptions) => Promise<string>;
|
|
579
610
|
} {
|
|
@@ -584,7 +615,8 @@ export class PrintableShellCommand {
|
|
|
584
615
|
}
|
|
585
616
|
|
|
586
617
|
#stderrSpawnGenerator(
|
|
587
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
618
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
619
|
+
AllowFailureOptions,
|
|
588
620
|
): AsyncGenerator<string> {
|
|
589
621
|
if (options && "stdio" in options) {
|
|
590
622
|
throw new Error("Unexpected `stdio` field.");
|
|
@@ -593,11 +625,12 @@ export class PrintableShellCommand {
|
|
|
593
625
|
...options,
|
|
594
626
|
stdio: ["ignore", "inherit", "pipe"],
|
|
595
627
|
});
|
|
596
|
-
return this.#generator(subprocess.stderr, subprocess
|
|
628
|
+
return this.#generator(subprocess.stderr, subprocess, options);
|
|
597
629
|
}
|
|
598
630
|
|
|
599
631
|
public stderr(
|
|
600
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
632
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
633
|
+
AllowFailureOptions,
|
|
601
634
|
): Response & {
|
|
602
635
|
text: (options?: TrailingNewlineOptions) => Promise<string>;
|
|
603
636
|
} {
|
|
@@ -630,15 +663,15 @@ export class PrintableShellCommand {
|
|
|
630
663
|
* This can make some simple invocations easier to read and/or fit on a single line.
|
|
631
664
|
*/
|
|
632
665
|
public async text(
|
|
633
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
634
|
-
|
|
635
|
-
|
|
666
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
667
|
+
TrailingNewlineOptions &
|
|
668
|
+
AllowFailureOptions,
|
|
636
669
|
): Promise<string> {
|
|
637
670
|
const {
|
|
638
671
|
trimTrailingNewlines: trimTrailingNewlinesOption,
|
|
639
|
-
...
|
|
672
|
+
...stdoutOptions
|
|
640
673
|
} = options ?? {};
|
|
641
|
-
return handleTrailingNewlines(this.stdout(
|
|
674
|
+
return handleTrailingNewlines(this.stdout(stdoutOptions).text(), {
|
|
642
675
|
trimTrailingNewlines: trimTrailingNewlinesOption,
|
|
643
676
|
});
|
|
644
677
|
}
|
|
@@ -651,7 +684,8 @@ export class PrintableShellCommand {
|
|
|
651
684
|
* This can make some simple invocations easier to read and/or fit on a single line.
|
|
652
685
|
*/
|
|
653
686
|
public json<T>(
|
|
654
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
687
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
688
|
+
AllowFailureOptions,
|
|
655
689
|
): Promise<T> {
|
|
656
690
|
return this.stdout(options).json() as Promise<T>;
|
|
657
691
|
}
|
|
@@ -662,7 +696,8 @@ export class PrintableShellCommand {
|
|
|
662
696
|
* A trailing NULL delimiter from `stdout` is required and removed.
|
|
663
697
|
*/
|
|
664
698
|
public async *text0(
|
|
665
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
699
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
700
|
+
AllowFailureOptions,
|
|
666
701
|
): AsyncGenerator<string> {
|
|
667
702
|
yield* this.#split0(this.#stdoutSpawnGenerator(options));
|
|
668
703
|
}
|
|
@@ -673,7 +708,8 @@ export class PrintableShellCommand {
|
|
|
673
708
|
* A trailing NULL delimiter from `stdout` is required and removed.
|
|
674
709
|
*/
|
|
675
710
|
public async *json0(
|
|
676
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
711
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
712
|
+
AllowFailureOptions,
|
|
677
713
|
): // biome-ignore lint/suspicious/noExplicitAny: `any` is the correct type for JSON
|
|
678
714
|
AsyncGenerator<any> {
|
|
679
715
|
for await (const part of this.#split0(
|
|
@@ -706,7 +742,7 @@ export class PrintableShellCommand {
|
|
|
706
742
|
} else {
|
|
707
743
|
this.print(printOptions);
|
|
708
744
|
}
|
|
709
|
-
await this.
|
|
745
|
+
await this.spawnPassthrough(spawnOptions).success;
|
|
710
746
|
}
|
|
711
747
|
}
|
|
712
748
|
|
package/src/spawn.ts
CHANGED
|
@@ -19,8 +19,11 @@ export type NodeWithCwd<T extends { cwd?: ProcessEnvOptions["cwd"] }> = Omit<
|
|
|
19
19
|
"cwd"
|
|
20
20
|
> & { cwd?: NodeCwd };
|
|
21
21
|
|
|
22
|
-
export interface
|
|
22
|
+
export interface WithExitPromises {
|
|
23
23
|
success: Promise<void>;
|
|
24
|
+
exited: Promise<void>;
|
|
25
|
+
// This can't be called `exitCode`, because that's already taken by the lazily populated property.
|
|
26
|
+
exitCodePromise: Promise<number>;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
export interface WithResponse {
|
|
@@ -39,13 +42,13 @@ export interface WithStderrResponse {
|
|
|
39
42
|
|
|
40
43
|
export declare function spawnType(
|
|
41
44
|
options?: NodeWithCwd<SpawnOptionsWithoutStdio>,
|
|
42
|
-
): ChildProcessWithoutNullStreams &
|
|
45
|
+
): ChildProcessWithoutNullStreams & WithExitPromises;
|
|
43
46
|
export declare function spawnType(
|
|
44
47
|
options: NodeWithCwd<
|
|
45
48
|
SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioPipe>
|
|
46
49
|
>,
|
|
47
50
|
): ChildProcessByStdio<Writable, Readable, Readable> &
|
|
48
|
-
|
|
51
|
+
WithExitPromises &
|
|
49
52
|
WithStdoutResponse &
|
|
50
53
|
WithStderrResponse;
|
|
51
54
|
export declare function spawnType(
|
|
@@ -53,43 +56,47 @@ export declare function spawnType(
|
|
|
53
56
|
SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioNull>
|
|
54
57
|
>,
|
|
55
58
|
): ChildProcessByStdio<Writable, Readable, null> &
|
|
56
|
-
|
|
59
|
+
WithExitPromises &
|
|
57
60
|
WithStdoutResponse;
|
|
58
61
|
export declare function spawnType(
|
|
59
62
|
options: NodeWithCwd<
|
|
60
63
|
SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioPipe>
|
|
61
64
|
>,
|
|
62
65
|
): ChildProcessByStdio<Writable, null, Readable> &
|
|
63
|
-
|
|
66
|
+
WithExitPromises &
|
|
64
67
|
WithStderrResponse;
|
|
65
68
|
export declare function spawnType(
|
|
66
69
|
options: NodeWithCwd<
|
|
67
70
|
SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioPipe>
|
|
68
71
|
>,
|
|
69
72
|
): ChildProcessByStdio<null, Readable, Readable> &
|
|
70
|
-
|
|
73
|
+
WithExitPromises &
|
|
71
74
|
WithStdoutResponse &
|
|
72
75
|
WithStderrResponse;
|
|
73
76
|
export declare function spawnType(
|
|
74
77
|
options: NodeWithCwd<
|
|
75
78
|
SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioNull>
|
|
76
79
|
>,
|
|
77
|
-
): ChildProcessByStdio<Writable, null, null> &
|
|
80
|
+
): ChildProcessByStdio<Writable, null, null> & WithExitPromises;
|
|
78
81
|
export declare function spawnType(
|
|
79
82
|
options: NodeWithCwd<
|
|
80
83
|
SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioNull>
|
|
81
84
|
>,
|
|
82
|
-
): ChildProcessByStdio<null, Readable, null> &
|
|
85
|
+
): ChildProcessByStdio<null, Readable, null> &
|
|
86
|
+
WithExitPromises &
|
|
87
|
+
WithStdoutResponse;
|
|
83
88
|
export declare function spawnType(
|
|
84
89
|
options: NodeWithCwd<
|
|
85
90
|
SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioPipe>
|
|
86
91
|
>,
|
|
87
|
-
): ChildProcessByStdio<null, null, Readable> &
|
|
92
|
+
): ChildProcessByStdio<null, null, Readable> &
|
|
93
|
+
WithExitPromises &
|
|
94
|
+
WithStderrResponse;
|
|
88
95
|
export declare function spawnType(
|
|
89
96
|
options: NodeWithCwd<
|
|
90
97
|
SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioNull>
|
|
91
98
|
>,
|
|
92
|
-
): ChildProcessByStdio<null, null, null> &
|
|
99
|
+
): ChildProcessByStdio<null, null, null> & WithExitPromises;
|
|
93
100
|
export declare function spawnType(
|
|
94
101
|
options: NodeWithCwd<SpawnOptions>,
|
|
95
|
-
): ChildProcess &
|
|
102
|
+
): ChildProcess & WithExitPromises;
|