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
JavaScript
"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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