UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

256 lines 37.2 kB
import { Injectable } from '@angular/core'; import { ApplicationAvailability, ApplicationType, FetchClient } from '@c8y/client'; import { ApplicationService } from '@c8y/client'; import { AppStateService, FilesService, ZipService } from '@c8y/ngx-components'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/ngx-components"; import * as i2 from "@c8y/client"; export class StaticAssetsService { constructor(appstate, appService, fetchClient, fileService, zip) { this.appstate = appstate; this.appService = appService; this.fetchClient = fetchClient; this.fileService = fileService; this.zip = zip; this.fileNames = { contents: 'contents.json', manifest: 'cumulocity.json', exportZipName: 'static-assets.zip' }; this.listFilesCachePromises = {}; } /** * Lists all files of the given type. * Forces a cache renewal. */ async listFiles(type) { return this.listFilesCached(type, true); } /** * Lists all files of the given type. * Uses a cache. */ async listFilesCached(type, forceCacheRenewal = false) { if (!this.listFilesCachePromises[type] || forceCacheRenewal) { this.listFilesCachePromises[type] = this._listFiles(type); } return await this.listFilesCachePromises[type]; } /** * Clones all assets of the given type from parent tenants into the current tenant. */ async cloneAssetsIntoTenant(type) { const { data: apps } = await this.appService.list({ availability: ApplicationAvailability.SHARED, type: ApplicationType.HOSTED, pageSize: 2000 }); const tenantIdsFromOtherAssetApps = apps .filter(app => { const result = app.owner?.tenant?.id && app.owner?.tenant?.id !== this.appstate.currentTenant.value?.name && app.contextPath === this.getContextPath(type, app.owner?.tenant?.id); return result; }) .map(app => app.owner?.tenant?.id); let filesOfCurrentTenant = await this._listFiles(type); let filesToUpload = new Array(); const oldAssets = new Array(); for (const tenantId of tenantIdsFromOtherAssetApps) { try { const filesOfApp = await this.getContentJSONForType(type, tenantId); oldAssets.push(...filesOfApp); for (const file of filesOfApp) { try { const response = await this.fetchClient.fetch(file.path); if (response.status !== 200) { console.warn(`Failed to get file "${file.fileName}" from path ${file.path}`); continue; } const fileContent = await response.blob(); // remove existing file with same name filesOfCurrentTenant = filesOfCurrentTenant.filter(existingFile => existingFile.fileName !== file.fileName); filesToUpload = filesToUpload.filter(existingFile => existingFile.name !== file.fileName); filesToUpload.push(new File([fileContent], file.fileName, { type: file.type })); } catch (e) { console.warn(`Failed to add file "${file.fileName}" from tenant ${tenantId}`, e); } } } catch (e) { console.warn(`Failed to get asset files from tenant ${tenantId}`); } } if (!filesToUpload.length) { return; } const newAssets = await this.addFilesToStaticAssets(type, filesToUpload, filesOfCurrentTenant); return { oldAssets, newAssets }; } /** * Adds the given files to the static assets of the given type. */ async addFilesToStaticAssets(type, files, existingFiles, throwErrorOnExistingFiles = true) { const app = await this.getAppForTenant(type); const filesToAddToContents = new Array(); const addedAt = new Date().toISOString(); const filesToUpload = []; for (const droppedFile of files) { const file = droppedFile instanceof File ? droppedFile : droppedFile.file; const fileName = file.name.toLowerCase().replace(/[^a-zA-Z0-9\-\_\.]/g, ''); const newFile = new File([file], fileName, { type: file.type, lastModified: file.lastModified }); if (existingFiles.find(existingFile => existingFile.fileName === fileName)) { if (throwErrorOnExistingFiles) { throw Error(`File with name "${fileName}" is already existing.`); } existingFiles = existingFiles.filter(existingFile => existingFile.fileName !== fileName); } const fileExtension = file.name.split('.').pop(); filesToAddToContents.push({ addedAt, lastModified: file.lastModified, extension: fileExtension, fileName: fileName, originalFileName: file.name, path: `/apps/public/${app.contextPath}/${fileName}`, size: newFile.size, type: newFile.type, hashSum: await this.fileService.getHashSumOfFile(newFile) }); filesToUpload.push({ contents: newFile, path: fileName }); } const newFiles = [...existingFiles, ...filesToAddToContents]; filesToUpload.push({ contents: new File([JSON.stringify(newFiles)], this.fileNames.contents, { type: 'application/json' }), path: this.fileNames.contents }); await this.appService.binary(app).updateFiles(filesToUpload); await this.ensureAddedFilesArePresent(filesToAddToContents); return newFiles; } /** * Gets the static assets app for the given type. */ async getAppForTenant(type) { const appName = this.getContextPath(type, false); const { data: apps } = await this.appService.listByName(appName); if (!apps.length) { throw Error(`No app with name ${appName} found.`); } return apps[0]; } getContentJSONForType(type, appendTenantId) { const path = this.getPathForContent(type, appendTenantId); return this.getContentJSONFromPath(path); } async getContentJSONFromPath(path) { const response = await this.fetchClient.fetch(path); if (response.status !== 200) { throw Error(`Failed to retrieve ${path}`); } const content = await response.json(); return content; } async ensureAddedFilesArePresent(files) { for (const file of files) { await this.ensureFileIsPresent(file); } } async ensureFileIsPresent(file) { for (let i = 0; i < 12; i++) { try { const currentDate = new Date(); const response = await this.fetchClient.fetch(`${file.path}?nocache=${currentDate.getTime()}`); if (response.status !== 200) { await this.sleep(5_000); continue; } const blob = await response.blob(); const hashSum = await this.fileService.getHashSumOfFile(blob); if (hashSum !== file.hashSum) { await this.sleep(5_000); continue; } return; } catch (e) { console.warn(e); continue; } } throw Error(`Unable to retrieve file from ${file.path}`); } sleep(duration) { return new Promise(resolve => setTimeout(() => resolve(), duration)); } async _listFiles(type) { try { const files = await this.getContentJSONForType(type); return files; } catch (e) { console.warn(e); } return await this.createEmptyApp(type); } getPathForContent(type, appendTenantId) { const currentDate = new Date(); const contextPath = this.getContextPath(type, appendTenantId); return `/apps/public/${contextPath}/${this.fileNames.contents}?nocache=${currentDate.getTime()}`; } getContextPath(type, appendTenantId) { let contextPath = type + '-assets'; const tenantId = appendTenantId === undefined ? this.appstate.currentTenant.value?.name : appendTenantId; if (tenantId) { contextPath = `${contextPath}-${tenantId}`; } return contextPath; } async createEmptyApp(type, appendTenantId) { const name = this.getContextPath(type, false); const contextPath = this.getContextPath(type, appendTenantId); const key = `${contextPath}-key`; const manifest = { name, contextPath, key, description: `Application containing static assets used for ${type}.`, noAppSwitcher: true, type: ApplicationType.HOSTED, availability: ApplicationAvailability.MARKET }; const content = []; const zipFile = await this.zip.createZip([ { fileName: `${this.fileNames.manifest}`, blob: new Blob([JSON.stringify(manifest)]) }, { fileName: `${this.fileNames.contents}`, blob: new Blob([JSON.stringify(content)]) } ]); const { data: app } = await this.appService.create(manifest); const { data: appBinary } = await this.appService .binary(app) .upload(zipFile, `empty-${name}.zip`); await this.appService.update({ id: app.id, activeVersionId: appBinary.id }); return []; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StaticAssetsService, deps: [{ token: i1.AppStateService }, { token: i2.ApplicationService }, { token: i2.FetchClient }, { token: i1.FilesService }, { token: i1.ZipService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StaticAssetsService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StaticAssetsService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.AppStateService }, { type: i2.ApplicationService }, { type: i2.FetchClient }, { type: i1.FilesService }, { type: i1.ZipService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLWFzc2V0cy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3RhdGljLWFzc2V0cy9kYXRhL3N0YXRpYy1hc3NldHMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxlQUFlLEVBQUUsV0FBVyxFQUFnQixNQUFNLGFBQWEsQ0FBQztBQUNsRyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDakQsT0FBTyxFQUFFLGVBQWUsRUFBZSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7Ozs7QUFJN0YsTUFBTSxPQUFPLG1CQUFtQjtJQVE5QixZQUNVLFFBQXlCLEVBQ3pCLFVBQThCLEVBQzlCLFdBQXdCLEVBQ3hCLFdBQXlCLEVBQ3pCLEdBQWU7UUFKZixhQUFRLEdBQVIsUUFBUSxDQUFpQjtRQUN6QixlQUFVLEdBQVYsVUFBVSxDQUFvQjtRQUM5QixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4QixnQkFBVyxHQUFYLFdBQVcsQ0FBYztRQUN6QixRQUFHLEdBQUgsR0FBRyxDQUFZO1FBWmhCLGNBQVMsR0FBRztZQUNuQixRQUFRLEVBQUUsZUFBZTtZQUN6QixRQUFRLEVBQUUsaUJBQWlCO1lBQzNCLGFBQWEsRUFBRSxtQkFBbUI7U0FDMUIsQ0FBQztRQUNILDJCQUFzQixHQUEyQyxFQUFFLENBQUM7SUFRekUsQ0FBQztJQUVKOzs7T0FHRztJQUNILEtBQUssQ0FBQyxTQUFTLENBQXFDLElBQU87UUFDekQsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGVBQWUsQ0FDbkIsSUFBTyxFQUNQLGlCQUFpQixHQUFHLEtBQUs7UUFF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LE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQzsrR0E1U1UsbUJBQW1CO21IQUFuQixtQkFBbUIsY0FETixNQUFNOzs0RkFDbkIsbUJBQW1CO2tCQUQvQixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFwcGxpY2F0aW9uQXZhaWxhYmlsaXR5LCBBcHBsaWNhdGlvblR5cGUsIEZldGNoQ2xpZW50LCBJQXBwbGljYXRpb24gfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBBcHBsaWNhdGlvblNlcnZpY2UgfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBBcHBTdGF0ZVNlcnZpY2UsIERyb3BwZWRGaWxlLCBGaWxlc1NlcnZpY2UsIFppcFNlcnZpY2UgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IFN0YXRpY0Fzc2V0LCBTdGF0aWNBc3NldFR5cGUgfSBmcm9tICcuL3N0YXRpYy1hc3NldHMubW9kZWwnO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFN0YXRpY0Fzc2V0c1NlcnZpY2Uge1xuICByZWFkb25seSBmaWxlTmFtZXMgPSB7XG4gICAgY29udGVudHM6ICdjb250ZW50cy5qc29uJyxcbiAgICBtYW5pZmVzdDogJ2N1bXVsb2NpdHkuanNvbicsXG4gICAgZXhwb3J0WmlwTmFtZTogJ3N0YXRpYy1hc3NldHMuemlwJ1xuICB9IGFzIGNvbnN0O1xuICBwcml2YXRlIGxpc3RGaWxlc0NhY2hlUHJvbWlzZXM6IFJlY29yZDxzdHJpbmcsIFByb21pc2U8U3RhdGljQXNzZXRbXT4+ID0ge307XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBhcHBzdGF0ZTogQXBwU3RhdGVTZXJ2aWNlLFxuICAgIHByaXZhdGUgYXBwU2VydmljZTogQXBwbGljYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgZmV0Y2hDbGllbnQ6IEZldGNoQ2xpZW50LFxuICAgIHByaXZhdGUgZmlsZVNlcnZpY2U6IEZpbGVzU2VydmljZSxcbiAgICBwcml2YXRlIHppcDogWmlwU2VydmljZVxuICApIHt9XG5cbiAgLyoqXG4gICAqIExpc3RzIGFsbCBmaWxlcyBvZiB0aGUgZ2l2ZW4gdHlwZS5cbiAgICogRm9yY2VzIGEgY2FjaGUgcmVuZXdhbC5cbiAgICovXG4gIGFzeW5jIGxpc3RGaWxlczxUIGV4dGVuZHMgc3RyaW5nID0gU3RhdGljQXNzZXRUeXBlPih0eXBlOiBUKTogUHJvbWlzZTxTdGF0aWNBc3NldFtdPiB7XG4gICAgcmV0dXJuIHRoaXMubGlzdEZpbGVzQ2FjaGVkKHR5cGUsIHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RzIGFsbCBmaWxlcyBvZiB0aGUgZ2l2ZW4gdHlwZS5cbiAgICogVXNlcyBhIGNhY2hlLlxuICAgKi9cbiAgYXN5bmMgbGlzdEZpbGVzQ2FjaGVkPFQgZXh0ZW5kcyBzdHJpbmcgPSBTdGF0aWNBc3NldFR5cGU+KFxuICAgIHR5cGU6IFQsXG4gICAgZm9yY2VDYWNoZVJlbmV3YWwgPSBmYWxzZVxuICApOiBQcm9taXNlPFN0YXRpY0Fzc2V0W10+IHtcbiAgICBpZiAoIXRoaXMubGlzdEZpbGVzQ2FjaGVQcm9taXNlc1t0eXBlXSB8fCBmb3JjZUNhY2hlUmVuZXdhbCkge1xuICAgICAgdGhpcy5saXN0RmlsZXNDYWNoZVByb21pc2VzW3R5cGVdID0gdGhpcy5fbGlzdEZpbGVzKHR5cGUpO1xuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCB0aGlzLmxpc3RGaWxlc0NhY2hlUHJvbWlzZXNbdHlwZV07XG4gIH1cblxuICAvKipcbiAgICogQ2xvbmVzIGFsbCBhc3NldHMgb2YgdGhlIGdpdmVuIHR5cGUgZnJvbSBwYXJlbnQgdGVuYW50cyBpbnRvIHRoZSBjdXJyZW50IHRlbmFudC5cbiAgICovXG4gIGFzeW5jIGNsb25lQXNzZXRzSW50b1RlbmFudDxUIGV4dGVuZHMgc3RyaW5nID0gU3RhdGljQXNzZXRUeXBlPih0eXBlOiBUKSB7XG4gICAgY29uc3QgeyBkYXRhOiBhcHBzIH0gPSBhd2FpdCB0aGlzLmFwcFNlcnZpY2UubGlzdCh7XG4gICAgICBhdmFpbGFiaWxpdHk6IEFwcGxpY2F0aW9uQXZhaWxhYmlsaXR5LlNIQVJFRCxcbiAgICAgIHR5cGU6IEFwcGxpY2F0aW9uVHlwZS5IT1NURUQsXG4gICAgICBwYWdlU2l6ZTogMjAwMFxuICAgIH0pO1xuXG4gICAgY29uc3QgdGVuYW50SWRzRnJvbU90aGVyQXNzZXRBcHBzID0gYXBwc1xuICAgICAgLmZpbHRlcihhcHAgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPVxuICAgICAgICAgIGFwcC5vd25lcj8udGVuYW50Py5pZCAmJlxuICAgICAgICAgIGFwcC5vd25lcj8udGVuYW50Py5pZCAhPT0gdGhpcy5hcHBzdGF0ZS5jdXJyZW50VGVuYW50LnZhbHVlPy5uYW1lICYmXG4gICAgICAgICAgYXBwLmNvbnRleHRQYXRoID09PSB0aGlzLmdldENvbnRleHRQYXRoKHR5cGUsIGFwcC5vd25lcj8udGVuYW50Py5pZCk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KVxuICAgICAgLm1hcChhcHAgPT4gYXBwLm93bmVyPy50ZW5hbnQ/LmlkKTtcblxuICAgIGxldCBmaWxlc09mQ3VycmVudFRlbmFudCA9IGF3YWl0IHRoaXMuX2xpc3RGaWxlcyh0eXBlKTtcblxuICAgIGxldCBmaWxlc1RvVXBsb2FkID0gbmV3IEFycmF5PEZpbGU+KCk7XG5cbiAgICBjb25zdCBvbGRBc3NldHMgPSBuZXcgQXJyYXk8U3RhdGljQXNzZXQ+KCk7XG5cbiAgICBmb3IgKGNvbnN0IHRlbmFudElkIG9mIHRlbmFudElkc0Zyb21PdGhlckFzc2V0QXBwcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZmlsZXNPZkFwcCA9IGF3YWl0IHRoaXMuZ2V0Q29udGVudEpTT05Gb3JUeXBlKHR5cGUsIHRlbmFudElkKTtcbiAgICAgICAgb2xkQXNzZXRzLnB1c2goLi4uZmlsZXNPZkFwcCk7XG4gICAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlc09mQXBwKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5mZXRjaENsaWVudC5mZXRjaChmaWxlLnBhdGgpO1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybihgRmFpbGVkIHRvIGdldCBmaWxlIFwiJHtmaWxlLmZpbGVOYW1lfVwiIGZyb20gcGF0aCAke2ZpbGUucGF0aH1gKTtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBmaWxlQ29udGVudCA9IGF3YWl0IHJlc3BvbnNlLmJsb2IoKTtcblxuICAgICAgICAgICAgLy8gcmVtb3ZlIGV4aXN0aW5nIGZpbGUgd2l0aCBzYW1lIG5hbWVcbiAgICAgICAgICAgIGZpbGVzT2ZDdXJyZW50VGVuYW50ID0gZmlsZXNPZkN1cnJlbnRUZW5hbnQuZmlsdGVyKFxuICAgICAgICAgICAgICBleGlzdGluZ0ZpbGUgPT4gZXhpc3RpbmdGaWxlLmZpbGVOYW1lICE9PSBmaWxlLmZpbGVOYW1lXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgZmlsZXNUb1VwbG9hZCA9IGZpbGVzVG9VcGxvYWQuZmlsdGVyKFxuICAgICAgICAgICAgICBleGlzdGluZ0ZpbGUgPT4gZXhpc3RpbmdGaWxlLm5hbWUgIT09IGZpbGUuZmlsZU5hbWVcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGZpbGVzVG9VcGxvYWQucHVzaChuZXcgRmlsZShbZmlsZUNvbnRlbnRdLCBmaWxlLmZpbGVOYW1lLCB7IHR5cGU6IGZpbGUudHlwZSB9KSk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBGYWlsZWQgdG8gYWRkIGZpbGUgXCIke2ZpbGUuZmlsZU5hbWV9XCIgZnJvbSB0ZW5hbnQgJHt0ZW5hbnRJZH1gLCBlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBGYWlsZWQgdG8gZ2V0IGFzc2V0IGZpbGVzIGZyb20gdGVuYW50ICR7dGVuYW50SWR9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFmaWxlc1RvVXBsb2FkLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG5ld0Fzc2V0cyA9IGF3YWl0IHRoaXMuYWRkRmlsZXNUb1N0YXRpY0Fzc2V0cyh0eXBlLCBmaWxlc1RvVXBsb2FkLCBmaWxlc09mQ3VycmVudFRlbmFudCk7XG5cbiAgICByZXR1cm4geyBvbGRBc3NldHMsIG5ld0Fzc2V0cyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgdGhlIGdpdmVuIGZpbGVzIHRvIHRoZSBzdGF0aWMgYXNzZXRzIG9mIHRoZSBnaXZlbiB0eXBlLlxuICAgKi9cbiAgYXN5bmMgYWRkRmlsZXNUb1N0YXRpY0Fzc2V0czxUIGV4dGVuZHMgc3RyaW5nID0gU3RhdGljQXNzZXRUeXBlPihcbiAgICB0eXBlOiBULFxuICAgIGZpbGVzOiBEcm9wcGVkRmlsZVtdIHwgRmlsZVtdLFxuICAgIGV4aXN0aW5nRmlsZXM6IFN0YXRpY0Fzc2V0W10sXG4gICAgdGhyb3dFcnJvck9uRXhpc3RpbmdGaWxlcyA9IHRydWVcbiAgKSB7XG4gICAgY29uc3QgYXBwID0gYXdhaXQgdGhpcy5nZXRBcHBGb3JUZW5hbnQodHlwZSk7XG4gICAgY29uc3QgZmlsZXNUb0FkZFRvQ29udGVudHMgPSBuZXcgQXJyYXk8U3RhdGljQXNzZXQ+KCk7XG4gICAgY29uc3QgYWRkZWRBdCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgICBjb25zdCBmaWxlc1RvVXBsb2FkOiB7XG4gICAgICBwYXRoOiBzdHJpbmc7XG4gICAgICBjb250ZW50czogQmxvYjtcbiAgICB9W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGRyb3BwZWRGaWxlIG9mIGZpbGVzKSB7XG4gICAgICBjb25zdCBmaWxlID0gZHJvcHBlZEZpbGUgaW5zdGFuY2VvZiBGaWxlID8gZHJvcHBlZEZpbGUgOiBkcm9wcGVkRmlsZS5maWxlO1xuICAgICAgY29uc3QgZmlsZU5hbWUgPSBmaWxlLm5hbWUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9bXmEtekEtWjAtOVxcLVxcX1xcLl0vZywgJycpO1xuICAgICAgY29uc3QgbmV3RmlsZSA9IG5ldyBGaWxlKFtmaWxlXSwgZmlsZU5hbWUsIHtcbiAgICAgICAgdHlwZTogZmlsZS50eXBlLFxuICAgICAgICBsYXN0TW9kaWZpZWQ6IGZpbGUubGFzdE1vZGlmaWVkXG4gICAgICB9KTtcbiAgICAgIGlmIChleGlzdGluZ0ZpbGVzLmZpbmQoZXhpc3RpbmdGaWxlID0+IGV4aXN0aW5nRmlsZS5maWxlTmFtZSA9PT0gZmlsZU5hbWUpKSB7XG4gICAgICAgIGlmICh0aHJvd0Vycm9yT25FeGlzdGluZ0ZpbGVzKSB7XG4gICAgICAgICAgdGhyb3cgRXJyb3IoYEZpbGUgd2l0aCBuYW1lIFwiJHtmaWxlTmFtZX1cIiBpcyBhbHJlYWR5IGV4aXN0aW5nLmApO1xuICAgICAgICB9XG4gICAgICAgIGV4aXN0aW5nRmlsZXMgPSBleGlzdGluZ0ZpbGVzLmZpbHRlcihleGlzdGluZ0ZpbGUgPT4gZXhpc3RpbmdGaWxlLmZpbGVOYW1lICE9PSBmaWxlTmFtZSk7XG4gICAgICB9XG4gICAgICBjb25zdCBmaWxlRXh0ZW5zaW9uID0gZmlsZS5uYW1lLnNwbGl0KCcuJykucG9wKCk7XG4gICAgICBmaWxlc1RvQWRkVG9Db250ZW50cy5wdXNoKHtcbiAgICAgICAgYWRkZWRBdCxcbiAgICAgICAgbGFzdE1vZGlmaWVkOiBmaWxlLmxhc3RNb2RpZmllZCxcbiAgICAgICAgZXh0ZW5zaW9uOiBmaWxlRXh0ZW5zaW9uLFxuICAgICAgICBmaWxlTmFtZTogZmlsZU5hbWUsXG4gICAgICAgIG9yaWdpbmFsRmlsZU5hbWU6IGZpbGUubmFtZSxcbiAgICAgICAgcGF0aDogYC9hcHBzL3B1YmxpYy8ke2FwcC5jb250ZXh0UGF0aH0vJHtmaWxlTmFtZX1gLFxuICAgICAgICBzaXplOiBuZXdGaWxlLnNpemUsXG4gICAgICAgIHR5cGU6IG5ld0ZpbGUudHlwZSxcbiAgICAgICAgaGFzaFN1bTogYXdhaXQgdGhpcy5maWxlU2VydmljZS5nZXRIYXNoU3VtT2ZGaWxlKG5ld0ZpbGUpXG4gICAgICB9KTtcbiAgICAgIGZpbGVzVG9VcGxvYWQucHVzaCh7XG4gICAgICAgIGNvbnRlbnRzOiBuZXdGaWxlLFxuICAgICAgICBwYXRoOiBmaWxlTmFtZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgbmV3RmlsZXM6IFN0YXRpY0Fzc2V0W10gPSBbLi4uZXhpc3RpbmdGaWxlcywgLi4uZmlsZXNUb0FkZFRvQ29udGVudHNdO1xuICAgIGZpbGVzVG9VcGxvYWQucHVzaCh7XG4gICAgICBjb250ZW50czogbmV3IEZpbGUoW0pTT04uc3RyaW5naWZ5KG5ld0ZpbGVzKV0sIHRoaXMuZmlsZU5hbWVzLmNvbnRlbnRzLCB7XG4gICAgICAgIHR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJ1xuICAgICAgfSksXG4gICAgICBwYXRoOiB0aGlzLmZpbGVOYW1lcy5jb250ZW50c1xuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuYXBwU2VydmljZS5iaW5hcnkoYXBwKS51cGRhdGVGaWxlcyhmaWxlc1RvVXBsb2FkKTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZUFkZGVkRmlsZXNBcmVQcmVzZW50KGZpbGVzVG9BZGRUb0NvbnRlbnRzKTtcbiAgICByZXR1cm4gbmV3RmlsZXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgc3RhdGljIGFzc2V0cyBhcHAgZm9yIHRoZSBnaXZlbiB0eXBlLlxuICAgKi9cbiAgYXN5bmMgZ2V0QXBwRm9yVGVuYW50PFQgZXh0ZW5kcyBzdHJpbmcgPSBTdGF0aWNBc3NldFR5cGU+KHR5cGU6IFQpOiBQcm9taXNlPElBcHBsaWNhdGlvbj4ge1xuICAgIGNvbnN0IGFwcE5hbWUgPSB0aGlzLmdldENvbnRleHRQYXRoKHR5cGUsIGZhbHNlKTtcbiAgICBjb25zdCB7IGRhdGE6IGFwcHMgfSA9IGF3YWl0IHRoaXMuYXBwU2VydmljZS5saXN0QnlOYW1lKGFwcE5hbWUpO1xuICAgIGlmICghYXBwcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IEVycm9yKGBObyBhcHAgd2l0aCBuYW1lICR7YXBwTmFtZX0gZm91bmQuYCk7XG4gICAgfVxuICAgIHJldHVybiBhcHBzWzBdO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb250ZW50SlNPTkZvclR5cGU8VCBleHRlbmRzIHN0cmluZyA9IFN0YXRpY0Fzc2V0VHlwZT4oXG4gICAgdHlwZTogVCxcbiAgICBhcHBlbmRUZW5hbnRJZD86IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWRcbiAgKSB7XG4gICAgY29uc3QgcGF0aCA9IHRoaXMuZ2V0UGF0aEZvckNvbnRlbnQodHlwZSwgYXBwZW5kVGVuYW50SWQpO1xuICAgIHJldHVybiB0aGlzLmdldENvbnRlbnRKU09ORnJvbVBhdGgocGF0aCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldENvbnRlbnRKU09ORnJvbVBhdGgocGF0aDogc3RyaW5nKTogUHJvbWlzZTxTdGF0aWNBc3NldFtdPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmZldGNoQ2xpZW50LmZldGNoKHBhdGgpO1xuICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgdGhyb3cgRXJyb3IoYEZhaWxlZCB0byByZXRyaWV2ZSAke3BhdGh9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgY29udGVudCA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICByZXR1cm4gY29udGVudDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlQWRkZWRGaWxlc0FyZVByZXNlbnQoZmlsZXM6IFN0YXRpY0Fzc2V0W10pIHtcbiAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlRmlsZUlzUHJlc2VudChmaWxlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVuc3VyZUZpbGVJc1ByZXNlbnQoZmlsZTogU3RhdGljQXNzZXQpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnREYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmZldGNoQ2xpZW50LmZldGNoKFxuICAgICAgICAgIGAke2ZpbGUucGF0aH0/bm9jYWNoZT0ke2N1cnJlbnREYXRlLmdldFRpbWUoKX1gXG4gICAgICAgICk7XG4gICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuc2xlZXAoNV8wMDApO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYmxvYiA9IGF3YWl0IHJlc3BvbnNlLmJsb2IoKTtcbiAgICAgICAgY29uc3QgaGFzaFN1bSA9IGF3YWl0IHRoaXMuZmlsZVNlcnZpY2UuZ2V0SGFzaFN1bU9mRmlsZShibG9iKTtcbiAgICAgICAgaWYgKGhhc2hTdW0gIT09IGZpbGUuaGFzaFN1bSkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuc2xlZXAoNV8wMDApO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGUpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgRXJyb3IoYFVuYWJsZSB0byByZXRyaWV2ZSBmaWxlIGZyb20gJHtmaWxlLnBhdGh9YCk7XG4gIH1cblxuICBwcml2YXRlIHNsZWVwKGR1cmF0aW9uOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4ocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KCgpID0+IHJlc29sdmUoKSwgZHVyYXRpb24pKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgX2xpc3RGaWxlczxUIGV4dGVuZHMgc3RyaW5nID0gU3RhdGljQXNzZXRUeXBlPih0eXBlOiBUKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgdGhpcy5nZXRDb250ZW50SlNPTkZvclR5cGUodHlwZSk7XG4gICAgICByZXR1cm4gZmlsZXM7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS53YXJuKGUpO1xuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCB0aGlzLmNyZWF0ZUVtcHR5QXBwKHR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYXRoRm9yQ29udGVudDxUIGV4dGVuZHMgc3RyaW5nID0gU3RhdGljQXNzZXRUeXBlPihcbiAgICB0eXBlOiBULFxuICAgIGFwcGVuZFRlbmFudElkPzogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZFxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IGN1cnJlbnREYXRlID0gbmV3IERhdGUoKTtcbiAgICBjb25zdCBjb250ZXh0UGF0aCA9IHRoaXMuZ2V0Q29udGV4dFBhdGgodHlwZSwgYXBwZW5kVGVuYW50SWQpO1xuICAgIHJldHVybiBgL2FwcHMvcHVibGljLyR7Y29udGV4dFBhdGh9LyR7XG4gICAgICB0aGlzLmZpbGVOYW1lcy5jb250ZW50c1xuICAgIH0/bm9jYWNoZT0ke2N1cnJlbnREYXRlLmdldFRpbWUoKX1gO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb250ZXh0UGF0aDxUIGV4dGVuZHMgc3RyaW5nID0gU3RhdGljQXNzZXRUeXBlPihcbiAgICB0eXBlOiBULFxuICAgIGFwcGVuZFRlbmFudElkPzogc3RyaW5nIHwgZmFsc2UgfCB1bmRlZmluZWRcbiAgKSB7XG4gICAgbGV0IGNvbnRleHRQYXRoOiBzdHJpbmcgPSB0eXBlICsgJy1hc3NldHMnO1xuICAgIGNvbnN0IHRlbmFudElkID1cbiAgICAgIGFwcGVuZFRlbmFudElkID09PSB1bmRlZmluZWQgPyB0aGlzLmFwcHN0YXRlLmN1cnJlbnRUZW5hbnQudmFsdWU/Lm5hbWUgOiBhcHBlbmRUZW5hbnRJZDtcbiAgICBpZiAodGVuYW50SWQpIHtcbiAgICAgIGNvbnRleHRQYXRoID0gYCR7Y29udGV4dFBhdGh9LSR7dGVuYW50SWR9YDtcbiAgICB9XG4gICAgcmV0dXJuIGNvbnRleHRQYXRoO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjcmVhdGVFbXB0eUFwcDxUIGV4dGVuZHMgc3RyaW5nID0gU3RhdGljQXNzZXRUeXBlPihcbiAgICB0eXBlOiBULFxuICAgIGFwcGVuZFRlbmFudElkPzogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZFxuICApOiBQcm9taXNlPFN0YXRpY0Fzc2V0W10+IHtcbiAgICBjb25zdCBuYW1lID0gdGhpcy5nZXRDb250ZXh0UGF0aCh0eXBlLCBmYWxzZSk7XG4gICAgY29uc3QgY29udGV4dFBhdGggPSB0aGlzLmdldENvbnRleHRQYXRoKHR5cGUsIGFwcGVuZFRlbmFudElkKTtcbiAgICBjb25zdCBrZXkgPSBgJHtjb250ZXh0UGF0aH0ta2V5YDtcbiAgICBjb25zdCBtYW5pZmVzdDogSUFwcGxpY2F0aW9uID0ge1xuICAgICAgbmFtZSxcbiAgICAgIGNvbnRleHRQYXRoLFxuICAgICAga2V5LFxuICAgICAgZGVzY3JpcHRpb246IGBBcHBsaWNhdGlvbiBjb250YWluaW5nIHN0YXRpYyBhc3NldHMgdXNlZCBmb3IgJHt0eXBlfS5gLFxuICAgICAgbm9BcHBTd2l0Y2hlcjogdHJ1ZSxcbiAgICAgIHR5cGU6IEFwcGxpY2F0aW9uVHlwZS5IT1NURUQsXG4gICAgICBhdmFpbGFiaWxpdHk6IEFwcGxpY2F0aW9uQXZhaWxhYmlsaXR5Lk1BUktFVFxuICAgIH07XG5cbiAgICBjb25zdCBjb250ZW50ID0gW107XG4gICAgY29uc3QgemlwRmlsZSA9IGF3YWl0IHRoaXMuemlwLmNyZWF0ZVppcChbXG4gICAgICB7XG4gICAgICAgIGZpbGVOYW1lOiBgJHt0aGlzLmZpbGVOYW1lcy5tYW5pZmVzdH1gLFxuICAgICAgICBibG9iOiBuZXcgQmxvYihbSlNPTi5zdHJpbmdpZnkobWFuaWZlc3QpXSlcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGZpbGVOYW1lOiBgJHt0aGlzLmZpbGVOYW1lcy5jb250ZW50c31gLFxuICAgICAgICBibG9iOiBuZXcgQmxvYihbSlNPTi5zdHJpbmdpZnkoY29udGVudCldKVxuICAgICAgfVxuICAgIF0pO1xuICAgIGNvbnN0IHsgZGF0YTogYXBwIH0gPSBhd2FpdCB0aGlzLmFwcFNlcnZpY2UuY3JlYXRlKG1hbmlmZXN0KTtcbiAgICBjb25zdCB7IGRhdGE6IGFwcEJpbmFyeSB9ID0gYXdhaXQgdGhpcy5hcHBTZXJ2aWNlXG4gICAgICAuYmluYXJ5KGFwcClcbiAgICAgIC51cGxvYWQoemlwRmlsZSwgYGVtcHR5LSR7bmFtZX0uemlwYCk7XG4gICAgYXdhaXQgdGhpcy5hcHBTZXJ2aWNlLnVwZGF0ZSh7IGlkOiBhcHAuaWQsIGFjdGl2ZVZlcnNpb25JZDogYXBwQmluYXJ5LmlkIGFzIHN0cmluZyB9KTtcbiAgICByZXR1cm4gW107XG4gIH1cbn1cbiJdfQ==