fsm-state-manager
Version:
A Flow FSM using a finite state machine pattern
100 lines (99 loc) • 4.39 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StateManagerFSM = void 0;
var subscription_manager_1 = require("./services/subscription-manager");
var StateManagerFSM = /** @class */ (function () {
function StateManagerFSM(transitionRules, options) {
if (options === void 0) { options = {}; }
this.stateData = { state: '', appliedData: [] };
this.options = { devMode: false, logTransitions: false, subscriptionMode: false };
this.transitionRules = transitionRules;
this.options = options;
this.subscriptionManager = new subscription_manager_1.SubscriptionManager();
if (!this.options.subscriptionMode) {
this.subscribe = (function () {
throw new Error('Subscription mode is disabled. ' +
'Turn on `subscriptionMode: true` in options, for using .subscribe().');
});
}
}
StateManagerFSM.prototype.setStateData = function (currentStateData) {
this.stateData = currentStateData;
if (this.options.subscriptionMode) {
this.subscriptionManager.notify(currentStateData.state, currentStateData);
}
};
StateManagerFSM.prototype.getStateData = function () {
return this.stateData;
};
StateManagerFSM.prototype.transition = function (event, appliedData) {
if (!this.isInitialized()) {
throw new Error('[FSM Error] Initial state not set. Use setStateData() first.');
}
var rule = this.transitionRules[this.stateData.state][event];
if (!rule)
return this.warnWrongTransition(event);
if (!this.checkGuard(event)) {
return this.warnGuard(event);
}
this.applyTransition(rule, event, appliedData);
};
StateManagerFSM.prototype.isInitialized = function () {
return this.stateData.state !== '';
};
StateManagerFSM.prototype.warnWrongTransition = function (event) {
if (this.options.devMode) {
console.warn("[FSM Warn] Invalid event '".concat(event, "' for state '").concat(this.stateData.state, "'"));
}
};
StateManagerFSM.prototype.warnGuard = function (event) {
console.warn("[FSM Warn] Guard blocked '".concat(event, "' in state '").concat(this.stateData.state, "'"));
};
StateManagerFSM.prototype.applyTransition = function (rule, event, appliedData) {
var next = rule.transitionAction(this.stateData, { appliedData: appliedData });
if (this.options.logTransitions) {
console.log("[FSM] Transition: '".concat(this.stateData.state, "' state \u2192 '").concat(next.state, "' state triggered by '").concat(event, "' event"));
}
this.stateData = next;
if (this.options.subscriptionMode) {
this.subscriptionManager.notify(next.state, next);
}
};
StateManagerFSM.prototype.transitionAction = function (event) {
var stateData = this.stateData;
if (!stateData) {
return;
}
return this.transitionRules[stateData.state][event];
};
StateManagerFSM.prototype.checkGuard = function (event) {
var transition = this.transitionAction(event);
if (!transition) {
return true;
}
else {
return transition.transitionGuard
? transition.transitionGuard(this.stateData.state, event)
: true;
}
};
StateManagerFSM.prototype.canTransition = function (event) {
var transition = this.transitionAction(event);
if (!transition) {
if (this.options.devMode) {
console.warn("[FSM Warn] We can't transition to another state with event '".concat(event, "' from state '").concat(this.stateData.state, "'"));
}
return false;
}
return typeof transition.transitionAction === 'function';
};
StateManagerFSM.prototype.subscribe = function (state, callback) {
if (!this.options.subscriptionMode) {
throw new Error('Subscription mode is disabled. ' +
'Turn on `subscriptionMode: true` in options, for using .subscribe().');
}
return this.subscriptionManager.subscribe(state, callback);
};
return StateManagerFSM;
}());
exports.StateManagerFSM = StateManagerFSM;