137 lines
4.4 KiB
JavaScript
137 lines
4.4 KiB
JavaScript
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import assert from "node:assert/strict";
|
|
import { afterEach, describe, it } from "vitest";
|
|
|
|
import {
|
|
checkPackageBoundaryImports,
|
|
checkSchemaOutput,
|
|
scanForbiddenPrismaOwnershipText,
|
|
verifyPrismaOwnership,
|
|
} from "./verify-prisma-ownership.mjs";
|
|
|
|
const fixtures = [];
|
|
|
|
function writeFile(rootDir, relativePath, content) {
|
|
const absolutePath = path.join(rootDir, relativePath);
|
|
fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
|
|
fs.writeFileSync(absolutePath, content);
|
|
}
|
|
|
|
function createFixture(overrides = {}) {
|
|
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "prisma-ownership-"));
|
|
fixtures.push(rootDir);
|
|
|
|
writeFile(
|
|
rootDir,
|
|
"prisma/schema/schema.prisma",
|
|
overrides.schema ?? `generator client {
|
|
provider = "prisma-client"
|
|
output = "../../packages/db/generated/prisma/client"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
}
|
|
`,
|
|
);
|
|
writeFile(
|
|
rootDir,
|
|
"packages/db/src/client.server.ts",
|
|
overrides.clientServer ?? `export * from "../generated/prisma/client/client.ts";
|
|
`,
|
|
);
|
|
writeFile(
|
|
rootDir,
|
|
"packages/db/src/prisma-browser.ts",
|
|
overrides.prismaBrowser ?? `export * from "../generated/prisma/client/browser.ts";
|
|
`,
|
|
);
|
|
writeFile(rootDir, "apps/web/app/routes/example.tsx", overrides.appSource ?? "export const route = true;\n");
|
|
writeFile(rootDir, "packages/db/generated/prisma/client/client.ts", "app/generated/prisma fixture text ignored in generated output\n");
|
|
|
|
return rootDir;
|
|
}
|
|
|
|
afterEach(() => {
|
|
while (fixtures.length > 0) {
|
|
fs.rmSync(fixtures.pop(), { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
describe("verify-prisma-ownership", () => {
|
|
it("passes for a repository using package-owned Prisma 7 TypeScript entrypoints", () => {
|
|
const rootDir = createFixture({
|
|
appSource: `import { Prisma } from "@toolctrl/db/prisma-browser";
|
|
|
|
export const route = Prisma;
|
|
`,
|
|
});
|
|
|
|
const result = verifyPrismaOwnership(rootDir);
|
|
|
|
assert.deepEqual(result.failures, []);
|
|
assert.ok(result.passes.some((pass) => pass.includes("generator output is package-owned")));
|
|
assert.ok(result.passes.some((pass) => pass.includes("client.server.ts")));
|
|
assert.ok(result.passes.some((pass) => pass.includes("repository text scan")));
|
|
});
|
|
|
|
it("fails when app code imports an app-local generated Prisma browser client", () => {
|
|
const rootDir = createFixture({
|
|
appSource: `import { Prisma } from "~/generated/prisma/client/browser";
|
|
|
|
export const route = Prisma;
|
|
`,
|
|
});
|
|
|
|
const result = scanForbiddenPrismaOwnershipText(rootDir);
|
|
|
|
assert.match(result.failures.join("\n"), /app\/routes\/example\.tsx: forbidden app-local generated Prisma client import/);
|
|
});
|
|
|
|
it("fails when app code imports the old root-local generated Prisma client", () => {
|
|
const rootDir = createFixture({
|
|
appSource: `const relativeGeneratedClientPath = "../generated/prisma/client";
|
|
const appGeneratedClientPath = "app/generated/prisma/client";
|
|
`,
|
|
});
|
|
|
|
const result = scanForbiddenPrismaOwnershipText(rootDir);
|
|
|
|
assert.match(result.failures.join("\n"), /app\/routes\/example\.tsx: forbidden root\/app Prisma generated-client path/);
|
|
});
|
|
|
|
it("fails when schema output points outside packages/db", () => {
|
|
const rootDir = createFixture({
|
|
schema: `generator client {
|
|
provider = "prisma-client"
|
|
output = "../../app/generated/prisma/client"
|
|
}
|
|
`,
|
|
});
|
|
|
|
const result = checkSchemaOutput(rootDir);
|
|
|
|
assert.match(result.failures.join("\n"), /prisma\/schema\/schema\.prisma: expected generator output/);
|
|
assert.match(result.failures.join("\n"), /old root\/app generated Prisma ownership/);
|
|
});
|
|
|
|
it("fails when package boundary files do not use package-owned generated TypeScript entrypoints", () => {
|
|
const rootDir = createFixture({
|
|
clientServer: `const crossedBoundaryPath = "../../../app/generated/prisma/client";
|
|
export const client = crossedBoundaryPath;
|
|
`,
|
|
prismaBrowser: `const wrongClientPath = "@prisma/client";
|
|
export { wrongClientPath };
|
|
`,
|
|
});
|
|
|
|
const result = checkPackageBoundaryImports(rootDir);
|
|
|
|
assert.match(result.failures.join("\n"), /packages\/db\/src\/client\.server\.ts: must import\/export/);
|
|
assert.match(result.failures.join("\n"), /packages\/db\/src\/client\.server\.ts: must not cross out/);
|
|
assert.match(result.failures.join("\n"), /packages\/db\/src\/prisma-browser\.ts: must import\/export/);
|
|
});
|
|
});
|