ChatGPT-Next-Web/app/utils/store.ts

79 lines
2.0 KiB
TypeScript
Raw Normal View History

import { create } from "zustand";
2024-08-26 13:13:35 +00:00
import { combine, persist, createJSONStorage } from "zustand/middleware";
import { Updater } from "../typing";
import { deepClone } from "./clone";
2024-08-27 02:05:37 +00:00
import { indexedDBStorage } from "@/app/utils/indexedDB-storage";
type SecondParam<T> = T extends (
_f: infer _F,
_s: infer S,
...args: infer _U
) => any
? S
: never;
type MakeUpdater<T> = {
lastUpdateTime: number;
2024-09-03 12:29:01 +00:00
_hasHydrated: boolean;
markUpdate: () => void;
update: Updater<T>;
2024-09-03 12:29:01 +00:00
setHasHydrated: (state: boolean) => void;
};
type SetStoreState<T> = (
partial: T | Partial<T> | ((state: T) => T | Partial<T>),
replace?: boolean | undefined,
) => void;
2023-11-09 18:43:30 +00:00
export function createPersistStore<T extends object, M>(
state: T,
methods: (
set: SetStoreState<T & MakeUpdater<T>>,
get: () => T & MakeUpdater<T>,
) => M,
persistOptions: SecondParam<typeof persist<T & M & MakeUpdater<T>>>,
) {
2024-08-27 02:05:37 +00:00
persistOptions.storage = createJSONStorage(() => indexedDBStorage);
2024-09-04 05:00:18 +00:00
const oldOonRehydrateStorage = persistOptions?.onRehydrateStorage;
persistOptions.onRehydrateStorage = (state) => {
oldOonRehydrateStorage?.(state);
return () => state.setHasHydrated(true);
};
2023-11-09 18:43:30 +00:00
return create(
persist(
combine(
{
...state,
lastUpdateTime: 0,
2024-09-03 12:29:01 +00:00
_hasHydrated: false,
},
2023-11-09 18:43:30 +00:00
(set, get) => {
return {
...methods(set, get as any),
markUpdate() {
set({ lastUpdateTime: Date.now() } as Partial<
T & M & MakeUpdater<T>
>);
},
update(updater) {
const state = deepClone(get());
updater(state);
set({
...state,
lastUpdateTime: Date.now(),
});
},
2024-09-03 12:29:01 +00:00
setHasHydrated: (state: boolean) => {
set({ _hasHydrated: state } as Partial<T & M & MakeUpdater<T>>);
},
2023-11-09 18:43:30 +00:00
} as M & MakeUpdater<T>;
},
2023-11-09 18:43:30 +00:00
),
persistOptions as any,
),
);
}