import {type ActionHandler} from "../module"; import {Module} from "../platform/Module"; import {type State} from "../reducer"; import {app} from "../app"; import {stringifyWithMask} from "../util/json-util"; import {type Logger} from "../Logger"; import {type SagaGenerator} from "../typed-saga"; export {Interval} from "./Interval"; export {Loading} from "./Loading"; export {Log} from "./Log"; export {Mutex} from "./Mutex"; export {RetryOnNetworkConnectionError} from "./RetryOnNetworkConnectionError"; export {SilentOnNetworkConnectionError} from "./SilentOnNetworkConnectionError"; /** * Decorator type declaration, required by TypeScript. */ type HandlerDecorator = (target: object, propertyKey: string, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor; type VoidFunctionDecorator = (target: object, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => void>) => TypedPropertyDescriptor<(...args: any[]) => void>; type ActionHandlerWithMetaData = ActionHandler & {actionName: string; maskedParams: string}; type HandlerInterceptor = (handler: ActionHandlerWithMetaData, thisModule: Module) => SagaGenerator; type FunctionInterceptor = (handler: () => void, rootState: Readonly, logger: Logger) => void; /** * A helper for ActionHandler functions (Saga). */ export function createActionHandlerDecorator(interceptor: HandlerInterceptor): HandlerDecorator { return (target, propertyKey, descriptor) => { const fn = descriptor.value!; descriptor.value = function* (...args: any[]): SagaGenerator { const boundFn: ActionHandlerWithMetaData = fn.bind(this, ...args) as any; // Do not use fn.actionName, it returns undefined // The reason is, fn is created before module register(), and the actionName had not been attached then boundFn.actionName = (descriptor.value as any).actionName; boundFn.maskedParams = stringifyWithMask(app.loggerConfig?.maskedKeywords || [], "***", ...args) || "[No Parameter]"; yield* interceptor(boundFn, this as any); }; return descriptor; }; } /** * A helper for regular functions. */ export function createRegularDecorator(interceptor: FunctionInterceptor): VoidFunctionDecorator { return (target, propertyKey, descriptor) => { const fn = descriptor.value!; descriptor.value = function (...args: any[]) { const rootState: S = app.store.getState() as S; const logger = app.logger; interceptor(fn.bind(this, ...args), rootState, logger); }; return descriptor; }; }