/* Node-only loader for derived-prices.generated.json (RFC-0767). Reads the file from process.cwd()/src/derived-prices.generated.json and returns null on ENOENT. NOT exported from the semantic barrel — uses node:fs and would pollute client bundles. Does not parse or validate the JSON shape — just reads and JSON.parse. Does not cache — callers are responsible for calling once and passing the result. RFC-0767: relocated loadDerivedPrices from packages/ui to packages/share to break circular dependency. Node-only subpath export. RFC-1074: return null for empty {} content — semantically equivalent to "no derived prices". RFC-1137: explicit site root for derived-prices loaders (ADR-0089 instance) */ import { readFileSync } from "node:fs"; import { join } from "node:path"; import type { DerivedPriceEntry } from "../../semantic/price-marker-resolver.ts"; // RFC-1137 / ADR-0089 (DNA-105): cwd is required — callers must pass the // site/workpiece root explicitly. The old process.cwd() default resolved // against the werkstatt repo root inside kernel pipeline steps. export function loadDerivedPrices(cwd: string): Record | null { const filePath = join(cwd, "src", "derived-prices.generated.json"); let raw: string; try { raw = readFileSync(filePath, "utf-8"); } catch (err: unknown) { if (err instanceof Error && (err as NodeJS.ErrnoException).code === "ENOENT") { console.warn( `[derived-prices] ${filePath} not found — currency-aware price variants will not render. ` + `Run: pnpm exec werkstatt run derived-prices.materialize --site `, ); return null; } throw err; } const parsed = JSON.parse(raw) as Record; return Object.keys(parsed).length > 0 ? parsed : null; }