// The module's migrations are its own files, each exactly `schemaStatements()` over the entities it // added (decision AT-D20: the entity definition is the one source of a column). Forward-only: the // first file stays the ledger's as first shipped, the revocation outbox is the second, and the // ledger's step record (`steps`, `provider`) is the third, two added columns. All global tables: an // account and an app session belong to no organization, so they carry no tenant column and no policy. import { readFileSync } from "node:fs" import { schemaStatements } from "@conusai-kit/data-kysely" import { describe, expect, it } from "vitest" import { ACCOUNT_ENTITIES, accountDeletions, accountModule, accountSessionRevocations } from "../index.js" function tablesOf(entities: Parameters[0]): string { const kernel = schemaStatements([]).length return `${schemaStatements(entities) .slice(kernel) .map((statement) => `${statement};`) .join("\n\n")}\n` } describe("the migration of the account module", () => { const migration = (name: string) => readFileSync(new URL(`../migrations/${name}`, import.meta.url), "utf8") // A migration that has run is never edited: the columns added since are a file of their own, and // the files together are exactly the entity. it("is its own file, the ledger table as first shipped, and a third file adds the step record", () => { const added = ',\n "steps" jsonb,\n "provider" text\n' const generated = tablesOf([accountDeletions]) expect(generated).toContain(added) expect(generated.replace(added, "\n")).toBe(migration("0001_account.sql")) expect(migration("0003_deletion_steps.sql")).toBe( 'alter table "account_deletion" add column "steps" jsonb;\n\nalter table "account_deletion" add column "provider" text;\n', ) }) it("adds the revocation outbox in a second file, exactly its table", async () => { await expect(tablesOf([accountSessionRevocations])).toMatchFileSnapshot("../migrations/0002_session_revocation.sql") expect(ACCOUNT_ENTITIES).toEqual([accountDeletions, accountSessionRevocations]) const sql = readFileSync(new URL("../migrations/0002_session_revocation.sql", import.meta.url), "utf8") expect(sql).not.toContain("org_id") }) it("is declared by the manifest for Postgres; on Convex the schema comes from the same entities", () => { expect(accountModule.migrations).toEqual({ postgres: "migrations" }) expect(accountModule.profiles).toEqual(["postgres", "convex"]) const sql = readFileSync(new URL("../migrations/0001_account.sql", import.meta.url), "utf8") expect(sql).toContain('create table "account_deletion"') expect(sql).not.toContain("org_id") }) })