frontend: add dependency-free source policy lint

This commit is contained in:
2026-08-26 22:12:52 +02:00
parent 6ac87a0504
commit 56b2a36528
+43
View File
@@ -0,0 +1,43 @@
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.");