UNPKG

metaapi.cloud-sdk

Version:

SDK for MetaApi, a professional cloud forex API which includes MetaTrader REST API and MetaTrader websocket API. Supports both MetaTrader 5 (MT5) and MetaTrader 4 (MT4). CopyFactory copy trading API included. (https://metaapi.cloud)

194 lines (193 loc) 26.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { HttpClientMock: function() { return HttpClientMock; }, default: function() { return HttpClient; } }); const _errorHandler = require("./errorHandler"); const _optionsValidator = /*#__PURE__*/ _interop_require_default(require("./optionsValidator")); const _timeoutError = /*#__PURE__*/ _interop_require_default(require("./timeoutError")); const _logger = /*#__PURE__*/ _interop_require_default(require("../logger")); const _lodash = /*#__PURE__*/ _interop_require_default(require("lodash")); function _define_property(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const axios = require("axios"); let HttpClient = class HttpClient { /** * Performs a request. Response errors are returned as ApiError or subclasses. * @param {Object} options request options * @returns {Object|String|any} request result */ async request(options, type = "", retryCounter = 0, endTime = Date.now() + this._maxRetryDelay * this._retries, isLongRunning = false) { options.timeout = this._timeout; let retryAfterSeconds = 0; options.callback = (e, res)=>{ this._logger.debug(`${type}: received request response with status ${res === null || res === void 0 ? void 0 : res.status}`); if ((res === null || res === void 0 ? void 0 : res.status) === 202) { var _res_data_metadata, _res_data; var _res_headers_retryafter; retryAfterSeconds = (_res_headers_retryafter = res.headers["retry-after"]) !== null && _res_headers_retryafter !== void 0 ? _res_headers_retryafter : (_res_data = res.data) === null || _res_data === void 0 ? void 0 : (_res_data_metadata = _res_data.metadata) === null || _res_data_metadata === void 0 ? void 0 : _res_data_metadata.recommendedRetryTime; this._logger.debug(`${type}: retry after value is ${retryAfterSeconds}`); if (isNaN(retryAfterSeconds)) { retryAfterSeconds = Math.max((new Date(retryAfterSeconds).getTime() - Date.now()) / 1000, 1); } if (!isLongRunning) { endTime = Date.now() + this._longRunningRequestTimeout; isLongRunning = true; } } }; let body; try { const response = await this._makeRequest(options, type); options.callback(null, response); body = response && response.data || undefined; } catch (err) { retryCounter = await this._handleError(err, type, retryCounter, endTime); return this.request(options, type, retryCounter, endTime); } if (retryAfterSeconds) { if (body && body.message) { this._logger.info(`Retrying request in ${Math.floor(retryAfterSeconds)} seconds because request ` + "returned message:", body.message); } await this._handleRetry(endTime, retryAfterSeconds * 1000); body = await this.request(options, type, retryCounter, endTime, isLongRunning); } return body; } _makeRequest(options, type) { var _optionsToLog_headers; let optionsToLog = _lodash.default.cloneDeep(options); if ((_optionsToLog_headers = optionsToLog.headers) === null || _optionsToLog_headers === void 0 ? void 0 : _optionsToLog_headers["auth-token"]) { optionsToLog.headers["auth-token"] = "..."; } this._logger.debug(`${type}: sending a request with options`, JSON.stringify(optionsToLog)); return axios({ transitional: { clarifyTimeoutError: true }, ...options }); } async _wait(pause) { await new Promise((res)=>setTimeout(res, pause)); } async _handleRetry(endTime, retryAfter) { if (endTime > Date.now() + retryAfter) { await this._wait(retryAfter); } else { throw new _timeoutError.default("Timed out waiting for the response"); } } async _handleError(err, type, retryCounter, endTime) { const error = this._convertError(err); if ([ "ConflictError", "InternalError", "ApiError", "TimeoutError" ].includes(error.name) && retryCounter < this._retries) { const pause = Math.min(Math.pow(2, retryCounter) * this._minRetryDelay, this._maxRetryDelay); await this._wait(pause); return retryCounter + 1; } else if (error.name === "TooManyRequestsError") { const retryTime = new Date(error.metadata.recommendedRetryTime).getTime(); if (retryTime < endTime) { this._logger.debug(`${type} request has failed with TooManyRequestsError (HTTP status code 429). ` + `Will retry request in ${Math.ceil((retryTime - Date.now()) / 1000)} seconds`); await this._wait(retryTime - Date.now()); return retryCounter; } } throw error; } // eslint-disable-next-line complexity _convertError(err) { var _err_config; const errorResponse = err.response || {}; const errorData = errorResponse.data || {}; const status = errorResponse.status || err.status; const url = err === null || err === void 0 ? void 0 : (_err_config = err.config) === null || _err_config === void 0 ? void 0 : _err_config.url; const errMsg = errorData.message || err.message; const errMsgDefault = errorData.message || err.code || err.message; switch(status){ case 400: return new _errorHandler.ValidationError(errMsg, errorData.details || err.details, url); case 401: return new _errorHandler.UnauthorizedError(errMsg, url); case 403: return new _errorHandler.ForbiddenError(errMsg, url); case 404: return new _errorHandler.NotFoundError(errMsg, url); case 409: return new _errorHandler.ConflictError(errMsg, url); case 429: return new _errorHandler.TooManyRequestsError(errMsg, errorData.metadata || err.metadata, url); case 500: return new _errorHandler.InternalError(errMsg, url); default: return new _errorHandler.ApiError(_errorHandler.ApiError, errMsgDefault, status, url); } } /** * Constructs HttpClient class instance * @param {Number} timeout request timeout in seconds * @param {RetryOptions} [retryOpts] retry options */ constructor(timeout = 60, retryOpts = {}){ _define_property(this, "_timeout", void 0); _define_property(this, "_retries", void 0); _define_property(this, "_minRetryDelay", void 0); _define_property(this, "_maxRetryDelay", void 0); _define_property(this, "_longRunningRequestTimeout", void 0); _define_property(this, "_logger", void 0); const validator = new _optionsValidator.default(); this._timeout = timeout * 1000; this._retries = validator.validateNumber(retryOpts.retries, 5, "retryOpts.retries"); this._minRetryDelay = validator.validateNonZero(retryOpts.minDelayInSeconds, 1, "retryOpts.minDelayInSeconds") * 1000; this._maxRetryDelay = validator.validateNonZero(retryOpts.maxDelayInSeconds, 30, "retryOpts.maxDelayInSeconds") * 1000; this._longRunningRequestTimeout = validator.validateNumber(retryOpts.longRunningRequestTimeoutInMinutes, 10, "retryOpts.longRunningRequestTimeoutInMinutes") * 60 * 1000; this._logger = _logger.default.getLogger("HttpClient"); } }; let HttpClientMock = class HttpClientMock extends HttpClient { _makeRequest(...args) { return this._requestFn(...args); } /** * Constructs HTTP client mock * @param {Function(options:Object):Promise} requestFn mocked request function * @param {Number} timeout request timeout in seconds * @param {RetryOptions} retryOpts retry options */ constructor(requestFn, timeout, retryOpts){ super(timeout, retryOpts); _define_property(this, "_requestFn", void 0); this._requestFn = requestFn; } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmNvbnN0IGF4aW9zID0gcmVxdWlyZSgnYXhpb3MnKTtcblxuaW1wb3J0IHtcbiAgVW5hdXRob3JpemVkRXJyb3IsIEZvcmJpZGRlbkVycm9yLCBBcGlFcnJvciwgVmFsaWRhdGlvbkVycm9yLCBJbnRlcm5hbEVycm9yLCBcbiAgTm90Rm91bmRFcnJvciwgVG9vTWFueVJlcXVlc3RzRXJyb3IsIENvbmZsaWN0RXJyb3Jcbn0gZnJvbSAnLi9lcnJvckhhbmRsZXInO1xuaW1wb3J0IE9wdGlvbnNWYWxpZGF0b3IgZnJvbSAnLi9vcHRpb25zVmFsaWRhdG9yJztcbmltcG9ydCBUaW1lb3V0RXJyb3IgZnJvbSAnLi90aW1lb3V0RXJyb3InO1xuaW1wb3J0IExvZ2dlck1hbmFnZXIsIHtMb2dnZXJ9IGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuXG4vKipcbiAqIEhUVFAgY2xpZW50IGxpYnJhcnkgYmFzZWQgb24gYXhpb3NcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSHR0cENsaWVudCB7XG4gIFxuICBwcml2YXRlIF90aW1lb3V0OiBudW1iZXI7XG4gIHByaXZhdGUgX3JldHJpZXM6IGFueTtcbiAgcHJpdmF0ZSBfbWluUmV0cnlEZWxheTogbnVtYmVyO1xuICBwcml2YXRlIF9tYXhSZXRyeURlbGF5OiBudW1iZXI7XG4gIHByaXZhdGUgX2xvbmdSdW5uaW5nUmVxdWVzdFRpbWVvdXQ6IG51bWJlcjtcbiAgcHJpdmF0ZSBfbG9nZ2VyOiBMb2dnZXI7XG4gIFxuICAvKipcbiAgICogQ29uc3RydWN0cyBIdHRwQ2xpZW50IGNsYXNzIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lb3V0IHJlcXVlc3QgdGltZW91dCBpbiBzZWNvbmRzXG4gICAqIEBwYXJhbSB7UmV0cnlPcHRpb25zfSBbcmV0cnlPcHRzXSByZXRyeSBvcHRpb25zXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih0aW1lb3V0ID0gNjAsIHJldHJ5T3B0czogUmV0cnlPcHRpb25zID0ge30pIHtcbiAgICBjb25zdCB2YWxpZGF0b3IgPSBuZXcgT3B0aW9uc1ZhbGlkYXRvcigpO1xuXG4gICAgdGhpcy5fdGltZW91dCA9IHRpbWVvdXQgKiAxMDAwO1xuICAgIHRoaXMuX3JldHJpZXMgPSB2YWxpZGF0b3IudmFsaWRhdGVOdW1iZXIocmV0cnlPcHRzLnJldHJpZXMsIDUsICdyZXRyeU9wdHMucmV0cmllcycpO1xuICAgIHRoaXMuX21pblJldHJ5RGVsYXkgPSB2YWxpZGF0b3IudmFsaWRhdGVOb25aZXJvKHJldHJ5T3B0cy5taW5EZWxheUluU2Vjb25kcywgMSxcbiAgICAgICdyZXRyeU9wdHMubWluRGVsYXlJblNlY29uZHMnKSAqIDEwMDA7XG4gICAgdGhpcy5fbWF4UmV0cnlEZWxheSA9IHZhbGlkYXRvci52YWxpZGF0ZU5vblplcm8ocmV0cnlPcHRzLm1heERlbGF5SW5TZWNvbmRzLCAzMCxcbiAgICAgICdyZXRyeU9wdHMubWF4RGVsYXlJblNlY29uZHMnKSAqIDEwMDA7XG4gICAgdGhpcy5fbG9uZ1J1bm5pbmdSZXF1ZXN0VGltZW91dCA9IHZhbGlkYXRvci52YWxpZGF0ZU51bWJlcihyZXRyeU9wdHMubG9uZ1J1bm5pbmdSZXF1ZXN0VGltZW91dEluTWludXRlcywgMTAsXG4gICAgICAncmV0cnlPcHRzLmxvbmdSdW5uaW5nUmVxdWVzdFRpbWVvdXRJbk1pbnV0ZXMnKSAqIDYwICogMTAwMDtcbiAgICB0aGlzLl9sb2dnZXIgPSBMb2dnZXJNYW5hZ2VyLmdldExvZ2dlcignSHR0cENsaWVudCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGEgcmVxdWVzdC4gUmVzcG9uc2UgZXJyb3JzIGFyZSByZXR1cm5lZCBhcyBBcGlFcnJvciBvciBzdWJjbGFzc2VzLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyByZXF1ZXN0IG9wdGlvbnNcbiAgICogQHJldHVybnMge09iamVjdHxTdHJpbmd8YW55fSByZXF1ZXN0IHJlc3VsdFxuICAgKi9cbiAgYXN5bmMgcmVxdWVzdDxUID0gYW55PihcbiAgICBvcHRpb25zLCB0eXBlID0gJycsIHJldHJ5Q291bnRlciA9IDAsIGVuZFRpbWUgPSBEYXRlLm5vdygpICsgdGhpcy5fbWF4UmV0cnlEZWxheSAqIHRoaXMuX3JldHJpZXMsXG4gICAgaXNMb25nUnVubmluZyA9IGZhbHNlXG4gICk6IFByb21pc2U8VD4ge1xuICAgIG9wdGlvbnMudGltZW91dCA9IHRoaXMuX3RpbWVvdXQ7XG4gICAgXG4gICAgbGV0IHJldHJ5QWZ0ZXJTZWNvbmRzID0gMDtcbiAgICBvcHRpb25zLmNhbGxiYWNrID0gKGUsIHJlcykgPT4ge1xuICAgICAgdGhpcy5fbG9nZ2VyLmRlYnVnKGAke3R5cGV9OiByZWNlaXZlZCByZXF1ZXN0IHJlc3BvbnNlIHdpdGggc3RhdHVzICR7cmVzPy5zdGF0dXN9YCk7XG4gICAgICBpZiAocmVzPy5zdGF0dXMgPT09IDIwMikge1xuICAgICAgICByZXRyeUFmdGVyU2Vjb25kcyA9IHJlcy5oZWFkZXJzWydyZXRyeS1hZnRlciddID8/IHJlcy5kYXRhPy5tZXRhZGF0YT8ucmVjb21tZW5kZWRSZXRyeVRpbWU7XG4gICAgICAgIHRoaXMuX2xvZ2dlci5kZWJ1ZyhgJHt0eXBlfTogcmV0cnkgYWZ0ZXIgdmFsdWUgaXMgJHtyZXRyeUFmdGVyU2Vjb25kc31gKTtcblxuICAgICAgICBpZiAoaXNOYU4ocmV0cnlBZnRlclNlY29uZHMpKSB7XG4gICAgICAgICAgcmV0cnlBZnRlclNlY29uZHMgPSBNYXRoLm1heCgobmV3IERhdGUocmV0cnlBZnRlclNlY29uZHMpLmdldFRpbWUoKSAtIERhdGUubm93KCkpIC8gMTAwMCwgMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0xvbmdSdW5uaW5nKSB7XG4gICAgICAgICAgZW5kVGltZSA9IERhdGUubm93KCkgKyB0aGlzLl9sb25nUnVubmluZ1JlcXVlc3RUaW1lb3V0O1xuICAgICAgICAgIGlzTG9uZ1J1bm5pbmcgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIGxldCBib2R5O1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fbWFrZVJlcXVlc3Qob3B0aW9ucywgdHlwZSk7XG4gICAgICBvcHRpb25zLmNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIGJvZHkgPSAocmVzcG9uc2UgJiYgcmVzcG9uc2UuZGF0YSkgfHwgdW5kZWZpbmVkO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcmV0cnlDb3VudGVyID0gYXdhaXQgdGhpcy5faGFuZGxlRXJyb3IoZXJyLCB0eXBlLCByZXRyeUNvdW50ZXIsIGVuZFRpbWUpO1xuICAgICAgcmV0dXJuIHRoaXMucmVxdWVzdChvcHRpb25zLCB0eXBlLCByZXRyeUNvdW50ZXIsIGVuZFRpbWUpO1xuICAgIH1cblxuICAgIGlmIChyZXRyeUFmdGVyU2Vjb25kcykge1xuICAgICAgaWYgKGJvZHkgJiYgYm9keS5tZXNzYWdlKSB7XG4gICAgICAgIHRoaXMuX2xvZ2dlci5pbmZvKGBSZXRyeWluZyByZXF1ZXN0IGluICR7TWF0aC5mbG9vcihyZXRyeUFmdGVyU2Vjb25kcyl9IHNlY29uZHMgYmVjYXVzZSByZXF1ZXN0IGAgK1xuICAgICAgICAgICdyZXR1cm5lZCBtZXNzYWdlOicsIGJvZHkubWVzc2FnZSk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLl9oYW5kbGVSZXRyeShlbmRUaW1lLCByZXRyeUFmdGVyU2Vjb25kcyAqIDEwMDApO1xuICAgICAgYm9keSA9IGF3YWl0IHRoaXMucmVxdWVzdChvcHRpb25zLCB0eXBlLCByZXRyeUNvdW50ZXIsIGVuZFRpbWUsIGlzTG9uZ1J1bm5pbmcpO1xuICAgIH1cblxuICAgIHJldHVybiBib2R5O1xuICB9XG5cbiAgX21ha2VSZXF1ZXN0KG9wdGlvbnMsIHR5cGUpIHtcbiAgICBsZXQgb3B0aW9uc1RvTG9nID0gXy5jbG9uZURlZXAob3B0aW9ucyk7XG4gICAgaWYgKG9wdGlvbnNUb0xvZy5oZWFkZXJzPy5bJ2F1dGgtdG9rZW4nXSkge1xuICAgICAgb3B0aW9uc1RvTG9nLmhlYWRlcnNbJ2F1dGgtdG9rZW4nXSA9ICcuLi4nO1xuICAgIH1cbiAgICB0aGlzLl9sb2dnZXIuZGVidWcoYCR7dHlwZX06IHNlbmRpbmcgYSByZXF1ZXN0IHdpdGggb3B0aW9uc2AsIEpTT04uc3RyaW5naWZ5KG9wdGlvbnNUb0xvZykpO1xuICAgIHJldHVybiBheGlvcyh7XG4gICAgICB0cmFuc2l0aW9uYWw6IHtcbiAgICAgICAgY2xhcmlmeVRpbWVvdXRFcnJvcjogdHJ1ZVxuICAgICAgfSxcbiAgICAgIC4uLm9wdGlvbnNcbiAgICB9KTtcbiAgfVxuICBcbiAgYXN5bmMgX3dhaXQocGF1c2UpIHtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXMgPT4gc2V0VGltZW91dChyZXMsIHBhdXNlKSk7XG4gIH1cbiAgXG4gIGFzeW5jIF9oYW5kbGVSZXRyeShlbmRUaW1lLCByZXRyeUFmdGVyKSB7XG4gICAgaWYgKGVuZFRpbWUgPiBEYXRlLm5vdygpICsgcmV0cnlBZnRlcikge1xuICAgICAgYXdhaXQgdGhpcy5fd2FpdChyZXRyeUFmdGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFRpbWVvdXRFcnJvcignVGltZWQgb3V0IHdhaXRpbmcgZm9yIHRoZSByZXNwb25zZScpO1xuICAgIH1cbiAgfVxuICBcbiAgYXN5bmMgX2hhbmRsZUVycm9yKGVyciwgdHlwZSwgcmV0cnlDb3VudGVyLCBlbmRUaW1lKSB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLl9jb252ZXJ0RXJyb3IoZXJyKTtcblxuICAgIGlmIChcbiAgICAgIFsnQ29uZmxpY3RFcnJvcicsICdJbnRlcm5hbEVycm9yJywgJ0FwaUVycm9yJywgJ1RpbWVvdXRFcnJvciddLmluY2x1ZGVzKGVycm9yLm5hbWUpICYmIFxuICAgICAgcmV0cnlDb3VudGVyIDwgdGhpcy5fcmV0cmllc1xuICAgICkge1xuICAgICAgY29uc3QgcGF1c2UgPSBNYXRoLm1pbihNYXRoLnBvdygyLCByZXRyeUNvdW50ZXIpICogdGhpcy5fbWluUmV0cnlEZWxheSwgdGhpcy5fbWF4UmV0cnlEZWxheSk7XG4gICAgICBhd2FpdCB0aGlzLl93YWl0KHBhdXNlKTtcblxuICAgICAgcmV0dXJuIHJldHJ5Q291bnRlciArIDE7XG4gICAgfSBlbHNlIGlmIChlcnJvci5uYW1lID09PSAnVG9vTWFueVJlcXVlc3RzRXJyb3InKSB7XG4gICAgICBjb25zdCByZXRyeVRpbWUgPSBuZXcgRGF0ZSgoZXJyb3IgYXMgVG9vTWFueVJlcXVlc3RzRXJyb3IpLm1ldGFkYXRhLnJlY29tbWVuZGVkUmV0cnlUaW1lKS5nZXRUaW1lKCk7XG4gICAgICBpZiAocmV0cnlUaW1lIDwgZW5kVGltZSkge1xuICAgICAgICB0aGlzLl9sb2dnZXIuZGVidWcoYCR7dHlwZX0gcmVxdWVzdCBoYXMgZmFpbGVkIHdpdGggVG9vTWFueVJlcXVlc3RzRXJyb3IgKEhUVFAgc3RhdHVzIGNvZGUgNDI5KS4gYCArXG4gICAgICAgICAgYFdpbGwgcmV0cnkgcmVxdWVzdCBpbiAke01hdGguY2VpbCgocmV0cnlUaW1lIC0gRGF0ZS5ub3coKSkgLyAxMDAwKX0gc2Vjb25kc2ApO1xuICAgICAgICBhd2FpdCB0aGlzLl93YWl0KHJldHJ5VGltZSAtIERhdGUubm93KCkpO1xuXG4gICAgICAgIHJldHVybiByZXRyeUNvdW50ZXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuICBfY29udmVydEVycm9yKGVycikge1xuICAgIGNvbnN0IGVycm9yUmVzcG9uc2UgPSBlcnIucmVzcG9uc2UgfHwge307XG4gICAgY29uc3QgZXJyb3JEYXRhID0gZXJyb3JSZXNwb25zZS5kYXRhIHx8IHt9O1xuICAgIGNvbnN0IHN0YXR1cyA9IGVycm9yUmVzcG9uc2Uuc3RhdHVzIHx8IGVyci5zdGF0dXM7XG4gICAgY29uc3QgdXJsID0gZXJyPy5jb25maWc/LnVybDtcblxuICAgIGNvbnN0IGVyck1zZyA9IGVycm9yRGF0YS5tZXNzYWdlIHx8IGVyci5tZXNzYWdlO1xuICAgIGNvbnN0IGVyck1zZ0RlZmF1bHQgPSBlcnJvckRhdGEubWVzc2FnZSB8fCBlcnIuY29kZSB8fCBlcnIubWVzc2FnZTtcblxuICAgIHN3aXRjaCAoc3RhdHVzKSB7XG4gICAgY2FzZSA0MDA6XG4gICAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25FcnJvcihlcnJNc2csIGVycm9yRGF0YS5kZXRhaWxzIHx8IGVyci5kZXRhaWxzLCB1cmwpO1xuICAgIGNhc2UgNDAxOlxuICAgICAgcmV0dXJuIG5ldyBVbmF1dGhvcml6ZWRFcnJvcihlcnJNc2csIHVybCk7XG4gICAgY2FzZSA0MDM6XG4gICAgICByZXR1cm4gbmV3IEZvcmJpZGRlbkVycm9yKGVyck1zZywgdXJsKTtcbiAgICBjYXNlIDQwNDpcbiAgICAgIHJldHVybiBuZXcgTm90Rm91bmRFcnJvcihlcnJNc2csIHVybCk7XG4gICAgY2FzZSA0MDk6XG4gICAgICByZXR1cm4gbmV3IENvbmZsaWN0RXJyb3IoZXJyTXNnLCB1cmwpO1xuICAgIGNhc2UgNDI5OlxuICAgICAgcmV0dXJuIG5ldyBUb29NYW55UmVxdWVzdHNFcnJvcihlcnJNc2csIGVycm9yRGF0YS5tZXRhZGF0YSB8fCBlcnIubWV0YWRhdGEsIHVybCk7XG4gICAgY2FzZSA1MDA6XG4gICAgICByZXR1cm4gbmV3IEludGVybmFsRXJyb3IoZXJyTXNnLCB1cmwpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbmV3IEFwaUVycm9yKEFwaUVycm9yLCBlcnJNc2dEZWZhdWx0LCBzdGF0dXMsIHVybCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogSFRUUCBjbGllbnQgc2VydmljZSBtb2NrIGZvciB0ZXN0c1xuICovXG5leHBvcnQgY2xhc3MgSHR0cENsaWVudE1vY2sgZXh0ZW5kcyBIdHRwQ2xpZW50IHtcbiAgX3JlcXVlc3RGbjogYW55O1xuICAvKipcbiAgICogQ29uc3RydWN0cyBIVFRQIGNsaWVudCBtb2NrXG4gICAqIEBwYXJhbSB7RnVuY3Rpb24ob3B0aW9uczpPYmplY3QpOlByb21pc2V9IHJlcXVlc3RGbiBtb2NrZWQgcmVxdWVzdCBmdW5jdGlvblxuICAgKiBAcGFyYW0ge051bWJlcn0gdGltZW91dCByZXF1ZXN0IHRpbWVvdXQgaW4gc2Vjb25kc1xuICAgKiBAcGFyYW0ge1JldHJ5T3B0aW9uc30gcmV0cnlPcHRzIHJldHJ5IG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKHJlcXVlc3RGbiwgdGltZW91dCwgcmV0cnlPcHRzKSB7XG4gICAgc3VwZXIodGltZW91dCwgcmV0cnlPcHRzKTtcbiAgICB0aGlzLl9yZXF1ZXN0Rm4gPSByZXF1ZXN0Rm47XG4gIH1cblxuICBfbWFrZVJlcXVlc3QoLi4uYXJncykge1xuICAgIHJldHVybiB0aGlzLl9yZXF1ZXN0Rm4oLi4uYXJncyk7XG4gIH1cblxufVxuXG4vKipcbiAqIHJldHJ5IG9wdGlvbnNcbiAqL1xuZXhwb3J0IGRlY2xhcmUgdHlwZSBSZXRyeU9wdGlvbnMgPSB7XG5cbiAgLyoqXG4gICAqIHRoZSBudW1iZXIgb2YgYXR0ZW1wdHMgdG8gcmV0cnkgZmFpbGVkIHJlcXVlc3QsIGRlZmF1bHQgNVxuICAgKi9cbiAgcmV0cmllcz86IG51bWJlcixcblxuICAvKipcbiAgICogbWluaW11bSBkZWxheSBpbiBzZWNvbmRzIGJlZm9yZSByZXRyeWluZywgZGVmYXVsdCAxXG4gICAqL1xuICBtaW5EZWxheUluU2Vjb25kcz86IG51bWJlcixcbiAgXG4gIC8qKlxuICAgKiBtYXhpbXVtIGRlbGF5IGluIHNlY29uZHMgYmVmb3JlIHJldHJ5aW5nLCBkZWZhdWx0IDMwXG4gICAqL1xuICBtYXhEZWxheUluU2Vjb25kcz86IG51bWJlcixcblxuICAvKipcbiAgICogdGltZW91dCBpbiBtaW51dGVzIGZvciBsb25nIHJ1bm5pbmcgcmVxdWVzdHMsIGRlZmF1bHQgMTBcbiAgICovXG4gIGxvbmdSdW5uaW5nUmVxdWVzdFRpbWVvdXRJbk1pbnV0ZXM/OiBudW1iZXIsXG5cbiAgLyoqXG4gICAqIHRpbWUgdG8gZGlzYWJsZSBuZXcgc3Vic2NyaXB0aW9ucyBmb3JcbiAgICovXG4gIHN1YnNjcmliZUNvb2xkb3duSW5TZWNvbmRzPzogbnVtYmVyXG59XG4iXSwibmFtZXMiOlsiSHR0cENsaWVudE1vY2siLCJIdHRwQ2xpZW50IiwiYXhpb3MiLCJyZXF1aXJlIiwicmVxdWVzdCIsIm9wdGlvbnMiLCJ0eXBlIiwicmV0cnlDb3VudGVyIiwiZW5kVGltZSIsIkRhdGUiLCJub3ciLCJfbWF4UmV0cnlEZWxheSIsIl9yZXRyaWVzIiwiaXNMb25nUnVubmluZyIsInRpbWVvdXQiLCJfdGltZW91dCIsInJldHJ5QWZ0ZXJTZWNvbmRzIiwiY2FsbGJhY2siLCJlIiwicmVzIiwiX2xvZ2dlciIsImRlYnVnIiwic3RhdHVzIiwiaGVhZGVycyIsImRhdGEiLCJtZXRhZGF0YSIsInJlY29tbWVuZGVkUmV0cnlUaW1lIiwiaXNOYU4iLCJNYXRoIiwibWF4IiwiZ2V0VGltZSIsIl9sb25nUnVubmluZ1JlcXVlc3RUaW1lb3V0IiwiYm9keSIsInJlc3BvbnNlIiwiX21ha2VSZXF1ZXN0IiwidW5kZWZpbmVkIiwiZXJyIiwiX2hhbmRsZUVycm9yIiwibWVzc2FnZSIsImluZm8iLCJmbG9vciIsIl9oYW5kbGVSZXRyeSIsIm9wdGlvbnNUb0xvZyIsIl8iLCJjbG9uZURlZXAiLCJKU09OIiwic3RyaW5naWZ5IiwidHJhbnNpdGlvbmFsIiwiY2xhcmlmeVRpbWVvdXRFcnJvciIsIl93YWl0IiwicGF1c2UiLCJQcm9taXNlIiwic2V0VGltZW91dCIsInJldHJ5QWZ0ZXIiLCJUaW1lb3V0RXJyb3IiLCJlcnJvciIsIl9jb252ZXJ0RXJyb3IiLCJpbmNsdWRlcyIsIm5hbWUiLCJtaW4iLCJwb3ciLCJfbWluUmV0cnlEZWxheSIsInJldHJ5VGltZSIsImNlaWwiLCJlcnJvclJlc3BvbnNlIiwiZXJyb3JEYXRhIiwidXJsIiwiY29uZmlnIiwiZXJyTXNnIiwiZXJyTXNnRGVmYXVsdCIsImNvZGUiLCJWYWxpZGF0aW9uRXJyb3IiLCJkZXRhaWxzIiwiVW5hdXRob3JpemVkRXJyb3IiLCJGb3JiaWRkZW5FcnJvciIsIk5vdEZvdW5kRXJyb3IiLCJDb25mbGljdEVycm9yIiwiVG9vTWFueVJlcXVlc3RzRXJyb3IiLCJJbnRlcm5hbEVycm9yIiwiQXBpRXJyb3IiLCJjb25zdHJ1Y3RvciIsInJldHJ5T3B0cyIsInZhbGlkYXRvciIsIk9wdGlvbnNWYWxpZGF0b3IiLCJ2YWxpZGF0ZU51bWJlciIsInJldHJpZXMiLCJ2YWxpZGF0ZU5vblplcm8iLCJtaW5EZWxheUluU2Vjb25kcyIsIm1heERlbGF5SW5TZWNvbmRzIiwibG9uZ1J1bm5pbmdSZXF1ZXN0VGltZW91dEluTWludXRlcyIsIkxvZ2dlck1hbmFnZXIiLCJnZXRMb2dnZXIiLCJhcmdzIiwiX3JlcXVlc3RGbiIsInJlcXVlc3RGbiJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0lBb0xhQSxjQUFjO2VBQWRBOzs7ZUFwS1FDOzs7OEJBVGQ7eUVBQ3NCO3FFQUNKOytEQUNXOytEQUN0Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVRkLE1BQU1DLFFBQVFDLFFBQVE7QUFjUCxJQUFBLEFBQU1GLGFBQU4sTUFBTUE7SUE0Qm5COzs7O0dBSUMsR0FDRCxNQUFNRyxRQUNKQyxPQUFPLEVBQUVDLE9BQU8sRUFBRSxFQUFFQyxlQUFlLENBQUMsRUFBRUMsVUFBVUMsS0FBS0MsR0FBRyxLQUFLLElBQUksQ0FBQ0MsY0FBYyxHQUFHLElBQUksQ0FBQ0MsUUFBUSxFQUNoR0MsZ0JBQWdCLEtBQUssRUFDVDtRQUNaUixRQUFRUyxPQUFPLEdBQUcsSUFBSSxDQUFDQyxRQUFRO1FBRS9CLElBQUlDLG9CQUFvQjtRQUN4QlgsUUFBUVksUUFBUSxHQUFHLENBQUNDLEdBQUdDO1lBQ3JCLElBQUks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