All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 1m16s
- Add noteHistoryMode setting (manual default / auto) with DB migration - Manual mode: commit button in editor toolbar creates snapshots on demand - Auto mode: smart snapshots with 20-char diff threshold + 5min cooldown, structural changes (color, pin, archive, labels) bypass cooldown - Add delete individual history entries from history modal - Fix sidebar: Notes nav no longer active on notebook pages - Fix sidebar icon: replace filled Lightbulb with outlined FileText - Fix title suggestions: change from amber to sky blue color scheme - Fix hydration mismatch: add suppressHydrationWarning on locale dates - Complete i18n: add history, sort, and AI chat translations for all 16 languages - Translate French AI assistant section (40+ keys) from English to French - Update README with new features and stack info Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
77 lines
2.9 KiB
JavaScript
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')
|