Răsfoiți Sursa

✨ feat(db): 重构数据库备份恢复功能

- 创建新的 backup.ts 文件整合所有备份相关功能
- 统一备份、恢复、清理和列表功能到单个文件中
- 更新 package.json 脚本指向新的 backup.ts 文件

🔧 chore(security): 添加数据库备份相关命令到安全配置

- 在 settings.local.json 中添加 db:backup:* 和 db:restore 命令到允许列表
- 支持通过命令行执行数据库备份、恢复和清理操作
yourname 1 lună în urmă
părinte
comite
1839244be2
3 a modificat fișierele cu 57 adăugiri și 4 ștergeri
  1. 5 1
      .claude/settings.local.json
  2. 3 3
      web/package.json
  3. 49 0
      web/src/server/utils/backup.ts

+ 5 - 1
.claude/settings.local.json

@@ -36,7 +36,11 @@
       "Bash(mkdir:*)",
       "Bash(xargs sed:*)",
       "Bash(git diff:*)",
-      "Bash(pnpm build)"
+      "Bash(pnpm build)",
+      "Bash(pnpm db:backup:*)",
+      "Bash(pnpm db:backup:list:*)",
+      "Bash(pnpm db:backup:cleanup:*)",
+      "Bash(pnpm db:restore)"
     ],
     "deny": [],
     "ask": []

+ 3 - 3
web/package.json

@@ -29,9 +29,9 @@
     "db:seed": "tsx scripts/seed.ts",
     "db:reset": "tsx scripts/reset-db.ts",
     "db:backup": "tsx src/server/utils/backup.ts backup",
-    "db:restore": "tsx src/server/utils/restore.ts restore",
-    "db:backup:list": "tsx src/server/utils/restore.ts list",
-    "db:backup:latest": "tsx src/server/utils/restore.ts latest",
+    "db:restore": "tsx src/server/utils/backup.ts restore",
+    "db:backup:list": "tsx src/server/utils/backup.ts list",
+    "db:backup:latest": "tsx src/server/utils/backup.ts latest",
     "db:backup:cleanup": "tsx src/server/utils/backup.ts cleanup",
     "test:analyze": "node scripts/analyze-test-results.js",
     "lint": "eslint . --ext .ts,.tsx",

+ 49 - 0
web/src/server/utils/backup.ts

@@ -0,0 +1,49 @@
+import { databaseBackup } from '@d8d/server/utils/backup'
+import { promises as fs } from 'fs'
+import path from 'path'
+import process from 'node:process'
+
+const BACKUP_DIR = process.env.BACKUP_DIR || './backups'
+
+async function main() {
+  const command = process.argv[2]
+
+  switch (command) {
+    case 'backup':
+      await databaseBackup.createBackup()
+      break
+    case 'restore':
+      const backupFile = process.argv[3]
+      if (!backupFile) {
+        console.error('请指定要恢复的备份文件')
+        process.exit(1)
+      }
+      // 如果备份文件不包含路径,则在备份目录中查找
+      const fullBackupPath = backupFile.includes('/') ? backupFile : path.join(BACKUP_DIR, backupFile)
+      await databaseBackup.restoreBackup(fullBackupPath)
+      break
+    case 'cleanup':
+      await databaseBackup.cleanupOldBackups()
+      break
+    case 'list':
+      const files = await fs.readdir(BACKUP_DIR)
+      const backupFiles = files.filter(f => f.endsWith('.dump'))
+      console.log('可用备份文件:')
+      backupFiles.forEach(file => console.log(`  - ${file}`))
+      break
+    case 'latest':
+      const latestFiles = await fs.readdir(BACKUP_DIR)
+      const latestBackupFiles = latestFiles.filter(f => f.endsWith('.dump')).sort().reverse()
+      if (latestBackupFiles.length > 0) {
+        console.log(latestBackupFiles[0])
+      } else {
+        console.log('没有找到备份文件')
+      }
+      break
+    default:
+      console.log('用法: node backup.ts [backup|restore <file>|cleanup|list]')
+      process.exit(1)
+  }
+}
+
+main().catch(console.error)