@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
236 lines • 37.8 kB
JavaScript
import { EventEmitter, Injectable } from '@angular/core';
import { LogLevel } from '@microsoft/windows-admin-center-sdk/core/diagnostics/log-level';
import { Logging } from '@microsoft/windows-admin-center-sdk/core/diagnostics/logging';
import { interval, throwError, timer } from 'rxjs';
import { delay, filter, take, takeUntil, takeWhile } from 'rxjs/operators';
import { AppContextService } from '../../service/app-context.service';
import * as i0 from "@angular/core";
import * as i1 from "../../service/app-context.service";
export var DataTableDownloadDataType;
(function (DataTableDownloadDataType) {
DataTableDownloadDataType["CSV"] = "text/csv";
DataTableDownloadDataType["JSON"] = "application/json";
})(DataTableDownloadDataType || (DataTableDownloadDataType = {}));
export class DataTableDownloadService {
constructor(appContextService) {
this.appContextService = appContextService;
/**
* The localization strings object for master view.
*/
this.resourceStrings = MsftSme.self().Resources.strings.MsftSmeShell.Angular.DataTable.DownloadService;
/**
* The download finished event emitter.
*/
this.downloadDataFinished = new EventEmitter();
/**
* Determines if one download service is ongoing.
*/
this.isBusy = false;
/**
* Adding a force delay time can help with general performance of the downloading function when dataset grows big.
* It can also help with improve granularity for notification state changes.
*/
this.minDownloadDelayTime = 1000;
/**
* Force timeout 2mins.
*/
this.maxDownloadTimeAllowed = 120000;
this.moduleName = MsftSme.self().Init.moduleName;
}
ngOnDestroy() {
this.worker?.terminate();
}
/*
* The download data from data table component function.
* @param dataTable The data table component to download data from.
* @param downloadType The type of data to be downloaded.
* @param contextParameters The context parameters from outside of the data table component from the extension.
*/
downloadData(dataTable, downloadType, contextParameters) {
this.notificationInstance = this.appContextService.notification.create(this.appContextService.gateway.gatewayName);
const inProgressTitle = this.resourceStrings.inProgressTitle;
const inProgressContent = this.resourceStrings.inProgressContent.format(this.moduleName);
const successTitle = this.resourceStrings.successTitle;
const successContent = this.resourceStrings.successContent.format(this.moduleName);
const failedTitle = this.resourceStrings.failedTitle;
this.notificationInstance.showInProgress(inProgressTitle, inProgressContent);
this.isBusy = true;
this.downloadDataCore(dataTable, downloadType, contextParameters).pipe(take(1)).subscribe({
error: error => {
Logging.log({
level: LogLevel.Warning,
message: `Download failed: ${error}`,
source: 'MasterViewComponent.onDownloadButtonClicked()'
});
const failedContent = this.resourceStrings.failedContent.format(this.moduleName, error);
this.notificationInstance.showError(failedTitle, failedContent);
this.worker.terminate();
this.downloadDataFinished.emit();
},
complete: () => {
this.notificationInstance.showSuccess(successTitle, successContent);
this.downloadDataFinished.emit();
}
});
}
/**
* It guarantees the valid DataTableDownloadDataType is passed in to the worker.
* @param downloadType the downloadType passed in from client side that needs validation.
* @returns a valid downloadType that comes from DataTableDownloadDataType
*/
validateMimeType(downloadType) {
return Object.values(DataTableDownloadDataType).includes(downloadType) ? downloadType : DataTableDownloadDataType.CSV;
}
/**
* The actual implementation core function for download data.
* @param dataTable the data table component reference.
* @param downloadType the downloadType passed in from client.
* @returns parsed error in string.
*/
downloadDataCore(dataTable, downloadType, contextParameters) {
const data = JSON.parse(JSON.stringify(dataTable.items));
const type = this.validateMimeType(downloadType);
const fileName = this.moduleName ? `${this.moduleName}-${new Date().getTime().toString()}.csv` : new Date().getTime().toString();
this.initWorker(type);
this.worker.postMessage({ data, type });
this.worker.onmessage = (event) => {
let processedData = '';
try {
if (downloadType === DataTableDownloadDataType.CSV) {
// Download rendered content from the table in CSV.
processedData = this.convertToCsv(event.data.processedData, dataTable, contextParameters);
}
else {
// Download RAW JSON.
processedData = JSON.stringify(event.data.processedData);
}
this.downloadAction(processedData, type, fileName);
this.isBusy = false;
}
catch (e) {
this.isBusy = false;
return throwError(() => e.toString()).pipe(delay(this.minDownloadDelayTime));
}
};
return interval(this.minDownloadDelayTime).pipe(takeUntil(timer(this.maxDownloadTimeAllowed)), takeWhile(() => this.isBusy, true), filter(() => !this.isBusy));
}
downloadAction(data, mimeType, fileName) {
const blob = new Blob([data], { type: mimeType });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = fileName;
link.click();
URL.revokeObjectURL(url);
}
convertToCsv(dataList, dataTable, contextParameters) {
const columns = dataTable.actualColumns.map(column => {
return {
field: column.field,
header: column.header,
hasTemplate: !!column.bodyTemplate,
downloadContentProcessor: column.downloadContentProcessor ?? undefined
};
});
const rows = [columns.map((column) => column.header).join(',')];
const errors = [];
dataList.forEach((dataItem, rowIndex) => {
const values = columns.map((column, columnIndex) => {
// Resolve nested object and get value.
let value = dataTable.resolveObjectPath(dataItem, column.field);
if (column.hasTemplate) {
if (column.downloadContentProcessor) {
// Process the data by passed in function.
value = column.downloadContentProcessor(value, dataItem, contextParameters);
// Wrap the string with double quote and still maintain valid string to prevent
// being recognized as separate columns from csv file.
if (typeof value !== 'string') {
try {
value = this.castToString(value);
}
catch (e) {
throw new Error(`Failed to cast ${value} to string ${e}`);
}
}
value = this.preventTextContentAsSeparatedColumns(value);
}
else {
if (!errors.includes(column['header'])) {
errors.push(column['header']);
}
value = this.getTableCellRenderedString(rowIndex, columnIndex, dataTable);
}
}
return value;
});
rows.push(values.join(','));
});
// Error handling.
if (errors && errors.length) {
throw new Error('Please add \'downloadContentProcessor\' function to listed field(s): ' + errors.join(','));
}
return rows.join('\r\n');
}
/**
* It converts any type to string.
* @param input any type of input.
* @returns the string representation for input.
*/
castToString(input) {
if (input === null || typeof input === 'undefined') {
return '';
}
if (typeof input === 'object' || typeof input === 'function') {
return JSON.stringify(input);
}
return String(input);
}
/**
* Prevents space to be recognized as different columns.
* The solution is to wrap the string with double quote and still forms a valid string.
* @param value The input string that needs to wrap with double quote.
* @returns the string wrapped with double quotes and is still a valid string.
*/
preventTextContentAsSeparatedColumns(value) {
if (value === undefined || value === null) {
return '""'; // Return empty double quotes for undefined or null values
}
return '"' + value.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
}
/**
* It gets the rendered string from the rendered table row and cell.
* @param rowIndex the row index from the data table.
* @param columnIndex the column index from the data table.
* @param dataTable the data table component reference.
* @returns the string representing the rendered data from DOM.
*/
getTableCellRenderedString(rowIndex, columnIndex, dataTable) {
if (!dataTable) {
return;
}
const cells = dataTable.getTableCells(rowIndex);
const cell = cells[columnIndex];
return cell?.textContent.trim() ?? '';
}
/**
* The initialization for the worker to be used for downloading data table text content.
*/
initWorker(type) {
const downloadWorkerFunction = `
self.onmessage = function(event) {
const { data, type } = event.data;
const processedData = data;
self.postMessage({ processedData });
};
`;
const workerBlob = new Blob([downloadWorkerFunction], { type });
const workerUrl = URL.createObjectURL(workerBlob);
this.worker = new Worker(workerUrl);
}
}
/** @nocollapse */ DataTableDownloadService.ɵfac = function DataTableDownloadService_Factory(t) { return new (t || DataTableDownloadService)(i0.ɵɵinject(i1.AppContextService)); };
/** @nocollapse */ DataTableDownloadService.ɵprov = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjectable({ token: DataTableDownloadService, factory: DataTableDownloadService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DataTableDownloadService, [{
type: Injectable
}], function () { return [{ type: i1.AppContextService }]; }, null); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS10YWJsZS1kb3dubG9hZC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vYW5ndWxhci9zcmMvY29udHJvbHMvZGF0YS10YWJsZS9kYXRhLXRhYmxlLWRvd25sb2FkLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFDcEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdFQUFnRSxDQUFDO0FBQzFGLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSw4REFBOEQsQ0FBQztBQUV2RixPQUFPLEVBQUUsUUFBUSxFQUFjLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0QsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQzs7O0FBR3RFLE1BQU0sQ0FBTixJQUFZLHlCQUdYO0FBSEQsV0FBWSx5QkFBeUI7SUFDakMsNkNBQWdCLENBQUE7SUFDaEIsc0RBQXlCLENBQUE7QUFDN0IsQ0FBQyxFQUhXLHlCQUF5QixLQUF6Qix5QkFBeUIsUUFHcEM7QUFHRCxNQUFNLE9BQU8sd0JBQXdCO0lBMENqQyxZQUFvQixpQkFBb0M7UUFBcEMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQXpDeEQ7O1dBRUc7UUFDSSxvQkFBZSxHQUFHLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQztRQUV6Rzs7V0FFRztRQUNJLHlCQUFvQixHQUF1QixJQUFJLFlBQVksRUFBUSxDQUFDO1FBaUIzRTs7V0FFRztRQUNLLFdB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Qix3QkFBd0I7dUZBQXhCLHdCQUF3QjtjQURwQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBJbmplY3RhYmxlLCBPbkRlc3Ryb3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgTG9nTGV2ZWwgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RpYWdub3N0aWNzL2xvZy1sZXZlbCc7XHJcbmltcG9ydCB7IExvZ2dpbmcgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RpYWdub3N0aWNzL2xvZ2dpbmcnO1xyXG5pbXBvcnQgeyBDbGllbnROb3RpZmljYXRpb25JbnN0YW5jZSB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvaW5kZXgnO1xyXG5pbXBvcnQgeyBpbnRlcnZhbCwgT2JzZXJ2YWJsZSwgdGhyb3dFcnJvciwgdGltZXIgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZGVsYXksIGZpbHRlciwgdGFrZSwgdGFrZVVudGlsLCB0YWtlV2hpbGUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IEFwcENvbnRleHRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZS9hcHAtY29udGV4dC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRGF0YVRhYmxlQ29tcG9uZW50IH0gZnJvbSAnLi9kYXRhLXRhYmxlLmNvbXBvbmVudCc7XHJcblxyXG5leHBvcnQgZW51bSBEYXRhVGFibGVEb3dubG9hZERhdGFUeXBlIHtcclxuICAgIENTViA9ICd0ZXh0L2NzdicsXHJcbiAgICBKU09OID0gJ2FwcGxpY2F0aW9uL2pzb24nXHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIERhdGFUYWJsZURvd25sb2FkU2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBsb2NhbGl6YXRpb24gc3RyaW5ncyBvYmplY3QgZm9yIG1hc3RlciB2aWV3LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVzb3VyY2VTdHJpbmdzID0gTXNmdFNtZS5zZWxmKCkuUmVzb3VyY2VzLnN0cmluZ3MuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuRGF0YVRhYmxlLkRvd25sb2FkU2VydmljZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBkb3dubG9hZCBmaW5pc2hlZCBldmVudCBlbWl0dGVyLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZG93bmxvYWREYXRhRmluaXNoZWQ6IEV2ZW50RW1pdHRlcjx2b2lkPiA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBub3RpZmljYXRpb24gaW5zdGFuY2UuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgbm90aWZpY2F0aW9uSW5zdGFuY2U6IENsaWVudE5vdGlmaWNhdGlvbkluc3RhbmNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGRvd25sb2FkIHdvcmtlci5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSB3b3JrZXI6IFdvcmtlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBjdXJyZW50IGV4dGVuc2lvbi9tb2R1bGUgZmlsZU5hbWUuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgbW9kdWxlTmFtZTogc3RyaW5nO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGV0ZXJtaW5lcyBpZiBvbmUgZG93bmxvYWQgc2VydmljZSBpcyBvbmdvaW5nLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGlzQnVzeSA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWRkaW5nIGEgZm9yY2UgZGVsYXkgdGltZSBjYW4gaGVscCB3aXRoIGdlbmVyYWwgcGVyZm9ybWFuY2Ugb2YgdGhlIGRvd25sb2FkaW5nIGZ1bmN0aW9uIHdoZW4gZGF0YXNldCBncm93cyBiaWcuXHJcbiAgICAgKiBJdCBjYW4gYWxzbyBoZWxwIHdpdGggaW1wcm92ZSBncmFudWxhcml0eSBmb3Igbm90aWZpY2F0aW9uIHN0YXRlIGNoYW5nZXMuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmVhZG9ubHkgbWluRG93bmxvYWREZWxheVRpbWUgPSAxMDAwO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRm9yY2UgdGltZW91dCAybWlucy5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSByZWFkb25seSBtYXhEb3dubG9hZFRpbWVBbGxvd2VkID0gMTIwMDAwO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgYXBwQ29udGV4dFNlcnZpY2U6IEFwcENvbnRleHRTZXJ2aWNlKSB7XHJcbiAgICAgICAgdGhpcy5tb2R1bGVOYW1lID0gTXNmdFNtZS5zZWxmKCkuSW5pdC5tb2R1bGVOYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLndvcmtlcj8udGVybWluYXRlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLypcclxuICAgICAqIFRoZSBkb3dubG9hZCBkYXRhIGZyb20gZGF0YSB0YWJsZSBjb21wb25lbnQgZnVuY3Rpb24uXHJcbiAgICAgKiBAcGFyYW0gZGF0YVRhYmxlIFRoZSBkYXRhIHRhYmxlIGNvbXBvbmVudCB0byBkb3dubG9hZCBkYXRhIGZyb20uXHJcbiAgICAgKiBAcGFyYW0gZG93bmxvYWRUeXBlIFRoZSB0eXBlIG9mIGRhdGEgdG8gYmUgZG93bmxvYWRlZC5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0UGFyYW1ldGVycyBUaGUgY29udGV4dCBwYXJhbWV0ZXJzIGZyb20gb3V0c2lkZSBvZiB0aGUgZGF0YSB0YWJsZSBjb21wb25lbnQgZnJvbSB0aGUgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZG93bmxvYWREYXRhKGRhdGFUYWJsZTogRGF0YVRhYmxlQ29tcG9uZW50LCBkb3dubG9hZFR5cGU6IERhdGFUYWJsZURvd25sb2FkRGF0YVR5cGUsIGNvbnRleHRQYXJhbWV0ZXJzPzogYW55KTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5ub3RpZmljYXRpb25JbnN0YW5jZSA9IHRoaXMuYXBwQ29udGV4dFNlcnZpY2Uubm90aWZpY2F0aW9uLmNyZWF0ZSh0aGlzLmFwcENvbnRleHRTZXJ2aWNlLmdhdGV3YXkuZ2F0ZXdheU5hbWUpO1xyXG4gICAgICAgIGNvbnN0IGluUHJvZ3Jlc3NUaXRsZSA9IHRoaXMucmVzb3VyY2VTdHJpbmdzLmluUHJvZ3Jlc3NUaXRsZTtcclxuICAgICAgICBjb25zdCBpblByb2dyZXNzQ29udGVudCA9IHRoaXMucmVzb3VyY2VTdHJpbmdzLmluUHJvZ3Jlc3NDb250ZW50LmZvcm1hdCh0aGlzLm1vZHVsZU5hbWUpO1xyXG4gICAgICAgIGNvbnN0IHN1Y2Nlc3NUaXRsZSA9IHRoaXMucmVzb3VyY2VTdHJpbmdzLnN1Y2Nlc3NUaXRsZTtcclxuICAgICAgICBjb25zdCBzdWNjZXNzQ29udGVudCA9IHRoaXMucmVzb3VyY2VTdHJpbmdzLnN1Y2Nlc3NDb250ZW50LmZvcm1hdCh0aGlzLm1vZHVsZU5hbWUpO1xyXG4gICAgICAgIGNvbnN0IGZhaWxlZFRpdGxlID0gdGhpcy5yZXNvdXJjZVN0cmluZ3MuZmFpbGVkVGl0bGU7XHJcblxyXG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uSW5zdGFuY2Uuc2hvd0luUHJvZ3Jlc3MoXHJcbiAgICAgICAgICAgIGluUHJvZ3Jlc3NUaXRsZSxcclxuICAgICAgICAgICAgaW5Qcm9ncmVzc0NvbnRlbnRcclxuICAgICAgICApO1xyXG5cclxuICAgICAgICB0aGlzLmlzQnVzeSA9IHRydWU7XHJcblxyXG4gICAgICAgIHRoaXMuZG93bmxvYWREYXRhQ29yZShkYXRhVGFibGUsIGRvd25sb2FkVHlwZSwgY29udGV4dFBhcmFtZXRlcnMpLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgZXJyb3I6IGVycm9yID0+IHtcclxuICAgICAgICAgICAgICAgIExvZ2dpbmcubG9nKHtcclxuICAgICAgICAgICAgICAgICAgICBsZXZlbDogTG9nTGV2ZWwuV2FybmluZyxcclxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgRG93bmxvYWQgZmFpbGVkOiAke2Vycm9yfWAsXHJcbiAgICAgICAgICAgICAgICAgICAgc291cmNlOiAnTWFzdGVyVmlld0NvbXBvbmVudC5vbkRvd25sb2FkQnV0dG9uQ2xpY2tlZCgpJ1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgZmFpbGVkQ29udGVudCA9IHRoaXMucmVzb3VyY2VTdHJpbmdzLmZhaWxlZENvbnRlbnQuZm9ybWF0KHRoaXMubW9kdWxlTmFtZSwgZXJyb3IpO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMubm90aWZpY2F0aW9uSW5zdGFuY2Uuc2hvd0Vycm9yKFxyXG4gICAgICAgICAgICAgICAgICAgIGZhaWxlZFRpdGxlLFxyXG4gICAgICAgICAgICAgICAgICAgIGZhaWxlZENvbnRlbnRcclxuICAgICAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy53b3JrZXIudGVybWluYXRlKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5kb3dubG9hZERhdGFGaW5pc2hlZC5lbWl0KCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbkluc3RhbmNlLnNob3dTdWNjZXNzKFxyXG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NUaXRsZSxcclxuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ29udGVudFxyXG4gICAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLmRvd25sb2FkRGF0YUZpbmlzaGVkLmVtaXQoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSXQgZ3VhcmFudGVlcyB0aGUgdmFsaWQgRGF0YVRhYmxlRG93bmxvYWREYXRhVHlwZSBpcyBwYXNzZWQgaW4gdG8gdGhlIHdvcmtlci5cclxuICAgICAqIEBwYXJhbSBkb3dubG9hZFR5cGUgdGhlIGRvd25sb2FkVHlwZSBwYXNzZWQgaW4gZnJvbSBjbGllbnQgc2lkZSB0aGF0IG5lZWRzIHZhbGlkYXRpb24uXHJcbiAgICAgKiBAcmV0dXJucyBhIHZhbGlkIGRvd25sb2FkVHlwZSB0aGF0IGNvbWVzIGZyb20gRGF0YVRhYmxlRG93bmxvYWREYXRhVHlwZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHZhbGlkYXRlTWltZVR5cGUoZG93bmxvYWRUeXBlOiBEYXRhVGFibGVEb3dubG9hZERhdGFUeXBlKTogRGF0YVRhYmxlRG93bmxvYWREYXRhVHlwZSB7XHJcbiAgICAgICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoRGF0YVRhYmxlRG93bmxvYWREYXRhVHlwZSkuaW5jbHVkZXMoZG93bmxvYWRUeXBlKSA/IGRvd25sb2FkVHlwZSA6IERhdGFUYWJsZURvd25sb2FkRGF0YVR5cGUuQ1NWO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGFjdHVhbCBpbXBsZW1lbnRhdGlvbiBjb3JlIGZ1bmN0aW9uIGZvciBkb3dubG9hZCBkYXRhLlxyXG4gICAgICogQHBhcmFtIGRhdGFUYWJsZSB0aGUgZGF0YSB0YWJsZSBjb21wb25lbnQgcmVmZXJlbmNlLlxyXG4gICAgICogQHBhcmFtIGRvd25sb2FkVHlwZSB0aGUgZG93bmxvYWRUeXBlIHBhc3NlZCBpbiBmcm9tIGNsaWVudC5cclxuICAgICAqIEByZXR1cm5zIHBhcnNlZCBlcnJvciBpbiBzdHJpbmcuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZG93bmxvYWREYXRhQ29yZShcclxuICAgICAgICBkYXRhVGFibGU6IERhdGFUYWJsZUNvbXBvbmVudCxcclxuICAgICAgICBkb3dubG9hZFR5cGU6IERhdGFUYWJsZURvd25sb2FkRGF0YVR5cGUsXHJcbiAgICAgICAgY29udGV4dFBhcmFtZXRlcnM/OiBhbnlcclxuICAgICk6IE9ic2VydmFibGU8YW55PiB7XHJcbiAgICAgICAgY29uc3QgZGF0YSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZGF0YVRhYmxlLml0ZW1zKSk7XHJcbiAgICAgICAgY29uc3QgdHlwZSA9IHRoaXMudmFsaWRhdGVNaW1lVHlwZShkb3dubG9hZFR5cGUpO1xyXG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gdGhpcy5tb2R1bGVOYW1lID8gYCR7dGhpcy5tb2R1bGVOYW1lfS0ke25ldyBEYXRlKCkuZ2V0VGltZSgpLnRvU3RyaW5nKCl9LmNzdmAgOiBuZXcgRGF0ZSgpLmdldFRpbWUoKS50b1N0cmluZygpO1xyXG5cclxuICAgICAgICB0aGlzLmluaXRXb3JrZXIodHlwZSk7XHJcblxyXG4gICAgICAgIHRoaXMud29ya2VyLnBvc3RNZXNzYWdlKHsgZGF0YSwgdHlwZSB9KTtcclxuXHJcbiAgICAgICAgdGhpcy53b3JrZXIub25tZXNzYWdlID0gKGV2ZW50KSA9PiB7XHJcbiAgICAgICAgICAgIGxldCBwcm9jZXNzZWREYXRhID0gJyc7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZG93bmxvYWRUeXBlID09PSBEYXRhVGFibGVEb3dubG9hZERhdGFUeXBlLkNTVikge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIERvd25sb2FkIHJlbmRlcmVkIGNvbnRlbnQgZnJvbSB0aGUgdGFibGUgaW4gQ1NWLlxyXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NlZERhdGEgPSB0aGlzLmNvbnZlcnRUb0NzdihldmVudC5kYXRhLnByb2Nlc3NlZERhdGEsIGRhdGFUYWJsZSwgY29udGV4dFBhcmFtZXRlcnMpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBEb3dubG9hZCBSQVcgSlNPTi5cclxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWREYXRhID0gSlNPTi5zdHJpbmdpZnkoZXZlbnQuZGF0YS5wcm9jZXNzZWREYXRhKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLmRvd25sb2FkQWN0aW9uKHByb2Nlc3NlZERhdGEsIHR5cGUsIGZpbGVOYW1lKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuaXNCdXN5ID0gZmFsc2U7XHJcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuaXNCdXN5ID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlLnRvU3RyaW5nKCkpLnBpcGUoZGVsYXkodGhpcy5taW5Eb3dubG9hZERlbGF5VGltZSkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGludGVydmFsKHRoaXMubWluRG93bmxvYWREZWxheVRpbWUpLnBpcGUoXHJcbiAgICAgICAgICAgIHRha2VVbnRpbCh0aW1lcih0aGlzLm1heERvd25sb2FkVGltZUFsbG93ZWQpKSxcclxuICAgICAgICAgICAgdGFrZVdoaWxlKCgpID0+IHRoaXMuaXNCdXN5LCB0cnVlKSxcclxuICAgICAgICAgICAgZmlsdGVyKCgpID0+ICF0aGlzLmlzQnVzeSlcclxuICAgICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBkb3dubG9hZEFjdGlvbihkYXRhOiBzdHJpbmcsIG1pbWVUeXBlOiBzdHJpbmcsIGZpbGVOYW1lOiBzdHJpbmcpIHtcclxuICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2RhdGFdLCB7IHR5cGU6IG1pbWVUeXBlIH0pO1xyXG4gICAgICAgIGNvbnN0IHVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XHJcbiAgICAgICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcclxuXHJcbiAgICAgICAgbGluay5ocmVmID0gdXJsO1xyXG4gICAgICAgIGxpbmsuZG93bmxvYWQgPSBmaWxlTmFtZTtcclxuICAgICAgICBsaW5rLmNsaWNrKCk7XHJcblxyXG4gICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNvbnZlcnRUb0NzdihkYXRhTGlzdDogYW55W10sIGRhdGFUYWJsZTogRGF0YVRhYmxlQ29tcG9uZW50LCBjb250ZXh0UGFyYW1ldGVycz86IGFueSk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgY29sdW1ucyA9IGRhdGFUYWJsZS5hY3R1YWxDb2x1bW5zLm1hcChjb2x1bW4gPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgZmllbGQ6IGNvbHVtbi5maWVsZCxcclxuICAgICAgICAgICAgICAgIGhlYWRlcjogY29sdW1uLmhlYWRlcixcclxuICAgICAgICAgICAgICAgIGhhc1RlbXBsYXRlOiAhIWNvbHVtbi5ib2R5VGVtcGxhdGUsXHJcbiAgICAgICAgICAgICAgICBkb3dubG9hZENvbnRlbnRQcm9jZXNzb3I6IGNvbHVtbi5kb3dubG9hZENvbnRlbnRQcm9jZXNzb3IgPz8gdW5kZWZpbmVkXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgY29uc3Qgcm93cyA9IFtjb2x1bW5zLm1hcCgoY29sdW1uKSA9PiBjb2x1bW4uaGVhZGVyKS5qb2luKCcsJyldO1xyXG4gICAgICAgIGNvbnN0IGVycm9ycyA9IFtdO1xyXG5cclxuICAgICAgICBkYXRhTGlzdC5mb3JFYWNoKChkYXRhSXRlbSwgcm93SW5kZXgpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gY29sdW1ucy5tYXAoKGNvbHVtbiwgY29sdW1uSW5kZXgpID0+IHtcclxuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbmVzdGVkIG9iamVjdCBhbmQgZ2V0IHZhbHVlLlxyXG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlID0gZGF0YVRhYmxlLnJlc29sdmVPYmplY3RQYXRoKGRhdGFJdGVtLCBjb2x1bW4uZmllbGQpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChjb2x1bW4uaGFzVGVtcGxhdGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY29sdW1uLmRvd25sb2FkQ29udGVudFByb2Nlc3Nvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQcm9jZXNzIHRoZSBkYXRhIGJ5IHBhc3NlZCBpbiBmdW5jdGlvbi5cclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBjb2x1bW4uZG93bmxvYWRDb250ZW50UHJvY2Vzc29yKHZhbHVlLCBkYXRhSXRlbSwgY29udGV4dFBhcmFtZXRlcnMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXcmFwIHRoZSBzdHJpbmcgd2l0aCBkb3VibGUgcXVvdGUgYW5kIHN0aWxsIG1haW50YWluIHZhbGlkIHN0cmluZyB0byBwcmV2ZW50XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJlaW5nIHJlY29nbml6ZWQgYXMgc2VwYXJhdGUgY29sdW1ucyBmcm9tIGNzdiBmaWxlLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY2FzdFRvU3RyaW5nKHZhbHVlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBjYXN0ICR7dmFsdWV9IHRvIHN0cmluZyAke2V9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5wcmV2ZW50VGV4dENvbnRlbnRBc1NlcGFyYXRlZENvbHVtbnModmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXJyb3JzLmluY2x1ZGVzKGNvbHVtblsnaGVhZGVyJ10pKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnMucHVzaChjb2x1bW5bJ2hlYWRlciddKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuZ2V0VGFibGVDZWxsUmVuZGVyZWRTdHJpbmcocm93SW5kZXgsIGNvbHVtbkluZGV4LCBkYXRhVGFibGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICByb3dzLnB1c2godmFsdWVzLmpvaW4oJywnKSk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIC8vIEVycm9yIGhhbmRsaW5nLlxyXG4gICAgICAgIGlmIChlcnJvcnMgJiYgZXJyb3JzLmxlbmd0aCkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsZWFzZSBhZGQgXFwnZG93bmxvYWRDb250ZW50UHJvY2Vzc29yXFwnIGZ1bmN0aW9uIHRvIGxpc3RlZCBmaWVsZChzKTogJyArIGVycm9ycy5qb2luKCcsJykpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHJvd3Muam9pbignXFxyXFxuJyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJdCBjb252ZXJ0cyBhbnkgdHlwZSB0byBzdHJpbmcuXHJcbiAgICAgKiBAcGFyYW0gaW5wdXQgYW55IHR5cGUgb2YgaW5wdXQuXHJcbiAgICAgKiBAcmV0dXJucyB0aGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIGZvciBpbnB1dC5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBjYXN0VG9TdHJpbmcoaW5wdXQ6IGFueSk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKGlucHV0ID09PSBudWxsIHx8IHR5cGVvZiBpbnB1dCA9PT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICAgICAgcmV0dXJuICcnO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIGlucHV0ID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShpbnB1dCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gU3RyaW5nKGlucHV0KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFByZXZlbnRzIHNwYWNlIHRvIGJlIHJlY29nbml6ZWQgYXMgZGlmZmVyZW50IGNvbHVtbnMuXHJcbiAgICAgKiBUaGUgc29sdXRpb24gaXMgdG8gd3JhcCB0aGUgc3RyaW5nIHdpdGggZG91YmxlIHF1b3RlIGFuZCBzdGlsbCBmb3JtcyBhIHZhbGlkIHN0cmluZy5cclxuICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgaW5wdXQgc3RyaW5nIHRoYXQgbmVlZHMgdG8gd3JhcCB3aXRoIGRvdWJsZSBxdW90ZS5cclxuICAgICAqIEByZXR1cm5zIHRoZSBzdHJpbmcgd3JhcHBlZCB3aXRoIGRvdWJsZSBxdW90ZXMgYW5kIGlzIHN0aWxsIGEgdmFsaWQgc3RyaW5nLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHByZXZlbnRUZXh0Q29udGVudEFzU2VwYXJhdGVkQ29sdW1ucyh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gJ1wiXCInOyAvLyBSZXR1cm4gZW1wdHkgZG91YmxlIHF1b3RlcyBmb3IgdW5kZWZpbmVkIG9yIG51bGwgdmFsdWVzXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiAnXCInICsgdmFsdWUucmVwbGFjZSgvXFxcXC9nLCAnXFxcXFxcXFwnKS5yZXBsYWNlKC9cIi9nLCAnXFxcXFwiJykgKyAnXCInO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSXQgZ2V0cyB0aGUgcmVuZGVyZWQgc3RyaW5nIGZyb20gdGhlIHJlbmRlcmVkIHRhYmxlIHJvdyBhbmQgY2VsbC5cclxuICAgICAqIEBwYXJhbSByb3dJbmRleCB0aGUgcm93IGluZGV4IGZyb20gdGhlIGRhdGEgdGFibGUuXHJcbiAgICAgKiBAcGFyYW0gY29sdW1uSW5kZXggdGhlIGNvbHVtbiBpbmRleCBmcm9tIHRoZSBkYXRhIHRhYmxlLlxyXG4gICAgICogQHBhcmFtIGRhdGFUYWJsZSB0aGUgZGF0YSB0YWJsZSBjb21wb25lbnQgcmVmZXJlbmNlLlxyXG4gICAgICogQHJldHVybnMgdGhlIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIHJlbmRlcmVkIGRhdGEgZnJvbSBET00uXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0VGFibGVDZWxsUmVuZGVyZWRTdHJpbmcocm93SW5kZXg6IG51bWJlciwgY29sdW1uSW5kZXg6IG51bWJlciwgZGF0YVRhYmxlOiBEYXRhVGFibGVDb21wb25lbnQpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICghZGF0YVRhYmxlKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGNlbGxzID0gZGF0YVRhYmxlLmdldFRhYmxlQ2VsbHMocm93SW5kZXgpO1xyXG4gICAgICAgIGNvbnN0IGNlbGwgPSBjZWxsc1tjb2x1bW5JbmRleF07XHJcbiAgICAgICAgcmV0dXJuIGNlbGw/LnRleHRDb250ZW50LnRyaW0oKSA/PyAnJztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBpbml0aWFsaXphdGlvbiBmb3IgdGhlIHdvcmtlciB0byBiZSB1c2VkIGZvciBkb3dubG9hZGluZyBkYXRhIHRhYmxlIHRleHQgY29udGVudC5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBpbml0V29ya2VyKHR5cGU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IGRvd25sb2FkV29ya2VyRnVuY3Rpb24gPSBgXHJcbiAgICAgICAgICAgIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24oZXZlbnQpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHsgZGF0YSwgdHlwZSB9ID0gZXZlbnQuZGF0YTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHByb2Nlc3NlZERhdGEgPSBkYXRhO1xyXG4gICAgICAgICAgICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7IHByb2Nlc3NlZERhdGEgfSk7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgYDtcclxuXHJcbiAgICAgICAgY29uc3Qgd29ya2VyQmxvYiA9IG5ldyBCbG9iKFtkb3dubG9hZFdvcmtlckZ1bmN0aW9uXSwgeyB0eXBlIH0pO1xyXG4gICAgICAgIGNvbnN0IHdvcmtlclVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwod29ya2VyQmxvYik7XHJcbiAgICAgICAgdGhpcy53b3JrZXIgPSBuZXcgV29ya2VyKHdvcmtlclVybCk7XHJcbiAgICB9XHJcbn1cclxuIl19