import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; import { join, resolve } from "node:path"; import { describe, expect, it } from "@suaveplan/testing/runner"; const PKG = resolve(__dirname, ".."); const SRC = resolve(PKG, "src"); interface PackageJson { readonly exports: Record; readonly dependencies?: Record; readonly peerDependencies?: Record; readonly devDependencies?: Record; } const pkg = JSON.parse( readFileSync(resolve(PKG, "package.json"), "utf8") ) as PackageJson; const EXEMPT_NO_MD = new Set(["index.ts"]); function walk(dir: string): string[] { const out: string[] = []; for (const entry of readdirSync(dir)) { const full = join(dir, entry); const s = statSync(full); if (s.isDirectory()) out.push(...walk(full)); else out.push(full); } return out; } describe("dep-graph", () => { it("every subpath export points to a real file (post-build) and has a matching source", { timeout: 5000, }, () => { const subpaths = Object.keys(pkg.exports).filter( (k) => k !== "./package.json" ); for (const subpath of subpaths) { const target = ( pkg.exports[subpath] as { import?: { default: string }; } )?.import?.default; expect(target, `${subpath} has import.default`).toBeDefined(); } expect(subpaths.length).toBeGreaterThanOrEqual(12); }); it("every impl .ts has a sibling .md", { timeout: 5000 }, () => { const files = walk(SRC); const tsFiles = files.filter( (f) => f.endsWith(".ts") && !f.endsWith(".test.ts") && !f.endsWith(".bench.ts") && !f.endsWith(".types.ts") && !f.endsWith("/index.ts") && !f.endsWith(".spec-conformance.test.ts") ); for (const file of tsFiles) { const base = file.slice(0, -3); const md = `${base}.md`; if (EXEMPT_NO_MD.has(file.split("/").pop() ?? "")) continue; expect(existsSync(md), `${file} missing sibling .md`).toBe(true); } }); it("dependencies match the allowlist", { timeout: 5000 }, () => { const allowed = new Set([ "@opentelemetry/api", "@suaveplan/error", "@suaveplan/surrealdb", "@suaveplan/types", "surrealdb", "tslib", "zod", ]); for (const dep of Object.keys(pkg.dependencies ?? {})) { expect(allowed.has(dep), `unexpected runtime dep: ${dep}`).toBe( true ); } expect(Object.keys(pkg.peerDependencies ?? {})).toEqual([ "better-auth", ]); }); it("no source file exceeds 300 lines", { timeout: 5000 }, () => { const files = walk(SRC).filter( (f) => f.endsWith(".ts") && !f.endsWith(".test.ts") && !f.endsWith(".bench.ts") ); for (const file of files) { const lines = readFileSync(file, "utf8").split("\n").length; expect( lines, `${file} has ${lines} lines (>300)` ).toBeLessThanOrEqual(300); } }); it("no source file uses export *", { timeout: 5000 }, () => { const files = walk(SRC).filter((f) => f.endsWith(".ts")); for (const file of files) { const content = readFileSync(file, "utf8"); expect( /\bexport \* from\b/.test(content), `${file} uses export *` ).toBe(false); } }); it("no source file imports from vitest or bun:test", { timeout: 5000, }, () => { const files = walk(SRC).filter( (f) => f.endsWith(".ts") || f.endsWith(".test.ts") ); for (const file of files) { const content = readFileSync(file, "utf8"); expect( /from\s+["'](vitest|bun:test)["']/.test(content), `${file} imports from vitest/bun:test directly` ).toBe(false); } }); it("README quick-start uses betterAuthSurrealAdapter v1.6 factory", { timeout: 5000, }, () => { const readme = readFileSync(resolve(PKG, "README.md"), "utf8"); const quickStartIdx = readme.indexOf("## Quick start"); expect(quickStartIdx).toBeGreaterThan(-1); // First non-install code block after `## Quick start` should use // `betterAuthSurrealAdapter`. const after = readme.slice(quickStartIdx); const firstFence = after.indexOf("```ts"); const firstBlockEnd = after.indexOf("```", firstFence + 5); const firstBlock = after.slice(firstFence, firstBlockEnd); expect(firstBlock).toContain("betterAuthSurrealAdapter"); expect(firstBlock).toContain("/adapter/v1.6"); }); it("./adapter/v1.6 subpath export resolves", { timeout: 5000 }, () => { const subpath = pkg.exports["./adapter/v1.6"] as | { import?: { default: string; types: string } } | undefined; expect(subpath).toBeDefined(); expect(subpath?.import?.default).toBe("./dist/adapter/v1.6.js"); expect(subpath?.import?.types).toBe("./dist/adapter/v1.6.d.ts"); }); });