#!/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); }