UNPKG

trimble-connect-sdk

Version:

Trimble Connect SDK for JavaScript

265 lines 42.7 kB
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* () { const headers = customHeaders !== null && customHeaders !== void 0 ? customHeaders : new Headers(); if (headers.has('Range')) { headers.delete('Range'); } const range = { start: 0, end: pageSize - 1 }; headers.append('Range', `items=${range.start}-${range.end}`); let response = yield this.makeRequest(url, 'GET', body, headers, auth); do { const responseRange = this.getRange(response); const hasNextPage = Array.isArray(response.data) && response.data.length !== 0 && responseRange && responseRange.total && responseRange.end < responseRange.total - 1; let nextPage; if (hasNextPage && responseRange && responseRange.total) { headers.delete('Range'); range.start = responseRange.end + 1; range.end = Math.min(responseRange.total - 1, range.start + pageSize - 1); headers.append('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); }); } 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; } } 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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QUMsQ0FBQyxDQUFDO1lBQzlCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVyQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQztTQUM5QjtRQUFDLFdBQU07WUFDTixPQUFPLFNBQVMsQ0FBQztTQUNsQjtJQUNILENBQUM7SUFPYSxHQUFHLENBQUMsSUFBWTs7WUFDNUIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDbEMsSUFBSSxNQUFNLEtBQUssU0FBUyxFQUFFO2dCQUN4QixJQUFJLE9BQU8sTUFBTSxDQUFDLEdBQUcsS0FBSyxVQUFVLEVBQUU7b0JBQ3BDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7aUJBQ2xCO3FCQUFNLElBQUksT0FBTyxNQUFNLENBQUMsS0FBSyxLQUFLLFVBQVUsRUFBRTtvQkFDN0MsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUM7aUJBQzNCO2FBQ0Y7UUFDSCxDQUFDO0tBQUE7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbmZpZ3VyYXRpb24gfSBmcm9tICcuL2NvbmZpZyc7XG5pbXBvcnQgeyBDcmVkZW50aWFscyB9IGZyb20gJy4vY3JlZGVudGlhbHMnO1xuaW1wb3J0IHsgUmFuZ2UgfSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgeyBTZXJ2aWNlRXJyb3IgfSBmcm9tICcuL2Vycm9yJztcbmltcG9ydCB7IFNlcnZpY2VSZXNwb25zZSB9IGZyb20gJy4vcmVzcG9uc2UnO1xuaW1wb3J0IHsgU2VydmljZUNyZWRlbnRpYWxzIH0gZnJvbSAnLi9zZXJ2aWNlX2NyZWRlbnRpYWxzJztcblxuLyoqIEBpbnRlcm5hbCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RFbmRwb2ludCh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHNjaGVtYUluZGV4ID0gdXJsLmluZGV4T2YoJy8vJyk7XG4gIGNvbnN0IGZpcnN0U2VwYXJhdG9ySW5kZXggPSB1cmwuaW5kZXhPZignLycsIHNjaGVtYUluZGV4ICsgMik7XG5cbiAgcmV0dXJuIHVybC5zdWJzdHJpbmcoMCwgZmlyc3RTZXBhcmF0b3JJbmRleCk7XG59XG5cbmZ1bmN0aW9uIGRlbGF5KG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgc2V0VGltZW91dChyZXNvbHZlLCBtcyk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFRoZSBzZXJ2aWNlIGNsaWVudCB0aGF0IHJlcHJlc2VudHMgY29ubmVjdGlvbiB0byB0aGUgT3JnYW5pemVyIFNlcnZpY2UuXG4gKiBFYWNoIEFQSSBvcGVyYXRpb24gaXMgZXhwb3NlZCBhcyBhIGZ1bmN0aW9uIG9uIHNlcnZpY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXJ2aWNlIHtcbiAgLyoqIFVzZWQgaWYgbWF4UmV0cmllcyBpcyBub3Qgc3BlY2lmaWVkIGluIHtAc2VlIENvbmZpZ3VyYXRpb24jbWF4UmV0cmllcyB9LiBUaGUgZGVmYXVsdFJldHJ5Q291bnQgY2FuIGJlIG92ZXJyaWRlbiBieSBzZXJ2aWNlIGNsYXNzZXMuICovXG4gIHByaXZhdGUgZGVmYXVsdFJldHJ5Q291bnQ6IG51bWJlciA9IDM7XG5cbiAgLyoqXG4gICAqIEBjb25zdHJ1Y3RvciBDb25zdHJ1Y3RzIGEgc2VydmljZSBvYmplY3QuXG4gICAqIEBwYXJhbSB7Q29uZmlnfSBjb25maWcgVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyAoZS5nLiBzZXJ2aWNlIHVybCkuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgY29uZmlnOiBDb25maWd1cmF0aW9uKSB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5zZXJ2aWNlVXJpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBzZXJ2aWNlVXJpIGlzIHJlcXVpcmVkJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoZWQgdGhlIG5leHQgcGFnZSBmcm9tdCBoZSBzZXF1ZW5jZSBvZiBwYWdlcyBpbml0aWF0ZWQgYnkge0BzZWUgT3JnYW5pemVyLmxpc3RUcmVlcyB9LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSB1cmwgdG8gbWFrZSByZXF1ZXN0IHRvLiBDb3VsZCBiZSBhYnNvbHV0ZSBvciByZWxhdGl2ZSB0byB0aGUgc2VydmljZSBiYXNlIHVyaS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBib2R5IFRoZSBib2R5IHRvIHNlbmQgaW4gdGhlIHJlcXVlc3QgKHdpbGwgYmUgc2VyaWFsaXplZCB0byBKU09OKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGhlYWRlcnMgVGhlIGhlYWRlcnMgdG8gYXR0YWNoIHRvIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXV0aCBUaGUgdmFsdWUgaW5kaWNhdGluZyB3ZXRoZXIgdGhlIHJlcXVlc3QgcmVxdWlyZXMgYXV0aGVudGljYXRpb24uIElmIHRydWUsIHRoZSBjcmVkZW50aWFscyB3aWxsIGJlIHJlcXVlc3RlZCBmcm9tIHRoZSBjb25maWd1cmF0aW9uIHtAc2VlIENvbmZpZyNjcmVkZW50aWFscyB9IGFuZCBBdXRob3JpemF0aW9uIGhlYWRlciB3aWxsIGJlIGF0dGFjaGVkLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTZXJ2aWNlUmVzcG9uc2U8RD4+fSBUaGUgc2VydmljZSByZXNwb25zZS5cbiAgICogQHRocm93cyB7U2VydmljZUVycm9yfSBpbiBjYXNlIG9mIHRoZSBlcnJvciByZXNwb25zZSBmcm9tIHRoZSBzZXJ2aWNlLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIG1ha2VSZXF1ZXN0PEQ+KFxuICAgIHVybDogc3RyaW5nLFxuICAgIG1ldGhvZDogJ0dFVCcgfCAnUFVUJyB8ICdQT1NUJyB8ICdQQVRDSCcgfCAnREVMRVRFJyA9ICdHRVQnLFxuICAgIGJvZHk/OiBzdHJpbmcgfCBGb3JtRGF0YSxcbiAgICBjdXN0b21IZWFkZXJzPzogSGVhZGVycyxcbiAgICBhdXRoOiBib29sZWFuID0gdHJ1ZVxuICApOiBQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj4ge1xuICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgSGVhZGVycyh7IEFjY2VwdDogJ2FwcGxpY2F0aW9uL2pzb24nIH0pO1xuICAgIGlmIChjdXN0b21IZWFkZXJzKSB7XG4gICAgICBjdXN0b21IZWFkZXJzLmZvckVhY2goKHZhbHVlOiBzdHJpbmcsIGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGhlYWRlcnMuYXBwZW5kKGtleSwgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3BvbnNlID0gKGF3YWl0IHRoaXMucmVxdWVzdChcbiAgICAgIHVybCxcbiAgICAgIG1ldGhvZCxcbiAgICAgIGJvZHksXG4gICAgICBoZWFkZXJzLFxuICAgICAgYXV0aFxuICAgICkpIGFzIGFueSBhcyBTZXJ2aWNlUmVzcG9uc2U8RD47XG5cbiAgICAvLyBkZXNlcmlhbGl6ZSByZXNwb25zZSBib2R5LiBJZiBzZXJ2aWNlIHJlc3BvbmRlZCB3aXRoIGFuIGVycm9yIGl0IHdhcyB0aHJvd24gYWxyZWFkeS5cbiAgICBpZiAocmVzcG9uc2UucmVzcG9uc2Uuc3RhdHVzICE9PSAyMDQpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gcmVzcG9uc2UucmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpO1xuICAgICAgaWYgKFxuICAgICAgICBjb250ZW50VHlwZSA9PT0gbnVsbCB8fFxuICAgICAgICBjb250ZW50VHlwZS5pbmRleE9mKCdhcHBsaWNhdGlvbi9qc29uJykgIT09IC0xXG4gICAgICApIHtcbiAgICAgICAgcmVzcG9uc2UuZGF0YSA9IChhd2FpdCByZXNwb25zZS5yZXNwb25zZS5qc29uKCkpIGFzIEQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgU2VydmljZUVycm9yKFxuICAgICAgICAgIHJlc3BvbnNlLnJlc3BvbnNlLFxuICAgICAgICAgICdDYW5ub3QgZGVzZXJpYWxpemUgcmVzcG9uc2UgYm9keSBhcyBpdCBpcyBub3QgaW4gYSBKU09OIGZvcm1hdC4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoZXMgYWxsIHRoZSBpdGVtcyBwYWdlIGJ5IHBhZ2UsIHJldHVybmluZyBlYWNoIHBhZ2UgcmVzdWx0cyBpbiBhIGNhbGxiYWNrLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSB1cmwgdG8gbWFrZSByZXF1ZXN0IHRvLiBDb3VsZCBiZSBhYnNvbHV0ZSBvciByZWxhdGl2ZSB0byB0aGUgc2VydmljZSBiYXNlIHVyaS5cbiAgICogQHBhcmFtIHsocmVzcG9uc2U6IFNlcnZpY2VSZXNwb25zZTxEPikgPT4gdm9pZH0gb25QYWdlUmV0cmlldmVkIFRoZSBjYWxsYmFjayB1c2VkIHRvIHJldHVybiByZXN1bHRzLCBwYWdlIGJ5IHBhZ2UuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwYWdlU2l6ZSBUaGUgcGFnZSBzaXplIHVzZWQgdG8gcmVxdWVzdCBpdGVtcy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGJvZHkgVGhlIGJvZHkgdG8gc2VuZCBpbiB0aGUgcmVxdWVzdCAod2lsbCBiZSBzZXJpYWxpemVkIHRvIEpTT04pLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gY3VzdG9tSGVhZGVycyBUaGUgaGVhZGVycyB0byBhdHRhY2ggdG8gcmVxdWVzdC5cbiAgICogQHBhcmFtIHtib29sZWFufSBhdXRoIFRoZSB2YWx1ZSBpbmRpY2F0aW5nIHdldGhlciB0aGUgcmVxdWVzdCByZXF1aXJlcyBhdXRoZW50aWNhdGlvbi4gSWYgdHJ1ZSwgdGhlIGNyZWRlbnRpYWxzIHdpbGwgYmUgcmVxdWVzdGVkIGZyb20gdGhlIGNvbmZpZ3VyYXRpb24ge0BzZWUgQ29uZmlnI2NyZWRlbnRpYWxzIH0gYW5kIEF1dGhvcml6YXRpb24gaGVhZGVyIHdpbGwgYmUgYXR0YWNoZWQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj59IFRoZSBzZXJ2aWNlIHJlc3BvbnNlLlxuICAgKiBAdGhyb3dzIHtTZXJ2aWNlRXJyb3J9IGluIGNhc2Ugb2YgdGhlIGVycm9yIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0SXRlbXNXaXRoUGFnZXM8RD4oXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb25QYWdlUmV0cmlldmVkOiAocmVzcG9uc2U6IFNlcnZpY2VSZXNwb25zZTxEPikgPT4gdm9pZCxcbiAgICBwYWdlU2l6ZTogbnVtYmVyLFxuICAgIGJvZHk/OiBzdHJpbmcgfCBGb3JtRGF0YSxcbiAgICBjdXN0b21IZWFkZXJzPzogSGVhZGVycyxcbiAgICBhdXRoOiBib29sZWFuID0gdHJ1ZVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBoZWFkZXJzID0gY3VzdG9tSGVhZGVycyA/PyBuZXcgSGVhZGVycygpO1xuICAgIGlmIChoZWFkZXJzLmhhcygnUmFuZ2UnKSkge1xuICAgICAgaGVhZGVycy5kZWxldGUoJ1JhbmdlJyk7XG4gICAgfVxuICAgIGNvbnN0IHJhbmdlOiBSYW5nZSA9IHsgc3RhcnQ6IDAsIGVuZDogcGFnZVNpemUgLSAxIH07XG4gICAgaGVhZGVycy5hcHBlbmQoJ1JhbmdlJywgYGl0ZW1zPSR7cmFuZ2Uuc3RhcnR9LSR7cmFuZ2UuZW5kfWApO1xuXG4gICAgbGV0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdDxEPih1cmwsICdHRVQnLCBib2R5LCBoZWFkZXJzLCBhdXRoKTtcblxuICAgIGRvIHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlUmFuZ2UgPSB0aGlzLmdldFJhbmdlKHJlc3BvbnNlKTtcblxuICAgICAgLy8gaWYgdGhlIHJlc3BvbnNlIHJldHVybnMgYW4gZW1wdHkgYXJyYXksIG9yIHdlIGhhdmUgbm8gY29udGVudCByYW5nZSBoZWFkZXIsIHdlIGhhdmUgYWNxdWlyZWQgYWxsIHRoZSBpdGVtcy5cbiAgICAgIC8vIGlmIHRoZSByZXNwb25zZSByYW5nZSBpcyBlcXVhbCB0byB0aGUgdG90YWwgbnVtYmVyIG9mIGl0ZW1zLCB3ZSBoYXZlIGFjcXVpcmVkIGFsbCB0aGUgaXRlbXMuXG4gICAgICBjb25zdCBoYXNOZXh0UGFnZSA9XG4gICAgICAgIEFycmF5LmlzQXJyYXkocmVzcG9uc2UuZGF0YSkgJiZcbiAgICAgICAgcmVzcG9uc2UuZGF0YS5sZW5ndGggIT09IDAgJiZcbiAgICAgICAgcmVzcG9uc2VSYW5nZSAmJlxuICAgICAgICByZXNwb25zZVJhbmdlLnRvdGFsICYmXG4gICAgICAgIHJlc3BvbnNlUmFuZ2UuZW5kIDwgcmVzcG9uc2VSYW5nZS50b3RhbCAtIDE7XG5cbiAgICAgIGxldCBuZXh0UGFnZTogUHJvbWlzZTxTZXJ2aWNlUmVzcG9uc2U8RD4+IHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKGhhc05leHRQYWdlICYmIHJlc3BvbnNlUmFuZ2UgJiYgcmVzcG9uc2VSYW5nZS50b3RhbCkge1xuICAgICAgICBoZWFkZXJzLmRlbGV0ZSgnUmFuZ2UnKTtcbiAgICAgICAgcmFuZ2Uuc3RhcnQgPSByZXNwb25zZVJhbmdlLmVuZCArIDE7XG4gICAgICAgIHJhbmdlLmVuZCA9IE1hdGgubWluKFxuICAgICAgICAgIHJlc3BvbnNlUmFuZ2UudG90YWwgLSAxLFxuICAgICAgICAgIHJhbmdlLnN0YXJ0ICsgcGFnZVNpemUgLSAxXG4gICAgICAgICk7XG4gICAgICAgIGhlYWRlcnMuYXBwZW5kKCdSYW5nZScsIGBpdGVtcz0ke3JhbmdlLnN0YXJ0fS0ke3JhbmdlLmVuZH1gKTtcblxuICAgICAgICAvLyBpbml0aWF0ZSBuZXh0IHBhZ2UgcmVxdWVzdCwgYnV0IGRvbid0IHdhaXQgb24gaXQgeWV0XG4gICAgICAgIG5leHRQYWdlID0gdGhpcy5tYWtlUmVxdWVzdDxEPih1cmwsICdHRVQnLCBib2R5LCBoZWFkZXJzLCBhdXRoKTtcbiAgICAgIH1cblxuICAgICAgb25QYWdlUmV0cmlldmVkKHJlc3BvbnNlKTtcblxuICAgICAgaWYgKG5leHRQYWdlKSB7XG4gICAgICAgIHJlc3BvbnNlID0gYXdhaXQgbmV4dFBhZ2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgLy8gaWYgd2UgcmVhY2hlZCB0aGlzIHBvaW50LCB3ZSBzdGlsbCBoYXZlIGl0ZW1zIHRvIGFjcXVpcmUuXG4gICAgfSB3aGlsZSAodHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogTWFrZXMgYSBzZXJ2aWNlIHJlcXVlc3Qgd2l0aCBhbGwgbmVlZGVkIGF1dGhlbnRpY2F0aW9uYW5kIHJldHJ5IGxvZ2ljLiBDb252ZXJ0cyBlcnJvciByZXNwb25zZSB0byBleGNlcHRpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgVGhlIHVybCB0byBtYWtlIHJlcXVlc3QgdG8uIENvdWxkIGJlIGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHRoZSBzZXJ2aWNlIGJhc2UgdXJpLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGJvZHkgVGhlIGJvZHkgdG8gc2VuZCBpbiB0aGUgcmVxdWVzdCAod2lsbCBiZSBzZXJpYWxpemVkIHRvIEpTT04pLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gY3VzdG9tSGVhZGVycyBUaGUgY3VzdG9tIGhlYWRlcnMgdG8gYXR0YWNoIHRvIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXV0aCBUaGUgdmFsdWUgaW5kaWNhdGluZyB3ZXRoZXIgdGhlIHJlcXVlc3QgcmVxdWlyZXMgYXV0aGVudGljYXRpb24uIElmIHRydWUsIHRoZSBjcmVkZW50aWFscyB3aWxsIGJlIHJlcXVlc3RlZCBmcm9tIHRoZSBjb25maWd1cmF0aW9uIHtAc2VlIENvbmZpZyNjcmVkZW50aWFscyB9IGFuZCBBdXRob3JpemF0aW9uIGhlYWRlciB3aWxsIGJlIGF0dGFjaGVkLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTZXJ2aWNlUmVzcG9uc2U8RD4+fSBUaGUgc2VydmljZSByZXNwb25zZS5cbiAgICogQHRocm93cyB7U2VydmljZUVycm9yfSBpbiBjYXNlIG9mIHRoZSBlcnJvciByZXNwb25zZSBmcm9tIHRoZSBzZXJ2aWNlLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlcXVlc3QoXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgbWV0aG9kOiAnR0VUJyB8ICdQVVQnIHwgJ1BPU1QnIHwgJ1BBVENIJyB8ICdERUxFVEUnID0gJ0dFVCcsXG4gICAgYm9keT86IHN0cmluZyB8IEZvcm1EYXRhIHwgQmxvYixcbiAgICBjdXN0b21IZWFkZXJzPzogSGVhZGVycyxcbiAgICBhdXRoOiBib29sZWFuID0gdHJ1ZVxuICApOiBQcm9taXNlPFNlcnZpY2VSZXNwb25zZTx2b2lkPj4ge1xuICAgIC8vIHRoaXMgbWV0aG9kIHN1cHBvcnRzIDMgY2FzZXM6IGFic29sdXRlIHVybCwgYWJzb2x1dGUgcGF0aCwgcmVsYXRpdmUgcGF0aFxuICAgIGNvbnN0IHJlcXVlc3RVcmwgPSB1cmwuc3RhcnRzV2l0aCgnaHR0cCcpXG4gICAgICA/IHVybFxuICAgICAgOiB1cmwuc3RhcnRzV2l0aCgnLycpXG4gICAgICA/IGV4dHJhY3RFbmRwb2ludCh0aGlzLmNvbmZpZy5zZXJ2aWNlVXJpKSArIHVybFxuICAgICAgOiB0aGlzLmNvbmZpZy5zZXJ2aWNlVXJpICsgdXJsO1xuXG4gICAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKCk7XG4gICAgY29uc3QgY29udGVudFR5cGUgPSBjdXN0b21IZWFkZXJzXG4gICAgICA/IGN1c3RvbUhlYWRlcnMuZ2V0KCdDb250ZW50LVR5cGUnKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgaWYgKCFjb250ZW50VHlwZSAmJiBib2R5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGhlYWRlcnMuc2V0KCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgIH1cblxuICAgIGlmIChjdXN0b21IZWFkZXJzKSB7XG4gICAgICBjdXN0b21IZWFkZXJzLmZvckVhY2goKHZhbHVlOiBzdHJpbmcsIGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGhlYWRlcnMuYXBwZW5kKGtleSwgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZmV0Y2hXaXRoUmV0cnkoXG4gICAgICByZXF1ZXN0VXJsLFxuICAgICAge1xuICAgICAgICBib2R5LFxuICAgICAgICBoZWFkZXJzLFxuICAgICAgICBtZXRob2QsXG4gICAgICAgIHJlZGlyZWN0OiAnZm9sbG93JyxcbiAgICAgIH0sXG4gICAgICBhdXRoXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIb3cgbWFueSB0aW1lcyBhIGZhaWxlZCByZXF1ZXN0IHNob3VsZCBiZSByZXRyaWVkIGJlZm9yZSBnaXZpbmcgdXAuXG4gICAqIHRoZSBkZWZhdWx0UmV0cnlDb3VudCBjYW4gYmUgb3ZlcnJpZGVuIGJ5IHNlcnZpY2UgY2xhc3Nlcy5cbiAgICpcbiAgICogQGFwaSBwcml2YXRlXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwdWJsaWMgbWF4UmV0cmllcygpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLmNvbmZpZy5tYXhSZXRyaWVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5tYXhSZXRyaWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5kZWZhdWx0UmV0cnlDb3VudDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRmlyc3QgcmV0cnkgZ29lcyBpbW1lZGlhdGx5ICgwbXMgZGVsYXkpIHRoZW4gZXhwb25lbnRpYWwgZ3Jvd3RoIHdpdGggMTAwbXMgYXMgYSBiYXNlLlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHB1YmxpYyBjYWxjdWxhdGVSZXRyeURlbGF5KHJldHJ5Q291bnQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKHJldHJ5Q291bnQgPT09IDApIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBiYXNlID0gMTAwO1xuICAgICAgcmV0dXJuIE1hdGgucmFuZG9tKCkgKiAoTWF0aC5wb3coMiwgcmV0cnlDb3VudCAtIDEpICogYmFzZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSByZXRyeWFibGVFcnJvcihlcnJvcjogU2VydmljZUVycm9yKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy50aW1lb3V0RXJyb3IoZXJyb3IpIHx8XG4gICAgICB0aGlzLm5ldHdvcmtpbmdFcnJvcihlcnJvcikgfHxcbiAgICAgIHRoaXMuZXhwaXJlZENyZWRlbnRpYWxzRXJyb3IoZXJyb3IpIHx8XG4gICAgICB0aGlzLnRocm90dGxlZEVycm9yKGVycm9yKSB8fFxuICAgICAgZXJyb3IucmVzcG9uc2Uuc3RhdHVzID49IDUwMFxuICAgICkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgbmV0d29ya2luZ0Vycm9yKGVycm9yOiBTZXJ2aWNlRXJyb3IpIHtcbiAgICByZXR1cm4gZXJyb3IuZXJyb3JDb2RlID09PSAnTmV0d29ya2luZ0Vycm9yJztcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgdGltZW91dEVycm9yKGVycm9yOiBTZXJ2aWNlRXJyb3IpIHtcbiAgICByZXR1cm4gZXJyb3IuZXJyb3JDb2RlID09PSAnVGltZW91dEVycm9yJztcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgZXhwaXJlZENyZWRlbnRpYWxzRXJyb3IoZXJyb3I6IFNlcnZpY2VFcnJvcikge1xuICAgIGlmIChlcnJvci5yZXNwb25zZS5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgY29uc3QgY3JlZGVudGlhbHMgPSB0aGlzLmNvbmZpZy5jcmVkZW50aWFscztcbiAgICAgIGlmIChcbiAgICAgICAgY3JlZGVudGlhbHMgJiZcbiAgICAgICAgdHlwZW9mIChjcmVkZW50aWFscyBhcyBDcmVkZW50aWFscykuZXhwaXJlZCA9PT0gJ2Jvb2xlYW4nXG4gICAgICApIHtcbiAgICAgICAgKGNyZWRlbnRpYWxzIGFzIENyZWRlbnRpYWxzKS5leHBpcmVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQGFwaSBwcml2YXRlXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIHRocm90dGxlZEVycm9yKGVycm9yOiBTZXJ2aWNlRXJyb3IpIHtcbiAgICAvLyBBV1MgQVBJIEdhdGV3YXkgcmV0dXJucyA0MjkgaW4gY2FzZSBvZiB0aHJvdHRsaW5nIGVycm9yc1xuICAgIGlmIChlcnJvci5yZXNwb25zZS5zdGF0dXMgPT09IDQyOSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFrZXMgYSBzZXJ2aWNlIGNhbGwgYW5kIHRha2VzIGNhcmUgYWJvdXQgcmV0cnkgbG9naWMgKHJlLWF1dGhlbnRpY2F0aW9uIGlmIG5lZWRlZCkuXG4gICAqIE5vdGUgdGhlIDx2b2lkPiBhcyBhIGdlbmVyaWMgcGFyYW1ldGVyLiBUaGlzIG1ldGhvZCBkb2VzIG5vdCByZWFkIHRoZSByZXNwb25zZSBib2R5LiBUaGUgU2VydmljZVJlc3BvbnNlIHJldHVybiB2YWx1ZSB3aWxsIGJlIGNhc2VkIHRvIG5lZWRlZCB0eXBlIG9uIHVwcGVyIGxldmVscyBvZiB0aGUgY29kZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHVybCBUaGUgdXJsIHRvIG1ha2UgcmVxdWVzdCB0by4gQ291bGQgYmUgYWJzb2x1dGUgb3IgcmVsYXRpdmUgdG8gdGhlIHNlcnZpY2UgYmFzZSB1cmkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMgVGhlIGZldGNoIHBhcmFtZXRlcnMuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXV0aCBUaGUgdmFsdWUgaW5kaWNhdGluZyB3ZXRoZXIgdGhlIHJlcXVlc3QgcmVxdWlyZXMgYXV0aGVudGljYXRpb24uIElmIHRydWUsIHRoZSBjcmVkZW50aWFscyB3aWxsIGJlIHJlcXVlc3RlZCBmcm9tIHRoZSBjb25maWd1cmF0aW9uIHtAc2VlIENvbmZpZyNjcmVkZW50aWFscyB9IGFuZCBBdXRob3JpemF0aW9uIGhlYWRlciB3aWxsIGJlIGF0dGFjaGVkLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTZXJ2aWNlUmVzcG9uc2U8dm9pZD4+fSBUaGUgc2VydmljZSByZXNwb25zZS5cbiAgICogQHRocm93cyB7U2VydmljZUVycm9yfSBpbiBjYXNlIG9mIHRoZSBlcnJvciByZXNwb25zZSBmcm9tIHRoZSBzZXJ2aWNlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaFdpdGhSZXRyeShcbiAgICB1cmw6IHN0cmluZyxcbiAgICBwYXJhbXM6IGFueSxcbiAgICBhdXRoOiBib29sZWFuID0gdHJ1ZVxuICApOiBQcm9taXNlPFNlcnZpY2VSZXNwb25zZTx2b2lkPj4ge1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMuY29uZmlnLmxvZ2dlcjtcbiAgICBjb25zdCByZXN1bHQ6IFNlcnZpY2VSZXNwb25zZTx2b2lkPiA9IG5ldyBTZXJ2aWNlUmVzcG9uc2U8dm9pZD4oXG4gICAgICB0aGlzLFxuICAgICAgbmV3IFJlc3BvbnNlKCksXG4gICAgICB2b2lkIDBcbiAgICApO1xuICAgIGRvIHtcbiAgICAgIGNvbnN0IGNyZWRlbnRpYWxzID0gdGhpcy5jb25maWcuY3JlZGVudGlhbHM7XG4gICAgICBpZiAoYXV0aCAmJiBjcmVkZW50aWFscykge1xuICAgICAgICBpZiAodHlwZW9mIChjcmVkZW50aWFscyBhcyBTZXJ2aWNlQ3JlZGVudGlhbHMpLmdldCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCAoY3JlZGVudGlhbHMgYXMgU2VydmljZUNyZWRlbnRpYWxzKS5nZXQoKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIHRoaXMubG9nKGBbVElEXSBGYWlsZWQgdG8gYWNxdWlyZSB0b2tlbnM6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY3JlZGVudGlhbHMudG9rZW4pIHtcbiAgICAgICAgICBwYXJhbXMuaGVhZGVycy5zZXQoJ0F1dGhvcml6YXRpb24nLCAnQmVhcmVyICcgKyBjcmVkZW50aWFscy50b2tlbik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5mZXRjaCh1cmwsIHBhcmFtcyk7XG4gICAgICBpZiAobG9nZ2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgZGVsdGEgPSAoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgLyAxMDAwO1xuICAgICAgICBjb25zdCBpc29EYXRlID0gbmV3IERhdGUoc3RhcnRUaW1lKS50b0lTT1N0cmluZygpO1xuICAgICAgICBjb25zdCByZXF1ZXN0Q29udGVudExlbmd0aCA9IHBhcmFtcy5ib2R5ID8gcGFyYW1zLmJvZHkubGVuZ3RoIDogMDtcbiAgICAgICAgY29uc3QgcmVzcG9uc2VDb250ZW50TGVuZ3RoID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtbGVuZ3RoJyk7XG4gICAgICAgIGNvbnN0IGxpbmUgPSBgJHtpc29EYXRlfSBbVEMgSFRUUF0gJHtwYXJhbXMubWV0aG9kfSAke3VybH0gJHtyZXNwb25zZS5zdGF0dXN9ICR7ZGVsdGF9ICR7cmVzdWx0LnJldHJ5Q291bnR9ICR7cmVxdWVzdENvbnRlbnRMZW5ndGh9ICR7cmVzcG9uc2VDb250ZW50TGVuZ3RofWA7XG4gICAgICAgIHRoaXMubG9nKGxpbmUpO1xuICAgICAgfVxuXG4gICAgICByZXN1bHQucmVzcG9uc2UgPSByZXNwb25zZTtcblxuICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgZXJyOiBTZXJ2aWNlRXJyb3I7XG4gICAgICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpO1xuICAgICAgICBpZiAoY29udGVudFR5cGUgJiYgY29udGVudFR5cGUuaW5kZXhPZignYXBwbGljYXRpb24vanNvbicpICE9PSAtMSkge1xuICAgICAgICAgIGNvbnN0IGVycm9ySW5mbyA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICBlcnIgPSBuZXcgU2VydmljZUVycm9yKFxuICAgICAgICAgICAgcmVzcG9uc2UsXG4gICAgICAgICAgICBlcnJvckluZm8ubWVzc2FnZSxcbiAgICAgICAgICAgIGVycm9ySW5mby5jb2RlIHx8IGVycm9ySW5mby5lcnJvcmNvZGVcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgICAgZXJyID0gbmV3IFNlcnZpY2VFcnJvcihyZXNwb25zZSwgbWVzc2FnZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgcmVzdWx0LnJldHJ5Q291bnQgKyAxIDwgdGhpcy5tYXhSZXRyaWVzKCkgJiZcbiAgICAgICAgICB0aGlzLnJldHJ5YWJsZUVycm9yKGVycilcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgcmV0cnlBZnRlckhlYWRlciA9IHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdyZXRyeS1hZnRlcicpO1xuICAgICAgICAgIGNvbnN0IHJldHJ5QWZ0ZXJNUyA9IHJldHJ5QWZ0ZXJIZWFkZXJcbiAgICAgICAgICAgID8gcGFyc2VJbnQocmV0cnlBZnRlckhlYWRlciwgMTApICogMTAwMFxuICAgICAgICAgICAgOiAwO1xuICAgICAgICAgIGNvbnN0IG1zID0gdGhpcy5jYWxjdWxhdGVSZXRyeURlbGF5KHJlc3VsdC5yZXRyeUNvdW50KSArIHJldHJ5QWZ0ZXJNUztcbiAgICAgICAgICBhd2FpdCBkZWxheShtcyk7XG4gICAgICAgICAgcmVzdWx0LnJldHJ5Q291bnQrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IHdoaWxlICh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgbG93ZXN0IGxldmVsIGZldGNoIGZ1bmN0aW9uIHdyYXBwZXIuXG4gICAqIFRoaXMgbWV0aG9kIGFsbG93cyB0byBzZXBhcnRlIHRoZSBzdGVwIG9mIGFjdHVhbCBzZW5kaW5nIG9mIHRoZSByZXF1ZXN0IGluIHRoZSBIVFRQIHBpcGxpbmUgYW5kIHBvdGVudGlhbGx5IGludGVyY2VwdCBpdCBhbmQgZmlyZSBldmVudHMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgVGhlIHVybCB0byBtYWtlIHJlcXVlc3QgdG8uIENvdWxkIGJlIGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHRoZSBzZXJ2aWNlIGJhc2UgdXJpLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyYW1zIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgZmV0Y2godXJsOiBzdHJpbmcsIHBhcmFtczogYW55KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuICAgIHJldHVybiBmZXRjaCh1cmwsIHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbmV4dCByYW5nZSBmb3IgdGhlIHJlc3Qgb2YgdGhlIHJlc3VsdHMgb2YgcmVzcG9uc2UgZGF0YS5cbiAgICogQHBhcmFtIHtTZXJ2aWNlUmVzcG9uc2U8RD59IHJlc3BvbnNlIFRoZSByZXNwb25zZSBmb3Igd2hpY2ggd2UgZ2V0IHRoZSBuZXh0IHJhbmdlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBnZXRSYW5nZTxEPihyZXNwb25zZTogU2VydmljZVJlc3BvbnNlPEQ+KTogUmFuZ2UgfCB1bmRlZmluZWQge1xuICAgIGlmICghcmVzcG9uc2UucmVzcG9uc2UuaGVhZGVycy5oYXMoJ0NvbnRlbnQtUmFuZ2UnKSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udGVudFJhbmdlID0gcmVzcG9uc2UucmVzcG9uc2UuaGVhZGVyc1xuICAgICAgICAuZ2V0KCdDb250ZW50LVJhbmdlJykhXG4gICAgICAgIC5zcGxpdCgnICcpO1xuICAgICAgY29uc3QgcmFuZ2VUb2tlbnMgPSBjb250ZW50UmFuZ2VbMV0uc3BsaXQoJy8nKTtcbiAgICAgIGNvbnN0IHRva2VucyA9IHJhbmdlVG9rZW5zWzBdLnNwbGl0KCctJyk7XG5cbiAgICAgIGNvbnN0IHN0YXJ0ID0gTnVtYmVyKHRva2Vuc1swXSk7XG4gICAgICBjb25zdCBlbmQgPSBOdW1iZXIodG9rZW5zWzFdKTtcbiAgICAgIGNvbnN0IHRvdGFsID0gTnVtYmVyKHJhbmdlVG9rZW5zWzFdKTtcblxuICAgICAgcmV0dXJuIHsgc3RhcnQsIGVuZCwgdG90YWwgfTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFB1dCBhIGxpbmUgb2YgdGV4dCB0byB0aGUgbG9nLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGluZSBUaGUgbGluZSB0byBsb2cuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGxvZyhsaW5lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLmNvbmZpZy5sb2dnZXI7XG4gICAgaWYgKGxvZ2dlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAodHlwZW9mIGxvZ2dlci5sb2cgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhsaW5lKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxvZ2dlci53cml0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBsb2dnZXIud3JpdGUobGluZSArICdcXG4nKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==