7a0648088c
Merge PR #159 after Code Queue rebase and validation. Runner verified M3 cardinality, hardware-loop smoke, patch-panel runtime smoke, m3 readonly contract, and git diff check. This is source/config blocker removal only; it does not claim DEV-LIVE M3 pass.
54 lines
1.9 KiB
JavaScript
54 lines
1.9 KiB
JavaScript
#!/usr/bin/env node
|
|
import { createM3Topology } from "../../internal/patchpanel/fixture.mjs";
|
|
import {
|
|
createPatchPanelRuntime,
|
|
createPatchPanelRuntimeFromFile
|
|
} from "../../internal/patchpanel/runtime.mjs";
|
|
import { createHealth } from "../../internal/sim/model.mjs";
|
|
import { createJsonServer, listen, parsePort, readJson } from "../../internal/sim/http.mjs";
|
|
|
|
const port = parsePort(process.env.PORT, 7301);
|
|
const wiringConfigPath = process.env.HWLAB_WIRING_CONFIG_PATH;
|
|
const topology = createM3Topology();
|
|
const endpointMap = parseEndpointMap(process.env.HWLAB_PATCH_PANEL_ENDPOINT_MAP) ?? {
|
|
res_boxsimu_2: "http://hwlab-box-simu-2.hwlab-dev.svc.cluster.local:7201"
|
|
};
|
|
const runtime = wiringConfigPath
|
|
? await createPatchPanelRuntimeFromFile({ path: wiringConfigPath })
|
|
: createPatchPanelRuntime({
|
|
wiringConfig: topology.wiringConfig,
|
|
endpointMap,
|
|
configSource: "internal:m3-topology"
|
|
});
|
|
|
|
const routes = new Map();
|
|
|
|
routes.set("GET /health/live", () =>
|
|
createHealth({ serviceId: "hwlab-patch-panel", name: "hwlab-patch-panel" })
|
|
);
|
|
routes.set("GET /status", () => runtime.status());
|
|
routes.set("GET /diagnostics", () => runtime.diagnostics());
|
|
routes.set("GET /wiring", () => runtime.wiringConfig);
|
|
routes.set("POST /wiring/apply", async ({ req }) => runtime.applyConfig(await readJson(req)));
|
|
routes.set("POST /wiring/reload", async ({ req }) => {
|
|
const body = await readJson(req);
|
|
const path = body.path ?? wiringConfigPath;
|
|
if (!path) {
|
|
throw new Error("wiring reload requires body.path or HWLAB_WIRING_CONFIG_PATH");
|
|
}
|
|
return runtime.reloadFromFile(path);
|
|
});
|
|
routes.set("POST /signals/route", async ({ req }) => runtime.routeSignal(await readJson(req)));
|
|
routes.set("POST /sync/tick", async ({ req }) => runtime.tick(await readJson(req)));
|
|
|
|
listen(createJsonServer({ routes }), port);
|
|
|
|
function parseEndpointMap(value) {
|
|
const source = String(value ?? "").trim();
|
|
if (!source) {
|
|
return null;
|
|
}
|
|
|
|
return JSON.parse(source);
|
|
}
|