prompt.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { create } from "zustand";
  2. import { persist } from "zustand/middleware";
  3. import Fuse from "fuse.js";
  4. export interface Prompt {
  5. id?: number;
  6. title: string;
  7. content: string;
  8. }
  9. export interface PromptStore {
  10. latestId: number;
  11. prompts: Map<number, Prompt>;
  12. add: (prompt: Prompt) => number;
  13. remove: (id: number) => void;
  14. search: (text: string) => Prompt[];
  15. }
  16. export const PROMPT_KEY = "prompt-store";
  17. export const SearchService = {
  18. ready: false,
  19. engine: new Fuse<Prompt>([], { keys: ["title"] }),
  20. count: {
  21. builtin: 0,
  22. },
  23. init(prompts: Prompt[]) {
  24. if (this.ready) {
  25. return;
  26. }
  27. this.engine.setCollection(prompts);
  28. this.ready = true;
  29. },
  30. remove(id: number) {
  31. this.engine.remove((doc) => doc.id === id);
  32. },
  33. add(prompt: Prompt) {
  34. this.engine.add(prompt);
  35. },
  36. search(text: string) {
  37. const results = this.engine.search(text);
  38. return results.map((v) => v.item);
  39. },
  40. };
  41. export const usePromptStore = create<PromptStore>()(
  42. persist(
  43. (set, get) => ({
  44. latestId: 0,
  45. prompts: new Map(),
  46. add(prompt) {
  47. const prompts = get().prompts;
  48. prompt.id = get().latestId + 1;
  49. prompts.set(prompt.id, prompt);
  50. set(() => ({
  51. latestId: prompt.id!,
  52. prompts: prompts,
  53. }));
  54. return prompt.id!;
  55. },
  56. remove(id) {
  57. const prompts = get().prompts;
  58. prompts.delete(id);
  59. SearchService.remove(id);
  60. set(() => ({
  61. prompts,
  62. }));
  63. },
  64. search(text) {
  65. return SearchService.search(text) as Prompt[];
  66. },
  67. }),
  68. {
  69. name: PROMPT_KEY,
  70. version: 1,
  71. onRehydrateStorage(state) {
  72. const PROMPT_URL = "./prompts.json";
  73. type PromptList = Array<[string, string]>;
  74. fetch(PROMPT_URL)
  75. .then((res) => res.json())
  76. .then((res) => {
  77. const builtinPrompts = [res.en, res.cn]
  78. .map((promptList: PromptList) => {
  79. return promptList.map(
  80. ([title, content]) =>
  81. ({
  82. title,
  83. content,
  84. } as Prompt)
  85. );
  86. })
  87. .concat([...(state?.prompts?.values() ?? [])]);
  88. const allPromptsForSearch = builtinPrompts.reduce(
  89. (pre, cur) => pre.concat(cur),
  90. []
  91. );
  92. SearchService.count.builtin = res.en.length + res.cn.length;
  93. SearchService.init(allPromptsForSearch);
  94. });
  95. },
  96. }
  97. )
  98. );