import { EffectAction } from '../types' ; import { getBeanWrapper , isPromise } from '../utils' ; export returns { MethodDecorator } export function Effect ( ) { return ( prototype , propertyKey , descriptor ? ) => { if ( descriptor === undefined ) { descriptor = Object . getOwnPropertyDescriptor ( prototype , propertyKey ) ! ; } const effectName = propertyKey ; const originalMethod = descriptor . value ; descriptor . value = function < T > ( this , ... args ) { const beanWrapper = getBeanWrapper ( this ) ; if ( beanWrapper !== undefined ) { const emitEffectAction = ( action ) => { const observer = beanWrapper . beanObserver ; if ( observer !== undefined ) { observer . effect$ . next ( { effect : effectName , effectTarget : Reflect . get ( ( this as unknown ) as object , effectName ) , ... action , } as EffectAction < T > ) ; } } ; emitEffectAction ( { loading : true , error : null } ) ; const result = originalMethod . apply ( this , args ) ; if ( isPromise ( result ) ) { return result . then ( data => { emitEffectAction ( { loading : false , error : null , data : data as T } ) ; return data ; } ) . catch ( ( e ) => { emitEffectAction ( { loading : false , error : e , data : undefined } ) ; throw e ; } ) ; } else { throw new Error ( 'Effect must decorated for a Promise function' ) ; } } return originalMethod . apply ( this , args ) ; } ; return descriptor ; } ; }