@orkestrel/process 0.0.14 → 0.0.16
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/dist/src/core/index.cjs +46 -21
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +14 -14
- package/dist/src/core/index.d.ts +14 -14
- package/dist/src/core/index.js +47 -22
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +345 -314
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +23 -9
- package/dist/src/server/index.d.ts +23 -9
- package/dist/src/server/index.js +345 -315
- package/dist/src/server/index.js.map +1 -1
- package/package.json +16 -16
package/dist/src/core/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let _orkestrel_contract = require("@orkestrel/contract");
|
|
3
|
-
|
|
3
|
+
// src/core/constants.ts
|
|
4
4
|
/** Names the default cooperative POSIX window, 5000 ms, between `SIGTERM` and `SIGKILL` during termination. */
|
|
5
5
|
var PROCESS_GRACE = 5e3;
|
|
6
6
|
/** Names the window, 5000 ms, a termination waits for the child's native exit after the final kill. */
|
|
@@ -43,8 +43,7 @@ var PROCESS_ERROR_CODES = Object.freeze([
|
|
|
43
43
|
"protocol",
|
|
44
44
|
"invalid"
|
|
45
45
|
]);
|
|
46
|
-
|
|
47
|
-
//#region src/core/errors.ts
|
|
46
|
+
// src/core/errors.ts
|
|
48
47
|
/**
|
|
49
48
|
* Represents a child-process failure with a stable machine-readable category.
|
|
50
49
|
*
|
|
@@ -72,7 +71,7 @@ var ProcessError = class extends Error {
|
|
|
72
71
|
constructor(message, options) {
|
|
73
72
|
const cause = options.cause;
|
|
74
73
|
super(message, cause === void 0 ? void 0 : { cause });
|
|
75
|
-
|
|
74
|
+
_orkestrel_contract.INTRINSICS.define(this, Symbol.for("@orkestrel/process.error"), { value: this });
|
|
76
75
|
this.code = options.code;
|
|
77
76
|
if (options.context !== void 0) this.context = options.context;
|
|
78
77
|
if (options.result !== void 0) this.result = options.result;
|
|
@@ -82,11 +81,11 @@ var ProcessError = class extends Error {
|
|
|
82
81
|
* Checks whether an unknown value is a {@link ProcessError}.
|
|
83
82
|
*
|
|
84
83
|
* @remarks
|
|
85
|
-
* Recognition
|
|
86
|
-
* prototype,
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
84
|
+
* Recognition requires a global own-property identity brand, the native `Error` base, a subclass
|
|
85
|
+
* prototype, a declared code, and correctly shaped optional context and result members. Subclass
|
|
86
|
+
* instances pass without reading `name`. Duplicate installations and ESM/CommonJS copies that stamp
|
|
87
|
+
* their own identity recognize each other. Older boolean brands, transparent proxies, and plain
|
|
88
|
+
* objects fail recognition.
|
|
90
89
|
*
|
|
91
90
|
* @param value - The value to inspect
|
|
92
91
|
* @returns True if the value is a `ProcessError` instance; false otherwise
|
|
@@ -98,13 +97,40 @@ var ProcessError = class extends Error {
|
|
|
98
97
|
* ```
|
|
99
98
|
*/
|
|
100
99
|
function isProcessError(value) {
|
|
101
|
-
if (!(0, _orkestrel_contract.
|
|
100
|
+
if (!(0, _orkestrel_contract.isObject)(value)) return false;
|
|
102
101
|
return (0, _orkestrel_contract.holds)(() => {
|
|
103
|
-
if (
|
|
104
|
-
if (
|
|
105
|
-
if (
|
|
106
|
-
const code = value
|
|
107
|
-
|
|
102
|
+
if (!(value instanceof _orkestrel_contract.INTRINSICS.error)) return false;
|
|
103
|
+
if (_orkestrel_contract.INTRINSICS.prototype(value) === _orkestrel_contract.INTRINSICS.error.prototype) return false;
|
|
104
|
+
if (_orkestrel_contract.INTRINSICS.describe(value, Symbol.for("@orkestrel/process.error"))?.value !== value) return false;
|
|
105
|
+
const code = _orkestrel_contract.INTRINSICS.reflect.read(value, "code");
|
|
106
|
+
if (!PROCESS_ERROR_CODES.some((declared) => declared === code)) return false;
|
|
107
|
+
const context = _orkestrel_contract.INTRINSICS.reflect.read(value, "context");
|
|
108
|
+
if (context !== void 0) {
|
|
109
|
+
if (!(0, _orkestrel_contract.isObject)(context) && !(0, _orkestrel_contract.isFunction)(context)) return false;
|
|
110
|
+
if (!["id", "command"].every((key) => {
|
|
111
|
+
const member = _orkestrel_contract.INTRINSICS.reflect.read(context, key);
|
|
112
|
+
return member === void 0 || typeof member === "string";
|
|
113
|
+
})) return false;
|
|
114
|
+
const exit = _orkestrel_contract.INTRINSICS.reflect.read(context, "code");
|
|
115
|
+
const signal = _orkestrel_contract.INTRINSICS.reflect.read(context, "signal");
|
|
116
|
+
if (exit !== void 0 && exit !== null && typeof exit !== "number") return false;
|
|
117
|
+
if (signal !== void 0 && signal !== null && typeof signal !== "string") return false;
|
|
118
|
+
}
|
|
119
|
+
const result = _orkestrel_contract.INTRINSICS.reflect.read(value, "result");
|
|
120
|
+
if (result === void 0) return true;
|
|
121
|
+
if (!(0, _orkestrel_contract.isObject)(result)) return false;
|
|
122
|
+
const exit = _orkestrel_contract.INTRINSICS.reflect.read(result, "code");
|
|
123
|
+
const signal = _orkestrel_contract.INTRINSICS.reflect.read(result, "signal");
|
|
124
|
+
return (exit === null || typeof exit === "number") && (signal === null || typeof signal === "string") && [
|
|
125
|
+
"command",
|
|
126
|
+
"stdout",
|
|
127
|
+
"stderr"
|
|
128
|
+
].every((key) => typeof _orkestrel_contract.INTRINSICS.reflect.read(result, key) === "string") && [
|
|
129
|
+
"failed",
|
|
130
|
+
"expired",
|
|
131
|
+
"aborted",
|
|
132
|
+
"truncated"
|
|
133
|
+
].every((key) => typeof _orkestrel_contract.INTRINSICS.reflect.read(result, key) === "boolean");
|
|
108
134
|
});
|
|
109
135
|
}
|
|
110
136
|
/**
|
|
@@ -164,11 +190,11 @@ function createInvalidError(subject, value) {
|
|
|
164
190
|
* @returns A typed run failure carrying its {@link ExecuteResult}
|
|
165
191
|
*/
|
|
166
192
|
function createExecuteError(result, cause) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
193
|
+
const exit = `exited with code ${String(result.code)}`;
|
|
194
|
+
const signal = result.signal !== null ? `was killed by ${result.signal}` : exit;
|
|
195
|
+
const output = result.truncated ? "exceeded its output limit" : signal;
|
|
196
|
+
const abort = result.aborted ? "was aborted" : output;
|
|
197
|
+
const reason = result.expired ? "timed out" : abort;
|
|
172
198
|
return new ProcessError(`Command '${result.command}' ${reason}`, {
|
|
173
199
|
code: result.expired ? "timeout" : "spawn",
|
|
174
200
|
context: {
|
|
@@ -180,7 +206,6 @@ function createExecuteError(result, cause) {
|
|
|
180
206
|
result
|
|
181
207
|
});
|
|
182
208
|
}
|
|
183
|
-
//#endregion
|
|
184
209
|
exports.PROCESS_BACKLOG = PROCESS_BACKLOG;
|
|
185
210
|
exports.PROCESS_CONFIRMATION = PROCESS_CONFIRMATION;
|
|
186
211
|
exports.PROCESS_DRAIN = PROCESS_DRAIN;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["isError","holds"],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts"],"sourcesContent":["/** Names the default cooperative POSIX window, 5000 ms, between `SIGTERM` and `SIGKILL` during termination. */\nexport const PROCESS_GRACE = 5_000\n\n/** Names the window, 5000 ms, a termination waits for the child's native exit after the final kill. */\nexport const PROCESS_CONFIRMATION = 5_000\n\n/**\n * Names the default window, 1000 ms, the package waits for the child's read ends to close after the\n * child's native exit or after a termination this package initiated, before cutting them off.\n *\n * @remarks\n * Measured on Windows 11 with Node v24.18.1 on 2026-08-21, spawning the `tests/src/server/fixtures`\n * child modes as real children and timing the host `close` event against the host `exit` event.\n * Every ordinary run closed within 0.02ms of the native exit, whether the child ended itself or a\n * kill ended it, and a `taskkill /F /T` that reaped a descendant while the root was still alive\n * closed within 0.01ms. The only finite late close came from a descendant that outlived its root and\n * then ended on its own, at 127.44ms to 193.41ms — that lag is the descendant's own remaining life\n * rather than a flush cost. A descendant that never ends never closes, so the distribution has no\n * finite tail to cover and this value bounds it instead: 1000ms is over five times the slowest\n * finite close measured, and it keeps an unreachable descendant from stretching a shutdown.\n */\nexport const PROCESS_DRAIN = 1_000\n\n/** Names the default maximum retained stderr tail, 2048 bytes, for a supervised {@link ProcessInterface}. */\nexport const PROCESS_EVIDENCE = 2_048\n\n/** Names the default soft high-water mark, 10485760 bytes, for a supervised {@link ProcessInterface} line backlog. */\nexport const PROCESS_BACKLOG = 10_485_760\n\n/** Names the default maximum captured bytes, 10485760 each, for a one-shot run's stdout and stderr. */\nexport const PROCESS_OUTPUT = 10_485_760\n\n/** Names the largest timer delay, 2147483647 ms, the host schedules without truncating it to one. */\nexport const PROCESS_TIMER = 2_147_483_647\n\n/** Lists the executable extensions a Windows lookup applies when the environment declares no `PATHEXT`, `.COM;.EXE;.BAT;.CMD`. */\nexport const PROCESS_PATHEXT = '.COM;.EXE;.BAT;.CMD'\n\n/**\n * Lists the machine-readable failure categories a {@link ProcessError} carries, in declaration order:\n * `spawn`, `timeout`, `input`, `duplicate`, `protocol`, and `invalid`.\n */\nexport const PROCESS_ERROR_CODES = Object.freeze([\n\t'spawn',\n\t'timeout',\n\t'input',\n\t'duplicate',\n\t'protocol',\n\t'invalid',\n] as const)\n","import type {\n\tProcessErrorCode,\n\tProcessErrorContext,\n\tProcessErrorOptions,\n\tExecuteResult,\n} from './types.js'\nimport { holds, isError } from '@orkestrel/contract'\nimport { PROCESS_ERROR_CODES } from './constants.js'\n\n/**\n * Represents a child-process failure with a stable machine-readable category.\n *\n * @example\n * ```ts\n * const error = new ProcessError('git status refused', {\n * \tcode: 'invalid',\n * \tcontext: { command: 'git status' },\n * })\n * error.code // 'invalid'\n * ```\n */\nexport class ProcessError extends Error {\n\toverride readonly name = 'ProcessError'\n\treadonly code: ProcessErrorCode\n\treadonly context?: ProcessErrorContext\n\t/** Carries the buffered run outcome, present when a one-shot run produced the failure. */\n\treadonly result?: ExecuteResult\n\n\t/**\n\t * Creates a process error.\n\t *\n\t * @param message - Human-readable failure description\n\t * @param options - Machine-readable category, optional context, optional cause, and optional run result\n\t */\n\tconstructor(message: string, options: ProcessErrorOptions) {\n\t\tconst cause = options.cause\n\t\tsuper(message, cause === undefined ? undefined : { cause })\n\t\tObject.defineProperty(this, Symbol.for('@orkestrel/process.error'), { value: true })\n\t\tthis.code = options.code\n\t\tif (options.context !== undefined) this.context = options.context\n\t\tif (options.result !== undefined) this.result = options.result\n\t}\n}\n\n/**\n * Checks whether an unknown value is a {@link ProcessError}.\n *\n * @remarks\n * Recognition combines a global own-property brand with the native `Error` base, the subclass\n * prototype, the fixed name, and a code {@link PROCESS_ERROR_CODES} declares. The brand is\n * recognized across duplicate installations and ESM/CommonJS module copies at 0.0.4 or later. A copy\n * earlier than 0.0.4 stamps no brand, so an error it throws stays outside the type, and so does a\n * plain or property-only lookalike.\n *\n * @param value - The value to inspect\n * @returns True if the value is a `ProcessError` instance; false otherwise\n *\n * @example\n * ```ts\n * isProcessError(new ProcessError('spawn failed', { code: 'spawn' })) // true\n * isProcessError(new Error('spawn failed')) // false\n * ```\n */\nexport function isProcessError(value: unknown): value is ProcessError {\n\tif (!isError(value)) return false\n\treturn holds(() => {\n\t\tif (Object.getPrototypeOf(value) === Error.prototype) return false\n\t\tif (value.name !== 'ProcessError' || !('code' in value)) return false\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(\n\t\t\tvalue,\n\t\t\tSymbol.for('@orkestrel/process.error'),\n\t\t)\n\t\tif (descriptor?.value !== true) return false\n\t\tconst code: unknown = value.code\n\t\treturn PROCESS_ERROR_CODES.some((declared) => declared === code)\n\t})\n}\n\n/**\n * Creates the `duplicate`-coded failure raised when a manager launch reuses a live id.\n *\n * @param id - The id already occupied by a live child\n * @returns A typed duplicate-id failure\n */\nexport function createDuplicateError(id: string): ProcessError {\n\treturn new ProcessError(`Process '${id}' is already live`, {\n\t\tcode: 'duplicate',\n\t\tcontext: { id },\n\t})\n}\n\n/**\n * Creates the `protocol`-coded failure raised when a launch is attempted on a registry that is\n * being destroyed.\n *\n * @param id - The id the refused launch asked for\n * @returns A typed protocol failure\n */\nexport function createProtocolError(id: string): ProcessError {\n\treturn new ProcessError(`Process '${id}' cannot launch: the registry is destroyed`, {\n\t\tcode: 'protocol',\n\t\tcontext: { id },\n\t})\n}\n\n/**\n * Creates the `invalid`-coded failure raised when a public input is refused before anything is\n * spawned.\n *\n * @param subject - The rejected input named as the caller wrote it, such as `option 'grace'`\n * @param value - The rejected value, carried as `context.value`\n * @returns A typed validation failure\n *\n * @example\n * ```ts\n * createInvalidError(\"option 'grace'\", -1).code // 'invalid'\n * ```\n */\nexport function createInvalidError(subject: string, value: unknown): ProcessError {\n\treturn new ProcessError(`Invalid ${subject}`, { code: 'invalid', context: { value } })\n}\n\n/**\n * Creates the failure raised when a run does not complete successfully and rejection is requested.\n *\n * @remarks\n * The category is `timeout` only when the run's own timeout elapsed; every other failure,\n * including an abort and an output overflow, is a `spawn` failure carrying its\n * {@link ExecuteResult}.\n *\n * @param result - The buffered run outcome that failed\n * @param cause - The underlying host fault, when one ended the run\n * @returns A typed run failure carrying its {@link ExecuteResult}\n */\nexport function createExecuteError(result: ExecuteResult, cause?: unknown): ProcessError {\n\tlet reason = `exited with code ${String(result.code)}`\n\tif (result.signal !== null) reason = `was killed by ${result.signal}`\n\tif (result.truncated) reason = 'exceeded its output limit'\n\tif (result.aborted) reason = 'was aborted'\n\tif (result.expired) reason = 'timed out'\n\treturn new ProcessError(`Command '${result.command}' ${reason}`, {\n\t\tcode: result.expired ? 'timeout' : 'spawn',\n\t\tcontext: { command: result.command, code: result.code, signal: result.signal },\n\t\t...(cause === undefined ? {} : { cause }),\n\t\tresult,\n\t})\n}\n"],"mappings":";;;;AACA,IAAa,gBAAgB;;AAG7B,IAAa,uBAAuB;;;;;;;;;;;;;;;;AAiBpC,IAAa,gBAAgB;;AAG7B,IAAa,mBAAmB;;AAGhC,IAAa,kBAAkB;;AAG/B,IAAa,iBAAiB;;AAG9B,IAAa,gBAAgB;;AAG7B,IAAa,kBAAkB;;;;;AAM/B,IAAa,sBAAsB,OAAO,OAAO;CAChD;CACA;CACA;CACA;CACA;CACA;AACD,CAAU;;;;;;;;;;;;;;;AC5BV,IAAa,eAAb,cAAkC,MAAM;CACvC,OAAyB;CACzB;CACA;;CAEA;;;;;;;CAQA,YAAY,SAAiB,SAA8B;EAC1D,MAAM,QAAQ,QAAQ;EACtB,MAAM,SAAS,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,MAAM,CAAC;EAC1D,OAAO,eAAe,MAAM,OAAO,IAAI,0BAA0B,GAAG,EAAE,OAAO,KAAK,CAAC;EACnF,KAAK,OAAO,QAAQ;EACpB,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;EAC1D,IAAI,QAAQ,WAAW,KAAA,GAAW,KAAK,SAAS,QAAQ;CACzD;AACD;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,eAAe,OAAuC;CACrE,IAAI,EAAA,GAACA,oBAAAA,QAAAA,CAAQ,KAAK,GAAG,OAAO;CAC5B,QAAA,GAAOC,oBAAAA,MAAAA,OAAY;EAClB,IAAI,OAAO,eAAe,KAAK,MAAM,MAAM,WAAW,OAAO;EAC7D,IAAI,MAAM,SAAS,kBAAkB,EAAE,UAAU,QAAQ,OAAO;EAKhE,IAJmB,OAAO,yBACzB,OACA,OAAO,IAAI,0BAA0B,CAElC,CAAA,EAAY,UAAU,MAAM,OAAO;EACvC,MAAM,OAAgB,MAAM;EAC5B,OAAO,oBAAoB,MAAM,aAAa,aAAa,IAAI;CAChE,CAAC;AACF;;;;;;;AAQA,SAAgB,qBAAqB,IAA0B;CAC9D,OAAO,IAAI,aAAa,YAAY,GAAG,oBAAoB;EAC1D,MAAM;EACN,SAAS,EAAE,GAAG;CACf,CAAC;AACF;;;;;;;;AASA,SAAgB,oBAAoB,IAA0B;CAC7D,OAAO,IAAI,aAAa,YAAY,GAAG,6CAA6C;EACnF,MAAM;EACN,SAAS,EAAE,GAAG;CACf,CAAC;AACF;;;;;;;;;;;;;;AAeA,SAAgB,mBAAmB,SAAiB,OAA8B;CACjF,OAAO,IAAI,aAAa,WAAW,WAAW;EAAE,MAAM;EAAW,SAAS,EAAE,MAAM;CAAE,CAAC;AACtF;;;;;;;;;;;;;AAcA,SAAgB,mBAAmB,QAAuB,OAA+B;CACxF,IAAI,SAAS,oBAAoB,OAAO,OAAO,IAAI;CACnD,IAAI,OAAO,WAAW,MAAM,SAAS,iBAAiB,OAAO;CAC7D,IAAI,OAAO,WAAW,SAAS;CAC/B,IAAI,OAAO,SAAS,SAAS;CAC7B,IAAI,OAAO,SAAS,SAAS;CAC7B,OAAO,IAAI,aAAa,YAAY,OAAO,QAAQ,IAAI,UAAU;EAChE,MAAM,OAAO,UAAU,YAAY;EACnC,SAAS;GAAE,SAAS,OAAO;GAAS,MAAM,OAAO;GAAM,QAAQ,OAAO;EAAO;EAC7E,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;EACvC;CACD,CAAC;AACF"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["isObject","holds","INTRINSICS","isFunction"],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts"],"sourcesContent":["/** Names the default cooperative POSIX window, 5000 ms, between `SIGTERM` and `SIGKILL` during termination. */\nexport const PROCESS_GRACE = 5_000\n\n/** Names the window, 5000 ms, a termination waits for the child's native exit after the final kill. */\nexport const PROCESS_CONFIRMATION = 5_000\n\n/**\n * Names the default window, 1000 ms, the package waits for the child's read ends to close after the\n * child's native exit or after a termination this package initiated, before cutting them off.\n *\n * @remarks\n * Measured on Windows 11 with Node v24.18.1 on 2026-08-21, spawning the `tests/src/server/fixtures`\n * child modes as real children and timing the host `close` event against the host `exit` event.\n * Every ordinary run closed within 0.02ms of the native exit, whether the child ended itself or a\n * kill ended it, and a `taskkill /F /T` that reaped a descendant while the root was still alive\n * closed within 0.01ms. The only finite late close came from a descendant that outlived its root and\n * then ended on its own, at 127.44ms to 193.41ms — that lag is the descendant's own remaining life\n * rather than a flush cost. A descendant that never ends never closes, so the distribution has no\n * finite tail to cover and this value bounds it instead: 1000ms is over five times the slowest\n * finite close measured, and it keeps an unreachable descendant from stretching a shutdown.\n */\nexport const PROCESS_DRAIN = 1_000\n\n/** Names the default maximum retained stderr tail, 2048 bytes, for a supervised {@link ProcessInterface}. */\nexport const PROCESS_EVIDENCE = 2_048\n\n/** Names the default soft high-water mark, 10485760 bytes, for a supervised {@link ProcessInterface} line backlog. */\nexport const PROCESS_BACKLOG = 10_485_760\n\n/** Names the default maximum captured bytes, 10485760 each, for a one-shot run's stdout and stderr. */\nexport const PROCESS_OUTPUT = 10_485_760\n\n/** Names the largest timer delay, 2147483647 ms, the host schedules without truncating it to one. */\nexport const PROCESS_TIMER = 2_147_483_647\n\n/** Lists the executable extensions a Windows lookup applies when the environment declares no `PATHEXT`, `.COM;.EXE;.BAT;.CMD`. */\nexport const PROCESS_PATHEXT = '.COM;.EXE;.BAT;.CMD'\n\n/**\n * Lists the machine-readable failure categories a {@link ProcessError} carries, in declaration order:\n * `spawn`, `timeout`, `input`, `duplicate`, `protocol`, and `invalid`.\n */\nexport const PROCESS_ERROR_CODES = Object.freeze([\n\t'spawn',\n\t'timeout',\n\t'input',\n\t'duplicate',\n\t'protocol',\n\t'invalid',\n] as const)\n","import type {\n\tProcessErrorCode,\n\tProcessErrorContext,\n\tProcessErrorOptions,\n\tExecuteResult,\n} from './types.js'\nimport { holds, INTRINSICS, isFunction, isObject } from '@orkestrel/contract'\nimport { PROCESS_ERROR_CODES } from './constants.js'\n\n/**\n * Represents a child-process failure with a stable machine-readable category.\n *\n * @example\n * ```ts\n * const error = new ProcessError('git status refused', {\n * \tcode: 'invalid',\n * \tcontext: { command: 'git status' },\n * })\n * error.code // 'invalid'\n * ```\n */\nexport class ProcessError extends Error {\n\toverride readonly name = 'ProcessError'\n\treadonly code: ProcessErrorCode\n\treadonly context?: ProcessErrorContext\n\t/** Carries the buffered run outcome, present when a one-shot run produced the failure. */\n\treadonly result?: ExecuteResult\n\n\t/**\n\t * Creates a process error.\n\t *\n\t * @param message - Human-readable failure description\n\t * @param options - Machine-readable category, optional context, optional cause, and optional run result\n\t */\n\tconstructor(message: string, options: ProcessErrorOptions) {\n\t\tconst cause = options.cause\n\t\tsuper(message, cause === undefined ? undefined : { cause })\n\t\tINTRINSICS.define(this, Symbol.for('@orkestrel/process.error'), { value: this })\n\t\tthis.code = options.code\n\t\tif (options.context !== undefined) this.context = options.context\n\t\tif (options.result !== undefined) this.result = options.result\n\t}\n}\n\n/**\n * Checks whether an unknown value is a {@link ProcessError}.\n *\n * @remarks\n * Recognition requires a global own-property identity brand, the native `Error` base, a subclass\n * prototype, a declared code, and correctly shaped optional context and result members. Subclass\n * instances pass without reading `name`. Duplicate installations and ESM/CommonJS copies that stamp\n * their own identity recognize each other. Older boolean brands, transparent proxies, and plain\n * objects fail recognition.\n *\n * @param value - The value to inspect\n * @returns True if the value is a `ProcessError` instance; false otherwise\n *\n * @example\n * ```ts\n * isProcessError(new ProcessError('spawn failed', { code: 'spawn' })) // true\n * isProcessError(new Error('spawn failed')) // false\n * ```\n */\nexport function isProcessError(value: unknown): value is ProcessError {\n\tif (!isObject(value)) return false\n\treturn holds(() => {\n\t\tif (!(value instanceof INTRINSICS.error)) return false\n\t\tif (INTRINSICS.prototype(value) === INTRINSICS.error.prototype) return false\n\t\tconst descriptor = INTRINSICS.describe(value, Symbol.for('@orkestrel/process.error'))\n\t\tif (descriptor?.value !== value) return false\n\t\tconst code: unknown = INTRINSICS.reflect.read(value, 'code')\n\t\tif (!PROCESS_ERROR_CODES.some((declared) => declared === code)) return false\n\t\tconst context: unknown = INTRINSICS.reflect.read(value, 'context')\n\t\tif (context !== undefined) {\n\t\t\tif (!isObject(context) && !isFunction(context)) return false\n\t\t\tif (\n\t\t\t\t!['id', 'command'].every((key) => {\n\t\t\t\t\tconst member: unknown = INTRINSICS.reflect.read(context, key)\n\t\t\t\t\treturn member === undefined || typeof member === 'string'\n\t\t\t\t})\n\t\t\t)\n\t\t\t\treturn false\n\t\t\tconst exit: unknown = INTRINSICS.reflect.read(context, 'code')\n\t\t\tconst signal: unknown = INTRINSICS.reflect.read(context, 'signal')\n\t\t\tif (exit !== undefined && exit !== null && typeof exit !== 'number') return false\n\t\t\tif (signal !== undefined && signal !== null && typeof signal !== 'string') return false\n\t\t}\n\t\tconst result: unknown = INTRINSICS.reflect.read(value, 'result')\n\t\tif (result === undefined) return true\n\t\tif (!isObject(result)) return false\n\t\tconst exit: unknown = INTRINSICS.reflect.read(result, 'code')\n\t\tconst signal: unknown = INTRINSICS.reflect.read(result, 'signal')\n\t\treturn (\n\t\t\t(exit === null || typeof exit === 'number') &&\n\t\t\t(signal === null || typeof signal === 'string') &&\n\t\t\t['command', 'stdout', 'stderr'].every(\n\t\t\t\t(key) => typeof INTRINSICS.reflect.read(result, key) === 'string',\n\t\t\t) &&\n\t\t\t['failed', 'expired', 'aborted', 'truncated'].every(\n\t\t\t\t(key) => typeof INTRINSICS.reflect.read(result, key) === 'boolean',\n\t\t\t)\n\t\t)\n\t})\n}\n\n/**\n * Creates the `duplicate`-coded failure raised when a manager launch reuses a live id.\n *\n * @param id - The id already occupied by a live child\n * @returns A typed duplicate-id failure\n */\nexport function createDuplicateError(id: string): ProcessError {\n\treturn new ProcessError(`Process '${id}' is already live`, {\n\t\tcode: 'duplicate',\n\t\tcontext: { id },\n\t})\n}\n\n/**\n * Creates the `protocol`-coded failure raised when a launch is attempted on a registry that is\n * being destroyed.\n *\n * @param id - The id the refused launch asked for\n * @returns A typed protocol failure\n */\nexport function createProtocolError(id: string): ProcessError {\n\treturn new ProcessError(`Process '${id}' cannot launch: the registry is destroyed`, {\n\t\tcode: 'protocol',\n\t\tcontext: { id },\n\t})\n}\n\n/**\n * Creates the `invalid`-coded failure raised when a public input is refused before anything is\n * spawned.\n *\n * @param subject - The rejected input named as the caller wrote it, such as `option 'grace'`\n * @param value - The rejected value, carried as `context.value`\n * @returns A typed validation failure\n *\n * @example\n * ```ts\n * createInvalidError(\"option 'grace'\", -1).code // 'invalid'\n * ```\n */\nexport function createInvalidError(subject: string, value: unknown): ProcessError {\n\treturn new ProcessError(`Invalid ${subject}`, { code: 'invalid', context: { value } })\n}\n\n/**\n * Creates the failure raised when a run does not complete successfully and rejection is requested.\n *\n * @remarks\n * The category is `timeout` only when the run's own timeout elapsed; every other failure,\n * including an abort and an output overflow, is a `spawn` failure carrying its\n * {@link ExecuteResult}.\n *\n * @param result - The buffered run outcome that failed\n * @param cause - The underlying host fault, when one ended the run\n * @returns A typed run failure carrying its {@link ExecuteResult}\n */\nexport function createExecuteError(result: ExecuteResult, cause?: unknown): ProcessError {\n\tconst exit = `exited with code ${String(result.code)}`\n\tconst signal = result.signal !== null ? `was killed by ${result.signal}` : exit\n\tconst output = result.truncated ? 'exceeded its output limit' : signal\n\tconst abort = result.aborted ? 'was aborted' : output\n\tconst reason = result.expired ? 'timed out' : abort\n\treturn new ProcessError(`Command '${result.command}' ${reason}`, {\n\t\tcode: result.expired ? 'timeout' : 'spawn',\n\t\tcontext: { command: result.command, code: result.code, signal: result.signal },\n\t\t...(cause === undefined ? {} : { cause }),\n\t\tresult,\n\t})\n}\n"],"mappings":"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"}
|
|
@@ -208,11 +208,11 @@ export declare interface ExecuteSyncOptions {
|
|
|
208
208
|
* Checks whether an unknown value is a {@link ProcessError}.
|
|
209
209
|
*
|
|
210
210
|
* @remarks
|
|
211
|
-
* Recognition
|
|
212
|
-
* prototype,
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
211
|
+
* Recognition requires a global own-property identity brand, the native `Error` base, a subclass
|
|
212
|
+
* prototype, a declared code, and correctly shaped optional context and result members. Subclass
|
|
213
|
+
* instances pass without reading `name`. Duplicate installations and ESM/CommonJS copies that stamp
|
|
214
|
+
* their own identity recognize each other. Older boolean brands, transparent proxies, and plain
|
|
215
|
+
* objects fail recognition.
|
|
216
216
|
*
|
|
217
217
|
* @param value - The value to inspect
|
|
218
218
|
* @returns True if the value is a `ProcessError` instance; false otherwise
|
|
@@ -281,7 +281,7 @@ export declare const PROCESS_TIMER = 2147483647;
|
|
|
281
281
|
* primitive.
|
|
282
282
|
* - **{@link SessionInterface}** — the same supervised child observed as raw bytes: an owned
|
|
283
283
|
* `Uint8Array` per stdout chunk, an open stdin channel closed by `end` rather than by a switch,
|
|
284
|
-
* the child's own `
|
|
284
|
+
* the child's own `ended` beside the terminal `exit`, and a typed {@link SessionEventMap}
|
|
285
285
|
* emitter. The transport primitive, for a child speaking a framed protocol.
|
|
286
286
|
* - **{@link ExecuteResult} / execute** — a one-shot spawn that buffers a child to completion and settles
|
|
287
287
|
* with its output and exit, the ergonomic layer for fire-and-collect commands.
|
|
@@ -512,7 +512,7 @@ export declare interface ProcessInterface {
|
|
|
512
512
|
* a consumer acts on: a child that was asked to end is not a child to send new work to. A child
|
|
513
513
|
* that exited on its own reports `false` here with `settled` true.
|
|
514
514
|
*/
|
|
515
|
-
readonly
|
|
515
|
+
readonly terminated: boolean;
|
|
516
516
|
/**
|
|
517
517
|
* Settles with the terminal child state, delivered once.
|
|
518
518
|
*
|
|
@@ -732,7 +732,7 @@ export declare interface ProcessOptions {
|
|
|
732
732
|
|
|
733
733
|
/**
|
|
734
734
|
* Represents the push observation surface of a {@link SessionInterface} — the moments a byte-oriented observer
|
|
735
|
-
* subscribes to, alongside the `
|
|
735
|
+
* subscribes to, alongside the `ended` and `exit` promises.
|
|
736
736
|
*
|
|
737
737
|
* @remarks
|
|
738
738
|
* Declared as a `type` alias so it satisfies the emitter's `EventMap` constraint structurally.
|
|
@@ -778,11 +778,11 @@ export declare type SessionEventMap = {
|
|
|
778
778
|
* attach to a failed exit — and the typed `emitter` carries the live `stdout` and `stderr` payloads,
|
|
779
779
|
* the child `error` cause, and the terminal `exit`.
|
|
780
780
|
*
|
|
781
|
-
* **Two endings, named apart.** `
|
|
781
|
+
* **Two endings, named apart.** `ended` settles at the child's own native exit and resolves no
|
|
782
782
|
* value, because `code` and `signal` already carry the terminal facts as soon as the host records
|
|
783
783
|
* them. `exit` settles at the terminal moment, which is the native exit plus at most `drain` when a
|
|
784
784
|
* descendant that inherited the child's stdio still holds the read ends open. A caller racing a
|
|
785
|
-
* cooperative shutdown window therefore awaits `
|
|
785
|
+
* cooperative shutdown window therefore awaits `ended`, and a caller collecting the final
|
|
786
786
|
* observation awaits `exit`. `settled`, the `exit` event, and `evidence` freezing all name that same
|
|
787
787
|
* terminal moment, exactly as they do on {@link ProcessInterface}.
|
|
788
788
|
*
|
|
@@ -833,7 +833,7 @@ export declare interface SessionInterface {
|
|
|
833
833
|
* turns it true, because closing the input channel terminates nothing. A child that exited on its
|
|
834
834
|
* own reports `false` here with `settled` true.
|
|
835
835
|
*/
|
|
836
|
-
readonly
|
|
836
|
+
readonly terminated: boolean;
|
|
837
837
|
/**
|
|
838
838
|
* Settles at the child's own ending, awaited without the terminal moment's drain window.
|
|
839
839
|
*
|
|
@@ -846,7 +846,7 @@ export declare interface SessionInterface {
|
|
|
846
846
|
* descendant holding the pipe, and a caller racing that promise escalates against a child that
|
|
847
847
|
* already ended.
|
|
848
848
|
*/
|
|
849
|
-
readonly
|
|
849
|
+
readonly ended: Promise<void>;
|
|
850
850
|
/**
|
|
851
851
|
* Settles with the terminal child state, delivered once.
|
|
852
852
|
*
|
|
@@ -881,9 +881,9 @@ export declare interface SessionInterface {
|
|
|
881
881
|
* Closes the standard-input channel and leaves the child running.
|
|
882
882
|
*
|
|
883
883
|
* @remarks
|
|
884
|
-
* Never rejects, and terminates nothing: `
|
|
884
|
+
* Never rejects, and terminates nothing: `terminated` stays false, no signal is sent, no drain
|
|
885
885
|
* window is armed, and the terminal moment does not arrive. The child observes end of input, which
|
|
886
|
-
* is how a cooperative protocol asks it to finish and exit on its own; await `
|
|
886
|
+
* is how a cooperative protocol asks it to finish and exit on its own; await `ended` for that
|
|
887
887
|
* exit and `stop` when it does not come.
|
|
888
888
|
*
|
|
889
889
|
* Every call shares one barrier, and it resolves after the host flushes the writes it had already
|
package/dist/src/core/index.d.ts
CHANGED
|
@@ -208,11 +208,11 @@ export declare interface ExecuteSyncOptions {
|
|
|
208
208
|
* Checks whether an unknown value is a {@link ProcessError}.
|
|
209
209
|
*
|
|
210
210
|
* @remarks
|
|
211
|
-
* Recognition
|
|
212
|
-
* prototype,
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
211
|
+
* Recognition requires a global own-property identity brand, the native `Error` base, a subclass
|
|
212
|
+
* prototype, a declared code, and correctly shaped optional context and result members. Subclass
|
|
213
|
+
* instances pass without reading `name`. Duplicate installations and ESM/CommonJS copies that stamp
|
|
214
|
+
* their own identity recognize each other. Older boolean brands, transparent proxies, and plain
|
|
215
|
+
* objects fail recognition.
|
|
216
216
|
*
|
|
217
217
|
* @param value - The value to inspect
|
|
218
218
|
* @returns True if the value is a `ProcessError` instance; false otherwise
|
|
@@ -281,7 +281,7 @@ export declare const PROCESS_TIMER = 2147483647;
|
|
|
281
281
|
* primitive.
|
|
282
282
|
* - **{@link SessionInterface}** — the same supervised child observed as raw bytes: an owned
|
|
283
283
|
* `Uint8Array` per stdout chunk, an open stdin channel closed by `end` rather than by a switch,
|
|
284
|
-
* the child's own `
|
|
284
|
+
* the child's own `ended` beside the terminal `exit`, and a typed {@link SessionEventMap}
|
|
285
285
|
* emitter. The transport primitive, for a child speaking a framed protocol.
|
|
286
286
|
* - **{@link ExecuteResult} / execute** — a one-shot spawn that buffers a child to completion and settles
|
|
287
287
|
* with its output and exit, the ergonomic layer for fire-and-collect commands.
|
|
@@ -512,7 +512,7 @@ export declare interface ProcessInterface {
|
|
|
512
512
|
* a consumer acts on: a child that was asked to end is not a child to send new work to. A child
|
|
513
513
|
* that exited on its own reports `false` here with `settled` true.
|
|
514
514
|
*/
|
|
515
|
-
readonly
|
|
515
|
+
readonly terminated: boolean;
|
|
516
516
|
/**
|
|
517
517
|
* Settles with the terminal child state, delivered once.
|
|
518
518
|
*
|
|
@@ -732,7 +732,7 @@ export declare interface ProcessOptions {
|
|
|
732
732
|
|
|
733
733
|
/**
|
|
734
734
|
* Represents the push observation surface of a {@link SessionInterface} — the moments a byte-oriented observer
|
|
735
|
-
* subscribes to, alongside the `
|
|
735
|
+
* subscribes to, alongside the `ended` and `exit` promises.
|
|
736
736
|
*
|
|
737
737
|
* @remarks
|
|
738
738
|
* Declared as a `type` alias so it satisfies the emitter's `EventMap` constraint structurally.
|
|
@@ -778,11 +778,11 @@ export declare type SessionEventMap = {
|
|
|
778
778
|
* attach to a failed exit — and the typed `emitter` carries the live `stdout` and `stderr` payloads,
|
|
779
779
|
* the child `error` cause, and the terminal `exit`.
|
|
780
780
|
*
|
|
781
|
-
* **Two endings, named apart.** `
|
|
781
|
+
* **Two endings, named apart.** `ended` settles at the child's own native exit and resolves no
|
|
782
782
|
* value, because `code` and `signal` already carry the terminal facts as soon as the host records
|
|
783
783
|
* them. `exit` settles at the terminal moment, which is the native exit plus at most `drain` when a
|
|
784
784
|
* descendant that inherited the child's stdio still holds the read ends open. A caller racing a
|
|
785
|
-
* cooperative shutdown window therefore awaits `
|
|
785
|
+
* cooperative shutdown window therefore awaits `ended`, and a caller collecting the final
|
|
786
786
|
* observation awaits `exit`. `settled`, the `exit` event, and `evidence` freezing all name that same
|
|
787
787
|
* terminal moment, exactly as they do on {@link ProcessInterface}.
|
|
788
788
|
*
|
|
@@ -833,7 +833,7 @@ export declare interface SessionInterface {
|
|
|
833
833
|
* turns it true, because closing the input channel terminates nothing. A child that exited on its
|
|
834
834
|
* own reports `false` here with `settled` true.
|
|
835
835
|
*/
|
|
836
|
-
readonly
|
|
836
|
+
readonly terminated: boolean;
|
|
837
837
|
/**
|
|
838
838
|
* Settles at the child's own ending, awaited without the terminal moment's drain window.
|
|
839
839
|
*
|
|
@@ -846,7 +846,7 @@ export declare interface SessionInterface {
|
|
|
846
846
|
* descendant holding the pipe, and a caller racing that promise escalates against a child that
|
|
847
847
|
* already ended.
|
|
848
848
|
*/
|
|
849
|
-
readonly
|
|
849
|
+
readonly ended: Promise<void>;
|
|
850
850
|
/**
|
|
851
851
|
* Settles with the terminal child state, delivered once.
|
|
852
852
|
*
|
|
@@ -881,9 +881,9 @@ export declare interface SessionInterface {
|
|
|
881
881
|
* Closes the standard-input channel and leaves the child running.
|
|
882
882
|
*
|
|
883
883
|
* @remarks
|
|
884
|
-
* Never rejects, and terminates nothing: `
|
|
884
|
+
* Never rejects, and terminates nothing: `terminated` stays false, no signal is sent, no drain
|
|
885
885
|
* window is armed, and the terminal moment does not arrive. The child observes end of input, which
|
|
886
|
-
* is how a cooperative protocol asks it to finish and exit on its own; await `
|
|
886
|
+
* is how a cooperative protocol asks it to finish and exit on its own; await `ended` for that
|
|
887
887
|
* exit and `stop` when it does not come.
|
|
888
888
|
*
|
|
889
889
|
* Every call shares one barrier, and it resolves after the host flushes the writes it had already
|
package/dist/src/core/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { holds,
|
|
2
|
-
|
|
1
|
+
import { INTRINSICS, holds, isFunction, isObject } from "@orkestrel/contract";
|
|
2
|
+
// src/core/constants.ts
|
|
3
3
|
/** Names the default cooperative POSIX window, 5000 ms, between `SIGTERM` and `SIGKILL` during termination. */
|
|
4
4
|
var PROCESS_GRACE = 5e3;
|
|
5
5
|
/** Names the window, 5000 ms, a termination waits for the child's native exit after the final kill. */
|
|
@@ -42,8 +42,7 @@ var PROCESS_ERROR_CODES = Object.freeze([
|
|
|
42
42
|
"protocol",
|
|
43
43
|
"invalid"
|
|
44
44
|
]);
|
|
45
|
-
|
|
46
|
-
//#region src/core/errors.ts
|
|
45
|
+
// src/core/errors.ts
|
|
47
46
|
/**
|
|
48
47
|
* Represents a child-process failure with a stable machine-readable category.
|
|
49
48
|
*
|
|
@@ -71,7 +70,7 @@ var ProcessError = class extends Error {
|
|
|
71
70
|
constructor(message, options) {
|
|
72
71
|
const cause = options.cause;
|
|
73
72
|
super(message, cause === void 0 ? void 0 : { cause });
|
|
74
|
-
|
|
73
|
+
INTRINSICS.define(this, Symbol.for("@orkestrel/process.error"), { value: this });
|
|
75
74
|
this.code = options.code;
|
|
76
75
|
if (options.context !== void 0) this.context = options.context;
|
|
77
76
|
if (options.result !== void 0) this.result = options.result;
|
|
@@ -81,11 +80,11 @@ var ProcessError = class extends Error {
|
|
|
81
80
|
* Checks whether an unknown value is a {@link ProcessError}.
|
|
82
81
|
*
|
|
83
82
|
* @remarks
|
|
84
|
-
* Recognition
|
|
85
|
-
* prototype,
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
83
|
+
* Recognition requires a global own-property identity brand, the native `Error` base, a subclass
|
|
84
|
+
* prototype, a declared code, and correctly shaped optional context and result members. Subclass
|
|
85
|
+
* instances pass without reading `name`. Duplicate installations and ESM/CommonJS copies that stamp
|
|
86
|
+
* their own identity recognize each other. Older boolean brands, transparent proxies, and plain
|
|
87
|
+
* objects fail recognition.
|
|
89
88
|
*
|
|
90
89
|
* @param value - The value to inspect
|
|
91
90
|
* @returns True if the value is a `ProcessError` instance; false otherwise
|
|
@@ -97,13 +96,40 @@ var ProcessError = class extends Error {
|
|
|
97
96
|
* ```
|
|
98
97
|
*/
|
|
99
98
|
function isProcessError(value) {
|
|
100
|
-
if (!
|
|
99
|
+
if (!isObject(value)) return false;
|
|
101
100
|
return holds(() => {
|
|
102
|
-
if (
|
|
103
|
-
if (
|
|
104
|
-
if (
|
|
105
|
-
const code = value
|
|
106
|
-
|
|
101
|
+
if (!(value instanceof INTRINSICS.error)) return false;
|
|
102
|
+
if (INTRINSICS.prototype(value) === INTRINSICS.error.prototype) return false;
|
|
103
|
+
if (INTRINSICS.describe(value, Symbol.for("@orkestrel/process.error"))?.value !== value) return false;
|
|
104
|
+
const code = INTRINSICS.reflect.read(value, "code");
|
|
105
|
+
if (!PROCESS_ERROR_CODES.some((declared) => declared === code)) return false;
|
|
106
|
+
const context = INTRINSICS.reflect.read(value, "context");
|
|
107
|
+
if (context !== void 0) {
|
|
108
|
+
if (!isObject(context) && !isFunction(context)) return false;
|
|
109
|
+
if (!["id", "command"].every((key) => {
|
|
110
|
+
const member = INTRINSICS.reflect.read(context, key);
|
|
111
|
+
return member === void 0 || typeof member === "string";
|
|
112
|
+
})) return false;
|
|
113
|
+
const exit = INTRINSICS.reflect.read(context, "code");
|
|
114
|
+
const signal = INTRINSICS.reflect.read(context, "signal");
|
|
115
|
+
if (exit !== void 0 && exit !== null && typeof exit !== "number") return false;
|
|
116
|
+
if (signal !== void 0 && signal !== null && typeof signal !== "string") return false;
|
|
117
|
+
}
|
|
118
|
+
const result = INTRINSICS.reflect.read(value, "result");
|
|
119
|
+
if (result === void 0) return true;
|
|
120
|
+
if (!isObject(result)) return false;
|
|
121
|
+
const exit = INTRINSICS.reflect.read(result, "code");
|
|
122
|
+
const signal = INTRINSICS.reflect.read(result, "signal");
|
|
123
|
+
return (exit === null || typeof exit === "number") && (signal === null || typeof signal === "string") && [
|
|
124
|
+
"command",
|
|
125
|
+
"stdout",
|
|
126
|
+
"stderr"
|
|
127
|
+
].every((key) => typeof INTRINSICS.reflect.read(result, key) === "string") && [
|
|
128
|
+
"failed",
|
|
129
|
+
"expired",
|
|
130
|
+
"aborted",
|
|
131
|
+
"truncated"
|
|
132
|
+
].every((key) => typeof INTRINSICS.reflect.read(result, key) === "boolean");
|
|
107
133
|
});
|
|
108
134
|
}
|
|
109
135
|
/**
|
|
@@ -163,11 +189,11 @@ function createInvalidError(subject, value) {
|
|
|
163
189
|
* @returns A typed run failure carrying its {@link ExecuteResult}
|
|
164
190
|
*/
|
|
165
191
|
function createExecuteError(result, cause) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
192
|
+
const exit = `exited with code ${String(result.code)}`;
|
|
193
|
+
const signal = result.signal !== null ? `was killed by ${result.signal}` : exit;
|
|
194
|
+
const output = result.truncated ? "exceeded its output limit" : signal;
|
|
195
|
+
const abort = result.aborted ? "was aborted" : output;
|
|
196
|
+
const reason = result.expired ? "timed out" : abort;
|
|
171
197
|
return new ProcessError(`Command '${result.command}' ${reason}`, {
|
|
172
198
|
code: result.expired ? "timeout" : "spawn",
|
|
173
199
|
context: {
|
|
@@ -179,7 +205,6 @@ function createExecuteError(result, cause) {
|
|
|
179
205
|
result
|
|
180
206
|
});
|
|
181
207
|
}
|
|
182
|
-
//#endregion
|
|
183
208
|
export { PROCESS_BACKLOG, PROCESS_CONFIRMATION, PROCESS_DRAIN, PROCESS_ERROR_CODES, PROCESS_EVIDENCE, PROCESS_GRACE, PROCESS_OUTPUT, PROCESS_PATHEXT, PROCESS_TIMER, ProcessError, createDuplicateError, createExecuteError, createInvalidError, createProtocolError, isProcessError };
|
|
184
209
|
|
|
185
210
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts"],"sourcesContent":["/** Names the default cooperative POSIX window, 5000 ms, between `SIGTERM` and `SIGKILL` during termination. */\nexport const PROCESS_GRACE = 5_000\n\n/** Names the window, 5000 ms, a termination waits for the child's native exit after the final kill. */\nexport const PROCESS_CONFIRMATION = 5_000\n\n/**\n * Names the default window, 1000 ms, the package waits for the child's read ends to close after the\n * child's native exit or after a termination this package initiated, before cutting them off.\n *\n * @remarks\n * Measured on Windows 11 with Node v24.18.1 on 2026-08-21, spawning the `tests/src/server/fixtures`\n * child modes as real children and timing the host `close` event against the host `exit` event.\n * Every ordinary run closed within 0.02ms of the native exit, whether the child ended itself or a\n * kill ended it, and a `taskkill /F /T` that reaped a descendant while the root was still alive\n * closed within 0.01ms. The only finite late close came from a descendant that outlived its root and\n * then ended on its own, at 127.44ms to 193.41ms — that lag is the descendant's own remaining life\n * rather than a flush cost. A descendant that never ends never closes, so the distribution has no\n * finite tail to cover and this value bounds it instead: 1000ms is over five times the slowest\n * finite close measured, and it keeps an unreachable descendant from stretching a shutdown.\n */\nexport const PROCESS_DRAIN = 1_000\n\n/** Names the default maximum retained stderr tail, 2048 bytes, for a supervised {@link ProcessInterface}. */\nexport const PROCESS_EVIDENCE = 2_048\n\n/** Names the default soft high-water mark, 10485760 bytes, for a supervised {@link ProcessInterface} line backlog. */\nexport const PROCESS_BACKLOG = 10_485_760\n\n/** Names the default maximum captured bytes, 10485760 each, for a one-shot run's stdout and stderr. */\nexport const PROCESS_OUTPUT = 10_485_760\n\n/** Names the largest timer delay, 2147483647 ms, the host schedules without truncating it to one. */\nexport const PROCESS_TIMER = 2_147_483_647\n\n/** Lists the executable extensions a Windows lookup applies when the environment declares no `PATHEXT`, `.COM;.EXE;.BAT;.CMD`. */\nexport const PROCESS_PATHEXT = '.COM;.EXE;.BAT;.CMD'\n\n/**\n * Lists the machine-readable failure categories a {@link ProcessError} carries, in declaration order:\n * `spawn`, `timeout`, `input`, `duplicate`, `protocol`, and `invalid`.\n */\nexport const PROCESS_ERROR_CODES = Object.freeze([\n\t'spawn',\n\t'timeout',\n\t'input',\n\t'duplicate',\n\t'protocol',\n\t'invalid',\n] as const)\n","import type {\n\tProcessErrorCode,\n\tProcessErrorContext,\n\tProcessErrorOptions,\n\tExecuteResult,\n} from './types.js'\nimport { holds, isError } from '@orkestrel/contract'\nimport { PROCESS_ERROR_CODES } from './constants.js'\n\n/**\n * Represents a child-process failure with a stable machine-readable category.\n *\n * @example\n * ```ts\n * const error = new ProcessError('git status refused', {\n * \tcode: 'invalid',\n * \tcontext: { command: 'git status' },\n * })\n * error.code // 'invalid'\n * ```\n */\nexport class ProcessError extends Error {\n\toverride readonly name = 'ProcessError'\n\treadonly code: ProcessErrorCode\n\treadonly context?: ProcessErrorContext\n\t/** Carries the buffered run outcome, present when a one-shot run produced the failure. */\n\treadonly result?: ExecuteResult\n\n\t/**\n\t * Creates a process error.\n\t *\n\t * @param message - Human-readable failure description\n\t * @param options - Machine-readable category, optional context, optional cause, and optional run result\n\t */\n\tconstructor(message: string, options: ProcessErrorOptions) {\n\t\tconst cause = options.cause\n\t\tsuper(message, cause === undefined ? undefined : { cause })\n\t\tObject.defineProperty(this, Symbol.for('@orkestrel/process.error'), { value: true })\n\t\tthis.code = options.code\n\t\tif (options.context !== undefined) this.context = options.context\n\t\tif (options.result !== undefined) this.result = options.result\n\t}\n}\n\n/**\n * Checks whether an unknown value is a {@link ProcessError}.\n *\n * @remarks\n * Recognition combines a global own-property brand with the native `Error` base, the subclass\n * prototype, the fixed name, and a code {@link PROCESS_ERROR_CODES} declares. The brand is\n * recognized across duplicate installations and ESM/CommonJS module copies at 0.0.4 or later. A copy\n * earlier than 0.0.4 stamps no brand, so an error it throws stays outside the type, and so does a\n * plain or property-only lookalike.\n *\n * @param value - The value to inspect\n * @returns True if the value is a `ProcessError` instance; false otherwise\n *\n * @example\n * ```ts\n * isProcessError(new ProcessError('spawn failed', { code: 'spawn' })) // true\n * isProcessError(new Error('spawn failed')) // false\n * ```\n */\nexport function isProcessError(value: unknown): value is ProcessError {\n\tif (!isError(value)) return false\n\treturn holds(() => {\n\t\tif (Object.getPrototypeOf(value) === Error.prototype) return false\n\t\tif (value.name !== 'ProcessError' || !('code' in value)) return false\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(\n\t\t\tvalue,\n\t\t\tSymbol.for('@orkestrel/process.error'),\n\t\t)\n\t\tif (descriptor?.value !== true) return false\n\t\tconst code: unknown = value.code\n\t\treturn PROCESS_ERROR_CODES.some((declared) => declared === code)\n\t})\n}\n\n/**\n * Creates the `duplicate`-coded failure raised when a manager launch reuses a live id.\n *\n * @param id - The id already occupied by a live child\n * @returns A typed duplicate-id failure\n */\nexport function createDuplicateError(id: string): ProcessError {\n\treturn new ProcessError(`Process '${id}' is already live`, {\n\t\tcode: 'duplicate',\n\t\tcontext: { id },\n\t})\n}\n\n/**\n * Creates the `protocol`-coded failure raised when a launch is attempted on a registry that is\n * being destroyed.\n *\n * @param id - The id the refused launch asked for\n * @returns A typed protocol failure\n */\nexport function createProtocolError(id: string): ProcessError {\n\treturn new ProcessError(`Process '${id}' cannot launch: the registry is destroyed`, {\n\t\tcode: 'protocol',\n\t\tcontext: { id },\n\t})\n}\n\n/**\n * Creates the `invalid`-coded failure raised when a public input is refused before anything is\n * spawned.\n *\n * @param subject - The rejected input named as the caller wrote it, such as `option 'grace'`\n * @param value - The rejected value, carried as `context.value`\n * @returns A typed validation failure\n *\n * @example\n * ```ts\n * createInvalidError(\"option 'grace'\", -1).code // 'invalid'\n * ```\n */\nexport function createInvalidError(subject: string, value: unknown): ProcessError {\n\treturn new ProcessError(`Invalid ${subject}`, { code: 'invalid', context: { value } })\n}\n\n/**\n * Creates the failure raised when a run does not complete successfully and rejection is requested.\n *\n * @remarks\n * The category is `timeout` only when the run's own timeout elapsed; every other failure,\n * including an abort and an output overflow, is a `spawn` failure carrying its\n * {@link ExecuteResult}.\n *\n * @param result - The buffered run outcome that failed\n * @param cause - The underlying host fault, when one ended the run\n * @returns A typed run failure carrying its {@link ExecuteResult}\n */\nexport function createExecuteError(result: ExecuteResult, cause?: unknown): ProcessError {\n\tlet reason = `exited with code ${String(result.code)}`\n\tif (result.signal !== null) reason = `was killed by ${result.signal}`\n\tif (result.truncated) reason = 'exceeded its output limit'\n\tif (result.aborted) reason = 'was aborted'\n\tif (result.expired) reason = 'timed out'\n\treturn new ProcessError(`Command '${result.command}' ${reason}`, {\n\t\tcode: result.expired ? 'timeout' : 'spawn',\n\t\tcontext: { command: result.command, code: result.code, signal: result.signal },\n\t\t...(cause === undefined ? {} : { cause }),\n\t\tresult,\n\t})\n}\n"],"mappings":";;;AACA,IAAa,gBAAgB;;AAG7B,IAAa,uBAAuB;;;;;;;;;;;;;;;;AAiBpC,IAAa,gBAAgB;;AAG7B,IAAa,mBAAmB;;AAGhC,IAAa,kBAAkB;;AAG/B,IAAa,iBAAiB;;AAG9B,IAAa,gBAAgB;;AAG7B,IAAa,kBAAkB;;;;;AAM/B,IAAa,sBAAsB,OAAO,OAAO;CAChD;CACA;CACA;CACA;CACA;CACA;AACD,CAAU;;;;;;;;;;;;;;;AC5BV,IAAa,eAAb,cAAkC,MAAM;CACvC,OAAyB;CACzB;CACA;;CAEA;;;;;;;CAQA,YAAY,SAAiB,SAA8B;EAC1D,MAAM,QAAQ,QAAQ;EACtB,MAAM,SAAS,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,MAAM,CAAC;EAC1D,OAAO,eAAe,MAAM,OAAO,IAAI,0BAA0B,GAAG,EAAE,OAAO,KAAK,CAAC;EACnF,KAAK,OAAO,QAAQ;EACpB,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;EAC1D,IAAI,QAAQ,WAAW,KAAA,GAAW,KAAK,SAAS,QAAQ;CACzD;AACD;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,eAAe,OAAuC;CACrE,IAAI,CAAC,QAAQ,KAAK,GAAG,OAAO;CAC5B,OAAO,YAAY;EAClB,IAAI,OAAO,eAAe,KAAK,MAAM,MAAM,WAAW,OAAO;EAC7D,IAAI,MAAM,SAAS,kBAAkB,EAAE,UAAU,QAAQ,OAAO;EAKhE,IAJmB,OAAO,yBACzB,OACA,OAAO,IAAI,0BAA0B,CAElC,CAAA,EAAY,UAAU,MAAM,OAAO;EACvC,MAAM,OAAgB,MAAM;EAC5B,OAAO,oBAAoB,MAAM,aAAa,aAAa,IAAI;CAChE,CAAC;AACF;;;;;;;AAQA,SAAgB,qBAAqB,IAA0B;CAC9D,OAAO,IAAI,aAAa,YAAY,GAAG,oBAAoB;EAC1D,MAAM;EACN,SAAS,EAAE,GAAG;CACf,CAAC;AACF;;;;;;;;AASA,SAAgB,oBAAoB,IAA0B;CAC7D,OAAO,IAAI,aAAa,YAAY,GAAG,6CAA6C;EACnF,MAAM;EACN,SAAS,EAAE,GAAG;CACf,CAAC;AACF;;;;;;;;;;;;;;AAeA,SAAgB,mBAAmB,SAAiB,OAA8B;CACjF,OAAO,IAAI,aAAa,WAAW,WAAW;EAAE,MAAM;EAAW,SAAS,EAAE,MAAM;CAAE,CAAC;AACtF;;;;;;;;;;;;;AAcA,SAAgB,mBAAmB,QAAuB,OAA+B;CACxF,IAAI,SAAS,oBAAoB,OAAO,OAAO,IAAI;CACnD,IAAI,OAAO,WAAW,MAAM,SAAS,iBAAiB,OAAO;CAC7D,IAAI,OAAO,WAAW,SAAS;CAC/B,IAAI,OAAO,SAAS,SAAS;CAC7B,IAAI,OAAO,SAAS,SAAS;CAC7B,OAAO,IAAI,aAAa,YAAY,OAAO,QAAQ,IAAI,UAAU;EAChE,MAAM,OAAO,UAAU,YAAY;EACnC,SAAS;GAAE,SAAS,OAAO;GAAS,MAAM,OAAO;GAAM,QAAQ,OAAO;EAAO;EAC7E,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;EACvC;CACD,CAAC;AACF"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts"],"sourcesContent":["/** Names the default cooperative POSIX window, 5000 ms, between `SIGTERM` and `SIGKILL` during termination. */\nexport const PROCESS_GRACE = 5_000\n\n/** Names the window, 5000 ms, a termination waits for the child's native exit after the final kill. */\nexport const PROCESS_CONFIRMATION = 5_000\n\n/**\n * Names the default window, 1000 ms, the package waits for the child's read ends to close after the\n * child's native exit or after a termination this package initiated, before cutting them off.\n *\n * @remarks\n * Measured on Windows 11 with Node v24.18.1 on 2026-08-21, spawning the `tests/src/server/fixtures`\n * child modes as real children and timing the host `close` event against the host `exit` event.\n * Every ordinary run closed within 0.02ms of the native exit, whether the child ended itself or a\n * kill ended it, and a `taskkill /F /T` that reaped a descendant while the root was still alive\n * closed within 0.01ms. The only finite late close came from a descendant that outlived its root and\n * then ended on its own, at 127.44ms to 193.41ms — that lag is the descendant's own remaining life\n * rather than a flush cost. A descendant that never ends never closes, so the distribution has no\n * finite tail to cover and this value bounds it instead: 1000ms is over five times the slowest\n * finite close measured, and it keeps an unreachable descendant from stretching a shutdown.\n */\nexport const PROCESS_DRAIN = 1_000\n\n/** Names the default maximum retained stderr tail, 2048 bytes, for a supervised {@link ProcessInterface}. */\nexport const PROCESS_EVIDENCE = 2_048\n\n/** Names the default soft high-water mark, 10485760 bytes, for a supervised {@link ProcessInterface} line backlog. */\nexport const PROCESS_BACKLOG = 10_485_760\n\n/** Names the default maximum captured bytes, 10485760 each, for a one-shot run's stdout and stderr. */\nexport const PROCESS_OUTPUT = 10_485_760\n\n/** Names the largest timer delay, 2147483647 ms, the host schedules without truncating it to one. */\nexport const PROCESS_TIMER = 2_147_483_647\n\n/** Lists the executable extensions a Windows lookup applies when the environment declares no `PATHEXT`, `.COM;.EXE;.BAT;.CMD`. */\nexport const PROCESS_PATHEXT = '.COM;.EXE;.BAT;.CMD'\n\n/**\n * Lists the machine-readable failure categories a {@link ProcessError} carries, in declaration order:\n * `spawn`, `timeout`, `input`, `duplicate`, `protocol`, and `invalid`.\n */\nexport const PROCESS_ERROR_CODES = Object.freeze([\n\t'spawn',\n\t'timeout',\n\t'input',\n\t'duplicate',\n\t'protocol',\n\t'invalid',\n] as const)\n","import type {\n\tProcessErrorCode,\n\tProcessErrorContext,\n\tProcessErrorOptions,\n\tExecuteResult,\n} from './types.js'\nimport { holds, INTRINSICS, isFunction, isObject } from '@orkestrel/contract'\nimport { PROCESS_ERROR_CODES } from './constants.js'\n\n/**\n * Represents a child-process failure with a stable machine-readable category.\n *\n * @example\n * ```ts\n * const error = new ProcessError('git status refused', {\n * \tcode: 'invalid',\n * \tcontext: { command: 'git status' },\n * })\n * error.code // 'invalid'\n * ```\n */\nexport class ProcessError extends Error {\n\toverride readonly name = 'ProcessError'\n\treadonly code: ProcessErrorCode\n\treadonly context?: ProcessErrorContext\n\t/** Carries the buffered run outcome, present when a one-shot run produced the failure. */\n\treadonly result?: ExecuteResult\n\n\t/**\n\t * Creates a process error.\n\t *\n\t * @param message - Human-readable failure description\n\t * @param options - Machine-readable category, optional context, optional cause, and optional run result\n\t */\n\tconstructor(message: string, options: ProcessErrorOptions) {\n\t\tconst cause = options.cause\n\t\tsuper(message, cause === undefined ? undefined : { cause })\n\t\tINTRINSICS.define(this, Symbol.for('@orkestrel/process.error'), { value: this })\n\t\tthis.code = options.code\n\t\tif (options.context !== undefined) this.context = options.context\n\t\tif (options.result !== undefined) this.result = options.result\n\t}\n}\n\n/**\n * Checks whether an unknown value is a {@link ProcessError}.\n *\n * @remarks\n * Recognition requires a global own-property identity brand, the native `Error` base, a subclass\n * prototype, a declared code, and correctly shaped optional context and result members. Subclass\n * instances pass without reading `name`. Duplicate installations and ESM/CommonJS copies that stamp\n * their own identity recognize each other. Older boolean brands, transparent proxies, and plain\n * objects fail recognition.\n *\n * @param value - The value to inspect\n * @returns True if the value is a `ProcessError` instance; false otherwise\n *\n * @example\n * ```ts\n * isProcessError(new ProcessError('spawn failed', { code: 'spawn' })) // true\n * isProcessError(new Error('spawn failed')) // false\n * ```\n */\nexport function isProcessError(value: unknown): value is ProcessError {\n\tif (!isObject(value)) return false\n\treturn holds(() => {\n\t\tif (!(value instanceof INTRINSICS.error)) return false\n\t\tif (INTRINSICS.prototype(value) === INTRINSICS.error.prototype) return false\n\t\tconst descriptor = INTRINSICS.describe(value, Symbol.for('@orkestrel/process.error'))\n\t\tif (descriptor?.value !== value) return false\n\t\tconst code: unknown = INTRINSICS.reflect.read(value, 'code')\n\t\tif (!PROCESS_ERROR_CODES.some((declared) => declared === code)) return false\n\t\tconst context: unknown = INTRINSICS.reflect.read(value, 'context')\n\t\tif (context !== undefined) {\n\t\t\tif (!isObject(context) && !isFunction(context)) return false\n\t\t\tif (\n\t\t\t\t!['id', 'command'].every((key) => {\n\t\t\t\t\tconst member: unknown = INTRINSICS.reflect.read(context, key)\n\t\t\t\t\treturn member === undefined || typeof member === 'string'\n\t\t\t\t})\n\t\t\t)\n\t\t\t\treturn false\n\t\t\tconst exit: unknown = INTRINSICS.reflect.read(context, 'code')\n\t\t\tconst signal: unknown = INTRINSICS.reflect.read(context, 'signal')\n\t\t\tif (exit !== undefined && exit !== null && typeof exit !== 'number') return false\n\t\t\tif (signal !== undefined && signal !== null && typeof signal !== 'string') return false\n\t\t}\n\t\tconst result: unknown = INTRINSICS.reflect.read(value, 'result')\n\t\tif (result === undefined) return true\n\t\tif (!isObject(result)) return false\n\t\tconst exit: unknown = INTRINSICS.reflect.read(result, 'code')\n\t\tconst signal: unknown = INTRINSICS.reflect.read(result, 'signal')\n\t\treturn (\n\t\t\t(exit === null || typeof exit === 'number') &&\n\t\t\t(signal === null || typeof signal === 'string') &&\n\t\t\t['command', 'stdout', 'stderr'].every(\n\t\t\t\t(key) => typeof INTRINSICS.reflect.read(result, key) === 'string',\n\t\t\t) &&\n\t\t\t['failed', 'expired', 'aborted', 'truncated'].every(\n\t\t\t\t(key) => typeof INTRINSICS.reflect.read(result, key) === 'boolean',\n\t\t\t)\n\t\t)\n\t})\n}\n\n/**\n * Creates the `duplicate`-coded failure raised when a manager launch reuses a live id.\n *\n * @param id - The id already occupied by a live child\n * @returns A typed duplicate-id failure\n */\nexport function createDuplicateError(id: string): ProcessError {\n\treturn new ProcessError(`Process '${id}' is already live`, {\n\t\tcode: 'duplicate',\n\t\tcontext: { id },\n\t})\n}\n\n/**\n * Creates the `protocol`-coded failure raised when a launch is attempted on a registry that is\n * being destroyed.\n *\n * @param id - The id the refused launch asked for\n * @returns A typed protocol failure\n */\nexport function createProtocolError(id: string): ProcessError {\n\treturn new ProcessError(`Process '${id}' cannot launch: the registry is destroyed`, {\n\t\tcode: 'protocol',\n\t\tcontext: { id },\n\t})\n}\n\n/**\n * Creates the `invalid`-coded failure raised when a public input is refused before anything is\n * spawned.\n *\n * @param subject - The rejected input named as the caller wrote it, such as `option 'grace'`\n * @param value - The rejected value, carried as `context.value`\n * @returns A typed validation failure\n *\n * @example\n * ```ts\n * createInvalidError(\"option 'grace'\", -1).code // 'invalid'\n * ```\n */\nexport function createInvalidError(subject: string, value: unknown): ProcessError {\n\treturn new ProcessError(`Invalid ${subject}`, { code: 'invalid', context: { value } })\n}\n\n/**\n * Creates the failure raised when a run does not complete successfully and rejection is requested.\n *\n * @remarks\n * The category is `timeout` only when the run's own timeout elapsed; every other failure,\n * including an abort and an output overflow, is a `spawn` failure carrying its\n * {@link ExecuteResult}.\n *\n * @param result - The buffered run outcome that failed\n * @param cause - The underlying host fault, when one ended the run\n * @returns A typed run failure carrying its {@link ExecuteResult}\n */\nexport function createExecuteError(result: ExecuteResult, cause?: unknown): ProcessError {\n\tconst exit = `exited with code ${String(result.code)}`\n\tconst signal = result.signal !== null ? `was killed by ${result.signal}` : exit\n\tconst output = result.truncated ? 'exceeded its output limit' : signal\n\tconst abort = result.aborted ? 'was aborted' : output\n\tconst reason = result.expired ? 'timed out' : abort\n\treturn new ProcessError(`Command '${result.command}' ${reason}`, {\n\t\tcode: result.expired ? 'timeout' : 'spawn',\n\t\tcontext: { command: result.command, code: result.code, signal: result.signal },\n\t\t...(cause === undefined ? {} : { cause }),\n\t\tresult,\n\t})\n}\n"],"mappings":"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"}
|