Files
blackcanyontickets/scripts/backup.js
2025-07-08 12:31:31 -06:00

209 lines
6.1 KiB
JavaScript
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* Backup management script
* Usage: node scripts/backup.js <command> [options]
*/
const { backupManager, backupScheduler, DisasterRecovery } = require('../src/lib/backup.ts');
// Parse command line arguments
const args = process.argv.slice(2);
const command = args[0];
async function main() {
try {
switch (command) {
case 'create':
await createBackup();
break;
case 'restore':
await restoreBackup();
break;
case 'list':
await listBackups();
break;
case 'cleanup':
await cleanupBackups();
break;
case 'schedule':
await startScheduler();
break;
case 'verify':
await verifyIntegrity();
break;
case 'disaster-recovery':
await createDisasterRecoveryBackup();
break;
default:
showUsage();
}
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}
}
async function createBackup() {
const type = args[1] || 'daily';
if (!['daily', 'weekly', 'monthly'].includes(type)) {
console.error('Invalid backup type. Use: daily, weekly, or monthly');
process.exit(1);
}
console.log(`Creating ${type} backup...`);
const backup = await backupManager.createBackup(type);
console.log('Backup created successfully!');
console.log(`ID: ${backup.id}`);
console.log(`Size: ${(backup.size / 1024 / 1024).toFixed(2)} MB`);
console.log(`Tables: ${backup.tables.join(', ')}`);
console.log(`Checksum: ${backup.checksum}`);
}
async function restoreBackup() {
const backupId = args[1];
const confirmFlag = args.includes('--confirm');
const dryRun = args.includes('--dry-run');
const tables = args.includes('--tables') ?
args[args.indexOf('--tables') + 1].split(',') : undefined;
if (!backupId) {
console.error('Backup ID is required');
console.log('Usage: node scripts/backup.js restore <backup-id> [--confirm] [--dry-run] [--tables table1,table2]');
process.exit(1);
}
if (!confirmFlag && !dryRun) {
console.error('WARNING: This will overwrite existing data!');
console.error('Use --confirm to proceed or --dry-run to simulate');
process.exit(1);
}
console.log(`${dryRun ? 'Simulating' : 'Starting'} restore from backup: ${backupId}`);
await backupManager.restoreBackup(backupId, {
tables,
dryRun,
confirmRestore: confirmFlag
});
console.log(`Restore ${dryRun ? 'simulation' : 'process'} completed successfully!`);
}
async function listBackups() {
console.log('Listing available backups...');
const backups = await backupManager.listBackups();
if (backups.length === 0) {
console.log('No backups found');
return;
}
console.log('\nAvailable backups:');
console.log('─'.repeat(80));
for (const backup of backups) {
const date = new Date(backup.timestamp).toLocaleString();
const size = (backup.size / 1024 / 1024).toFixed(2);
const status = backup.status === 'completed' ? '✓' :
backup.status === 'failed' ? '✗' : '⏳';
console.log(`${status} ${backup.id}`);
console.log(` Type: ${backup.type}`);
console.log(` Date: ${date}`);
console.log(` Size: ${size} MB`);
console.log(` Tables: ${backup.tables.length}`);
console.log('');
}
}
async function cleanupBackups() {
console.log('Cleaning up old backups...');
await backupManager.cleanupBackups();
console.log('Cleanup completed!');
}
async function startScheduler() {
console.log('Starting backup scheduler...');
backupScheduler.startScheduledBackups();
console.log('Backup scheduler is running. Press Ctrl+C to stop.');
// Keep the process running
process.on('SIGINT', () => {
console.log('\nStopping backup scheduler...');
backupScheduler.stopScheduledBackups();
process.exit(0);
});
// Keep alive
setInterval(() => {
console.log(`Scheduler running... ${new Date().toLocaleString()}`);
}, 60000); // Log every minute
}
async function verifyIntegrity() {
console.log('Verifying system integrity...');
const result = await DisasterRecovery.verifySystemIntegrity();
console.log(`\nSystem Status: ${result.status.toUpperCase()}`);
console.log('─'.repeat(50));
for (const check of result.checks) {
const icon = check.status === 'pass' ? '✓' : '✗';
console.log(`${icon} ${check.name}: ${check.message}`);
}
if (result.status !== 'healthy') {
console.log('\n⚠ System requires attention!');
process.exit(1);
} else {
console.log('\n✅ System is healthy');
}
}
async function createDisasterRecoveryBackup() {
const label = args[1] || `emergency-${Date.now()}`;
console.log(`Creating disaster recovery backup: ${label}`);
const backup = await DisasterRecovery.createPointInTimeBackup(label);
console.log('Disaster recovery backup created successfully!');
console.log(`ID: ${backup.id}`);
console.log(`Size: ${(backup.size / 1024 / 1024).toFixed(2)} MB`);
console.log(`Location: disaster-recovery/${label}`);
}
function showUsage() {
console.log(`
Backup Management Script
Usage: node scripts/backup.js <command> [options]
Commands:
create [type] Create a new backup (daily|weekly|monthly)
restore <id> [options] Restore from backup
list List available backups
cleanup Remove old backups according to retention policy
schedule Start automated backup scheduler
verify Verify system integrity
disaster-recovery [label] Create emergency backup
Restore options:
--confirm Confirm destructive restore operation
--dry-run Simulate restore without making changes
--tables table1,table2 Only restore specified tables
Examples:
node scripts/backup.js create daily
node scripts/backup.js restore daily-1234567890 --confirm
node scripts/backup.js restore daily-1234567890 --dry-run --tables users,events
node scripts/backup.js disaster-recovery pre-migration
node scripts/backup.js verify
`);
}
// Run the main function
main().catch(console.error);