@activejs/core
Version:
Pragmatic, Reactive State Management for JavaScript Apps
743 lines • 82.5 kB
JavaScript
import { DispatchFailReason, EventUnitClear, EventUnitClearCache, EventUnitClearPersistedValue, EventUnitClearValue, EventUnitDispatch, EventUnitDispatchFail, EventUnitFreeze, EventUnitJump, EventUnitReset, EventUnitResetValue, EventUnitUnfreeze, EventUnitUnmute, } from '../models';
import { Base } from './abstract-base';
import { Configuration } from './configuration';
import { Stream } from './stream';
import { remove, retrieve, save } from './persistence';
import { debounce, deepCopy, deepFreeze, isNumber } from '../utils/funcs';
import { checkSerializability } from '../checks/common';
/**
* UnitBase serves as the base for all the ActiveJS Units: GenericUnit, BoolUnit, ListUnit, etc.
* It extends {@link Base}.
*
* This is an internal construct, normally you'd never have to use this class directly.
* However, if you're just reading the documentation, or want to learn more about how ActiveJS works,
* or want to extend this class to build something on your own, please continue.
*
* UnitBase creates the foundation of all the ActiveJS Units.
* It implements the features like:
* - dispatching, clearing and resetting the value
* - caching the dispatched values
* - navigating through the cached values, by methods like goBack, goForward, jump etc.
* - observable events to listen to including but not limited to the above mentioned actions
* - freezing/unfreezing the Unit
* - muting/unmuting the Unit
* - persisting and retrieving the value to/from persistent-storage
* - debouncing the dispatch
* - resetting the Unit
* - etc.
*
* @category 2. Abstract
*/
export class UnitBase extends Base {
// tslint:enable:variable-name
/**
* @internal please do not use.
*/
constructor(config) {
super(Object.assign(Object.assign({}, Configuration.UNITS), config));
/**
* @internal please do not use.
*/
this._isFrozen = false;
/**
* @internal please do not use.
*/
this._isMuted = false;
/**
* @internal please do not use.
*/
this._cachedValues = [];
/**
* @internal please do not use.
*/
this._cacheIndex = 0;
/**
* @internal please do not use.
*/
this._initialValue = undefined;
const { cacheSize, initialValue, dispatchDebounce, dispatchDebounceMode, persistent, } = this.config;
this.cacheSize = isNumber(cacheSize) ? Math.max(1, cacheSize) : 2; // min 1, default 2
if (persistent === true) {
this.restoreValueFromPersistentStorage(initialValue);
}
else {
this.checkSerializabilityMaybe(initialValue);
this.dispatchInitialValue(this.deepCopyMaybe(initialValue));
}
if (dispatchDebounce === true || isNumber(dispatchDebounce)) {
this.dispatchMiddleware = debounce(this.dispatchMiddleware.bind(this), dispatchDebounce, dispatchDebounceMode);
}
}
/**
* Indicates whether the Unit is frozen or not.
* See {@link freeze} for more details.
*
* Note: It's not the same as [Object.isFrozen](https://cutt.ly/WyFdzPD).
*/
get isFrozen() {
return this._isFrozen;
}
/**
* Indicates whether the Unit is muted or not.
* See {@link mute} for more details.
*/
get isMuted() {
return this._isMuted;
}
/**
* Indicates whether the value is undefined or not.
*
* It should be preferred if the Unit is configured to be immutable, as it doesn't create a copy.
*/
get isEmpty() {
return this.rawValue() === this.defaultValue();
}
/**
* Count of all the cached values.
*/
get cachedValuesCount() {
return this._cachedValues.length;
}
/**
* Index of the current {@link value} in the {@link UnitBase.cachedValues}
*/
get cacheIndex() {
return this._cacheIndex;
}
/**
* The initialValue provided on instantiation.
* Creates a copy if the Unit is configured to be immutable.
*
* @category Access Value
*/
initialValue() {
return this.deepCopyMaybe(this.initialValueRaw());
}
/**
* Current value of the Unit.
* Creates a copy if the Unit is configured to be immutable.
*
* @default
* BoolUnit: `false` \
* NumUnit: `0` \
* StringUnit: `''` \
* ListUnit: `[]` \
* DictUnit: `{}` \
* GenericUnit: `undefined`
*
* @category Access Value
*/
value() {
return this.deepCopyMaybe(this.rawValue()); // apply the fallback and kill reference
}
/**
* If the Unit has a non-primitive value,
* use it to get access to the current {@link value}, without creating a deep-copy.
*
* This can come in handy if the Unit is configured to be immutable, and you want to perform a non-mutating action
* without creating a deep-copy of the value.
*
* @category Access Value
*/
rawValue() {
return this.applyFallbackValue(this._value);
}
/**
* All the cached values.
* Creates a copy if the Unit is configured to be immutable.
*
* @category Access Value
*/
cachedValues() {
return this._cachedValues.map(value => this.deepCopyMaybe(value));
}
/**
* @internal please do not use.
*/
initialValueRaw() {
return this.applyFallbackValue(this._initialValue);
}
/**
* @internal please do not use.
*/
defaultValue() {
return undefined;
}
/**
* A helper method that creates a stream by subscribing to the Observable returned by the param `observableProducer` callback.
*
* Ideally the callback function creates an Observable by applying `Observable.pipe`.
*
* Just know that you should catch the error in a sub-pipe (ie: do not let it propagate to the main-pipe), otherwise
* as usual the stream will stop working, and will not react on any further emissions.
*
* @param observableProducer A callback function that should return an Observable.
*
* @category Common
*/
createStream(observableProducer) {
const observable = observableProducer(this);
return new Stream(observable);
}
/**
* Given a value, this function determines whether it should be dispatched or not. \
* The dispatch is denied in following circumstances:
* - If the Unit is frozen. {@link isFrozen}
* - If {@link UnitConfig.distinctDispatchCheck} is set to `true`, and the new-value === current-value,
* - If {@link UnitConfig.customDispatchCheck} returns a `falsy` value.
*
* If the Unit is not frozen, you can bypass other dispatch-checks by passing param `force = true`.
*
* This function is used internally, when a value is dispatched {@link dispatch}. \
* Even initialValue {@link UnitConfig.initialValue} dispatch has to pass this check.
*
* You can also use it to check if the value will be dispatched or not before dispatching it.
*
* @param value The value to be dispatched.
* @param force Whether dispatch-checks should be bypassed or not.
* @returns A boolean indicating whether the param `value` would pass the dispatch-checks if dispatched.
*
* @category Common Units
*/
wouldDispatch(value, force = false) {
if (this.isFrozen) {
return false;
}
if (force === true) {
return true;
}
if (typeof this.config.customDispatchCheck === 'function' &&
!this.config.customDispatchCheck(this.rawValue(), value)) {
return false;
}
return this.distinctCheck(value);
}
/**
* Method to dispatch new value by passing the value directly, or \
* by passing a value-producer-function that produces the value using the current {@link value}.
*
* Given a value, it either gets dispatched if it's allowed by {@link wouldDispatch}, \
* or it gets ignored if not allowed.
*
* If the Unit is not configured to be immutable, then \
* the value-producer-function (param `valueOrProducer`) should not mutate the current {@link value}, \
* which is provided as an argument to the function.
*
* If you mutate the value, then the cached-value might also get mutated, \
* as the cached-value is saved by reference, which can result in unpredictable state.
*
* @param valueOrProducer A new-value, or a pure function that produces a new-value.
* @param options Dispatch options.
* @returns `true` if value got dispatched, otherwise `false`.
* If {@link UnitConfig.dispatchDebounce} is enabled, then it'll return `undefined`.
*
* @triggers {@link EventUnitDispatch}, or {@link EventUnitDispatchFail}, depending on the success of dispatch.
* @category Common Action/Units
*/
dispatch(valueOrProducer, options) {
if ((options === null || options === void 0 ? void 0 : options.bypassDebounce) === true) {
return this.dispatchActual(valueOrProducer, options);
}
return this.dispatchMiddleware(valueOrProducer, options);
}
/**
* To manually re-emit the last emitted value again. \
* It doesn't work if the Unit is frozen {@link isFrozen} or muted {@link isMuted}.
*
* Note: Even if the Unit is immutable, it does not create a copy of the Unit's value,
* it merely re-emits the last emitted value.
*
* @returns `true` if replayed successfully, otherwise `false`.
*
* @triggers {@link EventReplay}
* @category Common
*/
replay() {
if (this.isFrozen || this.isMuted) {
return false;
}
super.replay();
return true;
}
/**
* Go back in the cache and re-emit the previous value from the cache, \
* without creating a new entry in the cache.
*
* It can be used as Undo.
*
* It doesn't work if the Unit is frozen {@link isFrozen}.
* It only works if there's a previously dispatched value in the cache. \
* ie: the {@link cacheIndex} is not 0
*
* @returns `true` if the cache-navigation was successful, otherwise `false`.
*
* @triggers {@link EventUnitJump}
* @category Cache Navigation
*/
goBack() {
return this.jump(-1);
}
/**
* After going back in the cache (ie: re-emitting an old value from the cache), \
* use this method to go to the next value, without creating a new entry in the cache.
*
* It can be used as Redo.
*
* It doesn't work if the Unit is frozen {@link isFrozen}.
* It only works if the current {@link value} is not the last value in the cache. \
* ie: the {@link cacheIndex} is not equal to `cachedValuesCount - 1`
*
* @returns `true` if the cache-navigation was successful, otherwise `false`
*
* @triggers {@link EventUnitJump}
* @category Cache Navigation
*/
goForward() {
return this.jump(1);
}
/**
* Use this method to re-emit the first value in the cache, \
* without creating a new entry in the cache.
*
* It doesn't work if the Unit is frozen {@link isFrozen}.
* It only works if the {@link cacheIndex} is not already at the last value in the cache. \
* ie: the {@link cacheIndex} is not 0.
*
* @returns `true` if the cache-navigation was successful, otherwise `false`
*
* @triggers {@link EventUnitJump}
* @category Cache Navigation
*/
jumpToStart() {
return this.jump(-this.cacheIndex);
}
/**
* After going back in the cache (ie: re-emitting an old value from the cache), \
* use this method to re-dispatch the last (latest) value in the cache, \
* without creating a new entry in the cache.
*
* It doesn't work if the Unit is frozen {@link isFrozen}.
* It only works if the {@link cacheIndex} is not already at the last value in the cache.
*
* @returns `true` if the cache-navigation was successful, otherwise `false`
*
* @triggers {@link EventUnitJump}
* @category Cache Navigation
*/
jumpToEnd() {
return this.jump(this.cachedValuesCount - 1 - this.cacheIndex);
}
/**
* Use this method to re-emit a value from the cache, by jumping specific steps backwards or forwards, \
* without creating a new entry in the cache.
*
* It doesn't work if the Unit is frozen {@link isFrozen} or `steps` is not a `number`.
* It only works if the new calculated index is in the bounds of {@link cachedValues}, \
* ie: the new-index is >= 0, and less than {@link cachedValuesCount}, but \
* not equal to current {@link cacheIndex}.
*
* @param steps Number of steps to jump in the cache, negative to jump backwards, positive to jump forwards
* @returns `true` if the cache-navigation was successful, otherwise `false`.
*
* @triggers {@link EventUnitJump}
* @category Cache Navigation
*/
jump(steps) {
var _a;
if (this.isFrozen || !isNumber(steps)) {
return false;
}
const newIndex = this.cacheIndex + steps;
// no point going forward
if (newIndex < 0 || newIndex === this.cacheIndex || newIndex > this.cachedValuesCount - 1) {
return false;
}
this._cacheIndex = newIndex;
this.updateValueAndCache(this._cachedValues[this.cacheIndex], null, true);
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitJump(steps, newIndex));
}
return true;
}
/**
* Get cached value at a given index.
*
* @param index The index of cached value
* @returns The cached value if it exists, otherwise undefined
*
* @category Common Units
*/
getCachedValue(index) {
return this._cachedValues.hasOwnProperty(index)
? this.deepCopyMaybe(this._cachedValues[index])
: undefined;
}
/**
* Clears the cached values, current {@link value} stays intact, but it gets removed from the cache. \
* Meaning, if you dispatch a new value you can't {@link goBack}. \
* To keep the last value in the cache, pass `{leaveLast: true}` in the param `options`.
*
* It only works if the Unit is not frozen and there's something left to clear after evaluating the param `options`.
*
* Similar to preserving the last value, you can preserve the first value by passing `{leaveFirst: true}`.
* Or preserve both first and last value by passing both options together.
*
* @param options Clear cache options
* @returns `true` if the cache was cleared, otherwise `false`
*
* @triggers {@link EventUnitClearCache}
* @category Common Units
*/
clearCache(options) {
var _a;
const leaveFirst = (options === null || options === void 0 ? void 0 : options.leaveFirst) === true;
const leaveLast = (options === null || options === void 0 ? void 0 : options.leaveLast) === true;
if (this.isFrozen ||
this.cachedValuesCount === 0 ||
(this.cachedValuesCount === 1 && (leaveFirst || leaveLast)) ||
(this.cachedValuesCount === 2 && leaveFirst && leaveLast)) {
return false;
}
const start = leaveFirst ? 1 : 0;
const deleteCount = this.cachedValuesCount - start - (leaveLast ? 1 : 0);
this._cachedValues.splice(start, deleteCount);
this._cacheIndex = Math.max(0, this.cachedValuesCount - 1);
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitClearCache(options));
}
return true;
}
/**
* Clears the value by dispatching the default value. \
* It only works if the Unit is not frozen, and {@link emitCount} is not 0, and value is not empty {@link isEmpty}.
*
* @returns `true` if the value was cleared, otherwise `false`
*
* @triggers {@link EventUnitClearValue}
* @category Common Units
*/
clearValue() {
var _a;
if (this.isFrozen || this.emitCount === 0 || this.isEmpty) {
return false;
}
this.updateValueAndCache(this.defaultValue());
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitClearValue());
}
return true;
}
/**
* Holistically clears the Unit, \
* unfreezes using {@link unfreeze}, \
* clears the value using {@link clearValue}, \
* completely clears cache using {@link clearCache}, \
* in that specific order.
*
* @param options Clear cache options for {@link clearCache}.
*
* @triggers {@link EventUnitClear}
* @category Common Units
*/
clear(options) {
var _a;
this.unfreeze();
this.clearValue();
this.clearCache(options);
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitClear(options));
}
}
/**
* Resets the value by dispatching the initial-value, {@link UnitConfig.initialValue} if provided, \
* otherwise dispatches the default value.
*
* It only works if the Unit is not frozen, \
* and the {@link value} is not equal to the {@link initialValue}.
*
* @returns `true` if the reset was successful, otherwise `false`
*
* @triggers {@link EventUnitResetValue}
* @category Common Units
*/
resetValue() {
var _a;
if (this.isFrozen || this.rawValue() === this.initialValueRaw()) {
return false;
}
this.updateValueAndCache(this.initialValueRaw());
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitResetValue());
}
return true;
}
/**
* Holistically resets the Unit, \
* unfreezes using {@link unfreeze}, \
* resets the value using {@link resetValue}, \
* clears cache using {@link clearCache} and by default leaves last value; \
* in that specific order.
*
* @param options Clear cache options for {@link clearCache}. default is `{leaveLast: true}`
*
* @triggers {@link EventUnitReset}
* @category Common Units
*/
reset(options = { leaveLast: true }) {
var _a;
this.unfreeze();
this.resetValue();
this.clearCache(options);
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitReset(options));
}
}
/**
* Temporarily disables most of the functions of the Unit, except {@link unfreeze}, \
* {@link mute}/{@link unmute}, {@link clear} and {@link reset}.
*
* It's not the same as `Object.freeze`.
*
* Freezing prevents any new values from getting dispatched, \
* it disables all the mutating functions. \
* Which eventually ensures that no event is emitted while the Unit is frozen, \
* however all the read operations and operations that do not emit a value are allowed.
*
* @triggers {@link EventUnitFreeze}
* @category Common Units
*/
freeze() {
var _a;
// tslint:disable-next-line:no-console
console.trace();
if (this.isFrozen) {
return;
}
this._isFrozen = true;
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitFreeze());
}
}
/**
* Unfreezes the Unit, and re-enables all the functions disabled by {@link freeze}. \
* It only works if the Unit is frozen.
*
* @triggers {@link EventUnitUnfreeze}
* @category Common Units
*/
unfreeze() {
var _a;
if (!this.isFrozen) {
return;
}
this._isFrozen = false;
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitUnfreeze());
}
}
/**
* Mute the Unit, to stop emitting values as well as events, so that the subscribers are not triggered. \
* All other functionalities stay unaffected. ie: cache it still updated, value is still updated.
*
* Note: If you subscribe to the default Observable while the Unit is muted, \
* it will replay the last value emitted before muting the Unit, \
* because new values are not being emitted.
*
* @category Common Units
*/
mute() {
this._isMuted = true;
}
/**
* Unmute the Unit, to resume emitting values, and events. \
* If a value was dispatched while the Unit was muted, the most recent value immediately gets emitted, \
* so that subscribers can be in sync again. \
* However, other {@link events$} are lost, and they will only emit on the next event.
*
* It only works if the Unit is muted. \
* Moreover, it works even if the Unit is frozen, \
* but no value will be emitted because no values would have been dispatched while the Unit was frozen.
*
* @triggers {@link EventUnitUnmute}
* @category Common Units
*/
unmute() {
var _a;
if (!this.isMuted) {
return;
}
this._isMuted = false;
if (this.emitOnUnmute) {
this.emit();
this.emitOnUnmute = null;
}
if ((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) {
this.eventsSubject.next(new EventUnitUnmute());
}
}
/**
* Clears persisted value from persistent storage. \
* It doesn't turn off persistence, future values will get persisted again.
*
* It only works if the Unit is configured to be persistent. ie: `options.persistent` is true.
*
* @returns `true` if the Unit is configured to be persistent, otherwise `false`.
*
* @triggers {@link EventUnitClearPersistedValue}
* @category Common Units
*/
clearPersistedValue() {
var _a;
if (this.config.persistent === true) {
remove(this.config.id, this.config.storage);
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitClearPersistedValue());
}
return true;
}
return false;
}
/**
* @internal please do not use.
*/
deepCopyMaybe(o) {
return this.config.immutable === true ? deepCopy(o) : o;
}
/**
* @internal please do not use.
*/
checkSerializabilityMaybe(o) {
if (Configuration.ENVIRONMENT.checkSerializability === true) {
checkSerializability(o);
}
}
/**
* @internal please do not use.
*/
updateValueAndCache(value, options, skipCache = false) {
const { cacheReplace } = options || {};
if (Configuration.ENVIRONMENT.checkImmutability === true) {
deepFreeze(value);
}
if (!skipCache) {
this.updateCache(value, cacheReplace);
}
this._value = value;
if (this.isMuted) {
this.emitOnUnmute = true;
}
else {
this.emitOnUnmute = null;
this.emit();
}
this.updateValueInPersistentStorage();
}
/**
* @internal please do not use.
*/
applyFallbackValue(value) {
return value === undefined ? this.defaultValue() : value;
}
/**
* @internal please do not use.
*/
distinctCheck(value) {
return this.config.distinctDispatchCheck !== true || value !== this.rawValue();
}
/**
* @internal please do not use.
*/
dispatchMiddleware(valueOrProducer, options) {
return this.dispatchActual(valueOrProducer, options);
}
/**
* @internal please do not use.
*/
dispatchActual(valueOrProducer, options) {
var _a, _b;
const { force } = options || {};
const value = typeof valueOrProducer === 'function'
? valueOrProducer(this.value())
: valueOrProducer;
this.checkSerializabilityMaybe(value);
if (this.wouldDispatch(value, force)) {
this.updateValueAndCache(this.deepCopyMaybe(value), options); // clone and dispatch
if (((_a = this.eventsSubject) === null || _a === void 0 ? void 0 : _a.observers.length) && !this.isMuted) {
this.eventsSubject.next(new EventUnitDispatch(value, options));
}
return true;
}
if (((_b = this.eventsSubject) === null || _b === void 0 ? void 0 : _b.observers.length) && !this.isMuted) {
const failReason = (this.isFrozen && DispatchFailReason.FROZEN_UNIT) ||
(this.isValidValue(value) &&
(this.distinctCheck(value)
? DispatchFailReason.CUSTOM_DISPATCH_CHECK
: DispatchFailReason.DISTINCT_CHECK)) ||
DispatchFailReason.INVALID_VALUE;
this.eventsSubject.next(new EventUnitDispatchFail(value, failReason, options));
}
return false;
}
/**
* @internal please do not use.
*/
shouldDispatchInitialValue(initialValue) {
// not checking undefined in wouldDispatch to allow undefined values later on (for GenericUnit)
return initialValue !== undefined && this.isValidValue(initialValue);
}
/**
* @internal please do not use.
*/
updateCache(value, cacheReplace) {
if (cacheReplace === true) {
this._cachedValues[this.cacheIndex] = value;
}
else {
if (this.cachedValuesCount === 0 || this.cacheIndex === this.cachedValuesCount - 1) {
this._cachedValues.push(value);
if (this.cachedValuesCount > this.cacheSize) {
this._cachedValues.shift();
}
this._cacheIndex = this.cachedValuesCount - 1;
}
else {
this._cachedValues.splice(this.cacheIndex + 1, this.cachedValuesCount - 1 - this.cacheIndex, value);
++this._cacheIndex;
}
}
}
/**
* @internal please do not use.
*/
dispatchInitialValue(initialValue) {
if (this.shouldDispatchInitialValue(initialValue)) {
this._initialValue = initialValue;
this.updateValueAndCache(this.initialValueRaw());
}
else {
this.updateValueAndCache(this.defaultValue());
}
}
/**
* @internal please do not use.
*/
updateValueInPersistentStorage() {
if (this.config.persistent === true) {
save(this.config.id, this.rawValue(), this.config.storage);
}
}
/**
* @internal please do not use.
*/
restoreValueFromPersistentStorage(initialValue) {
const savedState = retrieve(this.config.id, this.config.storage);
if (savedState) {
this.dispatchInitialValue(savedState.value);
}
else {
this.checkSerializabilityMaybe(initialValue);
this.dispatchInitialValue(this.deepCopyMaybe(initialValue));
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3QtdW5pdC1iYXNlLmpzIiwic291cmNlUm9vdCI6Ii9ob21lL3J1bm5lci93b3JrL2FjdGl2ZWpzL2FjdGl2ZWpzL3BhY2thZ2VzL2NvcmUvc3JjLyIsInNvdXJjZXMiOlsibGliL2Fic3RyYWN0LXVuaXQtYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBRUwsa0JBQWtCLEVBR2xCLGNBQWMsRUFDZCxtQkFBbUIsRUFDbkIsNEJBQTRCLEVBQzVCLG1CQUFtQixFQUNuQixpQkFBaUIsRUFDakIscUJBQXFCLEVBQ3JCLGVBQWUsRUFDZixhQUFhLEVBQ2IsY0FBYyxFQUNkLG1CQUFtQixFQUNuQixpQkFBaUIsRUFDakIsZUFBZSxHQUloQixNQUFNLFdBQVcsQ0FBQztBQUNuQixPQUFPLEVBQUMsSUFBSSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDckMsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzlDLE9BQU8sRUFBQyxNQUFNLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDaEMsT0FBTyxFQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3JELE9BQU8sRUFBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4RSxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUV0RDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUNILE1BQU0sT0FBZ0IsUUFBWSxTQUFRLElBQU87SUF3Sy9DLDhCQUE4QjtJQUU5Qjs7T0FFRztJQUNILFlBQXNCLE1BQXNCO1FBQzFDLEtBQUssaUNBQ0EsYUFBYSxDQUFDLEtBQUssR0FDbkIsTUFBTSxFQUNULENBQUM7UUEvSkw7O1dBRUc7UUFDSyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBaUIxQjs7V0FFRztRQUNLLGFBQVEsR0FBRyxLQUFLLENB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Q0FBQyxhQUFhLEdBQUcsWUFBWSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQztTQUNsRDthQUFNO1lBQ0wsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1NBQy9DO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssOEJBQThCO1FBQ3BDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEtBQUssSUFBSSxFQUFFO1lBQ25DLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUM1RDtJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLGlDQUFpQyxDQUFDLFlBQVk7UUFDcEQsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFakUsSUFBSSxVQUFVLEVBQUU7WUFDZCxJQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQzdDO2FBQU07WUFDTCxJQUFJLENBQUMseUJBQXlCLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDN0MsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztTQUM3RDtJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7T2JzZXJ2YWJsZSwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBDbGVhckNhY2hlT3B0aW9ucyxcbiAgRGlzcGF0Y2hGYWlsUmVhc29uLFxuICBEaXNwYXRjaE9wdGlvbnMsXG4gIERpc3BhdGNoVmFsdWVQcm9kdWNlcixcbiAgRXZlbnRVbml0Q2xlYXIsXG4gIEV2ZW50VW5pdENsZWFyQ2FjaGUsXG4gIEV2ZW50VW5pdENsZWFyUGVyc2lzdGVkVmFsdWUsXG4gIEV2ZW50VW5pdENsZWFyVmFsdWUsXG4gIEV2ZW50VW5pdERpc3BhdGNoLFxuICBFdmVudFVuaXREaXNwYXRjaEZhaWwsXG4gIEV2ZW50VW5pdEZyZWV6ZSxcbiAgRXZlbnRVbml0SnVtcCxcbiAgRXZlbnRVbml0UmVzZXQsXG4gIEV2ZW50VW5pdFJlc2V0VmFsdWUsXG4gIEV2ZW50VW5pdFVuZnJlZXplLFxuICBFdmVudFVuaXRVbm11dGUsXG4gIFVuaXRDb25maWcsXG4gIFVuaXRFdmVudHMsXG4gIFVuaXRTdHJlYW1PYnNlcnZhYmxlUHJvZHVjZXIsXG59IGZyb20gJy4uL21vZGVscyc7XG5pbXBvcnQge0Jhc2V9IGZyb20gJy4vYWJzdHJhY3QtYmFzZSc7XG5pbXBvcnQge0NvbmZpZ3VyYXRpb259IGZyb20gJy4vY29uZmlndXJhdGlvbic7XG5pbXBvcnQge1N0cmVhbX0gZnJvbSAnLi9zdHJlYW0nO1xuaW1wb3J0IHtyZW1vdmUsIHJldHJpZXZlLCBzYXZlfSBmcm9tICcuL3BlcnNpc3RlbmNlJztcbmltcG9ydCB7ZGVib3VuY2UsIGRlZXBDb3B5LCBkZWVwRnJlZXplLCBpc051bWJlcn0gZnJvbSAnLi4vdXRpbHMvZnVuY3MnO1xuaW1wb3J0IHtjaGVja1NlcmlhbGl6YWJpbGl0eX0gZnJvbSAnLi4vY2hlY2tzL2NvbW1vbic7XG5cbi8qKlxuICogVW5pdEJhc2Ugc2VydmVzIGFzIHRoZSBiYXNlIGZvciBhbGwgdGhlIEFjdGl2ZUpTIFVuaXRzOiBHZW5lcmljVW5pdCwgQm9vbFVuaXQsIExpc3RVbml0LCBldGMuXG4gKiBJdCBleHRlbmRzIHtAbGluayBCYXNlfS5cbiAqXG4gKiBUaGlzIGlzIGFuIGludGVybmFsIGNvbnN0cnVjdCwgbm9ybWFsbHkgeW91J2QgbmV2ZXIgaGF2ZSB0byB1c2UgdGhpcyBjbGFzcyBkaXJlY3RseS5cbiAqIEhvd2V2ZXIsIGlmIHlvdSdyZSBqdXN0IHJlYWRpbmcgdGhlIGRvY3VtZW50YXRpb24sIG9yIHdhbnQgdG8gbGVhcm4gbW9yZSBhYm91dCBob3cgQWN0aXZlSlMgd29ya3MsXG4gKiBvciB3YW50IHRvIGV4dGVuZCB0aGlzIGNsYXNzIHRvIGJ1aWxkIHNvbWV0aGluZyBvbiB5b3VyIG93biwgcGxlYXNlIGNvbnRpbnVlLlxuICpcbiAqIFVuaXRCYXNlIGNyZWF0ZXMgdGhlIGZvdW5kYXRpb24gb2YgYWxsIHRoZSBBY3RpdmVKUyBVbml0cy5cbiAqIEl0IGltcGxlbWVudHMgdGhlIGZlYXR1cmVzIGxpa2U6XG4gKiAtIGRpc3BhdGNoaW5nLCBjbGVhcmluZyBhbmQgcmVzZXR0aW5nIHRoZSB2YWx1ZVxuICogLSBjYWNoaW5nIHRoZSBkaXNwYXRjaGVkIHZhbHVlc1xuICogLSBuYXZpZ2F0aW5nIHRocm91Z2ggdGhlIGNhY2hlZCB2YWx1ZXMsIGJ5IG1ldGhvZHMgbGlrZSBnb0JhY2ssIGdvRm9yd2FyZCwganVtcCBldGMuXG4gKiAtIG9ic2VydmFibGUgZXZlbnRzIHRvIGxpc3RlbiB0byBpbmNsdWRpbmcgYnV0IG5vdCBsaW1pdGVkIHRvIHRoZSBhYm92ZSBtZW50aW9uZWQgYWN0aW9uc1xuICogLSBmcmVlemluZy91bmZyZWV6aW5nIHRoZSBVbml0XG4gKiAtIG11dGluZy91bm11dGluZyB0aGUgVW5pdFxuICogLSBwZXJzaXN0aW5nIGFuZCByZXRyaWV2aW5nIHRoZSB2YWx1ZSB0by9mcm9tIHBlcnNpc3RlbnQtc3RvcmFnZVxuICogLSBkZWJvdW5jaW5nIHRoZSBkaXNwYXRjaFxuICogLSByZXNldHRpbmcgdGhlIFVuaXRcbiAqIC0gZXRjLlxuICpcbiAqIEBjYXRlZ29yeSAyLiBBYnN0cmFjdFxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVW5pdEJhc2U8VD4gZXh0ZW5kcyBCYXNlPFQ+IHtcbiAgLyoqXG4gICAqIENvbmZpZ3VyZWQgb3B0aW9ucy5cbiAgICogQ29tYmluYXRpb24gb2YgZ2xvYmFsLW9wdGlvbnMge0BsaW5rIEdsb2JhbFVuaXRDb25maWd9IGFuZCB0aGUgb3B0aW9ucyBwYXNzZWQgb24gaW5zdGFudGlhdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IGNvbmZpZzogUmVhZG9ubHk8VW5pdENvbmZpZzxUPj47XG5cbiAgLy8gdHNsaW50OmRpc2FibGU6dmFyaWFibGUtbmFtZVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZXZlbnRzU3ViamVjdDogU3ViamVjdDxVbml0RXZlbnRzPFQ+PjtcbiAgLyoqXG4gICAqIE9uLWRlbWFuZCBvYnNlcnZhYmxlIGV2ZW50cy5cbiAgICovXG4gIHJlYWRvbmx5IGV2ZW50cyQ6IE9ic2VydmFibGU8VW5pdEV2ZW50czxUPj47XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgX2lzRnJvemVuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBVbml0IGlzIGZyb3plbiBvciBub3QuXG4gICAqIFNlZSB7QGxpbmsgZnJlZXplfSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgKlxuICAgKiBOb3RlOiBJdCdzIG5vdCB0aGUgc2FtZSBhcyBbT2JqZWN0LmlzRnJvemVuXShodHRwczovL2N1dHQubHkvV3lGZHpQRCkuXG4gICAqL1xuICBnZXQgaXNGcm96ZW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2lzRnJvemVuO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgZW1pdE9uVW5tdXRlOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcml2YXRlIF9pc011dGVkID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBVbml0IGlzIG11dGVkIG9yIG5vdC5cbiAgICogU2VlIHtAbGluayBtdXRlfSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgKi9cbiAgZ2V0IGlzTXV0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2lzTXV0ZWQ7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhlIHZhbHVlIGlzIHVuZGVmaW5lZCBvciBub3QuXG4gICAqXG4gICAqIEl0IHNob3VsZCBiZSBwcmVmZXJyZWQgaWYgdGhlIFVuaXQgaXMgY29uZmlndXJlZCB0byBiZSBpbW11dGFibGUsIGFzIGl0IGRvZXNuJ3QgY3JlYXRlIGEgY29weS5cbiAgICovXG4gIGdldCBpc0VtcHR5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJhd1ZhbHVlKCkgPT09IHRoaXMuZGVmYXVsdFZhbHVlKCk7XG4gIH1cblxuICAvKipcbiAgICogU2l6ZSBvZiB0aGUgY2FjaGUsIGRpY3RhdGluZyBob3cgbWFueSB2YWx1ZXMgY2FuIGJlIGNhY2hlZCBhdCBhIGdpdmVuIHRpbWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IGAyYFxuICAgKiBAbWluaW11bSBgMWBcbiAgICogQG1heGltdW0gYEluZmluaXR5YFxuICAgKi9cbiAgcmVhZG9ubHkgY2FjaGVTaXplOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByb3RlY3RlZCByZWFkb25seSBfY2FjaGVkVmFsdWVzOiBUW10gPSBbXTtcblxuICAvKipcbiAgICogQ291bnQgb2YgYWxsIHRoZSBjYWNoZWQgdmFsdWVzLlxuICAgKi9cbiAgZ2V0IGNhY2hlZFZhbHVlc0NvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlZFZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsIHBsZWFzZSBkbyBub3QgdXNlLlxuICAgKi9cbiAgcHJpdmF0ZSBfY2FjaGVJbmRleCA9IDA7XG5cbiAgLyoqXG4gICAqIEluZGV4IG9mIHRoZSBjdXJyZW50IHtAbGluayB2YWx1ZX0gaW4gdGhlIHtAbGluayBVbml0QmFzZS5jYWNoZWRWYWx1ZXN9XG4gICAqL1xuICBnZXQgY2FjaGVJbmRleCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9jYWNoZUluZGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgX2luaXRpYWxWYWx1ZTogVCA9IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGludG