UNPKG

jsforce

Version:

Salesforce API Library for JavaScript

777 lines (752 loc) 80.3 kB
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