// ConfigStore — 应用配置 JSON 持久化(vault meta、最近库) import nodePath from 'node:path'; import { promises as fs } from 'node:fs'; import type { VaultMeta } from '@hunter/shared'; import { RECENT_VAULT_MAX } from '@hunter/shared'; export class ConfigStore { private file: string; private cache: { vault?: VaultMeta; appearance?: { themeId: string; params: Record; effect: string; bgImage: string | null }; keymaps?: { id: string; combo: string }[] } | null = null; constructor(userDataDir: string) { this.file = nodePath.join(userDataDir, 'config.json'); } private async read(): Promise<{ vault?: VaultMeta; appearance?: { themeId: string; params: Record; effect: string; bgImage: string | null }; keymaps?: { id: string; combo: string }[] }> { if (this.cache) return this.cache; try { const raw = await fs.readFile(this.file, 'utf8'); this.cache = JSON.parse(raw); } catch { this.cache = {}; } return this.cache!; } private async write(): Promise { const dir = nodePath.dirname(this.file); await fs.mkdir(dir, { recursive: true }); const tmp = this.file + '.tmp'; await fs.writeFile(tmp, JSON.stringify(this.cache, null, 2), 'utf8'); await fs.rename(tmp, this.file); } async getVaultMeta(): Promise { const c = await this.read(); return c.vault ?? { currentRoot: '', recents: [], defaultRoot: '' }; } async setCurrentRoot(root: string): Promise { const meta = await this.getVaultMeta(); meta.currentRoot = root; // 加入最近库(去重置顶,截断到上限) meta.recents = [root, ...meta.recents.filter(r => r !== root)].slice(0, RECENT_VAULT_MAX); (await this.read()).vault = meta; await this.write(); return meta; } async getAppearance(): Promise<{ themeId: string; params: Record; effect: string; bgImage: string | null } | null> { const c = await this.read(); return c.appearance ?? null; } async saveAppearance(data: { themeId: string; params: Record; effect: string; bgImage: string | null }): Promise { (await this.read()).appearance = data; await this.write(); } async getKeymaps(): Promise<{ id: string; combo: string }[] | null> { const c = await this.read(); return c.keymaps ?? null; } async saveKeymaps(data: { id: string; combo: string }[]): Promise { (await this.read()).keymaps = data; await this.write(); } async setDefaultRoot(root: string): Promise { const meta = await this.getVaultMeta(); meta.defaultRoot = root; (await this.read()).vault = meta; await this.write(); return meta; } }