Files
wwjcloud/tools/check-routes.js

67 lines
2.2 KiB
JavaScript
Raw Normal View History

const fs = require('fs');
const path = require('path');
// naive scan for @Controller and @Get/@Post/@Put/@Delete decorations
function scanControllers(rootDir) {
const results = [];
function walk(dir) {
for (const entry of fs.readdirSync(dir)) {
const full = path.join(dir, entry);
const stat = fs.statSync(full);
if (stat.isDirectory()) walk(full);
else if (entry.endsWith('.ts') && full.includes(path.join('controllers', 'adminapi'))) {
const txt = fs.readFileSync(full, 'utf8');
const controllerPrefixMatch = txt.match(/@Controller\(['"]([^'\"]+)['"]\)/);
const prefix = controllerPrefixMatch ? controllerPrefixMatch[1] : '';
const routeRegex = /@(Get|Post|Put|Delete)\(['"]([^'\"]*)['"]\)/g;
let m;
while ((m = routeRegex.exec(txt))) {
const method = m[1].toUpperCase();
const suffix = m[2];
const fullPath = suffix ? `${prefix}/${suffix}` : prefix;
results.push({ method, path: fullPath.replace(/\/:/g, '/:') });
}
}
}
}
walk(rootDir);
return results;
}
function main() {
const contract = JSON.parse(
fs.readFileSync(path.join(__dirname, 'contracts', 'routes.json'), 'utf8'),
);
const impl = scanControllers(path.join(__dirname, '..', 'wwjcloud', 'src', 'common'));
function normalizePath(p) {
// convert ${ var } or ${ params.var } to :var
return String(p).replace(/\$\{\s*(?:params\.)?([a-zA-Z_][\w]*)\s*\}/g, ':$1');
}
const toKey = (r) => `${r.method} ${normalizePath(r.path)}`;
const contractSet = new Set(contract.map(toKey));
const implSet = new Set(impl.map(toKey));
const missing = contract.filter((r) => !implSet.has(toKey(r)));
const extra = impl.filter((r) => !contractSet.has(toKey(r)));
if (missing.length || extra.length) {
console.error('Route contract mismatches found.');
if (missing.length) {
console.error('Missing routes:');
for (const r of missing) console.error(` ${r.method} ${r.path}`);
}
if (extra.length) {
console.error('Extra routes:');
for (const r of extra) console.error(` ${r.method} ${r.path}`);
}
process.exit(1);
}
console.log('All routes match contract.');
}
main();