Files
Momento/Momento-main/momento/memento-note/scripts/safe-migrate.js
Sepehr Ramezani ed807d3b2a
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 5s
Add safe database migration workflow and note history infrastructure.
This introduces guarded migrations with automatic backups, fixes note creation after DB reset, and wires snapshot/restore history across notes surfaces.
2026-04-28 17:14:26 +02:00

77 lines
2.9 KiB
JavaScript

#!/usr/bin/env node
/* eslint-disable no-console */
const fs = require('fs')
const path = require('path')
const { spawnSync } = require('child_process')
require('dotenv').config({ path: path.join(__dirname, '..', '.env') })
function run(command, args, options = {}) {
const result = spawnSync(command, args, {
stdio: 'inherit',
shell: process.platform === 'win32',
...options,
})
if (result.status !== 0) {
process.exit(result.status || 1)
}
}
function nowStamp() {
const d = new Date()
const pad = (n) => String(n).padStart(2, '0')
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}_${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`
}
const databaseUrl = process.env.DATABASE_URL
if (!databaseUrl) {
console.error('[safe-migrate] DATABASE_URL is missing in environment/.env')
process.exit(1)
}
const backupsDir = path.join(__dirname, '..', 'backups', 'migrations')
fs.mkdirSync(backupsDir, { recursive: true })
const isPostgres = databaseUrl.startsWith('postgres://') || databaseUrl.startsWith('postgresql://')
const isSqlite = databaseUrl.startsWith('file:')
console.log('[safe-migrate] Starting safe migration flow')
if (isPostgres) {
const backupFile = path.join(backupsDir, `pre_migrate_${nowStamp()}.sql`)
console.log(`[safe-migrate] Creating PostgreSQL backup: ${backupFile}`)
let dump = spawnSync(
'pg_dump',
['--no-owner', '--no-privileges', '--format=plain', '--file', backupFile, databaseUrl],
{ stdio: 'inherit', shell: process.platform === 'win32' }
)
if (dump.status !== 0) {
console.warn('[safe-migrate] Local pg_dump unavailable, trying Docker fallback...')
const pgUser = process.env.POSTGRES_USER || 'memento'
const pgDb = process.env.POSTGRES_DB || 'memento'
const dockerCmd = `docker exec memento-postgres pg_dump -U ${pgUser} -d ${pgDb} --no-owner --no-privileges --format=plain > "${backupFile}"`
dump = spawnSync(dockerCmd, { stdio: 'inherit', shell: true })
}
if (dump.status !== 0) {
console.error('[safe-migrate] Backup failed (local + docker). Migration aborted to protect data.')
process.exit(dump.status || 1)
}
} else if (isSqlite) {
const dbPath = databaseUrl.replace(/^file:/, '')
const absoluteDbPath = path.isAbsolute(dbPath) ? dbPath : path.join(__dirname, '..', dbPath)
if (fs.existsSync(absoluteDbPath)) {
const backupFile = path.join(backupsDir, `pre_migrate_${nowStamp()}.sqlite`)
console.log(`[safe-migrate] Creating SQLite backup: ${backupFile}`)
fs.copyFileSync(absoluteDbPath, backupFile)
} else {
console.warn(`[safe-migrate] SQLite file not found at ${absoluteDbPath}, skipping backup`)
}
} else {
console.warn('[safe-migrate] Unknown DATABASE_URL protocol, skipping backup step')
}
console.log('[safe-migrate] Applying migrations with prisma migrate deploy')
run('npx', ['prisma', 'migrate', 'deploy'])
console.log('[safe-migrate] Migration completed successfully')