102 lines
2.8 KiB
TypeScript
102 lines
2.8 KiB
TypeScript
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);
|
|
});
|
|
});
|