Some checks failed
Deploy to Production / deploy (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
import fs from 'fs'
|
|
import path from 'path'
|
|
import { db } from './db'
|
|
|
|
export async function runMigrations() {
|
|
const migrationsDir = path.join(process.cwd(), 'migrations')
|
|
|
|
// Create migrations tracking table
|
|
await db.query(`
|
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL UNIQUE,
|
|
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
)
|
|
`)
|
|
|
|
const files = fs.readdirSync(migrationsDir)
|
|
.filter(f => f.endsWith('.sql') && !f.startsWith('._'))
|
|
.sort()
|
|
|
|
for (const file of files) {
|
|
const { rows } = await db.query(
|
|
'SELECT id FROM _migrations WHERE name = $1',
|
|
[file],
|
|
)
|
|
if (rows.length > 0) continue // already applied
|
|
|
|
const sql = fs.readFileSync(path.join(migrationsDir, file), 'utf8')
|
|
console.log(`[migrate] Applying ${file}...`)
|
|
|
|
const client = await db.connect()
|
|
try {
|
|
await client.query('BEGIN')
|
|
await client.query(sql)
|
|
await client.query('INSERT INTO _migrations (name) VALUES ($1)', [file])
|
|
await client.query('COMMIT')
|
|
console.log(`[migrate] ✅ ${file} applied`)
|
|
} catch (err) {
|
|
await client.query('ROLLBACK')
|
|
console.error(`[migrate] ❌ ${file} failed:`, err)
|
|
throw err
|
|
} finally {
|
|
client.release()
|
|
}
|
|
}
|
|
|
|
console.log('[migrate] All migrations up to date')
|
|
}
|