UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

407 lines (405 loc) 51 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.filesToDataPayload = filesToDataPayload; exports.isArrowData = isArrowData; Object.defineProperty(exports, "isArrowTable", { enumerable: true, get: function get() { return _utils.isArrowTable; } }); exports.isFeature = isFeature; exports.isFeatureCollection = isFeatureCollection; exports.isGeoJson = isGeoJson; exports.isKeplerGlMap = isKeplerGlMap; exports.isRowObject = isRowObject; exports.makeProgressIterator = makeProgressIterator; exports.processFileData = processFileData; exports.readBatch = readBatch; exports.readFileInBatches = readFileInBatches; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _awaitAsyncGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/awaitAsyncGenerator")); var _wrapAsyncGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/wrapAsyncGenerator")); var _core = require("@loaders.gl/core"); var _json = require("@loaders.gl/json"); var _csv = require("@loaders.gl/csv"); var _arrow = require("@loaders.gl/arrow"); var _parquet = require("@loaders.gl/parquet"); var _utils = require("@kepler.gl/utils"); var _commonUtils = require("@kepler.gl/common-utils"); var _constants = require("@kepler.gl/constants"); var _table = require("@kepler.gl/table"); var _dataProcessor = require("./data-processor"); function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(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 t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _asyncIterator(r) { var n, t, o, e = 2; for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) { if (t && null != (n = r[t])) return n.call(r); if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r)); t = "@@asyncIterator", o = "@@iterator"; } throw new TypeError("Object is not async iterable"); } function AsyncFromSyncIterator(r) { function AsyncFromSyncIteratorContinuation(r) { if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); var n = r.done; return Promise.resolve(r.value).then(function (r) { return { value: r, done: n }; }); } return AsyncFromSyncIterator = function AsyncFromSyncIterator(r) { this.s = r, this.n = r.next; }, AsyncFromSyncIterator.prototype = { s: null, n: null, next: function next() { return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); }, "return": function _return(r) { var n = this.s["return"]; return void 0 === n ? Promise.resolve({ value: r, done: !0 }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); }, "throw": function _throw(r) { var n = this.s["return"]; return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); } }, new AsyncFromSyncIterator(r); } // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project var BATCH_TYPE = { METADATA: 'metadata', PARTIAL_RESULT: 'partial-result', FINAL_RESULT: 'final-result' }; var CSV_LOADER_OPTIONS = { shape: 'object-row-table', dynamicTyping: false // not working for now }; var ARROW_LOADER_OPTIONS = { shape: 'arrow-table', batchDebounceMs: 10 // time to delay between batches, for incremental loading }; var PARQUET_LOADER_OPTIONS = { shape: 'arrow-table' }; var JSON_LOADER_OPTIONS = { shape: 'object-row-table', // instruct loaders.gl on what json paths to stream jsonpaths: ['$', // JSON Row array '$.features', // GeoJSON '$.datasets' // KeplerGL JSON ] }; /** * check if data is an ArrowData object, which is an array of RecordBatch * @param data - object to check * @returns {boolean} - true if data is an ArrowData object type guarded */ function isArrowData(data) { return Array.isArray(data) && Boolean(data.length && data[0].data && data[0].schema); } function isGeoJson(json) { // json can be feature collection // or single feature return (0, _utils.isPlainObject)(json) && (isFeature(json) || isFeatureCollection(json)); } function isFeature(json) { return (0, _utils.isPlainObject)(json) && json.type === 'Feature' && Boolean(json.geometry); } function isFeatureCollection(json) { return (0, _utils.isPlainObject)(json) && json.type === 'FeatureCollection' && Boolean(json.features); } function isRowObject(json) { return Array.isArray(json) && (0, _utils.isPlainObject)(json[0]); } function isKeplerGlMap(json) { return Boolean((0, _utils.isPlainObject)(json) && json.datasets && json.config && json.info && (0, _utils.isPlainObject)(json.info) && json.info.app === 'kepler.gl'); } function makeProgressIterator(_x, _x2) { return _makeProgressIterator.apply(this, arguments); } // eslint-disable-next-line complexity function _makeProgressIterator() { _makeProgressIterator = (0, _wrapAsyncGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(asyncIterator, info) { var rowCount, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, batch, rowCountInBatch, percent, progress; return _regenerator["default"].wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: rowCount = 0; _iteratorAbruptCompletion = false; _didIteratorError = false; _context.prev = 3; _iterator = _asyncIterator(asyncIterator); case 5: _context.next = 7; return (0, _awaitAsyncGenerator2["default"])(_iterator.next()); case 7: if (!(_iteratorAbruptCompletion = !(_step = _context.sent).done)) { _context.next = 18; break; } batch = _step.value; // the length could be stored in `batch.length` for arrow batch rowCountInBatch = batch.data && (batch.data.length || batch.length) || 0; rowCount += rowCountInBatch; percent = Number.isFinite(batch.bytesUsed) ? batch.bytesUsed / info.size : null; // Update progress object progress = _objectSpread({ rowCount: rowCount, rowCountInBatch: rowCountInBatch }, Number.isFinite(percent) ? { percent: percent } : {}); _context.next = 15; return _objectSpread(_objectSpread({}, batch), {}, { progress: progress }); case 15: _iteratorAbruptCompletion = false; _context.next = 5; break; case 18: _context.next = 24; break; case 20: _context.prev = 20; _context.t0 = _context["catch"](3); _didIteratorError = true; _iteratorError = _context.t0; case 24: _context.prev = 24; _context.prev = 25; if (!(_iteratorAbruptCompletion && _iterator["return"] != null)) { _context.next = 29; break; } _context.next = 29; return (0, _awaitAsyncGenerator2["default"])(_iterator["return"]()); case 29: _context.prev = 29; if (!_didIteratorError) { _context.next = 32; break; } throw _iteratorError; case 32: return _context.finish(29); case 33: return _context.finish(24); case 34: case "end": return _context.stop(); } }, _callee, null, [[3, 20, 24, 34], [25,, 29, 33]]); })); return _makeProgressIterator.apply(this, arguments); } function readBatch(_x3, _x4) { return _readBatch.apply(this, arguments); } function _readBatch() { _readBatch = (0, _wrapAsyncGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(asyncIterator, fileName) { var result, batches, _iteratorAbruptCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, batch, streamingPath, batchData, i; return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: result = null; batches = []; _iteratorAbruptCompletion2 = false; _didIteratorError2 = false; _context2.prev = 4; _iterator2 = _asyncIterator(asyncIterator); case 6: _context2.next = 8; return (0, _awaitAsyncGenerator2["default"])(_iterator2.next()); case 8: if (!(_iteratorAbruptCompletion2 = !(_step2 = _context2.sent).done)) { _context2.next = 16; break; } batch = _step2.value; // Last batch will have this special type and will provide all the root // properties of the parsed document. // Only json parse will have `FINAL_RESULT` if (batch.batchType === BATCH_TYPE.FINAL_RESULT) { if (batch.container) { result = _objectSpread({}, batch.container); } // Set the streamed data correctly is Batch json path is set // and the path streamed is not the top level object (jsonpath = '$') if (batch.jsonpath && batch.jsonpath.length > 1) { streamingPath = new _json._JSONPath(batch.jsonpath); streamingPath.setFieldAtPath(result, batches); } else if (batch.jsonpath && batch.jsonpath.length === 1) { // The streamed object is a ROW JSON-batch (jsonpath = '$') // row objects result = batches; } } else { batchData = (0, _utils.isArrowTable)(batch.data) ? batch.data.batches : batch.data; for (i = 0; i < (batchData === null || batchData === void 0 ? void 0 : batchData.length); i++) { batches.push(batchData[i]); } } _context2.next = 13; return _objectSpread(_objectSpread(_objectSpread({}, batch), batch.schema ? { headers: Object.keys(batch.schema) } : {}), {}, { fileName: fileName, // if dataset is CSV, data is set to the raw batches data: result ? result : batches }); case 13: _iteratorAbruptCompletion2 = false; _context2.next = 6; break; case 16: _context2.next = 22; break; case 18: _context2.prev = 18; _context2.t0 = _context2["catch"](4); _didIteratorError2 = true; _iteratorError2 = _context2.t0; case 22: _context2.prev = 22; _context2.prev = 23; if (!(_iteratorAbruptCompletion2 && _iterator2["return"] != null)) { _context2.next = 27; break; } _context2.next = 27; return (0, _awaitAsyncGenerator2["default"])(_iterator2["return"]()); case 27: _context2.prev = 27; if (!_didIteratorError2) { _context2.next = 30; break; } throw _iteratorError2; case 30: return _context2.finish(27); case 31: return _context2.finish(22); case 32: case "end": return _context2.stop(); } }, _callee2, null, [[4, 18, 22, 32], [23,, 27, 31]]); })); return _readBatch.apply(this, arguments); } function readFileInBatches(_x5) { return _readFileInBatches.apply(this, arguments); } function _readFileInBatches() { _readFileInBatches = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(_ref) { var file, _ref$loaders, loaders, _ref$loadOptions, loadOptions, batchIterator, progressIterator; return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: file = _ref.file, _ref$loaders = _ref.loaders, loaders = _ref$loaders === void 0 ? [] : _ref$loaders, _ref$loadOptions = _ref.loadOptions, loadOptions = _ref$loadOptions === void 0 ? {} : _ref$loadOptions; loaders = [_json.JSONLoader, _csv.CSVLoader, _arrow.GeoArrowLoader, _parquet.ParquetWasmLoader].concat((0, _toConsumableArray2["default"])(loaders)); loadOptions = _objectSpread({ csv: CSV_LOADER_OPTIONS, arrow: ARROW_LOADER_OPTIONS, json: JSON_LOADER_OPTIONS, parquet: PARQUET_LOADER_OPTIONS, metadata: true }, loadOptions); _context3.next = 5; return (0, _core.parseInBatches)(file, loaders, loadOptions); case 5: batchIterator = _context3.sent; progressIterator = makeProgressIterator(batchIterator, { size: file.size }); return _context3.abrupt("return", readBatch(progressIterator, file.name)); case 8: case "end": return _context3.stop(); } }, _callee3); })); return _readFileInBatches.apply(this, arguments); } function processFileData(_x6) { return _processFileData.apply(this, arguments); } function _processFileData() { _processFileData = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(_ref2) { var _getApplicationConfig; var content, fileCache, fileName, data, format, processor, id, table, processorResult, result; return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: content = _ref2.content, fileCache = _ref2.fileCache; fileName = content.fileName, data = content.data; // generate unique id with length of 4 using fileName string id = (0, _utils.generateHashIdFromString)(fileName); // decide on which table class to use based on application config table = (_getApplicationConfig = (0, _utils.getApplicationConfig)().table) !== null && _getApplicationConfig !== void 0 ? _getApplicationConfig : _table.KeplerTable; if (typeof table.getFileProcessor === 'function') { // use custom processors from table class processorResult = table.getFileProcessor(data); format = processorResult.format; processor = processorResult.processor; } else { // use default processors if (isArrowData(data)) { format = _constants.DATASET_FORMATS.arrow; processor = _dataProcessor.processArrowBatches; } else if (isKeplerGlMap(data)) { format = _constants.DATASET_FORMATS.keplergl; processor = _dataProcessor.processKeplerglJSON; } else if (isRowObject(data)) { // csv file goes here format = _constants.DATASET_FORMATS.row; processor = _dataProcessor.processRowObject; } else if (isGeoJson(data)) { format = _constants.DATASET_FORMATS.geojson; processor = _dataProcessor.processGeojson; } } if (!(format && processor)) { _context4.next = 18; break; } _context4.prev = 6; _context4.next = 9; return processor(data); case 9: result = _context4.sent; _context4.next = 15; break; case 12: _context4.prev = 12; _context4.t0 = _context4["catch"](6); throw new Error("Can not process uploaded file, ".concat((0, _utils.getError)(_context4.t0))); case 15: return _context4.abrupt("return", [].concat((0, _toConsumableArray2["default"])(fileCache), [{ data: result, info: { id: id, label: content.fileName, format: format } }])); case 18: throw new Error('Can not process uploaded file, unknown file format'); case 19: case "end": return _context4.stop(); } }, _callee4, null, [[6, 12]]); })); return _processFileData.apply(this, arguments); } function filesToDataPayload(fileCache) { // seperate out files which could be a single datasets. or a keplergl map json var collection = fileCache.reduce(function (accu, file) { var data = file.data, info = file.info; if ((info === null || info === void 0 ? void 0 : info.format) === _constants.DATASET_FORMATS.keplergl) { // if file contains a single kepler map dataset & config accu.keplerMaps.push(_objectSpread(_objectSpread({}, data), {}, { options: { centerMap: !(data.config && data.config.mapState) } })); } else if (_constants.DATASET_FORMATS[info === null || info === void 0 ? void 0 : info.format]) { // if file contains only data var newDataset = { data: data, info: _objectSpread({ id: (info === null || info === void 0 ? void 0 : info.id) || (0, _commonUtils.generateHashId)(4) }, info || {}) }; accu.datasets.push(newDataset); } return accu; }, { datasets: [], keplerMaps: [] }); // add kepler map first with config // add datasets later in one add data call return collection.keplerMaps.concat({ datasets: collection.datasets }); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29yZSIsInJlcXVpcmUiLCJfanNvbiIsIl9jc3YiLCJfYXJyb3ciLCJfcGFycXVldCIsIl91dGlscyIsIl9jb21tb25VdGlscyIsIl9jb25zdGFudHMiLCJfdGFibGUiLCJfZGF0YVByb2Nlc3NvciIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlZmluZVByb3BlcnR5IiwiX2FzeW5jSXRlcmF0b3IiLCJuIiwiU3ltYm9sIiwiYXN5bmNJdGVyYXRvciIsIml0ZXJhdG9yIiwiY2FsbCIsIkFzeW5jRnJvbVN5bmNJdGVyYXRvciIsIlR5cGVFcnJvciIsIkFzeW5jRnJvbVN5bmNJdGVyYXRvckNvbnRpbnVhdGlvbiIsIlByb21pc2UiLCJyZWplY3QiLCJkb25lIiwicmVzb2x2ZSIsInZhbHVlIiwidGhlbiIsInMiLCJuZXh0IiwicHJvdG90eXBlIiwiX3JldHVybiIsIl90aHJvdyIsIkJBVENIX1RZUEUiLCJNRVRBREFUQSIsIlBBUlRJQUxfUkVTVUxUIiwiRklOQUxfUkVTVUxUIiwiQ1NWX0xPQURFUl9PUFRJT05TIiwic2hhcGUiLCJkeW5hbWljVHlwaW5nIiwiQVJST1dfTE9BREVSX09QVElPTlMiLCJiYXRjaERlYm91bmNlTXMiLCJQQVJRVUVUX0xPQURFUl9PUFRJT05TIiwiSlNPTl9MT0FERVJfT1BUSU9OUyIsImpzb25wYXRocyIsImlzQXJyb3dEYXRhIiwiZGF0YSIsIkFycmF5IiwiaXNBcnJheSIsIkJvb2xlYW4iLCJzY2hlbWEiLCJpc0dlb0pzb24iLCJqc29uIiwiaXNQbGFpbk9iamVjdCIsImlzRmVhdHVyZSIsImlzRmVhdHVyZUNvbGxlY3Rpb24iLCJ0eXBlIiwiZ2VvbWV0cnkiLCJmZWF0dXJlcyIsImlzUm93T2JqZWN0IiwiaXNLZXBsZXJHbE1hcCIsImRhdGFzZXRzIiwiY29uZmlnIiwiaW5mbyIsImFwcCIsIm1ha2VQcm9ncmVzc0l0ZXJhdG9yIiwiX3giLCJfeDIiLCJfbWFrZVByb2dyZXNzSXRlcmF0b3IiLCJfd3JhcEFzeW5jR2VuZXJhdG9yMiIsIl9yZWdlbmVyYXRvciIsIm1hcmsiLCJfY2FsbGVlIiwicm93Q291bnQiLCJfaXRlcmF0b3JBYnJ1cHRDb21wbGV0aW9uIiwiX2RpZEl0ZXJhdG9yRXJyb3IiLCJfaXRlcmF0b3JFcnJvciIsIl9pdGVyYXRvciIsIl9zdGVwIiwiYmF0Y2giLCJyb3dDb3VudEluQmF0Y2giLCJwZXJjZW50IiwicHJvZ3Jlc3MiLCJ3cmFwIiwiX2NhbGxlZSQiLCJfY29udGV4dCIsInByZXYiLCJfYXdhaXRBc3luY0dlbmVyYXRvcjIiLCJzZW50IiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJieXRlc1VzZWQiLCJzaXplIiwidDAiLCJmaW5pc2giLCJzdG9wIiwicmVhZEJhdGNoIiwiX3gzIiwiX3g0IiwiX3JlYWRCYXRjaCIsIl9jYWxsZWUyIiwiZmlsZU5hbWUiLCJyZXN1bHQiLCJiYXRjaGVzIiwiX2l0ZXJhdG9yQWJydXB0Q29tcGxldGlvbjIiLCJfZGlkSXRlcmF0b3JFcnJvcjIiLCJfaXRlcmF0b3JFcnJvcjIiLCJfaXRlcmF0b3IyIiwiX3N0ZXAyIiwic3RyZWFtaW5nUGF0aCIsImJhdGNoRGF0YSIsImkiLCJfY2FsbGVlMiQiLCJfY29udGV4dDIiLCJiYXRjaFR5cGUiLCJjb250YWluZXIiLCJqc29ucGF0aCIsIl9KU09OUGF0aCIsInNldEZpZWxkQXRQYXRoIiwiaXNBcnJvd1RhYmxlIiwiaGVhZGVycyIsInJlYWRGaWxlSW5CYXRjaGVzIiwiX3g1IiwiX3JlYWRGaWxlSW5CYXRjaGVzIiwiX2FzeW5jVG9HZW5lcmF0b3IyIiwiX2NhbGxlZTMiLCJfcmVmIiwiZmlsZSIsIl9yZWYkbG9hZGVycyIsImxvYWRlcnMiLCJfcmVmJGxvYWRPcHRpb25zIiwibG9hZE9wdGlvbnMiLCJiYXRjaEl0ZXJhdG9yIiwicHJvZ3Jlc3NJdGVyYXRvciIsIl9jYWxsZWUzJCIsIl9jb250ZXh0MyIsIkpTT05Mb2FkZXIiLCJDU1ZMb2FkZXIiLCJHZW9BcnJvd0xvYWRlciIsIlBhcnF1ZXRXYXNtTG9hZGVyIiwiY29uY2F0IiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsImNzdiIsImFycm93IiwicGFycXVldCIsIm1ldGFkYXRhIiwicGFyc2VJbkJhdGNoZXMiLCJhYnJ1cHQiLCJuYW1lIiwicHJvY2Vzc0ZpbGVEYXRhIiwiX3g2IiwiX3Byb2Nlc3NGaWxlRGF0YSIsIl9jYWxsZWU0IiwiX3JlZjIiLCJfZ2V0QXBwbGljYXRpb25Db25maWciLCJjb250ZW50IiwiZmlsZUNhY2hlIiwiZm9ybWF0IiwicHJvY2Vzc29yIiwiaWQiLCJ0YWJsZSIsInByb2Nlc3NvclJlc3VsdCIsIl9jYWxsZWU0JCIsIl9jb250ZXh0NCIsImdlbmVyYXRlSGFzaElkRnJvbVN0cmluZyIsImdldEFwcGxpY2F0aW9uQ29uZmlnIiwiS2VwbGVyVGFibGUiLCJnZXRGaWxlUHJvY2Vzc29yIiwiREFUQVNFVF9GT1JNQVRTIiwicHJvY2Vzc0Fycm93QmF0Y2hlcyIsImtlcGxlcmdsIiwicHJvY2Vzc0tlcGxlcmdsSlNPTiIsInJvdyIsInByb2Nlc3NSb3dPYmplY3QiLCJnZW9qc29uIiwicHJvY2Vzc0dlb2pzb24iLCJFcnJvciIsImdldEVycm9yIiwibGFiZWwiLCJmaWxlc1RvRGF0YVBheWxvYWQiLCJjb2xsZWN0aW9uIiwicmVkdWNlIiwiYWNjdSIsImtlcGxlck1hcHMiLCJvcHRpb25zIiwiY2VudGVyTWFwIiwibWFwU3RhdGUiLCJuZXdEYXRhc2V0IiwiZ2VuZXJhdGVIYXNoSWQiXSwic291cmNlcyI6WyIuLi9zcmMvZmlsZS1oYW5kbGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCB7cGFyc2VJbkJhdGNoZXN9IGZyb20gJ0Bsb2FkZXJzLmdsL2NvcmUnO1xuaW1wb3J0IHtKU09OTG9hZGVyLCBfSlNPTlBhdGh9IGZyb20gJ0Bsb2FkZXJzLmdsL2pzb24nO1xuaW1wb3J0IHtDU1ZMb2FkZXJ9IGZyb20gJ0Bsb2FkZXJzLmdsL2Nzdic7XG5pbXBvcnQge0dlb0Fycm93TG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9hcnJvdyc7XG5pbXBvcnQge1BhcnF1ZXRXYXNtTG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9wYXJxdWV0JztcbmltcG9ydCB7TG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9sb2FkZXItdXRpbHMnO1xuaW1wb3J0IHtcbiAgaXNQbGFpbk9iamVjdCxcbiAgZ2VuZXJhdGVIYXNoSWRGcm9tU3RyaW5nLFxuICBnZXRBcHBsaWNhdGlvbkNvbmZpZyxcbiAgZ2V0RXJyb3IsXG4gIGlzQXJyb3dUYWJsZVxufSBmcm9tICdAa2VwbGVyLmdsL3V0aWxzJztcbmltcG9ydCB7Z2VuZXJhdGVIYXNoSWR9IGZyb20gJ0BrZXBsZXIuZ2wvY29tbW9uLXV0aWxzJztcbmltcG9ydCB7REFUQVNFVF9GT1JNQVRTfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5pbXBvcnQge0FkZERhdGFUb01hcFBheWxvYWQsIEZlYXR1cmUsIExvYWRlZE1hcCwgUHJvY2Vzc29yUmVzdWx0fSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB7S2VwbGVyVGFibGV9IGZyb20gJ0BrZXBsZXIuZ2wvdGFibGUnO1xuaW1wb3J0IHtGZWF0dXJlQ29sbGVjdGlvbn0gZnJvbSAnQHR1cmYvaGVscGVycyc7XG5cbmltcG9ydCB7XG4gIHByb2Nlc3NBcnJvd0JhdGNoZXMsXG4gIHByb2Nlc3NHZW9qc29uLFxuICBwcm9jZXNzS2VwbGVyZ2xKU09OLFxuICBwcm9jZXNzUm93T2JqZWN0XG59IGZyb20gJy4vZGF0YS1wcm9jZXNzb3InO1xuXG5pbXBvcnQge0ZpbGVDYWNoZUl0ZW0sIFZhbGlkS2VwbGVyR2xNYXB9IGZyb20gJy4vdHlwZXMnO1xuXG5jb25zdCBCQVRDSF9UWVBFID0ge1xuICBNRVRBREFUQTogJ21ldGFkYXRhJyxcbiAgUEFSVElBTF9SRVNVTFQ6ICdwYXJ0aWFsLXJlc3VsdCcsXG4gIEZJTkFMX1JFU1VMVDogJ2ZpbmFsLXJlc3VsdCdcbn07XG5cbmNvbnN0IENTVl9MT0FERVJfT1BUSU9OUyA9IHtcbiAgc2hhcGU6ICdvYmplY3Qtcm93LXRhYmxlJyxcbiAgZHluYW1pY1R5cGluZzogZmFsc2UgLy8gbm90IHdvcmtpbmcgZm9yIG5vd1xufTtcblxuY29uc3QgQVJST1dfTE9BREVSX09QVElPTlMgPSB7XG4gIHNoYXBlOiAnYXJyb3ctdGFibGUnLFxuICBiYXRjaERlYm91bmNlTXM6IDEwIC8vIHRpbWUgdG8gZGVsYXkgYmV0d2VlbiBiYXRjaGVzLCBmb3IgaW5jcmVtZW50YWwgbG9hZGluZ1xufTtcblxuY29uc3QgUEFSUVVFVF9MT0FERVJfT1BUSU9OUyA9IHtcbiAgc2hhcGU6ICdhcnJvdy10YWJsZSdcbn07XG5cbmNvbnN0IEpTT05fTE9BREVSX09QVElPTlMgPSB7XG4gIHNoYXBlOiAnb2JqZWN0LXJvdy10YWJsZScsXG4gIC8vIGluc3RydWN0IGxvYWRlcnMuZ2wgb24gd2hhdCBqc29uIHBhdGhzIHRvIHN0cmVhbVxuICBqc29ucGF0aHM6IFtcbiAgICAnJCcsIC8vIEpTT04gUm93IGFycmF5XG4gICAgJyQuZmVhdHVyZXMnLCAvLyBHZW9KU09OXG4gICAgJyQuZGF0YXNldHMnIC8vIEtlcGxlckdMIEpTT05cbiAgXVxufTtcblxuZXhwb3J0IHR5cGUgUHJvY2Vzc0ZpbGVEYXRhQ29udGVudCA9IHtcbiAgZGF0YTogdW5rbm93bjtcbiAgZmlsZU5hbWU6IHN0cmluZztcbiAgbGVuZ3RoPzogbnVtYmVyO1xuICBwcm9ncmVzcz86IHtyb3dDb3VudD86IG51bWJlcjsgcm93Q291bnRJbkJhdGNoPzogbnVtYmVyOyBwZXJjZW50PzogbnVtYmVyfTtcbiAgLyoqICBtZXRhZGF0YSBlLmcuIGZvciBhcnJvdyBkYXRhLCBtZXRhZGF0YSBjb3VsZCBiZSB0aGUgc2NoZW1hLmZpZWxkcyAqL1xuICBtZXRhZGF0YT86IE1hcDxzdHJpbmcsIHN0cmluZz47XG59O1xuXG5leHBvcnQge2lzQXJyb3dUYWJsZX07XG5cbi8qKlxuICogY2hlY2sgaWYgZGF0YSBpcyBhbiBBcnJvd0RhdGEgb2JqZWN0LCB3aGljaCBpcyBhbiBhcnJheSBvZiBSZWNvcmRCYXRjaFxuICogQHBhcmFtIGRhdGEgLSBvYmplY3QgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIHRydWUgaWYgZGF0YSBpcyBhbiBBcnJvd0RhdGEgb2JqZWN0IHR5cGUgZ3VhcmRlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNBcnJvd0RhdGEoZGF0YTogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGRhdGEpICYmIEJvb2xlYW4oZGF0YS5sZW5ndGggJiYgZGF0YVswXS5kYXRhICYmIGRhdGFbMF0uc2NoZW1hKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzR2VvSnNvbihqc29uOiB1bmtub3duKToganNvbiBpcyBGZWF0dXJlIHwgRmVhdHVyZUNvbGxlY3Rpb24ge1xuICAvLyBqc29uIGNhbiBiZSBmZWF0dXJlIGNvbGxlY3Rpb25cbiAgLy8gb3Igc2luZ2xlIGZlYXR1cmVcbiAgcmV0dXJuIGlzUGxhaW5PYmplY3QoanNvbikgJiYgKGlzRmVhdHVyZShqc29uKSB8fCBpc0ZlYXR1cmVDb2xsZWN0aW9uKGpzb24pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzRmVhdHVyZShqc29uOiB1bmtub3duKToganNvbiBpcyBGZWF0dXJlIHtcbiAgcmV0dXJuIGlzUGxhaW5PYmplY3QoanNvbikgJiYganNvbi50eXBlID09PSAnRmVhdHVyZScgJiYgQm9vbGVhbihqc29uLmdlb21ldHJ5KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzRmVhdHVyZUNvbGxlY3Rpb24oanNvbjogdW5rbm93bik6IGpzb24gaXMgRmVhdHVyZUNvbGxlY3Rpb24ge1xuICByZXR1cm4gaXNQbGFpbk9iamVjdChqc29uKSAmJiBqc29uLnR5cGUgPT09ICdGZWF0dXJlQ29sbGVjdGlvbicgJiYgQm9vbGVhbihqc29uLmZlYXR1cmVzKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzUm93T2JqZWN0KGpzb246IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShqc29uKSAmJiBpc1BsYWluT2JqZWN0KGpzb25bMF0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNLZXBsZXJHbE1hcChqc29uOiB1bmtub3duKToganNvbiBpcyBWYWxpZEtlcGxlckdsTWFwIHtcbiAgcmV0dXJuIEJvb2xlYW4oXG4gICAgaXNQbGFpbk9iamVjdChqc29uKSAmJlxuICAgICAganNvbi5kYXRhc2V0cyAmJlxuICAgICAganNvbi5jb25maWcgJiZcbiAgICAgIGpzb24uaW5mbyAmJlxuICAgICAgaXNQbGFpbk9iamVjdChqc29uLmluZm8pICYmXG4gICAgICBqc29uLmluZm8uYXBwID09PSAna2VwbGVyLmdsJ1xuICApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24qIG1ha2VQcm9ncmVzc0l0ZXJhdG9yKFxuICBhc3luY0l0ZXJhdG9yOiBBc3luY0l0ZXJhYmxlPGFueT4sXG4gIGluZm86IHtzaXplOiBudW1iZXJ9XG4pOiBBc3luY0dlbmVyYXRvciB7XG4gIGxldCByb3dDb3VudCA9IDA7XG5cbiAgZm9yIGF3YWl0IChjb25zdCBiYXRjaCBvZiBhc3luY0l0ZXJhdG9yKSB7XG4gICAgLy8gdGhlIGxlbmd0aCBjb3VsZCBiZSBzdG9yZWQgaW4gYGJhdGNoLmxlbmd0aGAgZm9yIGFycm93IGJhdGNoXG4gICAgY29uc3Qgcm93Q291bnRJbkJhdGNoID0gKGJhdGNoLmRhdGEgJiYgKGJhdGNoLmRhdGEubGVuZ3RoIHx8IGJhdGNoLmxlbmd0aCkpIHx8IDA7XG4gICAgcm93Q291bnQgKz0gcm93Q291bnRJbkJhdGNoO1xuICAgIGNvbnN0IHBlcmNlbnQgPSBOdW1iZXIuaXNGaW5pdGUoYmF0Y2guYnl0ZXNVc2VkKSA/IGJhdGNoLmJ5dGVzVXNlZCAvIGluZm8uc2l6ZSA6IG51bGw7XG5cbiAgICAvLyBVcGRhdGUgcHJvZ3Jlc3Mgb2JqZWN0XG4gICAgY29uc3QgcHJvZ3Jlc3MgPSB7XG4gICAgICByb3dDb3VudCxcbiAgICAgIHJvd0NvdW50SW5CYXRjaCxcbiAgICAgIC4uLihOdW1iZXIuaXNGaW5pdGUocGVyY2VudCkgPyB7cGVyY2VudH0gOiB7fSlcbiAgICB9O1xuXG4gICAgeWllbGQgey4uLmJhdGNoLCBwcm9ncmVzc307XG4gIH1cbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiogcmVhZEJhdGNoKFxuICBhc3luY0l0ZXJhdG9yOiBBc3luY0l0ZXJhYmxlPGFueT4sXG4gIGZpbGVOYW1lOiBzdHJpbmdcbik6IEFzeW5jR2VuZXJhdG9yIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG4gIGNvbnN0IGJhdGNoZXMgPSA8YW55PltdO1xuICBmb3IgYXdhaXQgKGNvbnN0IGJhdGNoIG9mIGFzeW5jSXRlcmF0b3IpIHtcbiAgICAvLyBMYXN0IGJhdGNoIHdpbGwgaGF2ZSB0aGlzIHNwZWNpYWwgdHlwZSBhbmQgd2lsbCBwcm92aWRlIGFsbCB0aGUgcm9vdFxuICAgIC8vIHByb3BlcnRpZXMgb2YgdGhlIHBhcnNlZCBkb2N1bWVudC5cbiAgICAvLyBPbmx5IGpzb24gcGFyc2Ugd2lsbCBoYXZlIGBGSU5BTF9SRVNVTFRgXG4gICAgaWYgKGJhdGNoLmJhdGNoVHlwZSA9PT0gQkFUQ0hfVFlQRS5GSU5BTF9SRVNVTFQpIHtcbiAgICAgIGlmIChiYXRjaC5jb250YWluZXIpIHtcbiAgICAgICAgcmVzdWx0ID0gey4uLmJhdGNoLmNvbnRhaW5lcn07XG4gICAgICB9XG4gICAgICAvLyBTZXQgdGhlIHN0cmVhbWVkIGRhdGEgY29ycmVjdGx5IGlzIEJhdGNoIGpzb24gcGF0aCBpcyBzZXRcbiAgICAgIC8vIGFuZCB0aGUgcGF0aCBzdHJlYW1lZCBpcyBub3QgdGhlIHRvcCBsZXZlbCBvYmplY3QgKGpzb25wYXRoID0gJyQnKVxuICAgICAgaWYgKGJhdGNoLmpzb25wYXRoICYmIGJhdGNoLmpzb25wYXRoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgY29uc3Qgc3RyZWFtaW5nUGF0aCA9IG5ldyBfSlNPTlBhdGgoYmF0Y2guanNvbnBhdGgpO1xuICAgICAgICBzdHJlYW1pbmdQYXRoLnNldEZpZWxkQXRQYXRoKHJlc3VsdCwgYmF0Y2hlcyk7XG4gICAgICB9IGVsc2UgaWYgKGJhdGNoLmpzb25wYXRoICYmIGJhdGNoLmpzb25wYXRoLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAvLyBUaGUgc3RyZWFtZWQgb2JqZWN0IGlzIGEgUk9XIEpTT04tYmF0Y2ggKGpzb25wYXRoID0gJyQnKVxuICAgICAgICAvLyByb3cgb2JqZWN0c1xuICAgICAgICByZXN1bHQgPSBiYXRjaGVzO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBiYXRjaERhdGEgPSBpc0Fycm93VGFibGUoYmF0Y2guZGF0YSkgPyBiYXRjaC5kYXRhLmJhdGNoZXMgOiBiYXRjaC5kYXRhO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBiYXRjaERhdGE/Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGJhdGNoZXMucHVzaChiYXRjaERhdGFbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHlpZWxkIHtcbiAgICAgIC4uLmJhdGNoLFxuICAgICAgLi4uKGJhdGNoLnNjaGVtYSA/IHtoZWFkZXJzOiBPYmplY3Qua2V5cyhiYXRjaC5zY2hlbWEpfSA6IHt9KSxcbiAgICAgIGZpbGVOYW1lLFxuICAgICAgLy8gaWYgZGF0YXNldCBpcyBDU1YsIGRhdGEgaXMgc2V0IHRvIHRoZSByYXcgYmF0Y2hlc1xuICAgICAgZGF0YTogcmVzdWx0ID8gcmVzdWx0IDogYmF0Y2hlc1xuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRGaWxlSW5CYXRjaGVzKHtcbiAgZmlsZSxcbiAgbG9hZGVycyA9IFtdLFxuICBsb2FkT3B0aW9ucyA9IHt9XG59OiB7XG4gIGZpbGU6IEZpbGU7XG4gIGZpbGVDYWNoZTogRmlsZUNhY2hlSXRlbVtdO1xuICBsb2FkZXJzOiBMb2FkZXJbXTtcbiAgbG9hZE9wdGlvbnM6IGFueTtcbn0pOiBQcm9taXNlPEFzeW5jR2VuZXJhdG9yPiB7XG4gIGxvYWRlcnMgPSBbSlNPTkxvYWRlciwgQ1NWTG9hZGVyLCBHZW9BcnJvd0xvYWRlciwgUGFycXVldFdhc21Mb2FkZXIsIC4uLmxvYWRlcnNdO1xuICBsb2FkT3B0aW9ucyA9IHtcbiAgICBjc3Y6IENTVl9MT0FERVJfT1BUSU9OUyxcbiAgICBhcnJvdzogQVJST1dfTE9BREVSX09QVElPTlMsXG4gICAganNvbjogSlNPTl9MT0FERVJfT1BUSU9OUyxcbiAgICBwYXJxdWV0OiBQQVJRVUVUX0xPQURFUl9PUFRJT05TLFxuICAgIG1ldGFkYXRhOiB0cnVlLFxuICAgIC4uLmxvYWRPcHRpb25zXG4gIH07XG5cbiAgY29uc3QgYmF0Y2hJdGVyYXRvciA9IGF3YWl0IHBhcnNlSW5CYXRjaGVzKGZpbGUsIGxvYWRlcnMsIGxvYWRPcHRpb25zKTtcbiAgY29uc3QgcHJvZ3Jlc3NJdGVyYXRvciA9IG1ha2VQcm9ncmVzc0l0ZXJhdG9yKGJhdGNoSXRlcmF0b3IsIHtzaXplOiBmaWxlLnNpemV9KTtcblxuICByZXR1cm4gcmVhZEJhdGNoKHByb2dyZXNzSXRlcmF0b3IsIGZpbGUubmFtZSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcm9jZXNzRmlsZURhdGEoe1xuICBjb250ZW50LFxuICBmaWxlQ2FjaGVcbn06IHtcbiAgY29udGVudDogUHJvY2Vzc0ZpbGVEYXRhQ29udGVudDtcbiAgZmlsZUNhY2hlOiBGaWxlQ2FjaGVJdGVtW107XG59KTogUHJvbWlzZTxGaWxlQ2FjaGVJdGVtW10+IHtcbiAgY29uc3Qge2ZpbGVOYW1lLCBkYXRhfSA9IGNvbnRlbnQ7XG4gIGxldCBmb3JtYXQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgbGV0IHByb2Nlc3NvcjogKChkYXRhOiBhbnkpID0+IFByb2Nlc3NvclJlc3VsdCB8IExvYWRlZE1hcCB8IG51bGwpIHwgdW5kZWZpbmVkO1xuICAvLyBnZW5lcmF0ZSB1bmlxdWUgaWQgd2l0aCBsZW5ndGggb2YgNCB1c2luZyBmaWxlTmFtZSBzdHJpbmdcbiAgY29uc3QgaWQgPSBnZW5lcmF0ZUhhc2hJZEZyb21TdHJpbmcoZmlsZU5hbWUpO1xuICAvLyBkZWNpZGUgb24gd2hpY2ggdGFibGUgY2xhc3MgdG8gdXNlIGJhc2VkIG9uIGFwcGxpY2F0aW9uIGNvbmZpZ1xuICBjb25zdCB0YWJsZSA9IGdldEFwcGxpY2F0aW9uQ29uZmlnKCkudGFibGUgPz8gS2VwbGVyVGFibGU7XG5cbiAgaWYgKHR5cGVvZiB0YWJsZS5nZXRGaWxlUHJvY2Vzc29yID09PSAnZnVuY3Rpb24nKSB7XG4gICAgLy8gdXNlIGN1c3RvbSBwcm9jZXNzb3JzIGZyb20gdGFibGUgY2xhc3NcbiAgICBjb25zdCBwcm9jZXNzb3JSZXN1bHQgPSB0YWJsZS5nZXRGaWxlUHJvY2Vzc29yKGRhdGEpO1xuICAgIGZvcm1hdCA9IHByb2Nlc3NvclJlc3VsdC5mb3JtYXQ7XG4gICAgcHJvY2Vzc29yID0gcHJvY2Vzc29yUmVzdWx0LnByb2Nlc3NvcjtcbiAgfSBlbHNlIHtcbiAgICAvLyB1c2UgZGVmYXVsdCBwcm9jZXNzb3JzXG4gICAgaWYgKGlzQXJyb3dEYXRhKGRhdGEpKSB7XG4gICAgICBmb3JtYXQgPSBEQVRBU0VUX0ZPUk1BVFMuYXJyb3c7XG4gICAgICBwcm9jZXNzb3IgPSBwcm9jZXNzQXJyb3dCYXRjaGVzO1xuICAgIH0gZWxzZSBpZiAoaXNLZXBsZXJHbE1hcChkYXRhKSkge1xuICAgICAgZm9ybWF0ID0gREFUQVNFVF9GT1JNQVRTLmtlcGxlcmdsO1xuICAgICAgcHJvY2Vzc29yID0gcHJvY2Vzc0tlcGxlcmdsSlNPTjtcbiAgICB9IGVsc2UgaWYgKGlzUm93T2JqZWN0KGRhdGEpKSB7XG4gICAgICAvLyBjc3YgZmlsZSBnb2VzIGhlcmVcbiAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5yb3c7XG4gICAgICBwcm9jZXNzb3IgPSBwcm9jZXNzUm93T2JqZWN0O1xuICAgIH0gZWxzZSBpZiAoaXNHZW9Kc29uKGRhdGEpKSB7XG4gICAgICBmb3JtYXQgPSBEQVRBU0VUX0ZPUk1BVFMuZ2VvanNvbjtcbiAgICAgIHByb2Nlc3NvciA9IHByb2Nlc3NHZW9qc29uO1xuICAgIH1cbiAgfVxuICBpZiAoZm9ybWF0ICYmIHByb2Nlc3Nvcikge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2VsZXNzLWNhdGNoXG4gICAgbGV0IHJlc3VsdDtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgcHJvY2Vzc29yKGRhdGEpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbiBub3QgcHJvY2VzcyB1cGxvYWRlZCBmaWxlLCAke2dldEVycm9yKGVycm9yIGFzIEVycm9yKX1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW1xuICAgICAgLi4uZmlsZUNhY2hlLFxuICAgICAge1xuICAgICAgICBkYXRhOiByZXN1bHQsXG4gICAgICAgIGluZm86IHtcbiAgICAgICAgICBpZCxcbiAgICAgICAgICBsYWJlbDogY29udGVudC5maWxlTmFtZSxcbiAgICAgICAgICBmb3JtYXRcbiAgICAgICAgfVxuICAgICAgfVxuICAgIF07XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IHByb2Nlc3MgdXBsb2FkZWQgZmlsZSwgdW5rbm93biBmaWxlIGZvcm1hdCcpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaWxlc1RvRGF0YVBheWxvYWQoZmlsZUNhY2hlOiBGaWxlQ2FjaGVJdGVtW10pOiBBZGREYXRhVG9NYXBQYXlsb2FkW10ge1xuICAvLyBzZXBlcmF0ZSBvdXQgZmlsZXMgd2hpY2ggY291bGQgYmUgYSBzaW5nbGUgZGF0YXNldHMuIG9yIGEga2VwbGVyZ2wgbWFwIGpzb25cbiAgY29uc3QgY29sbGVjdGlvbiA9IGZpbGVDYWNoZS5yZWR1Y2U8e1xuICAgIGRhdGFzZXRzOiBGaWxlQ2FjaGVJdGVtW107XG4gICAga2VwbGVyTWFwczogQWRkRGF0YVRvTWFwUGF5bG9hZFtdO1xuICB9PihcbiAgICAoYWNjdSwgZmlsZSkgPT4ge1xuICAgICAgY29uc3Qge2RhdGEsIGluZm99ID0gZmlsZTtcbiAgICAgIGlmIChpbmZvPy5mb3JtYXQgPT09IERBVEFTRVRfRk9STUFUUy5rZXBsZXJnbCkge1xuICAgICAgICAvLyBpZiBmaWxlIGNvbnRhaW5zIGEgc2luZ2xlIGtlcGxlciBtYXAgZGF0YXNldCAmIGNvbmZpZ1xuICAgICAgICBhY2N1LmtlcGxlck1hcHMucHVzaCh7XG4gICAgICAgICAgLi4uZGF0YSxcbiAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICBjZW50ZXJNYXA6ICEoZGF0YS5jb25maWcgJiYgZGF0YS5jb25maWcubWFwU3RhdGUpXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoREFUQVNFVF9GT1JNQVRTW2luZm8/LmZvcm1hdF0pIHtcbiAgICAgICAgLy8gaWYgZmlsZSBjb250YWlucyBvbmx5IGRhdGFcbiAgICAgICAgY29uc3QgbmV3RGF0YXNldCA9IHtcbiAgICAgICAgICBkYXRhLFxuICAgICAgICAgIGluZm86IHtcbiAgICAgICAgICAgIGlkOiBpbmZvPy5pZCB8fCBnZW5lcmF0ZUhhc2hJZCg0KSxcbiAgICAgICAgICAgIC4uLihpbmZvIHx8IHt9KVxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgYWNjdS5kYXRhc2V0cy5wdXNoKG5ld0RhdGFzZXQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3U7XG4gICAgfSxcbiAgICB7ZGF0YXNldHM6IFtdLCBrZXBsZXJNYXBzOiBbXX1cbiAgKTtcblxuICAvLyBhZGQga2VwbGVyIG1hcCBmaXJzdCB3aXRoIGNvbmZpZ1xuICAvLyBhZGQgZGF0YXNldHMgbGF0ZXIgaW4gb25lIGFkZCBkYXRhIGNhbGxcbiAgcmV0dXJuIGNvbGxlY3Rpb24ua2VwbGVyTWFwcy5jb25jYXQoe2RhdGFzZXRzOiBjb2xsZWN0aW9uLmRhdGFzZXRzfSk7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsS0FBQSxHQUFBQyxPQUFBO0FBQ0EsSUFBQUMsS0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsSUFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsTUFBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksUUFBQSxHQUFBSixPQUFBO0FBRUEsSUFBQUssTUFBQSxHQUFBTCxPQUFBO0FBT0EsSUFBQU0sWUFBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sVUFBQSxHQUFBUCxPQUFBO0FBRUEsSUFBQVEsTUFBQSxHQUFBUixPQUFBO0FBR0EsSUFBQVMsY0FBQSxHQUFBVCxPQUFBO0FBSzBCLFNBQUFVLFFBQUFDLENBQUEsRUFBQUMsQ0FBQSxRQUFBQyxDQUFBLEdBQUFDLE1BQUEsQ0FBQUMsSUFBQSxDQUFBSixDQUFBLE9BQUFHLE1BQUEsQ0FBQUUscUJBQUEsUUFBQUMsQ0FBQSxHQUFBSCxNQUFBLENBQUFFLHFCQUFBLENBQUFMLENBQUEsR0FBQUMsQ0FBQSxLQUFBSyxDQUFBLEdBQUFBLENBQUEsQ0FBQUMsTUFBQSxXQUFBTixDQUFBLFdBQUFFLE1BQUEsQ0FBQUssd0JBQUEsQ0FBQVIsQ0FBQSxFQUFBQyxDQUFBLEVBQUFRLFVBQUEsT0FBQVAsQ0FBQSxDQUFBUSxJQUFBLENB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