feat: add backup file management settings
- Added settings UI to enable/disable .bak file creation when saving files - Created settings storage in .obsidian/obsiviewer.json to persist backup preferences - Added API endpoints to read/write backup settings (/api/settings) - Implemented automatic cleanup of existing .bak files when disabling backups - Modified file save operations to respect backup setting across notes, bookmarks and graph files - Removed existing .bak files from version control
This commit is contained in:
+102
-5
@@ -51,11 +51,74 @@ const distDir = path.join(rootDir, 'dist');
|
||||
// Centralized vault directory
|
||||
const vaultDir = path.isAbsolute(CFG_VAULT_PATH) ? CFG_VAULT_PATH : path.join(rootDir, CFG_VAULT_PATH);
|
||||
|
||||
const settingsPath = path.join(vaultDir, '.obsidian', 'obsiviewer.json');
|
||||
let enableBackups = true;
|
||||
|
||||
try {
|
||||
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
||||
enableBackups = settings.enableBackups;
|
||||
} catch (error) {
|
||||
// No settings file or invalid JSON, use default
|
||||
}
|
||||
|
||||
const vaultEventClients = new Set();
|
||||
|
||||
// Phase 3: Advanced caching and monitoring
|
||||
const metadataCache = new MetadataCache({ ttlMs: 5 * 60 * 1000, maxItems: 10_000 });
|
||||
|
||||
// ---------- Settings storage helpers ----------
|
||||
function ensureSettingsStorage() {
|
||||
const obsidianDir = path.join(vaultDir, '.obsidian');
|
||||
if (!fs.existsSync(obsidianDir)) {
|
||||
fs.mkdirSync(obsidianDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(settingsPath)) {
|
||||
const initial = { enableBackups: true };
|
||||
try { fs.writeFileSync(settingsPath, JSON.stringify(initial, null, 2), 'utf-8'); } catch {}
|
||||
}
|
||||
}
|
||||
|
||||
function readSettings() {
|
||||
ensureSettingsStorage();
|
||||
try {
|
||||
const raw = fs.readFileSync(settingsPath, 'utf-8');
|
||||
const parsed = JSON.parse(raw);
|
||||
return { enableBackups: parsed.enableBackups !== false };
|
||||
} catch {
|
||||
return { enableBackups: true };
|
||||
}
|
||||
}
|
||||
|
||||
function writeSettings(next) {
|
||||
ensureSettingsStorage();
|
||||
try {
|
||||
fs.writeFileSync(settingsPath, JSON.stringify(next, null, 2), 'utf-8');
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function deleteAllBakFiles(root) {
|
||||
let count = 0;
|
||||
const stack = [root];
|
||||
while (stack.length) {
|
||||
const dir = stack.pop();
|
||||
let entries = [];
|
||||
try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { continue; }
|
||||
for (const de of entries) {
|
||||
const full = path.join(dir, de.name);
|
||||
if (de.isDirectory()) { stack.push(full); continue; }
|
||||
if (!de.isFile()) continue;
|
||||
if (de.name.toLowerCase().endsWith('.bak')) {
|
||||
try { fs.unlinkSync(full); count++; } catch {}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Initialize settings on startup
|
||||
ensureSettingsStorage();
|
||||
enableBackups = readSettings().enableBackups;
|
||||
|
||||
// List all folders under the vault (relative paths, forward slashes)
|
||||
app.get('/api/folders/list', (req, res) => {
|
||||
try {
|
||||
@@ -507,6 +570,39 @@ app.use(cors({
|
||||
// Exposer les fichiers de la voûte pour un accès direct si nécessaire
|
||||
app.use('/vault', express.static(vaultDir));
|
||||
|
||||
// ---------- Settings API ----------
|
||||
app.get('/api/settings', (req, res) => {
|
||||
try {
|
||||
const current = readSettings();
|
||||
return res.json(current);
|
||||
} catch (error) {
|
||||
console.error('GET /api/settings error:', error);
|
||||
return res.status(500).json({ error: 'Unable to read settings' });
|
||||
}
|
||||
});
|
||||
|
||||
app.put('/api/settings', express.json(), (req, res) => {
|
||||
try {
|
||||
const body = req.body || {};
|
||||
const nextEnable = body.enableBackups !== false;
|
||||
const prev = readSettings();
|
||||
const next = { enableBackups: nextEnable };
|
||||
writeSettings(next);
|
||||
enableBackups = nextEnable;
|
||||
|
||||
let deleted = 0;
|
||||
if (prev.enableBackups && !nextEnable) {
|
||||
// On disabling backups, remove all existing .bak files
|
||||
deleted = deleteAllBakFiles(vaultDir);
|
||||
}
|
||||
|
||||
return res.json({ success: true, enableBackups, deletedBakFiles: deleted });
|
||||
} catch (error) {
|
||||
console.error('PUT /api/settings error:', error);
|
||||
return res.status(500).json({ error: 'Unable to save settings' });
|
||||
}
|
||||
});
|
||||
|
||||
// Résolution des attachements: recherche le fichier en remontant les dossiers depuis la note, puis dans la voûte
|
||||
app.get('/api/attachments/resolve', (req, res) => {
|
||||
try {
|
||||
@@ -1116,7 +1212,7 @@ app.put('/api/files', express.json({ limit: '10mb' }), express.text({ limit: '10
|
||||
const backup = abs + '.bak';
|
||||
|
||||
try {
|
||||
if (hasExisting) fs.copyFileSync(abs, backup);
|
||||
if (hasExisting && enableBackups) fs.copyFileSync(abs, backup);
|
||||
fs.writeFileSync(temp, finalContent, 'utf-8');
|
||||
fs.renameSync(temp, abs);
|
||||
console.log('[PUT /api/files] wrote file path=%s bytes=%d', rel, Buffer.byteLength(finalContent, 'utf-8'));
|
||||
@@ -1283,7 +1379,7 @@ app.put('/api/vault/graph', (req, res) => {
|
||||
|
||||
// Create backup before writing
|
||||
const backupPath = graphPath + '.bak';
|
||||
if (fs.existsSync(graphPath)) {
|
||||
if (enableBackups && fs.existsSync(graphPath)) {
|
||||
fs.copyFileSync(graphPath, backupPath);
|
||||
}
|
||||
|
||||
@@ -1341,7 +1437,7 @@ app.put('/api/vault/bookmarks', (req, res) => {
|
||||
|
||||
// Create backup before writing
|
||||
const backupPath = bookmarksPath + '.bak';
|
||||
if (fs.existsSync(bookmarksPath)) {
|
||||
if (enableBackups && fs.existsSync(bookmarksPath)) {
|
||||
fs.copyFileSync(bookmarksPath, backupPath);
|
||||
}
|
||||
|
||||
@@ -1469,8 +1565,9 @@ app.put(/^\/api\/notes\/(.+?)\/tags$/, express.json(), async (req, res) => {
|
||||
const backupPath = absolutePath + '.bak';
|
||||
|
||||
try {
|
||||
// Create backup
|
||||
fs.copyFileSync(absolutePath, backupPath);
|
||||
if (enableBackups) {
|
||||
fs.copyFileSync(absolutePath, backupPath);
|
||||
}
|
||||
|
||||
// Write to temp file
|
||||
fs.writeFileSync(tempPath, updatedContent, 'utf-8');
|
||||
|
||||
Reference in New Issue
Block a user