@orkestrel/process 0.0.3 → 0.0.4

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.
@@ -10,6 +10,20 @@ import { EmitterInterface } from '@orkestrel/emitter';
10
10
  */
11
11
  export declare function createDuplicateError(id: string): ProcessError;
12
12
 
13
+ /**
14
+ * Creates the failure raised when a run does not complete successfully and rejection is requested.
15
+ *
16
+ * @remarks
17
+ * The category is `timeout` only when the run's own timeout elapsed; every other failure,
18
+ * including an abort and an output overflow, is a `spawn` failure carrying its
19
+ * {@link ExecuteResult}.
20
+ *
21
+ * @param result - The buffered run outcome that failed
22
+ * @param cause - The underlying host fault, when one ended the run
23
+ * @returns A typed run failure carrying its {@link ExecuteResult}
24
+ */
25
+ export declare function createExecuteError(result: ExecuteResult, cause?: unknown): ProcessError;
26
+
13
27
  /**
14
28
  * Creates the failure raised when a public input is refused before anything is spawned.
15
29
  *
@@ -32,19 +46,6 @@ export declare function createInvalidError(subject: string, value: unknown): Pro
32
46
  */
33
47
  export declare function createProtocolError(id: string): ProcessError;
34
48
 
35
- /**
36
- * Creates the failure raised when a run does not complete successfully and rejection is requested.
37
- *
38
- * @remarks
39
- * The category is `timeout` only when the run's own timeout elapsed; every other failure, including
40
- * an abort and an output overflow, is a `spawn` failure carrying its {@link RunResult}.
41
- *
42
- * @param result - The buffered run outcome that failed
43
- * @param cause - The underlying host fault, when one ended the run
44
- * @returns A typed run failure carrying its {@link RunResult}
45
- */
46
- export declare function createRunError(result: RunResult, cause?: unknown): ProcessError;
47
-
48
49
  /**
49
50
  * Options for a detached fire-and-forget spawn.
50
51
  *
@@ -71,9 +72,137 @@ export declare interface ExecutableOptions {
71
72
  readonly environment?: Readonly<Record<string, string | undefined>>;
72
73
  }
73
74
 
75
+ /**
76
+ * The captured bytes and terminal facts one settled {@link ExecuteResult} is built from.
77
+ *
78
+ * @remarks
79
+ * Each byte field is trimmed to `limit` on a code-point boundary when the result is built, so a
80
+ * caller passes the raw retained head and never a decoded string. `cause` carries the host fault
81
+ * that ended the run, when one did; its presence alone marks the run failed.
82
+ */
83
+ export declare interface ExecuteInput {
84
+ /** The diagnostic command line. */
85
+ readonly command: string;
86
+ /** The retained standard-output bytes. */
87
+ readonly stdout: Uint8Array;
88
+ /** The retained standard-error bytes. */
89
+ readonly stderr: Uint8Array;
90
+ readonly code: number | null;
91
+ readonly signal: string | null;
92
+ /** If `true`, the run's own timeout elapsed; if `false`, it did not. */
93
+ readonly expired: boolean;
94
+ /** If `true`, the caller's signal aborted the run; if `false`, it did not. */
95
+ readonly aborted: boolean;
96
+ /** If `true`, a stream exceeded `limit`; if `false`, neither did. */
97
+ readonly truncated: boolean;
98
+ /** The maximum retained bytes for each stream. */
99
+ readonly limit: number;
100
+ /** The host fault that ended the run, when one did. */
101
+ readonly cause?: unknown;
102
+ }
103
+
104
+ /**
105
+ * Options for a one-shot run.
106
+ *
107
+ * @remarks
108
+ * A run is a fire-and-collect function, not a lifecycle entity, so it carries no emitter. `strict`
109
+ * decides how a failure is delivered: by default a non-zero exit rejects with a
110
+ * {@link ProcessError} carrying the {@link ExecuteResult}; `strict: false` resolves with the result
111
+ * instead, so the caller inspects `failed`. An invalid option or command rejects before the child is
112
+ * spawned, with a {@link ProcessError} coded `invalid`. `input` is standard-input payload and carries
113
+ * no NUL restriction. An unbounded run awaits stdio completion rather than process exit, so give
114
+ * `timeout` a value wherever a descendant may inherit the child's stdio and hold the pipe open past
115
+ * the child's own exit. Every option is read once, before the child is spawned, so the value
116
+ * validated is the value spawned and a caller's own getter runs while nothing has started: a getter
117
+ * that throws strands no process.
118
+ */
119
+ export declare interface ExecuteOptions {
120
+ /** The working directory. Default: the current working directory. */
121
+ readonly workspace?: string;
122
+ /** Environment overrides merged over the parent environment; an `undefined` value unsets a key. */
123
+ readonly environment?: Readonly<Record<string, string | undefined>>;
124
+ /** Standard-input payload written to the child, including any NUL characters. */
125
+ readonly input?: string;
126
+ /** Milliseconds before the child is terminated. `0` or omitted disables the timeout. */
127
+ readonly timeout?: number;
128
+ /** Cooperative POSIX window between `SIGTERM` and `SIGKILL` when terminating. Default: {@link PROCESS_GRACE}. */
129
+ readonly grace?: number;
130
+ /** Aborting this signal terminates the run and reports `aborted`. */
131
+ readonly signal?: AbortSignal;
132
+ /** If `false`, resolve with the result on failure instead of rejecting. Default: `true`. */
133
+ readonly strict?: boolean;
134
+ /** Maximum captured bytes for stdout and for stderr, each. Default: {@link PROCESS_OUTPUT}. */
135
+ readonly limit?: number;
136
+ }
137
+
138
+ /**
139
+ * The settled outcome of a one-shot run: the buffered output and the terminal state.
140
+ *
141
+ * @remarks
142
+ * `failed` is `true` when the child exited non-zero, was killed by a signal, expired, was aborted, or
143
+ * failed to spawn. `expired` and `aborted` name the ways the run ended the child rather than the
144
+ * child ending itself, and only the earliest observed is recorded. `truncated` is independent of
145
+ * both: it reports that a captured stream omitted output because it exceeded `limit`, which fails a
146
+ * synchronous run and does not fail an asynchronous one. `ProcessInterface` carries the same name for
147
+ * the same fact against a supervised child's retention bounds. A spawn fault reports the host's negative errno for `execute`. A spawn fault reports
148
+ * `null` for `executeSync`.
149
+ */
150
+ export declare interface ExecuteResult {
151
+ /** The command line that was run, for diagnostics. */
152
+ readonly command: string;
153
+ /** The captured standard output, byte-bounded by `limit`. */
154
+ readonly stdout: string;
155
+ /** The captured standard error, byte-bounded by `limit`. */
156
+ readonly stderr: string;
157
+ /** The exit code. A spawn fault reports the host's negative errno for `execute` and `null` for `executeSync`. */
158
+ readonly code: number | null;
159
+ readonly signal: string | null;
160
+ /** True if the run did not complete successfully. */
161
+ readonly failed: boolean;
162
+ /** True if the run's `timeout` elapsed before completion. */
163
+ readonly expired: boolean;
164
+ /** True if the caller's `signal` aborted the run before completion. */
165
+ readonly aborted: boolean;
166
+ /** True when either captured stream omitted output because it exceeded `limit`. */
167
+ readonly truncated: boolean;
168
+ }
169
+
170
+ /**
171
+ * Options for a synchronous one-shot run.
172
+ *
173
+ * @remarks
174
+ * The synchronous host offers neither a cooperative termination window nor in-flight cancellation,
175
+ * so this contract carries no `grace` and no `signal`. A `timeout` ends only the root process and can
176
+ * leave descendants running; use `execute` or {@link ProcessInterface} when timeout must terminate the
177
+ * tree. A `timeout` and an output overflow both end the root with `SIGKILL`; an overflow reports
178
+ * `truncated` and `failed` together, which is where `execute` and `executeSync` genuinely differ.
179
+ * `input` is standard-input payload and carries no NUL restriction.
180
+ */
181
+ export declare interface ExecuteSyncOptions {
182
+ /** The working directory. Default: the current working directory. */
183
+ readonly workspace?: string;
184
+ /** Environment overrides merged over the parent environment; an `undefined` value unsets a key. */
185
+ readonly environment?: Readonly<Record<string, string | undefined>>;
186
+ /** Standard-input payload written to the child, including any NUL characters. */
187
+ readonly input?: string;
188
+ /** Milliseconds before the host kills the root process alone. `0` or omitted disables the timeout. */
189
+ readonly timeout?: number;
190
+ /** If `false`, return the result on failure instead of throwing. Default: `true`. */
191
+ readonly strict?: boolean;
192
+ /** Maximum captured bytes for stdout and for stderr, each. Default: {@link PROCESS_OUTPUT}. */
193
+ readonly limit?: number;
194
+ }
195
+
74
196
  /**
75
197
  * Checks whether an unknown value is a {@link ProcessError}.
76
198
  *
199
+ * @remarks
200
+ * Recognition combines a global own-property brand with the native `Error` base, the subclass
201
+ * prototype, the fixed name, and a code {@link PROCESS_ERROR_CODES} declares. The brand is
202
+ * recognized across duplicate installations and ESM/CommonJS module copies at 0.0.4 or later. A copy
203
+ * earlier than 0.0.4 stamps no brand, so an error it throws stays outside the type, and so does a
204
+ * plain or property-only lookalike.
205
+ *
77
206
  * @param value - The value to inspect
78
207
  * @returns True only for a `ProcessError` instance; false otherwise
79
208
  *
@@ -91,6 +220,9 @@ export declare const PROCESS_BACKLOG = 10485760;
91
220
  /** The window in milliseconds a termination waits for the child's native exit after the final kill. */
92
221
  export declare const PROCESS_CONFIRMATION = 5000;
93
222
 
223
+ /** The machine-readable failure categories a {@link ProcessError} carries, in declaration order. */
224
+ export declare const PROCESS_ERROR_CODES: readonly ["spawn", "timeout", "duplicate", "protocol", "invalid"];
225
+
94
226
  /** The default maximum retained stderr tail in bytes for a supervised {@link ProcessInterface}. */
95
227
  export declare const PROCESS_EVIDENCE = 2048;
96
228
 
@@ -110,13 +242,13 @@ export declare const PROCESS_TIMER = 2147483647;
110
242
  * The public contracts for `@orkestrel/process`: a typed child-process toolkit.
111
243
  *
112
244
  * @remarks
113
- * Three tiers, smallest to largest:
245
+ * The tiers divide by lifetime:
114
246
  *
115
247
  * - **{@link ProcessInterface}** — one supervised child with framed stdout lines under a bounded
116
248
  * backlog, a byte-bounded stderr tail, a live stderr event, a writable stdin channel, a typed
117
249
  * lifecycle {@link ProcessEventMap} emitter, and bounded termination. The low-level streaming
118
250
  * primitive.
119
- * - **{@link RunResult} / run** — a one-shot runner that buffers a child to completion and settles
251
+ * - **{@link ExecuteResult} / execute** — a one-shot spawn that buffers a child to completion and settles
120
252
  * with its output and exit, the ergonomic layer for fire-and-collect commands.
121
253
  * - **{@link ProcessManagerInterface}** — a keyed registry of live {@link ProcessInterface}
122
254
  * children, launched and stopped by id, observed through its own {@link ProcessManagerEventMap}.
@@ -131,16 +263,19 @@ export declare const PROCESS_TIMER = 2147483647;
131
263
  * @remarks
132
264
  * `environment` merges over the parent process environment unless `isolated` is `true`, and an
133
265
  * `undefined` value unsets a key. On Windows the merge is case-insensitive and the last writer
134
- * wins, matching how the host resolves an environment variable. `input` is written to the child's
135
- * stdin immediately after spawn. Every string here is spawn-bound: an empty `file`, or a NUL
136
- * character anywhere, is refused with a {@link ProcessError} coded `invalid`.
266
+ * wins, matching how the host resolves an environment variable. `input` is standard-input payload
267
+ * written immediately after spawn, so it carries no NUL restriction. Every spawn-bound string here
268
+ * is validated: an empty `file`, or a NUL character in `file`, `arguments`, or `environment`, is
269
+ * refused with a {@link ProcessError} coded `invalid`. On a POSIX host, `isolated: true` leaves no
270
+ * `PATH`, so pass an absolute `file` or include `PATH` in `environment`. On Windows, libuv injects a
271
+ * host environment set even when `isolated` is `true`.
137
272
  */
138
273
  export declare interface ProcessCommand {
139
274
  readonly file: string;
140
275
  readonly arguments: readonly string[];
141
276
  readonly environment?: Readonly<Record<string, string | undefined>>;
142
277
  readonly input?: string;
143
- /** If `true`, the child environment is `environment` alone; if `false` or omitted, it merges over the parent environment. */
278
+ /** If `true`, exclude the parent environment; on POSIX this leaves no `PATH`, while Windows libuv still injects a host set. */
144
279
  readonly isolated?: boolean;
145
280
  }
146
281
 
@@ -150,7 +285,7 @@ export declare class ProcessError extends Error {
150
285
  readonly code: ProcessErrorCode;
151
286
  readonly context?: ProcessErrorContext;
152
287
  /** The buffered run outcome, present when a one-shot run produced the failure. */
153
- readonly result?: RunResult;
288
+ readonly result?: ExecuteResult;
154
289
  /**
155
290
  * Create a process error.
156
291
  *
@@ -160,8 +295,8 @@ export declare class ProcessError extends Error {
160
295
  constructor(message: string, options: ProcessErrorOptions);
161
296
  }
162
297
 
163
- /** The machine-readable {@link ProcessError} categories. */
164
- export declare type ProcessErrorCode = 'spawn' | 'timeout' | 'duplicate' | 'protocol' | 'invalid';
298
+ /** The machine-readable {@link ProcessError} categories, derived from {@link PROCESS_ERROR_CODES}. */
299
+ export declare type ProcessErrorCode = (typeof PROCESS_ERROR_CODES)[number];
165
300
 
166
301
  /** Structured context carried by a {@link ProcessError}. */
167
302
  export declare interface ProcessErrorContext {
@@ -185,8 +320,8 @@ export declare interface ProcessErrorOptions {
185
320
  readonly context?: ProcessErrorContext;
186
321
  /** The underlying cause, when one exists. */
187
322
  readonly cause?: unknown;
188
- /** The buffered run outcome, present when a {@link RunResult} produced the failure. */
189
- readonly result?: RunResult;
323
+ /** The buffered run outcome, present when an {@link ExecuteResult} produced the failure. */
324
+ readonly result?: ExecuteResult;
190
325
  }
191
326
 
192
327
  /**
@@ -210,7 +345,7 @@ export declare type ProcessEventMap = {
210
345
 
211
346
  /** The observed terminal state of a child process: its exit code, or the signal that ended it. */
212
347
  export declare interface ProcessExit {
213
- /** The exit code, or `null` when a signal ended the process. */
348
+ /** The exit code, or `null` when a signal ended the process. A spawn fault reports the host's negative errno for `Process` and `execute`. */
214
349
  readonly code: number | null;
215
350
  /** The terminating signal name, or `null` when the process exited on its own. */
216
351
  readonly signal: string | null;
@@ -221,24 +356,43 @@ export declare interface ProcessExit {
221
356
  *
222
357
  * @remarks
223
358
  * `lines` is pumped as soon as the child writes, and it is a single-consumer stream: each line goes
224
- * to exactly one waiting iterator, so two iterators split the output between them rather than each
225
- * receiving all of it. The policy for an unconsumed backlog follows
226
- * consumer intent. Once an iterator has been requested, stdout pauses at the `backlog` mark and
227
- * resumes at half of it, so the consumer loses nothing and the child feels real backpressure. While
359
+ * to exactly one waiting iterator, so concurrent iterators split the output between them rather
360
+ * than each receiving all of it. The policy for an unconsumed backlog follows consumer intent. After an iterator has been requested, stdout pauses at the `backlog` mark and
361
+ * resumes at half of it, so the consumer loses nothing before termination and the child feels real
362
+ * backpressure. Termination never reapplies the pause, so from the moment a stop begins retention is
363
+ * capped at twice `backlog` and later lines are dropped. While
228
364
  * no iterator has ever been requested, stdout keeps draining so `exit` still resolves, and retention
229
365
  * stops at the mark: a consumer attaching after that point receives the retained head, a gap, then
230
366
  * the live stream. `evidence` is the decoded, byte-bounded stderr tail — the diagnostic to attach to
231
- * a failed exit. The typed `emitter` carries the live `stderr` chunks, the child `error` cause, and
232
- * the terminal `exit`, alongside the `exit` promise. `stop` and `destroy` are idempotent and never
233
- * reject.
367
+ * a failed exit. `truncated` reports that the `lines` stream omitted output, because a retention
368
+ * bound was reached; the one-shot `ExecuteResult` carries the same name for the same fact against
369
+ * its own capture `limit`. The typed `emitter` carries the live `stderr` chunks, the child `error` cause, and the
370
+ * terminal `exit`, alongside the `exit` promise. `stop` and `destroy` are idempotent and never reject.
371
+ *
372
+ * The spawn is eager, so `pid` is fixed by the time construction returns; a spawn that produced no
373
+ * child reports `undefined` for that child's whole lifetime. An assigned id survives the exit and
374
+ * reports no liveness on its own, because the host reuses a dead child's id. Derive liveness as
375
+ * `pid !== undefined && code === null && signal === null`, and derive it again before every use of
376
+ * the id. `code` and `signal` mirror the host child's own terminal record, so they carry the native
377
+ * exit as soon as the host has it, while the `exit` promise settles on stdio close — a descendant
378
+ * holding inherited stdio keeps that close pending past the native exit, and a supervisor inside
379
+ * that window reads the terminal state here.
234
380
  */
235
381
  export declare interface ProcessInterface {
382
+ /** The host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
383
+ readonly pid: number | undefined;
384
+ /** The exit code the host recorded, or `null` while the child has not exited and when a signal ended it. A spawn fault reports the host's negative errno. */
385
+ readonly code: number | null;
386
+ /** The terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
387
+ readonly signal: string | null;
236
388
  /** The typed lifecycle observation surface. */
237
389
  readonly emitter: EmitterInterface<ProcessEventMap>;
238
390
  /** The captured stdout lines, in arrival order, for one consumer, ending when the child's stdout closes. */
239
391
  readonly lines: AsyncIterable<string>;
240
392
  /** The decoded byte-bounded stderr tail. */
241
393
  readonly evidence: string;
394
+ /** True when the `lines` stream omitted output because a retention bound was reached. */
395
+ readonly truncated: boolean;
242
396
  /** The terminal child state, observed once from the close event. */
243
397
  readonly exit: Promise<ProcessExit>;
244
398
  /**
@@ -331,8 +485,9 @@ export declare interface ProcessManagerInterface {
331
485
  * nothing has started and a throw from one strands no process. A getter that begins `destroy`
332
486
  * without throwing is the one remaining race, and it leaves a bounded residual: the child is
333
487
  * already spawned, so the launch is refused with `protocol` and that child is torn down
334
- * asynchronously, bounded by `grace` plus the confirmation window. The `destroy` barrier settled
335
- * before the refusal, so awaiting it does not cover that teardown.
488
+ * asynchronously, bounded by `grace` plus the confirmation window. The `protocol` refusal throws
489
+ * synchronously before the `destroy` barrier settles. The barrier does not cover that child's
490
+ * asynchronous teardown.
336
491
  *
337
492
  * @param id - The registry key, unique among live children
338
493
  * @param options - The child construction options
@@ -393,10 +548,14 @@ export declare interface ProcessManagerOptions {
393
548
  * `grace` is the cooperative window between `SIGTERM` and `SIGKILL` on a POSIX host; Windows has no
394
549
  * cooperative phase, so the value is unused there. There is no completion deadline — a caller that
395
550
  * wants one arms its own timer and calls `stop`. `backlog` bounds the unconsumed `lines` backlog.
396
- * `on` installs initial {@link ProcessEventMap} listeners and `error` receives isolated listener
397
- * failures. Every numeric option is validated at construction: a timer value outside
551
+ * During termination, retained lines are capped at twice `backlog`; later lines are dropped without
552
+ * pausing stdout, and {@link ProcessInterface.truncated} reports the omission. `on` installs initial
553
+ * {@link ProcessEventMap} listeners and `error` receives isolated listener failures. Every numeric
554
+ * option is validated at construction: a timer value outside
398
555
  * `[0, PROCESS_TIMER]`, a negative or fractional byte value, or a `backlog` below `1` throws a
399
- * {@link ProcessError} coded `invalid`.
556
+ * {@link ProcessError} coded `invalid`. POSIX detachment creates the process group used for tree
557
+ * termination, so the child survives the supervisor's `SIGKILL` and does not receive the terminal's
558
+ * `SIGINT`. A consumer must call `stop` or `destroy` during an orderly shutdown.
400
559
  */
401
560
  export declare interface ProcessOptions {
402
561
  readonly on?: EmitterHooks<ProcessEventMap>;
@@ -408,7 +567,7 @@ export declare interface ProcessOptions {
408
567
  readonly grace?: number;
409
568
  /** Maximum retained stderr tail in bytes. Default: {@link PROCESS_EVIDENCE}. */
410
569
  readonly evidence?: number;
411
- /** Soft high-water mark in bytes for the unconsumed `lines` backlog. Default: {@link PROCESS_BACKLOG}. */
570
+ /** Soft high-water mark in bytes for the unconsumed `lines` backlog; termination retains at most twice this value. Default: {@link PROCESS_BACKLOG}. */
412
571
  readonly backlog?: number;
413
572
  /** If `true`, stdin stays open for {@link ProcessInterface.send}; if `false` or omitted, stdin closes after any initial `input`. */
414
573
  readonly writable?: boolean;
@@ -416,119 +575,6 @@ export declare interface ProcessOptions {
416
575
  readonly signal?: AbortSignal;
417
576
  }
418
577
 
419
- /**
420
- * The captured bytes and terminal facts one settled {@link RunResult} is built from.
421
- *
422
- * @remarks
423
- * Both byte fields are trimmed to `limit` on a code-point boundary when the result is built, so a
424
- * caller passes the raw retained head and never a decoded string. `cause` carries the host fault
425
- * that ended the run, when one did; its presence alone marks the run failed.
426
- */
427
- export declare interface RunInput {
428
- /** The diagnostic command line. */
429
- readonly command: string;
430
- /** The retained standard-output bytes. */
431
- readonly stdout: Uint8Array;
432
- /** The retained standard-error bytes. */
433
- readonly stderr: Uint8Array;
434
- readonly code: number | null;
435
- readonly signal: string | null;
436
- /** If `true`, the run's own timeout elapsed; if `false`, it did not. */
437
- readonly expired: boolean;
438
- /** If `true`, the caller's signal aborted the run; if `false`, it did not. */
439
- readonly aborted: boolean;
440
- /** If `true`, a stream exceeded `limit`; if `false`, both fit. */
441
- readonly truncated: boolean;
442
- /** The maximum retained bytes for each stream. */
443
- readonly limit: number;
444
- /** The host fault that ended the run, when one did. */
445
- readonly cause?: unknown;
446
- }
447
-
448
- /**
449
- * Options for a one-shot run.
450
- *
451
- * @remarks
452
- * A run is a fire-and-collect function, not a lifecycle entity, so it carries no emitter. `strict`
453
- * decides how a failure is delivered: by default a non-zero exit rejects with a
454
- * {@link ProcessError} carrying the {@link RunResult}; `strict: false` resolves with the result
455
- * instead, so the caller inspects `failed`. An invalid option or command rejects before the child is
456
- * spawned, with a {@link ProcessError} coded `invalid`. An unbounded run awaits stdio completion
457
- * rather than process exit, so give `timeout` a value wherever a descendant may inherit the child's
458
- * stdio and hold the pipe open past the child's own exit.
459
- */
460
- export declare interface RunOptions {
461
- /** The working directory. Default: the current working directory. */
462
- readonly workspace?: string;
463
- /** Environment overrides merged over the parent environment; an `undefined` value unsets a key. */
464
- readonly environment?: Readonly<Record<string, string | undefined>>;
465
- /** Standard input written to the child. */
466
- readonly input?: string;
467
- /** Milliseconds before the child is terminated. `0` or omitted disables the timeout. */
468
- readonly timeout?: number;
469
- /** Cooperative POSIX window between `SIGTERM` and `SIGKILL` when terminating. Default: {@link PROCESS_GRACE}. */
470
- readonly grace?: number;
471
- /** Aborting this signal terminates the run and reports `aborted`. */
472
- readonly signal?: AbortSignal;
473
- /** If `false`, resolve with the result on failure instead of rejecting. Default: `true`. */
474
- readonly strict?: boolean;
475
- /** Maximum captured bytes for stdout and for stderr, each. Default: {@link PROCESS_OUTPUT}. */
476
- readonly limit?: number;
477
- }
478
-
479
- /**
480
- * The settled outcome of a one-shot run: the buffered output and the terminal state.
481
- *
482
- * @remarks
483
- * `failed` is `true` when the child exited non-zero, was killed by a signal, expired, was aborted, or
484
- * failed to spawn. `expired` and `aborted` are the two ways the run ended the child rather than the
485
- * child ending itself, and only the first of them observed is recorded. `truncated` is independent of
486
- * both: it reports that a stream exceeded `limit`, which fails a synchronous run and does not fail an
487
- * asynchronous one.
488
- */
489
- export declare interface RunResult {
490
- /** The command line that was run, for diagnostics. */
491
- readonly command: string;
492
- /** The captured standard output, byte-bounded by `limit`. */
493
- readonly stdout: string;
494
- /** The captured standard error, byte-bounded by `limit`. */
495
- readonly stderr: string;
496
- readonly code: number | null;
497
- readonly signal: string | null;
498
- /** True if the run did not complete successfully. */
499
- readonly failed: boolean;
500
- /** True if the run's `timeout` elapsed before completion. */
501
- readonly expired: boolean;
502
- /** True if the caller's `signal` aborted the run before completion. */
503
- readonly aborted: boolean;
504
- /** True if either stream exceeded `limit`, so the captured text is the retained head. */
505
- readonly truncated: boolean;
506
- }
507
-
508
- /**
509
- * Options for a synchronous one-shot run.
510
- *
511
- * @remarks
512
- * The synchronous host offers neither a cooperative termination window nor in-flight cancellation,
513
- * so this contract carries no `grace` and no `signal`. A `timeout` and an output overflow both end
514
- * the child with `SIGKILL`; an overflow reports `truncated` and `failed` together, which is where
515
- * the synchronous and asynchronous runners genuinely differ.
516
- */
517
- export declare interface RunSyncOptions {
518
- /** The working directory. Default: the current working directory. */
519
- readonly workspace?: string;
520
- /** Environment overrides merged over the parent environment; an `undefined` value unsets a key. */
521
- readonly environment?: Readonly<Record<string, string | undefined>>;
522
- /** Standard input written to the child. */
523
- readonly input?: string;
524
- /** Milliseconds before the host kills the child. `0` or omitted disables the timeout. */
525
- readonly timeout?: number;
526
- /** If `false`, return the result on failure instead of throwing. Default: `true`. */
527
- readonly strict?: boolean;
528
- /** Maximum captured bytes for stdout and for stderr, each. Default: {@link PROCESS_OUTPUT}. */
529
- readonly limit?: number;
530
- }
531
-
532
578
  /**
533
579
  * The resolved spawn form of one command: the executable to launch, the argument vector to pass,
534
580
  * and whether the host receives that vector verbatim.
@@ -1,4 +1,4 @@
1
- import { holds } from "@orkestrel/contract";
1
+ import { holds, isError } from "@orkestrel/contract";
2
2
  //#region src/core/constants.ts
3
3
  /** The default cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL` during termination. */
4
4
  var PROCESS_GRACE = 5e3;
@@ -14,6 +14,14 @@ var PROCESS_OUTPUT = 10485760;
14
14
  var PROCESS_TIMER = 2147483647;
15
15
  /** The executable extensions a Windows lookup applies when the environment declares no `PATHEXT`. */
16
16
  var PROCESS_PATHEXT = ".COM;.EXE;.BAT;.CMD";
17
+ /** The machine-readable failure categories a {@link ProcessError} carries, in declaration order. */
18
+ var PROCESS_ERROR_CODES = Object.freeze([
19
+ "spawn",
20
+ "timeout",
21
+ "duplicate",
22
+ "protocol",
23
+ "invalid"
24
+ ]);
17
25
  //#endregion
18
26
  //#region src/core/errors.ts
19
27
  /** A child-process failure with a stable machine-readable category. */
@@ -32,6 +40,7 @@ var ProcessError = class extends Error {
32
40
  constructor(message, options) {
33
41
  const cause = options.cause;
34
42
  super(message, cause === void 0 ? void 0 : { cause });
43
+ Object.defineProperty(this, Symbol.for("@orkestrel/process.error"), { value: true });
35
44
  this.code = options.code;
36
45
  if (options.context !== void 0) this.context = options.context;
37
46
  if (options.result !== void 0) this.result = options.result;
@@ -40,6 +49,13 @@ var ProcessError = class extends Error {
40
49
  /**
41
50
  * Checks whether an unknown value is a {@link ProcessError}.
42
51
  *
52
+ * @remarks
53
+ * Recognition combines a global own-property brand with the native `Error` base, the subclass
54
+ * prototype, the fixed name, and a code {@link PROCESS_ERROR_CODES} declares. The brand is
55
+ * recognized across duplicate installations and ESM/CommonJS module copies at 0.0.4 or later. A copy
56
+ * earlier than 0.0.4 stamps no brand, so an error it throws stays outside the type, and so does a
57
+ * plain or property-only lookalike.
58
+ *
43
59
  * @param value - The value to inspect
44
60
  * @returns True only for a `ProcessError` instance; false otherwise
45
61
  *
@@ -50,7 +66,14 @@ var ProcessError = class extends Error {
50
66
  * ```
51
67
  */
52
68
  function isProcessError(value) {
53
- return holds(() => value instanceof ProcessError);
69
+ if (!isError(value)) return false;
70
+ return holds(() => {
71
+ if (Object.getPrototypeOf(value) === Error.prototype) return false;
72
+ if (value.name !== "ProcessError" || !("code" in value)) return false;
73
+ if (Object.getOwnPropertyDescriptor(value, Symbol.for("@orkestrel/process.error"))?.value !== true) return false;
74
+ const code = value.code;
75
+ return PROCESS_ERROR_CODES.some((declared) => declared === code);
76
+ });
54
77
  }
55
78
  /**
56
79
  * Creates the failure raised when a manager launch reuses a live id.
@@ -98,14 +121,15 @@ function createInvalidError(subject, value) {
98
121
  * Creates the failure raised when a run does not complete successfully and rejection is requested.
99
122
  *
100
123
  * @remarks
101
- * The category is `timeout` only when the run's own timeout elapsed; every other failure, including
102
- * an abort and an output overflow, is a `spawn` failure carrying its {@link RunResult}.
124
+ * The category is `timeout` only when the run's own timeout elapsed; every other failure,
125
+ * including an abort and an output overflow, is a `spawn` failure carrying its
126
+ * {@link ExecuteResult}.
103
127
  *
104
128
  * @param result - The buffered run outcome that failed
105
129
  * @param cause - The underlying host fault, when one ended the run
106
- * @returns A typed run failure carrying its {@link RunResult}
130
+ * @returns A typed run failure carrying its {@link ExecuteResult}
107
131
  */
108
- function createRunError(result, cause) {
132
+ function createExecuteError(result, cause) {
109
133
  let reason = `exited with code ${String(result.code)}`;
110
134
  if (result.signal !== null) reason = `was killed by ${result.signal}`;
111
135
  if (result.truncated) reason = "exceeded its output limit";
@@ -123,6 +147,6 @@ function createRunError(result, cause) {
123
147
  });
124
148
  }
125
149
  //#endregion
126
- export { PROCESS_BACKLOG, PROCESS_CONFIRMATION, PROCESS_EVIDENCE, PROCESS_GRACE, PROCESS_OUTPUT, PROCESS_PATHEXT, PROCESS_TIMER, ProcessError, createDuplicateError, createInvalidError, createProtocolError, createRunError, isProcessError };
150
+ export { PROCESS_BACKLOG, PROCESS_CONFIRMATION, PROCESS_ERROR_CODES, PROCESS_EVIDENCE, PROCESS_GRACE, PROCESS_OUTPUT, PROCESS_PATHEXT, PROCESS_TIMER, ProcessError, createDuplicateError, createExecuteError, createInvalidError, createProtocolError, isProcessError };
127
151
 
128
152
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts"],"sourcesContent":["/** The default cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL` during termination. */\nexport const PROCESS_GRACE = 5_000\n\n/** The window in milliseconds a termination waits for the child's native exit after the final kill. */\nexport const PROCESS_CONFIRMATION = 5_000\n\n/** The default maximum retained stderr tail in bytes for a supervised {@link ProcessInterface}. */\nexport const PROCESS_EVIDENCE = 2_048\n\n/** The default soft high-water mark in bytes for a supervised {@link ProcessInterface} line backlog. */\nexport const PROCESS_BACKLOG = 10_485_760\n\n/** The default maximum captured bytes for a one-shot run's stdout and stderr, each. */\nexport const PROCESS_OUTPUT = 10_485_760\n\n/** The largest timer delay in milliseconds the host schedules without truncating it to one. */\nexport const PROCESS_TIMER = 2_147_483_647\n\n/** The executable extensions a Windows lookup applies when the environment declares no `PATHEXT`. */\nexport const PROCESS_PATHEXT = '.COM;.EXE;.BAT;.CMD'\n","import { holds } from '@orkestrel/contract'\nimport type {\n\tProcessErrorCode,\n\tProcessErrorContext,\n\tProcessErrorOptions,\n\tRunResult,\n} from './types.js'\n\n/** A child-process failure with a stable machine-readable category. */\nexport class ProcessError extends Error {\n\toverride readonly name = 'ProcessError'\n\treadonly code: ProcessErrorCode\n\treadonly context?: ProcessErrorContext\n\t/** The buffered run outcome, present when a one-shot run produced the failure. */\n\treadonly result?: RunResult\n\n\t/**\n\t * Create 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\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 * @param value - The value to inspect\n * @returns True only for 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\treturn holds(() => value instanceof ProcessError)\n}\n\n/**\n * Creates the 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 failure raised when a launch is attempted on a registry that is 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 failure raised when a public input is refused before anything is 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, including\n * an abort and an output overflow, is a `spawn` failure carrying its {@link RunResult}.\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 RunResult}\n */\nexport function createRunError(result: RunResult, 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;;AAGpC,IAAa,mBAAmB;;AAGhC,IAAa,kBAAkB;;AAG/B,IAAa,iBAAiB;;AAG9B,IAAa,gBAAgB;;AAG7B,IAAa,kBAAkB;;;;ACV/B,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,KAAK,OAAO,QAAQ;EACpB,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;EAC1D,IAAI,QAAQ,WAAW,KAAA,GAAW,KAAK,SAAS,QAAQ;CACzD;AACD;;;;;;;;;;;;;AAcA,SAAgB,eAAe,OAAuC;CACrE,OAAO,YAAY,iBAAiB,YAAY;AACjD;;;;;;;AAQA,SAAgB,qBAAqB,IAA0B;CAC9D,OAAO,IAAI,aAAa,YAAY,GAAG,oBAAoB;EAC1D,MAAM;EACN,SAAS,EAAE,GAAG;CACf,CAAC;AACF;;;;;;;AAQA,SAAgB,oBAAoB,IAA0B;CAC7D,OAAO,IAAI,aAAa,YAAY,GAAG,6CAA6C;EACnF,MAAM;EACN,SAAS,EAAE,GAAG;CACf,CAAC;AACF;;;;;;;;;;;;;AAcA,SAAgB,mBAAmB,SAAiB,OAA8B;CACjF,OAAO,IAAI,aAAa,WAAW,WAAW;EAAE,MAAM;EAAW,SAAS,EAAE,MAAM;CAAE,CAAC;AACtF;;;;;;;;;;;;AAaA,SAAgB,eAAe,QAAmB,OAA+B;CAChF,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":["/** The default cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL` during termination. */\nexport const PROCESS_GRACE = 5_000\n\n/** The window in milliseconds a termination waits for the child's native exit after the final kill. */\nexport const PROCESS_CONFIRMATION = 5_000\n\n/** The default maximum retained stderr tail in bytes for a supervised {@link ProcessInterface}. */\nexport const PROCESS_EVIDENCE = 2_048\n\n/** The default soft high-water mark in bytes for a supervised {@link ProcessInterface} line backlog. */\nexport const PROCESS_BACKLOG = 10_485_760\n\n/** The default maximum captured bytes for a one-shot run's stdout and stderr, each. */\nexport const PROCESS_OUTPUT = 10_485_760\n\n/** The largest timer delay in milliseconds the host schedules without truncating it to one. */\nexport const PROCESS_TIMER = 2_147_483_647\n\n/** The executable extensions a Windows lookup applies when the environment declares no `PATHEXT`. */\nexport const PROCESS_PATHEXT = '.COM;.EXE;.BAT;.CMD'\n\n/** The machine-readable failure categories a {@link ProcessError} carries, in declaration order. */\nexport const PROCESS_ERROR_CODES = Object.freeze([\n\t'spawn',\n\t'timeout',\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/** A child-process failure with a stable machine-readable category. */\nexport class ProcessError extends Error {\n\toverride readonly name = 'ProcessError'\n\treadonly code: ProcessErrorCode\n\treadonly context?: ProcessErrorContext\n\t/** The buffered run outcome, present when a one-shot run produced the failure. */\n\treadonly result?: ExecuteResult\n\n\t/**\n\t * Create 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 only for 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 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 failure raised when a launch is attempted on a registry that is 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 failure raised when a public input is refused before anything is 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;;AAGpC,IAAa,mBAAmB;;AAGhC,IAAa,kBAAkB;;AAG/B,IAAa,iBAAiB;;AAG9B,IAAa,gBAAgB;;AAG7B,IAAa,kBAAkB;;AAG/B,IAAa,sBAAsB,OAAO,OAAO;CAChD;CACA;CACA;CACA;CACA;AACD,CAAU;;;;AClBV,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;;;;;;;AAQA,SAAgB,oBAAoB,IAA0B;CAC7D,OAAO,IAAI,aAAa,YAAY,GAAG,6CAA6C;EACnF,MAAM;EACN,SAAS,EAAE,GAAG;CACf,CAAC;AACF;;;;;;;;;;;;;AAcA,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"}