// @vitest-environment node import assert from "node:assert/strict"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { afterEach, describe, test } from "vitest"; import { RUNTIME_CLOSURE_TARGETS, collectOpaquePackageSpecifiers, collectRuntimePackageImports, packageNameFromSpecifier, parseRuntimeSelection, verifyRuntimeClosure, } from "./verify-runtime-closures.mjs"; const fixtures = []; const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); afterEach(() => { for (const fixture of fixtures.splice(0)) fs.rmSync(fixture, { force: true, recursive: true }); }); describe("runtime closure verification", () => { test("includes separately spawned worker entry points in the runtime closure", () => { assert.ok(RUNTIME_CLOSURE_TARGETS.worker.entryPoints.includes("apps/worker/dist/jobs/plugin-sandbox-worker.js")); assert.ok(RUNTIME_CLOSURE_TARGETS.worker.entryPoints.includes("apps/worker/dist/jobs/file-preview-decoder-process.js")); }); test("includes the one-shot permission catalog migrator in the web runtime closure", () => { assert.ok(RUNTIME_CLOSURE_TARGETS.web.entryPoints.includes("packages/db/dist/deploy-permission-catalog-sync.server.js")); }); test("keeps pg external in database-backed service artifacts and runtime closures", () => { const buildScripts = { api: "apps/api/scripts/build.mjs", hocuspocus: "apps/hocuspocus/scripts/build.mjs", mcp: "apps/mcp/scripts/build.mjs", web: "scripts/build-web-server.mjs", }; for (const [target, buildScript] of Object.entries(buildScripts)) { const buildSource = fs.readFileSync(path.join(rootDir, buildScript), "utf8"); const runtimeManifest = JSON.parse(fs.readFileSync(path.join(rootDir, `runtime/${target}/package.json`), "utf8")); assert.match(buildSource, /specifier === "pg"/, target); assert.match(buildSource, /specifier\.startsWith\("pg\/"\)/, target); assert.equal(runtimeManifest.dependencies.pg, "^8.20.0", target); } }); test("normalizes package subpaths while excluding relative and Node imports", () => { assert.equal(packageNameFromSpecifier("@scope/package/subpath"), "@scope/package"); assert.equal(packageNameFromSpecifier("package/subpath"), "package"); assert.equal(packageNameFromSpecifier("node:http"), null); assert.equal(packageNameFromSpecifier("./chunk.js"), null); }); test("collects static, dynamic, and CommonJS package imports", async () => { const rootDir = createFixture({ "dist/index.js": [ 'import "side-effect";', 'import value from "@scope/static/subpath";', 'export { value } from "exported";', 'await import("dynamic/subpath");', 'require("commonjs/feature");', 'import "node:http";', 'import "./chunk.js";', ].join("\n"), "dist/chunk.js": "export const value = true;\n", }); assert.deepEqual(await collectRuntimePackageImports(rootDir, ["dist/index.js"]), ["@scope/static", "commonjs", "dynamic", "exported", "side-effect"]); }); test("collects package imports hidden behind runtime-resolved strings", async () => { const source = [ 'const moduleName = "opaque-dynamic/subpath";', "await import(/* runtime */ moduleName);", 'requireFromHere("@scope/opaque/feature");', ].join("\n"); assert.deepEqual(collectOpaquePackageSpecifiers(source), ["@scope/opaque/feature", "opaque-dynamic/subpath"]); const rootDir = createFixture({ "dist/index.js": source }); assert.deepEqual(await collectRuntimePackageImports(rootDir, ["dist/index.js"]), ["@scope/opaque", "opaque-dynamic"]); }); test("pairs a runtime-resolved import with the nearest preceding declaration of that name", () => { const source = [ 'const moduleName = "first-package";', "await import(moduleName);", 'const moduleName = "second-package";', "await import(moduleName);", ].join("\n"); assert.deepEqual(collectOpaquePackageSpecifiers(source), ["first-package", "second-package"]); }); test("ignores a declaration that is too far from the import to be the same binding", () => { const near = ['const moduleName = "near-package";', `// ${"x".repeat(400)}`, "await import(moduleName);"].join("\n"); const far = ['const moduleName = "far-package";', `// ${"x".repeat(600)}`, "await import(moduleName);"].join("\n"); assert.deepEqual(collectOpaquePackageSpecifiers(near), ["near-package"]); assert.deepEqual(collectOpaquePackageSpecifiers(far), []); }); test("scans a bundled artifact with megabyte-long generated lines without overflowing", () => { // A single generated line of this size used to blow the regex stack and fail the CI check outright. const source = [ 'const moduleName = "bundled-package";', "await import(moduleName);", `const filler = ${JSON.stringify("y".repeat(2_000_000))};`, ].join("\n"); assert.deepEqual(collectOpaquePackageSpecifiers(source), ["bundled-package"]); }); test("reports artifact imports absent from the target runtime manifest", async () => { const rootDir = createFixture({ "dist/index.js": 'import "present"; import "missing/subpath";\n', "runtime/package.json": JSON.stringify({ private: true, dependencies: { present: "1.0.0" } }), }); const result = await verifyRuntimeClosure(rootDir, "fixture", { entryPoints: ["dist/index.js"], manifestPath: "runtime/package.json", }); assert.deepEqual(result.missingDependencies, ["missing"]); }); test("reports dependencies missing only from a secondary runtime entry point", async () => { const rootDir = createFixture({ "dist/server.js": 'import "present";\n', "dist/migrator.js": 'import "migrator-only-missing/subpath";\n', "runtime/package.json": JSON.stringify({ private: true, dependencies: { present: "1.0.0" } }), }); const result = await verifyRuntimeClosure(rootDir, "fixture", { entryPoints: ["dist/server.js", "dist/migrator.js"], manifestPath: "runtime/package.json", }); assert.deepEqual(result.missingDependencies, ["migrator-only-missing"]); }); test("selects one or more explicit runtime targets for post-build CI verification", () => { assert.deepEqual(parseRuntimeSelection(["--runtime=api"]), ["api"]); assert.deepEqual(parseRuntimeSelection(["--", "--runtime=hocuspocus"]), ["hocuspocus"]); assert.deepEqual(parseRuntimeSelection(["--runtime", "worker", "--runtime=mcp"]), ["worker", "mcp"]); assert.deepEqual(parseRuntimeSelection(["--runtime=web", "--runtime=web"]), ["web"]); assert.throws(() => parseRuntimeSelection(["--runtime=unknown"]), /unknown runtime closure target/); assert.throws(() => parseRuntimeSelection(["--other=api"]), /unknown runtime closure argument/); assert.throws(() => parseRuntimeSelection(["--runtime"]), /requires a target name/); }); test("verifies only selected runtime targets", async () => { const rootDir = createFixture({ "dist/first.js": 'import "first-dependency";\n', "dist/second.js": 'import "second-dependency";\n', "runtime/first.json": JSON.stringify({ dependencies: { "first-dependency": "1.0.0" } }), "runtime/second.json": JSON.stringify({ dependencies: { "second-dependency": "1.0.0" } }), }); const targets = { first: { entryPoints: ["dist/first.js"], manifestPath: "runtime/first.json" }, second: { entryPoints: ["dist/second.js"], manifestPath: "runtime/second.json" }, }; const results = await Promise.all(["second"].map((targetName) => verifyRuntimeClosure(rootDir, targetName, targets[targetName]))); assert.deepEqual( results.map((result) => result.targetName), ["second"] ); assert.deepEqual(results[0].missingDependencies, []); }); }); function createFixture(files) { const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "runtime-closure-")); fixtures.push(rootDir); for (const [relativePath, content] of Object.entries(files)) { const filePath = path.join(rootDir, relativePath); fs.mkdirSync(path.dirname(filePath), { recursive: true }); fs.writeFileSync(filePath, content); } return rootDir; }