TorbatYar/frontend/scripts/validate-workspace-routes.mjs
Mortezakoohjani a483b47369 feat(workspace): complete production workspace and content operations
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-12 11:54:17 +03:30

98 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
const APP = path.join(ROOT, "app", "workspace");
const MODULE = path.join(ROOT, "modules", "workspace");
const MAX_LINES = 25;
const errors = [];
const ROUTES = [
"hub",
"hubs",
"hubs/[id]",
"projects",
"projects/[id]",
"tasks",
"teams",
"teams/[id]",
"content",
"content/[id]",
"content/calendar",
"content/board",
"approvals",
"assets",
"reports",
];
const FEATURE_FILES = [
"hub.tsx",
"hubs.tsx",
"hubDashboard.tsx",
"projects.tsx",
"projectDetail.tsx",
"tasks.tsx",
"teams.tsx",
"teamDetail.tsx",
"contentStudio.tsx",
"contentDetail.tsx",
"contentCalendar.tsx",
"contentBoard.tsx",
"approvals.tsx",
"assets.tsx",
"reports.tsx",
];
function walkPages(dir) {
for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
const p = path.join(dir, ent.name);
if (ent.isDirectory()) walkPages(p);
else if (ent.name === "page.tsx") checkPage(p);
}
}
function checkPage(file) {
const rel = path.relative(APP, file);
const content = fs.readFileSync(file, "utf8");
const lines = content.split("\n").length;
if (rel !== "page.tsx" && lines > MAX_LINES) errors.push(`${rel}: ${lines} lines (max ${MAX_LINES})`);
if (rel !== "page.tsx" && !content.includes("@/modules/workspace/")) {
errors.push(`${rel}: must import from @/modules/workspace/`);
}
}
for (const route of ROUTES) {
for (const file of ["page.tsx", "loading.tsx", "error.tsx"]) {
const p = path.join(APP, route, file);
if (!fs.existsSync(p)) errors.push(`missing app/workspace/${route}/${file}`);
}
}
for (const file of FEATURE_FILES) {
if (!fs.existsSync(path.join(MODULE, "features", file))) {
errors.push(`missing modules/workspace/features/${file}`);
}
}
for (const file of [
path.join(MODULE, "index.ts"),
path.join(MODULE, "services", "workspace-api.ts"),
path.join(MODULE, "labels.ts"),
path.join(ROOT, "app", "api", "workspace", "[...path]", "route.ts"),
path.join(APP, "layout.tsx"),
path.join(APP, "page.tsx"),
]) {
if (!fs.existsSync(file)) errors.push(`missing ${path.relative(ROOT, file)}`);
}
if (fs.existsSync(APP)) walkPages(APP);
else errors.push("app/workspace not found");
if (errors.length) {
console.error("Workspace route validation failed:\n" + errors.map((e) => " - " + e).join("\n"));
process.exit(1);
}
console.log(`Workspace routes OK (${ROUTES.length} routes, ${FEATURE_FILES.length} features)`);