UNPKG

ngx-smart-modal

Version:

Smart modal handler to manage modals and data everywhere in Angular apps.

471 lines 54.8 kB
import { ApplicationRef, Inject, Injectable, PLATFORM_ID, TemplateRef, Type } from '@angular/core';
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
import { NgxSmartModalComponent } from '../components/ngx-smart-modal.component';
import { NgxSmartModalConfig } from '../config/ngx-smart-modal.config';
import * as i0 from "@angular/core";
import * as i1 from "./ngx-smart-modal-stack.service";
export class NgxSmartModalService {
    constructor(_injector, _modalStack, _document, _platformId) {
        this._injector = _injector;
        this._modalStack = _modalStack;
        this._document = _document;
        this._platformId = _platformId;
        /**
         * Close the latest opened modal if escape key event is emitted
         * @param event The Keyboard Event
         */
        this._escapeKeyboardEvent = (event) => {
            if (event.key === 'Escape') {
                try {
                    const modal = this.getTopOpenedModal();
                    if (!modal.escapable) {
                        return false;
                    }
                    modal.onEscape.emit(modal);
                    this.closeLatestModal();
                    return true;
                }
                catch (e) {
                    return false;
                }
            }
            return false;
        };
        /**
         * While modal is open, the focus stay on it
         * @param event The Keyboar dEvent
         */
        this._trapFocusModal = (event) => {
            if (event.key === 'Tab') {
                try {
                    const modal = this.getTopOpenedModal();
                    if (!modal.nsmDialog.first.nativeElement.contains(document.activeElement)) {
                        event.preventDefault();
                        event.stopPropagation();
                        modal.nsmDialog.first.nativeElement.focus();
                    }
                    return true;
                }
                catch (e) {
                    return false;
                }
            }
            return false;
        };
        this._addEvents();
    }
    /**
     * Add a new modal instance. This step is essential and allows to retrieve any modal at any time.
     * It stores an object that contains the given modal identifier and the modal itself directly in the `modalStack`.
     *
     * @param modalInstance The object that contains the given modal identifier and the modal itself.
     * @param force Optional parameter that forces the overriding of modal instance if it already exists.
     * @returns nothing special.
     */
    addModal(modalInstance, force) {
        this._modalStack.addModal(modalInstance, force);
    }
    /**
     * Retrieve a modal instance by its identifier.
     *
     * @param id The modal identifier used at creation time.
     */
    getModal(id) {
        return this._modalStack.getModal(id);
    }
    /**
     * Alias of `getModal` to retrieve a modal instance by its identifier.
     *
     * @param id The modal identifier used at creation time.
     */
    get(id) {
        return this.getModal(id);
    }
    /**
     * Open a given modal
     *
     * @param id The modal identifier used at creation time.
     * @param force Tell the modal to open top of all other opened modals
     */
    open(id, force = false) {
        return this._openModal(this.get(id), force);
    }
    /**
     * Close a given modal
     *
     * @param id The modal identifier used at creation time.
     */
    close(id) {
        return this._closeModal(this.get(id));
    }
    /**
     * Close all opened modals
     */
    closeAll() {
        this.getOpenedModals().forEach((instance) => {
            this._closeModal(instance.modal);
        });
    }
    /**
     * Toggles a given modal
     * If the retrieved modal is opened it closes it, else it opens it.
     *
     * @param id The modal identifier used at creation time.
     * @param force Tell the modal to open top of all other opened modals
     */
    toggle(id, force = false) {
        return this._toggleModal(this.get(id), force);
    }
    /**
     * Retrieve all the created modals.
     *
     * @returns an array that contains all modal instances.
     */
    getModalStack() {
        return this._modalStack.getModalStack();
    }
    /**
     * Retrieve all the opened modals. It looks for all modal instances with their `visible` property set to `true`.
     *
     * @returns an array that contains all the opened modals.
     */
    getOpenedModals() {
        return this._modalStack.getOpenedModals();
    }
    /**
     * Retrieve the opened modal with highest z-index.
     *
     * @returns the opened modal with highest z-index.
     */
    getTopOpenedModal() {
        return this._modalStack.getTopOpenedModal();
    }
    /**
     * Get the higher `z-index` value between all the modal instances. It iterates over the `ModalStack` array and
     * calculates a higher value (it takes the highest index value between all the modal instances and adds 1).
     * Use it to make a modal appear foreground.
     *
     * @returns a higher index from all the existing modal instances.
     */
    getHigherIndex() {
        return this._modalStack.getHigherIndex();
    }
    /**
     * It gives the number of modal instances. It's helpful to know if the modal stack is empty or not.
     *
     * @returns the number of modal instances.
     */
    getModalStackCount() {
        return this._modalStack.getModalStackCount();
    }
    /**
     * Remove a modal instance from the modal stack.
     *
     * @param id The modal identifier.
     * @returns the removed modal instance.
     */
    removeModal(id) {
        const modalInstance = this._modalStack.removeModal(id);
        if (modalInstance) {
            this._destroyModal(modalInstance.modal);
        }
    }
    /**
     * Associate data to an identified modal. If the modal isn't already associated to some data, it creates a new
     * entry in the `modalData` array with its `id` and the given `data`. If the modal already has data, it rewrites
     * them with the new ones. Finally if no modal found it returns an error message in the console and false value
     * as method output.
     *
     * @param data The data you want to associate to the modal.
     * @param id The modal identifier.
     * @param force If true, overrides the previous stored data if there was.
     * @returns true if the given modal exists and the process has been tried, either false.
     */
    setModalData(data, id, force) {
        const modal = this.get(id);
        if (modal) {
            modal.setData(data, force);
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * Retrieve modal data by its identifier.
     *
     * @param id The modal identifier used at creation time.
     * @returns the associated modal data.
     */
    getModalData(id) {
        const modal = this.get(id);
        if (modal) {
            return modal.getData();
        }
        return null;
    }
    /**
     * Reset the data attached to a given modal.
     *
     * @param id The modal identifier used at creation time.
     * @returns the removed data or false if modal doesn't exist.
     */
    resetModalData(id) {
        if (this._modalStack.getModalStack().find((o) => o.id === id)) {
            const removed = this.getModal(id).getData();
            this.getModal(id).removeData();
            return removed;
        }
        else {
            return false;
        }
    }
    /**
     * Close the latest opened modal
     */
    closeLatestModal() {
        this.getTopOpenedModal().close();
    }
    /**
     * Create dynamic NgxSmartModalComponent
     * @param vcr A ViewContainerRef reference
     * @param id The modal identifier used at creation time
     * @param content The modal content (string, templateRef or Component)
     * @param options Any NgxSmartModalComponent available options
     */
    create(id, content, vcr, options = {}) {
        try {
            return this.getModal(id);
        }
        catch (e) {
            const ngContent = this._resolveNgContent(content);
            const componentRef = vcr.createComponent(NgxSmartModalComponent, { injector: this._injector, projectableNodes: ngContent });
            if (content instanceof Type) {
                componentRef.instance.contentComponent = content;
            }
            componentRef.instance.identifier = id;
            componentRef.instance.createFrom = 'service';
            if (typeof options.closable === 'boolean') {
                componentRef.instance.closable = options.closable;
            }
            if (typeof options.escapable === 'boolean') {
                componentRef.instance.escapable = options.escapable;
            }
            if (typeof options.dismissable === 'boolean') {
                componentRef.instance.dismissable = options.dismissable;
            }
            if (typeof options.customClass === 'string') {
                componentRef.instance.customClass = options.customClass;
            }
            if (typeof options.backdrop === 'boolean') {
                componentRef.instance.backdrop = options.backdrop;
            }
            if (typeof options.force === 'boolean') {
                componentRef.instance.force = options.force;
            }
            if (typeof options.hideDelay === 'number') {
                componentRef.instance.hideDelay = options.hideDelay;
            }
            if (typeof options.autostart === 'boolean') {
                componentRef.instance.autostart = options.autostart;
            }
            if (typeof options.target === 'string') {
                componentRef.instance.target = options.target;
            }
            if (typeof options.ariaLabel === 'string') {
                componentRef.instance.ariaLabel = options.ariaLabel;
            }
            if (typeof options.ariaLabelledBy === 'string') {
                componentRef.instance.ariaLabelledBy = options.ariaLabelledBy;
            }
            if (typeof options.ariaDescribedBy === 'string') {
                componentRef.instance.ariaDescribedBy = options.ariaDescribedBy;
            }
            if (typeof options.refocus === 'boolean') {
                componentRef.instance.refocus = options.refocus;
            }
            const domElem = componentRef.hostView.rootNodes[0];
            this._document.body.appendChild(domElem);
            return componentRef.instance;
        }
    }
    _addEvents() {
        if (!this.isBrowser) {
            return false;
        }
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'create', ((e) => {
            this._initModal(e.detail.instance);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'delete', ((e) => {
            this._deleteModal(e.detail.instance);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'open', ((e) => {
            this._openModal(e.detail.instance.modal, e.detail.extraData.top);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'toggle', ((e) => {
            this._toggleModal(e.detail.instance.modal, e.detail.extraData.top);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'close', ((e) => {
            this._closeModal(e.detail.instance.modal);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'dismiss', ((e) => {
            this._dismissModal(e.detail.instance.modal);
        }));
        window.addEventListener('keyup', this._escapeKeyboardEvent);
        return true;
    }
    _initModal(modalInstance) {
        modalInstance.modal.layerPosition += this.getModalStackCount();
        this.addModal(modalInstance, modalInstance.modal.force);
        if (modalInstance.modal.autostart) {
            this.open(modalInstance.id);
        }
    }
    _openModal(modal, top) {
        if (modal.visible) {
            return false;
        }
        this.lastElementFocused = document.activeElement;
        if (modal.escapable) {
            window.addEventListener('keyup', this._escapeKeyboardEvent);
        }
        if (modal.backdrop) {
            window.addEventListener('keydown', this._trapFocusModal);
        }
        if (top) {
            modal.layerPosition = this.getHigherIndex();
        }
        modal.addBodyClass();
        modal.overlayVisible = true;
        modal.visible = true;
        modal.onOpen.emit(modal);
        modal.markForCheck();
        setTimeout(() => {
            modal.openedClass = true;
            if (modal.target) {
                modal.targetPlacement();
            }
            modal.nsmDialog.first.nativeElement.setAttribute('role', 'dialog');
            modal.nsmDialog.first.nativeElement.setAttribute('tabIndex', '-1');
            modal.nsmDialog.first.nativeElement.setAttribute('aria-modal', 'true');
            modal.nsmDialog.first.nativeElement.focus();
            modal.markForCheck();
            modal.onOpenFinished.emit(modal);
        });
        return true;
    }
    _toggleModal(modal, top) {
        if (modal.visible) {
            return this._closeModal(modal);
        }
        else {
            return this._openModal(modal, top);
        }
    }
    _closeModal(modal) {
        if (!modal.openedClass) {
            return false;
        }
        modal.openedClass = false;
        modal.onClose.emit(modal);
        modal.onAnyCloseEvent.emit(modal);
        if (this.getOpenedModals().length < 2) {
            modal.removeBodyClass();
            window.removeEventListener('keyup', this._escapeKeyboardEvent);
            window.removeEventListener('keydown', this._trapFocusModal);
        }
        setTimeout(() => {
            modal.visibleChange.emit(modal.visible);
            modal.visible = false;
            modal.overlayVisible = false;
            modal.nsmDialog.first.nativeElement.removeAttribute('tabIndex');
            modal.markForCheck();
            modal.onCloseFinished.emit(modal);
            modal.onAnyCloseEventFinished.emit(modal);
            if (modal.refocus) {
                this.lastElementFocused.focus();
            }
        }, modal.hideDelay);
        return true;
    }
    _dismissModal(modal) {
        if (!modal.openedClass) {
            return false;
        }
        modal.openedClass = false;
        modal.onDismiss.emit(modal);
        modal.onAnyCloseEvent.emit(modal);
        if (this.getOpenedModals().length < 2) {
            modal.removeBodyClass();
        }
        setTimeout(() => {
            modal.visible = false;
            modal.visibleChange.emit(modal.visible);
            modal.overlayVisible = false;
            modal.markForCheck();
            modal.onDismissFinished.emit(modal);
            modal.onAnyCloseEventFinished.emit(modal);
        }, modal.hideDelay);
        return true;
    }
    _deleteModal(modalInstance) {
        this.removeModal(modalInstance.id);
        if (!this.getModalStack().length) {
            modalInstance.modal.removeBodyClass();
        }
    }
    /**
     * Resolve content according to the types
     * @param content The modal content (string, templateRef or Component)
     */
    _resolveNgContent(content) {
        if (typeof content === 'string') {
            const element = this._document.createTextNode(content);
            return [[element]];
        }
        if (content instanceof TemplateRef) {
            const viewRef = content.createEmbeddedView(null);
            this.appRef.attachView(viewRef);
            return [viewRef.rootNodes];
        }
        return [];
    }
    /**
     * Is current platform browser
     */
    get isBrowser() {
        return isPlatformBrowser(this._platformId);
    }
    /**
     * Remove dynamically created modal from DOM
     */
    _destroyModal(modal) {
        // Prevent destruction of the inline modals
        if (modal.createFrom !== 'service') {
            return;
        }
        this._document.body.removeChild(modal.elementRef.nativeElement);
    }
    /**
     * getter function to avoid circular dependency error
     * @returns ApplicationRef instance
     * */
    get appRef() {
        return this._injector.get(ApplicationRef);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.10", ngImport: i0, type: NgxSmartModalService, deps: [{ token: i0.Injector }, { token: i1.NgxSmartModalStackService }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.10", ngImport: i0, type: NgxSmartModalService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.10", ngImport: i0, type: NgxSmartModalService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i1.NgxSmartModalStackService }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DOCUMENT]
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [PLATFORM_ID]
                }] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXNtYXJ0LW1vZGFsLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc21hcnQtbW9kYWwvc3JjL2xpYi9zZXJ2aWNlcy9uZ3gtc21hcnQtbW9kYWwuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFtQixNQUFNLEVBQUUsVUFBVSxFQUFZLFdBQVcsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFvQixNQUFNLGVBQWUsQ0FBQztBQUNoSixPQUFPLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDakYsT0FBTyxFQUF5QixtQkFBbUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDOzs7QUFTOUYsTUFBTSxPQUFPLG9CQUFvQjtJQUcvQixZQUNVLFNBQW1CLEVBQ25CLFdBQXNDLEVBQ3BCLFNBQWMsRUFDWCxXQUFnQjtRQUhyQyxjQUFTLEdBQVQsU0FBUyxDQUFVO1FBQ25CLGdCQUFXLEdBQVgsV0FBVyxDQUEyQjtRQUNwQixjQUFTLEdBQVQsU0FBUyxDQUFLO1FBQ1gsZ0JBQVcsR0FBWCxXQUFXLENBQUs7UUE4Wi9DOzs7V0FHRztRQUNLLHlCQUFvQixHQUFHLENBQUMsS0FBb0IsRUFBRSxFQUFFO1lBQ3RELElBQUksS0FBSyxDQUFDLEdBQUcsS0FBSyxRQUFRLEVBQUU7Z0JBQzFCLElBQUk7b0JBQ0YsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7b0JBRXZDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFO3dCQUNwQixPQUFPLEtBQUssQ0FBQztxQkFDZDtvQkFFRCxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDM0IsSUFBSSxDQUFDLGdCQUFnQixF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bGljYXRpb25SZWYsIEVtYmVkZGVkVmlld1JlZiwgSW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3RvciwgUExBVEZPUk1fSUQsIFRlbXBsYXRlUmVmLCBUeXBlLCBWaWV3Q29udGFpbmVyUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBET0NVTUVOVCwgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgTmd4U21hcnRNb2RhbENvbXBvbmVudCB9IGZyb20gJy4uL2NvbXBvbmVudHMvbmd4LXNtYXJ0LW1vZGFsLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJTmd4U21hcnRNb2RhbE9wdGlvbnMsIE5neFNtYXJ0TW9kYWxDb25maWcgfSBmcm9tICcuLi9jb25maWcvbmd4LXNtYXJ0LW1vZGFsLmNvbmZpZyc7XG5pbXBvcnQgeyBOZ3hTbWFydE1vZGFsU3RhY2tTZXJ2aWNlIH0gZnJvbSAnLi9uZ3gtc21hcnQtbW9kYWwtc3RhY2suc2VydmljZSc7XG5pbXBvcnQgeyBNb2RhbEluc3RhbmNlIH0gZnJvbSAnLi9tb2RhbC1pbnN0YW5jZSc7XG5cbmV4cG9ydCB0eXBlIENvbnRlbnQ8VD4gPSBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxUPiB8IFR5cGU8VD47XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIE5neFNtYXJ0TW9kYWxTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBsYXN0RWxlbWVudEZvY3VzZWQ6IGFueTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9pbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJpdmF0ZSBfbW9kYWxTdGFjazogTmd4U21hcnRNb2RhbFN0YWNrU2VydmljZSxcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIF9kb2N1bWVudDogYW55LFxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgX3BsYXRmb3JtSWQ6IGFueVxuICApIHtcbiAgICB0aGlzLl9hZGRFdmVudHMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBuZXcgbW9kYWwgaW5zdGFuY2UuIFRoaXMgc3RlcCBpcyBlc3NlbnRpYWwgYW5kIGFsbG93cyB0byByZXRyaWV2ZSBhbnkgbW9kYWwgYXQgYW55IHRpbWUuXG4gICAqIEl0IHN0b3JlcyBhbiBvYmplY3QgdGhhdCBjb250YWlucyB0aGUgZ2l2ZW4gbW9kYWwgaWRlbnRpZmllciBhbmQgdGhlIG1vZGFsIGl0c2VsZiBkaXJlY3RseSBpbiB0aGUgYG1vZGFsU3RhY2tgLlxuICAgKlxuICAgKiBAcGFyYW0gbW9kYWxJbnN0YW5jZSBUaGUgb2JqZWN0IHRoYXQgY29udGFpbnMgdGhlIGdpdmVuIG1vZGFsIGlkZW50aWZpZXIgYW5kIHRoZSBtb2RhbCBpdHNlbGYuXG4gICAqIEBwYXJhbSBmb3JjZSBPcHRpb25hbCBwYXJhbWV0ZXIgdGhhdCBmb3JjZXMgdGhlIG92ZXJyaWRpbmcgb2YgbW9kYWwgaW5zdGFuY2UgaWYgaXQgYWxyZWFkeSBleGlzdHMuXG4gICAqIEByZXR1cm5zIG5vdGhpbmcgc3BlY2lhbC5cbiAgICovXG4gIHB1YmxpYyBhZGRNb2RhbChtb2RhbEluc3RhbmNlOiBNb2RhbEluc3RhbmNlLCBmb3JjZT86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLl9tb2RhbFN0YWNrLmFkZE1vZGFsKG1vZGFsSW5zdGFuY2UsIGZvcmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZSBhIG1vZGFsIGluc3RhbmNlIGJ5IGl0cyBpZGVudGlmaWVyLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgVGhlIG1vZGFsIGlkZW50aWZpZXIgdXNlZCBhdCBjcmVhdGlvbiB0aW1lLlxuICAgKi9cbiAgcHVibGljIGdldE1vZGFsKGlkOiBzdHJpbmcpOiBOZ3hTbWFydE1vZGFsQ29tcG9uZW50IHtcbiAgICByZXR1cm4gdGhpcy5fbW9kYWxTdGFjay5nZXRNb2RhbChpZCk7XG4gIH1cblxuICAvKipcbiAgICogQWxpYXMgb2YgYGdldE1vZGFsYCB0byByZXRyaWV2ZSBhIG1vZGFsIGluc3RhbmNlIGJ5IGl0cyBpZGVudGlmaWVyLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgVGhlIG1vZGFsIGlkZW50aWZpZXIgdXNlZCBhdCBjcmVhdGlvbiB0aW1lLlxuICAgKi9cbiAgcHVibGljIGdldChpZDogc3RyaW5nKTogTmd4U21hcnRNb2RhbENvbXBvbmVudCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0TW9kYWwoaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9wZW4gYSBnaXZlbiBtb2RhbFxuICAgKlxuICAgKiBAcGFyYW0gaWQgVGhlIG1vZGFsIGlkZW50aWZpZXIgdXNlZCBhdCBjcmVhdGlvbiB0aW1lLlxuICAgKiBAcGFyYW0gZm9yY2UgVGVsbCB0aGUgbW9kYWwgdG8gb3BlbiB0b3Agb2YgYWxsIG90aGVyIG9wZW5lZCBtb2RhbHNcbiAgICovXG4gIHB1YmxpYyBvcGVuKGlkOiBzdHJpbmcsIGZvcmNlID0gZmFsc2UpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fb3Blbk1vZGFsKHRoaXMuZ2V0KGlkKSwgZm9yY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIGEgZ2l2ZW4gbW9kYWxcbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSBtb2RhbCBpZGVudGlmaWVyIHVzZWQgYXQgY3JlYXRpb24gdGltZS5cbiAgICovXG4gIHB1YmxpYyBjbG9zZShpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2Nsb3NlTW9kYWwodGhpcy5nZXQoaWQpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZSBhbGwgb3BlbmVkIG1vZGFsc1xuICAgKi9cbiAgcHVibGljIGNsb3NlQWxsKCk6IHZvaWQge1xuICAgIHRoaXMuZ2V0T3BlbmVkTW9kYWxzKCkuZm9yRWFjaCgoaW5zdGFuY2U6IE1vZGFsSW5zdGFuY2UpID0+IHtcbiAgICAgIHRoaXMuX2Nsb3NlTW9kYWwoaW5zdGFuY2UubW9kYWwpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvZ2dsZXMgYSBnaXZlbiBtb2RhbFxuICAgKiBJZiB0aGUgcmV0cmlldmVkIG1vZGFsIGlzIG9wZW5lZCBpdCBjbG9zZXMgaXQsIGVsc2UgaXQgb3BlbnMgaXQuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgbW9kYWwgaWRlbnRpZmllciB1c2VkIGF0IGNyZWF0aW9uIHRpbWUuXG4gICAqIEBwYXJhbSBmb3JjZSBUZWxsIHRoZSBtb2RhbCB0byBvcGVuIHRvcCBvZiBhbGwgb3RoZXIgb3BlbmVkIG1vZGFsc1xuICAgKi9cbiAgcHVibGljIHRvZ2dsZShpZDogc3RyaW5nLCBmb3JjZSA9IGZhbHNlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX3RvZ2dsZU1vZGFsKHRoaXMuZ2V0KGlkKSwgZm9yY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIGFsbCB0aGUgY3JlYXRlZCBtb2RhbHMuXG4gICAqXG4gICAqIEByZXR1cm5zIGFuIGFycmF5IHRoYXQgY29udGFpbnMgYWxsIG1vZGFsIGluc3RhbmNlcy5cbiAgICovXG4gIHB1YmxpYyBnZXRNb2RhbFN0YWNrKCk6IE1vZGFsSW5zdGFuY2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuX21vZGFsU3RhY2suZ2V0TW9kYWxTdGFjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIGFsbCB0aGUgb3BlbmVkIG1vZGFscy4gSXQgbG9va3MgZm9yIGFsbCBtb2RhbCBpbnN0YW5jZXMgd2l0aCB0aGVpciBgdmlzaWJsZWAgcHJvcGVydHkgc2V0IHRvIGB0cnVlYC5cbiAgICpcbiAgICogQHJldHVybnMgYW4gYXJyYXkgdGhhdCBjb250YWlucyBhbGwgdGhlIG9wZW5lZCBtb2RhbHMuXG4gICAqL1xuICBwdWJsaWMgZ2V0T3BlbmVkTW9kYWxzKCk6IE1vZGFsSW5zdGFuY2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuX21vZGFsU3RhY2suZ2V0T3BlbmVkTW9kYWxzKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgdGhlIG9wZW5lZCBtb2RhbCB3aXRoIGhpZ2hlc3Qgei1pbmRleC5cbiAgICpcbiAgICogQHJldHVybnMgdGhlIG9wZW5lZCBtb2RhbCB3aXRoIGhpZ2hlc3Qgei1pbmRleC5cbiAgICovXG4gIHB1YmxpYyBnZXRUb3BPcGVuZWRNb2RhbCgpOiBOZ3hTbWFydE1vZGFsQ29tcG9uZW50IHtcbiAgICByZXR1cm4gdGhpcy5fbW9kYWxTdGFjay5nZXRUb3BPcGVuZWRNb2RhbCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgaGlnaGVyIGB6LWluZGV4YCB2YWx1ZSBiZXR3ZWVuIGFsbCB0aGUgbW9kYWwgaW5zdGFuY2VzLiBJdCBpdGVyYXRlcyBvdmVyIHRoZSBgTW9kYWxTdGFja2AgYXJyYXkgYW5kXG4gICAqIGNhbGN1bGF0ZXMgYSBoaWdoZXIgdmFsdWUgKGl0IHRha2VzIHRoZSBoaWdoZXN0IGluZGV4IHZhbHVlIGJldHdlZW4gYWxsIHRoZSBtb2RhbCBpbnN0YW5jZXMgYW5kIGFkZHMgMSkuXG4gICAqIFVzZSBpdCB0byBtYWtlIGEgbW9kYWwgYXBwZWFyIGZvcmVncm91bmQuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgaGlnaGVyIGluZGV4IGZyb20gYWxsIHRoZSBleGlzdGluZyBtb2RhbCBpbnN0YW5jZXMuXG4gICAqL1xuICBwdWJsaWMgZ2V0SGlnaGVySW5kZXgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kYWxTdGFjay5nZXRIaWdoZXJJbmRleCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEl0IGdpdmVzIHRoZSBudW1iZXIgb2YgbW9kYWwgaW5zdGFuY2VzLiBJdCdzIGhlbHBmdWwgdG8ga25vdyBpZiB0aGUgbW9kYWwgc3RhY2sgaXMgZW1wdHkgb3Igbm90LlxuICAgKlxuICAgKiBAcmV0dXJucyB0aGUgbnVtYmVyIG9mIG1vZGFsIGluc3RhbmNlcy5cbiAgICovXG4gIHB1YmxpYyBnZXRNb2RhbFN0YWNrQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kYWxTdGFjay5nZXRNb2RhbFN0YWNrQ291bnQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYSBtb2RhbCBpbnN0YW5jZSBmcm9tIHRoZSBtb2RhbCBzdGFjay5cbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSBtb2RhbCBpZGVudGlmaWVyLlxuICAgKiBAcmV0dXJucyB0aGUgcmVtb3ZlZCBtb2RhbCBpbnN0YW5jZS5cbiAgICovXG4gIHB1YmxpYyByZW1vdmVNb2RhbChpZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbW9kYWxJbnN0YW5jZSA9IHRoaXMuX21vZGFsU3RhY2sucmVtb3ZlTW9kYWwoaWQpO1xuICAgIGlmIChtb2RhbEluc3RhbmNlKSB7XG4gICAgICB0aGlzLl9kZXN0cm95TW9kYWwobW9kYWxJbnN0YW5jZS5tb2RhbCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFzc29jaWF0ZSBkYXRhIHRvIGFuIGlkZW50aWZpZWQgbW9kYWwuIElmIHRoZSBtb2RhbCBpc24ndCBhbHJlYWR5IGFzc29jaWF0ZWQgdG8gc29tZSBkYXRhLCBpdCBjcmVhdGVzIGEgbmV3XG4gICAqIGVudHJ5IGluIHRoZSBgbW9kYWxEYXRhYCBhcnJheSB3aXRoIGl0cyBgaWRgIGFuZCB0aGUgZ2l2ZW4gYGRhdGFgLiBJZiB0aGUgbW9kYWwgYWxyZWFkeSBoYXMgZGF0YSwgaXQgcmV3cml0ZXNcbiAgICogdGhlbSB3aXRoIHRoZSBuZXcgb25lcy4gRmluYWxseSBpZiBubyBtb2RhbCBmb3VuZCBpdCByZXR1cm5zIGFuIGVycm9yIG1lc3NhZ2UgaW4gdGhlIGNvbnNvbGUgYW5kIGZhbHNlIHZhbHVlXG4gICAqIGFzIG1ldGhvZCBvdXRwdXQuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHlvdSB3YW50IHRvIGFzc29jaWF0ZSB0byB0aGUgbW9kYWwuXG4gICAqIEBwYXJhbSBpZCBUaGUgbW9kYWwgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIGZvcmNlIElmIHRydWUsIG92ZXJyaWRlcyB0aGUgcHJldmlvdXMgc3RvcmVkIGRhdGEgaWYgdGhlcmUgd2FzLlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBnaXZlbiBtb2RhbCBleGlzdHMgYW5kIHRoZSBwcm9jZXNzIGhhcyBiZWVuIHRyaWVkLCBlaXRoZXIgZmFsc2UuXG4gICAqL1xuICBwdWJsaWMgc2V0TW9kYWxEYXRhKGRhdGE6IGFueSwgaWQ6IHN0cmluZywgZm9yY2U/OiBib29sZWFuKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbW9kYWwgPSB0aGlzLmdldChpZCk7XG4gICAgaWYgKG1vZGFsKSB7XG4gICAgICBtb2RhbC5zZXREYXRhKGRhdGEsIGZvcmNlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIG1vZGFsIGRhdGEgYnkgaXRzIGlkZW50aWZpZXIuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgbW9kYWwgaWRlbnRpZmllciB1c2VkIGF0IGNyZWF0aW9uIHRpbWUuXG4gICAqIEByZXR1cm5zIHRoZSBhc3NvY2lhdGVkIG1vZGFsIGRhdGEuXG4gICAqL1xuICBwdWJsaWMgZ2V0TW9kYWxEYXRhKGlkOiBzdHJpbmcpOiB1bmtub3duIHtcbiAgICBjb25zdCBtb2RhbCA9IHRoaXMuZ2V0KGlkKTtcbiAgICBpZiAobW9kYWwpIHtcbiAgICAgIHJldHVybiBtb2RhbC5nZXREYXRhKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgdGhlIGRhdGEgYXR0YWNoZWQgdG8gYSBnaXZlbiBtb2RhbC5cbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSBtb2RhbCBpZGVudGlmaWVyIHVzZWQgYXQgY3JlYXRpb24gdGltZS5cbiAgICogQHJldHVybnMgdGhlIHJlbW92ZWQgZGF0YSBvciBmYWxzZSBpZiBtb2RhbCBkb2Vzbid0IGV4aXN0LlxuICAgKi9cbiAgcHVibGljIHJlc2V0TW9kYWxEYXRhKGlkOiBzdHJpbmcpOiB1bmtub3duIHwgYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuX21vZGFsU3RhY2suZ2V0TW9kYWxTdGFjaygpLmZpbmQoKG86IE1vZGFsSW5zdGFuY2UpID0+IG8uaWQgPT09IGlkKSkge1xuICAgICAgY29uc3QgcmVtb3ZlZDogdW5rbm93biA9IHRoaXMuZ2V0TW9kYWwoaWQpLmdldERhdGEoKTtcbiAgICAgIHRoaXMuZ2V0TW9kYWwoaWQpLnJlbW92ZURhdGEoKTtcbiAgICAgIHJldHVybiByZW1vdmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSBsYXRlc3Qgb3BlbmVkIG1vZGFsXG4gICAqL1xuICBwdWJsaWMgY2xvc2VMYXRlc3RNb2RhbCgpOiB2b2lkIHtcbiAgICB0aGlzLmdldFRvcE9wZW5lZE1vZGFsKCkuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgZHluYW1pYyBOZ3hTbWFydE1vZGFsQ29tcG9uZW50XG4gICAqIEBwYXJhbSB2Y3IgQSBWaWV3Q29udGFpbmVyUmVmIHJlZmVyZW5jZVxuICAgKiBAcGFyYW0gaWQgVGhlIG1vZGFsIGlkZW50aWZpZXIgdXNlZCBhdCBjcmVhdGlvbiB0aW1lXG4gICAqIEBwYXJhbSBjb250ZW50IFRoZSBtb2RhbCBjb250ZW50IChzdHJpbmcsIHRlbXBsYXRlUmVmIG9yIENvbXBvbmVudClcbiAgICogQHBhcmFtIG9wdGlvbnMgQW55IE5neFNtYXJ0TW9kYWxDb21wb25lbnQgYXZhaWxhYmxlIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBjcmVhdGU8VD4oaWQ6IHN0cmluZywgY29udGVudDogQ29udGVudDxUPiwgdmNyOiBWaWV3Q29udGFpbmVyUmVmLCBvcHRpb25zOiBJTmd4U21hcnRNb2RhbE9wdGlvbnMgPSB7fSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRNb2RhbChpZCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc3QgbmdDb250ZW50ID0gdGhpcy5fcmVzb2x2ZU5nQ29udGVudChjb250ZW50KTtcblxuICAgICAgY29uc3QgY29tcG9uZW50UmVmID0gdmNyLmNyZWF0ZUNvbXBvbmVudChOZ3hTbWFydE1vZGFsQ29tcG9uZW50LCB7IGluamVjdG9yOiB0aGlzLl9pbmplY3RvciwgcHJvamVjdGFibGVOb2RlczogbmdDb250ZW50IH0pO1xuXG4gICAgICBpZiAoY29udGVudCBpbnN0YW5jZW9mIFR5cGUpIHtcbiAgICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLmNvbnRlbnRDb21wb25lbnQgPSBjb250ZW50O1xuICAgICAgfVxuXG4gICAgICBjb21wb25lbnRSZWYuaW5zdGFuY2UuaWRlbnRpZmllciA9IGlkO1xuICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLmNyZWF0ZUZyb20gPSAnc2VydmljZSc7XG5cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jbG9zYWJsZSA9PT0gJ2Jvb2xlYW4nKSB7IGNvbXBvbmVudFJlZi5pbnN0YW5jZS5jbG9zYWJsZSA9IG9wdGlvbnMuY2xvc2FibGU7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5lc2NhcGFibGUgPT09ICdib29sZWFuJykgeyBjb21wb25lbnRSZWYuaW5zdGFuY2UuZXNjYXBhYmxlID0gb3B0aW9ucy5lc2NhcGFibGU7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5kaXNtaXNzYWJsZSA9PT0gJ2Jvb2xlYW4nKSB7IGNvbXBvbmVudFJlZi5pbnN0YW5jZS5kaXNtaXNzYWJsZSA9IG9wdGlvbnMuZGlzbWlzc2FibGU7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jdXN0b21DbGFzcyA9PT0gJ3N0cmluZycpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmN1c3RvbUNsYXNzID0gb3B0aW9ucy5jdXN0b21DbGFzczsgfVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmJhY2tkcm9wID09PSAnYm9vbGVhbicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmJhY2tkcm9wID0gb3B0aW9ucy5iYWNrZHJvcDsgfVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmZvcmNlID09PSAnYm9vbGVhbicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmZvcmNlID0gb3B0aW9ucy5mb3JjZTsgfVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmhpZGVEZWxheSA9PT0gJ251bWJlcicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmhpZGVEZWxheSA9IG9wdGlvbnMuaGlkZURlbGF5OyB9XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMuYXV0b3N0YXJ0ID09PSAnYm9vbGVhbicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmF1dG9zdGFydCA9IG9wdGlvbnMuYXV0b3N0YXJ0OyB9XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMudGFyZ2V0ID09PSAnc3RyaW5nJykgeyBjb21wb25lbnRSZWYuaW5zdGFuY2UudGFyZ2V0ID0gb3B0aW9ucy50YXJnZXQ7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5hcmlhTGFiZWwgPT09ICdzdHJpbmcnKSB7IGNvbXBvbmVudFJlZi5pbnN0YW5jZS5hcmlhTGFiZWwgPSBvcHRpb25zLmFyaWFMYWJlbDsgfVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmFyaWFMYWJlbGxlZEJ5ID09PSAnc3RyaW5nJykgeyBjb21wb25lbnRSZWYuaW5zdGFuY2UuYXJpYUxhYmVsbGVkQnkgPSBvcHRpb25zLmFyaWFMYWJlbGxlZEJ5OyB9XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMuYXJpYURlc2NyaWJlZEJ5ID09PSAnc3RyaW5nJykgeyBjb21wb25lbnRSZWYuaW5zdGFuY2UuYXJpYURlc2NyaWJlZEJ5ID0gb3B0aW9ucy5hcmlhRGVzY3JpYmVkQnk7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yZWZvY3VzID09PSAnYm9vbGVhbicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLnJlZm9jdXMgPSBvcHRpb25zLnJlZm9jdXM7IH1cblxuICAgICAgY29uc3QgZG9tRWxlbSA9IChjb21wb25lbnRSZWYuaG9zdFZpZXcgYXMgRW1iZWRkZWRWaWV3UmVmPGFueT4pLnJvb3ROb2Rlc1swXSBhcyBIVE1MRWxlbWVudDtcbiAgICAgIHRoaXMuX2RvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZG9tRWxlbSk7XG5cbiAgICAgIHJldHVybiBjb21wb25lbnRSZWYuaW5zdGFuY2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfYWRkRXZlbnRzKCk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5pc0Jyb3dzZXIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihOZ3hTbWFydE1vZGFsQ29uZmlnLnByZWZpeEV2ZW50ICsgJ2NyZWF0ZScsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX2luaXRNb2RhbChlLmRldGFpbC5pbnN0YW5jZSk7XG4gICAgfSkgYXMgRXZlbnRMaXN0ZW5lcik7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihOZ3hTbWFydE1vZGFsQ29uZmlnLnByZWZpeEV2ZW50ICsgJ2RlbGV0ZScsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX2RlbGV0ZU1vZGFsKGUuZGV0YWlsLmluc3RhbmNlKTtcbiAgICB9KSBhcyBFdmVudExpc3RlbmVyKTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKE5neFNtYXJ0TW9kYWxDb25maWcucHJlZml4RXZlbnQgKyAnb3BlbicsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX29wZW5Nb2RhbChlLmRldGFpbC5pbnN0YW5jZS5tb2RhbCwgZS5kZXRhaWwuZXh0cmFEYXRhLnRvcCk7XG4gICAgfSkgYXMgRXZlbnRMaXN0ZW5lcik7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihOZ3hTbWFydE1vZGFsQ29uZmlnLnByZWZpeEV2ZW50ICsgJ3RvZ2dsZScsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX3RvZ2dsZU1vZGFsKGUuZGV0YWlsLmluc3RhbmNlLm1vZGFsLCBlLmRldGFpbC5leHRyYURhdGEudG9wKTtcbiAgICB9KSBhcyBFdmVudExpc3RlbmVyKTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKE5neFNtYXJ0TW9kYWxDb25maWcucHJlZml4RXZlbnQgKyAnY2xvc2UnLCAoKGU6IEN1c3RvbUV2ZW50KSA9PiB7XG4gICAgICB0aGlzLl9jbG9zZU1vZGFsKGUuZGV0YWlsLmluc3RhbmNlLm1vZGFsKTtcbiAgICB9KSBhcyBFdmVudExpc3RlbmVyKTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKE5neFNtYXJ0TW9kYWxDb25maWcucHJlZml4RXZlbnQgKyAnZGlzbWlzcycsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX2Rpc21pc3NNb2RhbChlLmRldGFpbC5pbnN0YW5jZS5tb2RhbCk7XG4gICAgfSkgYXMgRXZlbnRMaXN0ZW5lcik7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9lc2NhcGVLZXlib2FyZEV2ZW50KTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdE1vZGFsKG1vZGFsSW5zdGFuY2U6IE1vZGFsSW5zdGFuY2UpIHtcbiAgICBtb2RhbEluc3RhbmNlLm1vZGFsLmxheWVyUG9zaXRpb24gKz0gdGhpcy5nZXRNb2RhbFN0YWNrQ291bnQoKTtcbiAgICB0aGlzLmFkZE1vZGFsKG1vZGFsSW5zdGFuY2UsIG1vZGFsSW5zdGFuY2UubW9kYWwuZm9yY2UpO1xuXG4gICAgaWYgKG1vZGFsSW5zdGFuY2UubW9kYWwuYXV0b3N0YXJ0KSB7XG4gICAgICB0aGlzLm9wZW4obW9kYWxJbnN0YW5jZS5pZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfb3Blbk1vZGFsKG1vZGFsOiBOZ3hTbWFydE1vZGFsQ29tcG9uZW50LCB0b3A/OiBib29sZWFuKTogYm9vbGVhbiB7XG4gICAgaWYgKG1vZGFsLnZpc2libGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB0aGlzLmxhc3RFbGVtZW50Rm9jdXNlZCA9IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG5cbiAgICBpZiAobW9kYWwuZXNjYXBhYmxlKSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9lc2NhcGVLZXlib2FyZEV2ZW50KTtcbiAgICB9XG5cbiAgICBpZiAobW9kYWwuYmFja2Ryb3ApIHtcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5fdHJhcEZvY3VzTW9kYWwpO1xuICAgIH1cblxuICAgIGlmICh0b3ApIHtcbiAgICAgIG1vZGFsLmxheWVyUG9zaXRpb24gPSB0aGlzLmdldEhpZ2hlckluZGV4KCk7XG4gICAgfVxuXG4gICAgbW9kYWwuYWRkQm9keUNsYXNzKCk7XG4gICAgbW9kYWwub3ZlcmxheVZpc2libGUgPSB0cnVlO1xuICAgIG1vZGFsLnZpc2libGUgPSB0cnVlO1xuICAgIG1vZGFsLm9uT3Blbi5lbWl0KG1vZGFsKTtcbiAgICBtb2RhbC5tYXJrRm9yQ2hlY2soKTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgbW9kYWwub3BlbmVkQ2xhc3MgPSB0cnVlO1xuXG4gICAgICBpZiAobW9kYWwudGFyZ2V0KSB7XG4gICAgICAgIG1vZGFsLnRhcmdldFBsYWNlbWVudCgpO1xuICAgICAgfVxuXG4gICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnZGlhbG9nJyk7XG4gICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3RhYkluZGV4JywgJy0xJyk7XG4gICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtbW9kYWwnLCAndHJ1ZScpO1xuICAgICAgbW9kYWwubnNtRGlhbG9nLmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcblxuICAgICAgbW9kYWwubWFya0ZvckNoZWNrKCk7XG4gICAgICBtb2RhbC5vbk9wZW5GaW5pc2hlZC5lbWl0KG1vZGFsKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBfdG9nZ2xlTW9kYWwobW9kYWw6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQsIHRvcD86IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgICBpZiAobW9kYWwudmlzaWJsZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2Nsb3NlTW9kYWwobW9kYWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3Blbk1vZGFsKG1vZGFsLCB0b3ApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2Nsb3NlTW9kYWwobW9kYWw6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQpOiBib29sZWFuIHtcbiAgICBpZiAoIW1vZGFsLm9wZW5lZENsYXNzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbW9kYWwub3BlbmVkQ2xhc3MgPSBmYWxzZTtcbiAgICBtb2RhbC5vbkNsb3NlLmVtaXQobW9kYWwpO1xuICAgIG1vZGFsLm9uQW55Q2xvc2VFdmVudC5lbWl0KG1vZGFsKTtcblxuICAgIGlmICh0aGlzLmdldE9wZW5lZE1vZGFscygpLmxlbmd0aCA8IDIpIHtcbiAgICAgIG1vZGFsLnJlbW92ZUJvZHlDbGFzcygpO1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleXVwJywgdGhpcy5fZXNjYXBlS2V5Ym9hcmRFdmVudCk7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuX3RyYXBGb2N1c01vZGFsKTtcbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIG1vZGFsLnZpc2libGVDaGFuZ2UuZW1pdChtb2RhbC52aXNpYmxlKTtcbiAgICAgIG1vZGFsLnZpc2libGUgPSBmYWxzZTtcbiAgICAgIG1vZGFsLm92ZXJsYXlWaXNpYmxlID0gZmFsc2U7XG4gICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ3RhYkluZGV4Jyk7XG4gICAgICBtb2RhbC5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIG1vZGFsLm9uQ2xvc2VGaW5pc2hlZC5lbWl0KG1vZGFsKTtcbiAgICAgIG1vZGFsLm9uQW55Q2xvc2VFdmVudEZpbmlzaGVkLmVtaXQobW9kYWwpO1xuICAgICAgaWYgKG1vZGFsLnJlZm9jdXMpIHtcbiAgICAgICAgdGhpcy5sYXN0RWxlbWVudEZvY3VzZWQuZm9jdXMoKTtcbiAgICAgIH1cbiAgICB9LCBtb2RhbC5oaWRlRGVsYXkpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIF9kaXNtaXNzTW9kYWwobW9kYWw6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQpOiBib29sZWFuIHtcbiAgICBpZiAoIW1vZGFsLm9wZW5lZENsYXNzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbW9kYWwub3BlbmVkQ2xhc3MgPSBmYWxzZTtcbiAgICBtb2RhbC5vbkRpc21pc3MuZW1pdChtb2RhbCk7XG4gICAgbW9kYWwub25BbnlDbG9zZUV2ZW50LmVtaXQobW9kYWwpO1xuXG4gICAgaWYgKHRoaXMuZ2V0T3BlbmVkTW9kYWxzKCkubGVuZ3RoIDwgMikge1xuICAgICAgbW9kYWwucmVtb3ZlQm9keUNsYXNzKCk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBtb2RhbC52aXNpYmxlID0gZmFsc2U7XG4gICAgICBtb2RhbC52aXNpYmxlQ2hhbmdlLmVtaXQobW9kYWwudmlzaWJsZSk7XG4gICAgICBtb2RhbC5vdmVybGF5VmlzaWJsZSA9IGZhbHNlO1xuICAgICAgbW9kYWwubWFya0ZvckNoZWNrKCk7XG4gICAgICBtb2RhbC5vbkRpc21pc3NGaW5pc2hlZC5lbWl0KG1vZGFsKTtcbiAgICAgIG1vZGFsLm9uQW55Q2xvc2VFdmVudEZpbmlzaGVkLmVtaXQobW9kYWwpO1xuICAgIH0sIG1vZGFsLmhpZGVEZWxheSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgX2RlbGV0ZU1vZGFsKG1vZGFsSW5zdGFuY2U6IE1vZGFsSW5zdGFuY2UpIHtcbiAgICB0aGlzLnJlbW92ZU1vZGFsKG1vZGFsSW5zdGFuY2UuaWQpO1xuXG4gICAgaWYgKCF0aGlzLmdldE1vZGFsU3RhY2soKS5sZW5ndGgpIHtcbiAgICAgIG1vZGFsSW5zdGFuY2UubW9kYWwucmVtb3ZlQm9keUNsYXNzKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgY29udGVudCBhY2NvcmRpbmcgdG8gdGhlIHR5cGVzXG4gICAqIEBwYXJhbSBjb250ZW50IFRoZSBtb2RhbCBjb250ZW50IChzdHJpbmcsIHRlbXBsYXRlUmVmIG9yIENvbXBvbmVudClcbiAgICovXG4gIHByaXZhdGUgX3Jlc29sdmVOZ0NvbnRlbnQ8VD4oY29udGVudDogQ29udGVudDxUPik6IGFueVtdW10gfCBUZXh0W11bXSB7XG4gICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX2RvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNvbnRlbnQpO1xuICAgICAgcmV0dXJuIFtbZWxlbWVudF1dO1xuICAgIH1cblxuICAgIGlmIChjb250ZW50IGluc3RhbmNlb2YgVGVtcGxhdGVSZWYpIHtcbiAgICAgIGNvbnN0IHZpZXdSZWYgPSBjb250ZW50LmNyZWF0ZUVtYmVkZGVkVmlldyhudWxsIGFzIGFueSk7XG4gICAgICB0aGlzLmFwcFJlZi5hdHRhY2hWaWV3KHZpZXdSZWYpO1xuICAgICAgcmV0dXJuIFt2aWV3UmVmLnJvb3ROb2Rlc107XG4gICAgfVxuXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSBsYXRlc3Qgb3BlbmVkIG1vZGFsIGlmIGVzY2FwZSBrZXkgZXZlbnQgaXMgZW1pdHRlZFxuICAgKiBAcGFyYW0gZXZlbnQgVGhlIEtleWJvYXJkIEV2ZW50XG4gICAqL1xuICBwcml2YXRlIF9lc2NhcGVLZXlib2FyZEV2ZW50ID0gKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiB7XG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VzY2FwZScpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG1vZGFsID0gdGhpcy5nZXRUb3BPcGVuZWRNb2RhbCgpO1xuXG4gICAgICAgIGlmICghbW9kYWwuZXNjYXBhYmxlKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgbW9kYWwub25Fc2NhcGUuZW1pdChtb2RhbCk7XG4gICAgICAgIHRoaXMuY2xvc2VMYXRlc3RNb2RhbCgpO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIElzIGN1cnJlbnQgcGxhdGZvcm0gYnJvd3NlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXQgaXNCcm93c2VyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLl9wbGF0Zm9ybUlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGlsZSBtb2RhbCBpcyBvcGVuLCB0aGUgZm9jdXMgc3RheSBvbiBpdFxuICAgKiBAcGFyYW0gZXZlbnQgVGhlIEtleWJvYXIgZEV2ZW50XG4gICAqL1xuICBwcml2YXRlIF90cmFwRm9jdXNNb2RhbCA9IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4ge1xuICAgIGlmIChldmVudC5rZXkgPT09ICdUYWInKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBtb2RhbCA9IHRoaXMuZ2V0VG9wT3BlbmVkTW9kYWwoKTtcblxuICAgICAgICBpZiAoIW1vZGFsLm5zbURpYWxvZy5maXJzdC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGR5bmFtaWNhbGx5IGNyZWF0ZWQgbW9kYWwgZnJvbSBET01cbiAgICovXG4gIHByaXZhdGUgX2Rlc3Ryb3lNb2RhbChtb2RhbDogTmd4U21hcnRNb2RhbENvbXBvbmVudCk6IHZvaWQge1xuICAgIC8vIFByZXZlbnQgZGVzdHJ1Y3Rpb24gb2YgdGhlIGlubGluZSBtb2RhbHNcbiAgICBpZiAobW9kYWwuY3JlYXRlRnJvbSAhPT0gJ3NlcnZpY2UnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChtb2RhbC5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIGdldHRlciBmdW5jdGlvbiB0byBhdm9pZCBjaXJjdWxhciBkZXBlbmRlbmN5IGVycm9yXG4gICAqIEByZXR1cm5zIEFwcGxpY2F0aW9uUmVmIGluc3RhbmNlXG4gICAqICovXG4gIHByaXZhdGUgZ2V0IGFwcFJlZigpOiBBcHBsaWNhdGlvblJlZiB7XG4gICAgcmV0dXJuIHRoaXMuX2luamVjdG9yLmdldChBcHBsaWNhdGlvblJlZik7XG4gIH1cbn1cbiJdfQ==