UNPKG

state-switch

Version:

State Switch is a Change Monitor/Guarder for Async Actions.

138 lines 4.87 kB
"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