import { reaction , action } from 'mobx' ; import { serialize , deserialize , update , serializable , getDefaultModelSchema } from 'serializr' ; import * as Storage from './storage' ; import { mergeObservables } from './merge-x' ; import { types , Types } from './types' ; import { persistObject } from './persist-object' ; export function persist ( type , schema ? ) ; export function persist ( target , key , baseDescriptor ? ) ; export function persist ( schema ) ; export function persist ( ... args ) { const [ a , b , c ] = args ; if ( a in types ) { return serializable ( types [ a ] ( b ) ) ; } else if ( args . length === 1 ) { return ( target ) => persistObject ( target , a ) ; } else { return serializable . apply ( null , args ) ; } } export interface optionsType { storage ? : any ; jsonify ? : boolean ; debounce ? : number ; } export interface IHydrateResult < T > extends Promise < T > { rehydrate : ( ) => IHydrateResult < T > ; } export function create ( { storage = Storage as any , jsonify = true , debounce = 0 } = { } ) { if ( typeof localStorage !== 'undefined' && localStorage === storage ) storage = Storage ; return function hydrate < T extends Object > ( key , store , initialState = { } , customArgs = { } ) : IHydrateResult < T > { const schema = getDefaultModelSchema ( store as any ) ; function hydration ( ) { const promise = storage . getItem ( key ) . then ( ( d ) => ! jsonify ? d : JSON . parse ( d ) ) . then ( action ( `[mobx-persist ${ key }] LOAD_DATA` , ( persisted ) => { if ( persisted && typeof persisted === 'object' ) { update ( schema , store , persisted , null , customArgs ) ; } mergeObservables ( store , initialState ) ; return store ; } ) ) ; promise . rehydrate = hydration ; return promise ; } const result = hydration ( ) ; reaction ( ( ) => serialize ( schema , store ) , ( data ) => storage . setItem ( key , ! jsonify ? data : JSON . stringify ( data ) ) , { delay : debounce } ) ; return result ; } ; }