@orkestrel/process 0.0.9 → 0.0.11
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 +18 -23
- package/dist/src/core/index.cjs +33 -17
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +171 -148
- package/dist/src/core/index.d.ts +171 -148
- package/dist/src/core/index.js +33 -17
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +157 -97
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +316 -93
- package/dist/src/server/index.d.ts +316 -93
- package/dist/src/server/index.js +157 -98
- package/dist/src/server/index.js.map +1 -1
- package/package.json +11 -12
|
@@ -9,6 +9,42 @@ let _src_core = require("../core/index.cjs");
|
|
|
9
9
|
let node_readline = require("node:readline");
|
|
10
10
|
let _orkestrel_emitter = require("@orkestrel/emitter");
|
|
11
11
|
let node_string_decoder = require("node:string_decoder");
|
|
12
|
+
//#region src/server/cloners.ts
|
|
13
|
+
/**
|
|
14
|
+
* Takes one owned frozen snapshot of a caller's command.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* Every public entry point snapshots before it validates, so the object validated is the object
|
|
18
|
+
* spawned. Each property is read exactly once, because reading one runs the caller's own getter: a
|
|
19
|
+
* command whose `file` changes between reads would otherwise validate one executable and spawn
|
|
20
|
+
* another. The argument vector and the environment record are copied and frozen, so a caller
|
|
21
|
+
* mutating either after the call cannot reach the spawn. An absent optional stays absent rather than
|
|
22
|
+
* becoming an explicit `undefined`.
|
|
23
|
+
*
|
|
24
|
+
* @param command - The caller's command, whose properties may be getters
|
|
25
|
+
* @returns A frozen command carrying the values read at this instant
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* snapshotCommand({ file: 'git', arguments: ['status'] }) // { file: 'git', arguments: ['status'] }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function snapshotCommand(command) {
|
|
33
|
+
const file = command.file;
|
|
34
|
+
const argumentsList = Object.freeze([...command.arguments]);
|
|
35
|
+
const sourceEnvironment = command.environment;
|
|
36
|
+
const environment = sourceEnvironment === void 0 ? void 0 : Object.freeze({ ...sourceEnvironment });
|
|
37
|
+
const input = command.input;
|
|
38
|
+
const isolated = command.isolated;
|
|
39
|
+
return Object.freeze({
|
|
40
|
+
file,
|
|
41
|
+
arguments: argumentsList,
|
|
42
|
+
...environment === void 0 ? {} : { environment },
|
|
43
|
+
...input === void 0 ? {} : { input },
|
|
44
|
+
...isolated === void 0 ? {} : { isolated }
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
12
48
|
//#region src/server/helpers.ts
|
|
13
49
|
/**
|
|
14
50
|
* Trims a buffer to at most `limit` trailing bytes without splitting a UTF-8 sequence.
|
|
@@ -107,40 +143,6 @@ function captureChunk(chunk, room) {
|
|
|
107
143
|
return node_buffer.Buffer.from(chunk.subarray(0, room));
|
|
108
144
|
}
|
|
109
145
|
/**
|
|
110
|
-
* Takes one owned frozen snapshot of a caller's command.
|
|
111
|
-
*
|
|
112
|
-
* @remarks
|
|
113
|
-
* Every public entry point snapshots before it validates, so the object validated is the object
|
|
114
|
-
* spawned. Each property is read exactly once, because reading one runs the caller's own getter: a
|
|
115
|
-
* command whose `file` changes between reads would otherwise validate one executable and spawn
|
|
116
|
-
* another. The argument vector and the environment record are copied and frozen, so a caller
|
|
117
|
-
* mutating either after the call cannot reach the spawn. An absent optional stays absent rather than
|
|
118
|
-
* becoming an explicit `undefined`.
|
|
119
|
-
*
|
|
120
|
-
* @param command - The caller's command, whose properties may be getters
|
|
121
|
-
* @returns A frozen command carrying the values read at this instant
|
|
122
|
-
*
|
|
123
|
-
* @example
|
|
124
|
-
* ```ts
|
|
125
|
-
* snapshotCommand({ file: 'git', arguments: ['status'] }) // { file: 'git', arguments: ['status'] }
|
|
126
|
-
* ```
|
|
127
|
-
*/
|
|
128
|
-
function snapshotCommand(command) {
|
|
129
|
-
const file = command.file;
|
|
130
|
-
const argumentsList = Object.freeze([...command.arguments]);
|
|
131
|
-
const sourceEnvironment = command.environment;
|
|
132
|
-
const environment = sourceEnvironment === void 0 ? void 0 : Object.freeze({ ...sourceEnvironment });
|
|
133
|
-
const input = command.input;
|
|
134
|
-
const isolated = command.isolated;
|
|
135
|
-
return Object.freeze({
|
|
136
|
-
file,
|
|
137
|
-
arguments: argumentsList,
|
|
138
|
-
...environment === void 0 ? {} : { environment },
|
|
139
|
-
...input === void 0 ? {} : { input },
|
|
140
|
-
...isolated === void 0 ? {} : { isolated }
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
146
|
* Renders one command into its diagnostic command line.
|
|
145
147
|
*
|
|
146
148
|
* @param command - The executable and its argument vector
|
|
@@ -257,7 +259,7 @@ function mergeEnvironment(isolated, base, override) {
|
|
|
257
259
|
* command. An unreadable or malformed path reports `false` rather than throwing.
|
|
258
260
|
*
|
|
259
261
|
* @param target - The absolute or relative path to inspect
|
|
260
|
-
* @returns True
|
|
262
|
+
* @returns True if the path resolves to a regular file; false otherwise
|
|
261
263
|
*
|
|
262
264
|
* @example
|
|
263
265
|
* ```ts
|
|
@@ -305,7 +307,8 @@ function buildExecutableCandidates(file, workspace, environment, platform) {
|
|
|
305
307
|
return Object.freeze(targets);
|
|
306
308
|
}
|
|
307
309
|
/**
|
|
308
|
-
* Resolves a command file to the executable path the host would launch
|
|
310
|
+
* Resolves a command file to the executable path the host would launch, or to `undefined` on a POSIX
|
|
311
|
+
* host, which performs its own lookup.
|
|
309
312
|
*
|
|
310
313
|
* @param file - The command executable name or path
|
|
311
314
|
* @param options - The directory searched first and the child's effective environment
|
|
@@ -530,7 +533,7 @@ function validateWorkspace(workspace) {
|
|
|
530
533
|
* initiated against a pid the host may have reused.
|
|
531
534
|
*
|
|
532
535
|
* @param child - The child boundary
|
|
533
|
-
* @returns True
|
|
536
|
+
* @returns True if the process has exited; false otherwise
|
|
534
537
|
*
|
|
535
538
|
* @example
|
|
536
539
|
* ```ts
|
|
@@ -586,7 +589,7 @@ function killProcess(child, signal) {
|
|
|
586
589
|
*
|
|
587
590
|
* @param pid - The root process id of the tree to end
|
|
588
591
|
* @param timeout - The milliseconds the utility is given before it is killed
|
|
589
|
-
* @returns True
|
|
592
|
+
* @returns True if the utility reported success; false otherwise (it failed, was unavailable, or was cut off)
|
|
590
593
|
*
|
|
591
594
|
* @example
|
|
592
595
|
* ```ts
|
|
@@ -637,7 +640,7 @@ function waitForExit(child, timeout) {
|
|
|
637
640
|
*
|
|
638
641
|
* @param child - The child boundary
|
|
639
642
|
* @param timeout - The milliseconds to wait before giving up
|
|
640
|
-
* @returns True
|
|
643
|
+
* @returns True if the host close arrived inside the deadline; false otherwise
|
|
641
644
|
*
|
|
642
645
|
* @example
|
|
643
646
|
* ```ts
|
|
@@ -672,7 +675,7 @@ function waitForClose(child, timeout) {
|
|
|
672
675
|
* @param child - The child boundary
|
|
673
676
|
* @param grace - The cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL`
|
|
674
677
|
* @param confirm - The milliseconds the native exit is awaited after the final kill
|
|
675
|
-
* @returns True
|
|
678
|
+
* @returns True if the native exit was observed; false otherwise (`confirm` elapsed without it)
|
|
676
679
|
*
|
|
677
680
|
* @example
|
|
678
681
|
* ```ts
|
|
@@ -1030,7 +1033,7 @@ function detach(command, options) {
|
|
|
1030
1033
|
child.unref();
|
|
1031
1034
|
}
|
|
1032
1035
|
//#endregion
|
|
1033
|
-
//#region src/server/Supervisor.ts
|
|
1036
|
+
//#region src/server/processes/Supervisor.ts
|
|
1034
1037
|
/**
|
|
1035
1038
|
* Supervises one child process and reports each lifecycle moment to the face composing it.
|
|
1036
1039
|
*
|
|
@@ -1059,6 +1062,25 @@ function detach(command, options) {
|
|
|
1059
1062
|
* termination completes. `relieve` is optional because a face that never pauses the child's output
|
|
1060
1063
|
* holds no backpressure to release, and a face with nothing to do there would otherwise declare an
|
|
1061
1064
|
* empty method to say so.
|
|
1065
|
+
*
|
|
1066
|
+
* @example
|
|
1067
|
+
* ```ts
|
|
1068
|
+
* import { Supervisor } from '@orkestrel/process/server'
|
|
1069
|
+
*
|
|
1070
|
+
* const engine = new Supervisor(
|
|
1071
|
+
* { command: { file: 'node', arguments: ['--version'] }, workspace: process.cwd() },
|
|
1072
|
+
* {
|
|
1073
|
+
* chunk: () => undefined,
|
|
1074
|
+
* fault: () => undefined,
|
|
1075
|
+
* close: () => undefined,
|
|
1076
|
+
* terminal: () => undefined,
|
|
1077
|
+
* teardown: () => undefined,
|
|
1078
|
+
* },
|
|
1079
|
+
* )
|
|
1080
|
+
* const exit = await engine.exit
|
|
1081
|
+
* exit.code // 0
|
|
1082
|
+
* await engine.destroy()
|
|
1083
|
+
* ```
|
|
1062
1084
|
*/
|
|
1063
1085
|
var Supervisor = class {
|
|
1064
1086
|
#chunk;
|
|
@@ -1088,7 +1110,7 @@ var Supervisor = class {
|
|
|
1088
1110
|
#termination;
|
|
1089
1111
|
#destruction;
|
|
1090
1112
|
/**
|
|
1091
|
-
*
|
|
1113
|
+
* Spawns one child process and begins standard-error capture.
|
|
1092
1114
|
*
|
|
1093
1115
|
* @remarks
|
|
1094
1116
|
* The face's callbacks are captured before anything is read or spawned, so the first moment the
|
|
@@ -1165,36 +1187,36 @@ var Supervisor = class {
|
|
|
1165
1187
|
if (signal.aborted) this.stop();
|
|
1166
1188
|
}
|
|
1167
1189
|
}
|
|
1168
|
-
/**
|
|
1190
|
+
/** Holds the child's standard-output stream, for the composing face to attach its own consumer to. */
|
|
1169
1191
|
get stdout() {
|
|
1170
1192
|
return this.#child.stdout;
|
|
1171
1193
|
}
|
|
1172
|
-
/**
|
|
1194
|
+
/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
|
|
1173
1195
|
get pid() {
|
|
1174
1196
|
return this.#child.pid;
|
|
1175
1197
|
}
|
|
1176
|
-
/**
|
|
1198
|
+
/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
|
|
1177
1199
|
get code() {
|
|
1178
1200
|
return this.#child.exitCode;
|
|
1179
1201
|
}
|
|
1180
|
-
/**
|
|
1202
|
+
/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
|
|
1181
1203
|
get signal() {
|
|
1182
1204
|
return this.#child.signalCode;
|
|
1183
1205
|
}
|
|
1184
|
-
/**
|
|
1206
|
+
/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */
|
|
1185
1207
|
get evidence() {
|
|
1186
1208
|
return this.#tail.toString("utf8");
|
|
1187
1209
|
}
|
|
1188
|
-
/**
|
|
1210
|
+
/** Reports whether the terminal moment arrived and `exit` settled. */
|
|
1189
1211
|
get settled() {
|
|
1190
1212
|
return this.#settled;
|
|
1191
1213
|
}
|
|
1192
|
-
/**
|
|
1214
|
+
/** Reports whether termination began, including after the terminal moment. */
|
|
1193
1215
|
get stopping() {
|
|
1194
1216
|
return this.#stopping;
|
|
1195
1217
|
}
|
|
1196
1218
|
/**
|
|
1197
|
-
*
|
|
1219
|
+
* Settles at the child's own ending, awaited without the terminal moment's drain window.
|
|
1198
1220
|
*
|
|
1199
1221
|
* @remarks
|
|
1200
1222
|
* Never rejects, and resolves no value: `code` and `signal` carry the terminal facts as soon as
|
|
@@ -1204,7 +1226,7 @@ var Supervisor = class {
|
|
|
1204
1226
|
get ending() {
|
|
1205
1227
|
return this.#ending.promise;
|
|
1206
1228
|
}
|
|
1207
|
-
/**
|
|
1229
|
+
/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */
|
|
1208
1230
|
get exit() {
|
|
1209
1231
|
return this.#exit.promise;
|
|
1210
1232
|
}
|
|
@@ -1221,7 +1243,30 @@ var Supervisor = class {
|
|
|
1221
1243
|
* discard.
|
|
1222
1244
|
*
|
|
1223
1245
|
* @param bytes - The payload to write, already framed by the caller
|
|
1224
|
-
* @returns True
|
|
1246
|
+
* @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`)
|
|
1247
|
+
*
|
|
1248
|
+
* @example
|
|
1249
|
+
* ```ts
|
|
1250
|
+
* import { Supervisor } from '@orkestrel/process/server'
|
|
1251
|
+
*
|
|
1252
|
+
* const engine = new Supervisor(
|
|
1253
|
+
* {
|
|
1254
|
+
* command: { file: 'node', arguments: ['-e', 'process.stdin.pipe(process.stdout)'] },
|
|
1255
|
+
* workspace: process.cwd(),
|
|
1256
|
+
* writable: true,
|
|
1257
|
+
* },
|
|
1258
|
+
* {
|
|
1259
|
+
* chunk: () => undefined,
|
|
1260
|
+
* fault: () => undefined,
|
|
1261
|
+
* close: () => undefined,
|
|
1262
|
+
* terminal: () => undefined,
|
|
1263
|
+
* teardown: () => undefined,
|
|
1264
|
+
* },
|
|
1265
|
+
* )
|
|
1266
|
+
* const accepted = await engine.deliver(new TextEncoder().encode('ping\n'))
|
|
1267
|
+
* accepted // true
|
|
1268
|
+
* await engine.destroy()
|
|
1269
|
+
* ```
|
|
1225
1270
|
*/
|
|
1226
1271
|
deliver(bytes) {
|
|
1227
1272
|
const stdin = this.#child.stdin;
|
|
@@ -1272,7 +1317,7 @@ var Supervisor = class {
|
|
|
1272
1317
|
* and settles `exit` when they remain open. A cutoff reached before the native exit reports the
|
|
1273
1318
|
* `code` and `signal` the host had recorded by then, which is `null` for a child still running.
|
|
1274
1319
|
*
|
|
1275
|
-
* @returns True
|
|
1320
|
+
* @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)
|
|
1276
1321
|
*/
|
|
1277
1322
|
stop() {
|
|
1278
1323
|
if (this.#termination !== void 0) return this.#termination;
|
|
@@ -1400,9 +1445,10 @@ var Supervisor = class {
|
|
|
1400
1445
|
}
|
|
1401
1446
|
};
|
|
1402
1447
|
//#endregion
|
|
1403
|
-
//#region src/server/Process.ts
|
|
1448
|
+
//#region src/server/processes/Process.ts
|
|
1404
1449
|
/**
|
|
1405
|
-
* Supervises one child
|
|
1450
|
+
* Supervises one child, frames its standard output into lines under a bounded backlog, and keeps
|
|
1451
|
+
* every observation channel aligned at termination.
|
|
1406
1452
|
*
|
|
1407
1453
|
* @remarks
|
|
1408
1454
|
* The child's ending and the supervision's ending are distinct. `pid`, `code`, and `signal` read
|
|
@@ -1447,7 +1493,7 @@ var Process = class {
|
|
|
1447
1493
|
#truncated = false;
|
|
1448
1494
|
#ended = false;
|
|
1449
1495
|
/**
|
|
1450
|
-
*
|
|
1496
|
+
* Spawns one child process and begins stream capture.
|
|
1451
1497
|
*
|
|
1452
1498
|
* @param options - Command, workspace, termination, capture, stdin, and observation settings
|
|
1453
1499
|
* @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed
|
|
@@ -1502,48 +1548,48 @@ var Process = class {
|
|
|
1502
1548
|
this.#reader.on("line", this.#push.bind(this));
|
|
1503
1549
|
this.#reader.once("close", this.#finish.bind(this));
|
|
1504
1550
|
}
|
|
1505
|
-
/**
|
|
1551
|
+
/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
|
|
1506
1552
|
get pid() {
|
|
1507
1553
|
return this.#engine.pid;
|
|
1508
1554
|
}
|
|
1509
|
-
/**
|
|
1555
|
+
/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
|
|
1510
1556
|
get code() {
|
|
1511
1557
|
return this.#engine.code;
|
|
1512
1558
|
}
|
|
1513
|
-
/**
|
|
1559
|
+
/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
|
|
1514
1560
|
get signal() {
|
|
1515
1561
|
return this.#engine.signal;
|
|
1516
1562
|
}
|
|
1517
|
-
/**
|
|
1563
|
+
/** Holds the typed lifecycle observation surface. */
|
|
1518
1564
|
get emitter() {
|
|
1519
1565
|
return this.#emitter;
|
|
1520
1566
|
}
|
|
1521
|
-
/**
|
|
1567
|
+
/** Yields the captured stdout lines, in arrival order, ending after queued lines at the terminal moment. */
|
|
1522
1568
|
get lines() {
|
|
1523
1569
|
return this.#lines;
|
|
1524
1570
|
}
|
|
1525
|
-
/**
|
|
1571
|
+
/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */
|
|
1526
1572
|
get evidence() {
|
|
1527
1573
|
return this.#engine.evidence;
|
|
1528
1574
|
}
|
|
1529
|
-
/**
|
|
1575
|
+
/** Reports whether the `lines` stream omitted output after a retention bound was reached. */
|
|
1530
1576
|
get truncated() {
|
|
1531
1577
|
return this.#truncated;
|
|
1532
1578
|
}
|
|
1533
|
-
/**
|
|
1579
|
+
/** Reports whether the terminal moment arrived and `exit` settled. */
|
|
1534
1580
|
get settled() {
|
|
1535
1581
|
return this.#engine.settled;
|
|
1536
1582
|
}
|
|
1537
|
-
/**
|
|
1583
|
+
/** Reports whether termination began, including after the terminal moment. */
|
|
1538
1584
|
get stopping() {
|
|
1539
1585
|
return this.#engine.stopping;
|
|
1540
1586
|
}
|
|
1541
|
-
/**
|
|
1587
|
+
/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */
|
|
1542
1588
|
get exit() {
|
|
1543
1589
|
return this.#engine.exit;
|
|
1544
1590
|
}
|
|
1545
1591
|
/**
|
|
1546
|
-
*
|
|
1592
|
+
* Writes one line to the open standard-input channel.
|
|
1547
1593
|
*
|
|
1548
1594
|
* @remarks
|
|
1549
1595
|
* Never rejects. `true` means the host accepted the bytes without reporting a fault; it does not
|
|
@@ -1557,7 +1603,7 @@ var Process = class {
|
|
|
1557
1603
|
* for bytes the package is about to discard.
|
|
1558
1604
|
*
|
|
1559
1605
|
* @param text - The line text without its trailing newline
|
|
1560
|
-
* @returns True
|
|
1606
|
+
* @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`)
|
|
1561
1607
|
*/
|
|
1562
1608
|
send(text) {
|
|
1563
1609
|
return this.#engine.deliver(node_buffer.Buffer.from(`${text}\n`, "utf8"));
|
|
@@ -1571,7 +1617,7 @@ var Process = class {
|
|
|
1571
1617
|
* and settles `exit` when they remain open. A cutoff reached before the native exit reports the
|
|
1572
1618
|
* `code` and `signal` the host had recorded by then, which is `null` for a child still running.
|
|
1573
1619
|
*
|
|
1574
|
-
* @returns True
|
|
1620
|
+
* @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)
|
|
1575
1621
|
*/
|
|
1576
1622
|
stop() {
|
|
1577
1623
|
return this.#engine.stop();
|
|
@@ -1689,9 +1735,10 @@ var Process = class {
|
|
|
1689
1735
|
}
|
|
1690
1736
|
};
|
|
1691
1737
|
//#endregion
|
|
1692
|
-
//#region src/server/ProcessManager.ts
|
|
1738
|
+
//#region src/server/processes/ProcessManager.ts
|
|
1693
1739
|
/**
|
|
1694
|
-
*
|
|
1740
|
+
* Launches supervised children under caller-chosen ids, evicts each one as it settles, and destroys
|
|
1741
|
+
* every live child on teardown.
|
|
1695
1742
|
*
|
|
1696
1743
|
* @remarks
|
|
1697
1744
|
* A child launched under an id joins the registry and emits `launch`; when it settles it removes
|
|
@@ -1727,7 +1774,7 @@ var ProcessManager = class {
|
|
|
1727
1774
|
#destroying = false;
|
|
1728
1775
|
#ending;
|
|
1729
1776
|
/**
|
|
1730
|
-
*
|
|
1777
|
+
* Constructs a process registry.
|
|
1731
1778
|
*
|
|
1732
1779
|
* @param options - Initial fleet-level observation hooks and listener-error handling
|
|
1733
1780
|
*/
|
|
@@ -1739,16 +1786,16 @@ var ProcessManager = class {
|
|
|
1739
1786
|
...error === void 0 ? {} : { error }
|
|
1740
1787
|
});
|
|
1741
1788
|
}
|
|
1742
|
-
/**
|
|
1789
|
+
/** Holds the typed fleet-level observation surface. */
|
|
1743
1790
|
get emitter() {
|
|
1744
1791
|
return this.#emitter;
|
|
1745
1792
|
}
|
|
1746
|
-
/**
|
|
1793
|
+
/** Counts the live children. */
|
|
1747
1794
|
get count() {
|
|
1748
1795
|
return this.#children.size;
|
|
1749
1796
|
}
|
|
1750
1797
|
/**
|
|
1751
|
-
*
|
|
1798
|
+
* Returns the live child under `id`, or `undefined` when none is.
|
|
1752
1799
|
*
|
|
1753
1800
|
* @param id - The registry key
|
|
1754
1801
|
* @returns The child, or `undefined`
|
|
@@ -1757,7 +1804,7 @@ var ProcessManager = class {
|
|
|
1757
1804
|
return this.#children.get(id);
|
|
1758
1805
|
}
|
|
1759
1806
|
/**
|
|
1760
|
-
*
|
|
1807
|
+
* Returns a snapshot of every live child.
|
|
1761
1808
|
*
|
|
1762
1809
|
* @returns The live children in launch order
|
|
1763
1810
|
*/
|
|
@@ -1765,7 +1812,7 @@ var ProcessManager = class {
|
|
|
1765
1812
|
return [...this.#children.values()];
|
|
1766
1813
|
}
|
|
1767
1814
|
/**
|
|
1768
|
-
*
|
|
1815
|
+
* Spawns and registers one child under `id`.
|
|
1769
1816
|
*
|
|
1770
1817
|
* @remarks
|
|
1771
1818
|
* {@link Process} reads every option before it spawns, so a caller's own option getter runs while
|
|
@@ -1803,7 +1850,7 @@ var ProcessManager = class {
|
|
|
1803
1850
|
return this.#stopMany(target);
|
|
1804
1851
|
}
|
|
1805
1852
|
/**
|
|
1806
|
-
*
|
|
1853
|
+
* Stops every child, then destroys the registry emitter last.
|
|
1807
1854
|
*
|
|
1808
1855
|
* @remarks
|
|
1809
1856
|
* Always resolves, and refuses a later `launch` with a {@link createProtocolError}. Each child is
|
|
@@ -1856,7 +1903,7 @@ var ProcessManager = class {
|
|
|
1856
1903
|
}
|
|
1857
1904
|
};
|
|
1858
1905
|
//#endregion
|
|
1859
|
-
//#region src/server/Session.ts
|
|
1906
|
+
//#region src/server/processes/Session.ts
|
|
1860
1907
|
/**
|
|
1861
1908
|
* Supervises one child and publishes its standard output as raw bytes.
|
|
1862
1909
|
*
|
|
@@ -1893,7 +1940,7 @@ var Session = class {
|
|
|
1893
1940
|
#engine;
|
|
1894
1941
|
#output;
|
|
1895
1942
|
/**
|
|
1896
|
-
*
|
|
1943
|
+
* Spawns one child process and begins byte capture.
|
|
1897
1944
|
*
|
|
1898
1945
|
* @param options - Command, workspace, termination, evidence, stdin, and observation settings
|
|
1899
1946
|
* @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed
|
|
@@ -1931,39 +1978,39 @@ var Session = class {
|
|
|
1931
1978
|
});
|
|
1932
1979
|
this.#engine.stdout.on("data", this.#output);
|
|
1933
1980
|
}
|
|
1934
|
-
/**
|
|
1981
|
+
/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
|
|
1935
1982
|
get pid() {
|
|
1936
1983
|
return this.#engine.pid;
|
|
1937
1984
|
}
|
|
1938
|
-
/**
|
|
1985
|
+
/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
|
|
1939
1986
|
get code() {
|
|
1940
1987
|
return this.#engine.code;
|
|
1941
1988
|
}
|
|
1942
|
-
/**
|
|
1989
|
+
/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
|
|
1943
1990
|
get signal() {
|
|
1944
1991
|
return this.#engine.signal;
|
|
1945
1992
|
}
|
|
1946
|
-
/**
|
|
1993
|
+
/** Holds the typed lifecycle observation surface. */
|
|
1947
1994
|
get emitter() {
|
|
1948
1995
|
return this.#emitter;
|
|
1949
1996
|
}
|
|
1950
|
-
/**
|
|
1997
|
+
/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */
|
|
1951
1998
|
get evidence() {
|
|
1952
1999
|
return this.#engine.evidence;
|
|
1953
2000
|
}
|
|
1954
|
-
/**
|
|
2001
|
+
/** Reports whether the terminal moment arrived and `exit` settled. */
|
|
1955
2002
|
get settled() {
|
|
1956
2003
|
return this.#engine.settled;
|
|
1957
2004
|
}
|
|
1958
|
-
/**
|
|
2005
|
+
/** Reports whether termination began, including after the terminal moment. `end` never turns it true. */
|
|
1959
2006
|
get stopping() {
|
|
1960
2007
|
return this.#engine.stopping;
|
|
1961
2008
|
}
|
|
1962
|
-
/**
|
|
2009
|
+
/** Settles at the child's own ending, awaited without the terminal moment's drain window. */
|
|
1963
2010
|
get ending() {
|
|
1964
2011
|
return this.#engine.ending;
|
|
1965
2012
|
}
|
|
1966
|
-
/**
|
|
2013
|
+
/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */
|
|
1967
2014
|
get exit() {
|
|
1968
2015
|
return this.#engine.exit;
|
|
1969
2016
|
}
|
|
@@ -1977,7 +2024,7 @@ var Session = class {
|
|
|
1977
2024
|
* returned promise settles.
|
|
1978
2025
|
*
|
|
1979
2026
|
* @param bytes - The payload to write, already framed by the caller
|
|
1980
|
-
* @returns True
|
|
2027
|
+
* @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`)
|
|
1981
2028
|
*/
|
|
1982
2029
|
write(bytes) {
|
|
1983
2030
|
return this.#engine.deliver(bytes);
|
|
@@ -2001,7 +2048,7 @@ var Session = class {
|
|
|
2001
2048
|
* @remarks
|
|
2002
2049
|
* Never rejects, and every call shares one termination bounded by `grace` and `drain`.
|
|
2003
2050
|
*
|
|
2004
|
-
* @returns True
|
|
2051
|
+
* @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)
|
|
2005
2052
|
*/
|
|
2006
2053
|
stop() {
|
|
2007
2054
|
return this.#engine.stop();
|
|
@@ -2037,27 +2084,37 @@ var Session = class {
|
|
|
2037
2084
|
//#endregion
|
|
2038
2085
|
//#region src/server/factories.ts
|
|
2039
2086
|
/**
|
|
2040
|
-
* Creates one supervised child process
|
|
2087
|
+
* Creates one supervised child process and returns it as a {@link ProcessInterface}, so a caller
|
|
2088
|
+
* holds the published contract rather than the `Process` class.
|
|
2041
2089
|
*
|
|
2042
2090
|
* @param options - Command, workspace, termination, evidence, stdin, and observation settings
|
|
2043
2091
|
* @returns The launched {@link ProcessInterface}
|
|
2044
2092
|
*
|
|
2045
|
-
* @example
|
|
2093
|
+
* @example Supervise a child and read its lines
|
|
2046
2094
|
* ```ts
|
|
2047
2095
|
* import { createProcess } from '@orkestrel/process/server'
|
|
2048
2096
|
*
|
|
2049
2097
|
* const child = createProcess({
|
|
2050
|
-
* command: { file: 'node', arguments: ['
|
|
2098
|
+
* command: { file: 'node', arguments: ['-e', 'console.log("ready"); console.log("done")'] },
|
|
2051
2099
|
* workspace: process.cwd(),
|
|
2052
|
-
* grace:
|
|
2100
|
+
* grace: 5_000, // POSIX only: the window between SIGTERM and SIGKILL
|
|
2053
2101
|
* })
|
|
2102
|
+
*
|
|
2103
|
+
* const lines: string[] = []
|
|
2104
|
+
* for await (const line of child.lines) lines.push(line)
|
|
2105
|
+
* lines // ['ready', 'done']
|
|
2106
|
+
*
|
|
2107
|
+
* const exit = await child.exit
|
|
2108
|
+
* exit.code // 0
|
|
2109
|
+
* await child.destroy()
|
|
2054
2110
|
* ```
|
|
2055
2111
|
*/
|
|
2056
2112
|
function createProcess(options) {
|
|
2057
2113
|
return new Process(options);
|
|
2058
2114
|
}
|
|
2059
2115
|
/**
|
|
2060
|
-
* Creates one raw byte session over a supervised child process
|
|
2116
|
+
* Creates one raw byte session over a supervised child process and returns it as a
|
|
2117
|
+
* {@link SessionInterface}, so a caller holds the published contract rather than the `Session` class.
|
|
2061
2118
|
*
|
|
2062
2119
|
* @param options - Command, workspace, termination, evidence, stdin, and observation settings
|
|
2063
2120
|
* @returns The launched {@link SessionInterface}
|
|
@@ -2077,7 +2134,9 @@ function createSession(options) {
|
|
|
2077
2134
|
return new Session(options);
|
|
2078
2135
|
}
|
|
2079
2136
|
/**
|
|
2080
|
-
* Creates one keyed registry of supervised child processes
|
|
2137
|
+
* Creates one empty keyed registry of supervised child processes and returns it as a
|
|
2138
|
+
* {@link ProcessManagerInterface}, so a caller holds the published contract rather than the
|
|
2139
|
+
* `ProcessManager` class.
|
|
2081
2140
|
*
|
|
2082
2141
|
* @param options - Initial fleet-level observation hooks and listener-error handling
|
|
2083
2142
|
* @returns The {@link ProcessManagerInterface} registry
|
|
@@ -2096,6 +2155,7 @@ function createProcessManager(options) {
|
|
|
2096
2155
|
exports.Process = Process;
|
|
2097
2156
|
exports.ProcessManager = ProcessManager;
|
|
2098
2157
|
exports.Session = Session;
|
|
2158
|
+
exports.Supervisor = Supervisor;
|
|
2099
2159
|
exports.buildExecutableCandidates = buildExecutableCandidates;
|
|
2100
2160
|
exports.buildExecuteResult = buildExecuteResult;
|
|
2101
2161
|
exports.buildPlatformSpawn = buildPlatformSpawn;
|