import { applyMigrations, listMigrations, readAppliedRows, stampMigration, } from './migrate.js'; export function runMigrateCli(opts) { const stdout = opts.stdout ?? process.stdout; const stderr = opts.stderr ?? process.stderr; if (opts.command === 'stamp') { if (!opts.version) { stderr.write('error: version required\n'); return 1; } const db = opts.openDb(); try { const file = stampMigration(db, opts.migrationsDir, opts.version); stdout.write(`stamped:${file.version}\n`); db.close(); return 0; } catch (err) { const msg = err instanceof Error ? err.message : String(err); stderr.write(`error: ${msg}\n`); db.close(); return 1; } } if (opts.command === 'status') { const db = opts.openDb(); const files = listMigrations(opts.migrationsDir); const appliedByVersion = new Map(readAppliedRows(db).map((r) => [r.version, r])); let exitCode = 0; const pending = []; const mismatched = []; for (const file of files) { const applied = appliedByVersion.get(file.version); if (!applied) { pending.push(file.version); stdout.write(`pending:${file.version}\n`); continue; } if (applied.checksum !== file.checksum) { mismatched.push(file.version); stdout.write(`checksum-mismatch:${file.version}\n`); exitCode = 2; continue; } stdout.write(`applied:${file.version}\n`); } if (pending.length === 0 && mismatched.length === 0) { stdout.write(`pending:none\n`); } db.close(); return exitCode; } // migrate const db = opts.openDb(); const summary = applyMigrations(db, opts.migrationsDir, { stampGenesis: opts.stampGenesis, genesisProbeTable: opts.genesisProbeTable, logger: (msg) => stdout.write(`${msg}\n`), }); if (summary.stamped.length > 0) { stdout.write(`stamped:${summary.stamped.join(',')}\n`); } if (summary.applied === 0 && summary.stamped.length === 0) { stdout.write(`pending:none\n`); } else if (summary.applied > 0) { stdout.write(`applied:${summary.applied}\n`); } stdout.write(`migrations: ${summary.applied + summary.alreadyApplied} applied, ${summary.pending} pending\n`); db.close(); return 0; }