import { EffectHandler, IConfigurableFx, IEffectorFactory, IStore, Params, SimpleEffectHandler, StateEffectHandler, StateEffectVector, StoreEvent, } from "./model"; /* * These builtin effects don't use the effect() factory because they * need to remain properly generic; they have special conveniences * in the Effector that use them directly */ function dispatch( theStore: IStore, event: StoreEvent, ) { theStore.dispatch(event); } function dispatchLater( theStore: IStore, event: StoreEvent, timeoutMillis: number, ) { setTimeout(() => { theStore.dispatch(event); }, timeoutMillis); } /* * Effect handler util classes */ abstract class BaseEffector implements IConfigurableFx { abstract state: State; effects: StateEffectVector[] = []; store(newState: State): void { this.state = newState; } dispatch(event: StoreEvent): void { this.produce(dispatch, event); } dispatchLater(event: StoreEvent, timeoutMillis: number): void { this.produce(dispatchLater, event, timeoutMillis); } produce

(handler: SimpleEffectHandler

, ...params: P): void; produce

(handler: StateEffectHandler, ...params: P): void; produce

(handler: EffectHandler, ...params: P) { this.effects.push([handler as EffectHandler, params]); } /** * Invokes the effects enqueued in this Effector */ invokeQueued(store: IStore) { this.effects.forEach(([effectHandler, effectParams]) => { if (effectParams.length === effectHandler.length) { (effectHandler as SimpleEffectHandler)(...effectParams); } else { effectHandler(store, ...effectParams); } }); } reset() { // clear queued effects this.effects.splice(0); } } export class DefaultEffector extends BaseEffector { constructor( public state: State, ) { super(); } store(newState: State): void { this.state = newState; } } export class SingleEffectorFactory implements IEffectorFactory { private lastInstance: IConfigurableFx | undefined; acquire(state: State): IConfigurableFx { if (!this.lastInstance) { return new DefaultEffector(state); } const acquired = this.lastInstance; acquired.state = state; return acquired; } release(effector: IConfigurableFx): void { this.lastInstance = effector; effector.reset(); } }