Spaces:
Sleeping
Sleeping
| 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(); |