Files
MyNote/apps/desktop/src/main/services/vault-service.ts
T

64 lines
2.8 KiB
TypeScript

// VaultService — 统筹库管理:默认库、切换、最近库(FR-V)
import nodePath from 'node:path';
import { promises as fs } from 'node:fs';
import { app, dialog } from 'electron';
import { DEFAULT_VAULT_NAME } from '@hunter/shared';
import type { VaultMeta } from '@hunter/shared';
import { ConfigStore } from './config-store.js';
import { FileService } from './file-service.js';
import { SearchService } from './search-service.js';
export class VaultService {
fileService: FileService | null = null;
searchService: SearchService | null = null;
private config: ConfigStore;
constructor() {
this.config = new ConfigStore(app.getPath('userData'));
}
// 启动时初始化:确保有当前库(无则创建默认库)
async init(): Promise<VaultMeta> {
let meta = await this.config.getVaultMeta();
if (!meta.currentRoot) {
const defaultRoot = nodePath.join(app.getPath('userData'), DEFAULT_VAULT_NAME);
await fs.mkdir(defaultRoot, { recursive: true });
meta = await this.config.setCurrentRoot(defaultRoot);
}
this.fileService = new FileService(meta.currentRoot);
this.searchService = new SearchService(meta.currentRoot, this.fileService);
return meta;
}
async getMeta(): Promise<VaultMeta> { return this.config.getVaultMeta(); }
// 通过系统对话框选择并切换库(FR-V3)
async pickAndSwitch(): Promise<VaultMeta | null> {
const result = await dialog.showOpenDialog({ properties: ['openDirectory'] });
if (result.canceled || result.filePaths.length === 0) return null;
return this.switch(result.filePaths[0]);
}
// 仅浏览选择目录路径,不切换(FR-V5 设置页浏览按钮)
async pickDirectory(): Promise<string | null> {
const result = await dialog.showOpenDialog({ properties: ['openDirectory'] });
if (result.canceled || result.filePaths.length === 0) return null;
return result.filePaths[0];
}
async switch(root: string): Promise<VaultMeta> {
// 校验是存在的目录
const stat = await fs.stat(root).catch(() => null);
if (!stat || !stat.isDirectory()) throw new Error('目标路径不是有效目录: ' + root);
const meta = await this.config.setCurrentRoot(root);
this.fileService = new FileService(root);
this.searchService = new SearchService(root, this.fileService);
return meta;
}
async setDefaultRoot(root: string): Promise<void> { await this.config.setDefaultRoot(root); }
getAppearance() { return this.config.getAppearance(); }
saveAppearance(data: { themeId: string; params: Record<string, unknown>; effect: string; bgImage: string | null }) { return this.config.saveAppearance(data); }
getKeymaps() { return this.config.getKeymaps(); }
saveKeymaps(data: { id: string; combo: string }[]) { return this.config.saveKeymaps(data); }
}