@hypit/hypit 0.1.7 → 0.1.8
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/package.json +1 -1
- package/packages/cli/README.md +8 -0
- package/packages/cli/src/arguments.ts +12 -1
- package/packages/cli/src/commands/execution.ts +7 -1
- package/packages/cli/src/commands/results.ts +6 -2
- package/packages/cli/src/main.ts +2 -1
- package/packages/cli/src/output.ts +5 -0
- package/packages/cli/src/usage-error.ts +8 -0
package/package.json
CHANGED
package/packages/cli/README.md
CHANGED
|
@@ -14,6 +14,11 @@ invent targets, candidates or Provider choices.
|
|
|
14
14
|
Human and JSON output answer the same command-specific question. `--json` changes encoding;
|
|
15
15
|
`--verbose` expands scope. Compiler, Runtime and Repository objects are not default reports.
|
|
16
16
|
|
|
17
|
+
Argument errors use `CLI_USAGE` and point to the relevant `hypit help <command>`; JSON retains that
|
|
18
|
+
command in `error.help`. Unknown help topics fail explicitly. Runtime and execution failures retain
|
|
19
|
+
their own diagnostics and optional `--debug` trace. Result pagination changes only the `--before`
|
|
20
|
+
cursor on the current query, preserving its project, Source filter and other options.
|
|
21
|
+
|
|
17
22
|
| Command | Default scope | Explicit detail |
|
|
18
23
|
| --- | --- | --- |
|
|
19
24
|
| `check` | Validation, targets and counts | `--verbose`: exported names/types and historical references |
|
|
@@ -113,6 +118,9 @@ flow.
|
|
|
113
118
|
execution phases and Provider diagnostics. It reads a finished Result directly, without opening the
|
|
114
119
|
Runtime; an active Build is read through Runtime control. The selected Repository handles file access.
|
|
115
120
|
`--lines` limits the tail and the report states the omitted count; JSON carries records plus that count.
|
|
121
|
+
An unavailable log reports `source: "unavailable"` and exits unsuccessfully; a readable log with zero
|
|
122
|
+
records is a successful empty result. The human report distinguishes a finished Result with no log
|
|
123
|
+
from a lookup that still needs the Build's Runtime or correct project selection.
|
|
116
124
|
`inspect` exposes an available log separately from authored Outputs. `hypit runtime logs` reads the
|
|
117
125
|
Worker process log instead, for Runtime startup or process-level failures.
|
|
118
126
|
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
RuntimeSelectionCommand,
|
|
14
14
|
} from "./command.js";
|
|
15
15
|
import type { CliColorMode, CliOutputOptions } from "./output.js";
|
|
16
|
+
import { CliUsageError } from "./usage-error.js";
|
|
16
17
|
|
|
17
18
|
type RawOptions = {
|
|
18
19
|
readonly presentation: CliOutputOptions;
|
|
@@ -48,6 +49,15 @@ type RawOptions = {
|
|
|
48
49
|
const commonOptions = ["--json", "--color", "--no-color", "--verbose", "--debug"] as const;
|
|
49
50
|
|
|
50
51
|
export function parseCommand(argv: readonly string[]): CliCommand {
|
|
52
|
+
try { return parseArguments(argv); }
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof CliUsageError) throw error;
|
|
55
|
+
throw new CliUsageError(error instanceof Error ? error.message : String(error),
|
|
56
|
+
argv[0] === undefined ? "hypit help" : `hypit help ${argv[0]}`, { cause: error });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function parseArguments(argv: readonly string[]): CliCommand {
|
|
51
61
|
const [command, ...tail] = argv;
|
|
52
62
|
switch (command) {
|
|
53
63
|
case "check": {
|
|
@@ -246,7 +256,8 @@ export function parseCommand(argv: readonly string[]): CliCommand {
|
|
|
246
256
|
...optionalPackageRoot(options),
|
|
247
257
|
};
|
|
248
258
|
}
|
|
249
|
-
default: throw new
|
|
259
|
+
default: throw new CliUsageError(command === undefined ? "A command is required"
|
|
260
|
+
: `Unknown command ${JSON.stringify(command)}`, "hypit help");
|
|
250
261
|
}
|
|
251
262
|
}
|
|
252
263
|
|
|
@@ -83,13 +83,19 @@ export async function runExecutionCommand(input: {
|
|
|
83
83
|
const records = view?.records ?? [];
|
|
84
84
|
const omitted = (view?.total ?? 0) - records.length;
|
|
85
85
|
write({ format: "hypit.cli-logs@1", build: args.build, source, records, omittedRecords: omitted },
|
|
86
|
-
view === undefined ? "
|
|
86
|
+
view === undefined ? "Execution log unavailable" : "Build execution log", view === undefined ? "warning" : "info",
|
|
87
87
|
[["Build", args.build], ["Source", source]], [
|
|
88
|
+
...(view !== undefined ? [] : [finished
|
|
89
|
+
? "This Result has no saved execution log."
|
|
90
|
+
: activeProfile === undefined
|
|
91
|
+
? "No saved log found in this project. Select the Build's Runtime with --runtime <profile> to check active execution."
|
|
92
|
+
: "No log found in this project's Results or the selected Runtime. Check the Build id and project selection."]),
|
|
88
93
|
...(omitted > 0 ? [`Showing last ${records.length} records; ${omitted} earlier records omitted. Use --lines to read more.`] : []),
|
|
89
94
|
...records.map((record) => `${new Date(record.time).toISOString()} ${record.endpoint} ${record.command} ${
|
|
90
95
|
record.kind === "phase" ? record.phase : record.kind === "diagnostic" || record.kind === "failed"
|
|
91
96
|
? `${record.kind}: ${record.message}` : record.kind}`),
|
|
92
97
|
]);
|
|
98
|
+
if (view === undefined) io.setExitCode?.(1);
|
|
93
99
|
return;
|
|
94
100
|
}
|
|
95
101
|
|
|
@@ -54,7 +54,9 @@ export async function runProjectResultCommand(input: {
|
|
|
54
54
|
const label = item.title === undefined ? item.id : `${item.title} · ${item.id}`;
|
|
55
55
|
const run = item.run === undefined ? "" : ` · ${item.run}`;
|
|
56
56
|
return `${label}: ${item.outcome} · ${new Date(item.createdAt).toLocaleString()}${run} · ${item.targetCount} target${item.targetCount === 1 ? "" : "s"}`;
|
|
57
|
-
}).concat(page.next === undefined ? [] : [
|
|
57
|
+
}).concat(page.next === undefined ? [] : [
|
|
58
|
+
`Older Repeat this command with --before ${page.next}, keeping the other options.`,
|
|
59
|
+
]));
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -89,7 +91,9 @@ export async function runProjectResultCommand(input: {
|
|
|
89
91
|
const label = item.title === undefined ? item.build : `${item.title} · ${item.build}`;
|
|
90
92
|
return `${label}: ${item.outcome} · ${new Date(item.createdAt).toLocaleString()}`
|
|
91
93
|
+ (args.presentation.verbose ? ` · ${item.output.kind} · ${item.output.type}` : "");
|
|
92
|
-
}).concat(page.next === undefined ? [] : [
|
|
94
|
+
}).concat(page.next === undefined ? [] : [
|
|
95
|
+
`Older Repeat this command with --before ${page.next}, keeping the other options.`,
|
|
96
|
+
]));
|
|
93
97
|
return;
|
|
94
98
|
}
|
|
95
99
|
|
package/packages/cli/src/main.ts
CHANGED
|
@@ -62,7 +62,8 @@ export async function runCli(
|
|
|
62
62
|
distribution: CliDistribution,
|
|
63
63
|
): Promise<void> {
|
|
64
64
|
if (argv.length === 0 || argv[0] === "help" || argv.includes("--help")) {
|
|
65
|
-
const topic = argv[0] === "help" ? argv[1] : argv
|
|
65
|
+
const topic = argv[0] === "help" ? argv[1] : argv[0] === "--help" ? undefined
|
|
66
|
+
: argv.includes("--help") ? argv[0] : undefined;
|
|
66
67
|
writeCliHelp(io, topic);
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
@@ -3,6 +3,7 @@ import { relative, resolve } from "node:path";
|
|
|
3
3
|
import type { CanonicalValue } from "@hypit/protocol";
|
|
4
4
|
|
|
5
5
|
import type { OperationalMachineView } from "./machine-view.js";
|
|
6
|
+
import { CliUsageError } from "./usage-error.js";
|
|
6
7
|
|
|
7
8
|
export type CliTerminal = {
|
|
8
9
|
readonly isTTY: boolean;
|
|
@@ -986,6 +987,7 @@ export function writeCliHelp(io: CliIo, topic?: string): void {
|
|
|
986
987
|
io.write(`${selected.join("\n")}\n`);
|
|
987
988
|
return;
|
|
988
989
|
}
|
|
990
|
+
throw new CliUsageError(`Unknown help topic ${JSON.stringify(topic)}`, "hypit help");
|
|
989
991
|
}
|
|
990
992
|
io.write([
|
|
991
993
|
colors.accent(colors.strong("Hypit")),
|
|
@@ -1044,6 +1046,7 @@ export function renderCliError(error: unknown, options: {
|
|
|
1044
1046
|
error: {
|
|
1045
1047
|
code,
|
|
1046
1048
|
message: source.message,
|
|
1049
|
+
...(source instanceof CliUsageError ? { help: source.help } : {}),
|
|
1047
1050
|
...(options.debug && trace !== undefined && trace.length > 0 ? { trace } : {}),
|
|
1048
1051
|
},
|
|
1049
1052
|
}, null, 2)}\n`;
|
|
@@ -1058,6 +1061,8 @@ export function renderCliError(error: unknown, options: {
|
|
|
1058
1061
|
];
|
|
1059
1062
|
if (options.debug && trace !== undefined && trace.length > 0) {
|
|
1060
1063
|
lines.push("", colors.dim(trace));
|
|
1064
|
+
} else if (source instanceof CliUsageError) {
|
|
1065
|
+
lines.push("", `Usage ${source.help}`);
|
|
1061
1066
|
} else {
|
|
1062
1067
|
lines.push("", colors.dim("Run with --debug to include the internal stack trace."));
|
|
1063
1068
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Argument errors point to public usage rather than an internal stack trace. */
|
|
2
|
+
export class CliUsageError extends Error {
|
|
3
|
+
readonly code = "CLI_USAGE";
|
|
4
|
+
constructor(message: string, readonly help: string, options?: ErrorOptions) {
|
|
5
|
+
super(message, options);
|
|
6
|
+
this.name = "CliUsageError";
|
|
7
|
+
}
|
|
8
|
+
}
|