Spaces:
Sleeping
Sleeping
File size: 6,533 Bytes
da819ac |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
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(); |