UNPKG

@yantrix/automata

Version:

Yantrix framework core: reference Typescript implementation of finite state machine

1,078 lines (1,059 loc) 34.2 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/mixins/BaseClass.ts import { uniqId } from "@yantrix/utils"; var AbstractBaseClass = class { static { __name(this, "AbstractBaseClass"); } correlationId; constructor(...args) { (() => [...args])(); this.correlationId = uniqId(); } next() { return this; } }; // src/mixins/DictionaryContainer.ts function DictionaryContainer() { return (base) => class AbstractDictionaryContainer extends base { static { __name(this, "AbstractDictionaryContainer"); } _dictionary = {}; _dictionaryIndex = /* @__PURE__ */ new Map(); _namespaceIndex = {}; getDictionary(namespace) { if (namespace == null) return this._dictionary; return (this._namespaceIndex[namespace] ?? []).reduce( (dict, itemKey) => Object.assign(dict, { [itemKey]: this._dictionary[itemKey] }), {} ); } _stringHash(str) { let hash = 0; if (!str?.length) return hash; for (let i = 0; i < str.length; i++) { const chr = str.charCodeAt(i); hash = (hash << 5) - hash + chr; hash |= 0; } return Math.abs(hash); } _findItem(itemKey, namespace) { const k = this._getItemKey(itemKey, namespace); const v = this._dictionary[k]; if (v && this._dictionaryIndex.has(v)) return v; delete this._dictionary[k]; if (!namespace) return null; if (this._namespaceIndex[namespace]) this._namespaceIndex[namespace] = this._namespaceIndex[namespace].filter((v2) => v2 !== k); return null; } _getItemKey(itemKey, namespace = "") { if (!itemKey?.length) throw new Error(`item key is empty`); const prefix = namespace?.length ? `${namespace}__` : ""; return `${prefix}${itemKey}`; } _getItemValue(itemKey, namespace) { if (!itemKey?.length) throw new Error(`item key is empty`); let value = this._stringHash(this._getItemKey(itemKey, namespace)); if (Object.values(this._dictionary).includes(value)) value = value + this._stringHash(JSON.stringify(this._dictionary)); return value; } _deleteItemKey(itemKey) { const item = this?._dictionary[itemKey]; if (!item) return this; const meta = this._dictionaryIndex.get(item); delete this._dictionary[itemKey]; if (meta?.namespace) { this._namespaceIndex[meta.namespace] = this._namespaceIndex[meta.namespace]?.filter( (v) => v !== itemKey ); } this._dictionaryIndex.delete(item); return this; } _getValueData(value) { return this._dictionaryIndex.get(value) ?? null; } _addItemKey(itemKey, namespace) { const k = this._getItemKey(itemKey, namespace); if (this._dictionary[k]) { throw new Error( `Item key ${itemKey} is taken within ${namespace == null ? "default namespace" : `namespace "${namespace}"`}` ); } const value = this._getItemValue(itemKey, namespace); this._dictionary[k] = value; if (namespace) { if (!this._namespaceIndex[namespace]) this._namespaceIndex[namespace] = []; this._namespaceIndex[namespace].push(k); } this._dictionaryIndex.set(value, { key: k, namespace }); return value; } _clearItems(namespace) { if (namespace != null) { for (const itemKey of this._namespaceIndex[namespace] ?? []) { this._deleteItemKey(itemKey); } delete this._namespaceIndex[namespace]; } else { this._namespaceIndex = {}; this._dictionaryIndex.clear(); this._dictionary = {}; } return this; } }; } __name(DictionaryContainer, "DictionaryContainer"); // src/mixins/BasicActionContainer.ts import { isPositiveInteger } from "@yantrix/utils"; function BasicActionContainer() { return (Base) => class AbstractBasicActionContainer extends Base { static { __name(this, "AbstractBasicActionContainer"); } #_defaultActionValidator = isPositiveInteger; #_actionValidator; constructor(...args) { super(args); } get validateAction() { return this.#_actionValidator ?? this.#_defaultActionValidator; } setActionValidator(actionValidator = null) { if (actionValidator === null) { this.#_actionValidator = void 0; return this; } if (typeof actionValidator !== "function") throw new Error(`passed Action Validator is not a function`); this.#_actionValidator = actionValidator.bind(this); return this; } }; } __name(BasicActionContainer, "BasicActionContainer"); // src/mixins/ExtendedActionContainer.ts function ExtendedActionContainer() { return (Proto) => class AbstractExtendedActionContainer extends BasicActionContainer()(Proto) { static { __name(this, "AbstractExtendedActionContainer"); } _payloadValidator; get validateActionPayload() { return this._payloadValidator ?? this._defaultPayloadValidator; } setActionPayloadValidator(payloadValidator) { if (payloadValidator === null) { this._payloadValidator = void 0; return this; } if (typeof payloadValidator !== "function") throw new Error(`passed Payload Validator is not a function`); this._payloadValidator = payloadValidator.bind(this); return this; } _defaultPayloadValidator = /* @__PURE__ */ __name((p) => !!this.validateAction && this.validateAction(p?.action) && (p?.payload === null || typeof p.payload === "object"), "_defaultPayloadValidator"); }; } __name(ExtendedActionContainer, "ExtendedActionContainer"); // src/ActionDictionary.ts function createActionDictionary() { return (Base) => class AbstractActionDictionary extends DictionaryContainer()( ExtendedActionContainer()(Base) ) { static { __name(this, "AbstractActionDictionary"); } getActionKeys({ actions = [], namespace = void 0 }) { return (actions ?? []).map((action) => { if (!this.validateAction(action)) return null; const data = this._getValueData(action); if (!data) return null; if (namespace !== null && namespace !== data.namespace) return null; return data.key; }); } clearActions(namespace) { return this._clearItems(namespace); } removeActions({ namespace, actions = [], keys = [] }) { const actionsToDelete = [ ...actions.filter(this.validateAction), ...keys.flatMap((k) => k ? [this._findItem(k, namespace)] : []) ].filter((v) => v !== null); const actionKeys = actionsToDelete.map((action) => this._getValueData(action)).filter((data) => !!data && (namespace === null || namespace === data?.namespace)); for (const actionKey of actionKeys) { if (actionKey) this._deleteItemKey(actionKey.key); } return this; } getActionValues({ namespace = void 0, keys = [] }) { return (keys ?? []).flatMap((k) => k ? [this._findItem(k, namespace)] : []); } addActions({ namespace = void 0, keys }) { return (keys || []).flatMap((k) => k ? [this._addItemKey(k, namespace)] : []); } }; } __name(createActionDictionary, "createActionDictionary"); var BasicActionDictionary = class extends createActionDictionary()(AbstractBaseClass) { static { __name(this, "BasicActionDictionary"); } constructor() { super(); } }; // src/Automata.ts import { isPositiveInteger as isPositiveInteger4 } from "@yantrix/utils"; // src/mixins/BasicEventContainer.ts import { isPositiveInteger as isPositiveInteger2 } from "@yantrix/utils"; function BasicEventContainer() { return (Base) => class AbstractBasicEventContainer extends Base { static { __name(this, "AbstractBasicEventContainer"); } #_defaultEventValidator = isPositiveInteger2; #_eventValidator; constructor(...args) { super(args); } get validateEvent() { return this.#_eventValidator ?? this.#_defaultEventValidator; } setEventValidator(eventValidator = null) { if (eventValidator === null) { this.#_eventValidator = void 0; return this; } if (typeof eventValidator !== "function") throw new Error(`passed Event Validator is not a function`); this.#_eventValidator = eventValidator.bind(this); return this; } }; } __name(BasicEventContainer, "BasicEventContainer"); // src/mixins/BasicStateContainer.ts import { isPositiveInteger as isPositiveInteger3 } from "@yantrix/utils"; function BasicStateContainer() { return (Base) => class AbstractBasicStateContainer extends Base { static { __name(this, "AbstractBasicStateContainer"); } #_defaultStateValidator = isPositiveInteger3; #_stateValidator; constructor(...args) { super(args); } get validateState() { return this.#_stateValidator ?? this.#_defaultStateValidator; } setStateValidator(stateValidator = null) { if (stateValidator === null) { this.#_stateValidator = void 0; return this; } if (typeof stateValidator !== "function") throw new Error(`passed State Validator is not a function`); this.#_stateValidator = stateValidator.bind(this); return this; } }; } __name(BasicStateContainer, "BasicStateContainer"); // src/mixins/BasicValidatorContainer.ts function BasicValidatorContainer() { return (Proto) => class AbstractBasicValidatorContainer extends BasicStateContainer()( BasicEventContainer()(BasicActionContainer()(Proto)) ) { static { __name(this, "AbstractBasicValidatorContainer"); } }; } __name(BasicValidatorContainer, "BasicValidatorContainer"); // src/Automata.ts function createAutomata() { return (Base) => class AbstractGenericAutomata extends BasicValidatorContainer()(Base) { static { __name(this, "AbstractGenericAutomata"); } eventAdapter = null; #state = null; #context = null; #lastAction = null; #actionQueue = []; #enabled = true; #paused = false; #rootReducer = null; #functionRegistry = null; #currentCycle = 1; constructor(eventAdapter = null, ...args) { super(args); if (eventAdapter) this.eventAdapter = eventAdapter; } get state() { return this.#state; } get context() { return this.#context; } get lastAction() { return this.#lastAction; } set lastAction(action) { this.#lastAction = action; } get currentCycle() { return this.#currentCycle; } incrementCycle() { this.#currentCycle++; return this; } clearActionQueue() { this.#actionQueue = []; return this; } collapseActionQueue() { const actions = (this.#actionQueue ?? []).slice(); const newState = this.reduceQueue(); if (this.isEnabled()) { this.setContext(newState); this.clearActionQueue(); } return { actions, newState }; } enable() { this.#enabled = true; return this; } disable(clearQueue = false) { this.#enabled = false; if (clearQueue) this.clearActionQueue(); return this; } isEnabled() { return this.#enabled ?? true; } isPaused() { return this.#paused ?? false; } pause() { this.#paused = true; return this; } resume() { this.#paused = false; if (this.isEnabled()) this.collapseActionQueue(); return this; } init(params) { const { state = null, context, paused = false, enabled = true, rootReducer = null, stateValidator, actionValidator, eventValidator, functionRegistry } = params; if (rootReducer == null) this.#rootReducer = null; else if (rootReducer instanceof Function) this.#rootReducer = rootReducer; else throw new Error(`Invalid Root Reducer supplied: ${rootReducer}`); if (!this.validateState(state)) throw new Error(`Invalid initial State: ${state}`); if (functionRegistry == null) { this.#functionRegistry = null; } else { this.#functionRegistry = functionRegistry; } this.#actionQueue = []; this.#enabled = enabled; this.#paused = paused; this.setContext({ state, context }); if (stateValidator) this.setStateValidator(stateValidator); if (actionValidator) this.setActionValidator(actionValidator); if (eventValidator) this.setEventValidator(eventValidator); return this; } dispatch(action) { if (!this.validateAction(action?.action)) throw new Error(`Invalid Action: ${JSON.stringify(action)}`); if (!this.#rootReducer) { throw new Error( `Root Reducer is not defined. Please init the Instance with a rootReducer. Dispatched Action: ${JSON.stringify( action )}` ); } const reducedValue = this.#rootReducer({ ...action, ...this.reduceQueue() }); if (!reducedValue || !this.validateState(reducedValue.state)) throw new Error(`Invalid Reduced State: ${reducedValue}`); if (this.isPaused()) { this.#actionQueue = this.getActionQueue().concat(action); } else if (this.isEnabled()) { this.clearActionQueue(); this.setContext(reducedValue); if (this.eventAdapter) { this.eventAdapter.handleTransition(this.getContext()); } } return reducedValue; } getContext() { return { state: this.state, context: this.context }; } getActionQueue() { return (this.#actionQueue ?? []).slice(0); } getReducer() { return this.#rootReducer; } consumeAction(count = 1) { if (!isPositiveInteger4(count)) throw new Error(`Invalid Action Count: ${count}`); let currentResponse = { action: null, newState: this.getContext() }; const queue = this.getActionQueue().slice(0, count); while (queue.length) { currentResponse = this.reduceQueueItem(queue, currentResponse.newState); } if (this.isEnabled()) { this.setActionQueue(this.getActionQueue().slice(count)).setContext(currentResponse.newState); } return currentResponse; } reduceQueueItem(queue = this.getActionQueue(), newState = this.getContext()) { if (!this.#rootReducer) throw new Error(`Root Reducer is not defined. Please init the Instance with a rootReducer.`); const currentResponse = { action: null, newState: newState || this.getContext() }; if (!queue?.length) return currentResponse; const currentAction = queue.shift(); if (!currentAction) return currentResponse; if (!this.validateAction(currentAction?.action)) throw new Error(`Invalid Action: ${currentAction}`); currentResponse.newState = this.#rootReducer({ ...currentResponse.newState, ...currentAction }); currentResponse.action = currentAction; return currentResponse; } reduceQueue = /* @__PURE__ */ __name(() => { let reducedValue = this.getContext(); if (!this.#rootReducer) throw new Error(`Root Reducer is not defined. Please init the Instance with a rootReducer`); const queue = this.getActionQueue(); while (queue?.length) reducedValue = this.reduceQueueItem(queue, reducedValue).newState; return reducedValue; }, "reduceQueue"); setContext = /* @__PURE__ */ __name((context = null) => { if (!context || !this.validateState(context?.state)) throw new Error(`Invalid Context: ${context}`); this.#state = context.state; this.#context = context.context ?? null; return this; }, "setContext"); setActionQueue = /* @__PURE__ */ __name((queue) => { if (!Array.isArray(queue)) throw new Error(`Invalid Action Queue: ${queue}`); this.#actionQueue = queue; return this; }, "setActionQueue"); getFunctionRegistry() { return this.#functionRegistry; } setFunctionRegistry = /* @__PURE__ */ __name((registry = null) => { this.#functionRegistry = registry; return this; }, "setFunctionRegistry"); getEventAdapter() { return this.eventAdapter; } setEventAdapter = /* @__PURE__ */ __name((adapter = null) => { this.eventAdapter = adapter; return this; }, "setEventAdapter"); }; } __name(createAutomata, "createAutomata"); var GenericAutomata = class extends createAutomata()(AbstractBaseClass) { static { __name(this, "GenericAutomata"); } }; // src/EventAdapter.ts import { unifyObjectKey } from "@yantrix/utils"; // src/mixins/ExtendedEventContainer.ts function ExtendedEventContainer() { return (Proto) => class AbstractExtendedEventContainer extends BasicEventContainer()(Proto) { static { __name(this, "AbstractExtendedEventContainer"); } #__eventMetaValidator; get validateEventMeta() { return this.#__eventMetaValidator ?? this.#__defaultEventMetaValidator; } setEventMetaValidator(eventMetaValidator) { if (eventMetaValidator === null) { this.#__eventMetaValidator = void 0; return this; } if (typeof eventMetaValidator !== "function") throw new Error(`passed Event Meta Validator is not a function`); this.#__eventMetaValidator = eventMetaValidator.bind(this); return this; } #__defaultEventMetaValidator = /* @__PURE__ */ __name((p) => this.validateEvent(p?.event) && (p?.meta === null || typeof p.meta === "object"), "#__defaultEventMetaValidator"); }; } __name(ExtendedEventContainer, "ExtendedEventContainer"); // src/mixins/ExtendedStateContainer.ts function ExtendedStateContainer() { return (Proto) => class AbstractExtendedStateContainer extends BasicStateContainer()(Proto) { static { __name(this, "AbstractExtendedStateContainer"); } #__contextValidator; get validateContext() { return this.#__contextValidator ?? this.#__defaultContextValidator; } setContextValidator(contextValidator) { if (contextValidator === null) { this.#__contextValidator = void 0; return this; } if (typeof contextValidator !== "function") throw new Error(`passed Context Validator is not a function`); this.#__contextValidator = contextValidator.bind(this); return this; } #__defaultContextValidator = /* @__PURE__ */ __name((p) => this.validateState(p?.state) && (p?.context === null || typeof p.context === "object"), "#__defaultContextValidator"); }; } __name(ExtendedStateContainer, "ExtendedStateContainer"); // src/mixins/ExtendedValidatorContainer.ts function ExtendedValidatorContainer() { return (Proto) => class AbstractExtendedValidatorContainer extends ExtendedStateContainer()( ExtendedEventContainer()( ExtendedActionContainer()(Proto) ) ) { static { __name(this, "AbstractExtendedValidatorContainer"); } }; } __name(ExtendedValidatorContainer, "ExtendedValidatorContainer"); // src/EventAdapter.ts function createEventAdapter() { return (Base) => class AbstractAutomataEventAdapter extends ExtendedValidatorContainer()(Base) { static { __name(this, "AbstractAutomataEventAdapter"); } #eventListeners; #eventEmitters; constructor() { super(); this.#eventListeners = {}; this.#eventEmitters = {}; } addEventEmitter(on, emitter) { if (on === null || on === void 0 || !(emitter instanceof Function) || !this.validateState(on)) return null; this.#eventEmitters = Object.assign(this.#eventEmitters ?? {}, { [on]: (this.#eventEmitters[on] ?? []).concat(emitter) }); return () => { if (this.#eventEmitters?.[on]) { const newEmitters = (this.#eventEmitters[on] || []).filter((v) => v !== emitter); if (!newEmitters.length) delete this.#eventEmitters[on]; else this.#eventEmitters[on] = newEmitters; } }; } addEventListener(type, handler) { if (type === null || type === void 0 || !(handler instanceof Function) || !this.validateEvent(type)) return null; this.#eventListeners = Object.assign(this.#eventListeners ?? {}, { [type]: [...this.#eventListeners?.[type] ?? [], handler] }); return () => { if (this.#eventListeners?.[type]) { const newHandlers = (this.#eventListeners[type] || []).filter((v) => v !== handler); if (!newHandlers.length) delete this.#eventListeners[type]; else this.#eventListeners[type] = newHandlers; } }; } handleEvent(event) { if (!this.validateEventMeta(event)) return []; return (this.#eventListeners?.[event.event] || []).map((handler) => handler(event)).filter((action) => this.validateAction(action.action)); } handleTransition(newState) { if (!this.validateContext(newState)) return []; return (this.#eventEmitters?.[newState.state] || []).map((emitter) => emitter(newState)).filter((event) => this.validateEvent(event.event)); } removeAllListeners(type = null) { switch (true) { case type === null: this.#eventListeners = {}; break; default: if (this.validateEvent(type) && this.#eventListeners?.[type]) delete this.#eventListeners[type]; } return this; } removeAllEmitters(type = null) { switch (true) { case type === null: this.#eventEmitters = {}; break; default: if (this.validateState(type) && this.#eventEmitters?.[type]) delete this.#eventEmitters[type]; } return this; } getObservedEvents() { return Object.keys(this.#eventListeners).map(unifyObjectKey).filter((k) => this.#eventListeners[k]?.length).filter(this.validateEvent); } getObservedStates() { return Object.keys(this.#eventEmitters).map(unifyObjectKey).filter((k) => this.#eventEmitters[k]?.length).filter(this.validateState); } }; } __name(createEventAdapter, "createEventAdapter"); var AutomataEventAdapter = class extends createEventAdapter()(AbstractBaseClass) { static { __name(this, "AutomataEventAdapter"); } constructor() { super(); } }; // src/EventBus.ts function createEventBus() { return (Proto) => class AbstractAutomataEventBus extends ExtendedEventContainer()(Proto) { static { __name(this, "AbstractAutomataEventBus"); } #isProcessing; #isPaused; #eventStack; #eventSubscriptions; constructor() { super(); this.#eventStack = []; this.#eventSubscriptions = /* @__PURE__ */ new Map(); this.#isProcessing = false; this.#isPaused = false; } subscribe(event, callback) { let eventCallbacks = this.#eventSubscriptions.get(event); if (!eventCallbacks) { eventCallbacks = /* @__PURE__ */ new Set(); this.#eventSubscriptions.set(event, eventCallbacks); } eventCallbacks.add(callback); return this; } unsubscribe(event, callback) { const eventCallbacks = this.#eventSubscriptions.get(event); if (eventCallbacks && callback) { eventCallbacks.delete(callback); } return this; } dispatch(...events) { this.#eventStack.push(...events); this.processEvents(); return this; } getEventStack() { return this.#eventStack.slice(); } clearEventStack() { this.#eventStack = []; return this; } pause() { this.#isPaused = true; return this; } resume() { this.#isPaused = false; this.processEvents(); return this; } isRunning() { return !this.#isPaused; } processEvents() { if (this.#isProcessing || this.#isPaused) { return []; } this.#isProcessing = true; while (this.#eventStack.length > 0) { const eventObject = this.#eventStack.shift(); if (!eventObject) continue; if (this.validateEventMeta(eventObject)) { const eventCallbacks = this.#eventSubscriptions.get(eventObject.event); if (eventCallbacks) { eventCallbacks.forEach((callback) => { callback(eventObject); }); } } } this.#isProcessing = false; return this.#eventStack.slice(); } }; } __name(createEventBus, "createEventBus"); var BasicEventBus = class extends createEventBus()(AbstractBaseClass) { static { __name(this, "BasicEventBus"); } constructor() { super(); } }; // src/EventDictionary.ts function createEventDictionary() { return (Base) => class AbstractEventDictionary extends DictionaryContainer()( ExtendedEventContainer()(Base) ) { static { __name(this, "AbstractEventDictionary"); } /** * Retrieves event keys bound to the namespace * @param obj - object with list of events to get keys for and associated namespace * @param obj.events - list of events to get keys for * @param obj.namespace - associated namespace * @returns Array of event keys */ getEventKeys({ events = [], namespace = void 0 }) { return (events ?? []).map((event) => { if (!this.validateEvent(event)) return null; const data = this._getValueData(event); if (!data) return null; if (namespace !== null && namespace !== data.namespace) return null; return data?.key; }); } /** * Clears all events bound to the namespace * @param namespace * @returns dictionary */ clearEvents(namespace) { return this._clearItems(namespace); } /** * Removes specified events from the dictionary * @param obj - object with namespace, list of events/keys to delete * @returns dictionary */ removeEvents({ namespace, events = [], keys = [] }) { const eventsToDelete = [ ...events.filter(this.validateEvent), ...keys.flatMap((k) => k ? [this._findItem(k, namespace)] : []) ].filter((v) => v !== null); const eventKeys = eventsToDelete.map((event) => this._getValueData(event)).filter((data) => !!data && (namespace == null || namespace === data?.namespace)); for (const eventKey of eventKeys) { if (eventKey) this._deleteItemKey(eventKey.key); } return this; } /** * Retrieves event values bound to the namespace * @param obj - object with list of keys to get events from and associated namespace * @returns Array of event values */ getEventValues({ namespace = void 0, keys = [] }) { return (keys ?? []).flatMap((k) => k ? [this._findItem(k, namespace)] : []); } /** * Add events to the namespace * @param obj - object with list of keys to get events from and associated namespace * @returns Array of added events */ addEvents({ namespace = void 0, keys }) { return (keys || []).flatMap((k) => k ? [this._addItemKey(k, namespace)] : []); } }; } __name(createEventDictionary, "createEventDictionary"); var BasicEventDictionary = class extends createEventDictionary()(AbstractBaseClass) { static { __name(this, "BasicEventDictionary"); } constructor() { super(); } }; var EventDictionary = new BasicEventDictionary(); // src/FunctionDictionary.ts var FunctionDictionary = class { static { __name(this, "FunctionDictionary"); } functions; constructor(functions) { this.functions = functions ?? {}; } register(f, callback) { if (typeof f === "string" && callback != null) { return this.registerSingleFunction(f, callback); } else if (typeof f === "object") { return this.registerMultipleFunctions(f); } else { throw new TypeError("Incorrect arguments"); } } registerSingleFunction(functionKey, callback) { if (functionKey.length < 1 || functionKey.length > 255) { throw new Error(`Function key length must be between 1-255 symbols!`); } if (!functionKey.match(/^[a-z]\w+$/i)) { throw new Error("Incorrect function key format!"); } if (this.functions[functionKey] !== void 0) { throw new Error(`Function with the key ${functionKey} already exists, overwrite not permitted!`); } this.functions[functionKey] = callback; return { [functionKey]: callback }; } registerMultipleFunctions(functionMap) { Object.entries(functionMap).forEach(([name, callback]) => this.registerSingleFunction(name, callback)); return functionMap; } has(functionKey) { const func = this.functions[functionKey]; return func !== void 0; } get(functionKey) { const func = this.functions[functionKey]; if (func) return func; else throw new Error(`Function with the key ${functionKey} not found!`); } call(functionKey, ...args) { const func = this.get(functionKey); return func(...args); } clear() { this.functions = {}; } }; // src/StateDictionary.ts import { uniqId as uniqId2 } from "@yantrix/utils"; function createStateDictionary() { return (Base) => class AbstractStateDictionary extends DictionaryContainer()( ExtendedStateContainer()(Base) ) { static { __name(this, "AbstractStateDictionary"); } #transformers = {}; #transformersIndex = {}; getStateKeys({ states = [], namespace = void 0 }) { return (states ?? []).map((state) => { if (!this.validateState(state)) return null; const data = this._getValueData(state); if (!data) return null; if (namespace !== null && namespace !== data.namespace) return null; return data.key; }); } clearStates(namespace) { return this._clearItems(namespace); } removeStates({ namespace, states = [], keys = [] }, removeContextTransformers) { const statesToDelete = [ ...states.filter(this.validateState), ...keys.flatMap((k) => k ? [this._findItem(k, namespace)] : []) ].filter((v) => v != null); const stateKeys = statesToDelete.map((State) => this._getValueData(State)).filter((data) => !!data && (namespace == null || namespace === data?.namespace)); for (const stateKey of stateKeys) { if (stateKey) this._deleteItemKey(stateKey.key); } if (removeContextTransformers) { statesToDelete.flatMap((State) => Object.keys(this.#transformers[State] ?? {})).forEach((id) => this.removeContextTransformerById(id)); } return this; } getStateValues({ namespace = void 0, keys = [] }) { return (keys ?? []).map((k) => this._findItem(k, namespace)); } addStates({ namespace = void 0, keys }) { return (keys || []).map((k) => this._addItemKey(k, namespace)); } addContextTransformer(state, transformer, namespace) { const id = this.#getTransformerKey(state, namespace); this.#transformersIndex[id] = state; this.#transformers[state] = Object.assign(this.#transformers[state] ?? {}, { [id]: { namespace, transformer } }); return id; } removeContextTransformerById(id) { if (this.#transformersIndex[id]) { const state = this.#transformersIndex[id]; if (state && this.#transformers?.[state]?.[id]) { this.#transformers[state] = Object.fromEntries( Object.entries(this.#transformers[state] ?? {}).filter(([key]) => key !== id) ); } delete this.#transformersIndex[id]; } return this; } removeContextTransformer(state, transformer, namespace) { Object.keys(this.#transformers[state] ?? {}).find((id) => { const item = this.#transformers[state]?.[id]; if (!item) return false; if (item.transformer === transformer && (item?.namespace || null) === (namespace || null)) this.removeContextTransformerById(id); return true; }); return this; } getContextTransformers(namespace) { return Object.keys(this.#transformers).reduce( (obj, state) => ({ ...obj, [state]: Object.fromEntries( Object.entries(this.#transformers[state] ?? {}).filter( ([, value]) => (value.namespace || null) === (namespace || null) ) ) }), {} ); } runContextTransformers(id, context) { const stateType = this.#transformersIndex[id]; if (stateType !== context?.state) return context; const transformers = this.#transformers[stateType]?.[id]?.transformer; if (!transformers) return context; return transformers(context); } #getTransformerKey(state, namespace) { return this._getItemKey(`${state}/${uniqId2()}`, namespace); } }; } __name(createStateDictionary, "createStateDictionary"); var BasicStateDictionary = class extends createStateDictionary()(AbstractBaseClass) { static { __name(this, "BasicStateDictionary"); } constructor() { super(); } }; export { AutomataEventAdapter, BasicActionDictionary, BasicEventBus, BasicEventDictionary, BasicStateDictionary, EventDictionary, FunctionDictionary, GenericAutomata, createActionDictionary, createAutomata, createEventAdapter, createEventBus, createEventDictionary, createStateDictionary }; //# sourceMappingURL=index.js.map