UNPKG

trimble-connect-sdk

Version:

Trimble Connect SDK for JavaScript

270 lines 42.9 kB
"use strict"; 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Service = exports.extractEndpoint = void 0; const error_1 = require("./error"); const response_1 = require("./response"); function extractEndpoint(url) { const schemaIndex = url.indexOf('//'); const firstSeparatorIndex = url.indexOf('/', schemaIndex + 2); return url.substring(0, firstSeparatorIndex); } exports.extractEndpoint = extractEndpoint; function delay(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } 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 error_1.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 response_1.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 error_1.ServiceError(response, errorInfo.message, errorInfo.code || errorInfo.errorcode); } else { const message = yield response.text(); err = new error_1.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'); } } }); } } exports.Service = Service; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIuLyIsInNvdXJjZXMiOlsic2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFHQSxtQ0FBdUM7QUFDdkMseUNBQTZDO0FBSTdDLFNBQWdCLGVBQWUsQ0FBQyxHQUFXO0lBQ3pDLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsTUFBTSxtQkFBbUIsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFOUQsT0FBTyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFMRCwwQ0FLQztBQUVELFNBQVMsS0FBSyxDQUFDLEVBQVU7SUFDdkIsT0FBTyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFO1FBQ25DLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBTUQsTUFBYSxPQUFPO0lBUWxCLFlBQTRCLE1BQXFCO1FBQXJCLFdBQU0sR0FBTixNQUFNLENBQWU7UUFOekMsc0JBQWlCLEdBQVcsQ0FBQyxDQUFDO1FBT3BDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRTtZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7U0FDL0M7SUFDSCxDQUFDO0lBWVksV0FBVyxDQUN0QixHQUFXLEVBQ1gsU0FBc0QsS0FBSyxFQUMzRCxJQUF3QixFQUN4QixhQUF1QixFQUN2QixPQUFnQixJQUFJOztZQUVwQixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxrQkFBa0IsRUFBRSxDQUFDLENBQUM7WUFDNUQsSUFBSSxhQUFhLEVBQUU7Z0JBQ2pCLGFBQWEsQ0FB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VyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFckMsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUM7U0FDOUI7UUFBQyxXQUFNO1lBQ04sT0FBTyxTQUFTLENBQUM7U0FDbEI7SUFDSCxDQUFDO0lBT2EsR0FBRyxDQUFDLElBQVk7O1lBQzVCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ2xDLElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtnQkFDeEIsSUFBSSxPQUFPLE1BQU0sQ0FBQyxHQUFHLEtBQUssVUFBVSxFQUFFO29CQUNwQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO2lCQUNsQjtxQkFBTSxJQUFJLE9BQU8sTUFBTSxDQUFDLEtBQUssS0FBSyxVQUFVLEVBQUU7b0JBQzdDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDO2lCQUMzQjthQUNGO1FBQ0gsQ0FBQztLQUFBO0NBQ0Y7QUEvWkQsMEJBK1pDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29uZmlndXJhdGlvbiB9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7IENyZWRlbnRpYWxzIH0gZnJvbSAnLi9jcmVkZW50aWFscyc7XG5pbXBvcnQgeyBSYW5nZSB9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7IFNlcnZpY2VFcnJvciB9IGZyb20gJy4vZXJyb3InO1xuaW1wb3J0IHsgU2VydmljZVJlc3BvbnNlIH0gZnJvbSAnLi9yZXNwb25zZSc7XG5pbXBvcnQgeyBTZXJ2aWNlQ3JlZGVudGlhbHMgfSBmcm9tICcuL3NlcnZpY2VfY3JlZGVudGlhbHMnO1xuXG4vKiogQGludGVybmFsICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdEVuZHBvaW50KHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc2NoZW1hSW5kZXggPSB1cmwuaW5kZXhPZignLy8nKTtcbiAgY29uc3QgZmlyc3RTZXBhcmF0b3JJbmRleCA9IHVybC5pbmRleE9mKCcvJywgc2NoZW1hSW5kZXggKyAyKTtcblxuICByZXR1cm4gdXJsLnN1YnN0cmluZygwLCBmaXJzdFNlcGFyYXRvckluZGV4KTtcbn1cblxuZnVuY3Rpb24gZGVsYXkobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKTtcbiAgfSk7XG59XG5cbi8qKlxuICogVGhlIHNlcnZpY2UgY2xpZW50IHRoYXQgcmVwcmVzZW50cyBjb25uZWN0aW9uIHRvIHRoZSBPcmdhbml6ZXIgU2VydmljZS5cbiAqIEVhY2ggQVBJIG9wZXJhdGlvbiBpcyBleHBvc2VkIGFzIGEgZnVuY3Rpb24gb24gc2VydmljZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFNlcnZpY2Uge1xuICAvKiogVXNlZCBpZiBtYXhSZXRyaWVzIGlzIG5vdCBzcGVjaWZpZWQgaW4ge0BzZWUgQ29uZmlndXJhdGlvbiNtYXhSZXRyaWVzIH0uIFRoZSBkZWZhdWx0UmV0cnlDb3VudCBjYW4gYmUgb3ZlcnJpZGVuIGJ5IHNlcnZpY2UgY2xhc3Nlcy4gKi9cbiAgcHJpdmF0ZSBkZWZhdWx0UmV0cnlDb3VudDogbnVtYmVyID0gMztcblxuICAvKipcbiAgICogQGNvbnN0cnVjdG9yIENvbnN0cnVjdHMgYSBzZXJ2aWNlIG9iamVjdC5cbiAgICogQHBhcmFtIHtDb25maWd9IGNvbmZpZyBUaGUgY29uZmlndXJhdGlvbiBvcHRpb25zIChlLmcuIHNlcnZpY2UgdXJsKS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBjb25maWc6IENvbmZpZ3VyYXRpb24pIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnLnNlcnZpY2VVcmkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIHNlcnZpY2VVcmkgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2hlZCB0aGUgbmV4dCBwYWdlIGZyb210IGhlIHNlcXVlbmNlIG9mIHBhZ2VzIGluaXRpYXRlZCBieSB7QHNlZSBPcmdhbml6ZXIubGlzdFRyZWVzIH0uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgVGhlIHVybCB0byBtYWtlIHJlcXVlc3QgdG8uIENvdWxkIGJlIGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHRoZSBzZXJ2aWNlIGJhc2UgdXJpLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGJvZHkgVGhlIGJvZHkgdG8gc2VuZCBpbiB0aGUgcmVxdWVzdCAod2lsbCBiZSBzZXJpYWxpemVkIHRvIEpTT04pLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaGVhZGVycyBUaGUgaGVhZGVycyB0byBhdHRhY2ggdG8gcmVxdWVzdC5cbiAgICogQHBhcmFtIHtib29sZWFufSBhdXRoIFRoZSB2YWx1ZSBpbmRpY2F0aW5nIHdldGhlciB0aGUgcmVxdWVzdCByZXF1aXJlcyBhdXRoZW50aWNhdGlvbi4gSWYgdHJ1ZSwgdGhlIGNyZWRlbnRpYWxzIHdpbGwgYmUgcmVxdWVzdGVkIGZyb20gdGhlIGNvbmZpZ3VyYXRpb24ge0BzZWUgQ29uZmlnI2NyZWRlbnRpYWxzIH0gYW5kIEF1dGhvcml6YXRpb24gaGVhZGVyIHdpbGwgYmUgYXR0YWNoZWQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj59IFRoZSBzZXJ2aWNlIHJlc3BvbnNlLlxuICAgKiBAdGhyb3dzIHtTZXJ2aWNlRXJyb3J9IGluIGNhc2Ugb2YgdGhlIGVycm9yIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbWFrZVJlcXVlc3Q8RD4oXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgbWV0aG9kOiAnR0VUJyB8ICdQVVQnIHwgJ1BPU1QnIHwgJ1BBVENIJyB8ICdERUxFVEUnID0gJ0dFVCcsXG4gICAgYm9keT86IHN0cmluZyB8IEZvcm1EYXRhLFxuICAgIGN1c3RvbUhlYWRlcnM/OiBIZWFkZXJzLFxuICAgIGF1dGg6IGJvb2xlYW4gPSB0cnVlXG4gICk6IFByb21pc2U8U2VydmljZVJlc3BvbnNlPEQ+PiB7XG4gICAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKHsgQWNjZXB0OiAnYXBwbGljYXRpb24vanNvbicgfSk7XG4gICAgaWYgKGN1c3RvbUhlYWRlcnMpIHtcbiAgICAgIGN1c3RvbUhlYWRlcnMuZm9yRWFjaCgodmFsdWU6IHN0cmluZywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgaGVhZGVycy5hcHBlbmQoa2V5LCB2YWx1ZSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgY29uc3QgcmVzcG9uc2UgPSAoYXdhaXQgdGhpcy5yZXF1ZXN0KFxuICAgICAgdXJsLFxuICAgICAgbWV0aG9kLFxuICAgICAgYm9keSxcbiAgICAgIGhlYWRlcnMsXG4gICAgICBhdXRoXG4gICAgKSkgYXMgYW55IGFzIFNlcnZpY2VSZXNwb25zZTxEPjtcblxuICAgIC8vIGRlc2VyaWFsaXplIHJlc3BvbnNlIGJvZHkuIElmIHNlcnZpY2UgcmVzcG9uZGVkIHdpdGggYW4gZXJyb3IgaXQgd2FzIHRocm93biBhbHJlYWR5LlxuICAgIGlmIChyZXNwb25zZS5yZXNwb25zZS5zdGF0dXMgIT09IDIwNCkge1xuICAgICAgY29uc3QgY29udGVudFR5cGUgPSByZXNwb25zZS5yZXNwb25zZS5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJyk7XG4gICAgICBpZiAoXG4gICAgICAgIGNvbnRlbnRUeXBlID09PSBudWxsIHx8XG4gICAgICAgIGNvbnRlbnRUeXBlLmluZGV4T2YoJ2FwcGxpY2F0aW9uL2pzb24nKSAhPT0gLTFcbiAgICAgICkge1xuICAgICAgICByZXNwb25zZS5kYXRhID0gKGF3YWl0IHJlc3BvbnNlLnJlc3BvbnNlLmpzb24oKSkgYXMgRDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBTZXJ2aWNlRXJyb3IoXG4gICAgICAgICAgcmVzcG9uc2UucmVzcG9uc2UsXG4gICAgICAgICAgJ0Nhbm5vdCBkZXNlcmlhbGl6ZSByZXNwb25zZSBib2R5IGFzIGl0IGlzIG5vdCBpbiBhIEpTT04gZm9ybWF0LidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2hlcyBhbGwgdGhlIGl0ZW1zIHBhZ2UgYnkgcGFnZSwgcmV0dXJuaW5nIGVhY2ggcGFnZSByZXN1bHRzIGluIGEgY2FsbGJhY2suXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgVGhlIHVybCB0byBtYWtlIHJlcXVlc3QgdG8uIENvdWxkIGJlIGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHRoZSBzZXJ2aWNlIGJhc2UgdXJpLlxuICAgKiBAcGFyYW0geyhyZXNwb25zZTogU2VydmljZVJlc3BvbnNlPEQ+KSA9PiB2b2lkfSBvblBhZ2VSZXRyaWV2ZWQgVGhlIGNhbGxiYWNrIHVzZWQgdG8gcmV0dXJuIHJlc3VsdHMsIHBhZ2UgYnkgcGFnZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2VTaXplIFRoZSBwYWdlIHNpemUgdXNlZCB0byByZXF1ZXN0IGl0ZW1zLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYm9keSBUaGUgYm9keSB0byBzZW5kIGluIHRoZSByZXF1ZXN0ICh3aWxsIGJlIHNlcmlhbGl6ZWQgdG8gSlNPTikuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjdXN0b21IZWFkZXJzIFRoZSBoZWFkZXJzIHRvIGF0dGFjaCB0byByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGF1dGggVGhlIHZhbHVlIGluZGljYXRpbmcgd2V0aGVyIHRoZSByZXF1ZXN0IHJlcXVpcmVzIGF1dGhlbnRpY2F0aW9uLiBJZiB0cnVlLCB0aGUgY3JlZGVudGlhbHMgd2lsbCBiZSByZXF1ZXN0ZWQgZnJvbSB0aGUgY29uZmlndXJhdGlvbiB7QHNlZSBDb25maWcjY3JlZGVudGlhbHMgfSBhbmQgQXV0aG9yaXphdGlvbiBoZWFkZXIgd2lsbCBiZSBhdHRhY2hlZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8U2VydmljZVJlc3BvbnNlPEQ+Pn0gVGhlIHNlcnZpY2UgcmVzcG9uc2UuXG4gICAqIEB0aHJvd3Mge1NlcnZpY2VFcnJvcn0gaW4gY2FzZSBvZiB0aGUgZXJyb3IgcmVzcG9uc2UgZnJvbSB0aGUgc2VydmljZS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBnZXRJdGVtc1dpdGhQYWdlczxEPihcbiAgICB1cmw6IHN0cmluZyxcbiAgICBvblBhZ2VSZXRyaWV2ZWQ6IChyZXNwb25zZTogU2VydmljZVJlc3BvbnNlPEQ+KSA9PiB2b2lkLFxuICAgIHBhZ2VTaXplOiBudW1iZXIsXG4gICAgYm9keT86IHN0cmluZyB8IEZvcm1EYXRhLFxuICAgIGN1c3RvbUhlYWRlcnM/OiBIZWFkZXJzLFxuICAgIGF1dGg6IGJvb2xlYW4gPSB0cnVlXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGhlYWRlcnMgPSBjdXN0b21IZWFkZXJzID8/IG5ldyBIZWFkZXJzKCk7XG4gICAgaWYgKGhlYWRlcnMuaGFzKCdSYW5nZScpKSB7XG4gICAgICBoZWFkZXJzLmRlbGV0ZSgnUmFuZ2UnKTtcbiAgICB9XG4gICAgY29uc3QgcmFuZ2U6IFJhbmdlID0geyBzdGFydDogMCwgZW5kOiBwYWdlU2l6ZSAtIDEgfTtcbiAgICBoZWFkZXJzLmFwcGVuZCgnUmFuZ2UnLCBgaXRlbXM9JHtyYW5nZS5zdGFydH0tJHtyYW5nZS5lbmR9YCk7XG5cbiAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0PEQ+KHVybCwgJ0dFVCcsIGJvZHksIGhlYWRlcnMsIGF1dGgpO1xuXG4gICAgZG8ge1xuICAgICAgY29uc3QgcmVzcG9uc2VSYW5nZSA9IHRoaXMuZ2V0UmFuZ2UocmVzcG9uc2UpO1xuXG4gICAgICAvLyBpZiB0aGUgcmVzcG9uc2UgcmV0dXJucyBhbiBlbXB0eSBhcnJheSwgb3Igd2UgaGF2ZSBubyBjb250ZW50IHJhbmdlIGhlYWRlciwgd2UgaGF2ZSBhY3F1aXJlZCBhbGwgdGhlIGl0ZW1zLlxuICAgICAgLy8gaWYgdGhlIHJlc3BvbnNlIHJhbmdlIGlzIGVxdWFsIHRvIHRoZSB0b3RhbCBudW1iZXIgb2YgaXRlbXMsIHdlIGhhdmUgYWNxdWlyZWQgYWxsIHRoZSBpdGVtcy5cbiAgICAgIGNvbnN0IGhhc05leHRQYWdlID1cbiAgICAgICAgQXJyYXkuaXNBcnJheShyZXNwb25zZS5kYXRhKSAmJlxuICAgICAgICByZXNwb25zZS5kYXRhLmxlbmd0aCAhPT0gMCAmJlxuICAgICAgICByZXNwb25zZVJhbmdlICYmXG4gICAgICAgIHJlc3BvbnNlUmFuZ2UudG90YWwgJiZcbiAgICAgICAgcmVzcG9uc2VSYW5nZS5lbmQgPCByZXNwb25zZVJhbmdlLnRvdGFsIC0gMTtcblxuICAgICAgbGV0IG5leHRQYWdlOiBQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj4gfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoaGFzTmV4dFBhZ2UgJiYgcmVzcG9uc2VSYW5nZSAmJiByZXNwb25zZVJhbmdlLnRvdGFsKSB7XG4gICAgICAgIGhlYWRlcnMuZGVsZXRlKCdSYW5nZScpO1xuICAgICAgICByYW5nZS5zdGFydCA9IHJlc3BvbnNlUmFuZ2UuZW5kICsgMTtcbiAgICAgICAgcmFuZ2UuZW5kID0gTWF0aC5taW4oXG4gICAgICAgICAgcmVzcG9uc2VSYW5nZS50b3RhbCAtIDEsXG4gICAgICAgICAgcmFuZ2Uuc3RhcnQgKyBwYWdlU2l6ZSAtIDFcbiAgICAgICAgKTtcbiAgICAgICAgaGVhZGVycy5hcHBlbmQoJ1JhbmdlJywgYGl0ZW1zPSR7cmFuZ2Uuc3RhcnR9LSR7cmFuZ2UuZW5kfWApO1xuXG4gICAgICAgIC8vIGluaXRpYXRlIG5leHQgcGFnZSByZXF1ZXN0LCBidXQgZG9uJ3Qgd2FpdCBvbiBpdCB5ZXRcbiAgICAgICAgbmV4dFBhZ2UgPSB0aGlzLm1ha2VSZXF1ZXN0PEQ+KHVybCwgJ0dFVCcsIGJvZHksIGhlYWRlcnMsIGF1dGgpO1xuICAgICAgfVxuXG4gICAgICBvblBhZ2VSZXRyaWV2ZWQocmVzcG9uc2UpO1xuXG4gICAgICBpZiAobmV4dFBhZ2UpIHtcbiAgICAgICAgcmVzcG9uc2UgPSBhd2FpdCBuZXh0UGFnZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICAvLyBpZiB3ZSByZWFjaGVkIHRoaXMgcG9pbnQsIHdlIHN0aWxsIGhhdmUgaXRlbXMgdG8gYWNxdWlyZS5cbiAgICB9IHdoaWxlICh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlcyBhIHNlcnZpY2UgcmVxdWVzdCB3aXRoIGFsbCBuZWVkZWQgYXV0aGVudGljYXRpb25hbmQgcmV0cnkgbG9naWMuIENvbnZlcnRzIGVycm9yIHJlc3BvbnNlIHRvIGV4Y2VwdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHVybCBUaGUgdXJsIHRvIG1ha2UgcmVxdWVzdCB0by4gQ291bGQgYmUgYWJzb2x1dGUgb3IgcmVsYXRpdmUgdG8gdGhlIHNlcnZpY2UgYmFzZSB1cmkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2QgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYm9keSBUaGUgYm9keSB0byBzZW5kIGluIHRoZSByZXF1ZXN0ICh3aWxsIGJlIHNlcmlhbGl6ZWQgdG8gSlNPTikuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjdXN0b21IZWFkZXJzIFRoZSBjdXN0b20gaGVhZGVycyB0byBhdHRhY2ggdG8gcmVxdWVzdC5cbiAgICogQHBhcmFtIHtib29sZWFufSBhdXRoIFRoZSB2YWx1ZSBpbmRpY2F0aW5nIHdldGhlciB0aGUgcmVxdWVzdCByZXF1aXJlcyBhdXRoZW50aWNhdGlvbi4gSWYgdHJ1ZSwgdGhlIGNyZWRlbnRpYWxzIHdpbGwgYmUgcmVxdWVzdGVkIGZyb20gdGhlIGNvbmZpZ3VyYXRpb24ge0BzZWUgQ29uZmlnI2NyZWRlbnRpYWxzIH0gYW5kIEF1dGhvcml6YXRpb24gaGVhZGVyIHdpbGwgYmUgYXR0YWNoZWQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFNlcnZpY2VSZXNwb25zZTxEPj59IFRoZSBzZXJ2aWNlIHJlc3BvbnNlLlxuICAgKiBAdGhyb3dzIHtTZXJ2aWNlRXJyb3J9IGluIGNhc2Ugb2YgdGhlIGVycm9yIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVxdWVzdChcbiAgICB1cmw6IHN0cmluZyxcbiAgICBtZXRob2Q6ICdHRVQnIHwgJ1BVVCcgfCAnUE9TVCcgfCAnUEFUQ0gnIHwgJ0RFTEVURScgPSAnR0VUJyxcbiAgICBib2R5Pzogc3RyaW5nIHwgRm9ybURhdGEgfCBCbG9iLFxuICAgIGN1c3RvbUhlYWRlcnM/OiBIZWFkZXJzLFxuICAgIGF1dGg6IGJvb2xlYW4gPSB0cnVlXG4gICk6IFByb21pc2U8U2VydmljZVJlc3BvbnNlPHZvaWQ+PiB7XG4gICAgLy8gdGhpcyBtZXRob2Qgc3VwcG9ydHMgMyBjYXNlczogYWJzb2x1dGUgdXJsLCBhYnNvbHV0ZSBwYXRoLCByZWxhdGl2ZSBwYXRoXG4gICAgY29uc3QgcmVxdWVzdFVybCA9IHVybC5zdGFydHNXaXRoKCdodHRwJylcbiAgICAgID8gdXJsXG4gICAgICA6IHVybC5zdGFydHNXaXRoKCcvJylcbiAgICAgID8gZXh0cmFjdEVuZHBvaW50KHRoaXMuY29uZmlnLnNlcnZpY2VVcmkpICsgdXJsXG4gICAgICA6IHRoaXMuY29uZmlnLnNlcnZpY2VVcmkgKyB1cmw7XG5cbiAgICBjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKTtcbiAgICBjb25zdCBjb250ZW50VHlwZSA9IGN1c3RvbUhlYWRlcnNcbiAgICAgID8gY3VzdG9tSGVhZGVycy5nZXQoJ0NvbnRlbnQtVHlwZScpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICBpZiAoIWNvbnRlbnRUeXBlICYmIGJvZHkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaGVhZGVycy5zZXQoJ0NvbnRlbnQtVHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XG4gICAgfVxuXG4gICAgaWYgKGN1c3RvbUhlYWRlcnMpIHtcbiAgICAgIGN1c3RvbUhlYWRlcnMuZm9yRWFjaCgodmFsdWU6IHN0cmluZywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgaGVhZGVycy5hcHBlbmQoa2V5LCB2YWx1ZSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5mZXRjaFdpdGhSZXRyeShcbiAgICAgIHJlcXVlc3RVcmwsXG4gICAgICB7XG4gICAgICAgIGJvZHksXG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIG1ldGhvZCxcbiAgICAgICAgcmVkaXJlY3Q6ICdmb2xsb3cnLFxuICAgICAgfSxcbiAgICAgIGF1dGhcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvdyBtYW55IHRpbWVzIGEgZmFpbGVkIHJlcXVlc3Qgc2hvdWxkIGJlIHJldHJpZWQgYmVmb3JlIGdpdmluZyB1cC5cbiAgICogdGhlIGRlZmF1bHRSZXRyeUNvdW50IGNhbiBiZSBvdmVycmlkZW4gYnkgc2VydmljZSBjbGFzc2VzLlxuICAgKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHB1YmxpYyBtYXhSZXRyaWVzKCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuY29uZmlnLm1heFJldHJpZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLm1heFJldHJpZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmRlZmF1bHRSZXRyeUNvdW50O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaXJzdCByZXRyeSBnb2VzIGltbWVkaWF0bHkgKDBtcyBkZWxheSkgdGhlbiBleHBvbmVudGlhbCBncm93dGggd2l0aCAxMDBtcyBhcyBhIGJhc2UuXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHVibGljIGNhbGN1bGF0ZVJldHJ5RGVsYXkocmV0cnlDb3VudDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAocmV0cnlDb3VudCA9PT0gMCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGJhc2UgPSAxMDA7XG4gICAgICByZXR1cm4gTWF0aC5yYW5kb20oKSAqIChNYXRoLnBvdygyLCByZXRyeUNvdW50IC0gMSkgKiBiYXNlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGFwaSBwcml2YXRlXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIHJldHJ5YWJsZUVycm9yKGVycm9yOiBTZXJ2aWNlRXJyb3IpIHtcbiAgICBpZiAoXG4gICAgICB0aGlzLnRpbWVvdXRFcnJvcihlcnJvcikgfHxcbiAgICAgIHRoaXMubmV0d29ya2luZ0Vycm9yKGVycm9yKSB8fFxuICAgICAgdGhpcy5leHBpcmVkQ3JlZGVudGlhbHNFcnJvcihlcnJvcikgfHxcbiAgICAgIHRoaXMudGhyb3R0bGVkRXJyb3IoZXJyb3IpIHx8XG4gICAgICBlcnJvci5yZXNwb25zZS5zdGF0dXMgPj0gNTAwXG4gICAgKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBuZXR3b3JraW5nRXJyb3IoZXJyb3I6IFNlcnZpY2VFcnJvcikge1xuICAgIHJldHVybiBlcnJvci5lcnJvckNvZGUgPT09ICdOZXR3b3JraW5nRXJyb3InO1xuICB9XG5cbiAgLyoqXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSB0aW1lb3V0RXJyb3IoZXJyb3I6IFNlcnZpY2VFcnJvcikge1xuICAgIHJldHVybiBlcnJvci5lcnJvckNvZGUgPT09ICdUaW1lb3V0RXJyb3InO1xuICB9XG5cbiAgLyoqXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBleHBpcmVkQ3JlZGVudGlhbHNFcnJvcihlcnJvcjogU2VydmljZUVycm9yKSB7XG4gICAgaWYgKGVycm9yLnJlc3BvbnNlLnN0YXR1cyA9PT0gNDAxKSB7XG4gICAgICBjb25zdCBjcmVkZW50aWFscyA9IHRoaXMuY29uZmlnLmNyZWRlbnRpYWxzO1xuICAgICAgaWYgKFxuICAgICAgICBjcmVkZW50aWFscyAmJlxuICAgICAgICB0eXBlb2YgKGNyZWRlbnRpYWxzIGFzIENyZWRlbnRpYWxzKS5leHBpcmVkID09PSAnYm9vbGVhbidcbiAgICAgICkge1xuICAgICAgICAoY3JlZGVudGlhbHMgYXMgQ3JlZGVudGlhbHMpLmV4cGlyZWQgPSB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgdGhyb3R0bGVkRXJyb3IoZXJyb3I6IFNlcnZpY2VFcnJvcikge1xuICAgIC8vIEFXUyBBUEkgR2F0ZXdheSByZXR1cm5zIDQyOSBpbiBjYXNlIG9mIHRocm90dGxpbmcgZXJyb3JzXG4gICAgaWYgKGVycm9yLnJlc3BvbnNlLnN0YXR1cyA9PT0gNDI5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlcyBhIHNlcnZpY2UgY2FsbCBhbmQgdGFrZXMgY2FyZSBhYm91dCByZXRyeSBsb2dpYyAocmUtYXV0aGVudGljYXRpb24gaWYgbmVlZGVkKS5cbiAgICogTm90ZSB0aGUgPHZvaWQ+IGFzIGEgZ2VuZXJpYyBwYXJhbWV0ZXIuIFRoaXMgbWV0aG9kIGRvZXMgbm90IHJlYWQgdGhlIHJlc3BvbnNlIGJvZHkuIFRoZSBTZXJ2aWNlUmVzcG9uc2UgcmV0dXJuIHZhbHVlIHdpbGwgYmUgY2FzZWQgdG8gbmVlZGVkIHR5cGUgb24gdXBwZXIgbGV2ZWxzIG9mIHRoZSBjb2RlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSB1cmwgdG8gbWFrZSByZXF1ZXN0IHRvLiBDb3VsZCBiZSBhYnNvbHV0ZSBvciByZWxhdGl2ZSB0byB0aGUgc2VydmljZSBiYXNlIHVyaS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHBhcmFtcyBUaGUgZmV0Y2ggcGFyYW1ldGVycy5cbiAgICogQHBhcmFtIHtib29sZWFufSBhdXRoIFRoZSB2YWx1ZSBpbmRpY2F0aW5nIHdldGhlciB0aGUgcmVxdWVzdCByZXF1aXJlcyBhdXRoZW50aWNhdGlvbi4gSWYgdHJ1ZSwgdGhlIGNyZWRlbnRpYWxzIHdpbGwgYmUgcmVxdWVzdGVkIGZyb20gdGhlIGNvbmZpZ3VyYXRpb24ge0BzZWUgQ29uZmlnI2NyZWRlbnRpYWxzIH0gYW5kIEF1dGhvcml6YXRpb24gaGVhZGVyIHdpbGwgYmUgYXR0YWNoZWQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFNlcnZpY2VSZXNwb25zZTx2b2lkPj59IFRoZSBzZXJ2aWNlIHJlc3BvbnNlLlxuICAgKiBAdGhyb3dzIHtTZXJ2aWNlRXJyb3J9IGluIGNhc2Ugb2YgdGhlIGVycm9yIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZpY2UuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGZldGNoV2l0aFJldHJ5KFxuICAgIHVybDogc3RyaW5nLFxuICAgIHBhcmFtczogYW55LFxuICAgIGF1dGg6IGJvb2xlYW4gPSB0cnVlXG4gICk6IFByb21pc2U8U2VydmljZVJlc3BvbnNlPHZvaWQ+PiB7XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5jb25maWcubG9nZ2VyO1xuICAgIGNvbnN0IHJlc3VsdDogU2VydmljZVJlc3BvbnNlPHZvaWQ+ID0gbmV3IFNlcnZpY2VSZXNwb25zZTx2b2lkPihcbiAgICAgIHRoaXMsXG4gICAgICBuZXcgUmVzcG9uc2UoKSxcbiAgICAgIHZvaWQgMFxuICAgICk7XG4gICAgZG8ge1xuICAgICAgY29uc3QgY3JlZGVudGlhbHMgPSB0aGlzLmNvbmZpZy5jcmVkZW50aWFscztcbiAgICAgIGlmIChhdXRoICYmIGNyZWRlbnRpYWxzKSB7XG4gICAgICAgIGlmICh0eXBlb2YgKGNyZWRlbnRpYWxzIGFzIFNlcnZpY2VDcmVkZW50aWFscykuZ2V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IChjcmVkZW50aWFscyBhcyBTZXJ2aWNlQ3JlZGVudGlhbHMpLmdldCgpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgdGhpcy5sb2coYFtUSURdIEZhaWxlZCB0byBhY3F1aXJlIHRva2VuczogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjcmVkZW50aWFscy50b2tlbikge1xuICAgICAgICAgIHBhcmFtcy5oZWFkZXJzLnNldCgnQXV0aG9yaXphdGlvbicsICdCZWFyZXIgJyArIGNyZWRlbnRpYWxzLnRva2VuKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmZldGNoKHVybCwgcGFyYW1zKTtcbiAgICAgIGlmIChsb2dnZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCBkZWx0YSA9IChEYXRlLm5vdygpIC0gc3RhcnRUaW1lKSAvIDEwMDA7XG4gICAgICAgIGNvbnN0IGlzb0RhdGUgPSBuZXcgRGF0ZShzdGFydFRpbWUpLnRvSVNPU3RyaW5nKCk7XG4gICAgICAgIGNvbnN0IHJlcXVlc3RDb250ZW50TGVuZ3RoID0gcGFyYW1zLmJvZHkgPyBwYXJhbXMuYm9keS5sZW5ndGggOiAwO1xuICAgICAgICBjb25zdCByZXNwb25zZUNvbnRlbnRMZW5ndGggPSByZXNwb25zZS5oZWFkZXJzLmdldCgnY29udGVudC1sZW5ndGgnKTtcbiAgICAgICAgY29uc3QgbGluZSA9IGAke2lzb0RhdGV9IFtUQyBIVFRQXSAke3BhcmFtcy5tZXRob2R9ICR7dXJsfSAke3Jlc3BvbnNlLnN0YXR1c30gJHtkZWx0YX0gJHtyZXN1bHQucmV0cnlDb3VudH0gJHtyZXF1ZXN0Q29udGVudExlbmd0aH0gJHtyZXNwb25zZUNvbnRlbnRMZW5ndGh9YDtcbiAgICAgICAgdGhpcy5sb2cobGluZSk7XG4gICAgICB9XG5cbiAgICAgIHJlc3VsdC5yZXNwb25zZSA9IHJlc3BvbnNlO1xuXG4gICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBlcnI6IFNlcnZpY2VFcnJvcjtcbiAgICAgICAgY29uc3QgY29udGVudFR5cGUgPSByZXNwb25zZS5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJyk7XG4gICAgICAgIGlmIChjb250ZW50VHlwZSAmJiBjb250ZW50VHlwZS5pbmRleE9mKCdhcHBsaWNhdGlvbi9qc29uJykgIT09IC0xKSB7XG4gICAgICAgICAgY29uc3QgZXJyb3JJbmZvID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgICAgICAgIGVyciA9IG5ldyBTZXJ2aWNlRXJyb3IoXG4gICAgICAgICAgICByZXNwb25zZSxcbiAgICAgICAgICAgIGVycm9ySW5mby5tZXNzYWdlLFxuICAgICAgICAgICAgZXJyb3JJbmZvLmNvZGUgfHwgZXJyb3JJbmZvLmVycm9yY29kZVxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgbWVzc2FnZSA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcbiAgICAgICAgICBlcnIgPSBuZXcgU2VydmljZUVycm9yKHJlc3BvbnNlLCBtZXNzYWdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChcbiAgICAgICAgICByZXN1bHQucmV0cnlDb3VudCArIDEgPCB0aGlzLm1heFJldHJpZXMoKSAmJlxuICAgICAgICAgIHRoaXMucmV0cnlhYmxlRXJyb3IoZXJyKVxuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCByZXRyeUFmdGVySGVhZGVyID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ3JldHJ5LWFmdGVyJyk7XG4gICAgICAgICAgY29uc3QgcmV0cnlBZnRlck1TID0gcmV0cnlBZnRlckhlYWRlclxuICAgICAgICAgICAgPyBwYXJzZUludChyZXRyeUFmdGVySGVhZGVyLCAxMCkgKiAxMDAwXG4gICAgICAgICAgICA6IDA7XG4gICAgICAgICAgY29uc3QgbXMgPSB0aGlzLmNhbGN1bGF0ZVJldHJ5RGVsYXkocmVzdWx0LnJldHJ5Q291bnQpICsgcmV0cnlBZnRlck1TO1xuICAgICAgICAgIGF3YWl0IGRlbGF5KG1zKTtcbiAgICAgICAgICByZXN1bHQucmV0cnlDb3VudCsrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gd2hpbGUgKHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBsb3dlc3QgbGV2ZWwgZmV0Y2ggZnVuY3Rpb24gd3JhcHBlci5cbiAgICogVGhpcyBtZXRob2QgYWxsb3dzIHRvIHNlcGFydGUgdGhlIHN0ZXAgb2YgYWN0dWFsIHNlbmRpbmcgb2YgdGhlIHJlcXVlc3QgaW4gdGhlIEhUVFAgcGlwbGluZSBhbmQgcG90ZW50aWFsbHkgaW50ZXJjZXB0IGl0IGFuZCBmaXJlIGV2ZW50cy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHVybCBUaGUgdXJsIHRvIG1ha2UgcmVxdWVzdCB0by4gQ291bGQgYmUgYWJzb2x1dGUgb3IgcmVsYXRpdmUgdG8gdGhlIHNlcnZpY2UgYmFzZSB1cmkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBmZXRjaCh1cmw6IHN0cmluZywgcGFyYW1zOiBhbnkpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gICAgcmV0dXJuIGZldGNoKHVybCwgcGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBuZXh0IHJhbmdlIGZvciB0aGUgcmVzdCBvZiB0aGUgcmVzdWx0cyBvZiByZXNwb25zZSBkYXRhLlxuICAgKiBAcGFyYW0ge1NlcnZpY2VSZXNwb25zZTxEPn0gcmVzcG9uc2UgVGhlIHJlc3BvbnNlIGZvciB3aGljaCB3ZSBnZXQgdGhlIG5leHQgcmFuZ2UuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGdldFJhbmdlPEQ+KHJlc3BvbnNlOiBTZXJ2aWNlUmVzcG9uc2U8RD4pOiBSYW5nZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFyZXNwb25zZS5yZXNwb25zZS5oZWFkZXJzLmhhcygnQ29udGVudC1SYW5nZScpKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb250ZW50UmFuZ2UgPSByZXNwb25zZS5yZXNwb25zZS5oZWFkZXJzXG4gICAgICAgIC5nZXQoJ0NvbnRlbnQtUmFuZ2UnKSFcbiAgICAgICAgLnNwbGl0KCcgJyk7XG4gICAgICBjb25zdCByYW5nZVRva2VucyA9IGNvbnRlbnRSYW5nZVsxXS5zcGxpdCgnLycpO1xuICAgICAgY29uc3QgdG9rZW5zID0gcmFuZ2VUb2tlbnNbMF0uc3BsaXQoJy0nKTtcblxuICAgICAgY29uc3Qgc3RhcnQgPSBOdW1iZXIodG9rZW5zWzBdKTtcbiAgICAgIGNvbnN0IGVuZCA9IE51bWJlcih0b2tlbnNbMV0pO1xuICAgICAgY29uc3QgdG90YWwgPSBOdW1iZXIocmFuZ2VUb2tlbnNbMV0pO1xuXG4gICAgICByZXR1cm4geyBzdGFydCwgZW5kLCB0b3RhbCB9O1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHV0IGEgbGluZSBvZiB0ZXh0IHRvIHRoZSBsb2cuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsaW5lIFRoZSBsaW5lIHRvIGxvZy5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgbG9nKGxpbmU6IHN0cmluZykge1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMuY29uZmlnLmxvZ2dlcjtcbiAgICBpZiAobG9nZ2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmICh0eXBlb2YgbG9nZ2VyLmxvZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBsb2dnZXIubG9nKGxpbmUpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbG9nZ2VyLndyaXRlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGxvZ2dlci53cml0ZShsaW5lICsgJ1xcbicpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19