75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
// 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<string, unknown>; 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<string, unknown>; 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<void> {
|
|
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<VaultMeta> {
|
|
const c = await this.read();
|
|
return c.vault ?? { currentRoot: '', recents: [], defaultRoot: '' };
|
|
}
|
|
|
|
async setCurrentRoot(root: string): Promise<VaultMeta> {
|
|
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<string, unknown>; effect: string; bgImage: string | null } | null> {
|
|
const c = await this.read();
|
|
return c.appearance ?? null;
|
|
}
|
|
async saveAppearance(data: { themeId: string; params: Record<string, unknown>; effect: string; bgImage: string | null }): Promise<void> {
|
|
(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<void> {
|
|
(await this.read()).keymaps = data;
|
|
await this.write();
|
|
}
|
|
|
|
async setDefaultRoot(root: string): Promise<VaultMeta> {
|
|
const meta = await this.getVaultMeta();
|
|
meta.defaultRoot = root;
|
|
(await this.read()).vault = meta;
|
|
await this.write();
|
|
return meta;
|
|
}
|
|
}
|