52 lines
1.6 KiB
JavaScript
52 lines
1.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const root = path.resolve(__dirname, '..');
|
|
function frontendSources(dir) {
|
|
if (!fs.existsSync(dir)) return [];
|
|
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
const target = path.join(dir, entry.name);
|
|
if (entry.isDirectory()) return frontendSources(target);
|
|
return /\.(?:js|svelte)$/.test(entry.name) ? [target] : [];
|
|
});
|
|
}
|
|
|
|
const files = fs.readdirSync(path.join(root, 'plugins'))
|
|
.flatMap((plugin) => frontendSources(path.join(root, 'plugins', plugin, 'frontend', 'src')));
|
|
|
|
const renderPatterns = [
|
|
/statusText\s*=/,
|
|
/state\.error\s*=/,
|
|
/errorMsg\s*=/,
|
|
/setStatus\(/,
|
|
/setCreateError\(/,
|
|
/setRenameError\(/,
|
|
/renderEmpty\(/,
|
|
/output\.errors\.push\(/,
|
|
/window\.alert\(/,
|
|
/showExternalFallback\(/,
|
|
/de-error-msg/,
|
|
/files-error-msg/,
|
|
/body\.textContent\s*=/
|
|
];
|
|
|
|
const violations = [];
|
|
for (const file of files) {
|
|
const lines = fs.readFileSync(file, 'utf8').split('\n');
|
|
lines.forEach((line, index) => {
|
|
if (!/(?:err(?:or)?\.message|String\(err(?:or)?\b)/.test(line)) return;
|
|
if (!renderPatterns.some((pattern) => pattern.test(line))) return;
|
|
violations.push(`${path.relative(root, file)}:${index + 1}: technical error text reaches a user-facing UI sink`);
|
|
});
|
|
}
|
|
|
|
if (violations.length) {
|
|
console.error('User-facing UI must not render raw backend/plugin errors:');
|
|
violations.forEach((violation) => console.error(` ${violation}`));
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log('user-facing error messages do not expose raw backend details');
|