@robotlegsjs/core
Version:
An architecture-based IoC framework for JavaScript/TypeScript
207 lines • 8.45 kB
JavaScript
"use strict";
// ------------------------------------------------------------------------------
// Copyright (c) 2017-present, RobotlegsJS. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
// ------------------------------------------------------------------------------
Object.defineProperty(exports, "__esModule", { value: true });
exports.LifecycleTransition = void 0;
var LifecycleEvent_1 = require("../api/LifecycleEvent");
var MessageDispatcher_1 = require("./MessageDispatcher");
var safelyCallBack_1 = require("./safelyCallBack");
/**
* Handles a lifecycle transition
*
* @private
*/
var LifecycleTransition = /** @class */ (function () {
/*============================================================================*/
/* Constructor */
/*============================================================================*/
/**
* Creates a lifecycle transition
*
* @param name The name of the transition
* @param lifecycle The associated lifecycle instance
*/
function LifecycleTransition(name, lifecycle) {
/*============================================================================*/
/* Private Properties */
/*============================================================================*/
this._fromStates = [];
this._dispatcher = new MessageDispatcher_1.MessageDispatcher();
this._callbacks = [];
this._reverse = false;
this._name = name;
this._lifecycle = lifecycle;
}
/*============================================================================*/
/* Public Functions */
/*============================================================================*/
/**
* States that this transition is allowed to enter from
*
* @param states Allowed states
* @return Self
*/
LifecycleTransition.prototype.fromStates = function () {
var _this = this;
var states = [];
for (var _i = 0; _i < arguments.length; _i++) {
states[_i] = arguments[_i];
}
states.forEach(function (state) {
_this._fromStates.push(state);
});
return this;
};
/**
* The states that this transition applies
*
* @param transitionState The state that the target is put into during the transition
* @param finalState The state that the target is put into after the transition
* @return
*/
LifecycleTransition.prototype.toStates = function (transitionState, finalState) {
this._transitionState = transitionState;
this._finalState = finalState;
return this;
};
/**
* The events that the lifecycle will dispatch
*
* @param preTransitionEvent
* @param transitionEvent
* @param postTransitionEvent
* @return Self
*/
LifecycleTransition.prototype.withEvents = function (preTransitionEvent, transitionEvent, postTransitionEvent) {
this._preTransitionEvent = preTransitionEvent;
this._transitionEvent = transitionEvent;
this._postTransitionEvent = postTransitionEvent;
if (this._reverse) {
this._lifecycle.addReversedEventTypes(preTransitionEvent, transitionEvent, postTransitionEvent);
}
return this;
};
/**
* Reverse the dispatch order of this transition
*
* @return Self
*/
LifecycleTransition.prototype.inReverse = function () {
this._reverse = true;
this._lifecycle.addReversedEventTypes(this._preTransitionEvent, this._transitionEvent, this._postTransitionEvent);
return this;
};
/**
* A handler to run before the transition runs
*
* @param handler Possibly asynchronous before handler
* @return Self
*/
LifecycleTransition.prototype.addBeforeHandler = function (handler) {
this._dispatcher.addMessageHandler(this._name, handler);
return this;
};
/**
* Attempts to enter the transition
*
* @param callback Completion callback
*/
LifecycleTransition.prototype.enter = function (callback) {
var _this = this;
// immediately call back if we have already transitioned, and exit
if (this._lifecycle.state === this._finalState) {
if (callback) {
safelyCallBack_1.safelyCallBack(callback, null, this._name);
}
return;
}
// queue this callback if we are mid transition, and exit
if (this._lifecycle.state === this._transitionState) {
if (callback) {
this._callbacks.push(callback);
}
return;
}
// report invalid transition, and exit
if (this._invalidTransition()) {
this._reportError("Invalid transition", [callback]);
return;
}
// store the initial lifecycle state in case we need to roll back
var initialState = this._lifecycle.state;
// queue the first callback
if (callback) {
this._callbacks.push(callback);
}
// put lifecycle into transition state
this._setState(this._transitionState);
// run before handlers
this._dispatcher.dispatchMessage(this._name, function (error) {
// revert state, report error, and exit
if (error) {
_this._setState(initialState);
_this._reportError(error, _this._callbacks);
return;
}
// dispatch pre transition and transition events
_this._dispatch(_this._preTransitionEvent);
_this._dispatch(_this._transitionEvent);
// put lifecycle into final state
_this._setState(_this._finalState);
// process callback queue (dup and trash for safety)
var callbacks = _this._callbacks.concat();
_this._callbacks.length = 0;
callbacks.forEach(function (callbackChild) {
safelyCallBack_1.safelyCallBack(callbackChild, null, _this._name);
});
// dispatch post transition event
_this._dispatch(_this._postTransitionEvent);
}, this._reverse);
};
/*============================================================================*/
/* Private Functions */
/*============================================================================*/
LifecycleTransition.prototype._invalidTransition = function () {
return (this._fromStates.length > 0 && this._fromStates.indexOf(this._lifecycle.state) === -1);
};
LifecycleTransition.prototype._setState = function (state) {
if (state) {
this._lifecycle.setCurrentState(state);
}
};
LifecycleTransition.prototype._dispatch = function (type) {
if (type && this._lifecycle.hasEventListener(type)) {
this._lifecycle.dispatchEvent(new LifecycleEvent_1.LifecycleEvent(type));
}
};
LifecycleTransition.prototype._reportError = function (message, callbacks) {
var _this = this;
// turn message into Error
var error = message instanceof Error ? message : new Error(message);
// dispatch error event if a listener exists, or throw
if (this._lifecycle.hasEventListener(LifecycleEvent_1.LifecycleEvent.ERROR)) {
var event_1 = new LifecycleEvent_1.LifecycleEvent(LifecycleEvent_1.LifecycleEvent.ERROR, error);
this._lifecycle.dispatchEvent(event_1);
// process callback queue
if (callbacks) {
callbacks.forEach(function (callback) {
if (callback) {
safelyCallBack_1.safelyCallBack(callback, error, _this._name);
}
});
callbacks.length = 0;
}
}
else {
// explode!
throw error;
}
};
return LifecycleTransition;
}());
exports.LifecycleTransition = LifecycleTransition;
//# sourceMappingURL=LifecycleTransition.js.map