/** * Pure, disk-read helpers for the standalone Studio Vite middleware. * * `readManifest` / `foldTopology` are the Studio-side manifest readers (raw * string + parse). The telemetry-run readers are re-exported from `@nwire/scan` * (the shared home — see the re-export below), so the CLI dev host and Studio * run identical code without either package importing the other. * * All functions are synchronous, have no side effects beyond filesystem reads, * and accept an explicit `cwd` so callers can target any project root without * touching process state. */ import { existsSync, readFileSync } from "node:fs"; import { resolve } from "node:path"; // Telemetry-run readers live in `@nwire/scan` so the standalone Studio Vite // middleware and the CLI dev host share one implementation (both depend on // scan; neither imports the other). Re-exported here so the local callers keep // a single `nwire-read` import. export { listTelemetryRuns, readTelemetryRun, type TelemetryRunMeta } from "@nwire/scan"; // ── readManifest ───────────────────────────────────────────────────────────── /** * Read `.nwire/manifest.json` from `cwd` and return the raw JSON string. * * Returns `null` when the file does not exist or cannot be read. Callers that * need the parsed object can `JSON.parse` the result; returning the raw string * lets the Vite middleware forward bytes without a round-trip through JSON. */ export function readManifest(cwd: string): string | null { const manifestPath = resolve(cwd, ".nwire", "manifest.json"); if (!existsSync(manifestPath)) return null; try { return readFileSync(manifestPath, "utf8"); } catch { return null; } } // ── foldTopology ───────────────────────────────────────────────────────────── /** * Parse the manifest JSON from disk and (in future increments) fold in live * runtime topology data from the running app. * * Today: parses and returns the disk manifest as-is. The "fold" step — merging * live handler registrations from a running runtime so the manifest stays * accurate during HMR — is reserved for a future increment. The function * signature is sealed now so both callers can adopt it without a breaking * change later. * * Returns `null` when no manifest is present or the file is not valid JSON. */ export function foldTopology(manifest: string | null, _cwd: string): unknown | null { if (manifest === null) return null; try { return JSON.parse(manifest) as unknown; } catch { return null; } }