import { readdirSync, readFileSync, statSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, it } from "@suaveplan/testing/runner"; const SRC = new URL("../src/", import.meta.url).pathname; function walk(dir: string, acc: string[] = []): string[] { for (const name of readdirSync(dir)) { const p = join(dir, name); const st = statSync(p); if (st.isDirectory()) walk(p, acc); else if (/\.ts$/.test(p) && !/\.test\.ts$/.test(p)) acc.push(p); } return acc; } const FORBIDDEN_BROWSER_GLOBALS = [ "AudioContext", "AnalyserNode", "AudioBuffer", ]; const FORBIDDEN_NODE_IMPORTS = ["node:fs", "node:path"]; describe("purity — universal guard", () => { it("source references no platform-only globals", { timeout: 5000 }, () => { const files = walk(SRC); const violations: string[] = []; for (const f of files) { const text = readFileSync(f, "utf8"); for (const g of FORBIDDEN_BROWSER_GLOBALS) { const re = new RegExp(`\\b${g}\\b`); if (re.test(text)) violations.push(`${f}: contains ${g}`); } for (const g of FORBIDDEN_NODE_IMPORTS) { if (text.includes(g)) violations.push(`${f}: contains ${g}`); } } expect(violations).toEqual([]); }); it("dependency set is limited to the declared workspace deps and zod", { timeout: 5000, }, () => { const pkg = JSON.parse( readFileSync(new URL("../package.json", import.meta.url), "utf8") ) as { dependencies: Record; }; const allowed = new Set([ "@suaveplan/audio-core", "@suaveplan/error", "@suaveplan/types", "@opentelemetry/api", "tslib", "zod", ]); for (const dep of Object.keys(pkg.dependencies)) { expect(allowed.has(dep)).toBe(true); } }); it("importing the package mutates no global state", { timeout: 5000, }, async () => { // Import once to settle any one-shot runner bookkeeping, then verify // a second import adds no new keys of its own. await import("../src/index.js"); const before = new Set(Object.keys(globalThis)); await import("../src/index.js"); const added: string[] = []; for (const k of Object.keys(globalThis)) { if (!before.has(k)) added.push(k); } expect(added).toEqual([]); }); });