const mongoose = require('mongoose'); const fs = require('fs'); const path = require('path'); // MongoDB Atlas connection const MONGODB_URI = 'mongodb+srv://nothingyu:wSg3lbO1PkHiRMq9@sandbox.ecysggv.mongodb.net/test?retryWrites=true&w=majority&appName=sandbox'; const createCompleteBackup = async () => { try { console.log('šŸ”’ Creating complete backup...'); // Connect to MongoDB await mongoose.connect(MONGODB_URI); console.log('āœ… Connected to MongoDB Atlas'); // Create backup directory with timestamp const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const backupDir = path.join(__dirname, 'backups', `complete-backup-${timestamp}`); if (!fs.existsSync(path.dirname(backupDir))) { fs.mkdirSync(path.dirname(backupDir), { recursive: true }); } fs.mkdirSync(backupDir, { recursive: true }); console.log(`šŸ“ Backup directory: ${backupDir}`); // Collections to backup const collections = [ 'users', 'sourcetexts', 'submissions', 'subtitles', 'subtitlesubmissions' ]; const backupData = {}; // Backup each collection for (const collectionName of collections) { console.log(`šŸ“¦ Backing up ${collectionName}...`); try { const collection = mongoose.connection.db.collection(collectionName); const documents = await collection.find({}).toArray(); backupData[collectionName] = documents; // Save to JSON file const filePath = path.join(backupDir, `${collectionName}.json`); fs.writeFileSync(filePath, JSON.stringify(documents, null, 2)); console.log(`āœ… ${collectionName}: ${documents.length} documents`); } catch (error) { console.log(`āš ļø Warning: Could not backup ${collectionName}: ${error.message}`); } } // Create code backup directory const codeBackupDir = path.join(backupDir, 'code'); fs.mkdirSync(codeBackupDir, { recursive: true }); // Copy key frontend files const frontendDir = path.join(codeBackupDir, 'frontend'); fs.mkdirSync(frontendDir, { recursive: true }); const frontendFiles = [ '../frontend/client/src/pages/WeeklyPractice.tsx', '../frontend/client/src/pages/TutorialTasks.tsx', '../frontend/client/src/components/Layout.tsx', '../frontend/client/src/services/api.ts' ]; for (const file of frontendFiles) { try { const sourcePath = path.join(__dirname, file); const fileName = path.basename(file); const destPath = path.join(frontendDir, fileName); if (fs.existsSync(sourcePath)) { fs.copyFileSync(sourcePath, destPath); console.log(`šŸ“„ Copied frontend: ${fileName}`); } } catch (error) { console.log(`āš ļø Warning: Could not copy ${file}: ${error.message}`); } } // Copy key backend files const backendDir = path.join(codeBackupDir, 'backend'); fs.mkdirSync(backendDir, { recursive: true }); const backendFiles = [ 'index.js', 'routes/auth.js', 'routes/subtitles.js', 'routes/subtitleSubmissions.js', 'models/SourceText.js', 'models/Subtitle.js', 'models/SubtitleSubmission.js', 'seed-atlas-subtitles.js', 'seed-subtitle-submissions.js' ]; for (const file of backendFiles) { try { const sourcePath = path.join(__dirname, file); const destPath = path.join(backendDir, file); if (fs.existsSync(sourcePath)) { // Create subdirectories if needed const destDir = path.dirname(destPath); if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } fs.copyFileSync(sourcePath, destPath); console.log(`šŸ“„ Copied backend: ${file}`); } } catch (error) { console.log(`āš ļø Warning: Could not copy ${file}: ${error.message}`); } } // Create manifest const manifest = { backupInfo: { timestamp: new Date().toISOString(), backupType: 'Complete Backup', description: 'Full backup including database collections and key code files', version: '1.0' }, database: { collections: collections, totalDocuments: Object.values(backupData).reduce((sum, docs) => sum + docs.length, 0) }, codeFiles: { frontend: frontendFiles.filter(f => fs.existsSync(path.join(__dirname, f))), backend: backendFiles.filter(f => fs.existsSync(path.join(__dirname, f))) }, features: [ 'Database collections backup', 'Key frontend components backup', 'Backend routes and models backup', 'Seed data scripts backup', 'Manifest with backup details' ], restoreInstructions: { database: 'Use the JSON files to restore collections to MongoDB', code: 'Copy the code files back to their original locations', verification: 'Check manifest.json for backup contents and details' } }; const manifestPath = path.join(backupDir, 'manifest.json'); fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2)); console.log('\nšŸŽ‰ Complete backup created successfully!'); console.log(`šŸ“ Location: ${backupDir}`); console.log(`šŸ“‹ Manifest: ${manifestPath}`); console.log(`šŸ“Š Total documents: ${manifest.database.totalDocuments}`); console.log(`šŸ“„ Code files: ${manifest.codeFiles.frontend.length + manifest.codeFiles.backend.length}`); // List backup contents console.log('\nšŸ“‹ Backup Contents:'); console.log('Database Collections:'); collections.forEach(col => { const count = backupData[col] ? backupData[col].length : 0; console.log(` - ${col}: ${count} documents`); }); console.log('\nCode Files:'); console.log('Frontend:'); manifest.codeFiles.frontend.forEach(file => { const fileName = path.basename(file); console.log(` - ${fileName}`); }); console.log('Backend:'); manifest.codeFiles.backend.forEach(file => { console.log(` - ${file}`); }); } catch (error) { console.error('āŒ Backup failed:', error); } finally { await mongoose.disconnect(); console.log('šŸ”Œ Disconnected from MongoDB'); } }; // Run backup createCompleteBackup();