@yantrix/automata
Version:
Yantrix framework core: reference Typescript implementation of finite state machine
1,078 lines (1,059 loc) • 34.2 kB
JavaScript
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