From bd65db02c1e7c854dc6090bd1e3885fc0cd55ec8 Mon Sep 17 00:00:00 2001 From: Manuel Lautenschlager Date: Thu, 15 Oct 2026 14:22:32 +0000 Subject: [PATCH] fix(db): recognize postgres int8 as a number type in migration diffs (#10719) Co-authored-by: Taesu <166604494+bytaesu@users.noreply.github.com> --- .changeset/postgres-int8-migration-diff.md | 5 ++ .../src/db/get-migration-schema.test.ts | 60 ++++++++++++++++++- packages/better-auth/src/db/get-migration.ts | 1 + 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 .changeset/postgres-int8-migration-diff.md diff --git a/.changeset/postgres-int8-migration-diff.md b/.changeset/postgres-int8-migration-diff.md new file mode 100644 index 0000000000..563b20efda --- /dev/null +++ b/.changeset/postgres-int8-migration-diff.md @@ -0,0 +1,5 @@ +--- +"better-auth": patch +--- + +Recognize PostgreSQL `int8` as a valid number type in migration diffs. Kysely's introspector reports `pg_type.typname`, so Better Auth's own `bigint` columns (such as the database-backed rate limiter's `lastRequest`) came back as `int8` and were reported as a type mismatch on every run. diff --git a/packages/better-auth/src/db/get-migration-schema.test.ts b/packages/better-auth/src/db/get-migration-schema.test.ts index 23c752a007..514ecbe875 100644 --- a/packages/better-auth/src/db/get-migration-schema.test.ts +++ b/packages/better-auth/src/db/get-migration-schema.test.ts @@ -12,7 +12,7 @@ import { it, } from "vitest"; import { betterAuth } from "../auth/full"; -import { getMigrations } from "./get-migration"; +import { getMigrations, matchType } from "./get-migration"; const CONNECTION_STRING = "postgres://user:password@localhost:5433/better_auth"; // Check if PostgreSQL is available @@ -928,3 +928,61 @@ describe.runIf(isPostgresAvailable)("PostgreSQL configured schema name", () => { expect(await compileMigrations()).toEqual(";"); }); }); + +describe("matchType", () => { + /** + * @see https://github.com/better-auth/better-auth/issues/10718 + * + * Kysely's PostgreSQL introspector reports `pg_type.typname`, so a + * `bigint` column comes back as `int8` — the name the acceptable-types + * map has to carry for the diff to recognize Better Auth's own + * `rateLimit.lastRequest` column. + */ + it("should accept the pg_type name Kysely reports for a bigint column", () => { + expect(matchType("int8", "number", "postgres")).toBe(true); + }); + + it("should still accept the spelled-out bigint name", () => { + expect(matchType("bigint", "number", "postgres")).toBe(true); + }); +}); + +/** + * @see https://github.com/better-auth/better-auth/issues/10718 + */ +describe.runIf(isPostgresAvailable)("PostgreSQL rate limit schema diff", () => { + const pool = new Pool({ connectionString: CONNECTION_STRING }); + const dropTables = `DROP TABLE IF EXISTS public."rateLimit" CASCADE; DROP TABLE IF EXISTS public.session CASCADE; DROP TABLE IF EXISTS public.account CASCADE; DROP TABLE IF EXISTS public.verification CASCADE; DROP TABLE IF EXISTS public."user" CASCADE;`; + + beforeAll(async () => { + await pool.query(dropTables); + }); + + afterAll(async () => { + await pool.query(dropTables); + await pool.end(); + }); + + it("should not warn about its own bigint lastRequest column on a subsequent run", async () => { + const warnings: string[] = []; + const config: BetterAuthOptions = { + database: pool, + rateLimit: { + storage: "database", + }, + logger: { + log: (level, message) => { + if (level === "warn") warnings.push(message); + }, + }, + }; + + const initial = await getMigrations(config); + await initial.runMigrations(); + + const second = await getMigrations(config); + expect(second.toBeCreated.length).toBe(0); + expect(second.toBeAdded.length).toBe(0); + expect(warnings.filter((w) => w.includes("lastRequest"))).toEqual([]); + }); +}); diff --git a/packages/better-auth/src/db/get-migration.ts b/packages/better-auth/src/db/get-migration.ts index 028c961ad2..7a204e114a 100644 --- a/packages/better-auth/src/db/get-migration.ts +++ b/packages/better-auth/src/db/get-migration.ts @@ -44,6 +44,7 @@ const postgresMap = { string: ["character varying", "varchar", "text", "uuid"], number: [ "int4", + "int8", "integer", "bigint", "smallint",