UNPKG

@alfresco/adf-content-services

Version:
270 lines 41 kB
/*! * @license * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Injectable } from '@angular/core'; import { ContentApi, RenditionsApi, VersionsApi } from '@alfresco/js-api'; import { TranslationService, ViewUtilService } from '@alfresco/adf-core'; import { AlfrescoApiService } from '../../services/alfresco-api.service'; import * as i0 from "@angular/core"; import * as i1 from "../../services/alfresco-api.service"; import * as i2 from "@alfresco/adf-core"; export class RenditionService { static { this.TARGET = '_new'; } /** * Content groups based on categorization of files that can be viewed in the web browser. This * implementation or grouping is tied to the definition the ng component: ViewerRenderComponent */ static { this.ContentGroup = { IMAGE: 'image', MEDIA: 'media', PDF: 'pdf', TEXT: 'text' }; } /** * The name of the rendition with the media subtitles in the supported format */ static { this.SUBTITLES_RENDITION_NAME = 'webvtt'; } get renditionsApi() { this._renditionsApi = this._renditionsApi ?? new RenditionsApi(this.apiService.getInstance()); return this._renditionsApi; } get contentApi() { this._contentApi = this._contentApi ?? new ContentApi(this.apiService.getInstance()); return this._contentApi; } get versionsApi() { this._versionsApi = this._versionsApi ?? new VersionsApi(this.apiService.getInstance()); return this._versionsApi; } constructor(apiService, translateService, viewUtilsService) { this.apiService = apiService; this.translateService = translateService; this.viewUtilsService = viewUtilsService; /** * Based on ViewerRenderComponent Implementation, this value is used to determine how many times we try * to get the rendition of a file for preview, or printing. */ this.maxRetries = 5; /** * Timeout used for setInterval. */ this.TRY_TIMEOUT = 10000; this.DEFAULT_RENDITION = 'imgpreview'; } getRenditionUrl(nodeId, type, renditionExists) { return renditionExists && type !== RenditionService.ContentGroup.IMAGE ? this.contentApi.getRenditionUrl(nodeId, RenditionService.ContentGroup.PDF) : this.contentApi.getContentUrl(nodeId, false); } async waitRendition(nodeId, renditionId, retries) { if (this.maxRetries > retries) { const rendition = await this.renditionsApi.getRendition(nodeId, renditionId); const status = rendition.entry.status.toString(); if (status === 'CREATED') { return rendition; } else { retries += 1; await this.wait(1000); return this.waitRendition(nodeId, renditionId, retries); } } return Promise.resolve(null); } wait(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async getRendition(nodeId, renditionId) { const renditionPaging = await this.renditionsApi.listRenditions(nodeId); let rendition = renditionPaging.list.entries.find((renditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId); if (rendition) { const status = rendition.entry.status.toString(); if (status === 'NOT_CREATED') { try { await this.renditionsApi.createRendition(nodeId, { id: renditionId }); rendition = await this.waitRendition(nodeId, renditionId, 0); } catch { return null; } } } return new Promise((resolve) => resolve(rendition)); } async getNodeRendition(nodeId, versionId) { try { return versionId ? await this.resolveNodeRendition(nodeId, 'pdf', versionId) : await this.resolveNodeRendition(nodeId, 'pdf'); } catch { return null; } } async resolveNodeRendition(nodeId, renditionId, versionId) { renditionId = renditionId.toLowerCase(); const supportedRendition = versionId ? await this.versionsApi.listVersionRenditions(nodeId, versionId) : await this.renditionsApi.listRenditions(nodeId); let rendition = this.findRenditionById(supportedRendition, renditionId); if (!rendition) { renditionId = this.DEFAULT_RENDITION; rendition = this.findRenditionById(supportedRendition, this.DEFAULT_RENDITION); } if (rendition) { const status = rendition.entry.status.toString(); const mimeType = rendition.entry.content.mimeType; if (status === 'NOT_CREATED') { return { url: await this.requestCreateRendition(nodeId, renditionId, versionId), mimeType }; } else { return { url: await this.handleNodeRendition(nodeId, renditionId, versionId), mimeType }; } } return null; } async requestCreateRendition(nodeId, renditionId, versionId) { try { if (versionId) { await this.versionsApi.createVersionRendition(nodeId, versionId, { id: renditionId }); } else { await this.renditionsApi.createRendition(nodeId, { id: renditionId }); } try { return versionId ? await this.waitNodeRendition(nodeId, renditionId, versionId) : await this.waitNodeRendition(nodeId, renditionId); } catch (e) { return null; } } catch { return null; } } findRenditionById(supportedRendition, renditionId) { return supportedRendition.list.entries.find((renditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId); } async waitNodeRendition(nodeId, renditionId, versionId) { let currentRetry = 0; return new Promise((resolve, reject) => { const intervalId = setInterval(() => { currentRetry++; if (this.maxRetries >= currentRetry) { if (versionId) { this.versionsApi.getVersionRendition(nodeId, versionId, renditionId).then((rendition) => { const status = rendition.entry.status.toString(); if (status === 'CREATED') { clearInterval(intervalId); return resolve(this.handleNodeRendition(nodeId, rendition.entry.content.mimeType, versionId)); } }, () => reject(new Error('Error geting version rendition'))); } else { this.renditionsApi.getRendition(nodeId, renditionId).then((rendition) => { const status = rendition.entry.status.toString(); if (status === 'CREATED') { clearInterval(intervalId); return resolve(this.handleNodeRendition(nodeId, renditionId, versionId)); } }, () => reject(new Error('Error getting rendition'))); } } else { clearInterval(intervalId); return reject(new Error('Error getting rendition')); } }, this.TRY_TIMEOUT); }); } async handleNodeRendition(nodeId, renditionId, versionId) { return versionId ? this.contentApi.getVersionRenditionUrl(nodeId, versionId, renditionId) : this.contentApi.getRenditionUrl(nodeId, renditionId); } async generateMediaTracksRendition(nodeId) { return this.isRenditionAvailable(nodeId, RenditionService.SUBTITLES_RENDITION_NAME) .then((value) => { const tracks = []; if (value) { tracks.push({ kind: 'subtitles', src: this.contentApi.getRenditionUrl(nodeId, RenditionService.SUBTITLES_RENDITION_NAME), label: this.translateService.instant('ADF_VIEWER.SUBTITLES') }); } return tracks; }) .catch(() => []); } async isRenditionAvailable(nodeId, renditionId) { const renditionPaging = await this.renditionsApi.listRenditions(nodeId); const rendition = renditionPaging.list.entries.find((renditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId); return rendition?.entry?.status?.toString() === 'CREATED' || false; } /** * This method takes a url to trigger the print dialog against, and the type of artifact that it * is. * This URL should be one that can be rendered in the browser, for example PDF, Image, or Text * * @param url url to print * @param type type of the rendition */ printFile(url, type) { const pwa = window.open(url, RenditionService.TARGET); if (pwa) { pwa.onload = () => { pwa.print(); if (type === RenditionService.ContentGroup.IMAGE) { // Because of the way chrome focus and close image window vs. pdf preview window setTimeout(() => { pwa.close(); }, 500); } }; } } /** * Launch the File Print dialog from anywhere other than the preview service, which resolves the * rendition of the object that can be printed from a web browser. * These are: images, PDF files, or PDF rendition of files. * We also force PDF rendition for TEXT type objects, otherwise the default URL is to download. * TODO there are different TEXT type objects, (HTML, plaintext, xml, etc. we should determine how these are handled) * * @param objectId object it * @param mimeType mime type */ printFileGeneric(objectId, mimeType) { const nodeId = objectId; const type = this.viewUtilsService.getViewerTypeByMimeType(mimeType); this.getRendition(nodeId, RenditionService.ContentGroup.PDF) .then((value) => { const url = this.getRenditionUrl(nodeId, type, !!value); const printType = type === RenditionService.ContentGroup.PDF || type === RenditionService.ContentGroup.TEXT ? RenditionService.ContentGroup.PDF : type; this.printFile(url, printType); }) .catch(() => { }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: RenditionService, deps: [{ token: i1.AlfrescoApiService }, { token: i2.TranslationService }, { token: i2.ViewUtilService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: RenditionService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: RenditionService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.AlfrescoApiService }, { type: i2.TranslationService }, { type: i2.ViewUtilService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGl0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL2NvbW1vbi9zZXJ2aWNlcy9yZW5kaXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxVQUFVLEVBQW1DLGFBQWEsRUFBRSxXQUFXLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMzRyxPQUFPLEVBQVMsa0JBQWtCLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDaEYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0scUNBQXFDLENBQUM7Ozs7QUFLekUsTUFBTSxPQUFPLGdCQUFnQjthQUNsQixXQUFNLEdBQUcsTUFBTSxBQUFULENBQVU7SUFFdkI7OztPQUdHO2FBQ0ksaUJBQVksR0FBRztRQUNsQixLQUFLLEVBQUUsT0FBTztRQUNkLEtBQUssRUFBRSxPQUFPO1FBQ2QsR0FBRyxFQUFFLEtBQUs7UUFDVixJQUFJLEVBQUUsTUFBTTtLQUNmLEFBTGtCLENBS2pCO0lBRUY7O09BRUc7YUFDSSw2QkFBd0IsR0FBRyxRQUFRLEFBQVgsQ0FBWTtJQWMzQyxJQUFJLGFBQWE7UUFDYixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxjQUFjLElBQUksSUFBSSxhQUFhLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQzlGLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUMvQixDQUFDO0lBR0QsSUFBSSxVQUFVO1FBQ1YsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFF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QUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQzthQUN2RCxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNaLE1BQU0sR0FBRyxHQUFXLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEUsTUFBTSxTQUFTLEdBQ1gsSUFBSSxLQUFLLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxHQUFHLElBQUksSUFBSSxLQUFLLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxJQUFJO2dCQUNyRixDQUFDLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLEdBQUc7Z0JBQ25DLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDZixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNuQyxDQUFDLENBQUM7YUFDRCxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekIsQ0FBQzs4R0FqUlEsZ0JBQWdCO2tIQUFoQixnQkFBZ0IsY0FGYixNQUFNOzsyRkFFVCxnQkFBZ0I7a0JBSDVCLFVBQVU7bUJBQUM7b0JBQ1IsVUFBVSxFQUFFLE1BQU07aUJBQ3JCIiwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IMKpIDIwMDUtMjAyNSBIeWxhbmQgU29mdHdhcmUsIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb250ZW50QXBpLCBSZW5kaXRpb25FbnRyeSwgUmVuZGl0aW9uUGFnaW5nLCBSZW5kaXRpb25zQXBpLCBWZXJzaW9uc0FwaSB9IGZyb20gJ0BhbGZyZXNjby9qcy1hcGknO1xuaW1wb3J0IHsgVHJhY2ssIFRyYW5zbGF0aW9uU2VydmljZSwgVmlld1V0aWxTZXJ2aWNlIH0gZnJvbSAnQGFsZnJlc2NvL2FkZi1jb3JlJztcbmltcG9ydCB7IEFsZnJlc2NvQXBpU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FsZnJlc2NvLWFwaS5zZXJ2aWNlJztcblxuQEluamVjdGFibGUoe1xuICAgIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBSZW5kaXRpb25TZXJ2aWNlIHtcbiAgICBzdGF0aWMgVEFSR0VUID0gJ19uZXcnO1xuXG4gICAgLyoqXG4gICAgICogQ29udGVudCBncm91cHMgYmFzZWQgb24gY2F0ZWdvcml6YXRpb24gb2YgZmlsZXMgdGhhdCBjYW4gYmUgdmlld2VkIGluIHRoZSB3ZWIgYnJvd3Nlci4gVGhpc1xuICAgICAqIGltcGxlbWVudGF0aW9uIG9yIGdyb3VwaW5nIGlzIHRpZWQgdG8gdGhlIGRlZmluaXRpb24gdGhlIG5nIGNvbXBvbmVudDogVmlld2VyUmVuZGVyQ29tcG9uZW50XG4gICAgICovXG4gICAgc3RhdGljIENvbnRlbnRHcm91cCA9IHtcbiAgICAgICAgSU1BR0U6ICdpbWFnZScsXG4gICAgICAgIE1FRElBOiAnbWVkaWEnLFxuICAgICAgICBQREY6ICdwZGYnLFxuICAgICAgICBURVhUOiAndGV4dCdcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHJlbmRpdGlvbiB3aXRoIHRoZSBtZWRpYSBzdWJ0aXRsZXMgaW4gdGhlIHN1cHBvcnRlZCBmb3JtYXRcbiAgICAgKi9cbiAgICBzdGF0aWMgU1VCVElUTEVTX1JFTkRJVElPTl9OQU1FID0gJ3dlYnZ0dCc7XG5cbiAgICAvKipcbiAgICAgKiBCYXNlZCBvbiBWaWV3ZXJSZW5kZXJDb21wb25lbnQgSW1wbGVtZW50YXRpb24sIHRoaXMgdmFsdWUgaXMgdXNlZCB0byBkZXRlcm1pbmUgaG93IG1hbnkgdGltZXMgd2UgdHJ5XG4gICAgICogdG8gZ2V0IHRoZSByZW5kaXRpb24gb2YgYSBmaWxlIGZvciBwcmV2aWV3LCBvciBwcmludGluZy5cbiAgICAgKi9cbiAgICBtYXhSZXRyaWVzID0gNTtcblxuICAgIC8qKlxuICAgICAqIFRpbWVvdXQgdXNlZCBmb3Igc2V0SW50ZXJ2YWwuXG4gICAgICovXG4gICAgcHJpdmF0ZSBUUllfVElNRU9VVDogbnVtYmVyID0gMTAwMDA7XG5cbiAgICBfcmVuZGl0aW9uc0FwaTogUmVuZGl0aW9uc0FwaTtcbiAgICBnZXQgcmVuZGl0aW9uc0FwaSgpOiBSZW5kaXRpb25zQXBpIHtcbiAgICAgICAgdGhpcy5fcmVuZGl0aW9uc0FwaSA9IHRoaXMuX3JlbmRpdGlvbnNBcGkgPz8gbmV3IFJlbmRpdGlvbnNBcGkodGhpcy5hcGlTZXJ2aWNlLmdldEluc3RhbmNlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVuZGl0aW9uc0FwaTtcbiAgICB9XG5cbiAgICBfY29udGVudEFwaTogQ29udGVudEFwaTtcbiAgICBnZXQgY29udGVudEFwaSgpOiBDb250ZW50QXBpIHtcbiAgICAgICAgdGhpcy5fY29udGVudEFwaSA9IHRoaXMuX2NvbnRlbnRBcGkgPz8gbmV3IENvbnRlbnRBcGkodGhpcy5hcGlTZXJ2aWNlLmdldEluc3RhbmNlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fY29udGVudEFwaTtcbiAgICB9XG5cbiAgICBfdmVyc2lvbnNBcGk6IFZlcnNpb25zQXBpO1xuICAgIHByaXZhdGUgREVGQVVMVF9SRU5ESVRJT046IHN0cmluZyA9ICdpbWdwcmV2aWV3JztcblxuICAgIGdldCB2ZXJzaW9uc0FwaSgpOiBWZXJzaW9uc0FwaSB7XG4gICAgICAgIHRoaXMuX3ZlcnNpb25zQXBpID0gdGhpcy5fdmVyc2lvbnNBcGkgPz8gbmV3IFZlcnNpb25zQXBpKHRoaXMuYXBpU2VydmljZS5nZXRJbnN0YW5jZSgpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb25zQXBpO1xuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgYXBpU2VydmljZTogQWxmcmVzY29BcGlTZXJ2aWNlLCBwcml2YXRlIHRyYW5zbGF0ZVNlcnZpY2U6IFRyYW5zbGF0aW9uU2VydmljZSwgcHJpdmF0ZSB2aWV3VXRpbHNTZXJ2aWNlOiBWaWV3VXRpbFNlcnZpY2UpIHt9XG5cbiAgICBnZXRSZW5kaXRpb25Vcmwobm9kZUlkOiBzdHJpbmcsIHR5cGU6IHN0cmluZywgcmVuZGl0aW9uRXhpc3RzOiBib29sZWFuKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHJlbmRpdGlvbkV4aXN0cyAmJiB0eXBlICE9PSBSZW5kaXRpb25TZXJ2aWNlLkNvbnRlbnRHcm91cC5JTUFHRVxuICAgICAgICAgICAgPyB0aGlzLmNvbnRlbnRBcGkuZ2V0UmVuZGl0aW9uVXJsKG5vZGVJZCwgUmVuZGl0aW9uU2VydmljZS5Db250ZW50R3JvdXAuUERGKVxuICAgICAgICAgICAgOiB0aGlzLmNvbnRlbnRBcGkuZ2V0Q29udGVudFVybChub2RlSWQsIGZhbHNlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHdhaXRSZW5kaXRpb24obm9kZUlkOiBzdHJpbmcsIHJlbmRpdGlvbklkOiBzdHJpbmcsIHJldHJpZXM6IG51bWJlcik6IFByb21pc2U8UmVuZGl0aW9uRW50cnk+IHtcbiAgICAgICAgaWYgKHRoaXMubWF4UmV0cmllcyA+IHJldHJpZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlbmRpdGlvbiA9IGF3YWl0IHRoaXMucmVuZGl0aW9uc0FwaS5nZXRSZW5kaXRpb24obm9kZUlkLCByZW5kaXRpb25JZCk7XG4gICAgICAgICAgICBjb25zdCBzdGF0dXMgPSByZW5kaXRpb24uZW50cnkuc3RhdHVzLnRvU3RyaW5nKCk7XG5cbiAgICAgICAgICAgIGlmIChzdGF0dXMgPT09ICdDUkVBVEVEJykge1xuICAgICAgICAgICAgICAgIHJldHVybiByZW5kaXRpb247XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHJpZXMgKz0gMTtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLndhaXQoMTAwMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud2FpdFJlbmRpdGlvbihub2RlSWQsIHJlbmRpdGlvbklkLCByZXRyaWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB3YWl0KG1zOiBudW1iZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbiAgICB9XG5cbiAgICBhc3luYyBnZXRSZW5kaXRpb24obm9kZUlkOiBzdHJpbmcsIHJlbmRpdGlvbklkOiBzdHJpbmcpOiBQcm9taXNlPFJlbmRpdGlvbkVudHJ5PiB7XG4gICAgICAgIGNvbnN0IHJlbmRpdGlvblBhZ2luZzogUmVuZGl0aW9uUGFnaW5nID0gYXdhaXQgdGhpcy5yZW5kaXRpb25zQXBpLmxpc3RSZW5kaXRpb25zKG5vZGVJZCk7XG4gICAgICAgIGxldCByZW5kaXRpb246IFJlbmRpdGlvbkVudHJ5ID0gcmVuZGl0aW9uUGFnaW5nLmxpc3QuZW50cmllcy5maW5kKFxuICAgICAgICAgICAgKHJlbmRpdGlvbkVudHJ5OiBSZW5kaXRpb25FbnRyeSkgPT4gcmVuZGl0aW9uRW50cnkuZW50cnkuaWQudG9Mb3dlckNhc2UoKSA9PT0gcmVuZGl0aW9uSWRcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAocmVuZGl0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBzdGF0dXMgPSByZW5kaXRpb24uZW50cnkuc3RhdHVzLnRvU3RyaW5nKCk7XG5cbiAgICAgICAgICAgIGlmIChzdGF0dXMgPT09ICdOT1RfQ1JFQVRFRCcpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlbmRpdGlvbnNBcGkuY3JlYXRlUmVuZGl0aW9uKG5vZGVJZCwgeyBpZDogcmVuZGl0aW9uSWQgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRpdGlvbiA9IGF3YWl0IHRoaXMud2FpdFJlbmRpdGlvbihub2RlSWQsIHJlbmRpdGlvbklkLCAwKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxSZW5kaXRpb25FbnRyeT4oKHJlc29sdmUpID0+IHJlc29sdmUocmVuZGl0aW9uKSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZ2V0Tm9kZVJlbmRpdGlvbihub2RlSWQ6IHN0cmluZywgdmVyc2lvbklkPzogc3RyaW5nKTogUHJvbWlzZTx7IHVybDogc3RyaW5nOyBtaW1lVHlwZTogc3RyaW5nIH0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiB2ZXJzaW9uSWQgPyBhd2FpdCB0aGlzLnJlc29sdmVOb2RlUmVuZGl0aW9uKG5vZGVJZCwgJ3BkZicsIHZlcnNpb25JZCkgOiBhd2FpdCB0aGlzLnJlc29sdmVOb2RlUmVuZGl0aW9uKG5vZGVJZCwgJ3BkZicpO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZXNvbHZlTm9kZVJlbmRpdGlvbihub2RlSWQ6IHN0cmluZywgcmVuZGl0aW9uSWQ6IHN0cmluZywgdmVyc2lvbklkPzogc3RyaW5nKTogUHJvbWlzZTx7IHVybDogc3RyaW5nOyBtaW1lVHlwZTogc3RyaW5nIH0+IHtcbiAgICAgICAgcmVuZGl0aW9uSWQgPSByZW5kaXRpb25JZC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgIGNvbnN0IHN1cHBvcnRlZFJlbmRpdGlvbjogUmVuZGl0aW9uUGFnaW5nID0gdmVyc2lvbklkXG4gICAgICAgICAgICA/IGF3YWl0IHRoaXMudmVyc2lvbnNBcGkubGlzdFZlcnNpb25SZW5kaXRpb25zKG5vZGVJZCwgdmVyc2lvbklkKVxuICAgICAgICAgICAgOiBhd2FpdCB0aGlzLnJlbmRpdGlvbnNBcGkubGlzdFJlbmRpdGlvbnMobm9kZUlkKTtcblxuICAgICAgICBsZXQgcmVuZGl0aW9uID0gdGhpcy5maW5kUmVuZGl0aW9uQnlJZChzdXBwb3J0ZWRSZW5kaXRpb24sIHJlbmRpdGlvbklkKTtcbiAgICAgICAgaWYgKCFyZW5kaXRpb24pIHtcbiAgICAgICAgICAgIHJlbmRpdGlvbklkID0gdGhpcy5ERUZBVUxUX1JFTkRJVElPTjtcbiAgICAgICAgICAgIHJlbmRpdGlvbiA9IHRoaXMuZmluZFJlbmRpdGlvbkJ5SWQoc3VwcG9ydGVkUmVuZGl0aW9uLCB0aGlzLkRFRkFVTFRfUkVORElUSU9OKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZW5kaXRpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXR1czogc3RyaW5nID0gcmVuZGl0aW9uLmVudHJ5LnN0YXR1cy50b1N0cmluZygpO1xuICAgICAgICAgICAgY29uc3QgbWltZVR5cGU6IHN0cmluZyA9IHJlbmRpdGlvbi5lbnRyeS5jb250ZW50Lm1pbWVUeXBlO1xuXG4gICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnTk9UX0NSRUFURUQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgdXJsOiBhd2FpdCB0aGlzLnJlcXVlc3RDcmVhdGVSZW5kaXRpb24obm9kZUlkLCByZW5kaXRpb25JZCwgdmVyc2lvbklkKSwgbWltZVR5cGUgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgdXJsOiBhd2FpdCB0aGlzLmhhbmRsZU5vZGVSZW5kaXRpb24obm9kZUlkLCByZW5kaXRpb25JZCwgdmVyc2lvbklkKSwgbWltZVR5cGUgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVxdWVzdENyZWF0ZVJlbmRpdGlvbihub2RlSWQ6IHN0cmluZywgcmVuZGl0aW9uSWQ6IHN0cmluZywgdmVyc2lvbklkOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHZlcnNpb25JZCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMudmVyc2lvbnNBcGkuY3JlYXRlVmVyc2lvblJlbmRpdGlvbihub2RlSWQsIHZlcnNpb25JZCwgeyBpZDogcmVuZGl0aW9uSWQgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucmVuZGl0aW9uc0FwaS5jcmVhdGVSZW5kaXRpb24obm9kZUlkLCB7IGlkOiByZW5kaXRpb25JZCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZlcnNpb25JZCA/IGF3YWl0IHRoaXMud2FpdE5vZGVSZW5kaXRpb24obm9kZUlkLCByZW5kaXRpb25JZCwgdmVyc2lvbklkKSA6IGF3YWl0IHRoaXMud2FpdE5vZGVSZW5kaXRpb24obm9kZUlkLCByZW5kaXRpb25JZCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbmRSZW5kaXRpb25CeUlkKHN1cHBvcnRlZFJlbmRpdGlvbjogUmVuZGl0aW9uUGFnaW5nLCByZW5kaXRpb25JZDogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdXBwb3J0ZWRSZW5kaXRpb24ubGlzdC5lbnRyaWVzLmZpbmQoKHJlbmRpdGlvbkVudHJ5OiBSZW5kaXRpb25FbnRyeSkgPT4gcmVuZGl0aW9uRW50cnkuZW50cnkuaWQudG9Mb3dlckNhc2UoKSA9PT0gcmVuZGl0aW9uSWQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgd2FpdE5vZGVSZW5kaXRpb24obm9kZUlkOiBzdHJpbmcsIHJlbmRpdGlvbklkOiBzdHJpbmcsIHZlcnNpb25JZD86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIGxldCBjdXJyZW50UmV0cnk6IG51bWJlciA9IDA7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgY3VycmVudFJldHJ5Kys7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWF4UmV0cmllcyA+PSBjdXJyZW50UmV0cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZlcnNpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52ZXJzaW9uc0FwaS5nZXRWZXJzaW9uUmVuZGl0aW9uKG5vZGVJZCwgdmVyc2lvbklkLCByZW5kaXRpb25JZCkudGhlbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVuZGl0aW9uOiBSZW5kaXRpb25FbnRyeSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0dXM6IHN0cmluZyA9IHJlbmRpdGlvbi5lbnRyeS5zdGF0dXMudG9TdHJpbmcoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnQ1JFQVRFRCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh0aGlzLmhhbmRsZU5vZGVSZW5kaXRpb24obm9kZUlkLCByZW5kaXRpb24uZW50cnkuY29udGVudC5taW1lVHlwZSwgdmVyc2lvbklkKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICgpID0+IHJlamVjdChuZXcgRXJyb3IoJ0Vycm9yIGdldGluZyB2ZXJzaW9uIHJlbmRpdGlvbicpKVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGl0aW9uc0FwaS5nZXRSZW5kaXRpb24obm9kZUlkLCByZW5kaXRpb25JZCkudGhlbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVuZGl0aW9uOiBSZW5kaXRpb25FbnRyeSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0dXM6IHN0cmluZyA9IHJlbmRpdGlvbi5lbnRyeS5zdGF0dXMudG9TdHJpbmcoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnQ1JFQVRFRCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh0aGlzLmhhbmRsZU5vZGVSZW5kaXRpb24obm9kZUlkLCByZW5kaXRpb25JZCwgdmVyc2lvbklkKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICgpID0+IHJlamVjdChuZXcgRXJyb3IoJ0Vycm9yIGdldHRpbmcgcmVuZGl0aW9uJykpXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbElkKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoJ0Vycm9yIGdldHRpbmcgcmVuZGl0aW9uJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIHRoaXMuVFJZX1RJTUVPVVQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGhhbmRsZU5vZGVSZW5kaXRpb24obm9kZUlkOiBzdHJpbmcsIHJlbmRpdGlvbklkOiBzdHJpbmcsIHZlcnNpb25JZD86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiB2ZXJzaW9uSWRcbiAgICAgICAgICAgID8gdGhpcy5jb250ZW50QXBpLmdldFZlcnNpb25SZW5kaXRpb25Vcmwobm9kZUlkLCB2ZXJzaW9uSWQsIHJlbmRpdGlvbklkKVxuICAgICAgICAgICAgOiB0aGlzLmNvbnRlbnRBcGkuZ2V0UmVuZGl0aW9uVXJsKG5vZGVJZCwgcmVuZGl0aW9uSWQpO1xuICAgIH1cblxuICAgIGFzeW5jIGdlbmVyYXRlTWVkaWFUcmFja3NSZW5kaXRpb24obm9kZUlkOiBzdHJpbmcpOiBQcm9taXNlPFRyYWNrW10+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNSZW5kaXRpb25BdmFpbGFibGUobm9kZUlkLCBSZW5kaXRpb25TZXJ2aWNlLlNVQlRJVExFU19SRU5ESVRJT05fTkFNRSlcbiAgICAgICAgICAgIC50aGVuKCh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRyYWNrcyA9IFtdO1xuICAgICAgICAgICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB0cmFja3MucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBraW5kOiAnc3VidGl0bGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNyYzogdGhpcy5jb250ZW50QXBpLmdldFJlbmRpdGlvblVybChub2RlSWQsIFJlbmRpdGlvblNlcnZpY2UuU1VCVElUTEVTX1JFTkRJVElPTl9OQU1FKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudCgnQURGX1ZJRVdFUi5TVUJUSVRMRVMnKVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYWNrcztcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goKCkgPT4gW10pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgaXNSZW5kaXRpb25BdmFpbGFibGUobm9kZUlkOiBzdHJpbmcsIHJlbmRpdGlvbklkOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3QgcmVuZGl0aW9uUGFnaW5nOiBSZW5kaXRpb25QYWdpbmcgPSBhd2FpdCB0aGlzLnJlbmRpdGlvbnNBcGkubGlzdFJlbmRpdGlvbnMobm9kZUlkKTtcbiAgICAgICAgY29uc3QgcmVuZGl0aW9uOiBSZW5kaXRpb25FbnRyeSA9IHJlbmRpdGlvblBhZ2luZy5saXN0LmVudHJpZXMuZmluZChcbiAgICAgICAgICAgIChyZW5kaXRpb25FbnRyeTogUmVuZGl0aW9uRW50cnkpID0+IHJlbmRpdGlvbkVudHJ5LmVudHJ5LmlkLnRvTG93ZXJDYXNlKCkgPT09IHJlbmRpdGlvbklkXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHJlbmRpdGlvbj8uZW50cnk/LnN0YXR1cz8udG9TdHJpbmcoKSA9PT0gJ0NSRUFURUQnIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIHRha2VzIGEgdXJsIHRvIHRyaWdnZXIgdGhlIHByaW50IGRpYWxvZyBhZ2FpbnN0LCBhbmQgdGhlIHR5cGUgb2YgYXJ0aWZhY3QgdGhhdCBpdFxuICAgICAqIGlzLlxuICAgICAqIFRoaXMgVVJMIHNob3VsZCBiZSBvbmUgdGhhdCBjYW4gYmUgcmVuZGVyZWQgaW4gdGhlIGJyb3dzZXIsIGZvciBleGFtcGxlIFBERiwgSW1hZ2UsIG9yIFRleHRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB1cmwgdXJsIHRvIHByaW50XG4gICAgICogQHBhcmFtIHR5cGUgdHlwZSBvZiB0aGUgcmVuZGl0aW9uXG4gICAgICovXG4gICAgcHJpbnRGaWxlKHVybDogc3RyaW5nLCB0eXBlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgcHdhID0gd2luZG93Lm9wZW4odXJsLCBSZW5kaXRpb25TZXJ2aWNlLlRBUkdFVCk7XG4gICAgICAgIGlmIChwd2EpIHtcbiAgICAgICAgICAgIHB3YS5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcHdhLnByaW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGUgPT09IFJlbmRpdGlvblNlcnZpY2UuQ29udGVudEdyb3VwLklNQUdFKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2Ugb2YgdGhlIHdheSBjaHJvbWUgZm9jdXMgYW5kIGNsb3NlIGltYWdlIHdpbmRvdyB2cy4gcGRmIHByZXZpZXcgd2luZG93XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHdhLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExhdW5jaCB0aGUgRmlsZSBQcmludCBkaWFsb2cgZnJvbSBhbnl3aGVyZSBvdGhlciB0aGFuIHRoZSBwcmV2aWV3IHNlcnZpY2UsIHdoaWNoIHJlc29sdmVzIHRoZVxuICAgICAqIHJlbmRpdGlvbiBvZiB0aGUgb2JqZWN0IHRoYXQgY2FuIGJlIHByaW50ZWQgZnJvbSBhIHdlYiBicm93c2VyLlxuICAgICAqIFRoZXNlIGFyZTogaW1hZ2VzLCBQREYgZmlsZXMsIG9yIFBERiByZW5kaXRpb24gb2YgZmlsZXMuXG4gICAgICogV2UgYWxzbyBmb3JjZSBQREYgcmVuZGl0aW9uIGZvciBURVhUIHR5cGUgb2JqZWN0cywgb3RoZXJ3aXNlIHRoZSBkZWZhdWx0IFVSTCBpcyB0byBkb3dubG9hZC5cbiAgICAgKiBUT0RPIHRoZXJlIGFyZSBkaWZmZXJlbnQgVEVYVCB0eXBlIG9iamVjdHMsIChIVE1MLCBwbGFpbnRleHQsIHhtbCwgZXRjLiB3ZSBzaG91bGQgZGV0ZXJtaW5lIGhvdyB0aGVzZSBhcmUgaGFuZGxlZClcbiAgICAgKlxuICAgICAqIEBwYXJhbSBvYmplY3RJZCBvYmplY3QgaXRcbiAgICAgKiBAcGFyYW0gbWltZVR5cGUgbWltZSB0eXBlXG4gICAgICovXG4gICAgcHJpbnRGaWxlR2VuZXJpYyhvYmplY3RJZDogc3RyaW5nLCBtaW1lVHlwZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG5vZGVJZCA9IG9iamVjdElkO1xuICAgICAgICBjb25zdCB0eXBlOiBzdHJpbmcgPSB0aGlzLnZpZXdVdGlsc1NlcnZpY2UuZ2V0Vmlld2VyVHlwZUJ5TWltZVR5cGUobWltZVR5cGUpO1xuXG4gICAgICAgIHRoaXMuZ2V0UmVuZGl0aW9uKG5vZGVJZCwgUmVuZGl0aW9uU2VydmljZS5Db250ZW50R3JvdXAuUERGKVxuICAgICAgICAgICAgLnRoZW4oKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSB0aGlzLmdldFJlbmRpdGlvblVybChub2RlSWQsIHR5cGUsICEhdmFsdWUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHByaW50VHlwZSA9XG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPT09IFJlbmRpdGlvblNlcnZpY2UuQ29udGVudEdyb3VwLlBERiB8fCB0eXBlID09PSBSZW5kaXRpb25TZXJ2aWNlLkNvbnRlbnRHcm91cC5URVhUXG4gICAgICAgICAgICAgICAgICAgICAgICA/IFJlbmRpdGlvblNlcnZpY2UuQ29udGVudEdyb3VwLlBERlxuICAgICAgICAgICAgICAgICAgICAgICAgOiB0eXBlO1xuICAgICAgICAgICAgICAgIHRoaXMucHJpbnRGaWxlKHVybCwgcHJpbnRUeXBlKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goKCkgPT4ge30pO1xuICAgIH1cbn1cbiJdfQ==