@orkestrel/process 0.0.9 → 0.0.10
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 +13 -7
- package/dist/src/core/index.cjs +24 -13
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +155 -141
- package/dist/src/core/index.d.ts +155 -141
- package/dist/src/core/index.js +24 -13
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +134 -89
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +292 -77
- package/dist/src/server/index.d.ts +292 -77
- package/dist/src/server/index.js +134 -90
- package/dist/src/server/index.js.map +1 -1
- package/package.json +10 -10
|
@@ -9,14 +9,22 @@ import { ExecuteSyncOptions } from '@orkestrel/process';
|
|
|
9
9
|
import { ProcessCommand } from '@orkestrel/process';
|
|
10
10
|
import { ProcessEventMap } from '@orkestrel/process';
|
|
11
11
|
import { ProcessExit } from '@orkestrel/process';
|
|
12
|
+
import { ProcessExit as ProcessExit_2 } from '@orkestrel/process';
|
|
12
13
|
import { ProcessInterface } from '@orkestrel/process';
|
|
14
|
+
import { ProcessInterface as ProcessInterface_2 } from '@orkestrel/process';
|
|
13
15
|
import { ProcessManagerEventMap } from '@orkestrel/process';
|
|
14
16
|
import { ProcessManagerInterface } from '@orkestrel/process';
|
|
17
|
+
import { ProcessManagerInterface as ProcessManagerInterface_2 } from '@orkestrel/process';
|
|
15
18
|
import { ProcessManagerOptions } from '@orkestrel/process';
|
|
19
|
+
import { ProcessManagerOptions as ProcessManagerOptions_2 } from '@orkestrel/process';
|
|
16
20
|
import { ProcessOptions } from '@orkestrel/process';
|
|
21
|
+
import { ProcessOptions as ProcessOptions_2 } from '@orkestrel/process';
|
|
22
|
+
import { Readable } from 'node:stream';
|
|
17
23
|
import { SessionEventMap } from '@orkestrel/process';
|
|
18
24
|
import { SessionInterface } from '@orkestrel/process';
|
|
25
|
+
import { SessionInterface as SessionInterface_2 } from '@orkestrel/process';
|
|
19
26
|
import { SessionOptions } from '@orkestrel/process';
|
|
27
|
+
import { SessionOptions as SessionOptions_2 } from '@orkestrel/process';
|
|
20
28
|
import { SpawnInput } from '@orkestrel/process';
|
|
21
29
|
|
|
22
30
|
/**
|
|
@@ -301,14 +309,14 @@ export declare function formatCommand(command: ProcessCommand): string;
|
|
|
301
309
|
* initiated against a pid the host may have reused.
|
|
302
310
|
*
|
|
303
311
|
* @param child - The child boundary
|
|
304
|
-
* @returns True
|
|
312
|
+
* @returns True if the process has exited; false otherwise
|
|
305
313
|
*
|
|
306
314
|
* @example
|
|
307
315
|
* ```ts
|
|
308
316
|
* isExited({ exitCode: 0, signalCode: null }) // true
|
|
309
317
|
* ```
|
|
310
318
|
*/
|
|
311
|
-
export declare function isExited(child: Pick<
|
|
319
|
+
export declare function isExited(child: Pick<ProcessChildInterface, 'exitCode' | 'signalCode'>): boolean;
|
|
312
320
|
|
|
313
321
|
/**
|
|
314
322
|
* Checks whether a path names a regular file.
|
|
@@ -318,7 +326,7 @@ export declare function isExited(child: Pick<ProcessChild, 'exitCode' | 'signalC
|
|
|
318
326
|
* command. An unreadable or malformed path reports `false` rather than throwing.
|
|
319
327
|
*
|
|
320
328
|
* @param target - The absolute or relative path to inspect
|
|
321
|
-
* @returns True
|
|
329
|
+
* @returns True if the path resolves to a regular file; false otherwise
|
|
322
330
|
*
|
|
323
331
|
* @example
|
|
324
332
|
* ```ts
|
|
@@ -347,7 +355,7 @@ export declare function isFile(target: string): boolean;
|
|
|
347
355
|
* killProcess(child, 'SIGTERM')
|
|
348
356
|
* ```
|
|
349
357
|
*/
|
|
350
|
-
export declare function killProcess(child: Pick<
|
|
358
|
+
export declare function killProcess(child: Pick<ProcessChildInterface, 'pid' | 'kill'>, signal: NodeJS.Signals): void;
|
|
351
359
|
|
|
352
360
|
/**
|
|
353
361
|
* Kills one Windows process tree through `taskkill`.
|
|
@@ -361,7 +369,7 @@ export declare function killProcess(child: Pick<ProcessChild, 'pid' | 'kill'>, s
|
|
|
361
369
|
*
|
|
362
370
|
* @param pid - The root process id of the tree to end
|
|
363
371
|
* @param timeout - The milliseconds the utility is given before it is killed
|
|
364
|
-
* @returns True
|
|
372
|
+
* @returns True if the utility reported success; false otherwise (it failed, was unavailable, or was cut off)
|
|
365
373
|
*
|
|
366
374
|
* @example
|
|
367
375
|
* ```ts
|
|
@@ -438,37 +446,37 @@ export declare function mergePlatformEnvironment(platform: NodeJS.Platform, pare
|
|
|
438
446
|
* await child.destroy()
|
|
439
447
|
* ```
|
|
440
448
|
*/
|
|
441
|
-
export declare class Process implements
|
|
449
|
+
export declare class Process implements ProcessInterface_2 {
|
|
442
450
|
#private;
|
|
443
451
|
/**
|
|
444
|
-
*
|
|
452
|
+
* Spawns one child process and begins stream capture.
|
|
445
453
|
*
|
|
446
454
|
* @param options - Command, workspace, termination, capture, stdin, and observation settings
|
|
447
455
|
* @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed
|
|
448
456
|
*/
|
|
449
|
-
constructor(options:
|
|
450
|
-
/**
|
|
457
|
+
constructor(options: ProcessOptions_2);
|
|
458
|
+
/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
|
|
451
459
|
get pid(): number | undefined;
|
|
452
|
-
/**
|
|
460
|
+
/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
|
|
453
461
|
get code(): number | null;
|
|
454
|
-
/**
|
|
462
|
+
/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
|
|
455
463
|
get signal(): string | null;
|
|
456
|
-
/**
|
|
464
|
+
/** Holds the typed lifecycle observation surface. */
|
|
457
465
|
get emitter(): EmitterInterface<ProcessEventMap>;
|
|
458
|
-
/**
|
|
466
|
+
/** Yields the captured stdout lines, in arrival order, ending after queued lines at the terminal moment. */
|
|
459
467
|
get lines(): AsyncIterable<string>;
|
|
460
|
-
/**
|
|
468
|
+
/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */
|
|
461
469
|
get evidence(): string;
|
|
462
|
-
/**
|
|
470
|
+
/** Reports whether the `lines` stream omitted output after a retention bound was reached. */
|
|
463
471
|
get truncated(): boolean;
|
|
464
|
-
/**
|
|
472
|
+
/** Reports whether the terminal moment arrived and `exit` settled. */
|
|
465
473
|
get settled(): boolean;
|
|
466
|
-
/**
|
|
474
|
+
/** Reports whether termination began, including after the terminal moment. */
|
|
467
475
|
get stopping(): boolean;
|
|
468
|
-
/**
|
|
469
|
-
get exit(): Promise<
|
|
476
|
+
/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */
|
|
477
|
+
get exit(): Promise<ProcessExit_2>;
|
|
470
478
|
/**
|
|
471
|
-
*
|
|
479
|
+
* Writes one line to the open standard-input channel.
|
|
472
480
|
*
|
|
473
481
|
* @remarks
|
|
474
482
|
* Never rejects. `true` means the host accepted the bytes without reporting a fault; it does not
|
|
@@ -482,7 +490,7 @@ export declare class Process implements ProcessInterface {
|
|
|
482
490
|
* for bytes the package is about to discard.
|
|
483
491
|
*
|
|
484
492
|
* @param text - The line text without its trailing newline
|
|
485
|
-
* @returns True
|
|
493
|
+
* @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)
|
|
486
494
|
*/
|
|
487
495
|
send(text: string): Promise<boolean>;
|
|
488
496
|
/**
|
|
@@ -494,7 +502,7 @@ export declare class Process implements ProcessInterface {
|
|
|
494
502
|
* and settles `exit` when they remain open. A cutoff reached before the native exit reports the
|
|
495
503
|
* `code` and `signal` the host had recorded by then, which is `null` for a child still running.
|
|
496
504
|
*
|
|
497
|
-
* @returns True
|
|
505
|
+
* @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)
|
|
498
506
|
*/
|
|
499
507
|
stop(): Promise<boolean>;
|
|
500
508
|
/**
|
|
@@ -509,15 +517,7 @@ export declare class Process implements ProcessInterface {
|
|
|
509
517
|
}
|
|
510
518
|
|
|
511
519
|
/**
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
* @remarks
|
|
515
|
-
* The host-independent contracts live in `@orkestrel/process`. This module declares only what a
|
|
516
|
-
* Node child process boundary requires, which the published contracts cannot express without
|
|
517
|
-
* naming `node:child_process` types.
|
|
518
|
-
*/
|
|
519
|
-
/**
|
|
520
|
-
* The child boundary the termination helpers drive.
|
|
520
|
+
* Represents the child boundary the termination helpers drive.
|
|
521
521
|
*
|
|
522
522
|
* @remarks
|
|
523
523
|
* A `ChildProcess` satisfies this structurally, and so does any object carrying the same
|
|
@@ -531,30 +531,42 @@ export declare class Process implements ProcessInterface {
|
|
|
531
531
|
* the route that reaches it: `killProcess` signals the negated `pid` first and falls back to `kill`
|
|
532
532
|
* when the host reports that no group owns that pid.
|
|
533
533
|
*/
|
|
534
|
-
export declare interface
|
|
535
|
-
/**
|
|
534
|
+
export declare interface ProcessChildInterface {
|
|
535
|
+
/** Holds the process id the host assigned, or `undefined` when the spawn never produced one. */
|
|
536
536
|
readonly pid?: number | undefined;
|
|
537
|
-
/**
|
|
537
|
+
/** Holds the exit code, or `null` while the process is live or a signal ended it. */
|
|
538
538
|
readonly exitCode: number | null;
|
|
539
|
-
/**
|
|
539
|
+
/** Holds the terminating signal name, or `null` while the process is live or it exited on its own. */
|
|
540
540
|
readonly signalCode: string | null;
|
|
541
541
|
/**
|
|
542
|
-
*
|
|
542
|
+
* Delivers one signal to the process.
|
|
543
543
|
*
|
|
544
544
|
* @param signal - The signal to deliver
|
|
545
|
-
* @returns True
|
|
545
|
+
* @returns True if the host accepted the signal; false otherwise
|
|
546
|
+
*
|
|
547
|
+
* @example
|
|
548
|
+
* ```ts
|
|
549
|
+
* const accepted = child.kill('SIGTERM')
|
|
550
|
+
* accepted // true
|
|
551
|
+
* ```
|
|
546
552
|
*/
|
|
547
553
|
kill(signal: NodeJS.Signals): boolean;
|
|
548
554
|
/**
|
|
549
|
-
*
|
|
555
|
+
* Registers a one-shot listener for the native exit or stream close.
|
|
550
556
|
*
|
|
551
557
|
* @param event - The `exit` or `close` event name
|
|
552
558
|
* @param listener - The listener invoked after the selected event
|
|
553
559
|
* @returns Whatever the emitter returns, which the helpers ignore
|
|
560
|
+
*
|
|
561
|
+
* @example
|
|
562
|
+
* ```ts
|
|
563
|
+
* const settle = (): void => undefined
|
|
564
|
+
* child.once('exit', settle)
|
|
565
|
+
* ```
|
|
554
566
|
*/
|
|
555
567
|
once(event: 'exit' | 'close', listener: () => void): unknown;
|
|
556
568
|
/**
|
|
557
|
-
*
|
|
569
|
+
* Releases one previously registered exit or close listener.
|
|
558
570
|
*
|
|
559
571
|
* @remarks
|
|
560
572
|
* `waitForExit` releases its `exit` listener, and `waitForClose` releases its `close` listener, so
|
|
@@ -563,12 +575,19 @@ export declare interface ProcessChild {
|
|
|
563
575
|
* @param event - The `exit` or `close` event name
|
|
564
576
|
* @param listener - The listener registered through `once`
|
|
565
577
|
* @returns Whatever the emitter returns, which the helpers ignore
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```ts
|
|
581
|
+
* const settle = (): void => undefined
|
|
582
|
+
* child.once('exit', settle)
|
|
583
|
+
* child.off('exit', settle)
|
|
584
|
+
* ```
|
|
566
585
|
*/
|
|
567
586
|
off(event: 'exit' | 'close', listener: () => void): unknown;
|
|
568
587
|
}
|
|
569
588
|
|
|
570
589
|
/**
|
|
571
|
-
*
|
|
590
|
+
* Represents a keyed registry of live supervised child processes.
|
|
572
591
|
*
|
|
573
592
|
* @remarks
|
|
574
593
|
* A child launched under an id joins the registry and emits `launch`; when it settles it removes
|
|
@@ -596,33 +615,33 @@ export declare interface ProcessChild {
|
|
|
596
615
|
* await manager.destroy()
|
|
597
616
|
* ```
|
|
598
617
|
*/
|
|
599
|
-
export declare class ProcessManager implements
|
|
618
|
+
export declare class ProcessManager implements ProcessManagerInterface_2 {
|
|
600
619
|
#private;
|
|
601
620
|
/**
|
|
602
|
-
*
|
|
621
|
+
* Constructs a process registry.
|
|
603
622
|
*
|
|
604
623
|
* @param options - Initial fleet-level observation hooks and listener-error handling
|
|
605
624
|
*/
|
|
606
|
-
constructor(options?:
|
|
607
|
-
/**
|
|
625
|
+
constructor(options?: ProcessManagerOptions_2);
|
|
626
|
+
/** Holds the typed fleet-level observation surface. */
|
|
608
627
|
get emitter(): EmitterInterface<ProcessManagerEventMap>;
|
|
609
|
-
/**
|
|
628
|
+
/** Counts the live children. */
|
|
610
629
|
get count(): number;
|
|
611
630
|
/**
|
|
612
|
-
*
|
|
631
|
+
* Returns the live child under `id`, or `undefined` when none is.
|
|
613
632
|
*
|
|
614
633
|
* @param id - The registry key
|
|
615
634
|
* @returns The child, or `undefined`
|
|
616
635
|
*/
|
|
617
|
-
process(id: string):
|
|
636
|
+
process(id: string): ProcessInterface_2 | undefined;
|
|
618
637
|
/**
|
|
619
|
-
*
|
|
638
|
+
* Returns a snapshot of every live child.
|
|
620
639
|
*
|
|
621
640
|
* @returns The live children in launch order
|
|
622
641
|
*/
|
|
623
|
-
processes(): readonly
|
|
642
|
+
processes(): readonly ProcessInterface_2[];
|
|
624
643
|
/**
|
|
625
|
-
*
|
|
644
|
+
* Spawns and registers one child under `id`.
|
|
626
645
|
*
|
|
627
646
|
* @remarks
|
|
628
647
|
* {@link Process} reads every option before it spawns, so a caller's own option getter runs while
|
|
@@ -638,29 +657,29 @@ export declare class ProcessManager implements ProcessManagerInterface {
|
|
|
638
657
|
* @returns The launched child
|
|
639
658
|
* @throws A {@link ProcessError} coded `duplicate` when `id` is already live, `protocol` when the registry is being destroyed, or `invalid` when an option or command string is malformed
|
|
640
659
|
*/
|
|
641
|
-
launch(id: string, options:
|
|
660
|
+
launch(id: string, options: ProcessOptions_2): ProcessInterface_2;
|
|
642
661
|
/**
|
|
643
|
-
*
|
|
662
|
+
* Terminates the named children and awaits their exit.
|
|
644
663
|
*
|
|
645
664
|
* @param ids - The registry keys to stop
|
|
646
|
-
* @returns True
|
|
665
|
+
* @returns True if every named child was live and its exit was confirmed; false otherwise
|
|
647
666
|
*/
|
|
648
667
|
stop(ids: readonly string[]): Promise<boolean>;
|
|
649
668
|
/**
|
|
650
|
-
*
|
|
669
|
+
* Terminates one child and awaits its exit.
|
|
651
670
|
*
|
|
652
671
|
* @param id - The registry key to stop
|
|
653
|
-
* @returns True
|
|
672
|
+
* @returns True if the child was live and its exit was confirmed; false otherwise (the id was not live, or the confirmation deadline elapsed)
|
|
654
673
|
*/
|
|
655
674
|
stop(id: string): Promise<boolean>;
|
|
656
675
|
/**
|
|
657
|
-
*
|
|
676
|
+
* Terminates every live child and awaits their exit.
|
|
658
677
|
*
|
|
659
678
|
* @returns A promise that resolves after every child stops
|
|
660
679
|
*/
|
|
661
680
|
stop(): Promise<void>;
|
|
662
681
|
/**
|
|
663
|
-
*
|
|
682
|
+
* Stops every child, then destroys the registry emitter last.
|
|
664
683
|
*
|
|
665
684
|
* @remarks
|
|
666
685
|
* Always resolves, and refuses a later `launch` with a {@link createProtocolError}. Each child is
|
|
@@ -770,33 +789,33 @@ export declare function resolveExecutable(file: string, options?: ExecutableOpti
|
|
|
770
789
|
* })
|
|
771
790
|
* ```
|
|
772
791
|
*/
|
|
773
|
-
export declare class Session implements
|
|
792
|
+
export declare class Session implements SessionInterface_2 {
|
|
774
793
|
#private;
|
|
775
794
|
/**
|
|
776
|
-
*
|
|
795
|
+
* Spawns one child process and begins byte capture.
|
|
777
796
|
*
|
|
778
797
|
* @param options - Command, workspace, termination, evidence, stdin, and observation settings
|
|
779
798
|
* @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed
|
|
780
799
|
*/
|
|
781
|
-
constructor(options:
|
|
782
|
-
/**
|
|
800
|
+
constructor(options: SessionOptions_2);
|
|
801
|
+
/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
|
|
783
802
|
get pid(): number | undefined;
|
|
784
|
-
/**
|
|
803
|
+
/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
|
|
785
804
|
get code(): number | null;
|
|
786
|
-
/**
|
|
805
|
+
/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
|
|
787
806
|
get signal(): string | null;
|
|
788
|
-
/**
|
|
807
|
+
/** Holds the typed lifecycle observation surface. */
|
|
789
808
|
get emitter(): EmitterInterface<SessionEventMap>;
|
|
790
|
-
/**
|
|
809
|
+
/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */
|
|
791
810
|
get evidence(): string;
|
|
792
|
-
/**
|
|
811
|
+
/** Reports whether the terminal moment arrived and `exit` settled. */
|
|
793
812
|
get settled(): boolean;
|
|
794
|
-
/**
|
|
813
|
+
/** Reports whether termination began, including after the terminal moment. `end` never turns it true. */
|
|
795
814
|
get stopping(): boolean;
|
|
796
|
-
/**
|
|
815
|
+
/** Settles at the child's own ending, awaited without the terminal moment's drain window. */
|
|
797
816
|
get ending(): Promise<void>;
|
|
798
|
-
/**
|
|
799
|
-
get exit(): Promise<
|
|
817
|
+
/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */
|
|
818
|
+
get exit(): Promise<ProcessExit_2>;
|
|
800
819
|
/**
|
|
801
820
|
* Writes raw bytes to the open standard-input channel.
|
|
802
821
|
*
|
|
@@ -807,7 +826,7 @@ export declare class Session implements SessionInterface {
|
|
|
807
826
|
* returned promise settles.
|
|
808
827
|
*
|
|
809
828
|
* @param bytes - The payload to write, already framed by the caller
|
|
810
|
-
* @returns True
|
|
829
|
+
* @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)
|
|
811
830
|
*/
|
|
812
831
|
write(bytes: Uint8Array): Promise<boolean>;
|
|
813
832
|
/**
|
|
@@ -827,7 +846,7 @@ export declare class Session implements SessionInterface {
|
|
|
827
846
|
* @remarks
|
|
828
847
|
* Never rejects, and every call shares one termination bounded by `grace` and `drain`.
|
|
829
848
|
*
|
|
830
|
-
* @returns True
|
|
849
|
+
* @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)
|
|
831
850
|
*/
|
|
832
851
|
stop(): Promise<boolean>;
|
|
833
852
|
/**
|
|
@@ -880,14 +899,210 @@ export declare function snapshotCommand(command: ProcessCommand): ProcessCommand
|
|
|
880
899
|
* @param child - The child boundary
|
|
881
900
|
* @param grace - The cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL`
|
|
882
901
|
* @param confirm - The milliseconds the native exit is awaited after the final kill
|
|
883
|
-
* @returns True
|
|
902
|
+
* @returns True if the native exit was observed; false otherwise (`confirm` elapsed without it)
|
|
884
903
|
*
|
|
885
904
|
* @example
|
|
886
905
|
* ```ts
|
|
887
906
|
* const confirmed = await stopChild(child, 5_000, 5_000)
|
|
888
907
|
* ```
|
|
889
908
|
*/
|
|
890
|
-
export declare function stopChild(child:
|
|
909
|
+
export declare function stopChild(child: ProcessChildInterface, grace: number, confirm: number): Promise<boolean>;
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Supervises one child process and reports each lifecycle moment to the face composing it.
|
|
913
|
+
*
|
|
914
|
+
* @remarks
|
|
915
|
+
* This is the engine every supervised-child face shares. It owns the eager spawn, the byte-bounded
|
|
916
|
+
* stderr tail and its decoded chunks, the standard-input channel and its bounded confirmation, the
|
|
917
|
+
* termination sequence, and the progression from the child's native exit through the bounded `drain`
|
|
918
|
+
* window to one terminal moment. It owns no output framing and no observation surface: a face
|
|
919
|
+
* attaches its own consumer to `stdout`, frames bytes however its contract promises, and owns the
|
|
920
|
+
* emitter and event map its consumers subscribe to.
|
|
921
|
+
*
|
|
922
|
+
* The child's ending and the supervision's ending are distinct. `pid`, `code`, and `signal` read the
|
|
923
|
+
* host child directly, so they expose native exit as soon as the host records it, and `ending`
|
|
924
|
+
* settles at that same moment. `settled`, `exit`, and `evidence` reach one terminal moment after the
|
|
925
|
+
* read channels close or the bounded `drain` window cuts them off. That window is armed by the
|
|
926
|
+
* child's native exit and by a termination this package initiated, so every way a child can end
|
|
927
|
+
* reaches the moment. The terminal routine hands the face its `close` and `terminal` moments before
|
|
928
|
+
* it destroys stdout and stderr, so a face's own pull surfaces are final while its read ends still
|
|
929
|
+
* exist.
|
|
930
|
+
*
|
|
931
|
+
* The face is a set of callbacks rather than an emitter, because each face publishes a different
|
|
932
|
+
* event map over the same moments. `chunk` and `fault` carry the live stderr text and the child or
|
|
933
|
+
* channel faults, `relieve` reports that a termination began so the face can release whatever
|
|
934
|
+
* backpressure it holds, `close` ends the face's read pipeline at the terminal moment, `terminal`
|
|
935
|
+
* carries the frozen {@link ProcessExit}, and `teardown` releases the face's own surface after the
|
|
936
|
+
* termination completes. `relieve` is optional because a face that never pauses the child's output
|
|
937
|
+
* holds no backpressure to release, and a face with nothing to do there would otherwise declare an
|
|
938
|
+
* empty method to say so.
|
|
939
|
+
*
|
|
940
|
+
* @example
|
|
941
|
+
* ```ts
|
|
942
|
+
* import { Supervisor } from '@orkestrel/process/server'
|
|
943
|
+
*
|
|
944
|
+
* const engine = new Supervisor(
|
|
945
|
+
* { command: { file: 'node', arguments: ['--version'] }, workspace: process.cwd() },
|
|
946
|
+
* {
|
|
947
|
+
* chunk: () => undefined,
|
|
948
|
+
* fault: () => undefined,
|
|
949
|
+
* close: () => undefined,
|
|
950
|
+
* terminal: () => undefined,
|
|
951
|
+
* teardown: () => undefined,
|
|
952
|
+
* },
|
|
953
|
+
* )
|
|
954
|
+
* const exit = await engine.exit
|
|
955
|
+
* exit.code // 0
|
|
956
|
+
* await engine.destroy()
|
|
957
|
+
* ```
|
|
958
|
+
*/
|
|
959
|
+
export declare class Supervisor {
|
|
960
|
+
#private;
|
|
961
|
+
/**
|
|
962
|
+
* Spawns one child process and begins standard-error capture.
|
|
963
|
+
*
|
|
964
|
+
* @remarks
|
|
965
|
+
* The face's callbacks are captured before anything is read or spawned, so the first moment the
|
|
966
|
+
* child can produce already has somewhere to go. `options` supplies the command, workspace,
|
|
967
|
+
* termination, capture, and standard-input settings; a face's own settings, such as an output
|
|
968
|
+
* retention bound, are read and validated by that face before it constructs this engine, so an
|
|
969
|
+
* invalid one refuses construction while nothing has been spawned.
|
|
970
|
+
*
|
|
971
|
+
* @param options - Command, workspace, termination, capture, and stdin settings
|
|
972
|
+
* @param face - The composing face's callbacks for each lifecycle moment
|
|
973
|
+
* @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed
|
|
974
|
+
*/
|
|
975
|
+
constructor(options: ProcessOptions_2, face: SupervisorFace);
|
|
976
|
+
/** Holds the child's standard-output stream, for the composing face to attach its own consumer to. */
|
|
977
|
+
get stdout(): Readable;
|
|
978
|
+
/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
|
|
979
|
+
get pid(): number | undefined;
|
|
980
|
+
/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
|
|
981
|
+
get code(): number | null;
|
|
982
|
+
/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
|
|
983
|
+
get signal(): string | null;
|
|
984
|
+
/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */
|
|
985
|
+
get evidence(): string;
|
|
986
|
+
/** Reports whether the terminal moment arrived and `exit` settled. */
|
|
987
|
+
get settled(): boolean;
|
|
988
|
+
/** Reports whether termination began, including after the terminal moment. */
|
|
989
|
+
get stopping(): boolean;
|
|
990
|
+
/**
|
|
991
|
+
* Settles at the child's own ending, awaited without the terminal moment's drain window.
|
|
992
|
+
*
|
|
993
|
+
* @remarks
|
|
994
|
+
* Never rejects, and resolves no value: `code` and `signal` carry the terminal facts as soon as
|
|
995
|
+
* the host records them. It settles at the native exit, and at the terminal moment for a child
|
|
996
|
+
* whose spawn produced no native exit at all, so it can never outlive the supervision.
|
|
997
|
+
*/
|
|
998
|
+
get ending(): Promise<void>;
|
|
999
|
+
/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */
|
|
1000
|
+
get exit(): Promise<ProcessExit_2>;
|
|
1001
|
+
/**
|
|
1002
|
+
* Writes raw bytes to the open standard-input channel.
|
|
1003
|
+
*
|
|
1004
|
+
* @remarks
|
|
1005
|
+
* Never rejects, and adds no framing: a face composes whatever terminator its contract promises
|
|
1006
|
+
* before it calls this. `true` means the host accepted the bytes without reporting a fault; it
|
|
1007
|
+
* does not prove that the child read them. An ordinary write settles when the kernel accepts it.
|
|
1008
|
+
* Only a full pipe can hold the write unconfirmed. The `delivery` option can bound that wait, and
|
|
1009
|
+
* every terminal teardown path settles pending writes. After `stop` or `destroy` begins, a later
|
|
1010
|
+
* call settles `false`, because teardown cannot confirm delivery for bytes it is about to
|
|
1011
|
+
* discard.
|
|
1012
|
+
*
|
|
1013
|
+
* @param bytes - The payload to write, already framed by the caller
|
|
1014
|
+
* @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)
|
|
1015
|
+
*
|
|
1016
|
+
* @example
|
|
1017
|
+
* ```ts
|
|
1018
|
+
* import { Supervisor } from '@orkestrel/process/server'
|
|
1019
|
+
*
|
|
1020
|
+
* const engine = new Supervisor(
|
|
1021
|
+
* {
|
|
1022
|
+
* command: { file: 'node', arguments: ['-e', 'process.stdin.pipe(process.stdout)'] },
|
|
1023
|
+
* workspace: process.cwd(),
|
|
1024
|
+
* writable: true,
|
|
1025
|
+
* },
|
|
1026
|
+
* {
|
|
1027
|
+
* chunk: () => undefined,
|
|
1028
|
+
* fault: () => undefined,
|
|
1029
|
+
* close: () => undefined,
|
|
1030
|
+
* terminal: () => undefined,
|
|
1031
|
+
* teardown: () => undefined,
|
|
1032
|
+
* },
|
|
1033
|
+
* )
|
|
1034
|
+
* const accepted = await engine.deliver(new TextEncoder().encode('ping\n'))
|
|
1035
|
+
* accepted // true
|
|
1036
|
+
* await engine.destroy()
|
|
1037
|
+
* ```
|
|
1038
|
+
*/
|
|
1039
|
+
deliver(bytes: Uint8Array): Promise<boolean>;
|
|
1040
|
+
/**
|
|
1041
|
+
* Closes the standard-input channel while leaving the child running.
|
|
1042
|
+
*
|
|
1043
|
+
* @remarks
|
|
1044
|
+
* Never rejects, and terminates nothing: no signal is sent, `stopping` stays false, no drain
|
|
1045
|
+
* window is armed, and the terminal moment does not arrive. The child observes end of input and
|
|
1046
|
+
* decides for itself what to do about it, which is what separates this from `stop`.
|
|
1047
|
+
*
|
|
1048
|
+
* Every call shares one barrier, and it resolves after the host flushes the writes it had already
|
|
1049
|
+
* accepted, or reports that it cannot. A `deliver` after this call resolves `false`, because the
|
|
1050
|
+
* host stops reporting the channel writable the moment it is ended. That same flag keeps the
|
|
1051
|
+
* ended channel quiet for its remaining life, so a later host fault on it settles pending writes
|
|
1052
|
+
* and reaches no face. After `stop` or `destroy` has begun, or after the terminal moment, the
|
|
1053
|
+
* call resolves and changes nothing, because the channel is already being discarded.
|
|
1054
|
+
*
|
|
1055
|
+
* @returns The stable barrier shared by every call
|
|
1056
|
+
*/
|
|
1057
|
+
end(): Promise<void>;
|
|
1058
|
+
/**
|
|
1059
|
+
* Terminates the child process tree and reaches the terminal observation moment.
|
|
1060
|
+
*
|
|
1061
|
+
* @remarks
|
|
1062
|
+
* Never rejects, and every call shares one termination. After the termination sequence returns,
|
|
1063
|
+
* confirmed or not, it waits at most `drain` for the read channels to close, then cuts them off
|
|
1064
|
+
* and settles `exit` when they remain open. A cutoff reached before the native exit reports the
|
|
1065
|
+
* `code` and `signal` the host had recorded by then, which is `null` for a child still running.
|
|
1066
|
+
*
|
|
1067
|
+
* @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)
|
|
1068
|
+
*/
|
|
1069
|
+
stop(): Promise<boolean>;
|
|
1070
|
+
/**
|
|
1071
|
+
* Stops the child and releases the composing face after the terminal state freezes.
|
|
1072
|
+
*
|
|
1073
|
+
* @remarks
|
|
1074
|
+
* Always resolves, including when termination was never confirmed. Every call shares one barrier.
|
|
1075
|
+
*
|
|
1076
|
+
* @returns The stable barrier shared by every call
|
|
1077
|
+
*/
|
|
1078
|
+
destroy(): Promise<void>;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Represents the composing face's callbacks for each lifecycle moment of one supervised child.
|
|
1083
|
+
*
|
|
1084
|
+
* @remarks
|
|
1085
|
+
* `Process` and `Session` each construct one and hand it to the supervision engine, which captures
|
|
1086
|
+
* every callback before anything is read or spawned, so the first moment the child can produce
|
|
1087
|
+
* already has somewhere to go. `chunk` receives each decoded standard-error fragment, `fault` the
|
|
1088
|
+
* host error that ended the run, `close` the moment the read channels closed, `terminal` the frozen
|
|
1089
|
+
* exit state, and `teardown` the release of whatever the face still holds. `relieve` is optional
|
|
1090
|
+
* because a face that never pauses the child's output holds no backpressure to release.
|
|
1091
|
+
*/
|
|
1092
|
+
export declare interface SupervisorFace {
|
|
1093
|
+
/** Receives one decoded standard-error fragment. */
|
|
1094
|
+
readonly chunk: (text: string) => void;
|
|
1095
|
+
/** Receives the host error that ended the run. */
|
|
1096
|
+
readonly fault: (cause: unknown) => void;
|
|
1097
|
+
/** Reports that a termination began, so a face holding output backpressure releases it. */
|
|
1098
|
+
readonly relieve?: () => void;
|
|
1099
|
+
/** Reports that the child's read channels closed. */
|
|
1100
|
+
readonly close: () => void;
|
|
1101
|
+
/** Receives the frozen terminal state. */
|
|
1102
|
+
readonly terminal: (exit: ProcessExit) => void;
|
|
1103
|
+
/** Releases whatever the face still holds after the terminal moment. */
|
|
1104
|
+
readonly teardown: () => void;
|
|
1105
|
+
}
|
|
891
1106
|
|
|
892
1107
|
/**
|
|
893
1108
|
* Trims a buffer to at most `limit` leading bytes without splitting a UTF-8 sequence.
|
|
@@ -1036,14 +1251,14 @@ export declare function validateWorkspace(workspace: string | undefined): void;
|
|
|
1036
1251
|
*
|
|
1037
1252
|
* @param child - The child boundary
|
|
1038
1253
|
* @param timeout - The milliseconds to wait before giving up
|
|
1039
|
-
* @returns True
|
|
1254
|
+
* @returns True if the host close arrived inside the deadline; false otherwise
|
|
1040
1255
|
*
|
|
1041
1256
|
* @example
|
|
1042
1257
|
* ```ts
|
|
1043
1258
|
* const closed = await waitForClose(child, 5_000)
|
|
1044
1259
|
* ```
|
|
1045
1260
|
*/
|
|
1046
|
-
export declare function waitForClose(child: Pick<
|
|
1261
|
+
export declare function waitForClose(child: Pick<ProcessChildInterface, 'once' | 'off'>, timeout: number): Promise<boolean>;
|
|
1047
1262
|
|
|
1048
1263
|
/**
|
|
1049
1264
|
* Waits for one child process's native exit, bounded by a deadline.
|
|
@@ -1057,6 +1272,6 @@ export declare function waitForClose(child: Pick<ProcessChild, 'once' | 'off'>,
|
|
|
1057
1272
|
* await waitForExit(child, 5_000)
|
|
1058
1273
|
* ```
|
|
1059
1274
|
*/
|
|
1060
|
-
export declare function waitForExit(child: Pick<
|
|
1275
|
+
export declare function waitForExit(child: Pick<ProcessChildInterface, 'exitCode' | 'signalCode' | 'once' | 'off'>, timeout: number): Promise<void>;
|
|
1061
1276
|
|
|
1062
1277
|
export { }
|