Move business logic out of App Router into module packages, add boundary validation scripts, and keep all routes as thin re-exports without changing URLs or API behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
80 lines
2.2 KiB
JavaScript
80 lines
2.2 KiB
JavaScript
#!/usr/bin/env node
|
|
/** Simple import-graph cycle detection for src/modules/healthcare. */
|
|
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
import { join, relative } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const ROOT = join(fileURLToPath(new URL(".", import.meta.url)), "..");
|
|
const MODULE = join(ROOT, "src", "modules", "healthcare");
|
|
const importRe = /from\s+["'](@\/[^"']+)["']/g;
|
|
|
|
const graph = new Map();
|
|
|
|
function walk(dir) {
|
|
for (const e of readdirSync(dir)) {
|
|
const f = join(dir, e);
|
|
if (statSync(f).isDirectory()) walk(f);
|
|
else if (/\.tsx?$/.test(e)) {
|
|
const rel = relative(ROOT, f).replace(/\\/g, "/");
|
|
const deps = [];
|
|
const content = readFileSync(f, "utf8");
|
|
let m;
|
|
importRe.lastIndex = 0;
|
|
while ((m = importRe.exec(content)) !== null) {
|
|
if (m[1].startsWith("@/src/modules/healthcare/")) deps.push(m[1]);
|
|
}
|
|
graph.set(rel, deps);
|
|
}
|
|
}
|
|
}
|
|
|
|
walk(MODULE);
|
|
|
|
function resolve(importPath) {
|
|
const base = importPath.replace("@/", "").replace(/\/$/, "");
|
|
const candidates = [
|
|
`${base}.tsx`,
|
|
`${base}.ts`,
|
|
`${base}/index.tsx`,
|
|
`${base}/index.ts`,
|
|
];
|
|
for (const c of candidates) {
|
|
if (graph.has(c)) return c;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function findCycles() {
|
|
const cycles = [];
|
|
const visited = new Set();
|
|
const stack = new Set();
|
|
|
|
function dfs(node, path) {
|
|
if (stack.has(node)) {
|
|
cycles.push([...path, node]);
|
|
return;
|
|
}
|
|
if (visited.has(node)) return;
|
|
visited.add(node);
|
|
stack.add(node);
|
|
for (const dep of graph.get(node) ?? []) {
|
|
const resolved = resolve(dep);
|
|
if (resolved) dfs(resolved, [...path, node]);
|
|
}
|
|
stack.delete(node);
|
|
}
|
|
|
|
for (const node of graph.keys()) dfs(node, []);
|
|
return cycles;
|
|
}
|
|
|
|
const cycles = findCycles();
|
|
console.log("Circular Dependency Check (healthcare module)\n");
|
|
if (cycles.length) {
|
|
console.error("❌ Cycles found:");
|
|
for (const c of cycles) console.error(" ", c.join(" → "));
|
|
process.exit(1);
|
|
}
|
|
console.log(`✅ No cycles in ${graph.size} healthcare module files`);
|
|
process.exit(0);
|