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