From 47c22e92a8a8085148b44b316d649b695ff8071a Mon Sep 17 00:00:00 2001 From: Ali Mihandoost Date: Fri, 17 Mar 2023 02:47:59 +0330 Subject: [PATCH] feat(fsm): custom signal callback Co-authored-by: Mohammad Honarvar --- core/fsm/src/core.ts | 37 ++++++++++++---------- core/fsm/src/type.ts | 27 ++++++++++++++-- demo/finite-state-machine/light-machine.ts | 2 +- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/core/fsm/src/core.ts b/core/fsm/src/core.ts index c495f2645..93aa72337 100644 --- a/core/fsm/src/core.ts +++ b/core/fsm/src/core.ts @@ -3,13 +3,14 @@ import {ListenerSpec, contextProvider, contextConsumer} from '@alwatr/signal'; import type { ActionRecord, + ConstructorSignalConfig, FsmConstructor, FsmConstructorConfig, FsmConsumerInterface, FsmInstance, FsmState, FsmTypeHelper, - SignalConfig, + InstanceSignalConfig, } from './type.js'; import type {OmitFirstParam, SingleOrArray, StringifyableRecord} from '@alwatr/type'; @@ -249,31 +250,33 @@ export const initFsmInstance = (instanceId: string, constructorId: string): void export const subscribeSignals = ( instanceId: string, - signalList: Array, + signalList: Array, subscribeConstructorSignals = true, ): Array => { logger.logMethodArgs('subscribeSignals', {instanceId, signalList}); const listenerList: Array = []; if (subscribeConstructorSignals) { - signalList = getFsmConstructor(getFsmInstance(instanceId).constructorId).signalList.concat(signalList); + signalList = signalList.concat(getFsmConstructor(getFsmInstance(instanceId).constructorId).signalList); } for (const signalConfig of signalList) { listenerList.push( contextConsumer.subscribe( signalConfig.signalId, - (signalDetail: StringifyableRecord): void => { - transition( - instanceId, - signalConfig.transition, - signalConfig.contextName - ? { - [signalConfig.contextName]: signalDetail, - } - : undefined, - ); - }, + signalConfig.callback + ? signalConfig.callback + : (signalDetail: StringifyableRecord): void => { + transition( + instanceId, + signalConfig.transition, + signalConfig.contextName + ? { + [signalConfig.contextName]: signalDetail, + } + : undefined, + ); + }, {receivePrevious: signalConfig.receivePrevious ?? 'No'}, ), ); @@ -292,7 +295,7 @@ export const subscribeSignals = ( export const defineConstructorSignals = ( constructorId: string, - signalList: Array>, + signalList: Array>, ): void => { logger.logMethodArgs('defineSignals', {constructorId, signalList: signalList}); const fsmConstructor = getFsmConstructor(constructorId); @@ -301,11 +304,11 @@ export const defineConstructorSignals = ( export const defineInstanceSignals = ( instanceId: string, - signalList: Array>, + signalList: Array>, subscribeConstructorSignals = true, ): Array => { logger.logMethodArgs('defineSignals', {instanceId, signals: signalList}); - return subscribeSignals(instanceId, signalList, subscribeConstructorSignals); + return subscribeSignals(instanceId, signalList as Array, subscribeConstructorSignals); }; export const render = ( diff --git a/core/fsm/src/type.ts b/core/fsm/src/type.ts index 10abef0c7..2607ac846 100644 --- a/core/fsm/src/type.ts +++ b/core/fsm/src/type.ts @@ -9,7 +9,7 @@ export interface FsmConstructor { readonly id: string; readonly config: FsmConstructorConfig; actionRecord: ActionRecord; - signalList: Array; + signalList: Array; } export interface FsmConstructorConfig< @@ -110,7 +110,7 @@ export type ActionRecord = { readonly [P in T['TActionName']]?: (finiteStateMachine: FsmConsumerInterface) => void | boolean; }; -export type SignalConfig< +export type ConstructorSignalConfig< TEventId extends string = string, TContext extends StringifyableRecord = StringifyableRecord > = { @@ -121,9 +121,30 @@ export type SignalConfig< receivePrevious?: DebounceType; transition: TEventId; contextName?: keyof TContext; - actions?: never; }; +export type InstanceSignalConfig< + TEventId extends string = string, + TContext extends StringifyableRecord = StringifyableRecord +> = { + signalId: string; + /** + * @default `No` + */ + receivePrevious?: DebounceType; +} & ( + | { + transition: TEventId; + contextName?: keyof TContext; + callback?: never; + } + | { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + callback: (detail: any) => void; + transition?: never; + } +); + // type helper export type FsmTypeHelper = Readonly<{ TState: Exclude; diff --git a/demo/finite-state-machine/light-machine.ts b/demo/finite-state-machine/light-machine.ts index d110b3081..621eab5aa 100644 --- a/demo/finite-state-machine/light-machine.ts +++ b/demo/finite-state-machine/light-machine.ts @@ -113,7 +113,7 @@ lightMachineConsumer.defineSignals([ }, { signalId: 'jafang', - callback: (signalDetail) => { + callback: (signalDetail: Record): void => { console.log(signalDetail); }, receivePrevious: 'NextCycle',