diff --git a/.gitignore b/.gitignore index a2a5e4ec..711467a5 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,6 @@ tsconfig.focus.json # Subagent-driven-development scratch (ledger, briefs, review packages) .superpowers/ + +# Scratch modules written by tests that must resolve this workspace. +.tmp-tests/ diff --git a/packages/compiler/test/apis-server-emit.test.ts b/packages/compiler/test/apis-server-emit.test.ts index 43536044..3f23279b 100644 --- a/packages/compiler/test/apis-server-emit.test.ts +++ b/packages/compiler/test/apis-server-emit.test.ts @@ -1,29 +1,20 @@ import { afterEach, expect, test } from "bun:test"; -import { mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node:fs"; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { parse } from "@wrnexus/syntax"; import { runWithRequestContext } from "@wrnexus/core"; import { generate } from "../src/codegen.ts"; -// The generated module dynamically imported below is written to an OS -// tmpdir with no node_modules of its own, so Node's bare-specifier -// resolution for "@wrnexus/core" would otherwise walk up to whatever -// (possibly stale, globally-installed) copy happens to sit outside the -// workspace. Symlink the workspace package in so it resolves to the real, -// currently-built `@wrnexus/core` — the same one every other package in -// this repo gets via its own `node_modules/@wrnexus/core` symlink. -const WORKSPACE_CORE = join(import.meta.dir, "../../core"); - -function linkWorkspaceCore(root: string): void { - const scopeDir = join(root, "node_modules", "@wrnexus"); - mkdirSync(scopeDir, { recursive: true }); - symlinkSync( - WORKSPACE_CORE, - join(scopeDir, "core"), - process.platform === "win32" ? "junction" : "dir", - ); -} +// The generated module dynamically imported below resolves "@wrnexus/core" +// by walking up from its own directory, so it is written inside the repo +// rather than an OS tmpdir: the walk then reaches this workspace's +// node_modules and loads the very same module instance the test itself +// holds. That identity is what these tests rest on -- the request context +// lives in an AsyncLocalStorage inside `@wrnexus/core`, and a second copy of +// the package (which is what a junction from another volume produced) has a +// store of its own that the test could never populate. +const WORKSPACE_TMP = join(import.meta.dir, "../../../.tmp-tests"); const ROOT_TSCONFIG = join(import.meta.dir, "../../../tsconfig.json").replace(/\\/g, "/"); // The repo's own tsc, not a `bunx`-fetched one — `bunx tsc` can resolve an @@ -69,10 +60,9 @@ function typecheckGenerated(source: string): { ok: boolean; output: string } { } async function importServerModule(source: string): Promise { - const root = mkdtempSync(join(tmpdir(), "wrnexus-apis-server-exec-")); + mkdirSync(WORKSPACE_TMP, { recursive: true }); + const root = mkdtempSync(join(WORKSPACE_TMP, "apis-server-exec-")); roots.push(root); - mkdirSync(root, { recursive: true }); - linkWorkspaceCore(root); const file = join(root, "page.ts"); writeFileSync(file, source); return import(`${file.replace(/\\/g, "/")}?t=${Date.now()}`);