state-switch
Version:
State Switch is a Change Monitor/Guarder for Async Actions.
138 lines • 4.87 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StateSwitch = void 0;
const brolog_1 = require("brolog");
const nop_1 = require("@pipeletteio/nop");
const version_js_1 = require("./version.js");
const events_js_1 = require("./events.js");
let COUNTER = 0;
class StateSwitch extends events_js_1.StateSwitchEventEmitter {
_name;
_options;
_log;
_activePromise;
_inactivePromise;
_activeResolver;
_inactiveResolver;
_isActive;
_isPending;
constructor(_name = `StateSwitch#${COUNTER++}`, _options = {}) {
super();
this._name = _name;
this._options = _options;
this._log = (0, brolog_1.getLoggable)(_options.log);
this._log.verbose('StateSwitch', 'constructor(%s, "%s")', _name, JSON.stringify(_options));
this._isActive = false;
this._isPending = false;
/**
* for ready()
*/
this._activeResolver = nop_1.nop;
this._inactiveResolver = nop_1.nop;
this._activePromise = new Promise(resolve => {
this._activeResolver = resolve;
});
this._inactivePromise = Promise.resolve();
}
name() {
return this._name;
}
version() {
return version_js_1.VERSION;
}
active(state) {
/**
* Set
*/
if (state) {
this._log.verbose('StateSwitch', '<%s> active(%s) <- (%s)', this._name, state, this.active());
this._isActive = true;
this._isPending = (state === 'pending');
this.emit('active', state);
/**
* for stable()
*/
if ((0, nop_1.isNop)(this._inactiveResolver)) {
this._inactivePromise = new Promise(resolve => (this._inactiveResolver = resolve));
}
if (state === true && !(0, nop_1.isNop)(this._activeResolver)) {
this._activeResolver();
this._activeResolver = nop_1.nop;
}
return;
}
/**
* Get
*/
const activeState = this._isActive
? this._isPending ? 'pending' : true
: false;
this._log.silly('StateSwitch', '<%s> active() is %s', this._name, activeState);
return activeState;
}
inactive(state) {
/**
* Set
*/
if (state) {
this._log.verbose('StateSwitch', '<%s> inactive(%s) <- (%s)', this._name, state, this.inactive());
this._isActive = false;
this._isPending = (state === 'pending');
this.emit('inactive', state);
/**
* for stable()
*/
if ((0, nop_1.isNop)(this._activeResolver)) {
this._activePromise = new Promise(resolve => (this._activeResolver = resolve));
}
if (state === true && !(0, nop_1.isNop)(this._inactiveResolver)) {
this._inactiveResolver();
this._inactiveResolver = nop_1.nop;
}
return;
}
/**
* Get
*/
const inactiveState = !this._isActive
? this._isPending ? 'pending' : true
: false;
this._log.silly('StateSwitch', '<%s> inactive() is %s', this._name, inactiveState);
return inactiveState;
}
/**
* does the state is not stable(in process)?
*/
pending() {
this._log.silly('StateSwitch', '<%s> pending() is %s', this._name, this._isPending);
return this._isPending;
}
/**
* Wait the pending state to be stable.
*/
async stable(state, noCross = false) {
this._log.verbose('StateSwitch', '<%s> stable(%s, noCross=%s)', this._name, state, noCross);
if (typeof state === 'undefined') {
state = this._isActive ? 'active' : 'inactive';
}
if (state === 'active') {
if (this._isActive === false && noCross === true) {
throw new Error('stable(active) but the state is inactive. call stable(active, false) to disable noCross');
}
await this._activePromise;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
}
else if (state === 'inactive') {
if (this._isActive === true && noCross === true) {
throw new Error('stable(inactive) but the state is active. call stable(inactive, false) to disable noCross');
}
await this._inactivePromise;
}
else {
throw new Error(`should not go here. ${state} should be of type 'never'`);
}
this._log.silly('StateSwitch', '<%s> stable(%s, %s) resolved.', this._name, state, noCross);
}
}
exports.StateSwitch = StateSwitch;
//# sourceMappingURL=state-switch.js.map