import { create } from "zustand"; import { persist } from "zustand/middleware"; import { Updater } from "../typing"; import { deepClone } from "./clone"; type SecondParam<T> = T extends ( _f: infer _F, _s: infer S, ...args: infer _U ) => any ? S : never; type MakeUpdater<T> = { lastUpdateTime: number; markUpdate: () => void; update: Updater<T>; }; type SetStoreState<T> = ( partial: T | Partial<T> | ((state: T) => T | Partial<T>), replace?: boolean | undefined, ) => void; export function createPersistStore<T, M>( defaultState: T, methods: ( set: SetStoreState<T & MakeUpdater<T>>, get: () => T & MakeUpdater<T>, ) => M, persistOptions: SecondParam<typeof persist<T & M & MakeUpdater<T>>>, ) { return create<T & M & MakeUpdater<T>>()( persist((set, get) => { return { ...defaultState, ...methods(set as any, get), lastUpdateTime: 0, markUpdate() { set({ lastUpdateTime: Date.now() } as Partial< T & M & MakeUpdater<T> >); }, update(updater) { const state = deepClone(get()); updater(state); get().markUpdate(); set(state); }, }; }, persistOptions), ); }