import { IPersistenceMethod , IProduce , isClientSide } from "../common" ; import { isPromise } from "../utils/isPromise" ; export type PersistenceStoragePlugin < T = any > = { getState : ( ) => void | Promise < void > ; setState : ( state : T ) => void | Promise < void > ; current : Pick < ConnectPersistenceStorageArgs , "persistenceKey" | "isSSR" | "persistenceMethod" | "debounceWait" > & { isConnected : boolean ; } ; } ; export type IPersistenceOptions = { type { number } debounceWait ? : number ; type { string } persistenceKey ? : string ; type { boolean } isActive ? : boolean ; type { IPersistenceMethod } persistenceMethod ? : IPersistenceMethod ; type { boolean } isSSR ? : boolean ; } ; export type ConnectPersistenceStorageArgs = { persistenceKey : string ; produce : IProduce < any > ; debounceWait : number | undefined ; persistenceMethod ? : IPersistenceMethod | undefined ; isSSR : boolean | undefined ; resolve : ( ) => void ; reject : ( reason ? : any ) => void ; } ; export const connectPersistenceStorage = ( { persistenceKey : persistenceName , produce , debounceWait = 3000 , persistenceMethod = isClientSide ? window . localStorage : undefined , isSSR , resolve , reject , } ) : PersistenceStoragePlugin | null => { if ( ! persistenceMethod ) return null ; let isConnected = false ; let timeout ; const setStateFn = ( state ) => { const possiblePromise = persistenceMethod . setItem ( persistenceName , JSON . stringify ( state ) ) ; if ( isPromise ( possiblePromise ) ) { return possiblePromise . then ( ( ) => { isConnected = true ; } ) ; } if ( ! isConnected ) isConnected = true ; return void 0 ; } ; const setState = ( state ) => { const execPersistence = ( ) => { timeout = undefined ; setStateFn ( state ) ; } ; if ( timeout !== undefined ) clearTimeout ( timeout ) ; if ( debounceWait <= 0 ) { execPersistence ( ) ; timeout = undefined ; } else { timeout = setTimeout ( execPersistence , debounceWait ) ; } } ; const getState = ( ) => { if ( isConnected || ! persistenceMethod ) { resolve ( ) ; return void 0 ; } try { const statePromise = persistenceMethod . getItem ( persistenceName ) ; if ( isPromise ( statePromise ) ) { return statePromise . then ( ( state ) => { if ( state == null ) { isConnected = true ; resolve ( ) ; return void 0 ; } produce ( ( ) => ( { ... produce ( ) , ... JSON . parse ( state ) , } ) ) ; isConnected = true ; resolve ( ) ; return void 0 ; } ) . catch ( reject ) ; } else { if ( statePromise == null ) { isConnected = true ; resolve ( ) ; return void 0 ; } produce ( ( ) => ( { ... produce ( ) , ... JSON . parse ( statePromise ) , } ) ) ; isConnected = true ; resolve ( ) ; return void 0 ; } } catch ( err ) { reject ( err ) ; return void 0 ; } } ; if ( isSSR ) { resolve ( ) ; } else { getState ( ) ; } return { getState , setState , current : { persistenceKey : persistenceName , persistenceMethod , isSSR , isConnected , debounceWait , } , } ; } ;