@zodiac-ui/ng-observable
Version:
Create powerful reactive components with Angular. AoT compatible and Ivy ready.
243 lines • 18.8 kB
JavaScript
/**
* @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==