UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

200 lines 29.6 kB
import { inject, Injectable } from '@angular/core'; import { AlertService, GainsightService, gettext, HumanizeAppNamePipe, PluginsService } from '@c8y/ngx-components'; import { ApplicationType } from '@c8y/client'; import { AppsToUpdateRemotesSelectComponent } from './apps-to-update-remotes-select.component'; import { firstValueFrom } from 'rxjs'; import { TranslateService } from '@ngx-translate/core'; import { pick } from 'lodash-es'; import { BsModalService } from 'ngx-bootstrap/modal'; import { EcosystemService, PRODUCT_EXPERIENCE_ECOSYSTEM } from '@c8y/ngx-components/ecosystem/shared'; import * as i0 from "@angular/core"; export class PluginListService { constructor() { this.CURRENT_LOCATION = location.href; this.updatingPluginId = { install: '', uninstall: '' }; this.appsDisabled = new Set(); this.gainsightService = inject(GainsightService); this.pluginsService = inject(PluginsService); this.alertService = inject(AlertService); this.ecosystemService = inject(EcosystemService); this.humanizeAppNamePipe = inject(HumanizeAppNamePipe); this.translateService = inject(TranslateService); this.bsModalService = inject(BsModalService); } async updateAppRemotes(plugin, updateType, pluginPackage) { this.updatingPluginId[updateType] = plugin?.id; let initialState; try { const apps = await this.getAppsForUpdate(plugin, updateType); initialState = { apps, updateType, pluginName: plugin.name, appsDisabled: this.appsDisabled }; } catch (e) { this.alertService.addServerFailure(e); this.updatingPluginId[updateType] = ''; return; } let selectedApps; try { selectedApps = await this.selectApps(initialState); if (!selectedApps) { this.updatingPluginId[updateType] = ''; return; } } catch { // unreached } if (updateType === 'install') { const isArchived = await this.ecosystemService.verifyArchived([plugin]); if (!isArchived) { this.updatingPluginId[updateType] = ''; return; } const licensesVerifiedByUser = await this.ecosystemService.verifyLicenses([plugin]); if (!licensesVerifiedByUser) { this.updatingPluginId[updateType] = ''; return; } } for (const app of selectedApps) { try { if (updateType === 'install') { const versionIsCompatible = await this.ecosystemService.verifyPluginVersionsCompatibility([plugin], app); if (!versionIsCompatible) { continue; } } await this.handleRemotesUpdate(app, plugin, updateType, pluginPackage); const humanizedAppName = await firstValueFrom(this.humanizeAppNamePipe.transform(app)); const successText = updateType === 'install' ? this.translateService.instant(gettext('Plugin installed to application "{{ appName }}".'), { appName: humanizedAppName }) : this.translateService.instant(gettext('Plugin uninstalled from application "{{ appName }}".'), { appName: humanizedAppName }); this.alertService.success(successText); this.onUpdateEventHandleGS(plugin, app, updateType); } catch (error) { this.onUpdateEventHandleGS(plugin, app, updateType, error); } } this.updatingPluginId[updateType] = ''; } async getAppsForUpdate(plugin, updateType) { let apps = (await this.ecosystemService.getWebApplications()).filter(app => this.ecosystemService.isOwner(app) && app.type !== ApplicationType.EXTERNAL); if (updateType === 'install') { this.appsDisabled.clear(); for (const app of apps) { if (this.isPluginInstalledInApp(plugin, app)) { this.appsDisabled.add(app.id); } } } if (updateType === 'uninstall') { const installedApps = []; for (const app of apps) { if (this.isPluginInstalledInApp(plugin, app)) { installedApps.push(app); } } apps = installedApps; } return apps; } onUpdateEventHandleGS(plugin, app, updateType, error) { const pluginCustomEventInfo = pick(plugin, [ 'name', 'contextPath', 'module', 'version', 'type', 'id' ]); const gsEventResult = updateType === 'install' ? PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.PLUGIN_INSTALLED : PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.PLUGIN_REMOVED; const eventData = { component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.PLUGIN_LIST, result: error || gsEventResult, url: this.CURRENT_LOCATION, ...pluginCustomEventInfo, targetApplicationName: app.name, targetApplicationContextPath: app.contextPath, ...(error && { error }) }; this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_PLUGINS, eventData); } isPluginInstalledInApp(plugin, app) { const appRemotes = this.pluginsService.getMFRemotes(app) || {}; for (const [remoteName, modules] of Object.entries(appRemotes)) { const pluginFromThisPackageIsInstalled = this.getPluginContextPathWithoutVersion(remoteName) === plugin.contextPath; const specificPluginModuleIsInstalled = modules.some(module => module === plugin.module); if (pluginFromThisPackageIsInstalled && specificPluginModuleIsInstalled) { return true; } } return false; } getPluginContextPathWithoutVersion(remote) { return remote.split('@')[0]; } async handleRemotesUpdate(application, plugin, updateType, pluginPackage) { try { // When remotes object is not set in the configuration object of an application. // Fallback to setInitialRemotes is triggered. const { remotes, excludedRemotes } = await (updateType === 'install' ? this.pluginsService.addRemotes(application, plugin) : this.pluginsService.removeRemotes(application, this.getAllPluginsToRemove(plugin, pluginPackage))); if (!application.config) { application.config = {}; } application.config.remotes = remotes; application.config.excludedRemotes = excludedRemotes; const actualRemotes = this.pluginsService.getMFRemotes(application); return actualRemotes; } catch (er) { if (er) { this.alertService.addServerFailure(er); } throw er; } } getAllPluginsToRemove(plugin, pluginPackage) { return pluginPackage.applicationVersions.map(av => ({ id: `${plugin.contextPath}@${av.version}/${plugin.module}`, idLatest: `${plugin.contextPath}/${plugin.module}`, module: plugin.module, path: plugin.path })); } async selectApps(initialState) { try { return await this.bsModalService.show(AppsToUpdateRemotesSelectComponent, { class: 'modal-sm', ariaDescribedby: 'modal-body', ariaLabelledBy: 'modal-title', initialState, ignoreBackdropClick: true, keyboard: false }).content.result; } catch (er) { return; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWxpc3Quc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2Vjb3N5c3RlbS9hcHBsaWNhdGlvbi1wbHVnaW5zL3BsdWdpbi1saXN0LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUNMLFlBQVksRUFFWixnQkFBZ0IsRUFDaEIsT0FBTyxFQUNQLG1CQUFtQixFQUNuQixjQUFjLEVBQ2YsTUFBTSxxQkFBcUIsQ0FBQztBQUU3QixPQUFPLEVBQUUsZUFBZSxFQUFnQixNQUFNLGFBQWEsQ0FBQztBQUM1RCxPQUFPLEVBQUUsa0NBQWtDLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUMvRixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDakMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3JELE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsNEJBQTRCLEVBQzdCLE1BQU0sc0NBQXNDLENBQUM7O0FBSzlDLE1BQU0sT0FBTyxpQkFBaUI7SUFIOUI7UUFJRSxxQkFBZ0IsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO1FBQ2pDLHFCQUFnQixHQUErQixFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ3RFLGlCQUFZLEdBQTRCLElBQUksR0FBRyxFQUFzQixDQUFDO1FBRXRFLHFCQUFnQixHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzVDLG1CQUFjLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3hDLGlCQUFZLEdBQUcsTUFB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LEVBQUUsR0FBRyxNQUFNLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUMxRCxRQUFRLEVBQUUsR0FBRyxNQUFNLENBQUMsV0FBVyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUU7WUFDbEQsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1lBQ3JCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtTQUNsQixDQUFDLENBQUMsQ0FBQztJQUNOLENBQUM7SUFFTyxLQUFLLENBQUMsVUFBVSxDQUN0QixZQUdDO1FBRUQsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUNMLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxFQUFFO2dCQUMzRCxLQUFLLEVBQUUsVUFBVTtnQkFDakIsZUFBZSxFQUFFLFlBQVk7Z0JBQzdCLGNBQWMsRUFBRSxhQUFhO2dCQUM3QixZQUFZO2dCQUNaLG1CQUFtQixFQUFFLElBQUk7Z0JBQ3pCLFFBQVEsRUFBRSxLQUFLO2FBQ2hCLENBQUMsQ0FBQyxPQUNKLENBQUMsTUFBTSxDQUFDO1FBQ1gsQ0FBQztRQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDWixPQUFPO1FBQ1QsQ0FBQztJQUNILENBQUM7K0dBalBVLGlCQUFpQjttSEFBakIsaUJBQWlCLGNBRmhCLE1BQU07OzRGQUVQLGlCQUFpQjtrQkFIN0IsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEFsZXJ0U2VydmljZSxcbiAgQXBwbGljYXRpb25QbHVnaW4sXG4gIEdhaW5zaWdodFNlcnZpY2UsXG4gIGdldHRleHQsXG4gIEh1bWFuaXplQXBwTmFtZVBpcGUsXG4gIFBsdWdpbnNTZXJ2aWNlXG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHsgVXBkYXRlVHlwZSB9IGZyb20gJy4vYXBwcy10by11cGRhdGUtcmVtb3Rlcy1zZWxlY3QubW9kZWwnO1xuaW1wb3J0IHsgQXBwbGljYXRpb25UeXBlLCBJQXBwbGljYXRpb24gfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBBcHBzVG9VcGRhdGVSZW1vdGVzU2VsZWN0Q29tcG9uZW50IH0gZnJvbSAnLi9hcHBzLXRvLXVwZGF0ZS1yZW1vdGVzLXNlbGVjdC5jb21wb25lbnQnO1xuaW1wb3J0IHsgZmlyc3RWYWx1ZUZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7IHBpY2sgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgQnNNb2RhbFNlcnZpY2UgfSBmcm9tICduZ3gtYm9vdHN0cmFwL21vZGFsJztcbmltcG9ydCB7XG4gIEVjb3N5c3RlbVNlcnZpY2UsXG4gIFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU1cbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9lY29zeXN0ZW0vc2hhcmVkJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgUGx1Z2luTGlzdFNlcnZpY2Uge1xuICBDVVJSRU5UX0xPQ0FUSU9OID0gbG9jYXRpb24uaHJlZjtcbiAgdXBkYXRpbmdQbHVnaW5JZDogUmVjb3JkPFVwZGF0ZVR5cGUsIHN0cmluZz4gPSB7IGluc3RhbGw6ICcnLCB1bmluc3RhbGw6ICcnIH07XG4gIHByaXZhdGUgYXBwc0Rpc2FibGVkOiBTZXQ8SUFwcGxpY2F0aW9uWydpZCddPiA9IG5ldyBTZXQ8SUFwcGxpY2F0aW9uWydpZCddPigpO1xuXG4gIHByaXZhdGUgZ2FpbnNpZ2h0U2VydmljZSA9IGluamVjdChHYWluc2lnaHRTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBwbHVnaW5zU2VydmljZSA9IGluamVjdChQbHVnaW5zU2VydmljZSk7XG4gIHByaXZhdGUgYWxlcnRTZXJ2aWNlID0gaW5qZWN0KEFsZXJ0U2VydmljZSk7XG4gIHByaXZhdGUgZWNvc3lzdGVtU2VydmljZSA9IGluamVjdChFY29zeXN0ZW1TZXJ2aWNlKTtcbiAgcHJpdmF0ZSBodW1hbml6ZUFwcE5hbWVQaXBlID0gaW5qZWN0KEh1bWFuaXplQXBwTmFtZVBpcGUpO1xuICBwcml2YXRlIHRyYW5zbGF0ZVNlcnZpY2UgPSBpbmplY3QoVHJhbnNsYXRlU2VydmljZSk7XG4gIHByaXZhdGUgYnNNb2RhbFNlcnZpY2UgPSBpbmplY3QoQnNNb2RhbFNlcnZpY2UpO1xuXG4gIGFzeW5jIHVwZGF0ZUFwcFJlbW90ZXMoXG4gICAgcGx1Z2luOiBBcHBsaWNhdGlvblBsdWdpbixcbiAgICB1cGRhdGVUeXBlOiBVcGRhdGVUeXBlLFxuICAgIHBsdWdpblBhY2thZ2U6IElBcHBsaWNhdGlvblxuICApIHtcbiAgICB0aGlzLnVwZGF0aW5nUGx1Z2luSWRbdXBkYXRlVHlwZV0gPSBwbHVnaW4/LmlkO1xuICAgIGxldCBpbml0aWFsU3RhdGU6IFBpY2s8XG4gICAgICBBcHBzVG9VcGRhdGVSZW1vdGVzU2VsZWN0Q29tcG9uZW50LFxuICAgICAgJ2FwcHMnIHwgJ3VwZGF0ZVR5cGUnIHwgJ3BsdWdpbk5hbWUnIHwgJ2FwcHNEaXNhYmxlZCdcbiAgICA+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcHBzID0gYXdhaXQgdGhpcy5nZXRBcHBzRm9yVXBkYXRlKHBsdWdpbiwgdXBkYXRlVHlwZSk7XG5cbiAgICAgIGluaXRpYWxTdGF0ZSA9IHtcbiAgICAgICAgYXBwcyxcbiAgICAgICAgdXBkYXRlVHlwZSxcbiAgICAgICAgcGx1Z2luTmFtZTogcGx1Z2luLm5hbWUsXG4gICAgICAgIGFwcHNEaXNhYmxlZDogdGhpcy5hcHBzRGlzYWJsZWRcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5hbGVydFNlcnZpY2UuYWRkU2VydmVyRmFpbHVyZShlKTtcbiAgICAgIHRoaXMudXBkYXRpbmdQbHVnaW5JZFt1cGRhdGVUeXBlXSA9ICcnO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBzZWxlY3RlZEFwcHM6IElBcHBsaWNhdGlvbltdO1xuICAgIHRyeSB7XG4gICAgICBzZWxlY3RlZEFwcHMgPSBhd2FpdCB0aGlzLnNlbGVjdEFwcHMoaW5pdGlhbFN0YXRlKTtcbiAgICAgIGlmICghc2VsZWN0ZWRBcHBzKSB7XG4gICAgICAgIHRoaXMudXBkYXRpbmdQbHVnaW5JZFt1cGRhdGVUeXBlXSA9ICcnO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyB1bnJlYWNoZWRcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlVHlwZSA9PT0gJ2luc3RhbGwnKSB7XG4gICAgICBjb25zdCBpc0FyY2hpdmVkID0gYXdhaXQgdGhpcy5lY29zeXN0ZW1TZXJ2aWNlLnZlcmlmeUFyY2hpdmVkKFtwbHVnaW5dKTtcbiAgICAgIGlmICghaXNBcmNoaXZlZCkge1xuICAgICAgICB0aGlzLnVwZGF0aW5nUGx1Z2luSWRbdXBkYXRlVHlwZV0gPSAnJztcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBsaWNlbnNlc1ZlcmlmaWVkQnlVc2VyID0gYXdhaXQgdGhpcy5lY29zeXN0ZW1TZXJ2aWNlLnZlcmlmeUxpY2Vuc2VzKFtwbHVnaW5dKTtcbiAgICAgIGlmICghbGljZW5zZXNWZXJpZmllZEJ5VXNlcikge1xuICAgICAgICB0aGlzLnVwZGF0aW5nUGx1Z2luSWRbdXBkYXRlVHlwZV0gPSAnJztcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgYXBwIG9mIHNlbGVjdGVkQXBwcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKHVwZGF0ZVR5cGUgPT09ICdpbnN0YWxsJykge1xuICAgICAgICAgIGNvbnN0IHZlcnNpb25Jc0NvbXBhdGlibGUgPSBhd2FpdCB0aGlzLmVjb3N5c3RlbVNlcnZpY2UudmVyaWZ5UGx1Z2luVmVyc2lvbnNDb21wYXRpYmlsaXR5KFxuICAgICAgICAgICAgW3BsdWdpbl0sXG4gICAgICAgICAgICBhcHBcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgaWYgKCF2ZXJzaW9uSXNDb21wYXRpYmxlKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZVJlbW90ZXNVcGRhdGUoYXBwLCBwbHVnaW4sIHVwZGF0ZVR5cGUsIHBsdWdpblBhY2thZ2UpO1xuICAgICAgICBjb25zdCBodW1hbml6ZWRBcHBOYW1lID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20odGhpcy5odW1hbml6ZUFwcE5hbWVQaXBlLnRyYW5zZm9ybShhcHApKTtcbiAgICAgICAgY29uc3Qgc3VjY2Vzc1RleHQgPVxuICAgICAgICAgIHVwZGF0ZVR5cGUgPT09ICdpbnN0YWxsJ1xuICAgICAgICAgICAgPyB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChcbiAgICAgICAgICAgICAgICBnZXR0ZXh0KCdQbHVnaW4gaW5zdGFsbGVkIHRvIGFwcGxpY2F0aW9uIFwie3sgYXBwTmFtZSB9fVwiLicpLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGFwcE5hbWU6IGh1bWFuaXplZEFwcE5hbWVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIDogdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoXG4gICAgICAgICAgICAgICAgZ2V0dGV4dCgnUGx1Z2luIHVuaW5zdGFsbGVkIGZyb20gYXBwbGljYXRpb24gXCJ7eyBhcHBOYW1lIH19XCIuJyksXG4gICAgICAgICAgICAgICAgeyBhcHBOYW1lOiBodW1hbml6ZWRBcHBOYW1lIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgdGhpcy5hbGVydFNlcnZpY2Uuc3VjY2VzcyhzdWNjZXNzVGV4dCk7XG4gICAgICAgIHRoaXMub25VcGRhdGVFdmVudEhhbmRsZUdTKHBsdWdpbiwgYXBwLCB1cGRhdGVUeXBlKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRoaXMub25VcGRhdGVFdmVudEhhbmRsZUdTKHBsdWdpbiwgYXBwLCB1cGRhdGVUeXBlLCBlcnJvcik7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMudXBkYXRpbmdQbHVnaW5JZFt1cGRhdGVUeXBlXSA9ICcnO1xuICB9XG5cbiAgYXN5bmMgZ2V0QXBwc0ZvclVwZGF0ZShwbHVnaW46IEFwcGxpY2F0aW9uUGx1Z2luLCB1cGRhdGVUeXBlOiBVcGRhdGVUeXBlKSB7XG4gICAgbGV0IGFwcHMgPSAoYXdhaXQgdGhpcy5lY29zeXN0ZW1TZXJ2aWNlLmdldFdlYkFwcGxpY2F0aW9ucygpKS5maWx0ZXIoXG4gICAgICBhcHAgPT4gdGhpcy5lY29zeXN0ZW1TZXJ2aWNlLmlzT3duZXIoYXBwKSAmJiBhcHAudHlwZSAhPT0gQXBwbGljYXRpb25UeXBlLkVYVEVSTkFMXG4gICAgKTtcblxuICAgIGlmICh1cGRhdGVUeXBlID09PSAnaW5zdGFsbCcpIHtcbiAgICAgIHRoaXMuYXBwc0Rpc2FibGVkLmNsZWFyKCk7XG4gICAgICBmb3IgKGNvbnN0IGFwcCBvZiBhcHBzKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUGx1Z2luSW5zdGFsbGVkSW5BcHAocGx1Z2luLCBhcHApKSB7XG4gICAgICAgICAgdGhpcy5hcHBzRGlzYWJsZWQuYWRkKGFwcC5pZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodXBkYXRlVHlwZSA9PT0gJ3VuaW5zdGFsbCcpIHtcbiAgICAgIGNvbnN0IGluc3RhbGxlZEFwcHM6IElBcHBsaWNhdGlvbltdID0gW107XG4gICAgICBmb3IgKGNvbnN0IGFwcCBvZiBhcHBzKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUGx1Z2luSW5zdGFsbGVkSW5BcHAocGx1Z2luLCBhcHApKSB7XG4gICAgICAgICAgaW5zdGFsbGVkQXBwcy5wdXNoKGFwcCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGFwcHMgPSBpbnN0YWxsZWRBcHBzO1xuICAgIH1cbiAgICByZXR1cm4gYXBwcztcbiAgfVxuXG4gIHByaXZhdGUgb25VcGRhdGVFdmVudEhhbmRsZUdTKFxuICAgIHBsdWdpbjogQXBwbGljYXRpb25QbHVnaW4sXG4gICAgYXBwOiBJQXBwbGljYXRpb24sXG4gICAgdXBkYXRlVHlwZTogVXBkYXRlVHlwZSxcbiAgICBlcnJvcj86IHVua25vd25cbiAgKSB7XG4gICAgY29uc3QgcGx1Z2luQ3VzdG9tRXZlbnRJbmZvID0gcGljayhwbHVnaW4sIFtcbiAgICAgICduYW1lJyxcbiAgICAgICdjb250ZXh0UGF0aCcsXG4gICAgICAnbW9kdWxlJyxcbiAgICAgICd2ZXJzaW9uJyxcbiAgICAgICd0eXBlJyxcbiAgICAgICdpZCdcbiAgICBdIHNhdGlzZmllcyAoa2V5b2YgQXBwbGljYXRpb25QbHVnaW4pW10pO1xuXG4gICAgY29uc3QgZ3NFdmVudFJlc3VsdCA9XG4gICAgICB1cGRhdGVUeXBlID09PSAnaW5zdGFsbCdcbiAgICAgICAgPyBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5SRVNVTFRTLlBMVUdJTl9JTlNUQUxMRURcbiAgICAgICAgOiBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5SRVNVTFRTLlBMVUdJTl9SRU1PVkVEO1xuXG4gICAgY29uc3QgZXZlbnREYXRhID0ge1xuICAgICAgY29tcG9uZW50OiBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5DT01QT05FTlRTLlBMVUdJTl9MSVNULFxuICAgICAgcmVzdWx0OiBlcnJvciB8fCBnc0V2ZW50UmVzdWx0LFxuICAgICAgdXJsOiB0aGlzLkNVUlJFTlRfTE9DQVRJT04sXG4gICAgICAuLi5wbHVnaW5DdXN0b21FdmVudEluZm8sXG4gICAgICB0YXJnZXRBcHBsaWNhdGlvbk5hbWU6IGFwcC5uYW1lLFxuICAgICAgdGFyZ2V0QXBwbGljYXRpb25Db250ZXh0UGF0aDogYXBwLmNvbnRleHRQYXRoLFxuICAgICAgLi4uKGVycm9yICYmIHsgZXJyb3IgfSlcbiAgICB9O1xuXG4gICAgdGhpcy5nYWluc2lnaHRTZXJ2aWNlLnRyaWdnZXJFdmVudChcbiAgICAgIFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLkVWRU5UUy5QQUNLQUdFX1BMVUdJTlMsXG4gICAgICBldmVudERhdGFcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1BsdWdpbkluc3RhbGxlZEluQXBwKHBsdWdpbjogQXBwbGljYXRpb25QbHVnaW4sIGFwcDogSUFwcGxpY2F0aW9uKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYXBwUmVtb3RlcyA9IHRoaXMucGx1Z2luc1NlcnZpY2UuZ2V0TUZSZW1vdGVzKGFwcCkgfHwge307XG5cbiAgICBmb3IgKGNvbnN0IFtyZW1vdGVOYW1lLCBtb2R1bGVzXSBvZiBPYmplY3QuZW50cmllcyhhcHBSZW1vdGVzKSkge1xuICAgICAgY29uc3QgcGx1Z2luRnJvbVRoaXNQYWNrYWdlSXNJbnN0YWxsZWQgPVxuICAgICAgICB0aGlzLmdldFBsdWdpbkNvbnRleHRQYXRoV2l0aG91dFZlcnNpb24ocmVtb3RlTmFtZSkgPT09IHBsdWdpbi5jb250ZXh0UGF0aDtcbiAgICAgIGNvbnN0IHNwZWNpZmljUGx1Z2luTW9kdWxlSXNJbnN0YWxsZWQgPSBtb2R1bGVzLnNvbWUobW9kdWxlID0+IG1vZHVsZSA9PT0gcGx1Z2luLm1vZHVsZSk7XG4gICAgICBpZiAocGx1Z2luRnJvbVRoaXNQYWNrYWdlSXNJbnN0YWxsZWQgJiYgc3BlY2lmaWNQbHVnaW5Nb2R1bGVJc0luc3RhbGxlZCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQbHVnaW5Db250ZXh0UGF0aFdpdGhvdXRWZXJzaW9uKHJlbW90ZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHJlbW90ZS5zcGxpdCgnQCcpWzBdO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVSZW1vdGVzVXBkYXRlKFxuICAgIGFwcGxpY2F0aW9uOiBJQXBwbGljYXRpb24sXG4gICAgcGx1Z2luOiBBcHBsaWNhdGlvblBsdWdpbixcbiAgICB1cGRhdGVUeXBlOiBVcGRhdGVUeXBlLFxuICAgIHBsdWdpblBhY2thZ2U6IElBcHBsaWNhdGlvblxuICApIHtcbiAgICB0cnkge1xuICAgICAgLy8gV2hlbiByZW1vdGVzIG9iamVjdCBpcyBub3Qgc2V0IGluIHRoZSBjb25maWd1cmF0aW9uIG9iamVjdCBvZiBhbiBhcHBsaWNhdGlvbi5cbiAgICAgIC8vIEZhbGxiYWNrIHRvIHNldEluaXRpYWxSZW1vdGVzIGlzIHRyaWdnZXJlZC5cbiAgICAgIGNvbnN0IHsgcmVtb3RlcywgZXhjbHVkZWRSZW1vdGVzIH0gPSBhd2FpdCAodXBkYXRlVHlwZSA9PT0gJ2luc3RhbGwnXG4gICAgICAgID8gdGhpcy5wbHVnaW5zU2VydmljZS5hZGRSZW1vdGVzKGFwcGxpY2F0aW9uLCBwbHVnaW4pXG4gICAgICAgIDogdGhpcy5wbHVnaW5zU2VydmljZS5yZW1vdmVSZW1vdGVzKFxuICAgICAgICAgICAgYXBwbGljYXRpb24sXG4gICAgICAgICAgICB0aGlzLmdldEFsbFBsdWdpbnNUb1JlbW92ZShwbHVnaW4sIHBsdWdpblBhY2thZ2UpXG4gICAgICAgICAgKSk7XG4gICAgICBpZiAoIWFwcGxpY2F0aW9uLmNvbmZpZykge1xuICAgICAgICBhcHBsaWNhdGlvbi5jb25maWcgPSB7fTtcbiAgICAgIH1cbiAgICAgIGFwcGxpY2F0aW9uLmNvbmZpZy5yZW1vdGVzID0gcmVtb3RlcztcbiAgICAgIGFwcGxpY2F0aW9uLmNvbmZpZy5leGNsdWRlZFJlbW90ZXMgPSBleGNsdWRlZFJlbW90ZXM7XG4gICAgICBjb25zdCBhY3R1YWxSZW1vdGVzID0gdGhpcy5wbHVnaW5zU2VydmljZS5nZXRNRlJlbW90ZXMoYXBwbGljYXRpb24pO1xuICAgICAgcmV0dXJuIGFjdHVhbFJlbW90ZXM7XG4gICAgfSBjYXRjaCAoZXIpIHtcbiAgICAgIGlmIChlcikge1xuICAgICAgICB0aGlzLmFsZXJ0U2VydmljZS5hZGRTZXJ2ZXJGYWlsdXJlKGVyKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVyO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0QWxsUGx1Z2luc1RvUmVtb3ZlKFxuICAgIHBsdWdpbjogQXBwbGljYXRpb25QbHVnaW4sXG4gICAgcGx1Z2luUGFja2FnZTogSUFwcGxpY2F0aW9uXG4gICk6IEFwcGxpY2F0aW9uUGx1Z2luW10ge1xuICAgIHJldHVybiBwbHVnaW5QYWNrYWdlLmFwcGxpY2F0aW9uVmVyc2lvbnMubWFwKGF2ID0+ICh7XG4gICAgICBpZDogYCR7cGx1Z2luLmNvbnRleHRQYXRofUAke2F2LnZlcnNpb259LyR7cGx1Z2luLm1vZHVsZX1gLFxuICAgICAgaWRMYXRlc3Q6IGAke3BsdWdpbi5jb250ZXh0UGF0aH0vJHtwbHVnaW4ubW9kdWxlfWAsXG4gICAgICBtb2R1bGU6IHBsdWdpbi5tb2R1bGUsXG4gICAgICBwYXRoOiBwbHVnaW4ucGF0aFxuICAgIH0pKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2VsZWN0QXBwcyhcbiAgICBpbml0aWFsU3RhdGU6IFBpY2s8XG4gICAgICBBcHBzVG9VcGRhdGVSZW1vdGVzU2VsZWN0Q29tcG9uZW50LFxuICAgICAgJ2FwcHMnIHwgJ3VwZGF0ZVR5cGUnIHwgJ3BsdWdpbk5hbWUnIHwgJ2FwcHNEaXNhYmxlZCdcbiAgICA+XG4gICk6IFByb21pc2U8SUFwcGxpY2F0aW9uW10+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IChcbiAgICAgICAgdGhpcy5ic01vZGFsU2VydmljZS5zaG93KEFwcHNUb1VwZGF0ZVJlbW90ZXNTZWxlY3RDb21wb25lbnQsIHtcbiAgICAgICAgICBjbGFzczogJ21vZGFsLXNtJyxcbiAgICAgICAgICBhcmlhRGVzY3JpYmVkYnk6ICdtb2RhbC1ib2R5JyxcbiAgICAgICAgICBhcmlhTGFiZWxsZWRCeTogJ21vZGFsLXRpdGxlJyxcbiAgICAgICAgICBpbml0aWFsU3RhdGUsXG4gICAgICAgICAgaWdub3JlQmFja2Ryb3BDbGljazogdHJ1ZSxcbiAgICAgICAgICBrZXlib2FyZDogZmFsc2VcbiAgICAgICAgfSkuY29udGVudCBhcyBBcHBzVG9VcGRhdGVSZW1vdGVzU2VsZWN0Q29tcG9uZW50XG4gICAgICApLnJlc3VsdDtcbiAgICB9IGNhdGNoIChlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxufVxuIl19