Files
Zos/Skills/@be/be/node_modules/jibo-state-machine/lib/jibo-state-machine.js

938 lines
34 KiB
JavaScript

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jiboStateMachine = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const Transition_1 = require("./Transition");
const TimeoutTransition_1 = require("./TimeoutTransition");
const Utils_1 = require("./Utils");
const log_1 = require("./log");
const log = log_1.default.createChild("State");
class State {
constructor(sm, name, transitions) {
this.sm = sm;
this.name = name;
this.transitions = [];
this._isCurrent = false;
this._entryCounter = 0;
this._exitCounter = 0;
this._isExiting = false;
this._internals = [];
this._events = new Map();
this._typedEvents = new Map();
sm._addState(this);
if (transitions) {
this.addTransition(transitions);
}
}
addTransition(transition) {
if (Array.isArray(transition)) {
transition.forEach(trans => {
this._addTransition(trans);
});
}
else {
this._addTransition(transition);
}
return this;
}
_addTransition(transition) {
if (transition.getSourceState()) {
this.sm._rejectCurrentPromise(new Error(`This transition has already been assigned to a source state`));
}
transition._setSourceState(this);
this.transitions.push(transition);
}
addInternalTransition(name, destState) {
const exists = this._internals.some(i => (i.name === name && i.destState === destState));
if (exists) {
throw new Error(`State already has internal transition of name '${name}' to state '${destState.name}'`);
}
let internal = {
name,
destState,
transition: new Transition_1.Transition(name, destState)
};
this._internals.push(internal);
this.addTransition(internal.transition);
return this;
}
addEventTransition(event, destState) {
return this._addEventTransition(event, destState, false);
}
_addEventTransition(event, destState, global = false) {
if (this._events.has(event)) {
throw new Error(`Duplicate event transition. State: '${this.name}', event: '${event}'`);
}
let trans = new Transition_1.Transition(Utils_1.createEventTransitionName(event), destState);
trans._isGlobal = global;
const handler = (result) => {
if (this._isCurrent) {
trans.trigger(result);
}
};
this._events.set(event, { event, handler });
this.addTransition(trans);
return this;
}
addTypedEventTransition(event, destState) {
return this._addTypedEventTransition(event, destState, false);
}
_addTypedEventTransition(event, destState, global = false) {
let trans = new Transition_1.Transition(Utils_1.createTypedEventTransitionName(event), destState);
trans._isGlobal = global;
const handler = (result) => {
if (this._isCurrent) {
trans.trigger(result);
}
};
this._typedEvents.set(event, { event, handler });
this.addTransition(trans);
return this;
}
addDoneTransition(destState) {
if (this._doneTransition) {
this.sm._rejectCurrentPromise(new Error(`Done transition for state '${this.name}' already registered`));
}
this._doneTransition = new Transition_1.Transition('Done', destState);
this.addTransition(this._doneTransition);
}
_enter(transition, result) {
return __awaiter(this, void 0, void 0, function* () {
this._entryCounter++;
this._isCurrent = true;
this._lastIncomingResults = result;
// Here we subscribe to all events
this._events.forEach(eventCont => {
this.sm.on(eventCont.event, eventCont.handler);
});
this._typedEvents.forEach(eventCont => {
eventCont.event.on(eventCont.handler);
});
// Here we emit the sm transition event since all the state is appropriate at this time
this.sm.stateChanged.emit(transition);
// We evaluate this state's onEntry method
if (this.onEntry) {
try {
const ret = this.onEntry(transition, result);
if (ret instanceof Promise) {
// If we have a done transition then we wait on the result from the promise
// and pass it into the next state
if (this._doneTransition) {
const entryCounterThisTime = this._entryCounter;
const retFromPromise = yield ret;
if (this._isCurrent && this._entryCounter === entryCounterThisTime) {
this._doneTransition.trigger(retFromPromise);
}
}
else {
ret.catch(error => {
this.sm._rejectCurrentPromise(error);
});
}
}
else {
if (this._doneTransition) {
this._doneTransition.trigger(ret);
}
}
}
catch (e) {
this.sm._rejectCurrentPromise(e);
}
}
else {
if (this._doneTransition) {
this._doneTransition.trigger(null);
}
}
// We evaluate this state's transitions' onEntry methods
// There is a chance that we are not current anymore
if (this._isCurrent) {
for (let trans of this.transitions) {
trans._enter();
}
}
});
}
_exit(transition) {
this._isExiting = true;
// Here we unsubscribe from all events
this._events.forEach(eventCont => {
this.sm.removeListener(eventCont.event, eventCont.handler);
});
this._typedEvents.forEach(eventCont => {
eventCont.event.removeListener(eventCont.handler);
});
let retPromise;
if (this.onExit) {
try {
const ret = this.onExit(transition);
if (ret instanceof Promise) {
retPromise = ret;
}
}
catch (e) {
this.sm._rejectCurrentPromise(e);
}
}
for (let trans of this.transitions) {
trans._exit();
}
let exitCleanup = () => {
this._exitCounter++;
this._isExiting = false;
this._isCurrent = false;
};
if (retPromise) {
return retPromise
.then(exitCleanup)
.catch(e => this.sm._rejectCurrentPromise(e));
}
else {
exitCleanup();
}
}
_stop() {
let retPromise;
this.transitions.forEach(trans => {
if (trans instanceof TimeoutTransition_1.TimeoutTransition) {
trans.stop();
}
});
// First we call onStop if it is defined
if (this.onStop) {
try {
const ret = this.onStop();
if (ret instanceof Promise) {
retPromise = ret;
}
}
catch (e) {
this.sm._rejectCurrentPromise(e);
}
}
if (!this._isExiting && this._exitCounter !== this._entryCounter) {
// We also call exit
const finalTransition = new Transition_1.Transition('FINAL TRANSITON', null);
finalTransition._setSourceState(this);
const callExit = () => {
let exitRet;
try {
exitRet = this._exit(finalTransition);
}
catch (e) {
this.sm._rejectCurrentPromise(e);
}
return exitRet;
};
// If we have a stop promise we chain this to that
if (retPromise) {
retPromise = retPromise.then(() => callExit());
}
else {
// Otherwise we just call Exit
let exitRet = callExit();
if (exitRet instanceof Promise) {
retPromise = exitRet;
}
}
}
if (retPromise instanceof Promise) {
return retPromise.then(() => undefined);
}
}
/**
* Retrieves the last result that was provided to this state upon entry
* @returns {Object}
*/
getLastIncomingResult() {
return this._lastIncomingResults;
}
/**
* Returns whether this is the current state of the state machine
* @return {boolean}
*/
isCurrent() {
return this._isCurrent;
}
transitionTo(arg1, arg2, arg3) {
let destState;
let name;
let result;
// If we are being given a transition name
if (typeof arg1 === 'string') {
name = arg1;
if (arg2 instanceof State) {
destState = arg2;
result = arg3;
}
else {
result = arg2;
}
}
else if (arg1 instanceof State) {
destState = arg1;
result = arg2;
}
// Here we find the internal transition that matches
const results = this._internals.filter(i => {
return ((name === undefined) || (name === i.name)) &&
((destState === undefined) || (destState === i.destState));
});
const destStateName = destState ? destState.name : 'unknown';
if (results.length === 0) {
throw new Error(`State '${this.name}': no internal transition of name '${name}' to state '${destStateName}' found`);
}
else if (results.length > 1) {
throw new Error(`State '${this.name}': has more than one matching internal transition: '${name}' to state '${destStateName}'`);
}
else {
const internal = results[0];
const internalDestStateName = internal.destState ? internal.destState.name : 'unknown';
const internalTransName = internal.transition ? internal.transition.name : 'unknown';
if (!this._isCurrent) {
let warn = `Attempting internal transition out of a non-current state. ` +
`This state: '${this.name}', target state: '${internalDestStateName}', ` +
`transition name: '${internalTransName}'. `;
if (this.sm.current) {
warn += `Current state: '${this.sm.current.name}'.`;
}
else {
warn += `The state machine is currently not running.`;
}
log.warn(warn);
}
else {
internal.transition.trigger(result);
}
}
}
/**
* Destroys the state. Should be called when state machine is getting discarded
*/
destroy() {
// this._isCurrent = false;
this._events.forEach(eventContainer => {
this.sm.removeListener(eventContainer.event, eventContainer.handler);
});
this._events.clear();
this._typedEvents.forEach(eventContainer => {
eventContainer.event.removeListener(eventContainer.handler);
});
this._typedEvents.clear();
this.transitions.forEach(trans => trans.destroy());
// this.transitions = [];
// this._internalTransitions.clear();
this._lastIncomingResults = null;
this.onEntry = null;
this.onExit = null;
this.onUpdate = null;
this.onStop = null;
}
toString() {
return 'State: ' + this.name;
}
}
exports.State = State;
// For unit tests
State.prototype.log = log;
},{"./TimeoutTransition":3,"./Transition":4,"./Utils":5,"./log":6}],2:[function(require,module,exports){
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const events = require("events");
const fs = require("fs");
const jibo_typed_events_1 = require("jibo-typed-events");
const Transition_1 = require("./Transition");
const Utils_1 = require("./Utils");
const log_1 = require("./log");
const log = log_1.default.createChild("StateMachine");
class StateMachine extends events.EventEmitter {
constructor() {
super();
this.states = new Map();
this.stateChanged = new jibo_typed_events_1.Event(`State transitioned`);
this._globalEvents = new Map();
this._globalTypedEvents = new Map();
this._inTransition = false;
this._loopDetection = new Map();
this._isStopped = false;
this._traceIndex = 0;
this._trace = [];
this._cleanupAll();
}
/**
* Adds a global event that will transition out of any state into a destination state
* @param {string} event - Name of event
* @param {State} destState - State to transition to
* @param {State[]} [exceptionStates] - States that this global transition does NOT apply to
* @returns {this}
* @memberof StateMachine
*/
addGlobalEventTransition(event, destState, exceptionStates = []) {
if (this._globalEvents.has(event)) {
throw new Error(`Duplicate global event transition. Event: '${event}'`);
}
this._globalEvents.set(event, {
event: event,
destination: destState,
exceptions: exceptionStates
});
// Add to all existing states
this.states.forEach(state => {
if (state !== destState && exceptionStates.indexOf(state) === -1) {
state._addEventTransition(event, destState, true);
}
});
return this;
}
/**
* Adds a global event that will transition out of any state into a destination state
* @param {Event} event - Typed event
* @param {State} destState - State to transition to
* @param {State[]} [exceptionStates] - States that this global transition does NOT apply to
* @returns {this}
* @memberof StateMachine
*/
addGlobalTypedEventTransition(event, destState, exceptionStates = []) {
if (this._globalTypedEvents.has(event)) {
throw new Error(`Duplicate global typed event transition. Event: '${event.name}'`);
}
this._globalTypedEvents.set(event, {
event: event,
destination: destState,
exceptions: exceptionStates
});
// Add to all existing states
this.states.forEach(state => {
if (state !== destState && exceptionStates.indexOf(state) === -1) {
state._addTypedEventTransition(event, destState, true);
}
});
return this;
}
/**
* Rejects currently running start promise
* @param {string|Error} error
* @private
*/
_rejectCurrentPromise(error) {
return __awaiter(this, void 0, void 0, function* () {
if (this._promiseReject) {
this._promiseReject(error);
}
else {
log.warn(`Reject being called when SM isn't running, with error: `, error);
}
});
}
/**
* Resoles currently running start promise
* @param {object} data
* @private
*/
_resolveCurrentPromise(data) {
if (this._promiseResolve) {
this._promiseResolve(data);
}
else {
log.warn(`Resolve called when SM isn't running, with data: `, data);
}
}
/**
* Destroys the state machine and all of its states.
* Should be called when state machine is getting discarded
*/
destroy() {
const destroy = () => {
this._globalEvents.clear();
this._globalTypedEvents.clear();
this.states.forEach(state => {
state.destroy();
});
this.states.clear();
this._cleanupAll();
};
if (this._currentRunPromise) {
return this.stop().then(destroy);
}
else {
return Promise.resolve().then(destroy);
}
}
/**
* Returns current state of state machine
* @returns {State}
*/
getCurrentState() {
return this.current;
}
/**
* Sets the initial state of the state machine
* @param state
* @returns {StateMachine}
*/
setInitial(state) {
this.initial = state;
return this;
}
/**
* Starts the state machine. This is required to be called once.
* @param {Object} [input] - Optional input data
* @returns {Promise} resolved when any state throws an error or calls this.exit();
*/
start(input) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.initial) {
return Promise.reject(new Error(`State machine does not yet have an initial state`));
}
else if (this._currentRunPromise) {
return Promise.reject(new Error(`State machine already running, please call stop first`));
}
this._currentRunPromise = new Promise((resolve, reject) => {
this._promiseResolve = resolve;
this._promiseReject = reject;
}).then((data) => {
this._cleanupAfterStart();
return data;
}).catch((e) => __awaiter(this, void 0, void 0, function* () {
try {
yield this.stop();
}
catch (stopError) {
log.error(`Error while stopping state machine because of an earlier error`);
log.error(stopError);
}
finally {
this._cleanupAfterStart();
throw e;
}
}));
this._cleanupBeforeStart();
this.current = this.initial;
this.current._isCurrent = true;
let initialTransition = new Transition_1.Transition('INITIAL TRANSITON', this.initial);
this._addToTrace(initialTransition);
this.current._enter(initialTransition, input);
return this._currentRunPromise;
});
}
/**
* Informs whether the state machine is currently running
* @return {boolean} True if the state machine is currently running
*/
isRunning() {
return (!!this._currentRunPromise);
}
/**
* Waits until state machine is finished. If it isn't running, it resolves promise immediately
* @return {Promise<any>}
*/
waitUntilFinished() {
if (this._currentRunPromise) {
return this._currentRunPromise;
}
else {
return Promise.resolve();
}
}
_addState(state) {
if (this.states.has(state.name)) {
this._rejectCurrentPromise(new Error(`State with name '${state.name}' already exists`));
return;
}
if (!this.initial) {
this.setInitial(state);
}
// Here we add all current global transitions to this state
this._globalEvents.forEach(event => {
if (event.destination !== state && event.exceptions.indexOf(state) === -1) {
state._addEventTransition(event.event, event.destination, true);
}
});
this._globalTypedEvents.forEach(event => {
if (event.destination !== state && event.exceptions.indexOf(state) === -1) {
state._addTypedEventTransition(event.event, event.destination, true);
}
});
this.states.set(state.name, state);
return this;
}
/**
* Get state by name
* @param {string} name
* @returns {State}
*/
getState(name) {
return this.states.get(name);
}
_addToTrace(transition) {
const te = {
transition: transition,
timestamp: Date.now(),
};
if (this._trace.length < StateMachine.TRACE_MAX_LENGTH) {
this._trace.push(te);
}
else {
this._trace[this._traceIndex] = te;
this._traceIndex = (this._traceIndex + 1) % StateMachine.TRACE_MAX_LENGTH;
}
}
/**
* Updates the current state, if it has an onUpdate callback.
* Normal functionality of the StateMachine does not require that you call this, only if your
* state should be connected to an update loop.
*/
update() {
if (this.current && this.current.onUpdate) {
this.current.onUpdate();
}
}
/**
* Stops the current state (calls its onStop callback).
* @returns {Promise} resolved when stop is complete
*/
stop(data) {
// If we have a current run instance
if (this._currentRunPromise) {
this._isStopped = true;
if (this.current) {
this._isStopped = true;
const stopRet = this.current._stop();
// We wait for the exit promise to complete if it exists
const exitWait = this._currentStateExitPromise || Promise.resolve();
if (stopRet instanceof Promise) {
return exitWait.then(() => stopRet).then(() => {
this.current = null;
this._resolveCurrentPromise(data);
});
}
else {
return exitWait.then(() => {
this.current = null;
this._resolveCurrentPromise(data);
});
}
}
else {
return Promise.resolve();
}
}
else {
// Stop being called but SM wasn't running
return Promise.resolve();
}
}
/**
* Returns the trace of transitions leading up to the current one (limited
* by StateMachine.TRACE_MAX_LENGTH)
* @returns {TraceElement[]}
*/
getTrace() {
let out = [];
if (this._trace.length < StateMachine.TRACE_MAX_LENGTH) {
for (let i = 0; i < this._trace.length; i++) {
out.push(this._trace[i]);
}
}
else {
for (let i = 0; i < this._trace.length; i++) {
let ind = (this._traceIndex + i) % StateMachine.TRACE_MAX_LENGTH;
out.push(this._trace[ind]);
}
}
return out;
}
/**
* Provides a convenient string representation of getTrace()
* @returns {string}
*/
traceToString() {
let trace = this.getTrace();
let str = '';
trace.forEach(t => {
let sName = t.transition.getSourceState() ? t.transition.getSourceState().name : 'none';
str += `Source: '${sName}' -> Transition: '${t.transition.name}' @ ${t.timestamp} ` +
`-> Destination: '${t.transition.getDestinationState().name}' \n`;
});
return str;
}
/**
* Transitions using a particular transition
* @param transition
* @param result
* @private
*/
_transitionTo(transition, result) {
if (this._isStopped) {
return;
}
// if the state machine is stopped, do nothing
if (!this.current) {
return;
}
// See if this is the first in sequence of continuous transitions
let isThisFirstTransition = !this._inTransition;
if (isThisFirstTransition) {
this._inTransition = true;
}
// Here we look for loops
let destName = transition.getDestinationState().name;
let loopCounter = this._loopDetection.get(destName);
if (!loopCounter) {
this._loopDetection.set(destName, 1);
}
else if (loopCounter > StateMachine.MAX_LOOPS) {
return this._rejectCurrentPromise(new Error(`State machine has looped '${loopCounter}' times in ` +
`one transition. Next state: '${destName}'`));
}
else {
this._loopDetection.set(destName, loopCounter + 1);
}
this._addToTrace(transition);
if (transition.getSourceState() !== this.current) {
this._rejectCurrentPromise(new Error(`Can't apply transition '${transition}' since the `
+ `current state is '${this.current}'`));
}
// Notify current state and transitions of exit
const exitDone = () => {
this._currentStateExitPromise = null;
if (!this._isStopped) {
// Notify next state and transitions of entry
this.current = transition.getDestinationState();
this.current._enter(transition, result);
// When leaving the first transition in a sequence, we clear our loop
// detection mechanism
if (isThisFirstTransition) {
this._inTransition = false;
this._loopDetection.clear();
}
}
};
const exitRet = this.current._exit(transition);
if (exitRet instanceof Promise) {
this._currentStateExitPromise = exitRet;
return exitRet.then(exitDone).catch(e => this._rejectCurrentPromise(e));
}
else {
exitDone();
}
}
/**
* Produces a .dot file from current state graph
* Writes dotfile to disk at filepath
* @param {string} filePath
* @returns {string}
*/
toDotFile(filePath) {
const regBgColor = "lightgrey";
const globalBgColor = "#a0a0a0";
let lines = ['digraph graphname {'];
this.states.forEach(state => {
let name = state.name.replace(/\"/ig, '\\"');
let lineColor = (state === this.initial) ? 'black' : regBgColor;
lines.push(`"${name}" [style=filled,fillcolor="${regBgColor}",color="${lineColor}"];`);
});
// Here we handle all global transitions
if (this._globalEvents.size > 0 || this._globalTypedEvents.size > 0) {
let globalName = "Any state";
lines.push(`"${globalName}" [shape=box,style=filled,fillcolor="${globalBgColor}",color=black];`);
this._globalEvents.forEach(event => {
let targetName = event.destination.name.replace(/\"/ig, '\\"');
let transitionName = Utils_1.createEventTransitionName(event.event).replace(/\"/ig, '\\"');
lines.push(` "${globalName}" -> "${targetName}" [label = "${transitionName}"];`);
});
this._globalTypedEvents.forEach(event => {
let targetName = event.destination.name.replace(/\"/ig, '\\"');
let transitionName = Utils_1.createTypedEventTransitionName(event.event).replace(/\"/ig, '\\"');
lines.push(` "${globalName}" -> "${targetName}" [label = "${transitionName}"];`);
});
}
// Here we handle all non-global transitions
this.states.forEach(state => {
state.transitions.forEach((transition) => {
if (!transition._isGlobal) {
let sourceStateName = state.name.replace(/\"/ig, '\\"');
let targetName = transition.getDestinationState().name.replace(/\"/ig, '\\"');
let transitionName = transition.name.replace(/\"/ig, '\\"');
lines.push(` "${sourceStateName}" -> "${targetName}" [label = "${transitionName}"];`);
}
});
});
lines.push('}');
const str = lines.join('\n');
if (filePath) {
fs.writeFileSync(filePath, str, { encoding: 'utf8' });
}
return str;
}
_cleanupAll() {
this._cleanupBeforeStart();
this._cleanupAfterStart();
}
_cleanupAfterStart() {
this._isStopped = false;
this._currentRunPromise = null;
this._currentStateExitPromise = null;
this._promiseResolve = null;
this._promiseReject = null;
this._inTransition = false;
}
_cleanupBeforeStart() {
this._isStopped = false;
this._inTransition = false;
this._traceIndex = 0;
this._trace = [];
this._loopDetection.clear();
}
}
StateMachine.TRACE_MAX_LENGTH = 20;
StateMachine.MAX_LOOPS = 5;
exports.StateMachine = StateMachine;
},{"./Transition":4,"./Utils":5,"./log":6,"events":undefined,"fs":undefined,"jibo-typed-events":undefined}],3:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Transition_1 = require("./Transition");
class TimeoutTransition extends Transition_1.Transition {
constructor(name, destState, timeMs) {
super(name, destState);
this.onEntry = () => {
this._timeoutHandle = setTimeout(() => {
this._timeoutHandle = null;
this.trigger();
}, timeMs);
};
this.onExit = () => {
if (this._timeoutHandle) {
clearTimeout(this._timeoutHandle);
this._timeoutHandle = null;
}
};
}
stop() {
this.onExit();
}
}
exports.TimeoutTransition = TimeoutTransition;
},{"./Transition":4}],4:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class Transition {
constructor(name, _destState) {
this.name = name;
this._destState = _destState;
// Is only used for global states and only matters for dot visualization
this._isGlobal = false;
}
/**
* Called to trigger the current transition
* @param {object} [result] to pass to next state
*/
trigger(result) {
if (this._sourceState) {
this._sourceState.sm._transitionTo(this, result);
}
}
_enter() {
if (this.onEntry) {
this.onEntry();
}
}
_exit() {
if (this.onExit) {
this.onExit();
}
}
/**
* The source state for this transition
* @returns {State}
*/
getSourceState() {
return this._sourceState;
}
/**
* The destination for this transition
* @returns {State}
*/
getDestinationState() {
return this._destState;
}
/**
* Sets the source state, should only be called when adding transition to
* the source state.
* Can only be called once per transition
* @param sourceState
* @private
*/
_setSourceState(sourceState) {
if (this._sourceState) {
this._sourceState.sm._rejectCurrentPromise(new Error(`Transition '${this}' already has source state`));
}
this._sourceState = sourceState;
}
/**
* Destroys the transition. Should be called when state machine is getting discarded
*/
destroy() {
this.onEntry = null;
this.onExit = null;
this._sourceState = null;
}
toString() {
return this.name;
}
}
exports.Transition = Transition;
},{}],5:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function createTypedEventTransitionName(event) {
return 'TEvent: ' + event.name;
}
exports.createTypedEventTransitionName = createTypedEventTransitionName;
function createEventTransitionName(event) {
return 'Event: ' + event;
}
exports.createEventTransitionName = createEventTransitionName;
},{}],6:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jibo_log_1 = require("jibo-log");
exports.default = new jibo_log_1.Log('StateMachine');
},{"jibo-log":undefined}],7:[function(require,module,exports){
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./StateMachine"));
__export(require("./Transition"));
__export(require("./State"));
__export(require("./TimeoutTransition"));
},{"./State":1,"./StateMachine":2,"./TimeoutTransition":3,"./Transition":4}]},{},[7])(7)
});
//# sourceMappingURL=jibo-state-machine.js.map