refactor(cli): split tjwater cli modules
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import { CliError } from "./core/errors.js";
|
||||
import { handlers } from "./handlers.js";
|
||||
import { helpPayload } from "./help/index.js";
|
||||
import { failure, json } from "./core/output.js";
|
||||
import type { RuntimeContext } from "./core/types.js";
|
||||
|
||||
export async function dispatch(ctx: RuntimeContext | null, argv: string[]): Promise<void> {
|
||||
if (argv.length === 0 || argv.includes("--help")) {
|
||||
process.stdout.write("Usage: tjwater-cli [OPTIONS] COMMAND [ARGS]...\n\nStructured JSON:\n tjwater-cli help\n");
|
||||
return;
|
||||
}
|
||||
if (argv[0] === "help") {
|
||||
const payload = helpPayload(argv.slice(1));
|
||||
if (!payload) {
|
||||
failure({
|
||||
summary: "未找到命令",
|
||||
code: "COMMAND_NOT_FOUND",
|
||||
message: `unknown command path: ${argv.slice(1).join(" ")}`,
|
||||
retryable: false,
|
||||
data: { usage: "tjwater-cli help <command-path>", examples: ["tjwater-cli help simulation run", "tjwater-cli simulation help"] },
|
||||
nextCommands: ["tjwater-cli help", "tjwater-cli help simulation"],
|
||||
});
|
||||
return;
|
||||
}
|
||||
json(payload);
|
||||
return;
|
||||
}
|
||||
const matched = matchCommand(argv);
|
||||
if (!matched) throw new CliError("未找到命令", "COMMAND_NOT_FOUND", `No such command: ${argv.join(" ")}`, 2, false, { usage: "tjwater-cli help" }, ["tjwater-cli help"]);
|
||||
const handler = handlers[matched.path];
|
||||
if (!handler) throw new CliError("未找到命令", "COMMAND_NOT_FOUND", `No such command: ${argv.join(" ")}`, 2, false, { usage: "tjwater-cli help" }, ["tjwater-cli help"]);
|
||||
if (!ctx && matched.path !== "__noop") throw new CliError("CLI 参数错误", "RUNTIME_REQUIRED", "runtime context is required for command execution", 2);
|
||||
await handler(ctx!, matched.args);
|
||||
}
|
||||
|
||||
function matchCommand(argv: string[]): { path: string; args: string[] } | null {
|
||||
const paths = Object.keys(handlers).sort((a, b) => b.split(" ").length - a.split(" ").length);
|
||||
for (const path of paths) {
|
||||
const parts = path.split(" ");
|
||||
if (parts.every((part, index) => argv[index] === part)) return { path, args: argv.slice(parts.length) };
|
||||
}
|
||||
if (argv.at(-1) === "help") {
|
||||
const payload = helpPayload(argv.slice(0, -1));
|
||||
if (payload) {
|
||||
json(payload);
|
||||
return { path: "__noop", args: [] };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user