sliftutils 1.7.122 → 1.7.124

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "1.7.122",
3
+ "version": "1.7.124",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -40,6 +40,10 @@ const ROLLOVER_BYTES = 5 * 1024 * 1024;
40
40
  const MEMORY_WATCHDOG_INTERVAL_MS = 60 * 1000;
41
41
  const STALE_DELETE_MS = 24 * 60 * 60 * 1000;
42
42
  const MAX_INDEX_RELOAD_ATTEMPTS = 3;
43
+ // A bulk file under this is "loose" - still worth rolling up into a bigger one. Half the target file size, because that is exactly where combining stops paying: merging two files that are each over half the target just splits back into two files again, so the file count (and with it the per-file key list every read holds in memory) does not drop. Under half, any two inputs fit in one output, so phase 2 always makes the count go down.
44
+ //
45
+ // NOT the target size itself. runPlannedMerge cuts a chunk BEFORE adding the key that would exceed the target, so every file it writes is under TARGET_FILE_BYTES - testing against the target would classify the entire collection as loose and re-merge all of it, forever.
46
+ const LOOSE_BULK_MAX_BYTES = TARGET_FILE_BYTES / 2;
43
47
  const KEY_GROUP_BYTES = 800 * 1024 * 1024;
44
48
  const DUP_THRESHOLD = 0.4;
45
49
  // Whole-tier dedup short-circuit (start of phase 3): when the combined tier is over this size AND the overall key duplication fraction is over this threshold, fold every combined file in one merge instead of the per-key-group walk (which spaces merges 5 min apart — 16 h for 200 groups).
@@ -363,16 +367,13 @@ export class BulkDatabaseBase<T extends { key: string }> {
363
367
  return this.streamBytesOnDisk > bulkDatabase2Timing.streamFoldTriggerBytes;
364
368
  }
365
369
 
366
- // Stream files nobody can still be appending to, split by who owned them:
367
- // retirable - a fold may delete these the moment it has consumed them, instead of waiting out streamSealAgeMs. Includes our own sealed files and merge-carry output.
368
- // ownerGone - nobody is left to fold these (a closed tab's leftovers, or a legacy name with no owner stamp), and until one is folded every reader has to decode all of it just to build the index. Worth folding at any size. Our own files are deliberately NOT in here: every merge pass seals ours, so counting them would fold on every tick; the streamFileMaxBytes rollover and the streamFoldTriggerBytes gate cover ours instead.
370
+ // Stream files nobody can still be appending to: our own sealed files, merge-carry output, and files whose owner is gone (a closed tab's leftovers, or a legacy name with no owner stamp). A fold may delete these the moment it has consumed them, instead of waiting out streamSealAgeMs.
369
371
  //
370
372
  // Foreign owners are probed over the sync channel. In Node there is no channel, so we cannot know - every foreign owner is assumed alive and the streamSealAgeMs rule stands.
371
373
  //
372
374
  // assumeSealed is for planning: a merge pass broadcasts a seal before it starts, so by the time it merges our current file IS final. The planner passes isSyncSupported() to predict that; anything deciding a real deletion passes false and goes by streamFileName as it actually stands.
373
- private async findAbandonedStreams(streamFiles: StreamFileInfo[], assumeSealed: boolean): Promise<{ retirable: Set<string>; ownerGone: Set<string> }> {
375
+ private async findAbandonedStreams(streamFiles: StreamFileInfo[], assumeSealed: boolean): Promise<Set<string>> {
374
376
  const retirable = new Set<string>();
375
- const ownerGone = new Set<string>();
376
377
  const hasForeignOwner = streamFiles.some(f => f.ownerId && f.ownerId !== writerId && f.ownerId !== MERGE_OUTPUT_OWNER);
377
378
  const live = hasForeignOwner && await queryLiveWriters(this.name, bulkDatabase2Timing.liveWriterProbeMs) || undefined;
378
379
  for (const f of streamFiles) {
@@ -382,12 +383,9 @@ export class BulkDatabaseBase<T extends { key: string }> {
382
383
  if (assumeSealed || f.fileName !== this.streamFileName) retirable.add(f.fileName);
383
384
  continue;
384
385
  }
385
- if (!f.ownerId || live && !live.has(f.ownerId)) {
386
- retirable.add(f.fileName);
387
- ownerGone.add(f.fileName);
388
- }
386
+ if (!f.ownerId || live && !live.has(f.ownerId)) retirable.add(f.fileName);
389
387
  }
390
- return { retirable, ownerGone };
388
+ return retirable;
391
389
  }
392
390
 
393
391
  private async automaticCompactionAllowed(): Promise<boolean> {
@@ -858,7 +856,7 @@ export class BulkDatabaseBase<T extends { key: string }> {
858
856
  const streamReader = ordered.length ? streamReaderFromEntries(ordered, 0).reader : undefined;
859
857
 
860
858
  // An abandoned stream that yielded no entries (zero bytes, or nothing but torn bytes) holds no data and has no writer left. Retire it here: the merge below never lists it as a used source, so the normal retirement path would skip it and it would re-trigger the abandoned-stream fold on every pass. replacedBy is empty because nothing supersedes it - the marker hides it from reads immediately and processMarkers deletes it once aged.
861
- const { retirable: retirableStreams } = await this.findAbandonedStreams(streamFiles, false);
859
+ const retirableStreams = await this.findAbandonedStreams(streamFiles, false);
862
860
  const contributingStreams = new Set(streamData.entries.map(e => e.fileName));
863
861
  const emptyAbandoned = streamFiles.filter(f => retirableStreams.has(f.fileName) && !contributingStreams.has(f.fileName)).map(f => f.fileName);
864
862
  if (emptyAbandoned.length) await writeDeleteMarker(storage, { deleteFiles: emptyAbandoned, replacedBy: [] });
@@ -966,7 +964,7 @@ export class BulkDatabaseBase<T extends { key: string }> {
966
964
  return true;
967
965
  }
968
966
 
969
- // Splits the bulk tier the way the merge writer does. A merge cuts an output file once it reaches TARGET_FILE_BYTES, so only its LAST output can be under that — meaning a sub-target file is either a single stream fold or the tail of an earlier merge, and is still waiting to be rolled up ("loose"). Anything at or over the target is done growing ("combined") and only phase 3 touches it again.
967
+ // Splits the bulk tier into files still worth rolling up ("loose", under LOOSE_BULK_MAX_BYTES - a single stream fold, or the tail end of an earlier merge) and files that are done growing ("combined", which only phase 3 touches again).
970
968
  //
971
969
  // A file whose size won't read is reported as combined: phase 2 can't consume one (its reader won't load, so the merge won't retire it), and calling it loose would re-trigger phase 2 on every pass until handleUnreadableFile finally deletes it.
972
970
  private async splitBulkTier(bulkFiles: BulkFileInfo[]): Promise<{ loose: BulkFileInfo[]; looseBytes: number; combined: BulkFileInfo[]; sizes: Map<string, number> }> {
@@ -978,7 +976,7 @@ export class BulkDatabaseBase<T extends { key: string }> {
978
976
  for (let i = 0; i < bulkFiles.length; i++) {
979
977
  const bytes = logicalSizes[i];
980
978
  sizes.set(bulkFiles[i].fileName, bytes ?? 0);
981
- if (bytes === undefined || bytes >= TARGET_FILE_BYTES) {
979
+ if (bytes === undefined || bytes >= LOOSE_BULK_MAX_BYTES) {
982
980
  combined.push(bulkFiles[i]);
983
981
  continue;
984
982
  }
@@ -1064,28 +1062,26 @@ export class BulkDatabaseBase<T extends { key: string }> {
1064
1062
  });
1065
1063
 
1066
1064
  // A pass seals before it merges, so by then our own current file is final too - predict that rather than reporting it as still-open.
1067
- const { retirable, ownerGone } = await this.findAbandonedStreams(streamFiles, isSyncSupported());
1065
+ const retirable = await this.findAbandonedStreams(streamFiles, isSyncSupported());
1068
1066
  // Only fold what we can also retire. Folding a stream a live foreign owner may still append to would copy it into bulk without removing it, so the bytes would stay in memory and just get re-folded next pass; that owner rolls its own file over at streamFileMaxBytes instead.
1069
1067
  // Aged past streamSealAgeMs counts as retirable too (canDeleteStream's own first rule): no writer appends past the seal age, and this is the only thing that frees the tier in Node, where liveness cannot be probed at all.
1070
1068
  const foldable = streamFiles.filter(f => f.ownerId !== MERGE_OUTPUT_OWNER
1071
1069
  && (retirable.has(f.fileName) || time - f.timestamp >= bulkDatabase2Timing.streamSealAgeMs));
1072
1070
  // Merge-carry files hold nothing but tombstones and are never a REASON to fold - folding one alone would just rewrite it into another carry file, forever. They ride along whenever something else folds, which collapses however many have piled up into one.
1073
1071
  const carry = streamFiles.filter(f => f.ownerId === MERGE_OUTPUT_OWNER);
1074
- // A stream whose writer is gone will never grow and nothing else will ever fold it, so fold it at any size - even one row. Zero-byte ones don't count: they hold no data to fold, and mergeFileSetInner retires them directly.
1075
- const abandoned = foldable.filter(f => ownerGone.has(f.fileName) && streamSizes.get(f.fileName));
1072
+ // Size is the only reason to fold. An abandoned stream is NOT one on its own: it is already retirable, so it is counted here and gets swept up the moment the tier is worth folding, and until then it is bounded by this very threshold. Triggering on one would fold on essentially every pass - a browser leaves a file behind whose writer never answers the liveness probe on every reload - which mints a small bulk file each time and pushes the fragmentation into phase 2.
1076
1073
  const foldTriggers = [
1077
1074
  makeTrigger({ name: "foldableBytes", value: streamBytes(foldable), threshold: bulkDatabase2Timing.streamFoldTriggerBytes, unit: "bytes" }),
1078
- makeTrigger({ name: "abandonedFiles", value: abandoned.length, threshold: 1, unit: "count" }),
1079
1075
  ];
1080
1076
  steps.push({
1081
- phase: 1, kind: "streamFold", requires: "any", triggers: foldTriggers,
1077
+ phase: 1, kind: "streamFold", requires: "all", triggers: foldTriggers,
1082
1078
  // Skipped when the hard limit already folds everything this would have.
1083
- ready: !hardLimit.met && foldTriggers.some(t => t.met),
1079
+ ready: !hardLimit.met && foldTriggers.every(t => t.met),
1084
1080
  bulkFiles: [], streamFiles: [...foldable, ...carry], bytes: streamBytes([...foldable, ...carry]),
1085
1081
  });
1086
1082
 
1087
1083
  // ── Phase 2: loose bulk -> combined bulk ─────────────────────────────────────────────────────
1088
- // Phase 1 emits one small bulk file per fold. Each is cheap to read (index only) but holds its whole key list in memory and joins into every read, so they have to be rolled up. Merging just the loose ones also dedupes them for free - a rewrite-heavy workload collapses a gigabyte of near-identical folds into almost nothing - and it always terminates, because a merge cuts every output but the last at TARGET_FILE_BYTES, so one pass can leave at most one loose file behind.
1084
+ // Phase 1 emits one small bulk file per fold. Each is cheap to read (index only) but holds its whole key list in memory and joins into every read, so they have to be rolled up. Merging just the loose ones also dedupes them for free - a rewrite-heavy workload collapses a gigabyte of near-identical folds into almost nothing - and it always terminates: a chunk is only cut once the next key would take it past TARGET_FILE_BYTES, so every output but the last is over half the target and lands in the combined tier, leaving at most one loose file behind.
1089
1085
  const { loose, looseBytes, combined, sizes } = await this.splitBulkTier(bulkFiles);
1090
1086
  const looseTriggers = [
1091
1087
  makeTrigger({ name: "looseBytes", value: looseBytes, threshold: bulkDatabase2Timing.looseBulkTriggerBytes, unit: "bytes" }),
@@ -1,17 +1,5 @@
1
- import { delay } from "socket-function/src/batching";
2
1
  import { IStorageRaw } from "./IStorage";
3
2
 
4
- const WRITE_CONFLICT_RETRIES = 5;
5
- const WRITE_CONFLICT_DELAY = 100;
6
-
7
- // Serializes writes to the same file within this process, so two overlapping set calls can never hold a writable on the same file at once. Keyed by full path, as separate instances are commonly created for the same root.
8
- let writeChains = new Map<string, Promise<unknown>>();
9
-
10
- // OPFS rejects a write when the file changed between resolving the handle and finishing the write (another tab, or an overlapping write we don't control). We always write the file in full, so re-resolving the handle and writing again is correct.
11
- function isStaleHandleError(error: unknown): boolean {
12
- return String((error as Error)?.stack || error).includes("InvalidStateError");
13
- }
14
-
15
3
  export class PrivateFileSystemStorage implements IStorageRaw {
16
4
  private rootHandle: FileSystemDirectoryHandle | undefined;
17
5
 
@@ -145,37 +133,12 @@ export class PrivateFileSystemStorage implements IStorageRaw {
145
133
  }
146
134
 
147
135
  public async set(key: string, value: Buffer): Promise<void> {
148
- const write = async () => {
149
- for (let attempt = 1; attempt <= WRITE_CONFLICT_RETRIES; attempt++) {
150
- try {
151
- await this.ensureInitialized();
152
- const { dir, name } = await this.resolveKey(key, true);
153
- const fileHandle = await dir.getFileHandle(name, { create: true });
154
- const writable = await fileHandle.createWritable();
155
- await writable.write(value);
156
- await writable.close();
157
- return;
158
- } catch (error) {
159
- if (!isStaleHandleError(error) || attempt === WRITE_CONFLICT_RETRIES) {
160
- throw error;
161
- }
162
- console.warn(`Write of ${this.path}/${key} conflicted with another writer, retrying (attempt ${attempt} of ${WRITE_CONFLICT_RETRIES}):`, String((error as Error)?.stack || error));
163
- await delay(WRITE_CONFLICT_DELAY);
164
- }
165
- }
166
- };
167
-
168
- const chainKey = `${this.path}/${key}`;
169
- const previous = writeChains.get(chainKey) || Promise.resolve();
170
- const current = previous.catch(() => { }).then(write);
171
- writeChains.set(chainKey, current);
172
- try {
173
- await current;
174
- } finally {
175
- if (writeChains.get(chainKey) === current) {
176
- writeChains.delete(chainKey);
177
- }
178
- }
136
+ await this.ensureInitialized();
137
+ const { dir, name } = await this.resolveKey(key, true);
138
+ const fileHandle = await dir.getFileHandle(name, { create: true });
139
+ const writable = await fileHandle.createWritable();
140
+ await writable.write(value);
141
+ await writable.close();
179
142
  }
180
143
 
181
144
  public async append(key: string, value: Buffer): Promise<void> {
@@ -1,15 +1,6 @@
1
1
  "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
3
  //exports.PrivateFileSystemStorage = void 0;
4
- const batching_1 = require("socket-function/src/batching");
5
- const WRITE_CONFLICT_RETRIES = 5;
6
- const WRITE_CONFLICT_DELAY = 100;
7
- // Serializes writes to the same file within this process, so two overlapping set calls can never hold a writable on the same file at once. Keyed by full path, as separate instances are commonly created for the same root.
8
- let writeChains = new Map();
9
- // OPFS rejects a write when the file changed between resolving the handle and finishing the write (another tab, or an overlapping write we don't control). We always write the file in full, so re-resolving the handle and writing again is correct.
10
- function isStaleHandleError(error) {
11
- return String((error === null || error === void 0 ? void 0 : error.stack) || error).includes("InvalidStateError");
12
- }
13
4
  class PrivateFileSystemStorage {
14
5
  constructor(path) {
15
6
  this.path = path;
@@ -129,38 +120,12 @@ class PrivateFileSystemStorage {
129
120
  return Buffer.from(arrayBuffer);
130
121
  }
131
122
  async set(key, value) {
132
- const write = async () => {
133
- for (let attempt = 1; attempt <= WRITE_CONFLICT_RETRIES; attempt++) {
134
- try {
135
- await this.ensureInitialized();
136
- const { dir, name } = await this.resolveKey(key, true);
137
- const fileHandle = await dir.getFileHandle(name, { create: true });
138
- const writable = await fileHandle.createWritable();
139
- await writable.write(value);
140
- await writable.close();
141
- return;
142
- }
143
- catch (error) {
144
- if (!isStaleHandleError(error) || attempt === WRITE_CONFLICT_RETRIES) {
145
- throw error;
146
- }
147
- console.warn(`Write of ${this.path}/${key} conflicted with another writer, retrying (attempt ${attempt} of ${WRITE_CONFLICT_RETRIES}):`, String((error === null || error === void 0 ? void 0 : error.stack) || error));
148
- await (0, batching_1.delay)(WRITE_CONFLICT_DELAY);
149
- }
150
- }
151
- };
152
- const chainKey = `${this.path}/${key}`;
153
- const previous = writeChains.get(chainKey) || Promise.resolve();
154
- const current = previous.catch(() => { }).then(write);
155
- writeChains.set(chainKey, current);
156
- try {
157
- await current;
158
- }
159
- finally {
160
- if (writeChains.get(chainKey) === current) {
161
- writeChains.delete(chainKey);
162
- }
163
- }
123
+ await this.ensureInitialized();
124
+ const { dir, name } = await this.resolveKey(key, true);
125
+ const fileHandle = await dir.getFileHandle(name, { create: true });
126
+ const writable = await fileHandle.createWritable();
127
+ await writable.write(value);
128
+ await writable.close();
164
129
  }
165
130
  async append(key, value) {
166
131
  const existingContent = await this.get(key);
@@ -218,5 +183,5 @@ class PrivateFileSystemStorage {
218
183
  }
219
184
  }
220
185
  exports.PrivateFileSystemStorage = PrivateFileSystemStorage;
221
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJpdmF0ZUZpbGVTeXN0ZW1TdG9yYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiUHJpdmF0ZUZpbGVTeXN0ZW1TdG9yYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJEQUFxRDtBQUdyRCxNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyw2TkFBNk47QUFDN04sSUFBSSxXQUFXLEdBQUcsSUFBSSxHQUFHLEVBQTRCLENBQUM7QUFFdEQsc1BBQXNQO0FBQ3RQLFNBQVMsa0JBQWtCLENBQUMsS0FBYztJQUN0QyxPQUFPLE1BQU0sQ0FBQyxDQUFDLEtBQWUsYUFBZixLQUFLLHVCQUFMLEtBQUssQ0FBWSxLQUFLLEtBQUksS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDbEYsQ0FBQztBQUVELE1BQWEsd0JBQXdCO0lBR2pDLFlBQW9CLElBQVk7UUFBWixTQUFJLEdBQUosSUFBSSxDQUFRO0lBQUksQ0FBQztJQUU3QixLQUFLLENBQUMsaUJBQWlCOztRQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxDQUFBLE1BQUEsU0FBUyxDQUFDLE9BQU8sMENBQUUsWUFBWSxDQUFBLEVBQUUsQ0FBQztnQkFDbkMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO1lBQ3BGLENBQUM7WUFDRCxJQUFJLFFBQVEsQ0FBQyxRQUFRLEtBQUssT0FBTyxFQUFFLENBQUM7Z0JBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQUMsOEtBQThLLENBQUMsQ0FBQztZQUNwTSxDQUFDO1lBQ0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLFNBQVMsQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDN0QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUMzQixDQUFD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QztZQUNMLENBQUM7UUFDTCxDQUFDLENBQUM7UUFDRixNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDMUIsT0FBTyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUNNLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBVztRQUk1QixJQUFJLFVBQVUsR0FBRyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3RELElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNkLE9BQU8sU0FBUyxDQUFDO1FBQ3JCLENBQUM7UUFDRCxJQUFJLElBQUksR0FBRyxNQUFNLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN0QyxPQUFPO1lBQ0gsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO1lBQ2YsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO1NBQ2xDLENBQUM7SUFDTixDQUFDO0lBQ00sS0FBSyxDQUFDLEtBQUs7UUFDZCxNQUFNLElBQUksS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDdkMsQ0FBQztDQUNKO0FBak9ELDREQWlPQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRlbGF5IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvYmF0Y2hpbmdcIjtcbmltcG9ydCB7IElTdG9yYWdlUmF3IH0gZnJvbSBcIi4vSVN0b3JhZ2VcIjtcblxuY29uc3QgV1JJVEVfQ09ORkxJQ1RfUkVUUklFUyA9IDU7XG5jb25zdCBXUklURV9DT05GTElDVF9ERUxBWSA9IDEwMDtcblxuLy8gU2VyaWFsaXplcyB3cml0ZXMgdG8gdGhlIHNhbWUgZmlsZSB3aXRoaW4gdGhpcyBwcm9jZXNzLCBzbyB0d28gb3ZlcmxhcHBpbmcgc2V0IGNhbGxzIGNhbiBuZXZlciBob2xkIGEgd3JpdGFibGUgb24gdGhlIHNhbWUgZmlsZSBhdCBvbmNlLiBLZXllZCBieSBmdWxsIHBhdGgsIGFzIHNlcGFyYXRlIGluc3RhbmNlcyBhcmUgY29tbW9ubHkgY3JlYXRlZCBmb3IgdGhlIHNhbWUgcm9vdC5cbmxldCB3cml0ZUNoYWlucyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPHVua25vd24+PigpO1xuXG4vLyBPUEZTIHJlamVjdHMgYSB3cml0ZSB3aGVuIHRoZSBmaWxlIGNoYW5nZWQgYmV0d2VlbiByZXNvbHZpbmcgdGhlIGhhbmRsZSBhbmQgZmluaXNoaW5nIHRoZSB3cml0ZSAoYW5vdGhlciB0YWIsIG9yIGFuIG92ZXJsYXBwaW5nIHdyaXRlIHdlIGRvbid0IGNvbnRyb2wpLiBXZSBhbHdheXMgd3JpdGUgdGhlIGZpbGUgaW4gZnVsbCwgc28gcmUtcmVzb2x2aW5nIHRoZSBoYW5kbGUgYW5kIHdyaXRpbmcgYWdhaW4gaXMgY29ycmVjdC5cbmZ1bmN0aW9uIGlzU3RhbGVIYW5kbGVFcnJvcihlcnJvcjogdW5rbm93bik6IGJvb2xlYW4ge1xuICAgIHJldHVybiBTdHJpbmcoKGVycm9yIGFzIEVycm9yKT8uc3RhY2sgfHwgZXJyb3IpLmluY2x1ZGVzKFwiSW52YWxpZFN0YXRlRXJyb3JcIik7XG59XG5cbmV4cG9ydCBjbGFzcyBQcml2YXRlRmlsZVN5c3RlbVN0b3JhZ2UgaW1wbGVtZW50cyBJU3RvcmFnZVJhdyB7XG4gICAgcHJpdmF0ZSByb290SGFuZGxlOiBGaWxlU3lzdGVtRGlyZWN0b3J5SGFuZGxlIHwgdW5kZWZpbmVkO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBwYXRoOiBzdHJpbmcpIHsgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBlbnN1cmVJbml0aWFsaXplZCgpOiBQcm9taXNlPEZpbGVTeXN0ZW1EaXJlY3RvcnlIYW5kbGU+IHtcbiAgICAgICAgaWYgKCF0aGlzLnJvb3RIYW5kbGUpIHtcbiAgICAgICAgICAgIGlmICghbmF2aWdhdG9yLnN0b3JhZ2U/LmdldERpcmVjdG9yeSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlByaXZhdGUgRmlsZSBTeXN0ZW0gQWNjZXNzIEFQSSBub3Qgc3VwcG9ydGVkIGluIHRoaXMgYnJvd3NlclwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChsb2NhdGlvbi5wcm90b2NvbCA9PT0gXCJmaWxlOlwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQcml2YXRlIEZpbGUgU3lzdGVtIEFQSSBpcyBkaXNhbGxvd2VkIGluIGZpbGU6Ly8gdHlwZSBsb2NhdGlvbnMuIEVpdGhlciB1c2UgdGhlIEZpbGUgU3lzdGVtIEFQSSAodGhlIHVzZSBnaXZlcyB5b3UgYWNjZXNzIHRvIHRoZWlyIGZpbGUgc3lzdGVtKSwgb3IgaG9zdCBvbiBhbiBhY3R1YWwgZG9tYWluYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJvb3RIYW5kbGUgPSBhd2FpdCBuYXZpZ2F0b3Iuc3RvcmFnZS5nZXREaXJlY3RvcnkoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yb290SGFuZGxlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZGlyZWN0b3J5RXhpc3RzKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBjb25zdCByb290ID0gYXdhaXQgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMucGF0aCB8fCB0aGlzLnBhdGggPT09IFwiXCIgfHwgdGhpcy5wYXRoID09PSBcIi9cIikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOyAvLyBSb290IGFsd2F5cyBleGlzdHNcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcGF0aFBhcnRzID0gdGhpcy5wYXRoLnNwbGl0KFwiL1wiKS5maWx0ZXIocGFydCA9PiBwYXJ0Lmxlbmd0aCA+IDApO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRIYW5kbGUgPSByb290O1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHBhcnQgb2YgcGF0aFBhcnRzKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEhhbmRsZSA9IGF3YWl0IGN1cnJlbnRIYW5kbGUuZ2V0RGlyZWN0b3J5SGFuZGxlKHBhcnQpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBnZXREaXJlY3RvcnlIYW5kbGUoY3JlYXRlUGF0aDogYm9vbGVhbiA9IHRydWUpOiBQcm9taXNlPEZpbGVTeXN0ZW1EaXJlY3RvcnlIYW5kbGU+IHtcbiAgICAgICAgY29uc3Qgcm9vdCA9IGF3YWl0IHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcblxuICAgICAgICBpZiAoIXRoaXMucGF0aCB8fCB0aGlzLnBhdGggPT09IFwiXCIgfHwgdGhpcy5wYXRoID09PSBcIi9cIikge1xuICAgICAgICAgICAgcmV0dXJuIHJvb3Q7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXRoUGFydHMgPSB0aGlzLnBhdGguc3BsaXQoXCIvXCIpLmZpbHRlcihwYXJ0ID0+IHBhcnQubGVuZ3RoID4gMCk7XG4gICAgICAgIGxldCBjdXJyZW50SGFuZGxlID0gcm9vdDtcblxuICAgICAgICBmb3IgKGNvbnN0IHBhcnQgb2YgcGF0aFBhcnRzKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRIYW5kbGUgPSBhd2FpdCBjdXJyZW50SGFuZGxlLmdldERpcmVjdG9yeUhhbmRsZShwYXJ0LCB7IGNyZWF0ZTogY3JlYXRlUGF0aCB9KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFjcmVhdGVQYXRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRGlyZWN0b3J5IG5vdCBmb3VuZDogJHt0aGlzLnBhdGh9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGN1cnJlbnRIYW5kbGU7XG4gICAgfVxuXG4gICAgLy8gS2V5cyBtYXkgY29udGFpbiBcIi9cIiAobmVzdGVkIHBhdGhzKS4gT1BGUyBoYW5kbGVzIHJlamVjdCBzZXBhcmF0b3JzIGluIG5hbWVzLCBzbyB3ZVxuICAgIC8vIHdhbGsvY3JlYXRlIHRoZSBpbnRlcm1lZGlhdGUgZGlyZWN0b3JpZXMgYW5kIHJldHVybiB0aGUgbGVhZiBkaXJlY3RvcnkgKyBmaWxlIG5hbWUuXG4gICAgcHJpdmF0ZSBhc3luYyByZXNvbHZlS2V5KGtleTogc3RyaW5nLCBjcmVhdGU6IGJvb2xlYW4pOiBQcm9taXNlPHsgZGlyOiBGaWxlU3lzdGVtRGlyZWN0b3J5SGFuZGxlOyBuYW1lOiBzdHJpbmcgfT4ge1xuICAgICAgICBsZXQgZGlyID0gYXdhaXQgdGhpcy5nZXREaXJlY3RvcnlIYW5kbGUoY3JlYXRlKTtcbiAgICAgICAgY29uc3QgcGFydHMgPSBrZXkuc3BsaXQoXCIvXCIpLmZpbHRlcihwYXJ0ID0+IHBhcnQubGVuZ3RoID4gMCk7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBwYXJ0cy5wb3AoKTtcbiAgICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZW1wdHkga2V5OiAke0pTT04uc3RyaW5naWZ5KGtleSl9YCk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgICAgICAgICBkaXIgPSBhd2FpdCBkaXIuZ2V0RGlyZWN0b3J5SGFuZGxlKHBhcnQsIHsgY3JlYXRlIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IGRpciwgbmFtZSB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZ2V0RmlsZUhhbmRsZShrZXk6IHN0cmluZywgY3JlYXRlOiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPEZpbGVTeXN0ZW1GaWxlSGFuZGxlIHwgdW5kZWZpbmVkPiB7XG4gICAgICAgIGF3YWl0IHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcbiAgICAgICAgaWYgKGNyZWF0ZSkge1xuICAgICAgICAgICAgY29uc3QgeyBkaXIsIG5hbWUgfSA9IGF3YWl0IHRoaXMucmVzb2x2ZUtleShrZXksIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGRpci5nZXRGaWxlSGFuZGxlKG5hbWUsIHsgY3JlYXRlOiB0cnVlIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB7IGRpciwgbmFtZSB9ID0gYXdhaXQgdGhpcy5yZXNvbHZlS2V5KGtleSwgZmFsc2UpO1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGRpci5nZXRGaWxlSGFuZGxlKG5hbWUpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZmlsZUV4aXN0cyhrZXk6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gISEoYXdhaXQgdGhpcy5nZXRGaWxlSGFuZGxlKGtleSwgZmFsc2UpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgZmlsZSBleGlzdHMgZmlyc3QgdG8gYXZvaWQgdW5uZWNlc3NhcnkgZXJyb3JzXG4gICAgICAgIGlmICghKGF3YWl0IHRoaXMuZmlsZUV4aXN0cyhrZXkpKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlSGFuZGxlID0gYXdhaXQgdGhpcy5nZXRGaWxlSGFuZGxlKGtleSwgZmFsc2UpO1xuICAgICAgICAgICAgaWYgKCFmaWxlSGFuZGxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgZmlsZSA9IGF3YWl0IGZpbGVIYW5kbGUuZ2V0RmlsZSgpO1xuICAgICAgICAgICAgY29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCBmaWxlLmFycmF5QnVmZmVyKCk7XG4gICAgICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oYXJyYXlCdWZmZXIpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBFcnJvciByZWFkaW5nIGZpbGUgJHtrZXl9OmAsIGVycm9yKTtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0UmFuZ2Uoa2V5OiBzdHJpbmcsIGNvbmZpZzogeyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlciB9KTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgY29uc3QgZmlsZUhhbmRsZSA9IGF3YWl0IHRoaXMuZ2V0RmlsZUhhbmRsZShrZXksIGZhbHNlKTtcbiAgICAgICAgaWYgKCFmaWxlSGFuZGxlKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmlsZSA9IGF3YWl0IGZpbGVIYW5kbGUuZ2V0RmlsZSgpO1xuICAgICAgICBjb25zdCBhcnJheUJ1ZmZlciA9IGF3YWl0IGZpbGUuc2xpY2UoY29uZmlnLnN0YXJ0LCBjb25maWcuZW5kKS5hcnJheUJ1ZmZlcigpO1xuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oYXJyYXlCdWZmZXIpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBCdWZmZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3Qgd3JpdGUgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSBXUklURV9DT05GTElDVF9SRVRSSUVTOyBhdHRlbXB0KyspIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgZGlyLCBuYW1lIH0gPSBhd2FpdCB0aGlzLnJlc29sdmVLZXkoa2V5LCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsZUhhbmRsZSA9IGF3YWl0IGRpci5nZXRGaWxlSGFuZGxlKG5hbWUsIHsgY3JlYXRlOiB0cnVlIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB3cml0YWJsZSA9IGF3YWl0IGZpbGVIYW5kbGUuY3JlYXRlV3JpdGFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgd3JpdGFibGUud3JpdGUodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB3cml0YWJsZS5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1N0YWxlSGFuZGxlRXJyb3IoZXJyb3IpIHx8IGF0dGVtcHQgPT09IFdSSVRFX0NPTkZMSUNUX1JFVFJJRVMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgV3JpdGUgb2YgJHt0aGlzLnBhdGh9LyR7a2V5fSBjb25mbGljdGVkIHdpdGggYW5vdGhlciB3cml0ZXIsIHJldHJ5aW5nIChhdHRlbXB0ICR7YXR0ZW1wdH0gb2YgJHtXUklURV9DT05GTElDVF9SRVRSSUVTfSk6YCwgU3RyaW5nKChlcnJvciBhcyBFcnJvcik/LnN0YWNrIHx8IGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGRlbGF5KFdSSVRFX0NPTkZMSUNUX0RFTEFZKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgY2hhaW5LZXkgPSBgJHt0aGlzLnBhdGh9LyR7a2V5fWA7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzID0gd3JpdGVDaGFpbnMuZ2V0KGNoYWluS2V5KSB8fCBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgY29uc3QgY3VycmVudCA9IHByZXZpb3VzLmNhdGNoKCgpID0+IHsgfSkudGhlbih3cml0ZSk7XG4gICAgICAgIHdyaXRlQ2hhaW5zLnNldChjaGFpbktleSwgY3VycmVudCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBjdXJyZW50O1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgaWYgKHdyaXRlQ2hhaW5zLmdldChjaGFpbktleSkgPT09IGN1cnJlbnQpIHtcbiAgICAgICAgICAgICAgICB3cml0ZUNoYWlucy5kZWxldGUoY2hhaW5LZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGFwcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBleGlzdGluZ0NvbnRlbnQgPSBhd2FpdCB0aGlzLmdldChrZXkpO1xuICAgICAgICBsZXQgbmV3Q29udGVudDogQnVmZmVyO1xuICAgICAgICBpZiAoZXhpc3RpbmdDb250ZW50KSB7XG4gICAgICAgICAgICBuZXdDb250ZW50ID0gQnVmZmVyLmNvbmNhdChbZXhpc3RpbmdDb250ZW50LCB2YWx1ZV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3Q29udGVudCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMuc2V0KGtleSwgbmV3Q29udGVudCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlbW92ZShrZXk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICAvLyBDaGVjayBpZiBmaWxlIGV4aXN0cyBmaXJzdCB0byBhdm9pZCB1bm5lY2Vzc2FyeSBlcnJvcnNcbiAgICAgICAgaWYgKCEoYXdhaXQgdGhpcy5maWxlRXhpc3RzKGtleSkpKSB7XG4gICAgICAgICAgICByZXR1cm47IC8vIEZpbGUgZG9lc24ndCBleGlzdCwgbm90aGluZyB0byByZW1vdmVcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgZGlyLCBuYW1lIH0gPSBhd2FpdCB0aGlzLnJlc29sdmVLZXkoa2V5LCBmYWxzZSk7XG4gICAgICAgIGF3YWl0IGRpci5yZW1vdmVFbnRyeShuYW1lKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0S2V5cygpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICAgIC8vIENoZWNrIGlmIGRpcmVjdG9yeSBleGlzdHMgZmlyc3QgdG8gYXZvaWQgdW5uZWNlc3NhcnkgZXJyb3JzXG4gICAgICAgIGlmICghKGF3YWl0IHRoaXMuZGlyZWN0b3J5RXhpc3RzKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkaXJIYW5kbGUgPSBhd2FpdCB0aGlzLmdldERpcmVjdG9yeUhhbmRsZShmYWxzZSk7XG4gICAgICAgIGNvbnN0IGtleXM6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGNvbnN0IHdhbGsgPSBhc3luYyAoZGlyOiBGaWxlU3lzdGVtRGlyZWN0b3J5SGFuZGxlLCBwcmVmaXg6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgLy8gVXNlIHRoZSBhc3luYyBpdGVyYXRvciBwcm90b2NvbCBmb3IgRmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZVxuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBbbmFtZSwgaGFuZGxlXSBvZiAoZGlyIGFzIGFueSkuZW50cmllcygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZS5raW5kID09PSBcImZpbGVcIikge1xuICAgICAgICAgICAgICAgICAgICBrZXlzLnB1c2gocHJlZml4ICsgbmFtZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChoYW5kbGUua2luZCA9PT0gXCJkaXJlY3RvcnlcIikge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB3YWxrKGhhbmRsZSwgcHJlZml4ICsgbmFtZSArIFwiL1wiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IHdhbGsoZGlySGFuZGxlLCBcIlwiKTtcbiAgICAgICAgcmV0dXJuIGtleXMuc29ydCgpO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZ2V0SW5mbyhrZXk6IHN0cmluZyk6IFByb21pc2U8dW5kZWZpbmVkIHwge1xuICAgICAgICBzaXplOiBudW1iZXI7XG4gICAgICAgIGxhc3RNb2RpZmllZDogbnVtYmVyO1xuICAgIH0+IHtcbiAgICAgICAgbGV0IGZpbGVIYW5kbGUgPSBhd2FpdCB0aGlzLmdldEZpbGVIYW5kbGUoa2V5LCBmYWxzZSk7XG4gICAgICAgIGlmICghZmlsZUhhbmRsZSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZmlsZSA9IGF3YWl0IGZpbGVIYW5kbGUuZ2V0RmlsZSgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc2l6ZTogZmlsZS5zaXplLFxuICAgICAgICAgICAgbGFzdE1vZGlmaWVkOiBmaWxlLmxhc3RNb2RpZmllZCxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIHJlc2V0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgaW1wbGVtZW50ZWRcIik7XG4gICAgfVxufSJdfQ==
222
- /* _JS_SOURCE_HASH = "d48d77b8abb9d34713bc4fea1980d744ec120d119496a16a6c55cbc3af0f65fb"; */
186
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJpdmF0ZUZpbGVTeXN0ZW1TdG9yYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiUHJpdmF0ZUZpbGVTeXN0ZW1TdG9yYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLE1BQWEsd0JBQXdCO0lBR2pDLFlBQW9CLElBQVk7UUFBWixTQUFJLEdBQUosSUFBSSxDQUFRO0lBQUksQ0FBQztJQUU3QixLQUFLLENBQUMsaUJBQWlCOztRQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxDQUFBLE1BQUEsU0FBUyxDQUFDLE9BQU8sMENBQUUsWUFBWSxDQUFBLEVBQUUsQ0FBQztnQkFDbkMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO1lBQ3BGLENBQUM7WUFDRCxJQUFJLFFBQVEsQ0FBQyxRQUFRLEtBQUssT0FBTyxFQUFFLENBQUM7Z0JBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQUMsOEtBQThLLENBQUMsQ0FBQztZQUNwTSxDQUFDO1lBQ0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLFNBQVMsQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDN0QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUMzQixDQUFDO0lBRU8sS0FBSyxDQUFDLGVBQWU7UUFDekIsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUM1QyxJQUFJLENBQUM7WUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLEVBQUUsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO2dCQUN0RCxPQUFPLElBQUksQ0FBQyxDQUFDLHFCQUFxQjtZQUN0QyxDQUFDO1lBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFD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QUFZO1NBQ2xDLENBQUM7SUFDTixDQUFDO0lBQ00sS0FBSyxDQUFDLEtBQUs7UUFDZCxNQUFNLElBQUksS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDdkMsQ0FBQztDQUNKO0FBeE1ELDREQXdNQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElTdG9yYWdlUmF3IH0gZnJvbSBcIi4vSVN0b3JhZ2VcIjtcblxuZXhwb3J0IGNsYXNzIFByaXZhdGVGaWxlU3lzdGVtU3RvcmFnZSBpbXBsZW1lbnRzIElTdG9yYWdlUmF3IHtcbiAgICBwcml2YXRlIHJvb3RIYW5kbGU6IEZpbGVTeXN0ZW1EaXJlY3RvcnlIYW5kbGUgfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHBhdGg6IHN0cmluZykgeyB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGVuc3VyZUluaXRpYWxpemVkKCk6IFByb21pc2U8RmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZT4ge1xuICAgICAgICBpZiAoIXRoaXMucm9vdEhhbmRsZSkge1xuICAgICAgICAgICAgaWYgKCFuYXZpZ2F0b3Iuc3RvcmFnZT8uZ2V0RGlyZWN0b3J5KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUHJpdmF0ZSBGaWxlIFN5c3RlbSBBY2Nlc3MgQVBJIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBicm93c2VyXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxvY2F0aW9uLnByb3RvY29sID09PSBcImZpbGU6XCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFByaXZhdGUgRmlsZSBTeXN0ZW0gQVBJIGlzIGRpc2FsbG93ZWQgaW4gZmlsZTovLyB0eXBlIGxvY2F0aW9ucy4gRWl0aGVyIHVzZSB0aGUgRmlsZSBTeXN0ZW0gQVBJICh0aGUgdXNlIGdpdmVzIHlvdSBhY2Nlc3MgdG8gdGhlaXIgZmlsZSBzeXN0ZW0pLCBvciBob3N0IG9uIGFuIGFjdHVhbCBkb21haW5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucm9vdEhhbmRsZSA9IGF3YWl0IG5hdmlnYXRvci5zdG9yYWdlLmdldERpcmVjdG9yeSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJvb3RIYW5kbGU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBkaXJlY3RvcnlFeGlzdHMoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIGNvbnN0IHJvb3QgPSBhd2FpdCB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gICAgICAgIHRyeSB7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5wYXRoIHx8IHRoaXMucGF0aCA9PT0gXCJcIiB8fCB0aGlzLnBhdGggPT09IFwiL1wiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7IC8vIFJvb3QgYWx3YXlzIGV4aXN0c1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBwYXRoUGFydHMgPSB0aGlzLnBhdGguc3BsaXQoXCIvXCIpLmZpbHRlcihwYXJ0ID0+IHBhcnQubGVuZ3RoID4gMCk7XG4gICAgICAgICAgICBsZXQgY3VycmVudEhhbmRsZSA9IHJvb3Q7XG5cbiAgICAgICAgICAgIGZvciAoY29uc3QgcGFydCBvZiBwYXRoUGFydHMpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SGFuZGxlID0gYXdhaXQgY3VycmVudEhhbmRsZS5nZXREaXJlY3RvcnlIYW5kbGUocGFydCk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGdldERpcmVjdG9yeUhhbmRsZShjcmVhdGVQYXRoOiBib29sZWFuID0gdHJ1ZSk6IFByb21pc2U8RmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZT4ge1xuICAgICAgICBjb25zdCByb290ID0gYXdhaXQgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuXG4gICAgICAgIGlmICghdGhpcy5wYXRoIHx8IHRoaXMucGF0aCA9PT0gXCJcIiB8fCB0aGlzLnBhdGggPT09IFwiL1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gcm9vdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhdGhQYXJ0cyA9IHRoaXMucGF0aC5zcGxpdChcIi9cIikuZmlsdGVyKHBhcnQgPT4gcGFydC5sZW5ndGggPiAwKTtcbiAgICAgICAgbGV0IGN1cnJlbnRIYW5kbGUgPSByb290O1xuXG4gICAgICAgIGZvciAoY29uc3QgcGFydCBvZiBwYXRoUGFydHMpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEhhbmRsZSA9IGF3YWl0IGN1cnJlbnRIYW5kbGUuZ2V0RGlyZWN0b3J5SGFuZGxlKHBhcnQsIHsgY3JlYXRlOiBjcmVhdGVQYXRoIH0pO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWNyZWF0ZVBhdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBEaXJlY3Rvcnkgbm90IGZvdW5kOiAke3RoaXMucGF0aH1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY3VycmVudEhhbmRsZTtcbiAgICB9XG5cbiAgICAvLyBLZXlzIG1heSBjb250YWluIFwiL1wiIChuZXN0ZWQgcGF0aHMpLiBPUEZTIGhhbmRsZXMgcmVqZWN0IHNlcGFyYXRvcnMgaW4gbmFtZXMsIHNvIHdlXG4gICAgLy8gd2Fsay9jcmVhdGUgdGhlIGludGVybWVkaWF0ZSBkaXJlY3RvcmllcyBhbmQgcmV0dXJuIHRoZSBsZWFmIGRpcmVjdG9yeSArIGZpbGUgbmFtZS5cbiAgICBwcml2YXRlIGFzeW5jIHJlc29sdmVLZXkoa2V5OiBzdHJpbmcsIGNyZWF0ZTogYm9vbGVhbik6IFByb21pc2U8eyBkaXI6IEZpbGVTeXN0ZW1EaXJlY3RvcnlIYW5kbGU7IG5hbWU6IHN0cmluZyB9PiB7XG4gICAgICAgIGxldCBkaXIgPSBhd2FpdCB0aGlzLmdldERpcmVjdG9yeUhhbmRsZShjcmVhdGUpO1xuICAgICAgICBjb25zdCBwYXJ0cyA9IGtleS5zcGxpdChcIi9cIikuZmlsdGVyKHBhcnQgPT4gcGFydC5sZW5ndGggPiAwKTtcbiAgICAgICAgY29uc3QgbmFtZSA9IHBhcnRzLnBvcCgpO1xuICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBlbXB0eSBrZXk6ICR7SlNPTi5zdHJpbmdpZnkoa2V5KX1gKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IHBhcnQgb2YgcGFydHMpIHtcbiAgICAgICAgICAgIGRpciA9IGF3YWl0IGRpci5nZXREaXJlY3RvcnlIYW5kbGUocGFydCwgeyBjcmVhdGUgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgZGlyLCBuYW1lIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBnZXRGaWxlSGFuZGxlKGtleTogc3RyaW5nLCBjcmVhdGU6IGJvb2xlYW4gPSBmYWxzZSk6IFByb21pc2U8RmlsZVN5c3RlbUZpbGVIYW5kbGUgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICAgICAgICBpZiAoY3JlYXRlKSB7XG4gICAgICAgICAgICBjb25zdCB7IGRpciwgbmFtZSB9ID0gYXdhaXQgdGhpcy5yZXNvbHZlS2V5KGtleSwgdHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZGlyLmdldEZpbGVIYW5kbGUobmFtZSwgeyBjcmVhdGU6IHRydWUgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHsgZGlyLCBuYW1lIH0gPSBhd2FpdCB0aGlzLnJlc29sdmVLZXkoa2V5LCBmYWxzZSk7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZGlyLmdldEZpbGVIYW5kbGUobmFtZSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBmaWxlRXhpc3RzKGtleTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiAhIShhd2FpdCB0aGlzLmdldEZpbGVIYW5kbGUoa2V5LCBmYWxzZSkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPEJ1ZmZlciB8IHVuZGVmaW5lZD4ge1xuICAgICAgICAvLyBDaGVjayBpZiBmaWxlIGV4aXN0cyBmaXJzdCB0byBhdm9pZCB1bm5lY2Vzc2FyeSBlcnJvcnNcbiAgICAgICAgaWYgKCEoYXdhaXQgdGhpcy5maWxlRXhpc3RzKGtleSkpKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGZpbGVIYW5kbGUgPSBhd2FpdCB0aGlzLmdldEZpbGVIYW5kbGUoa2V5LCBmYWxzZSk7XG4gICAgICAgICAgICBpZiAoIWZpbGVIYW5kbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBmaWxlID0gYXdhaXQgZmlsZUhhbmRsZS5nZXRGaWxlKCk7XG4gICAgICAgICAgICBjb25zdCBhcnJheUJ1ZmZlciA9IGF3YWl0IGZpbGUuYXJyYXlCdWZmZXIoKTtcbiAgICAgICAgICAgIHJldHVybiBCdWZmZXIuZnJvbShhcnJheUJ1ZmZlcik7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYEVycm9yIHJlYWRpbmcgZmlsZSAke2tleX06YCwgZXJyb3IpO1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRSYW5nZShrZXk6IHN0cmluZywgY29uZmlnOiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyIH0pOiBQcm9taXNlPEJ1ZmZlciB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBjb25zdCBmaWxlSGFuZGxlID0gYXdhaXQgdGhpcy5nZXRGaWxlSGFuZGxlKGtleSwgZmFsc2UpO1xuICAgICAgICBpZiAoIWZpbGVIYW5kbGUpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmaWxlID0gYXdhaXQgZmlsZUhhbmRsZS5nZXRGaWxlKCk7XG4gICAgICAgIGNvbnN0IGFycmF5QnVmZmVyID0gYXdhaXQgZmlsZS5zbGljZShjb25maWcuc3RhcnQsIGNvbmZpZy5lbmQpLmFycmF5QnVmZmVyKCk7XG4gICAgICAgIHJldHVybiBCdWZmZXIuZnJvbShhcnJheUJ1ZmZlcik7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldChrZXk6IHN0cmluZywgdmFsdWU6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gICAgICAgIGNvbnN0IHsgZGlyLCBuYW1lIH0gPSBhd2FpdCB0aGlzLnJlc29sdmVLZXkoa2V5LCB0cnVlKTtcbiAgICAgICAgY29uc3QgZmlsZUhhbmRsZSA9IGF3YWl0IGRpci5nZXRGaWxlSGFuZGxlKG5hbWUsIHsgY3JlYXRlOiB0cnVlIH0pO1xuICAgICAgICBjb25zdCB3cml0YWJsZSA9IGF3YWl0IGZpbGVIYW5kbGUuY3JlYXRlV3JpdGFibGUoKTtcbiAgICAgICAgYXdhaXQgd3JpdGFibGUud3JpdGUodmFsdWUpO1xuICAgICAgICBhd2FpdCB3cml0YWJsZS5jbG9zZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBCdWZmZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdDb250ZW50ID0gYXdhaXQgdGhpcy5nZXQoa2V5KTtcbiAgICAgICAgbGV0IG5ld0NvbnRlbnQ6IEJ1ZmZlcjtcbiAgICAgICAgaWYgKGV4aXN0aW5nQ29udGVudCkge1xuICAgICAgICAgICAgbmV3Q29udGVudCA9IEJ1ZmZlci5jb25jYXQoW2V4aXN0aW5nQ29udGVudCwgdmFsdWVdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld0NvbnRlbnQgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLnNldChrZXksIG5ld0NvbnRlbnQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZW1vdmUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgZmlsZSBleGlzdHMgZmlyc3QgdG8gYXZvaWQgdW5uZWNlc3NhcnkgZXJyb3JzXG4gICAgICAgIGlmICghKGF3YWl0IHRoaXMuZmlsZUV4aXN0cyhrZXkpKSkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBGaWxlIGRvZXNuJ3QgZXhpc3QsIG5vdGhpbmcgdG8gcmVtb3ZlXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IGRpciwgbmFtZSB9ID0gYXdhaXQgdGhpcy5yZXNvbHZlS2V5KGtleSwgZmFsc2UpO1xuICAgICAgICBhd2FpdCBkaXIucmVtb3ZlRW50cnkobmFtZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGdldEtleXMoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgICAgICAvLyBDaGVjayBpZiBkaXJlY3RvcnkgZXhpc3RzIGZpcnN0IHRvIGF2b2lkIHVubmVjZXNzYXJ5IGVycm9yc1xuICAgICAgICBpZiAoIShhd2FpdCB0aGlzLmRpcmVjdG9yeUV4aXN0cygpKSkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGlySGFuZGxlID0gYXdhaXQgdGhpcy5nZXREaXJlY3RvcnlIYW5kbGUoZmFsc2UpO1xuICAgICAgICBjb25zdCBrZXlzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICBjb25zdCB3YWxrID0gYXN5bmMgKGRpcjogRmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZSwgcHJlZml4OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIC8vIFVzZSB0aGUgYXN5bmMgaXRlcmF0b3IgcHJvdG9jb2wgZm9yIEZpbGVTeXN0ZW1EaXJlY3RvcnlIYW5kbGVcbiAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgW25hbWUsIGhhbmRsZV0gb2YgKGRpciBhcyBhbnkpLmVudHJpZXMoKSkge1xuICAgICAgICAgICAgICAgIGlmIChoYW5kbGUua2luZCA9PT0gXCJmaWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5cy5wdXNoKHByZWZpeCArIG5hbWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaGFuZGxlLmtpbmQgPT09IFwiZGlyZWN0b3J5XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgd2FsayhoYW5kbGUsIHByZWZpeCArIG5hbWUgKyBcIi9cIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBhd2FpdCB3YWxrKGRpckhhbmRsZSwgXCJcIik7XG4gICAgICAgIHJldHVybiBrZXlzLnNvcnQoKTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGdldEluZm8oa2V5OiBzdHJpbmcpOiBQcm9taXNlPHVuZGVmaW5lZCB8IHtcbiAgICAgICAgc2l6ZTogbnVtYmVyO1xuICAgICAgICBsYXN0TW9kaWZpZWQ6IG51bWJlcjtcbiAgICB9PiB7XG4gICAgICAgIGxldCBmaWxlSGFuZGxlID0gYXdhaXQgdGhpcy5nZXRGaWxlSGFuZGxlKGtleSwgZmFsc2UpO1xuICAgICAgICBpZiAoIWZpbGVIYW5kbGUpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGZpbGUgPSBhd2FpdCBmaWxlSGFuZGxlLmdldEZpbGUoKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNpemU6IGZpbGUuc2l6ZSxcbiAgICAgICAgICAgIGxhc3RNb2RpZmllZDogZmlsZS5sYXN0TW9kaWZpZWQsXG4gICAgICAgIH07XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyByZXNldCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm90IGltcGxlbWVudGVkXCIpO1xuICAgIH1cbn0iXX0=
187
+ /* _JS_SOURCE_HASH = "d36140aa01c59609e7b32f01e6afca9fd5be1f57c25820dea2bf3779303d78c0"; */