trimble-connect-sdk
Version:
Trimble Connect SDK for JavaScript
315 lines • 55.2 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { ServiceError } from './error';
import { ServiceResponse } from './response';
export function extractEndpoint(url) {
const schemaIndex = url.indexOf('//');
const firstSeparatorIndex = url.indexOf('/', schemaIndex + 2);
return url.substring(0, firstSeparatorIndex);
}
function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
export class Service {
constructor(config) {
this.config = config;
this.defaultRetryCount = 3;
if (!this.config.serviceUri) {
throw new Error('The serviceUri is required');
}
}
makeRequest(url, method = 'GET', body, customHeaders, auth = true) {
return __awaiter(this, void 0, void 0, function* () {
const headers = new Headers({ Accept: 'application/json' });
if (customHeaders) {
customHeaders.forEach((value, key) => {
headers.append(key, value);
});
}
const response = (yield this.request(url, method, body, headers, auth));
if (response.response.status !== 204) {
const contentType = response.response.headers.get('content-type');
if (contentType === null ||
contentType.indexOf('application/json') !== -1) {
response.data = (yield response.response.json());
}
else {
throw new ServiceError(response.response, 'Cannot deserialize response body as it is not in a JSON format.');
}
}
return response;
});
}
getItemsWithPages(url, onPageRetrieved, pageSize, body, customHeaders, auth = true) {
return __awaiter(this, void 0, void 0, function* () {
if (pageSize <= 0 || !Number.isInteger(pageSize)) {
throw new RangeError('pageSize must be a positive integer');
}
const headers = customHeaders ? new Headers(customHeaders) : new Headers();
const range = { start: 0, end: pageSize - 1 };
headers.set('Range', `items=${range.start}-${range.end}`);
let response = yield this.makeRequest(url, 'GET', body, headers, auth);
do {
const responseRange = this.getRange(response);
const hasNextPage = this.hasMorePages(response, responseRange);
let nextPage;
if (hasNextPage && responseRange && responseRange.total) {
range.start = responseRange.end + 1;
range.end = Math.min(responseRange.total - 1, range.start + pageSize - 1);
headers.set('Range', `items=${range.start}-${range.end}`);
nextPage = this.makeRequest(url, 'GET', body, headers, auth);
}
onPageRetrieved(response);
if (nextPage) {
response = yield nextPage;
}
else {
break;
}
} while (true);
});
}
getItemsWithPagesAdaptive(url, onPageRetrieved, initialPageSize = 10, standardPageSize = 100, threshold = 50, body, customHeaders, auth = true) {
return __awaiter(this, void 0, void 0, function* () {
if (initialPageSize <= 0 || !Number.isInteger(initialPageSize)) {
throw new RangeError('initialPageSize must be a positive integer');
}
if (standardPageSize <= 0 || !Number.isInteger(standardPageSize)) {
throw new RangeError('standardPageSize must be a positive integer');
}
if (threshold < 0 || !Number.isInteger(threshold)) {
throw new RangeError('threshold must be a non-negative integer');
}
const headers = customHeaders ? new Headers(customHeaders) : new Headers();
let totalLoaded = 0;
let currentIndex = 0;
const firstPageSize = threshold === 0 ? standardPageSize : initialPageSize;
headers.set('Range', `items=${currentIndex}-${currentIndex + firstPageSize - 1}`);
let response = yield this.makeRequest(url, 'GET', body, headers, auth);
do {
const itemsInPage = Array.isArray(response.data)
? response.data.length
: 0;
const responseRange = this.getRange(response);
const hasMorePages = this.hasMorePages(response, responseRange);
totalLoaded += itemsInPage;
if (responseRange && typeof responseRange.end === 'number') {
currentIndex = responseRange.end + 1;
}
else {
currentIndex += itemsInPage;
}
let nextPage;
if (hasMorePages && responseRange && responseRange.total) {
const nextPageSize = totalLoaded < threshold ? initialPageSize : standardPageSize;
const endIndex = Math.min(responseRange.total - 1, currentIndex + nextPageSize - 1);
headers.set('Range', `items=${currentIndex}-${endIndex}`);
nextPage = this.makeRequest(url, 'GET', body, headers, auth);
}
onPageRetrieved(response);
if (nextPage) {
response = yield nextPage;
}
else {
break;
}
} while (true);
});
}
request(url, method = 'GET', body, customHeaders, auth = true) {
return __awaiter(this, void 0, void 0, function* () {
const requestUrl = url.startsWith('http')
? url
: url.startsWith('/')
? extractEndpoint(this.config.serviceUri) + url
: this.config.serviceUri + url;
const headers = new Headers();
const contentType = customHeaders
? customHeaders.get('Content-Type')
: undefined;
if (!contentType && body !== undefined) {
headers.set('Content-Type', 'application/json');
}
if (customHeaders) {
customHeaders.forEach((value, key) => {
headers.append(key, value);
});
}
return this.fetchWithRetry(requestUrl, {
body,
headers,
method,
redirect: 'follow',
}, auth);
});
}
maxRetries() {
if (this.config.maxRetries !== undefined) {
return this.config.maxRetries;
}
else {
return this.defaultRetryCount;
}
}
calculateRetryDelay(retryCount) {
if (retryCount === 0) {
return 0;
}
else {
const base = 100;
return Math.random() * (Math.pow(2, retryCount - 1) * base);
}
}
retryableError(error) {
if (this.timeoutError(error) ||
this.networkingError(error) ||
this.expiredCredentialsError(error) ||
this.throttledError(error) ||
error.response.status >= 500) {
return true;
}
return false;
}
networkingError(error) {
return error.errorCode === 'NetworkingError';
}
timeoutError(error) {
return error.errorCode === 'TimeoutError';
}
expiredCredentialsError(error) {
if (error.response.status === 401) {
const credentials = this.config.credentials;
if (credentials &&
typeof credentials.expired === 'boolean') {
credentials.expired = true;
}
return true;
}
return false;
}
throttledError(error) {
if (error.response.status === 429) {
return true;
}
else {
return false;
}
}
fetchWithRetry(url, params, auth = true) {
return __awaiter(this, void 0, void 0, function* () {
const logger = this.config.logger;
const result = new ServiceResponse(this, new Response(), void 0);
do {
const credentials = this.config.credentials;
if (auth && credentials) {
if (typeof credentials.get === 'function') {
try {
yield credentials.get();
}
catch (err) {
if (logger !== undefined) {
this.log(`[TID] Failed to acquire tokens: ${err.message}`);
}
throw err;
}
}
if (credentials.token) {
params.headers.set('Authorization', 'Bearer ' + credentials.token);
}
}
const startTime = Date.now();
const response = yield this.fetch(url, params);
if (logger !== undefined) {
const delta = (Date.now() - startTime) / 1000;
const isoDate = new Date(startTime).toISOString();
const requestContentLength = params.body ? params.body.length : 0;
const responseContentLength = response.headers.get('content-length');
const line = `${isoDate} [TC HTTP] ${params.method} ${url} ${response.status} ${delta} ${result.retryCount} ${requestContentLength} ${responseContentLength}`;
this.log(line);
}
result.response = response;
if (response.ok) {
return result;
}
else {
let err;
const contentType = response.headers.get('content-type');
if (contentType && contentType.indexOf('application/json') !== -1) {
const errorInfo = yield response.json();
err = new ServiceError(response, errorInfo.message, errorInfo.code || errorInfo.errorcode);
}
else {
const message = yield response.text();
err = new ServiceError(response, message);
}
if (result.retryCount + 1 < this.maxRetries() &&
this.retryableError(err)) {
const retryAfterHeader = response.headers.get('retry-after');
const retryAfterMS = retryAfterHeader
? parseInt(retryAfterHeader, 10) * 1000
: 0;
const ms = this.calculateRetryDelay(result.retryCount) + retryAfterMS;
yield delay(ms);
result.retryCount++;
}
else {
throw err;
}
}
} while (true);
});
}
fetch(url, params) {
return fetch(url, params);
}
getRange(response) {
if (!response.response.headers.has('Content-Range')) {
return undefined;
}
try {
const contentRange = response.response.headers
.get('Content-Range')
.split(' ');
const rangeTokens = contentRange[1].split('/');
const tokens = rangeTokens[0].split('-');
const start = Number(tokens[0]);
const end = Number(tokens[1]);
const total = Number(rangeTokens[1]);
return { start, end, total };
}
catch (_a) {
return undefined;
}
}
hasMorePages(response, responseRange) {
const range = responseRange !== null && responseRange !== void 0 ? responseRange : this.getRange(response);
return (Array.isArray(response.data) &&
response.data.length !== 0 &&
range !== undefined &&
range.total !== undefined &&
range.end < range.total - 1);
}
log(line) {
return __awaiter(this, void 0, void 0, function* () {
const logger = this.config.logger;
if (logger !== undefined) {
if (typeof logger.log === 'function') {
logger.log(line);
}
else if (typeof logger.write === 'function') {
logger.write(line + '\n');
}
}
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIuLyIsInNvdXJjZXMiOlsic2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFHQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFJN0MsTUFBTSxVQUFVLGVBQWUsQ0FBQyxHQUFXO0lBQ3pDLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsTUFBTSxtQkFBbUIsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFOUQsT0FBTyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRCxTQUFTLEtBQUssQ0FBQyxFQUFVO0lBQ3ZCLE9BQU8sSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUNuQyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzFCLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQU1ELE1BQU0sT0FBTyxPQUFPO0lBUWxCLFlBQTRCLE1BQXFCO1FBQXJCLFdBQU0sR0FBTixNQUFNLENBQWU7UUFOekMsc0JBQWlCLEdBQVcsQ0FBQyxDQUFDO1FBT3BDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRTtZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7U0FDL0M7SUFDSCxDQUFDO0lBWVksV0FBVyxDQUN0QixHQUFXLEVBQ1gsU0FBc0QsS0FBSyxFQUMzRCxJQUF3QixFQUN4QixhQUF1QixFQUN2QixPQUFnQixJQUFJOztZQUVwQixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxrQkFBa0Is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b3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25maWd1cmF0aW9uIH0gZnJvbSAnLi9jb25maWcnO1xuaW1wb3J0IHsgQ3JlZGVudGlhbHMgfSBmcm9tICcuL2NyZWRlbnRpYWxzJztcbmltcG9ydCB7IFJhbmdlIH0gZnJvbSAnLi9jb21tb24nO1xuaW1wb3J0IHsgU2VydmljZUVycm9yIH0gZnJvbSAnLi9lcnJvcic7XG5pbXBvcnQgeyBTZXJ2aWNlUmVzcG9uc2UgfSBmcm9tICcuL3Jlc3BvbnNlJztcbmltcG9ydCB7IFNlcnZpY2VDcmVkZW50aWFscyB9IGZyb20gJy4vc2VydmljZV9jcmVkZW50aWFscyc7XG5cbi8qKiBAaW50ZXJuYWwgKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0RW5kcG9pbnQodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBzY2hlbWFJbmRleCA9IHVybC5pbmRleE9mKCcvLycpO1xuICBjb25zdCBmaXJzdFNlcGFyYXRvckluZGV4ID0gdXJsLmluZGV4T2YoJy8nLCBzY2hlbWFJbmRleCArIDIpO1xuXG4gIHJldHVybiB1cmwuc3Vic3RyaW5nKDAsIGZpcnN0U2VwYXJhdG9ySW5kZXgpO1xufVxuXG5mdW5jdGlvbiBkZWxheShtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBUaGUgc2VydmljZSBjbGllbnQgdGhhdCByZXByZXNlbnRzIGNvbm5lY3Rpb24gdG8gdGhlIE9yZ2FuaXplciBTZXJ2aWNlLlxuICogRWFjaCBBUEkgb3BlcmF0aW9uIGlzIGV4cG9zZWQgYXMgYSBmdW5jdGlvbiBvbiBzZXJ2aWNlLlxuICovXG5leHBvcnQgY2xhc3MgU2VydmljZSB7XG4gIC8qKiBVc2VkIGlmIG1heFJldHJpZXMgaXMgbm90IHNwZWNpZmllZCBpbiB7QHNlZSBDb25maWd1cmF0aW9uI21heFJldHJpZXMgfS4gVGhlIGRlZmF1bHRSZXRyeUNvdW50IGNhbiBiZSBvdmVycmlkZGVuIGJ5IHNlcnZpY2UgY2xhc3Nlcy4gKi9cbiAgcHJpdmF0ZSBkZWZhdWx0UmV0cnlDb3VudDogbnVtYmVyID0gMztcblxuICAvKipcbiAgICogQGNvbnN0cnVjdG9yIENvbnN0cnVjdHMgYSBzZXJ2aWNlIG9iamVjdC5cbiAgICogQHBhcmFtIHtDb25maWd9IGNvbmZpZyBUaGUgY29uZmlndXJhdGlvbiBvcHRpb25zIChlLmcuIHNlcnZpY2UgdXJsKS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBjb25maWc6IENvbmZpZ3VyYXRpb24pIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnLnNlcnZpY2VVcmkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIHNlcnZpY2VVcmkgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2hlcyB0aGUgbmV4dCBwYWdlIGZyb20gdGhlIHNlcXVlbmNlIG9mIHBhZ2VzIGluaXRpYXRlZCBieSB7QHNlZSBPcmdhbml6ZXIubGlzdFRyZWVzIH0uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgVGhlIHVybCB0byBtYWtlIHJlcXVlc3QgdG8uIENvdWxkIGJlIGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHRoZSBzZXJ2aWNlIGJhc2UgdXJpLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBGb3JtRGF0YX0gYm9keSBPcHRpb25hbCBib2R5IHRvIHNlbmQgaW4gdGhlIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7SGVhZGVyc30gY3VzdG9tSGVhZGVycyBPcHRpb25hbCBoZWFkZXJzIHRvIGF0dGFjaCB0byByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGF1dGggVGhlIHZhbHVlIGluZGljYXRpbmcgd2hldGhlciB0aGUgcmVxdWVzdCByZXF1aXJlcyBhdXRoZW50aWNhdGlvbi4gSWYgdHJ1ZSwgdGhlIGNyZWRlbnRpYWxzIHdpbGwgYmUgcmVxdWVzdGVkIGZyb20gdGhlIGNvbmZpZ3VyYXRpb24ge0BzZWUgQ29uZmlnI2NyZWRlbnRpYWxzIH0gYW5kIEF1dGhvcml6YXRpb24gaGVhZGVyIHdpbGwgYmUgYXR0YWNoZWQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj59IFRoZSBzZXJ2aWNlIHJlc3BvbnNlLlxuICAgKiBAdGhyb3dzIHtTZXJ2aWNlRXJyb3J9IGluIGNhc2Ugb2YgdGhlIGVycm9yIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbWFrZVJlcXVlc3Q8RD4oXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgbWV0aG9kOiAnR0VUJyB8ICdQVVQnIHwgJ1BPU1QnIHwgJ1BBVENIJyB8ICdERUxFVEUnID0gJ0dFVCcsXG4gICAgYm9keT86IHN0cmluZyB8IEZvcm1EYXRhLFxuICAgIGN1c3RvbUhlYWRlcnM/OiBIZWFkZXJzLFxuICAgIGF1dGg6IGJvb2xlYW4gPSB0cnVlLFxuICApOiBQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj4ge1xuICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgSGVhZGVycyh7IEFjY2VwdDogJ2FwcGxpY2F0aW9uL2pzb24nIH0pO1xuICAgIGlmIChjdXN0b21IZWFkZXJzKSB7XG4gICAgICBjdXN0b21IZWFkZXJzLmZvckVhY2goKHZhbHVlOiBzdHJpbmcsIGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGhlYWRlcnMuYXBwZW5kKGtleSwgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3BvbnNlID0gKGF3YWl0IHRoaXMucmVxdWVzdChcbiAgICAgIHVybCxcbiAgICAgIG1ldGhvZCxcbiAgICAgIGJvZHksXG4gICAgICBoZWFkZXJzLFxuICAgICAgYXV0aCxcbiAgICApKSBhcyBhbnkgYXMgU2VydmljZVJlc3BvbnNlPEQ+O1xuXG4gICAgLy8gZGVzZXJpYWxpemUgcmVzcG9uc2UgYm9keS4gSWYgc2VydmljZSByZXNwb25kZWQgd2l0aCBhbiBlcnJvciBpdCB3YXMgdGhyb3duIGFscmVhZHkuXG4gICAgaWYgKHJlc3BvbnNlLnJlc3BvbnNlLnN0YXR1cyAhPT0gMjA0KSB7XG4gICAgICBjb25zdCBjb250ZW50VHlwZSA9IHJlc3BvbnNlLnJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdjb250ZW50LXR5cGUnKTtcbiAgICAgIGlmIChcbiAgICAgICAgY29udGVudFR5cGUgPT09IG51bGwgfHxcbiAgICAgICAgY29udGVudFR5cGUuaW5kZXhPZignYXBwbGljYXRpb24vanNvbicpICE9PSAtMVxuICAgICAgKSB7XG4gICAgICAgIHJlc3BvbnNlLmRhdGEgPSAoYXdhaXQgcmVzcG9uc2UucmVzcG9uc2UuanNvbigpKSBhcyBEO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IFNlcnZpY2VFcnJvcihcbiAgICAgICAgICByZXNwb25zZS5yZXNwb25zZSxcbiAgICAgICAgICAnQ2Fubm90IGRlc2VyaWFsaXplIHJlc3BvbnNlIGJvZHkgYXMgaXQgaXMgbm90IGluIGEgSlNPTiBmb3JtYXQuJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2hlcyBhbGwgdGhlIGl0ZW1zIHBhZ2UgYnkgcGFnZSwgcmV0dXJuaW5nIGVhY2ggcGFnZSByZXN1bHRzIGluIGEgY2FsbGJhY2suXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgVGhlIHVybCB0byBtYWtlIHJlcXVlc3QgdG8uIENvdWxkIGJlIGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHRoZSBzZXJ2aWNlIGJhc2UgdXJpLlxuICAgKiBAcGFyYW0geyhyZXNwb25zZTogU2VydmljZVJlc3BvbnNlPEQ+KSA9PiB2b2lkfSBvblBhZ2VSZXRyaWV2ZWQgVGhlIGNhbGxiYWNrIHVzZWQgdG8gcmV0dXJuIHJlc3VsdHMsIHBhZ2UgYnkgcGFnZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2VTaXplIFRoZSBwYWdlIHNpemUgdXNlZCB0byByZXF1ZXN0IGl0ZW1zLlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IEZvcm1EYXRhfSBib2R5IE9wdGlvbmFsIGJvZHkgdG8gc2VuZCBpbiB0aGUgcmVxdWVzdC5cbiAgICogQHBhcmFtIHtIZWFkZXJzfSBjdXN0b21IZWFkZXJzIE9wdGlvbmFsIGhlYWRlcnMgdG8gYXR0YWNoIHRvIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXV0aCBUaGUgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSByZXF1ZXN0IHJlcXVpcmVzIGF1dGhlbnRpY2F0aW9uLiBJZiB0cnVlLCB0aGUgY3JlZGVudGlhbHMgd2lsbCBiZSByZXF1ZXN0ZWQgZnJvbSB0aGUgY29uZmlndXJhdGlvbiB7QHNlZSBDb25maWcjY3JlZGVudGlhbHMgfSBhbmQgQXV0aG9yaXphdGlvbiBoZWFkZXIgd2lsbCBiZSBhdHRhY2hlZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBwYWdlcyBoYXZlIGJlZW4gcmV0cmlldmVkLlxuICAgKiBAdGhyb3dzIHtTZXJ2aWNlRXJyb3J9IGluIGNhc2Ugb2YgdGhlIGVycm9yIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0SXRlbXNXaXRoUGFnZXM8RD4oXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb25QYWdlUmV0cmlldmVkOiAocmVzcG9uc2U6IFNlcnZpY2VSZXNwb25zZTxEPikgPT4gdm9pZCxcbiAgICBwYWdlU2l6ZTogbnVtYmVyLFxuICAgIGJvZHk/OiBzdHJpbmcgfCBGb3JtRGF0YSxcbiAgICBjdXN0b21IZWFkZXJzPzogSGVhZGVycyxcbiAgICBhdXRoOiBib29sZWFuID0gdHJ1ZSxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gVmFsaWRhdGUgcGFyYW1ldGVyXG4gICAgaWYgKHBhZ2VTaXplIDw9IDAgfHwgIU51bWJlci5pc0ludGVnZXIocGFnZVNpemUpKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcigncGFnZVNpemUgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXInKTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkZXJzID0gY3VzdG9tSGVhZGVycyA/IG5ldyBIZWFkZXJzKGN1c3RvbUhlYWRlcnMpIDogbmV3IEhlYWRlcnMoKTtcbiAgICBjb25zdCByYW5nZTogUmFuZ2UgPSB7IHN0YXJ0OiAwLCBlbmQ6IHBhZ2VTaXplIC0gMSB9O1xuICAgIGhlYWRlcnMuc2V0KCdSYW5nZScsIGBpdGVtcz0ke3JhbmdlLnN0YXJ0fS0ke3JhbmdlLmVuZH1gKTtcblxuICAgIGxldCByZXNwb25zZSA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3Q8RD4odXJsLCAnR0VUJywgYm9keSwgaGVhZGVycywgYXV0aCk7XG5cbiAgICBkbyB7XG4gICAgICBjb25zdCByZXNwb25zZVJhbmdlID0gdGhpcy5nZXRSYW5nZShyZXNwb25zZSk7XG4gICAgICBjb25zdCBoYXNOZXh0UGFnZSA9IHRoaXMuaGFzTW9yZVBhZ2VzKHJlc3BvbnNlLCByZXNwb25zZVJhbmdlKTtcblxuICAgICAgbGV0IG5leHRQYWdlOiBQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj4gfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoaGFzTmV4dFBhZ2UgJiYgcmVzcG9uc2VSYW5nZSAmJiByZXNwb25zZVJhbmdlLnRvdGFsKSB7XG4gICAgICAgIHJhbmdlLnN0YXJ0ID0gcmVzcG9uc2VSYW5nZS5lbmQgKyAxO1xuICAgICAgICByYW5nZS5lbmQgPSBNYXRoLm1pbihcbiAgICAgICAgICByZXNwb25zZVJhbmdlLnRvdGFsIC0gMSxcbiAgICAgICAgICByYW5nZS5zdGFydCArIHBhZ2VTaXplIC0gMSxcbiAgICAgICAgKTtcbiAgICAgICAgaGVhZGVycy5zZXQoJ1JhbmdlJywgYGl0ZW1zPSR7cmFuZ2Uuc3RhcnR9LSR7cmFuZ2UuZW5kfWApO1xuXG4gICAgICAgIC8vIGluaXRpYXRlIG5leHQgcGFnZSByZXF1ZXN0LCBidXQgZG9uJ3Qgd2FpdCBvbiBpdCB5ZXRcbiAgICAgICAgbmV4dFBhZ2UgPSB0aGlzLm1ha2VSZXF1ZXN0PEQ+KHVybCwgJ0dFVCcsIGJvZHksIGhlYWRlcnMsIGF1dGgpO1xuICAgICAgfVxuXG4gICAgICBvblBhZ2VSZXRyaWV2ZWQocmVzcG9uc2UpO1xuXG4gICAgICBpZiAobmV4dFBhZ2UpIHtcbiAgICAgICAgcmVzcG9uc2UgPSBhd2FpdCBuZXh0UGFnZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICAvLyBpZiB3ZSByZWFjaGVkIHRoaXMgcG9pbnQsIHdlIHN0aWxsIGhhdmUgaXRlbXMgdG8gYWNxdWlyZS5cbiAgICB9IHdoaWxlICh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaGVzIGFsbCB0aGUgaXRlbXMgcGFnZSBieSBwYWdlIHVzaW5nIGFkYXB0aXZlIHBhZ2luYXRpb24sIHJldHVybmluZyBlYWNoIHBhZ2UgcmVzdWx0cyBpbiBhIGNhbGxiYWNrLlxuICAgKiBTdGFydHMgd2l0aCBhIHNtYWxsIGluaXRpYWwgcGFnZSBzaXplIGZvciBmYXN0ZXIgZmlyc3QgcmVzcG9uc2UsIHRoZW4gc3dpdGNoZXMgdG8gYSBsYXJnZXIgcGFnZSBzaXplIGFmdGVyIGEgdGhyZXNob2xkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSB1cmwgdG8gbWFrZSByZXF1ZXN0IHRvLiBDb3VsZCBiZSBhYnNvbHV0ZSBvciByZWxhdGl2ZSB0byB0aGUgc2VydmljZSBiYXNlIHVyaS5cbiAgICogQHBhcmFtIHsocmVzcG9uc2U6IFNlcnZpY2VSZXNwb25zZTxEPikgPT4gdm9pZH0gb25QYWdlUmV0cmlldmVkIFRoZSBjYWxsYmFjayB1c2VkIHRvIHJldHVybiByZXN1bHRzLCBwYWdlIGJ5IHBhZ2UuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbml0aWFsUGFnZVNpemUgVGhlIHBhZ2Ugc2l6ZSBmb3IgaW5pdGlhbCByZXF1ZXN0cyAoZGVmYXVsdDogMTApLlxuICAgKiBAcGFyYW0ge251bWJlcn0gc3RhbmRhcmRQYWdlU2l6ZSBUaGUgcGFnZSBzaXplIGFmdGVyIHRocmVzaG9sZCBpcyByZWFjaGVkIChkZWZhdWx0OiAxMDApLlxuICAgKiBAcGFyYW0ge251bWJlcn0gdGhyZXNob2xkIFRoZSBudW1iZXIgb2YgaXRlbXMgdG8gbG9hZCBiZWZvcmUgc3dpdGNoaW5nIHRvIHN0YW5kYXJkIHBhZ2Ugc2l6ZSAoZGVmYXVsdDogNTApLlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IEZvcm1EYXRhfSBib2R5IE9wdGlvbmFsIGJvZHkgdG8gc2VuZCBpbiB0aGUgcmVxdWVzdC5cbiAgICogQHBhcmFtIHtIZWFkZXJzfSBjdXN0b21IZWFkZXJzIE9wdGlvbmFsIGhlYWRlcnMgdG8gYXR0YWNoIHRvIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXV0aCBUaGUgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSByZXF1ZXN0IHJlcXVpcmVzIGF1dGhlbnRpY2F0aW9uLiBJZiB0cnVlLCB0aGUgY3JlZGVudGlhbHMgd2lsbCBiZSByZXF1ZXN0ZWQgZnJvbSB0aGUgY29uZmlndXJhdGlvbiB7QHNlZSBDb25maWcjY3JlZGVudGlhbHMgfSBhbmQgQXV0aG9yaXphdGlvbiBoZWFkZXIgd2lsbCBiZSBhdHRhY2hlZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBwYWdlcyBoYXZlIGJlZW4gcmV0cmlldmVkLlxuICAgKiBAdGhyb3dzIHtTZXJ2aWNlRXJyb3J9IGluIGNhc2Ugb2YgdGhlIGVycm9yIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0SXRlbXNXaXRoUGFnZXNBZGFwdGl2ZTxEPihcbiAgICB1cmw6IHN0cmluZyxcbiAgICBvblBhZ2VSZXRyaWV2ZWQ6IChyZXNwb25zZTogU2VydmljZVJlc3BvbnNlPEQ+KSA9PiB2b2lkLFxuICAgIGluaXRpYWxQYWdlU2l6ZTogbnVtYmVyID0gMTAsXG4gICAgc3RhbmRhcmRQYWdlU2l6ZTogbnVtYmVyID0gMTAwLFxuICAgIHRocmVzaG9sZDogbnVtYmVyID0gNTAsXG4gICAgYm9keT86IHN0cmluZyB8IEZvcm1EYXRhLFxuICAgIGN1c3RvbUhlYWRlcnM/OiBIZWFkZXJzLFxuICAgIGF1dGg6IGJvb2xlYW4gPSB0cnVlLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBWYWxpZGF0aW5nIHBhcmFtZXRlcnMuLi5cbiAgICBpZiAoaW5pdGlhbFBhZ2VTaXplIDw9IDAgfHwgIU51bWJlci5pc0ludGVnZXIoaW5pdGlhbFBhZ2VTaXplKSkge1xuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luaXRpYWxQYWdlU2l6ZSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlcicpO1xuICAgIH1cbiAgICBpZiAoc3RhbmRhcmRQYWdlU2l6ZSA8PSAwIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHN0YW5kYXJkUGFnZVNpemUpKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc3RhbmRhcmRQYWdlU2l6ZSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlcicpO1xuICAgIH1cbiAgICBpZiAodGhyZXNob2xkIDwgMCB8fCAhTnVtYmVyLmlzSW50ZWdlcih0aHJlc2hvbGQpKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndGhyZXNob2xkIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlcicpO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWRlcnMgPSBjdXN0b21IZWFkZXJzID8gbmV3IEhlYWRlcnMoY3VzdG9tSGVhZGVycykgOiBuZXcgSGVhZGVycygpO1xuXG4gICAgbGV0IHRvdGFsTG9hZGVkID0gMDtcbiAgICBsZXQgY3VycmVudEluZGV4ID0gMDtcblxuICAgIC8vIE1ha2UgZmlyc3QgcmVxdWVzdCB3aXRoIGFwcHJvcHJpYXRlIHBhZ2Ugc2l6ZSAodXNlIHN0YW5kYXJkUGFnZVNpemUgaWYgdGhyZXNob2xkIGlzIDApXG4gICAgY29uc3QgZmlyc3RQYWdlU2l6ZSA9IHRocmVzaG9sZCA9PT0gMCA/IHN0YW5kYXJkUGFnZVNpemUgOiBpbml0aWFsUGFnZVNpemU7XG4gICAgaGVhZGVycy5zZXQoXG4gICAgICAnUmFuZ2UnLFxuICAgICAgYGl0ZW1zPSR7Y3VycmVudEluZGV4fS0ke2N1cnJlbnRJbmRleCArIGZpcnN0UGFnZVNpemUgLSAxfWAsXG4gICAgKTtcbiAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0PEQ+KHVybCwgJ0dFVCcsIGJvZHksIGhlYWRlcnMsIGF1dGgpO1xuXG4gICAgZG8ge1xuICAgICAgLy8gQ29tcHV0ZSBwYWdpbmF0aW9uIHN0YXRlIEJFRk9SRSBjYWxsaW5nIGNhbGxiYWNrIChpbiBjYXNlIGNhbGxiYWNrIG11dGF0ZXMgcmVzcG9uc2UuZGF0YSlcbiAgICAgIGNvbnN0IGl0ZW1zSW5QYWdlID0gQXJyYXkuaXNBcnJheShyZXNwb25zZS5kYXRhKVxuICAgICAgICA/IHJlc3BvbnNlLmRhdGEubGVuZ3RoXG4gICAgICAgIDogMDtcbiAgICAgIGNvbnN0IHJlc3BvbnNlUmFuZ2UgPSB0aGlzLmdldFJhbmdlKHJlc3BvbnNlKTtcbiAgICAgIGNvbnN0IGhhc01vcmVQYWdlcyA9IHRoaXMuaGFzTW9yZVBhZ2VzKHJlc3BvbnNlLCByZXNwb25zZVJhbmdlKTtcblxuICAgICAgLy8gVXBkYXRlIGNvdW50ZXJzXG4gICAgICAvLyBVc2UgYWN0dWFsIGFycmF5IGxlbmd0aCBmb3IgdG90YWxMb2FkZWQgKHNvdXJjZSBvZiB0cnV0aCBmb3IgaXRlbXMgcmV0cmlldmVkKVxuICAgICAgdG90YWxMb2FkZWQgKz0gaXRlbXNJblBhZ2U7XG5cbiAgICAgIC8vIFVzZSByZXNwb25zZVJhbmdlLmVuZCArIDEgZm9yIG5leHQgaW5kZXggKGF1dGhvcml0YXRpdmUgZm9yIHJhbmdlLWJhc2VkIHBhZ2luYXRpb24pXG4gICAgICAvLyBUaGlzIHByZXZlbnRzIG92ZXJsYXBwaW5nL2R1cGxpY2F0ZSByZXF1ZXN0cyBldmVuIGlmIHRoZSBzZXJ2ZXIgcmV0dXJucyBmZXdlciBpdGVtcyB0aGFuIHRoZSByYW5nZVxuICAgICAgaWYgKHJlc3BvbnNlUmFuZ2UgJiYgdHlwZW9mIHJlc3BvbnNlUmFuZ2UuZW5kID09PSAnbnVtYmVyJykge1xuICAgICAgICBjdXJyZW50SW5kZXggPSByZXNwb25zZVJhbmdlLmVuZCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGYWxsYmFjayBpZiBubyByYW5nZSBoZWFkZXIgKHNob3VsZG4ndCBoYXBwZW4gaW4gbm9ybWFsIHJhbmdlLWJhc2VkIHBhZ2luYXRpb24pXG4gICAgICAgIGN1cnJlbnRJbmRleCArPSBpdGVtc0luUGFnZTtcbiAgICAgIH1cblxuICAgICAgbGV0IG5leHRQYWdlOiBQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj4gfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoaGFzTW9yZVBhZ2VzICYmIHJlc3BvbnNlUmFuZ2UgJiYgcmVzcG9uc2VSYW5nZS50b3RhbCkge1xuICAgICAgICAvLyBEZXRlcm1pbmUgbmV4dCBwYWdlIHNpemUgYmFzZWQgb24gdXBkYXRlZCB0b3RhbExvYWRlZFxuICAgICAgICBjb25zdCBuZXh0UGFnZVNpemUgPVxuICAgICAgICAgIHRvdGFsTG9hZGVkIDwgdGhyZXNob2xkID8gaW5pdGlhbFBhZ2VTaXplIDogc3RhbmRhcmRQYWdlU2l6ZTtcbiAgICAgICAgLy8gVXNlIGN1cnJlbnQgcmVzcG9uc2UncyB0b3RhbCBmb3IgY2xhbXBpbmcgKGhhbmRsZXMgZHluYW1pYyB0b3RhbCBjaGFuZ2VzKVxuICAgICAgICBjb25zdCBlbmRJbmRleCA9IE1hdGgubWluKFxuICAgICAgICAgIHJlc3BvbnNlUmFuZ2UudG90YWwgLSAxLFxuICAgICAgICAgIGN1cnJlbnRJbmRleCArIG5leHRQYWdlU2l6ZSAtIDEsXG4gICAgICAgICk7XG5cbiAgICAgICAgaGVhZGVycy5zZXQoJ1JhbmdlJywgYGl0ZW1zPSR7Y3VycmVudEluZGV4fS0ke2VuZEluZGV4fWApO1xuXG4gICAgICAgIC8vIEluaXRpYXRlIG5leHQgcGFnZSByZXF1ZXN0LCBidXQgZG9uJ3Qgd2FpdCBvbiBpdCB5ZXRcbiAgICAgICAgbmV4dFBhZ2UgPSB0aGlzLm1ha2VSZXF1ZXN0PEQ+KHVybCwgJ0dFVCcsIGJvZHksIGhlYWRlcnMsIGF1dGgpO1xuICAgICAgfVxuXG4gICAgICAvLyBDYWxsIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBwYWdlIGRhdGFcbiAgICAgIG9uUGFnZVJldHJpZXZlZChyZXNwb25zZSk7XG5cbiAgICAgIGlmIChuZXh0UGFnZSkge1xuICAgICAgICByZXNwb25zZSA9IGF3YWl0IG5leHRQYWdlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIC8vIElmIHdlIHJlYWNoZWQgdGhpcyBwb2ludCwgd2Ugc3RpbGwgaGF2ZSBpdGVtcyB0byBhY3F1aXJlXG4gICAgfSB3aGlsZSAodHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogTWFrZXMgYSBzZXJ2aWNlIHJlcXVlc3Qgd2l0aCBhbGwgbmVlZGVkIGF1dGhlbnRpY2F0aW9uIGFuZCByZXRyeSBsb2dpYy4gQ29udmVydHMgZXJyb3IgcmVzcG9uc2UgdG8gZXhjZXB0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSB1cmwgdG8gbWFrZSByZXF1ZXN0IHRvLiBDb3VsZCBiZSBhYnNvbHV0ZSBvciByZWxhdGl2ZSB0byB0aGUgc2VydmljZSBiYXNlIHVyaS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgRm9ybURhdGEgfCBCbG9ifSBib2R5IFRoZSBib2R5IHRvIHNlbmQgaW4gdGhlIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7SGVhZGVyc30gY3VzdG9tSGVhZGVycyBUaGUgY3VzdG9tIGhlYWRlcnMgdG8gYXR0YWNoIHRvIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXV0aCBUaGUgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSByZXF1ZXN0IHJlcXVpcmVzIGF1dGhlbnRpY2F0aW9uLiBJZiB0cnVlLCB0aGUgY3JlZGVudGlhbHMgd2lsbCBiZSByZXF1ZXN0ZWQgZnJvbSB0aGUgY29uZmlndXJhdGlvbiB7QHNlZSBDb25maWcjY3JlZGVudGlhbHMgfSBhbmQgQXV0aG9yaXphdGlvbiBoZWFkZXIgd2lsbCBiZSBhdHRhY2hlZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8U2VydmljZVJlc3BvbnNlPEQ+Pn0gVGhlIHNlcnZpY2UgcmVzcG9uc2UuXG4gICAqIEB0aHJvd3Mge1NlcnZpY2VFcnJvcn0gaW4gY2FzZSBvZiB0aGUgZXJyb3IgcmVzcG9uc2UgZnJvbSB0aGUgc2VydmljZS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyByZXF1ZXN0KFxuICAgIHVybDogc3RyaW5nLFxuICAgIG1ldGhvZDogJ0dFVCcgfCAnUFVUJyB8ICdQT1NUJyB8ICdQQVRDSCcgfCAnREVMRVRFJyA9ICdHRVQnLFxuICAgIGJvZHk/OiBzdHJpbmcgfCBGb3JtRGF0YSB8IEJsb2IsXG4gICAgY3VzdG9tSGVhZGVycz86IEhlYWRlcnMsXG4gICAgYXV0aDogYm9vbGVhbiA9IHRydWUsXG4gICk6IFByb21pc2U8U2VydmljZVJlc3BvbnNlPHZvaWQ+PiB7XG4gICAgLy8gdGhpcyBtZXRob2Qgc3VwcG9ydHMgMyBjYXNlczogYWJzb2x1dGUgdXJsLCBhYnNvbHV0ZSBwYXRoLCByZWxhdGl2ZSBwYXRoXG4gICAgY29uc3QgcmVxdWVzdFVybCA9IHVybC5zdGFydHNXaXRoKCdodHRwJylcbiAgICAgID8gdXJsXG4gICAgICA6IHVybC5zdGFydHNXaXRoKCcvJylcbiAgICAgICAgPyBleHRyYWN0RW5kcG9pbnQodGhpcy5jb25maWcuc2VydmljZVVyaSkgKyB1cmxcbiAgICAgICAgOiB0aGlzLmNvbmZpZy5zZXJ2aWNlVXJpICsgdXJsO1xuXG4gICAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKCk7XG4gICAgY29uc3QgY29udGVudFR5cGUgPSBjdXN0b21IZWFkZXJzXG4gICAgICA/IGN1c3RvbUhlYWRlcnMuZ2V0KCdDb250ZW50LVR5cGUnKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgaWYgKCFjb250ZW50VHlwZSAmJiBib2R5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGhlYWRlcnMuc2V0KCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgIH1cblxuICAgIGlmIChjdXN0b21IZWFkZXJzKSB7XG4gICAgICBjdXN0b21IZWFkZXJzLmZvckVhY2goKHZhbHVlOiBzdHJpbmcsIGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGhlYWRlcnMuYXBwZW5kKGtleSwgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZmV0Y2hXaXRoUmV0cnkoXG4gICAgICByZXF1ZXN0VXJsLFxuICAgICAge1xuICAgICAgICBib2R5LFxuICAgICAgICBoZWFkZXJzLFxuICAgICAgICBtZXRob2QsXG4gICAgICAgIHJlZGlyZWN0OiAnZm9sbG93JyxcbiAgICAgIH0sXG4gICAgICBhdXRoLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogSG93IG1hbnkgdGltZXMgYSBmYWlsZWQgcmVxdWVzdCBzaG91bGQgYmUgcmV0cmllZCBiZWZvcmUgZ2l2aW5nIHVwLlxuICAgKiB0aGUgZGVmYXVsdFJldHJ5Q291bnQgY2FuIGJlIG92ZXJyaWRkZW4gYnkgc2VydmljZSBjbGFzc2VzLlxuICAgKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHB1YmxpYyBtYXhSZXRyaWVzKCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuY29uZmlnLm1heFJldHJpZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLm1heFJldHJpZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmRlZmF1bHRSZXRyeUNvdW50O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaXJzdCByZXRyeSBnb2VzIGltbWVkaWF0ZWx5ICgwbXMgZGVsYXkpIHRoZW4gZXhwb25lbnRpYWwgZ3Jvd3RoIHdpdGggMTAwbXMgYXMgYSBiYXNlLlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHB1YmxpYyBjYWxjdWxhdGVSZXRyeURlbGF5KHJldHJ5Q291bnQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKHJldHJ5Q291bnQgPT09IDApIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBiYXNlID0gMTAwO1xuICAgICAgcmV0dXJuIE1hdGgucmFuZG9tKCkgKiAoTWF0aC5wb3coMiwgcmV0cnlDb3VudCAtIDEpICogYmFzZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSByZXRyeWFibGVFcnJvcihlcnJvcjogU2VydmljZUVycm9yKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy50aW1lb3V0RXJyb3IoZXJyb3IpIHx8XG4gICAgICB0aGlzLm5ldHdvcmtpbmdFcnJvcihlcnJvcikgfHxcbiAgICAgIHRoaXMuZXhwaXJlZENyZWRlbnRpYWxzRXJyb3IoZXJyb3IpIHx8XG4gICAgICB0aGlzLnRocm90dGxlZEVycm9yKGVycm9yKSB8fFxuICAgICAgZXJyb3IucmVzcG9uc2Uuc3RhdHVzID49IDUwMFxuICAgICkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgbmV0d29ya2luZ0Vycm9yKGVycm9yOiBTZXJ2aWNlRXJyb3IpIHtcbiAgICByZXR1cm4gZXJyb3IuZXJyb3JDb2RlID09PSAnTmV0d29ya2luZ0Vycm9yJztcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgdGltZW91dEVycm9yKGVycm9yOiBTZXJ2aWNlRXJyb3IpIHtcbiAgICByZXR1cm4gZXJyb3IuZXJyb3JDb2RlID09PSAnVGltZW91dEVycm9yJztcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgZXhwaXJlZENyZWRlbnRpYWxzRXJyb3IoZXJyb3I6IFNlcnZpY2VFcnJvcikge1xuICAgIGlmIChlcnJvci5yZXNwb25zZS5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgY29uc3QgY3JlZGVudGlhbHMgPSB0aGlzLmNvbmZpZy5jcmVkZW50aWFscztcbiAgICAgIGlmIChcbiAgICAgICAgY3JlZGVudGlhbHMgJiZcbiAgICAgICAgdHlwZW9mIChjcmVkZW50aWFscyBhcyBDcmVkZW50aWFscykuZXhwaXJlZCA9PT0gJ2Jvb2xlYW4nXG4gICAgICApIHtcbiAgICAgICAgKGNyZWRlbnRpYWxzIGFzIENyZWRlbnRpYWxzKS5leHBpcmVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQGFwaSBwcml2YXRlXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIHRocm90dGxlZEVycm9yKGVycm9yOiBTZXJ2aWNlRXJyb3IpIHtcbiAgICAvLyBBV1MgQVBJIEdhdGV3YXkgcmV0dXJucyA0MjkgaW4gY2FzZSBvZiB0aHJvdHRsaW5nIGVycm9yc1xuICAgIGlmIChlcnJvci5yZXNwb25zZS5zdGF0dXMgPT09IDQyOSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFrZXMgYSBzZXJ2aWNlIGNhbGwgYW5kIHRha2VzIGNhcmUgYWJvdXQgcmV0cnkgbG9naWMgKHJlLWF1dGhlbnRpY2F0aW9uIGlmIG5lZWRlZCkuXG4gICAqIE5vdGUgdGhlIDx2b2lkPiBhcyBhIGdlbmVyaWMgcGFyYW1ldGVyLiBUaGlzIG1ldGhvZCBkb2VzIG5vdCByZWFkIHRoZSByZXNwb25zZSBib2R5LiBUaGUgU2VydmljZVJlc3BvbnNlIHJldHVybiB2YWx1ZSB3aWxsIGJlIGNhc2VkIHRvIG5lZWRlZCB0eXBlIG9uIHVwcGVyIGxldmVscyBvZiB0aGUgY29kZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHVybCBUaGUgdXJsIHRvIG1ha2UgcmVxdWVzdCB0by4gQ291bGQgYmUgYWJzb2x1dGUgb3IgcmVsYXRpdmUgdG8gdGhlIHNlcnZpY2UgYmFzZSB1cmkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMgVGhlIGZldGNoIHBhcmFtZXRlcnMuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXV0aCBUaGUgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSByZXF1ZXN0IHJlcXVpcmVzIGF1dGhlbnRpY2F0aW9uLiBJZiB0cnVlLCB0aGUgY3JlZGVudGlhbHMgd2lsbCBiZSByZXF1ZXN0ZWQgZnJvbSB0aGUgY29uZmlndXJhdGlvbiB7QHNlZSBDb25maWcjY3JlZGVudGlhbHMgfSBhbmQgQXV0aG9yaXphdGlvbiBoZWFkZXIgd2lsbCBiZSBhdHRhY2hlZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8U2VydmljZVJlc3BvbnNlPHZvaWQ+Pn0gVGhlIHNlcnZpY2UgcmVzcG9uc2UuXG4gICAqIEB0aHJvd3Mge1NlcnZpY2VFcnJvcn0gaW4gY2FzZSBvZiB0aGUgZXJyb3IgcmVzcG9uc2UgZnJvbSB0aGUgc2VydmljZS5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hXaXRoUmV0cnkoXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgcGFyYW1zOiBhbnksXG4gICAgYXV0aDogYm9vbGVhbiA9IHRydWUsXG4gICk6IFByb21pc2U8U2VydmljZVJlc3BvbnNlPHZvaWQ+PiB7XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5jb25maWcubG9nZ2VyO1xuICAgIGNvbnN0IHJlc3VsdDogU2VydmljZVJlc3BvbnNlPHZvaWQ+ID0gbmV3IFNlcnZpY2VSZXNwb25zZTx2b2lkPihcbiAgICAgIHRoaXMsXG4gICAgICBuZXcgUmVzcG9uc2UoKSxcbiAgICAgIHZvaWQgMCxcbiAgICApO1xuICAgIGRvIHtcbiAgICAgIGNvbnN0IGNyZWRlbnRpYWxzID0gdGhpcy5jb25maWcuY3JlZGVudGlhbHM7XG4gICAgICBpZiAoYXV0aCAmJiBjcmVkZW50aWFscykge1xuICAgICAgICBpZiAodHlwZW9mIChjcmVkZW50aWFscyBhcyBTZXJ2aWNlQ3JlZGVudGlhbHMpLmdldCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCAoY3JlZGVudGlhbHMgYXMgU2VydmljZUNyZWRlbnRpYWxzKS5nZXQoKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIHRoaXMubG9nKGBbVElEXSBGYWlsZWQgdG8gYWNxdWlyZSB0b2tlbnM6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY3JlZGVudGlhbHMudG9rZW4pIHtcbiAgICAgICAgICBwYXJhbXMuaGVhZGVycy5zZXQoJ0F1dGhvcml6YXRpb24nLCAnQmVhcmVyICcgKyBjcmVkZW50aWFscy50b2tlbik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5mZXRjaCh1cmwsIHBhcmFtcyk7XG4gICAgICBpZiAobG9nZ2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgZGVsdGEgPSAoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgLyAxMDAwO1xuICAgICAgICBjb25zdCBpc29EYXRlID0gbmV3IERhdGUoc3RhcnRUaW1lKS50b0lTT1N0cmluZygpO1xuICAgICAgICBjb25zdCByZXF1ZXN0Q29udGVudExlbmd0aCA9IHBhcmFtcy5ib2R5ID8gcGFyYW1zLmJvZHkubGVuZ3RoIDogMDtcbiAgICAgICAgY29uc3QgcmVzcG9uc2VDb250ZW50TGVuZ3RoI