Skip to content

Commit

Permalink
feat(fsm): custom signal callback
Browse files Browse the repository at this point in the history
Co-authored-by: Mohammad Honarvar <honarvar.info@gmail.com>
  • Loading branch information
AliMD and mohammadhonarvar committed Mar 17, 2023
1 parent 9170694 commit 47c22e9
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 21 deletions.
37 changes: 20 additions & 17 deletions core/fsm/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -249,31 +250,33 @@ export const initFsmInstance = (instanceId: string, constructorId: string): void

export const subscribeSignals = (
instanceId: string,
signalList: Array<SignalConfig>,
signalList: Array<InstanceSignalConfig>,
subscribeConstructorSignals = true,
): Array<ListenerSpec> => {
logger.logMethodArgs('subscribeSignals', {instanceId, signalList});
const listenerList: Array<ListenerSpec> = [];

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'},
),
);
Expand All @@ -292,7 +295,7 @@ export const subscribeSignals = (

export const defineConstructorSignals = <T extends FsmTypeHelper>(
constructorId: string,
signalList: Array<SignalConfig<T['TEventId'], T['TContext']>>,
signalList: Array<ConstructorSignalConfig<T['TEventId'], T['TContext']>>,
): void => {
logger.logMethodArgs('defineSignals', {constructorId, signalList: signalList});
const fsmConstructor = getFsmConstructor(constructorId);
Expand All @@ -301,11 +304,11 @@ export const defineConstructorSignals = <T extends FsmTypeHelper>(

export const defineInstanceSignals = <T extends FsmTypeHelper>(
instanceId: string,
signalList: Array<SignalConfig<T['TEventId'], T['TContext']>>,
signalList: Array<InstanceSignalConfig<T['TEventId'], T['TContext']>>,
subscribeConstructorSignals = true,
): Array<ListenerSpec> => {
logger.logMethodArgs('defineSignals', {instanceId, signals: signalList});
return subscribeSignals(instanceId, signalList, subscribeConstructorSignals);
return subscribeSignals(instanceId, signalList as Array<InstanceSignalConfig>, subscribeConstructorSignals);
};

export const render = <TState extends string = string>(
Expand Down
27 changes: 24 additions & 3 deletions core/fsm/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface FsmConstructor {
readonly id: string;
readonly config: FsmConstructorConfig;
actionRecord: ActionRecord;
signalList: Array<SignalConfig>;
signalList: Array<ConstructorSignalConfig>;
}

export interface FsmConstructorConfig<
Expand Down Expand Up @@ -110,7 +110,7 @@ export type ActionRecord<T extends FsmTypeHelper = FsmTypeHelper> = {
readonly [P in T['TActionName']]?: (finiteStateMachine: FsmConsumerInterface<T>) => void | boolean;
};

export type SignalConfig<
export type ConstructorSignalConfig<
TEventId extends string = string,
TContext extends StringifyableRecord = StringifyableRecord
> = {
Expand All @@ -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<T extends FsmConstructorConfig = FsmConstructorConfig> = Readonly<{
TState: Exclude<keyof T['stateRecord'], '$all'>;
Expand Down
2 changes: 1 addition & 1 deletion demo/finite-state-machine/light-machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ lightMachineConsumer.defineSignals([
},
{
signalId: 'jafang',
callback: (signalDetail) => {
callback: (signalDetail: Record<string, string>): void => {
console.log(signalDetail);
},
receivePrevious: 'NextCycle',
Expand Down

0 comments on commit 47c22e9

Please sign in to comment.