const PREFIX = '__PAPERCUPS__' ; type StorageType = 'local' | 'session' | 'cookie' | 'memory' | 'none' | null ; interface Storage { get : ( key : string ) => any ; set : ( key : string , value : any ) => void ; remove : ( key : string ) => any ; } type FallbackStorage = Storage & { _db : Record < string , any > ; getItem : ( key : string ) => any ; setItem : ( key : string , value : any ) => void ; removeItem : ( key : string ) => any ; } ; const useFallbackStorage = ( ) : FallbackStorage => { return { _db : { } , getItem ( key ) { return this . _db [ key ] || null ; } , setItem ( key , value ) { this . _db [ key ] = value ; } , removeItem ( key ) { delete this . _db [ key ] ; } , get ( key ) { return this . _db [ key ] || null ; } , set ( key , value ) { this . _db [ key ] = value ; } , remove ( key ) { delete this . _db [ key ] ; } , } ; } ; const useLocalStorage = ( w ) : Storage => { try { const storage = w && w . localStorage ; return { ... storage , get : ( key ) => { const result = storage . getItem ( `${ PREFIX }${ key }` ) ; if ( ! result ) { return null ; } try { return JSON . parse ( result ) ; } catch ( e ) { return result ; } } , set : ( key , value ) => { storage . setItem ( `${ PREFIX }${ key }` , JSON . stringify ( value ) ) ; } , remove : ( key ) => { storage . removeItem ( key ) ; } , } ; } catch ( e ) { return useFallbackStorage ( ) ; } } ; const useSessionStorage = ( w ) : Storage => { try { const storage = w && w . sessionStorage ; return { ... storage , get : ( key ) => { const result = storage . getItem ( `${ PREFIX }${ key }` ) ; if ( ! result ) { return null ; } try { return JSON . parse ( result ) ; } catch ( e ) { return result ; } } , set : ( key , value ) => { storage . setItem ( `${ PREFIX }${ key }` , JSON . stringify ( value ) ) ; } , remove : ( key ) => { storage . removeItem ( key ) ; } , } ; } catch ( e ) { return useFallbackStorage ( ) ; } } ; const useCookieStorage = ( ) : Storage => { try { throw new Error ( 'Cookie storage has not been implemented!' ) ; } catch ( e ) { return useFallbackStorage ( ) ; } } ; const getPreferredStorage = ( w , type = 'local' ) : Storage => { try { switch ( type ) { case 'local' : return useLocalStorage ( w ) ; case 'session' : return useSessionStorage ( w ) ; case 'cookie' : return useCookieStorage ( ) ; case 'memory' : default : return useFallbackStorage ( ) ; } } catch ( e ) { return useFallbackStorage ( ) ; } } ; export default function store ( w , options = { } ) { const { defaultType = 'local' , openStateType = 'session' } = options ; const defaultStorage = getPreferredStorage ( w , defaultType ) ; const openStateStorage = getPreferredStorage ( w , openStateType ) ; return { getCustomerId : ( ) => defaultStorage . get ( '__CUSTOMER_ID__' ) , setCustomerId : ( id ) => defaultStorage . set ( '__CUSTOMER_ID__' , id ) , removeCustomerId : ( ) => defaultStorage . remove ( '__CUSTOMER_ID__' ) , getOpenState : ( ) => openStateStorage . get ( ':open' ) , setOpenState : ( state ) => openStateStorage . set ( ':open' , state ) , clearOpenState : ( ) => openStateStorage . remove ( ':open' ) , getPopupSeen : ( ) => openStateStorage . get ( ':pop_up_seen' ) , setPopupSeen : ( state ) => openStateStorage . set ( ':pop_up_seen' , state ) , clearPopupSeen : ( ) => openStateStorage . remove ( ':pop_up_seen' ) , } ; }