UNPKG

@activejs/core

Version:

Pragmatic, Reactive State Management for JavaScript Apps

272 lines 29.4 kB
import { Base } from './abstract-base'; import { Stream } from './stream'; import { makeNonEnumerable } from '../utils/funcs'; import { checkAsyncSystemConfig } from '../checks/common'; import { Configuration } from './configuration'; /** * Base class for AsyncSystem. * * It can be used to create custom, {@link AsyncSystem} like Systems. * * See {@link https://docs.activejs.dev/fundamentals/systems/custom-asyncsystem} for more details. * * Just like every other ActiveJS construct: * - AsyncSystem extends {@link Base} * - Which further extends `Observable` * * @category 3. Systems */ export class AsyncSystemBase extends Base { constructor( /** * The member Unit that is intended to portray the role of `query` aspect of an async task. * @category Member Units */ queryUnit, /** * The member Unit that is intended to portray the role of `response` aspect of an async task. * @category Member Units */ dataUnit, /** * The member Unit that is intended to portray the role of `error` aspect of an async task. * @category Member Units */ errorUnit, /** * The member Unit that is intended to portray the role of `pending-status` of an async task. * @category Member Units */ pendingUnit, config) { super(config); this.queryUnit = queryUnit; this.dataUnit = dataUnit; this.errorUnit = errorUnit; this.pendingUnit = pendingUnit; /** * @internal please do not use. * * It works because all our Subjects and operations are synchronous. */ this.relationshipsAutoPaused = false; this.relationshipsManuallyPaused = false; checkAsyncSystemConfig(config)(); this.emit(); this.createRelationshipsAmongMemberUnits(); makeNonEnumerable(this); } /** * To check whether the inter-relationships among the member Units are active or not. * * @default `true` */ get relationshipsWorking() { return !this.relationshipsAutoPaused && !this.relationshipsManuallyPaused; } /** * Combined value of all the member Units. * * @category Access Value */ value() { const val = { query: this.queryUnit.value(), data: this.dataUnit.value(), error: this.errorUnit.value(), pending: this.pendingUnit.value(), }; if (Configuration.ENVIRONMENT.checkImmutability === true) { Object.freeze(val); } return val; } /** * 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` * on the {@link queryUnit} or `queryUnit.future$` as source Observable. * * Then, after a successful data flow, dispatch the data to the {@link dataUnit}; \ * and after a failure, dispatch the error to the {@link errorUnit}, caught by using RxJS' catchError operator. * * 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.queryUnit, this.dataUnit, this.errorUnit, this.pendingUnit); return new Stream(observable); } /** * To pause inter-relationships among the member Units. Also see {@link relationshipsWorking}. * * When inter-relationships are paused, * you can perform any number of operations on the member Units * without triggering the automatic relationships like {@link AsyncSystemBaseConfig.clearErrorOnData}, * {@link AsyncSystemBaseConfig.autoUpdatePendingValue}, etc. * * This also means that the AsyncSystem stops emitting new values. * * @category Custom AsyncSystem */ pauseRelationships() { if (this.relationshipsManuallyPaused === true) { return; } this.relationshipsManuallyPaused = true; this.unitsEmitCountsBeforePausing = this.unitsEmitCounts(); } /** * To resume inter-relationships among the member Units. Also see {@link relationshipsWorking}. * * It restores the inter-relationships like {@link AsyncSystemBaseConfig.clearErrorOnData}, * {@link AsyncSystemBaseConfig.autoUpdatePendingValue}, etc. * * This also means that the AsyncSystem starts emitting new values. \ * And if any of the member Units emitted a value while the relationships were paused, * the AsyncSystem will emit a new value immediately to bring itself and its subscribers in sync * with the member Units. * * @category Custom AsyncSystem */ resumeRelationships() { if (this.relationshipsManuallyPaused === false) { return; } this.relationshipsManuallyPaused = false; if (this.unitsEmitCountsBeforePausing.join() !== this.unitsEmitCounts().join()) { this.emit(); } } /** * @internal please do not use. */ unitsEmitCounts() { return [ this.queryUnit.emitCount, this.dataUnit.emitCount, this.errorUnit.emitCount, this.pendingUnit.emitCount, ]; } /** * @internal please do not use. */ createRelationshipsAmongMemberUnits() { this.queryUnit.future$.subscribe(() => { if (this.relationshipsWorking) { this.executeQueryUnitRelationship(); } }); this.dataUnit.future$.subscribe(() => { if (this.relationshipsWorking) { this.executeDataUnitRelationship(); } }); this.errorUnit.future$.subscribe(() => { if (this.relationshipsWorking) { this.executeErrorUnitRelationship(); } }); this.pendingUnit.future$.subscribe(isPending => { if (!this.relationshipsManuallyPaused) { this.toggleQueryUnitFreezeMaybe(isPending); } if (this.relationshipsWorking) { this.emit(); } }); } /** * @internal please do not use. */ executeQueryUnitRelationship() { this.relationshipsAutoPaused = true; this.autoUpdatePendingValue(true); if (this.config.clearDataOnQuery === true) { this.dataUnit.clearValue(); } if (this.config.clearErrorOnQuery === true) { this.errorUnit.clearValue(); } this.relationshipsAutoPaused = false; this.emit(); } /** * @internal please do not use. */ executeDataUnitRelationship() { this.relationshipsAutoPaused = true; this.autoUpdatePendingValue(false); if (this.config.clearErrorOnQuery !== true && this.config.clearErrorOnData !== false) { this.errorUnit.clearValue(); } if (this.config.clearQueryOnData === true) { this.queryUnit.clearValue(); } this.relationshipsAutoPaused = false; this.emit(); } /** * @internal please do not use. */ executeErrorUnitRelationship() { this.relationshipsAutoPaused = true; this.autoUpdatePendingValue(false); if (this.config.clearDataOnQuery !== true && this.config.clearDataOnError === true) { this.dataUnit.clearValue(); } if (this.config.clearQueryOnError === true) { this.queryUnit.clearValue(); } this.relationshipsAutoPaused = false; this.emit(); } /** * @internal please do not use. */ toggleQueryUnitFreezeMaybe(isPending) { if (this.config.freezeQueryWhilePending === true) { if (isPending) { this.queryUnit.freeze(); } else { this.queryUnit.unfreeze(); } } } /** * @internal please do not use. */ autoUpdatePendingValue(isPending) { if (this.config.autoUpdatePendingValue !== false) { this.pendingUnit.dispatch(isPending, { bypassDebounce: true }); } } /** * @internal please do not use. */ emit(value = this.combinedEmittedValues()) { if (Configuration.ENVIRONMENT.checkImmutability === true) { Object.freeze(value); } super.emit(value); } /** * @internal please do not use. */ combinedEmittedValues() { // tslint:disable:no-string-literal return { query: this.queryUnit['emittedValue'], data: this.dataUnit['emittedValue'], error: this.errorUnit['emittedValue'], pending: this.pendingUnit['emittedValue'], }; // tslint:enable:no-string-literal } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtc3lzdGVtLWJhc2UuanMiLCJzb3VyY2VSb290IjoiL2hvbWUvcnVubmVyL3dvcmsvYWN0aXZlanMvYWN0aXZlanMvcGFja2FnZXMvY29yZS9zcmMvIiwic291cmNlcyI6WyJsaWIvYXN5bmMtc3lzdGVtLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRXJDLE9BQU8sRUFBQyxNQUFNLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDaEMsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFRakQsT0FBTyxFQUFDLHNCQUFzQixFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFFeEQsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRTlDOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILE1BQU0sT0FBTyxlQU9YLFNBQVEsSUFBMEM7SUErQ2xEO0lBQ0U7OztPQUdHO0lBQ2EsU0FBb0I7SUFDcEM7OztPQUdHO0lBQ2EsUUFBa0I7SUFDbEM7OztPQUdHO0lBQ2EsU0FBb0I7SUFDcEM7OztPQUdHO0lBQ2EsV0FBcUIsRUFDckMsTUFBa0Q7UUFFbEQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBbEJFLGNBQVMsR0FBVCxTQUFTLENBQVc7UUFLcEIsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUtsQixjQUFTLEdBQVQsU0FBUyxDQUFXO1FBS3BCLGdCQUFXLEdBQVgsV0FBVyxDQUFVO1FBNUR2Qzs7OztXQUlHO1FBQ0ssNEJBQXVCLEdBQUcsS0FBSyxDQUFDO1FBQ2hDLGdDQUEyQixHQUFHLEtBQUssQ0FBQztRQTJEMUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUVqQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDWixJQUFJLENBQUMsbUNBQW1DLEVBQUUsQ0FBQztRQUMzQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJ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V0FBVyxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsRUFBQyxjQUFjLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQztTQUM5RDtJQUNILENBQUM7SUFFRDs7T0FFRztJQUNPLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFO1FBQ2pELElBQUksYUFBYSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsS0FBSyxJQUFJLEVBQUU7WUFDeEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUN0QjtRQUNELEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEIsQ0FBQztJQUVEOztPQUVHO0lBQ0sscUJBQXFCO1FBQzNCLG1DQUFtQztRQUNuQyxPQUFPO1lBQ0wsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDO1lBQ3JDLElBQUksRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQztZQUNuQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUM7WUFDckMsT0FBTyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDO1NBQzFDLENBQUM7UUFDRixrQ0FBa0M7SUFDcEMsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtCYXNlfSBmcm9tICcuL2Fic3RyYWN0LWJhc2UnO1xuaW1wb3J0IHtCb29sVW5pdH0gZnJvbSAnLi9ib29sLXVuaXQnO1xuaW1wb3J0IHtTdHJlYW19IGZyb20gJy4vc3RyZWFtJztcbmltcG9ydCB7bWFrZU5vbkVudW1lcmFibGV9IGZyb20gJy4uL3V0aWxzL2Z1bmNzJztcbmltcG9ydCB7XG4gIEFzeW5jU3lzdGVtQmFzZUNvbmZpZyxcbiAgQXN5bmNTeXN0ZW1TdHJlYW1PYnNlcnZhYmxlUHJvZHVjZXIgYXMgU3RyZWFtT2JzZXJ2YWJsZVByb2R1Y2VyLFxuICBBc3luY1N5c3RlbVZhbHVlLFxuICBVbml0VG9WYWx1ZVR5cGUsXG4gIFVuaXQsXG59IGZyb20gJy4uL21vZGVscyc7XG5pbXBvcnQge2NoZWNrQXN5bmNTeXN0ZW1Db25maWd9IGZyb20gJy4uL2NoZWNrcy9jb21tb24nO1xuaW1wb3J0IHtBc3luY1N5c3RlbX0gZnJvbSAnLi9hc3luYy1zeXN0ZW0nO1xuaW1wb3J0IHtDb25maWd1cmF0aW9ufSBmcm9tICcuL2NvbmZpZ3VyYXRpb24nO1xuXG4vKipcbiAqIEJhc2UgY2xhc3MgZm9yIEFzeW5jU3lzdGVtLlxuICpcbiAqIEl0IGNhbiBiZSB1c2VkIHRvIGNyZWF0ZSBjdXN0b20sIHtAbGluayBBc3luY1N5c3RlbX0gbGlrZSBTeXN0ZW1zLlxuICpcbiAqIFNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmFjdGl2ZWpzLmRldi9mdW5kYW1lbnRhbHMvc3lzdGVtcy9jdXN0b20tYXN5bmNzeXN0ZW19IGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogSnVzdCBsaWtlIGV2ZXJ5IG90aGVyIEFjdGl2ZUpTIGNvbnN0cnVjdDpcbiAqIC0gQXN5bmNTeXN0ZW0gZXh0ZW5kcyB7QGxpbmsgQmFzZX1cbiAqIC0gV2hpY2ggZnVydGhlciBleHRlbmRzIGBPYnNlcnZhYmxlYFxuICpcbiAqIEBjYXRlZ29yeSAzLiBTeXN0ZW1zXG4gKi9cbmV4cG9ydCBjbGFzcyBBc3luY1N5c3RlbUJhc2U8XG4gIFF1ZXJ5VW5pdCBleHRlbmRzIFVuaXQsXG4gIERhdGFVbml0IGV4dGVuZHMgVW5pdCxcbiAgRXJyb3JVbml0IGV4dGVuZHMgVW5pdCxcbiAgUXVlcnkgZXh0ZW5kcyBVbml0VG9WYWx1ZVR5cGU8UXVlcnlVbml0PiA9IFVuaXRUb1ZhbHVlVHlwZTxRdWVyeVVuaXQ+LFxuICBEYXRhIGV4dGVuZHMgVW5pdFRvVmFsdWVUeXBlPERhdGFVbml0PiA9IFVuaXRUb1ZhbHVlVHlwZTxEYXRhVW5pdD4sXG4gIEVycm9yIGV4dGVuZHMgVW5pdFRvVmFsdWVUeXBlPEVycm9yVW5pdD4gPSBVbml0VG9WYWx1ZVR5cGU8RXJyb3JVbml0PlxuPiBleHRlbmRzIEJhc2U8QXN5bmNTeXN0ZW1WYWx1ZTxRdWVyeSwgRGF0YSwgRXJyb3I+PiB7XG4gIC8qKlxuICAgKiBDb25maWd1cmVkIG9wdGlvbnMuIFxcXG4gICAqIENvbWJpbmF0aW9uIG9mIGdsb2JhbC1vcHRpb25zIHtAbGluayBHbG9iYWxBc3luY1N5c3RlbUNvbmZpZ30gYW5kIHRoZSBvcHRpb25zIHBhc3NlZCBvbiBpbnN0YW50aWF0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgY29uZmlnOiBSZWFkb25seTxBc3luY1N5c3RlbUJhc2VDb25maWc8UXVlcnksIERhdGEsIEVycm9yPj47XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICpcbiAgICogSXQgd29ya3MgYmVjYXVzZSBhbGwgb3VyIFN1YmplY3RzIGFuZCBvcGVyYXRpb25zIGFyZSBzeW5jaHJvbm91cy5cbiAgICovXG4gIHByaXZhdGUgcmVsYXRpb25zaGlwc0F1dG9QYXVzZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZWxhdGlvbnNoaXBzTWFudWFsbHlQYXVzZWQgPSBmYWxzZTtcblxuICAvKipcbiAgICogVG8gY2hlY2sgd2hldGhlciB0aGUgaW50ZXItcmVsYXRpb25zaGlwcyBhbW9uZyB0aGUgbWVtYmVyIFVuaXRzIGFyZSBhY3RpdmUgb3Igbm90LlxuICAgKlxuICAgKiBAZGVmYXVsdCBgdHJ1ZWBcbiAgICovXG4gIGdldCByZWxhdGlvbnNoaXBzV29ya2luZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIXRoaXMucmVsYXRpb25zaGlwc0F1dG9QYXVzZWQgJiYgIXRoaXMucmVsYXRpb25zaGlwc01hbnVhbGx5UGF1c2VkO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgdW5pdHNFbWl0Q291bnRzQmVmb3JlUGF1c2luZzogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG5cbiAgLyoqXG4gICAqIENvbWJpbmVkIHZhbHVlIG9mIGFsbCB0aGUgbWVtYmVyIFVuaXRzLlxuICAgKlxuICAgKiBAY2F0ZWdvcnkgQWNjZXNzIFZhbHVlXG4gICAqL1xuICB2YWx1ZSgpOiBBc3luY1N5c3RlbVZhbHVlPFF1ZXJ5LCBEYXRhLCBFcnJvcj4ge1xuICAgIGNvbnN0IHZhbCA9IHtcbiAgICAgIHF1ZXJ5OiB0aGlzLnF1ZXJ5VW5pdC52YWx1ZSgpLFxuICAgICAgZGF0YTogdGhpcy5kYXRhVW5pdC52YWx1ZSgpLFxuICAgICAgZXJyb3I6IHRoaXMuZXJyb3JVbml0LnZhbHVlKCksXG4gICAgICBwZW5kaW5nOiB0aGlzLnBlbmRpbmdVbml0LnZhbHVlKCksXG4gICAgfTtcbiAgICBpZiAoQ29uZmlndXJhdGlvbi5FTlZJUk9OTUVOVC5jaGVja0ltbXV0YWJpbGl0eSA9PT0gdHJ1ZSkge1xuICAgICAgT2JqZWN0LmZyZWV6ZSh2YWwpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgLyoqXG4gICAgICogVGhlIG1lbWJlciBVbml0IHRoYXQgaXMgaW50ZW5kZWQgdG8gcG9ydHJheSB0aGUgcm9sZSBvZiBgcXVlcnlgIGFzcGVjdCBvZiBhbiBhc3luYyB0YXNrLlxuICAgICAqIEBjYXRlZ29yeSBNZW1iZXIgVW5pdHNcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgcXVlcnlVbml0OiBRdWVyeVVuaXQsXG4gICAgLyoqXG4gICAgICogVGhlIG1lbWJlciBVbml0IHRoYXQgaXMgaW50ZW5kZWQgdG8gcG9ydHJheSB0aGUgcm9sZSBvZiBgcmVzcG9uc2VgIGFzcGVjdCBvZiBhbiBhc3luYyB0YXNrLlxuICAgICAqIEBjYXRlZ29yeSBNZW1iZXIgVW5pdHNcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZGF0YVVuaXQ6IERhdGFVbml0LFxuICAgIC8qKlxuICAgICAqIFRoZSBtZW1iZXIgVW5pdCB0aGF0IGlzIGludGVuZGVkIHRvIHBvcnRyYXkgdGhlIHJvbGUgb2YgYGVycm9yYCBhc3BlY3Qgb2YgYW4gYXN5bmMgdGFzay5cbiAgICAgKiBAY2F0ZWdvcnkgTWVtYmVyIFVuaXRzXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGVycm9yVW5pdDogRXJyb3JVbml0LFxuICAgIC8qKlxuICAgICAqIFRoZSBtZW1iZXIgVW5pdCB0aGF0IGlzIGludGVuZGVkIHRvIHBvcnRyYXkgdGhlIHJvbGUgb2YgYHBlbmRpbmctc3RhdHVzYCBvZiBhbiBhc3luYyB0YXNrLlxuICAgICAqIEBjYXRlZ29yeSBNZW1iZXIgVW5pdHNcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgcGVuZGluZ1VuaXQ6IEJvb2xVbml0LFxuICAgIGNvbmZpZz86IEFzeW5jU3lzdGVtQmFzZUNvbmZpZzxRdWVyeSwgRGF0YSwgRXJyb3I+XG4gICkge1xuICAgIHN1cGVyKGNvbmZpZyk7XG5cbiAgICBjaGVja0FzeW5jU3lzdGVtQ29uZmlnKGNvbmZpZykoKTtcblxuICAgIHRoaXMuZW1pdCgpO1xuICAgIHRoaXMuY3JlYXRlUmVsYXRpb25zaGlwc0Ftb25nTWVtYmVyVW5pdHMoKTtcbiAgICBtYWtlTm9uRW51bWVyYWJsZSh0aGlzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGhlbHBlciBtZXRob2QgdGhhdCBjcmVhdGVzIGEgc3RyZWFtIGJ5IHN1YnNjcmliaW5nIHRvIHRoZSBPYnNlcnZhYmxlIHJldHVybmVkIGJ5IHRoZSBwYXJhbSBgb2JzZXJ2YWJsZVByb2R1Y2VyYCBjYWxsYmFjay5cbiAgICpcbiAgICogSWRlYWxseSB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gY3JlYXRlcyBhbiBPYnNlcnZhYmxlIGJ5IGFwcGx5aW5nIGBPYnNlcnZhYmxlLnBpcGVgXG4gICAqIG9uIHRoZSB7QGxpbmsgcXVlcnlVbml0fSBvciBgcXVlcnlVbml0LmZ1dHVyZSRgIGFzIHNvdXJjZSBPYnNlcnZhYmxlLlxuICAgKlxuICAgKiBUaGVuLCBhZnRlciBhIHN1Y2Nlc3NmdWwgZGF0YSBmbG93LCBkaXNwYXRjaCB0aGUgZGF0YSB0byB0aGUge0BsaW5rIGRhdGFVbml0fTsgXFxcbiAgICogYW5kIGFmdGVyIGEgZmFpbHVyZSwgZGlzcGF0Y2ggdGhlIGVycm9yIHRvIHRoZSB7QGxpbmsgZXJyb3JVbml0fSwgY2F1Z2h0IGJ5IHVzaW5nIFJ4SlMnIGNhdGNoRXJyb3Igb3BlcmF0b3IuXG4gICAqXG4gICAqIEp1c3Qga25vdyB0aGF0IHlvdSBzaG91bGQgY2F0Y2ggdGhlIGVycm9yIGluIGEgc3ViLXBpcGUgKGllOiBkbyBub3QgbGV0IGl0IHByb3BhZ2F0ZSB0byB0aGUgbWFpbi1waXBlKSwgb3RoZXJ3aXNlXG4gICAqIGFzIHVzdWFsIHRoZSBzdHJlYW0gd2lsbCBzdG9wIHdvcmtpbmcsIGFuZCB3aWxsIG5vdCByZWFjdCBvbiBhbnkgZnVydGhlciBlbWlzc2lvbnMuXG4gICAqXG4gICAqIEBwYXJhbSBvYnNlcnZhYmxlUHJvZHVjZXIgQSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IHNob3VsZCByZXR1cm4gYW4gT2JzZXJ2YWJsZS5cbiAgICpcbiAgICogQGNhdGVnb3J5IENvbW1vblxuICAgKi9cbiAgY3JlYXRlU3RyZWFtPFI+KFxuICAgIG9ic2VydmFibGVQcm9kdWNlcjogU3RyZWFtT2JzZXJ2YWJsZVByb2R1Y2VyPFF1ZXJ5VW5pdCwgRGF0YVVuaXQsIEVycm9yVW5pdCwgUj5cbiAgKTogU3RyZWFtIHtcbiAgICBjb25zdCBvYnNlcnZhYmxlID0gb2JzZXJ2YWJsZVByb2R1Y2VyKFxuICAgICAgdGhpcy5xdWVyeVVuaXQsXG4gICAgICB0aGlzLmRhdGFVbml0LFxuICAgICAgdGhpcy5lcnJvclVuaXQsXG4gICAgICB0aGlzLnBlbmRpbmdVbml0XG4gICAgKTtcblxuICAgIHJldHVybiBuZXcgU3RyZWFtKG9ic2VydmFibGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvIHBhdXNlIGludGVyLXJlbGF0aW9uc2hpcHMgYW1vbmcgdGhlIG1lbWJlciBVbml0cy4gQWxzbyBzZWUge0BsaW5rIHJlbGF0aW9uc2hpcHNXb3JraW5nfS5cbiAgICpcbiAgICogV2hlbiBpbnRlci1yZWxhdGlvbnNoaXBzIGFyZSBwYXVzZWQsXG4gICAqIHlvdSBjYW4gcGVyZm9ybSBhbnkgbnVtYmVyIG9mIG9wZXJhdGlvbnMgb24gdGhlIG1lbWJlciBVbml0c1xuICAgKiB3aXRob3V0IHRyaWdnZXJpbmcgdGhlIGF1dG9tYXRpYyByZWxhdGlvbnNoaXBzIGxpa2Uge0BsaW5rIEFzeW5jU3lzdGVtQmFzZUNvbmZpZy5jbGVhckVycm9yT25EYXRhfSxcbiAgICoge0BsaW5rIEFzeW5jU3lzdGVtQmFzZUNvbmZpZy5hdXRvVXBkYXRlUGVuZGluZ1ZhbHVlfSwgZXRjLlxuICAgKlxuICAgKiBUaGlzIGFsc28gbWVhbnMgdGhhdCB0aGUgQXN5bmNTeXN0ZW0gc3RvcHMgZW1pdHRpbmcgbmV3IHZhbHVlcy5cbiAgICpcbiAgICogQGNhdGVnb3J5IEN1c3RvbSBBc3luY1N5c3RlbVxuICAgKi9cbiAgcGF1c2VSZWxhdGlvbnNoaXBzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlbGF0aW9uc2hpcHNNYW51YWxseVBhdXNlZCA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnJlbGF0aW9uc2hpcHNNYW51YWxseVBhdXNlZCA9IHRydWU7XG4gICAgdGhpcy51bml0c0VtaXRDb3VudHNCZWZvcmVQYXVzaW5nID0gdGhpcy51bml0c0VtaXRDb3VudHMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUbyByZXN1bWUgaW50ZXItcmVsYXRpb25zaGlwcyBhbW9uZyB0aGUgbWVtYmVyIFVuaXRzLiBBbHNvIHNlZSB7QGxpbmsgcmVsYXRpb25zaGlwc1dvcmtpbmd9LlxuICAgKlxuICAgKiBJdCByZXN0b3JlcyB0aGUgaW50ZXItcmVsYXRpb25zaGlwcyBsaWtlIHtAbGluayBBc3luY1N5c3RlbUJhc2VDb25maWcuY2xlYXJFcnJvck9uRGF0YX0sXG4gICAqIHtAbGluayBBc3luY1N5c3RlbUJhc2VDb25maWcuYXV0b1VwZGF0ZVBlbmRpbmdWYWx1ZX0sIGV0Yy5cbiAgICpcbiAgICogVGhpcyBhbHNvIG1lYW5zIHRoYXQgdGhlIEFzeW5jU3lzdGVtIHN0YXJ0cyBlbWl0dGluZyBuZXcgdmFsdWVzLiBcXFxuICAgKiBBbmQgaWYgYW55IG9mIHRoZSBtZW1iZXIgVW5pdHMgZW1pdHRlZCBhIHZhbHVlIHdoaWxlIHRoZSByZWxhdGlvbnNoaXBzIHdlcmUgcGF1c2VkLFxuICAgKiB0aGUgQXN5bmNTeXN0ZW0gd2lsbCBlbWl0IGEgbmV3IHZhbHVlIGltbWVkaWF0ZWx5IHRvIGJyaW5nIGl0c2VsZiBhbmQgaXRzIHN1YnNjcmliZXJzIGluIHN5bmNcbiAgICogd2l0aCB0aGUgbWVtYmVyIFVuaXRzLlxuICAgKlxuICAgKiBAY2F0ZWdvcnkgQ3VzdG9tIEFzeW5jU3lzdGVtXG4gICAqL1xuICByZXN1bWVSZWxhdGlvbnNoaXBzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlbGF0aW9uc2hpcHNNYW51YWxseVBhdXNlZCA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5yZWxhdGlvbnNoaXBzTWFudWFsbHlQYXVzZWQgPSBmYWxzZTtcbiAgICBpZiAodGhpcy51bml0c0VtaXRDb3VudHNCZWZvcmVQYXVzaW5nLmpvaW4oKSAhPT0gdGhpcy51bml0c0VtaXRDb3VudHMoKS5qb2luKCkpIHtcbiAgICAgIHRoaXMuZW1pdCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcml2YXRlIHVuaXRzRW1pdENvdW50cygpOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIHRoaXMucXVlcnlVbml0LmVtaXRDb3VudCxcbiAgICAgIHRoaXMuZGF0YVVuaXQuZW1pdENvdW50LFxuICAgICAgdGhpcy5lcnJvclVuaXQuZW1pdENvdW50LFxuICAgICAgdGhpcy5wZW5kaW5nVW5pdC5lbWl0Q291bnQsXG4gICAgXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZVJlbGF0aW9uc2hpcHNBbW9uZ01lbWJlclVuaXRzKCkge1xuICAgIHRoaXMucXVlcnlVbml0LmZ1dHVyZSQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLnJlbGF0aW9uc2hpcHNXb3JraW5nKSB7XG4gICAgICAgIHRoaXMuZXhlY3V0ZVF1ZXJ5VW5pdFJlbGF0aW9uc2hpcCgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5kYXRhVW5pdC5mdXR1cmUkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5yZWxhdGlvbnNoaXBzV29ya2luZykge1xuICAgICAgICB0aGlzLmV4ZWN1dGVEYXRhVW5pdFJlbGF0aW9uc2hpcCgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5lcnJvclVuaXQuZnV0dXJlJC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMucmVsYXRpb25zaGlwc1dvcmtpbmcpIHtcbiAgICAgICAgdGhpcy5leGVjdXRlRXJyb3JVbml0UmVsYXRpb25zaGlwKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLnBlbmRpbmdVbml0LmZ1dHVyZSQuc3Vic2NyaWJlKGlzUGVuZGluZyA9PiB7XG4gICAgICBpZiAoIXRoaXMucmVsYXRpb25zaGlwc01hbnVhbGx5UGF1c2VkKSB7XG4gICAgICAgIHRoaXMudG9nZ2xlUXVlcnlVbml0RnJlZXplTWF5YmUoaXNQZW5kaW5nKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnJlbGF0aW9uc2hpcHNXb3JraW5nKSB7XG4gICAgICAgIHRoaXMuZW1pdCgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgZXhlY3V0ZVF1ZXJ5VW5pdFJlbGF0aW9uc2hpcCgpIHtcbiAgICB0aGlzLnJlbGF0aW9uc2hpcHNBdXRvUGF1c2VkID0gdHJ1ZTtcblxuICAgIHRoaXMuYXV0b1VwZGF0ZVBlbmRpbmdWYWx1ZSh0cnVlKTtcblxuICAgIGlmICh0aGlzLmNvbmZpZy5jbGVhckRhdGFPblF1ZXJ5ID09PSB0cnVlKSB7XG4gICAgICB0aGlzLmRhdGFVbml0LmNsZWFyVmFsdWUoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuY29uZmlnLmNsZWFyRXJyb3JPblF1ZXJ5ID09PSB0cnVlKSB7XG4gICAgICB0aGlzLmVycm9yVW5pdC5jbGVhclZhbHVlKCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWxhdGlvbnNoaXBzQXV0b1BhdXNlZCA9IGZhbHNlO1xuICAgIHRoaXMuZW1pdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgZXhlY3V0ZURhdGFVbml0UmVsYXRpb25zaGlwKCkge1xuICAgIHRoaXMucmVsYXRpb25zaGlwc0F1dG9QYXVzZWQgPSB0cnVlO1xuXG4gICAgdGhpcy5hdXRvVXBkYXRlUGVuZGluZ1ZhbHVlKGZhbHNlKTtcblxuICAgIGlmICh0aGlzLmNvbmZpZy5jbGVhckVycm9yT25RdWVyeSAhPT0gdHJ1ZSAmJiB0aGlzLmNvbmZpZy5jbGVhckVycm9yT25EYXRhICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy5lcnJvclVuaXQuY2xlYXJWYWx1ZSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5jb25maWcuY2xlYXJRdWVyeU9uRGF0YSA9PT0gdHJ1ZSkge1xuICAgICAgdGhpcy5xdWVyeVVuaXQuY2xlYXJWYWx1ZSgpO1xuICAgIH1cblxuICAgIHRoaXMucmVsYXRpb25zaGlwc0F1dG9QYXVzZWQgPSBmYWxzZTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcml2YXRlIGV4ZWN1dGVFcnJvclVuaXRSZWxhdGlvbnNoaXAoKSB7XG4gICAgdGhpcy5yZWxhdGlvbnNoaXBzQXV0b1BhdXNlZCA9IHRydWU7XG5cbiAgICB0aGlzLmF1dG9VcGRhdGVQZW5kaW5nVmFsdWUoZmFsc2UpO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLmNsZWFyRGF0YU9uUXVlcnkgIT09IHRydWUgJiYgdGhpcy5jb25maWcuY2xlYXJEYXRhT25FcnJvciA9PT0gdHJ1ZSkge1xuICAgICAgdGhpcy5kYXRhVW5pdC5jbGVhclZhbHVlKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbmZpZy5jbGVhclF1ZXJ5T25FcnJvciA9PT0gdHJ1ZSkge1xuICAgICAgdGhpcy5xdWVyeVVuaXQuY2xlYXJWYWx1ZSgpO1xuICAgIH1cblxuICAgIHRoaXMucmVsYXRpb25zaGlwc0F1dG9QYXVzZWQgPSBmYWxzZTtcbiAgICB0aGlzLmVtaXQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcml2YXRlIHRvZ2dsZVF1ZXJ5VW5pdEZyZWV6ZU1heWJlKGlzUGVuZGluZzogYm9vbGVhbikge1xuICAgIGlmICh0aGlzLmNvbmZpZy5mcmVlemVRdWVyeVdoaWxlUGVuZGluZyA9PT0gdHJ1ZSkge1xuICAgICAgaWYgKGlzUGVuZGluZykge1xuICAgICAgICB0aGlzLnF1ZXJ5VW5pdC5mcmVlemUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucXVlcnlVbml0LnVuZnJlZXplKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgYXV0b1VwZGF0ZVBlbmRpbmdWYWx1ZShpc1BlbmRpbmc6IGJvb2xlYW4pIHtcbiAgICBpZiAodGhpcy5jb25maWcuYXV0b1VwZGF0ZVBlbmRpbmdWYWx1ZSAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMucGVuZGluZ1VuaXQuZGlzcGF0Y2goaXNQZW5kaW5nLCB7YnlwYXNzRGVib3VuY2U6IHRydWV9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsIHBsZWFzZSBkbyBub3QgdXNlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGVtaXQodmFsdWUgPSB0aGlzLmNvbWJpbmVkRW1pdHRlZFZhbHVlcygpKSB7XG4gICAgaWYgKENvbmZpZ3VyYXRpb24uRU5WSVJPTk1FTlQuY2hlY2tJbW11dGFiaWxpdHkgPT09IHRydWUpIHtcbiAgICAgIE9iamVjdC5mcmVlemUodmFsdWUpO1xuICAgIH1cbiAgICBzdXBlci5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcml2YXRlIGNvbWJpbmVkRW1pdHRlZFZhbHVlcygpOiBBc3luY1N5c3RlbVZhbHVlPFF1ZXJ5LCBEYXRhLCBFcnJvcj4ge1xuICAgIC8vIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsXG4gICAgcmV0dXJuIHtcbiAgICAgIHF1ZXJ5OiB0aGlzLnF1ZXJ5VW5pdFsnZW1pdHRlZFZhbHVlJ10sXG4gICAgICBkYXRhOiB0aGlzLmRhdGFVbml0WydlbWl0dGVkVmFsdWUnXSxcbiAgICAgIGVycm9yOiB0aGlzLmVycm9yVW5pdFsnZW1pdHRlZFZhbHVlJ10sXG4gICAgICBwZW5kaW5nOiB0aGlzLnBlbmRpbmdVbml0WydlbWl0dGVkVmFsdWUnXSxcbiAgICB9O1xuICAgIC8vIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgfVxufVxuIl19