import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; // The request layer, the notification store and the error boundary all log through lib/log.ts, so // log.ts must not reach any of them at runtime: the import would be a cycle, and the module that // logs a failure would load the one that failed. A type-only import is erased, so it does not count. // The comment in log.ts said this for a long time while nothing checked it. const LIB = new URL("./", import.meta.url); const ALLOWED = ["log.ts", "storage.ts", "version.ts"]; /** The app modules `file` imports at runtime (relative, not `import type`), as lib/ file names. */ function runtimeImports(file: string): string[] { const text = readFileSync(new URL(file, LIB), "utf-8"); return [...text.matchAll(/^import\s+(?!type\b)[^;]*?from\s+"(\.[^"]+)";/gms)].map( (m) => `${m[1]!.replace(/^\.\//, "")}.ts`, ); } describe("lib/log.ts", () => { it("reaches only the build stamp and the key registry at runtime", () => { const seen = new Set(); const queue = ["log.ts"]; while (queue.length) { const file = queue.pop()!; if (seen.has(file)) continue; seen.add(file); if (ALLOWED.includes(file)) queue.push(...runtimeImports(file)); } expect([...seen].sort()).toEqual([...ALLOWED].sort()); }); });