const { logger } = require('@nexusai/shared'); // Forward-only schema migrations. Entry i takes the database from user_version i // to i+1, so migrations[0] is the v0→v1 step, migrations[1] the v1→v2 step, etc. // // schema.js already holds the COMPLETE current shape, so a fresh database is // created whole and stamped straight to LATEST_VERSION — these run only to carry // an OLDER database forward. Add a new schema change by appending a function here // (which bumps LATEST_VERSION by one); never edit an existing entry once shipped, // since databases already stamped past it will not re-run it. // // Each migration receives the better-sqlite3 db handle and runs inside a // transaction together with its version bump, so a failure rolls back cleanly. const migrations = [ // v0 → v1: baseline. The historical ALTER TABLE / CREATE INDEX statements that // used to run (wrapped in try/catch) on every boot are folded into schema.js. // Nothing to do here — this entry exists to mark v1 as the consolidated baseline. (_db) => {}, ]; const LATEST_VERSION = migrations.length; // Applies any migrations newer than the database's current user_version, one at a // time, each with its version bump, inside a transaction. Returns the resulting // version. A no-op when the database is already current. The migrations list and // target version are injectable for testing; production callers pass just `db`. function migrate(db, migs = migrations, latest = migs.length) { const current = db.pragma('user_version', { simple: true }); if (current >= latest) return current; for (let v = current; v < latest; v++) { const step = db.transaction(() => { migs[v](db); db.pragma(`user_version = ${v + 1}`); }); step(); } logger.info(`[db] schema migrated ${current} -> ${latest}`); return latest; } module.exports = { migrate, migrations, LATEST_VERSION };