import fs from "node:fs"; import path from "node:path"; import process from "node:process"; const root = path.resolve(import.meta.dirname, "..", "src"); const extensions = new Set([".ts", ".tsx"]); const checks = [ { pattern: /\bdebugger\s*;/g, message: "debugger statement" }, { pattern: /@ts-ignore\b/g, message: "@ts-ignore is forbidden; use an explicit typed boundary" }, { pattern: /\beval\s*\(/g, message: "eval() is forbidden" }, { pattern: /\bnew\s+Function\s*\(/g, message: "new Function() is forbidden" }, ]; function walk(directory) { const entries = fs.readdirSync(directory, { withFileTypes: true }); const files = []; for (const entry of entries) { const full = path.join(directory, entry.name); if (entry.isDirectory()) files.push(...walk(full)); else if (extensions.has(path.extname(entry.name))) files.push(full); } return files; } const violations = []; for (const file of walk(root)) { const text = fs.readFileSync(file, "utf8"); for (const check of checks) { check.pattern.lastIndex = 0; for (const match of text.matchAll(check.pattern)) { const line = text.slice(0, match.index).split("\n").length; violations.push(`${path.relative(path.resolve(root, ".."), file)}:${line}: ${check.message}`); } } } if (violations.length > 0) { console.error("Frontend source-policy violations:"); for (const violation of violations) console.error(` - ${violation}`); process.exit(1); } console.log("Frontend source-policy lint passed.");