UNPKG

kepler.gl

Version:

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

416 lines (413 loc) 54.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.filesToDataPayload = filesToDataPayload; exports.isArrowData = isArrowData; exports.isArrowTable = 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 arrow = _interopRequireWildcard(require("apache-arrow")); 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 _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } 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 table is an ArrowTable object * @param table - object to check * @returns {boolean} - true if table is an ArrowTable object type guarded */ function isArrowTable(table) { return Boolean(table instanceof arrow.Table); } /** * 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 = 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; console.log('Processing file', fileName); // 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 = 19; break; } _context4.prev = 7; _context4.next = 10; return processor(data); case 10: result = _context4.sent; _context4.next = 16; break; case 13: _context4.prev = 13; _context4.t0 = _context4["catch"](7); throw new Error("Can not process uploaded file, ".concat((0, _utils.getError)(_context4.t0))); case 16: return _context4.abrupt("return", [].concat((0, _toConsumableArray2["default"])(fileCache), [{ data: result, info: { id: id, label: content.fileName, format: format } }])); case 19: throw new Error('Can not process uploaded file, unknown file format'); case 20: case "end": return _context4.stop(); } }, _callee4, null, [[7, 13]]); })); 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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhcnJvdyIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwicmVxdWlyZSIsIl9jb3JlIiwiX2pzb24iLCJfY3N2IiwiX2Fycm93IiwiX3BhcnF1ZXQiLCJfdXRpbHMiLCJfY29tbW9uVXRpbHMiLCJfY29uc3RhbnRzIiwiX3RhYmxlIiwiX2RhdGFQcm9jZXNzb3IiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsIl90eXBlb2YiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJvd25LZXlzIiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJfYXN5bmNJdGVyYXRvciIsIlN5bWJvbCIsImFzeW5jSXRlcmF0b3IiLCJpdGVyYXRvciIsIkFzeW5jRnJvbVN5bmNJdGVyYXRvciIsIlR5cGVFcnJvciIsIkFzeW5jRnJvbVN5bmNJdGVyYXRvckNvbnRpbnVhdGlvbiIsIlByb21pc2UiLCJyZWplY3QiLCJkb25lIiwicmVzb2x2ZSIsInZhbHVlIiwidGhlbiIsInMiLCJuZXh0IiwicHJvdG90eXBlIiwiX3JldHVybiIsIl90aHJvdyIsIkJBVENIX1RZUEUiLCJNRVRBREFUQSIsIlBBUlRJQUxfUkVTVUxUIiwiRklOQUxfUkVTVUxUIiwiQ1NWX0xPQURFUl9PUFRJT05TIiwic2hhcGUiLCJkeW5hbWljVHlwaW5nIiwiQVJST1dfTE9BREVSX09QVElPTlMiLCJiYXRjaERlYm91bmNlTXMiLCJQQVJRVUVUX0xPQURFUl9PUFRJT05TIiwiSlNPTl9MT0FERVJfT1BUSU9OUyIsImpzb25wYXRocyIsImlzQXJyb3dUYWJsZSIsInRhYmxlIiwiQm9vbGVhbiIsIlRhYmxlIiwiaXNBcnJvd0RhdGEiLCJkYXRhIiwiQXJyYXkiLCJpc0FycmF5Iiwic2NoZW1hIiwiaXNHZW9Kc29uIiwianNvbiIsImlzUGxhaW5PYmplY3QiLCJpc0ZlYXR1cmUiLCJpc0ZlYXR1cmVDb2xsZWN0aW9uIiwidHlwZSIsImdlb21ldHJ5IiwiZmVhdHVyZXMiLCJpc1Jvd09iamVjdCIsImlzS2VwbGVyR2xNYXAiLCJkYXRhc2V0cyIsImNvbmZpZyIsImluZm8iLCJhcHAiLCJtYWtlUHJvZ3Jlc3NJdGVyYXRvciIsIl94IiwiX3gyIiwiX21ha2VQcm9ncmVzc0l0ZXJhdG9yIiwiX3dyYXBBc3luY0dlbmVyYXRvcjIiLCJfcmVnZW5lcmF0b3IiLCJtYXJrIiwiX2NhbGxlZSIsInJvd0NvdW50IiwiX2l0ZXJhdG9yQWJydXB0Q29tcGxldGlvbiIsIl9kaWRJdGVyYXRvckVycm9yIiwiX2l0ZXJhdG9yRXJyb3IiLCJfaXRlcmF0b3IiLCJfc3RlcCIsImJhdGNoIiwicm93Q291bnRJbkJhdGNoIiwicGVyY2VudCIsInByb2dyZXNzIiwid3JhcCIsIl9jYWxsZWUkIiwiX2NvbnRleHQiLCJwcmV2IiwiX2F3YWl0QXN5bmNHZW5lcmF0b3IyIiwic2VudCIsIk51bWJlciIsImlzRmluaXRlIiwiYnl0ZXNVc2VkIiwic2l6ZSIsInQwIiwiZmluaXNoIiwic3RvcCIsInJlYWRCYXRjaCIsIl94MyIsIl94NCIsIl9yZWFkQmF0Y2giLCJfY2FsbGVlMiIsImZpbGVOYW1lIiwicmVzdWx0IiwiYmF0Y2hlcyIsIl9pdGVyYXRvckFicnVwdENvbXBsZXRpb24yIiwiX2RpZEl0ZXJhdG9yRXJyb3IyIiwiX2l0ZXJhdG9yRXJyb3IyIiwiX2l0ZXJhdG9yMiIsIl9zdGVwMiIsInN0cmVhbWluZ1BhdGgiLCJiYXRjaERhdGEiLCJfY2FsbGVlMiQiLCJfY29udGV4dDIiLCJiYXRjaFR5cGUiLCJjb250YWluZXIiLCJqc29ucGF0aCIsIl9KU09OUGF0aCIsInNldEZpZWxkQXRQYXRoIiwiaGVhZGVycyIsInJlYWRGaWxlSW5CYXRjaGVzIiwiX3g1IiwiX3JlYWRGaWxlSW5CYXRjaGVzIiwiX2FzeW5jVG9HZW5lcmF0b3IyIiwiX2NhbGxlZTMiLCJfcmVmIiwiZmlsZSIsIl9yZWYkbG9hZGVycyIsImxvYWRlcnMiLCJfcmVmJGxvYWRPcHRpb25zIiwibG9hZE9wdGlvbnMiLCJiYXRjaEl0ZXJhdG9yIiwicHJvZ3Jlc3NJdGVyYXRvciIsIl9jYWxsZWUzJCIsIl9jb250ZXh0MyIsIkpTT05Mb2FkZXIiLCJDU1ZMb2FkZXIiLCJHZW9BcnJvd0xvYWRlciIsIlBhcnF1ZXRXYXNtTG9hZGVyIiwiY29uY2F0IiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsImNzdiIsInBhcnF1ZXQiLCJtZXRhZGF0YSIsInBhcnNlSW5CYXRjaGVzIiwiYWJydXB0IiwibmFtZSIsInByb2Nlc3NGaWxlRGF0YSIsIl94NiIsIl9wcm9jZXNzRmlsZURhdGEiLCJfY2FsbGVlNCIsIl9yZWYyIiwiX2dldEFwcGxpY2F0aW9uQ29uZmlnIiwiY29udGVudCIsImZpbGVDYWNoZSIsImZvcm1hdCIsInByb2Nlc3NvciIsImlkIiwicHJvY2Vzc29yUmVzdWx0IiwiX2NhbGxlZTQkIiwiX2NvbnRleHQ0IiwiY29uc29sZSIsImxvZyIsImdlbmVyYXRlSGFzaElkRnJvbVN0cmluZyIsImdldEFwcGxpY2F0aW9uQ29uZmlnIiwiS2VwbGVyVGFibGUiLCJnZXRGaWxlUHJvY2Vzc29yIiwiREFUQVNFVF9GT1JNQVRTIiwicHJvY2Vzc0Fycm93QmF0Y2hlcyIsImtlcGxlcmdsIiwicHJvY2Vzc0tlcGxlcmdsSlNPTiIsInJvdyIsInByb2Nlc3NSb3dPYmplY3QiLCJnZW9qc29uIiwicHJvY2Vzc0dlb2pzb24iLCJFcnJvciIsImdldEVycm9yIiwibGFiZWwiLCJmaWxlc1RvRGF0YVBheWxvYWQiLCJjb2xsZWN0aW9uIiwicmVkdWNlIiwiYWNjdSIsImtlcGxlck1hcHMiLCJvcHRpb25zIiwiY2VudGVyTWFwIiwibWFwU3RhdGUiLCJuZXdEYXRhc2V0IiwiZ2VuZXJhdGVIYXNoSWQiXSwic291cmNlcyI6WyIuLi9zcmMvZmlsZS1oYW5kbGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCAqIGFzIGFycm93IGZyb20gJ2FwYWNoZS1hcnJvdyc7XG5pbXBvcnQge3BhcnNlSW5CYXRjaGVzfSBmcm9tICdAbG9hZGVycy5nbC9jb3JlJztcbmltcG9ydCB7SlNPTkxvYWRlciwgX0pTT05QYXRofSBmcm9tICdAbG9hZGVycy5nbC9qc29uJztcbmltcG9ydCB7Q1NWTG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9jc3YnO1xuaW1wb3J0IHtHZW9BcnJvd0xvYWRlcn0gZnJvbSAnQGxvYWRlcnMuZ2wvYXJyb3cnO1xuaW1wb3J0IHtQYXJxdWV0V2FzbUxvYWRlcn0gZnJvbSAnQGxvYWRlcnMuZ2wvcGFycXVldCc7XG5pbXBvcnQge0xvYWRlcn0gZnJvbSAnQGxvYWRlcnMuZ2wvbG9hZGVyLXV0aWxzJztcbmltcG9ydCB7XG4gIGlzUGxhaW5PYmplY3QsXG4gIGdlbmVyYXRlSGFzaElkRnJvbVN0cmluZyxcbiAgZ2V0QXBwbGljYXRpb25Db25maWcsXG4gIGdldEVycm9yXG59IGZyb20gJ0BrZXBsZXIuZ2wvdXRpbHMnO1xuaW1wb3J0IHtnZW5lcmF0ZUhhc2hJZH0gZnJvbSAnQGtlcGxlci5nbC9jb21tb24tdXRpbHMnO1xuaW1wb3J0IHtEQVRBU0VUX0ZPUk1BVFN9IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcbmltcG9ydCB7QWRkRGF0YVRvTWFwUGF5bG9hZCwgRmVhdHVyZSwgTG9hZGVkTWFwLCBQcm9jZXNzb3JSZXN1bHR9IGZyb20gJ0BrZXBsZXIuZ2wvdHlwZXMnO1xuaW1wb3J0IHtLZXBsZXJUYWJsZX0gZnJvbSAnQGtlcGxlci5nbC90YWJsZSc7XG5pbXBvcnQge0ZlYXR1cmVDb2xsZWN0aW9ufSBmcm9tICdAdHVyZi9oZWxwZXJzJztcblxuaW1wb3J0IHtcbiAgcHJvY2Vzc0Fycm93QmF0Y2hlcyxcbiAgcHJvY2Vzc0dlb2pzb24sXG4gIHByb2Nlc3NLZXBsZXJnbEpTT04sXG4gIHByb2Nlc3NSb3dPYmplY3Rcbn0gZnJvbSAnLi9kYXRhLXByb2Nlc3Nvcic7XG5cbmltcG9ydCB7RmlsZUNhY2hlSXRlbSwgVmFsaWRLZXBsZXJHbE1hcH0gZnJvbSAnLi90eXBlcyc7XG5cbmNvbnN0IEJBVENIX1RZUEUgPSB7XG4gIE1FVEFEQVRBOiAnbWV0YWRhdGEnLFxuICBQQVJUSUFMX1JFU1VMVDogJ3BhcnRpYWwtcmVzdWx0JyxcbiAgRklOQUxfUkVTVUxUOiAnZmluYWwtcmVzdWx0J1xufTtcblxuY29uc3QgQ1NWX0xPQURFUl9PUFRJT05TID0ge1xuICBzaGFwZTogJ29iamVjdC1yb3ctdGFibGUnLFxuICBkeW5hbWljVHlwaW5nOiBmYWxzZSAvLyBub3Qgd29ya2luZyBmb3Igbm93XG59O1xuXG5jb25zdCBBUlJPV19MT0FERVJfT1BUSU9OUyA9IHtcbiAgc2hhcGU6ICdhcnJvdy10YWJsZScsXG4gIGJhdGNoRGVib3VuY2VNczogMTAgLy8gdGltZSB0byBkZWxheSBiZXR3ZWVuIGJhdGNoZXMsIGZvciBpbmNyZW1lbnRhbCBsb2FkaW5nXG59O1xuXG5jb25zdCBQQVJRVUVUX0xPQURFUl9PUFRJT05TID0ge1xuICBzaGFwZTogJ2Fycm93LXRhYmxlJ1xufTtcblxuY29uc3QgSlNPTl9MT0FERVJfT1BUSU9OUyA9IHtcbiAgc2hhcGU6ICdvYmplY3Qtcm93LXRhYmxlJyxcbiAgLy8gaW5zdHJ1Y3QgbG9hZGVycy5nbCBvbiB3aGF0IGpzb24gcGF0aHMgdG8gc3RyZWFtXG4gIGpzb25wYXRoczogW1xuICAgICckJywgLy8gSlNPTiBSb3cgYXJyYXlcbiAgICAnJC5mZWF0dXJlcycsIC8vIEdlb0pTT05cbiAgICAnJC5kYXRhc2V0cycgLy8gS2VwbGVyR0wgSlNPTlxuICBdXG59O1xuXG5leHBvcnQgdHlwZSBQcm9jZXNzRmlsZURhdGFDb250ZW50ID0ge1xuICBkYXRhOiB1bmtub3duO1xuICBmaWxlTmFtZTogc3RyaW5nO1xuICBsZW5ndGg/OiBudW1iZXI7XG4gIHByb2dyZXNzPzoge3Jvd0NvdW50PzogbnVtYmVyOyByb3dDb3VudEluQmF0Y2g/OiBudW1iZXI7IHBlcmNlbnQ/OiBudW1iZXJ9O1xuICAvKiogIG1ldGFkYXRhIGUuZy4gZm9yIGFycm93IGRhdGEsIG1ldGFkYXRhIGNvdWxkIGJlIHRoZSBzY2hlbWEuZmllbGRzICovXG4gIG1ldGFkYXRhPzogTWFwPHN0cmluZywgc3RyaW5nPjtcbn07XG5cbi8qKlxuICogY2hlY2sgaWYgdGFibGUgaXMgYW4gQXJyb3dUYWJsZSBvYmplY3RcbiAqIEBwYXJhbSB0YWJsZSAtIG9iamVjdCB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IC0gdHJ1ZSBpZiB0YWJsZSBpcyBhbiBBcnJvd1RhYmxlIG9iamVjdCB0eXBlIGd1YXJkZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQXJyb3dUYWJsZSh0YWJsZTogYW55KTogdGFibGUgaXMgYXJyb3cuVGFibGUge1xuICByZXR1cm4gQm9vbGVhbih0YWJsZSBpbnN0YW5jZW9mIGFycm93LlRhYmxlKTtcbn1cblxuLyoqXG4gKiBjaGVjayBpZiBkYXRhIGlzIGFuIEFycm93RGF0YSBvYmplY3QsIHdoaWNoIGlzIGFuIGFycmF5IG9mIFJlY29yZEJhdGNoXG4gKiBAcGFyYW0gZGF0YSAtIG9iamVjdCB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IC0gdHJ1ZSBpZiBkYXRhIGlzIGFuIEFycm93RGF0YSBvYmplY3QgdHlwZSBndWFyZGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Fycm93RGF0YShkYXRhOiBhbnkpOiBib29sZWFuIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoZGF0YSkgJiYgQm9vbGVhbihkYXRhLmxlbmd0aCAmJiBkYXRhWzBdLmRhdGEgJiYgZGF0YVswXS5zY2hlbWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNHZW9Kc29uKGpzb246IHVua25vd24pOiBqc29uIGlzIEZlYXR1cmUgfCBGZWF0dXJlQ29sbGVjdGlvbiB7XG4gIC8vIGpzb24gY2FuIGJlIGZlYXR1cmUgY29sbGVjdGlvblxuICAvLyBvciBzaW5nbGUgZmVhdHVyZVxuICByZXR1cm4gaXNQbGFpbk9iamVjdChqc29uKSAmJiAoaXNGZWF0dXJlKGpzb24pIHx8IGlzRmVhdHVyZUNvbGxlY3Rpb24oanNvbikpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNGZWF0dXJlKGpzb246IHVua25vd24pOiBqc29uIGlzIEZlYXR1cmUge1xuICByZXR1cm4gaXNQbGFpbk9iamVjdChqc29uKSAmJiBqc29uLnR5cGUgPT09ICdGZWF0dXJlJyAmJiBCb29sZWFuKGpzb24uZ2VvbWV0cnkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNGZWF0dXJlQ29sbGVjdGlvbihqc29uOiB1bmtub3duKToganNvbiBpcyBGZWF0dXJlQ29sbGVjdGlvbiB7XG4gIHJldHVybiBpc1BsYWluT2JqZWN0KGpzb24pICYmIGpzb24udHlwZSA9PT0gJ0ZlYXR1cmVDb2xsZWN0aW9uJyAmJiBCb29sZWFuKGpzb24uZmVhdHVyZXMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNSb3dPYmplY3QoanNvbjogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGpzb24pICYmIGlzUGxhaW5PYmplY3QoanNvblswXSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0tlcGxlckdsTWFwKGpzb246IHVua25vd24pOiBqc29uIGlzIFZhbGlkS2VwbGVyR2xNYXAge1xuICByZXR1cm4gQm9vbGVhbihcbiAgICBpc1BsYWluT2JqZWN0KGpzb24pICYmXG4gICAgICBqc29uLmRhdGFzZXRzICYmXG4gICAgICBqc29uLmNvbmZpZyAmJlxuICAgICAganNvbi5pbmZvICYmXG4gICAgICBpc1BsYWluT2JqZWN0KGpzb24uaW5mbykgJiZcbiAgICAgIGpzb24uaW5mby5hcHAgPT09ICdrZXBsZXIuZ2wnXG4gICk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiogbWFrZVByb2dyZXNzSXRlcmF0b3IoXG4gIGFzeW5jSXRlcmF0b3I6IEFzeW5jSXRlcmFibGU8YW55PixcbiAgaW5mbzoge3NpemU6IG51bWJlcn1cbik6IEFzeW5jR2VuZXJhdG9yIHtcbiAgbGV0IHJvd0NvdW50ID0gMDtcblxuICBmb3IgYXdhaXQgKGNvbnN0IGJhdGNoIG9mIGFzeW5jSXRlcmF0b3IpIHtcbiAgICAvLyB0aGUgbGVuZ3RoIGNvdWxkIGJlIHN0b3JlZCBpbiBgYmF0Y2gubGVuZ3RoYCBmb3IgYXJyb3cgYmF0Y2hcbiAgICBjb25zdCByb3dDb3VudEluQmF0Y2ggPSAoYmF0Y2guZGF0YSAmJiAoYmF0Y2guZGF0YS5sZW5ndGggfHwgYmF0Y2gubGVuZ3RoKSkgfHwgMDtcbiAgICByb3dDb3VudCArPSByb3dDb3VudEluQmF0Y2g7XG4gICAgY29uc3QgcGVyY2VudCA9IE51bWJlci5pc0Zpbml0ZShiYXRjaC5ieXRlc1VzZWQpID8gYmF0Y2guYnl0ZXNVc2VkIC8gaW5mby5zaXplIDogbnVsbDtcblxuICAgIC8vIFVwZGF0ZSBwcm9ncmVzcyBvYmplY3RcbiAgICBjb25zdCBwcm9ncmVzcyA9IHtcbiAgICAgIHJvd0NvdW50LFxuICAgICAgcm93Q291bnRJbkJhdGNoLFxuICAgICAgLi4uKE51bWJlci5pc0Zpbml0ZShwZXJjZW50KSA/IHtwZXJjZW50fSA6IHt9KVxuICAgIH07XG5cbiAgICB5aWVsZCB7Li4uYmF0Y2gsIHByb2dyZXNzfTtcbiAgfVxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiByZWFkQmF0Y2goXG4gIGFzeW5jSXRlcmF0b3I6IEFzeW5jSXRlcmFibGU8YW55PixcbiAgZmlsZU5hbWU6IHN0cmluZ1xuKTogQXN5bmNHZW5lcmF0b3Ige1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcbiAgY29uc3QgYmF0Y2hlcyA9IDxhbnk+W107XG4gIGZvciBhd2FpdCAoY29uc3QgYmF0Y2ggb2YgYXN5bmNJdGVyYXRvcikge1xuICAgIC8vIExhc3QgYmF0Y2ggd2lsbCBoYXZlIHRoaXMgc3BlY2lhbCB0eXBlIGFuZCB3aWxsIHByb3ZpZGUgYWxsIHRoZSByb290XG4gICAgLy8gcHJvcGVydGllcyBvZiB0aGUgcGFyc2VkIGRvY3VtZW50LlxuICAgIC8vIE9ubHkganNvbiBwYXJzZSB3aWxsIGhhdmUgYEZJTkFMX1JFU1VMVGBcbiAgICBpZiAoYmF0Y2guYmF0Y2hUeXBlID09PSBCQVRDSF9UWVBFLkZJTkFMX1JFU1VMVCkge1xuICAgICAgaWYgKGJhdGNoLmNvbnRhaW5lcikge1xuICAgICAgICByZXN1bHQgPSB7Li4uYmF0Y2guY29udGFpbmVyfTtcbiAgICAgIH1cbiAgICAgIC8vIFNldCB0aGUgc3RyZWFtZWQgZGF0YSBjb3JyZWN0bHkgaXMgQmF0Y2gganNvbiBwYXRoIGlzIHNldFxuICAgICAgLy8gYW5kIHRoZSBwYXRoIHN0cmVhbWVkIGlzIG5vdCB0aGUgdG9wIGxldmVsIG9iamVjdCAoanNvbnBhdGggPSAnJCcpXG4gICAgICBpZiAoYmF0Y2guanNvbnBhdGggJiYgYmF0Y2guanNvbnBhdGgubGVuZ3RoID4gMSkge1xuICAgICAgICBjb25zdCBzdHJlYW1pbmdQYXRoID0gbmV3IF9KU09OUGF0aChiYXRjaC5qc29ucGF0aCk7XG4gICAgICAgIHN0cmVhbWluZ1BhdGguc2V0RmllbGRBdFBhdGgocmVzdWx0LCBiYXRjaGVzKTtcbiAgICAgIH0gZWxzZSBpZiAoYmF0Y2guanNvbnBhdGggJiYgYmF0Y2guanNvbnBhdGgubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIC8vIFRoZSBzdHJlYW1lZCBvYmplY3QgaXMgYSBST1cgSlNPTi1iYXRjaCAoanNvbnBhdGggPSAnJCcpXG4gICAgICAgIC8vIHJvdyBvYmplY3RzXG4gICAgICAgIHJlc3VsdCA9IGJhdGNoZXM7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGJhdGNoRGF0YSA9IGlzQXJyb3dUYWJsZShiYXRjaC5kYXRhKSA/IGJhdGNoLmRhdGEuYmF0Y2hlcyA6IGJhdGNoLmRhdGE7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJhdGNoRGF0YT8ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYmF0Y2hlcy5wdXNoKGJhdGNoRGF0YVtpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgeWllbGQge1xuICAgICAgLi4uYmF0Y2gsXG4gICAgICAuLi4oYmF0Y2guc2NoZW1hID8ge2hlYWRlcnM6IE9iamVjdC5rZXlzKGJhdGNoLnNjaGVtYSl9IDoge30pLFxuICAgICAgZmlsZU5hbWUsXG4gICAgICAvLyBpZiBkYXRhc2V0IGlzIENTViwgZGF0YSBpcyBzZXQgdG8gdGhlIHJhdyBiYXRjaGVzXG4gICAgICBkYXRhOiByZXN1bHQgPyByZXN1bHQgOiBiYXRjaGVzXG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEZpbGVJbkJhdGNoZXMoe1xuICBmaWxlLFxuICBsb2FkZXJzID0gW10sXG4gIGxvYWRPcHRpb25zID0ge31cbn06IHtcbiAgZmlsZTogRmlsZTtcbiAgZmlsZUNhY2hlOiBGaWxlQ2FjaGVJdGVtW107XG4gIGxvYWRlcnM6IExvYWRlcltdO1xuICBsb2FkT3B0aW9uczogYW55O1xufSk6IFByb21pc2U8QXN5bmNHZW5lcmF0b3I+IHtcbiAgbG9hZGVycyA9IFtKU09OTG9hZGVyLCBDU1ZMb2FkZXIsIEdlb0Fycm93TG9hZGVyLCBQYXJxdWV0V2FzbUxvYWRlciwgLi4ubG9hZGVyc107XG4gIGxvYWRPcHRpb25zID0ge1xuICAgIGNzdjogQ1NWX0xPQURFUl9PUFRJT05TLFxuICAgIGFycm93OiBBUlJPV19MT0FERVJfT1BUSU9OUyxcbiAgICBqc29uOiBKU09OX0xPQURFUl9PUFRJT05TLFxuICAgIHBhcnF1ZXQ6IFBBUlFVRVRfTE9BREVSX09QVElPTlMsXG4gICAgbWV0YWRhdGE6IHRydWUsXG4gICAgLi4ubG9hZE9wdGlvbnNcbiAgfTtcblxuICBjb25zdCBiYXRjaEl0ZXJhdG9yID0gYXdhaXQgcGFyc2VJbkJhdGNoZXMoZmlsZSwgbG9hZGVycywgbG9hZE9wdGlvbnMpO1xuICBjb25zdCBwcm9ncmVzc0l0ZXJhdG9yID0gbWFrZVByb2dyZXNzSXRlcmF0b3IoYmF0Y2hJdGVyYXRvciwge3NpemU6IGZpbGUuc2l6ZX0pO1xuXG4gIHJldHVybiByZWFkQmF0Y2gocHJvZ3Jlc3NJdGVyYXRvciwgZmlsZS5uYW1lKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NGaWxlRGF0YSh7XG4gIGNvbnRlbnQsXG4gIGZpbGVDYWNoZVxufToge1xuICBjb250ZW50OiBQcm9jZXNzRmlsZURhdGFDb250ZW50O1xuICBmaWxlQ2FjaGU6IEZpbGVDYWNoZUl0ZW1bXTtcbn0pOiBQcm9taXNlPEZpbGVDYWNoZUl0ZW1bXT4ge1xuICBjb25zdCB7ZmlsZU5hbWUsIGRhdGF9ID0gY29udGVudDtcbiAgbGV0IGZvcm1hdDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBsZXQgcHJvY2Vzc29yOiAoKGRhdGE6IGFueSkgPT4gUHJvY2Vzc29yUmVzdWx0IHwgTG9hZGVkTWFwIHwgbnVsbCkgfCB1bmRlZmluZWQ7XG4gIGNvbnNvbGUubG9nKCdQcm9jZXNzaW5nIGZpbGUnLCBmaWxlTmFtZSk7XG4gIC8vIGdlbmVyYXRlIHVuaXF1ZSBpZCB3aXRoIGxlbmd0aCBvZiA0IHVzaW5nIGZpbGVOYW1lIHN0cmluZ1xuICBjb25zdCBpZCA9IGdlbmVyYXRlSGFzaElkRnJvbVN0cmluZyhmaWxlTmFtZSk7XG4gIC8vIGRlY2lkZSBvbiB3aGljaCB0YWJsZSBjbGFzcyB0byB1c2UgYmFzZWQgb24gYXBwbGljYXRpb24gY29uZmlnXG4gIGNvbnN0IHRhYmxlID0gZ2V0QXBwbGljYXRpb25Db25maWcoKS50YWJsZSA/PyBLZXBsZXJUYWJsZTtcblxuICBpZiAodHlwZW9mIHRhYmxlLmdldEZpbGVQcm9jZXNzb3IgPT09ICdmdW5jdGlvbicpIHtcbiAgICAvLyB1c2UgY3VzdG9tIHByb2Nlc3NvcnMgZnJvbSB0YWJsZSBjbGFzc1xuICAgIGNvbnN0IHByb2Nlc3NvclJlc3VsdCA9IHRhYmxlLmdldEZpbGVQcm9jZXNzb3IoZGF0YSk7XG4gICAgZm9ybWF0ID0gcHJvY2Vzc29yUmVzdWx0LmZvcm1hdDtcbiAgICBwcm9jZXNzb3IgPSBwcm9jZXNzb3JSZXN1bHQucHJvY2Vzc29yO1xuICB9IGVsc2Uge1xuICAgIC8vIHVzZSBkZWZhdWx0IHByb2Nlc3NvcnNcbiAgICBpZiAoaXNBcnJvd0RhdGEoZGF0YSkpIHtcbiAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5hcnJvdztcbiAgICAgIHByb2Nlc3NvciA9IHByb2Nlc3NBcnJvd0JhdGNoZXM7XG4gICAgfSBlbHNlIGlmIChpc0tlcGxlckdsTWFwKGRhdGEpKSB7XG4gICAgICBmb3JtYXQgPSBEQVRBU0VUX0ZPUk1BVFMua2VwbGVyZ2w7XG4gICAgICBwcm9jZXNzb3IgPSBwcm9jZXNzS2VwbGVyZ2xKU09OO1xuICAgIH0gZWxzZSBpZiAoaXNSb3dPYmplY3QoZGF0YSkpIHtcbiAgICAgIC8vIGNzdiBmaWxlIGdvZXMgaGVyZVxuICAgICAgZm9ybWF0ID0gREFUQVNFVF9GT1JNQVRTLnJvdztcbiAgICAgIHByb2Nlc3NvciA9IHByb2Nlc3NSb3dPYmplY3Q7XG4gICAgfSBlbHNlIGlmIChpc0dlb0pzb24oZGF0YSkpIHtcbiAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5nZW9qc29uO1xuICAgICAgcHJvY2Vzc29yID0gcHJvY2Vzc0dlb2pzb247XG4gICAgfVxuICB9XG4gIGlmIChmb3JtYXQgJiYgcHJvY2Vzc29yKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY2F0Y2hcbiAgICBsZXQgcmVzdWx0O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCBwcm9jZXNzb3IoZGF0YSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuIG5vdCBwcm9jZXNzIHVwbG9hZGVkIGZpbGUsICR7Z2V0RXJyb3IoZXJyb3IgYXMgRXJyb3IpfWApO1xuICAgIH1cblxuICAgIHJldHVybiBbXG4gICAgICAuLi5maWxlQ2FjaGUsXG4gICAgICB7XG4gICAgICAgIGRhdGE6IHJlc3VsdCxcbiAgICAgICAgaW5mbzoge1xuICAgICAgICAgIGlkLFxuICAgICAgICAgIGxhYmVsOiBjb250ZW50LmZpbGVOYW1lLFxuICAgICAgICAgIGZvcm1hdFxuICAgICAgICB9XG4gICAgICB9XG4gICAgXTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgcHJvY2VzcyB1cGxvYWRlZCBmaWxlLCB1bmtub3duIGZpbGUgZm9ybWF0Jyk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbGVzVG9EYXRhUGF5bG9hZChmaWxlQ2FjaGU6IEZpbGVDYWNoZUl0ZW1bXSk6IEFkZERhdGFUb01hcFBheWxvYWRbXSB7XG4gIC8vIHNlcGVyYXRlIG91dCBmaWxlcyB3aGljaCBjb3VsZCBiZSBhIHNpbmdsZSBkYXRhc2V0cy4gb3IgYSBrZXBsZXJnbCBtYXAganNvblxuICBjb25zdCBjb2xsZWN0aW9uID0gZmlsZUNhY2hlLnJlZHVjZTx7XG4gICAgZGF0YXNldHM6IEZpbGVDYWNoZUl0ZW1bXTtcbiAgICBrZXBsZXJNYXBzOiBBZGREYXRhVG9NYXBQYXlsb2FkW107XG4gIH0+KFxuICAgIChhY2N1LCBmaWxlKSA9PiB7XG4gICAgICBjb25zdCB7ZGF0YSwgaW5mb30gPSBmaWxlO1xuICAgICAgaWYgKGluZm8/LmZvcm1hdCA9PT0gREFUQVNFVF9GT1JNQVRTLmtlcGxlcmdsKSB7XG4gICAgICAgIC8vIGlmIGZpbGUgY29udGFpbnMgYSBzaW5nbGUga2VwbGVyIG1hcCBkYXRhc2V0ICYgY29uZmlnXG4gICAgICAgIGFjY3Uua2VwbGVyTWFwcy5wdXNoKHtcbiAgICAgICAgICAuLi5kYXRhLFxuICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIGNlbnRlck1hcDogIShkYXRhLmNvbmZpZyAmJiBkYXRhLmNvbmZpZy5tYXBTdGF0ZSlcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChEQVRBU0VUX0ZPUk1BVFNbaW5mbz8uZm9ybWF0XSkge1xuICAgICAgICAvLyBpZiBmaWxlIGNvbnRhaW5zIG9ubHkgZGF0YVxuICAgICAgICBjb25zdCBuZXdEYXRhc2V0ID0ge1xuICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgaW5mbzoge1xuICAgICAgICAgICAgaWQ6IGluZm8/LmlkIHx8IGdlbmVyYXRlSGFzaElkKDQpLFxuICAgICAgICAgICAgLi4uKGluZm8gfHwge30pXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBhY2N1LmRhdGFzZXRzLnB1c2gobmV3RGF0YXNldCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdTtcbiAgICB9LFxuICAgIHtkYXRhc2V0czogW10sIGtlcGxlck1hcHM6IFtdfVxuICApO1xuXG4gIC8vIGFkZCBrZXBsZXIgbWFwIGZpcnN0IHdpdGggY29uZmlnXG4gIC8vIGFkZCBkYXRhc2V0cyBsYXRlciBpbiBvbmUgYWRkIGRhdGEgY2FsbFxuICByZXR1cm4gY29sbGVjdGlvbi5rZXBsZXJNYXBzLmNvbmNhdCh7ZGF0YXNldHM6IGNvbGxlY3Rpb24uZGF0YXNldHN9KTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUdBLElBQUFBLEtBQUEsR0FBQUMsdUJBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLEtBQUEsR0FBQUQsT0FB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