-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathresolve.ts
More file actions
41 lines (38 loc) · 1.73 KB
/
Copy pathresolve.ts
File metadata and controls
41 lines (38 loc) · 1.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import type { AnyCommand } from "bailian-cli-core";
import { type UsageError } from "bailian-cli-core";
import type { CommandRegistry } from "./registry.ts";
import { parsePath } from "./args.ts";
/**
* What an invocation resolves to — "what to do" expressed as data, not control
* flow. A single pure function (`resolve`) produces one of these; `createCli`'s
* dispatch switches on it. No scattered `argv.includes(...)` + `process.exit`.
* - version: print the version and stop.
* - help: print help for `path` (root [] / a group / an explicit --help). Terminal.
* - run: execute `command`; `rest` is the flag region for parseFlags.
* - usageError: the path doesn't exist (or has unexpected args); render and stop.
*/
export type Resolution =
| { kind: "version" }
| { kind: "help"; path: string[] }
| { kind: "run"; path: string[]; command: AnyCommand; rest: string[] }
| { kind: "usageError"; error: UsageError };
/**
* Classify argv into a {@link Resolution}. Pure over (argv, registry): one
* `parsePath` scan for the command path + flag region, one `registry.locate`
* for the routing decision. Never throws. Trivially unit-testable.
*/
export function resolve(argv: string[], registry: CommandRegistry): Resolution {
const { path, rest, hasHelpFlag, hasVersionFlag } = parsePath(argv);
if (hasVersionFlag) return { kind: "version" };
const target = registry.locate(path);
switch (target.kind) {
case "leaf":
return hasHelpFlag
? { kind: "help", path: target.matched }
: { kind: "run", path: target.matched, command: target.command, rest };
case "group":
return { kind: "help", path: target.matched };
case "unknown":
return { kind: "usageError", error: target.error };
}
}