UNPKG

@activejs/core

Version:

Pragmatic, Reactive State Management for JavaScript Apps

743 lines 82.5 kB
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