printable-shell-command 5.2.0 → 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 +56 -32
- 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 +7 -4
- package/src/PrintableShellCommand.ts +86 -48
- 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,29 +296,47 @@ 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
|
});
|
|
@@ -326,12 +344,12 @@ var PrintableShellCommand = class {
|
|
|
326
344
|
const s = subprocess;
|
|
327
345
|
let cachedResponse;
|
|
328
346
|
s.stdout.response = () => cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
329
|
-
new Response(Readable.from(this.#generator(s.stdout, s
|
|
347
|
+
new Response(Readable.from(this.#generator(s.stdout, s)))
|
|
330
348
|
);
|
|
331
349
|
s.stdout.text = wrapHandleTrailingNewlinesForResponder(s.stdout);
|
|
332
350
|
const thisCached = this;
|
|
333
351
|
s.stdout.text0 = async function* () {
|
|
334
|
-
yield* thisCached.#split0(thisCached.#generator(s.stdout, s
|
|
352
|
+
yield* thisCached.#split0(thisCached.#generator(s.stdout, s));
|
|
335
353
|
};
|
|
336
354
|
s.stdout.json = () => s.stdout.response().json();
|
|
337
355
|
}
|
|
@@ -339,12 +357,12 @@ var PrintableShellCommand = class {
|
|
|
339
357
|
const s = subprocess;
|
|
340
358
|
let cachedResponse;
|
|
341
359
|
s.stderr.response = () => cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
342
|
-
new Response(Readable.from(this.#generator(s.stderr, s
|
|
360
|
+
new Response(Readable.from(this.#generator(s.stderr, s)))
|
|
343
361
|
);
|
|
344
362
|
s.stderr.text = wrapHandleTrailingNewlinesForResponder(s.stderr);
|
|
345
363
|
const thisCached = this;
|
|
346
364
|
s.stderr.text0 = async function* () {
|
|
347
|
-
yield* thisCached.#split0(thisCached.#generator(s.stderr, s
|
|
365
|
+
yield* thisCached.#split0(thisCached.#generator(s.stderr, s));
|
|
348
366
|
};
|
|
349
367
|
s.stderr.json = () => s.stderr.response().json();
|
|
350
368
|
}
|
|
@@ -379,12 +397,14 @@ var PrintableShellCommand = class {
|
|
|
379
397
|
* then it acts "transparent" and allows user to interact with the subprocess
|
|
380
398
|
* in its stead.
|
|
381
399
|
*/
|
|
382
|
-
|
|
400
|
+
spawnPassthrough(options) {
|
|
383
401
|
if (options && "stdio" in options) {
|
|
384
402
|
throw new Error("Unexpected `stdio` field.");
|
|
385
403
|
}
|
|
386
404
|
return this.spawn({ ...options, stdio: "inherit" });
|
|
387
405
|
}
|
|
406
|
+
/** @deprecated Use `.spawnPassthrough(…)` instead. */
|
|
407
|
+
spawnTransparently = (...args) => this.spawnPassthrough(...args);
|
|
388
408
|
/**
|
|
389
409
|
* A wrapper for {@link PrintableShellCommand.spawn | `.spawn(…)`} that:
|
|
390
410
|
*
|
|
@@ -411,12 +431,16 @@ var PrintableShellCommand = class {
|
|
|
411
431
|
});
|
|
412
432
|
childProcess.unref();
|
|
413
433
|
}
|
|
414
|
-
#generator(readable,
|
|
434
|
+
#generator(readable, exiter, options) {
|
|
415
435
|
return (async function* () {
|
|
416
436
|
for await (const chunk of readable) {
|
|
417
437
|
yield chunk;
|
|
418
438
|
}
|
|
419
|
-
|
|
439
|
+
if (options?.allowFailure) {
|
|
440
|
+
await exiter.exited;
|
|
441
|
+
} else {
|
|
442
|
+
await exiter.success;
|
|
443
|
+
}
|
|
420
444
|
})();
|
|
421
445
|
}
|
|
422
446
|
#stdoutSpawnGenerator(options) {
|
|
@@ -427,7 +451,7 @@ var PrintableShellCommand = class {
|
|
|
427
451
|
...options,
|
|
428
452
|
stdio: ["ignore", "pipe", "inherit"]
|
|
429
453
|
});
|
|
430
|
-
return this.#generator(subprocess.stdout, subprocess
|
|
454
|
+
return this.#generator(subprocess.stdout, subprocess, options);
|
|
431
455
|
}
|
|
432
456
|
stdout(options) {
|
|
433
457
|
return wrapHandleTrailingNewlinesForResponse(
|
|
@@ -442,7 +466,7 @@ var PrintableShellCommand = class {
|
|
|
442
466
|
...options,
|
|
443
467
|
stdio: ["ignore", "inherit", "pipe"]
|
|
444
468
|
});
|
|
445
|
-
return this.#generator(subprocess.stderr, subprocess
|
|
469
|
+
return this.#generator(subprocess.stderr, subprocess, options);
|
|
446
470
|
}
|
|
447
471
|
stderr(options) {
|
|
448
472
|
return wrapHandleTrailingNewlinesForResponse(
|
|
@@ -473,9 +497,9 @@ var PrintableShellCommand = class {
|
|
|
473
497
|
async text(options) {
|
|
474
498
|
const {
|
|
475
499
|
trimTrailingNewlines: trimTrailingNewlinesOption,
|
|
476
|
-
...
|
|
500
|
+
...stdoutOptions
|
|
477
501
|
} = options ?? {};
|
|
478
|
-
return handleTrailingNewlines(this.stdout(
|
|
502
|
+
return handleTrailingNewlines(this.stdout(stdoutOptions).text(), {
|
|
479
503
|
trimTrailingNewlines: trimTrailingNewlinesOption
|
|
480
504
|
});
|
|
481
505
|
}
|
|
@@ -526,7 +550,7 @@ var PrintableShellCommand = class {
|
|
|
526
550
|
} else {
|
|
527
551
|
this.print(printOptions);
|
|
528
552
|
}
|
|
529
|
-
await this.
|
|
553
|
+
await this.spawnPassthrough(spawnOptions).success;
|
|
530
554
|
}
|
|
531
555
|
};
|
|
532
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 (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 (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",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"@biomejs/biome": "^2.4.8",
|
|
27
27
|
"@cubing/dev-config": ">=0.9.4",
|
|
28
28
|
"@lgarron-bin/repo": "^0.14.5",
|
|
29
|
-
"@types/bun": "^1.3.
|
|
30
|
-
"@types/node": "^25.
|
|
31
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
29
|
+
"@types/bun": "^1.3.12",
|
|
30
|
+
"@types/node": "^25.6.0",
|
|
31
|
+
"@typescript/native-preview": "^7.0.0-dev.20260413.1",
|
|
32
32
|
"bun-dx": "^0.1.4",
|
|
33
33
|
"clipboardy": "^5.0.2",
|
|
34
34
|
"esbuild": "^0.27.2",
|
|
@@ -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,49 +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
466
|
(cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
447
|
-
new Response(Readable.from(this.#generator(s.stdout, s
|
|
467
|
+
new Response(Readable.from(this.#generator(s.stdout, s))),
|
|
448
468
|
));
|
|
449
469
|
s.stdout.text = wrapHandleTrailingNewlinesForResponder(s.stdout);
|
|
450
470
|
const thisCached = this; // TODO: make this type-check using `.bind(…)`
|
|
451
471
|
s.stdout.text0 = async function* () {
|
|
452
|
-
yield* thisCached.#split0(thisCached.#generator(s.stdout, s
|
|
472
|
+
yield* thisCached.#split0(thisCached.#generator(s.stdout, s));
|
|
453
473
|
};
|
|
454
474
|
s.stdout.json = <T>() => s.stdout.response().json() as Promise<T>;
|
|
455
475
|
}
|
|
@@ -457,16 +477,16 @@ export class PrintableShellCommand {
|
|
|
457
477
|
// TODO: dedupe
|
|
458
478
|
const s = subprocess as unknown as Readable &
|
|
459
479
|
WithStderrResponse &
|
|
460
|
-
|
|
480
|
+
WithExitPromises;
|
|
461
481
|
let cachedResponse: Response | undefined;
|
|
462
482
|
s.stderr.response = () =>
|
|
463
483
|
(cachedResponse ??= wrapHandleTrailingNewlinesForResponse(
|
|
464
|
-
new Response(Readable.from(this.#generator(s.stderr, s
|
|
484
|
+
new Response(Readable.from(this.#generator(s.stderr, s))),
|
|
465
485
|
));
|
|
466
486
|
s.stderr.text = wrapHandleTrailingNewlinesForResponder(s.stderr);
|
|
467
487
|
const thisCached = this; // TODO: make this type-check using `.bind(…)`
|
|
468
488
|
s.stderr.text0 = async function* () {
|
|
469
|
-
yield* thisCached.#split0(thisCached.#generator(s.stderr, s
|
|
489
|
+
yield* thisCached.#split0(thisCached.#generator(s.stderr, s));
|
|
470
490
|
};
|
|
471
491
|
s.stderr.json = <T>() => s.stderr.response().json() as Promise<T>;
|
|
472
492
|
}
|
|
@@ -503,9 +523,9 @@ export class PrintableShellCommand {
|
|
|
503
523
|
* then it acts "transparent" and allows user to interact with the subprocess
|
|
504
524
|
* in its stead.
|
|
505
525
|
*/
|
|
506
|
-
public
|
|
526
|
+
public spawnPassthrough(
|
|
507
527
|
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">>,
|
|
508
|
-
): ChildProcessByStdio<null, null, null> &
|
|
528
|
+
): ChildProcessByStdio<null, null, null> & WithExitPromises {
|
|
509
529
|
if (options && "stdio" in options) {
|
|
510
530
|
throw new Error("Unexpected `stdio` field.");
|
|
511
531
|
}
|
|
@@ -514,6 +534,12 @@ export class PrintableShellCommand {
|
|
|
514
534
|
return this.spawn({ ...options, stdio: "inherit" }) as any;
|
|
515
535
|
}
|
|
516
536
|
|
|
537
|
+
/** @deprecated Use `.spawnPassthrough(…)` instead. */
|
|
538
|
+
spawnTransparently = (
|
|
539
|
+
...args: Parameters<PrintableShellCommand["spawnPassthrough"]>
|
|
540
|
+
): ReturnType<PrintableShellCommand["spawnPassthrough"]> =>
|
|
541
|
+
this.spawnPassthrough(...args);
|
|
542
|
+
|
|
517
543
|
/**
|
|
518
544
|
* A wrapper for {@link PrintableShellCommand.spawn | `.spawn(…)`} that:
|
|
519
545
|
*
|
|
@@ -545,7 +571,8 @@ export class PrintableShellCommand {
|
|
|
545
571
|
|
|
546
572
|
#generator(
|
|
547
573
|
readable: Readable,
|
|
548
|
-
|
|
574
|
+
exiter: WithExitPromises,
|
|
575
|
+
options?: AllowFailureOptions,
|
|
549
576
|
): AsyncGenerator<string> {
|
|
550
577
|
// TODO: we'd make this a `ReadableStream`, but `ReadableStream.from(…)` is
|
|
551
578
|
// not implemented in `bun`: https://github.com/oven-sh/bun/issues/3700
|
|
@@ -553,12 +580,17 @@ export class PrintableShellCommand {
|
|
|
553
580
|
for await (const chunk of readable) {
|
|
554
581
|
yield chunk;
|
|
555
582
|
}
|
|
556
|
-
|
|
583
|
+
if (options?.allowFailure) {
|
|
584
|
+
await exiter.exited;
|
|
585
|
+
} else {
|
|
586
|
+
await exiter.success;
|
|
587
|
+
}
|
|
557
588
|
})();
|
|
558
589
|
}
|
|
559
590
|
|
|
560
591
|
#stdoutSpawnGenerator(
|
|
561
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
592
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
593
|
+
AllowFailureOptions,
|
|
562
594
|
): AsyncGenerator<string> {
|
|
563
595
|
if (options && "stdio" in options) {
|
|
564
596
|
throw new Error("Unexpected `stdio` field.");
|
|
@@ -567,11 +599,12 @@ export class PrintableShellCommand {
|
|
|
567
599
|
...options,
|
|
568
600
|
stdio: ["ignore", "pipe", "inherit"],
|
|
569
601
|
});
|
|
570
|
-
return this.#generator(subprocess.stdout, subprocess
|
|
602
|
+
return this.#generator(subprocess.stdout, subprocess, options);
|
|
571
603
|
}
|
|
572
604
|
|
|
573
605
|
public stdout(
|
|
574
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
606
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
607
|
+
AllowFailureOptions,
|
|
575
608
|
): Response & {
|
|
576
609
|
text: (options?: TrailingNewlineOptions) => Promise<string>;
|
|
577
610
|
} {
|
|
@@ -582,7 +615,8 @@ export class PrintableShellCommand {
|
|
|
582
615
|
}
|
|
583
616
|
|
|
584
617
|
#stderrSpawnGenerator(
|
|
585
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
618
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
619
|
+
AllowFailureOptions,
|
|
586
620
|
): AsyncGenerator<string> {
|
|
587
621
|
if (options && "stdio" in options) {
|
|
588
622
|
throw new Error("Unexpected `stdio` field.");
|
|
@@ -591,11 +625,12 @@ export class PrintableShellCommand {
|
|
|
591
625
|
...options,
|
|
592
626
|
stdio: ["ignore", "inherit", "pipe"],
|
|
593
627
|
});
|
|
594
|
-
return this.#generator(subprocess.stderr, subprocess
|
|
628
|
+
return this.#generator(subprocess.stderr, subprocess, options);
|
|
595
629
|
}
|
|
596
630
|
|
|
597
631
|
public stderr(
|
|
598
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
632
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
633
|
+
AllowFailureOptions,
|
|
599
634
|
): Response & {
|
|
600
635
|
text: (options?: TrailingNewlineOptions) => Promise<string>;
|
|
601
636
|
} {
|
|
@@ -628,15 +663,15 @@ export class PrintableShellCommand {
|
|
|
628
663
|
* This can make some simple invocations easier to read and/or fit on a single line.
|
|
629
664
|
*/
|
|
630
665
|
public async text(
|
|
631
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
632
|
-
|
|
633
|
-
|
|
666
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
667
|
+
TrailingNewlineOptions &
|
|
668
|
+
AllowFailureOptions,
|
|
634
669
|
): Promise<string> {
|
|
635
670
|
const {
|
|
636
671
|
trimTrailingNewlines: trimTrailingNewlinesOption,
|
|
637
|
-
...
|
|
672
|
+
...stdoutOptions
|
|
638
673
|
} = options ?? {};
|
|
639
|
-
return handleTrailingNewlines(this.stdout(
|
|
674
|
+
return handleTrailingNewlines(this.stdout(stdoutOptions).text(), {
|
|
640
675
|
trimTrailingNewlines: trimTrailingNewlinesOption,
|
|
641
676
|
});
|
|
642
677
|
}
|
|
@@ -649,7 +684,8 @@ export class PrintableShellCommand {
|
|
|
649
684
|
* This can make some simple invocations easier to read and/or fit on a single line.
|
|
650
685
|
*/
|
|
651
686
|
public json<T>(
|
|
652
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
687
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
688
|
+
AllowFailureOptions,
|
|
653
689
|
): Promise<T> {
|
|
654
690
|
return this.stdout(options).json() as Promise<T>;
|
|
655
691
|
}
|
|
@@ -660,7 +696,8 @@ export class PrintableShellCommand {
|
|
|
660
696
|
* A trailing NULL delimiter from `stdout` is required and removed.
|
|
661
697
|
*/
|
|
662
698
|
public async *text0(
|
|
663
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
699
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
700
|
+
AllowFailureOptions,
|
|
664
701
|
): AsyncGenerator<string> {
|
|
665
702
|
yield* this.#split0(this.#stdoutSpawnGenerator(options));
|
|
666
703
|
}
|
|
@@ -671,7 +708,8 @@ export class PrintableShellCommand {
|
|
|
671
708
|
* A trailing NULL delimiter from `stdout` is required and removed.
|
|
672
709
|
*/
|
|
673
710
|
public async *json0(
|
|
674
|
-
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio"
|
|
711
|
+
options?: NodeWithCwd<Omit<NodeSpawnOptions, "stdio">> &
|
|
712
|
+
AllowFailureOptions,
|
|
675
713
|
): // biome-ignore lint/suspicious/noExplicitAny: `any` is the correct type for JSON
|
|
676
714
|
AsyncGenerator<any> {
|
|
677
715
|
for await (const part of this.#split0(
|
|
@@ -704,7 +742,7 @@ export class PrintableShellCommand {
|
|
|
704
742
|
} else {
|
|
705
743
|
this.print(printOptions);
|
|
706
744
|
}
|
|
707
|
-
await this.
|
|
745
|
+
await this.spawnPassthrough(spawnOptions).success;
|
|
708
746
|
}
|
|
709
747
|
}
|
|
710
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;
|