Files
pikasTech-HWLAB/scripts/src/playwright-launch-guard.mjs
T
2026-06-04 20:35:58 +08:00

73 lines
2.5 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
export const defaultPlaywrightLaunchScanRoots = Object.freeze(["scripts", "tools", "web"]);
export const defaultPlaywrightLaunchAllowlist = Object.freeze([
"scripts/src/browser-launcher.mjs"
]);
const sourceExtensions = new Set([".cjs", ".cts", ".js", ".jsx", ".mjs", ".mts", ".ts", ".tsx"]);
const skippedDirectories = new Set([".git", ".state", ".worktree", "dist", "node_modules"]);
const directChromiumLaunchPattern = new RegExp("\\bchromium\\s*\\.\\s*launch\\s*\\(", "u");
export function findDirectChromiumLaunches(options = {}) {
const repoRoot = path.resolve(options.repoRoot ?? process.cwd());
const roots = options.roots ?? defaultPlaywrightLaunchScanRoots;
const allowlist = new Set(options.allowlist ?? defaultPlaywrightLaunchAllowlist);
const scannedFiles = [];
const allowed = [];
const violations = [];
for (const root of roots) {
const absoluteRoot = path.resolve(repoRoot, root);
if (!fs.existsSync(absoluteRoot)) continue;
for (const file of collectSourceFiles(absoluteRoot)) {
const relativePath = normalizeRelative(repoRoot, file);
scannedFiles.push(relativePath);
const matches = findMatches(file, relativePath);
if (matches.length === 0) continue;
if (allowlist.has(relativePath)) allowed.push(...matches);
else violations.push(...matches);
}
}
return {
status: violations.length === 0 ? "pass" : "fail",
repoRoot,
roots,
allowlist: [...allowlist].sort(),
scannedFileCount: scannedFiles.length,
allowed,
violations
};
}
function collectSourceFiles(directory) {
const out = [];
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
if (entry.isDirectory()) {
if (!skippedDirectories.has(entry.name)) out.push(...collectSourceFiles(path.join(directory, entry.name)));
continue;
}
if (!entry.isFile()) continue;
const full = path.join(directory, entry.name);
if (sourceExtensions.has(path.extname(entry.name))) out.push(full);
}
return out;
}
function findMatches(file, relativePath) {
const lines = fs.readFileSync(file, "utf8").split(/\r?\n/u);
const matches = [];
lines.forEach((line, index) => {
if (directChromiumLaunchPattern.test(line)) {
matches.push({ file: relativePath, line: index + 1, text: line.trim().slice(0, 200) });
}
});
return matches;
}
function normalizeRelative(root, file) {
return path.relative(root, file).split(path.sep).join("/");
}