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/LnVybDtcblxuICAgIGNvbnN0IGVyck1zZyA9IGVycm9yRGF0YS5tZXNzYWdlIHx8IGVyci5tZXNzYWdlO1xuICAgIGNvbnN0IGVyck1zZ0RlZmF1bHQgPSBlcnJvckRhdGEubWVzc2FnZSB8fCBlcnIuY29kZSB8fCBlcnIubWVzc2FnZTtcblxuICAgIHN3aXRjaCAoc3RhdHVzKSB7XG4gICAgY2FzZSA0MDA6XG4gICAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25FcnJvcihlcnJNc2csIGVycm9yRGF0YS5kZXRhaWxzIHx8IGVyci5kZXRhaWxzLCB1cmwpO1xuICAgIGNhc2UgNDAxOlxuICAgICAgcmV0dXJuIG5ldyBVbmF1dGhvcml6ZWRFcnJvcihlcnJNc2csIHVybCk7XG4gICAgY2FzZSA0MDM6XG4gICAgICByZXR1cm4gbmV3IEZvcmJpZGRlbkVycm9yKGVyck1zZywgdXJsKTtcbiAgICBjYXNlIDQwNDpcbiAgICAgIHJldHVybiBuZXcgTm90Rm91bmRFcnJvcihlcnJNc2csIHVybCk7XG4gICAgY2FzZSA0MDk6XG4gICAgICByZXR1cm4gbmV3IENvbmZsaWN0RXJyb3IoZXJyTXNnLCB1cmwpO1xuICAgIGNhc2UgNDI5OlxuICAgICAgcmV0dXJuIG5ldyBUb29NYW55UmVxdWVzdHNFcnJvcihlcnJNc2csIGVycm9yRGF0YS5tZXRhZGF0YSB8fCBlcnIubWV0YWRhdGEsIHVybCk7XG4gICAgY2FzZSA1MDA6XG4gICAgICByZXR1cm4gbmV3IEludGVybmFsRXJyb3IoZXJyTXNnLCB1cmwpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbmV3IEFwaUVycm9yKEFwaUVycm9yLCBlcnJNc2dEZWZhdWx0LCBzdGF0dXMsIHVybCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogSFRUUCBjbGllbnQgc2VydmljZSBtb2NrIGZvciB0ZXN0c1xuICovXG5leHBvcnQgY2xhc3MgSHR0cENsaWVudE1vY2sgZXh0ZW5kcyBIdHRwQ2xpZW50IHtcbiAgX3JlcXVlc3RGbjogYW55O1xuICAvKipcbiAgICogQ29uc3RydWN0cyBIVFRQIGNsaWVudCBtb2NrXG4gICAqIEBwYXJhbSB7RnVuY3Rpb24ob3B0aW9uczpPYmplY3QpOlByb21pc2V9IHJlcXVlc3RGbiBtb2NrZWQgcmVxdWVzdCBmdW5jdGlvblxuICAgKiBAcGFyYW0ge051bWJlcn0gdGltZW91dCByZXF1ZXN0IHRpbWVvdXQgaW4gc2Vjb25kc1xuICAgKiBAcGFyYW0ge1JldHJ5T3B0aW9uc30gcmV0cnlPcHRzIHJldHJ5IG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKHJlcXVlc3RGbiwgdGltZW91dD8sIHJldHJ5T3B0cz8pIHtcbiAgICBzdXBlcih0aW1lb3V0LCByZXRyeU9wdHMpO1xuICAgIHRoaXMuX3JlcXVlc3RGbiA9IHJlcXVlc3RGbjtcbiAgfVxuXG4gIF9tYWtlUmVxdWVzdCguLi5hcmdzKSB7XG4gICAgcmV0dXJuIHRoaXMuX3JlcXVlc3RGbiguLi5hcmdzKTtcbiAgfVxuXG59XG5cbi8qKlxuICogcmV0cnkgb3B0aW9uc1xuICovXG5leHBvcnQgZGVjbGFyZSB0eXBlIFJldHJ5T3B0aW9ucyA9IHtcblxuICAvKipcbiAgICogdGhlIG51bWJlciBvZiBhdHRlbXB0cyB0byByZXRyeSBmYWlsZWQgcmVxdWVzdCwgZGVmYXVsdCA1XG4gICAqL1xuICByZXRyaWVzPzogbnVtYmVyLFxuXG4gIC8qKlxuICAgKiBtaW5pbXVtIGRlbGF5IGluIHNlY29uZHMgYmVmb3JlIHJldHJ5aW5nLCBkZWZhdWx0IDFcbiAgICovXG4gIG1pbkRlbGF5SW5TZWNvbmRzPzogbnVtYmVyLFxuICBcbiAgLyoqXG4gICAqIG1heGltdW0gZGVsYXkgaW4gc2Vjb25kcyBiZWZvcmUgcmV0cnlpbmcsIGRlZmF1bHQgMzBcbiAgICovXG4gIG1heERlbGF5SW5TZWNvbmRzPzogbnVtYmVyLFxuXG4gIC8qKlxuICAgKiB0aW1lb3V0IGluIG1pbnV0ZXMgZm9yIGxvbmcgcnVubmluZyByZXF1ZXN0cywgZGVmYXVsdCAxMFxuICAgKi9cbiAgbG9uZ1J1bm5pbmdSZXF1ZXN0VGltZW91dEluTWludXRlcz86IG51bWJlcixcblxuICAvKipcbiAgICogdGltZSB0byBkaXNhYmxlIG5ldyBzdWJzY3JpcHRpb25zIGZvclxuICAgKi9cbiAgc3Vic2NyaWJlQ29vbGRvd25JblNlY29uZHM/OiBudW1iZXJcbn1cbiJdLCJuYW1lcyI6WyJIdHRwQ2xpZW50TW9jayIsIkh0dHBDbGllbnQiLCJheGlvcyIsInJlcXVpcmUiLCJyZXF1ZXN0Iiwib3B0aW9ucyIsInR5cGUiLCJyZXRyeUNvdW50ZXIiLCJlbmRUaW1lIiwiRGF0ZSIsIm5vdyIsIl9tYXhSZXRyeURlbGF5IiwiX3JldHJpZXMiLCJpc0xvbmdSdW5uaW5nIiwidGltZW91dCIsIl90aW1lb3V0IiwicmV0cnlBZnRlclNlY29uZHMiLCJjYWxsYmFjayIsImUiLCJyZXMiLCJfbG9nZ2VyIiwiZGVidWciLCJzdGF0dXMiLCJoZWFkZXJzIiwiZGF0YSIsIm1ldGFkYXRhIiwicmVjb21tZW5kZWRSZXRyeVRpbWUiLCJpc05hTiIsIk1hdGgiLCJtYXgiLCJnZXRUaW1lIiwiX2xvbmdSdW5uaW5nUmVxdWVzdFRpbWVvdXQiLCJib2R5IiwicmVzcG9uc2UiLCJfbWFrZVJlcXVlc3QiLCJ1bmRlZmluZWQiLCJlcnIiLCJfaGFuZGxlRXJyb3IiLCJtZXNzYWdlIiwiaW5mbyIsImZsb29yIiwiX2hhbmRsZVJldHJ5Iiwib3B0aW9uc1RvTG9nIiwiXyIsImNsb25lRGVlcCIsIkpTT04iLCJzdHJpbmdpZnkiLCJ0cmFuc2l0aW9uYWwiLCJjbGFyaWZ5VGltZW91dEVycm9yIiwiX3dhaXQiLCJwYXVzZSIsIlByb21pc2UiLCJzZXRUaW1lb3V0IiwicmV0cnlBZnRlciIsIlRpbWVvdXRFcnJvciIsImVycm9yIiwiX2NvbnZlcnRFcnJvciIsImluY2x1ZGVzIiwibmFtZSIsIm1pbiIsInBvdyIsIl9taW5SZXRyeURlbGF5IiwicmV0cnlUaW1lIiwiY2VpbCIsImVycm9yUmVzcG9uc2UiLCJlcnJvckRhdGEiLCJ1cmwiLCJjb25maWciLCJlcnJNc2ciLCJlcnJNc2dEZWZhdWx0IiwiY29kZSIsIlZhbGlkYXRpb25FcnJvciIsImRldGFpbHMiLCJVbmF1dGhvcml6ZWRFcnJvciIsIkZvcmJpZGRlbkVycm9yIiwiTm90Rm91bmRFcnJvciIsIkNvbmZsaWN0RXJyb3IiLCJUb29NYW55UmVxdWVzdHNFcnJvciIsIkludGVybmFsRXJyb3IiLCJBcGlFcnJvciIsImNvbnN0cnVjdG9yIiwicmV0cnlPcHRzIiwidmFsaWRhdG9yIiwiT3B0aW9uc1ZhbGlkYXRvciIsInZhbGlkYXRlTnVtYmVyIiwicmV0cmllcyIsInZhbGlkYXRlTm9uWmVybyIsIm1pbkRlbGF5SW5TZWNvbmRzIiwibWF4RGVsYXlJblNlY29uZHMiLCJsb25nUnVubmluZ1JlcXVlc3RUaW1lb3V0SW5NaW51dGVzIiwiTG9nZ2VyTWFuYWdlciIsImdldExvZ2dlciIsImFyZ3MiLCJfcmVxdWVzdEZuIiwicmVxdWVzdEZuIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7SUFvTGFBLGNBQWM7ZUFBZEE7OztlQXBLUUM7Ozs4QkFUZDt5RUFDc0I7cUVBQ0o7K0RBQ1c7K0RBQ3RCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBVGQsTUFBTUMsUUFBUUMsUUFBUTtBQWNQLElBQUEsQUFBTUYsYUFBTixNQUFNQTtJQTRCbkI7Ozs7R0FJQyxHQUNELE1BQU1HLFFBQ0pDLE9BQU8sRUFBRUMsT0FBTyxFQUFFLEVBQUVDLGVBQWUsQ0FBQyxFQUFFQyxVQUFVQyxLQUFLQyxHQUFHLEtBQUssSUFBSSxDQUFDQyxjQUFjLEdBQUcsSUFBSSxDQUFDQyxRQUFRLEVBQ2hHQyxnQkFBZ0IsS0FBSyxFQUNUO1FBQ1pSLFFBQVFTLE9BQU8sR0FBRyxJQUFJLENBQUNDLFFBQVE7UUFFL0IsSUFBSUMsb0JBQW9CO1FBQ3hCWCxRQUFRWSxRQUFRLEdBQUcsQ0FBQ0MsR0FBR0M7WUFDckIsSUFB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