import { SyncAction as NewAdvancedSyncAction , AsyncActionPromise as NewAsynchActionPromise , DecoratedActions , EffectsInvocationContext , ErrorEffectsInvocationContext , ErrorSideEffectsInvocationContext , GetPromiseInvocationContext , InvocationContext , OnPropsChangeEffectsContext , OnPropsChangeSideEffectsContext , PromiseResult , SideEffectsInvocationContext , StoreActions , StoreOptions , MiddlewareFactory , } from './types' ; import { createStore , StoreApi , setGlobalConfig , ConflictPolicy } from './index' ; import { AdvancedSynchAction , AsynchActionPromiseGet , StateDecoratorAction , StateDecoratorActions , StateDecoratorOptions , AsynchActionPromise , SynchAction , LoadingMap , LoadingProps , LoadingMapParallelActions , AsynchAction , } from './v5_types' ; export { AdvancedSynchAction , AsynchActionPromiseGet , StateDecoratorAction , StateDecoratorActions , StateDecoratorOptions , AsynchActionPromise , SynchAction , LoadingMap , LoadingMapParallelActions , LoadingProps , ConflictPolicy , setGlobalConfig , } ; import { useEffect , useLayoutEffect , useReducer , useRef } from 'react' ; import { logDetailedEffects } from './middlewares' ; function isAsyncActionPromise < S , F extends ( ... args : any [ ] ) => any , A , P > ( action ) { return ! ( action instanceof Function ) && action . hasOwnProperty ( 'promise' ) ; } function isAsyncActionPromiseGet < S , F extends ( ... args : any [ ] ) => any , A , P > ( action ) { return ! ( action instanceof Function ) && action . hasOwnProperty ( 'promiseGet' ) ; } /**
 * Type guard function to test if an action is a asynchronous action.
 */ export function isAsyncAction < S , F extends ( ... args : any [ ] ) => any , A , P > ( action ) { return ! ( action instanceof Function ) && ( action . hasOwnProperty ( 'promise' ) || action . hasOwnProperty ( 'promiseGet' ) ) ; } /**
 * Type guard function to test if an action is a asynchronous action.
 */ export function isAsyncPromiseGetAction < S , F extends ( ... args : any [ ] ) => any , A , P > ( action ) { return ! ( action instanceof Function ) && ! ( action . hasOwnProperty ( 'promise' ) && action . hasOwnProperty ( 'promiseGet' ) ) ; } /**
 * Type guard function to test if an action is a synchronous action.
 */ export function isSyncAction < S , F extends ( ... args : any [ ] ) => any , A , P > ( action ) { return action instanceof Function ; } /**
 * Type guard function to test if an action is a synchronous action.
 */ export function isAdvancedSyncAction < S , F extends ( ... args : any [ ] ) => any , A , P > ( action ) { return ! ( action instanceof Function ) && ! action . hasOwnProperty ( 'promise' ) && ! action . hasOwnProperty ( 'promiseGet' ) ; } function convertV5Actions < S , A extends DecoratedActions , P > ( sourceActions ) { const actionNames = Object . keys ( sourceActions ) ; return actionNames . reduce ( ( acc , actionName ) => { const sourceAction = sourceActions [ actionName ] ; if ( isSyncAction ( sourceAction ) ) { acc [ actionName ] = ( ctx ) => sourceAction ( ctx . s , ctx . args as Parameters < A [ keyof A ] > , ctx . p ) ; } else if ( isAdvancedSyncAction ( sourceAction ) ) { const action = { effects : ( ctx ) => sourceAction . action ( ctx . s , ctx . args as Parameters < A [ keyof A ] > , ctx . p ) , } ; if ( sourceAction . onActionDone ) { action . sideEffects = ( { s , p , args , a , notifyWarning } ) => { sourceAction . onActionDone ( s , args as Parameters < A [ keyof A ] > , p , a , notifyWarning ) ; } ; } acc [ actionName ] = action ; } else if ( isAsyncActionPromise ( sourceAction ) || isAsyncActionPromiseGet ( sourceAction ) ) { let asyncAction ; if ( isAsyncActionPromiseGet ( sourceAction ) ) { asyncAction = { getPromise : ( { s , p , a , args , abortSignal } ) => sourceAction . promiseGet ( args as Parameters < A [ keyof A ] > , s , p , a , abortSignal ) , retryCount : 3 , conflictPolicy : ConflictPolicy . REUSE , } ; } else { asyncAction = { getPromise : ( { s , p , a , args , abortSignal } ) => sourceAction . promise ( args as Parameters < A [ keyof A ] > , s , p , a , abortSignal ) , } ; } [ 'abortable' , 'conflictPolicy' , 'getPromiseId' , 'isTriggerRetryError' , 'rejectPromiseOnError' , 'retryCount' , 'debounceTimeout' , 'debounceSideEffectsTimeout' , 'retryDelaySeed' , ] . forEach ( ( prop ) => { if ( ( sourceAction as any ) [ prop ] != null ) { ( asyncAction as any ) [ prop ] = ( sourceAction as any ) [ prop ] ; } } ) ; if ( sourceAction . successMessage ) { asyncAction . getSuccessMessage = ( ) => sourceAction . successMessage ; } if ( sourceAction . errorMessage ) { asyncAction . getSuccessMessage = ( ) => sourceAction . errorMessage ; } if ( sourceAction . getSuccessMessage ) { asyncAction . getSuccessMessage = ( { res , args , p } ) => sourceAction . getSuccessMessage ( res as any , args as any , p ) ; } if ( sourceAction . getErrorMessage ) { asyncAction . getErrorMessage = ( { err , args , p } ) => sourceAction . getErrorMessage ( err , args as any , p ) ; } if ( sourceAction . preReducer ) { asyncAction . preEffects = ( { s , p , args } ) => sourceAction . preReducer ( s , args as Parameters < A [ keyof A ] > , p ) ; } if ( sourceAction . optimisticReducer ) { asyncAction . optimisticEffects = ( { s , p , args } ) => sourceAction . optimisticReducer ( s , args as Parameters < A [ keyof A ] > , p ) ; } if ( sourceAction . reducer ) { asyncAction . effects = ( { s , res , p , args } ) => sourceAction . reducer ( s , res as PromiseResult < ReturnType < A [ keyof A ] > > , args as Parameters < A [ keyof A ] > , p ) ; } if ( sourceAction . errorReducer ) { asyncAction . errorEffects = ( { s , err , p , args } ) => sourceAction . errorReducer ( s , err , args as Parameters < A [ keyof A ] > , p ) ; } if ( sourceAction . onDone ) { asyncAction . sideEffects = ( { s , res , p , args , a , notifyWarning , } ) => sourceAction . onDone ( s , res as PromiseResult < ReturnType < A [ keyof A ] > > , args as Parameters < A [ keyof A ] > , p , a , notifyWarning ) ; } if ( sourceAction . onFail ) { asyncAction . errorSideEffects = ( { s , err , p , args , a , notifyWarning , } ) => sourceAction . onFail ( s , err , args as Parameters < A [ keyof A ] > , p , a , notifyWarning ) ; } acc [ actionName ] = asyncAction ; } return acc ; } , { } as StoreActions < S , A , P > ) ; } function convertV5Options < S , P , A > ( sourceOptions ) { const opts = { } ; const keys = Object . keys ( sourceOptions ) as ( keyof StateDecoratorOptions < S , A , P > ) [ ] ; const doNotCopyProps = [ 'onPropsChange' , 'onPropsChangeReducer' , 'getPropsRefValues' , 'onMount' , 'initialActionsMarkedLoading' , ] ; keys . forEach ( ( prop ) => { if ( ! doNotCopyProps . includes ( prop ) ) { ( opts as any ) [ prop ] = sourceOptions [ prop ] ; } } ) ; if ( sourceOptions . onMount ) { opts . onMount = ( { s , p , a } ) => sourceOptions . onMount ( a , p , s ) ; } if ( sourceOptions . getPropsRefValues ) { opts . onPropsChange = { getDeps : sourceOptions . getPropsRefValues , effects : ( { s , p , indices } ) => sourceOptions . onPropsChangeReducer ? sourceOptions . onPropsChangeReducer ( s , p , indices ) : null , sideEffects : ( { s , p , a , indices } ) => sourceOptions . onPropsChange == null ? null : sourceOptions . onPropsChange ( s , p , a , indices ) , } ; } if ( sourceOptions . initialActionsMarkedLoading ) { opts . initialActionsMarkedLoading = sourceOptions . initialActionsMarkedLoading ; } return opts ; } function useStateDecorator < S , A extends DecoratedActions , P > ( getInitialState , actions , props , options = { } , middlewares ? ) { const [ , forceRefresh ] = useReducer ( ( s ) => ( s > 100 ? 0 : s + 1 ) , 0 ) ; const actionsRef = useRef < StoreActions < S , A , P > > ( ) ; const optionsRef = useRef < StoreOptions < S , A , P , { } > > ( ) ; if ( actionsRef . current == null ) { actionsRef . current = convertV5Actions ( actions ) ; } if ( optionsRef . current == null ) { optionsRef . current = convertV5Options ( options ) ; } const storeRef = useRef < StoreApi < S , A , P > > ( ) ; if ( storeRef . current == null ) { const middlewareFactories = middlewares ; if ( options . logEnabled ) { middlewareFactories . push ( logDetailedEffects ( ) ) ; } storeRef . current = createStore ( getInitialState , actionsRef . current , optionsRef . current , middlewareFactories ) ; } storeRef . current . setProps ( props ) ; useLayoutEffect ( ( ) => storeRef . current . addStateListener ( ( ) => { forceRefresh ( ) ; } ) , [ ] ) ; const store = storeRef . current ; return { state : store . state , actions : store . actions , loading : store . loading , loadingMap : store . loadingMap , loadingParallelMap : store . loadingParallelMap , abortAction : store . abortAction , } ; } export default useStateDecorator ; param onMount export function useOnMount ( onMount ) { useEffect ( ( ) => { const removeListener = onMount ( ) ; return typeof removeListener === 'function' ? removeListener : undefined ; } , [ ] ) ; } param onUnMount export function useOnUnmount ( onUnmount , propList = [ ] ) { useEffect ( ( ) => { return onUnmount ; } , propList ) ; } param onUnMount export function useOnUnload ( onUnload ) { useEffect ( ( ) => { document . addEventListener ( 'beforeunload' , onUnload ) ; return ( ) => { document . removeEventListener ( 'beforeunload' , onUnload ) ; } ; } , [ ] ) ; }