@gobing-ai/ts-runtime 0.4.12 → 0.4.14
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 +8 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/process-executor.d.ts +18 -1
- package/dist/process-executor.d.ts.map +1 -1
- package/dist/process-executor.js +49 -2
- package/package.json +4 -4
- package/src/index.ts +1 -0
- package/src/process-executor.ts +71 -3
package/README.md
CHANGED
|
@@ -597,8 +597,14 @@ unsub();
|
|
|
597
597
|
|
|
598
598
|
`rejectOnError: true` throws on non-zero exits. `OutputPolicy` controls
|
|
599
599
|
buffered vs streamed output. `ProcessOptions` supports timeout, env, cwd,
|
|
600
|
-
maxOutput, forceBuffered,
|
|
601
|
-
`
|
|
600
|
+
maxOutput, forceBuffered, an optional synchronous `onOutput({ stream, chunk,
|
|
601
|
+
timestamp })` observer, and registry fields (`source`, `teamId`, `agentId`).
|
|
602
|
+
`onOutput` observes live chunks while the returned `ProcessResult` retains the
|
|
603
|
+
complete buffered stdout/stderr; observers must enqueue and return, and thrown
|
|
604
|
+
observer errors are isolated from the child. When `signal` is supplied, one-shot
|
|
605
|
+
commands run in an isolated process group on Unix so abort terminates descendants
|
|
606
|
+
that could otherwise retain the output pipes; Windows falls back to direct-child
|
|
607
|
+
cancellation. Inject the same `ProcessRegistry` into every executor that should
|
|
602
608
|
appear in one watch list; without a registry, behavior is unchanged.
|
|
603
609
|
|
|
604
610
|
Cloudflare Workers do not expose process execution; check
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { createNodeFileSystem, findProjectRoot } from './file-system-node';
|
|
|
8
8
|
export { atomicWriteFile, atomicWriteJson, createLogStream, ensureDirForFile, readJsonFile, walkDir, writeJsonFile, } from './fs';
|
|
9
9
|
export * from './path';
|
|
10
10
|
export { _resetRuntimeFactory, isCloudflareWorkerRuntime, loadRuntimeFactory } from './platform';
|
|
11
|
-
export type { OutputPolicy, PipeProcess, PipeProcessOptions, ProcessEventDetail, ProcessEventSink, ProcessEvents, ProcessExecutorConfig, ProcessExitReason, ProcessOptions, ProcessResult, ProcessSignal, TracerPort, } from './process-executor';
|
|
11
|
+
export type { OutputPolicy, PipeProcess, PipeProcessOptions, ProcessEventDetail, ProcessEventSink, ProcessEvents, ProcessExecutorConfig, ProcessExitReason, ProcessOptions, ProcessOutputChunk, ProcessResult, ProcessSignal, TracerPort, } from './process-executor';
|
|
12
12
|
export { NodeProcessExecutor, ProcessExecutor } from './process-executor';
|
|
13
13
|
export type { InMemoryProcessRegistryOptions, ProcessExecution, ProcessExecutionBegin, ProcessExecutionComplete, ProcessExecutionFilter, ProcessExecutionSource, ProcessExecutionStatus, ProcessRegistry, ProcessRegistryEvent, } from './process-registry';
|
|
14
14
|
export { createInMemoryProcessRegistry, InMemoryProcessRegistry } from './process-registry';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC9E,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACH,eAAe,EACf,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,aAAa,GAChB,MAAM,MAAM,CAAC;AACd,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACjG,YAAY,EACR,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,UAAU,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,YAAY,EACR,8BAA8B,EAC9B,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,6BAA6B,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC1E,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AAIxB,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEnF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC,cAAc,oBAAoB,EAAE,sBAAsB,CAAC,CAAC;AAE3G;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,cAAc,oBAAoB,EAAE,qBAAqB,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC9E,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACH,eAAe,EACf,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,aAAa,GAChB,MAAM,MAAM,CAAC;AACd,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACjG,YAAY,EACR,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,UAAU,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,YAAY,EACR,8BAA8B,EAC9B,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,6BAA6B,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC1E,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AAIxB,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEnF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC,cAAc,oBAAoB,EAAE,sBAAsB,CAAC,CAAC;AAE3G;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,cAAc,oBAAoB,EAAE,qBAAqB,CAAC,CAAC"}
|
|
@@ -31,8 +31,19 @@ export interface ProcessOptions {
|
|
|
31
31
|
label?: string;
|
|
32
32
|
rejectOnError?: boolean;
|
|
33
33
|
forceBuffered?: boolean;
|
|
34
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* AbortSignal forwarded to execa and, on Unix, to the child's isolated
|
|
36
|
+
* process group so descendants cannot outlive a cancelled one-shot run.
|
|
37
|
+
*/
|
|
35
38
|
signal?: AbortSignal;
|
|
39
|
+
/**
|
|
40
|
+
* Optional non-blocking observer for incremental stdout/stderr.
|
|
41
|
+
*
|
|
42
|
+
* The executor invokes this synchronously from the child stream and isolates
|
|
43
|
+
* observer failures. Consumers must enqueue and return; the buffered
|
|
44
|
+
* {@link ProcessResult} remains authoritative.
|
|
45
|
+
*/
|
|
46
|
+
onOutput?: (output: ProcessOutputChunk) => void;
|
|
36
47
|
/**
|
|
37
48
|
* Registry metadata (spur#0264). Defaults: source `'one-shot'` for `run`.
|
|
38
49
|
* Pass `source: 'supervisor'` (and optional teamId/agentId) when the spawn is
|
|
@@ -42,6 +53,12 @@ export interface ProcessOptions {
|
|
|
42
53
|
teamId?: string;
|
|
43
54
|
agentId?: string;
|
|
44
55
|
}
|
|
56
|
+
/** One incremental process-output observation. */
|
|
57
|
+
export interface ProcessOutputChunk {
|
|
58
|
+
readonly stream: 'stdout' | 'stderr';
|
|
59
|
+
readonly chunk: string;
|
|
60
|
+
readonly timestamp: string;
|
|
61
|
+
}
|
|
45
62
|
/** Result of a completed child process, including exit code, captured output, and duration. */
|
|
46
63
|
export interface ProcessResult {
|
|
47
64
|
command: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-executor.d.ts","sourceRoot":"","sources":["../src/process-executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAIlF,uGAAuG;AACvG,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtF,sGAAsG;AACtG,MAAM,WAAW,qBAAqB;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB
|
|
1
|
+
{"version":3,"file":"process-executor.d.ts","sourceRoot":"","sources":["../src/process-executor.ts"],"names":[],"mappings":"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"}
|
package/dist/process-executor.js
CHANGED
|
@@ -52,7 +52,11 @@ export class NodeProcessExecutor {
|
|
|
52
52
|
...(options.label !== undefined ? { label: options.label } : {}),
|
|
53
53
|
});
|
|
54
54
|
try {
|
|
55
|
-
const
|
|
55
|
+
const subprocess = execa(options.command, args, execaOptions);
|
|
56
|
+
const stopGroupCancellation = observeProcessGroupCancellation(subprocess, options.signal);
|
|
57
|
+
observeOutput(subprocess.stdout, 'stdout', options.onOutput);
|
|
58
|
+
observeOutput(subprocess.stderr, 'stderr', options.onOutput);
|
|
59
|
+
const result = await subprocess.finally(stopGroupCancellation);
|
|
56
60
|
// execa@9 Result does not expose pid — buffered runs leave pid unset.
|
|
57
61
|
const processResult = {
|
|
58
62
|
command: options.command,
|
|
@@ -352,8 +356,51 @@ function buildExecaOptions(opts) {
|
|
|
352
356
|
...(opts.env !== undefined ? { env: opts.env } : {}),
|
|
353
357
|
...(opts.timeout !== undefined ? { timeout: opts.timeout } : {}),
|
|
354
358
|
...(opts.maxOutput !== undefined ? { maxBuffer: opts.maxOutput } : {}),
|
|
355
|
-
...(opts.signal !== undefined
|
|
359
|
+
...(opts.signal !== undefined
|
|
360
|
+
? {
|
|
361
|
+
cancelSignal: opts.signal,
|
|
362
|
+
// Node's negative-pid group signal requires the child to lead
|
|
363
|
+
// a distinct process group. Windows has no equivalent.
|
|
364
|
+
...(process.platform !== 'win32' ? { detached: true } : {}),
|
|
365
|
+
}
|
|
366
|
+
: {}),
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
function observeProcessGroupCancellation(subprocess, signal) {
|
|
370
|
+
const pid = subprocess.pid;
|
|
371
|
+
if (signal === undefined || process.platform === 'win32' || pid === undefined)
|
|
372
|
+
return () => { };
|
|
373
|
+
const abort = () => {
|
|
374
|
+
try {
|
|
375
|
+
process.kill(-pid, 'SIGTERM');
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
// The leader may already have exited through execa's cancelSignal.
|
|
379
|
+
// Fall back to the direct child without changing cancellation semantics.
|
|
380
|
+
subprocess.kill('SIGTERM');
|
|
381
|
+
}
|
|
356
382
|
};
|
|
383
|
+
if (signal.aborted)
|
|
384
|
+
abort();
|
|
385
|
+
else
|
|
386
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
387
|
+
return () => signal.removeEventListener('abort', abort);
|
|
388
|
+
}
|
|
389
|
+
function observeOutput(stream, name, observer) {
|
|
390
|
+
if (!stream || !observer)
|
|
391
|
+
return;
|
|
392
|
+
stream.on('data', (chunk) => {
|
|
393
|
+
try {
|
|
394
|
+
observer({
|
|
395
|
+
stream: name,
|
|
396
|
+
chunk: asString(chunk),
|
|
397
|
+
timestamp: new Date().toISOString(),
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
// Observability is best-effort and must never interrupt child I/O.
|
|
402
|
+
}
|
|
403
|
+
});
|
|
357
404
|
}
|
|
358
405
|
function asString(value) {
|
|
359
406
|
if (typeof value === 'string')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/ts-runtime",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.14",
|
|
4
4
|
"description": "@gobing-ai/ts-runtime — Runtime abstractions for Bun, Node, and Cloudflare Workers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -58,17 +58,17 @@
|
|
|
58
58
|
"release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-runtime-v<version> && git push --tags' && exit 1"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@gobing-ai/ts-utils": "^0.4.
|
|
61
|
+
"@gobing-ai/ts-utils": "^0.4.14",
|
|
62
62
|
"execa": "^9.5.0",
|
|
63
63
|
"yaml": "^2.7.0",
|
|
64
64
|
"zod": "^4.1.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
67
|
+
"@gobing-ai/ts-db": "^0.4.14",
|
|
68
68
|
"@types/bun": "1.3.14"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
71
|
+
"@gobing-ai/ts-db": "^0.4.14"
|
|
72
72
|
},
|
|
73
73
|
"peerDependenciesMeta": {
|
|
74
74
|
"@gobing-ai/ts-db": {
|
package/src/index.ts
CHANGED
package/src/process-executor.ts
CHANGED
|
@@ -33,8 +33,19 @@ export interface ProcessOptions {
|
|
|
33
33
|
label?: string;
|
|
34
34
|
rejectOnError?: boolean;
|
|
35
35
|
forceBuffered?: boolean;
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* AbortSignal forwarded to execa and, on Unix, to the child's isolated
|
|
38
|
+
* process group so descendants cannot outlive a cancelled one-shot run.
|
|
39
|
+
*/
|
|
37
40
|
signal?: AbortSignal;
|
|
41
|
+
/**
|
|
42
|
+
* Optional non-blocking observer for incremental stdout/stderr.
|
|
43
|
+
*
|
|
44
|
+
* The executor invokes this synchronously from the child stream and isolates
|
|
45
|
+
* observer failures. Consumers must enqueue and return; the buffered
|
|
46
|
+
* {@link ProcessResult} remains authoritative.
|
|
47
|
+
*/
|
|
48
|
+
onOutput?: (output: ProcessOutputChunk) => void;
|
|
38
49
|
/**
|
|
39
50
|
* Registry metadata (spur#0264). Defaults: source `'one-shot'` for `run`.
|
|
40
51
|
* Pass `source: 'supervisor'` (and optional teamId/agentId) when the spawn is
|
|
@@ -45,6 +56,13 @@ export interface ProcessOptions {
|
|
|
45
56
|
agentId?: string;
|
|
46
57
|
}
|
|
47
58
|
|
|
59
|
+
/** One incremental process-output observation. */
|
|
60
|
+
export interface ProcessOutputChunk {
|
|
61
|
+
readonly stream: 'stdout' | 'stderr';
|
|
62
|
+
readonly chunk: string;
|
|
63
|
+
readonly timestamp: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
48
66
|
/** Result of a completed child process, including exit code, captured output, and duration. */
|
|
49
67
|
export interface ProcessResult {
|
|
50
68
|
command: string;
|
|
@@ -205,7 +223,11 @@ export class NodeProcessExecutor implements ProcessExecutor {
|
|
|
205
223
|
});
|
|
206
224
|
|
|
207
225
|
try {
|
|
208
|
-
const
|
|
226
|
+
const subprocess = execa(options.command, args, execaOptions);
|
|
227
|
+
const stopGroupCancellation = observeProcessGroupCancellation(subprocess, options.signal);
|
|
228
|
+
observeOutput(subprocess.stdout, 'stdout', options.onOutput);
|
|
229
|
+
observeOutput(subprocess.stderr, 'stderr', options.onOutput);
|
|
230
|
+
const result = await subprocess.finally(stopGroupCancellation);
|
|
209
231
|
// execa@9 Result does not expose pid — buffered runs leave pid unset.
|
|
210
232
|
const processResult = {
|
|
211
233
|
command: options.command,
|
|
@@ -584,8 +606,54 @@ function buildExecaOptions(opts: {
|
|
|
584
606
|
...(opts.env !== undefined ? { env: opts.env } : {}),
|
|
585
607
|
...(opts.timeout !== undefined ? { timeout: opts.timeout } : {}),
|
|
586
608
|
...(opts.maxOutput !== undefined ? { maxBuffer: opts.maxOutput } : {}),
|
|
587
|
-
...(opts.signal !== undefined
|
|
609
|
+
...(opts.signal !== undefined
|
|
610
|
+
? {
|
|
611
|
+
cancelSignal: opts.signal,
|
|
612
|
+
// Node's negative-pid group signal requires the child to lead
|
|
613
|
+
// a distinct process group. Windows has no equivalent.
|
|
614
|
+
...(process.platform !== 'win32' ? { detached: true } : {}),
|
|
615
|
+
}
|
|
616
|
+
: {}),
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function observeProcessGroupCancellation(
|
|
621
|
+
subprocess: { pid?: number; kill(signal?: NodeJS.Signals | number): boolean },
|
|
622
|
+
signal: AbortSignal | undefined,
|
|
623
|
+
): () => void {
|
|
624
|
+
const pid = subprocess.pid;
|
|
625
|
+
if (signal === undefined || process.platform === 'win32' || pid === undefined) return () => {};
|
|
626
|
+
const abort = (): void => {
|
|
627
|
+
try {
|
|
628
|
+
process.kill(-pid, 'SIGTERM');
|
|
629
|
+
} catch {
|
|
630
|
+
// The leader may already have exited through execa's cancelSignal.
|
|
631
|
+
// Fall back to the direct child without changing cancellation semantics.
|
|
632
|
+
subprocess.kill('SIGTERM');
|
|
633
|
+
}
|
|
588
634
|
};
|
|
635
|
+
if (signal.aborted) abort();
|
|
636
|
+
else signal.addEventListener('abort', abort, { once: true });
|
|
637
|
+
return () => signal.removeEventListener('abort', abort);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function observeOutput(
|
|
641
|
+
stream: NodeJS.ReadableStream | null | undefined,
|
|
642
|
+
name: ProcessOutputChunk['stream'],
|
|
643
|
+
observer: ProcessOptions['onOutput'],
|
|
644
|
+
): void {
|
|
645
|
+
if (!stream || !observer) return;
|
|
646
|
+
stream.on('data', (chunk: string | Uint8Array) => {
|
|
647
|
+
try {
|
|
648
|
+
observer({
|
|
649
|
+
stream: name,
|
|
650
|
+
chunk: asString(chunk),
|
|
651
|
+
timestamp: new Date().toISOString(),
|
|
652
|
+
});
|
|
653
|
+
} catch {
|
|
654
|
+
// Observability is best-effort and must never interrupt child I/O.
|
|
655
|
+
}
|
|
656
|
+
});
|
|
589
657
|
}
|
|
590
658
|
|
|
591
659
|
function asString(value: string | string[] | unknown[] | Uint8Array | undefined): string {
|