UNPKG

@zodiac-ui/ng-observable

Version:

Create powerful reactive components with Angular. AoT compatible and Ivy ready.

243 lines 18.8 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { ChangeDetectorRef, Inject, Injectable, isDevMode, Optional } from "@angular/core"; import { asapScheduler, BehaviorSubject } from "rxjs"; import { Stream } from "./stream"; import { STATE_CHANGE_STRATEGY, StateChangeStrategy } from "./constants"; import { debounceTime } from "rxjs/operators"; import { InvokeSubject } from "./invoke-subject"; /** * State object for bound `valueRef`. State changes mutate the original object in-place and notifies any observers * with a new object reference. * * @see {\@link StateFactory} * * \@usageNotes * * \@publicApi * @template T */ export class State extends BehaviorSubject { /** * Creates a new State `instance`. * * @param {?} valueRef The mutable value object reference to apply state changes to. * @param {?} markForCheck Notifier that schedules change detection to run on the next microtask. */ constructor(valueRef, markForCheck) { super(Object.create(valueRef)); this.valueRef = valueRef; this.next = (/** * @param {?=} partialState * @return {?} */ (partialState) => { this.patchValue(partialState); markForCheck(); }); this.patchValue = (/** * @param {?=} partialState * @return {?} */ (partialState) => { Object.assign(valueRef, partialState); super.next(Object.create(valueRef)); }); } } if (false) { /** * Mutate the state, notify observers and queue change detection. * * \@param partialState A plain object containing values to mutate the existing state with. * @type {?} */ State.prototype.next; /** * * Mutate the state and notify observers without running change detection. * * \@param partialState A plain object containing values to mutate the existing state with. * @type {?} */ State.prototype.patchValue; /** * The value object reference to be mutated. * @type {?} * @private */ State.prototype.valueRef; } /** * Reactive state management for Angular components and directives. * * @see {\@link State} * * \@usageNotes * * Create a `State<T>` instance by passing the component instance as an argument. All mutations to * the internal component state should be handled with this service so that observers can be notified * of changes. * * ```typescript * export interface MyProps { * title: string * } * * export interface MyState extends MyProps { * model: string * } * * \@Component({ * viewProviders: [StateFactory, Stream] // or providers * }) * export class MyComponent implements MyState { * \@Input() * title: string * model: string * * constructor(\@Self() stateFactory: StateFactory<MyState>, \@Self() stream: Stream) { * const state = stateFactory.create(this) * * // Imperative usage * state.next({ * model: "app" * }) * * // Reactive usage * stream(state)(of({ model: "app" })) * } * } * ``` * * ### Connecting `\@Input()` properties * * Changes received from `\@Input()` properties can be mapped onto the state to keep state observers up to date: * * ```ts * \@Component() * export class MyComponent extends NgObservable implements MyState { * \@Input() * value: any * mappedValue: any * * constructor(\@Self() stateFactory: StateFactory<MyState>, \@Self() stream: Stream) { * const state = stateFactory.create(this) * * // assuming 1:1 map between inputs and state * stream(state)(mapInputsToState(this)) * * // map inputs to some other value * stream(state)(mapInputsToState(this).pipe( * map((props) => ({ * mappedValue: props.value * })) * ) * } * } * ``` * * \@publicApi * @template T */ export class StateFactory { /** * Creates an instance of `StateFactory` * * @param {?} strategy The {\@link StateChangeStrategy} to be used. It will wither detach or reattach * the `ChangeDetectorRef` if one is provided. * * @param {?=} cdr The `ChangeDetectorRef` for the current view. * */ constructor(strategy, cdr) { this.stream = new Stream(); this.cdr = cdr; this.strategy = strategy; this.checkNoChanges = isDevMode(); } /** * Creates an instance of {\@link State} bound to the given `valueRef`. Performs change detection when notified * by `markForCheck`. * * @param {?} valueRef The mutable value object reference to apply state changes to. * @return {?} */ create(valueRef) { const { cdr, strategy, stream, checkNoChanges } = this; /** @type {?} */ const markForCheck = new InvokeSubject(); /** @type {?} */ const state = new State(valueRef, markForCheck); /** @type {?} */ const shouldDetach = strategy === StateChangeStrategy.DETACH; if (cdr) { /** @type {?} */ const detectChanges = (/** * @return {?} */ () => { cdr.detectChanges(); if (checkNoChanges) { cdr.checkNoChanges(); } }); if (shouldDetach) { cdr.detach(); } else { cdr.reattach(); } Promise.resolve().then((/** * @return {?} */ () => { if (shouldDetach) { detectChanges(); } stream(detectChanges)(debounceTime(0, asapScheduler)(markForCheck)); })); } return state; } /** * Cleanup when the injector is destroyed * @return {?} */ ngOnDestroy() { this.stream.complete(); } } StateFactory.decorators = [ { type: Injectable } ]; /** @nocollapse */ StateFactory.ctorParameters = () => [ { type: StateChangeStrategy, decorators: [{ type: Inject, args: [STATE_CHANGE_STRATEGY,] }] }, { type: ChangeDetectorRef, decorators: [{ type: Optional }] } ]; if (false) { /** * @type {?} * @private */ StateFactory.prototype.stream; /** * @type {?} * @private */ StateFactory.prototype.strategy; /** * @type {?} * @private */ StateFactory.prototype.cdr; /** * @type {?} * @private */ StateFactory.prototype.checkNoChanges; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Aem9kaWFjLXVpL25nLW9ic2VydmFibGUvIiwic291cmNlcyI6WyJsaWIvc3RhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBYSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDckcsT0FBTyxFQUFFLGFBQWEsRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUE7QUFDckQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUNqQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDeEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQzdDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTs7Ozs7Ozs7Ozs7O0FBWWhELE1BQU0sT0FBTyxLQUF3QixTQUFRLGVBQWtCOzs7Ozs7O0lBMkIzRCxZQUFZLFFBQVcsRUFBRSxZQUFzQjtRQUMzQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFBO1FBRTlCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFBO1FBRXhCLElBQUksQ0FBQyxJQUFJOzs7O1FBQUcsQ0FBQyxZQUF5QixFQUFFLEVBQUU7WUFDdEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQTtZQUM3QixZQUFZLEVBQUUsQ0FBQTtRQUNsQixDQUFDLENBQUEsQ0FBQTtRQUVELElBQUksQ0FBQyxVQUFVOzs7O1FBQUcsQ0FBQyxZQUF5QixFQUFFLEVBQUU7WUFDNUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDLENBQUE7WUFDckMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUE7UUFDdkMsQ0FBQyxDQUFBLENBQUE7SUFDTCxDQUFDO0NBQ0o7Ozs7Ozs7O0lBcENHLHFCQUF5RDs7Ozs7Ozs7SUFRekQsMkJBQStEOzs7Ozs7SUFLL0QseUJBQTRCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWlHaEMsTUFBTSxPQUFPLFlBQVk7Ozs7Ozs7Ozs7SUFlckIsWUFDbUMsUUFBNkIsRUFDaEQsR0FBdUI7UUFFbkMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFBO1FBQzFCLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFBO1FBQ2QsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUE7UUFDeEIsSUFBSSxDQUFDLGNBQWMsR0FBRyxTQUFTLEVBQUUsQ0FBQTtJQUNyQyxDQUFDOzs7Ozs7OztJQVFNLE1BQU0sQ0FBQyxRQUFXO2NBQ2YsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsR0FBRyxJQUFJOztjQUNoRCxZQUFZLEdBQUcsSUFBSSxhQUFhLEVBQU87O2NBQ3ZDLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDOztjQUN6QyxZQUFZLEdBQUcsUUFBUSxLQUFLLG1CQUFtQixDQUFDLE1BQU07UUFFNUQsSUFBSSxHQUFHLEVBQUU7O2tCQUNDLGFBQWE7OztZQUFHLEdBQUcsRUFBRTtnQkFDdkIsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFBO2dCQUNuQixJQUFJLGNBQWMsRUFBRTtvQkFDaEIsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFBO2lCQUN2QjtZQUNMLENBQUMsQ0FBQTtZQUNELElBQUksWUFBWSxFQUFFO2dCQUNkLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQTthQUNmO2lCQUNJO2dCQUNELEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQTthQUNqQjtZQUNELE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJOzs7WUFBQyxHQUFHLEVBQUU7Z0JBQ3hCLElBQUksWUFBWSxFQUFFO29CQUNkLGFBQWEsRUFBRSxDQUFBO2lCQUNsQjtnQkFDRCxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFBO1lBQ3ZFLENBQUMsRUFBQyxDQUFBO1NBQ0w7UUFFRCxPQUFPLEtBQUssQ0FBQTtJQUNoQixDQUFDOzs7OztJQUtNLFdBQVc7UUFDZCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFBO0lBQzFCLENBQUM7OztZQW5FSixVQUFVOzs7O1lBaklxQixtQkFBbUIsdUJBa0oxQyxNQUFNLFNBQUMscUJBQXFCO1lBcko1QixpQkFBaUIsdUJBc0pqQixRQUFROzs7Ozs7O0lBaEJiLDhCQUErQjs7Ozs7SUFDL0IsZ0NBQThDOzs7OztJQUM5QywyQkFBd0M7Ozs7O0lBQ3hDLHNDQUF3QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdG9yUmVmLCBJbmplY3QsIEluamVjdGFibGUsIGlzRGV2TW9kZSwgT25EZXN0cm95LCBPcHRpb25hbCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCJcclxuaW1wb3J0IHsgYXNhcFNjaGVkdWxlciwgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSBcInJ4anNcIlxyXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tIFwiLi9zdHJlYW1cIlxyXG5pbXBvcnQgeyBTVEFURV9DSEFOR0VfU1RSQVRFR1ksIFN0YXRlQ2hhbmdlU3RyYXRlZ3kgfSBmcm9tIFwiLi9jb25zdGFudHNcIlxyXG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIlxyXG5pbXBvcnQgeyBJbnZva2VTdWJqZWN0IH0gZnJvbSBcIi4vaW52b2tlLXN1YmplY3RcIlxyXG5cclxuLyoqXHJcbiAqIFN0YXRlIG9iamVjdCBmb3IgYm91bmQgYHZhbHVlUmVmYC4gU3RhdGUgY2hhbmdlcyBtdXRhdGUgdGhlIG9yaWdpbmFsIG9iamVjdCBpbi1wbGFjZSBhbmQgbm90aWZpZXMgYW55IG9ic2VydmVyc1xyXG4gKiB3aXRoIGEgbmV3IG9iamVjdCByZWZlcmVuY2UuXHJcbiAqXHJcbiAqIEBzZWUge0BsaW5rIFN0YXRlRmFjdG9yeX1cclxuICpcclxuICogQHVzYWdlTm90ZXNcclxuICpcclxuICogQHB1YmxpY0FwaVxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFN0YXRlPFQgZXh0ZW5kcyBvYmplY3Q+IGV4dGVuZHMgQmVoYXZpb3JTdWJqZWN0PFQ+IHtcclxuICAgIC8qKlxyXG4gICAgICogTXV0YXRlIHRoZSBzdGF0ZSwgbm90aWZ5IG9ic2VydmVycyBhbmQgcXVldWUgY2hhbmdlIGRldGVjdGlvbi5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gcGFydGlhbFN0YXRlIEEgcGxhaW4gb2JqZWN0IGNvbnRhaW5pbmcgdmFsdWVzIHRvIG11dGF0ZSB0aGUgZXhpc3Rpbmcgc3RhdGUgd2l0aC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG5leHQ6IChwYXJ0aWFsU3RhdGU/OiBQYXJ0aWFsPFQ+KSA9PiB2b2lkXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKlxyXG4gICAgICogTXV0YXRlIHRoZSBzdGF0ZSBhbmQgbm90aWZ5IG9ic2VydmVycyB3aXRob3V0IHJ1bm5pbmcgY2hhbmdlIGRldGVjdGlvbi5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gcGFydGlhbFN0YXRlIEEgcGxhaW4gb2JqZWN0IGNvbnRhaW5pbmcgdmFsdWVzIHRvIG11dGF0ZSB0aGUgZXhpc3Rpbmcgc3RhdGUgd2l0aC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IHBhdGNoVmFsdWU6IChwYXJ0aWFsU3RhdGU/OiBQYXJ0aWFsPFQ+KSA9PiB2b2lkXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgdmFsdWUgb2JqZWN0IHJlZmVyZW5jZSB0byBiZSBtdXRhdGVkLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHZhbHVlUmVmOiBUXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGEgbmV3IFN0YXRlIGBpbnN0YW5jZWAuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHZhbHVlUmVmIFRoZSBtdXRhYmxlIHZhbHVlIG9iamVjdCByZWZlcmVuY2UgdG8gYXBwbHkgc3RhdGUgY2hhbmdlcyB0by5cclxuICAgICAqIEBwYXJhbSBtYXJrRm9yQ2hlY2sgTm90aWZpZXIgdGhhdCBzY2hlZHVsZXMgY2hhbmdlIGRldGVjdGlvbiB0byBydW4gb24gdGhlIG5leHQgbWljcm90YXNrLlxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcih2YWx1ZVJlZjogVCwgbWFya0ZvckNoZWNrOiBGdW5jdGlvbikge1xyXG4gICAgICAgIHN1cGVyKE9iamVjdC5jcmVhdGUodmFsdWVSZWYpKVxyXG5cclxuICAgICAgICB0aGlzLnZhbHVlUmVmID0gdmFsdWVSZWZcclxuXHJcbiAgICAgICAgdGhpcy5uZXh0ID0gKHBhcnRpYWxTdGF0ZT86IFBhcnRpYWw8VD4pID0+IHtcclxuICAgICAgICAgICAgdGhpcy5wYXRjaFZhbHVlKHBhcnRpYWxTdGF0ZSlcclxuICAgICAgICAgICAgbWFya0ZvckNoZWNrKClcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMucGF0Y2hWYWx1ZSA9IChwYXJ0aWFsU3RhdGU/OiBQYXJ0aWFsPFQ+KSA9PiB7XHJcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odmFsdWVSZWYsIHBhcnRpYWxTdGF0ZSlcclxuICAgICAgICAgICAgc3VwZXIubmV4dChPYmplY3QuY3JlYXRlKHZhbHVlUmVmKSlcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWFjdGl2ZSBzdGF0ZSBtYW5hZ2VtZW50IGZvciBBbmd1bGFyIGNvbXBvbmVudHMgYW5kIGRpcmVjdGl2ZXMuXHJcbiAqXHJcbiAqIEBzZWUge0BsaW5rIFN0YXRlfVxyXG4gKlxyXG4gKiBAdXNhZ2VOb3Rlc1xyXG4gKlxyXG4gKiBDcmVhdGUgYSBgU3RhdGU8VD5gIGluc3RhbmNlIGJ5IHBhc3NpbmcgdGhlIGNvbXBvbmVudCBpbnN0YW5jZSBhcyBhbiBhcmd1bWVudC4gQWxsIG11dGF0aW9ucyB0b1xyXG4gKiB0aGUgaW50ZXJuYWwgY29tcG9uZW50IHN0YXRlIHNob3VsZCBiZSBoYW5kbGVkIHdpdGggdGhpcyBzZXJ2aWNlIHNvIHRoYXQgb2JzZXJ2ZXJzIGNhbiBiZSBub3RpZmllZFxyXG4gKiBvZiBjaGFuZ2VzLlxyXG4gKlxyXG4gKiBgYGB0eXBlc2NyaXB0XHJcbiAqIGV4cG9ydCBpbnRlcmZhY2UgTXlQcm9wcyB7XHJcbiAqICAgICB0aXRsZTogc3RyaW5nXHJcbiAqIH1cclxuICpcclxuICogZXhwb3J0IGludGVyZmFjZSBNeVN0YXRlIGV4dGVuZHMgTXlQcm9wcyB7XHJcbiAqICAgICBtb2RlbDogc3RyaW5nXHJcbiAqIH1cclxuICpcclxuICogQENvbXBvbmVudCh7XHJcbiAqICAgICB2aWV3UHJvdmlkZXJzOiBbU3RhdGVGYWN0b3J5LCBTdHJlYW1dIC8vIG9yIHByb3ZpZGVyc1xyXG4gKiB9KVxyXG4gKiBleHBvcnQgY2xhc3MgTXlDb21wb25lbnQgaW1wbGVtZW50cyBNeVN0YXRlIHtcclxuICogICAgIEBJbnB1dCgpXHJcbiAqICAgICB0aXRsZTogc3RyaW5nXHJcbiAqICAgICBtb2RlbDogc3RyaW5nXHJcbiAqXHJcbiAqICAgICBjb25zdHJ1Y3RvcihAU2VsZigpIHN0YXRlRmFjdG9yeTogU3RhdGVGYWN0b3J5PE15U3RhdGU+LCBAU2VsZigpIHN0cmVhbTogU3RyZWFtKSB7XHJcbiAqICAgICAgICAgY29uc3Qgc3RhdGUgPSBzdGF0ZUZhY3RvcnkuY3JlYXRlKHRoaXMpXHJcbiAqXHJcbiAqICAgICAgICAgLy8gSW1wZXJhdGl2ZSB1c2FnZVxyXG4gKiAgICAgICAgIHN0YXRlLm5leHQoe1xyXG4gKiAgICAgICAgICAgICBtb2RlbDogXCJhcHBcIlxyXG4gKiAgICAgICAgIH0pXHJcbiAqXHJcbiAqICAgICAgICAgLy8gUmVhY3RpdmUgdXNhZ2VcclxuICogICAgICAgICBzdHJlYW0oc3RhdGUpKG9mKHsgbW9kZWw6IFwiYXBwXCIgfSkpXHJcbiAqICAgICB9XHJcbiAqIH1cclxuICogYGBgXHJcbiAqXHJcbiAqICMjIyBDb25uZWN0aW5nIGBASW5wdXQoKWAgcHJvcGVydGllc1xyXG4gKlxyXG4gKiBDaGFuZ2VzIHJlY2VpdmVkIGZyb20gYEBJbnB1dCgpYCBwcm9wZXJ0aWVzIGNhbiBiZSBtYXBwZWQgb250byB0aGUgc3RhdGUgdG8ga2VlcCBzdGF0ZSBvYnNlcnZlcnMgdXAgdG8gZGF0ZTpcclxuICpcclxuICogYGBgdHNcclxuICogQENvbXBvbmVudCgpXHJcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbXBvbmVudCBleHRlbmRzIE5nT2JzZXJ2YWJsZSBpbXBsZW1lbnRzIE15U3RhdGUge1xyXG4gKiAgICAgQElucHV0KClcclxuICogICAgIHZhbHVlOiBhbnlcclxuICogICAgIG1hcHBlZFZhbHVlOiBhbnlcclxuICpcclxuICogICAgIGNvbnN0cnVjdG9yKEBTZWxmKCkgc3RhdGVGYWN0b3J5OiBTdGF0ZUZhY3Rvcnk8TXlTdGF0ZT4sIEBTZWxmKCkgc3RyZWFtOiBTdHJlYW0pIHtcclxuICogICAgICAgICBjb25zdCBzdGF0ZSA9IHN0YXRlRmFjdG9yeS5jcmVhdGUodGhpcylcclxuICpcclxuICogICAgICAgICAvLyBhc3N1bWluZyAxOjEgbWFwIGJldHdlZW4gaW5wdXRzIGFuZCBzdGF0ZVxyXG4gKiAgICAgICAgIHN0cmVhbShzdGF0ZSkobWFwSW5wdXRzVG9TdGF0ZSh0aGlzKSlcclxuICpcclxuICogICAgICAgICAvLyBtYXAgaW5wdXRzIHRvIHNvbWUgb3RoZXIgdmFsdWVcclxuICogICAgICAgICBzdHJlYW0oc3RhdGUpKG1hcElucHV0c1RvU3RhdGUodGhpcykucGlwZShcclxuICogICAgICAgICAgICAgbWFwKChwcm9wcykgPT4gKHtcclxuICogICAgICAgICAgICAgICAgIG1hcHBlZFZhbHVlOiBwcm9wcy52YWx1ZVxyXG4gKiAgICAgICAgICAgICB9KSlcclxuICogICAgICAgICApXHJcbiAqICAgICB9XHJcbiAqIH1cclxuICogYGBgXHJcbiAqXHJcbiAqIEBwdWJsaWNBcGlcclxuICovXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIFN0YXRlRmFjdG9yeTxUIGV4dGVuZHMgT2JqZWN0PiBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHN0cmVhbTogU3RyZWFtXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHN0cmF0ZWd5OiBTdGF0ZUNoYW5nZVN0cmF0ZWd5XHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNkcj86IENoYW5nZURldGVjdG9yUmVmXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNoZWNrTm9DaGFuZ2VzOiBib29sZWFuXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIGBTdGF0ZUZhY3RvcnlgXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHN0cmF0ZWd5IFRoZSB7QGxpbmsgU3RhdGVDaGFuZ2VTdHJhdGVneX0gdG8gYmUgdXNlZC4gSXQgd2lsbCB3aXRoZXIgZGV0YWNoIG9yIHJlYXR0YWNoXHJcbiAgICAgKiB0aGUgYENoYW5nZURldGVjdG9yUmVmYCBpZiBvbmUgaXMgcHJvdmlkZWQuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGNkciBUaGUgYENoYW5nZURldGVjdG9yUmVmYCBmb3IgdGhlIGN1cnJlbnQgdmlldy5cclxuICAgICAqXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIEBJbmplY3QoU1RBVEVfQ0hBTkdFX1NUUkFURUdZKSBzdHJhdGVneTogU3RhdGVDaGFuZ2VTdHJhdGVneSxcclxuICAgICAgICBAT3B0aW9uYWwoKSBjZHI/OiBDaGFuZ2VEZXRlY3RvclJlZixcclxuICAgICkge1xyXG4gICAgICAgIHRoaXMuc3RyZWFtID0gbmV3IFN0cmVhbSgpXHJcbiAgICAgICAgdGhpcy5jZHIgPSBjZHJcclxuICAgICAgICB0aGlzLnN0cmF0ZWd5ID0gc3RyYXRlZ3lcclxuICAgICAgICB0aGlzLmNoZWNrTm9DaGFuZ2VzID0gaXNEZXZNb2RlKClcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2Yge0BsaW5rIFN0YXRlfSBib3VuZCB0byB0aGUgZ2l2ZW4gYHZhbHVlUmVmYC4gUGVyZm9ybXMgY2hhbmdlIGRldGVjdGlvbiB3aGVuIG5vdGlmaWVkXHJcbiAgICAgKiBieSBgbWFya0ZvckNoZWNrYC5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gdmFsdWVSZWYgVGhlIG11dGFibGUgdmFsdWUgb2JqZWN0IHJlZmVyZW5jZSB0byBhcHBseSBzdGF0ZSBjaGFuZ2VzIHRvLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgY3JlYXRlKHZhbHVlUmVmOiBUKTogU3RhdGU8VD4ge1xyXG4gICAgICAgIGNvbnN0IHsgY2RyLCBzdHJhdGVneSwgc3RyZWFtLCBjaGVja05vQ2hhbmdlcyB9ID0gdGhpc1xyXG4gICAgICAgIGNvbnN0IG1hcmtGb3JDaGVjayA9IG5ldyBJbnZva2VTdWJqZWN0PGFueT4oKVxyXG4gICAgICAgIGNvbnN0IHN0YXRlID0gbmV3IFN0YXRlKHZhbHVlUmVmLCBtYXJrRm9yQ2hlY2spXHJcbiAgICAgICAgY29uc3Qgc2hvdWxkRGV0YWNoID0gc3RyYXRlZ3kgPT09IFN0YXRlQ2hhbmdlU3RyYXRlZ3kuREVUQUNIXHJcblxyXG4gICAgICAgIGlmIChjZHIpIHtcclxuICAgICAgICAgICAgY29uc3QgZGV0ZWN0Q2hhbmdlcyA9ICgpID0+IHtcclxuICAgICAgICAgICAgICAgIGNkci5kZXRlY3RDaGFuZ2VzKClcclxuICAgICAgICAgICAgICAgIGlmIChjaGVja05vQ2hhbmdlcykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNkci5jaGVja05vQ2hhbmdlcygpXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHNob3VsZERldGFjaCkge1xyXG4gICAgICAgICAgICAgICAgY2RyLmRldGFjaCgpXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBjZHIucmVhdHRhY2goKVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKHNob3VsZERldGFjaCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGRldGVjdENoYW5nZXMoKVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgc3RyZWFtKGRldGVjdENoYW5nZXMpKGRlYm91bmNlVGltZSgwLCBhc2FwU2NoZWR1bGVyKShtYXJrRm9yQ2hlY2spKVxyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHN0YXRlXHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDbGVhbnVwIHdoZW4gdGhlIGluamVjdG9yIGlzIGRlc3Ryb3llZFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKSB7XHJcbiAgICAgICAgdGhpcy5zdHJlYW0uY29tcGxldGUoKVxyXG4gICAgfVxyXG59XHJcbiJdfQ==