@shell-shock/core 0.15.2 → 0.16.1

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.
Files changed (99) hide show
  1. package/dist/api.cjs +10 -7
  2. package/dist/api.cjs.map +1 -1
  3. package/dist/api.d.cts +1 -1
  4. package/dist/api.d.cts.map +1 -1
  5. package/dist/api.d.mts +1 -1
  6. package/dist/api.d.mts.map +1 -1
  7. package/dist/api.mjs +11 -8
  8. package/dist/api.mjs.map +1 -1
  9. package/dist/components/helpers.cjs +1 -1
  10. package/dist/components/helpers.cjs.map +1 -1
  11. package/dist/components/helpers.mjs +1 -1
  12. package/dist/components/helpers.mjs.map +1 -1
  13. package/dist/components/index.cjs +8 -4
  14. package/dist/components/index.d.cts +4 -2
  15. package/dist/components/index.d.mts +4 -2
  16. package/dist/components/index.mjs +4 -2
  17. package/dist/components/options-parser-logic.cjs +68 -48
  18. package/dist/components/options-parser-logic.cjs.map +1 -1
  19. package/dist/components/options-parser-logic.d.cts.map +1 -1
  20. package/dist/components/options-parser-logic.d.mts.map +1 -1
  21. package/dist/components/options-parser-logic.mjs +68 -48
  22. package/dist/components/options-parser-logic.mjs.map +1 -1
  23. package/dist/components/spawn-builtin.cjs +656 -0
  24. package/dist/components/spawn-builtin.cjs.map +1 -0
  25. package/dist/components/spawn-builtin.d.cts +12 -0
  26. package/dist/components/spawn-builtin.d.cts.map +1 -0
  27. package/dist/components/spawn-builtin.d.mts +12 -0
  28. package/dist/components/spawn-builtin.d.mts.map +1 -0
  29. package/dist/components/spawn-builtin.mjs +653 -0
  30. package/dist/components/spawn-builtin.mjs.map +1 -0
  31. package/dist/components/state-builtin.cjs +553 -0
  32. package/dist/components/state-builtin.cjs.map +1 -0
  33. package/dist/components/state-builtin.d.cts +18 -0
  34. package/dist/components/state-builtin.d.cts.map +1 -0
  35. package/dist/components/state-builtin.d.mts +18 -0
  36. package/dist/components/state-builtin.d.mts.map +1 -0
  37. package/dist/components/state-builtin.mjs +547 -0
  38. package/dist/components/state-builtin.mjs.map +1 -0
  39. package/dist/components/utils-builtin.cjs +3 -499
  40. package/dist/components/utils-builtin.cjs.map +1 -1
  41. package/dist/components/utils-builtin.d.cts +1 -10
  42. package/dist/components/utils-builtin.d.cts.map +1 -1
  43. package/dist/components/utils-builtin.d.mts +1 -10
  44. package/dist/components/utils-builtin.d.mts.map +1 -1
  45. package/dist/components/utils-builtin.mjs +5 -498
  46. package/dist/components/utils-builtin.mjs.map +1 -1
  47. package/dist/config.cjs.map +1 -1
  48. package/dist/config.mjs.map +1 -1
  49. package/dist/contexts/options.cjs +9 -9
  50. package/dist/contexts/options.cjs.map +1 -1
  51. package/dist/contexts/options.d.cts +2 -2
  52. package/dist/contexts/options.d.cts.map +1 -1
  53. package/dist/contexts/options.d.mts +2 -2
  54. package/dist/contexts/options.d.mts.map +1 -1
  55. package/dist/contexts/options.mjs +9 -9
  56. package/dist/contexts/options.mjs.map +1 -1
  57. package/dist/index.cjs +2 -10
  58. package/dist/index.d.cts +1 -2
  59. package/dist/index.d.mts +1 -2
  60. package/dist/index.mjs +1 -7
  61. package/dist/plugin.cjs +11 -26
  62. package/dist/plugin.cjs.map +1 -1
  63. package/dist/plugin.d.cts +1 -1
  64. package/dist/plugin.d.cts.map +1 -1
  65. package/dist/plugin.d.mts +1 -1
  66. package/dist/plugin.d.mts.map +1 -1
  67. package/dist/plugin.mjs +10 -24
  68. package/dist/plugin.mjs.map +1 -1
  69. package/dist/types/config.cjs +3 -1
  70. package/dist/types/config.cjs.map +1 -1
  71. package/dist/types/config.d.cts +1 -1
  72. package/dist/types/config.d.cts.map +1 -1
  73. package/dist/types/config.d.mts +1 -1
  74. package/dist/types/config.d.mts.map +1 -1
  75. package/dist/types/config.mjs +3 -1
  76. package/dist/types/config.mjs.map +1 -1
  77. package/dist/types/env.cjs +2 -1
  78. package/dist/types/env.cjs.map +1 -1
  79. package/dist/types/env.d.cts +15 -0
  80. package/dist/types/env.d.cts.map +1 -1
  81. package/dist/types/env.d.mts +15 -0
  82. package/dist/types/env.d.mts.map +1 -1
  83. package/dist/types/env.mjs +2 -1
  84. package/dist/types/env.mjs.map +1 -1
  85. package/dist/types/index.cjs +0 -2
  86. package/dist/types/index.d.cts +1 -2
  87. package/dist/types/index.d.mts +1 -2
  88. package/dist/types/index.mjs +1 -2
  89. package/package.json +50 -36
  90. package/dist/index.cjs.map +0 -1
  91. package/dist/index.mjs.map +0 -1
  92. package/dist/types/runtime.cjs +0 -13
  93. package/dist/types/runtime.cjs.map +0 -1
  94. package/dist/types/runtime.d.cts +0 -14
  95. package/dist/types/runtime.d.cts.map +0 -1
  96. package/dist/types/runtime.d.mts +0 -14
  97. package/dist/types/runtime.d.mts.map +0 -1
  98. package/dist/types/runtime.mjs +0 -11
  99. package/dist/types/runtime.mjs.map +0 -1
@@ -0,0 +1,653 @@
1
+ import { createComponent, mergeProps } from "@alloy-js/core/jsx-runtime";
2
+ import defu$1 from "defu";
3
+ import { Show, code, splitProps } from "@alloy-js/core";
4
+ import { Spacing } from "@powerlines/plugin-alloy/core/components/spacing";
5
+ import { FunctionDeclaration, InterfaceDeclaration, InterfaceMember, VarDeclaration } from "@alloy-js/typescript";
6
+ import { ReflectionKind } from "@powerlines/deepkit/vendor/type";
7
+ import { BuiltinFile } from "@powerlines/plugin-alloy/typescript/components/builtin-file";
8
+ import { TSDoc, TSDocDefaultValue, TSDocParam, TSDocReturns } from "@powerlines/plugin-alloy/typescript/components/tsdoc";
9
+
10
+ //#region src/components/spawn-builtin.tsx
11
+ /**
12
+ * A built-in module for handling child process spawning in Shell Shock.
13
+ */
14
+ function SpawnBuiltin(props) {
15
+ const [{ children }, rest] = splitProps(props, ["children"]);
16
+ return createComponent(BuiltinFile, mergeProps({
17
+ id: "spawn",
18
+ description: "A module to handle spawning child processes."
19
+ }, rest, {
20
+ get imports() {
21
+ return defu$1(rest.imports ?? {}, {
22
+ "node:path": [
23
+ "basename",
24
+ "extname",
25
+ "dirname",
26
+ "join"
27
+ ],
28
+ "node:fs": ["existsSync"],
29
+ "node:child_process": [{
30
+ name: "spawn",
31
+ alias: "_spawn"
32
+ }],
33
+ "node:stream": [{
34
+ name: "Stream",
35
+ default: true,
36
+ type: true
37
+ }]
38
+ });
39
+ },
40
+ get builtinImports() {
41
+ return defu$1(rest.builtinImports ?? {}, { env: ["isWindows"] });
42
+ },
43
+ get children() {
44
+ return [
45
+ createComponent(FunctionDeclaration, {
46
+ name: "resolveCommandEnv",
47
+ parameters: [{
48
+ name: "params",
49
+ type: "{ argv: string[]; env?: NodeJS.ProcessEnv; baseEnv?: NodeJS.ProcessEnv; }"
50
+ }],
51
+ returnType: "NodeJS.ProcessEnv",
52
+ children: code`const baseEnv = params.baseEnv ?? process.env;
53
+ const argv = params.argv;
54
+ const shouldSuppressNpmFund = (() => {
55
+ const cmd = basename(argv[0] ?? "");
56
+ if (cmd === "npm" || cmd === "npm.cmd" || cmd === "npm.exe") {
57
+ return true;
58
+ }
59
+ if (cmd === "node" || cmd === "node.exe") {
60
+ const script = argv[1] ?? "";
61
+
62
+ return script.includes("npm-cli.js");
63
+ }
64
+ return false;
65
+ })();
66
+
67
+ const mergedEnv = params.env ? { ...baseEnv, ...params.env } : { ...baseEnv };
68
+ const resolvedEnv = Object.fromEntries(
69
+ Object.entries(mergedEnv)
70
+ .filter(([, value]) => value !== undefined)
71
+ .map(([key, value]) => [key, String(value)])
72
+ );
73
+ if (shouldSuppressNpmFund) {
74
+ resolvedEnv.NPM_CONFIG_FUND ??= "false";
75
+ resolvedEnv.npm_config_fund ??= "false";
76
+ }
77
+ return resolvedEnv;`
78
+ }),
79
+ createComponent(Spacing, {}),
80
+ createComponent(FunctionDeclaration, {
81
+ name: "isWindowsBatchCommand",
82
+ parameters: [{
83
+ name: "resolvedCommand",
84
+ type: "string"
85
+ }],
86
+ returnType: "boolean",
87
+ children: code`if (!isWindows) {
88
+ return false;
89
+ }
90
+ const ext = extname(resolvedCommand).toLowerCase();
91
+
92
+ return ext === ".cmd" || ext === ".bat";`
93
+ }),
94
+ createComponent(Spacing, {}),
95
+ createComponent(FunctionDeclaration, {
96
+ name: "escapeForCmdExe",
97
+ parameters: [{
98
+ name: "arg",
99
+ type: "string"
100
+ }],
101
+ returnType: "string",
102
+ children: code`if (/[&|<>^%\\\\r\\\\n]/.test(arg)) {
103
+ throw new Error(
104
+ \`Unsafe Windows cmd.exe argument detected: \${JSON.stringify(arg)}. \` +
105
+ "Pass an explicit shell-wrapper argv at the call site instead."
106
+ );
107
+ }
108
+ if (!arg.includes(" ") && !arg.includes('"')) {
109
+ return arg;
110
+ }
111
+ return \`"\${arg.replace(/"/g, '""')}"\`;`
112
+ }),
113
+ createComponent(Spacing, {}),
114
+ createComponent(FunctionDeclaration, {
115
+ name: "buildCmdExeCommandLine",
116
+ parameters: [{
117
+ name: "resolvedCommand",
118
+ type: "string"
119
+ }, {
120
+ name: "args",
121
+ type: "string[]"
122
+ }],
123
+ returnType: "string",
124
+ children: code`return [escapeForCmdExe(resolvedCommand), ...args.map(escapeForCmdExe)].join(
125
+ " "
126
+ );`
127
+ }),
128
+ createComponent(Spacing, {}),
129
+ createComponent(FunctionDeclaration, {
130
+ name: "resolveNpmArgvForWindows",
131
+ doc: "On Windows, Node 18.20.2+ (CVE-2024-27980) rejects spawning .cmd/.bat directly without shell, causing EINVAL. Resolve npm/npx to node + cli script so we spawn node.exe instead of npm.cmd.",
132
+ parameters: [{
133
+ name: "argv",
134
+ type: "string[]"
135
+ }],
136
+ returnType: "string[] | null",
137
+ children: code`if (!isWindows || argv.length === 0) {
138
+ return null;
139
+ }
140
+ const base = basename(argv[0] ?? "")
141
+ .toLowerCase()
142
+ .replace(/\.(?:cmd|exe|bat)$/, "");
143
+ const cliName =
144
+ base === "npx" ? "npx-cli.js" : base === "npm" ? "npm-cli.js" : null;
145
+ if (!cliName) {
146
+ return null;
147
+ }
148
+ const nodeDir = dirname(process.execPath);
149
+ const cliPath = join(nodeDir, "node_modules", "npm", "bin", cliName);
150
+ if (!existsSync(cliPath)) {
151
+ const command = argv[0] ?? "";
152
+ const ext = extname(command).toLowerCase();
153
+ const shimmedCommand = ext ? command : \`\${command}.cmd\`;
154
+
155
+ return [shimmedCommand, ...argv.slice(1)];
156
+ }
157
+ return [process.execPath, cliPath, ...argv.slice(1)];`
158
+ }),
159
+ createComponent(Spacing, {}),
160
+ createComponent(FunctionDeclaration, {
161
+ name: "resolveCommand",
162
+ doc: "Resolves a command for Windows compatibility. On Windows, non-.exe commands (like pnpm, yarn) are resolved to .cmd; npm/npx are handled by resolveNpmArgvForWindows to avoid spawn EINVAL (no direct .cmd).",
163
+ parameters: [{
164
+ name: "command",
165
+ type: "string"
166
+ }],
167
+ returnType: "string",
168
+ children: code`if (!isWindows) {
169
+ return command;
170
+ }
171
+ const base = basename(command).toLowerCase();
172
+ if (extname(base)) {
173
+ return command;
174
+ }
175
+ if (["pnpm", "yarn"].includes(base)) {
176
+ return \`\${command}.cmd\`;
177
+ }
178
+ return command;`
179
+ }),
180
+ createComponent(Spacing, {}),
181
+ createComponent(FunctionDeclaration, {
182
+ name: "resolveCommandStdio",
183
+ parameters: [{
184
+ name: "params",
185
+ type: "{ hasInput: boolean; preferInherit: boolean; }"
186
+ }],
187
+ returnType: "[\"pipe\" | \"inherit\" | \"ignore\", \"pipe\", \"pipe\"]",
188
+ children: code`const stdin = params.hasInput
189
+ ? "pipe"
190
+ : params.preferInherit
191
+ ? "inherit"
192
+ : "pipe";
193
+
194
+ return [stdin, "pipe", "pipe"];`
195
+ }),
196
+ createComponent(Spacing, {}),
197
+ createComponent(FunctionDeclaration, {
198
+ name: "resolveChildProcessInvocation",
199
+ parameters: [{
200
+ name: "params",
201
+ type: "{ argv: string[]; windowsVerbatimArguments?: boolean; }"
202
+ }],
203
+ returnType: "{ args: string[]; command: string; usesWindowsExitCodeShim: boolean; windowsHide: true; windowsVerbatimArguments?: boolean; }",
204
+ children: code`const finalArgv =
205
+ isWindows
206
+ ? (resolveNpmArgvForWindows(params.argv) ?? params.argv)
207
+ : params.argv;
208
+ const resolvedCommand =
209
+ finalArgv !== params.argv
210
+ ? (finalArgv[0] ?? "")
211
+ : resolveCommand(params.argv[0] ?? "");
212
+ const useCmdWrapper = isWindowsBatchCommand(resolvedCommand);
213
+
214
+ return {
215
+ command: useCmdWrapper
216
+ ? (process.env.ComSpec ?? "cmd.exe")
217
+ : resolvedCommand,
218
+ args: useCmdWrapper
219
+ ? [
220
+ "/d",
221
+ "/s",
222
+ "/c",
223
+ buildCmdExeCommandLine(resolvedCommand, finalArgv.slice(1))
224
+ ]
225
+ : finalArgv.slice(1),
226
+ usesWindowsExitCodeShim:
227
+ isWindows &&
228
+ (useCmdWrapper || finalArgv !== params.argv),
229
+ windowsHide: true,
230
+ windowsVerbatimArguments: useCmdWrapper
231
+ ? true
232
+ : params.windowsVerbatimArguments
233
+ };`
234
+ }),
235
+ createComponent(Spacing, {}),
236
+ createComponent(FunctionDeclaration, {
237
+ name: "resolveProcessExitCode",
238
+ parameters: [{
239
+ name: "params",
240
+ type: "{ explicitCode: number | null | undefined; childExitCode: number | null | undefined; resolvedSignal: NodeJS.Signals | null; usesWindowsExitCodeShim: boolean; timedOut: boolean; noOutputTimedOut: boolean; killIssuedByTimeout: boolean; }"
241
+ }],
242
+ returnType: "number | null",
243
+ children: code`return (
244
+ params.explicitCode ??
245
+ params.childExitCode ??
246
+ (params.usesWindowsExitCodeShim &&
247
+ params.resolvedSignal == null &&
248
+ !params.timedOut &&
249
+ !params.noOutputTimedOut &&
250
+ !params.killIssuedByTimeout
251
+ ? 0
252
+ : null)
253
+ );`
254
+ }),
255
+ createComponent(Spacing, {}),
256
+ createComponent(FunctionDeclaration, {
257
+ name: "shouldSpawnWithShell",
258
+ parameters: [{
259
+ name: "params",
260
+ type: "{ resolvedCommand: string; platform: NodeJS.Platform; }"
261
+ }],
262
+ returnType: "boolean",
263
+ children: code`// SECURITY: never enable \`shell\` for argv-based execution.
264
+ // \`shell\` routes through cmd.exe on Windows, which turns untrusted argv values
265
+ // (like chat prompts passed as CLI args) into command-injection primitives.
266
+ // If you need a shell, use an explicit shell-wrapper argv (e.g. \`cmd.exe /c ...\`)
267
+ // and validate/escape at the call site.
268
+ void params;
269
+ return false;`
270
+ }),
271
+ createComponent(Spacing, {}),
272
+ createComponent(TSDoc, { heading: "The result of a spawn operation." }),
273
+ createComponent(InterfaceDeclaration, {
274
+ "export": true,
275
+ name: "SpawnResult",
276
+ get children() {
277
+ return [
278
+ createComponent(TSDoc, { heading: "The PID of the spawned child process, if available." }),
279
+ createComponent(InterfaceMember, {
280
+ name: "pid",
281
+ optional: true,
282
+ type: "number"
283
+ }),
284
+ createComponent(Spacing, {}),
285
+ createComponent(TSDoc, { heading: "The standard output produced by the child process." }),
286
+ createComponent(InterfaceMember, {
287
+ name: "stdout",
288
+ type: "string"
289
+ }),
290
+ createComponent(Spacing, {}),
291
+ createComponent(TSDoc, { heading: "The standard error produced by the child process." }),
292
+ createComponent(InterfaceMember, {
293
+ name: "stderr",
294
+ type: "string"
295
+ }),
296
+ createComponent(Spacing, {}),
297
+ createComponent(TSDoc, { heading: "The exit code of the child process, if available." }),
298
+ createComponent(InterfaceMember, {
299
+ name: "code",
300
+ type: "number | null"
301
+ }),
302
+ createComponent(Spacing, {}),
303
+ createComponent(TSDoc, { heading: "The signal that caused the child process to terminate, if it was killed by a signal." }),
304
+ createComponent(InterfaceMember, {
305
+ name: "signal",
306
+ type: "NodeJS.Signals | null"
307
+ }),
308
+ createComponent(Spacing, {}),
309
+ createComponent(TSDoc, { heading: "Whether the child process was killed." }),
310
+ createComponent(InterfaceMember, {
311
+ name: "killed",
312
+ type: "boolean"
313
+ }),
314
+ createComponent(Spacing, {}),
315
+ createComponent(TSDoc, { heading: "The reason for the child process termination." }),
316
+ createComponent(InterfaceMember, {
317
+ name: "termination",
318
+ type: code`"exit" | "timeout" | "no-output-timeout" | "signal"`
319
+ }),
320
+ createComponent(Spacing, {}),
321
+ createComponent(TSDoc, { heading: "Whether the child process timed out due to no output." }),
322
+ createComponent(InterfaceMember, {
323
+ name: "noOutputTimedOut",
324
+ optional: true,
325
+ type: "boolean"
326
+ })
327
+ ];
328
+ }
329
+ }),
330
+ createComponent(Spacing, {}),
331
+ createComponent(TSDoc, { heading: "Options for spawning a child process." }),
332
+ createComponent(InterfaceDeclaration, {
333
+ "export": true,
334
+ name: "SpawnOptions",
335
+ get children() {
336
+ return [
337
+ createComponent(TSDoc, {
338
+ heading: "The timeout in milliseconds for the spawn operation. If the process runs longer than this, it will be killed and the spawn promise will reject. This can also be provided as a number directly to the spawn function for convenience. Providing \\`-1\\` will disable the timeout.",
339
+ get children() {
340
+ return createComponent(TSDocDefaultValue, {
341
+ get type() {
342
+ return ReflectionKind.number;
343
+ },
344
+ defaultValue: "300000"
345
+ });
346
+ }
347
+ }),
348
+ createComponent(InterfaceMember, {
349
+ name: "timeoutMs",
350
+ type: "number"
351
+ }),
352
+ createComponent(Spacing, {}),
353
+ createComponent(TSDoc, { heading: "The current working directory of the child process." }),
354
+ createComponent(InterfaceMember, {
355
+ name: "cwd",
356
+ optional: true,
357
+ type: "string"
358
+ }),
359
+ createComponent(Spacing, {}),
360
+ createComponent(TSDoc, { heading: "The input to be passed to the child process." }),
361
+ createComponent(InterfaceMember, {
362
+ name: "input",
363
+ optional: true,
364
+ type: "string"
365
+ }),
366
+ createComponent(Spacing, {}),
367
+ createComponent(TSDoc, { heading: "The environment variables for the child process." }),
368
+ createComponent(InterfaceMember, {
369
+ name: "env",
370
+ optional: true,
371
+ type: "NodeJS.ProcessEnv"
372
+ }),
373
+ createComponent(Spacing, {}),
374
+ createComponent(TSDoc, { heading: "Whether to pass arguments to the child process verbatim on Windows." }),
375
+ createComponent(InterfaceMember, {
376
+ name: "windowsVerbatimArguments",
377
+ optional: true,
378
+ type: "boolean"
379
+ }),
380
+ createComponent(Spacing, {}),
381
+ createComponent(TSDoc, { heading: "The timeout in milliseconds for the child process to produce output on stdout or stderr. If the process produces no output for this duration, it will be killed and the spawn promise will reject with a no-output-timeout termination reason." }),
382
+ createComponent(InterfaceMember, {
383
+ name: "noOutputTimeoutMs",
384
+ optional: true,
385
+ type: "number"
386
+ })
387
+ ];
388
+ }
389
+ }),
390
+ createComponent(Spacing, {}),
391
+ createComponent(VarDeclaration, {
392
+ "const": true,
393
+ name: "WINDOWS_CLOSE_STATE_SETTLE_TIMEOUT_MS",
394
+ initializer: code`250`
395
+ }),
396
+ createComponent(Spacing, {}),
397
+ createComponent(VarDeclaration, {
398
+ "const": true,
399
+ name: "WINDOWS_CLOSE_STATE_POLL_MS",
400
+ initializer: code`10`
401
+ }),
402
+ createComponent(Spacing, {}),
403
+ createComponent(TSDoc, {
404
+ heading: "Spawns a child process with the given arguments and options, returning a promise that resolves with the result of the spawn operation.",
405
+ get children() {
406
+ return [
407
+ createComponent(TSDocParam, {
408
+ name: "argv",
409
+ children: "The command and its arguments to spawn."
410
+ }),
411
+ createComponent(TSDocParam, {
412
+ name: "optionsOrTimeoutMs",
413
+ children: `The options for spawning the command, or a number representing the timeout in milliseconds. This allows for a convenient shorthand when only a timeout is needed. Providing \`-1\` will disable the timeout. If no options or timeout are provided, a default timeout of 5 minutes will be used.`
414
+ }),
415
+ createComponent(TSDocReturns, { children: "A promise that resolves with the result of the spawn operation, including stdout, stderr, exit code, signal, and termination reason." })
416
+ ];
417
+ }
418
+ }),
419
+ createComponent(FunctionDeclaration, {
420
+ "export": true,
421
+ async: true,
422
+ name: "spawn",
423
+ parameters: [{
424
+ name: "argv",
425
+ type: "string[]"
426
+ }, {
427
+ name: "optionsOrTimeoutMs",
428
+ type: "number | SpawnOptions",
429
+ default: "300000"
430
+ }],
431
+ returnType: "Promise<SpawnResult>",
432
+ children: code`const options: SpawnOptions =
433
+ typeof optionsOrTimeoutMs === "number"
434
+ ? { timeoutMs: optionsOrTimeoutMs }
435
+ : optionsOrTimeoutMs;
436
+ const { timeoutMs, cwd, input, env, noOutputTimeoutMs } = options;
437
+ const hasInput = input !== undefined;
438
+ const resolvedEnv = resolveCommandEnv({ argv, env });
439
+ const stdio = resolveCommandStdio({ hasInput, preferInherit: true });
440
+ const invocation = resolveChildProcessInvocation({
441
+ argv,
442
+ windowsVerbatimArguments: options.windowsVerbatimArguments
443
+ });
444
+
445
+ const child = _spawn(invocation.command, invocation.args, {
446
+ stdio,
447
+ cwd,
448
+ env: resolvedEnv,
449
+ windowsHide: invocation.windowsHide,
450
+ windowsVerbatimArguments: invocation.windowsVerbatimArguments,
451
+ ...(shouldSpawnWithShell({
452
+ resolvedCommand: invocation.command,
453
+ platform: process.platform
454
+ })
455
+ ? { shell: true }
456
+ : {})
457
+ });
458
+
459
+ return new Promise((resolve, reject) => {
460
+ let stdout = "";
461
+ let stderr = "";
462
+ let settled = false;
463
+ let timedOut = false;
464
+ let noOutputTimedOut = false;
465
+ let killIssuedByTimeout = false;
466
+ let childExitState: {
467
+ code: number | null;
468
+ signal: NodeJS.Signals | null;
469
+ } | null = null;
470
+ let closeFallbackTimer: NodeJS.Timeout | null = null;
471
+ let noOutputTimer: NodeJS.Timeout | null = null;
472
+ const shouldTrackOutputTimeout =
473
+ typeof noOutputTimeoutMs === "number" &&
474
+ Number.isFinite(noOutputTimeoutMs) &&
475
+ noOutputTimeoutMs > 0;
476
+
477
+ const clearNoOutputTimer = () => {
478
+ if (!noOutputTimer) {
479
+ return;
480
+ }
481
+ clearTimeout(noOutputTimer);
482
+ noOutputTimer = null;
483
+ };
484
+
485
+ const clearCloseFallbackTimer = () => {
486
+ if (!closeFallbackTimer) {
487
+ return;
488
+ }
489
+ clearTimeout(closeFallbackTimer);
490
+ closeFallbackTimer = null;
491
+ };
492
+
493
+ const killChild = () => {
494
+ if (settled || typeof child?.kill !== "function") {
495
+ return;
496
+ }
497
+ killIssuedByTimeout = true;
498
+ child.kill("SIGKILL");
499
+ };
500
+
501
+ const armNoOutputTimer = () => {
502
+ if (!shouldTrackOutputTimeout || settled) {
503
+ return;
504
+ }
505
+ clearNoOutputTimer();
506
+ noOutputTimer = setTimeout(() => {
507
+ if (settled) {
508
+ return;
509
+ }
510
+ noOutputTimedOut = true;
511
+ killChild();
512
+ }, Math.floor(noOutputTimeoutMs));
513
+ };
514
+
515
+ const timer = setTimeout(() => {
516
+ timedOut = true;
517
+ killChild();
518
+ }, timeoutMs >= 0 ? timeoutMs : Number.POSITIVE_INFINITY);
519
+ armNoOutputTimer();
520
+
521
+ if (hasInput && child.stdin) {
522
+ child.stdin.write(input ?? "");
523
+ child.stdin.end();
524
+ }
525
+
526
+ child.stdout?.on("data", (d: Stream) => {
527
+ stdout += d.toString();
528
+ armNoOutputTimer();
529
+ });
530
+ child.stderr?.on("data", (d: Stream) => {
531
+ stderr += d.toString();
532
+ armNoOutputTimer();
533
+ });
534
+ child.on("error", err => {
535
+ if (settled) {
536
+ return;
537
+ }
538
+ settled = true;
539
+ clearTimeout(timer);
540
+ clearNoOutputTimer();
541
+ clearCloseFallbackTimer();
542
+ reject(err);
543
+ });
544
+ child.on("exit", (code, signal) => {
545
+ childExitState = { code, signal };
546
+ if (settled || closeFallbackTimer) {
547
+ return;
548
+ }
549
+ closeFallbackTimer = setTimeout(() => {
550
+ if (settled) {
551
+ return;
552
+ }
553
+ child.stdout?.destroy();
554
+ child.stderr?.destroy();
555
+ }, 250);
556
+ });
557
+ const resolveFromClose = (
558
+ code: number | null,
559
+ signal: NodeJS.Signals | null
560
+ ) => {
561
+ if (settled) {
562
+ return;
563
+ }
564
+ settled = true;
565
+ clearTimeout(timer);
566
+ clearNoOutputTimer();
567
+ clearCloseFallbackTimer();
568
+ const resolvedSignal =
569
+ childExitState?.signal ?? signal ?? child.signalCode ?? null;
570
+ const resolvedCode = resolveProcessExitCode({
571
+ explicitCode: childExitState?.code ?? code,
572
+ childExitCode: child.exitCode,
573
+ resolvedSignal,
574
+ usesWindowsExitCodeShim: invocation.usesWindowsExitCodeShim,
575
+ timedOut,
576
+ noOutputTimedOut,
577
+ killIssuedByTimeout
578
+ });
579
+ const termination = noOutputTimedOut
580
+ ? "no-output-timeout"
581
+ : timedOut
582
+ ? "timeout"
583
+ : resolvedSignal != null
584
+ ? "signal"
585
+ : "exit";
586
+ const normalizedCode =
587
+ termination === "timeout" || termination === "no-output-timeout"
588
+ ? resolvedCode === 0
589
+ ? 124
590
+ : resolvedCode
591
+ : resolvedCode;
592
+ resolve({
593
+ pid: child.pid ?? undefined,
594
+ stdout,
595
+ stderr,
596
+ code: normalizedCode,
597
+ signal: resolvedSignal,
598
+ killed: child.killed,
599
+ termination,
600
+ noOutputTimedOut
601
+ });
602
+ };
603
+ child.on("close", (code, signal) => {
604
+ if (
605
+ !isWindows ||
606
+ childExitState != null ||
607
+ code != null ||
608
+ signal != null ||
609
+ child.exitCode != null ||
610
+ child.signalCode != null
611
+ ) {
612
+ resolveFromClose(code, signal);
613
+ return;
614
+ }
615
+
616
+ const startedAt = Date.now();
617
+ const waitForExitState = () => {
618
+ if (settled) {
619
+ return;
620
+ }
621
+ if (
622
+ childExitState != null ||
623
+ child.exitCode != null ||
624
+ child.signalCode != null
625
+ ) {
626
+ resolveFromClose(code, signal);
627
+ return;
628
+ }
629
+ if (Date.now() - startedAt >= WINDOWS_CLOSE_STATE_SETTLE_TIMEOUT_MS) {
630
+ resolveFromClose(code, signal);
631
+ return;
632
+ }
633
+ setTimeout(waitForExitState, WINDOWS_CLOSE_STATE_POLL_MS);
634
+ };
635
+ waitForExitState();
636
+ });
637
+ });`
638
+ }),
639
+ createComponent(Spacing, {}),
640
+ createComponent(Show, {
641
+ get when() {
642
+ return Boolean(children);
643
+ },
644
+ children
645
+ })
646
+ ];
647
+ }
648
+ }));
649
+ }
650
+
651
+ //#endregion
652
+ export { SpawnBuiltin };
653
+ //# sourceMappingURL=spawn-builtin.mjs.map