metaapi.cloud-metastats-sdk
Version:
Javascript SDK for MetaStats forex trading statistics API. Can calculate metrics for MetaTrader accounts added to MetaApi. Supports both MetaTrader 5 (MT5) and MetaTrader 4 (MT4). (https://metaapi.cloud)
227 lines (226 loc) • 22.9 kB
JavaScript
;
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _async_to_generator(fn) {
return function() {
var self = this, args = arguments;
return new Promise(function(resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
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 _object_spread(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === "function") {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_define_property(target, key, source[key]);
});
}
return target;
}
import axios from 'axios';
import { UnauthorizedError, ForbiddenError, ApiError, ValidationError, InternalError, NotFoundError, TooManyRequestsError } from './errorHandler';
import TimeoutError from './timeoutError';
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
*/ request(options, endTime = Date.now() + this._maxRetryDelay * this._retries) {
var _this = this;
return _async_to_generator(function*() {
options.timeout = _this._timeout;
let retryAfterSeconds = 0;
options.callback = (e, res)=>{
if (res && res.status === 202) {
retryAfterSeconds = res.headers['retry-after'];
}
};
let body;
try {
const response = yield _this._makeRequest(options);
options.callback(null, response);
body = response && response.data || undefined;
} catch (err) {
throw _this._convertError(err);
}
if (retryAfterSeconds) {
yield _this._handleRetry(endTime, retryAfterSeconds * 1000);
body = yield _this.request(options, endTime);
}
return body;
})();
}
/**
* Performs a request with failover. Response errors are returned as ApiError or subclasses.
* @param {Object} options request options
* @returns {Object|String|any} request result
*/ requestWithFailover(options, retryCounter = 0, endTime = Date.now() + this._maxRetryDelay * this._retries) {
var _this = this;
return _async_to_generator(function*() {
options.timeout = _this._timeout;
let retryAfterSeconds = 0;
options.callback = (e, res)=>{
if (res && res.status === 202) {
retryAfterSeconds = res.headers['retry-after'];
}
};
let body;
try {
const response = yield _this._makeRequest(options);
options.callback(null, response);
body = response && response.data || undefined;
} catch (err) {
retryCounter = yield _this._handleError(err, retryCounter, endTime);
return _this.requestWithFailover(options, retryCounter, endTime);
}
if (retryAfterSeconds) {
yield _this._handleRetry(endTime, retryAfterSeconds * 1000);
body = yield _this.requestWithFailover(options, retryCounter, endTime);
}
return body;
})();
}
_makeRequest(options) {
return axios(_object_spread({
transitional: {
clarifyTimeoutError: true
}
}, options));
}
_wait(pause) {
return _async_to_generator(function*() {
yield new Promise((res)=>setTimeout(res, pause));
})();
}
_handleRetry(endTime, retryAfter) {
var _this = this;
return _async_to_generator(function*() {
if (endTime > Date.now() + retryAfter) {
yield _this._wait(retryAfter);
} else {
throw new TimeoutError('Timed out waiting for the end of the process of calculating metrics');
}
})();
}
_handleError(err, retryCounter, endTime) {
var _this = this;
return _async_to_generator(function*() {
const error = _this._convertError(err);
if ([
'InternalError',
'ApiError'
].includes(error.name) && retryCounter < _this._retries) {
const pause = Math.min(Math.pow(2, retryCounter) * _this._minRetryDelay, _this._maxRetryDelay);
yield _this._wait(pause);
return retryCounter + 1;
} else if (error.name === 'TooManyRequestsError') {
const retryTime = Date.parse(error.metadata.recommendedRetryTime);
if (retryTime < endTime) {
yield _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 ValidationError(errMsg, errorData.details || err.details, url);
case 401:
return new UnauthorizedError(errMsg, url);
case 403:
return new ForbiddenError(errMsg, url);
case 404:
return new NotFoundError(errMsg, url);
case 429:
return new TooManyRequestsError(errMsg, errorData.metadata || err.metadata, url);
case 500:
return new InternalError(errMsg, url);
default:
return new ApiError(ApiError, errMsgDefault, status, url);
}
}
/**
* @typedef {Object} RetryOptions retry options
* @property {Number} [retries] the number of attempts to retry failed request, default 5
* @property {Number} [minDelayInSeconds] minimum delay in seconds before retrying, default 1
* @property {Number} [maxDelayInSeconds] maximum delay in seconds before retrying, default 30
*/ /**
* Constructs HttpClient class instance
* @param {Number} timeout request timeout in seconds
* @param {RetryOptions} [retryOpts] retry options
*/ constructor(timeout = 60, retryOpts = {}){
this._timeout = timeout * 1000;
this._retries = retryOpts.retries || 5;
this._minRetryDelay = (retryOpts.minDelayInSeconds || 1) * 1000;
this._maxRetryDelay = (retryOpts.maxDelayInSeconds || 30) * 1000;
}
};
/**
* HTTP client library based on request-promise
*/ export { HttpClient as default };
/**
* HTTP client service mock for tests
*/ export class HttpClientMock extends HttpClient {
_makeRequest() {
return this._requestFn.apply(this, arguments);
}
/**
* 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);
this._requestFn = requestFn;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBheGlvcyBmcm9tICdheGlvcyc7XG5cbmltcG9ydCB7XG4gIFVuYXV0aG9yaXplZEVycm9yLCBGb3JiaWRkZW5FcnJvciwgQXBpRXJyb3IsIFZhbGlkYXRpb25FcnJvciwgSW50ZXJuYWxFcnJvciwgTm90Rm91bmRFcnJvciwgVG9vTWFueVJlcXVlc3RzRXJyb3Jcbn0gZnJvbSAnLi9lcnJvckhhbmRsZXInO1xuaW1wb3J0IFRpbWVvdXRFcnJvciBmcm9tICcuL3RpbWVvdXRFcnJvcic7XG5cbi8qKlxuICogSFRUUCBjbGllbnQgbGlicmFyeSBiYXNlZCBvbiByZXF1ZXN0LXByb21pc2VcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSHR0cENsaWVudCB7XG5cbiAgLyoqXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IFJldHJ5T3B0aW9ucyByZXRyeSBvcHRpb25zXG4gICAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbcmV0cmllc10gdGhlIG51bWJlciBvZiBhdHRlbXB0cyB0byByZXRyeSBmYWlsZWQgcmVxdWVzdCwgZGVmYXVsdCA1XG4gICAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbbWluRGVsYXlJblNlY29uZHNdIG1pbmltdW0gZGVsYXkgaW4gc2Vjb25kcyBiZWZvcmUgcmV0cnlpbmcsIGRlZmF1bHQgMVxuICAgKiBAcHJvcGVydHkge051bWJlcn0gW21heERlbGF5SW5TZWNvbmRzXSBtYXhpbXVtIGRlbGF5IGluIHNlY29uZHMgYmVmb3JlIHJldHJ5aW5nLCBkZWZhdWx0IDMwXG4gICAqL1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIEh0dHBDbGllbnQgY2xhc3MgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtOdW1iZXJ9IHRpbWVvdXQgcmVxdWVzdCB0aW1lb3V0IGluIHNlY29uZHNcbiAgICogQHBhcmFtIHtSZXRyeU9wdGlvbnN9IFtyZXRyeU9wdHNdIHJldHJ5IG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKHRpbWVvdXQgPSA2MCwgcmV0cnlPcHRzID0ge30pIHtcbiAgICB0aGlzLl90aW1lb3V0ID0gdGltZW91dCAqIDEwMDA7XG4gICAgdGhpcy5fcmV0cmllcyA9IHJldHJ5T3B0cy5yZXRyaWVzIHx8IDU7XG4gICAgdGhpcy5fbWluUmV0cnlEZWxheSA9IChyZXRyeU9wdHMubWluRGVsYXlJblNlY29uZHMgfHwgMSkgKiAxMDAwO1xuICAgIHRoaXMuX21heFJldHJ5RGVsYXkgPSAocmV0cnlPcHRzLm1heERlbGF5SW5TZWNvbmRzIHx8IDMwKSAqIDEwMDA7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgYSByZXF1ZXN0LiBSZXNwb25zZSBlcnJvcnMgYXJlIHJldHVybmVkIGFzIEFwaUVycm9yIG9yIHN1YmNsYXNzZXMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIHJlcXVlc3Qgb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7T2JqZWN0fFN0cmluZ3xhbnl9IHJlcXVlc3QgcmVzdWx0XG4gICAqL1xuICBhc3luYyByZXF1ZXN0KG9wdGlvbnMsIGVuZFRpbWUgPSBEYXRlLm5vdygpICsgdGhpcy5fbWF4UmV0cnlEZWxheSAqIHRoaXMuX3JldHJpZXMpIHtcbiAgICBvcHRpb25zLnRpbWVvdXQgPSB0aGlzLl90aW1lb3V0O1xuICAgIGxldCByZXRyeUFmdGVyU2Vjb25kcyA9IDA7XG4gICAgb3B0aW9ucy5jYWxsYmFjayA9IChlLCByZXMpID0+IHtcbiAgICAgIGlmIChyZXMgJiYgcmVzLnN0YXR1cyA9PT0gMjAyKSB7XG4gICAgICAgIHJldHJ5QWZ0ZXJTZWNvbmRzID0gcmVzLmhlYWRlcnNbJ3JldHJ5LWFmdGVyJ107XG4gICAgICB9XG4gICAgfTtcbiAgICBsZXQgYm9keTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLl9tYWtlUmVxdWVzdChvcHRpb25zKTtcbiAgICAgIG9wdGlvbnMuY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgYm9keSA9IChyZXNwb25zZSAmJiByZXNwb25zZS5kYXRhKSB8fCB1bmRlZmluZWQ7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aHJvdyB0aGlzLl9jb252ZXJ0RXJyb3IoZXJyKTtcbiAgICB9XG4gICAgaWYgKHJldHJ5QWZ0ZXJTZWNvbmRzKSB7XG4gICAgICBhd2FpdCB0aGlzLl9oYW5kbGVSZXRyeShlbmRUaW1lLCByZXRyeUFmdGVyU2Vjb25kcyAqIDEwMDApO1xuICAgICAgYm9keSA9IGF3YWl0IHRoaXMucmVxdWVzdChvcHRpb25zLCBlbmRUaW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIGJvZHk7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgYSByZXF1ZXN0IHdpdGggZmFpbG92ZXIuIFJlc3BvbnNlIGVycm9ycyBhcmUgcmV0dXJuZWQgYXMgQXBpRXJyb3Igb3Igc3ViY2xhc3Nlcy5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgcmVxdWVzdCBvcHRpb25zXG4gICAqIEByZXR1cm5zIHtPYmplY3R8U3RyaW5nfGFueX0gcmVxdWVzdCByZXN1bHRcbiAgICovXG4gIGFzeW5jIHJlcXVlc3RXaXRoRmFpbG92ZXIob3B0aW9ucywgcmV0cnlDb3VudGVyID0gMCwgZW5kVGltZSA9IERhdGUubm93KCkgKyB0aGlzLl9tYXhSZXRyeURlbGF5ICogdGhpcy5fcmV0cmllcykge1xuICAgIG9wdGlvbnMudGltZW91dCA9IHRoaXMuX3RpbWVvdXQ7XG4gICAgbGV0IHJldHJ5QWZ0ZXJTZWNvbmRzID0gMDtcblxuICAgIG9wdGlvbnMuY2FsbGJhY2sgPSAoZSwgcmVzKSA9PiB7XG4gICAgICBpZiAocmVzICYmIHJlcy5zdGF0dXMgPT09IDIwMikge1xuICAgICAgICByZXRyeUFmdGVyU2Vjb25kcyA9IHJlcy5oZWFkZXJzWydyZXRyeS1hZnRlciddO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBsZXQgYm9keTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLl9tYWtlUmVxdWVzdChvcHRpb25zKTtcbiAgICAgIG9wdGlvbnMuY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgYm9keSA9IChyZXNwb25zZSAmJiByZXNwb25zZS5kYXRhKSB8fCB1bmRlZmluZWQ7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZXRyeUNvdW50ZXIgPSBhd2FpdCB0aGlzLl9oYW5kbGVFcnJvcihlcnIsIHJldHJ5Q291bnRlciwgZW5kVGltZSk7XG4gICAgICByZXR1cm4gdGhpcy5yZXF1ZXN0V2l0aEZhaWxvdmVyKG9wdGlvbnMsIHJldHJ5Q291bnRlciwgZW5kVGltZSk7XG4gICAgfVxuXG5cbiAgICBpZiAocmV0cnlBZnRlclNlY29uZHMpIHtcbiAgICAgIGF3YWl0IHRoaXMuX2hhbmRsZVJldHJ5KGVuZFRpbWUsIHJldHJ5QWZ0ZXJTZWNvbmRzICogMTAwMCk7XG4gICAgICBib2R5ID0gYXdhaXQgdGhpcy5yZXF1ZXN0V2l0aEZhaWxvdmVyKG9wdGlvbnMsIHJldHJ5Q291bnRlciwgZW5kVGltZSk7XG4gICAgfVxuICAgIHJldHVybiBib2R5O1xuICB9XG5cbiAgX21ha2VSZXF1ZXN0KG9wdGlvbnMpIHtcbiAgICByZXR1cm4gYXhpb3Moe1xuICAgICAgdHJhbnNpdGlvbmFsOiB7XG4gICAgICAgIGNsYXJpZnlUaW1lb3V0RXJyb3I6IHRydWVcbiAgICAgIH0sXG4gICAgICAuLi5vcHRpb25zXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBfd2FpdChwYXVzZSkge1xuICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlcyA9PiBzZXRUaW1lb3V0KHJlcywgcGF1c2UpKTtcbiAgfVxuXG4gIGFzeW5jIF9oYW5kbGVSZXRyeShlbmRUaW1lLCByZXRyeUFmdGVyKSB7XG4gICAgaWYgKGVuZFRpbWUgPiBEYXRlLm5vdygpICsgcmV0cnlBZnRlcikge1xuICAgICAgYXdhaXQgdGhpcy5fd2FpdChyZXRyeUFmdGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFRpbWVvdXRFcnJvcignVGltZWQgb3V0IHdhaXRpbmcgZm9yIHRoZSBlbmQgb2YgdGhlIHByb2Nlc3Mgb2YgY2FsY3VsYXRpbmcgbWV0cmljcycpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIF9oYW5kbGVFcnJvcihlcnIsIHJldHJ5Q291bnRlciwgZW5kVGltZSkge1xuICAgIGNvbnN0IGVycm9yID0gdGhpcy5fY29udmVydEVycm9yKGVycik7XG4gICAgaWYgKFsnSW50ZXJuYWxFcnJvcicsICdBcGlFcnJvciddLmluY2x1ZGVzKGVycm9yLm5hbWUpICYmIHJldHJ5Q291bnRlciA8IHRoaXMuX3JldHJpZXMpIHtcbiAgICAgIGNvbnN0IHBhdXNlID0gTWF0aC5taW4oTWF0aC5wb3coMiwgcmV0cnlDb3VudGVyKSAqIHRoaXMuX21pblJldHJ5RGVsYXksIHRoaXMuX21heFJldHJ5RGVsYXkpO1xuICAgICAgYXdhaXQgdGhpcy5fd2FpdChwYXVzZSk7XG4gICAgICByZXR1cm4gcmV0cnlDb3VudGVyICsgMTtcbiAgICB9IGVsc2UgaWYgKGVycm9yLm5hbWUgPT09ICdUb29NYW55UmVxdWVzdHNFcnJvcicpIHtcbiAgICAgIGNvbnN0IHJldHJ5VGltZSA9IERhdGUucGFyc2UoZXJyb3IubWV0YWRhdGEucmVjb21tZW5kZWRSZXRyeVRpbWUpO1xuICAgICAgaWYgKHJldHJ5VGltZSA8IGVuZFRpbWUpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5fd2FpdChyZXRyeVRpbWUgLSBEYXRlLm5vdygpKTtcbiAgICAgICAgcmV0dXJuIHJldHJ5Q291bnRlcjtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuICBfY29udmVydEVycm9yKGVycikge1xuICAgIGNvbnN0IGVycm9yUmVzcG9uc2UgPSBlcnIucmVzcG9uc2UgfHwge307XG4gICAgY29uc3QgZXJyb3JEYXRhID0gZXJyb3JSZXNwb25zZS5kYXRhIHx8IHt9O1xuICAgIGNvbnN0IHN0YXR1cyA9IGVycm9yUmVzcG9uc2Uuc3RhdHVzIHx8IGVyci5zdGF0dXM7XG4gICAgY29uc3QgdXJsID0gZXJyPy5jb25maWc/LnVybDtcblxuICAgIGNvbnN0IGVyck1zZyA9IGVycm9yRGF0YS5tZXNzYWdlIHx8IGVyci5tZXNzYWdlO1xuICAgIGNvbnN0IGVyck1zZ0RlZmF1bHQgPSBlcnJvckRhdGEubWVzc2FnZSB8fCBlcnIuY29kZSB8fCBlcnIubWVzc2FnZTtcblxuICAgIHN3aXRjaCAoc3RhdHVzKSB7XG4gICAgY2FzZSA0MDA6XG4gICAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25FcnJvcihlcnJNc2csIGVycm9yRGF0YS5kZXRhaWxzIHx8IGVyci5kZXRhaWxzLCB1cmwpO1xuICAgIGNhc2UgNDAxOlxuICAgICAgcmV0dXJuIG5ldyBVbmF1dGhvcml6ZWRFcnJvcihlcnJNc2csIHVybCk7XG4gICAgY2FzZSA0MDM6XG4gICAgICByZXR1cm4gbmV3IEZvcmJpZGRlbkVycm9yKGVyck1zZywgdXJsKTtcbiAgICBjYXNlIDQwNDpcbiAgICAgIHJldHVybiBuZXcgTm90Rm91bmRFcnJvcihlcnJNc2csIHVybCk7XG4gICAgY2FzZSA0Mjk6XG4gICAgICByZXR1cm4gbmV3IFRvb01hbnlSZXF1ZXN0c0Vycm9yKGVyck1zZywgZXJyb3JEYXRhLm1ldGFkYXRhIHx8IGVyci5tZXRhZGF0YSwgdXJsKTtcbiAgICBjYXNlIDUwMDpcbiAgICAgIHJldHVybiBuZXcgSW50ZXJuYWxFcnJvcihlcnJNc2csIHVybCk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBuZXcgQXBpRXJyb3IoQXBpRXJyb3IsIGVyck1zZ0RlZmF1bHQsIHN0YXR1cywgdXJsKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBIVFRQIGNsaWVudCBzZXJ2aWNlIG1vY2sgZm9yIHRlc3RzXG4gKi9cbmV4cG9ydCBjbGFzcyBIdHRwQ2xpZW50TW9jayBleHRlbmRzIEh0dHBDbGllbnQge1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIEhUVFAgY2xpZW50IG1vY2tcbiAgICogQHBhcmFtIHtGdW5jdGlvbihvcHRpb25zOk9iamVjdCk6UHJvbWlzZX0gcmVxdWVzdEZuIG1vY2tlZCByZXF1ZXN0IGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lb3V0IHJlcXVlc3QgdGltZW91dCBpbiBzZWNvbmRzXG4gICAqIEBwYXJhbSB7UmV0cnlPcHRpb25zfSByZXRyeU9wdHMgcmV0cnkgb3B0aW9uc1xuICAgKi9cbiAgY29uc3RydWN0b3IocmVxdWVzdEZuLCB0aW1lb3V0LCByZXRyeU9wdHMpIHtcbiAgICBzdXBlcih0aW1lb3V0LCByZXRyeU9wdHMpO1xuICAgIHRoaXMuX3JlcXVlc3RGbiA9IHJlcXVlc3RGbjtcbiAgfVxuXG4gIF9tYWtlUmVxdWVzdCgpIHtcbiAgICByZXR1cm4gdGhpcy5fcmVxdWVzdEZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJheGlvcyIsIlVuYXV0aG9yaXplZEVycm9yIiwiRm9yYmlkZGVuRXJyb3IiLCJBcGlFcnJvciIsIlZhbGlkYXRpb25FcnJvciIsIkludGVybmFsRXJyb3IiLCJOb3RGb3VuZEVycm9yIiwiVG9vTWFueVJlcXVlc3RzRXJyb3IiLCJUaW1lb3V0RXJyb3IiLCJIdHRwQ2xpZW50IiwicmVxdWVzdCIsIm9wdGlvbnMiLCJlbmRUaW1lIiwiRGF0ZSIsIm5vdyIsIl9tYXhSZXRyeURlbGF5IiwiX3JldHJpZXMiLCJ0aW1lb3V0IiwiX3RpbWVvdXQiLCJyZXRyeUFmdGVyU2Vjb25kcyIsImNhbGxiYWNrIiwiZSIsInJlcyIsInN0YXR1cyIsImhlYWRlcnMiLCJib2R5IiwicmVzcG9uc2UiLCJfbWFrZVJlcXVlc3QiLCJkYXRhIiwidW5kZWZpbmVkIiwiZXJyIiwiX2NvbnZlcnRFcnJvciIsIl9oYW5kbGVSZXRyeSIsInJlcXVlc3RXaXRoRmFpbG92ZXIiLCJyZXRyeUNvdW50ZXIiLCJfaGFuZGxlRXJyb3IiLCJ0cmFuc2l0aW9uYWwiLCJjbGFyaWZ5VGltZW91dEVycm9yIiwiX3dhaXQiLCJwYXVzZSIsIlByb21pc2UiLCJzZXRUaW1lb3V0IiwicmV0cnlBZnRlciIsImVycm9yIiwiaW5jbHVkZXMiLCJuYW1lIiwiTWF0aCIsIm1pbiIsInBvdyIsIl9taW5SZXRyeURlbGF5IiwicmV0cnlUaW1lIiwicGFyc2UiLCJtZXRhZGF0YSIsInJlY29tbWVuZGVkUmV0cnlUaW1lIiwiZXJyb3JSZXNwb25zZSIsImVycm9yRGF0YSIsInVybCIsImNvbmZpZyIsImVyck1zZyIsIm1lc3NhZ2UiLCJlcnJNc2dEZWZhdWx0IiwiY29kZSIsImRldGFpbHMiLCJjb25zdHJ1Y3RvciIsInJldHJ5T3B0cyIsInJldHJpZXMiLCJtaW5EZWxheUluU2Vjb25kcyIsIm1heERlbGF5SW5TZWNvbmRzIiwiSHR0cENsaWVudE1vY2siLCJfcmVxdWVzdEZuIiwiYXBwbHkiLCJhcmd1bWVudHMiLCJyZXF1ZXN0Rm4iXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsT0FBT0EsV0FBVyxRQUFRO0FBRTFCLFNBQ0VDLGlCQUFpQixFQUFFQyxjQUFjLEVBQUVDLFFBQVEsRUFBRUMsZUFBZSxFQUFFQyxhQUFhLEVBQUVDLGFBQWEsRUFBRUMsb0JBQW9CLFFBQzNHLGlCQUFpQjtBQUN4QixPQUFPQyxrQkFBa0IsaUJBQWlCO0FBSzNCLElBQUEsQUFBTUMsYUFBTixNQUFNQTtJQXFCbkI7Ozs7R0FJQyxHQUNELEFBQU1DLFFBQVFDLE9BQU8sRUFBRUMsVUFBVUMsS0FBS0MsR0FBRyxLQUFLLElBQUksQ0FBQ0MsY0FBYyxHQUFHLElBQUksQ0FBQ0MsUUFBUTs7ZUFBakYsb0JBQUE7WUFDRUwsUUFBUU0sT0FBTyxHQUFHLE1BQUtDLFFBQVE7WUFDL0IsSUFBSUMsb0JBQW9CO1lBQ3hCUixRQUFR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