UNPKG

claudes-office

Version:

CLI tool to initialize Claude's office in your project

261 lines 9.23 kB
"use strict"; /** * Backup system utilities for the update command * These utilities help create, manage and restore backups */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createBackup = createBackup; exports.restoreBackup = restoreBackup; exports.listBackups = listBackups; exports.deleteBackup = deleteBackup; exports.cleanupOldBackups = cleanupOldBackups; exports.formatBackupSize = formatBackupSize; const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const crypto = __importStar(require("crypto")); const archiver_1 = __importDefault(require("archiver")); const extract_zip_1 = __importDefault(require("extract-zip")); /** * Create a backup of a directory * @param sourceDir - Directory to backup * @param options - Backup options * @returns Information about the created backup */ async function createBackup(sourceDir, options = {}) { // Create a unique ID for this backup const timestamp = Date.now(); const randomPart = crypto.randomBytes(4).toString('hex'); const backupId = `backup-${timestamp}-${randomPart}`; // Determine backup name const backupName = options.name || `backup-${new Date().toISOString().replace(/:/g, '-')}`; // Determine backup directory const backupDir = options.backupDir || path.join(sourceDir, '.backups'); await fs.ensureDir(backupDir); // Create backup file path const backupPath = path.join(backupDir, `${backupName}.zip`); // Create a zip archive const output = fs.createWriteStream(backupPath); const archive = (0, archiver_1.default)('zip', { zlib: { level: 9 }, // Maximum compression }); // Listen for archive events await new Promise((resolve, reject) => { output.on('close', () => { resolve(); }); archive.on('error', (err) => { reject(err); }); // Pipe archive data to the file archive.pipe(output); // Add files to the archive if (options.include && options.include.length > 0) { // Only include specified files/directories for (const includePath of options.include) { const fullPath = path.join(sourceDir, includePath); const isDir = fs.statSync(fullPath).isDirectory(); if (isDir) { archive.directory(fullPath, includePath); } else { archive.file(fullPath, { name: includePath }); } } } else { // Include everything except excluded files archive.glob('**/*', { cwd: sourceDir, ignore: options.exclude || [], dot: true, // Include hidden files/directories }, { prefix: '' }); } // Finalize the archive archive.finalize(); }); // Get file size const stats = await fs.stat(backupPath); // Return backup info return { id: backupId, name: backupName, path: backupPath, createdAt: new Date(timestamp), size: stats.size, }; } /** * Restore a backup to a directory * @param backupPath - Path to the backup file * @param destDir - Directory to restore to * @param overwrite - Whether to overwrite existing files * @returns Whether the restoration was successful */ async function restoreBackup(backupPath, destDir, overwrite = false) { try { // Check if backup file exists if (!await fs.pathExists(backupPath)) { throw new Error(`Backup file not found: ${backupPath}`); } // Check if destination directory exists await fs.ensureDir(destDir); // If not overwriting, check if destination has files if (!overwrite) { const entries = await fs.readdir(destDir); if (entries.length > 0) { throw new Error('Destination directory is not empty and overwrite is not enabled'); } } // Extract the zip archive await (0, extract_zip_1.default)(backupPath, { dir: destDir }); return true; } catch (error) { console.error('Error restoring backup:', error); return false; } } /** * List all backups in a directory * @param backupDir - Directory containing backups * @returns Array of backup information */ async function listBackups(backupDir) { try { // Check if backup directory exists if (!await fs.pathExists(backupDir)) { return []; } // Get all zip files in the backup directory const files = await fs.readdir(backupDir); const backupFiles = files.filter(file => file.endsWith('.zip')); // Get information about each backup const backups = []; for (const file of backupFiles) { const backupPath = path.join(backupDir, file); const stats = await fs.stat(backupPath); // Extract backup ID and name from filename const backupName = file.replace(/\.zip$/, ''); // Create unique ID from file path and timestamp const fileHash = crypto.createHash('md5').update(backupPath).digest('hex').slice(0, 8); const timestamp = stats.mtimeMs; const backupId = `backup-${timestamp}-${fileHash}`; backups.push({ id: backupId, name: backupName, path: backupPath, createdAt: stats.mtime, size: stats.size, }); } // Sort by creation time (newest first) backups.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()); return backups; } catch (error) { console.error('Error listing backups:', error); return []; } } /** * Delete a backup * @param backupPath - Path to the backup file * @returns Whether the deletion was successful */ async function deleteBackup(backupPath) { try { // Check if backup file exists if (!await fs.pathExists(backupPath)) { return false; } // Delete the backup file await fs.unlink(backupPath); return true; } catch (error) { console.error('Error deleting backup:', error); return false; } } /** * Delete old backups exceeding a limit * @param backupDir - Directory containing backups * @param limit - Maximum number of backups to keep * @returns Number of backups deleted */ async function cleanupOldBackups(backupDir, limit) { try { // Get all backups const backups = await listBackups(backupDir); // If we're under the limit, do nothing if (backups.length <= limit) { return 0; } // Delete the oldest backups const backupsToDelete = backups.slice(limit); let deletedCount = 0; for (const backup of backupsToDelete) { const success = await deleteBackup(backup.path); if (success) { deletedCount++; } } return deletedCount; } catch (error) { console.error('Error cleaning up old backups:', error); return 0; } } /** * Format backup size for display * @param size - Size in bytes * @returns Formatted size string */ function formatBackupSize(size) { const units = ['B', 'KB', 'MB', 'GB', 'TB']; let index = 0; let formattedSize = size; while (formattedSize >= 1024 && index < units.length - 1) { formattedSize /= 1024; index++; } return `${formattedSize.toFixed(2)} ${units[index]}`; } //# sourceMappingURL=backupSystem.js.map