fix(db): recognize postgres int8 as a number type in migration diffs (#10719)

Co-authored-by: Taesu <166604494+bytaesu@users.noreply.github.com>
This commit is contained in:
Manuel Lautenschlager
2026-10-15 14:22:32 +00:00
committed by GitHub
co-authored by Taesu
parent b734a418bf
commit bd65db02c1
3 changed files with 65 additions and 1 deletions
@@ -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.
@@ -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([]);
});
});
@@ -44,6 +44,7 @@ const postgresMap = {
string: ["character varying", "varchar", "text", "uuid"],
number: [
"int4",
"int8",
"integer",
"bigint",
"smallint",