Something went wrong. Try again.
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798import { describe, expect, it } from "vitest";import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";import { tmpdir } from "node:os";import { join, resolve } from "node:path";import { buildAllowlist } from "../../runner/checkAllowlist";import { bundleEngineHost, listBuiltinChecks } from "../../tools/extensionHost";
/** * P8-6, P8-11: the code an extension carries (parser, engine, include expansion, command handlers, the debugger adapter and the checks a person approved) has no * Node dependency. The browser bundle fails to build if one comes back, and a check that has not been approved is never compiled in. */
const root = resolve(__dirname, "../..");
function checksDir(files: Record<string, string>, allowlist: "build" | "none" | Record<string, string> = "build") { const dir = mkdtempSync(join(tmpdir(), "aite-checks-")); const checks = join(dir, "scripts/checks"); mkdirSync(checks, { recursive: true }); for (const [n, t] of Object.entries(files)) writeFileSync(join(checks, n), t); if (allowlist === "build") writeFileSync(join(checks, "allowlist.json"), buildAllowlist(checks)); else if (allowlist !== "none") writeFileSync(join(checks, "allowlist.json"), JSON.stringify({ version: 1, checks: allowlist })); return { checks, cleanup: () => rmSync(dir, { recursive: true, force: true }) };}
describe("the engine host bundle", () => { it("builds for the browser with no node: import and no Node global, with the project's own checks inside", async () => { const code = await bundleEngineHost(root); expect(code.length).toBeGreaterThan(10_000); expect(code).not.toMatch(/node:[a-z]+/); expect(code).not.toMatch(/require\(["'](fs|path|os|child_process|net|http)["']\)/); expect(code).toContain("balance-at-least"); expect(code).toContain("session-check"); }); it("is a single script that registers the host entry point", async () => { expect(await bundleEngineHost(root)).toContain("aiteHost"); }); it("lists the built-in checks by name", () => { expect(listBuiltinChecks(join(root, "scripts/checks"))).toEqual(["balance-at-least", "session-check"]); });});
describe("which checks are compiled in", () => { it("only the ones on the allowlist: a file nobody listed is not in the bundle and not in the names", async () => { const d = checksDir({ "listed.ts": "export default () => undefined;" }); try { writeFileSync(join(d.checks, "sneaky.ts"), "export default () => ({ ok: false, message: 'SNEAKY-MARKER' });"); expect(listBuiltinChecks(d.checks)).toEqual(["listed"]); const code = await bundleEngineHost(root, { checksDir: d.checks }); expect(code).not.toContain("SNEAKY-MARKER"); } finally { d.cleanup(); } }); it("refuses to build when a listed check changed since it was approved", async () => { const d = checksDir({ "c.ts": "export default () => undefined;" }); try { writeFileSync(join(d.checks, "c.ts"), "export default () => ({ ok: false });"); await expect(bundleEngineHost(root, { checksDir: d.checks })).rejects.toThrow(/changed since it was listed/); expect(() => listBuiltinChecks(d.checks)).toThrow(/changed since it was listed/); } finally { d.cleanup(); } }); it("refuses to build with no allowlist at all", async () => { const d = checksDir({ "c.ts": "export default () => undefined;" }, "none"); try { await expect(bundleEngineHost(root, { checksDir: d.checks })).rejects.toThrow(/allowlist/); } finally { d.cleanup(); } }); it("an approved check that needs Node cannot be built into the extension", async () => { const d = checksDir({ "uses-fs.ts": 'import { readFileSync } from "node:fs";\nexport default () => (readFileSync("/etc/hostname"), undefined);' }); try { await expect(bundleEngineHost(root, { checksDir: d.checks })).rejects.toThrow(/node:fs/); } finally { d.cleanup(); } }); it("a folder with an empty allowlist builds, with no checks", async () => { const d = checksDir({}); try { expect(listBuiltinChecks(d.checks)).toEqual([]); expect(await bundleEngineHost(root, { checksDir: d.checks })).toContain("aiteHost"); } finally { d.cleanup(); } }); it("accepts a check exported as `check` as well as default, like the runner", async () => { const d = checksDir({ "named.ts": "export const check = () => undefined;" }); try { expect(await bundleEngineHost(root, { checksDir: d.checks })).toContain("named"); } finally { d.cleanup(); } });});