import { alias, getTableConfig, integer } from "drizzle-orm/pg-core"; import { describe, expect, it } from "vitest"; import { moduleTableName, parseModuleSchemaDefinition, physicalModuleTableNameSchema, } from "../src/index.js"; import { pgTable } from "drizzle-orm/pg-core"; describe("module schema contract", () => { it("creates deterministic physical names from module and local identifiers", () => { expect(moduleTableName("calendar", "events")).toBe("calendar_events"); expect(moduleTableName("care-team", "member_notes")).toBe("care_team_member_notes"); }); it("rejects unsafe logical names and PostgreSQL identifiers beyond 63 characters", () => { expect(() => moduleTableName("calendar", "EventItems")).toThrow(); expect(() => moduleTableName("calendar", "event-items")).toThrow(); expect(physicalModuleTableNameSchema.safeParse("a".repeat(63)).success).toBe(true); expect(physicalModuleTableNameSchema.safeParse("a".repeat(64)).success).toBe(false); expect(() => moduleTableName("a".repeat(60), "rows")).toThrow( "The namespaced PostgreSQL table name is invalid or too long.", ); }); it("normalizes and freezes a typed schema definition without freezing its tables", () => { const records = pgTable("example_records", { id: integer().primaryKey() }); const definition = parseModuleSchemaDefinition({ moduleId: "example", tables: { records }, }); expect(definition.tables.records).toBe(records); expect(getTableConfig(records).name).toBe("example_records"); expect(Object.isFrozen(definition)).toBe(true); expect(Object.isFrozen(definition.tables)).toBe(true); expect(Object.isFrozen(records)).toBe(false); }); it("rejects malformed, empty, unknown, and non-PostgreSQL table definitions", () => { const records = pgTable("example_records", { id: integer() }); const disguisedRecords = alias(records, "example_disguised_records"); expect(() => parseModuleSchemaDefinition({ moduleId: "example", tables: {} })).toThrow(); expect(() => parseModuleSchemaDefinition({ moduleId: "example", tables: { records: {} } }), ).toThrow(); expect(() => parseModuleSchemaDefinition({ moduleId: "example", tables: { records }, extra: true }), ).toThrow(); expect(() => parseModuleSchemaDefinition({ moduleId: "example", tables: { disguisedRecords } }), ).toThrow(); }); });