Skip to content

Commit 0abaf05

Browse files
committed
fix(cli): detect json mode for combined and =-form flags in error handler
`handleCliError` picked the error output format with a `--json`/`-j` substring-free includes check, missing `--json=...` and combined short flags like `-jy`/`-yj`. A parse-time ValidationError in those invocations printed the human-readable ANSI error instead of the structured VALIDATION_ERROR envelope. Broaden detection to a parse-free heuristic matching `--json`, `--json=...`, `-j`, and combined short flags containing `j`. Adds a `-jy` envelope test case.
1 parent 0d146b3 commit 0abaf05

2 files changed

Lines changed: 21 additions & 3 deletions

File tree

main.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,7 @@ function handleCliError(e: unknown): never {
5757
const context: GlobalContext = {
5858
debug: Deno.args.includes("--debug"),
5959
endpoint: "",
60-
json: Deno.args.includes("--json") || Deno.args.includes("-j")
61-
? true
62-
: undefined,
60+
json: Deno.args.some(isJsonModeArg) ? true : undefined,
6361
};
6462

6563
if (e instanceof ValidationError) {
@@ -72,6 +70,16 @@ function handleCliError(e: unknown): never {
7270
error(context, e instanceof Error ? e.message : String(e));
7371
}
7472

73+
/**
74+
* Best-effort `--json` detection without a parsed context, used by
75+
* `handleCliError` to pick the error output format when `parse()` itself throws.
76+
* Matches `--json`, `--json=...`, `-j`, and combined short flags like `-jy`.
77+
*/
78+
function isJsonModeArg(arg: string): boolean {
79+
return arg === "-j" || arg === "--json" || arg.startsWith("--json=") ||
80+
/^-[a-z]*j[a-z]*$/.test(arg);
81+
}
82+
7583
export function createSwitchCommand(
7684
handleApp: boolean,
7785
): Command<GlobalContext> {

tests/cli_contract.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ Deno.test("unknown flag with --json emits a USAGE envelope on stderr, clean stdo
4343
);
4444
});
4545

46+
Deno.test("combined short flag -jy is detected as JSON mode for the error envelope", async () => {
47+
// `-jy` bundles `-j` (json) and `-y` (non-interactive); a bad flag must still
48+
// surface the structured envelope on stderr, not the human-readable error.
49+
const res = await runCli(["-jy", "--does-not-exist"]);
50+
assertEquals(res.code, 2, `stderr: ${res.stderr}`);
51+
assertEquals(res.stdout.trim(), "", `stdout should be empty: ${res.stdout}`);
52+
const envelope = JSON.parse(res.stderr.trim().split("\n").pop()!);
53+
assertEquals(envelope.error.code, "VALIDATION_ERROR");
54+
});
55+
4656
Deno.test("--help exits 0", async () => {
4757
const res = await runCli(["--help"]);
4858
assertEquals(res.code, 0, `stderr: ${res.stderr}`);

0 commit comments

Comments
 (0)