Files
mangabaka-seeder/test/boundaries.test.ts
T

36 lines
1.5 KiB
TypeScript

import { expect, test } from "bun:test";
import { Glob } from "bun";
// AGENTS.md: src/core runs in a browser, a userscript and Bun.
const CORE_FORBIDDEN: [RegExp, string][] = [
[/\bdocument\b|\bwindow\b|\blocalStorage\b|\bsessionStorage\b/, "DOM global"],
[/\bBun\./, "Bun API"],
[/from\s+["']node:|import\(["']node:/, "node:* import"],
[/\bGM_\w+|\bGM\./, "GM_* API"],
[/from\s+["'](?:\.\.\/)+(?:web|server|userscript|cli)\//, "import from a front end"],
];
// spec §4: these server files stay web-standard so a Workers entry can be added later.
const PORTABLE_SERVER = ["app.ts", "storage.ts", "rate-limit.ts", "config.ts", "assets-path.ts"];
const PORTABLE_FORBIDDEN: [RegExp, string][] = [
[/\bBun\./, "Bun API"],
[/from\s+["']node:|import\(["']node:/, "node:* import"],
];
async function violations(pattern: string, rules: [RegExp, string][], only?: string[]) {
const problems: string[] = [];
for await (const file of new Glob(pattern).scan(".")) {
if (only && !only.some((name) => file.endsWith(`/${name}`))) continue;
const text = await Bun.file(file).text();
for (const [re, what] of rules) if (re.test(text)) problems.push(`${file}: ${what}`);
}
return problems;
}
test("src/core uses no platform APIs and imports no front end", async () => {
expect(await violations("src/core/**/*.ts", CORE_FORBIDDEN)).toEqual([]);
});
test("portable server files use only web-standard APIs", async () => {
expect(await violations("src/server/*.ts", PORTABLE_FORBIDDEN, PORTABLE_SERVER)).toEqual([]);
});