Files
HiveGrid-Wireframes/hivegrid-cloud/scripts/verify-db-boundary-eslint.test.mjs
T

95 lines
3.9 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import assert from "node:assert/strict";
import { describe, it } from "vitest";
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const rootDir = path.resolve(scriptDir, "..");
const eslintConfig = JSON.parse(fs.readFileSync(path.join(rootDir, ".eslintrc"), "utf8"));
function findRestrictedImportRules(config) {
const rules = [];
if (config.rules?.["no-restricted-imports"]) {
rules.push({ files: ["<root>"], rule: config.rules["no-restricted-imports"] });
}
for (const override of config.overrides ?? []) {
if (override.rules?.["no-restricted-imports"]) {
rules.push({ files: override.files ?? [], rule: override.rules["no-restricted-imports"] });
}
}
return rules;
}
function collectRestrictedPatterns(rule) {
const options = Array.isArray(rule) ? rule.slice(1) : [];
const patterns = [];
for (const option of options) {
if (typeof option === "string") {
patterns.push(option);
continue;
}
if (!option || typeof option !== "object") {
continue;
}
for (const entry of option.patterns ?? []) {
if (typeof entry === "string") {
patterns.push(entry);
} else if (entry?.group) {
patterns.push(...entry.group);
}
}
}
return patterns;
}
describe("DB Boundary ESLint DB boundary guard", () => {
it("restricts generated Prisma client source imports without blocking the package browser boundary", () => {
const restrictedRules = findRestrictedImportRules(eslintConfig);
assert.ok(restrictedRules.length > 0, "expected a no-restricted-imports rule");
const patterns = restrictedRules.flatMap(({ rule }) => collectRestrictedPatterns(rule));
assert.ok(patterns.includes("~/generated/prisma/client/*"), "missing tilde generated Prisma client restriction");
assert.ok(patterns.includes("app/generated/prisma/client/*"), "missing app generated Prisma client restriction");
assert.ok(patterns.includes("@prisma/client"), "missing direct @prisma/client restriction");
assert.ok(patterns.includes("@prisma/client/*"), "missing direct @prisma/client subpath restriction");
assert.ok(!patterns.includes("@toolctrl/db/prisma-browser"), "package Prisma browser boundary must remain importable");
});
it("keeps package-owned generated Prisma entrypoints available to db boundary files", () => {
const restrictedRules = findRestrictedImportRules(eslintConfig);
const boundaryOverrides = restrictedRules.filter(({ files }) =>
files.includes("packages/db/src/client.server.ts") || files.includes("packages/db/src/prisma-browser.ts"),
);
assert.ok(boundaryOverrides.length > 0, "expected db boundary override for generated Prisma entrypoints");
for (const { rule } of boundaryOverrides) {
const patterns = collectRestrictedPatterns(rule);
assert.ok(!patterns.includes("../generated/prisma/client/*"));
assert.ok(!patterns.includes("../generated/prisma/client/client.js"));
assert.ok(!patterns.includes("../generated/prisma/client/browser.js"));
}
});
it("blocks React imports in apps/web/app/utils/db without blocking Prisma browser package imports", () => {
const restrictedRules = findRestrictedImportRules(eslintConfig);
const dbOverrides = restrictedRules.filter(({ files }) => files.includes("apps/web/app/utils/db/**/*.ts"));
assert.ok(dbOverrides.length > 0, "expected apps/web/app/utils/db/**/*.ts override");
const patterns = dbOverrides.flatMap(({ rule }) => collectRestrictedPatterns(rule));
assert.ok(patterns.includes("react"), "missing react import restriction for apps/web/app/utils/db");
assert.ok(patterns.includes("react/*"), "missing react subpath import restriction for apps/web/app/utils/db");
assert.ok(!patterns.includes("@toolctrl/db/prisma-browser"), "db legacy boundary must allow Prisma browser type imports");
});
});