This commit is contained in:
2026-07-16 09:53:14 +07:00
parent 0fc112a2e8
commit 29cec708a3
1236 changed files with 212848 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const ROOT = process.cwd();
const dashboardRoot = path.join(ROOT, 'src', 'app', 'dashboard');
const requiredGuardPattern =
/require(Employee|HRD|IT|UserManagement|SuperAdmin|Permission)DashboardAccess/;
const allowedWithoutGuard = new Set([
'src/app/dashboard/layout.tsx',
'src/app/dashboard/page.tsx',
'src/app/dashboard/overview/layout.tsx',
'src/app/dashboard/organizers/page.tsx'
]);
const legacyRoutePrefixes = [
'src/app/dashboard/billing/',
'src/app/dashboard/chat/',
'src/app/dashboard/elements/',
'src/app/dashboard/exclusive/',
'src/app/dashboard/forms/',
'src/app/dashboard/kanban/',
'src/app/dashboard/profile/',
'src/app/dashboard/product/',
'src/app/dashboard/react-query/',
'src/app/dashboard/workspaces/'
];
const guardedByLayoutPrefixes = ['src/app/dashboard/overview/'];
function walk(dir, results = []) {
if (!fs.existsSync(dir)) {
return results;
}
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
walk(fullPath, results);
continue;
}
if (entry.name === 'page.tsx' || entry.name === 'layout.tsx') {
results.push(fullPath);
}
}
return results;
}
function isLegacy(relativePath) {
return legacyRoutePrefixes.some((prefix) => relativePath.startsWith(prefix));
}
function isGuardedByParentLayout(relativePath) {
return guardedByLayoutPrefixes.some(
(prefix) => relativePath.startsWith(prefix) && relativePath !== `${prefix}layout.tsx`
);
}
function main() {
const files = walk(dashboardRoot);
const missingGuards = [];
for (const filePath of files) {
const relativePath = path.relative(ROOT, filePath).replace(/\\/g, '/');
if (
allowedWithoutGuard.has(relativePath) ||
isLegacy(relativePath) ||
isGuardedByParentLayout(relativePath)
) {
continue;
}
const content = fs.readFileSync(filePath, 'utf8');
if (!requiredGuardPattern.test(content)) {
missingGuards.push(relativePath);
}
}
if (missingGuards.length === 0) {
console.log('check-architecture: passed');
return;
}
console.error('check-architecture: dashboard entrypoints missing shared page guards');
for (const relativePath of missingGuards) {
console.error(`- ${relativePath}`);
}
process.exitCode = 1;
}
main();