import { readdir, readFile } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; const scriptDirectory = path.dirname(fileURLToPath(import.meta.url)); const repoRoot = path.resolve(scriptDirectory, ".."); const directoriesToScan = [ path.join(repoRoot, "RpgRoller", "frontend"), path.join(repoRoot, "RpgRoller", "wwwroot"), path.join(repoRoot, "openapi") ]; const filesToScan = [ path.join(repoRoot, "package.json"), path.join(repoRoot, "tsconfig.frontend.json"), path.join(repoRoot, "scripts", "generate-api-client.mjs"), path.join(repoRoot, "scripts", "lint-frontend.mjs"), path.join(repoRoot, "scripts", "format-check.mjs") ]; async function collectFiles(directory) { const entries = await readdir(directory, { withFileTypes: true }); const results = []; for (const entry of entries) { const fullPath = path.join(directory, entry.name); if (entry.isDirectory()) { const children = await collectFiles(fullPath); results.push(...children); } else { results.push(fullPath); } } return results; } const allFiles = [...filesToScan]; for (const directory of directoriesToScan) { const directoryFiles = await collectFiles(directory); allFiles.push(...directoryFiles); } const failures = []; for (const filePath of allFiles) { const text = await readFile(filePath, "utf8"); const relativePath = path.relative(repoRoot, filePath); const lines = text.split(/\r?\n/); for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) { if (/[ \t]+$/.test(lines[lineNumber])) { failures.push(`${relativePath}:${lineNumber + 1} has trailing whitespace.`); } } if (text.includes("\t")) { failures.push(`${relativePath} contains tab characters.`); } if (text.length > 0 && !text.endsWith("\n") && !text.endsWith("\r\n")) { failures.push(`${relativePath} is missing a trailing newline.`); } } if (failures.length > 0) { throw new Error(failures.join("\n")); } console.log("Frontend format checks passed.");