Fix Postgres Better Auth migration index SQL

This commit is contained in:
2026-02-24 15:44:09 -05:00
parent 468ea5f252
commit 44bc53820f

View File

@@ -21,6 +21,67 @@ function parseCsvList(value: string | undefined) {
.filter((entry) => entry.length > 0);
}
function isPostgresConnectionString(value: string | undefined) {
if (!value) {
return false;
}
try {
const protocol = new URL(value).protocol.toLowerCase();
return protocol === 'postgres:' || protocol === 'postgresql:';
} catch {
return /^postgres(?:ql)?:\/\//i.test(value);
}
}
function splitSqlStatements(sqlText: string) {
return sqlText
.split(';')
.map((statement) => statement.trim())
.filter((statement) => statement.length > 0);
}
function buildPostgresMigrationPlan(sqlText: string) {
const immediateStatements: string[] = [];
const deferredIndexStatements: string[] = [];
const addIndexPattern = /^alter table\s+([^\s]+)\s+add\s+index\s+([^\s]+)\s+\((.+)\)$/i;
for (const rawStatement of splitSqlStatements(sqlText)) {
const statement = rawStatement.replace(/\s+/g, ' ').trim();
const match = statement.match(addIndexPattern);
if (!match) {
immediateStatements.push(statement);
continue;
}
const [, tableName, indexName, columns] = match;
deferredIndexStatements.push(`create index if not exists ${indexName} on ${tableName} (${columns})`);
}
return [...immediateStatements, ...deferredIndexStatements];
}
async function runPostgresMigrations(pool: Pool, sqlText: string) {
const statements = buildPostgresMigrationPlan(sqlText);
if (statements.length === 0) {
return;
}
const client = await pool.connect();
try {
await client.query('BEGIN');
for (const statement of statements) {
await client.query(statement);
}
await client.query('COMMIT');
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}
}
function getPool() {
const connectionString = process.env.DATABASE_URL?.trim();
if (!connectionString) {
@@ -73,11 +134,18 @@ export function getAuth() {
export async function ensureAuthSchema() {
const auth = getAuth();
const connectionString = process.env.DATABASE_URL?.trim();
if (!migrationPromise) {
migrationPromise = (async () => {
const { runMigrations } = await getMigrations(auth.options);
await runMigrations();
const migrations = await getMigrations(auth.options);
if (isPostgresConnectionString(connectionString)) {
const sql = await migrations.compileMigrations();
await runPostgresMigrations(getPool(), sql);
return;
}
await migrations.runMigrations();
})();
}