import { app } from "./app" ; import { Exception } from "./Exception" ; import { Module , ModuleLifecycleListener } from "./platform/Module" ; import { ModuleProxy } from "./platform/ModuleProxy" ; import { Action , setStateAction } from "./reducer" ; import { SagaGenerator } from "./typed-saga" ; import { captureError } from "./util/error-util" ; import { stringifyWithMask } from "./util/json-util" ; export interface TickIntervalDecoratorFlag { tickInterval ? : number ; } export type ActionHandler = ( ... args : any [ ] ) => SagaGenerator ; export type ErrorHandler = ( error : Exception ) => SagaGenerator ; export interface ErrorListener { onError : ErrorHandler ; } type ActionCreator < H > = H extends ( ... args : infer P ) => SagaGenerator ? ( ... args : P ) => Action < P > : never ; type HandlerKeys < H > = { [ K in keyof H ] : H [ K ] extends ( ... args : any [ ] ) => SagaGenerator ? K : never ; } [ Exclude < keyof H , keyof ModuleLifecycleListener | keyof ErrorListener > ] ; export type ActionCreators < H > = { readonly [ K in HandlerKeys < H > ] : ActionCreator < H [ K ] > ; } ; export function register < M extends Module < any , any > > ( module ) { const moduleName = module . name ; if ( ! app . store . getState ( ) . app [ moduleName ] ) { app . store . dispatch ( setStateAction ( moduleName , module . initialState , `@@${ moduleName }/@@init` ) ) ; } const actions = { } ; getKeys ( module ) . forEach ( ( actionType ) => { const method = module [ actionType ] ; const qualifiedActionType = `${ moduleName }/${ actionType }` ; method . actionName = qualifiedActionType ; actions [ actionType ] = ( ... payload ) : Action < any [ ] > => ( { type : qualifiedActionType , payload } ) ; app . actionHandlers [ qualifiedActionType ] = method . bind ( module ) ; } ) ; return new ModuleProxy ( module , actions ) ; } export function * executeAction ( actionName , handler , ... payload ) { try { yield * handler ( ... payload ) ; } catch ( error ) { const actionPayload = stringifyWithMask ( app . loggerConfig ?. maskedKeywords || [ ] , "***" , ... payload ) || "[No Parameter]" ; captureError ( error , actionName , { actionPayload } ) ; } } function getKeys < M extends Module < any , any > > ( module ) { const keys = [ ] ; for ( const propertyName of Object . getOwnPropertyNames ( Object . getPrototypeOf ( module ) ) ) { if ( module [ propertyName ] instanceof Function && propertyName !== "constructor" ) { keys . push ( propertyName ) ; } } return keys ; }