import Database from "better-sqlite3"; import fs from "fs"; import path from "path"; const dbPath = "data/database.sqlite"; const backupDir = "backups"; // Ensure backup directory exists if (!fs.existsSync(backupDir)) { fs.mkdirSync(backupDir); } // Generate timestamp for backup filename const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); const backupPath = path.join(backupDir, `backup-${timestamp}.sqlite`); // Create backup by copying the database file fs.copyFileSync(dbPath, backupPath); console.log(`✅ Backup created: ${backupPath}`); // Send notification if configured try { const { createNotification, NOTIFICATION_TYPES } = await import("./src/lib/notifications.js"); const db = (await import("./src/lib/db.js")).default; const setting = db.prepare("SELECT value FROM settings WHERE key = 'backup_notification_user_id'").get(); if (setting && setting.value) { const userId = setting.value; await createNotification({ userId, type: NOTIFICATION_TYPES.SYSTEM_ANNOUNCEMENT, title: "Database Backup Completed", message: `Daily database backup completed successfully. Backup file: ${backupPath}`, priority: "normal" }); console.log(`📢 Notification sent to user ${userId}`); } } catch (error) { console.error("Failed to send backup notification:", error); } // Cleanup: keep only last 30 backups const files = fs.readdirSync(backupDir) .filter(f => f.startsWith('backup-')) .map(f => ({ name: f, path: path.join(backupDir, f), mtime: fs.statSync(path.join(backupDir, f)).mtime })) .sort((a, b) => b.mtime - a.mtime); // Sort by modification time, newest first if (files.length > 30) { const toDelete = files.slice(30); toDelete.forEach(f => { fs.unlinkSync(f.path); console.log(`🗑️ Deleted old backup: ${f.name}`); }); } console.log(`📁 Total backups kept: ${Math.min(files.length, 30)}`);