import { mkdir, readdir, writeFile } from "node:fs/promises"; import { spawnSync } from "node:child_process"; await mkdir("artifacts/quality", { recursive: true }); const pnpmCli = /** @type {string} */ (process.env.npm_execpath); if (!pnpmCli) { throw new Error("check:architecture must run through the pnpm script"); } /** @param {string[]} arguments_ */ function runPnpm(arguments_) { return spawnSync(process.execPath, [pnpmCli, ...arguments_], { encoding: "utf8", }); } const production = runPnpm( [ "exec", "depcruise", "src", "--config", ".dependency-cruiser.cjs", "--output-type", "json", ], ); await writeFile( "artifacts/quality/dependency-report.json", production.stdout || JSON.stringify({ summary: { errors: 1 } }), ); if (production.status !== 0) { process.stderr.write( production.error?.message ?? production.stderr ?? production.stdout ?? "failed", ); process.exit(production.status ?? 1); } const allowed = runPnpm( [ "exec", "eslint", "tests/fixtures/architecture/allowed", "--no-ignore", "--max-warnings=0", ], ); const forbidden = runPnpm( [ "exec", "eslint", "tests/fixtures/architecture/forbidden", "--no-ignore", "--max-warnings=0", ], ); /** @param {string} directory @returns {Promise} */ async function fixtureFiles(directory) { const entries = await readdir(directory, { withFileTypes: true }); const files = await Promise.all( entries.map((entry) => { const target = `${directory}/${entry.name}`; return entry.isDirectory() ? fixtureFiles(target) : /\.(?:js|jsx|mjs|ts|tsx|mts)$/.test(entry.name) ? [target] : []; }), ); return files.flat(); } const forbiddenResults = await Promise.all( (await fixtureFiles("tests/fixtures/architecture/forbidden")).map((file) => ({ file, result: runPnpm([ "exec", "eslint", file, "--no-ignore", "--max-warnings=0", ]), })), ); const acceptedForbidden = forbiddenResults.filter( ({ result }) => result.status === 0, ); if ( allowed.status !== 0 || forbidden.status === 0 || acceptedForbidden.length > 0 ) { process.stderr.write(allowed.stderr || allowed.stdout); process.stderr.write(forbidden.stderr || forbidden.stdout); for (const { file } of acceptedForbidden) { process.stderr.write(`Forbidden fixture was accepted: ${file}\n`); } process.exit(1); } process.stdout.write( `Architecture fixtures: allowed PASS, ${forbiddenResults.length} forbidden rejected\n`, );