hacksh 0.15.0 → 0.17.0

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.
@@ -1,11 +1,89 @@
1
1
  import { $ZodIssue, $ZodObject, JSONSchemaMeta, output } from "zod/v4/core";
2
+ //#region src/exec.d.ts
3
+ type Environment = Readonly<Record<string, string | undefined>>;
4
+ interface ExecOptions {
5
+ cwd?: string;
6
+ env?: Environment;
7
+ input?: string;
8
+ reject?: boolean;
9
+ timeout?: number;
10
+ signal?: AbortSignal;
11
+ maxBuffer?: number;
12
+ forceKillAfterDelay?: number;
13
+ stdin?: "pipe" | "inherit";
14
+ stdout?: "pipe" | "inherit";
15
+ stderr?: "pipe" | "inherit";
16
+ interactive?: boolean;
17
+ display?: boolean;
18
+ redact?: readonly string[];
19
+ dryRun?: boolean;
20
+ }
21
+ interface ExecCommand {
22
+ file: string;
23
+ args: readonly string[];
24
+ cwd: string | undefined;
25
+ }
26
+ interface ExecSuccess {
27
+ status: "succeeded";
28
+ command: ExecCommand;
29
+ stdout: string;
30
+ stderr: string;
31
+ exitCode: 0;
32
+ }
33
+ type ExecFailure = {
34
+ status: "failed";
35
+ command: ExecCommand;
36
+ stdout: string;
37
+ stderr: string;
38
+ } & ({
39
+ reason: "exit-code";
40
+ exitCode: number;
41
+ } | {
42
+ reason: "signal";
43
+ signal: string;
44
+ } | {
45
+ reason: "spawn";
46
+ error: Error;
47
+ } | {
48
+ reason: "timeout" | "aborted" | "output-limit";
49
+ } | {
50
+ reason: "json-output" | "non-interactive" | "overlapping";
51
+ });
52
+ type ExecFailureReason = ExecFailure["reason"];
53
+ type ExecResult = ExecSuccess | ExecFailure;
54
+ interface ExecSkipped {
55
+ status: "skipped";
56
+ command: ExecCommand;
57
+ }
58
+ type ExecOutcome<O extends ExecOptions> = "reject" extends keyof O ? false extends O["reject"] ? ExecResult : ExecSuccess : ExecSuccess;
59
+ type SpecifiedDryRun<O> = "dryRun" extends keyof O ? O["dryRun"] : false;
60
+ type ReturnsFailure<O extends ExecOptions> = "reject" extends keyof O ? false extends O["reject"] ? true : false : false;
61
+ type AbortedFailure = {
62
+ status: "failed";
63
+ command: ExecCommand;
64
+ stdout: string;
65
+ stderr: string;
66
+ reason: "aborted";
67
+ };
68
+ type DefiniteSkip<O extends ExecOptions> = ReturnsFailure<O> extends true ? ExecSkipped | AbortedFailure : ExecSkipped;
69
+ type ExecReturn<O extends ExecOptions> = true extends SpecifiedDryRun<O> ? false extends SpecifiedDryRun<O> ? ExecSkipped | ExecOutcome<O> : undefined extends SpecifiedDryRun<O> ? ExecSkipped | ExecOutcome<O> : DefiniteSkip<O> : ExecOutcome<O>;
70
+ type RejectInheritedInput<O> = O extends {
71
+ input: string;
72
+ stdin: "inherit";
73
+ } ? never : unknown;
74
+ type Exec = <const O extends ExecOptions = {}>(file: string, args?: readonly string[], options?: O & { [K in Exclude<keyof O, keyof ExecOptions>]: never; } & RejectInheritedInput<O>) => Promise<ExecReturn<O>>;
75
+ //#endregion
2
76
  //#region src/errors.d.ts
3
77
  interface HackshIssue {
4
78
  arg: string;
5
79
  message: string;
6
80
  issue?: $ZodIssue;
7
81
  }
8
- declare class HackshUsageError extends Error {
82
+ /** An expected CLI failure that runMain reports; application errors can extend this class. */
83
+ declare class HackshError extends Error {
84
+ constructor(message?: string, options?: ErrorOptions);
85
+ }
86
+ declare class HackshUsageError extends HackshError {
9
87
  readonly command: AnyCommandDef;
10
88
  constructor(message: string, command: AnyCommandDef, options?: ErrorOptions);
11
89
  }
@@ -21,19 +99,19 @@ interface PromptErrorDetails {
21
99
  choices?: readonly string[];
22
100
  }
23
101
  /** An input request that could not be completed safely. */
24
- declare class HackshPromptError extends Error {
102
+ declare class HackshPromptError extends HackshError {
25
103
  readonly reason: HackshPromptErrorReason;
26
104
  readonly prompt: PromptErrorDetails;
27
105
  constructor(reason: HackshPromptErrorReason, prompt: PromptErrorDetails, message: string, options?: ErrorOptions);
28
106
  }
29
107
  /** An external command that did not succeed; `result` is not enumerable so error summaries omit child output. */
30
- declare class HackshExecError extends Error {
108
+ declare class HackshExecError extends HackshError {
31
109
  #private;
32
110
  constructor(message: string, result: ExecFailure, options?: ErrorOptions);
33
111
  get result(): ExecFailure;
34
112
  }
35
113
  /** A requested process exit status; `runMain` exits with it and reports only a non-empty message. */
36
- declare class HackshExitError extends Error {
114
+ declare class HackshExitError extends HackshError {
37
115
  readonly exitCode: number;
38
116
  constructor(exitCode: number, message?: string, options?: ErrorOptions);
39
117
  }
@@ -136,16 +214,21 @@ declare function showUsage(command: AnyCommandDef, options: ShowUsageOptions): P
136
214
  type PrintStream = "stdout" | "stderr";
137
215
  type OutputPreference = "auto" | "pretty" | "json";
138
216
  type OutputFormat = Exclude<OutputPreference, "auto">;
217
+ interface StreamColors {
218
+ stdout: boolean;
219
+ stderr: boolean;
220
+ }
139
221
  interface OutputMode {
140
222
  format: OutputFormat;
141
223
  interactive: boolean;
142
- color: boolean;
224
+ color: StreamColors;
143
225
  }
144
226
  interface ResolveOutputModeOptions {
145
227
  output?: OutputPreference;
146
228
  env?: Readonly<Record<string, string | undefined>>;
147
229
  inputIsTTY?: boolean;
148
230
  outputIsTTY?: boolean;
231
+ errorOutputIsTTY?: boolean;
149
232
  }
150
233
  /** Resolve output behavior once, before command routing or argument parsing. */
151
234
  declare function resolveOutputMode(options?: ResolveOutputModeOptions): OutputMode;
@@ -199,6 +282,16 @@ interface PromptPrintEvent {
199
282
  type: "prompt";
200
283
  prompt: PromptState;
201
284
  }
285
+ /** Command output: exact text written to stdout, or a JSON value. */
286
+ type OutputPrintEvent = {
287
+ type: "output";
288
+ kind: "text";
289
+ text: string;
290
+ } | {
291
+ type: "output";
292
+ kind: "json";
293
+ data: unknown;
294
+ };
202
295
  interface ExecPrintEvent {
203
296
  type: "exec";
204
297
  phase: "start" | "skip";
@@ -213,7 +306,7 @@ interface ExecPrintEvent {
213
306
  interactive: boolean;
214
307
  }
215
308
  /** A semantic, command- and schema-free output value emitted by hacksh. */
216
- type PrintEvent = UsagePrintEvent | VersionPrintEvent | ErrorPrintEvent | LogPrintEvent | PromptPrintEvent | ExecPrintEvent;
309
+ type PrintEvent = UsagePrintEvent | VersionPrintEvent | ErrorPrintEvent | LogPrintEvent | PromptPrintEvent | OutputPrintEvent | ExecPrintEvent;
217
310
  /** Receives every output event produced by one command invocation. */
218
311
  interface Printer {
219
312
  print(event: PrintEvent): void | Promise<void>;
@@ -242,79 +335,16 @@ interface JsonPrinterOptions {
242
335
  /** Create a one-semantic-event-per-line JSON printer. */
243
336
  declare function createJsonPrinter(options?: JsonPrinterOptions): Printer;
244
337
  //#endregion
245
- //#region src/exec.d.ts
246
- type Environment = Readonly<Record<string, string | undefined>>;
247
- interface ExecOptions {
248
- cwd?: string;
249
- env?: Environment;
250
- input?: string;
251
- reject?: boolean;
252
- timeout?: number;
253
- signal?: AbortSignal;
254
- maxBuffer?: number;
255
- forceKillAfterDelay?: number;
256
- stdin?: "pipe" | "inherit";
257
- stdout?: "pipe" | "inherit";
258
- stderr?: "pipe" | "inherit";
259
- interactive?: boolean;
260
- display?: boolean;
261
- redact?: readonly string[];
262
- dryRun?: boolean;
263
- }
264
- interface ExecCommand {
265
- file: string;
266
- args: readonly string[];
267
- cwd: string | undefined;
268
- }
269
- interface ExecSuccess {
270
- status: "succeeded";
271
- command: ExecCommand;
272
- stdout: string;
273
- stderr: string;
274
- exitCode: 0;
275
- }
276
- type ExecFailure = {
277
- status: "failed";
278
- command: ExecCommand;
279
- stdout: string;
280
- stderr: string;
281
- } & ({
282
- reason: "exit-code";
283
- exitCode: number;
284
- } | {
285
- reason: "signal";
286
- signal: string;
287
- } | {
288
- reason: "spawn";
289
- error: Error;
290
- } | {
291
- reason: "timeout" | "aborted" | "output-limit";
292
- } | {
293
- reason: "json-output" | "non-interactive" | "overlapping";
294
- });
295
- type ExecFailureReason = ExecFailure["reason"];
296
- type ExecResult = ExecSuccess | ExecFailure;
297
- interface ExecSkipped {
298
- status: "skipped";
299
- command: ExecCommand;
338
+ //#region src/command-output.d.ts
339
+ /** Writes a command's results to stdout, separately from logs. */
340
+ interface Output {
341
+ /** Write text exactly as given. */
342
+ print(text: string): void;
343
+ /** Write text followed by a newline. */
344
+ println(text?: string): void;
345
+ /** Write a JSON value. */
346
+ json(value: unknown): void;
300
347
  }
301
- type ExecOutcome<O extends ExecOptions> = "reject" extends keyof O ? false extends O["reject"] ? ExecResult : ExecSuccess : ExecSuccess;
302
- type SpecifiedDryRun<O> = "dryRun" extends keyof O ? O["dryRun"] : false;
303
- type ReturnsFailure<O extends ExecOptions> = "reject" extends keyof O ? false extends O["reject"] ? true : false : false;
304
- type AbortedFailure = {
305
- status: "failed";
306
- command: ExecCommand;
307
- stdout: string;
308
- stderr: string;
309
- reason: "aborted";
310
- };
311
- type DefiniteSkip<O extends ExecOptions> = ReturnsFailure<O> extends true ? ExecSkipped | AbortedFailure : ExecSkipped;
312
- type ExecReturn<O extends ExecOptions> = true extends SpecifiedDryRun<O> ? false extends SpecifiedDryRun<O> ? ExecSkipped | ExecOutcome<O> : undefined extends SpecifiedDryRun<O> ? ExecSkipped | ExecOutcome<O> : DefiniteSkip<O> : ExecOutcome<O>;
313
- type RejectInheritedInput<O> = O extends {
314
- input: string;
315
- stdin: "inherit";
316
- } ? never : unknown;
317
- type Exec = <const O extends ExecOptions = {}>(file: string, args?: readonly string[], options?: O & { [K in Exclude<keyof O, keyof ExecOptions>]: never; } & RejectInheritedInput<O>) => Promise<ExecReturn<O>>;
318
348
  //#endregion
319
349
  //#region src/prompts.d.ts
320
350
  interface SelectOption<T extends string> {
@@ -366,6 +396,7 @@ interface CommandContext<S extends ArgsSchema> {
366
396
  unknown: string[];
367
397
  passthrough: string[];
368
398
  };
399
+ output: Output;
369
400
  logger: Logger;
370
401
  prompt: Prompter;
371
402
  exec: Exec;
@@ -383,7 +414,7 @@ interface CommandDef<S extends ArgsSchema = EmptyArgs, R = unknown, Children ext
383
414
  run?(context: CommandContext<S>): R;
384
415
  }
385
416
  type AnyCommandDef = CommandDef<ArgsSchema>;
386
- declare function defineCommand<S extends ArgsSchema = EmptyArgs, R = never, Children extends Record<string, AnyCommandDef> = {}>(def: CommandDef<S, R, Children>): CommandDef<S, NoInfer<R>, NoInfer<Children>>;
417
+ declare function defineCommand<S extends ArgsSchema = EmptyArgs, R = never, Children extends Record<string, AnyCommandDef> = {}>(def: CommandDef<S, R, Children>): NoInfer<CommandDef<S, R, Children>>;
387
418
  //#endregion
388
- export { LogKind as $, PrintStream as A, TextPromptState as B, JsonPrinterOptions as C, OutputPreference as D, OutputMode as E, PromptStatus as F, ShowUsageOptions as G, VersionPrintEvent as H, ResolveOutputModeOptions as I, UsageOptionSummary as J, UsageArgumentSummary as K, SelectPromptState as L, PromptChoiceState as M, PromptPrintEvent as N, OutputWriter as O, PromptState as P, summarizeUsage as Q, TerminalInput as R, ExecPrintEvent as S, OutputFormat as T, createJsonPrinter as U, UsagePrintEvent as V, resolveOutputMode as W, renderUsage as X, UsageSummary as Y, showUsage as Z, ExecReturn as _, ArgsSchema as a, HackshErrorSummary as at, ConfirmPromptState as b, SelectOption as c, HackshIssue as ct, Exec as d, HackshUsageError as dt, LogLevel as et, ExecCommand as f, HackshValidationError as ft, ExecResult as g, ExecOptions as h, ValidationIssueSummary as ht, defineCommand as i, HackshErrorKind as it, Printer as j, PrintEvent as k, SelectOptions as l, HackshPromptError as lt, ExecFailureReason as m, PromptKind as mt, CommandContext as n, LogRecord as nt, ConfirmOptions as o, HackshExecError as ot, ExecFailure as p, PromptErrorDetails as pt, UsageCommandSummary as q, CommandDef as r, Logger as rt, Prompter as s, HackshExitError as st, AnyCommandDef as t, LogProperties as tt, TextOptions as u, HackshPromptErrorReason as ut, ExecSkipped as v, LogPrintEvent as w, ErrorPrintEvent as x, ExecSuccess as y, TerminalOutput as z };
389
- //# sourceMappingURL=command-pPKGCjNA.d.ts.map
419
+ export { HackshErrorKind as $, SelectPromptState as A, UsageArgumentSummary as B, PrintStream as C, PromptState as D, PromptPrintEvent as E, UsagePrintEvent as F, showUsage as G, UsageOptionSummary as H, VersionPrintEvent as I, LogLevel as J, summarizeUsage as K, createJsonPrinter as L, TerminalInput as M, TerminalOutput as N, PromptStatus as O, TextPromptState as P, HackshError as Q, resolveOutputMode as R, PrintEvent as S, PromptChoiceState as T, UsageSummary as U, UsageCommandSummary as V, renderUsage as W, LogRecord as X, LogProperties as Y, Logger as Z, OutputFormat as _, ExecReturn as _t, ArgsSchema as a, HackshPromptErrorReason as at, OutputPrintEvent as b, SelectOption as c, PromptErrorDetails as ct, Output as d, Exec as dt, HackshErrorSummary as et, ConfirmPromptState as f, ExecCommand as ft, LogPrintEvent as g, ExecResult as gt, JsonPrinterOptions as h, ExecOptions as ht, defineCommand as i, HackshPromptError as it, StreamColors as j, ResolveOutputModeOptions as k, SelectOptions as l, PromptKind as lt, ExecPrintEvent as m, ExecFailureReason as mt, CommandContext as n, HackshExitError as nt, ConfirmOptions as o, HackshUsageError as ot, ErrorPrintEvent as p, ExecFailure as pt, LogKind as q, CommandDef as r, HackshIssue as rt, Prompter as s, HackshValidationError as st, AnyCommandDef as t, HackshExecError as tt, TextOptions as u, ValidationIssueSummary as ut, OutputMode as v, ExecSkipped as vt, Printer as w, OutputWriter as x, OutputPreference as y, ExecSuccess as yt, ShowUsageOptions as z };
420
+ //# sourceMappingURL=command-t16M3-AZ.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as OutputPreference, G as ShowUsageOptions, O as OutputWriter, Q as summarizeUsage, R as TerminalInput, X as renderUsage, Z as showUsage, _ as ExecReturn, a as ArgsSchema, c as SelectOption, ct as HackshIssue, d as Exec, dt as HackshUsageError, f as ExecCommand, ft as HackshValidationError, g as ExecResult, h as ExecOptions, i as defineCommand, j as Printer, l as SelectOptions, lt as HackshPromptError, m as ExecFailureReason, mt as PromptKind, n as CommandContext, o as ConfirmOptions, ot as HackshExecError, p as ExecFailure, pt as PromptErrorDetails, r as CommandDef, rt as Logger, s as Prompter, st as HackshExitError, t as AnyCommandDef, u as TextOptions, ut as HackshPromptErrorReason, v as ExecSkipped, y as ExecSuccess, z as TerminalOutput } from "./command-pPKGCjNA.js";
1
+ import { G as showUsage, K as summarizeUsage, M as TerminalInput, N as TerminalOutput, Q as HackshError, W as renderUsage, Z as Logger, _t as ExecReturn, a as ArgsSchema, at as HackshPromptErrorReason, c as SelectOption, ct as PromptErrorDetails, d as Output, dt as Exec, ft as ExecCommand, gt as ExecResult, ht as ExecOptions, i as defineCommand, it as HackshPromptError, l as SelectOptions, lt as PromptKind, mt as ExecFailureReason, n as CommandContext, nt as HackshExitError, o as ConfirmOptions, ot as HackshUsageError, pt as ExecFailure, r as CommandDef, rt as HackshIssue, s as Prompter, st as HackshValidationError, t as AnyCommandDef, tt as HackshExecError, u as TextOptions, vt as ExecSkipped, w as Printer, y as OutputPreference, yt as ExecSuccess, z as ShowUsageOptions } from "./command-t16M3-AZ.js";
2
2
  import { output } from "zod/v4/core";
3
3
  //#region src/parser.d.ts
4
4
  /**
@@ -17,7 +17,7 @@ interface OutputOptions {
17
17
  env?: Readonly<Record<string, string | undefined>>;
18
18
  stdin?: TerminalInput;
19
19
  stdout?: TerminalOutput;
20
- stderr?: OutputWriter;
20
+ stderr?: TerminalOutput;
21
21
  }
22
22
  //#endregion
23
23
  //#region src/run.d.ts
@@ -33,11 +33,11 @@ type CommandResult<C> = HandlerResult<C> | (C extends {
33
33
  } ? Children extends Record<string, AnyCommandDef> ? string extends keyof Children ? unknown : CommandResult<Children[keyof Children]> : never : never);
34
34
  declare function runCommand<C extends AnyCommandDef>(root: C, argv: string[], options?: RunCommandOptions): Promise<CommandResult<C> | undefined>;
35
35
  interface RunMainOptions extends OutputOptions {
36
- onError?: (error: unknown) => void | Promise<void>;
36
+ onError?: (error: HackshError) => void | Promise<void>;
37
37
  argv?: string[];
38
38
  printer?: Printer;
39
39
  }
40
40
  declare function runMain<S extends ArgsSchema>(command: CommandDef<S>, options?: RunMainOptions): Promise<void>;
41
41
  //#endregion
42
- export { type CommandContext, type CommandDef, type ConfirmOptions, type Exec, type ExecCommand, type ExecFailure, type ExecFailureReason, type ExecOptions, type ExecResult, type ExecReturn, type ExecSkipped, type ExecSuccess, HackshExecError, HackshExitError, type HackshIssue, HackshPromptError, type HackshPromptErrorReason, HackshUsageError, HackshValidationError, type Logger, type OutputOptions, type PromptErrorDetails, type PromptKind, type Prompter, type RunCommandOptions, type RunMainOptions, type SelectOption, type SelectOptions, type ShowUsageOptions, type TextOptions, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage, summarizeUsage };
42
+ export { type CommandContext, type CommandDef, type ConfirmOptions, type Exec, type ExecCommand, type ExecFailure, type ExecFailureReason, type ExecOptions, type ExecResult, type ExecReturn, type ExecSkipped, type ExecSuccess, HackshError, HackshExecError, HackshExitError, type HackshIssue, HackshPromptError, type HackshPromptErrorReason, HackshUsageError, HackshValidationError, type Logger, type Output, type OutputOptions, type PromptErrorDetails, type PromptKind, type Prompter, type RunCommandOptions, type RunMainOptions, type SelectOption, type SelectOptions, type ShowUsageOptions, type TextOptions, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage, summarizeUsage };
43
43
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as createExec, c as HackshPromptError, d as summarizeError, f as summarizeErrors, i as resolveOutputMode, l as HackshUsageError, n as createJsonPrinter, o as HackshExecError, r as createPrintQueue, s as HackshExitError, t as createPrettyPrinter, u as HackshValidationError } from "./pretty-BFub611x.js";
1
+ import { a as createExec, c as HackshExitError, d as HackshValidationError, f as summarizeError, i as resolveOutputMode, l as HackshPromptError, n as createJsonPrinter, o as HackshError, p as summarizeErrors, r as createPrintQueue, s as HackshExecError, t as createPrettyPrinter, u as HackshUsageError } from "./pretty-Db7-kATM.js";
2
2
  import { globalRegistry, safeParseAsync } from "zod/v4/core";
3
3
  import { parseArgs as parseArgs$1 } from "node:util";
4
4
  import { readFile, realpath } from "node:fs/promises";
@@ -475,6 +475,27 @@ async function parseArgs(command, argv, options) {
475
475
  return (await parseCommandArgs(command, argv, tokenizeCommandArgs(command, argv), options?.env, envPath)).args;
476
476
  }
477
477
  //#endregion
478
+ //#region src/command-output.ts
479
+ /** Create the output for one command invocation. */
480
+ function createOutput(printer) {
481
+ function print(text) {
482
+ printer.print({
483
+ type: "output",
484
+ kind: "text",
485
+ text
486
+ });
487
+ }
488
+ return {
489
+ print,
490
+ println: (text = "") => print(`${text}\n`),
491
+ json: (data) => void printer.print({
492
+ type: "output",
493
+ kind: "json",
494
+ data
495
+ })
496
+ };
497
+ }
498
+ //#endregion
478
499
  //#region src/terminal.ts
479
500
  var TerminalLock = class {
480
501
  #owner;
@@ -885,7 +906,8 @@ function selectOutputPrinter(options, override, resolvedMode) {
885
906
  output: options.output,
886
907
  env: options.env,
887
908
  inputIsTTY: stdin.isTTY,
888
- outputIsTTY: stdout.isTTY
909
+ outputIsTTY: stdout.isTTY,
910
+ errorOutputIsTTY: stderr.isTTY
889
911
  });
890
912
  if (override) return override;
891
913
  if (mode.format === "json") return createJsonPrinter({
@@ -1109,6 +1131,7 @@ async function executeCommand(root, argv, output, env, signal, fallbackVersion =
1109
1131
  unknown: parsed.extraArgs,
1110
1132
  passthrough: parsed.passthrough
1111
1133
  },
1134
+ output: createOutput(printer),
1112
1135
  logger: createLogger(printer, category),
1113
1136
  prompt: new PromptController({
1114
1137
  interactive: output.interactive,
@@ -1136,7 +1159,8 @@ function prepareOutput(options, env) {
1136
1159
  output: options.output,
1137
1160
  env,
1138
1161
  inputIsTTY: input.isTTY,
1139
- outputIsTTY: (options.stdout ?? process.stdout).isTTY
1162
+ outputIsTTY: (options.stdout ?? process.stdout).isTTY,
1163
+ errorOutputIsTTY: (options.stderr ?? process.stderr).isTTY
1140
1164
  });
1141
1165
  return {
1142
1166
  ...createPrintQueue(selectOutputPrinter(options, options.printer, mode)),
@@ -1154,13 +1178,6 @@ async function runCommand(root, argv, options = {}) {
1154
1178
  await output.drain();
1155
1179
  }
1156
1180
  }
1157
- async function drainAndExit(output, code = 1) {
1158
- try {
1159
- await output.drain();
1160
- } finally {
1161
- process.exit(code);
1162
- }
1163
- }
1164
1181
  function commandErrorExitCode(error) {
1165
1182
  if (error instanceof HackshExitError) return error.exitCode;
1166
1183
  return error instanceof HackshPromptError && error.reason === "cancelled" ? 130 : 1;
@@ -1189,21 +1206,6 @@ function listenForExitSignals() {
1189
1206
  }
1190
1207
  };
1191
1208
  }
1192
- async function reportOutputSetupError(error, options) {
1193
- if (options.onError) {
1194
- await options.onError(error);
1195
- return drainAndExit(createPrintQueue(options.printer ?? { print: () => void 0 }));
1196
- }
1197
- const output = createPrintQueue(options.printer ?? createJsonPrinter({
1198
- stdout: options.stdout ?? process.stdout,
1199
- stderr: options.stderr ?? process.stderr
1200
- }));
1201
- await output.printer.print({
1202
- type: "error",
1203
- error: summarizeError(error)
1204
- });
1205
- return drainAndExit(output);
1206
- }
1207
1209
  async function reportCommandError(error, output) {
1208
1210
  if (error instanceof HackshExitError && error.message === "") return;
1209
1211
  await output.printer.print({
@@ -1216,37 +1218,33 @@ async function reportCommandError(error, output) {
1216
1218
  });
1217
1219
  }
1218
1220
  async function runMain(command, options = {}) {
1219
- let output;
1220
- try {
1221
- output = prepareOutput(options, options.env ?? process.env);
1222
- } catch (error) {
1223
- return reportOutputSetupError(error, options);
1224
- }
1221
+ const output = prepareOutput(options, options.env ?? process.env);
1225
1222
  const signals = listenForExitSignals();
1226
- const exit = (code) => {
1227
- signals.release();
1228
- return drainAndExit(output, signals.exitCode() ?? code);
1229
- };
1223
+ let exitCode;
1230
1224
  try {
1231
- await executeCommand(command, options.argv ?? process.argv.slice(2), output, options.env, signals.signal, () => findPackageVersion(process.argv[1]));
1232
- } catch (error) {
1233
- if (options.onError) {
1234
- await options.onError(error);
1235
- return exit(commandErrorExitCode(error));
1225
+ try {
1226
+ await executeCommand(command, options.argv ?? process.argv.slice(2), output, options.env, signals.signal, () => findPackageVersion(process.argv[1]));
1227
+ } catch (error) {
1228
+ const signalExitCode = signals.exitCode();
1229
+ if (signalExitCode !== void 0 && error === signals.signal.reason) exitCode = signalExitCode;
1230
+ else {
1231
+ if (!(error instanceof HackshError)) throw error;
1232
+ if (options.onError) await options.onError(error);
1233
+ else await reportCommandError(error, output);
1234
+ exitCode = commandErrorExitCode(error);
1235
+ }
1236
1236
  }
1237
+ } finally {
1237
1238
  try {
1238
- await reportCommandError(error, output);
1239
+ await output.drain();
1239
1240
  } finally {
1240
- await exit(commandErrorExitCode(error));
1241
+ signals.release();
1241
1242
  }
1242
- } finally {
1243
- signals.release();
1244
1243
  }
1245
- const signalExitCode = signals.exitCode();
1246
- if (signalExitCode !== void 0) return drainAndExit(output, signalExitCode);
1247
- await output.drain();
1244
+ const code = signals.exitCode() ?? exitCode;
1245
+ if (code !== void 0) process.exit(code);
1248
1246
  }
1249
1247
  //#endregion
1250
- export { HackshExecError, HackshExitError, HackshPromptError, HackshUsageError, HackshValidationError, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage, summarizeUsage };
1248
+ export { HackshError, HackshExecError, HackshExitError, HackshPromptError, HackshUsageError, HackshValidationError, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage, summarizeUsage };
1251
1249
 
1252
1250
  //# sourceMappingURL=index.js.map