mirror of
https://github.com/harivansh-afk/betterNAS.git
synced 2026-04-15 14:03:48 +00:00
117 lines
2.9 KiB
JavaScript
117 lines
2.9 KiB
JavaScript
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const repoRoot = process.cwd();
|
|
const sourceExtensions = new Set([".js", ".mjs", ".cjs", ".ts", ".tsx"]);
|
|
const ignoredDirectories = new Set([
|
|
".git",
|
|
".next",
|
|
".turbo",
|
|
"coverage",
|
|
"dist",
|
|
"node_modules",
|
|
]);
|
|
|
|
const laneRoots = [];
|
|
for (const baseDir of ["apps", "packages"]) {
|
|
const absoluteBaseDir = path.join(repoRoot, baseDir);
|
|
for (const entry of readdirSync(absoluteBaseDir, { withFileTypes: true })) {
|
|
if (entry.isDirectory()) {
|
|
laneRoots.push(path.join(absoluteBaseDir, entry.name));
|
|
}
|
|
}
|
|
}
|
|
|
|
const disallowedWorkspacePackages = new Set([
|
|
"@betternas/sdk-ts",
|
|
"@betternas/web",
|
|
"@betternas/control-plane",
|
|
"@betternas/node-agent",
|
|
"@betternas/nextcloud-app",
|
|
]);
|
|
|
|
const importPattern =
|
|
/\b(?:import|export)\b[\s\S]*?\bfrom\s*["']([^"']+)["']|import\s*\(\s*["']([^"']+)["']\s*\)/g;
|
|
|
|
const errors = [];
|
|
|
|
walk(path.join(repoRoot, "apps"));
|
|
walk(path.join(repoRoot, "packages"));
|
|
|
|
if (errors.length > 0) {
|
|
console.error("Boundary check failed:\n");
|
|
for (const error of errors) {
|
|
console.error(`- ${error}`);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("Boundary check passed.");
|
|
|
|
function walk(currentPath) {
|
|
const stat = statSync(currentPath);
|
|
if (stat.isDirectory()) {
|
|
if (ignoredDirectories.has(path.basename(currentPath))) {
|
|
return;
|
|
}
|
|
|
|
for (const entry of readdirSync(currentPath, { withFileTypes: true })) {
|
|
walk(path.join(currentPath, entry.name));
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!sourceExtensions.has(path.extname(currentPath))) {
|
|
return;
|
|
}
|
|
|
|
const fileContent = readFileSync(currentPath, "utf8");
|
|
const fileRoot = findLaneRoot(currentPath);
|
|
if (fileRoot === null) {
|
|
return;
|
|
}
|
|
|
|
for (const match of fileContent.matchAll(importPattern)) {
|
|
const specifier = match[1] ?? match[2];
|
|
if (!specifier) {
|
|
continue;
|
|
}
|
|
|
|
if (disallowedWorkspacePackages.has(specifier)) {
|
|
errors.push(
|
|
`${relativeToRepo(currentPath)} imports forbidden workspace package ${specifier}`,
|
|
);
|
|
continue;
|
|
}
|
|
|
|
if (!specifier.startsWith(".")) {
|
|
continue;
|
|
}
|
|
|
|
const resolvedImport = path.resolve(path.dirname(currentPath), specifier);
|
|
const targetRoot = findLaneRoot(resolvedImport);
|
|
if (targetRoot !== null && targetRoot !== fileRoot) {
|
|
errors.push(
|
|
`${relativeToRepo(currentPath)} crosses lane boundary with relative import ${specifier}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function findLaneRoot(targetPath) {
|
|
const normalizedTargetPath = path.normalize(targetPath);
|
|
for (const laneRoot of laneRoots) {
|
|
const normalizedLaneRoot = path.normalize(laneRoot);
|
|
if (
|
|
normalizedTargetPath === normalizedLaneRoot ||
|
|
normalizedTargetPath.startsWith(`${normalizedLaneRoot}${path.sep}`)
|
|
) {
|
|
return normalizedLaneRoot;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function relativeToRepo(targetPath) {
|
|
return path.relative(repoRoot, targetPath) || ".";
|
|
}
|