import { app } from 'electron' import { join } from 'path' import { readFileSync, writeFileSync, existsSync } from 'fs' import type { HistoryEntry } from '@shared/ipc' import { isValidHistoryEntry } from './validation' // Plain JSON in userData (portable build redirects userData next to the exe). // Kept simple per the build plan; can migrate to better-sqlite3 later. const MAX_ENTRIES = 500 function historyFile(): string { return join(app.getPath('userData'), 'history.json') } // Per-entry validation (isValidHistoryEntry, in validation.ts) so a hand-edited // or corrupted history.json can't feed the UI (or openPath) entries with the // wrong shape — invalid rows are dropped rather than trusted. (audit S5) export function listHistory(): HistoryEntry[] { try { if (!existsSync(historyFile())) return [] const data = JSON.parse(readFileSync(historyFile(), 'utf8')) return Array.isArray(data) ? data.filter(isValidHistoryEntry) : [] } catch { return [] } } function save(entries: HistoryEntry[]): void { try { writeFileSync(historyFile(), JSON.stringify(entries.slice(0, MAX_ENTRIES), null, 2)) } catch { /* best-effort; a read-only data dir just means no persisted history */ } } export function addHistory(entry: HistoryEntry): HistoryEntry[] { // De-dupe by id (a retry of the same item replaces its prior entry). const entries = [entry, ...listHistory().filter((e) => e.id !== entry.id)] save(entries) return entries } export function removeHistory(id: string): HistoryEntry[] { const entries = listHistory().filter((e) => e.id !== id) save(entries) return entries } export function removeManyHistory(ids: string[]): HistoryEntry[] { const remove = new Set(ids) const entries = listHistory().filter((e) => !remove.has(e.id)) save(entries) return entries } export function clearHistory(): HistoryEntry[] { save([]) return [] }