import { describe, expect, it } from "vitest"; import { DRIZZLE_MIGRATION_ORIGIN_UUID, moduleMigrationTagSchema, parseDrizzleMigrationJournal, parseDrizzleMigrationSnapshotHeader, parseModuleMigrationPolicy, } from "../src/index.js"; describe("module migration contracts", () => { it("parses the supported stable Drizzle PostgreSQL journal format", () => { const journal = parseDrizzleMigrationJournal({ version: "7", dialect: "postgresql", entries: [ { idx: 0, version: "7", when: 1_750_000_000_000, tag: "0000_initial", breakpoints: true, }, ], }); expect(journal.entries[0]?.tag).toBe("0000_initial"); }); it("rejects unsupported journal versions, dialects, and unknown metadata", () => { const base = { version: "7", dialect: "postgresql", entries: [ { idx: 0, version: "7", when: 1, tag: "0000_initial", breakpoints: true, }, ], }; expect(() => parseDrizzleMigrationJournal({ ...base, version: "8" })).toThrow(); expect(() => parseDrizzleMigrationJournal({ ...base, dialect: "sqlite" })).toThrow(); expect(() => parseDrizzleMigrationJournal({ ...base, extra: true })).toThrow(); }); it("parses snapshot identity metadata while allowing Drizzle's schema payload", () => { const snapshot = parseDrizzleMigrationSnapshotHeader({ version: "7", dialect: "postgresql", id: "10000000-0000-4000-8000-000000000001", prevId: DRIZZLE_MIGRATION_ORIGIN_UUID, tables: {}, _meta: { tables: {}, schemas: {}, columns: {} }, }); expect(snapshot.prevId).toBe(DRIZZLE_MIGRATION_ORIGIN_UUID); }); it("requires explicit non-destructive or approval-required policy declarations", () => { expect( parseModuleMigrationPolicy({ version: 1, moduleId: "calendar", entries: [ { tag: "0000_initial", destructive: { mode: "none" } }, { tag: "0001_remove_legacy", destructive: { mode: "approval-required", reason: "Removes a legacy column." }, }, ], }).entries, ).toHaveLength(2); expect(() => parseModuleMigrationPolicy({ version: 1, moduleId: "calendar", entries: [ { tag: "0000_initial", destructive: { mode: "approval-required", reason: "Drops data.", approved: true }, }, ], }), ).toThrow(); }); it.each([ "../outside", "/absolute", "0000_nested/name", "0000_back\\slash", "0000_already.sql", "0000_Uppercase", ])("rejects unsafe migration tag %s", (tag) => { expect(moduleMigrationTagSchema.safeParse(tag).success).toBe(false); }); });