@gmickel/gno 1.0.5 → 1.2.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.
package/src/cli/errors.ts CHANGED
@@ -9,21 +9,52 @@
9
9
  // Error Types
10
10
  // ─────────────────────────────────────────────────────────────────────────────
11
11
 
12
- export type CliErrorCode = "VALIDATION" | "RUNTIME";
12
+ export type CliErrorCode = "VALIDATION" | "RUNTIME" | "NOT_RUNNING";
13
+
14
+ export interface CliErrorOptions {
15
+ details?: Record<string, unknown>;
16
+ /**
17
+ * Suppress all stderr output for this error. The exit code still
18
+ * propagates via `exitCodeFor()`. Used for `--stop` "not-running" where
19
+ * the spec says exit 3 silently with no envelope on either stream.
20
+ * See `spec/cli.md` Error Output section.
21
+ */
22
+ silent?: boolean;
23
+ }
13
24
 
14
25
  export class CliError extends Error {
15
26
  readonly code: CliErrorCode;
16
27
  readonly details?: Record<string, unknown>;
28
+ readonly silent: boolean;
17
29
 
18
30
  constructor(
19
31
  code: CliErrorCode,
20
32
  message: string,
21
- details?: Record<string, unknown>
33
+ detailsOrOptions?: Record<string, unknown> | CliErrorOptions
22
34
  ) {
23
35
  super(message);
24
36
  this.code = code;
25
- this.details = details;
26
37
  this.name = "CliError";
38
+ // Backwards-compat: callers passing a plain details record continue to
39
+ // work; the new options object is detected by the `silent`/`details`
40
+ // shape.
41
+ if (
42
+ detailsOrOptions &&
43
+ ("silent" in detailsOrOptions || "details" in detailsOrOptions) &&
44
+ // Disambiguate: a details payload could legitimately have a `details`
45
+ // key. Treat as options only when the bag has at most the two
46
+ // recognized keys to avoid swallowing user metadata.
47
+ Object.keys(detailsOrOptions).every(
48
+ (k) => k === "silent" || k === "details"
49
+ )
50
+ ) {
51
+ const opts = detailsOrOptions as CliErrorOptions;
52
+ this.details = opts.details;
53
+ this.silent = opts.silent ?? false;
54
+ } else {
55
+ this.details = detailsOrOptions as Record<string, unknown> | undefined;
56
+ this.silent = false;
57
+ }
27
58
  }
28
59
  }
29
60
 
@@ -31,8 +62,14 @@ export class CliError extends Error {
31
62
  // Exit Codes
32
63
  // ─────────────────────────────────────────────────────────────────────────────
33
64
 
34
- export function exitCodeFor(err: CliError): 1 | 2 {
35
- return err.code === "VALIDATION" ? 1 : 2;
65
+ export function exitCodeFor(err: CliError): 1 | 2 | 3 {
66
+ if (err.code === "VALIDATION") {
67
+ return 1;
68
+ }
69
+ if (err.code === "NOT_RUNNING") {
70
+ return 3;
71
+ }
72
+ return 2;
36
73
  }
37
74
 
38
75
  // ─────────────────────────────────────────────────────────────────────────────