jsforce
Version:
Salesforce API Library for JavaScript
777 lines (752 loc) • 80.3 kB
JavaScript
import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys";
import _Object$getOwnPropertySymbols from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols";
import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
import _Object$getOwnPropertyDescriptor from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor";
import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each";
import _Object$getOwnPropertyDescriptors from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors";
import _Object$defineProperties from "@babel/runtime-corejs3/core-js-stable/object/define-properties";
import _Object$defineProperty from "@babel/runtime-corejs3/core-js-stable/object/define-property";
import _Reflect$construct from "@babel/runtime-corejs3/core-js-stable/reflect/construct";
import _get from "@babel/runtime-corejs3/helpers/get";
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 _asyncToGenerator from "@babel/runtime-corejs3/helpers/asyncToGenerator";
import _classCallCheck from "@babel/runtime-corejs3/helpers/classCallCheck";
import _createClass from "@babel/runtime-corejs3/helpers/createClass";
import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty";
import _objectWithoutProperties from "@babel/runtime-corejs3/helpers/objectWithoutProperties";
var _excluded = ["$"];
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.push.js";
import "core-js/modules/es.object.to-string.js";
import "core-js/modules/es.regexp.to-string.js";
import _regeneratorRuntime from "@babel/runtime-corejs3/regenerator";
import _Array$isArray from "@babel/runtime-corejs3/core-js-stable/array/is-array";
import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
import _JSON$stringify from "@babel/runtime-corejs3/core-js-stable/json/stringify";
import _Promise from "@babel/runtime-corejs3/core-js-stable/promise";
import _setTimeout from "@babel/runtime-corejs3/core-js-stable/set-timeout";
function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context15, _context16; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context15 = ownKeys(Object(t), !0)).call(_context15, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context16 = ownKeys(Object(t))).call(_context16, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
/**
* @file Manages Salesforce Metadata API
* @author Shinichi Tomita <shinichi.tomita@gmail.com>
*/
import { EventEmitter } from 'events';
import { Readable } from 'stream';
import FormData from 'form-data';
import { registerModule } from '../jsforce';
import SOAP from '../soap';
import { isObject } from '../util/function';
import { ApiSchemas } from './metadata/schema';
export * from './metadata/schema';
/**
*
*/
/**
*
*/
function deallocateTypeWithMetadata(metadata) {
var _ref = metadata,
$ = _ref.$,
md = _objectWithoutProperties(_ref, _excluded);
return md;
}
function assignTypeWithMetadata(metadata, type) {
var convert = function convert(md) {
return _objectSpread(_defineProperty({}, '@xsi:type', type), md);
};
return _Array$isArray(metadata) ? _mapInstanceProperty(metadata).call(metadata, convert) : convert(metadata);
}
/**
* Class for Salesforce Metadata API
*/
export var MetadataApi = /*#__PURE__*/function () {
/**
*
*/
function MetadataApi(conn) {
_classCallCheck(this, MetadataApi);
/**
* Polling interval in milliseconds
*/
_defineProperty(this, "pollInterval", 1000);
/**
* Polling timeout in milliseconds
*/
_defineProperty(this, "pollTimeout", 10000);
this._conn = conn;
}
/**
* Call Metadata API SOAP endpoint
*
* @private
*/
return _createClass(MetadataApi, [{
key: "_invoke",
value: (function () {
var _invoke2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(method, message, schema) {
var _context;
var soapEndpoint, res;
return _regeneratorRuntime.wrap(function _callee$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
soapEndpoint = new SOAP(this._conn, {
xmlns: 'http://soap.sforce.com/2006/04/metadata',
endpointUrl: _concatInstanceProperty(_context = "".concat(this._conn.instanceUrl, "/services/Soap/m/")).call(_context, this._conn.version)
});
_context2.next = 3;
return soapEndpoint.invoke(method, message, schema ? {
result: schema
} : undefined, ApiSchemas);
case 3:
res = _context2.sent;
return _context2.abrupt("return", res.result);
case 5:
case "end":
return _context2.stop();
}
}, _callee, this);
}));
function _invoke(_x, _x2, _x3) {
return _invoke2.apply(this, arguments);
}
return _invoke;
}()
/**
* Add one or more new metadata components to the organization.
*/
)
}, {
key: "create",
value: function create(type, metadata) {
var isArray = _Array$isArray(metadata);
metadata = assignTypeWithMetadata(metadata, type);
var schema = isArray ? [ApiSchemas.SaveResult] : ApiSchemas.SaveResult;
return this._invoke('createMetadata', {
metadata: metadata
}, schema);
}
/**
* Read specified metadata components in the organization.
*/
}, {
key: "read",
value: function () {
var _read = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(type, fullNames) {
var _context3;
var ReadResultSchema, res;
return _regeneratorRuntime.wrap(function _callee2$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
ReadResultSchema = type in ApiSchemas ? {
type: ApiSchemas.ReadResult.type,
props: {
records: [type]
}
} : ApiSchemas.ReadResult;
_context4.next = 3;
return this._invoke('readMetadata', {
type: type,
fullNames: fullNames
}, ReadResultSchema);
case 3:
res = _context4.sent;
return _context4.abrupt("return", _Array$isArray(fullNames) ? _mapInstanceProperty(_context3 = res.records).call(_context3, deallocateTypeWithMetadata) : deallocateTypeWithMetadata(res.records[0]));
case 5:
case "end":
return _context4.stop();
}
}, _callee2, this);
}));
function read(_x4, _x5) {
return _read.apply(this, arguments);
}
return read;
}()
/**
* Update one or more metadata components in the organization.
*/
}, {
key: "update",
value: function update(type, metadata) {
var isArray = _Array$isArray(metadata);
metadata = assignTypeWithMetadata(metadata, type);
var schema = isArray ? [ApiSchemas.SaveResult] : ApiSchemas.SaveResult;
return this._invoke('updateMetadata', {
metadata: metadata
}, schema);
}
/**
* Upsert one or more components in your organization's data.
*/
}, {
key: "upsert",
value: function upsert(type, metadata) {
var isArray = _Array$isArray(metadata);
metadata = assignTypeWithMetadata(metadata, type);
var schema = isArray ? [ApiSchemas.UpsertResult] : ApiSchemas.UpsertResult;
return this._invoke('upsertMetadata', {
metadata: metadata
}, schema);
}
/**
* Deletes specified metadata components in the organization.
*/
}, {
key: "delete",
value: function _delete(type, fullNames) {
var schema = _Array$isArray(fullNames) ? [ApiSchemas.SaveResult] : ApiSchemas.SaveResult;
return this._invoke('deleteMetadata', {
type: type,
fullNames: fullNames
}, schema);
}
/**
* Rename fullname of a metadata component in the organization
*/
}, {
key: "rename",
value: function rename(type, oldFullName, newFullName) {
return this._invoke('renameMetadata', {
type: type,
oldFullName: oldFullName,
newFullName: newFullName
}, ApiSchemas.SaveResult);
}
/**
* Retrieves the metadata which describes your organization, including Apex classes and triggers,
* custom objects, custom fields on standard objects, tab sets that define an app,
* and many other components.
*/
}, {
key: "describe",
value: function describe(asOfVersion) {
if (!asOfVersion) {
asOfVersion = this._conn.version;
}
return this._invoke('describeMetadata', {
asOfVersion: asOfVersion
}, ApiSchemas.DescribeMetadataResult);
}
/**
* Retrieves property information about metadata components in your organization
*/
}, {
key: "list",
value: function list(queries, asOfVersion) {
if (!asOfVersion) {
asOfVersion = this._conn.version;
}
return this._invoke('listMetadata', {
queries: queries,
asOfVersion: asOfVersion
}, [ApiSchemas.FileProperties]);
}
/**
* Checks the status of asynchronous metadata calls
*/
}, {
key: "checkStatus",
value: function checkStatus(asyncProcessId) {
var res = this._invoke('checkStatus', {
asyncProcessId: asyncProcessId
}, ApiSchemas.AsyncResult);
return new AsyncResultLocator(this, res);
}
/**
* Retrieves XML file representations of components in an organization
*/
}, {
key: "retrieve",
value: function retrieve(request) {
var res = this._invoke('retrieve', {
request: request
}, ApiSchemas.RetrieveResult);
return new RetrieveResultLocator(this, res);
}
/**
* Checks the status of declarative metadata call retrieve() and returns the zip file contents
*/
}, {
key: "checkRetrieveStatus",
value: function checkRetrieveStatus(asyncProcessId) {
return this._invoke('checkRetrieveStatus', {
asyncProcessId: asyncProcessId
}, ApiSchemas.RetrieveResult);
}
/**
* Will deploy a recently validated deploy request
*
* @param options.id = the deploy ID that's been validated already from a previous checkOnly deploy request
* @param options.rest = a boolean whether or not to use the REST API
* @returns the deploy ID of the recent validation request
*/
}, {
key: "deployRecentValidation",
value: (function () {
var _deployRecentValidation = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(options) {
var id, rest, response, messageBody, requestInfo, requestOptions;
return _regeneratorRuntime.wrap(function _callee3$(_context5) {
while (1) switch (_context5.prev = _context5.next) {
case 0:
id = options.id, rest = options.rest;
if (!rest) {
_context5.next = 10;
break;
}
messageBody = _JSON$stringify({
validatedDeployRequestId: id
});
requestInfo = {
method: 'POST',
url: "".concat(this._conn._baseUrl(), "/metadata/deployRequest"),
body: messageBody,
headers: {
'content-type': 'application/json'
}
};
requestOptions = {
headers: 'json'
}; // This is the deploy ID of the deployRecentValidation response, not
// the already validated deploy ID (i.e., validateddeployrequestid).
// REST returns an object with an id property, SOAP returns the id as a string directly.
_context5.next = 7;
return this._conn.request(requestInfo, requestOptions);
case 7:
response = _context5.sent.id;
_context5.next = 13;
break;
case 10:
_context5.next = 12;
return this._invoke('deployRecentValidation', {
validationId: id
});
case 12:
response = _context5.sent;
case 13:
return _context5.abrupt("return", response);
case 14:
case "end":
return _context5.stop();
}
}, _callee3, this);
}));
function deployRecentValidation(_x6) {
return _deployRecentValidation.apply(this, arguments);
}
return deployRecentValidation;
}()
/**
* Deploy components into an organization using zipped file representations
* using the REST Metadata API instead of SOAP
*/
)
}, {
key: "deployRest",
value: function deployRest(zipInput) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var form = new FormData();
form.append('file', zipInput, {
contentType: 'application/zip',
filename: 'package.xml'
});
// Add the deploy options
form.append('entity_content', _JSON$stringify({
deployOptions: options
}), {
contentType: 'application/json'
});
var request = {
url: '/metadata/deployRequest',
method: 'POST',
headers: _objectSpread({}, form.getHeaders()),
body: form.getBuffer()
};
var res = this._conn.request(request);
return new DeployResultLocator(this, res);
}
/**
* Deploy components into an organization using zipped file representations
*/
}, {
key: "deploy",
value: function deploy(zipInput) {
var _this = this;
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var res = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
var zipContentB64;
return _regeneratorRuntime.wrap(function _callee4$(_context6) {
while (1) switch (_context6.prev = _context6.next) {
case 0:
_context6.next = 2;
return new _Promise(function (resolve, reject) {
if (isObject(zipInput) && 'pipe' in zipInput && typeof zipInput.pipe === 'function') {
var bufs = [];
zipInput.on('data', function (d) {
return bufs.push(d);
});
zipInput.on('error', reject);
zipInput.on('end', function () {
resolve(_concatInstanceProperty(Buffer).call(Buffer, bufs).toString('base64'));
});
// zipInput.resume();
} else if (zipInput instanceof Buffer) {
resolve(zipInput.toString('base64'));
} else if (zipInput instanceof String || typeof zipInput === 'string') {
resolve(zipInput);
} else {
throw 'Unexpected zipInput type';
}
});
case 2:
zipContentB64 = _context6.sent;
return _context6.abrupt("return", _this._invoke('deploy', {
ZipFile: zipContentB64,
DeployOptions: options
}, ApiSchemas.DeployResult));
case 4:
case "end":
return _context6.stop();
}
}, _callee4);
}))();
return new DeployResultLocator(this, res);
}
/**
* Checks the status of declarative metadata call deploy(), using either
* SOAP or REST APIs. SOAP is the default.
*/
}, {
key: "checkDeployStatus",
value: (function () {
var _checkDeployStatus = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(asyncProcessId) {
var includeDetails,
rest,
_context7,
url,
_args5 = arguments;
return _regeneratorRuntime.wrap(function _callee5$(_context8) {
while (1) switch (_context8.prev = _context8.next) {
case 0:
includeDetails = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : false;
rest = _args5.length > 2 && _args5[2] !== undefined ? _args5[2] : false;
if (!rest) {
_context8.next = 9;
break;
}
url = _concatInstanceProperty(_context7 = "/metadata/deployRequest/".concat(asyncProcessId)).call(_context7, includeDetails ? '?includeDetails=true' : '');
_context8.next = 6;
return this._conn.requestGet(url);
case 6:
return _context8.abrupt("return", _context8.sent.deployResult);
case 9:
return _context8.abrupt("return", this._invoke('checkDeployStatus', {
asyncProcessId: asyncProcessId,
includeDetails: includeDetails
}, ApiSchemas.DeployResult));
case 10:
case "end":
return _context8.stop();
}
}, _callee5, this);
}));
function checkDeployStatus(_x7) {
return _checkDeployStatus.apply(this, arguments);
}
return checkDeployStatus;
}())
}, {
key: "cancelDeploy",
value: function () {
var _cancelDeploy = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(id) {
return _regeneratorRuntime.wrap(function _callee6$(_context9) {
while (1) switch (_context9.prev = _context9.next) {
case 0:
return _context9.abrupt("return", this._invoke('cancelDeploy', {
id: id
}));
case 1:
case "end":
return _context9.stop();
}
}, _callee6, this);
}));
function cancelDeploy(_x8) {
return _cancelDeploy.apply(this, arguments);
}
return cancelDeploy;
}()
}]);
}();
/*--------------------------------------------*/
/**
* The locator class for Metadata API asynchronous call result
*/
export var AsyncResultLocator = /*#__PURE__*/function (_EventEmitter) {
/**
*
*/
function AsyncResultLocator(meta, promise) {
var _this2;
_classCallCheck(this, AsyncResultLocator);
_this2 = _callSuper(this, AsyncResultLocator);
_this2._meta = meta;
_this2._promise = promise;
return _this2;
}
/**
* Promise/A+ interface
* http://promises-aplus.github.io/promises-spec/
*
* @method Metadata~AsyncResultLocator#then
*/
_inherits(AsyncResultLocator, _EventEmitter);
return _createClass(AsyncResultLocator, [{
key: "then",
value: function then(onResolve, onReject) {
return this._promise.then(onResolve, onReject);
}
/**
* Check the status of async request
*/
}, {
key: "check",
value: (function () {
var _check = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7() {
var result;
return _regeneratorRuntime.wrap(function _callee7$(_context10) {
while (1) switch (_context10.prev = _context10.next) {
case 0:
_context10.next = 2;
return this._promise;
case 2:
result = _context10.sent;
this._id = result.id;
return _context10.abrupt("return", this._meta.checkStatus(result.id));
case 5:
case "end":
return _context10.stop();
}
}, _callee7, this);
}));
function check() {
return _check.apply(this, arguments);
}
return check;
}()
/**
* Polling until async call status becomes complete or error
*/
)
}, {
key: "poll",
value: function poll(interval, timeout) {
var _this3 = this;
var startTime = new Date().getTime();
var poll = /*#__PURE__*/function () {
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8() {
var now, errMsg, result;
return _regeneratorRuntime.wrap(function _callee8$(_context11) {
while (1) switch (_context11.prev = _context11.next) {
case 0:
_context11.prev = 0;
now = new Date().getTime();
if (!(startTime + timeout < now)) {
_context11.next = 7;
break;
}
errMsg = 'Polling time out.';
if (_this3._id) {
errMsg += ' Process Id = ' + _this3._id;
}
_this3.emit('error', new Error(errMsg));
return _context11.abrupt("return");
case 7:
_context11.next = 9;
return _this3.check();
case 9:
result = _context11.sent;
if (result.done) {
_this3.emit('complete', result);
} else {
_this3.emit('progress', result);
_setTimeout(poll, interval);
}
_context11.next = 16;
break;
case 13:
_context11.prev = 13;
_context11.t0 = _context11["catch"](0);
_this3.emit('error', _context11.t0);
case 16:
case "end":
return _context11.stop();
}
}, _callee8, null, [[0, 13]]);
}));
return function poll() {
return _ref3.apply(this, arguments);
};
}();
_setTimeout(poll, interval);
}
/**
* Check and wait until the async requests become in completed status
*/
}, {
key: "complete",
value: function complete() {
var _this4 = this;
return new _Promise(function (resolve, reject) {
_this4.on('complete', resolve);
_this4.on('error', reject);
_this4.poll(_this4._meta.pollInterval, _this4._meta.pollTimeout);
});
}
}]);
}(EventEmitter);
/*--------------------------------------------*/
/**
* The locator class to track retreive() Metadata API call result
*/
export var RetrieveResultLocator = /*#__PURE__*/function (_AsyncResultLocator) {
function RetrieveResultLocator() {
_classCallCheck(this, RetrieveResultLocator);
return _callSuper(this, RetrieveResultLocator, arguments);
}
_inherits(RetrieveResultLocator, _AsyncResultLocator);
return _createClass(RetrieveResultLocator, [{
key: "complete",
value: (
/**
* Check and wait until the async request becomes in completed status,
* and retrieve the result data.
*/
function () {
var _complete = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9() {
var result;
return _regeneratorRuntime.wrap(function _callee9$(_context12) {
while (1) switch (_context12.prev = _context12.next) {
case 0:
_context12.next = 2;
return _get(_getPrototypeOf(RetrieveResultLocator.prototype), "complete", this).call(this);
case 2:
result = _context12.sent;
return _context12.abrupt("return", this._meta.checkRetrieveStatus(result.id));
case 4:
case "end":
return _context12.stop();
}
}, _callee9, this);
}));
function complete() {
return _complete.apply(this, arguments);
}
return complete;
}()
/**
* Change the retrieved result to Node.js readable stream
*/
)
}, {
key: "stream",
value: function stream() {
var _this5 = this;
var resultStream = new Readable();
var reading = false;
resultStream._read = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10() {
var result;
return _regeneratorRuntime.wrap(function _callee10$(_context13) {
while (1) switch (_context13.prev = _context13.next) {
case 0:
if (!reading) {
_context13.next = 2;
break;
}
return _context13.abrupt("return");
case 2:
reading = true;
_context13.prev = 3;
_context13.next = 6;
return _this5.complete();
case 6:
result = _context13.sent;
resultStream.push(Buffer.from(result.zipFile, 'base64'));
resultStream.push(null);
_context13.next = 14;
break;
case 11:
_context13.prev = 11;
_context13.t0 = _context13["catch"](3);
resultStream.emit('error', _context13.t0);
case 14:
case "end":
return _context13.stop();
}
}, _callee10, null, [[3, 11]]);
}));
return resultStream;
}
}]);
}(AsyncResultLocator);
/*--------------------------------------------*/
/**
* The locator class to track deploy() Metadata API call result
*
* @protected
* @class Metadata~DeployResultLocator
* @extends Metadata~AsyncResultLocator
* @param {Metadata} meta - Metadata API object
* @param {Promise.<Metadata~AsyncResult>} result - Promise object for async result of deploy() call
*/
export var DeployResultLocator = /*#__PURE__*/function (_AsyncResultLocator2) {
function DeployResultLocator() {
_classCallCheck(this, DeployResultLocator);
return _callSuper(this, DeployResultLocator, arguments);
}
_inherits(DeployResultLocator, _AsyncResultLocator2);
return _createClass(DeployResultLocator, [{
key: "complete",
value: (
/**
* Check and wait until the async request becomes in completed status,
* and retrieve the result data.
*/
function () {
var _complete2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11(includeDetails) {
var result;
return _regeneratorRuntime.wrap(function _callee11$(_context14) {
while (1) switch (_context14.prev = _context14.next) {
case 0:
_context14.next = 2;
return _get(_getPrototypeOf(DeployResultLocator.prototype), "complete", this).call(this);
case 2:
result = _context14.sent;
return _context14.abrupt("return", this._meta.checkDeployStatus(result.id, includeDetails));
case 4:
case "end":
return _context14.stop();
}
}, _callee11, this);
}));
function complete(_x9) {
return _complete2.apply(this, arguments);
}
return complete;
}())
}]);
}(AsyncResultLocator);
/*--------------------------------------------*/
/*
* Register hook in connection instantiation for dynamically adding this API module features
*/
registerModule('metadata', function (conn) {
return new MetadataApi(conn);
});
export default MetadataApi;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJFdmVudEVtaXR0ZXIiLCJSZWFkYWJsZSIsIkZvcm1EYXRhIiwicmVnaXN0ZXJNb2R1bGUiLCJTT0FQIiwiaXNPYmplY3QiLCJBcGlTY2hlbWFzIiwiZGVhbGxvY2F0ZVR5cGVXaXRoTWV0YWRhdGEiLCJtZXRhZGF0YSIsIl9yZWYiLCIkIiwibWQiLCJfb2JqZWN0V2l0aG91dFByb3BlcnRpZXMiLCJfZXhjbHVkZWQiLCJhc3NpZ25UeXBlV2l0aE1ldGFkYXRhIiwidHlwZSIsImNvbnZlcnQiLCJfb2JqZWN0U3ByZWFkIiwiX2RlZmluZVByb3BlcnR5IiwiX0FycmF5JGlzQXJyYXkiLCJfbWFwSW5zdGFuY2VQcm9wZXJ0eSIsImNhbGwiLCJNZXRhZGF0YUFwaSIsImNvbm4iLCJfY2xhc3NDYWxsQ2hlY2siLCJfY29ubiIsIl9jcmVhdGVDbGFzcyIsImtleSIsInZhbHVlIiwiX2ludm9rZTIiLCJfYXN5bmNUb0dlbmVyYXRvciIsIl9yZWdlbmVyYXRvclJ1bnRpbWUiLCJtYXJrIiwiX2NhbGxlZSIsIm1ldGhvZCIsIm1lc3NhZ2UiLCJzY2hlbWEiLCJfY29udGV4dCIsInNvYXBFbmRwb2ludCIsInJlcyIsIndyYXAiLCJfY2FsbGVlJCIsIl9jb250ZXh0MiIsInByZXYiLCJuZXh0IiwieG1sbnMiLCJlbmRwb2ludFVybCIsIl9jb25jYXRJbnN0YW5jZVByb3BlcnR5IiwiY29uY2F0IiwiaW5zdGFuY2VVcmwiLCJ2ZXJzaW9uIiwiaW52b2tlIiwicmVzdWx0IiwidW5kZWZpbmVkIiwic2VudCIsImFicnVwdCIsInN0b3AiLCJfaW52b2tlIiwiX3giLCJfeDIiLCJfeDMiLCJhcHBseSIsImFyZ3VtZW50cyIsImNyZWF0ZSIsImlzQXJyYXkiLCJTYXZlUmVzdWx0IiwiX3JlYWQiLCJfY2FsbGVlMiIsImZ1bGxOYW1lcyIsIl9jb250ZXh0MyIsIlJlYWRSZXN1bHRTY2hlbWEiLCJfY2FsbGVlMiQiLCJfY29udGV4dDQiLCJSZWFkUmVzdWx0IiwicHJvcHMiLCJyZWNvcmRzIiwicmVhZCIsIl94NCIsIl94NSIsInVwZGF0ZSIsInVwc2VydCIsIlVwc2VydFJlc3VsdCIsIl9kZWxldGUiLCJyZW5hbWUiLCJvbGRGdWxsTmFtZSIsIm5ld0Z1bGxOYW1lIiwiZGVzY3JpYmUiLCJhc09mVmVyc2lvbiIsIkRlc2NyaWJlTWV0YWRhdGFSZXN1bHQiLCJsaXN0IiwicXVlcmllcyIsIkZpbGVQcm9wZXJ0aWVzIiwiY2hlY2tTdGF0dXMiLCJhc3luY1Byb2Nlc3NJZCIsIkFzeW5jUmVzdWx0IiwiQXN5bmNSZXN1bHRMb2NhdG9yIiwicmV0cmlldmUiLCJyZXF1ZXN0IiwiUmV0cmlldmVSZXN1bHQiLCJSZXRyaWV2ZVJlc3VsdExvY2F0b3IiLCJjaGVja1JldHJpZXZlU3RhdHVzIiwiX2RlcGxveVJlY2VudFZhbGlkYXRpb24iLCJfY2FsbGVlMyIsIm9wdGlvbnMiLCJpZCIsInJlc3QiLCJyZXNwb25zZSIsIm1lc3NhZ2VCb2R5IiwicmVxdWVzdEluZm8iLCJyZXF1ZXN0T3B0aW9ucyIsIl9jYWxsZWUzJCIsIl9jb250ZXh0NSIsIl9KU09OJHN0cmluZ2lmeSIsInZhbGlkYXRlZERlcGxveVJlcXVlc3RJZCIsInVybCIsIl9iYXNlVXJsIiwiYm9keSIsImhlYWRlcnMiLCJ2YWxpZGF0aW9uSWQiLCJkZXBsb3lSZWNlbnRWYWxpZGF0aW9uIiwiX3g2IiwiZGVwbG95UmVzdCIsInppcElucHV0IiwibGVuZ3RoIiwiZm9ybSIsImFwcGVuZCIsImNvbnRlbnRUeXBlIiwiZmlsZW5hbWUiLCJkZXBsb3lPcHRpb25zIiwiZ2V0SGVhZGVycyIsImdldEJ1ZmZlciIsIkRlcGxveVJlc3VsdExvY2F0b3IiLCJkZXBsb3kiLCJfdGhpcyIsIl9jYWxsZWU0IiwiemlwQ29udGVudEI2NCIsIl9jYWxsZWU0JCIsIl9jb250ZXh0NiIsIl9Qcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsInBpcGUiLCJidWZzIiwib24iLCJkIiwicHVzaCIsIkJ1ZmZlciIsInRvU3RyaW5nIiwiU3RyaW5nIiwiWmlwRmlsZSIsIkRlcGxveU9wdGlvbnMiLCJEZXBsb3lSZXN1bHQiLCJfY2hlY2tEZXBsb3lTdGF0dXMiLCJfY2FsbGVlNSIsImluY2x1ZGVEZXRhaWxzIiwiX2NvbnRleHQ3IiwiX2FyZ3M1IiwiX2NhbGxlZTUkIiwiX2NvbnRleHQ4IiwicmVxdWVzdEdldCIsImRlcGxveVJlc3VsdCIsImNoZWNrRGVwbG95U3RhdHVzIiwiX3g3IiwiX2NhbmNlbERlcGxveSIsIl9jYWxsZWU2IiwiX2NhbGxlZTYkIiwiX2NvbnRleHQ5IiwiY2FuY2VsRGVwbG95IiwiX3g4IiwiX0V2ZW50RW1pdHRlciIsIm1ldGEiLCJwcm9taXNlIiwiX3RoaXMyIiwiX2NhbGxTdXBlciIsIl9tZXRhIiwiX3Byb21pc2UiLCJfaW5oZXJpdHMiLCJ0aGVuIiwib25SZXNvbHZlIiwib25SZWplY3QiLCJfY2hlY2siLCJfY2FsbGVlNyIsIl9jYWxsZWU3JCIsIl9jb250ZXh0MTAiLCJfaWQiLCJjaGVjayIsInBvbGwiLCJpbnRlcnZhbCIsInRpbWVvdXQiLCJfdGhpczMiLCJzdGFydFRpbWUiLCJEYXRlIiwiZ2V0VGltZSIsIl9yZWYzIiwiX2NhbGxlZTgiLCJub3ciLCJlcnJNc2ciLCJfY2FsbGVlOCQiLCJfY29udGV4dDExIiwiZW1pdCIsIkVycm9yIiwiZG9uZSIsIl9zZXRUaW1lb3V0IiwidDAiLCJjb21wbGV0ZSIsIl90aGlzNCIsInBvbGxJbnRlcnZhbCIsInBvbGxUaW1lb3V0IiwiX0FzeW5jUmVzdWx0TG9jYXRvciIsIl9jb21wbGV0ZSIsIl9jYWxsZWU5IiwiX2NhbGxlZTkkIiwiX2NvbnRleHQxMiIsIl9nZXQiLCJfZ2V0UHJvdG90eXBlT2YiLCJwcm90b3R5cGUiLCJzdHJlYW0iLCJfdGhpczUiLCJyZXN1bHRTdHJlYW0iLCJyZWFkaW5nIiwiX2NhbGxlZTEwIiwiX2NhbGxlZTEwJCIsIl9jb250ZXh0MTMiLCJmcm9tIiwiemlwRmlsZSIsIl9Bc3luY1Jlc3VsdExvY2F0b3IyIiwiX2NvbXBsZXRlMiIsIl9jYWxsZWUxMSIsIl9jYWxsZWUxMSQiLCJfY29udGV4dDE0IiwiX3g5Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwaS9tZXRhZGF0YS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBmaWxlIE1hbmFnZXMgU2FsZXNmb3JjZSBNZXRhZGF0YSBBUElcbiAqIEBhdXRob3IgU2hpbmljaGkgVG9taXRhIDxzaGluaWNoaS50b21pdGFAZ21haWwuY29tPlxuICovXG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdldmVudHMnO1xuaW1wb3J0IHsgUmVhZGFibGUgfSBmcm9tICdzdHJlYW0nO1xuaW1wb3J0IEZvcm1EYXRhIGZyb20gJ2Zvcm0tZGF0YSc7XG5pbXBvcnQgeyByZWdpc3Rlck1vZHVsZSB9IGZyb20gJy4uL2pzZm9yY2UnO1xuaW1wb3J0IENvbm5lY3Rpb24gZnJvbSAnLi4vY29ubmVjdGlvbic7XG5pbXBvcnQgU09BUCBmcm9tICcuLi9zb2FwJztcbmltcG9ydCB7IGlzT2JqZWN0IH0gZnJvbSAnLi4vdXRpbC9mdW5jdGlvbic7XG5pbXBvcnQgeyBTY2hlbWEsIFNvYXBTY2hlbWFEZWYsIFNvYXBTY2hlbWEsIEh0dHBSZXF1ZXN0IH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHtcbiAgQXBpU2NoZW1hcyxcbiAgTWV0YWRhdGEsXG4gIFJlYWRSZXN1bHQsXG4gIFNhdmVSZXN1bHQsXG4gIFVwc2VydFJlc3VsdCxcbiAgTGlzdE1ldGFkYXRhUXVlcnksXG4gIEZpbGVQcm9wZXJ0aWVzLFxuICBEZXNjcmliZU1ldGFkYXRhUmVzdWx0LFxuICBSZXRyaWV2ZVJlcXVlc3QsXG4gIERlcGxveU9wdGlvbnMsXG4gIFJldHJpZXZlUmVzdWx0LFxuICBEZXBsb3lSZXN1bHQsXG4gIEFzeW5jUmVzdWx0LFxuICBBcGlTY2hlbWFUeXBlcywgQ2FuY2VsRGVwbG95UmVzdWx0LFxufSBmcm9tICcuL21ldGFkYXRhL3NjaGVtYSc7XG5leHBvcnQgKiBmcm9tICcuL21ldGFkYXRhL3NjaGVtYSc7XG5cbi8qKlxuICpcbiAqL1xudHlwZSBNZXRhZGF0YVR5cGVfPFxuICBLIGV4dGVuZHMga2V5b2YgQXBpU2NoZW1hVHlwZXMgPSBrZXlvZiBBcGlTY2hlbWFUeXBlc1xuPiA9IEsgZXh0ZW5kcyBrZXlvZiBBcGlTY2hlbWFUeXBlc1xuICA/IEFwaVNjaGVtYVR5cGVzW0tdIGV4dGVuZHMgTWV0YWRhdGFcbiAgICA/IEtcbiAgICA6IG5ldmVyXG4gIDogbmV2ZXI7XG5cbmV4cG9ydCB0eXBlIE1ldGFkYXRhVHlwZSA9IE1ldGFkYXRhVHlwZV87XG5cbmV4cG9ydCB0eXBlIE1ldGFkYXRhRGVmaW5pdGlvbjxcbiAgVCBleHRlbmRzIHN0cmluZyxcbiAgTSBleHRlbmRzIE1ldGFkYXRhID0gTWV0YWRhdGFcbj4gPSBNZXRhZGF0YSBleHRlbmRzIE1cbiAgPyBUIGV4dGVuZHMga2V5b2YgQXBpU2NoZW1hVHlwZXMgJiBNZXRhZGF0YVR5cGVcbiAgICA/IEFwaVNjaGVtYVR5cGVzW1RdIGV4dGVuZHMgTWV0YWRhdGFcbiAgICAgID8gQXBpU2NoZW1hVHlwZXNbVF1cbiAgICAgIDogTWV0YWRhdGFcbiAgICA6IE1ldGFkYXRhXG4gIDogTTtcblxudHlwZSBEZWVwUGFydGlhbDxUPiA9IFQgZXh0ZW5kcyBhbnlbXVxuICA/IEFycmF5PERlZXBQYXJ0aWFsPFRbbnVtYmVyXT4+XG4gIDogVCBleHRlbmRzIG9iamVjdFxuICA/IHsgW0sgaW4ga2V5b2YgVF0/OiBEZWVwUGFydGlhbDxUW0tdPiB9XG4gIDogVDtcblxuZXhwb3J0IHR5cGUgSW5wdXRNZXRhZGF0YURlZmluaXRpb248XG4gIFQgZXh0ZW5kcyBzdHJpbmcsXG4gIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhXG4+ID0gRGVlcFBhcnRpYWw8TWV0YWRhdGFEZWZpbml0aW9uPFQsIE0+PjtcblxuLyoqXG4gKlxuICovXG5mdW5jdGlvbiBkZWFsbG9jYXRlVHlwZVdpdGhNZXRhZGF0YTxNIGV4dGVuZHMgTWV0YWRhdGE+KG1ldGFkYXRhOiBNKTogTSB7XG4gIGNvbnN0IHsgJCwgLi4ubWQgfSA9IG1ldGFkYXRhIGFzIGFueTtcbiAgcmV0dXJuIG1kO1xufVxuXG5mdW5jdGlvbiBhc3NpZ25UeXBlV2l0aE1ldGFkYXRhKG1ldGFkYXRhOiBNZXRhZGF0YSB8IE1ldGFkYXRhW10sIHR5cGU6IHN0cmluZykge1xuICBjb25zdCBjb252ZXJ0ID0gKG1kOiBNZXRhZGF0YSkgPT4gKHsgWydAeHNpOnR5cGUnXTogdHlwZSwgLi4ubWQgfSk7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KG1ldGFkYXRhKSA/IG1ldGFkYXRhLm1hcChjb252ZXJ0KSA6IGNvbnZlcnQobWV0YWRhdGEpO1xufVxuXG4vKipcbiAqIENsYXNzIGZvciBTYWxlc2ZvcmNlIE1ldGFkYXRhIEFQSVxuICovXG5leHBvcnQgY2xhc3MgTWV0YWRhdGFBcGk8UyBleHRlbmRzIFNjaGVtYT4ge1xuICBfY29ubjogQ29ubmVjdGlvbjxTPjtcblxuICAvKipcbiAgICogUG9sbGluZyBpbnRlcnZhbCBpbiBtaWxsaXNlY29uZHNcbiAgICovXG4gIHBvbGxJbnRlcnZhbDogbnVtYmVyID0gMTAwMDtcblxuICAvKipcbiAgICogUG9sbGluZyB0aW1lb3V0IGluIG1pbGxpc2Vjb25kc1xuICAgKi9cbiAgcG9sbFRpbWVvdXQ6IG51bWJlciA9IDEwMDAwO1xuXG4gIC8qKlxuICAgKlxuICAgKi9cbiAgY29uc3RydWN0b3IoY29ubjogQ29ubmVjdGlvbjxTPikge1xuICAgIHRoaXMuX2Nvbm4gPSBjb25uO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGwgTWV0YWRhdGEgQVBJIFNPQVAgZW5kcG9pbnRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGFzeW5jIF9pbnZva2UoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgbWVzc2FnZTogb2JqZWN0LFxuICAgIHNjaGVtYT86IFNvYXBTY2hlbWEgfCBTb2FwU2NoZW1hRGVmLFxuICApIHtcbiAgICBjb25zdCBzb2FwRW5kcG9pbnQgPSBuZXcgU09BUCh0aGlzLl9jb25uLCB7XG4gICAgICB4bWxuczogJ2h0dHA6Ly9zb2FwLnNmb3JjZS5jb20vMjAwNi8wNC9tZXRhZGF0YScsXG4gICAgICBlbmRwb2ludFVybDogYCR7dGhpcy5fY29ubi5pbnN0YW5jZVVybH0vc2VydmljZXMvU29hcC9tLyR7dGhpcy5fY29ubi52ZXJzaW9ufWAsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgc29hcEVuZHBvaW50Lmludm9rZShcbiAgICAgIG1ldGhvZCxcbiAgICAgIG1lc3NhZ2UsXG4gICAgICBzY2hlbWEgPyAoeyByZXN1bHQ6IHNjaGVtYSB9IGFzIFNvYXBTY2hlbWEpIDogdW5kZWZpbmVkLFxuICAgICAgQXBpU2NoZW1hcyxcbiAgICApO1xuICAgIHJldHVybiByZXMucmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBvbmUgb3IgbW9yZSBuZXcgbWV0YWRhdGEgY29tcG9uZW50cyB0byB0aGUgb3JnYW5pemF0aW9uLlxuICAgKi9cbiAgY3JlYXRlPFxuICAgIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhLFxuICAgIFQgZXh0ZW5kcyBNZXRhZGF0YVR5cGUgPSBNZXRhZGF0YVR5cGUsXG4gICAgTUQgZXh0ZW5kcyBJbnB1dE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPiA9IElucHV0TWV0YWRhdGFEZWZpbml0aW9uPFQsIE0+XG4gID4odHlwZTogVCwgbWV0YWRhdGE6IE1EW10pOiBQcm9taXNlPFNhdmVSZXN1bHRbXT47XG4gIGNyZWF0ZTxcbiAgICBNIGV4dGVuZHMgTWV0YWRhdGEgPSBNZXRhZGF0YSxcbiAgICBUIGV4dGVuZHMgTWV0YWRhdGFUeXBlID0gTWV0YWRhdGFUeXBlLFxuICAgIE1EIGV4dGVuZHMgSW5wdXRNZXRhZGF0YURlZmluaXRpb248VCwgTT4gPSBJbnB1dE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPlxuICA+KHR5cGU6IFQsIG1ldGFkYXRhOiBNRCk6IFByb21pc2U8U2F2ZVJlc3VsdD47XG4gIGNyZWF0ZTxcbiAgICBNIGV4dGVuZHMgTWV0YWRhdGEgPSBNZXRhZGF0YSxcbiAgICBUIGV4dGVuZHMgTWV0YWRhdGFUeXBlID0gTWV0YWRhdGFUeXBlLFxuICAgIE1EIGV4dGVuZHMgSW5wdXRNZXRhZGF0YURlZmluaXRpb248VCwgTT4gPSBJbnB1dE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPlxuICA+KHR5cGU6IFQsIG1ldGFkYXRhOiBNRCB8IE1EW10pOiBQcm9taXNlPFNhdmVSZXN1bHQgfCBTYXZlUmVzdWx0W10+O1xuICBjcmVhdGUodHlwZTogc3RyaW5nLCBtZXRhZGF0YTogTWV0YWRhdGEgfCBNZXRhZGF0YVtdKSB7XG4gICAgY29uc3QgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkobWV0YWRhdGEpO1xuICAgIG1ldGFkYXRhID0gYXNzaWduVHlwZVdpdGhNZXRhZGF0YShtZXRhZGF0YSwgdHlwZSk7XG4gICAgY29uc3Qgc2NoZW1hID0gaXNBcnJheSA/IFtBcGlTY2hlbWFzLlNhdmVSZXN1bHRdIDogQXBpU2NoZW1hcy5TYXZlUmVzdWx0O1xuICAgIHJldHVybiB0aGlzLl9pbnZva2UoJ2NyZWF0ZU1ldGFkYXRhJywgeyBtZXRhZGF0YSB9LCBzY2hlbWEpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlYWQgc3BlY2lmaWVkIG1ldGFkYXRhIGNvbXBvbmVudHMgaW4gdGhlIG9yZ2FuaXphdGlvbi5cbiAgICovXG4gIHJlYWQ8XG4gICAgTSBleHRlbmRzIE1ldGFkYXRhID0gTWV0YWRhdGEsXG4gICAgVCBleHRlbmRzIE1ldGFkYXRhVHlwZSA9IE1ldGFkYXRhVHlwZSxcbiAgICBNRCBleHRlbmRzIE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPiA9IE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPlxuICA+KHR5cGU6IFQsIGZ1bGxOYW1lczogc3RyaW5nW10pOiBQcm9taXNlPE1EW10+O1xuICByZWFkPFxuICAgIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhLFxuICAgIFQgZXh0ZW5kcyBNZXRhZGF0YVR5cGUgPSBNZXRhZGF0YVR5cGUsXG4gICAgTUQgZXh0ZW5kcyBNZXRhZGF0YURlZmluaXRpb248VCwgTT4gPSBNZXRhZGF0YURlZmluaXRpb248VCwgTT5cbiAgPih0eXBlOiBULCBmdWxsTmFtZXM6IHN0cmluZyk6IFByb21pc2U8TUQ+O1xuICByZWFkPFxuICAgIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhLFxuICAgIFQgZXh0ZW5kcyBNZXRhZGF0YVR5cGUgPSBNZXRhZGF0YVR5cGUsXG4gICAgTUQgZXh0ZW5kcyBNZXRhZGF0YURlZmluaXRpb248VCwgTT4gPSBNZXRhZGF0YURlZmluaXRpb248VCwgTT5cbiAgPih0eXBlOiBULCBmdWxsTmFtZXM6IHN0cmluZyB8IHN0cmluZ1tdKTogUHJvbWlzZTxNRCB8IE1EW10+O1xuICBhc3luYyByZWFkKHR5cGU6IHN0cmluZywgZnVsbE5hbWVzOiBzdHJpbmcgfCBzdHJpbmdbXSkge1xuICAgIGNvbnN0IFJlYWRSZXN1bHRTY2hlbWEgPVxuICAgICAgdHlwZSBpbiBBcGlTY2hlbWFzXG4gICAgICAgID8gKHtcbiAgICAgICAgICAgIHR5cGU6IEFwaVNjaGVtYXMuUmVhZFJlc3VsdC50eXBlLFxuICAgICAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICAgICAgcmVjb3JkczogW3R5cGVdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9IGFzIGNvbnN0KVxuICAgICAgICA6IEFwaVNjaGVtYXMuUmVhZFJlc3VsdDtcbiAgICBjb25zdCByZXM6IFJlYWRSZXN1bHQgPSBhd2FpdCB0aGlzLl9pbnZva2UoXG4gICAgICAncmVhZE1ldGFkYXRhJyxcbiAgICAgIHsgdHlwZSwgZnVsbE5hbWVzIH0sXG4gICAgICBSZWFkUmVzdWx0U2NoZW1hLFxuICAgICk7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoZnVsbE5hbWVzKVxuICAgICAgPyByZXMucmVjb3Jkcy5tYXAoZGVhbGxvY2F0ZVR5cGVXaXRoTWV0YWRhdGEpXG4gICAgICA6IGRlYWxsb2NhdGVUeXBlV2l0aE1ldGFkYXRhKHJlcy5yZWNvcmRzWzBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgb25lIG9yIG1vcmUgbWV0YWRhdGEgY29tcG9uZW50cyBpbiB0aGUgb3JnYW5pemF0aW9uLlxuICAgKi9cbiAgdXBkYXRlPFxuICAgIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhLFxuICAgIFQgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gICAgTUQgZXh0ZW5kcyBJbnB1dE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPiA9IElucHV0TWV0YWRhdGFEZWZpbml0aW9uPFQsIE0+XG4gID4odHlwZTogVCwgbWV0YWRhdGE6IEFycmF5PFBhcnRpYWw8TUQ+Pik6IFByb21pc2U8U2F2ZVJlc3VsdFtdPjtcbiAgdXBkYXRlPFxuICAgIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhLFxuICAgIFQgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gICAgTUQgZXh0ZW5kcyBJbnB1dE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPiA9IElucHV0TWV0YWRhdGFEZWZpbml0aW9uPFQsIE0+XG4gID4odHlwZTogVCwgbWV0YWRhdGE6IFBhcnRpYWw8TUQ+KTogUHJvbWlzZTxTYXZlUmVzdWx0PjtcbiAgdXBkYXRlPFxuICAgIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhLFxuICAgIFQgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gICAgTUQgZXh0ZW5kcyBJbnB1dE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPiA9IElucHV0TWV0YWRhdGFEZWZpbml0aW9uPFQsIE0+XG4gID4oXG4gICAgdHlwZTogVCxcbiAgICBtZXRhZGF0YTogUGFydGlhbDxNRD4gfCBBcnJheTxQYXJ0aWFsPE1EPj4sXG4gICk6IFByb21pc2U8U2F2ZVJlc3VsdCB8IFNhdmVSZXN1bHRbXT47XG4gIHVwZGF0ZSh0eXBlOiBzdHJpbmcsIG1ldGFkYXRhOiBNZXRhZGF0YSB8IE1ldGFkYXRhW10pIHtcbiAgICBjb25zdCBpc0FycmF5ID0gQXJyYXkuaXNBcnJheShtZXRhZGF0YSk7XG4gICAgbWV0YWRhdGEgPSBhc3NpZ25UeXBlV2l0aE1ldGFkYXRhKG1ldGFkYXRhLCB0eXBlKTtcbiAgICBjb25zdCBzY2hlbWEgPSBpc0FycmF5ID8gW0FwaVNjaGVtYXMuU2F2ZVJlc3VsdF0gOiBBcGlTY2hlbWFzLlNhdmVSZXN1bHQ7XG4gICAgcmV0dXJuIHRoaXMuX2ludm9rZSgndXBkYXRlTWV0YWRhdGEnLCB7IG1ldGFkYXRhIH0sIHNjaGVtYSk7XG4gIH1cblxuICAvKipcbiAgICogVXBzZXJ0IG9uZSBvciBtb3JlIGNvbXBvbmVudHMgaW4geW91ciBvcmdhbml6YXRpb24ncyBkYXRhLlxuICAgKi9cbiAgdXBzZXJ0PFxuICAgIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhLFxuICAgIFQgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gICAgTUQgZXh0ZW5kcyBJbnB1dE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPiA9IElucHV0TWV0YWRhdGFEZWZpbml0aW9uPFQsIE0+XG4gID4odHlwZTogVCwgbWV0YWRhdGE6IE1EW10pOiBQcm9taXNlPFVwc2VydFJlc3VsdFtdPjtcbiAgdXBzZXJ0PFxuICAgIE0gZXh0ZW5kcyBNZXRhZGF0YSA9IE1ldGFkYXRhLFxuICAgIFQgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gICAgTUQgZXh0ZW5kcyBJbnB1dE1ldGFkYXRhRGVmaW5pdGlvbjxULCBNPiA9IElucHV0TWV0YWRhdGFEZWZpbml0aW9uPFQsIE0+XG4gID4odHlwZTogVCwgbWV0YWRhdGE6IE1EKTogUHJvbWlzZTxVcHNlcnRSZXN1bHQ+O1xuICB1cHNlcnQ8XG4gICAgTSBleHRlbmRzIE1ldGFkYXRhID0gTWV0YWRhdGEsXG4gICAgVCBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgICBNRCBleHRlbmRzIElucHV0TWV0YWRhdGFEZWZpbml0aW9uPFQsIE0+ID0gSW5wdXRNZXRhZGF0YURlZmluaXRpb248VCwgTT5cbiAgPih0eXBlOiBULCBtZXRhZGF0YTogTUQgfCBNRFtdKTogUHJvbWlzZTxVcHNlcnRSZXN1bHQgfCBVcHNlcnRSZXN1bHRbXT47XG4gIHVwc2VydCh0eXBlOiBzdHJpbmcsIG1ldGFkYXRhOiBNZXRhZGF0YSB8IE1ldGFkYXRhW10pIHtcbiAgICBjb25zdCBpc0FycmF5ID0gQXJyYXkuaXNBcnJheShtZXRhZGF0YSk7XG4gICAgbWV0YWRhdGEgPSBhc3NpZ25UeXBlV2l0aE1ldGFkYXRhKG1ldGFkYXRhLCB0eXBlKTtcbiAgICBjb25zdCBzY2hlbWEgPSBpc0FycmF5XG4gICAgICA/IFtBcGlTY2hlbWFzLlVwc2VydFJlc3VsdF1cbiAgICAgIDogQXBpU2NoZW1hcy5VcHNlcnRSZXN1bHQ7XG4gICAgcmV0dXJuIHRoaXMuX2ludm9rZSgndXBzZXJ0TWV0YWRhdGEnLCB7IG1ldGFkYXRhIH0sIHNjaGVtYSk7XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyBzcGVjaWZpZWQgbWV0YWRhdGEgY29tcG9uZW50cyBpbiB0aGUgb3JnYW5pemF0aW9uLlxuICAgKi9cbiAgZGVsZXRlKHR5cGU6IHN0cmluZywgZnVsbE5hbWVzOiBzdHJpbmdbXSk6IFByb21pc2U8U2F2ZVJlc3VsdFtdPjtcbiAgZGVsZXRlKHR5cGU6IHN0cmluZywgZnVsbE5hbWVzOiBzdHJpbmcpOiBQcm9taXNlPFNhdmVSZXN1bHQ+O1xuICBkZWxldGUoXG4gICAgdHlwZTogc3RyaW5nLFxuICAgIGZ1bGxOYW1lczogc3RyaW5nIHwgc3RyaW5nW10sXG4gICk6IFByb21pc2U8U2F2ZVJlc3VsdCB8IFNhdmVSZXN1bHRbXT47XG4gIGRlbGV0ZSh0eXBlOiBzdHJpbmcsIGZ1bGxOYW1lczogc3RyaW5nIHwgc3RyaW5nW10pIHtcbiAgICBjb25zdCBzY2hlbWEgPSBBcnJheS5pc0FycmF5KGZ1bGxOYW1lcylcbiAgICAgID8gW0FwaVNjaGVtYXMuU2F2ZVJlc3VsdF1cbiAgICAgIDogQXBpU2NoZW1hcy5TYXZlUmVzdWx0O1xuICAgIHJldHVybiB0aGlzLl9pbnZva2UoJ2RlbGV0ZU1ldGFkYXRhJywgeyB0eXBlLCBmdWxsTmFtZXMgfSwgc2NoZW1hKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5hbWUgZnVsbG5hbWUgb2YgYSBtZXRhZGF0YSBjb21wb25lbnQgaW4gdGhlIG9yZ2FuaXphdGlvblxuICAgKi9cbiAgcmVuYW1lKFxuICAgIHR5cGU6IHN0cmluZyxcbiAgICBvbGRGdWxsTmFtZTogc3RyaW5nLFxuICAgIG5ld0Z1bGxOYW1lOiBzdHJpbmcsXG4gICk6IFByb21pc2U8U2F2ZVJlc3VsdD4ge1xuICAgIHJldHVybiB0aGlzLl9pbnZva2UoXG4gICAgICAncmVuYW1lTWV0YWRhdGEnLFxuICAgICAgeyB0eXBlLCBvbGRGdWxsTmFtZSwgbmV3RnVsbE5hbWUgfSxcbiAgICAgIEFwaVNjaGVtYXMuU2F2ZVJlc3VsdCxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgbWV0YWRhdGEgd2hpY2ggZGVzY3JpYmVzIHlvdXIgb3JnYW5pemF0aW9uLCBpbmNsdWRpbmcgQXBleCBjbGFzc2VzIGFuZCB0cmlnZ2VycyxcbiAgICogY3VzdG9tIG9iamVjdHMsIGN1c3RvbSBmaWVsZHMgb24gc3RhbmRhcmQgb2JqZWN0cywgdGFiIHNldHMgdGhhdCBkZWZpbmUgYW4gYXBwLFxuICAgKiBhbmQgbWFueSBvdGhlciBjb21wb25lbnRzLlxuICAgKi9cbiAgZGVzY3JpYmUoYXNPZlZlcnNpb24/OiBzdHJpbmcpOiBQcm9taXNlPERlc2NyaWJlTWV0YWRhdGFSZXN1bHQ+IHtcbiAgICBpZiAoIWFzT2ZWZXJzaW9uKSB7XG4gICAgICBhc09mVmVyc2lvbiA9IHRoaXMuX2Nvbm4udmVyc2lvbjtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2ludm9rZShcbiAgICAgICdkZXNjcmliZU1ldGFkYXRhJyxcbiAgICAgIHsgYXNPZlZlcnNpb24gfSxcbiAgICAgIEFwaVNjaGVtYXMuRGVzY3JpYmVNZXRhZGF0YVJlc3VsdCxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyBwcm9wZXJ0eSBpbmZvcm1hdGlvbiBhYm91dCBtZXRhZGF0YSBjb21wb25lbnRzIGluIHlvdXIgb3JnYW5pemF0aW9uXG4gICAqL1xuICBsaXN0KFxuICAgIHF1ZXJpZXM6IExpc3RNZXRhZGF0YVF1ZXJ5IHwgTGlzdE1ldGFkYXRhUXVlcnlbXSxcbiAgICBhc09mVmVyc2lvbj86IHN0cmluZyxcbiAgKTogUHJvbWlzZTxGaWxlUHJvcGVydGllc1tdPiB7XG4gICAgaWYgKCFhc09mVmVyc2lvbikge1xuICAgICAgYXNPZlZlcnNpb24gPSB0aGlzLl9jb25uLnZlcnNpb247XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9pbnZva2UoJ2xpc3RNZXRhZGF0YScsIHsgcXVlcmllcywgYXNPZlZlcnNpb24gfSwgW1xuICAgICAgQXBpU2NoZW1hcy5GaWxlUHJvcGVydGllcyxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgdGhlIHN0YXR1cyBvZiBhc3luY2hyb25vdXMgbWV0YWRhdGEgY2FsbHNcbiAgICovXG4gIGNoZWNrU3RhdHVzKGFzeW5jUHJvY2Vzc0lkOiBzdHJpbmcpIHtcbiAgICBjb25zdCByZXMgPSB0aGlzLl9pbnZva2UoXG4gICAgICAnY2hlY2tTdGF0dXMnLFxuICAgICAgeyBhc3luY1Byb2Nlc3NJZCB9LFxuICAgICAgQXBpU2NoZW1hcy5Bc3luY1Jlc3VsdCxcbiAgICApO1xuICAgIHJldHVybiBuZXcgQXN5bmNSZXN1bHRMb2NhdG9yKHRoaXMsIHJlcyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIFhNTCBmaWxlIHJlcHJlc2VudGF0aW9ucyBvZiBjb21wb25lbnRzIGluIGFuIG9yZ2FuaXphdGlvblxuICAgKi9cbiAgcmV0cmlldmUocmVxdWVzdDogUGFydGlhbDxSZXRyaWV2ZVJlcXVlc3Q+KSB7XG4gICAgY29uc3QgcmVzID0gdGhpcy5faW52b2tlKFxuICAgICAgJ3JldHJpZXZlJyxcbiAgICAgIHsgcmVxdWVzdCB9LFxuICAgICAgQXBpU2NoZW1hcy5SZXRyaWV2ZVJlc3VsdCxcbiAgICApO1xuICAgIHJldHVybiBuZXcgUmV0cmlldmVSZXN1bHRMb2NhdG9yKHRoaXMsIHJlcyk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHRoZSBzdGF0dXMgb2YgZGVjbGFyYXRpdmUgbWV0YWRhdGEgY2FsbCByZXRyaWV2ZSgpIGFuZCByZXR1cm5zIHRoZSB6aXAgZmlsZSBjb250ZW50c1xuICAgKi9cbiAgY2hlY2tSZXRyaWV2ZVN0YXR1cyhhc3luY1Byb2Nlc3NJZDogc3RyaW5nKTogUHJvbWlzZTxSZXRyaWV2ZVJlc3VsdD4ge1xuICAgIHJldHVybiB0aGlzLl9pbnZva2UoXG4gICAgICAnY2hlY2tSZXRyaWV2ZVN0YXR1cycsXG4gICAgICB7IGFzeW5jUHJvY2Vzc0lkIH0sXG4gICAgICBBcGlTY2hlbWFzLlJldHJpZXZlUmVzdWx0LFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogV2lsbCBkZXBsb3kgYSByZWNlbnRseSB2YWxpZGF0ZWQgZGVwbG95IHJlcXVlc3RcbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMuaWQgPSB0aGUgZGVwbG95IElEIHRoYXQncyBiZWVuIHZhbGlkYXRlZCBhbHJlYWR5IGZyb20gYSBwcmV2aW91cyBjaGVja09ubHkgZGVwbG95IHJlcXVlc3RcbiAgICogQHBhcmFtIG9wdGlvbnMucmVzdCA9IGEgYm9vbGVhbiB3aGV0aGVyIG9yIG5vdCB0byB1c2UgdGhlIFJFU1QgQVBJXG4gICAqIEByZXR1cm5zIHRoZSBkZXBsb3kgSUQgb2YgdGhlIHJlY2VudCB2YWxpZGF0aW9uIHJlcXVlc3RcbiAgICovXG4gIHB1YmxpYyBhc3luYyBkZXBsb3lSZWNlbnRWYWxpZGF0aW9uKG9wdGlvbnM6IHtcbiAgICBpZDogc3RyaW5nO1xuICAgIHJlc3Q/OiBib29sZWFuO1xuICB9KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGlkLCByZXN0IH0gPSBvcHRpb25zO1xuICAgIGxldCByZXNwb25zZTogc3RyaW5nO1xuICAgIGlmIChyZXN0KSB7XG4gICAgICBjb25zdCBtZXNzYWdlQm9keSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgdmFsaWRhdGVkRGVwbG95UmVxdWVzdElkOiBpZCxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXF1ZXN0SW5mbzogSHR0cFJlcXVlc3QgPSB7XG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICB1cmw6IGAke3RoaXMuX2Nvbm4uX2Jhc2VVcmwoKX0vbWV0YWRhdGEvZGVwbG95UmVxdWVzdGAsXG4gICAgICAgIGJvZHk6IG1lc3NhZ2VCb2R5LFxuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgJ2NvbnRlbnQtdHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IHsgaGVhZGVyczogJ2pzb24nIH07XG4gICAgICAvLyBUaGlzIGlzIHRoZSBkZXBsb3kgSUQgb2YgdGhlIGRlcGxveVJlY2VudFZhbGlkYXRpb24gcmVzcG9uc2UsIG5vdFxuICAgICAgLy8gdGhlIGFscmVhZHkgdmFsaWRhdGVkIGRlcGxveSBJRCAoaS5lLiwgdmFsaWRhdGVkZGVwbG95cmVxdWVzdGlkKS5cbiAgICAgIC8vIFJFU1QgcmV0dXJucyBhbiBvYmplY3Qgd2l0aCBhbiBpZCBwcm9wZXJ0eSwgU09BUCByZXR1cm5zIHRoZSBpZCBhcyBhIHN0cmluZyBkaXJlY3RseS5cbiAgICAgIHJlc3BvbnNlID0gKFxuICAgICAgICBhd2FpdCB0aGlzLl9jb25uLnJlcXVlc3Q8eyBpZDogc3RyaW5nIH0+KHJlcXVlc3RJbmZvLCByZXF1ZXN0T3B0aW9ucylcbiAgICAgICkuaWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3BvbnNlID0gYXdhaXQgdGhpcy5faW52b2tlKCdkZXBsb3lSZWNlbnRWYWxpZGF0aW9uJywge1xuICAgICAgICB2YWxpZGF0aW9uSWQ6IGlkLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG5cbiAgLyoqXG4gICAqIERlcGxveSBjb21wb25lbnRzIGludG8gYW4gb3JnYW5pemF0aW9uIHVzaW5nIHppcHBlZCBmaWxlIHJlcHJlc2VudGF0aW9uc1xuICAgKiB1c2luZyB0aGUgUkVTVCBNZXRhZGF0YSBBUEkgaW5zdGVhZCBvZiBTT0FQXG4gICAqL1xuICBkZXBsb3lSZXN0KFxuICAgIHppcElucHV0OiBCdWZmZXIsXG4gICAgb3B0aW9uczogUGFydGlhbDxEZXBsb3lPcHRpb25zPiA9IHt9LFxuICApOiBEZXBsb3lSZXN1bHRMb2NhdG9yPFM+IHtcbiAgICBjb25zdCBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgZm9ybS5hcHBlbmQoJ2ZpbGUnLCB6aXBJbnB1dCwge1xuICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi96aXAnLFxuICAgICAgZmlsZW5hbWU6ICdwYWNrYWdlLnhtbCcsXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgdGhlIGRlcGxveSBvcHRpb25zXG4gICAgZm9ybS5hcHBlbmQoJ2VudGl0eV9jb250ZW50JywgSlNPTi5zdHJpbmdpZnkoeyBkZXBsb3lPcHRpb25zOiBvcHRpb25zIH0pLCB7XG4gICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVxdWVzdDogSHR0cFJlcXVlc3QgPSB7XG4gICAgICB1cmw6ICcvbWV0YWRhdGEvZGVwbG95UmVxdWVzdCcsXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHsgLi4uZm9ybS5nZXRIZWFkZXJzKCkgfSxcbiAgICAgIGJvZHk6IGZvcm0uZ2V0QnVmZmVyKCksXG4gICAgfTtcbiAgICBjb25zdCByZXMgPSB0aGlzLl9jb25uLnJlcXVlc3Q8QXN5bmNSZXN1bHQ+KHJlcXVlc3QpO1xuXG4gICAgcmV0dXJuIG5ldyBEZXBsb3lSZXN1bHRMb2NhdG9yKHRoaXMsIHJlcyk7XG4gIH1cblxuICAvKipcbiAgICogRGVwbG95IGNvbXBvbmVudHMgaW50byBhbiBvcmdhbml6YXRpb24gdXNpbmcgemlwcGVkIGZpbGUgcmVwcmVzZW50YXRpb25zXG4gICAqL1xuICBkZXBsb3koXG4gICAgemlwSW5wdXQ6IFJlYWRhYmxlIHwgQnVmZmVyIHwgc3RyaW5nLFxuICAgIG9wdGlvbnM6IFBhcnRpYWw8RGVwbG95T3B0aW9ucz4gPSB7fSxcbiAgKTogRGVwbG95UmVzdWx0TG9jYXRvcjxTPiB7XG4gICAgY29uc3QgcmVzID0gKGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHppcENvbnRlbnRCNjQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBpc09iamVjdCh6aXBJbnB1dCkgJiZcbiAgICAgICAgICAncGlwZScgaW4gemlwSW5wdXQgJiZcbiAgICAgICAgICB0eXBlb2YgemlwSW5wdXQucGlwZSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCBidWZzOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgICAgIHppcElucHV0Lm9uKCdkYXRhJywgKGQpID0+IGJ1ZnMucHVzaChkKSk7XG4gICAgICAgICAgemlwSW5wdXQub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgICAgICB6aXBJbnB1dC5vbignZW5kJywgKCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZShCdWZmZXIuY29uY2F0KGJ1ZnMpLnRvU3RyaW5nKCdiYXNlNjQnKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgLy8gemlwSW5wdXQucmVzdW1lKCk7XG4gICAgICAgIH0gZWxzZSBpZiAo