jsforce
Version:
Salesforce API Library for JavaScript
505 lines (489 loc) • 52.4 kB
JavaScript
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 _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 { 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);
if (!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) {
var _context9;
// TODO:
// The connected app msg only applies to Agent API requests, we should move this to a separate SFAP/Agent API class later.
return response.statusCode === 401 && !_includesInstanceProperty(_context9 = response.body).call(_context9, 'Connected app is not attached to Agent');
}
/**
* 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;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJFdmVudEVtaXR0ZXIiLCJ4bWwyanMiLCJnZXRMb2dnZXIiLCJTdHJlYW1Qcm9taXNlIiwicGFyc2VDU1YiLCJjcmVhdGVMYXp5U3RyZWFtIiwiZ2V0Qm9keVNpemUiLCJwYXJzZUpTT04iLCJzdHIiLCJKU09OIiwicGFyc2UiLCJwYXJzZVhNTCIsIl94IiwiX3BhcnNlWE1MIiwiYXBwbHkiLCJhcmd1bWVudHMiLCJfYXN5bmNUb0dlbmVyYXRvciIsIl9yZWdlbmVyYXRvclJ1bnRpbWUiLCJtYXJrIiwiX2NhbGxlZTUiLCJ3cmFwIiwiX2NhbGxlZTUkIiwiX2NvbnRleHQxMSIsInByZXYiLCJuZXh0IiwiYWJydXB0IiwicGFyc2VTdHJpbmdQcm9taXNlIiwiZXhwbGljaXRBcnJheSIsInN0b3AiLCJwYXJzZVRleHQiLCJIdHRwQXBpIiwiX0V2ZW50RW1pdHRlciIsImNvbm4iLCJvcHRpb25zIiwiX3RoaXMiLCJfY2xhc3NDYWxsQ2hlY2siLCJfY2FsbFN1cGVyIiwiX2Nvbm4iLCJfbG9nZ2VyIiwiX2xvZ0xldmVsIiwiY3JlYXRlSW5zdGFuY2UiLCJfcmVzcG9uc2VUeXBlIiwicmVzcG9uc2VUeXBlIiwiX3RyYW5zcG9ydCIsInRyYW5zcG9ydCIsIl9ub0NvbnRlbnRSZXNwb25zZSIsIm5vQ29udGVudFJlc3BvbnNlIiwiX29wdGlvbnMiLCJfaW5oZXJpdHMiLCJfY3JlYXRlQ2xhc3MiLCJrZXkiLCJ2YWx1ZSIsInJlcXVlc3QiLCJfdGhpczIiLCJjcmVhdGUiLCJfY3JlYXRlTGF6eVN0cmVhbSIsInN0cmVhbSIsInNldFN0cmVhbSIsInByb21pc2UiLCJfY2FsbGVlIiwiX2NvbnRleHQiLCJfY29udGV4dDIiLCJyZWZyZXNoRGVsZWdhdGUiLCJib2R5UHJvbWlzZSIsIl9ib2R5MiIsInJlcXVlc3RUaW1lIiwicmVxdWVzdFByb21pc2UiLCJyZXNwb25zZSIsInJlc3BvbnNlVGltZSIsImVyciIsImJvZHkiLCJfY2FsbGVlJCIsIl9jb250ZXh0MyIsImdldFJlZnJlc2hEZWxlZ2F0ZSIsImlzUmVmcmVzaGluZyIsIndhaXRSZWZyZXNoIiwic2VudCIsImJlZm9yZVNlbmQiLCJlbWl0IiwiZGVidWciLCJfY29uY2F0SW5zdGFuY2VQcm9wZXJ0eSIsImNvbmNhdCIsIm1ldGhvZCIsImNhbGwiLCJ1cmwiLCJfRGF0ZSRub3ciLCJodHRwUmVxdWVzdCIsInQwIiwiZXJyb3IiLCJmaW5pc2giLCJTdHJpbmciLCJzdGF0dXNDb2RlIiwiaXNTZXNzaW9uRXhwaXJlZCIsInJlZnJlc2giLCJoZWFkZXJzIiwiaXNFcnJvclJlc3BvbnNlIiwiZ2V0RXJyb3IiLCJnZXRSZXNwb25zZUJvZHkiLCJfcmVmcmVzaERlbGVnYXRlIiwiX2NvbnRleHQ1IiwiYWNjZXNzVG9rZW4iLCJBdXRob3JpemF0aW9uIiwiX2NhbGxPcHRpb25zIiwiY2FsbE9wdGlvbnMiLCJfaSIsIl9PYmplY3Qka2V5cyIsIl9PYmplY3Qka2V5czIiLCJsZW5ndGgiLCJfY29udGV4dDQiLCJuYW1lIiwicHVzaCIsImpvaW4iLCJib2R5U2l6ZSIsImNhbm5vdEhhdmVCb2R5IiwiX2luY2x1ZGVzSW5zdGFuY2VQcm9wZXJ0eSIsImdldFJlc3BvbnNlQ29udGVudFR5cGUiLCJfcGFyc2VSZXNwb25zZUJvZHkiLCJfY2FsbGVlMiIsImNvbnRlbnRUeXBlIiwicGFyc2VCb2R5IiwiX2NvbnRleHQ2IiwiX2NhbGxlZTIkIiwiX2NvbnRleHQ3IiwidGVzdCIsIm1lc3NhZ2UiLCJwYXJzZVJlc3BvbnNlQm9keSIsIl94MiIsIl9nZXRSZXNwb25zZUJvZHkiLCJfY2FsbGVlMyIsIl9jYWxsZWUzJCIsIl9jb250ZXh0OCIsImhhc0Vycm9ySW5SZXNwb25zZUJvZHkiLCJIdHRwQXBpRXJyb3IiLCJfeDMiLCJfY29udGV4dDkiLCJfYm9keSIsInBhcnNlRXJyb3IiLCJlcnJvcnMiLCJFcnJvcnMiLCJFcnJvciIsIl9nZXRFcnJvciIsIl9jYWxsZWU0IiwiX2NhbGxlZTQkIiwiX2NvbnRleHQxMCIsInQxIiwidDIiLCJ0MyIsIl9BcnJheSRpc0FycmF5IiwiX3R5cGVvZiIsImVycm9yQ29kZSIsIl94NCIsIl94NSIsIl9kZWZpbmVQcm9wZXJ0eSIsIl9FcnJvciIsImRhdGEiLCJfdGhpczMiLCJnZXQiLCJfd3JhcE5hdGl2ZVN1cGVyIl0sInNvdXJjZXMiOlsiLi4vc3JjL2h0dHAtYXBpLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICpcbiAqL1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCB4bWwyanMgZnJvbSAneG1sMmpzJztcbmltcG9ydCB7IExvZ2dlciwgZ2V0TG9nZ2VyIH0gZnJvbSAnLi91dGlsL2xvZ2dlcic7XG5pbXBvcnQgeyBTdHJlYW1Qcm9taXNlIH0gZnJvbSAnLi91dGlsL3Byb21pc2UnO1xuaW1wb3J0IENvbm5lY3Rpb24gZnJvbSAnLi9jb25uZWN0aW9uJztcbmltcG9ydCBUcmFuc3BvcnQgZnJvbSAnLi90cmFuc3BvcnQnO1xuaW1wb3J0IHsgcGFyc2VDU1YgfSBmcm9tICcuL2Nzdic7XG5pbXBvcnQge1xuICBIdHRwUmVxdWVzdCxcbiAgSHR0cFJlcXVlc3RPcHRpb25zLFxuICBIdHRwUmVzcG9uc2UsXG4gIE9wdGlvbmFsLFxuICBTY2hlbWEsXG59IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgY3JlYXRlTGF6eVN0cmVhbSB9IGZyb20gJy4vdXRpbC9zdHJlYW0nO1xuaW1wb3J0IHsgZ2V0Qm9keVNpemUgfSBmcm9tICcuL3V0aWwvZ2V0LWJvZHktc2l6ZSc7XG5cbi8qKiBAcHJpdmF0ZSAqL1xuZnVuY3Rpb24gcGFyc2VKU09OKHN0cjogc3RyaW5nKSB7XG4gIHJldHVybiBKU09OLnBhcnNlKHN0cik7XG59XG5cbi8qKiBAcHJpdmF0ZSAqL1xuYXN5bmMgZnVuY3Rpb24gcGFyc2VYTUwoc3RyOiBzdHJpbmcpIHtcbiAgcmV0dXJuIHhtbDJqcy5wYXJzZVN0cmluZ1Byb21pc2Uoc3RyLCB7IGV4cGxpY2l0QXJyYXk6IGZhbHNlIH0pO1xufVxuXG4vKiogQHByaXZhdGUgKi9cbmZ1bmN0aW9uIHBhcnNlVGV4dChzdHI6IHN0cmluZykge1xuICByZXR1cm4gc3RyO1xufVxuXG4vKipcbiAqIEhUVFAgYmFzZWQgQVBJIGNsYXNzIHdpdGggYXV0aG9yaXphdGlvbiBob29rXG4gKi9cbmV4cG9ydCBjbGFzcyBIdHRwQXBpPFMgZXh0ZW5kcyBTY2hlbWE+IGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgc3RhdGljIF9sb2dnZXIgPSBnZXRMb2dnZXIoJ2h0dHAtYXBpJyk7XG5cbiAgX2Nvbm46IENvbm5lY3Rpb248Uz47XG4gIF9sb2dnZXI6IExvZ2dlcjtcbiAgX3RyYW5zcG9ydDogVHJhbnNwb3J0O1xuICBfcmVzcG9uc2VUeXBlOiBzdHJpbmcgfCB2b2lkO1xuICBfbm9Db250ZW50UmVzcG9uc2U6IHN0cmluZyB8IHZvaWQ7XG4gIF9vcHRpb25zOiBIdHRwUmVxdWVzdE9wdGlvbnM7XG5cbiAgY29uc3RydWN0b3IoY29ubjogQ29ubmVjdGlvbjxTPiwgb3B0aW9uczogYW55KSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLl9jb25uID0gY29ubjtcbiAgICB0aGlzLl9sb2dnZXIgPSBjb25uLl9sb2dMZXZlbFxuICAgICAgPyBIdHRwQXBpLl9sb2dnZXIuY3JlYXRlSW5zdGFuY2UoY29ubi5fbG9nTGV2ZWwpXG4gICAgICA6IEh0dHBBcGkuX2xvZ2dlcjtcbiAgICB0aGlzLl9yZXNwb25zZVR5cGUgPSBvcHRpb25zLnJlc3BvbnNlVHlwZTtcbiAgICB0aGlzLl90cmFuc3BvcnQgPSBvcHRpb25zLnRyYW5zcG9ydCB8fCBjb25uLl90cmFuc3BvcnQ7XG4gICAgdGhpcy5fbm9Db250ZW50UmVzcG9uc2UgPSBvcHRpb25zLm5vQ29udGVudFJlc3BvbnNlO1xuICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxvdXQgdG8gQVBJIGVuZHBvaW50IHVzaW5nIGh0dHBcbiAgICovXG4gIHJlcXVlc3Q8UiA9IHVua25vd24+KHJlcXVlc3Q6IEh0dHBSZXF1ZXN0KTogU3RyZWFtUHJvbWlzZTxSPiB7XG4gICAgcmV0dXJuIFN0cmVhbVByb21pc2UuY3JlYXRlPFI+KCgpID0+IHtcbiAgICAgIGNvbnN0IHsgc3RyZWFtLCBzZXRTdHJlYW0gfSA9IGNyZWF0ZUxhenlTdHJlYW0oKTtcbiAgICAgIGNvbnN0IHByb21pc2UgPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCByZWZyZXNoRGVsZWdhdGUgPSB0aGlzLmdldFJlZnJlc2hEZWxlZ2F0ZSgpO1xuICAgICAgICAvKiBUT0RPIGRlY2lkZSByZW1vdmUgb3Igbm90IHRoaXMgc2VjdGlvbiAqL1xuICAgICAgICAvKlxuICAgICAgICAvLyByZW1lbWJlciBwcmV2aW91cyBpbnN0YW5jZSB1cmwgaW4gY2FzZSBpdCBjaGFuZ2VzIGFmdGVyIGEgcmVmcmVzaFxuICAgICAgICBjb25zdCBsYXN0SW5zdGFuY2VVcmwgPSBjb25uLmluc3RhbmNlVXJsO1xuXG4gICAgICAgIC8vIGNoZWNrIHRvIHNlZSBpZiB0aGUgdG9rZW4gcmVmcmVzaCBoYXMgY2hhbmdlZCB0aGUgaW5zdGFuY2UgdXJsXG4gICAgICAgIGlmKGxhc3RJbnN0YW5jZVVybCAhPT0gY29ubi5pbnN0YW5jZVVybCl7XG4gICAgICAgICAgLy8gaWYgdGhlIGluc3RhbmNlIHVybCBoYXMgY2hhbmdlZFxuICAgICAgICAgIC8vIHRoZW4gcmVwbGFjZSB0aGUgY3VycmVudCByZXF1ZXN0IHVybHMgaW5zdGFuY2UgdXJsIGZyYWdtZW50XG4gICAgICAgICAgLy8gd2l0aCB0aGUgdXBkYXRlZCBpbnN0YW5jZSB1cmxcbiAgICAgICAgICByZXF1ZXN0LnVybCA9IHJlcXVlc3QudXJsLnJlcGxhY2UobGFzdEluc3RhbmNlVXJsLGNvbm4uaW5zdGFuY2VVcmwpO1xuICAgICAgICB9XG4gICAgICAgICovXG4gICAgICAgIGlmIChyZWZyZXNoRGVsZWdhdGUgJiYgcmVmcmVzaERlbGVnYXRlLmlzUmVmcmVzaGluZygpKSB7XG4gICAgICAgICAgYXdhaXQgcmVmcmVzaERlbGVnYXRlLndhaXRSZWZyZXNoKCk7XG4gICAgICAgICAgY29uc3QgYm9keVByb21pc2UgPSB0aGlzLnJlcXVlc3QocmVxdWVzdCk7XG4gICAgICAgICAgc2V0U3RyZWFtKGJvZHlQcm9taXNlLnN0cmVhbSgpKTtcbiAgICAgICAgICBjb25zdCBib2R5ID0gYXdhaXQgYm9keVByb21pc2U7XG4gICAgICAgICAgcmV0dXJuIGJvZHk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBob29rIGJlZm9yZSBzZW5kaW5nXG4gICAgICAgIHRoaXMuYmVmb3JlU2VuZChyZXF1ZXN0KTtcblxuICAgICAgICB0aGlzLmVtaXQoJ3JlcXVlc3QnLCByZXF1ZXN0KTtcbiAgICAgICAgdGhpcy5fbG9nZ2VyLmRlYnVnKFxuICAgICAgICAgIGA8cmVxdWVzdD4gbWV0aG9kPSR7cmVxdWVzdC5tZXRob2R9LCB1cmw9JHtyZXF1ZXN0LnVybH1gLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHJlcXVlc3RQcm9taXNlID0gdGhpcy5fdHJhbnNwb3J0Lmh0dHBSZXF1ZXN0KFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgdGhpcy5fb3B0aW9ucyxcbiAgICAgICAgKTtcblxuICAgICAgICBzZXRTdHJlYW0ocmVxdWVzdFByb21pc2Uuc3RyZWFtKCkpO1xuXG4gICAgICAgIGxldCByZXNwb25zZTogSHR0cFJlc3BvbnNlIHwgdm9pZDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3RQcm9taXNlO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aGlzLl9sb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgY29uc3QgcmVzcG9uc2VUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICB0aGlzLl9sb2dnZXIuZGVidWcoXG4gICAgICAgICAgICBgZWxhcHNlZCB0aW1lOiAke3Jlc3BvbnNlVGltZSAtIHJlcXVlc3RUaW1lfSBtc2VjYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fbG9nZ2VyLmRlYnVnKFxuICAgICAgICAgIGA8cmVzcG9uc2U+IHN0YXR1cz0ke1N0cmluZyhyZXNwb25zZS5zdGF0dXNDb2RlKX0sIHVybD0ke1xuICAgICAgICAgICAgcmVxdWVzdC51cmxcbiAgICAgICAgICB9YCxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5lbWl0KCdyZXNwb25zZScsIHJlc3BvbnNlKTtcbiAgICAgICAgLy8gUmVmcmVzaCB0b2tlbiBpZiBzZXNzaW9uIGhhcyBiZWVuIGV4cGlyZWQgYW5kIHJlcXVpcmVzIGF1dGhlbnRpY2F0aW9uXG4gICAgICAgIC8vIHdoZW4gc2Vzc2lvbiByZWZyZXNoIGRlbGVnYXRlIGlzIGF2YWlsYWJsZVxuICAgICAgICBpZiAodGhpcy5pc1Nlc3Npb25FeHBpcmVkKHJlc3BvbnNlKSAmJiByZWZyZXNoRGVsZWdhdGUpIHtcbiAgICAgICAgICBhd2FpdCByZWZyZXNoRGVsZWdhdGUucmVmcmVzaChyZXF1ZXN0VGltZSk7XG4gICAgICAgICAgLyogcmVtb3ZlIHRoZSBgY29udGVudC1sZW5ndGhgIGhlYWRlciBhZnRlciB0b2tlbiByZWZyZXNoXG4gICAgICAgICAgICpcbiAgICAgICAgICAgKiBTT0FQIHJlcXVlc3RzIGluY2x1ZGUgdGhlIGFjY2VzcyB0b2tlbiB0aGVpciB0aGUgYm9keSxcbiAgICAgICAgICAgKiBpZiB0aGUgZmlyc3QgcmVxIGhhZCBhbiBpbnZhbGlkIHRva2VuIGFuZCBqc2ZvcmNlIHN1Y2Nlc3NmdWxseVxuICAgICAgICAgICAqIHJlZnJlc2hlZCBpdCB3ZSBuZWVkIHRvIHJlbW92ZSB0aGUgYGNvbnRlbnQtbGVuZ3RoYCBoZWFkZXJcbiAgICAgICAgICAgKiBzbyB0aGF0IGl0IGdldCdzIHJlLWNhbGN1bGF0ZWQgYWdhaW4gd2l0aCB0aGUgbmV3IGJvZHkuXG4gICAgICAgICAgICpcbiAgICAgICAgICAgKiBSRVNUIHJlcXVlc3QgYXJlbid0IGFmZmVjdGVkIGJ5IHRoaXMgYmVjYXVzZSB0aGUgYWNjZXNzIHRva2VuXG4gICAgICAgICAgICogaXMgc2VudCB2aWEgSFRUUCBoZWFkZXJzXG4gICAgICAgICAgICpcbiAgICAgICAgICAgKiBgX21lc3NhZ2VgIGlzIG9ubHkgcHJlc2VudCBpbiBTT0FQIHJlcXVlc3RzXG4gICAgICAgICAgICovXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgJ19tZXNzYWdlJyBpbiByZXF1ZXN0ICYmXG4gICAgICAgICAgICByZXF1ZXN0LmhlYWRlcnMgJiZcbiAgICAgICAgICAgICdjb250ZW50LWxlbmd0aCcgaW4gcmVxdWVzdC5oZWFkZXJzXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBkZWxldGUgcmVxdWVzdC5oZWFkZXJzWydjb250ZW50LWxlbmd0aCddO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdGhpcy5yZXF1ZXN0KHJlcXVlc3QpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzRXJyb3JSZXNwb25zZShyZXNwb25zZSkpIHtcbiAgICAgICAgICBjb25zdCBlcnIgPSBhd2FpdCB0aGlzLmdldEVycm9yKHJlc3BvbnNlKTtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYm9keSA9IGF3YWl0IHRoaXMuZ2V0UmVzcG9uc2VCb2R5KHJlc3BvbnNlKTtcbiAgICAgICAgcmV0dXJuIGJvZHk7XG4gICAgICB9KSgpO1xuICAgICAgcmV0dXJuIHsgc3RyZWFtLCBwcm9taXNlIH07XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgZ2V0UmVmcmVzaERlbGVnYXRlKCkge1xuICAgIHJldHVybiB0aGlzLl9jb25uLl9yZWZyZXNoRGVsZWdhdGU7XG4gIH1cblxuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgYmVmb3JlU2VuZChyZXF1ZXN0OiBIdHRwUmVxdWVzdCkge1xuICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLXBhcmFtLXJlYXNzaWduICovXG4gICAgY29uc3QgaGVhZGVycyA9IHJlcXVlc3QuaGVhZGVycyB8fCB7fTtcbiAgICBpZiAodGhpcy5fY29ubi5hY2Nlc3NUb2tlbikge1xuICAgICAgaGVhZGVycy5BdXRob3JpemF0aW9uID0gYEJlYXJlciAke3RoaXMuX2Nvbm4uYWNjZXNzVG9rZW59YDtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2Nvbm4uX2NhbGxPcHRpb25zKSB7XG4gICAgICBjb25zdCBjYWxsT3B0aW9ucyA9IFtdO1xuICAgICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKHRoaXMuX2Nvbm4uX2NhbGxPcHRpb25zKSkge1xuICAgICAgICBjYWxsT3B0aW9ucy5wdXNoKGAke25hbWV9PSR7dGhpcy5fY29ubi5fY2FsbE9wdGlvbnNbbmFtZV19YCk7XG4gICAgICB9XG4gICAgICBoZWFkZXJzWydTZm9yY2UtQ2FsbC1PcHRpb25zJ10gPSBjYWxsT3B0aW9ucy5qb2luKCcsICcpO1xuICAgIH1cblxuICAgIGNvbnN0IGJvZHlTaXplID0gZ2V0Qm9keVNpemUocmVxdWVzdC5ib2R5LCBoZWFkZXJzKTtcblxuICAgIGNvbnN0IGNhbm5vdEhhdmVCb2R5ID0gWydHRVQnLCAnSEVBRCcsICdPUFRJT05TJ10uaW5jbHVkZXMocmVxdWVzdC5tZXRob2QpO1xuXG4gICAgaWYgKFxuICAgICAgIWNhbm5vdEhhdmVCb2R5ICYmXG4gICAgICAhIXJlcXVlc3QuYm9keSAmJlxuICAgICAgISgndHJhbnNmZXItZW5jb2RpbmcnIGluIGhlYWRlcnMpICYmXG4gICAgICAhKCdjb250ZW50LWxlbmd0aCcgaW4gaGVhZGVycykgJiZcbiAgICAgICEhYm9keVNpemVcbiAgICApIHtcbiAgICAgIHRoaXMuX2xvZ2dlci5kZWJ1ZyhcbiAgICAgICAgYG1pc3NpbmcgJ2NvbnRlbnQtbGVuZ3RoJyBoZWFkZXIsIHNldHRpbmcgaXQgdG86ICR7Ym9keVNpemV9YCxcbiAgICAgICk7XG4gICAgICBoZWFkZXJzWydjb250ZW50LWxlbmd0aCddID0gU3RyaW5nKGJvZHlTaXplKTtcbiAgICB9XG4gICAgcmVxdWVzdC5oZWFkZXJzID0gaGVhZGVycztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlY3QgcmVzcG9uc2UgY29udGVudCBtaW1lLXR5cGVcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgZ2V0UmVzcG9uc2VDb250ZW50VHlwZShyZXNwb25zZTogSHR0cFJlc3BvbnNlKTogT3B0aW9uYWw8c3RyaW5nPiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuX3Jlc3BvbnNlVHlwZSB8fFxuICAgICAgKHJlc3BvbnNlLmhlYWRlcnMgJiYgcmVzcG9uc2UuaGVhZGVyc1snY29udGVudC10eXBlJ10pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9yZXF1aXJlLWF3YWl0XG4gIGFzeW5jIHBhcnNlUmVzcG9uc2VCb2R5KHJlc3BvbnNlOiBIdHRwUmVzcG9uc2UpIHtcbiAgICBjb25zdCBjb250ZW50VHlwZSA9IHRoaXMuZ2V0UmVzcG9uc2VDb250ZW50VHlwZShyZXNwb25zZSkgfHwgJyc7XG4gICAgY29uc3QgcGFyc2VCb2R5ID0gL14odGV4dHxhcHBsaWNhdGlvbilcXC94bWwoO3wkKS8udGVzdChjb250ZW50VHlwZSlcbiAgICAgID8gcGFyc2VYTUxcbiAgICAgIDogL15hcHBsaWNhdGlvblxcL2pzb24oO3wkKS8udGVzdChjb250ZW50VHlwZSlcbiAgICAgID8gcGFyc2VKU09OXG4gICAgICA6IC9edGV4dFxcL2Nzdig7fCQpLy50ZXN0KGNvbnRlbnRUeXBlKVxuICAgICAgPyBwYXJzZUNTVlxuICAgICAgOiBwYXJzZVRleHQ7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBwYXJzZUJvZHkocmVzcG9uc2UuYm9keSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gVE9ETyhuZXh0IG1ham9yKTogd2UgY291bGQgdGhyb3cgYSBuZXcgXCJpbnZhbGlkIHJlc3BvbnNlIGJvZHlcIiBlcnJvciBpbnN0ZWFkLlxuICAgICAgdGhpcy5fbG9nZ2VyLmRlYnVnKGBGYWlsZWQgdG8gcGFyc2UgYm9keSBvZiBjb250ZW50LXR5cGU6ICR7Y29udGVudFR5cGV9LiBFcnJvcjogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKVxuICAgICAgcmV0dXJuIHJlc3BvbnNlLmJvZHk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCByZXNwb25zZSBib2R5XG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIGFzeW5jIGdldFJlc3BvbnNlQm9keShyZXNwb25zZTogSHR0cFJlc3BvbnNlKSB7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPT09IDIwNCkge1xuICAgICAgLy8gTm8gQ29udGVudFxuICAgICAgcmV0dXJuIHRoaXMuX25vQ29udGVudFJlc3BvbnNlO1xuICAgIH1cbiAgICBjb25zdCBib2R5ID0gYXdhaXQgdGhpcy5wYXJzZVJlc3BvbnNlQm9keShyZXNwb25zZSk7XG4gICAgbGV0IGVycjtcbiAgICBpZiAodGhpcy5oYXNFcnJvckluUmVzcG9uc2VCb2R5KGJvZHkpKSB7XG4gICAgICBlcnIgPSBhd2FpdCB0aGlzLmdldEVycm9yKHJlc3BvbnNlLCBib2R5KTtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPT09IDMwMCkge1xuICAgICAgLy8gTXVsdGlwbGUgQ2hvaWNlc1xuICAgICAgdGhyb3cgbmV3IEh0dHBBcGlFcnJvcihcbiAgICAgICAgJ011bHRpcGxlIHJlY29yZHMgZm91bmQnLFxuICAgICAgICAnTVVMVElQTEVfQ0hPSUNFUycsXG4gICAgICAgIGJvZHksXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gYm9keTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlY3Qgc2Vzc2lvbiBleHBpcnlcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgaXNTZXNzaW9uRXhwaXJlZChyZXNwb25zZTogSHR0cFJlc3BvbnNlKSB7XG4gICAgLy8gVE9ETzpcbiAgICAvLyBUaGUgY29ubmVjdGVkIGFwcCBtc2cgb25seSBhcHBsaWVzIHRvIEFnZW50IEFQSSByZXF1ZXN0cywgd2Ugc2hvdWxkIG1vdmUgdGhpcyB0byBhIHNlcGFyYXRlIFNGQVAvQWdlbnQgQVBJIGNsYXNzIGxhdGVyLlxuICAgIHJldHVybiByZXNwb25zZS5zdGF0dXNDb2RlID09PSA0MDEgJiYgIXJlc3BvbnNlLmJvZHkuaW5jbHVkZXMoJ0Nvbm5lY3RlZCBhcHAgaXMgbm90IGF0dGFjaGVkIHRvIEFnZW50JylcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlY3QgZXJyb3IgcmVzcG9uc2VcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgaXNFcnJvclJlc3BvbnNlKHJlc3BvbnNlOiBIdHRwUmVzcG9uc2UpIHtcbiAgICByZXR1cm4gcmVzcG9uc2Uuc3RhdHVzQ29kZSA+PSA0MDA7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZWN0IGVycm9yIGluIHJlc3BvbnNlIGJvZHlcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgaGFzRXJyb3JJblJlc3BvbnNlQm9keShfYm9keTogT3B0aW9uYWw8c3RyaW5nPikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzaW5nIGVycm9yIG1lc3NhZ2UgaW4gcmVzcG9uc2VcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgcGFyc2VFcnJvcihib2R5OiBhbnkpIHtcbiAgICBjb25zdCBlcnJvcnMgPSBib2R5O1xuXG4gICAgLy8gWE1MIHJlc3BvbnNlXG4gICAgaWYgKGVycm9ycy5FcnJvcnMpIHtcbiAgICAgIHJldHVybiBlcnJvcnMuRXJyb3JzLkVycm9yO1xuICAgIH1cblxuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGVycm9yIG1lc3NhZ2UgaW4gcmVzcG9uc2VcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgYXN5bmMgZ2V0RXJyb3IocmVzcG9uc2U6IEh0dHBSZXNwb25zZSwgYm9keT86IGFueSk6IFByb21pc2U8RXJyb3I+IHtcbiAgICBsZXQgZXJyb3I7XG4gICAgdHJ5IHtcbiAgICAgIGVycm9yID0gdGhpcy5wYXJzZUVycm9yKGJvZHkgfHwgKGF3YWl0IHRoaXMucGFyc2VSZXNwb25zZUJvZHkocmVzcG9uc2UpKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUgbm8tZW1wdHlcbiAgICB9XG4gICAgXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZXJyb3IpKSB7XG4gICAgICBpZiAoZXJyb3IubGVuZ3RoID09PSAxKXtcbiAgICAgICAgZXJyb3IgPSBlcnJvclswXVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG5ldyBIdHRwQXBpRXJyb3IoXG4gICAgICAgICAgYE11bHRpcGxlIGVycm9ycyByZXR1cm5lZC5cbiAgQ2hlY2sgXFxgZXJyb3IuZGF0YVxcYCBmb3IgdGhlIGVycm9yIGRldGFpbHNgLCAnTVVMVElQTEVfQVBJX0VSUk9SUycsIGVycm9yKSAgIFxuICAgICAgfVxuICAgIH1cblxuICAgIGVycm9yID1cbiAgICAgIHR5cGVvZiBlcnJvciA9PT0gJ29iamVjdCcgJiZcbiAgICAgIGVycm9yICE9PSBudWxsICYmXG4gICAgICB0eXBlb2YgZXJyb3IubWVzc2FnZSA9PT0gJ3N0cmluZydcbiAgICAgICAgPyBlcnJvclxuICAgICAgICA6IHtcbiAgICAgICAgICAgIGVycm9yQ29kZTogYEVSUk9SX0hUVFBfJHtyZXNwb25zZS5zdGF0dXNDb2RlfWAsXG4gICAgICAgICAgICBtZXNzYWdlOiByZXNwb25zZS5ib2R5LFxuICAgICAgICAgIH07XG5cbiAgICBpZiAocmVzcG9uc2UuaGVhZGVyc1snY29udGVudC10eXBlJ10gPT09ICd0ZXh0L2h0bWwnKSB7XG4gICAgICB0aGlzLl9sb2dnZXIuZGVidWcoYGh0bWwgcmVzcG9uc2UuYm9keTogJHtyZXNwb25zZS5ib2R5fWApO1xuICAgICAgcmV0dXJuIG5ldyBIdHRwQXBpRXJyb3IoXG4gICAgICAgIGBIVFRQIHJlc3BvbnNlIGNvbnRhaW5zIGh0bWwgY29udGVudC5cbkNoZWNrIHRoYXQgdGhlIG9yZyBleGlzdHMgYW5kIGNhbiBiZSByZWFjaGVkLlxuU2VlIFxcYGVycm9yLmRhdGFcXGAgZm9yIHRoZSBmdWxsIGh0bWwgcmVzcG9uc2UuYCxcbiAgICAgICAgZXJyb3IuZXJyb3JDb2RlLFxuICAgICAgICBlcnJvci5tZXNzYWdlLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBIdHRwQXBpRXJyb3IgPyBlcnJvciA6IG5ldyBIdHRwQXBpRXJyb3IoZXJyb3IubWVzc2FnZSwgZXJyb3IuZXJyb3JDb2RlLCBlcnJvcik7XG4gIH1cbn1cblxuLyoqXG4gKlxuICovXG5jbGFzcyBIdHRwQXBpRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIC8qKlxuICAgKiBUaGlzIGNvbnRhaW5zIGVycm9yLXNwZWNpZmljIGRldGFpbHMsIHVzdWFsbHkgcmV0dXJuZWQgZnJvbSB0aGUgQVBJLlxuICAgKi9cbiAgZGF0YTogYW55XG4gIGVycm9yQ29kZTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZywgZXJyb3JDb2RlPzogc3RyaW5nIHwgdW5kZWZpbmVkLCBkYXRhPzogYW55KSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gZXJyb3JDb2RlIHx8IHRoaXMubmFtZTtcbiAgICB0aGlzLmVycm9yQ29kZSA9IHRoaXMubmFtZTtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgd2lsbCBiZSByZW1vdmVkIGluIHRoZSBuZXh0IG1ham9yICh2NClcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBlcnJvci5kYXRhYCBpbnN0ZWFkXG4gICAqL1xuICBnZXQgY29udGVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEh0dHBBcGk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQSxZQUFZLFFBQVEsUUFBUTtBQUNyQyxPQUFPQyxNQUFNLE1BQU0sUUFBUTtBQUMzQixTQUFpQkMsU0FBUyxRQUFRLGVBQWU7QUFDakQsU0FBU0MsYUFBYSxRQUFRLGdCQUFnQjtBQUc5QyxTQUFTQyxRQUFRLFFBQVEsT0FBTztBQVFoQyxTQUFTQyxnQkFBZ0IsUUFBUSxlQUFlO0FBQ2hELFNBQVNDLFdBQVcsUUFBUSxzQkFBc0I7O0FBRWxEO0FBQ0EsU0FBU0MsU0FBU0EsQ0FBQ0MsR0FBVyxFQUFFO0VBQzlCLE9BQU9DLElBQUksQ0FBQ0MsS0FBSyxDQUFDRixHQUFHLENBQUM7QUFDeEI7O0FBRUE7QUFBQSxTQUNlRyxRQUFRQSxDQUFBQyxFQUFBO0VBQUEsT0FBQUMsU0FBQSxDQUFBQyxLQUFBLE9BQUFDLFNBQUE7QUFBQTtBQUl2QjtBQUFBLFNBQUFGLFVBQUE7RUFBQUEsU0FBQSxHQUFBRyxpQkFBQSxjQUFBQyxtQkFBQSxDQUFBQyxJQUFBLENBSkEsU0FBQUMsU0FBd0JYLEdBQVc7SUFBQSxPQUFBUyxtQkFBQSxDQUFBRyxJQUFBLFVBQUFDLFVBQUFDLFVBQUE7TUFBQSxrQkFBQUEsVUFBQSxDQUFBQyxJQUFBLEdBQUFELFVBQUEsQ0FBQUUsSUFBQTtRQUFBO1VBQUEsT0FBQUYsVUFBQSxDQUFBRyxNQUFBLFdBQzFCeEIsTUFBTSxDQUFDeUIsa0JB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