🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
209 lines
6.1 KiB
JavaScript
Executable File
209 lines
6.1 KiB
JavaScript
Executable File
#!/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); |