@orkestrel/process 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -17
- package/dist/src/core/index.cjs +32 -6
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +228 -160
- package/dist/src/core/index.d.ts +228 -160
- package/dist/src/core/index.js +32 -7
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +660 -383
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +287 -136
- package/dist/src/server/index.d.ts +287 -136
- package/dist/src/server/index.js +654 -382
- package/dist/src/server/index.js.map +1 -1
- package/package.json +25 -13
|
@@ -2,7 +2,13 @@ import { Buffer as Buffer_2 } from 'node:buffer';
|
|
|
2
2
|
import { DetachOptions } from '@orkestrel/process';
|
|
3
3
|
import { EmitterInterface } from '@orkestrel/emitter';
|
|
4
4
|
import { ExecutableOptions } from '@orkestrel/process';
|
|
5
|
+
import { ExecuteInput } from '@orkestrel/process';
|
|
6
|
+
import { ExecuteOptions } from '@orkestrel/process';
|
|
7
|
+
import { ExecuteResult } from '@orkestrel/process';
|
|
8
|
+
import { ExecuteResult as ExecuteResult_2 } from '@orkestrel/process';
|
|
9
|
+
import { ExecuteSyncOptions } from '@orkestrel/process';
|
|
5
10
|
import { ProcessCommand } from '@orkestrel/process';
|
|
11
|
+
import { ProcessCommand as ProcessCommand_2 } from '@orkestrel/process';
|
|
6
12
|
import { ProcessEventMap } from '@orkestrel/process';
|
|
7
13
|
import { ProcessExit } from '@orkestrel/process';
|
|
8
14
|
import { ProcessInterface } from '@orkestrel/process';
|
|
@@ -10,19 +16,43 @@ import { ProcessManagerEventMap } from '@orkestrel/process';
|
|
|
10
16
|
import { ProcessManagerInterface } from '@orkestrel/process';
|
|
11
17
|
import { ProcessManagerOptions } from '@orkestrel/process';
|
|
12
18
|
import { ProcessOptions } from '@orkestrel/process';
|
|
13
|
-
import { RunInput } from '@orkestrel/process';
|
|
14
|
-
import { RunOptions } from '@orkestrel/process';
|
|
15
|
-
import { RunResult } from '@orkestrel/process';
|
|
16
|
-
import { RunSyncOptions } from '@orkestrel/process';
|
|
17
19
|
import { SpawnInput } from '@orkestrel/process';
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
|
-
* Builds
|
|
22
|
+
* Builds the executable candidates an explicit platform would search.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* Windows alone needs this list: the host searches the working directory before `PATH` and applies
|
|
26
|
+
* `PATHEXT`, and Node reproduces neither for a direct spawn. Within each searched directory the
|
|
27
|
+
* literal name is tried first and each `PATHEXT` candidate after it, whether or not the name already
|
|
28
|
+
* carries an extension — so `report.txt` resolves to a `report.txt` file where one exists and to
|
|
29
|
+
* `report.txt.cmd` where none does. The lookup reads the child's effective environment, so an
|
|
30
|
+
* overridden `PATH` selects the executable the child would have found. A POSIX host resolves the
|
|
31
|
+
* file itself, so the candidate list there is empty. An appended extension is spelled the way
|
|
32
|
+
* `PATHEXT` spells it rather than the way the directory entry does, which the case-insensitive host
|
|
33
|
+
* treats as the same file. A non-Windows platform returns an empty list because `execvp` performs
|
|
34
|
+
* its own lookup.
|
|
35
|
+
*
|
|
36
|
+
* @param file - The command executable name or path
|
|
37
|
+
* @param workspace - The directory searched first
|
|
38
|
+
* @param environment - The child's effective environment
|
|
39
|
+
* @param platform - The platform whose lookup rules apply
|
|
40
|
+
* @returns The ordered absolute candidate paths
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* buildExecutableCandidates('git', 'C:\\work', { PATH: 'C:\\bin' }, 'win32')
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildExecutableCandidates(file: string, workspace: string, environment: Readonly<Record<string, string | undefined>>, platform: NodeJS.Platform): readonly string[];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Builds one settled {@link ExecuteResult} from a completed run's captured bytes and terminal facts.
|
|
21
51
|
*
|
|
22
52
|
* @remarks
|
|
23
53
|
* `failed` is derived: a run failed when it timed out, was aborted, ended on a host fault, was ended
|
|
24
54
|
* by a signal, or exited with a code other than `0` — a `null` code from a spawn fault is therefore
|
|
25
|
-
* a failure.
|
|
55
|
+
* a failure. Each byte field is bounded by `limit` on a code-point boundary here, which is the one
|
|
26
56
|
* place the captured bytes are decoded.
|
|
27
57
|
*
|
|
28
58
|
* @param input - The captured bytes, terminal state, and capture limit
|
|
@@ -30,7 +60,7 @@ import { SpawnInput } from '@orkestrel/process';
|
|
|
30
60
|
*
|
|
31
61
|
* @example
|
|
32
62
|
* ```ts
|
|
33
|
-
*
|
|
63
|
+
* buildExecuteResult({
|
|
34
64
|
* command: 'git status',
|
|
35
65
|
* stdout: Buffer.from('ok'),
|
|
36
66
|
* stderr: Buffer.alloc(0),
|
|
@@ -43,20 +73,37 @@ import { SpawnInput } from '@orkestrel/process';
|
|
|
43
73
|
* }).failed // false
|
|
44
74
|
* ```
|
|
45
75
|
*/
|
|
46
|
-
export declare function
|
|
76
|
+
export declare function buildExecuteResult(input: ExecuteInput): ExecuteResult;
|
|
47
77
|
|
|
48
78
|
/**
|
|
49
|
-
* Builds
|
|
79
|
+
* Builds a spawn form from a resolved file and an explicit platform.
|
|
50
80
|
*
|
|
51
81
|
* @remarks
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
82
|
+
* A resolved `.cmd` or `.bat` script cannot be spawned directly **on Windows**, so it runs there
|
|
83
|
+
* through an explicitly quoted `cmd.exe /d /s /c` command line with the argument vector passed
|
|
84
|
+
* verbatim. No path uses a shell, so a metacharacter in an argument is never interpreted. `cmd.exe`
|
|
85
|
+
* expands `%NAME%` before it parses quotes, so no quoting can carry a percent sign through to a
|
|
86
|
+
* Windows batch target: an argument carrying one is refused there rather than silently rewritten.
|
|
87
|
+
* The whole batch path is Windows-only. A POSIX host has no `cmd.exe` and no restriction on spawning
|
|
88
|
+
* a file directly, so a target named `worker.cmd` spawns directly there and receives a percent sign
|
|
89
|
+
* as literal text.
|
|
90
|
+
*
|
|
91
|
+
* @param command - The executable and its argument vector
|
|
92
|
+
* @param file - The resolved executable file
|
|
93
|
+
* @param environment - The child's effective environment
|
|
94
|
+
* @param platform - The platform whose batch rules apply
|
|
95
|
+
* @returns The file, argument vector, and verbatim flag to spawn with
|
|
96
|
+
* @throws A {@link ProcessError} coded `invalid` when `platform` is `win32`, the resolved target is a batch script, and an argument carries a percent sign
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* buildPlatformSpawn({ file: 'node', arguments: ['--version'] }, 'node', {}, 'linux').verbatim // false
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare function buildPlatformSpawn(command: ProcessCommand, file: string, environment: Readonly<Record<string, string | undefined>>, platform: NodeJS.Platform): SpawnInput;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Builds the resolved spawn form of one command for the current host.
|
|
60
107
|
*
|
|
61
108
|
* @param command - The executable and its argument vector
|
|
62
109
|
* @param options - The directory searched first and the child's effective environment
|
|
@@ -123,13 +170,74 @@ export declare function createProcessManager(options?: ProcessManagerOptions): P
|
|
|
123
170
|
* detach({ file: 'node', arguments: ['daemon.js'] }, { workspace: process.cwd() })
|
|
124
171
|
* ```
|
|
125
172
|
*/
|
|
126
|
-
export declare function detach(command:
|
|
173
|
+
export declare function detach(command: ProcessCommand_2, options?: DetachOptions): void;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Runs one command to completion, buffering its output, and settles with the outcome.
|
|
177
|
+
*
|
|
178
|
+
* @remarks
|
|
179
|
+
* The executable is resolved through {@link buildSpawn}, so no run uses a shell. On a POSIX host the
|
|
180
|
+
* child is detached, which is what lets its whole process group be terminated. Standard output and
|
|
181
|
+
* error are each byte-bounded by `limit` (default {@link PROCESS_OUTPUT}) and `truncated` reports
|
|
182
|
+
* whether either stream exceeded it. A positive `timeout` and an aborting `signal` both terminate the
|
|
183
|
+
* child through the same bounded stop, and only the earliest is recorded: a timeout reports
|
|
184
|
+
* `expired` and an abort reports `aborted`, never both. After termination the outcome is awaited for
|
|
185
|
+
* a bounded window, so a descendant holding the child's stdio cannot keep the run pending. That bound
|
|
186
|
+
* covers a terminated run alone: a run with no `timeout` and no `signal` settles on stdio completion
|
|
187
|
+
* rather than on process exit, so a descendant that inherited the child's stdio holds the run open
|
|
188
|
+
* after the child itself has gone. Give such a run a `timeout`. The child's `environment` merges over
|
|
189
|
+
* the parent unless the command is `isolated`, then `options.environment` on top, and `options.input`
|
|
190
|
+
* overrides `command.input`. A host fault while writing that input terminates the run by design and
|
|
191
|
+
* marks its result failed; a strict rejection carries the host fault as its cause. This differs
|
|
192
|
+
* from `Process` constructor input, whose package-initiated input phase stays quiet. Unless `strict`
|
|
193
|
+
* is `false`, a failed run rejects with a {@link ProcessError} carrying the {@link ExecuteResult};
|
|
194
|
+
* {@link createExecuteError} constructs every rejection outside the input-fault door. An invalid
|
|
195
|
+
* option or command string rejects before the child is spawned, because an async function cannot
|
|
196
|
+
* throw synchronously.
|
|
197
|
+
*
|
|
198
|
+
* @param command - The executable, arguments, and optional environment and input
|
|
199
|
+
* @param options - Working directory, timeout, grace, signal, capture limit, and failure delivery
|
|
200
|
+
* @returns The settled run outcome
|
|
201
|
+
* @throws A {@link ProcessError} coded `invalid` for a malformed option, command string, or batch-bound argument, or one carrying the {@link ExecuteResult} when the run failed and `strict` is not `false`
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* const result = await execute({ file: 'git', arguments: ['status'] }, { workspace: process.cwd() })
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
export declare function execute(command: ProcessCommand_2, options?: ExecuteOptions): Promise<ExecuteResult_2>;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Runs one command to completion synchronously, buffering its output, and returns the outcome.
|
|
212
|
+
*
|
|
213
|
+
* @remarks
|
|
214
|
+
* The synchronous counterpart of {@link execute}, spawned through the same resolver and never through a
|
|
215
|
+
* shell. The host offers no cooperative termination window and no in-flight cancellation, so this
|
|
216
|
+
* contract carries neither. A positive `timeout` ends only the root process and can leave
|
|
217
|
+
* descendants running; use {@link execute} or {@link Process} when timeout must terminate the tree. A
|
|
218
|
+
* timeout and an output overflow both end the root with `SIGKILL`: an overflow reports `truncated`
|
|
219
|
+
* and `failed` together and trims the partial output to `limit`, where {@link execute} keeps reading and
|
|
220
|
+
* reports `truncated` without failing. The environment and input follow the same merge as
|
|
221
|
+
* {@link execute}. Unless `strict` is `false`, a failed run throws a {@link createExecuteError}
|
|
222
|
+
* carrying the {@link ExecuteResult}.
|
|
223
|
+
*
|
|
224
|
+
* @param command - The executable, arguments, and optional environment and input
|
|
225
|
+
* @param options - Working directory, timeout, capture limit, and failure delivery
|
|
226
|
+
* @returns The run outcome
|
|
227
|
+
* @throws A {@link ProcessError} coded `invalid` for a malformed option, command string, or batch-bound argument, or one carrying the {@link ExecuteResult} when the run failed and `strict` is not `false`
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```ts
|
|
231
|
+
* const result = executeSync({ file: 'git', arguments: ['--version'] }, { strict: false })
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
export declare function executeSync(command: ProcessCommand_2, options?: ExecuteSyncOptions): ExecuteResult_2;
|
|
127
235
|
|
|
128
236
|
/**
|
|
129
237
|
* Renders one command into its diagnostic command line.
|
|
130
238
|
*
|
|
131
239
|
* @param command - The executable and its argument vector
|
|
132
|
-
* @returns The space-joined command line, for
|
|
240
|
+
* @returns The space-joined command line, for an {@link ExecuteResult} and error messages
|
|
133
241
|
*
|
|
134
242
|
* @example
|
|
135
243
|
* ```ts
|
|
@@ -178,10 +286,11 @@ export declare function isFile(target: string): boolean;
|
|
|
178
286
|
*
|
|
179
287
|
* @remarks
|
|
180
288
|
* On a POSIX host a child spawned `detached` leads its own process group, so signalling the
|
|
181
|
-
* negated pid reaches the whole tree.
|
|
182
|
-
* the child directly.
|
|
183
|
-
*
|
|
184
|
-
*
|
|
289
|
+
* negated pid reaches the whole tree. When no group owns the pid and the host reports `ESRCH`, the
|
|
290
|
+
* signal falls back to the child directly. On Windows, or when no pid is available, the signal also
|
|
291
|
+
* goes to the child directly. Every other throw during signalling is swallowed: the process can
|
|
292
|
+
* exit between the caller's liveness check and this call, and the child's native exit remains the
|
|
293
|
+
* authoritative terminal state.
|
|
185
294
|
*
|
|
186
295
|
* @param child - The child boundary
|
|
187
296
|
* @param signal - The signal to deliver
|
|
@@ -216,13 +325,30 @@ export declare function killProcess(child: Pick<ProcessChild, 'pid' | 'kill'>, s
|
|
|
216
325
|
export declare function killTree(pid: number, timeout: number): Promise<boolean>;
|
|
217
326
|
|
|
218
327
|
/**
|
|
219
|
-
* Merges environment overrides into the environment one child receives.
|
|
328
|
+
* Merges environment overrides into the environment one child receives on the current host.
|
|
329
|
+
*
|
|
330
|
+
* @param isolated - If `true`, the parent environment is excluded; if `false`, the overrides layer over it
|
|
331
|
+
* @param base - The command's own environment overrides
|
|
332
|
+
* @param override - Per-invocation overrides applied last
|
|
333
|
+
* @returns The environment for a spawn, carrying no unset key
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* mergeEnvironment(true, { TOKEN: 'a' }) // { TOKEN: 'a' }
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
export declare function mergeEnvironment(isolated: boolean, base?: Readonly<Record<string, string | undefined>>, override?: Readonly<Record<string, string | undefined>>): NodeJS.ProcessEnv;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Merges environment layers under an explicit platform's key rules.
|
|
220
344
|
*
|
|
221
345
|
* @remarks
|
|
222
|
-
* Later maps override earlier ones and an `undefined` value unsets a key.
|
|
346
|
+
* Later maps override earlier ones and an `undefined` value unsets a key. For `win32` the keys fold
|
|
223
347
|
* case-insensitively and the last writer wins, so `PATH` followed by `Path` yields one variable
|
|
224
348
|
* rather than two the host would resolve unpredictably.
|
|
225
349
|
*
|
|
350
|
+
* @param platform - The platform whose key rules apply
|
|
351
|
+
* @param parent - The parent environment layer
|
|
226
352
|
* @param isolated - If `true`, the parent environment is excluded; if `false`, the overrides layer over it
|
|
227
353
|
* @param base - The command's own environment overrides
|
|
228
354
|
* @param override - Per-invocation overrides applied last
|
|
@@ -230,30 +356,35 @@ export declare function killTree(pid: number, timeout: number): Promise<boolean>
|
|
|
230
356
|
*
|
|
231
357
|
* @example
|
|
232
358
|
* ```ts
|
|
233
|
-
*
|
|
359
|
+
* mergePlatformEnvironment('linux', {}, false, { TOKEN: 'a' }, { TOKEN: undefined }) // TOKEN unset
|
|
234
360
|
* ```
|
|
235
361
|
*/
|
|
236
|
-
export declare function
|
|
362
|
+
export declare function mergePlatformEnvironment(platform: NodeJS.Platform, parent: Readonly<Record<string, string | undefined>>, isolated: boolean, base?: Readonly<Record<string, string | undefined>>, override?: Readonly<Record<string, string | undefined>>): NodeJS.ProcessEnv;
|
|
237
363
|
|
|
238
364
|
/**
|
|
239
365
|
* One supervised child process with framed output, a bounded backlog, and bounded termination.
|
|
240
366
|
*
|
|
241
367
|
* @remarks
|
|
242
368
|
* Standard output is framed through `readline` into a single-consumer stream: each line goes to
|
|
243
|
-
* exactly one waiting iterator, so
|
|
244
|
-
* it. While no consumer has ever requested an iterator,
|
|
245
|
-
*
|
|
246
|
-
* consumer attaching later receives the retained head, a gap, then the live stream.
|
|
369
|
+
* exactly one waiting iterator, so concurrent iterators split the output rather than each receiving
|
|
370
|
+
* all of it. While no consumer has ever requested an iterator, stdout keeps draining so `exit` still
|
|
371
|
+
* resolves, and retention stops at the `backlog` mark: a
|
|
372
|
+
* consumer attaching later receives the retained head, a gap, then the live stream. After an iterator
|
|
247
373
|
* has been requested, stdout pauses at the mark and resumes at half of it, so that consumer loses
|
|
248
|
-
* nothing and the child feels real backpressure. The mark is soft — the
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
374
|
+
* nothing before termination and the child feels real backpressure. The mark is soft — the ordinary backlog can
|
|
375
|
+
* overshoot it by the line that crossed it plus the rest of its delivered chunk. Termination never
|
|
376
|
+
* reapplies backpressure, and retained lines are capped at twice `backlog`; later lines are dropped
|
|
377
|
+
* and `truncated` reports the omission. Standard error is decoded and forwarded live as the `stderr`
|
|
378
|
+
* event while a byte-bounded raw tail is retained as `evidence`. The typed `emitter` also carries a
|
|
379
|
+
* child `error` cause on a spawn fault, a `protocol` {@link ProcessError} on a host-reported stdin
|
|
380
|
+
* fault after the constructor input phase, and the terminal `exit`, alongside the `exit` promise.
|
|
381
|
+
* A fault arising from the constructor-supplied `input` write or its closing `end` stays quiet
|
|
382
|
+
* because the package initiated that sequence. `pid`,
|
|
383
|
+
* `code`, and `signal` read the spawned child directly, so the native exit is readable before the
|
|
384
|
+
* `exit` promise settles on stdio close. `stop` ends the whole tree and reports whether the native
|
|
385
|
+
* exit was observed; `destroy` stops the child, destroys stdin so every pending `send` settles, and
|
|
386
|
+
* destroys the emitter last. `destroy` resolving does not imply the child's stdio has closed, so
|
|
387
|
+
* `exit` and `lines` can still be outstanding when a descendant holds an inherited pipe.
|
|
257
388
|
*
|
|
258
389
|
* @example
|
|
259
390
|
* ```ts
|
|
@@ -276,25 +407,38 @@ export declare class Process implements ProcessInterface {
|
|
|
276
407
|
* @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed
|
|
277
408
|
*/
|
|
278
409
|
constructor(options: ProcessOptions);
|
|
410
|
+
/** The host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
|
|
411
|
+
get pid(): number | undefined;
|
|
412
|
+
/** The exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
|
|
413
|
+
get code(): number | null;
|
|
414
|
+
/** The terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
|
|
415
|
+
get signal(): string | null;
|
|
279
416
|
/** The typed lifecycle observation surface. */
|
|
280
417
|
get emitter(): EmitterInterface<ProcessEventMap>;
|
|
281
418
|
/** The captured stdout lines, in arrival order, ending when the child's stdout closes. */
|
|
282
419
|
get lines(): AsyncIterable<string>;
|
|
283
420
|
/** The decoded byte-bounded stderr tail. */
|
|
284
421
|
get evidence(): string;
|
|
422
|
+
/** True when the `lines` stream omitted output after a retention bound was reached. */
|
|
423
|
+
get truncated(): boolean;
|
|
285
424
|
/** The terminal child state, observed once from the close event. */
|
|
286
425
|
get exit(): Promise<ProcessExit>;
|
|
287
426
|
/**
|
|
288
427
|
* Write one line to the open standard-input channel.
|
|
289
428
|
*
|
|
290
429
|
* @remarks
|
|
291
|
-
* Never rejects.
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
430
|
+
* Never rejects. `true` means the host accepted the bytes without reporting a fault; it does not
|
|
431
|
+
* prove that the child read them. An ordinary write settles when the kernel accepts it. Only a
|
|
432
|
+
* full pipe can hold the write unconfirmed. The `delivery` option can bound that wait, and every
|
|
433
|
+
* terminal teardown path settles pending writes. On Windows 11 with Node v24.18.1, measured on
|
|
434
|
+
* 2026-08-21, a child that closes its own file descriptor 0 can leave the parent pipe writable:
|
|
435
|
+
* the write can settle `true` without a callback error or a stream error while the child remains
|
|
436
|
+
* alive. After `stop` or `destroy` begins, a later call settles `false`. Version 0.0.4 could settle
|
|
437
|
+
* that call `true` before teardown destroyed the pipe; returning `false` avoids claiming delivery
|
|
438
|
+
* for bytes the package is about to discard.
|
|
295
439
|
*
|
|
296
440
|
* @param text - The line text without its trailing newline
|
|
297
|
-
* @returns True when the
|
|
441
|
+
* @returns True when the host accepted the bytes without reporting a fault; false when the channel was closed, destroyed, ended, failed, or remained unconfirmed through `delivery`
|
|
298
442
|
*/
|
|
299
443
|
send(text: string): Promise<boolean>;
|
|
300
444
|
/**
|
|
@@ -329,11 +473,16 @@ export declare class Process implements ProcessInterface {
|
|
|
329
473
|
* The child boundary the termination helpers drive.
|
|
330
474
|
*
|
|
331
475
|
* @remarks
|
|
332
|
-
* A `ChildProcess` satisfies this structurally, and so does any object carrying the same
|
|
476
|
+
* A `ChildProcess` satisfies this structurally, and so does any object carrying the same
|
|
333
477
|
* members, which is what lets a caller drive `stopChild` over a child it spawned itself. Each helper
|
|
334
478
|
* takes the slice of this contract it reads: `exitCode` and `signalCode` are the host's
|
|
335
479
|
* authoritative liveness answer, `pid` addresses a POSIX process group, `kill` delivers one signal,
|
|
336
|
-
*
|
|
480
|
+
* `once` reports the native exit, and `off` releases that listener when the wait ends at its
|
|
481
|
+
* deadline instead.
|
|
482
|
+
*
|
|
483
|
+
* A non-detached child stays in its caller's process group, so no group carries its pid. `kill` is
|
|
484
|
+
* the route that reaches it: `killProcess` signals the negated `pid` first and falls back to `kill`
|
|
485
|
+
* when the host reports that no group owns that pid.
|
|
337
486
|
*/
|
|
338
487
|
export declare interface ProcessChild {
|
|
339
488
|
/** The process id the host assigned, or `undefined` when the spawn never produced one. */
|
|
@@ -353,10 +502,22 @@ export declare interface ProcessChild {
|
|
|
353
502
|
* Register a one-shot listener for the native exit.
|
|
354
503
|
*
|
|
355
504
|
* @param event - The `exit` event name
|
|
356
|
-
* @param listener - The listener invoked
|
|
505
|
+
* @param listener - The listener invoked after the process exits
|
|
357
506
|
* @returns Whatever the emitter returns, which the helpers ignore
|
|
358
507
|
*/
|
|
359
508
|
once(event: 'exit', listener: () => void): unknown;
|
|
509
|
+
/**
|
|
510
|
+
* Release one previously registered exit listener.
|
|
511
|
+
*
|
|
512
|
+
* @remarks
|
|
513
|
+
* `waitForExit` calls this when its deadline elapses before the exit, so a child that outlives
|
|
514
|
+
* several bounded waits accumulates no listeners.
|
|
515
|
+
*
|
|
516
|
+
* @param event - The `exit` event name
|
|
517
|
+
* @param listener - The listener registered through `once`
|
|
518
|
+
* @returns Whatever the emitter returns, which the helpers ignore
|
|
519
|
+
*/
|
|
520
|
+
off(event: 'exit', listener: () => void): unknown;
|
|
360
521
|
}
|
|
361
522
|
|
|
362
523
|
/**
|
|
@@ -421,8 +582,9 @@ export declare class ProcessManager implements ProcessManagerInterface {
|
|
|
421
582
|
* nothing has started and a throw from one strands no process. A getter that begins `destroy`
|
|
422
583
|
* without throwing is the one remaining race, and it leaves a bounded residual: the child is
|
|
423
584
|
* already spawned, so the launch is refused with a {@link createProtocolError} and that child is
|
|
424
|
-
* torn down asynchronously, bounded by `grace` plus the confirmation window. The `
|
|
425
|
-
*
|
|
585
|
+
* torn down asynchronously, bounded by `grace` plus the confirmation window. The `protocol`
|
|
586
|
+
* refusal throws synchronously before the `destroy` barrier settles. The barrier does not cover
|
|
587
|
+
* that child's asynchronous teardown.
|
|
426
588
|
*
|
|
427
589
|
* @param id - The registry key, unique among live children
|
|
428
590
|
* @param options - The child construction options
|
|
@@ -469,8 +631,9 @@ export declare class ProcessManager implements ProcessManagerInterface {
|
|
|
469
631
|
* @remarks
|
|
470
632
|
* A token carrying whitespace or a shell metacharacter is wrapped in double quotes so `cmd.exe`
|
|
471
633
|
* passes it as one literal argument; an embedded double quote is doubled, which is how `cmd.exe`
|
|
472
|
-
* reads a literal quote inside a quoted token.
|
|
473
|
-
*
|
|
634
|
+
* reads a literal quote inside a quoted token. The quoted set includes `%`, although quoting cannot
|
|
635
|
+
* stop `cmd.exe` expansion; {@link buildSpawn} therefore refuses `%` in an argument to a Windows
|
|
636
|
+
* batch target.
|
|
474
637
|
*
|
|
475
638
|
* @param value - The token to quote
|
|
476
639
|
* @returns The token, quoted only when `cmd.exe` would otherwise split or interpret it
|
|
@@ -483,139 +646,127 @@ export declare class ProcessManager implements ProcessManagerInterface {
|
|
|
483
646
|
export declare function quoteArgument(value: string): string;
|
|
484
647
|
|
|
485
648
|
/**
|
|
486
|
-
* Reads one environment variable
|
|
649
|
+
* Reads one environment variable under an explicit platform's key rules.
|
|
487
650
|
*
|
|
488
651
|
* @remarks
|
|
489
652
|
* Windows environment keys are case-insensitive, so a merged record can hold `Path` where the
|
|
490
|
-
* caller asks for `PATH`. The exact key is tried first and a folded scan runs only
|
|
653
|
+
* caller asks for `PATH`. The exact key is tried first and a folded scan runs only for `win32`.
|
|
491
654
|
*
|
|
492
655
|
* @param environment - The environment record to read
|
|
493
656
|
* @param name - The variable name
|
|
657
|
+
* @param platform - The platform whose key rules apply
|
|
494
658
|
* @returns The value, or `undefined` when the environment declares no such variable
|
|
495
659
|
*
|
|
496
660
|
* @example
|
|
497
661
|
* ```ts
|
|
498
|
-
*
|
|
662
|
+
* readPlatformVariable({ Path: 'C:\\Windows' }, 'PATH', 'win32') // 'C:\\Windows'
|
|
499
663
|
* ```
|
|
500
664
|
*/
|
|
501
|
-
export declare function
|
|
665
|
+
export declare function readPlatformVariable(environment: Readonly<Record<string, string | undefined>>, name: string, platform: NodeJS.Platform): string | undefined;
|
|
502
666
|
|
|
503
667
|
/**
|
|
504
|
-
*
|
|
668
|
+
* Reads one environment variable the way the current host resolves it.
|
|
505
669
|
*
|
|
506
|
-
* @
|
|
507
|
-
*
|
|
508
|
-
*
|
|
509
|
-
* literal name is tried first and each `PATHEXT` candidate after it, whether or not the name already
|
|
510
|
-
* carries an extension — so `report.txt` resolves to a `report.txt` file where one exists and to
|
|
511
|
-
* `report.txt.cmd` where none does. The lookup reads the child's effective environment, so an
|
|
512
|
-
* overridden `PATH` selects the executable the child would have found. A POSIX host resolves the
|
|
513
|
-
* file itself, so the answer there is always `undefined`. An appended extension is spelled the way
|
|
514
|
-
* `PATHEXT` spells it rather than the way the directory entry does, which the case-insensitive host
|
|
515
|
-
* treats as the same file.
|
|
516
|
-
*
|
|
517
|
-
* @param file - The command executable name or path
|
|
518
|
-
* @param options - The directory searched first and the child's effective environment
|
|
519
|
-
* @returns The resolved absolute path, or `undefined` when no candidate is a regular file
|
|
670
|
+
* @param environment - The environment record to read
|
|
671
|
+
* @param name - The variable name
|
|
672
|
+
* @returns The value, or `undefined` when the environment declares no such variable
|
|
520
673
|
*
|
|
521
674
|
* @example
|
|
522
675
|
* ```ts
|
|
523
|
-
*
|
|
676
|
+
* readVariable({ PATH: '/usr/bin' }, 'PATH') // '/usr/bin'
|
|
524
677
|
* ```
|
|
525
678
|
*/
|
|
526
|
-
export declare function
|
|
679
|
+
export declare function readVariable(environment: Readonly<Record<string, string | undefined>>, name: string): string | undefined;
|
|
527
680
|
|
|
528
681
|
/**
|
|
529
|
-
*
|
|
682
|
+
* Resolves a command file to the executable path the host would launch.
|
|
530
683
|
*
|
|
531
|
-
* @
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
* and slot `1` counts the retained bytes, so a caller compares slot `0` against `limit` to learn
|
|
535
|
-
* whether the capture was truncated.
|
|
536
|
-
*
|
|
537
|
-
* @param chunk - The delivered chunk, ignored when it is not a buffer
|
|
538
|
-
* @param chunks - The retained head, appended to in place
|
|
539
|
-
* @param counts - The `[delivered, retained]` tally, updated in place
|
|
540
|
-
* @param limit - The maximum retained byte count
|
|
541
|
-
* @returns Nothing
|
|
684
|
+
* @param file - The command executable name or path
|
|
685
|
+
* @param options - The directory searched first and the child's effective environment
|
|
686
|
+
* @returns The resolved absolute path, or `undefined` when no candidate is a regular file
|
|
542
687
|
*
|
|
543
688
|
* @example
|
|
544
689
|
* ```ts
|
|
545
|
-
*
|
|
546
|
-
* const counts = [0, 0]
|
|
547
|
-
* retainChunk(Buffer.from('hello'), chunks, counts, 3)
|
|
548
|
-
* counts[1] // 3
|
|
690
|
+
* resolveExecutable('git', {}) ?? 'git' // an absolute path on Windows, 'git' elsewhere
|
|
549
691
|
* ```
|
|
550
692
|
*/
|
|
551
|
-
export declare function
|
|
693
|
+
export declare function resolveExecutable(file: string, options?: ExecutableOptions): string | undefined;
|
|
552
694
|
|
|
553
695
|
/**
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
* @remarks
|
|
557
|
-
* The executable is resolved through {@link buildSpawn}, so no run uses a shell. On a POSIX host the
|
|
558
|
-
* child is detached, which is what lets its whole process group be terminated. Standard output and
|
|
559
|
-
* error are each byte-bounded by `limit` (default {@link PROCESS_OUTPUT}) and `truncated` reports
|
|
560
|
-
* whether either stream exceeded it. A positive `timeout` and an aborting `signal` both terminate the
|
|
561
|
-
* child through the same bounded stop, and only the first of them is recorded: a timeout reports
|
|
562
|
-
* `expired` and an abort reports `aborted`, never both. After termination the outcome is awaited for
|
|
563
|
-
* a bounded window, so a descendant holding the child's stdio cannot keep the run pending. That bound
|
|
564
|
-
* covers a terminated run alone: a run with no `timeout` and no `signal` settles on stdio completion
|
|
565
|
-
* rather than on process exit, so a descendant that inherited the child's stdio holds the run open
|
|
566
|
-
* after the child itself has gone. Give such a run a `timeout`. The child's `environment` merges over
|
|
567
|
-
* the parent unless the command is `isolated`, then `options.environment` on top, and `options.input`
|
|
568
|
-
* overrides `command.input`. Unless `strict` is `false`, a failed run rejects with a
|
|
569
|
-
* {@link createRunError} carrying the {@link RunResult}. An invalid option or command string rejects
|
|
570
|
-
* before the child is spawned, because an async function cannot throw synchronously.
|
|
571
|
-
*
|
|
572
|
-
* @param command - The executable, arguments, and optional environment and input
|
|
573
|
-
* @param options - Working directory, timeout, grace, signal, capture limit, and failure delivery
|
|
574
|
-
* @returns The settled run outcome
|
|
575
|
-
* @throws A {@link ProcessError} coded `invalid` for a malformed option, command string, or batch-bound argument, or one carrying the {@link RunResult} when the run failed and `strict` is not `false`
|
|
696
|
+
* Accumulates byte totals while retaining a bounded stream head.
|
|
576
697
|
*
|
|
577
698
|
* @example
|
|
578
699
|
* ```ts
|
|
579
|
-
* const
|
|
700
|
+
* const retention = new Retention()
|
|
701
|
+
* retention.retain(Buffer.from('hello'), 3)?.toString('utf8') // 'hel'
|
|
702
|
+
* retention.retained // 3
|
|
580
703
|
* ```
|
|
581
704
|
*/
|
|
582
|
-
export declare
|
|
705
|
+
export declare class Retention implements RetentionInterface {
|
|
706
|
+
#private;
|
|
707
|
+
/** The bytes delivered by the stream. */
|
|
708
|
+
get delivered(): number;
|
|
709
|
+
/** The bytes retained from the stream head. */
|
|
710
|
+
get retained(): number;
|
|
711
|
+
/**
|
|
712
|
+
* Retains a delivered chunk within a byte limit.
|
|
713
|
+
*
|
|
714
|
+
* @param chunk - The delivered chunk, ignored when it is not a buffer
|
|
715
|
+
* @param limit - The maximum retained byte count
|
|
716
|
+
* @returns The retained slice, or `undefined` when the chunk contributes no retained bytes
|
|
717
|
+
*/
|
|
718
|
+
retain(chunk: unknown, limit: number): Buffer_2 | undefined;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/** Exposes byte totals and bounded stream-head retention. */
|
|
722
|
+
export declare interface RetentionInterface {
|
|
723
|
+
/** The bytes delivered by the stream. */
|
|
724
|
+
readonly delivered: number;
|
|
725
|
+
/** The bytes retained from the stream head. */
|
|
726
|
+
readonly retained: number;
|
|
727
|
+
/**
|
|
728
|
+
* Retains a delivered chunk within a byte limit.
|
|
729
|
+
*
|
|
730
|
+
* @param chunk - The delivered chunk, ignored when it is not a buffer
|
|
731
|
+
* @param limit - The maximum retained byte count
|
|
732
|
+
* @returns The retained slice, or `undefined` when the chunk contributes no retained bytes
|
|
733
|
+
*/
|
|
734
|
+
retain(chunk: unknown, limit: number): Buffer_2 | undefined;
|
|
735
|
+
}
|
|
583
736
|
|
|
584
737
|
/**
|
|
585
|
-
*
|
|
738
|
+
* Takes one owned frozen snapshot of a caller's command.
|
|
586
739
|
*
|
|
587
740
|
* @remarks
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
* {@link createRunError} carrying the {@link RunResult}.
|
|
741
|
+
* Every public entry point snapshots before it validates, so the object validated is the object
|
|
742
|
+
* spawned. Each property is read exactly once, because reading one runs the caller's own getter: a
|
|
743
|
+
* command whose `file` changes between reads would otherwise validate one executable and spawn
|
|
744
|
+
* another. The argument vector and the environment record are copied and frozen, so a caller
|
|
745
|
+
* mutating either after the call cannot reach the spawn. An absent optional stays absent rather than
|
|
746
|
+
* becoming an explicit `undefined`.
|
|
595
747
|
*
|
|
596
|
-
* @param command - The
|
|
597
|
-
* @
|
|
598
|
-
* @returns The run outcome
|
|
599
|
-
* @throws A {@link ProcessError} coded `invalid` for a malformed option, command string, or batch-bound argument, or one carrying the {@link RunResult} when the run failed and `strict` is not `false`
|
|
748
|
+
* @param command - The caller's command, whose properties may be getters
|
|
749
|
+
* @returns A frozen command carrying the values read at this instant
|
|
600
750
|
*
|
|
601
751
|
* @example
|
|
602
752
|
* ```ts
|
|
603
|
-
*
|
|
753
|
+
* snapshotCommand({ file: 'git', arguments: ['status'] }) // { file: 'git', arguments: ['status'] }
|
|
604
754
|
* ```
|
|
605
755
|
*/
|
|
606
|
-
export declare function
|
|
756
|
+
export declare function snapshotCommand(command: ProcessCommand): ProcessCommand;
|
|
607
757
|
|
|
608
758
|
/**
|
|
609
759
|
* Terminates one child process tree and reports whether its native exit was observed.
|
|
610
760
|
*
|
|
611
761
|
* @remarks
|
|
612
|
-
* Windows ends the tree at once through {@link killTree}, falling back to a direct kill
|
|
613
|
-
* utility fails, because the host has no cooperative termination to offer. A POSIX host signals
|
|
614
|
-
* process group `SIGTERM`,
|
|
615
|
-
*
|
|
616
|
-
*
|
|
617
|
-
*
|
|
618
|
-
* the
|
|
762
|
+
* Windows ends the whole tree at once through {@link killTree}, falling back to a direct kill after
|
|
763
|
+
* the utility fails, because the host has no cooperative termination to offer. A POSIX host signals
|
|
764
|
+
* the process group `SIGTERM`, falls back to the direct child when no group owns its pid, waits
|
|
765
|
+
* `grace`, then sends `SIGKILL` through the same route. No signal is initiated after the native exit
|
|
766
|
+
* is observed; the window between initiating a signal and the host delivering it belongs to the
|
|
767
|
+
* operating system. `confirm` bounds each awaited step rather than the call as a whole: on Windows
|
|
768
|
+
* it bounds the `taskkill` call and then the final wait, and on a POSIX host `grace` bounds the
|
|
769
|
+
* cooperative wait and `confirm` the final one. Never rejects.
|
|
619
770
|
*
|
|
620
771
|
* @param child - The child boundary
|
|
621
772
|
* @param grace - The cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL`
|
|
@@ -780,6 +931,6 @@ export declare function validateWorkspace(workspace: string | undefined): void;
|
|
|
780
931
|
* await waitForExit(child, 5_000)
|
|
781
932
|
* ```
|
|
782
933
|
*/
|
|
783
|
-
export declare function waitForExit(child: Pick<ProcessChild, 'exitCode' | 'signalCode' | 'once'>, timeout: number): Promise<void>;
|
|
934
|
+
export declare function waitForExit(child: Pick<ProcessChild, 'exitCode' | 'signalCode' | 'once' | 'off'>, timeout: number): Promise<void>;
|
|
784
935
|
|
|
785
936
|
export { }
|