kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
415 lines (412 loc) • 54 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;
// 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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhcnJvdyIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwicmVxdWlyZSIsIl9jb3JlIiwiX2pzb24iLCJfY3N2IiwiX2Fycm93IiwiX3BhcnF1ZXQiLCJfdXRpbHMiLCJfY29tbW9uVXRpbHMiLCJfY29uc3RhbnRzIiwiX3RhYmxlIiwiX2RhdGFQcm9jZXNzb3IiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsIl90eXBlb2YiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJvd25LZXlzIiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJfYXN5bmNJdGVyYXRvciIsIlN5bWJvbCIsImFzeW5jSXRlcmF0b3IiLCJpdGVyYXRvciIsIkFzeW5jRnJvbVN5bmNJdGVyYXRvciIsIlR5cGVFcnJvciIsIkFzeW5jRnJvbVN5bmNJdGVyYXRvckNvbnRpbnVhdGlvbiIsIlByb21pc2UiLCJyZWplY3QiLCJkb25lIiwicmVzb2x2ZSIsInZhbHVlIiwidGhlbiIsInMiLCJuZXh0IiwicHJvdG90eXBlIiwiX3JldHVybiIsIl90aHJvdyIsIkJBVENIX1RZUEUiLCJNRVRBREFUQSIsIlBBUlRJQUxfUkVTVUxUIiwiRklOQUxfUkVTVUxUIiwiQ1NWX0xPQURFUl9PUFRJT05TIiwic2hhcGUiLCJkeW5hbWljVHlwaW5nIiwiQVJST1dfTE9BREVSX09QVElPTlMiLCJiYXRjaERlYm91bmNlTXMiLCJQQVJRVUVUX0xPQURFUl9PUFRJT05TIiwiSlNPTl9MT0FERVJfT1BUSU9OUyIsImpzb25wYXRocyIsImlzQXJyb3dUYWJsZSIsInRhYmxlIiwiQm9vbGVhbiIsIlRhYmxlIiwiaXNBcnJvd0RhdGEiLCJkYXRhIiwiQXJyYXkiLCJpc0FycmF5Iiwic2NoZW1hIiwiaXNHZW9Kc29uIiwianNvbiIsImlzUGxhaW5PYmplY3QiLCJpc0ZlYXR1cmUiLCJpc0ZlYXR1cmVDb2xsZWN0aW9uIiwidHlwZSIsImdlb21ldHJ5IiwiZmVhdHVyZXMiLCJpc1Jvd09iamVjdCIsImlzS2VwbGVyR2xNYXAiLCJkYXRhc2V0cyIsImNvbmZpZyIsImluZm8iLCJhcHAiLCJtYWtlUHJvZ3Jlc3NJdGVyYXRvciIsIl94IiwiX3gyIiwiX21ha2VQcm9ncmVzc0l0ZXJhdG9yIiwiX3dyYXBBc3luY0dlbmVyYXRvcjIiLCJfcmVnZW5lcmF0b3IiLCJtYXJrIiwiX2NhbGxlZSIsInJvd0NvdW50IiwiX2l0ZXJhdG9yQWJydXB0Q29tcGxldGlvbiIsIl9kaWRJdGVyYXRvckVycm9yIiwiX2l0ZXJhdG9yRXJyb3IiLCJfaXRlcmF0b3IiLCJfc3RlcCIsImJhdGNoIiwicm93Q291bnRJbkJhdGNoIiwicGVyY2VudCIsInByb2dyZXNzIiwid3JhcCIsIl9jYWxsZWUkIiwiX2NvbnRleHQiLCJwcmV2IiwiX2F3YWl0QXN5bmNHZW5lcmF0b3IyIiwic2VudCIsIk51bWJlciIsImlzRmluaXRlIiwiYnl0ZXNVc2VkIiwic2l6ZSIsInQwIiwiZmluaXNoIiwic3RvcCIsInJlYWRCYXRjaCIsIl94MyIsIl94NCIsIl9yZWFkQmF0Y2giLCJfY2FsbGVlMiIsImZpbGVOYW1lIiwicmVzdWx0IiwiYmF0Y2hlcyIsIl9pdGVyYXRvckFicnVwdENvbXBsZXRpb24yIiwiX2RpZEl0ZXJhdG9yRXJyb3IyIiwiX2l0ZXJhdG9yRXJyb3IyIiwiX2l0ZXJhdG9yMiIsIl9zdGVwMiIsInN0cmVhbWluZ1BhdGgiLCJiYXRjaERhdGEiLCJfY2FsbGVlMiQiLCJfY29udGV4dDIiLCJiYXRjaFR5cGUiLCJjb250YWluZXIiLCJqc29ucGF0aCIsIl9KU09OUGF0aCIsInNldEZpZWxkQXRQYXRoIiwiaGVhZGVycyIsInJlYWRGaWxlSW5CYXRjaGVzIiwiX3g1IiwiX3JlYWRGaWxlSW5CYXRjaGVzIiwiX2FzeW5jVG9HZW5lcmF0b3IyIiwiX2NhbGxlZTMiLCJfcmVmIiwiZmlsZSIsIl9yZWYkbG9hZGVycyIsImxvYWRlcnMiLCJfcmVmJGxvYWRPcHRpb25zIiwibG9hZE9wdGlvbnMiLCJiYXRjaEl0ZXJhdG9yIiwicHJvZ3Jlc3NJdGVyYXRvciIsIl9jYWxsZWUzJCIsIl9jb250ZXh0MyIsIkpTT05Mb2FkZXIiLCJDU1ZMb2FkZXIiLCJHZW9BcnJvd0xvYWRlciIsIlBhcnF1ZXRXYXNtTG9hZGVyIiwiY29uY2F0IiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsImNzdiIsInBhcnF1ZXQiLCJtZXRhZGF0YSIsInBhcnNlSW5CYXRjaGVzIiwiYWJydXB0IiwibmFtZSIsInByb2Nlc3NGaWxlRGF0YSIsIl94NiIsIl9wcm9jZXNzRmlsZURhdGEiLCJfY2FsbGVlNCIsIl9yZWYyIiwiX2dldEFwcGxpY2F0aW9uQ29uZmlnIiwiY29udGVudCIsImZpbGVDYWNoZSIsImZvcm1hdCIsInByb2Nlc3NvciIsImlkIiwicHJvY2Vzc29yUmVzdWx0IiwiX2NhbGxlZTQkIiwiX2NvbnRleHQ0IiwiZ2VuZXJhdGVIYXNoSWRGcm9tU3RyaW5nIiwiZ2V0QXBwbGljYXRpb25Db25maWciLCJLZXBsZXJUYWJsZSIsImdldEZpbGVQcm9jZXNzb3IiLCJEQVRBU0VUX0ZPUk1BVFMiLCJwcm9jZXNzQXJyb3dCYXRjaGVzIiwia2VwbGVyZ2wiLCJwcm9jZXNzS2VwbGVyZ2xKU09OIiwicm93IiwicHJvY2Vzc1Jvd09iamVjdCIsImdlb2pzb24iLCJwcm9jZXNzR2VvanNvbiIsIkVycm9yIiwiZ2V0RXJyb3IiLCJsYWJlbCIsImZpbGVzVG9EYXRhUGF5bG9hZCIsImNvbGxlY3Rpb24iLCJyZWR1Y2UiLCJhY2N1Iiwia2VwbGVyTWFwcyIsIm9wdGlvbnMiLCJjZW50ZXJNYXAiLCJtYXBTdGF0ZSIsIm5ld0RhdGFzZXQiLCJnZW5lcmF0ZUhhc2hJZCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9maWxlLWhhbmRsZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0ICogYXMgYXJyb3cgZnJvbSAnYXBhY2hlLWFycm93JztcbmltcG9ydCB7cGFyc2VJbkJhdGNoZXN9IGZyb20gJ0Bsb2FkZXJzLmdsL2NvcmUnO1xuaW1wb3J0IHtKU09OTG9hZGVyLCBfSlNPTlBhdGh9IGZyb20gJ0Bsb2FkZXJzLmdsL2pzb24nO1xuaW1wb3J0IHtDU1ZMb2FkZXJ9IGZyb20gJ0Bsb2FkZXJzLmdsL2Nzdic7XG5pbXBvcnQge0dlb0Fycm93TG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9hcnJvdyc7XG5pbXBvcnQge1BhcnF1ZXRXYXNtTG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9wYXJxdWV0JztcbmltcG9ydCB7TG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9sb2FkZXItdXRpbHMnO1xuaW1wb3J0IHtcbiAgaXNQbGFpbk9iamVjdCxcbiAgZ2VuZXJhdGVIYXNoSWRGcm9tU3RyaW5nLFxuICBnZXRBcHBsaWNhdGlvbkNvbmZpZyxcbiAgZ2V0RXJyb3Jcbn0gZnJvbSAnQGtlcGxlci5nbC91dGlscyc7XG5pbXBvcnQge2dlbmVyYXRlSGFzaElkfSBmcm9tICdAa2VwbGVyLmdsL2NvbW1vbi11dGlscyc7XG5pbXBvcnQge0RBVEFTRVRfRk9STUFUU30gZnJvbSAnQGtlcGxlci5nbC9jb25zdGFudHMnO1xuaW1wb3J0IHtBZGREYXRhVG9NYXBQYXlsb2FkLCBGZWF0dXJlLCBMb2FkZWRNYXAsIFByb2Nlc3NvclJlc3VsdH0gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5pbXBvcnQge0tlcGxlclRhYmxlfSBmcm9tICdAa2VwbGVyLmdsL3RhYmxlJztcbmltcG9ydCB7RmVhdHVyZUNvbGxlY3Rpb259IGZyb20gJ0B0dXJmL2hlbHBlcnMnO1xuXG5pbXBvcnQge1xuICBwcm9jZXNzQXJyb3dCYXRjaGVzLFxuICBwcm9jZXNzR2VvanNvbixcbiAgcHJvY2Vzc0tlcGxlcmdsSlNPTixcbiAgcHJvY2Vzc1Jvd09iamVjdFxufSBmcm9tICcuL2RhdGEtcHJvY2Vzc29yJztcblxuaW1wb3J0IHtGaWxlQ2FjaGVJdGVtLCBWYWxpZEtlcGxlckdsTWFwfSBmcm9tICcuL3R5cGVzJztcblxuY29uc3QgQkFUQ0hfVFlQRSA9IHtcbiAgTUVUQURBVEE6ICdtZXRhZGF0YScsXG4gIFBBUlRJQUxfUkVTVUxUOiAncGFydGlhbC1yZXN1bHQnLFxuICBGSU5BTF9SRVNVTFQ6ICdmaW5hbC1yZXN1bHQnXG59O1xuXG5jb25zdCBDU1ZfTE9BREVSX09QVElPTlMgPSB7XG4gIHNoYXBlOiAnb2JqZWN0LXJvdy10YWJsZScsXG4gIGR5bmFtaWNUeXBpbmc6IGZhbHNlIC8vIG5vdCB3b3JraW5nIGZvciBub3dcbn07XG5cbmNvbnN0IEFSUk9XX0xPQURFUl9PUFRJT05TID0ge1xuICBzaGFwZTogJ2Fycm93LXRhYmxlJyxcbiAgYmF0Y2hEZWJvdW5jZU1zOiAxMCAvLyB0aW1lIHRvIGRlbGF5IGJldHdlZW4gYmF0Y2hlcywgZm9yIGluY3JlbWVudGFsIGxvYWRpbmdcbn07XG5cbmNvbnN0IFBBUlFVRVRfTE9BREVSX09QVElPTlMgPSB7XG4gIHNoYXBlOiAnYXJyb3ctdGFibGUnXG59O1xuXG5jb25zdCBKU09OX0xPQURFUl9PUFRJT05TID0ge1xuICBzaGFwZTogJ29iamVjdC1yb3ctdGFibGUnLFxuICAvLyBpbnN0cnVjdCBsb2FkZXJzLmdsIG9uIHdoYXQganNvbiBwYXRocyB0byBzdHJlYW1cbiAganNvbnBhdGhzOiBbXG4gICAgJyQnLCAvLyBKU09OIFJvdyBhcnJheVxuICAgICckLmZlYXR1cmVzJywgLy8gR2VvSlNPTlxuICAgICckLmRhdGFzZXRzJyAvLyBLZXBsZXJHTCBKU09OXG4gIF1cbn07XG5cbmV4cG9ydCB0eXBlIFByb2Nlc3NGaWxlRGF0YUNvbnRlbnQgPSB7XG4gIGRhdGE6IHVua25vd247XG4gIGZpbGVOYW1lOiBzdHJpbmc7XG4gIGxlbmd0aD86IG51bWJlcjtcbiAgcHJvZ3Jlc3M/OiB7cm93Q291bnQ/OiBudW1iZXI7IHJvd0NvdW50SW5CYXRjaD86IG51bWJlcjsgcGVyY2VudD86IG51bWJlcn07XG4gIC8qKiAgbWV0YWRhdGEgZS5nLiBmb3IgYXJyb3cgZGF0YSwgbWV0YWRhdGEgY291bGQgYmUgdGhlIHNjaGVtYS5maWVsZHMgKi9cbiAgbWV0YWRhdGE/OiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xufTtcblxuLyoqXG4gKiBjaGVjayBpZiB0YWJsZSBpcyBhbiBBcnJvd1RhYmxlIG9iamVjdFxuICogQHBhcmFtIHRhYmxlIC0gb2JqZWN0IHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0cnVlIGlmIHRhYmxlIGlzIGFuIEFycm93VGFibGUgb2JqZWN0IHR5cGUgZ3VhcmRlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNBcnJvd1RhYmxlKHRhYmxlOiBhbnkpOiB0YWJsZSBpcyBhcnJvdy5UYWJsZSB7XG4gIHJldHVybiBCb29sZWFuKHRhYmxlIGluc3RhbmNlb2YgYXJyb3cuVGFibGUpO1xufVxuXG4vKipcbiAqIGNoZWNrIGlmIGRhdGEgaXMgYW4gQXJyb3dEYXRhIG9iamVjdCwgd2hpY2ggaXMgYW4gYXJyYXkgb2YgUmVjb3JkQmF0Y2hcbiAqIEBwYXJhbSBkYXRhIC0gb2JqZWN0IHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0cnVlIGlmIGRhdGEgaXMgYW4gQXJyb3dEYXRhIG9iamVjdCB0eXBlIGd1YXJkZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQXJyb3dEYXRhKGRhdGE6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShkYXRhKSAmJiBCb29sZWFuKGRhdGEubGVuZ3RoICYmIGRhdGFbMF0uZGF0YSAmJiBkYXRhWzBdLnNjaGVtYSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0dlb0pzb24oanNvbjogdW5rbm93bik6IGpzb24gaXMgRmVhdHVyZSB8IEZlYXR1cmVDb2xsZWN0aW9uIHtcbiAgLy8ganNvbiBjYW4gYmUgZmVhdHVyZSBjb2xsZWN0aW9uXG4gIC8vIG9yIHNpbmdsZSBmZWF0dXJlXG4gIHJldHVybiBpc1BsYWluT2JqZWN0KGpzb24pICYmIChpc0ZlYXR1cmUoanNvbikgfHwgaXNGZWF0dXJlQ29sbGVjdGlvbihqc29uKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0ZlYXR1cmUoanNvbjogdW5rbm93bik6IGpzb24gaXMgRmVhdHVyZSB7XG4gIHJldHVybiBpc1BsYWluT2JqZWN0KGpzb24pICYmIGpzb24udHlwZSA9PT0gJ0ZlYXR1cmUnICYmIEJvb2xlYW4oanNvbi5nZW9tZXRyeSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0ZlYXR1cmVDb2xsZWN0aW9uKGpzb246IHVua25vd24pOiBqc29uIGlzIEZlYXR1cmVDb2xsZWN0aW9uIHtcbiAgcmV0dXJuIGlzUGxhaW5PYmplY3QoanNvbikgJiYganNvbi50eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nICYmIEJvb2xlYW4oanNvbi5mZWF0dXJlcyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1Jvd09iamVjdChqc29uOiBhbnkpOiBib29sZWFuIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoanNvbikgJiYgaXNQbGFpbk9iamVjdChqc29uWzBdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzS2VwbGVyR2xNYXAoanNvbjogdW5rbm93bik6IGpzb24gaXMgVmFsaWRLZXBsZXJHbE1hcCB7XG4gIHJldHVybiBCb29sZWFuKFxuICAgIGlzUGxhaW5PYmplY3QoanNvbikgJiZcbiAgICAgIGpzb24uZGF0YXNldHMgJiZcbiAgICAgIGpzb24uY29uZmlnICYmXG4gICAgICBqc29uLmluZm8gJiZcbiAgICAgIGlzUGxhaW5PYmplY3QoanNvbi5pbmZvKSAmJlxuICAgICAganNvbi5pbmZvLmFwcCA9PT0gJ2tlcGxlci5nbCdcbiAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBtYWtlUHJvZ3Jlc3NJdGVyYXRvcihcbiAgYXN5bmNJdGVyYXRvcjogQXN5bmNJdGVyYWJsZTxhbnk+LFxuICBpbmZvOiB7c2l6ZTogbnVtYmVyfVxuKTogQXN5bmNHZW5lcmF0b3Ige1xuICBsZXQgcm93Q291bnQgPSAwO1xuXG4gIGZvciBhd2FpdCAoY29uc3QgYmF0Y2ggb2YgYXN5bmNJdGVyYXRvcikge1xuICAgIC8vIHRoZSBsZW5ndGggY291bGQgYmUgc3RvcmVkIGluIGBiYXRjaC5sZW5ndGhgIGZvciBhcnJvdyBiYXRjaFxuICAgIGNvbnN0IHJvd0NvdW50SW5CYXRjaCA9IChiYXRjaC5kYXRhICYmIChiYXRjaC5kYXRhLmxlbmd0aCB8fCBiYXRjaC5sZW5ndGgpKSB8fCAwO1xuICAgIHJvd0NvdW50ICs9IHJvd0NvdW50SW5CYXRjaDtcbiAgICBjb25zdCBwZXJjZW50ID0gTnVtYmVyLmlzRmluaXRlKGJhdGNoLmJ5dGVzVXNlZCkgPyBiYXRjaC5ieXRlc1VzZWQgLyBpbmZvLnNpemUgOiBudWxsO1xuXG4gICAgLy8gVXBkYXRlIHByb2dyZXNzIG9iamVjdFxuICAgIGNvbnN0IHByb2dyZXNzID0ge1xuICAgICAgcm93Q291bnQsXG4gICAgICByb3dDb3VudEluQmF0Y2gsXG4gICAgICAuLi4oTnVtYmVyLmlzRmluaXRlKHBlcmNlbnQpID8ge3BlcmNlbnR9IDoge30pXG4gICAgfTtcblxuICAgIHlpZWxkIHsuLi5iYXRjaCwgcHJvZ3Jlc3N9O1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24qIHJlYWRCYXRjaChcbiAgYXN5bmNJdGVyYXRvcjogQXN5bmNJdGVyYWJsZTxhbnk+LFxuICBmaWxlTmFtZTogc3RyaW5nXG4pOiBBc3luY0dlbmVyYXRvciB7XG4gIGxldCByZXN1bHQgPSBudWxsO1xuICBjb25zdCBiYXRjaGVzID0gPGFueT5bXTtcbiAgZm9yIGF3YWl0IChjb25zdCBiYXRjaCBvZiBhc3luY0l0ZXJhdG9yKSB7XG4gICAgLy8gTGFzdCBiYXRjaCB3aWxsIGhhdmUgdGhpcyBzcGVjaWFsIHR5cGUgYW5kIHdpbGwgcHJvdmlkZSBhbGwgdGhlIHJvb3RcbiAgICAvLyBwcm9wZXJ0aWVzIG9mIHRoZSBwYXJzZWQgZG9jdW1lbnQuXG4gICAgLy8gT25seSBqc29uIHBhcnNlIHdpbGwgaGF2ZSBgRklOQUxfUkVTVUxUYFxuICAgIGlmIChiYXRjaC5iYXRjaFR5cGUgPT09IEJBVENIX1RZUEUuRklOQUxfUkVTVUxUKSB7XG4gICAgICBpZiAoYmF0Y2guY29udGFpbmVyKSB7XG4gICAgICAgIHJlc3VsdCA9IHsuLi5iYXRjaC5jb250YWluZXJ9O1xuICAgICAgfVxuICAgICAgLy8gU2V0IHRoZSBzdHJlYW1lZCBkYXRhIGNvcnJlY3RseSBpcyBCYXRjaCBqc29uIHBhdGggaXMgc2V0XG4gICAgICAvLyBhbmQgdGhlIHBhdGggc3RyZWFtZWQgaXMgbm90IHRoZSB0b3AgbGV2ZWwgb2JqZWN0IChqc29ucGF0aCA9ICckJylcbiAgICAgIGlmIChiYXRjaC5qc29ucGF0aCAmJiBiYXRjaC5qc29ucGF0aC5sZW5ndGggPiAxKSB7XG4gICAgICAgIGNvbnN0IHN0cmVhbWluZ1BhdGggPSBuZXcgX0pTT05QYXRoKGJhdGNoLmpzb25wYXRoKTtcbiAgICAgICAgc3RyZWFtaW5nUGF0aC5zZXRGaWVsZEF0UGF0aChyZXN1bHQsIGJhdGNoZXMpO1xuICAgICAgfSBlbHNlIGlmIChiYXRjaC5qc29ucGF0aCAmJiBiYXRjaC5qc29ucGF0aC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgLy8gVGhlIHN0cmVhbWVkIG9iamVjdCBpcyBhIFJPVyBKU09OLWJhdGNoIChqc29ucGF0aCA9ICckJylcbiAgICAgICAgLy8gcm93IG9iamVjdHNcbiAgICAgICAgcmVzdWx0ID0gYmF0Y2hlcztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgYmF0Y2hEYXRhID0gaXNBcnJvd1RhYmxlKGJhdGNoLmRhdGEpID8gYmF0Y2guZGF0YS5iYXRjaGVzIDogYmF0Y2guZGF0YTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmF0Y2hEYXRhPy5sZW5ndGg7IGkrKykge1xuICAgICAgICBiYXRjaGVzLnB1c2goYmF0Y2hEYXRhW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB5aWVsZCB7XG4gICAgICAuLi5iYXRjaCxcbiAgICAgIC4uLihiYXRjaC5zY2hlbWEgPyB7aGVhZGVyczogT2JqZWN0LmtleXMoYmF0Y2guc2NoZW1hKX0gOiB7fSksXG4gICAgICBmaWxlTmFtZSxcbiAgICAgIC8vIGlmIGRhdGFzZXQgaXMgQ1NWLCBkYXRhIGlzIHNldCB0byB0aGUgcmF3IGJhdGNoZXNcbiAgICAgIGRhdGE6IHJlc3VsdCA/IHJlc3VsdCA6IGJhdGNoZXNcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkRmlsZUluQmF0Y2hlcyh7XG4gIGZpbGUsXG4gIGxvYWRlcnMgPSBbXSxcbiAgbG9hZE9wdGlvbnMgPSB7fVxufToge1xuICBmaWxlOiBGaWxlO1xuICBmaWxlQ2FjaGU6IEZpbGVDYWNoZUl0ZW1bXTtcbiAgbG9hZGVyczogTG9hZGVyW107XG4gIGxvYWRPcHRpb25zOiBhbnk7XG59KTogUHJvbWlzZTxBc3luY0dlbmVyYXRvcj4ge1xuICBsb2FkZXJzID0gW0pTT05Mb2FkZXIsIENTVkxvYWRlciwgR2VvQXJyb3dMb2FkZXIsIFBhcnF1ZXRXYXNtTG9hZGVyLCAuLi5sb2FkZXJzXTtcbiAgbG9hZE9wdGlvbnMgPSB7XG4gICAgY3N2OiBDU1ZfTE9BREVSX09QVElPTlMsXG4gICAgYXJyb3c6IEFSUk9XX0xPQURFUl9PUFRJT05TLFxuICAgIGpzb246IEpTT05fTE9BREVSX09QVElPTlMsXG4gICAgcGFycXVldDogUEFSUVVFVF9MT0FERVJfT1BUSU9OUyxcbiAgICBtZXRhZGF0YTogdHJ1ZSxcbiAgICAuLi5sb2FkT3B0aW9uc1xuICB9O1xuXG4gIGNvbnN0IGJhdGNoSXRlcmF0b3IgPSBhd2FpdCBwYXJzZUluQmF0Y2hlcyhmaWxlLCBsb2FkZXJzLCBsb2FkT3B0aW9ucyk7XG4gIGNvbnN0IHByb2dyZXNzSXRlcmF0b3IgPSBtYWtlUHJvZ3Jlc3NJdGVyYXRvcihiYXRjaEl0ZXJhdG9yLCB7c2l6ZTogZmlsZS5zaXplfSk7XG5cbiAgcmV0dXJuIHJlYWRCYXRjaChwcm9ncmVzc0l0ZXJhdG9yLCBmaWxlLm5hbWUpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0ZpbGVEYXRhKHtcbiAgY29udGVudCxcbiAgZmlsZUNhY2hlXG59OiB7XG4gIGNvbnRlbnQ6IFByb2Nlc3NGaWxlRGF0YUNvbnRlbnQ7XG4gIGZpbGVDYWNoZTogRmlsZUNhY2hlSXRlbVtdO1xufSk6IFByb21pc2U8RmlsZUNhY2hlSXRlbVtdPiB7XG4gIGNvbnN0IHtmaWxlTmFtZSwgZGF0YX0gPSBjb250ZW50O1xuICBsZXQgZm9ybWF0OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxldCBwcm9jZXNzb3I6ICgoZGF0YTogYW55KSA9PiBQcm9jZXNzb3JSZXN1bHQgfCBMb2FkZWRNYXAgfCBudWxsKSB8IHVuZGVmaW5lZDtcbiAgLy8gZ2VuZXJhdGUgdW5pcXVlIGlkIHdpdGggbGVuZ3RoIG9mIDQgdXNpbmcgZmlsZU5hbWUgc3RyaW5nXG4gIGNvbnN0IGlkID0gZ2VuZXJhdGVIYXNoSWRGcm9tU3RyaW5nKGZpbGVOYW1lKTtcbiAgLy8gZGVjaWRlIG9uIHdoaWNoIHRhYmxlIGNsYXNzIHRvIHVzZSBiYXNlZCBvbiBhcHBsaWNhdGlvbiBjb25maWdcbiAgY29uc3QgdGFibGUgPSBnZXRBcHBsaWNhdGlvbkNvbmZpZygpLnRhYmxlID8/IEtlcGxlclRhYmxlO1xuXG4gIGlmICh0eXBlb2YgdGFibGUuZ2V0RmlsZVByb2Nlc3NvciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIHVzZSBjdXN0b20gcHJvY2Vzc29ycyBmcm9tIHRhYmxlIGNsYXNzXG4gICAgY29uc3QgcHJvY2Vzc29yUmVzdWx0ID0gdGFibGUuZ2V0RmlsZVByb2Nlc3NvcihkYXRhKTtcbiAgICBmb3JtYXQgPSBwcm9jZXNzb3JSZXN1bHQuZm9ybWF0O1xuICAgIHByb2Nlc3NvciA9IHByb2Nlc3NvclJlc3VsdC5wcm9jZXNzb3I7XG4gIH0gZWxzZSB7XG4gICAgLy8gdXNlIGRlZmF1bHQgcHJvY2Vzc29yc1xuICAgIGlmIChpc0Fycm93RGF0YShkYXRhKSkge1xuICAgICAgZm9ybWF0ID0gREFUQVNFVF9GT1JNQVRTLmFycm93O1xuICAgICAgcHJvY2Vzc29yID0gcHJvY2Vzc0Fycm93QmF0Y2hlcztcbiAgICB9IGVsc2UgaWYgKGlzS2VwbGVyR2xNYXAoZGF0YSkpIHtcbiAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5rZXBsZXJnbDtcbiAgICAgIHByb2Nlc3NvciA9IHByb2Nlc3NLZXBsZXJnbEpTT047XG4gICAgfSBlbHNlIGlmIChpc1Jvd09iamVjdChkYXRhKSkge1xuICAgICAgLy8gY3N2IGZpbGUgZ29lcyBoZXJlXG4gICAgICBmb3JtYXQgPSBEQVRBU0VUX0ZPUk1BVFMucm93O1xuICAgICAgcHJvY2Vzc29yID0gcHJvY2Vzc1Jvd09iamVjdDtcbiAgICB9IGVsc2UgaWYgKGlzR2VvSnNvbihkYXRhKSkge1xuICAgICAgZm9ybWF0ID0gREFUQVNFVF9GT1JNQVRTLmdlb2pzb247XG4gICAgICBwcm9jZXNzb3IgPSBwcm9jZXNzR2VvanNvbjtcbiAgICB9XG4gIH1cbiAgaWYgKGZvcm1hdCAmJiBwcm9jZXNzb3IpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1jYXRjaFxuICAgIGxldCByZXN1bHQ7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IHByb2Nlc3NvcihkYXRhKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gbm90IHByb2Nlc3MgdXBsb2FkZWQgZmlsZSwgJHtnZXRFcnJvcihlcnJvciBhcyBFcnJvcil9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtcbiAgICAgIC4uLmZpbGVDYWNoZSxcbiAgICAgIHtcbiAgICAgICAgZGF0YTogcmVzdWx0LFxuICAgICAgICBpbmZvOiB7XG4gICAgICAgICAgaWQsXG4gICAgICAgICAgbGFiZWw6IGNvbnRlbnQuZmlsZU5hbWUsXG4gICAgICAgICAgZm9ybWF0XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICBdO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBwcm9jZXNzIHVwbG9hZGVkIGZpbGUsIHVua25vd24gZmlsZSBmb3JtYXQnKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZmlsZXNUb0RhdGFQYXlsb2FkKGZpbGVDYWNoZTogRmlsZUNhY2hlSXRlbVtdKTogQWRkRGF0YVRvTWFwUGF5bG9hZFtdIHtcbiAgLy8gc2VwZXJhdGUgb3V0IGZpbGVzIHdoaWNoIGNvdWxkIGJlIGEgc2luZ2xlIGRhdGFzZXRzLiBvciBhIGtlcGxlcmdsIG1hcCBqc29uXG4gIGNvbnN0IGNvbGxlY3Rpb24gPSBmaWxlQ2FjaGUucmVkdWNlPHtcbiAgICBkYXRhc2V0czogRmlsZUNhY2hlSXRlbVtdO1xuICAgIGtlcGxlck1hcHM6IEFkZERhdGFUb01hcFBheWxvYWRbXTtcbiAgfT4oXG4gICAgKGFjY3UsIGZpbGUpID0+IHtcbiAgICAgIGNvbnN0IHtkYXRhLCBpbmZvfSA9IGZpbGU7XG4gICAgICBpZiAoaW5mbz8uZm9ybWF0ID09PSBEQVRBU0VUX0ZPUk1BVFMua2VwbGVyZ2wpIHtcbiAgICAgICAgLy8gaWYgZmlsZSBjb250YWlucyBhIHNpbmdsZSBrZXBsZXIgbWFwIGRhdGFzZXQgJiBjb25maWdcbiAgICAgICAgYWNjdS5rZXBsZXJNYXBzLnB1c2goe1xuICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgY2VudGVyTWFwOiAhKGRhdGEuY29uZmlnICYmIGRhdGEuY29uZmlnLm1hcFN0YXRlKVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKERBVEFTRVRfRk9STUFUU1tpbmZvPy5mb3JtYXRdKSB7XG4gICAgICAgIC8vIGlmIGZpbGUgY29udGFpbnMgb25seSBkYXRhXG4gICAgICAgIGNvbnN0IG5ld0RhdGFzZXQgPSB7XG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBpbmZvOiB7XG4gICAgICAgICAgICBpZDogaW5mbz8uaWQgfHwgZ2VuZXJhdGVIYXNoSWQoNCksXG4gICAgICAgICAgICAuLi4oaW5mbyB8fCB7fSlcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGFjY3UuZGF0YXNldHMucHVzaChuZXdEYXRhc2V0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1O1xuICAgIH0sXG4gICAge2RhdGFzZXRzOiBbXSwga2VwbGVyTWFwczogW119XG4gICk7XG5cbiAgLy8gYWRkIGtlcGxlciBtYXAgZmlyc3Qgd2l0aCBjb25maWdcbiAgLy8gYWRkIGRhdGFzZXRzIGxhdGVyIGluIG9uZSBhZGQgZGF0YSBjYWxsXG4gIHJldHVybiBjb2xsZWN0aW9uLmtlcGxlck1hcHMuY29uY2F0KHtkYXRhc2V0czogY29sbGVjdGlvbi5kYXRhc2V0c30pO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsS0FBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsS0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsS0FBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsSUFBQSxHQUFBSCxPQUFBO0FBQ0Es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