/** * Database Migration * * Runs drizzle-kit migrations from the drizzle/ directory. * Safe to call on every startup - only applies pending migrations. */ import { migrate } from 'drizzle-orm/better-sqlite3/migrator'; import { join, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import { existsSync } from 'node:fs'; import type { DrizzleDatabase } from './index.js'; import { createModuleLogger } from '../logger/index.js'; const log = createModuleLogger('db'); /** * Resolve the migrations directory relative to the package root. * Works both in development (src/) and after build (dist/). */ function getMigrationsPath(): string { const currentDir = dirname(fileURLToPath(import.meta.url)); // In dev (tsx): apps/server/db/ — need 3 levels up to workspace root // In dist (tsc): dist/db/ — need 2 levels up to workspace root const upThree = join(currentDir, '..', '..', '..', 'drizzle'); if (existsSync(upThree)) return upThree; return join(currentDir, '..', '..', 'drizzle'); } /** * Run all pending database migrations. * * Uses drizzle-kit's migration system which tracks applied migrations * in a __drizzle_migrations table. Safe to call on every startup. * * @param db - Drizzle database instance */ export function ensureSchema(db: DrizzleDatabase): void { log.info('applying database migrations'); migrate(db, { migrationsFolder: getMigrationsPath() }); log.info('database migrations complete'); }