import { mkdir, readFile, rm, writeFile, } from "node:fs/promises"; import path from "node:path"; import { assertNoRuntimeImports, prepareRemovalFixture, pruneRemovalFixtureCiContract, regenerateRemovalFixtureWorkflow, removeRuntimeDependentTests, requireRemovalFixtureEnvironment, runRemovalFixturePnpm, } from "./lib/removal-fixture.ts"; const fixtureRoot = path.resolve(".tmp/realtime-runtime-removal"); const pnpmCli = requireRemovalFixtureEnvironment("npm_execpath"); const runtimePaths = [ "src/application/ports/realtime", "src/application/ports/out/web-push-control.ts", "src/application/policies/bounded-polling.ts", "src/contracts/realtime-events.ts", "src/contracts/realtime-streams.ts", "src/contracts/web-push.ts", "src/adapters/realtime", "src/adapters/web-push", "tests/fixtures/realtime-boundaries", ] as const; const runtimeSourceRoots = runtimePaths.filter((entry) => entry.startsWith("src/"), ); const runtimeScripts = [ "check:realtime-boundaries", "check:realtime-boundaries:fixture", "test:realtime-removal", ] as const; const removedEvidencePathFragments = [ "realtime-boundaries", "realtime-runtime-removal", ] as const; function runPnpm(script: string): boolean { return runRemovalFixturePnpm(fixtureRoot, pnpmCli, script); } await prepareRemovalFixture(fixtureRoot); const removedRuntimeTests = await removeRuntimeDependentTests(fixtureRoot, runtimeSourceRoots); for (const runtimePath of runtimePaths) { await rm(path.join(fixtureRoot, runtimePath), { recursive: true, force: true, }); } const outputPortsIndexPath = path.join( fixtureRoot, "src/application/ports/out/index.ts", ); const outputPortsIndex = await readFile(outputPortsIndexPath, "utf8"); await writeFile( outputPortsIndexPath, outputPortsIndex.replace( 'export type { WebPushControlPort } from "./web-push-control.ts";\n', "", ), ); const catalogPath = path.join( fixtureRoot, "config/recipes/frontend-capability-recipes.json", ); const catalog = JSON.parse(await readFile(catalogPath, "utf8")) as { recipes: Array>; }; const realtimeRecipe = catalog.recipes.find( (recipe) => recipe.id === "realtime", ); if (!realtimeRecipe || !Object.hasOwn(realtimeRecipe, "referenceRuntime")) { throw new Error("Expected realtime reference runtime catalog entry"); } delete realtimeRecipe.referenceRuntime; await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\n`); for (const scriptPath of [ "scripts/check-realtime-boundaries.ts", "scripts/check-realtime-boundary-fixtures.ts", "scripts/lib/realtime-boundaries.ts", "scripts/test-realtime-runtime-removal.ts", ]) { await rm(path.join(fixtureRoot, scriptPath), { force: true }); } // The root snapshot locks the full repository inventory. This removal fixture // validates its smaller registry through check:ci and its regenerated workflow. await rm( path.join(fixtureRoot, "tests/unit/ci-workflow-generation.test.ts"), { force: true }, ); await rm( path.join( fixtureRoot, "tests/unit/__snapshots__/ci-workflow-generation.test.ts.snap", ), { force: true }, ); await pruneRemovalFixtureCiContract({ root: fixtureRoot, removedScripts: new Set(runtimeScripts), removedEvidencePathFragments, }); await regenerateRemovalFixtureWorkflow(fixtureRoot); await assertNoRuntimeImports(fixtureRoot, runtimeSourceRoots, "realtime"); const checks: Array = [ ["typecheck", runPnpm("check:types")], ["lint", runPnpm("lint")], ["architecture", runPnpm("check:architecture")], ["test", runPnpm("test:all")], ["build", runPnpm("build")], ["optional-catalog", runPnpm("check:optional-recipes:source")], ["ci-contract", runPnpm("check:ci")], ]; const passed = checks.every(([, result]) => result); await mkdir("artifacts/tests", { recursive: true }); await writeFile( "artifacts/tests/realtime-runtime-removal.xml", `\n` + `` + checks .map( ([name, result]) => `${result ? "" : ""}`, ) .join("") + `\n`, ); await rm(fixtureRoot, { recursive: true, force: true }); if (!passed) { process.stderr.write( `Realtime runtime removal failed: ${checks .filter(([, result]) => !result) .map(([name]) => name) .join(", ")}\n`, ); process.exit(1); } process.stdout.write( `Realtime runtime removal: PASS (${checks.length} base checks, ${removedRuntimeTests} runtime-dependent tests removed by import graph)\n`, );