@kepler.gl/duckdb 3.3.0-alpha.0 → 3.3.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/cjs/adapters/duckdb-wasm-adapter.js +258 -0
  2. package/dist/{components → cjs/components}/index.js +1 -1
  3. package/dist/cjs/components/monaco-editor.js +174 -0
  4. package/dist/cjs/components/preview-data-panel.js +127 -0
  5. package/dist/cjs/components/schema-panel.js +170 -0
  6. package/dist/cjs/components/sql-panel.js +395 -0
  7. package/dist/cjs/components/tree.js +90 -0
  8. package/dist/{index.js → cjs/index.js} +1 -1
  9. package/dist/{plugin.js → cjs/plugin.js} +2 -2
  10. package/dist/cjs/processors/data-processor.js +353 -0
  11. package/dist/cjs/table/duckdb-table-utils.js +670 -0
  12. package/dist/cjs/table/duckdb-table.js +482 -0
  13. package/dist/{table → cjs/table}/index.js +1 -1
  14. package/dist/cjs/utils/perf.js +46 -0
  15. package/dist/esm/adapters/duckdb-wasm-adapter.js +251 -0
  16. package/dist/esm/components/index.js +9 -0
  17. package/dist/esm/components/monaco-editor.js +167 -0
  18. package/dist/esm/components/preview-data-panel.js +120 -0
  19. package/dist/esm/components/schema-panel.js +164 -0
  20. package/dist/esm/components/sql-panel.js +388 -0
  21. package/dist/esm/components/tree.js +82 -0
  22. package/dist/esm/index.js +9 -0
  23. package/dist/esm/plugin.js +22 -0
  24. package/dist/esm/processors/data-processor.js +342 -0
  25. package/dist/esm/table/duckdb-table-utils.js +645 -0
  26. package/dist/esm/table/duckdb-table.js +477 -0
  27. package/dist/esm/table/index.js +5 -0
  28. package/dist/esm/utils/perf.js +40 -0
  29. package/dist/table/duckdb-table-utils.d.ts +7 -0
  30. package/package.json +28 -24
  31. package/dist/adapters/duckdb-wasm-adapter.js +0 -259
  32. package/dist/components/monaco-editor.js +0 -175
  33. package/dist/components/preview-data-panel.js +0 -128
  34. package/dist/components/schema-panel.js +0 -171
  35. package/dist/components/sql-panel.js +0 -396
  36. package/dist/components/tree.js +0 -91
  37. package/dist/processors/data-processor.js +0 -353
  38. package/dist/table/duckdb-table-utils.js +0 -669
  39. package/dist/table/duckdb-table.js +0 -480
  40. package/dist/utils/perf.js +0 -46
@@ -0,0 +1,342 @@
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
5
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
6
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
7
+ 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; }
8
+ 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) { _defineProperty(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; }
9
+ // SPDX-License-Identifier: MIT
10
+ // Copyright contributors to the kepler.gl project
11
+
12
+ import normalize from '@mapbox/geojson-normalize';
13
+ import { getSampleForTypeAnalyze, getFieldsFromData, generateHashId, notNullorUndefined } from '@kepler.gl/common-utils';
14
+ import { ALL_FIELD_TYPES, GUIDES_FILE_FORMAT_DOC } from '@kepler.gl/constants';
15
+ import { processKeplerglJSON } from '@kepler.gl/processors';
16
+ import { getApplicationConfig } from '@kepler.gl/utils';
17
+ export var CSV_NULLS = /^(null|NULL|Null|NaN|\/N||)$/;
18
+ var COLUMN_TYPES = /*#__PURE__*/function (COLUMN_TYPES) {
19
+ COLUMN_TYPES["GEOMETRY"] = "GEOMETRY";
20
+ COLUMN_TYPES["BOOLEAN"] = "BOOLEAN";
21
+ COLUMN_TYPES["INTEGER"] = "INTEGER";
22
+ COLUMN_TYPES["FLOAT"] = "FLOAT";
23
+ COLUMN_TYPES["TIME"] = "TIME";
24
+ COLUMN_TYPES["DATE"] = "DATE";
25
+ COLUMN_TYPES["TIMESTAMP"] = "TIMESTAMP";
26
+ COLUMN_TYPES["VARCHAR"] = "VARCHAR";
27
+ return COLUMN_TYPES;
28
+ }(COLUMN_TYPES || {}); // https://duckdb.org/docs/data/csv/auto_detection.html#type-detection
29
+ export var COLUMN_TYPES_PRIORITIES = ['GEOMETRY', 'BOOLEAN', 'INTEGER', 'FLOAT', 'TIME', 'DATE', 'TIMESTAMP', 'VARCHAR'];
30
+ export function columnTypeToFieldType(columnType) {
31
+ switch (columnType) {
32
+ case COLUMN_TYPES.BOOLEAN:
33
+ return ALL_FIELD_TYPES["boolean"];
34
+ case COLUMN_TYPES.DATE:
35
+ return ALL_FIELD_TYPES.date;
36
+ case COLUMN_TYPES.INTEGER:
37
+ return ALL_FIELD_TYPES.integer;
38
+ case COLUMN_TYPES.FLOAT:
39
+ return ALL_FIELD_TYPES.real;
40
+ case COLUMN_TYPES.VARCHAR:
41
+ return ALL_FIELD_TYPES.string;
42
+ case COLUMN_TYPES.TIMESTAMP:
43
+ return ALL_FIELD_TYPES.timestamp;
44
+ case COLUMN_TYPES.GEOMETRY:
45
+ return ALL_FIELD_TYPES.geojson;
46
+ default:
47
+ // is there any other type we didn't cover?
48
+ console.warn("Unsupported DuckDB Column type: ".concat(columnType));
49
+ return null;
50
+ }
51
+ }
52
+ export function fieldTypeToColumnType(fieldType) {
53
+ switch (fieldType) {
54
+ case ALL_FIELD_TYPES["boolean"]:
55
+ return COLUMN_TYPES.BOOLEAN;
56
+ case ALL_FIELD_TYPES.date:
57
+ return COLUMN_TYPES.DATE;
58
+ case ALL_FIELD_TYPES.integer:
59
+ return COLUMN_TYPES.INTEGER;
60
+ case ALL_FIELD_TYPES.real:
61
+ return COLUMN_TYPES.FLOAT;
62
+ case ALL_FIELD_TYPES.string:
63
+ return COLUMN_TYPES.VARCHAR;
64
+ case ALL_FIELD_TYPES.timestamp:
65
+ return COLUMN_TYPES.TIMESTAMP;
66
+ case ALL_FIELD_TYPES.geojson:
67
+ return COLUMN_TYPES.GEOMETRY;
68
+ default:
69
+ // is there any other type we didn't cover?
70
+ console.warn("Unsupported Field type for DuckDb: ".concat(fieldType));
71
+ return null;
72
+ }
73
+ }
74
+
75
+ /*
76
+ * Process uploaded exported Keplergl json map.
77
+ * We need to populate field with proper DuckDb compatible type.
78
+ */
79
+ // TODO: merge with logic from processCsvRowObject. Different formats: [[]] vs [{}]
80
+ export function processKeplerglJSONforDuckDb(_x) {
81
+ return _processKeplerglJSONforDuckDb.apply(this, arguments);
82
+ }
83
+
84
+ /*
85
+ * Process uploaded csv returned by loaders.gl as row object and string value
86
+ */
87
+ function _processKeplerglJSONforDuckDb() {
88
+ _processKeplerglJSONforDuckDb = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(keplerJson) {
89
+ var res, datasets, _iterator, _step, _loop2;
90
+ return _regeneratorRuntime.wrap(function _callee$(_context2) {
91
+ while (1) switch (_context2.prev = _context2.next) {
92
+ case 0:
93
+ res = processKeplerglJSON(keplerJson);
94
+ datasets = (res === null || res === void 0 ? void 0 : res.datasets) || [];
95
+ _iterator = _createForOfIteratorHelper(datasets);
96
+ _context2.prev = 3;
97
+ _loop2 = /*#__PURE__*/_regeneratorRuntime.mark(function _loop2() {
98
+ var dataset, rowsAll, fieldsAll, header, sample, schema, fieldsUpd;
99
+ return _regeneratorRuntime.wrap(function _loop2$(_context) {
100
+ while (1) switch (_context.prev = _context.next) {
101
+ case 0:
102
+ dataset = _step.value;
103
+ rowsAll = dataset.data.rows;
104
+ fieldsAll = dataset.data.fields;
105
+ header = fieldsAll.map(function (f) {
106
+ return f.name;
107
+ });
108
+ sample = getSampleForTypeAnalyze({
109
+ fields: header,
110
+ rows: rowsAll
111
+ });
112
+ if (!(sample.length > 0)) {
113
+ _context.next = 11;
114
+ break;
115
+ }
116
+ _context.next = 8;
117
+ return sniffCsvSchema(sample);
118
+ case 8:
119
+ _context.t0 = _context.sent;
120
+ _context.next = 12;
121
+ break;
122
+ case 11:
123
+ _context.t0 = fieldsAll.reduce(function (acc, field) {
124
+ acc[field.name] = fieldTypeToColumnType(field.type);
125
+ return acc;
126
+ }, {});
127
+ case 12:
128
+ schema = _context.t0;
129
+ fieldsUpd = consolidateFieldTypes(dataset.data.fields, schema);
130
+ dataset.data.fields = fieldsAll.map(function (f, i) {
131
+ return _objectSpread(_objectSpread({}, fieldsUpd[i]), f);
132
+ });
133
+ case 15:
134
+ case "end":
135
+ return _context.stop();
136
+ }
137
+ }, _loop2);
138
+ });
139
+ _iterator.s();
140
+ case 6:
141
+ if ((_step = _iterator.n()).done) {
142
+ _context2.next = 10;
143
+ break;
144
+ }
145
+ return _context2.delegateYield(_loop2(), "t0", 8);
146
+ case 8:
147
+ _context2.next = 6;
148
+ break;
149
+ case 10:
150
+ _context2.next = 15;
151
+ break;
152
+ case 12:
153
+ _context2.prev = 12;
154
+ _context2.t1 = _context2["catch"](3);
155
+ _iterator.e(_context2.t1);
156
+ case 15:
157
+ _context2.prev = 15;
158
+ _iterator.f();
159
+ return _context2.finish(15);
160
+ case 18:
161
+ return _context2.abrupt("return", res);
162
+ case 19:
163
+ case "end":
164
+ return _context2.stop();
165
+ }
166
+ }, _callee, null, [[3, 12, 15, 18]]);
167
+ }));
168
+ return _processKeplerglJSONforDuckDb.apply(this, arguments);
169
+ }
170
+ export function processCsvRowObject(_x2) {
171
+ return _processCsvRowObject.apply(this, arguments);
172
+ }
173
+ function _processCsvRowObject() {
174
+ _processCsvRowObject = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(rawData) {
175
+ var header, sample, schema, fieldsWAnalyzerType, fields;
176
+ return _regeneratorRuntime.wrap(function _callee2$(_context3) {
177
+ while (1) switch (_context3.prev = _context3.next) {
178
+ case 0:
179
+ if (!(!Array.isArray(rawData) || !rawData.length)) {
180
+ _context3.next = 2;
181
+ break;
182
+ }
183
+ return _context3.abrupt("return", {
184
+ fields: [],
185
+ rows: []
186
+ });
187
+ case 2:
188
+ header = Object.keys(rawData[0]); // [lat, lng, value]
189
+ // row object can still contain values like `Null` or `N/A`
190
+ cleanUpFalsyCsvValue(rawData);
191
+ sample = getSampleForTypeAnalyze({
192
+ fields: header,
193
+ rows: rawData
194
+ }); // add sample data to duckdb and get schema
195
+ _context3.next = 7;
196
+ return sniffCsvSchema(sample);
197
+ case 7:
198
+ schema = _context3.sent;
199
+ fieldsWAnalyzerType = getFieldsFromData(sample, header);
200
+ fields = consolidateFieldTypes(fieldsWAnalyzerType, schema);
201
+ return _context3.abrupt("return", {
202
+ rows: rawData,
203
+ fields: fields
204
+ });
205
+ case 11:
206
+ case "end":
207
+ return _context3.stop();
208
+ }
209
+ }, _callee2);
210
+ }));
211
+ return _processCsvRowObject.apply(this, arguments);
212
+ }
213
+ function cleanUpFalsyCsvValue(rows) {
214
+ var re = new RegExp(CSV_NULLS, 'g');
215
+ var _loop = function _loop(i) {
216
+ Object.keys(rows[i]).forEach(function (key) {
217
+ // here we parse empty data as null
218
+ if (typeof rows[i][key] === 'string' && rows[i][key].match(re)) {
219
+ rows[i][key] = null;
220
+ }
221
+ });
222
+ };
223
+ for (var i = 0; i < rows.length; i++) {
224
+ _loop(i);
225
+ }
226
+ }
227
+
228
+ // align type analyzer types with DuckDB csv auto detected column types
229
+ export function consolidateFieldTypes(fields, schema) {
230
+ return fields.map(function (field) {
231
+ var columnName = field.name;
232
+ var detectedColumnType = schema[columnName];
233
+
234
+ // TODO columnTypeToFieldType tranforms detected timestamps to string,
235
+ // completely breaking time filter logic.
236
+ // const fieldType = columnTypeToFieldType(detectedColumnType) || field.type;
237
+
238
+ return _objectSpread(_objectSpread({}, field), {}, {
239
+ // type: fieldType,
240
+ duckDBColumnType: detectedColumnType
241
+ });
242
+ });
243
+ }
244
+ function toCSVRow(row) {
245
+ return "".concat(row.map(function (r) {
246
+ var rToStr = notNullorUndefined(r) ? String(r).replace(/"/g, '\\"') : '';
247
+ return rToStr.includes(',') ? "\"".concat(rToStr, "\"") : rToStr;
248
+ }).join(','), "\n");
249
+ }
250
+
251
+ // Use DucckDB to detect csv column schema
252
+ function sniffCsvSchema(_x3) {
253
+ return _sniffCsvSchema.apply(this, arguments);
254
+ }
255
+ function _sniffCsvSchema() {
256
+ _sniffCsvSchema = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(sample) {
257
+ var headerRow, csvContent, db, c, fileName, result, schemaResult, columns, schema, i;
258
+ return _regeneratorRuntime.wrap(function _callee3$(_context4) {
259
+ while (1) switch (_context4.prev = _context4.next) {
260
+ case 0:
261
+ if (!(!Array.isArray(sample) || sample.length < 0)) {
262
+ _context4.next = 2;
263
+ break;
264
+ }
265
+ return _context4.abrupt("return");
266
+ case 2:
267
+ headerRow = toCSVRow(Object.keys(sample[0]));
268
+ csvContent = sample.reduce(function (accu, row) {
269
+ return "".concat(accu).concat(toCSVRow(Object.values(row)));
270
+ }, headerRow);
271
+ db = getApplicationConfig().database;
272
+ if (db) {
273
+ _context4.next = 8;
274
+ break;
275
+ }
276
+ console.error('The database is not configured properly.');
277
+ return _context4.abrupt("return");
278
+ case 8:
279
+ _context4.next = 10;
280
+ return db.connect();
281
+ case 10:
282
+ c = _context4.sent;
283
+ fileName = generateHashId();
284
+ _context4.next = 14;
285
+ return db.registerFileText("".concat(fileName, "-").concat(generateHashId, ".csv"), csvContent);
286
+ case 14:
287
+ _context4.next = 16;
288
+ return c.query("\n FROM sniff_csv('".concat(fileName, "-").concat(generateHashId, ".csv', \n sample_size = 500,\n auto_type_candidates = ['FLOAT', 'INTEGER', 'TIMESTAMP', 'DATE', 'TIME', 'VARCHAR', 'BOOLEAN']);\n "));
289
+ case 16:
290
+ result = _context4.sent;
291
+ schemaResult = result.toArray().map(function (row) {
292
+ return row.toJSON();
293
+ });
294
+ columns = schemaResult[0].Columns;
295
+ schema = {};
296
+ for (i = 0; i < columns.length; i++) {
297
+ schema[columns.get(i).name] = columns.get(i).type;
298
+ }
299
+ return _context4.abrupt("return", schema);
300
+ case 22:
301
+ case "end":
302
+ return _context4.stop();
303
+ }
304
+ }, _callee3);
305
+ }));
306
+ return _sniffCsvSchema.apply(this, arguments);
307
+ }
308
+ export function processGeojson(rawData) {
309
+ var normalizedGeojson = normalize(rawData);
310
+ if (!normalizedGeojson || !Array.isArray(normalizedGeojson.features)) {
311
+ var error = new Error("Read File Failed: File is not a valid GeoJSON. Read more about [supported file format](".concat(GUIDES_FILE_FORMAT_DOC, ")"));
312
+ throw error;
313
+ }
314
+
315
+ // @ts-expect-error Don't pass empty fields, as duck db outputs an empty dataset
316
+ return {
317
+ rows: normalizedGeojson
318
+ // TODO get fields to preserve field names?
319
+ // fields: []
320
+ };
321
+ }
322
+
323
+ /**
324
+ * A utility function to extend existing fields with native DuckDB column type.
325
+ * @param fields Array of fields to extend.
326
+ * @param typeOverrides An optional mapping of DuckDB column types to override.
327
+ * @returns An array of fields with the DuckDB column type extended.
328
+ */
329
+ export function extendFieldsWithDuckDBColumnType(fields, typeOverrides) {
330
+ var schema = fields.reduce(function (acc, field) {
331
+ acc[field.name] = fieldTypeToColumnType(field.type);
332
+ return acc;
333
+ }, {});
334
+ var updatedFields = consolidateFieldTypes(fields, schema);
335
+ updatedFields.forEach(function (field) {
336
+ if (typeOverrides[field.duckDBColumnType]) {
337
+ field.duckDBColumnType = typeOverrides[field.duckDBColumnType];
338
+ }
339
+ });
340
+ return updatedFields;
341
+ }
342
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJub3JtYWxpemUiLCJnZXRTYW1wbGVGb3JUeXBlQW5hbHl6ZSIsImdldEZpZWxkc0Zyb21EYXRhIiwiZ2VuZXJhdGVIYXNoSWQiLCJub3ROdWxsb3JVbmRlZmluZWQiLCJBTExfRklFTERfVFlQRVMiLCJHVUlERVNfRklMRV9GT1JNQVRfRE9DIiwicHJvY2Vzc0tlcGxlcmdsSlNPTiIsImdldEFwcGxpY2F0aW9uQ29uZmlnIiwiQ1NWX05VTExTIiwiQ09MVU1OX1RZUEVTIiwiQ09MVU1OX1RZUEVTX1BSSU9SSVRJRVMiLCJjb2x1bW5UeXBlVG9GaWVsZFR5cGUiLCJjb2x1bW5UeXBlIiwiQk9PTEVBTiIsIkRBVEUiLCJkYXRlIiwiSU5URUdFUiIsImludGVnZXIiLCJGTE9BVCIsInJlYWwiLCJWQVJDSEFSIiwic3RyaW5nIiwiVElNRVNUQU1QIiwidGltZXN0YW1wIiwiR0VPTUVUUlkiLCJnZW9qc29uIiwiY29uc29sZSIsIndhcm4iLCJjb25jYXQiLCJmaWVsZFR5cGVUb0NvbHVtblR5cGUiLCJmaWVsZFR5cGUiLCJwcm9jZXNzS2VwbGVyZ2xKU09OZm9yRHVja0RiIiwiX3giLCJfcHJvY2Vzc0tlcGxlcmdsSlNPTmZvckR1Y2tEYiIsImFwcGx5IiwiYXJndW1lbnRzIiwiX2FzeW5jVG9HZW5lcmF0b3IiLCJfcmVnZW5lcmF0b3JSdW50aW1lIiwibWFyayIsIl9jYWxsZWUiLCJrZXBsZXJKc29uIiwicmVzIiwiZGF0YXNldHMiLCJfaXRlcmF0b3IiLCJfc3RlcCIsIl9sb29wMiIsIndyYXAiLCJfY2FsbGVlJCIsIl9jb250ZXh0MiIsInByZXYiLCJuZXh0IiwiX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIiLCJkYXRhc2V0Iiwicm93c0FsbCIsImZpZWxkc0FsbCIsImhlYWRlciIsInNhbXBsZSIsInNjaGVtYSIsImZpZWxkc1VwZCIsIl9sb29wMiQiLCJfY29udGV4dCIsInZhbHVlIiwiZGF0YSIsInJvd3MiLCJmaWVsZHMiLCJtYXAiLCJmIiwibmFtZSIsImxlbmd0aCIsInNuaWZmQ3N2U2NoZW1hIiwidDAiLCJzZW50IiwicmVkdWNlIiwiYWNjIiwiZmllbGQiLCJ0eXBlIiwiY29uc29saWRhdGVGaWVsZFR5cGVzIiwiaSIsIl9vYmplY3RTcHJlYWQiLCJzdG9wIiwicyIsIm4iLCJkb25lIiwiZGVsZWdhdGVZaWVsZCIsInQxIiwiZSIsImZpbmlzaCIsImFicnVwdCIsInByb2Nlc3NDc3ZSb3dPYmplY3QiLCJfeDIiLCJfcHJvY2Vzc0NzdlJvd09iamVjdCIsIl9jYWxsZWUyIiwicmF3RGF0YSIsImZpZWxkc1dBbmFseXplclR5cGUiLCJfY2FsbGVlMiQiLCJfY29udGV4dDMiLCJBcnJheSIsImlzQXJyYXkiLCJPYmplY3QiLCJrZXlzIiwiY2xlYW5VcEZhbHN5Q3N2VmFsdWUiLCJyZSIsIlJlZ0V4cCIsIl9sb29wIiwiZm9yRWFjaCIsImtleSIsIm1hdGNoIiwiY29sdW1uTmFtZSIsImRldGVjdGVkQ29sdW1uVHlwZSIsImR1Y2tEQkNvbHVtblR5cGUiLCJ0b0NTVlJvdyIsInJvdyIsInIiLCJyVG9TdHIiLCJTdHJpbmciLCJyZXBsYWNlIiwiaW5jbHVkZXMiLCJqb2luIiwiX3gzIiwiX3NuaWZmQ3N2U2NoZW1hIiwiX2NhbGxlZTMiLCJoZWFkZXJSb3ciLCJjc3ZDb250ZW50IiwiZGIiLCJjIiwiZmlsZU5hbWUiLCJyZXN1bHQiLCJzY2hlbWFSZXN1bHQiLCJjb2x1bW5zIiwiX2NhbGxlZTMkIiwiX2NvbnRleHQ0IiwiYWNjdSIsInZhbHVlcyIsImRhdGFiYXNlIiwiZXJyb3IiLCJjb25uZWN0IiwicmVnaXN0ZXJGaWxlVGV4dCIsInF1ZXJ5IiwidG9BcnJheSIsInRvSlNPTiIsIkNvbHVtbnMiLCJnZXQiLCJwcm9jZXNzR2VvanNvbiIsIm5vcm1hbGl6ZWRHZW9qc29uIiwiZmVhdHVyZXMiLCJFcnJvciIsImV4dGVuZEZpZWxkc1dpdGhEdWNrREJDb2x1bW5UeXBlIiwidHlwZU92ZXJyaWRlcyIsInVwZGF0ZWRGaWVsZHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcHJvY2Vzc29ycy9kYXRhLXByb2Nlc3Nvci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgKiBhcyBhcnJvdyBmcm9tICdhcGFjaGUtYXJyb3cnO1xuaW1wb3J0IG5vcm1hbGl6ZSBmcm9tICdAbWFwYm94L2dlb2pzb24tbm9ybWFsaXplJztcblxuaW1wb3J0IHtcbiAgZ2V0U2FtcGxlRm9yVHlwZUFuYWx5emUsXG4gIGdldEZpZWxkc0Zyb21EYXRhLFxuICBnZW5lcmF0ZUhhc2hJZCxcbiAgbm90TnVsbG9yVW5kZWZpbmVkXG59IGZyb20gJ0BrZXBsZXIuZ2wvY29tbW9uLXV0aWxzJztcbmltcG9ydCB7UHJvdG9EYXRhc2V0RmllbGR9IGZyb20gJ0BrZXBsZXIuZ2wvdHlwZXMnO1xuaW1wb3J0IHtBTExfRklFTERfVFlQRVMsIEdVSURFU19GSUxFX0ZPUk1BVF9ET0N9IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcbmltcG9ydCB7cHJvY2Vzc0tlcGxlcmdsSlNPTn0gZnJvbSAnQGtlcGxlci5nbC9wcm9jZXNzb3JzJztcbmltcG9ydCB7Z2V0QXBwbGljYXRpb25Db25maWd9IGZyb20gJ0BrZXBsZXIuZ2wvdXRpbHMnO1xuXG5leHBvcnQgY29uc3QgQ1NWX05VTExTID0gL14obnVsbHxOVUxMfE51bGx8TmFOfFxcL058fCkkLztcblxudHlwZSBSb3dzQXNBcnJheSA9IGFueVtdW107XG50eXBlIFJvd3NBc09iamVjdCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107XG50eXBlIFJvd0RhdGEgPSBSb3dzQXNBcnJheSB8IFJvd3NBc09iamVjdDtcblxuZXhwb3J0IHR5cGUgUHJvY2Vzc29yUmVzdWx0ID0ge1xuICBjb2xzPzogYXJyb3cuVmVjdG9yW107XG4gIHJvd3M6IFJvd0RhdGE7XG4gIGZpZWxkczogUHJvdG9EYXRhc2V0RmllbGRbXTtcbn07XG5cbmVudW0gQ09MVU1OX1RZUEVTIHtcbiAgR0VPTUVUUlkgPSAnR0VPTUVUUlknLFxuICBCT09MRUFOID0gJ0JPT0xFQU4nLFxuICBJTlRFR0VSID0gJ0lOVEVHRVInLFxuICBGTE9BVCA9ICdGTE9BVCcsXG4gIFRJTUUgPSAnVElNRScsXG4gIERBVEUgPSAnREFURScsXG4gIFRJTUVTVEFNUCA9ICdUSU1FU1RBTVAnLFxuICBWQVJDSEFSID0gJ1ZBUkNIQVInXG59XG4vLyBodHRwczovL2R1Y2tkYi5vcmcvZG9jcy9kYXRhL2Nzdi9hdXRvX2RldGVjdGlvbi5odG1sI3R5cGUtZGV0ZWN0aW9uXG5leHBvcnQgY29uc3QgQ09MVU1OX1RZUEVTX1BSSU9SSVRJRVMgPSBbXG4gICdHRU9NRVRSWScsXG4gICdCT09MRUFOJyxcbiAgJ0lOVEVHRVInLFxuICAnRkxPQVQnLFxuICAnVElNRScsXG4gICdEQVRFJyxcbiAgJ1RJTUVTVEFNUCcsXG4gICdWQVJDSEFSJ1xuXTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbHVtblR5cGVUb0ZpZWxkVHlwZShjb2x1bW5UeXBlOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgc3dpdGNoIChjb2x1bW5UeXBlKSB7XG4gICAgY2FzZSBDT0xVTU5fVFlQRVMuQk9PTEVBTjpcbiAgICAgIHJldHVybiBBTExfRklFTERfVFlQRVMuYm9vbGVhbjtcbiAgICBjYXNlIENPTFVNTl9UWVBFUy5EQVRFOlxuICAgICAgcmV0dXJuIEFMTF9GSUVMRF9UWVBFUy5kYXRlO1xuICAgIGNhc2UgQ09MVU1OX1RZUEVTLklOVEVHRVI6XG4gICAgICByZXR1cm4gQUxMX0ZJRUxEX1RZUEVTLmludGVnZXI7XG4gICAgY2FzZSBDT0xVTU5fVFlQRVMuRkxPQVQ6XG4gICAgICByZXR1cm4gQUxMX0ZJRUxEX1RZUEVTLnJlYWw7XG4gICAgY2FzZSBDT0xVTU5fVFlQRVMuVkFSQ0hBUjpcbiAgICAgIHJldHVybiBBTExfRklFTERfVFlQRVMuc3RyaW5nO1xuICAgIGNhc2UgQ09MVU1OX1RZUEVTLlRJTUVTVEFNUDpcbiAgICAgIHJldHVybiBBTExfRklFTERfVFlQRVMudGltZXN0YW1wO1xuICAgIGNhc2UgQ09MVU1OX1RZUEVTLkdFT01FVFJZOlxuICAgICAgcmV0dXJuIEFMTF9GSUVMRF9UWVBFUy5nZW9qc29uO1xuICAgIGRlZmF1bHQ6XG4gICAgICAvLyBpcyB0aGVyZSBhbnkgb3RoZXIgdHlwZSB3ZSBkaWRuJ3QgY292ZXI/XG4gICAgICBjb25zb2xlLndhcm4oYFVuc3VwcG9ydGVkIER1Y2tEQiBDb2x1bW4gdHlwZTogJHtjb2x1bW5UeXBlfWApO1xuICAgICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpZWxkVHlwZVRvQ29sdW1uVHlwZShmaWVsZFR5cGU6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBzd2l0Y2ggKGZpZWxkVHlwZSkge1xuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmJvb2xlYW46XG4gICAgICByZXR1cm4gQ09MVU1OX1RZUEVTLkJPT0xFQU47XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMuZGF0ZTpcbiAgICAgIHJldHVybiBDT0xVTU5fVFlQRVMuREFURTtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5pbnRlZ2VyOlxuICAgICAgcmV0dXJuIENPTFVNTl9UWVBFUy5JTlRFR0VSO1xuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLnJlYWw6XG4gICAgICByZXR1cm4gQ09MVU1OX1RZUEVTLkZMT0FUO1xuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLnN0cmluZzpcbiAgICAgIHJldHVybiBDT0xVTU5fVFlQRVMuVkFSQ0hBUjtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy50aW1lc3RhbXA6XG4gICAgICByZXR1cm4gQ09MVU1OX1RZUEVTLlRJTUVTVEFNUDtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5nZW9qc29uOlxuICAgICAgcmV0dXJuIENPTFVNTl9UWVBFUy5HRU9NRVRSWTtcbiAgICBkZWZhdWx0OlxuICAgICAgLy8gaXMgdGhlcmUgYW55IG90aGVyIHR5cGUgd2UgZGlkbid0IGNvdmVyP1xuICAgICAgY29uc29sZS53YXJuKGBVbnN1cHBvcnRlZCBGaWVsZCB0eXBlIGZvciBEdWNrRGI6ICR7ZmllbGRUeXBlfWApO1xuICAgICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuLypcbiAqIFByb2Nlc3MgdXBsb2FkZWQgZXhwb3J0ZWQgS2VwbGVyZ2wganNvbiBtYXAuXG4gKiBXZSBuZWVkIHRvIHBvcHVsYXRlIGZpZWxkIHdpdGggcHJvcGVyIER1Y2tEYiBjb21wYXRpYmxlIHR5cGUuXG4gKi9cbi8vIFRPRE86IG1lcmdlIHdpdGggbG9naWMgZnJvbSBwcm9jZXNzQ3N2Um93T2JqZWN0LiBEaWZmZXJlbnQgZm9ybWF0czogW1tdXSB2cyBbe31dXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0tlcGxlcmdsSlNPTmZvckR1Y2tEYihcbiAga2VwbGVySnNvblxuKTogUHJvbWlzZTxSZXR1cm5UeXBlPHR5cGVvZiBwcm9jZXNzS2VwbGVyZ2xKU09OPj4ge1xuICBjb25zdCByZXMgPSBwcm9jZXNzS2VwbGVyZ2xKU09OKGtlcGxlckpzb24pO1xuXG4gIGNvbnN0IGRhdGFzZXRzID0gcmVzPy5kYXRhc2V0cyB8fCBbXTtcbiAgZm9yIChjb25zdCBkYXRhc2V0IG9mIGRhdGFzZXRzKSB7XG4gICAgY29uc3Qgcm93c0FsbCA9IGRhdGFzZXQuZGF0YS5yb3dzO1xuICAgIGNvbnN0IGZpZWxkc0FsbCA9IGRhdGFzZXQuZGF0YS5maWVsZHM7XG5cbiAgICBjb25zdCBoZWFkZXIgPSBmaWVsZHNBbGwubWFwKGYgPT4gZi5uYW1lKTtcbiAgICBjb25zdCBzYW1wbGUgPSBnZXRTYW1wbGVGb3JUeXBlQW5hbHl6ZSh7ZmllbGRzOiBoZWFkZXIsIHJvd3M6IHJvd3NBbGx9KTtcblxuICAgIGNvbnN0IHNjaGVtYSA9XG4gICAgICBzYW1wbGUubGVuZ3RoID4gMFxuICAgICAgICA/IGF3YWl0IHNuaWZmQ3N2U2NoZW1hKHNhbXBsZSlcbiAgICAgICAgOiBmaWVsZHNBbGwucmVkdWNlKChhY2MsIGZpZWxkKSA9PiB7XG4gICAgICAgICAgICBhY2NbZmllbGQubmFtZV0gPSBmaWVsZFR5cGVUb0NvbHVtblR5cGUoZmllbGQudHlwZSk7XG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICAgIH0sIHt9KTtcbiAgICBjb25zdCBmaWVsZHNVcGQgPSBjb25zb2xpZGF0ZUZpZWxkVHlwZXMoZGF0YXNldC5kYXRhLmZpZWxkcywgc2NoZW1hKTtcblxuICAgIGRhdGFzZXQuZGF0YS5maWVsZHMgPSBmaWVsZHNBbGwubWFwKChmLCBpKSA9PiB7XG4gICAgICByZXR1cm4gey4uLmZpZWxkc1VwZFtpXSwgLi4uZn07XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gcmVzO1xufVxuXG4vKlxuICogUHJvY2VzcyB1cGxvYWRlZCBjc3YgcmV0dXJuZWQgYnkgbG9hZGVycy5nbCBhcyByb3cgb2JqZWN0IGFuZCBzdHJpbmcgdmFsdWVcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NDc3ZSb3dPYmplY3QoXG4gIHJhd0RhdGE6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bGw+W11cbik6IFByb21pc2U8UHJvY2Vzc29yUmVzdWx0PiB7XG4gIGlmICghQXJyYXkuaXNBcnJheShyYXdEYXRhKSB8fCAhcmF3RGF0YS5sZW5ndGgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZmllbGRzOiBbXSxcbiAgICAgIHJvd3M6IFtdXG4gICAgfTtcbiAgfVxuXG4gIGNvbnN0IGhlYWRlciA9IE9iamVjdC5rZXlzKHJhd0RhdGFbMF0pOyAvLyBbbGF0LCBsbmcsIHZhbHVlXVxuXG4gIC8vIHJvdyBvYmplY3QgY2FuIHN0aWxsIGNvbnRhaW4gdmFsdWVzIGxpa2UgYE51bGxgIG9yIGBOL0FgXG4gIGNsZWFuVXBGYWxzeUNzdlZhbHVlKHJhd0RhdGEpO1xuICBjb25zdCBzYW1wbGUgPSBnZXRTYW1wbGVGb3JUeXBlQW5hbHl6ZSh7ZmllbGRzOiBoZWFkZXIsIHJvd3M6IHJhd0RhdGF9KTtcbiAgLy8gYWRkIHNhbXBsZSBkYXRhIHRvIGR1Y2tkYiBhbmQgZ2V0IHNjaGVtYVxuICBjb25zdCBzY2hlbWEgPSBhd2FpdCBzbmlmZkNzdlNjaGVtYShzYW1wbGUpO1xuXG4gIGNvbnN0IGZpZWxkc1dBbmFseXplclR5cGUgPSBnZXRGaWVsZHNGcm9tRGF0YShzYW1wbGUsIGhlYWRlcik7XG5cbiAgY29uc3QgZmllbGRzID0gY29uc29saWRhdGVGaWVsZFR5cGVzKGZpZWxkc1dBbmFseXplclR5cGUsIHNjaGVtYSk7XG5cbiAgcmV0dXJuIHtyb3dzOiByYXdEYXRhLCBmaWVsZHN9O1xufVxuXG5mdW5jdGlvbiBjbGVhblVwRmFsc3lDc3ZWYWx1ZShyb3dzOiBSb3dEYXRhKTogdm9pZCB7XG4gIGNvbnN0IHJlID0gbmV3IFJlZ0V4cChDU1ZfTlVMTFMsICdnJyk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcm93cy5sZW5ndGg7IGkrKykge1xuICAgIE9iamVjdC5rZXlzKHJvd3NbaV0pLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIC8vIGhlcmUgd2UgcGFyc2UgZW1wdHkgZGF0YSBhcyBudWxsXG4gICAgICBpZiAodHlwZW9mIHJvd3NbaV1ba2V5XSA9PT0gJ3N0cmluZycgJiYgKHJvd3NbaV1ba2V5XSBhcyBzdHJpbmcpLm1hdGNoKHJlKSkge1xuICAgICAgICByb3dzW2ldW2tleV0gPSBudWxsO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG5cbi8vIGFsaWduIHR5cGUgYW5hbHl6ZXIgdHlwZXMgd2l0aCBEdWNrREIgY3N2IGF1dG8gZGV0ZWN0ZWQgY29sdW1uIHR5cGVzXG5leHBvcnQgZnVuY3Rpb24gY29uc29saWRhdGVGaWVsZFR5cGVzKGZpZWxkcywgc2NoZW1hKSB7XG4gIHJldHVybiBmaWVsZHMubWFwKGZpZWxkID0+IHtcbiAgICBjb25zdCBjb2x1bW5OYW1lID0gZmllbGQubmFtZTtcblxuICAgIGNvbnN0IGRldGVjdGVkQ29sdW1uVHlwZSA9IHNjaGVtYVtjb2x1bW5OYW1lXTtcblxuICAgIC8vIFRPRE8gY29sdW1uVHlwZVRvRmllbGRUeXBlIHRyYW5mb3JtcyBkZXRlY3RlZCB0aW1lc3RhbXBzIHRvIHN0cmluZyxcbiAgICAvLyBjb21wbGV0ZWx5IGJyZWFraW5nIHRpbWUgZmlsdGVyIGxvZ2ljLlxuICAgIC8vIGNvbnN0IGZpZWxkVHlwZSA9IGNvbHVtblR5cGVUb0ZpZWxkVHlwZShkZXRlY3RlZENvbHVtblR5cGUpIHx8IGZpZWxkLnR5cGU7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uZmllbGQsXG4gICAgICAvLyB0eXBlOiBmaWVsZFR5cGUsXG4gICAgICBkdWNrREJDb2x1bW5UeXBlOiBkZXRlY3RlZENvbHVtblR5cGVcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdG9DU1ZSb3cocm93OiB1bmtub3duW10pOiBzdHJpbmcge1xuICByZXR1cm4gYCR7cm93XG4gICAgLm1hcChyID0+IHtcbiAgICAgIGNvbnN0IHJUb1N0ciA9IG5vdE51bGxvclVuZGVmaW5lZChyKSA/IFN0cmluZyhyKS5yZXBsYWNlKC9cIi9nLCAnXFxcXFwiJykgOiAnJztcbiAgICAgIHJldHVybiByVG9TdHIuaW5jbHVkZXMoJywnKSA/IGBcIiR7clRvU3RyfVwiYCA6IHJUb1N0cjtcbiAgICB9KVxuICAgIC5qb2luKCcsJyl9XFxuYDtcbn1cblxuLy8gVXNlIER1Y2NrREIgdG8gZGV0ZWN0IGNzdiBjb2x1bW4gc2NoZW1hXG5hc3luYyBmdW5jdGlvbiBzbmlmZkNzdlNjaGVtYShzYW1wbGU6IFJvd0RhdGEpIHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KHNhbXBsZSkgfHwgc2FtcGxlLmxlbmd0aCA8IDApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgaGVhZGVyUm93ID0gdG9DU1ZSb3coT2JqZWN0LmtleXMoc2FtcGxlWzBdKSk7XG5cbiAgY29uc3QgY3N2Q29udGVudCA9IChzYW1wbGUgYXMgKGFueVtdIHwgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW10pLnJlZHVjZShcbiAgICAoYWNjdTogc3RyaW5nLCByb3cpID0+IGAke2FjY3V9JHt0b0NTVlJvdyhPYmplY3QudmFsdWVzKHJvdykpfWAsXG4gICAgaGVhZGVyUm93XG4gICk7XG5cbiAgY29uc3QgZGIgPSBnZXRBcHBsaWNhdGlvbkNvbmZpZygpLmRhdGFiYXNlO1xuICBpZiAoIWRiKSB7XG4gICAgY29uc29sZS5lcnJvcignVGhlIGRhdGFiYXNlIGlzIG5vdCBjb25maWd1cmVkIHByb3Blcmx5LicpO1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBjID0gYXdhaXQgZGIuY29ubmVjdCgpO1xuXG4gIGNvbnN0IGZpbGVOYW1lID0gZ2VuZXJhdGVIYXNoSWQoKTtcbiAgYXdhaXQgZGIucmVnaXN0ZXJGaWxlVGV4dChgJHtmaWxlTmFtZX0tJHtnZW5lcmF0ZUhhc2hJZH0uY3N2YCwgY3N2Q29udGVudCk7XG5cbiAgLy8gaHR0cHM6Ly9kdWNrZGIub3JnL2RvY3MvZGF0YS9jc3YvYXV0b19kZXRlY3Rpb24uaHRtbFxuICBjb25zdCByZXN1bHQgPSBhd2FpdCBjLnF1ZXJ5KGBcbiAgICAgICAgRlJPTSBzbmlmZl9jc3YoJyR7ZmlsZU5hbWV9LSR7Z2VuZXJhdGVIYXNoSWR9LmNzdicsIFxuICAgICAgICBzYW1wbGVfc2l6ZSA9IDUwMCxcbiAgICAgICAgYXV0b190eXBlX2NhbmRpZGF0ZXMgPSBbJ0ZMT0FUJywgJ0lOVEVHRVInLCAnVElNRVNUQU1QJywgJ0RBVEUnLCAnVElNRScsICdWQVJDSEFSJywgJ0JPT0xFQU4nXSk7XG4gICAgYCk7XG5cbiAgY29uc3Qgc2NoZW1hUmVzdWx0ID0gcmVzdWx0LnRvQXJyYXkoKS5tYXAocm93ID0+IHJvdy50b0pTT04oKSk7XG5cbiAgY29uc3QgY29sdW1ucyA9IHNjaGVtYVJlc3VsdFswXS5Db2x1bW5zO1xuICBjb25zdCBzY2hlbWEgPSB7fTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb2x1bW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgc2NoZW1hW2NvbHVtbnMuZ2V0KGkpLm5hbWVdID0gY29sdW1ucy5nZXQoaSkudHlwZTtcbiAgfVxuXG4gIHJldHVybiBzY2hlbWE7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcm9jZXNzR2VvanNvbihyYXdEYXRhOiB1bmtub3duKTogUHJvY2Vzc29yUmVzdWx0IHtcbiAgY29uc3Qgbm9ybWFsaXplZEdlb2pzb24gPSBub3JtYWxpemUocmF3RGF0YSk7XG5cbiAgaWYgKCFub3JtYWxpemVkR2VvanNvbiB8fCAhQXJyYXkuaXNBcnJheShub3JtYWxpemVkR2VvanNvbi5mZWF0dXJlcykpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihcbiAgICAgIGBSZWFkIEZpbGUgRmFpbGVkOiBGaWxlIGlzIG5vdCBhIHZhbGlkIEdlb0pTT04uIFJlYWQgbW9yZSBhYm91dCBbc3VwcG9ydGVkIGZpbGUgZm9ybWF0XSgke0dVSURFU19GSUxFX0ZPUk1BVF9ET0N9KWBcbiAgICApO1xuICAgIHRocm93IGVycm9yO1xuICB9XG5cbiAgLy8gQHRzLWV4cGVjdC1lcnJvciBEb24ndCBwYXNzIGVtcHR5IGZpZWxkcywgYXMgZHVjayBkYiBvdXRwdXRzIGFuIGVtcHR5IGRhdGFzZXRcbiAgcmV0dXJuIHtcbiAgICByb3dzOiBub3JtYWxpemVkR2VvanNvblxuICAgIC8vIFRPRE8gZ2V0IGZpZWxkcyB0byBwcmVzZXJ2ZSBmaWVsZCBuYW1lcz9cbiAgICAvLyBmaWVsZHM6IFtdXG4gIH07XG59XG5cbi8qKlxuICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGV4dGVuZCBleGlzdGluZyBmaWVsZHMgd2l0aCBuYXRpdmUgRHVja0RCIGNvbHVtbiB0eXBlLlxuICogQHBhcmFtIGZpZWxkcyBBcnJheSBvZiBmaWVsZHMgdG8gZXh0ZW5kLlxuICogQHBhcmFtIHR5cGVPdmVycmlkZXMgQW4gb3B0aW9uYWwgbWFwcGluZyBvZiBEdWNrREIgY29sdW1uIHR5cGVzIHRvIG92ZXJyaWRlLlxuICogQHJldHVybnMgQW4gYXJyYXkgb2YgZmllbGRzIHdpdGggdGhlIER1Y2tEQiBjb2x1bW4gdHlwZSBleHRlbmRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dGVuZEZpZWxkc1dpdGhEdWNrREJDb2x1bW5UeXBlKFxuICBmaWVsZHM6IFByb3RvRGF0YXNldEZpZWxkW10sXG4gIHR5cGVPdmVycmlkZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbik6IFByb21pc2U8UHJvdG9EYXRhc2V0RmllbGRbXT4ge1xuICBjb25zdCBzY2hlbWEgPSBmaWVsZHMucmVkdWNlKChhY2MsIGZpZWxkKSA9PiB7XG4gICAgYWNjW2ZpZWxkLm5hbWVdID0gZmllbGRUeXBlVG9Db2x1bW5UeXBlKGZpZWxkLnR5cGUpO1xuICAgIHJldHVybiBhY2M7XG4gIH0sIHt9KTtcblxuICBjb25zdCB1cGRhdGVkRmllbGRzID0gY29uc29saWRhdGVGaWVsZFR5cGVzKGZpZWxkcywgc2NoZW1hKTtcbiAgdXBkYXRlZEZpZWxkcy5mb3JFYWNoKGZpZWxkID0+IHtcbiAgICBpZiAodHlwZU92ZXJyaWRlc1tmaWVsZC5kdWNrREJDb2x1bW5UeXBlXSkge1xuICAgICAgZmllbGQuZHVja0RCQ29sdW1uVHlwZSA9IHR5cGVPdmVycmlkZXNbZmllbGQuZHVja0RCQ29sdW1uVHlwZV07XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHVwZGF0ZWRGaWVsZHM7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7QUFDQTs7QUFHQSxPQUFPQSxTQUFTLE1BQU0sMkJBQTJCO0FBRWpELFNBQ0VDLHVCQUF1QixFQUN2QkMsaUJBQWlCLEVBQ2pCQyxjQUFjLEVBQ2RDLGtCQUFrQixRQUNiLHlCQUF5QjtBQUVoQyxTQUFRQyxlQUFlLEVBQUVDLHNCQUFzQixRQUFPLHNCQUFzQjtBQUM1RSxTQUFRQyxtQkFBbUIsUUFBTyx1QkFBdUI7QUFDekQsU0FBUUMsb0JBQW9CLFFBQU8sa0JBQWtCO0FBRXJELE9BQU8sSUFBTUMsU0FBUyxHQUFHLDhC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