import { IActionMapBasic, IActionMapInternal } from './action-map'; import { IActionCreator } from './action'; export type ActionHandlerCallback = ( this: IActionHandler, actionMap: AM, inject: Inject ) => any; export interface IActionHandlerConfiguration { inputs: readonly IActionCreator[]; outputs?: readonly IActionCreator[]; run: ActionHandlerCallback; name?: string; inject?: Inject; } export interface IActionHandler { getName: () => string; getInputs: () => readonly IActionCreator[]; getInputSet: () => ReadonlySet; getOutputs: () => readonly IActionCreator[] | undefined; getOutputSet: () => ReadonlySet | undefined; getInputsAndOutputs: () => readonly IActionCreator[]; getInputsAndOutputsSet: () => ReadonlySet; inject: (inject: Inject) => void; getInjected: () => Inject; invoke: (actionMap: IActionMapInternal) => any; } export class ActionHandler implements IActionHandler { protected _inputs: readonly IActionCreator[]; protected _inputSet: ReadonlySet; protected _outputs?: readonly IActionCreator[]; protected _outputSet?: ReadonlySet; protected _inputsAndOutputs: readonly IActionCreator[]; protected _inputsAndOutputsSet: ReadonlySet; protected _name: string; protected _injected: Inject; protected _callback: ActionHandlerCallback; constructor(config: IActionHandlerConfiguration) { this._callback = config.run; this._inputSet = new Set(config.inputs); this._inputs = [...this._inputSet]; this._inputsAndOutputs = [...this._inputs]; if (config.outputs && config.outputs.length) { this._outputSet = new Set(config.outputs); this._outputs = [...this._outputSet]; // @ts-expect-error - _inputsAndOutputs is readonly and must be because it is exposed as a public method this._inputsAndOutputs.push(...this._outputs); } this._inputsAndOutputsSet = new Set(this._inputsAndOutputs); this._injected = config.inject!; this._name = config.name ?? 'ActionHandler(Unnamed)'; } getName() { return this._name; } getInputs() { return this._inputs; } getInputSet() { return this._inputSet; } getOutputs() { return this._outputs; } getOutputSet() { return this._outputSet; } getInputsAndOutputs() { return this._inputsAndOutputs; } getInputsAndOutputsSet() { return this._inputsAndOutputsSet; } inject(inject: Inject) { this._injected = inject; } getInjected() { return this._injected; } invoke(actionMap: IActionMapInternal) { actionMap._setIsHandlerExecuted(true); const result = this._callback(actionMap as unknown as AM, this._injected); actionMap._setIsHandlerExecuted(false); return result; } } export function createHandler( config: IActionHandlerConfiguration ): ActionHandler { return new ActionHandler(config); }