@ariestools/cli-kit 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,9 @@ This package is intentionally independent of XL1 and xyo-chain. Application pack
6
6
 
7
7
  The package also provides structural `ProcessHost` and `ProcessIO` boundaries for adapting an application's concrete process runtime without importing Node APIs into the core. Arguments, environment values, terminal width, output, prompts, interrupts, and exits are all supplied by the host. Use `exitProcess` at exit points that occur before the end of a command: production hosts may terminate immediately, while recording hosts receive a `ProcessExitError` that stops control flow deterministically. `RuntimeSession` owns one application-supplied stop operation and preserves fail-fast shutdown behavior while making repeated stop requests idempotent. It can also own one structural interrupt binding, coalesce repeated interrupts while the application listener settles, and dispose the binding at the correct manual or interrupt-driven shutdown boundary.
8
8
 
9
- `runProcessApplication` owns the outermost application failure boundary. It absorbs standardized exit signals that have already been routed through a `ProcessHost`, hides unexpected error details outside development, and requests exit code one for unhandled failures. Concrete process adapters remain separate packages; Node applications can use `@ariestools/cli-kit-node`.
9
+ `runProcessApplication` owns the outermost application failure boundary. It absorbs standardized exit signals that have already been routed through a `ProcessHost`, hides unexpected error details outside development, and requests exit code one for unhandled failures. An optional `mapFailureToExitCode` mapper lets the application select a different exit code per failure; it receives the error plus a `FailureOrigin` (`'parse'` or `'handler'`), returning `undefined` retains the default one, and intentional `ProcessExitError` exits are never offered to the mapper. The mapper stays inside the failure boundary: a mapper that throws, or returns a code outside the integer range 0–255, falls back to exit code one instead of escaping the boundary. Concrete process adapters remain separate packages; Node applications can use `@ariestools/cli-kit-node`.
10
+
11
+ `SYS_EXITS` supplies the BSD `sysexits.h` exit-code vocabulary used across applications (`ok`, `usage`, `dataErr`, `noInput`, `software`, `ioErr`, `config`), with `SysExitCode` as the derived literal union. Use it with `exitProcess` or a `mapFailureToExitCode` mapper instead of repeating numeric literals.
10
12
 
11
13
  `createCommandCatalog` registers ordered command factories against a structural `CliApplicationContext`. The command type is supplied by the application, so parser-specific types and domain-specific configuration remain outside the core. A catalog is immutable and reusable; each application invocation materializes fresh command objects with its own context.
12
14
 
@@ -22,7 +24,7 @@ The package also provides structural `ProcessHost` and `ProcessIO` boundaries fo
22
24
  - A runtime session accepts at most one interrupt binding while active.
23
25
  - Repeated interrupts share one listener promise and retain the binding until that listener settles.
24
26
  - Manual shutdown disposes its interrupt binding before cleanup begins.
25
- - Process applications absorb host-routed exits and map unexpected failures to exit code one.
27
+ - Process applications absorb host-routed exits and map unexpected failures to exit code one, or to the code selected by an application-supplied mapper.
26
28
  - Command catalogs preserve registration order and reject blank or duplicate ids.
27
29
  - Command factories receive the exact per-application context and are invoked again for each materialization.
28
30
 
@@ -1,9 +1,40 @@
1
1
  import { type ProcessHost } from './ProcessHost.ts';
2
2
  /** Application entry point executed against an explicit process boundary. */
3
3
  export type ProcessApplication = (host: ProcessHost) => Promise<void>;
4
+ /**
5
+ * Where an unexpected failure originated.
6
+ *
7
+ * - `'parse'`: argument parsing or validation failed before any command
8
+ * handler ran (for example a Yargs usage error).
9
+ * - `'handler'`: the app body, command handler, or middleware failed after
10
+ * arguments were accepted.
11
+ */
12
+ export type FailureOrigin = 'handler' | 'parse';
13
+ /**
14
+ * Optional application-supplied failure policy. Returning a number selects
15
+ * the exit code for that failure; returning `undefined` retains the default
16
+ * exit code one. The `origin` argument distinguishes parse/validation
17
+ * failures from handler failures so mappers such as `usage` (64) versus
18
+ * `software` (70) need no runner-specific error sniffing. Intentional exits
19
+ * carried by `ProcessExitError` are never offered to the mapper.
20
+ *
21
+ * Results outside the integer range 0–255 (including `NaN`) and errors
22
+ * thrown by the mapper itself fall back to exit code one; the mapper is
23
+ * inside the failure boundary, not above it. Prefer drawing codes from
24
+ * `SYS_EXITS`.
25
+ */
26
+ export type FailureExitCodeMapper = (error: unknown, origin: FailureOrigin) => number | undefined;
27
+ /**
28
+ * Resolves the exit code for an unexpected failure through an optional
29
+ * mapper. A missing mapper, an `undefined` result, a thrown mapper, or a
30
+ * result outside the integer range 0–255 all resolve to the default exit
31
+ * code one, keeping the failure boundary intact.
32
+ */
33
+ export declare function resolveFailureExitCode(mapFailureToExitCode: FailureExitCodeMapper | undefined, error: unknown, origin: FailureOrigin): number;
4
34
  export interface RunProcessApplicationOptions {
5
35
  readonly application: ProcessApplication;
6
36
  readonly host: ProcessHost;
37
+ readonly mapFailureToExitCode?: FailureExitCodeMapper;
7
38
  }
8
39
  /**
9
40
  * Runs one CLI app at the outermost process boundary.
@@ -11,7 +42,7 @@ export interface RunProcessApplicationOptions {
11
42
  * Immediate exits requested through `exitProcess` have already been
12
43
  * routed to the host and are absorbed here. Unexpected failures retain the
13
44
  * established CLI policy of logging details only in development before
14
- * requesting exit code one.
45
+ * requesting exit code one, or the code selected by `mapFailureToExitCode`.
15
46
  */
16
- export declare function runProcessApplication({ application, host, }: RunProcessApplicationOptions): Promise<void>;
47
+ export declare function runProcessApplication({ application, host, mapFailureToExitCode, }: RunProcessApplicationOptions): Promise<void>;
17
48
  //# sourceMappingURL=ProcessApplication.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProcessApplication.d.ts","sourceRoot":"","sources":["../../src/ProcessApplication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAErE,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAErE,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAA;IACxC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,EAC1C,WAAW,EACX,IAAI,GACL,EAAE,4BAA4B,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ9C"}
1
+ {"version":3,"file":"ProcessApplication.d.ts","sourceRoot":"","sources":["../../src/ProcessApplication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAErE,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAErE;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,CAAA;AAE/C;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,CAAA;AAEjG;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,oBAAoB,EAAE,qBAAqB,GAAG,SAAS,EACvD,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,aAAa,GACpB,MAAM,CAQR;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAA;IACxC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,QAAQ,CAAC,oBAAoB,CAAC,EAAE,qBAAqB,CAAA;CACtD;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,EAC1C,WAAW,EACX,IAAI,EACJ,oBAAoB,GACrB,EAAE,4BAA4B,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ9C"}
@@ -5,4 +5,5 @@ export * from './ManagedActor.ts';
5
5
  export * from './ProcessApplication.ts';
6
6
  export * from './ProcessHost.ts';
7
7
  export * from './RuntimeSession.ts';
8
+ export * from './sysExits.ts';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA"}
@@ -250,16 +250,26 @@ function exitProcess(host, exitCode) {
250
250
  }
251
251
 
252
252
  // src/ProcessApplication.ts
253
+ function resolveFailureExitCode(mapFailureToExitCode, error, origin) {
254
+ if (mapFailureToExitCode === void 0) return 1;
255
+ try {
256
+ const code = mapFailureToExitCode(error, origin);
257
+ return code !== void 0 && Number.isSafeInteger(code) && code >= 0 && code <= 255 ? code : 1;
258
+ } catch {
259
+ return 1;
260
+ }
261
+ }
253
262
  async function runProcessApplication({
254
263
  application,
255
- host
264
+ host,
265
+ mapFailureToExitCode
256
266
  }) {
257
267
  try {
258
268
  await application(host);
259
269
  } catch (error) {
260
270
  if (error instanceof ProcessExitError) return;
261
271
  if (host.isDevelopment) host.io.error("An error occurred during startup:", error);
262
- host.exit(1);
272
+ host.exit(resolveFailureExitCode(mapFailureToExitCode, error, "handler"));
263
273
  }
264
274
  }
265
275
 
@@ -359,6 +369,24 @@ var RuntimeSession = class {
359
369
  }
360
370
  }
361
371
  };
372
+
373
+ // src/sysExits.ts
374
+ var SYS_EXITS = {
375
+ /** `EX_OK` (0): successful termination. */
376
+ ok: 0,
377
+ /** `EX_USAGE` (64): command line usage error, such as bad arguments or flags. */
378
+ usage: 64,
379
+ /** `EX_DATAERR` (65): input data was incorrect in some way. */
380
+ dataErr: 65,
381
+ /** `EX_NOINPUT` (66): an input file did not exist or was not readable. */
382
+ noInput: 66,
383
+ /** `EX_SOFTWARE` (70): internal software error not caused by the operating system. */
384
+ software: 70,
385
+ /** `EX_IOERR` (74): an error occurred while doing I/O on a file. */
386
+ ioErr: 74,
387
+ /** `EX_CONFIG` (78): something was found in an unconfigured or misconfigured state. */
388
+ config: 78
389
+ };
362
390
  export {
363
391
  ActorReadinessError,
364
392
  ActorReadinessTimeoutError,
@@ -369,9 +397,11 @@ export {
369
397
  ActorSupervisorStateError,
370
398
  ProcessExitError,
371
399
  RuntimeSession,
400
+ SYS_EXITS,
372
401
  createActorBuilderCatalog,
373
402
  createCommandCatalog,
374
403
  exitProcess,
404
+ resolveFailureExitCode,
375
405
  runProcessApplication
376
406
  };
377
407
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/ActorBuilderCatalog.ts", "../../src/ActorSupervisor.ts", "../../src/CommandCatalog.ts", "../../src/ProcessHost.ts", "../../src/ProcessApplication.ts", "../../src/RuntimeSession.ts"],
4
- "sourcesContent": ["export interface ActorBuilderDefinition<TContext, TActor> {\n readonly name: string\n build(context: TContext): Promise<TActor>\n}\n\nexport interface ActorBuilderCatalog<TContext, TActor> {\n readonly names: readonly string[]\n build(name: string, context: TContext): Promise<TActor>\n}\n\n/** Creates an ordered, instance-scoped actor builder catalog. */\nexport function createActorBuilderCatalog<TContext, TActor>(\n definitions: readonly ActorBuilderDefinition<TContext, TActor>[],\n): ActorBuilderCatalog<TContext, TActor> {\n const definitionsByName = new Map<string, ActorBuilderDefinition<TContext, TActor>>()\n const names: string[] = []\n for (const definition of definitions) {\n if (definitionsByName.has(definition.name)) {\n throw new Error(`Actor builder \"${definition.name}\" is already registered`)\n }\n definitionsByName.set(definition.name, definition)\n names.push(definition.name)\n }\n\n return {\n names: Object.freeze(names),\n async build(name: string, context: TContext): Promise<TActor> {\n const definition = definitionsByName.get(name)\n if (definition === undefined) throw new Error(`Unknown actor: ${name}`)\n return await definition.build(context)\n },\n }\n}\n", "import type {\n ManagedActor, ManagedActorLifecycleResult, ReadinessSignal, ReadyState,\n} from './ManagedActor.ts'\n\nexport type ActorSupervisorState = 'failed' | 'idle' | 'started' | 'starting' | 'stopped' | 'stopping'\n\nexport class ActorRegistrationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ActorRegistrationError'\n }\n}\n\nexport class ActorSupervisorStateError extends Error {\n readonly state: ActorSupervisorState\n\n constructor(operation: string, state: ActorSupervisorState) {\n super(`Cannot ${operation} while actor supervisor is ${state}`)\n this.name = 'ActorSupervisorStateError'\n this.state = state\n }\n}\n\nexport class ActorStartupError extends Error {\n readonly actorName: string\n readonly rollbackErrors: readonly Error[]\n\n constructor(actorName: string, cause: unknown, rollbackErrors: readonly Error[]) {\n super(`Actor \"${actorName}\" failed to start`, { cause })\n this.name = 'ActorStartupError'\n this.actorName = actorName\n this.rollbackErrors = rollbackErrors\n }\n}\n\nexport class ActorReadinessError extends Error {\n readonly actorName: string\n\n constructor(actorName: string, cause: unknown) {\n super(`Actor \"${actorName}\" failed to become ready`, { cause })\n this.name = 'ActorReadinessError'\n this.actorName = actorName\n }\n}\n\nexport class ActorReadinessTimeoutError extends Error {\n readonly timeoutMs: number\n\n constructor(timeoutMs: number) {\n super(`Actors did not become ready within ${timeoutMs}ms`)\n this.name = 'ActorReadinessTimeoutError'\n this.timeoutMs = timeoutMs\n }\n}\n\nexport class ActorShutdownError extends AggregateError {\n constructor(errors: readonly Error[]) {\n super(errors, `${errors.length} actor(s) failed to stop`)\n this.name = 'ActorShutdownError'\n }\n}\n\ninterface TimerHost {\n clearTimeout(handle: unknown): void\n setTimeout(callback: () => void, timeoutMs: number): unknown\n}\n\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error))\n}\n\nfunction assertLifecycleSucceeded(actor: ManagedActor, operation: 'start' | 'stop', result: ManagedActorLifecycleResult): void {\n if (result === false) {\n throw new Error(`Actor \"${actor.name}\" ${operation}() reported failure`)\n }\n}\n\nfunction assertTimeout(timeoutMs: number): void {\n if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {\n throw new RangeError('Readiness timeout must be a finite, non-negative number')\n }\n}\n\nasync function waitWithTimeout(signal: ReadinessSignal, timeoutMs: number): Promise<void> {\n const timerHost = globalThis as unknown as TimerHost\n let timeoutHandle: unknown\n const expired = new Promise<never>((_resolve, reject) => {\n timeoutHandle = timerHost.setTimeout(() => reject(new ActorReadinessTimeoutError(timeoutMs)), timeoutMs)\n })\n try {\n await Promise.race([signal.whenReady(timeoutMs), expired])\n } finally {\n timerHost.clearTimeout(timeoutHandle)\n }\n}\n\n/**\n * Instance-scoped coordinator for structural managed actors.\n *\n * Startup and readiness follow registration order. Rollback and ordinary shutdown\n * follow reverse startup order. A supervisor is single-use after it has stopped or\n * failed; construct a new instance for a new lifecycle.\n */\nexport class ActorSupervisor implements ReadinessSignal {\n private readonly _actorNames = new Set<string>()\n private readonly _actors: ManagedActor[] = []\n private _readyError?: Error\n private _startPromise?: Promise<void>\n private readonly _startedActors: ManagedActor[] = []\n private _state: ActorSupervisorState = 'idle'\n private _stopPromise?: Promise<void>\n\n constructor(actors: readonly ManagedActor[] = []) {\n for (const actor of actors) this.register(actor)\n }\n\n get actors(): readonly ManagedActor[] {\n return [...this._actors]\n }\n\n get readyError(): Error | undefined {\n if (this._readyError !== undefined) return this._readyError\n return this._actors.find(actor => actor.readyState === 'failed')?.readyError\n }\n\n get readyState(): ReadyState {\n if (this._readyError !== undefined || this._state === 'failed' || this._actors.some(actor => actor.readyState === 'failed')) {\n return 'failed'\n }\n if (this._state === 'started' && this._actors.every(actor => actor.readyState === 'ready')) return 'ready'\n return 'pending'\n }\n\n get state(): ActorSupervisorState {\n return this._state\n }\n\n isReady(): boolean {\n return this.readyState === 'ready'\n }\n\n register(actor: ManagedActor): void {\n if (this._state !== 'idle') throw new ActorSupervisorStateError('register an actor', this._state)\n if (actor.name.trim().length === 0) throw new ActorRegistrationError('Actor name must not be empty')\n if (this._actorNames.has(actor.name)) {\n throw new ActorRegistrationError(`Actor \"${actor.name}\" is already registered`)\n }\n this._actorNames.add(actor.name)\n this._actors.push(actor)\n }\n\n start(): Promise<void> {\n if (this._startPromise !== undefined) return this._startPromise\n if (this._state !== 'idle') return Promise.reject(new ActorSupervisorStateError('start', this._state))\n this._state = 'starting'\n this._startPromise = this.startActors()\n return this._startPromise\n }\n\n stop(): Promise<void> {\n this._stopPromise ??= this.stopActors()\n return this._stopPromise\n }\n\n async whenReady(timeoutMs?: number): Promise<void> {\n if (timeoutMs !== undefined) assertTimeout(timeoutMs)\n if (this._state === 'starting' && this._startPromise !== undefined) {\n await this._startPromise\n }\n if (this._state !== 'started') throw new ActorSupervisorStateError('wait for readiness', this._state)\n\n const startedAt = Date.now()\n for (const actor of this._actors) {\n try {\n if (timeoutMs === undefined) {\n await actor.whenReady()\n } else {\n const elapsed = Date.now() - startedAt\n const remainingTimeoutMs = timeoutMs - elapsed\n if (remainingTimeoutMs < 0) throw new ActorReadinessTimeoutError(timeoutMs)\n await waitWithTimeout(actor, remainingTimeoutMs)\n }\n } catch (error) {\n const readinessError = new ActorReadinessError(actor.name, error)\n this._readyError = readinessError\n throw readinessError\n }\n }\n }\n\n private async startActors(): Promise<void> {\n for (const actor of this._actors) {\n try {\n const result = await actor.start()\n assertLifecycleSucceeded(actor, 'start', result)\n this._startedActors.push(actor)\n } catch (error) {\n const rollbackErrors = await this.stopStartedActors()\n const startupError = new ActorStartupError(actor.name, error, rollbackErrors)\n this._readyError = startupError\n this._state = 'failed'\n throw startupError\n }\n }\n this._state = 'started'\n }\n\n private async stopActors(): Promise<void> {\n if (this._state === 'starting' && this._startPromise !== undefined) {\n try {\n await this._startPromise\n } catch {\n // Startup already rolled back every actor that reached started state.\n }\n }\n\n if (this._state === 'stopped') return\n if (this._state === 'idle' || (this._state === 'failed' && this._startedActors.length === 0)) {\n this._state = 'stopped'\n return\n }\n\n this._state = 'stopping'\n const errors = await this.stopStartedActors()\n this._state = 'stopped'\n if (errors.length > 0) throw new ActorShutdownError(errors)\n }\n\n private async stopStartedActors(): Promise<Error[]> {\n const errors: Error[] = []\n while (this._startedActors.length > 0) {\n const actor = this._startedActors.pop()\n if (actor === undefined) continue\n try {\n const result = await actor.stop()\n assertLifecycleSucceeded(actor, 'stop', result)\n } catch (error) {\n errors.push(new Error(`Actor \"${actor.name}\" failed to stop`, { cause: asError(error) }))\n }\n }\n return errors\n }\n}\n", "import type { ProcessHost } from './ProcessHost.ts'\n\n/** Process capability shared by every command created for one CLI app. */\nexport interface CliApplicationContext {\n readonly host: ProcessHost\n}\n\n/** Adapter-neutral factory for one parser-specific command object. */\nexport interface CommandDefinition<TContext extends CliApplicationContext, TCommand> {\n readonly create: (context: TContext) => TCommand\n /** Internal registration identity; it does not define parser syntax or aliases. */\n readonly id: string\n}\n\n/** Ordered command factories materialized for one app context. */\nexport interface CommandCatalog<TContext extends CliApplicationContext, TCommand> {\n readonly createCommands: (context: TContext) => readonly TCommand[]\n readonly ids: readonly string[]\n}\n\n/** Creates an immutable, adapter-neutral command catalog. */\nexport function createCommandCatalog<TContext extends CliApplicationContext, TCommand>(\n definitions: readonly CommandDefinition<TContext, TCommand>[],\n): CommandCatalog<TContext, TCommand> {\n const registeredIds = new Set<string>()\n const retainedDefinitions = definitions.map(definition => Object.freeze({\n create: definition.create,\n id: definition.id,\n }))\n const ids: string[] = []\n\n for (const definition of retainedDefinitions) {\n if (definition.id.trim().length === 0) throw new Error('Command id must not be empty')\n if (registeredIds.has(definition.id)) throw new Error(`Command \"${definition.id}\" is already registered`)\n registeredIds.add(definition.id)\n ids.push(definition.id)\n }\n\n return Object.freeze({\n ids: Object.freeze(ids),\n createCommands: (context: TContext): readonly TCommand[] =>\n Object.freeze(retainedDefinitions.map(definition => definition.create(context))),\n })\n}\n", "/** Process-facing input and output used by a command-line app. */\nexport interface ProcessIO {\n /** Available terminal width when output is attached to a sized terminal. */\n readonly columns?: number\n readonly isInteractive: boolean\n error(...values: readonly unknown[]): void\n log(...values: readonly unknown[]): void\n question(prompt: string): Promise<string>\n warn(...values: readonly unknown[]): void\n}\n\n/** Control-flow signal used when a non-terminating host records an immediate exit. */\nexport class ProcessExitError extends Error {\n readonly exitCode: number\n\n constructor(exitCode: number) {\n super(`Process requested exit with code ${exitCode}`)\n this.name = 'ProcessExitError'\n this.exitCode = exitCode\n }\n}\n\n/**\n * Structural process boundary for a command-line app.\n *\n * Production implementations may terminate from {@link exit}; recording hosts\n * may return after retaining the requested status.\n */\nexport interface ProcessHost {\n /** Full argument vector, including the executable and script entries. */\n readonly argv: readonly string[]\n /** Environment visible to this app invocation. */\n readonly environment: Readonly<Record<string, string | undefined>>\n readonly io: ProcessIO\n readonly isDevelopment: boolean\n exit(code: number): void\n onInterrupt(listener: () => Promise<void> | void): () => void\n}\n\n/**\n * Requests immediate process termination and prevents a recording host from\n * accidentally continuing through code that follows the exit point.\n */\nexport function exitProcess(host: Pick<ProcessHost, 'exit'>, exitCode: number): never {\n host.exit(exitCode)\n throw new ProcessExitError(exitCode)\n}\n", "import { ProcessExitError, type ProcessHost } from './ProcessHost.ts'\n\n/** Application entry point executed against an explicit process boundary. */\nexport type ProcessApplication = (host: ProcessHost) => Promise<void>\n\nexport interface RunProcessApplicationOptions {\n readonly application: ProcessApplication\n readonly host: ProcessHost\n}\n\n/**\n * Runs one CLI app at the outermost process boundary.\n *\n * Immediate exits requested through `exitProcess` have already been\n * routed to the host and are absorbed here. Unexpected failures retain the\n * established CLI policy of logging details only in development before\n * requesting exit code one.\n */\nexport async function runProcessApplication({\n application,\n host,\n}: RunProcessApplicationOptions): Promise<void> {\n try {\n await application(host)\n } catch (error) {\n if (error instanceof ProcessExitError) return\n if (host.isDevelopment) host.io.error('An error occurred during startup:', error)\n host.exit(1)\n }\n}\n", "import type { ProcessHost } from './ProcessHost.ts'\n\n/** Lifecycle state of one active runtime session. */\nexport type RuntimeSessionState = 'active' | 'failed' | 'stopped' | 'stopping'\n\n/** Application-owned cleanup invoked when a runtime session stops. */\nexport type RuntimeStopDelegate = () => Promise<void> | void\n\n/** Application-owned work invoked for the first process interrupt. */\nexport type RuntimeInterruptListener = () => Promise<void> | void\n\n/**\n * Instance-scoped owner for one runtime cleanup operation.\n *\n * Every call to {@link stop} returns the same promise. A cleanup failure is\n * retained and rethrown without wrapping so callers can preserve their\n * existing fail-fast behavior.\n */\nexport class RuntimeSession {\n private _exitCode?: number\n private _exitHost?: Pick<ProcessHost, 'exit'>\n private _exitPromise?: Promise<void>\n private _hasInterruptBinding = false\n private _interruptDisposer?: () => void\n private _interruptPromise?: Promise<void>\n private _isInterruptDisposed = false\n private _state: RuntimeSessionState = 'active'\n private readonly _stopDelegate: RuntimeStopDelegate\n private _stopError?: unknown\n private _stopPromise?: Promise<void>\n\n constructor(stopDelegate: RuntimeStopDelegate) {\n this._stopDelegate = stopDelegate\n }\n\n get state(): RuntimeSessionState {\n return this._state\n }\n\n get stopError(): unknown {\n return this._stopError\n }\n\n bindInterrupt(host: Pick<ProcessHost, 'onInterrupt'>, listener: RuntimeInterruptListener): void {\n if (this._hasInterruptBinding) throw new Error('An interrupt listener is already bound to this runtime session.')\n if (this.state !== 'active') throw new Error('An interrupt listener cannot be bound after runtime shutdown has started.')\n\n this._hasInterruptBinding = true\n let isRegistrationComplete = false\n let isInterruptPending = false\n const handleInterrupt = (): Promise<void> | void => {\n if (!isRegistrationComplete) {\n isInterruptPending = true\n return\n }\n return this.handleInterrupt(listener)\n }\n this._interruptDisposer = host.onInterrupt(handleInterrupt)\n isRegistrationComplete = true\n\n // A structural host may deliver an interrupt while registering the listener.\n // Defer that delivery until the returned disposer is retained so it can be\n // removed after the interrupt handler settles.\n if (isInterruptPending) void this.handleInterrupt(listener)\n }\n\n /**\n * Coalesces competing process-exit requests for this session. Requests made\n * in the same turn retain the highest exit code and every caller observes\n * the same exactly-once exit operation.\n */\n requestExit(host: Pick<ProcessHost, 'exit'>, exitCode: number): Promise<void> {\n this._exitCode = Math.max(this._exitCode ?? exitCode, exitCode)\n this._exitHost ??= host\n this._exitPromise ??= Promise.try(async () => {\n await Promise.resolve()\n this._exitHost?.exit(this._exitCode ?? exitCode)\n })\n return this._exitPromise\n }\n\n stop(): Promise<void> {\n // Manual shutdown owns listener disposal immediately. Interrupt-driven\n // shutdown retains the listener until its handler settles so repeated\n // interrupts are coalesced instead of reaching the host's default handler.\n if (this._interruptPromise === undefined) this.disposeInterrupt()\n if (this._stopPromise === undefined) {\n this._state = 'stopping'\n this._stopPromise = Promise.try(async () => {\n await Promise.resolve()\n await this.stopOnce()\n })\n }\n return this._stopPromise\n }\n\n private disposeInterrupt(): void {\n if (!this._hasInterruptBinding || this._isInterruptDisposed) return\n this._isInterruptDisposed = true\n const dispose = this._interruptDisposer\n this._interruptDisposer = undefined\n dispose?.()\n }\n\n private handleInterrupt(listener: RuntimeInterruptListener): Promise<void> {\n if (this._interruptPromise === undefined) {\n if (this._isInterruptDisposed) return Promise.resolve()\n this._interruptPromise = Promise.try(async () => {\n await Promise.resolve()\n try {\n await listener()\n } finally {\n this.disposeInterrupt()\n }\n })\n }\n return this._interruptPromise\n }\n\n private async stopOnce(): Promise<void> {\n try {\n await this._stopDelegate()\n this._state = 'stopped'\n } catch (error) {\n this._stopError = error\n this._state = 'failed'\n throw error\n }\n }\n}\n"],
5
- "mappings": "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",
3
+ "sources": ["../../src/ActorBuilderCatalog.ts", "../../src/ActorSupervisor.ts", "../../src/CommandCatalog.ts", "../../src/ProcessHost.ts", "../../src/ProcessApplication.ts", "../../src/RuntimeSession.ts", "../../src/sysExits.ts"],
4
+ "sourcesContent": ["export interface ActorBuilderDefinition<TContext, TActor> {\n readonly name: string\n build(context: TContext): Promise<TActor>\n}\n\nexport interface ActorBuilderCatalog<TContext, TActor> {\n readonly names: readonly string[]\n build(name: string, context: TContext): Promise<TActor>\n}\n\n/** Creates an ordered, instance-scoped actor builder catalog. */\nexport function createActorBuilderCatalog<TContext, TActor>(\n definitions: readonly ActorBuilderDefinition<TContext, TActor>[],\n): ActorBuilderCatalog<TContext, TActor> {\n const definitionsByName = new Map<string, ActorBuilderDefinition<TContext, TActor>>()\n const names: string[] = []\n for (const definition of definitions) {\n if (definitionsByName.has(definition.name)) {\n throw new Error(`Actor builder \"${definition.name}\" is already registered`)\n }\n definitionsByName.set(definition.name, definition)\n names.push(definition.name)\n }\n\n return {\n names: Object.freeze(names),\n async build(name: string, context: TContext): Promise<TActor> {\n const definition = definitionsByName.get(name)\n if (definition === undefined) throw new Error(`Unknown actor: ${name}`)\n return await definition.build(context)\n },\n }\n}\n", "import type {\n ManagedActor, ManagedActorLifecycleResult, ReadinessSignal, ReadyState,\n} from './ManagedActor.ts'\n\nexport type ActorSupervisorState = 'failed' | 'idle' | 'started' | 'starting' | 'stopped' | 'stopping'\n\nexport class ActorRegistrationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ActorRegistrationError'\n }\n}\n\nexport class ActorSupervisorStateError extends Error {\n readonly state: ActorSupervisorState\n\n constructor(operation: string, state: ActorSupervisorState) {\n super(`Cannot ${operation} while actor supervisor is ${state}`)\n this.name = 'ActorSupervisorStateError'\n this.state = state\n }\n}\n\nexport class ActorStartupError extends Error {\n readonly actorName: string\n readonly rollbackErrors: readonly Error[]\n\n constructor(actorName: string, cause: unknown, rollbackErrors: readonly Error[]) {\n super(`Actor \"${actorName}\" failed to start`, { cause })\n this.name = 'ActorStartupError'\n this.actorName = actorName\n this.rollbackErrors = rollbackErrors\n }\n}\n\nexport class ActorReadinessError extends Error {\n readonly actorName: string\n\n constructor(actorName: string, cause: unknown) {\n super(`Actor \"${actorName}\" failed to become ready`, { cause })\n this.name = 'ActorReadinessError'\n this.actorName = actorName\n }\n}\n\nexport class ActorReadinessTimeoutError extends Error {\n readonly timeoutMs: number\n\n constructor(timeoutMs: number) {\n super(`Actors did not become ready within ${timeoutMs}ms`)\n this.name = 'ActorReadinessTimeoutError'\n this.timeoutMs = timeoutMs\n }\n}\n\nexport class ActorShutdownError extends AggregateError {\n constructor(errors: readonly Error[]) {\n super(errors, `${errors.length} actor(s) failed to stop`)\n this.name = 'ActorShutdownError'\n }\n}\n\ninterface TimerHost {\n clearTimeout(handle: unknown): void\n setTimeout(callback: () => void, timeoutMs: number): unknown\n}\n\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error))\n}\n\nfunction assertLifecycleSucceeded(actor: ManagedActor, operation: 'start' | 'stop', result: ManagedActorLifecycleResult): void {\n if (result === false) {\n throw new Error(`Actor \"${actor.name}\" ${operation}() reported failure`)\n }\n}\n\nfunction assertTimeout(timeoutMs: number): void {\n if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {\n throw new RangeError('Readiness timeout must be a finite, non-negative number')\n }\n}\n\nasync function waitWithTimeout(signal: ReadinessSignal, timeoutMs: number): Promise<void> {\n const timerHost = globalThis as unknown as TimerHost\n let timeoutHandle: unknown\n const expired = new Promise<never>((_resolve, reject) => {\n timeoutHandle = timerHost.setTimeout(() => reject(new ActorReadinessTimeoutError(timeoutMs)), timeoutMs)\n })\n try {\n await Promise.race([signal.whenReady(timeoutMs), expired])\n } finally {\n timerHost.clearTimeout(timeoutHandle)\n }\n}\n\n/**\n * Instance-scoped coordinator for structural managed actors.\n *\n * Startup and readiness follow registration order. Rollback and ordinary shutdown\n * follow reverse startup order. A supervisor is single-use after it has stopped or\n * failed; construct a new instance for a new lifecycle.\n */\nexport class ActorSupervisor implements ReadinessSignal {\n private readonly _actorNames = new Set<string>()\n private readonly _actors: ManagedActor[] = []\n private _readyError?: Error\n private _startPromise?: Promise<void>\n private readonly _startedActors: ManagedActor[] = []\n private _state: ActorSupervisorState = 'idle'\n private _stopPromise?: Promise<void>\n\n constructor(actors: readonly ManagedActor[] = []) {\n for (const actor of actors) this.register(actor)\n }\n\n get actors(): readonly ManagedActor[] {\n return [...this._actors]\n }\n\n get readyError(): Error | undefined {\n if (this._readyError !== undefined) return this._readyError\n return this._actors.find(actor => actor.readyState === 'failed')?.readyError\n }\n\n get readyState(): ReadyState {\n if (this._readyError !== undefined || this._state === 'failed' || this._actors.some(actor => actor.readyState === 'failed')) {\n return 'failed'\n }\n if (this._state === 'started' && this._actors.every(actor => actor.readyState === 'ready')) return 'ready'\n return 'pending'\n }\n\n get state(): ActorSupervisorState {\n return this._state\n }\n\n isReady(): boolean {\n return this.readyState === 'ready'\n }\n\n register(actor: ManagedActor): void {\n if (this._state !== 'idle') throw new ActorSupervisorStateError('register an actor', this._state)\n if (actor.name.trim().length === 0) throw new ActorRegistrationError('Actor name must not be empty')\n if (this._actorNames.has(actor.name)) {\n throw new ActorRegistrationError(`Actor \"${actor.name}\" is already registered`)\n }\n this._actorNames.add(actor.name)\n this._actors.push(actor)\n }\n\n start(): Promise<void> {\n if (this._startPromise !== undefined) return this._startPromise\n if (this._state !== 'idle') return Promise.reject(new ActorSupervisorStateError('start', this._state))\n this._state = 'starting'\n this._startPromise = this.startActors()\n return this._startPromise\n }\n\n stop(): Promise<void> {\n this._stopPromise ??= this.stopActors()\n return this._stopPromise\n }\n\n async whenReady(timeoutMs?: number): Promise<void> {\n if (timeoutMs !== undefined) assertTimeout(timeoutMs)\n if (this._state === 'starting' && this._startPromise !== undefined) {\n await this._startPromise\n }\n if (this._state !== 'started') throw new ActorSupervisorStateError('wait for readiness', this._state)\n\n const startedAt = Date.now()\n for (const actor of this._actors) {\n try {\n if (timeoutMs === undefined) {\n await actor.whenReady()\n } else {\n const elapsed = Date.now() - startedAt\n const remainingTimeoutMs = timeoutMs - elapsed\n if (remainingTimeoutMs < 0) throw new ActorReadinessTimeoutError(timeoutMs)\n await waitWithTimeout(actor, remainingTimeoutMs)\n }\n } catch (error) {\n const readinessError = new ActorReadinessError(actor.name, error)\n this._readyError = readinessError\n throw readinessError\n }\n }\n }\n\n private async startActors(): Promise<void> {\n for (const actor of this._actors) {\n try {\n const result = await actor.start()\n assertLifecycleSucceeded(actor, 'start', result)\n this._startedActors.push(actor)\n } catch (error) {\n const rollbackErrors = await this.stopStartedActors()\n const startupError = new ActorStartupError(actor.name, error, rollbackErrors)\n this._readyError = startupError\n this._state = 'failed'\n throw startupError\n }\n }\n this._state = 'started'\n }\n\n private async stopActors(): Promise<void> {\n if (this._state === 'starting' && this._startPromise !== undefined) {\n try {\n await this._startPromise\n } catch {\n // Startup already rolled back every actor that reached started state.\n }\n }\n\n if (this._state === 'stopped') return\n if (this._state === 'idle' || (this._state === 'failed' && this._startedActors.length === 0)) {\n this._state = 'stopped'\n return\n }\n\n this._state = 'stopping'\n const errors = await this.stopStartedActors()\n this._state = 'stopped'\n if (errors.length > 0) throw new ActorShutdownError(errors)\n }\n\n private async stopStartedActors(): Promise<Error[]> {\n const errors: Error[] = []\n while (this._startedActors.length > 0) {\n const actor = this._startedActors.pop()\n if (actor === undefined) continue\n try {\n const result = await actor.stop()\n assertLifecycleSucceeded(actor, 'stop', result)\n } catch (error) {\n errors.push(new Error(`Actor \"${actor.name}\" failed to stop`, { cause: asError(error) }))\n }\n }\n return errors\n }\n}\n", "import type { ProcessHost } from './ProcessHost.ts'\n\n/** Process capability shared by every command created for one CLI app. */\nexport interface CliApplicationContext {\n readonly host: ProcessHost\n}\n\n/** Adapter-neutral factory for one parser-specific command object. */\nexport interface CommandDefinition<TContext extends CliApplicationContext, TCommand> {\n readonly create: (context: TContext) => TCommand\n /** Internal registration identity; it does not define parser syntax or aliases. */\n readonly id: string\n}\n\n/** Ordered command factories materialized for one app context. */\nexport interface CommandCatalog<TContext extends CliApplicationContext, TCommand> {\n readonly createCommands: (context: TContext) => readonly TCommand[]\n readonly ids: readonly string[]\n}\n\n/** Creates an immutable, adapter-neutral command catalog. */\nexport function createCommandCatalog<TContext extends CliApplicationContext, TCommand>(\n definitions: readonly CommandDefinition<TContext, TCommand>[],\n): CommandCatalog<TContext, TCommand> {\n const registeredIds = new Set<string>()\n const retainedDefinitions = definitions.map(definition => Object.freeze({\n create: definition.create,\n id: definition.id,\n }))\n const ids: string[] = []\n\n for (const definition of retainedDefinitions) {\n if (definition.id.trim().length === 0) throw new Error('Command id must not be empty')\n if (registeredIds.has(definition.id)) throw new Error(`Command \"${definition.id}\" is already registered`)\n registeredIds.add(definition.id)\n ids.push(definition.id)\n }\n\n return Object.freeze({\n ids: Object.freeze(ids),\n createCommands: (context: TContext): readonly TCommand[] =>\n Object.freeze(retainedDefinitions.map(definition => definition.create(context))),\n })\n}\n", "/** Process-facing input and output used by a command-line app. */\nexport interface ProcessIO {\n /** Available terminal width when output is attached to a sized terminal. */\n readonly columns?: number\n readonly isInteractive: boolean\n error(...values: readonly unknown[]): void\n log(...values: readonly unknown[]): void\n question(prompt: string): Promise<string>\n warn(...values: readonly unknown[]): void\n}\n\n/** Control-flow signal used when a non-terminating host records an immediate exit. */\nexport class ProcessExitError extends Error {\n readonly exitCode: number\n\n constructor(exitCode: number) {\n super(`Process requested exit with code ${exitCode}`)\n this.name = 'ProcessExitError'\n this.exitCode = exitCode\n }\n}\n\n/**\n * Structural process boundary for a command-line app.\n *\n * Production implementations may terminate from {@link exit}; recording hosts\n * may return after retaining the requested status.\n */\nexport interface ProcessHost {\n /** Full argument vector, including the executable and script entries. */\n readonly argv: readonly string[]\n /** Environment visible to this app invocation. */\n readonly environment: Readonly<Record<string, string | undefined>>\n readonly io: ProcessIO\n readonly isDevelopment: boolean\n exit(code: number): void\n onInterrupt(listener: () => Promise<void> | void): () => void\n}\n\n/**\n * Requests immediate process termination and prevents a recording host from\n * accidentally continuing through code that follows the exit point.\n */\nexport function exitProcess(host: Pick<ProcessHost, 'exit'>, exitCode: number): never {\n host.exit(exitCode)\n throw new ProcessExitError(exitCode)\n}\n", "import { ProcessExitError, type ProcessHost } from './ProcessHost.ts'\n\n/** Application entry point executed against an explicit process boundary. */\nexport type ProcessApplication = (host: ProcessHost) => Promise<void>\n\n/**\n * Where an unexpected failure originated.\n *\n * - `'parse'`: argument parsing or validation failed before any command\n * handler ran (for example a Yargs usage error).\n * - `'handler'`: the app body, command handler, or middleware failed after\n * arguments were accepted.\n */\nexport type FailureOrigin = 'handler' | 'parse'\n\n/**\n * Optional application-supplied failure policy. Returning a number selects\n * the exit code for that failure; returning `undefined` retains the default\n * exit code one. The `origin` argument distinguishes parse/validation\n * failures from handler failures so mappers such as `usage` (64) versus\n * `software` (70) need no runner-specific error sniffing. Intentional exits\n * carried by `ProcessExitError` are never offered to the mapper.\n *\n * Results outside the integer range 0\u2013255 (including `NaN`) and errors\n * thrown by the mapper itself fall back to exit code one; the mapper is\n * inside the failure boundary, not above it. Prefer drawing codes from\n * `SYS_EXITS`.\n */\nexport type FailureExitCodeMapper = (error: unknown, origin: FailureOrigin) => number | undefined\n\n/**\n * Resolves the exit code for an unexpected failure through an optional\n * mapper. A missing mapper, an `undefined` result, a thrown mapper, or a\n * result outside the integer range 0\u2013255 all resolve to the default exit\n * code one, keeping the failure boundary intact.\n */\nexport function resolveFailureExitCode(\n mapFailureToExitCode: FailureExitCodeMapper | undefined,\n error: unknown,\n origin: FailureOrigin,\n): number {\n if (mapFailureToExitCode === undefined) return 1\n try {\n const code = mapFailureToExitCode(error, origin)\n return code !== undefined && Number.isSafeInteger(code) && code >= 0 && code <= 255 ? code : 1\n } catch {\n return 1\n }\n}\n\nexport interface RunProcessApplicationOptions {\n readonly application: ProcessApplication\n readonly host: ProcessHost\n readonly mapFailureToExitCode?: FailureExitCodeMapper\n}\n\n/**\n * Runs one CLI app at the outermost process boundary.\n *\n * Immediate exits requested through `exitProcess` have already been\n * routed to the host and are absorbed here. Unexpected failures retain the\n * established CLI policy of logging details only in development before\n * requesting exit code one, or the code selected by `mapFailureToExitCode`.\n */\nexport async function runProcessApplication({\n application,\n host,\n mapFailureToExitCode,\n}: RunProcessApplicationOptions): Promise<void> {\n try {\n await application(host)\n } catch (error) {\n if (error instanceof ProcessExitError) return\n if (host.isDevelopment) host.io.error('An error occurred during startup:', error)\n host.exit(resolveFailureExitCode(mapFailureToExitCode, error, 'handler'))\n }\n}\n", "import type { ProcessHost } from './ProcessHost.ts'\n\n/** Lifecycle state of one active runtime session. */\nexport type RuntimeSessionState = 'active' | 'failed' | 'stopped' | 'stopping'\n\n/** Application-owned cleanup invoked when a runtime session stops. */\nexport type RuntimeStopDelegate = () => Promise<void> | void\n\n/** Application-owned work invoked for the first process interrupt. */\nexport type RuntimeInterruptListener = () => Promise<void> | void\n\n/**\n * Instance-scoped owner for one runtime cleanup operation.\n *\n * Every call to {@link stop} returns the same promise. A cleanup failure is\n * retained and rethrown without wrapping so callers can preserve their\n * existing fail-fast behavior.\n */\nexport class RuntimeSession {\n private _exitCode?: number\n private _exitHost?: Pick<ProcessHost, 'exit'>\n private _exitPromise?: Promise<void>\n private _hasInterruptBinding = false\n private _interruptDisposer?: () => void\n private _interruptPromise?: Promise<void>\n private _isInterruptDisposed = false\n private _state: RuntimeSessionState = 'active'\n private readonly _stopDelegate: RuntimeStopDelegate\n private _stopError?: unknown\n private _stopPromise?: Promise<void>\n\n constructor(stopDelegate: RuntimeStopDelegate) {\n this._stopDelegate = stopDelegate\n }\n\n get state(): RuntimeSessionState {\n return this._state\n }\n\n get stopError(): unknown {\n return this._stopError\n }\n\n bindInterrupt(host: Pick<ProcessHost, 'onInterrupt'>, listener: RuntimeInterruptListener): void {\n if (this._hasInterruptBinding) throw new Error('An interrupt listener is already bound to this runtime session.')\n if (this.state !== 'active') throw new Error('An interrupt listener cannot be bound after runtime shutdown has started.')\n\n this._hasInterruptBinding = true\n let isRegistrationComplete = false\n let isInterruptPending = false\n const handleInterrupt = (): Promise<void> | void => {\n if (!isRegistrationComplete) {\n isInterruptPending = true\n return\n }\n return this.handleInterrupt(listener)\n }\n this._interruptDisposer = host.onInterrupt(handleInterrupt)\n isRegistrationComplete = true\n\n // A structural host may deliver an interrupt while registering the listener.\n // Defer that delivery until the returned disposer is retained so it can be\n // removed after the interrupt handler settles.\n if (isInterruptPending) void this.handleInterrupt(listener)\n }\n\n /**\n * Coalesces competing process-exit requests for this session. Requests made\n * in the same turn retain the highest exit code and every caller observes\n * the same exactly-once exit operation.\n */\n requestExit(host: Pick<ProcessHost, 'exit'>, exitCode: number): Promise<void> {\n this._exitCode = Math.max(this._exitCode ?? exitCode, exitCode)\n this._exitHost ??= host\n this._exitPromise ??= Promise.try(async () => {\n await Promise.resolve()\n this._exitHost?.exit(this._exitCode ?? exitCode)\n })\n return this._exitPromise\n }\n\n stop(): Promise<void> {\n // Manual shutdown owns listener disposal immediately. Interrupt-driven\n // shutdown retains the listener until its handler settles so repeated\n // interrupts are coalesced instead of reaching the host's default handler.\n if (this._interruptPromise === undefined) this.disposeInterrupt()\n if (this._stopPromise === undefined) {\n this._state = 'stopping'\n this._stopPromise = Promise.try(async () => {\n await Promise.resolve()\n await this.stopOnce()\n })\n }\n return this._stopPromise\n }\n\n private disposeInterrupt(): void {\n if (!this._hasInterruptBinding || this._isInterruptDisposed) return\n this._isInterruptDisposed = true\n const dispose = this._interruptDisposer\n this._interruptDisposer = undefined\n dispose?.()\n }\n\n private handleInterrupt(listener: RuntimeInterruptListener): Promise<void> {\n if (this._interruptPromise === undefined) {\n if (this._isInterruptDisposed) return Promise.resolve()\n this._interruptPromise = Promise.try(async () => {\n await Promise.resolve()\n try {\n await listener()\n } finally {\n this.disposeInterrupt()\n }\n })\n }\n return this._interruptPromise\n }\n\n private async stopOnce(): Promise<void> {\n try {\n await this._stopDelegate()\n this._state = 'stopped'\n } catch (error) {\n this._stopError = error\n this._state = 'failed'\n throw error\n }\n }\n}\n", "/**\n * BSD `sysexits.h` exit codes shared across the CLI fleet.\n *\n * Only the subset actually used by apps is included so exit-code\n * policy stays reviewable. Use these with {@link exitProcess} or a\n * failure-to-exit-code mapper instead of repeating numeric literals.\n */\nexport const SYS_EXITS = {\n /** `EX_OK` (0): successful termination. */\n ok: 0,\n /** `EX_USAGE` (64): command line usage error, such as bad arguments or flags. */\n usage: 64,\n /** `EX_DATAERR` (65): input data was incorrect in some way. */\n dataErr: 65,\n /** `EX_NOINPUT` (66): an input file did not exist or was not readable. */\n noInput: 66,\n /** `EX_SOFTWARE` (70): internal software error not caused by the operating system. */\n software: 70,\n /** `EX_IOERR` (74): an error occurred while doing I/O on a file. */\n ioErr: 74,\n /** `EX_CONFIG` (78): something was found in an unconfigured or misconfigured state. */\n config: 78,\n} as const\n\n/** Exit code drawn from the supported `sysexits.h` vocabulary. */\nexport type SysExitCode = typeof SYS_EXITS[keyof typeof SYS_EXITS]\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * BSD `sysexits.h` exit codes shared across the CLI fleet.
3
+ *
4
+ * Only the subset actually used by apps is included so exit-code
5
+ * policy stays reviewable. Use these with {@link exitProcess} or a
6
+ * failure-to-exit-code mapper instead of repeating numeric literals.
7
+ */
8
+ export declare const SYS_EXITS: {
9
+ /** `EX_OK` (0): successful termination. */
10
+ readonly ok: 0;
11
+ /** `EX_USAGE` (64): command line usage error, such as bad arguments or flags. */
12
+ readonly usage: 64;
13
+ /** `EX_DATAERR` (65): input data was incorrect in some way. */
14
+ readonly dataErr: 65;
15
+ /** `EX_NOINPUT` (66): an input file did not exist or was not readable. */
16
+ readonly noInput: 66;
17
+ /** `EX_SOFTWARE` (70): internal software error not caused by the operating system. */
18
+ readonly software: 70;
19
+ /** `EX_IOERR` (74): an error occurred while doing I/O on a file. */
20
+ readonly ioErr: 74;
21
+ /** `EX_CONFIG` (78): something was found in an unconfigured or misconfigured state. */
22
+ readonly config: 78;
23
+ };
24
+ /** Exit code drawn from the supported `sysexits.h` vocabulary. */
25
+ export type SysExitCode = typeof SYS_EXITS[keyof typeof SYS_EXITS];
26
+ //# sourceMappingURL=sysExits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sysExits.d.ts","sourceRoot":"","sources":["../../src/sysExits.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;IACpB,2CAA2C;;IAE3C,iFAAiF;;IAEjF,+DAA+D;;IAE/D,0EAA0E;;IAE1E,sFAAsF;;IAEtF,oEAAoE;;IAEpE,uFAAuF;;CAE/E,CAAA;AAEV,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG,OAAO,SAAS,CAAC,MAAM,OAAO,SAAS,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ariestools/cli-kit",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Reusable actor lifecycle core for command-line applications",
5
5
  "keywords": [
6
6
  "ariestools",
@@ -46,10 +46,10 @@
46
46
  "@ariestools/toolchain": "~8.7.21",
47
47
  "@ariestools/tsconfig": "~8.7.21",
48
48
  "eslint": "~10.7.0",
49
+ "eslint-import-resolver-typescript": "~4.4.5",
49
50
  "typescript": "~6.0.3",
50
51
  "vite": "~8.1.5",
51
- "vitest": "~4.1.10",
52
- "eslint-import-resolver-typescript": "~4.4.5"
52
+ "vitest": "~4.1.10"
53
53
  },
54
54
  "engines": {
55
55
  "node": ">=24"