feat(db): migrate from lowdb to SQLite with repos pattern

- Add modular DB layer (adapters, migrations, repos, helpers)
- Replace localDb/usageDb/requestDetailsDb monoliths with repos
- Add Tailscale tunnel integration & status check API
- Add /api/cli-tools/all-statuses aggregated endpoint
- Add settingsStore (Zustand) and mitm/dbReader
- Add DB unit tests (benchmark, concurrent, migration, vs-lowdb)
This commit is contained in:
decolua committed 2026-05-09 17:48:20 +07:00
1 parent 145f588cc0
commit bee8dad946
63 files changed
+4223 -2330

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
import fs from "node:fs";
import path from "node:path";
import { BACKUPS_DIR, ensureDirs } from "./paths.js";
import { timestampSlug, getAppVersion } from "./version.js";
const KEEP_BACKUPS = 5;
export function makeBackupDir(label) {
ensureDirs();
const ver = getAppVersion();
const slug = `${label}-${ver}-${timestampSlug()}`;
const dir = path.join(BACKUPS_DIR, slug);
fs.mkdirSync(dir, { recursive: true });
return dir;
}
export function backupFile(srcPath, destDir, destName = null) {
if (!fs.existsSync(srcPath)) return null;
const name = destName || path.basename(srcPath);
const dest = path.join(destDir, name);
fs.copyFileSync(srcPath, dest);
return dest;
}
export function pruneOldBackups() {
if (!fs.existsSync(BACKUPS_DIR)) return;
const entries = fs.readdirSync(BACKUPS_DIR, { withFileTypes: true })
.filter((e) => e.isDirectory())
.map((e) => ({ name: e.name, full: path.join(BACKUPS_DIR, e.name), mtime: fs.statSync(path.join(BACKUPS_DIR, e.name)).mtimeMs }))
.sort((a, b) => b.mtime - a.mtime);
for (const old of entries.slice(KEEP_BACKUPS)) {
try { fs.rmSync(old.full, { recursive: true, force: true }); } catch {}
}
}