Initial Commit
This commit is contained in:
134
packages/api-stack/api/api-plugin-auth/tests/dep-graph.test.ts
Normal file
134
packages/api-stack/api/api-plugin-auth/tests/dep-graph.test.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { readdirSync, readFileSync, statSync } from "node:fs";
|
||||
import { join, resolve } from "node:path";
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
|
||||
const pkgRoot = resolve(__dirname, "..");
|
||||
const srcRoot = join(pkgRoot, "src");
|
||||
|
||||
function walk(dir: string): string[] {
|
||||
const out: string[] = [];
|
||||
for (const entry of readdirSync(dir)) {
|
||||
const full = join(dir, entry);
|
||||
const st = statSync(full);
|
||||
if (st.isDirectory()) out.push(...walk(full));
|
||||
else out.push(full);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
describe("@suaveplan/api-plugin-auth dep graph + layout", () => {
|
||||
it("package.json carries required dependencies", { timeout: 5000 }, () => {
|
||||
const pkg = JSON.parse(
|
||||
readFileSync(join(pkgRoot, "package.json"), "utf8")
|
||||
) as {
|
||||
dependencies: Record<string, string>;
|
||||
devDependencies: Record<string, string>;
|
||||
};
|
||||
const deps = pkg.dependencies;
|
||||
expect(deps["@suaveplan/api-plugin"]).toBe("workspace:^");
|
||||
expect(deps["@suaveplan/api-openapi"]).toBe("workspace:^");
|
||||
expect(deps["@suaveplan/api-migrations"]).toBe("workspace:^");
|
||||
expect(deps["@suaveplan/better-auth-surrealdb"]).toBe("workspace:^");
|
||||
expect(deps["@suaveplan/surrealdb"]).toBe("workspace:^");
|
||||
expect(deps["@suaveplan/error"]).toBe("workspace:^");
|
||||
expect(deps["@suaveplan/types"]).toBe("workspace:^");
|
||||
expect(deps["hono"]).toBe("catalog:");
|
||||
expect(deps["@hono/zod-openapi"]).toBe("catalog:server");
|
||||
expect(deps["zod"]).toBe("catalog:forms");
|
||||
expect(deps["better-auth"]).toBe("catalog:auth");
|
||||
expect(deps["@opentelemetry/api"]).toBe("catalog:observability");
|
||||
});
|
||||
|
||||
it("package.json exposes 15 subpath exports", { timeout: 5000 }, () => {
|
||||
const pkg = JSON.parse(
|
||||
readFileSync(join(pkgRoot, "package.json"), "utf8")
|
||||
) as { exports: Record<string, unknown> };
|
||||
const subs = Object.keys(pkg.exports).filter(
|
||||
(k) => k.startsWith("./") && k !== "./package.json"
|
||||
);
|
||||
// 15 named feature subpaths (root "." is excluded by filter).
|
||||
expect(subs.length).toBe(15);
|
||||
});
|
||||
|
||||
it("every impl .ts has a sibling .md", { timeout: 5000 }, () => {
|
||||
const missing: string[] = [];
|
||||
for (const file of walk(srcRoot)) {
|
||||
if (!file.endsWith(".ts")) continue;
|
||||
if (
|
||||
file.endsWith(".test.ts") ||
|
||||
file.endsWith(".spec.ts") ||
|
||||
file.endsWith(".types.ts") ||
|
||||
file.endsWith("/index.ts")
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const md = file.replace(/\.ts$/, ".md");
|
||||
try {
|
||||
statSync(md);
|
||||
} catch {
|
||||
missing.push(md);
|
||||
}
|
||||
}
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
|
||||
it("every schemas/routes/<name>.ts has a sibling .md", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const routesDir = join(srcRoot, "schemas", "routes");
|
||||
const missing: string[] = [];
|
||||
for (const entry of readdirSync(routesDir)) {
|
||||
if (!entry.endsWith(".ts")) continue;
|
||||
if (
|
||||
entry === "index.ts" ||
|
||||
entry.endsWith(".test.ts") ||
|
||||
entry.endsWith(".types.ts")
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const md = join(routesDir, entry.replace(/\.ts$/, ".md"));
|
||||
try {
|
||||
statSync(md);
|
||||
} catch {
|
||||
missing.push(md);
|
||||
}
|
||||
}
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
|
||||
it("README.md is present at package root", { timeout: 5000 }, () => {
|
||||
const readme = readFileSync(join(pkgRoot, "README.md"), "utf8");
|
||||
expect(readme.length).toBeGreaterThan(200);
|
||||
expect(readme).toContain("@suaveplan/api-plugin-auth");
|
||||
});
|
||||
|
||||
it("every subpath export resolves to a file within src/", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const pkg = JSON.parse(
|
||||
readFileSync(join(pkgRoot, "package.json"), "utf8")
|
||||
) as {
|
||||
exports: Record<string, { import?: { default?: string } } | string>;
|
||||
};
|
||||
const missing: string[] = [];
|
||||
for (const [sub, val] of Object.entries(pkg.exports)) {
|
||||
if (sub === "./package.json") continue;
|
||||
const defaultPath =
|
||||
typeof val === "string"
|
||||
? val
|
||||
: (val?.import?.default ?? undefined);
|
||||
if (defaultPath === undefined) continue;
|
||||
// dist/<rel>.js → src/<rel>.ts
|
||||
const rel = defaultPath
|
||||
.replace(/^\.\/dist\//, "")
|
||||
.replace(/\.js$/, ".ts");
|
||||
const srcPath = join(srcRoot, rel);
|
||||
try {
|
||||
statSync(srcPath);
|
||||
} catch {
|
||||
missing.push(`${sub} → ${srcPath}`);
|
||||
}
|
||||
}
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user