import { describe, expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { buildRouter } from "../src/index.ts"; const root = join(import.meta.dir, ".tmp-services"); mkdirSync(root, { recursive: true }); function makeApp(): string { const base = mkdtempSync(join(root, "app-")); mkdirSync(join(base, "app", "pages"), { recursive: true }); return join(base, "app"); } describe("service discovery", () => { test("discovers source services and skips generated files", () => { const appDir = makeApp(); const services = join(appDir, "services"); mkdirSync(services, { recursive: true }); writeFileSync(join(services, "billing.ts"), "export default {};"); writeFileSync(join(services, "types.gen.ts"), "export type T = string;"); expect(buildRouter(appDir).services.map((service) => service.name)).toEqual(["billing"]); }); test("throws naming both files when two services collide on name", () => { const appDir = makeApp(); const services = join(appDir, "services"); const nested = join(services, "legacy"); mkdirSync(nested, { recursive: true }); const top = join(services, "billing.ts"); const shadow = join(nested, "billing.ts"); writeFileSync(top, "export default {};"); writeFileSync(shadow, "export default {};"); expect(() => buildRouter(appDir)).toThrow(/WRN-SERVICE-COLLISION/); try { buildRouter(appDir); } catch (error) { const message = (error as Error).message; expect(message).toContain(top); expect(message).toContain(shadow); } }); test("unsafe service names are skipped with a warning", () => { const appDir = makeApp(); const services = join(appDir, "services"); mkdirSync(services, { recursive: true }); writeFileSync(join(services, "bad name.ts"), "export default {};"); const originalWarn = console.warn; let warned = false; console.warn = (...args: unknown[]) => { if (String(args[0]).includes("skipping service with unsafe name")) warned = true; }; try { expect(buildRouter(appDir).services).toEqual([]); expect(warned).toBe(true); } finally { console.warn = originalWarn; } }); test("a missing services directory yields []", () => { const appDir = makeApp(); expect(buildRouter(appDir).services).toEqual([]); }); test("discovers .js service files", () => { const appDir = makeApp(); const services = join(appDir, "services"); mkdirSync(services, { recursive: true }); writeFileSync(join(services, "reports.js"), "export default {};"); expect(buildRouter(appDir).services.map((service) => service.name)).toEqual(["reports"]); }); });