import { describe, expect, it, vi } from "vitest"; const poolConstructor = vi.hoisted(() => vi.fn()); vi.mock("pg", () => ({ Pool: poolConstructor })); import { createIdentityDrizzleDatabase, IdentityDatabaseError } from "../src/identity/database.js"; describe("Core identity Drizzle database composition", () => { it("does not construct a pool merely because the module is imported", () => { expect(poolConstructor).not.toHaveBeenCalled(); }); it.each([ "", " ", "not-a-database-url", "https://admin:do-not-log@db.example.test/database", ])("rejects an invalid connection string without exposing it (%s)", (connectionString) => { let captured: unknown; try { createIdentityDrizzleDatabase(connectionString); } catch (error) { captured = error; } expect(captured).toBeInstanceOf(IdentityDatabaseError); expect(captured).toMatchObject({ code: "IDENTITY_DATABASE_CONFIGURATION_INVALID" }); const publicText = `${String(captured)}\n${ captured instanceof Error ? (captured.stack ?? "") : "" }`; if (connectionString) { expect(publicText).not.toContain(connectionString); } expect(poolConstructor).not.toHaveBeenCalled(); }); it("explicitly constructs the pool only when called, with the identity schema attached", () => { poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on: vi.fn() }; }); const handle = createIdentityDrizzleDatabase( "postgresql://operator:do-not-log@example.test/ekklesia", ); expect(poolConstructor).toHaveBeenCalledTimes(1); expect(handle.db).toBeDefined(); expect(typeof handle.close).toBe("function"); expect(Object.isFrozen(handle)).toBe(true); }); it("passes the connection timeout through to the pool configuration", () => { poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on: vi.fn() }; }); poolConstructor.mockClear(); createIdentityDrizzleDatabase("postgresql://example.test/ekklesia", { connectionTimeoutMs: 5_000, }); expect(poolConstructor).toHaveBeenCalledWith( expect.objectContaining({ connectionTimeoutMillis: 5_000 }), ); }); it("passes the operation timeout through to the pool configuration as both query_timeout and statement_timeout", () => { poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on: vi.fn() }; }); poolConstructor.mockClear(); createIdentityDrizzleDatabase("postgresql://example.test/ekklesia", { operationTimeoutMs: 7_500, }); expect(poolConstructor).toHaveBeenCalledWith( expect.objectContaining({ query_timeout: 7_500, statement_timeout: 7_500 }), ); }); it("does not set query_timeout, statement_timeout, or connectionTimeoutMillis when no timeout is configured", () => { poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on: vi.fn() }; }); poolConstructor.mockClear(); createIdentityDrizzleDatabase("postgresql://example.test/ekklesia"); const [poolConfig] = poolConstructor.mock.calls[0] as [Record]; expect(poolConfig).not.toHaveProperty("query_timeout"); expect(poolConfig).not.toHaveProperty("statement_timeout"); expect(poolConfig).not.toHaveProperty("connectionTimeoutMillis"); }); it.each([ ["operationTimeoutMs", 0], ["operationTimeoutMs", -1], ["operationTimeoutMs", Number.NaN], ["operationTimeoutMs", 1.5], ["operationTimeoutMs", 2_147_483_648], ["connectionTimeoutMs", 0], ["connectionTimeoutMs", -1], ["connectionTimeoutMs", Number.NaN], ] as const)("rejects an invalid %s (%s) without constructing a pool and without leaking the value", (optionName, value) => { poolConstructor.mockClear(); let captured: unknown; try { createIdentityDrizzleDatabase("postgresql://example.test/ekklesia", { [optionName]: value, }); } catch (error) { captured = error; } expect(captured).toBeInstanceOf(IdentityDatabaseError); expect(captured).toMatchObject({ code: "IDENTITY_DATABASE_CONFIGURATION_INVALID" }); const publicText = `${String(captured)}\n${ captured instanceof Error ? (captured.stack ?? "") : "" }`; expect(publicText).not.toContain(String(value)); expect(poolConstructor).not.toHaveBeenCalled(); }); it("registers a pool-level error listener so an idle client failure never becomes an uncaught exception", () => { const on = vi.fn(); poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on }; }); createIdentityDrizzleDatabase("postgresql://example.test/ekklesia"); expect(on).toHaveBeenCalledWith("error", expect.any(Function)); const handler = on.mock.calls.find((call) => call[0] === "error")?.[1] as | ((error: unknown) => void) | undefined; expect(() => handler?.(new Error("terminating connection due to administrator command")), ).not.toThrow(); }); });