Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

vipera-npm-registry / motif-web-admin-core   js

Repository URL to install this package:

Version: 0.3.1 

/ esm2015 / lib / services / ServiceCatalogService.js

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
import { Injectable } from '@angular/core';
import { DomainsService, ApplicationsService, } from '@wa-motif-open-api/platform-service';
import { ServicesService, OperationsService } from '@wa-motif-open-api/catalog-service';
import { ApplicationsService as AppService } from '@wa-motif-open-api/catalog-service';
import { Observable } from 'rxjs';
import { NGXLogger } from 'web-console-core';
/** @type {?} */
const LOG_TAG = '[ServiceCatalogService]';
export class ServiceCatalogService {
    /**
     * @param {?} domainService
     * @param {?} applicationService
     * @param {?} appService
     * @param {?} servicesService
     * @param {?} operationsService
     * @param {?} logger
     */
    constructor(domainService, applicationService, appService, servicesService, operationsService, logger) {
        this.domainService = domainService;
        this.applicationService = applicationService;
        this.appService = appService;
        this.servicesService = servicesService;
        this.operationsService = operationsService;
        this.logger = logger;
    }
    /**
     * Returns a JSON with the Service Catalog Structure
     * @return {?}
     */
    getServiceCatalog() {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'getServiceCatalog called');
            /** @type {?} */
            const serviceCatalog = [];
            this.domainService.getDomains().subscribe((/**
             * @param {?} domains
             * @return {?}
             */
            (domains) => {
                /** @type {?} */
                const domainsCount = domains.length;
                /** @type {?} */
                let processedDomains = 0;
                for (const domain of domains) {
                    /** @type {?} */
                    const domainInfo = domain;
                    domainInfo.applications = [];
                    serviceCatalog.push(domainInfo);
                    this.applicationService.getApplications(domain.name).subscribe((/**
                     * @param {?} applications
                     * @return {?}
                     */
                    (applications) => {
                        /** @type {?} */
                        const appCount = applications.length;
                        /** @type {?} */
                        let processedApps = 0;
                        if (appCount === 0) {
                            processedDomains++;
                            if (processedDomains === domainsCount) {
                                observer.next(serviceCatalog);
                                observer.complete();
                                this.logger.debug(LOG_TAG, 'getServiceCatalog completed');
                            }
                        }
                        for (const application of applications) {
                            /** @type {?} */
                            const applicationInfo = application;
                            this.appService.getServiceList(domain.name, application.name).subscribe((/**
                             * @param {?} services
                             * @return {?}
                             */
                            (services) => {
                                applicationInfo.services = services;
                                // tslint:disable-next-line:max-line-length
                                this.logger.debug(LOG_TAG, 'getServiceCatalog services[' + application.name + '@' + domain.name + ']:', services);
                            }), (/**
                             * @param {?} error
                             * @return {?}
                             */
                            (error) => {
                                this.logger.error(LOG_TAG, 'getServiceCatalog error:', error);
                                observer.error(error);
                            }), (/**
                             * @return {?}
                             */
                            () => {
                                processedApps++;
                                if (processedApps === appCount) {
                                    processedDomains++;
                                }
                                if (processedDomains === domainsCount) {
                                    observer.next(serviceCatalog);
                                    observer.complete();
                                    this.logger.debug(LOG_TAG, 'getServiceCatalog completed');
                                }
                            }));
                            domainInfo.applications.push(applicationInfo);
                        }
                    }), (/**
                     * @param {?} error
                     * @return {?}
                     */
                    (error) => {
                        this.logger.error(LOG_TAG, 'getServiceCatalog error:', error);
                        observer.error(error);
                    }));
                    if (processedDomains === domainsCount) {
                        observer.next(serviceCatalog);
                        observer.complete();
                        this.logger.debug(LOG_TAG, 'getServiceCatalog completed');
                    }
                }
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                this.logger.error(LOG_TAG, 'getServiceCatalog error:', error);
                observer.error(error);
            }));
        }));
    }
    /**
     * @return {?}
     */
    getServices() {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'getServices called');
            /** @type {?} */
            const services = [];
            this.getServiceCatalog().subscribe((/**
             * @param {?} serviceCatalog
             * @return {?}
             */
            (serviceCatalog) => {
                this.logger.debug(LOG_TAG, 'getServices rawData:', serviceCatalog);
                serviceCatalog.forEach((/**
                 * @param {?} domain
                 * @return {?}
                 */
                domain => {
                    if (domain.applications) {
                        for (let i = 0; i < domain.applications.length; i++) {
                            /** @type {?} */
                            const application = domain.applications[i];
                            if (application.services) {
                                for (let y = 0; y < application.services.length; y++) {
                                    /** @type {?} */
                                    const service = application.services[y];
                                    if (service.serviceOperationList) {
                                        for (let z = 0; z < service.serviceOperationList.length; z++) {
                                            /** @type {?} */
                                            const operation = service.serviceOperationList[z];
                                            /** @type {?} */
                                            const serviceEntry = {
                                                domain: domain.name,
                                                application: application.name,
                                                service: service.name,
                                                serviceEnabled: service.enabled,
                                                channel: service.channel,
                                                name: operation.name,
                                                description: operation.description,
                                                type: 'Operation'
                                            };
                                            services.push(serviceEntry);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }));
                observer.next(services);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                this.logger.error(LOG_TAG, 'getServices error:', error);
                observer.error(error);
            }));
        }));
    }
    /**
     * @param {?} domainName
     * @return {?}
     */
    createNewDomain(domainName) {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'createNewDomain called for ', domainName);
            /** @type {?} */
            const domainCreate = { name: domainName, description: 'Description of ' + domainName };
            this.domainService.createDomain(domainCreate).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                observer.next(data);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                observer.error(error);
            }));
        }));
    }
    /**
     * @param {?} domain
     * @param {?} applicationName
     * @return {?}
     */
    createNewApplication(domain, applicationName) {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'createNewApplication called for ', domain, applicationName);
            /** @type {?} */
            const appCreate = { name: applicationName, description: 'Description of ' + applicationName };
            this.applicationService.createApplication(domain, appCreate).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                observer.next(data);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                observer.error(error);
            }));
        }));
    }
    /**
     * @param {?} domain
     * @param {?} application
     * @param {?} serviceName
     * @param {?} channel
     * @return {?}
     */
    createNewService(domain, application, serviceName, channel) {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'createNewService called for ', domain, application, serviceName, channel);
            /** @type {?} */
            const serviceCreate = {
                name: serviceName
            };
            this.servicesService.createService(channel, domain, application, serviceCreate).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                observer.next(data);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                observer.error(error);
            }));
        }));
    }
    /**
     * @param {?} channel
     * @param {?} domain
     * @param {?} application
     * @param {?} service
     * @param {?} operationName
     * @param {?} description
     * @param {?} pluginName
     * @param {?} encrypted
     * @param {?} secure
     * @param {?} counted
     * @param {?} sessionless
     * @param {?} inputParams
     * @param {?} outputParams
     * @return {?}
     */
    createNewOperation(channel, domain, application, service, operationName, description, pluginName, encrypted, secure, counted, sessionless, inputParams, outputParams) {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'createNewOperation called for ', domain, application, service, operationName);
            /** @type {?} */
            const serviceOperation = {
                counted: counted,
                encryptActive: encrypted,
                inputParams: inputParams,
                outputParams: outputParams,
                pluginName: pluginName,
                secure: secure,
                sessionless: sessionless,
                name: operationName,
                description: description
            };
            this.operationsService.createServiceOperation(channel, domain, application, service, serviceOperation).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                observer.next(data);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                observer.error(error);
            }));
        }));
    }
    /**
     * @param {?} domainName
     * @return {?}
     */
    deleteDomain(domainName) {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'deleteDomain called for ', domainName);
            this.domainService.deleteDomain(domainName).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                observer.next(data);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                observer.error(error);
            }));
        }));
    }
    /**
     * @param {?} domainName
     * @param {?} applicationName
     * @return {?}
     */
    deleteApplication(domainName, applicationName) {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'deleteApplication called for ', domainName, applicationName);
            this.applicationService.deleteApplication(domainName, applicationName).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                observer.next(data);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                observer.error(error);
            }));
        }));
    }
    /**
     * @param {?} channel
     * @param {?} domainName
     * @param {?} applicationName
     * @param {?} serviceName
     * @return {?}
     */
    deleteService(channel, domainName, applicationName, serviceName) {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'deleteService called for ', domainName, applicationName, serviceName);
            this.servicesService.deleteService(channel, domainName, applicationName, serviceName).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                observer.next(data);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                observer.error(error);
            }));
        }));
    }
    /**
     * @param {?} channel
     * @param {?} domainName
     * @param {?} applicationName
     * @param {?} serviceName
     * @param {?} operationName
     * @return {?}
     */
    deleteOperation(channel, domainName, applicationName, serviceName, operationName) {
        return new Observable((/**
         * @param {?} observer
         * @return {?}
         */
        (observer) => {
            this.logger.debug(LOG_TAG, 'deleteOperation called for ', domainName, applicationName, serviceName, operationName);
            this.operationsService.deleteServiceOperation(channel, domainName, applicationName, serviceName, operationName).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                observer.next(data);
                observer.complete();
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                observer.error(error);
            }));
        }));
    }
}
ServiceCatalogService.decorators = [
    { type: Injectable }
];
/** @nocollapse */
ServiceCatalogService.ctorParameters = () => [
    { type: DomainsService },
    { type: ApplicationsService },
    { type: AppService },
    { type: ServicesService },
    { type: OperationsService },
    { type: NGXLogger }
];
if (false) {
    /**
     * @type {?}
     * @private
     */
    ServiceCatalogService.prototype.domainsList;
    /**
     * @type {?}
     * @private
     */
    ServiceCatalogService.prototype.domainService;
    /**
     * @type {?}
     * @private
     */
    ServiceCatalogService.prototype.applicationService;
    /**
     * @type {?}
     * @private
     */
    ServiceCatalogService.prototype.appService;
    /**
     * @type {?}
     * @private
     */
    ServiceCatalogService.prototype.servicesService;
    /**
     * @type {?}
     * @private
     */
    ServiceCatalogService.prototype.operationsService;
    /**
     * @type {?}
     * @private
     */
    ServiceCatalogService.prototype.logger;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmljZUNhdGFsb2dTZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbW90aWYtd2ViLWFkbWluLWNvcmUvIiwic291cmNlcyI6WyJsaWIvc2VydmljZXMvU2VydmljZUNhdGFsb2dTZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxjQUFjLEVBRWQsbUJBQW1CLEdBR2pCLE1BQU0scUNBQXFDLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFHcEIsaUJBQWlCLEVBQ0MsTUFBTSxvQ0FBb0MsQ0FBQztBQUNqRSxPQUFPLEVBQUUsbUJBQW1CLElBQUksVUFBVSxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFFdkYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7O01BRXZDLE9BQU8sR0FBRyx5QkFBeUI7QUFHekMsTUFBTSxPQUFPLHFCQUFxQjs7Ozs7Ozs7O0lBSTlCLFlBQW9CLGFBQTZCLEVBQ3JDLGtCQUF1QyxFQUN2QyxVQUFzQixFQUN0QixlQUFnQyxFQUNoQyxpQkFBb0MsRUFDcEMsTUFBaUI7UUFMVCxrQkFBYSxHQUFiLGFBQWEsQ0FBZ0I7UUFDckMsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFxQjtRQUN2QyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBQ3RCLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUNoQyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBQ3BDLFdBQU0sR0FBTixNQUFNLENBQVc7SUFDN0IsQ0FBQzs7Ozs7SUFLTSxpQkFBaUI7UUFDcEIsT0FBTyxJQUFJLFVBQVU7Ozs7UUFBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO1lBRS9CLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSwwQkFBMEIsQ0FBRSxD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LENBQUMsS0FBSyxDQUFDLENBQUM7WUFDMUIsQ0FBQyxFQUFDLENBQUM7UUFDUCxDQUFDLEVBQUMsQ0FBQztJQUNQLENBQUM7OztZQS9SSixVQUFVOzs7O1lBbEJGLGNBQWM7WUFFZCxtQkFBbUI7WUFTSSxVQUFVO1lBTGpDLGVBQWU7WUFHcEIsaUJBQWlCO1lBS1osU0FBUzs7Ozs7OztJQU9kLDRDQUFtQzs7Ozs7SUFFdkIsOENBQXFDOzs7OztJQUM3QyxtREFBK0M7Ozs7O0lBQy9DLDJDQUE4Qjs7Ozs7SUFDOUIsZ0RBQXdDOzs7OztJQUN4QyxrREFBNEM7Ozs7O0lBQzVDLHVDQUF5QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERvbWFpbnNTZXJ2aWNlLFxuICAgICAgICAgRG9tYWluLCBEb21haW5DcmVhdGUsXG4gICAgICAgICBBcHBsaWNhdGlvbnNTZXJ2aWNlLFxuICAgICAgICAgQXBwbGljYXRpb24sXG4gICAgICAgICBBcHBsaWNhdGlvbkNyZWF0ZSxcbiAgICAgICAgICB9IGZyb20gJ0B3YS1tb3RpZi1vcGVuLWFwaS9wbGF0Zm9ybS1zZXJ2aWNlJztcbmltcG9ydCB7IFNlcnZpY2VzU2VydmljZSxcbiAgICBTZXJ2aWNlLFxuICAgIFNlcnZpY2VDcmVhdGUsXG4gICAgT3BlcmF0aW9uc1NlcnZpY2UsXG4gICAgU2VydmljZU9wZXJhdGlvbiB9IGZyb20gJ0B3YS1tb3RpZi1vcGVuLWFwaS9jYXRhbG9nLXNlcnZpY2UnO1xuaW1wb3J0IHsgQXBwbGljYXRpb25zU2VydmljZSBhcyBBcHBTZXJ2aWNlIH0gZnJvbSAnQHdhLW1vdGlmLW9wZW4tYXBpL2NhdGFsb2ctc2VydmljZSc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5HWExvZ2dlciB9IGZyb20gJ3dlYi1jb25zb2xlLWNvcmUnO1xuXG5jb25zdCBMT0dfVEFHID0gJ1tTZXJ2aWNlQ2F0YWxvZ1NlcnZpY2VdJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFNlcnZpY2VDYXRhbG9nU2VydmljZSB7XG5cbiAgICBwcml2YXRlIGRvbWFpbnNMaXN0OiBBcnJheTxEb21haW4+O1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBkb21haW5TZXJ2aWNlOiBEb21haW5zU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBhcHBsaWNhdGlvblNlcnZpY2U6IEFwcGxpY2F0aW9uc1NlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgYXBwU2VydmljZTogQXBwU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBzZXJ2aWNlc1NlcnZpY2U6IFNlcnZpY2VzU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBvcGVyYXRpb25zU2VydmljZTogT3BlcmF0aW9uc1NlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgbG9nZ2VyOiBOR1hMb2dnZXIpIHtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgSlNPTiB3aXRoIHRoZSBTZXJ2aWNlIENhdGFsb2cgU3RydWN0dXJlXG4gICAgICovXG4gICAgcHVibGljIGdldFNlcnZpY2VDYXRhbG9nKCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoTE9HX1RBRywgJ2dldFNlcnZpY2VDYXRhbG9nIGNhbGxlZCcgKTtcblxuICAgICAgICAgICAgY29uc3Qgc2VydmljZUNhdGFsb2cgPSBbXTtcblxuICAgICAgICAgICAgdGhpcy5kb21haW5TZXJ2aWNlLmdldERvbWFpbnMoKS5zdWJzY3JpYmUoKCBkb21haW5zOiBBcnJheTxEb21haW4+ICkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRvbWFpbnNDb3VudCA9IGRvbWFpbnMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGxldCBwcm9jZXNzZWREb21haW5zID0gMDtcblxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZG9tYWluIG9mIGRvbWFpbnMpIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkb21haW5JbmZvOiBhbnkgPSBkb21haW47XG4gICAgICAgICAgICAgICAgICAgIGRvbWFpbkluZm8uYXBwbGljYXRpb25zID0gW107XG4gICAgICAgICAgICAgICAgICAgIHNlcnZpY2VDYXRhbG9nLnB1c2goZG9tYWluSW5mbyk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hcHBsaWNhdGlvblNlcnZpY2UuZ2V0QXBwbGljYXRpb25zKGRvbWFpbi5uYW1lKS5zdWJzY3JpYmUoKCBhcHBsaWNhdGlvbnM6IEFycmF5PEFwcGxpY2F0aW9uPiApID0+IHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXBwQ291bnQgPSBhcHBsaWNhdGlvbnMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHByb2Nlc3NlZEFwcHMgPSAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXBwQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWREb21haW5zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCBwcm9jZXNzZWREb21haW5zID09PSBkb21haW5zQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCggc2VydmljZUNhdGFsb2cgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoTE9HX1RBRywgJ2dldFNlcnZpY2VDYXRhbG9nIGNvbXBsZXRlZCcgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgYXBwbGljYXRpb24gb2YgYXBwbGljYXRpb25zICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFwcGxpY2F0aW9uSW5mbzogYW55ID0gYXBwbGljYXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hcHBTZXJ2aWNlLmdldFNlcnZpY2VMaXN0KGRvbWFpbi5uYW1lLCBhcHBsaWNhdGlvbi5uYW1lKS5zdWJzY3JpYmUoICggc2VydmljZXM6IEFycmF5PFNlcnZpY2U+ICkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBsaWNhdGlvbkluZm8uc2VydmljZXMgPSBzZXJ2aWNlcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHLCAnZ2V0U2VydmljZUNhdGFsb2cgc2VydmljZXNbJyArIGFwcGxpY2F0aW9uLm5hbWUgKyAnQCcgKyBkb21haW4ubmFtZSArICddOicsIHNlcnZpY2VzICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgKCBlcnJvciApID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoTE9HX1RBRywgJ2dldFNlcnZpY2VDYXRhbG9nIGVycm9yOicgLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NlZEFwcHMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb2Nlc3NlZEFwcHMgPT09IGFwcENvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWREb21haW5zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCBwcm9jZXNzZWREb21haW5zID09PSBkb21haW5zQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoIHNlcnZpY2VDYXRhbG9nICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoTE9HX1RBRywgJ2dldFNlcnZpY2VDYXRhbG9nIGNvbXBsZXRlZCcgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbkluZm8uYXBwbGljYXRpb25zLnB1c2goYXBwbGljYXRpb25JbmZvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB9LCAoIGVycm9yICkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoTE9HX1RBRywgJ2dldFNlcnZpY2VDYXRhbG9nIGVycm9yOicgLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICggcHJvY2Vzc2VkRG9tYWlucyA9PT0gZG9tYWluc0NvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KCBzZXJ2aWNlQ2F0YWxvZyApO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKExPR19UQUcsICdnZXRTZXJ2aWNlQ2F0YWxvZyBjb21wbGV0ZWQnICk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKExPR19UQUcsICdnZXRTZXJ2aWNlQ2F0YWxvZyBlcnJvcjonICwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2VydmljZXMoKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKChvYnNlcnZlcikgPT4ge1xuXG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHLCAnZ2V0U2VydmljZXMgY2FsbGVkJyApO1xuXG4gICAgICAgICAgICBjb25zdCBzZXJ2aWNlczogYW55ID0gW107XG5cbiAgICAgICAgICAgIHRoaXMuZ2V0U2VydmljZUNhdGFsb2coKS5zdWJzY3JpYmUoKHNlcnZpY2VDYXRhbG9nKSA9PiB7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHLCAnZ2V0U2VydmljZXMgcmF3RGF0YTonLCBzZXJ2aWNlQ2F0YWxvZyApO1xuXG4gICAgICAgICAgICAgICAgc2VydmljZUNhdGFsb2cuZm9yRWFjaChkb21haW4gPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21haW4uYXBwbGljYXRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCA7IGkgPCBkb21haW4uYXBwbGljYXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXBwbGljYXRpb24gPSBkb21haW4uYXBwbGljYXRpb25zW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFwcGxpY2F0aW9uLnNlcnZpY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgYXBwbGljYXRpb24uc2VydmljZXMubGVuZ3RoOyB5KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlcnZpY2UgPSBhcHBsaWNhdGlvbi5zZXJ2aWNlc1t5XTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcnZpY2Uuc2VydmljZU9wZXJhdGlvbkxpc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB6ID0gMDsgeiA8IHNlcnZpY2Uuc2VydmljZU9wZXJhdGlvbkxpc3QubGVuZ3RoOyB6KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3BlcmF0aW9uID0gc2VydmljZS5zZXJ2aWNlT3BlcmF0aW9uTGlzdFt6XTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzZXJ2aWNlRW50cnk6IGFueSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbjogZG9tYWluLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBsaWNhdGlvbjogYXBwbGljYXRpb24ubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcnZpY2U6IHNlcnZpY2UubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcnZpY2VFbmFibGVkIDogc2VydmljZS5lbmFibGVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbDogc2VydmljZS5jaGFubmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogb3BlcmF0aW9uLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogb3BlcmF0aW9uLmRlc2NyaXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ09wZXJhdGlvbidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VydmljZXMucHVzaChzZXJ2aWNlRW50cnkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KCBzZXJ2aWNlcyApO1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG5cbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKExPR19UQUcsICdnZXRTZXJ2aWNlcyBlcnJvcjonICwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBjcmVhdGVOZXdEb21haW4oZG9tYWluTmFtZTogc3RyaW5nKTogT2JzZXJ2YWJsZTxEb21haW4+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKChvYnNlcnZlcikgPT4ge1xuXG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHLCAnY3JlYXRlTmV3RG9tYWluIGNhbGxlZCBmb3IgJywgZG9tYWluTmFtZSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGRvbWFpbkNyZWF0ZTogRG9tYWluQ3JlYXRlID0geyBuYW1lOiBkb21haW5OYW1lLCBkZXNjcmlwdGlvbjogJ0Rlc2NyaXB0aW9uIG9mICcgKyBkb21haW5OYW1lIH07XG5cbiAgICAgICAgICAgIHRoaXMuZG9tYWluU2VydmljZS5jcmVhdGVEb21haW4oZG9tYWluQ3JlYXRlKS5zdWJzY3JpYmUoKGRhdGE6IERvbWFpbikgPT4ge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoZGF0YSk7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlTmV3QXBwbGljYXRpb24oZG9tYWluOiBzdHJpbmcsIGFwcGxpY2F0aW9uTmFtZTogc3RyaW5nKTogT2JzZXJ2YWJsZTxBcHBsaWNhdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKExPR19UQUcsICdjcmVhdGVOZXdBcHBsaWNhdGlvbiBjYWxsZWQgZm9yICcsIGRvbWFpbiwgYXBwbGljYXRpb25OYW1lKTtcblxuICAgICAgICAgICAgY29uc3QgYXBwQ3JlYXRlOiBBcHBsaWNhdGlvbkNyZWF0ZSA9IHsgbmFtZTogYXBwbGljYXRpb25OYW1lLCBkZXNjcmlwdGlvbjogJ0Rlc2NyaXB0aW9uIG9mICcgKyBhcHBsaWNhdGlvbk5hbWUgfTtcblxuICAgICAgICAgICAgdGhpcy5hcHBsaWNhdGlvblNlcnZpY2UuY3JlYXRlQXBwbGljYXRpb24oZG9tYWluLCBhcHBDcmVhdGUpLnN1YnNjcmliZSgoZGF0YTogQXBwbGljYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KGRhdGEpO1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGNyZWF0ZU5ld1NlcnZpY2UoZG9tYWluOiBzdHJpbmcsIGFwcGxpY2F0aW9uOiBzdHJpbmcsIHNlcnZpY2VOYW1lOiBzdHJpbmcsIGNoYW5uZWw6IHN0cmluZyk6IE9ic2VydmFibGU8U2VydmljZT4ge1xuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKExPR19UQUcsICdjcmVhdGVOZXdTZXJ2aWNlIGNhbGxlZCBmb3IgJywgZG9tYWluLCBhcHBsaWNhdGlvbiwgc2VydmljZU5hbWUsIGNoYW5uZWwpO1xuXG4gICAgICAgICAgICBjb25zdCBzZXJ2aWNlQ3JlYXRlOiBTZXJ2aWNlQ3JlYXRlID0ge1xuICAgICAgICAgICAgICAgIG5hbWU6IHNlcnZpY2VOYW1lXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLnNlcnZpY2VzU2VydmljZS5jcmVhdGVTZXJ2aWNlKGNoYW5uZWwsIGRvbWFpbiwgYXBwbGljYXRpb24sIHNlcnZpY2VDcmVhdGUpLnN1YnNjcmliZSgoZGF0YTogU2VydmljZSkgPT4ge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoZGF0YSk7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlTmV3T3BlcmF0aW9uKGNoYW5uZWw6IHN0cmluZyxcbiAgICAgICAgZG9tYWluOiBzdHJpbmcsXG4gICAgICAgIGFwcGxpY2F0aW9uOiBzdHJpbmcsXG4gICAgICAgIHNlcnZpY2U6IHN0cmluZyxcbiAgICAgICAgb3BlcmF0aW9uTmFtZTogc3RyaW5nLFxuICAgICAgICBkZXNjcmlwdGlvbjogc3RyaW5nLFxuICAgICAgICBwbHVnaW5OYW1lOiBzdHJpbmcsXG4gICAgICAgIGVuY3J5cHRlZDogYm9vbGVhbixcbiAgICAgICAgc2VjdXJlOiBib29sZWFuLFxuICAgICAgICBjb3VudGVkOiBib29sZWFuLFxuICAgICAgICBzZXNzaW9ubGVzczogYm9vbGVhbixcbiAgICAgICAgaW5wdXRQYXJhbXM6IHN0cmluZyxcbiAgICAgICAgb3V0cHV0UGFyYW1zOiBzdHJpbmdcbiAgICAgICAgKTogT2JzZXJ2YWJsZTxTZXJ2aWNlT3BlcmF0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoTE9HX1RBRywgJ2NyZWF0ZU5ld09wZXJhdGlvbiBjYWxsZWQgZm9yICcsIGRvbWFpbiwgYXBwbGljYXRpb24sIHNlcnZpY2UsIG9wZXJhdGlvbk5hbWUpO1xuICAgICAgICAgICAgY29uc3Qgc2VydmljZU9wZXJhdGlvbjogU2VydmljZU9wZXJhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBjb3VudGVkOiBjb3VudGVkLFxuICAgICAgICAgICAgICAgIGVuY3J5cHRBY3RpdmU6IGVuY3J5cHRlZCxcbiAgICAgICAgICAgICAgICBpbnB1dFBhcmFtczogaW5wdXRQYXJhbXMsXG4gICAgICAgICAgICAgICAgb3V0cHV0UGFyYW1zOiBvdXRwdXRQYXJhbXMsXG4gICAgICAgICAgICAgICAgcGx1Z2luTmFtZTogcGx1Z2luTmFtZSxcbiAgICAgICAgICAgICAgICBzZWN1cmU6IHNlY3VyZSxcbiAgICAgICAgICAgICAgICBzZXNzaW9ubGVzczogc2Vzc2lvbmxlc3MsXG4gICAgICAgICAgICAgICAgbmFtZTogb3BlcmF0aW9uTmFtZSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogZGVzY3JpcHRpb25cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlcmF0aW9uc1NlcnZpY2UuY3JlYXRlU2VydmljZU9wZXJhdGlvbihjaGFubmVsLFxuICAgICAgICAgICAgICAgIGRvbWFpbiwgYXBwbGljYXRpb24sIHNlcnZpY2UsIHNlcnZpY2VPcGVyYXRpb24pLiBzdWJzY3JpYmUoKGRhdGE6IFNlcnZpY2VPcGVyYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgcHVibGljIGRlbGV0ZURvbWFpbihkb21haW5OYW1lOiBzdHJpbmcpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHLCAnZGVsZXRlRG9tYWluIGNhbGxlZCBmb3IgJywgZG9tYWluTmFtZSk7XG4gICAgICAgICAgICB0aGlzLmRvbWFpblNlcnZpY2UuZGVsZXRlRG9tYWluKGRvbWFpbk5hbWUpLnN1YnNjcmliZSgoZGF0YTogRG9tYWluKSA9PiB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChkYXRhKTtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBkZWxldGVBcHBsaWNhdGlvbihkb21haW5OYW1lOiBzdHJpbmcsIGFwcGxpY2F0aW9uTmFtZTogc3RyaW5nKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKChvYnNlcnZlcikgPT4ge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoTE9HX1RBRywgJ2RlbGV0ZUFwcGxpY2F0aW9uIGNhbGxlZCBmb3IgJywgZG9tYWluTmFtZSwgYXBwbGljYXRpb25OYW1lKTtcbiAgICAgICAgICAgIHRoaXMuYXBwbGljYXRpb25TZXJ2aWNlLmRlbGV0ZUFwcGxpY2F0aW9uKGRvbWFpbk5hbWUsIGFwcGxpY2F0aW9uTmFtZSkuc3Vic2NyaWJlKChkYXRhKSA9PiB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChkYXRhKTtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBkZWxldGVTZXJ2aWNlKGNoYW5uZWw6IHN0cmluZywgZG9tYWluTmFtZTogc3RyaW5nLCBhcHBsaWNhdGlvbk5hbWU6IHN0cmluZywgc2VydmljZU5hbWU6IHN0cmluZyk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKExPR19UQUcsICdkZWxldGVTZXJ2aWNlIGNhbGxlZCBmb3IgJywgZG9tYWluTmFtZSwgYXBwbGljYXRpb25OYW1lLCBzZXJ2aWNlTmFtZSk7XG4gICAgICAgICAgICB0aGlzLnNlcnZpY2VzU2VydmljZS5kZWxldGVTZXJ2aWNlKGNoYW5uZWwsIGRvbWFpbk5hbWUsIGFwcGxpY2F0aW9uTmFtZSwgc2VydmljZU5hbWUpLnN1YnNjcmliZSgoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoZGF0YSk7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGVsZXRlT3BlcmF0aW9uKGNoYW5uZWw6IHN0cmluZyxcbiAgICAgICAgZG9tYWluTmFtZTogc3RyaW5nLFxuICAgICAgICBhcHBsaWNhdGlvbk5hbWU6IHN0cmluZyxcbiAgICAgICAgc2VydmljZU5hbWU6IHN0cmluZyxcbiAgICAgICAgb3BlcmF0aW9uTmFtZTogc3RyaW5nKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKChvYnNlcnZlcikgPT4ge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoTE9HX1RBRywgJ2RlbGV0ZU9wZXJhdGlvbiBjYWxsZWQgZm9yICcsIGRvbWFpbk5hbWUsIGFwcGxpY2F0aW9uTmFtZSwgc2VydmljZU5hbWUsIG9wZXJhdGlvbk5hbWUpO1xuICAgICAgICAgICAgdGhpcy5vcGVyYXRpb25zU2VydmljZS5kZWxldGVTZXJ2aWNlT3BlcmF0aW9uKGNoYW5uZWwsXG4gICAgICAgICAgICAgICAgZG9tYWluTmFtZSwgYXBwbGljYXRpb25OYW1lLCBzZXJ2aWNlTmFtZSwgb3BlcmF0aW9uTmFtZSkuIHN1YnNjcmliZSgoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxufVxuXG5cblxuIl19