UNPKG

jsforce

Version:

Salesforce API Library for JavaScript

526 lines (509 loc) 55.6 kB
import _Reflect$construct from "@babel/runtime-corejs3/core-js-stable/reflect/construct"; import _wrapNativeSuper from "@babel/runtime-corejs3/helpers/wrapNativeSuper"; import _typeof from "@babel/runtime-corejs3/helpers/typeof"; import _classCallCheck from "@babel/runtime-corejs3/helpers/classCallCheck"; import _createClass from "@babel/runtime-corejs3/helpers/createClass"; import _possibleConstructorReturn from "@babel/runtime-corejs3/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime-corejs3/helpers/getPrototypeOf"; import _inherits from "@babel/runtime-corejs3/helpers/inherits"; import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty"; import _asyncToGenerator from "@babel/runtime-corejs3/helpers/asyncToGenerator"; import _regeneratorRuntime from "@babel/runtime-corejs3/regenerator"; import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat"; import _Date$now from "@babel/runtime-corejs3/core-js-stable/date/now"; import _Object$keys2 from "@babel/runtime-corejs3/core-js-stable/object/keys"; import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes"; import _globalThis from "@babel/runtime-corejs3/core-js/global-this"; import _Array$isArray from "@babel/runtime-corejs3/core-js-stable/array/is-array"; function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? _Reflect$construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } import "core-js/modules/es.error.cause.js"; import "core-js/modules/es.array.join.js"; import "core-js/modules/es.array.push.js"; import "core-js/modules/es.function.name.js"; import "core-js/modules/es.object.keys.js"; import "core-js/modules/es.regexp.exec.js"; import "core-js/modules/es.regexp.test.js"; import "core-js/modules/web.self.js"; /** * */ import { EventEmitter } from 'events'; import xml2js from 'xml2js'; import { getLogger } from './util/logger'; import { StreamPromise } from './util/promise'; import { parseCSV } from './csv'; import { createLazyStream } from './util/stream'; import { getBodySize } from './util/get-body-size'; /** @private */ function parseJSON(str) { return JSON.parse(str); } /** @private */ function parseXML(_x) { return _parseXML.apply(this, arguments); } /** @private */ function _parseXML() { _parseXML = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(str) { return _regeneratorRuntime.wrap(function _callee5$(_context11) { while (1) switch (_context11.prev = _context11.next) { case 0: return _context11.abrupt("return", xml2js.parseStringPromise(str, { explicitArray: false })); case 1: case "end": return _context11.stop(); } }, _callee5); })); return _parseXML.apply(this, arguments); } function parseText(str) { return str; } /** * HTTP based API class with authorization hook */ export var HttpApi = /*#__PURE__*/function (_EventEmitter) { function HttpApi(conn, options) { var _this; _classCallCheck(this, HttpApi); _this = _callSuper(this, HttpApi); _this._conn = conn; _this._logger = conn._logLevel ? HttpApi._logger.createInstance(conn._logLevel) : HttpApi._logger; _this._responseType = options.responseType; _this._transport = options.transport || conn._transport; _this._noContentResponse = options.noContentResponse; _this._options = options; return _this; } /** * Callout to API endpoint using http */ _inherits(HttpApi, _EventEmitter); return _createClass(HttpApi, [{ key: "request", value: function request(_request) { var _this2 = this; return StreamPromise.create(function () { var _createLazyStream = createLazyStream(), stream = _createLazyStream.stream, setStream = _createLazyStream.setStream; var promise = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() { var _context, _context2; var refreshDelegate, bodyPromise, _body2, requestTime, requestPromise, response, responseTime, err, body; return _regeneratorRuntime.wrap(function _callee$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: refreshDelegate = _this2.getRefreshDelegate(); /* TODO decide remove or not this section */ /* // remember previous instance url in case it changes after a refresh const lastInstanceUrl = conn.instanceUrl; // check to see if the token refresh has changed the instance url if(lastInstanceUrl !== conn.instanceUrl){ // if the instance url has changed // then replace the current request urls instance url fragment // with the updated instance url request.url = request.url.replace(lastInstanceUrl,conn.instanceUrl); } */ if (!(refreshDelegate && refreshDelegate.isRefreshing())) { _context3.next = 10; break; } _context3.next = 4; return refreshDelegate.waitRefresh(); case 4: bodyPromise = _this2.request(_request); setStream(bodyPromise.stream()); _context3.next = 8; return bodyPromise; case 8: _body2 = _context3.sent; return _context3.abrupt("return", _body2); case 10: // hook before sending _this2.beforeSend(_request); _this2.emit('request', _request); _this2._logger.debug(_concatInstanceProperty(_context = "<request> method=".concat(_request.method, ", url=")).call(_context, _request.url)); requestTime = _Date$now(); requestPromise = _this2._transport.httpRequest(_request, _this2._options); setStream(requestPromise.stream()); _context3.prev = 16; _context3.next = 19; return requestPromise; case 19: response = _context3.sent; _context3.next = 26; break; case 22: _context3.prev = 22; _context3.t0 = _context3["catch"](16); _this2._logger.error(_context3.t0); throw _context3.t0; case 26: _context3.prev = 26; responseTime = _Date$now(); _this2._logger.debug("elapsed time: ".concat(responseTime - requestTime, " msec")); return _context3.finish(26); case 30: if (response) { _context3.next = 32; break; } return _context3.abrupt("return"); case 32: _this2._logger.debug(_concatInstanceProperty(_context2 = "<response> status=".concat(String(response.statusCode), ", url=")).call(_context2, _request.url)); _this2.emit('response', response); // Refresh token if session has been expired and requires authentication // when session refresh delegate is available if (!(_this2.isSessionExpired(response) && refreshDelegate)) { _context3.next = 39; break; } _context3.next = 37; return refreshDelegate.refresh(requestTime); case 37: /* remove the `content-length` header after token refresh * * SOAP requests include the access token their the body, * if the first req had an invalid token and jsforce successfully * refreshed it we need to remove the `content-length` header * so that it get's re-calculated again with the new body. * * REST request aren't affected by this because the access token * is sent via HTTP headers * * `_message` is only present in SOAP requests */ if ('_message' in _request && _request.headers && 'content-length' in _request.headers) { delete _request.headers['content-length']; } return _context3.abrupt("return", _this2.request(_request)); case 39: if (!_this2.isErrorResponse(response)) { _context3.next = 44; break; } _context3.next = 42; return _this2.getError(response); case 42: err = _context3.sent; throw err; case 44: _context3.next = 46; return _this2.getResponseBody(response); case 46: body = _context3.sent; return _context3.abrupt("return", body); case 48: case "end": return _context3.stop(); } }, _callee, null, [[16, 22, 26, 30]]); }))(); return { stream: stream, promise: promise }; }); } /** * @protected */ }, { key: "getRefreshDelegate", value: function getRefreshDelegate() { return this._conn._refreshDelegate; } /** * @protected */ }, { key: "beforeSend", value: function beforeSend(request) { var _context5; /* eslint-disable no-param-reassign */ var headers = request.headers || {}; if (this._conn.accessToken) { headers.Authorization = "Bearer ".concat(this._conn.accessToken); } if (this._conn._callOptions) { var callOptions = []; for (var _i = 0, _Object$keys = _Object$keys2(this._conn._callOptions); _i < _Object$keys.length; _i++) { var _context4; var name = _Object$keys[_i]; callOptions.push(_concatInstanceProperty(_context4 = "".concat(name, "=")).call(_context4, this._conn._callOptions[name])); } headers['Sforce-Call-Options'] = callOptions.join(', '); } var bodySize = getBodySize(request.body, headers); var cannotHaveBody = _includesInstanceProperty(_context5 = ['GET', 'HEAD', 'OPTIONS']).call(_context5, request.method); // Don't set content-length in browsers as it's not allowed var isBrowser = 'window' in _globalThis || 'self' in _globalThis; if (!isBrowser && // Don't set content-length in browsers as it's not allowed !cannotHaveBody && !!request.body && !('transfer-encoding' in headers) && !('content-length' in headers) && !!bodySize) { this._logger.debug("missing 'content-length' header, setting it to: ".concat(bodySize)); headers['content-length'] = String(bodySize); } request.headers = headers; } /** * Detect response content mime-type * @protected */ }, { key: "getResponseContentType", value: function getResponseContentType(response) { return this._responseType || response.headers && response.headers['content-type']; } /** * @private */ // eslint-disable-next-line @typescript-eslint/require-await }, { key: "parseResponseBody", value: (function () { var _parseResponseBody = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(response) { var contentType, parseBody, _context6; return _regeneratorRuntime.wrap(function _callee2$(_context7) { while (1) switch (_context7.prev = _context7.next) { case 0: contentType = this.getResponseContentType(response) || ''; parseBody = /^(text|application)\/xml(;|$)/.test(contentType) ? parseXML : /^application\/json(;|$)/.test(contentType) ? parseJSON : /^text\/csv(;|$)/.test(contentType) ? parseCSV : parseText; _context7.prev = 2; return _context7.abrupt("return", parseBody(response.body)); case 6: _context7.prev = 6; _context7.t0 = _context7["catch"](2); // TODO(next major): we could throw a new "invalid response body" error instead. this._logger.debug(_concatInstanceProperty(_context6 = "Failed to parse body of content-type: ".concat(contentType, ". Error: ")).call(_context6, _context7.t0.message)); return _context7.abrupt("return", response.body); case 10: case "end": return _context7.stop(); } }, _callee2, this, [[2, 6]]); })); function parseResponseBody(_x2) { return _parseResponseBody.apply(this, arguments); } return parseResponseBody; }() /** * Get response body * @protected */ ) }, { key: "getResponseBody", value: (function () { var _getResponseBody = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(response) { var body, err; return _regeneratorRuntime.wrap(function _callee3$(_context8) { while (1) switch (_context8.prev = _context8.next) { case 0: if (!(response.statusCode === 204)) { _context8.next = 2; break; } return _context8.abrupt("return", this._noContentResponse); case 2: _context8.next = 4; return this.parseResponseBody(response); case 4: body = _context8.sent; if (!this.hasErrorInResponseBody(body)) { _context8.next = 10; break; } _context8.next = 8; return this.getError(response, body); case 8: err = _context8.sent; throw err; case 10: if (!(response.statusCode === 300)) { _context8.next = 12; break; } throw new HttpApiError('Multiple records found', 'MULTIPLE_CHOICES', body); case 12: return _context8.abrupt("return", body); case 13: case "end": return _context8.stop(); } }, _callee3, this); })); function getResponseBody(_x3) { return _getResponseBody.apply(this, arguments); } return getResponseBody; }() /** * Detect session expiry * @protected */ ) }, { key: "isSessionExpired", value: function isSessionExpired(response) { // REST API status codes: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/errorcodes.htm // // "401 - The session ID or OAuth token used has expired or is invalid. The response body contains the message and errorCode." if (response.statusCode === 401) { // Known list of 401 responses that shouldn't be considered as "session expired". // // These usualy come from an CA/ECA, OAuth, IP restriction change in the org that block connections, we need to skip these // org jsforce will enter into an infinite loop trying to get a valid token. var responsesToSkip = ['Connected app is not attached to Agent', 'This session is not valid for use with the REST API']; for (var _i2 = 0, _responsesToSkip = responsesToSkip; _i2 < _responsesToSkip.length; _i2++) { var _context9; var p = _responsesToSkip[_i2]; if (_includesInstanceProperty(_context9 = response.body).call(_context9, p)) return false; } return true; } return false; } /** * Detect error response * @protected */ }, { key: "isErrorResponse", value: function isErrorResponse(response) { return response.statusCode >= 400; } /** * Detect error in response body * @protected */ }, { key: "hasErrorInResponseBody", value: function hasErrorInResponseBody(_body) { return false; } /** * Parsing error message in response * @protected */ }, { key: "parseError", value: function parseError(body) { var errors = body; // XML response if (errors.Errors) { return errors.Errors.Error; } return errors; } /** * Get error message in response * @protected */ }, { key: "getError", value: (function () { var _getError = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(response, body) { var error; return _regeneratorRuntime.wrap(function _callee4$(_context10) { while (1) switch (_context10.prev = _context10.next) { case 0: _context10.prev = 0; _context10.t0 = this; _context10.t1 = body; if (_context10.t1) { _context10.next = 7; break; } _context10.next = 6; return this.parseResponseBody(response); case 6: _context10.t1 = _context10.sent; case 7: _context10.t2 = _context10.t1; error = _context10.t0.parseError.call(_context10.t0, _context10.t2); _context10.next = 13; break; case 11: _context10.prev = 11; _context10.t3 = _context10["catch"](0); case 13: if (!_Array$isArray(error)) { _context10.next = 19; break; } if (!(error.length === 1)) { _context10.next = 18; break; } error = error[0]; _context10.next = 19; break; case 18: return _context10.abrupt("return", new HttpApiError("Multiple errors returned.\n Check `error.data` for the error details", 'MULTIPLE_API_ERRORS', error)); case 19: error = _typeof(error) === 'object' && error !== null && typeof error.message === 'string' ? error : { errorCode: "ERROR_HTTP_".concat(response.statusCode), message: response.body }; if (!(response.headers['content-type'] === 'text/html')) { _context10.next = 23; break; } this._logger.debug("html response.body: ".concat(response.body)); return _context10.abrupt("return", new HttpApiError("HTTP response contains html content.\nCheck that the org exists and can be reached.\nSee `error.data` for the full html response.", error.errorCode, error.message)); case 23: return _context10.abrupt("return", error instanceof HttpApiError ? error : new HttpApiError(error.message, error.errorCode, error)); case 24: case "end": return _context10.stop(); } }, _callee4, this, [[0, 11]]); })); function getError(_x4, _x5) { return _getError.apply(this, arguments); } return getError; }()) }]); }(EventEmitter); /** * */ _defineProperty(HttpApi, "_logger", getLogger('http-api')); var HttpApiError = /*#__PURE__*/function (_Error) { /** * This contains error-specific details, usually returned from the API. */ function HttpApiError(message, errorCode, data) { var _this3; _classCallCheck(this, HttpApiError); _this3 = _callSuper(this, HttpApiError, [message]); _this3.name = errorCode || _this3.name; _this3.errorCode = _this3.name; _this3.data = data; return _this3; } /** * This will be removed in the next major (v4) * * @deprecated use `error.data` instead */ _inherits(HttpApiError, _Error); return _createClass(HttpApiError, [{ key: "content", get: function get() { return this.data; } }]); }(/*#__PURE__*/_wrapNativeSuper(Error)); export default HttpApi; export var isBrowser = 'window' in _globalThis || 'self' in _globalThis; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJFdmVudEVtaXR0ZXIiLCJ4bWwyanMiLCJnZXRMb2dnZXIiLCJTdHJlYW1Qcm9taXNlIiwicGFyc2VDU1YiLCJjcmVhdGVMYXp5U3RyZWFtIiwiZ2V0Qm9keVNpemUiLCJwYXJzZUpTT04iLCJzdHIiLCJKU09OIiwicGFyc2UiLCJwYXJzZVhNTCIsIl94IiwiX3BhcnNlWE1MIiwiYXBwbHkiLCJhcmd1bWVudHMiLCJfYXN5bmNUb0dlbmVyYXRvciIsIl9yZWdlbmVyYXRvclJ1bnRpbWUiLCJtYXJrIiwiX2NhbGxlZTUiLCJ3cmFwIiwiX2NhbGxlZTUkIiwiX2NvbnRleHQxMSIsInByZXYiLCJuZXh0IiwiYWJydXB0IiwicGFyc2VTdHJpbmdQcm9taXNlIiwiZXhwbGljaXRBcnJheSIsInN0b3AiLCJwYXJzZVRleHQiLCJIdHRwQXBpIiwiX0V2ZW50RW1pdHRlciIsImNvbm4iLCJvcHRpb25zIiwiX3RoaXMiLCJfY2xhc3NDYWxsQ2hlY2siLCJfY2FsbFN1cGVyIiwiX2Nvbm4iLCJfbG9nZ2VyIiwiX2xvZ0xldmVsIiwiY3JlYXRlSW5zdGFuY2UiLCJfcmVzcG9uc2VUeXBlIiwicmVzcG9uc2VUeXBlIiwiX3RyYW5zcG9ydCIsInRyYW5zcG9ydCIsIl9ub0NvbnRlbnRSZXNwb25zZSIsIm5vQ29udGVudFJlc3BvbnNlIiwiX29wdGlvbnMiLCJfaW5oZXJpdHMiLCJfY3JlYXRlQ2xhc3MiLCJrZXkiLCJ2YWx1ZSIsInJlcXVlc3QiLCJfdGhpczIiLCJjcmVhdGUiLCJfY3JlYXRlTGF6eVN0cmVhbSIsInN0cmVhbSIsInNldFN0cmVhbSIsInByb21pc2UiLCJfY2FsbGVlIiwiX2NvbnRleHQiLCJfY29udGV4dDIiLCJyZWZyZXNoRGVsZWdhdGUiLCJib2R5UHJvbWlzZSIsIl9ib2R5MiIsInJlcXVlc3RUaW1lIiwicmVxdWVzdFByb21pc2UiLCJyZXNwb25zZSIsInJlc3BvbnNlVGltZSIsImVyciIsImJvZHkiLCJfY2FsbGVlJCIsIl9jb250ZXh0MyIsImdldFJlZnJlc2hEZWxlZ2F0ZSIsImlzUmVmcmVzaGluZyIsIndhaXRSZWZyZXNoIiwic2VudCIsImJlZm9yZVNlbmQiLCJlbWl0IiwiZGVidWciLCJfY29uY2F0SW5zdGFuY2VQcm9wZXJ0eSIsImNvbmNhdCIsIm1ldGhvZCIsImNhbGwiLCJ1cmwiLCJfRGF0ZSRub3ciLCJodHRwUmVxdWVzdCIsInQwIiwiZXJyb3IiLCJmaW5pc2giLCJTdHJpbmciLCJzdGF0dXNDb2RlIiwiaXNTZXNzaW9uRXhwaXJlZCIsInJlZnJlc2giLCJoZWFkZXJzIiwiaXNFcnJvclJlc3BvbnNlIiwiZ2V0RXJyb3IiLCJnZXRSZXNwb25zZUJvZHkiLCJfcmVmcmVzaERlbGVnYXRlIiwiX2NvbnRleHQ1IiwiYWNjZXNzVG9rZW4iLCJBdXRob3JpemF0aW9uIiwiX2NhbGxPcHRpb25zIiwiY2FsbE9wdGlvbnMiLCJfaSIsIl9PYmplY3Qka2V5cyIsIl9PYmplY3Qka2V5czIiLCJsZW5ndGgiLCJfY29udGV4dDQiLCJuYW1lIiwicHVzaCIsImpvaW4iLCJib2R5U2l6ZSIsImNhbm5vdEhhdmVCb2R5IiwiX2luY2x1ZGVzSW5zdGFuY2VQcm9wZXJ0eSIsImlzQnJvd3NlciIsIl9nbG9iYWxUaGlzIiwiZ2V0UmVzcG9uc2VDb250ZW50VHlwZSIsIl9wYXJzZVJlc3BvbnNlQm9keSIsIl9jYWxsZWUyIiwiY29udGVudFR5cGUiLCJwYXJzZUJvZHkiLCJfY29udGV4dDYiLCJfY2FsbGVlMiQiLCJfY29udGV4dDciLCJ0ZXN0IiwibWVzc2FnZSIsInBhcnNlUmVzcG9uc2VCb2R5IiwiX3gyIiwiX2dldFJlc3BvbnNlQm9keSIsIl9jYWxsZWUzIiwiX2NhbGxlZTMkIiwiX2NvbnRleHQ4IiwiaGFzRXJyb3JJblJlc3BvbnNlQm9keSIsIkh0dHBBcGlFcnJvciIsIl94MyIsInJlc3BvbnNlc1RvU2tpcCIsIl9pMiIsIl9yZXNwb25zZXNUb1NraXAiLCJfY29udGV4dDkiLCJwIiwiX2JvZHkiLCJwYXJzZUVycm9yIiwiZXJyb3JzIiwiRXJyb3JzIiwiRXJyb3IiLCJfZ2V0RXJyb3IiLCJfY2FsbGVlNCIsIl9jYWxsZWU0JCIsIl9jb250ZXh0MTAiLCJ0MSIsInQyIiwidDMiLCJfQXJyYXkkaXNBcnJheSIsIl90eXBlb2YiLCJlcnJvckNvZGUiLCJfeDQiLCJfeDUiLCJfZGVmaW5lUHJvcGVydHkiLCJfRXJyb3IiLCJkYXRhIiwiX3RoaXMzIiwiZ2V0IiwiX3dyYXBOYXRpdmVTdXBlciJdLCJzb3VyY2VzIjpbIi4uL3NyYy9odHRwLWFwaS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqXG4gKi9cbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQgeG1sMmpzIGZyb20gJ3htbDJqcyc7XG5pbXBvcnQgeyBMb2dnZXIsIGdldExvZ2dlciB9IGZyb20gJy4vdXRpbC9sb2dnZXInO1xuaW1wb3J0IHsgU3RyZWFtUHJvbWlzZSB9IGZyb20gJy4vdXRpbC9wcm9taXNlJztcbmltcG9ydCBDb25uZWN0aW9uIGZyb20gJy4vY29ubmVjdGlvbic7XG5pbXBvcnQgVHJhbnNwb3J0IGZyb20gJy4vdHJhbnNwb3J0JztcbmltcG9ydCB7IHBhcnNlQ1NWIH0gZnJvbSAnLi9jc3YnO1xuaW1wb3J0IHtcbiAgSHR0cFJlcXVlc3QsXG4gIEh0dHBSZXF1ZXN0T3B0aW9ucyxcbiAgSHR0cFJlc3BvbnNlLFxuICBPcHRpb25hbCxcbiAgU2NoZW1hLFxufSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IGNyZWF0ZUxhenlTdHJlYW0gfSBmcm9tICcuL3V0aWwvc3RyZWFtJztcbmltcG9ydCB7IGdldEJvZHlTaXplIH0gZnJvbSAnLi91dGlsL2dldC1ib2R5LXNpemUnO1xuXG4vKiogQHByaXZhdGUgKi9cbmZ1bmN0aW9uIHBhcnNlSlNPTihzdHI6IHN0cmluZykge1xuICByZXR1cm4gSlNPTi5wYXJzZShzdHIpO1xufVxuXG4vKiogQHByaXZhdGUgKi9cbmFzeW5jIGZ1bmN0aW9uIHBhcnNlWE1MKHN0cjogc3RyaW5nKSB7XG4gIHJldHVybiB4bWwyanMucGFyc2VTdHJpbmdQcm9taXNlKHN0ciwgeyBleHBsaWNpdEFycmF5OiBmYWxzZSB9KTtcbn1cblxuLyoqIEBwcml2YXRlICovXG5mdW5jdGlvbiBwYXJzZVRleHQoc3RyOiBzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cjtcbn1cblxuLyoqXG4gKiBIVFRQIGJhc2VkIEFQSSBjbGFzcyB3aXRoIGF1dGhvcml6YXRpb24gaG9va1xuICovXG5leHBvcnQgY2xhc3MgSHR0cEFwaTxTIGV4dGVuZHMgU2NoZW1hPiBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIHN0YXRpYyBfbG9nZ2VyID0gZ2V0TG9nZ2VyKCdodHRwLWFwaScpO1xuXG4gIF9jb25uOiBDb25uZWN0aW9uPFM+O1xuICBfbG9nZ2VyOiBMb2dnZXI7XG4gIF90cmFuc3BvcnQ6IFRyYW5zcG9ydDtcbiAgX3Jlc3BvbnNlVHlwZTogc3RyaW5nIHwgdm9pZDtcbiAgX25vQ29udGVudFJlc3BvbnNlOiBzdHJpbmcgfCB2b2lkO1xuICBfb3B0aW9uczogSHR0cFJlcXVlc3RPcHRpb25zO1xuXG4gIGNvbnN0cnVjdG9yKGNvbm46IENvbm5lY3Rpb248Uz4sIG9wdGlvbnM6IGFueSkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5fY29ubiA9IGNvbm47XG4gICAgdGhpcy5fbG9nZ2VyID0gY29ubi5fbG9nTGV2ZWxcbiAgICAgID8gSHR0cEFwaS5fbG9nZ2VyLmNyZWF0ZUluc3RhbmNlKGNvbm4uX2xvZ0xldmVsKVxuICAgICAgOiBIdHRwQXBpLl9sb2dnZXI7XG4gICAgdGhpcy5fcmVzcG9uc2VUeXBlID0gb3B0aW9ucy5yZXNwb25zZVR5cGU7XG4gICAgdGhpcy5fdHJhbnNwb3J0ID0gb3B0aW9ucy50cmFuc3BvcnQgfHwgY29ubi5fdHJhbnNwb3J0O1xuICAgIHRoaXMuX25vQ29udGVudFJlc3BvbnNlID0gb3B0aW9ucy5ub0NvbnRlbnRSZXNwb25zZTtcbiAgICB0aGlzLl9vcHRpb25zID0gb3B0aW9ucztcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsb3V0IHRvIEFQSSBlbmRwb2ludCB1c2luZyBodHRwXG4gICAqL1xuICByZXF1ZXN0PFIgPSB1bmtub3duPihyZXF1ZXN0OiBIdHRwUmVxdWVzdCk6IFN0cmVhbVByb21pc2U8Uj4ge1xuICAgIHJldHVybiBTdHJlYW1Qcm9taXNlLmNyZWF0ZTxSPigoKSA9PiB7XG4gICAgICBjb25zdCB7IHN0cmVhbSwgc2V0U3RyZWFtIH0gPSBjcmVhdGVMYXp5U3RyZWFtKCk7XG4gICAgICBjb25zdCBwcm9taXNlID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgcmVmcmVzaERlbGVnYXRlID0gdGhpcy5nZXRSZWZyZXNoRGVsZWdhdGUoKTtcbiAgICAgICAgLyogVE9ETyBkZWNpZGUgcmVtb3ZlIG9yIG5vdCB0aGlzIHNlY3Rpb24gKi9cbiAgICAgICAgLypcbiAgICAgICAgLy8gcmVtZW1iZXIgcHJldmlvdXMgaW5zdGFuY2UgdXJsIGluIGNhc2UgaXQgY2hhbmdlcyBhZnRlciBhIHJlZnJlc2hcbiAgICAgICAgY29uc3QgbGFzdEluc3RhbmNlVXJsID0gY29ubi5pbnN0YW5jZVVybDtcblxuICAgICAgICAvLyBjaGVjayB0byBzZWUgaWYgdGhlIHRva2VuIHJlZnJlc2ggaGFzIGNoYW5nZWQgdGhlIGluc3RhbmNlIHVybFxuICAgICAgICBpZihsYXN0SW5zdGFuY2VVcmwgIT09IGNvbm4uaW5zdGFuY2VVcmwpe1xuICAgICAgICAgIC8vIGlmIHRoZSBpbnN0YW5jZSB1cmwgaGFzIGNoYW5nZWRcbiAgICAgICAgICAvLyB0aGVuIHJlcGxhY2UgdGhlIGN1cnJlbnQgcmVxdWVzdCB1cmxzIGluc3RhbmNlIHVybCBmcmFnbWVudFxuICAgICAgICAgIC8vIHdpdGggdGhlIHVwZGF0ZWQgaW5zdGFuY2UgdXJsXG4gICAgICAgICAgcmVxdWVzdC51cmwgPSByZXF1ZXN0LnVybC5yZXBsYWNlKGxhc3RJbnN0YW5jZVVybCxjb25uLmluc3RhbmNlVXJsKTtcbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICBpZiAocmVmcmVzaERlbGVnYXRlICYmIHJlZnJlc2hEZWxlZ2F0ZS5pc1JlZnJlc2hpbmcoKSkge1xuICAgICAgICAgIGF3YWl0IHJlZnJlc2hEZWxlZ2F0ZS53YWl0UmVmcmVzaCgpO1xuICAgICAgICAgIGNvbnN0IGJvZHlQcm9taXNlID0gdGhpcy5yZXF1ZXN0KHJlcXVlc3QpO1xuICAgICAgICAgIHNldFN0cmVhbShib2R5UHJvbWlzZS5zdHJlYW0oKSk7XG4gICAgICAgICAgY29uc3QgYm9keSA9IGF3YWl0IGJvZHlQcm9taXNlO1xuICAgICAgICAgIHJldHVybiBib2R5O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaG9vayBiZWZvcmUgc2VuZGluZ1xuICAgICAgICB0aGlzLmJlZm9yZVNlbmQocmVxdWVzdCk7XG5cbiAgICAgICAgdGhpcy5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCk7XG4gICAgICAgIHRoaXMuX2xvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICBgPHJlcXVlc3Q+IG1ldGhvZD0ke3JlcXVlc3QubWV0aG9kfSwgdXJsPSR7cmVxdWVzdC51cmx9YCxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCByZXF1ZXN0UHJvbWlzZSA9IHRoaXMuX3RyYW5zcG9ydC5odHRwUmVxdWVzdChcbiAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgIHRoaXMuX29wdGlvbnMsXG4gICAgICAgICk7XG5cbiAgICAgICAgc2V0U3RyZWFtKHJlcXVlc3RQcm9taXNlLnN0cmVhbSgpKTtcblxuICAgICAgICBsZXQgcmVzcG9uc2U6IEh0dHBSZXNwb25zZSB8IHZvaWQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0UHJvbWlzZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgdGhpcy5fbG9nZ2VyLmVycm9yKGVycik7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlVGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgdGhpcy5fbG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgYGVsYXBzZWQgdGltZTogJHtyZXNwb25zZVRpbWUgLSByZXF1ZXN0VGltZX0gbXNlY2AsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXJlc3BvbnNlKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2xvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICBgPHJlc3BvbnNlPiBzdGF0dXM9JHtTdHJpbmcocmVzcG9uc2Uuc3RhdHVzQ29kZSl9LCB1cmw9JHtcbiAgICAgICAgICAgIHJlcXVlc3QudXJsXG4gICAgICAgICAgfWAsXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZW1pdCgncmVzcG9uc2UnLCByZXNwb25zZSk7XG4gICAgICAgIC8vIFJlZnJlc2ggdG9rZW4gaWYgc2Vzc2lvbiBoYXMgYmVlbiBleHBpcmVkIGFuZCByZXF1aXJlcyBhdXRoZW50aWNhdGlvblxuICAgICAgICAvLyB3aGVuIHNlc3Npb24gcmVmcmVzaCBkZWxlZ2F0ZSBpcyBhdmFpbGFibGVcbiAgICAgICAgaWYgKHRoaXMuaXNTZXNzaW9uRXhwaXJlZChyZXNwb25zZSkgJiYgcmVmcmVzaERlbGVnYXRlKSB7XG4gICAgICAgICAgYXdhaXQgcmVmcmVzaERlbGVnYXRlLnJlZnJlc2gocmVxdWVzdFRpbWUpO1xuICAgICAgICAgIC8qIHJlbW92ZSB0aGUgYGNvbnRlbnQtbGVuZ3RoYCBoZWFkZXIgYWZ0ZXIgdG9rZW4gcmVmcmVzaFxuICAgICAgICAgICAqXG4gICAgICAgICAgICogU09BUCByZXF1ZXN0cyBpbmNsdWRlIHRoZSBhY2Nlc3MgdG9rZW4gdGhlaXIgdGhlIGJvZHksXG4gICAgICAgICAgICogaWYgdGhlIGZpcnN0IHJlcSBoYWQgYW4gaW52YWxpZCB0b2tlbiBhbmQganNmb3JjZSBzdWNjZXNzZnVsbHlcbiAgICAgICAgICAgKiByZWZyZXNoZWQgaXQgd2UgbmVlZCB0byByZW1vdmUgdGhlIGBjb250ZW50LWxlbmd0aGAgaGVhZGVyXG4gICAgICAgICAgICogc28gdGhhdCBpdCBnZXQncyByZS1jYWxjdWxhdGVkIGFnYWluIHdpdGggdGhlIG5ldyBib2R5LlxuICAgICAgICAgICAqXG4gICAgICAgICAgICogUkVTVCByZXF1ZXN0IGFyZW4ndCBhZmZlY3RlZCBieSB0aGlzIGJlY2F1c2UgdGhlIGFjY2VzcyB0b2tlblxuICAgICAgICAgICAqIGlzIHNlbnQgdmlhIEhUVFAgaGVhZGVyc1xuICAgICAgICAgICAqXG4gICAgICAgICAgICogYF9tZXNzYWdlYCBpcyBvbmx5IHByZXNlbnQgaW4gU09BUCByZXF1ZXN0c1xuICAgICAgICAgICAqL1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICdfbWVzc2FnZScgaW4gcmVxdWVzdCAmJlxuICAgICAgICAgICAgcmVxdWVzdC5oZWFkZXJzICYmXG4gICAgICAgICAgICAnY29udGVudC1sZW5ndGgnIGluIHJlcXVlc3QuaGVhZGVyc1xuICAgICAgICAgICkge1xuICAgICAgICAgICAgZGVsZXRlIHJlcXVlc3QuaGVhZGVyc1snY29udGVudC1sZW5ndGgnXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMucmVxdWVzdChyZXF1ZXN0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc0Vycm9yUmVzcG9uc2UocmVzcG9uc2UpKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gYXdhaXQgdGhpcy5nZXRFcnJvcihyZXNwb25zZSk7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJvZHkgPSBhd2FpdCB0aGlzLmdldFJlc3BvbnNlQm9keShyZXNwb25zZSk7XG4gICAgICAgIHJldHVybiBib2R5O1xuICAgICAgfSkoKTtcbiAgICAgIHJldHVybiB7IHN0cmVhbSwgcHJvbWlzZSB9O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIGdldFJlZnJlc2hEZWxlZ2F0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fY29ubi5fcmVmcmVzaERlbGVnYXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIGJlZm9yZVNlbmQocmVxdWVzdDogSHR0cFJlcXVlc3QpIHtcbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1wYXJhbS1yZWFzc2lnbiAqL1xuICAgIGNvbnN0IGhlYWRlcnMgPSByZXF1ZXN0LmhlYWRlcnMgfHwge307XG4gICAgaWYgKHRoaXMuX2Nvbm4uYWNjZXNzVG9rZW4pIHtcbiAgICAgIGhlYWRlcnMuQXV0aG9yaXphdGlvbiA9IGBCZWFyZXIgJHt0aGlzLl9jb25uLmFjY2Vzc1Rva2VufWA7XG4gICAgfVxuICAgIGlmICh0aGlzLl9jb25uLl9jYWxsT3B0aW9ucykge1xuICAgICAgY29uc3QgY2FsbE9wdGlvbnMgPSBbXTtcbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyh0aGlzLl9jb25uLl9jYWxsT3B0aW9ucykpIHtcbiAgICAgICAgY2FsbE9wdGlvbnMucHVzaChgJHtuYW1lfT0ke3RoaXMuX2Nvbm4uX2NhbGxPcHRpb25zW25hbWVdfWApO1xuICAgICAgfVxuICAgICAgaGVhZGVyc1snU2ZvcmNlLUNhbGwtT3B0aW9ucyddID0gY2FsbE9wdGlvbnMuam9pbignLCAnKTtcbiAgICB9XG5cbiAgICBjb25zdCBib2R5U2l6ZSA9IGdldEJvZHlTaXplKHJlcXVlc3QuYm9keSwgaGVhZGVycyk7XG5cbiAgICBjb25zdCBjYW5ub3RIYXZlQm9keSA9IFsnR0VUJywgJ0hFQUQnLCAnT1BUSU9OUyddLmluY2x1ZGVzKHJlcXVlc3QubWV0aG9kKTtcblxuICAgIC8vIERvbid0IHNldCBjb250ZW50LWxlbmd0aCBpbiBicm93c2VycyBhcyBpdCdzIG5vdCBhbGxvd2VkXG4gICAgY29uc3QgaXNCcm93c2VyID0gJ3dpbmRvdycgaW4gZ2xvYmFsVGhpcyB8fCAnc2VsZicgaW4gZ2xvYmFsVGhpcztcblxuICAgIGlmIChcbiAgICAgICFpc0Jyb3dzZXIgJiYgLy8gRG9uJ3Qgc2V0IGNvbnRlbnQtbGVuZ3RoIGluIGJyb3dzZXJzIGFzIGl0J3Mgbm90IGFsbG93ZWRcbiAgICAgICFjYW5ub3RIYXZlQm9keSAmJlxuICAgICAgISFyZXF1ZXN0LmJvZHkgJiZcbiAgICAgICEoJ3RyYW5zZmVyLWVuY29kaW5nJyBpbiBoZWFkZXJzKSAmJlxuICAgICAgISgnY29udGVudC1sZW5ndGgnIGluIGhlYWRlcnMpICYmXG4gICAgICAhIWJvZHlTaXplXG4gICAgKSB7XG4gICAgICB0aGlzLl9sb2dnZXIuZGVidWcoXG4gICAgICAgIGBtaXNzaW5nICdjb250ZW50LWxlbmd0aCcgaGVhZGVyLCBzZXR0aW5nIGl0IHRvOiAke2JvZHlTaXplfWAsXG4gICAgICApO1xuICAgICAgaGVhZGVyc1snY29udGVudC1sZW5ndGgnXSA9IFN0cmluZyhib2R5U2l6ZSk7XG4gICAgfVxuICAgIHJlcXVlc3QuaGVhZGVycyA9IGhlYWRlcnM7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZWN0IHJlc3BvbnNlIGNvbnRlbnQgbWltZS10eXBlXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIGdldFJlc3BvbnNlQ29udGVudFR5cGUocmVzcG9uc2U6IEh0dHBSZXNwb25zZSk6IE9wdGlvbmFsPHN0cmluZz4ge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLl9yZXNwb25zZVR5cGUgfHxcbiAgICAgIChyZXNwb25zZS5oZWFkZXJzICYmIHJlc3BvbnNlLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvcmVxdWlyZS1hd2FpdFxuICBhc3luYyBwYXJzZVJlc3BvbnNlQm9keShyZXNwb25zZTogSHR0cFJlc3BvbnNlKSB7XG4gICAgY29uc3QgY29udGVudFR5cGUgPSB0aGlzLmdldFJlc3BvbnNlQ29udGVudFR5cGUocmVzcG9uc2UpIHx8ICcnO1xuICAgIGNvbnN0IHBhcnNlQm9keSA9IC9eKHRleHR8YXBwbGljYXRpb24pXFwveG1sKDt8JCkvLnRlc3QoY29udGVudFR5cGUpXG4gICAgICA/IHBhcnNlWE1MXG4gICAgICA6IC9eYXBwbGljYXRpb25cXC9qc29uKDt8JCkvLnRlc3QoY29udGVudFR5cGUpXG4gICAgICA/IHBhcnNlSlNPTlxuICAgICAgOiAvXnRleHRcXC9jc3YoO3wkKS8udGVzdChjb250ZW50VHlwZSlcbiAgICAgID8gcGFyc2VDU1ZcbiAgICAgIDogcGFyc2VUZXh0O1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gcGFyc2VCb2R5KHJlc3BvbnNlLmJvZHkpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIFRPRE8obmV4dCBtYWpvcik6IHdlIGNvdWxkIHRocm93IGEgbmV3IFwiaW52YWxpZCByZXNwb25zZSBib2R5XCIgZXJyb3IgaW5zdGVhZC5cbiAgICAgIHRoaXMuX2xvZ2dlci5kZWJ1ZyhcbiAgICAgICAgYEZhaWxlZCB0byBwYXJzZSBib2R5IG9mIGNvbnRlbnQtdHlwZTogJHtjb250ZW50VHlwZX0uIEVycm9yOiAke1xuICAgICAgICAgIChlIGFzIEVycm9yKS5tZXNzYWdlXG4gICAgICAgIH1gLFxuICAgICAgKTtcbiAgICAgIHJldHVybiByZXNwb25zZS5ib2R5O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcmVzcG9uc2UgYm9keVxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuICBhc3luYyBnZXRSZXNwb25zZUJvZHkocmVzcG9uc2U6IEh0dHBSZXNwb25zZSkge1xuICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlID09PSAyMDQpIHtcbiAgICAgIC8vIE5vIENvbnRlbnRcbiAgICAgIHJldHVybiB0aGlzLl9ub0NvbnRlbnRSZXNwb25zZTtcbiAgICB9XG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHRoaXMucGFyc2VSZXNwb25zZUJvZHkocmVzcG9uc2UpO1xuICAgIGxldCBlcnI7XG4gICAgaWYgKHRoaXMuaGFzRXJyb3JJblJlc3BvbnNlQm9keShib2R5KSkge1xuICAgICAgZXJyID0gYXdhaXQgdGhpcy5nZXRFcnJvcihyZXNwb25zZSwgYm9keSk7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlID09PSAzMDApIHtcbiAgICAgIC8vIE11bHRpcGxlIENob2ljZXNcbiAgICAgIHRocm93IG5ldyBIdHRwQXBpRXJyb3IoXG4gICAgICAgICdNdWx0aXBsZSByZWNvcmRzIGZvdW5kJyxcbiAgICAgICAgJ01VTFRJUExFX0NIT0lDRVMnLFxuICAgICAgICBib2R5LFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGJvZHk7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZWN0IHNlc3Npb24gZXhwaXJ5XG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIGlzU2Vzc2lvbkV4cGlyZWQocmVzcG9uc2U6IEh0dHBSZXNwb25zZSkge1xuICAgIC8vIFJFU1QgQVBJIHN0YXR1cyBjb2RlczogaHR0cHM6Ly9kZXZlbG9wZXIuc2FsZXNmb3JjZS5jb20vZG9jcy9hdGxhcy5lbi11cy5hcGlfcmVzdC5tZXRhL2FwaV9yZXN0L2Vycm9yY29kZXMuaHRtXG4gICAgLy9cbiAgICAvLyBcIjQwMSAtIFRoZSBzZXNzaW9uIElEIG9yIE9BdXRoIHRva2VuIHVzZWQgaGFzIGV4cGlyZWQgb3IgaXMgaW52YWxpZC4gVGhlIHJlc3BvbnNlIGJvZHkgY29udGFpbnMgdGhlIG1lc3NhZ2UgYW5kIGVycm9yQ29kZS5cIlxuICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlID09PSA0MDEpIHtcbiAgICAgIC8vIEtub3duIGxpc3Qgb2YgNDAxIHJlc3BvbnNlcyB0aGF0IHNob3VsZG4ndCBiZSBjb25zaWRlcmVkIGFzIFwic2Vzc2lvbiBleHBpcmVkXCIuXG4gICAgICAvL1xuICAgICAgLy8gVGhlc2UgdXN1YWx5IGNvbWUgZnJvbSBhbiBDQS9FQ0EsIE9BdXRoLCBJUCByZXN0cmljdGlvbiBjaGFuZ2UgaW4gdGhlIG9yZyB0aGF0IGJsb2NrIGNvbm5lY3Rpb25zLCB3ZSBuZWVkIHRvIHNraXAgdGhlc2VcbiAgICAgIC8vIG9yZyBqc2ZvcmNlIHdpbGwgZW50ZXIgaW50byBhbiBpbmZpbml0ZSBsb29wIHRyeWluZyB0byBnZXQgYSB2YWxpZCB0b2tlbi5cbiAgICAgIGNvbnN0IHJlc3BvbnNlc1RvU2tpcCA9IFsnQ29ubmVjdGVkIGFwcCBpcyBub3QgYXR0YWNoZWQgdG8gQWdlbnQnLCAnVGhpcyBzZXNzaW9uIGlzIG5vdCB2YWxpZCBmb3IgdXNlIHdpdGggdGhlIFJFU1QgQVBJJ107XG4gICAgICBmb3IgKGNvbnN0IHAgb2YgcmVzcG9uc2VzVG9Ta2lwKSB7XG4gICAgICAgIGlmIChyZXNwb25zZS5ib2R5LmluY2x1ZGVzKHApKSByZXR1cm4gZmFsc2VcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlY3QgZXJyb3IgcmVzcG9uc2VcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgaXNFcnJvclJlc3BvbnNlKHJlc3BvbnNlOiBIdHRwUmVzcG9uc2UpIHtcbiAgICByZXR1cm4gcmVzcG9uc2Uuc3RhdHVzQ29kZSA+PSA0MDA7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZWN0IGVycm9yIGluIHJlc3BvbnNlIGJvZHlcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgaGFzRXJyb3JJblJlc3BvbnNlQm9keShfYm9keTogT3B0aW9uYWw8c3RyaW5nPikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzaW5nIGVycm9yIG1lc3NhZ2UgaW4gcmVzcG9uc2VcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgcGFyc2VFcnJvcihib2R5OiBhbnkpIHtcbiAgICBjb25zdCBlcnJvcnMgPSBib2R5O1xuXG4gICAgLy8gWE1MIHJlc3BvbnNlXG4gICAgaWYgKGVycm9ycy5FcnJvcnMpIHtcbiAgICAgIHJldHVybiBlcnJvcnMuRXJyb3JzLkVycm9yO1xuICAgIH1cblxuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGVycm9yIG1lc3NhZ2UgaW4gcmVzcG9uc2VcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgYXN5bmMgZ2V0RXJyb3IocmVzcG9uc2U6IEh0dHBSZXNwb25zZSwgYm9keT86IGFueSk6IFByb21pc2U8RXJyb3I+IHtcbiAgICBsZXQgZXJyb3I7XG4gICAgdHJ5IHtcbiAgICAgIGVycm9yID0gdGhpcy5wYXJzZUVycm9yKGJvZHkgfHwgKGF3YWl0IHRoaXMucGFyc2VSZXNwb25zZUJvZHkocmVzcG9uc2UpKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUgbm8tZW1wdHlcbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShlcnJvcikpIHtcbiAgICAgIGlmIChlcnJvci5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgZXJyb3IgPSBlcnJvclswXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBuZXcgSHR0cEFwaUVycm9yKFxuICAgICAgICAgIGBNdWx0aXBsZSBlcnJvcnMgcmV0dXJuZWQuXG4gIENoZWNrIFxcYGVycm9yLmRhdGFcXGAgZm9yIHRoZSBlcnJvciBkZXRhaWxzYCxcbiAgICAgICAgICAnTVVMVElQTEVfQVBJX0VSUk9SUycsXG4gICAgICAgICAgZXJyb3IsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZXJyb3IgPVxuICAgICAgdHlwZW9mIGVycm9yID09PSAnb2JqZWN0JyAmJlxuICAgICAgZXJyb3IgIT09IG51bGwgJiZcbiAgICAgIHR5cGVvZiBlcnJvci5tZXNzYWdlID09PSAnc3RyaW5nJ1xuICAgICAgICA/IGVycm9yXG4gICAgICAgIDoge1xuICAgICAgICAgICAgZXJyb3JDb2RlOiBgRVJST1JfSFRUUF8ke3Jlc3BvbnNlLnN0YXR1c0NvZGV9YCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IHJlc3BvbnNlLmJvZHksXG4gICAgICAgICAgfTtcblxuICAgIGlmIChyZXNwb25zZS5oZWFkZXJzWydjb250ZW50LXR5cGUnXSA9PT0gJ3RleHQvaHRtbCcpIHtcbiAgICAgIHRoaXMuX2xvZ2dlci5kZWJ1ZyhgaHRtbCByZXNwb25zZS5ib2R5OiAke3Jlc3BvbnNlLmJvZHl9YCk7XG4gICAgICByZXR1cm4gbmV3IEh0dHBBcGlFcnJvcihcbiAgICAgICAgYEhUVFAgcmVzcG9uc2UgY29udGFpbnMgaHRtbCBjb250ZW50LlxuQ2hlY2sgdGhhdCB0aGUgb3JnIGV4aXN0cyBhbmQgY2FuIGJlIHJlYWNoZWQuXG5TZWUgXFxgZXJyb3IuZGF0YVxcYCBmb3IgdGhlIGZ1bGwgaHRtbCByZXNwb25zZS5gLFxuICAgICAgICBlcnJvci5lcnJvckNvZGUsXG4gICAgICAgIGVycm9yLm1lc3NhZ2UsXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBlcnJvciBpbnN0YW5jZW9mIEh0dHBBcGlFcnJvclxuICAgICAgPyBlcnJvclxuICAgICAgOiBuZXcgSHR0cEFwaUVycm9yKGVycm9yLm1lc3NhZ2UsIGVycm9yLmVycm9yQ29kZSwgZXJyb3IpO1xuICB9XG59XG5cbi8qKlxuICpcbiAqL1xuY2xhc3MgSHR0cEFwaUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAvKipcbiAgICogVGhpcyBjb250YWlucyBlcnJvci1zcGVjaWZpYyBkZXRhaWxzLCB1c3VhbGx5IHJldHVybmVkIGZyb20gdGhlIEFQSS5cbiAgICovXG4gIGRhdGE6IGFueTtcbiAgZXJyb3JDb2RlOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nLCBlcnJvckNvZGU/OiBzdHJpbmcgfCB1bmRlZmluZWQsIGRhdGE/OiBhbnkpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSBlcnJvckNvZGUgfHwgdGhpcy5uYW1lO1xuICAgIHRoaXMuZXJyb3JDb2RlID0gdGhpcy5uYW1lO1xuICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyB3aWxsIGJlIHJlbW92ZWQgaW4gdGhlIG5leHQgbWFqb3IgKHY0KVxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgYGVycm9yLmRhdGFgIGluc3RlYWRcbiAgICovXG4gIGdldCBjb250ZW50KCkge1xuICAgIHJldHVybiB0aGlzLmRhdGE7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSHR0cEFwaTtcbmV4cG9ydCBjb25zdCBpc0Jyb3dzZXIgPSAnd2luZG93JyBpbiBnbG9iYWxUaGlzIHx8ICdzZWxmJyBpbiBnbG9iYWxUaGlzO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQSxZQUFZLFFBQVEsUUFBUTtBQUNyQyxPQUFPQyxNQUFNLE1BQU0sUUFBUTtBQUMzQixTQUFpQkMsU0FBUyxRQUFRLGVBQWU7QUFDakQsU0FBU0MsYUFBYSxRQUFRLGdCQUFnQjtBQUc5QyxTQUFTQyxRQUFRLFFBQVEsT0FBTztBQVFoQyxTQUFTQyxnQkFBZ0IsUUFBUSxlQUFlO0FBQ2hELFNBQVNDLFdBQVcsUUFBUSxzQkFBc0I7O0FBRWxEO0FBQ0EsU0FBU0MsU0FBU0EsQ0FBQ0MsR0FBVyxFQUFFO0VBQzlCLE9BQU9DLElBQUksQ0FBQ0MsS0FBSyxDQUFDRixHQUFHLENBQUM7QUFDeEI7O0FBRUE7QUFBQSxTQUNlRyxRQUFRQSxDQUFBQyxFQUFBO0VBQUEsT0FBQUMsU0FBQSxDQUFBQyxLQUFBLE9BQUFDLFNBQUE7QUFBQTtBQUl2QjtBQUFBLFNBQUFGLFVBQUE7RUFBQUEsU0FBQSxHQUFBRyxp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