import { create } from "zustand"; import { persist } from "zustand/middleware"; import JsSearch from "js-search"; export interface Prompt { id?: number; shortcut: string; title: string; content: string; } export interface PromptStore { latestId: number; prompts: Map; add: (prompt: Prompt) => number; remove: (id: number) => void; search: (text: string) => Prompt[]; } export const PROMPT_KEY = "prompt-store"; export const SearchService = { ready: false, progress: 0, // 0 - 1, 1 means ready engine: new JsSearch.Search("prompts"), deleted: new Set(), async init(prompts: PromptStore["prompts"]) { this.engine.addIndex("id"); this.engine.addIndex("shortcut"); this.engine.addIndex("title"); const n = prompts.size; let count = 0; for await (const prompt of prompts.values()) { this.engine.addDocument(prompt); count += 1; this.progress = count / n; } this.ready = true; }, remove(id: number) { this.deleted.add(id); }, add(prompt: Prompt) { this.engine.addDocument(prompt); }, search(text: string) { const results = this.engine.search(text) as Prompt[]; return results.filter((v) => !v.id || !this.deleted.has(v.id)); }, }; export const usePromptStore = create()( persist( (set, get) => ({ latestId: 0, prompts: new Map(), add(prompt) { const prompts = get().prompts; prompt.id = get().latestId + 1; prompts.set(prompt.id, prompt); set(() => ({ latestId: prompt.id!, prompts: prompts, })); return prompt.id!; }, remove(id) { const prompts = get().prompts; prompts.delete(id); SearchService.remove(id); set(() => ({ prompts, })); }, search(text) { return SearchService.search(text) as Prompt[]; }, }), { name: PROMPT_KEY, version: 1, } ) );