store.ts 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { create } from "zustand";
  2. import { persist } from "zustand/middleware";
  3. import { Updater } from "../typing";
  4. import { deepClone } from "./clone";
  5. type SecondParam<T> = T extends (
  6. _f: infer _F,
  7. _s: infer S,
  8. ...args: infer _U
  9. ) => any
  10. ? S
  11. : never;
  12. type MakeUpdater<T> = {
  13. lastUpdateTime: number;
  14. markUpdate: () => void;
  15. update: Updater<T>;
  16. };
  17. type SetStoreState<T> = (
  18. partial: T | Partial<T> | ((state: T) => T | Partial<T>),
  19. replace?: boolean | undefined,
  20. ) => void;
  21. export function createPersistStore<T, M>(
  22. defaultState: T,
  23. methods: (
  24. set: SetStoreState<T & MakeUpdater<T>>,
  25. get: () => T & MakeUpdater<T>,
  26. ) => M,
  27. persistOptions: SecondParam<typeof persist<T & M & MakeUpdater<T>>>,
  28. ) {
  29. return create<T & M & MakeUpdater<T>>()(
  30. persist((set, get) => {
  31. return {
  32. ...defaultState,
  33. ...methods(set as any, get),
  34. lastUpdateTime: 0,
  35. markUpdate() {
  36. set({ lastUpdateTime: Date.now() } as Partial<
  37. T & M & MakeUpdater<T>
  38. >);
  39. },
  40. update(updater) {
  41. const state = deepClone(get());
  42. updater(state);
  43. get().markUpdate();
  44. set(state);
  45. },
  46. };
  47. }, persistOptions),
  48. );
  49. }