hacksh 0.1.1 → 0.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/README.md +217 -26
- package/dist/index.d.ts +283 -28
- package/dist/index.js +1154 -49
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -35,9 +35,10 @@ const main = defineCommand({
|
|
|
35
35
|
verbose: z.boolean().default(false).describe("Show details"),
|
|
36
36
|
}),
|
|
37
37
|
argOptions: { repo: { alias: "R" }, verbose: { alias: ["v", "V"] } },
|
|
38
|
-
async run({ args, rawArgs, extraArgs, passthrough }) {
|
|
38
|
+
async run({ args, rawArgs, extraArgs, passthrough, logger }) {
|
|
39
39
|
// args is { _: [number?]; repo?: string; verbose: boolean }
|
|
40
|
-
|
|
40
|
+
logger.info("Loading commits for {repo}", { repo: args.repo ?? "the current repository" });
|
|
41
|
+
logger.debug("Invocation arguments", { rawArgs, extraArgs, passthrough });
|
|
41
42
|
},
|
|
42
43
|
});
|
|
43
44
|
|
|
@@ -143,8 +144,9 @@ OPTIONS
|
|
|
143
144
|
when an alias is longer than one character or is used by more than one option, and when
|
|
144
145
|
`argOptions` has a `_` key. Without an alias of the same letter, `-h` and `-v` are shorthands
|
|
145
146
|
for `--help` and `--version`. Defining an `h` or `v` alias replaces the shorthand, so `convert -v`
|
|
146
|
-
above sets `verbose`; `--help` and `--version` remain available.
|
|
147
|
-
|
|
147
|
+
above sets `verbose`; `--help` and `--version` remain available. Output selection does not reserve
|
|
148
|
+
any additional command-line flags, so names such as `--json`, `--output`, and `--log-format` remain
|
|
149
|
+
available to application schemas.
|
|
148
150
|
|
|
149
151
|
## Subcommands
|
|
150
152
|
|
|
@@ -155,8 +157,8 @@ const main = defineCommand({
|
|
|
155
157
|
subCommands: {
|
|
156
158
|
new: defineCommand({
|
|
157
159
|
args: z.object({ name: z.string() }),
|
|
158
|
-
async run({ args }) {
|
|
159
|
-
|
|
160
|
+
async run({ args, logger }) {
|
|
161
|
+
logger.success("Created {name}", { name: args.name });
|
|
160
162
|
},
|
|
161
163
|
}),
|
|
162
164
|
migrate: defineCommand({
|
|
@@ -179,22 +181,209 @@ listing, including usage shown for an unknown command. Hidden commands remain av
|
|
|
179
181
|
their own `--help` output remains available. If every subcommand is hidden, help keeps the generic
|
|
180
182
|
`<COMMAND>` syntax but omits the empty `COMMANDS` section.
|
|
181
183
|
|
|
184
|
+
## Structured logging
|
|
185
|
+
|
|
186
|
+
Every `run` context has a `logger`. Its `trace`, `debug`, `info`, `warn`, `error`, and `fatal`
|
|
187
|
+
methods emit structured records through the invocation's printer. `step` and `success` are
|
|
188
|
+
info-level records with a distinct semantic kind for presentation. Placeholders in braces use the
|
|
189
|
+
record's properties. Every level is emitted and displayed by the default printer; there is no
|
|
190
|
+
built-in severity threshold or verbose flag.
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
const deploy = defineCommand({
|
|
194
|
+
name: "deploy",
|
|
195
|
+
async run({ logger }) {
|
|
196
|
+
const log = logger.with({ app: "web", env: "prod" });
|
|
197
|
+
log.step("Deploying {app} to {env}");
|
|
198
|
+
log.getChild("upload").debug("Uploaded {files} files", { files: 12 });
|
|
199
|
+
log.success("Deployed {app}");
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Properties passed to an individual call override properties bound by `with`. `getChild` appends a
|
|
205
|
+
category segment; hacksh automatically starts the category with the named root and each resolved
|
|
206
|
+
subcommand. Missing placeholders, and placeholders whose values cannot be converted to text,
|
|
207
|
+
remain unchanged without discarding their properties. Passing an `Error` to `error` or `fatal`
|
|
208
|
+
uses its message and adds a canonical, schema-free error summary as `properties.error`. Error
|
|
209
|
+
values nested in other log properties are summarized the same way before custom printers receive
|
|
210
|
+
the event.
|
|
211
|
+
|
|
212
|
+
Each `log` print event contains a `record` with `level`, `kind`, `category`, interpolated `message`,
|
|
213
|
+
template `rawMessage`, merged `properties`, and a numeric `timestamp`. Logger calls do not need to
|
|
214
|
+
be awaited: they use the invocation's serialized output queue, which is drained before execution
|
|
215
|
+
finishes. A printer failure rejects the invocation without changing a successful `run` value.
|
|
216
|
+
|
|
217
|
+
## Interactive input
|
|
218
|
+
|
|
219
|
+
The logger also owns the invocation's interactive input. Use `select`, `confirm`, and `text` from
|
|
220
|
+
the same logger (including loggers returned by `with` and `getChild`) so prompts use the selected
|
|
221
|
+
printer and output mode.
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
const deploy = defineCommand({
|
|
225
|
+
name: "deploy",
|
|
226
|
+
async run({ logger }) {
|
|
227
|
+
const environment = await logger.select({
|
|
228
|
+
message: "Environment",
|
|
229
|
+
options: [
|
|
230
|
+
{ value: "staging", hint: "safe default" },
|
|
231
|
+
{ value: "production", label: "Production" },
|
|
232
|
+
] as const,
|
|
233
|
+
initialValue: "staging",
|
|
234
|
+
}); // "staging" | "production"
|
|
235
|
+
const confirmed = await logger.confirm({ message: `Deploy to ${environment}?` });
|
|
236
|
+
if (!confirmed) return;
|
|
237
|
+
const release = await logger.text({
|
|
238
|
+
message: "Release name",
|
|
239
|
+
placeholder: "v1.2.3",
|
|
240
|
+
validate: (value) => (value.length === 0 ? "A release name is required" : undefined),
|
|
241
|
+
});
|
|
242
|
+
logger.success("Deploying {release}", { release });
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Select values retain their literal union type. Arrow keys change the selected choice, Enter accepts
|
|
248
|
+
it, and `initialValue` controls the initial selection. Confirm accepts `y`, `n`, or Enter; Enter
|
|
249
|
+
uses `initialValue` when supplied and otherwise means no. Text displays its placeholder without
|
|
250
|
+
using it as input, supports editing, and repeats the prompt only when `validate` returns a nonempty
|
|
251
|
+
message; `""` means valid. Backspace removes one Unicode code point. Input pasted after a selection
|
|
252
|
+
or confirmation is retained for the next sequential prompt instead of being discarded.
|
|
253
|
+
The built-in prompt API intentionally stops at select, confirm, and text; it does not provide a
|
|
254
|
+
multiselect prompt.
|
|
255
|
+
|
|
256
|
+
Prompts are allowed only when the resolved mode is interactive: pretty output outside CI with TTY
|
|
257
|
+
stdin and stdout. JSON, CI, and non-TTY invocations throw `HackshPromptError` immediately even if a
|
|
258
|
+
default is available. Its `reason` and `prompt` fields identify why input failed and the prompt's
|
|
259
|
+
`kind`, `message`, and select `choices`. Reasons distinguish `non-interactive`, `cancelled`, `eof`,
|
|
260
|
+
`overlapping`, `invalid-options`, `input-error`, and `printer-error`. Ctrl-C and Escape cancel;
|
|
261
|
+
`runMain` reports cancellation and exits with status 130. Only one prompt may be active in an
|
|
262
|
+
invocation. Input listeners and raw terminal mode are restored after every outcome.
|
|
263
|
+
Failed prompts emit a non-visible `closed` prompt state through the same printer before rejecting,
|
|
264
|
+
so callers that catch cancellation, EOF, input, or printer errors do not leave stale terminal UI.
|
|
265
|
+
|
|
266
|
+
Active pretty prompts redraw in place rather than appending a block for every key. A completed
|
|
267
|
+
prompt collapses to one result line. If a logger event arrives while a prompt is active, the
|
|
268
|
+
printer removes the prompt, renders the event, and then redraws the current prompt state.
|
|
269
|
+
Physical rows are calculated from explicit newlines, ANSI-free Unicode display width, and
|
|
270
|
+
`stdout.columns`, including terminal wrapping. When a custom output writer does not expose a
|
|
271
|
+
positive `columns` value, the renderer conservatively counts explicit lines only.
|
|
272
|
+
|
|
273
|
+
## Output formats
|
|
274
|
+
|
|
275
|
+
`runMain` and `runCommand` resolve one output mode before command routing, parsing, or execution.
|
|
276
|
+
Their `output` option accepts `"auto"` (the default), `"pretty"`, or `"json"`. A valid
|
|
277
|
+
`HACKSH_OUTPUT` environment value takes precedence over that option. `auto` selects JSON only when
|
|
278
|
+
`CI` has a non-empty value; redirecting or piping stdout alone retains pretty output. Invalid
|
|
279
|
+
explicit option or environment values never execute the command. `runCommand` rejects with a
|
|
280
|
+
`TypeError`. `runMain` gives that error to `onError` when configured; otherwise it emits the error
|
|
281
|
+
through a supplied printer or as a dedicated JSON error line, drains output, and exits with status
|
|
282
|
+
code `1`. Output values are case-sensitive.
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
await runMain(main, { output: "auto" });
|
|
286
|
+
// HACKSH_OUTPUT=json my-cli --help overrides the configured preference.
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
The resolved `OutputMode` has `format`, `interactive`, and `color` fields. Interaction is enabled
|
|
290
|
+
only for pretty output outside CI when both stdin and stdout are TTYs. Color is enabled only for
|
|
291
|
+
pretty output to a stdout TTY when `NO_COLOR` is empty or absent. These decisions are independent: an
|
|
292
|
+
explicit pretty format in CI can use color, but remains noninteractive. `env`, `stdin`, `stdout`,
|
|
293
|
+
and `stderr` can be supplied in execution options for embedded or tested invocations.
|
|
294
|
+
Custom `stdin` values implement the readable-stream operations `on`, `removeListener`, `resume`,
|
|
295
|
+
and `pause`; `isTTY`, `isRaw`, `readableFlowing`, and `setRawMode` describe optional terminal
|
|
296
|
+
capabilities. A stream without those readable operations fails with an `input-error` if prompting
|
|
297
|
+
is attempted.
|
|
298
|
+
|
|
299
|
+
JSON output contains exactly one `PrintEvent` object per line. Help and version events and
|
|
300
|
+
trace/debug/info logs go to stdout; errors and warning/error/fatal logs go to stderr. Usage attached
|
|
301
|
+
to an error retains its `stderr` stream. Every log level is emitted by default. JSON strings have
|
|
302
|
+
terminal control sequences removed, and the printer never serializes executable command or Zod
|
|
303
|
+
schema objects.
|
|
304
|
+
|
|
305
|
+
Arbitrary log properties and error details are normalized predictably: BigInt values become
|
|
306
|
+
decimal strings; non-finite numbers become `null`; `undefined`, symbols, and functions receive
|
|
307
|
+
explicit string markers; dates and URLs use their guarded `toJSON` representations; Buffer uses
|
|
308
|
+
its `{ type, data }` representation; typed arrays become arrays; maps and sets become arrays; and
|
|
309
|
+
cycles become `"[Circular]"`. ANSI sequences are removed from keys as well as values. Errors retain
|
|
310
|
+
their kind, name, message, stack, canonical cause, validation issues, and independently readable
|
|
311
|
+
enumerable properties. Unreadable properties become `"[Unserializable]"`; a throwing `toJSON`
|
|
312
|
+
falls back to those properties. If an exotic value prevents normalization entirely, the line
|
|
313
|
+
keeps the original event `type` and adds `serializationError`, so downstream JSON-lines parsing
|
|
314
|
+
remains synchronized.
|
|
315
|
+
|
|
316
|
+
Pretty output uses a fixed presentation with semantic marks and a continuation bar. Trace, debug,
|
|
317
|
+
info, warning, error, and fatal records each have a distinct mark; step and success records have
|
|
318
|
+
their own marks as well, so meaning does not depend on color. Categories appear before log messages,
|
|
319
|
+
and every line of multiline messages, properties, help, and errors remains inside the same visual
|
|
320
|
+
block. All six log levels are displayed by default.
|
|
321
|
+
|
|
322
|
+
```text
|
|
323
|
+
◇ [deploy] Building web
|
|
324
|
+
│ files: 12
|
|
325
|
+
✔ [deploy] Deployed web
|
|
326
|
+
▲ [deploy] Cache was not cleared
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Pretty output uses Unicode symbols by default. Set `unicode: false` on `runMain` or `runCommand` for
|
|
330
|
+
ASCII marks and bars. Color is still resolved from the selected output mode: it requires pretty
|
|
331
|
+
output and a stdout TTY, and any non-empty `NO_COLOR` disables it. Unicode selection does not affect
|
|
332
|
+
JSON output. An invocation does not add automatic start or end messages; the renderer presents only
|
|
333
|
+
the semantic events that the command emits.
|
|
334
|
+
|
|
182
335
|
## Programmatic execution and errors
|
|
183
336
|
|
|
184
|
-
`runCommand(command, argv)` handles help and version output without exiting, throws errors
|
|
185
|
-
caller, and returns the selected `run` handler's result.
|
|
337
|
+
`runCommand(command, argv, options)` handles help and version output without exiting, throws errors
|
|
338
|
+
to its caller, and returns the selected `run` handler's result. Pass a `printer` in `options` to
|
|
339
|
+
receive all output produced by that invocation as structured events:
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
import { runCommand, type PrintEvent, type Printer } from "hacksh";
|
|
343
|
+
|
|
344
|
+
const events: PrintEvent[] = [];
|
|
345
|
+
const printer: Printer = {
|
|
346
|
+
async print(event) {
|
|
347
|
+
events.push(event);
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
await runCommand(main, ["--help"], { printer });
|
|
352
|
+
// events[0] is { type: "usage", usage, text, stream: "stdout" }
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
The current events are `usage`, `version`, `error`, `log`, and `prompt`. Usage events include the resolved
|
|
356
|
+
command's schema-free name, version, description, synopsis, arguments, options, and visible child
|
|
357
|
+
commands, plus rendered text and the intended `stdout` or `stderr` stream. Version events include
|
|
358
|
+
the version string. Error events contain a schema-free summary with an explicit `kind`, structured
|
|
359
|
+
validation issues, standard `Error` fields, custom enumerable properties, and recursively
|
|
360
|
+
canonical causes; log events contain the structured record described above. Prompt events contain
|
|
361
|
+
the prompt kind, status, current value or choices, placeholder, and validation message. Printer calls are serialized, may be asynchronous, and are
|
|
362
|
+
drained before `runCommand` or `runMain` completes or exits. A printer rejection rejects
|
|
363
|
+
`runCommand`.
|
|
364
|
+
|
|
365
|
+
Use `createPrettyPrinter({ color, unicode, stdout, stderr })` to reuse the built-in human-readable
|
|
366
|
+
renderer with custom writable targets, or `createJsonPrinter({ stdout, stderr })` to reuse the
|
|
367
|
+
built-in JSON-lines behavior. The pretty renderer has no public theme API; replacing the fixed
|
|
368
|
+
presentation requires a custom `Printer`. `consolePrinter` and `createStreamPrinter` remain the
|
|
369
|
+
undecorated compatibility adapters. `summarizeUsage(command)` returns the same canonical help
|
|
370
|
+
metadata carried by a usage event. `resolveOutputMode(...)` exposes the selection contract for
|
|
371
|
+
wrappers and the later presentation or prompting layers.
|
|
186
372
|
|
|
187
373
|
For parsing and usage rendering without execution, use the async composition APIs. `parseArgs`
|
|
188
374
|
parses exactly the supplied command definition and argument segment, returns its schema output only,
|
|
189
375
|
and throws `ZittyValidationError` on failure. It does not route subcommands, act on help or version
|
|
190
376
|
tokens, or bypass validation; callers that resolve commands themselves must pass the selected
|
|
191
377
|
command and its segment. `renderUsage` has no output side effects; `showUsage` sends that same text
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
378
|
+
through an explicit printer or the same automatic pretty/JSON selection used by command
|
|
379
|
+
invocations. Its `output`, `env`, `stdin`, `stdout`, `stderr`, and `unicode` options configure that
|
|
380
|
+
automatic path. The existing synchronous or asynchronous `write` option remains supported and
|
|
381
|
+
takes precedence over printer selection; an explicit `printer` also retains its existing behavior.
|
|
382
|
+
These functions are async so future command-resolution features can be added without changing
|
|
383
|
+
their return types.
|
|
195
384
|
|
|
196
385
|
```ts
|
|
197
|
-
import { parseArgs, renderUsage, showUsage } from "hacksh";
|
|
386
|
+
import { consolePrinter, parseArgs, renderUsage, showUsage } from "hacksh";
|
|
198
387
|
|
|
199
388
|
const args = await parseArgs(main, ["42", "--repo", "owner/repo"]);
|
|
200
389
|
// args is inferred from the schema as:
|
|
@@ -202,10 +391,8 @@ const args = await parseArgs(main, ["42", "--repo", "owner/repo"]);
|
|
|
202
391
|
|
|
203
392
|
const text: string = await renderUsage(main); // does not write output
|
|
204
393
|
await showUsage(main, {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
console.info(usage);
|
|
208
|
-
},
|
|
394
|
+
printer: consolePrinter,
|
|
395
|
+
stream: "stderr",
|
|
209
396
|
});
|
|
210
397
|
```
|
|
211
398
|
|
|
@@ -225,9 +412,11 @@ await mainEntry(); // uses the configured argv
|
|
|
225
412
|
await mainEntry([]); // an explicit empty invocation overrides it
|
|
226
413
|
```
|
|
227
414
|
|
|
228
|
-
`showUsage` customizes both ordinary help and the usage
|
|
229
|
-
|
|
230
|
-
|
|
415
|
+
The legacy `RunMainOptions.showUsage` callback still customizes both ordinary help and the usage
|
|
416
|
+
appended to validation or routing errors. Its supplied `write` function targets stdout for help and
|
|
417
|
+
stderr for errors by emitting usage events through the invocation's selected printer, and the
|
|
418
|
+
callback may be async. Pass `onError` to replace the entire default error display, including usage;
|
|
419
|
+
output written by this application callback remains its own responsibility:
|
|
231
420
|
|
|
232
421
|
```ts
|
|
233
422
|
await runMain(main, {
|
|
@@ -243,16 +432,18 @@ await runMain(main, {
|
|
|
243
432
|
|
|
244
433
|
Usage failures are `ZittyUsageError` instances. Argument failures are
|
|
245
434
|
`ZittyValidationError` instances whose `issues` identify CLI names such as `--repo` or `<PR>`.
|
|
435
|
+
Prompt failures are `HackshPromptError` instances with structured `reason` and `prompt` fields.
|
|
246
436
|
|
|
247
437
|
## Development
|
|
248
438
|
|
|
249
|
-
| Command
|
|
250
|
-
|
|
|
251
|
-
| `vp check`
|
|
252
|
-
| `vp test`
|
|
253
|
-
| `
|
|
254
|
-
| `vp
|
|
255
|
-
| `
|
|
439
|
+
| Command | Description |
|
|
440
|
+
| ---------------------- | ----------------------------------------------------- |
|
|
441
|
+
| `vp check` | Format, lint, and type check |
|
|
442
|
+
| `vp test` | Run tests |
|
|
443
|
+
| `pnpm test:prompt-pty` | Probe prompts in a real terminal |
|
|
444
|
+
| `vp pack` | Build `src/index.ts` into `dist` |
|
|
445
|
+
| `vp run ready` | Run check, test, and build |
|
|
446
|
+
| `pnpm test:packed` | Test the tarball with Node 22.18, host Node, and Deno |
|
|
256
447
|
|
|
257
448
|
The packed-consumer test must execute its Node consumer with exactly Node 22.18.0. Run pnpm itself
|
|
258
449
|
under that version, or supply an absolute executable path explicitly:
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,270 @@
|
|
|
1
1
|
import { $ZodIssue, $ZodObject, output } from "zod/v4/core";
|
|
2
|
+
//#region src/errors.d.ts
|
|
3
|
+
interface ZittyIssue {
|
|
4
|
+
arg: string;
|
|
5
|
+
message: string;
|
|
6
|
+
issue?: $ZodIssue;
|
|
7
|
+
}
|
|
8
|
+
declare class ZittyUsageError extends Error {
|
|
9
|
+
readonly command: AnyCommandDef;
|
|
10
|
+
constructor(message: string, command: AnyCommandDef, options?: ErrorOptions);
|
|
11
|
+
}
|
|
12
|
+
declare class ZittyValidationError extends ZittyUsageError {
|
|
13
|
+
readonly issues: ReadonlyArray<ZittyIssue>;
|
|
14
|
+
constructor(command: AnyCommandDef, issues: ReadonlyArray<ZittyIssue>);
|
|
15
|
+
}
|
|
16
|
+
type PromptKind = "select" | "confirm" | "text";
|
|
17
|
+
type HackshPromptErrorReason = "non-interactive" | "cancelled" | "eof" | "overlapping" | "invalid-options" | "input-error" | "printer-error";
|
|
18
|
+
interface PromptErrorDetails {
|
|
19
|
+
kind: PromptKind;
|
|
20
|
+
message: string;
|
|
21
|
+
choices?: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/** An input request that could not be completed safely. */
|
|
24
|
+
declare class HackshPromptError extends Error {
|
|
25
|
+
readonly reason: HackshPromptErrorReason;
|
|
26
|
+
readonly prompt: PromptErrorDetails;
|
|
27
|
+
constructor(reason: HackshPromptErrorReason, prompt: PromptErrorDetails, message: string, options?: ErrorOptions);
|
|
28
|
+
}
|
|
29
|
+
type HackshErrorKind = "error" | "prompt" | "usage" | "validation" | "thrown";
|
|
30
|
+
interface ValidationIssueSummary {
|
|
31
|
+
arg: string;
|
|
32
|
+
message: string;
|
|
33
|
+
code?: string;
|
|
34
|
+
path?: readonly PropertyKey[];
|
|
35
|
+
details?: Readonly<Record<string, unknown>>;
|
|
36
|
+
}
|
|
37
|
+
interface HackshErrorSummary {
|
|
38
|
+
kind: HackshErrorKind;
|
|
39
|
+
name: string;
|
|
40
|
+
message: string;
|
|
41
|
+
stack?: string;
|
|
42
|
+
cause?: unknown;
|
|
43
|
+
issues?: readonly ValidationIssueSummary[];
|
|
44
|
+
properties?: Readonly<Record<string, unknown>>;
|
|
45
|
+
value?: unknown;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/output.d.ts
|
|
49
|
+
interface OutputOptions {
|
|
50
|
+
output?: OutputPreference;
|
|
51
|
+
/** Use Unicode presentation symbols in pretty output. Defaults to true. */
|
|
52
|
+
unicode?: boolean;
|
|
53
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
54
|
+
stdin?: TerminalInput;
|
|
55
|
+
stdout?: TerminalOutput;
|
|
56
|
+
stderr?: OutputWriter;
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/usage.d.ts
|
|
60
|
+
interface UsageArgumentSummary {
|
|
61
|
+
name: string;
|
|
62
|
+
required: boolean;
|
|
63
|
+
variadic: boolean;
|
|
64
|
+
description?: string;
|
|
65
|
+
choices?: readonly string[];
|
|
66
|
+
defaultValue?: unknown;
|
|
67
|
+
}
|
|
68
|
+
interface UsageOptionSummary {
|
|
69
|
+
name: string;
|
|
70
|
+
flags: readonly string[];
|
|
71
|
+
takesValue: boolean;
|
|
72
|
+
valueName?: string;
|
|
73
|
+
required: boolean;
|
|
74
|
+
description?: string;
|
|
75
|
+
choices?: readonly string[];
|
|
76
|
+
defaultValue?: unknown;
|
|
77
|
+
negatedDescription?: string;
|
|
78
|
+
}
|
|
79
|
+
interface UsageCommandSummary {
|
|
80
|
+
name: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
}
|
|
83
|
+
/** A schema-free description of the useful help metadata for a command. */
|
|
84
|
+
interface UsageSummary {
|
|
85
|
+
name: string;
|
|
86
|
+
heading?: string;
|
|
87
|
+
version?: string;
|
|
88
|
+
description?: string;
|
|
89
|
+
synopsis: string;
|
|
90
|
+
arguments: readonly UsageArgumentSummary[];
|
|
91
|
+
options: readonly UsageOptionSummary[];
|
|
92
|
+
commands: readonly UsageCommandSummary[];
|
|
93
|
+
}
|
|
94
|
+
/** Build a serializable help summary without retaining command or schema objects. */
|
|
95
|
+
declare function summarizeUsage(command: AnyCommandDef): UsageSummary;
|
|
96
|
+
type UsageWriter = (text: string) => void | Promise<void>;
|
|
97
|
+
interface ShowUsageOptions extends OutputOptions {
|
|
98
|
+
write?: UsageWriter;
|
|
99
|
+
printer?: Printer;
|
|
100
|
+
stream?: PrintStream;
|
|
101
|
+
}
|
|
102
|
+
type UsageOutput = Required<Pick<ShowUsageOptions, "write">>;
|
|
103
|
+
type ShowUsageCallback = (command: AnyCommandDef, output: UsageOutput) => void | Promise<void>;
|
|
104
|
+
/** Generate usage text without writing to stdout or stderr. */
|
|
105
|
+
declare function renderUsage(command: AnyCommandDef): Promise<string>;
|
|
106
|
+
/** Generate and write usage text, awaiting asynchronous writers. */
|
|
107
|
+
declare function showUsage(command: AnyCommandDef, options?: ShowUsageOptions): Promise<void>;
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/printer.d.ts
|
|
110
|
+
type PrintStream = "stdout" | "stderr";
|
|
111
|
+
type OutputPreference = "auto" | "pretty" | "json";
|
|
112
|
+
type OutputFormat = Exclude<OutputPreference, "auto">;
|
|
113
|
+
interface OutputMode {
|
|
114
|
+
format: OutputFormat;
|
|
115
|
+
interactive: boolean;
|
|
116
|
+
color: boolean;
|
|
117
|
+
}
|
|
118
|
+
interface ResolveOutputModeOptions {
|
|
119
|
+
output?: OutputPreference;
|
|
120
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
121
|
+
inputIsTTY?: boolean;
|
|
122
|
+
outputIsTTY?: boolean;
|
|
123
|
+
}
|
|
124
|
+
/** Resolve output behavior once, before command routing or argument parsing. */
|
|
125
|
+
declare function resolveOutputMode(options?: ResolveOutputModeOptions): OutputMode;
|
|
126
|
+
interface UsagePrintEvent {
|
|
127
|
+
type: "usage";
|
|
128
|
+
usage: UsageSummary;
|
|
129
|
+
text: string;
|
|
130
|
+
stream: PrintStream;
|
|
131
|
+
}
|
|
132
|
+
interface VersionPrintEvent {
|
|
133
|
+
type: "version";
|
|
134
|
+
version: string;
|
|
135
|
+
}
|
|
136
|
+
interface ErrorPrintEvent {
|
|
137
|
+
type: "error";
|
|
138
|
+
error: HackshErrorSummary;
|
|
139
|
+
}
|
|
140
|
+
interface LogPrintEvent {
|
|
141
|
+
type: "log";
|
|
142
|
+
record: LogRecord;
|
|
143
|
+
}
|
|
144
|
+
interface PromptChoiceState {
|
|
145
|
+
value: string;
|
|
146
|
+
label: string;
|
|
147
|
+
hint?: string;
|
|
148
|
+
selected: boolean;
|
|
149
|
+
}
|
|
150
|
+
type PromptStatus = "active" | "error" | "submitted" | "closed";
|
|
151
|
+
interface PromptStateBase {
|
|
152
|
+
message: string;
|
|
153
|
+
status: PromptStatus;
|
|
154
|
+
error?: string;
|
|
155
|
+
}
|
|
156
|
+
interface SelectPromptState extends PromptStateBase {
|
|
157
|
+
kind: "select";
|
|
158
|
+
choices: readonly PromptChoiceState[];
|
|
159
|
+
value: string;
|
|
160
|
+
}
|
|
161
|
+
interface ConfirmPromptState extends PromptStateBase {
|
|
162
|
+
kind: "confirm";
|
|
163
|
+
value: boolean;
|
|
164
|
+
defaultValue?: boolean;
|
|
165
|
+
}
|
|
166
|
+
interface TextPromptState extends PromptStateBase {
|
|
167
|
+
kind: "text";
|
|
168
|
+
value: string;
|
|
169
|
+
placeholder?: string;
|
|
170
|
+
}
|
|
171
|
+
type PromptState = SelectPromptState | ConfirmPromptState | TextPromptState;
|
|
172
|
+
interface PromptPrintEvent {
|
|
173
|
+
type: "prompt";
|
|
174
|
+
prompt: PromptState;
|
|
175
|
+
}
|
|
176
|
+
/** A semantic, command- and schema-free output value emitted by hacksh. */
|
|
177
|
+
type PrintEvent = UsagePrintEvent | VersionPrintEvent | ErrorPrintEvent | LogPrintEvent | PromptPrintEvent;
|
|
178
|
+
/** Receives every output event produced by one command invocation. */
|
|
179
|
+
interface Printer {
|
|
180
|
+
print(event: PrintEvent): void | Promise<void>;
|
|
181
|
+
}
|
|
182
|
+
/** Undecorated console compatibility adapter; automatic output uses the selected format printer. */
|
|
183
|
+
declare const consolePrinter: Printer;
|
|
184
|
+
interface OutputWriter {
|
|
185
|
+
write(text: string): unknown;
|
|
186
|
+
}
|
|
187
|
+
interface TerminalInput {
|
|
188
|
+
readonly isTTY?: boolean;
|
|
189
|
+
readonly isRaw?: boolean;
|
|
190
|
+
readonly readableFlowing?: boolean | null;
|
|
191
|
+
setRawMode?(mode: boolean): unknown;
|
|
192
|
+
resume(): unknown;
|
|
193
|
+
pause(): unknown;
|
|
194
|
+
on(event: string, listener: (...args: never[]) => void): unknown;
|
|
195
|
+
removeListener(event: string, listener: (...args: never[]) => void): unknown;
|
|
196
|
+
}
|
|
197
|
+
interface TerminalOutput extends OutputWriter {
|
|
198
|
+
readonly isTTY?: boolean;
|
|
199
|
+
readonly columns?: number;
|
|
200
|
+
}
|
|
201
|
+
interface JsonPrinterOptions {
|
|
202
|
+
stdout?: OutputWriter;
|
|
203
|
+
stderr?: OutputWriter;
|
|
204
|
+
}
|
|
205
|
+
interface StreamPrinterOptions {
|
|
206
|
+
stdout: OutputWriter;
|
|
207
|
+
stderr: OutputWriter;
|
|
208
|
+
}
|
|
209
|
+
/** Create an undecorated stream-backed compatibility adapter. */
|
|
210
|
+
declare function createStreamPrinter(options: StreamPrinterOptions): Printer;
|
|
211
|
+
/** Create a one-semantic-event-per-line JSON printer. */
|
|
212
|
+
declare function createJsonPrinter(options?: JsonPrinterOptions): Printer;
|
|
213
|
+
//#endregion
|
|
214
|
+
//#region src/prompts.d.ts
|
|
215
|
+
interface SelectOption<T extends string> {
|
|
216
|
+
value: T;
|
|
217
|
+
label?: string;
|
|
218
|
+
hint?: string;
|
|
219
|
+
}
|
|
220
|
+
interface SelectOptions<T extends string> {
|
|
221
|
+
message: string;
|
|
222
|
+
options: readonly SelectOption<T>[];
|
|
223
|
+
initialValue?: T;
|
|
224
|
+
}
|
|
225
|
+
interface ConfirmOptions {
|
|
226
|
+
message: string;
|
|
227
|
+
initialValue?: boolean;
|
|
228
|
+
}
|
|
229
|
+
interface TextOptions {
|
|
230
|
+
message: string;
|
|
231
|
+
placeholder?: string;
|
|
232
|
+
validate?(value: string): string | undefined;
|
|
233
|
+
}
|
|
234
|
+
interface Prompter {
|
|
235
|
+
select<const T extends string>(options: SelectOptions<T>): Promise<T>;
|
|
236
|
+
confirm(options: ConfirmOptions): Promise<boolean>;
|
|
237
|
+
text(options: TextOptions): Promise<string>;
|
|
238
|
+
}
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/logger.d.ts
|
|
241
|
+
type LogLevel = "trace" | "debug" | "info" | "warning" | "error" | "fatal";
|
|
242
|
+
type LogKind = "message" | "step" | "success";
|
|
243
|
+
type LogProperties = Record<string, unknown>;
|
|
244
|
+
/** A structured message emitted by a command's logger. */
|
|
245
|
+
interface LogRecord {
|
|
246
|
+
level: LogLevel;
|
|
247
|
+
kind: LogKind;
|
|
248
|
+
category: readonly string[];
|
|
249
|
+
message: string;
|
|
250
|
+
rawMessage: string;
|
|
251
|
+
properties: LogProperties;
|
|
252
|
+
timestamp: number;
|
|
253
|
+
}
|
|
254
|
+
interface Logger extends Prompter {
|
|
255
|
+
readonly category: readonly string[];
|
|
256
|
+
trace(message: string, properties?: LogProperties): void;
|
|
257
|
+
debug(message: string, properties?: LogProperties): void;
|
|
258
|
+
info(message: string, properties?: LogProperties): void;
|
|
259
|
+
warn(message: string, properties?: LogProperties): void;
|
|
260
|
+
error(message: string | Error, properties?: LogProperties): void;
|
|
261
|
+
fatal(message: string | Error, properties?: LogProperties): void;
|
|
262
|
+
step(message: string, properties?: LogProperties): void;
|
|
263
|
+
success(message: string, properties?: LogProperties): void;
|
|
264
|
+
with(properties: LogProperties): Logger;
|
|
265
|
+
getChild(category: string): Logger;
|
|
266
|
+
}
|
|
267
|
+
//#endregion
|
|
2
268
|
//#region src/schema.d.ts
|
|
3
269
|
type ArgsSchema = $ZodObject;
|
|
4
270
|
type EmptyArgs = $ZodObject<{}>;
|
|
@@ -20,6 +286,7 @@ interface CommandContext<S extends ArgsSchema> {
|
|
|
20
286
|
rawArgs: string[];
|
|
21
287
|
passthrough: string[];
|
|
22
288
|
extraArgs: string[];
|
|
289
|
+
logger: Logger;
|
|
23
290
|
}
|
|
24
291
|
interface CommandDef<S extends ArgsSchema = EmptyArgs> {
|
|
25
292
|
name?: string;
|
|
@@ -34,48 +301,36 @@ interface CommandDef<S extends ArgsSchema = EmptyArgs> {
|
|
|
34
301
|
type AnyCommandDef = CommandDef<ArgsSchema>;
|
|
35
302
|
declare function defineCommand<S extends ArgsSchema = EmptyArgs>(def: CommandDef<S>): CommandDef<S>;
|
|
36
303
|
//#endregion
|
|
37
|
-
//#region src/errors.d.ts
|
|
38
|
-
interface ZittyIssue {
|
|
39
|
-
arg: string;
|
|
40
|
-
message: string;
|
|
41
|
-
issue?: $ZodIssue;
|
|
42
|
-
}
|
|
43
|
-
declare class ZittyUsageError extends Error {
|
|
44
|
-
readonly command: AnyCommandDef;
|
|
45
|
-
constructor(message: string, command: AnyCommandDef, options?: ErrorOptions);
|
|
46
|
-
}
|
|
47
|
-
declare class ZittyValidationError extends ZittyUsageError {
|
|
48
|
-
readonly issues: ReadonlyArray<ZittyIssue>;
|
|
49
|
-
constructor(command: AnyCommandDef, issues: ReadonlyArray<ZittyIssue>);
|
|
50
|
-
}
|
|
51
|
-
//#endregion
|
|
52
304
|
//#region src/parser.d.ts
|
|
53
305
|
/**
|
|
54
306
|
* Parse and validate one command segment without routing, builtin handling, or output.
|
|
55
307
|
*/
|
|
56
308
|
declare function parseArgs<S extends ArgsSchema>(command: CommandDef<S>, argv: string[]): Promise<output<S>>;
|
|
57
309
|
//#endregion
|
|
58
|
-
//#region src/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
310
|
+
//#region src/pretty.d.ts
|
|
311
|
+
interface PrettyPrinterOptions {
|
|
312
|
+
color: boolean;
|
|
313
|
+
unicode: boolean;
|
|
314
|
+
stdout?: TerminalOutput;
|
|
315
|
+
stderr?: OutputWriter;
|
|
62
316
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
/** Generate usage text without writing to stdout or stderr. */
|
|
66
|
-
declare function renderUsage(command: AnyCommandDef): Promise<string>;
|
|
67
|
-
/** Generate and write usage text, awaiting asynchronous writers. */
|
|
68
|
-
declare function showUsage(command: AnyCommandDef, options?: ShowUsageOptions): Promise<void>;
|
|
317
|
+
/** Create the fixed human-readable renderer used for pretty output. */
|
|
318
|
+
declare function createPrettyPrinter(options: PrettyPrinterOptions): Printer;
|
|
69
319
|
//#endregion
|
|
70
320
|
//#region src/run.d.ts
|
|
71
|
-
|
|
72
|
-
|
|
321
|
+
interface RunCommandOptions extends OutputOptions {
|
|
322
|
+
printer?: Printer;
|
|
323
|
+
showUsage?: ShowUsageCallback;
|
|
324
|
+
}
|
|
325
|
+
declare function runCommand<S extends ArgsSchema>(root: CommandDef<S>, argv: string[], options?: RunCommandOptions): Promise<unknown>;
|
|
326
|
+
interface RunMainOptions extends OutputOptions {
|
|
73
327
|
onError?: (error: unknown) => void | Promise<void>;
|
|
74
328
|
argv?: string[];
|
|
329
|
+
printer?: Printer;
|
|
75
330
|
showUsage?: ShowUsageCallback;
|
|
76
331
|
}
|
|
77
332
|
declare function runMain<S extends ArgsSchema>(command: CommandDef<S>, options?: RunMainOptions): Promise<void>;
|
|
78
333
|
declare function createMain<S extends ArgsSchema>(command: CommandDef<S>, options?: RunMainOptions): (argv?: string[]) => Promise<void>;
|
|
79
334
|
//#endregion
|
|
80
|
-
export { type ArgOptions, type ArgOptionsMap, type CommandContext, type CommandDef, type RunMainOptions, type ShowUsageCallback, type ShowUsageOptions, type UsageOutput, type UsageWriter, type ZittyIssue, ZittyUsageError, ZittyValidationError, createMain, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage };
|
|
335
|
+
export { type ArgOptions, type ArgOptionsMap, type CommandContext, type CommandDef, type ConfirmOptions, type ConfirmPromptState, type ErrorPrintEvent, type HackshErrorKind, type HackshErrorSummary, HackshPromptError, type HackshPromptErrorReason, type JsonPrinterOptions, type LogKind, type LogLevel, type LogPrintEvent, type LogProperties, type LogRecord, type Logger, type OutputFormat, type OutputMode, type OutputOptions, type OutputPreference, type OutputWriter, type PrettyPrinterOptions, type PrintEvent, type PrintStream, type Printer, type PromptChoiceState, type PromptErrorDetails, type PromptKind, type PromptPrintEvent, type PromptState, type PromptStatus, type Prompter, type ResolveOutputModeOptions, type RunCommandOptions, type RunMainOptions, type SelectOption, type SelectOptions, type SelectPromptState, type ShowUsageCallback, type ShowUsageOptions, type StreamPrinterOptions, type TerminalInput, type TerminalOutput, type TextOptions, type TextPromptState, type UsageArgumentSummary, type UsageCommandSummary, type UsageOptionSummary, type UsageOutput, type UsagePrintEvent, type UsageSummary, type UsageWriter, type ValidationIssueSummary, type VersionPrintEvent, type ZittyIssue, ZittyUsageError, ZittyValidationError, consolePrinter, createJsonPrinter, createMain, createPrettyPrinter, createStreamPrinter, defineCommand, parseArgs, renderUsage, resolveOutputMode, runCommand, runMain, showUsage, summarizeUsage };
|
|
81
336
|
//# sourceMappingURL=index.d.ts.map
|