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/browser-file-storage-runtime-removal", ); const pnpmCli = requireRemovalFixtureEnvironment("npm_execpath"); const runtimePaths = [ "src/application/ports/browser-file-storage", "src/application/ports/browser-transfer", "src/adapters/browser-file-storage", "src/adapters/browser-files", "src/adapters/browser-transfer", "src/adapters/cache-storage", "src/adapters/storage/indexeddb", "src/adapters/storage/opfs", "tests/browser-capabilities", "tests/fixtures/browser-file-storage-boundaries", ] as const; const runtimeSourceRoots = runtimePaths.filter((entry) => entry.startsWith("src/"), ); const removedScripts = new Set([ "test:browser-capabilities", "verify:browser-capability-evidence", "check:browser-file-storage-boundaries", "test:browser-file-storage-removal", ]); const removedEvidencePathFragments = [ "browser-capabilities", "browser-file-storage-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 catalogPath = path.join( fixtureRoot, "config/recipes/frontend-capability-recipes.json", ); const catalog = JSON.parse(await readFile(catalogPath, "utf8")) as { recipes: Array>; }; const browserFileRuntimeRecipeIds = new Set([ "offline-indexeddb", "service-worker-pwa", "file-transfer", ]); let removedRuntimeEntries = 0; for (const recipe of catalog.recipes) { if ( typeof recipe.id !== "string" || !browserFileRuntimeRecipeIds.has(recipe.id) || !Object.hasOwn(recipe, "referenceRuntime") ) { continue; } delete recipe.referenceRuntime; removedRuntimeEntries += 1; } if (removedRuntimeEntries !== 3) { throw new Error( `Expected three reference runtime catalog entries, removed ${removedRuntimeEntries}`, ); } await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\n`); await rm(path.join(fixtureRoot, "playwright.capabilities.config.ts"), { force: true, }); await rm( path.join(fixtureRoot, "scripts/check-browser-file-storage-boundaries.ts"), { force: true }, ); await rm( path.join(fixtureRoot, "scripts/verify-browser-capability-evidence.ts"), { force: true }, ); await rm( path.join(fixtureRoot, "scripts/test-browser-file-storage-runtime-removal.ts"), { 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, removedEvidencePathFragments, }); await regenerateRemovalFixtureWorkflow(fixtureRoot); await assertNoRuntimeImports( fixtureRoot, runtimeSourceRoots, "browser file/storage", ); 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/browser-file-storage-runtime-removal.xml", `\n` + `` + checks .map( ([name, result]) => `${result ? "" : ""}`, ) .join("") + `\n`, ); await rm(fixtureRoot, { recursive: true, force: true }); if (!passed) { process.stderr.write( `Browser file/storage runtime removal failed: ${checks .filter(([, result]) => !result) .map(([name]) => name) .join(", ")}\n`, ); process.exit(1); } process.stdout.write( `Browser file/storage runtime removal: PASS (${checks.length} base checks, ${removedRuntimeTests} runtime-dependent tests removed by import graph)\n`, );