feat: add deployment guide, backup functionality, and cron jobs for automated backups
This commit is contained in:
40
backup-db.mjs
Normal file
40
backup-db.mjs
Normal file
@@ -0,0 +1,40 @@
|
||||
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}`);
|
||||
|
||||
// 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)}`);
|
||||
Reference in New Issue
Block a user