Files
pikasTech-HWLAB/tools/hwlab-cli/lib/cli.mjs
T
2026-05-21 14:45:20 +00:00

193 lines
5.2 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
import { DEV_ENDPOINT } from "../../../internal/protocol/index.mjs";
const DEFAULT_PROJECTS = [
{
projectId: "proj_mvp-l6",
name: "HWLAB L6 MVP",
status: "active",
environment: "dev",
updatedAt: "2026-05-21T00:00:00.000Z"
},
{
projectId: "proj_cloud-web",
name: "Cloud Web Skeleton",
status: "active",
environment: "dev",
updatedAt: "2026-05-20T12:00:00.000Z"
}
];
function loadRuntimeFixture(cwd) {
const fixturePath = path.resolve(cwd, "fixtures/mvp/runtime.json");
if (!fs.existsSync(fixturePath)) {
return null;
}
const raw = fs.readFileSync(fixturePath, "utf8");
return JSON.parse(raw);
}
function resolveRuntime(cwd) {
const fixture = loadRuntimeFixture(cwd);
if (fixture) {
return fixture;
}
return {
endpoints: { dev: DEV_ENDPOINT },
projects: DEFAULT_PROJECTS,
mvpSteps: [
"browser/CLI/gateway",
"master hwlab-edge-proxy",
"frp",
"D601 hwlab-dev/hwlab-router",
"cloud-web/cloud-api",
"hardware trusted closed loop",
"agent automation closed loop",
"evidence record",
"worker cleanup"
],
loops: [
{ name: "hardware trusted closed loop" },
{ name: "agent automation closed loop" }
],
evidence: [],
cleanup: []
};
}
function formatJson(value) {
return JSON.stringify(value, null, 2);
}
function writeLine(stream, line = "") {
stream.write(`${line}\n`);
}
function writeProjectList(runtime, stdout) {
writeLine(stdout, "hwlab-cli project list");
writeLine(stdout, `endpoint: ${runtime.endpoints?.dev ?? DEV_ENDPOINT}`);
for (const project of runtime.projects ?? []) {
writeLine(
stdout,
`${project.projectId} | ${project.name} | ${project.status} | ${project.environment} | ${project.updatedAt}`
);
}
}
function writeHealth(runtime, stdout) {
writeLine(stdout, "hwlab-cli health");
writeLine(stdout, "status: ok");
writeLine(stdout, `environment: dev`);
writeLine(stdout, `endpoint: ${runtime.endpoints?.dev ?? DEV_ENDPOINT}`);
writeLine(stdout, `projects: ${(runtime.projects ?? []).length}`);
}
function writeDryRun(runtime, stdout) {
writeLine(stdout, "hwlab-cli test e2e --env dev --mvp --dry-run");
writeLine(stdout, `endpoint: ${runtime.endpoints?.dev ?? DEV_ENDPOINT}`);
writeLine(stdout, "mvp route:");
writeLine(
stdout,
` ${runtime.serviceRoute?.join(" -> ") ?? "browser/CLI/gateway -> master hwlab-edge-proxy -> frp -> D601 hwlab-dev/hwlab-router -> cloud-web/cloud-api"}`
);
for (const step of runtime.mvpSteps ?? []) {
writeLine(stdout, `- ${step}`);
}
writeLine(stdout, "closed loops:");
for (const loop of runtime.loops ?? []) {
writeLine(stdout, `- ${loop.name}${loop.description ? `: ${loop.description}` : ""}`);
}
writeLine(stdout, "evidence record:");
for (const evidence of runtime.evidence ?? []) {
writeLine(
stdout,
`- ${evidence.evidenceId} | ${evidence.kind} | ${evidence.serviceId} | ${evidence.uri}`
);
}
writeLine(stdout, "worker cleanup:");
for (const step of runtime.cleanup ?? []) {
writeLine(stdout, `- ${step}`);
}
writeLine(stdout, "dry-run only: no DEV/PROD changes were made");
}
function writeHelp(stdout) {
writeLine(stdout, "hwlab-cli");
writeLine(stdout, "commands:");
writeLine(stdout, " health");
writeLine(stdout, " project list");
writeLine(stdout, " test e2e --env dev --mvp --dry-run");
}
function parseArgs(args) {
const flags = new Set();
const options = new Map();
const rest = [];
for (let index = 0; index < args.length; index += 1) {
const arg = args[index];
if (arg.startsWith("--")) {
flags.add(arg);
const next = args[index + 1];
if (next && !next.startsWith("--")) {
options.set(arg, next);
index += 1;
}
} else {
rest.push(arg);
}
}
return { flags, options, rest };
}
export async function runCli(argv, io) {
const stdout = io.stdout ?? process.stdout;
const stderr = io.stderr ?? process.stderr;
const runtime = resolveRuntime(io.cwd ?? process.cwd());
const [command = "help", subcommand, ...rest] = argv;
const { flags, options } = parseArgs(rest);
if (command === "health") {
writeHealth(runtime, stdout);
return 0;
}
if (command === "project" && subcommand === "list") {
writeProjectList(runtime, stdout);
return 0;
}
if (command === "test" && subcommand === "e2e") {
const env = options.get("--env") ?? null;
const isDryRun = flags.has("--dry-run");
const isMvp = flags.has("--mvp");
if (env !== "dev") {
writeLine(stderr, "only --env dev is supported in the skeleton");
return 1;
}
if (!isMvp || !isDryRun) {
writeLine(stderr, "use --mvp --dry-run for the skeleton");
return 1;
}
writeDryRun(runtime, stdout);
return 0;
}
if (command === "project" && !subcommand) {
writeLine(stderr, "usage: hwlab-cli project list");
return 1;
}
if (command === "test" && !subcommand) {
writeLine(stderr, "usage: hwlab-cli test e2e --env dev --mvp --dry-run");
return 1;
}
writeHelp(stdout);
return 0;
}
export function formatRuntime(runtime) {
return formatJson(runtime);
}