64 lines
1.5 KiB
JavaScript
64 lines
1.5 KiB
JavaScript
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
|
|
const WRITE_APIS = [
|
|
'writeFile',
|
|
'writeFileSync',
|
|
'appendFile',
|
|
'appendFileSync',
|
|
'createWriteStream',
|
|
];
|
|
|
|
function listFilesRecursive(dir) {
|
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
const files = [];
|
|
|
|
for (const entry of entries) {
|
|
const fullPath = path.join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
files.push(...listFilesRecursive(fullPath));
|
|
} else if (/\.(ts|tsx|js|mjs|cjs)$/i.test(entry.name)) {
|
|
files.push(fullPath);
|
|
}
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
function findLineNumber(source, index) {
|
|
const prefix = source.slice(0, index);
|
|
return prefix.split(/\r?\n/).length;
|
|
}
|
|
|
|
export function scanForDirectIssuesJsonlWrites(rootDir) {
|
|
if (!fs.existsSync(rootDir)) {
|
|
return [];
|
|
}
|
|
|
|
const files = listFilesRecursive(rootDir);
|
|
const violations = [];
|
|
|
|
for (const filePath of files) {
|
|
const source = fs.readFileSync(filePath, 'utf8');
|
|
const lowered = source.toLowerCase();
|
|
|
|
if (!lowered.includes('issues.jsonl')) {
|
|
continue;
|
|
}
|
|
|
|
for (const api of WRITE_APIS) {
|
|
const regex = new RegExp(`${api}\\s*\\([\\s\\S]{0,300}?issues\\.jsonl`, 'gi');
|
|
let match = regex.exec(source);
|
|
while (match) {
|
|
violations.push({
|
|
file: filePath.replaceAll('\\\\', '/'),
|
|
line: findLineNumber(source, match.index),
|
|
snippet: match[0].slice(0, 160),
|
|
});
|
|
match = regex.exec(source);
|
|
}
|
|
}
|
|
}
|
|
|
|
return violations;
|
|
}
|