sliftutils 1.7.111 → 1.7.113

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 (66) hide show
  1. package/dist/treeSummary.ts.cache +2 -2
  2. package/index.d.ts +2 -1
  3. package/misc/dist/environment.ts.cache +2 -2
  4. package/misc/dist/getSecret.ts.cache +2 -2
  5. package/misc/dist/strings.ts.cache +2 -2
  6. package/misc/dist/zip.ts.cache +2 -2
  7. package/misc/https/dist/certs.ts.cache +2 -2
  8. package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
  9. package/package.json +1 -1
  10. package/render-utils/dist/observer.tsx.cache +2 -2
  11. package/storage/ArchivesDisk.ts +8 -7
  12. package/storage/IArchives.d.ts +1 -0
  13. package/storage/IArchives.ts +2 -1
  14. package/storage/TransactionFile.d.ts +1 -1
  15. package/storage/TransactionFile.ts +13 -2
  16. package/storage/archiveHelpers.ts +11 -9
  17. package/storage/dist/ArchivesDisk.ts.cache +10 -9
  18. package/storage/dist/FileFolderAPI.tsx.cache +2 -2
  19. package/storage/dist/IArchives.ts.cache +3 -3
  20. package/storage/dist/IndexedDBFileFolderAPI.ts.cache +2 -2
  21. package/storage/dist/JSONStorage.ts.cache +2 -2
  22. package/storage/dist/PendingManager.tsx.cache +2 -2
  23. package/storage/dist/StreamingLogs.ts.cache +2 -2
  24. package/storage/dist/TransactionFile.ts.cache +16 -5
  25. package/storage/dist/TransactionStorage.ts.cache +2 -2
  26. package/storage/dist/archiveHelpers.ts.cache +13 -11
  27. package/storage/dist/backblaze.ts.cache +2 -2
  28. package/storage/dist/fileSystemPointer.ts.cache +2 -2
  29. package/storage/dist/remoteFileStorage.ts.cache +2 -2
  30. package/storage/remoteStorage/ArchivesDelayed.ts +3 -3
  31. package/storage/remoteStorage/ArchivesRemote.ts +2 -2
  32. package/storage/remoteStorage/blobStore.ts +15 -15
  33. package/storage/remoteStorage/bucketDisk.ts +2 -1
  34. package/storage/remoteStorage/chainStartup.ts +2 -2
  35. package/storage/remoteStorage/createArchives.ts +13 -13
  36. package/storage/remoteStorage/deployTakeover.ts +1 -1
  37. package/storage/remoteStorage/dist/ArchivesDelayed.ts.cache +6 -6
  38. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +5 -5
  39. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +2 -2
  40. package/storage/remoteStorage/dist/accessStats.ts.cache +2 -2
  41. package/storage/remoteStorage/dist/blobStore.ts.cache +17 -17
  42. package/storage/remoteStorage/dist/bucketDisk.ts.cache +5 -4
  43. package/storage/remoteStorage/dist/certTrustModal.tsx.cache +2 -2
  44. package/storage/remoteStorage/dist/chainStartup.ts.cache +5 -5
  45. package/storage/remoteStorage/dist/cliArgs.ts.cache +2 -2
  46. package/storage/remoteStorage/dist/createArchives.ts.cache +14 -14
  47. package/storage/remoteStorage/dist/deployTakeover.ts.cache +4 -4
  48. package/storage/remoteStorage/dist/intermediateManagement.ts.cache +2 -2
  49. package/storage/remoteStorage/dist/intermediateSources.ts.cache +2 -2
  50. package/storage/remoteStorage/dist/remoteConfig.ts.cache +4 -4
  51. package/storage/remoteStorage/dist/serverConfig.ts.cache +2 -2
  52. package/storage/remoteStorage/dist/sourceWrapper.ts.cache +6 -6
  53. package/storage/remoteStorage/dist/sourcesList.ts.cache +2 -2
  54. package/storage/remoteStorage/dist/storageClientController.ts.cache +2 -2
  55. package/storage/remoteStorage/dist/storageController.ts.cache +7 -7
  56. package/storage/remoteStorage/dist/storageServerState.ts.cache +4 -4
  57. package/storage/remoteStorage/dist/storeConfig.ts.cache +2 -2
  58. package/storage/remoteStorage/dist/storePlan.ts.cache +2 -2
  59. package/storage/remoteStorage/dist/storeSources.ts.cache +2 -2
  60. package/storage/remoteStorage/dist/storeSync.ts.cache +11 -11
  61. package/storage/remoteStorage/dist/validation.ts.cache +2 -2
  62. package/storage/remoteStorage/remoteConfig.ts +1 -1
  63. package/storage/remoteStorage/sourceWrapper.ts +3 -3
  64. package/storage/remoteStorage/storageController.ts +4 -4
  65. package/storage/remoteStorage/storageServerState.ts +1 -1
  66. package/storage/remoteStorage/storeSync.ts +10 -10
@@ -152,7 +152,7 @@ export class BlobStore {
152
152
  if (provided) {
153
153
  console.log(`Store ${JSON.stringify(this.storeName)} (folder ${this.folder}) initialized with no configuration; the requesting client provided routing config version ${getConfigVersion(provided)} - adopting it`);
154
154
  // Straight onto the disk, not through set(): set waits for init, which is what is running right now
155
- await this.ownDisk.set(ROUTING_FILE, Buffer.from(serializeRemoteConfig(provided)), { lastModified: Date.now() });
155
+ await this.ownDisk.set(ROUTING_FILE, Buffer.from(serializeRemoteConfig(provided)), { lastModified: Math.floor(Date.now()) });
156
156
  await this.applyRoutingConfig();
157
157
  } else {
158
158
  logStorageWarn(`Store ${JSON.stringify(this.storeName)} (folder ${this.folder}) initialized with no configuration, and the requesting client had no routing config naming it either - running unconfigured`);
@@ -374,10 +374,10 @@ export class BlobStore {
374
374
  public async set(config: { path: string; data: Buffer; lastModified?: number; forceSetImmutable?: boolean; internal?: boolean; undelete?: boolean }): Promise<void> {
375
375
  let { path: key, data } = config;
376
376
  if (!data.length) {
377
- throw new Error(`set was called with an empty buffer for ${JSON.stringify(key)} (store ${this.folder}): an empty file IS a deletion in this system and would read back as missing - call del instead`);
377
+ throw new Error(`Empty write refused: set was called with an empty buffer for ${JSON.stringify(key)} (store ${this.folder}): an empty file IS a deletion in this system and would read back as missing - call del instead`);
378
378
  }
379
379
  await this.init();
380
- let writeTime = config.lastModified || Date.now();
380
+ let writeTime = Math.floor(config.lastModified || Date.now());
381
381
  let route = getRoute(key);
382
382
  // The routing file defines the windows/routes, so they can't possibly apply to it (and it never flows through validation) - but it has a rule of its own, which is ours to enforce because the file is ours
383
383
  if (key === ROUTING_FILE) {
@@ -448,7 +448,7 @@ export class BlobStore {
448
448
  }
449
449
  let result = await this.get2({ path: config.fromPath });
450
450
  if (!result || !result.data.length) {
451
- throw new Error(`Cannot move ${JSON.stringify(config.fromPath)} to ${JSON.stringify(config.toPath)}: the source file does not exist (store ${this.folder})`);
451
+ throw new Error(`Move source does not exist. Cannot move ${JSON.stringify(config.fromPath)} to ${JSON.stringify(config.toPath)} (store ${this.folder})`);
452
452
  }
453
453
  await this.set({ path: config.toPath, data: result.data });
454
454
  await this.del({ path: config.fromPath });
@@ -648,7 +648,7 @@ export class BlobStore {
648
648
  await this.init();
649
649
  let key = config?.path;
650
650
  if (key) {
651
- let writeTime = config?.lastModified || Date.now();
651
+ let writeTime = Math.floor(config?.lastModified || Date.now());
652
652
  let route = getRoute(key);
653
653
  if (key !== ROUTING_FILE) {
654
654
  this.assertWriteTarget(key, route, config?.lastModified);
@@ -742,7 +742,7 @@ export class BlobStore {
742
742
  public sourcesListIndexOfSlot(slot: number): number {
743
743
  let index = this.slotSourcesListIndexes[slot];
744
744
  if (index === undefined) {
745
- throw new Error(`Source slot ${slot} (${this.sources[slot]?.url}) has no registered sourcesListIndex yet (store ${this.folder})`);
745
+ throw new Error(`Source slot is not registered yet. Slot ${slot} (${this.sources[slot]?.url}) has no sourcesListIndex (store ${this.folder})`);
746
746
  }
747
747
  return index;
748
748
  }
@@ -848,7 +848,7 @@ export class BlobStore {
848
848
  console.log(`Undelete of ${JSON.stringify(key)} (store ${this.folder}) has nothing to restore here - this node may never have held the file`);
849
849
  return;
850
850
  }
851
- throw new Error(`Cannot undelete ${JSON.stringify(key)} (store ${this.folder}): it has no marked deletion to restore - it was never deleted here${this.getDeletedEntry(key) && ", or its deletion history was already dropped (a plain tombstone remains, but the bytes are gone)" || ""}`);
851
+ throw new Error(`Undelete failed - nothing to restore. Cannot undelete ${JSON.stringify(key)} (store ${this.folder}): it has no marked deletion to restore - it was never deleted here${this.getDeletedEntry(key) && ", or its deletion history was already dropped (a plain tombstone remains, but the bytes are gone)" || ""}`);
852
852
  }
853
853
  console.log(`Undeleted ${JSON.stringify(key)} (store ${this.folder}): the index entry (${marked?.size} bytes, deleted ${marked && new Date(marked.deleteTime).toISOString()}) is live again as of ${new Date(writeTime).toISOString()} - the bytes never left the disk`);
854
854
  logMutation({ op: "undelete", folder: this.folder, store: this.storeName, path: key, size: marked?.size, writeTime, internal });
@@ -932,7 +932,7 @@ export class BlobStore {
932
932
  if (!this.storeConfig.all().length) {
933
933
  let detail = this.unconfiguredDetail();
934
934
  logWrongTargetRejection(`Rejecting write of ${JSON.stringify(key)}: ${detail}`);
935
- throw new Error(`${STORAGE_NOT_CONFIGURED} Cannot write ${JSON.stringify(key)}: ${detail} Data written to a store with no configuration entry would never be scanned or reconciled, so accepting it would silently lose it. Re-resolve the currently valid source and retry - or, if this store is genuinely meant to take this write, write the bucket's routing config with an entry naming it on this server.`);
935
+ throw new Error(`${STORAGE_NOT_CONFIGURED} Write rejected: this store has no configuration. Cannot write ${JSON.stringify(key)}: ${detail} Data written to a store with no configuration entry would never be scanned or reconciled, so accepting it would silently lose it. Re-resolve the currently valid source and retry - or, if this store is genuinely meant to take this write, write the bucket's routing config with an entry naming it on this server.`);
936
936
  }
937
937
  if (!lastModified) {
938
938
  this.assertFreshWriteTarget(key, Date.now(), route);
@@ -941,7 +941,7 @@ export class BlobStore {
941
941
  // A stamped write picked its own time, so no window can judge it (that is the whole point of a synchronized write) - but the ROUTE is not a matter of timing, and a stamped write to the wrong shard is exactly as invisible as a fresh one
942
942
  if (this.storeConfig.all().some(x => routeContains(x.route, route))) return;
943
943
  logWrongTargetRejection(`Rejecting stamped write of ${JSON.stringify(key)} (store ${this.folder}): route ${route} is outside every route we serve ${JSON.stringify(this.storeConfig.all().map(x => x.route || FULL_ROUTE))}`);
944
- throw new Error(`${STORAGE_WRONG_ROUTE} This store does not handle route ${route} (key ${JSON.stringify(key)}, our routes: ${JSON.stringify(this.storeConfig.all().map(x => x.route || FULL_ROUTE))}, store ${this.folder}). Re-resolve the source for this key and retry.`);
944
+ throw new Error(`${STORAGE_WRONG_ROUTE} Write rejected: wrong route for this store. Route ${route} (key ${JSON.stringify(key)}, our routes: ${JSON.stringify(this.storeConfig.all().map(x => x.route || FULL_ROUTE))}, store ${this.folder}). Re-resolve the source for this key and retry.`);
945
945
  }
946
946
 
947
947
  /** Exactly why this store has no configuration entries - which of the three possible reasons it is, with the values that decided it, because "not configured" alone is undiagnosable. */
@@ -974,7 +974,7 @@ export class BlobStore {
974
974
  let incoming = getConfigVersion(routing);
975
975
  let current = this.routingVersion();
976
976
  if (incoming >= current) return;
977
- throw new Error(`Refusing to write ${ROUTING_FILE} to store ${this.folder}: its version (${incoming}) is older than the one this store is running (${current}). Increment the version to update it.`);
977
+ throw new Error(`Routing config write refused - the version is not newer. Refusing to write ${ROUTING_FILE} to store ${this.folder}: its version (${incoming}) is older than the one this store is running (${current}). Increment the version to update it.`);
978
978
  }
979
979
 
980
980
  // A fresh (unstamped) write must land on the node the config currently points at: the markers tell the client its config is stale, so it re-resolves and retries against the right node instead of us silently accepting data we were never meant to hold.
@@ -982,11 +982,11 @@ export class BlobStore {
982
982
  let timeValid = this.storeConfig.all().filter(x => writeTime >= x.validWindow[0] && writeTime < x.validWindow[1]);
983
983
  if (!timeValid.length) {
984
984
  logWrongTargetRejection(`Rejecting fresh write of ${JSON.stringify(key)} (store ${this.folder}): writeTime ${writeTime} (${new Date(writeTime).toISOString()}) is outside all our valid windows ${JSON.stringify(this.storeConfig.all().map(x => x.validWindow))} (a switchover moved the write target)`);
985
- throw new Error(`${STORAGE_WRONG_VALID_WINDOW} Cannot write ${JSON.stringify(key)}: its write time ${writeTime} (${new Date(writeTime).toISOString()}) is outside every valid window of store ${JSON.stringify(this.storeName)} (windows: ${JSON.stringify(this.storeConfig.all().map(x => x.validWindow))}, folder ${this.folder}) - a switchover moved the write target. Re-resolve the currently valid source and retry.`);
985
+ throw new Error(`${STORAGE_WRONG_VALID_WINDOW} Write rejected: write time is outside our valid windows. Cannot write ${JSON.stringify(key)}: its write time ${writeTime} (${new Date(writeTime).toISOString()}) is outside every valid window of store ${JSON.stringify(this.storeName)} (windows: ${JSON.stringify(this.storeConfig.all().map(x => x.validWindow))}, folder ${this.folder}) - a switchover moved the write target. Re-resolve the currently valid source and retry.`);
986
986
  }
987
987
  if (!timeValid.some(x => routeContains(x.route, route))) {
988
988
  logWrongTargetRejection(`Rejecting fresh write of ${JSON.stringify(key)} (store ${this.folder}): route ${route} is outside our routes ${JSON.stringify(timeValid.map(x => x.route || FULL_ROUTE))} at writeTime ${writeTime} (the client's shard config is stale)`);
989
- throw new Error(`${STORAGE_WRONG_ROUTE} This store does not handle route ${route} (key ${JSON.stringify(key)}, our routes at this time: ${JSON.stringify(timeValid.map(x => x.route || FULL_ROUTE))}, store ${this.folder}). Re-resolve the source for this key and retry.`);
989
+ throw new Error(`${STORAGE_WRONG_ROUTE} Write rejected: wrong route for this store. Route ${route} (key ${JSON.stringify(key)}, our routes at this time: ${JSON.stringify(timeValid.map(x => x.route || FULL_ROUTE))}, store ${this.folder}). Re-resolve the source for this key and retry.`);
990
990
  }
991
991
  }
992
992
 
@@ -995,7 +995,7 @@ export class BlobStore {
995
995
  let self = selectEntryAt(this.storeConfig.all(), writeTime, getRoute(key));
996
996
  if (!self?.immutable) return;
997
997
  if (await this.getInfo({ path: key })) {
998
- throw new Error(`This store is immutable (at write time ${writeTime}) and ${JSON.stringify(key)} already exists, so it cannot be written to (store ${this.folder})`);
998
+ throw new Error(`Write rejected - immutable store and the file already exists. At write time ${writeTime}, ${JSON.stringify(key)} already exists (store ${this.folder})`);
999
999
  }
1000
1000
  }
1001
1001
 
@@ -1004,7 +1004,7 @@ export class BlobStore {
1004
1004
  if (!this.storeConfig.all().length) return;
1005
1005
  let covered = this.storeConfig.all().some(x => writeTime >= x.validWindow[0] && writeTime < x.validWindow[1] && routeContains(x.route, route));
1006
1006
  if (!covered) {
1007
- throw new Error(`Internal write of ${JSON.stringify(key)} rejected: writeTime ${writeTime} (${new Date(writeTime).toISOString()}) at route ${route} is outside every window/route this store is configured for: ${JSON.stringify(this.storeConfig.all().map(x => ({ validWindow: x.validWindow, route: x.route || FULL_ROUTE })))} (store ${this.folder})`);
1007
+ throw new Error(`Internal write rejected - outside every configured window/route. Writing ${JSON.stringify(key)}: writeTime ${writeTime} (${new Date(writeTime).toISOString()}) at route ${route} is outside every window/route this store is configured for: ${JSON.stringify(this.storeConfig.all().map(x => ({ validWindow: x.validWindow, route: x.route || FULL_ROUTE })))} (store ${this.folder})`);
1008
1008
  }
1009
1009
  }
1010
1010
 
@@ -1057,7 +1057,7 @@ export class BlobStore {
1057
1057
  if (lastModified < await this.currentWriteTime(key)) return;
1058
1058
  }
1059
1059
  // Fast writes are not handled here: a source that was configured with a write delay buffers them itself (see ArchivesDelayed), so this write lands in memory and returns, exactly as it would have. The index is updated either way, so the write is immediately visible to readers of this store.
1060
- await this.writeToSources(key, data, lastModified || Date.now());
1060
+ await this.writeToSources(key, data, Math.floor(lastModified || Date.now()));
1061
1061
  }
1062
1062
 
1063
1063
  /** The instant every delayed write must be on its source: the end of our own write window that contains now, minus the flush margin (so the next window's source finds the data on handoff). The LATEST end among covering windows - overlapping windows hand off at the last one. No window contains now (an inert store, or a moment between our windows) -> 0, i.e. nothing may be delayed at all. */
@@ -51,7 +51,8 @@ export async function readRoutingFile(folder: string): Promise<{ data: Buffer; w
51
51
  try {
52
52
  let data = await fs.promises.readFile(filePath);
53
53
  let stats = await fs.promises.stat(filePath);
54
- return { data, writeTime: stats.mtimeMs };
54
+ // Floored like every time ArchivesDisk reports - sub-millisecond mtime digits can't round-trip through utimes, so they are noise, not ordering
55
+ return { data, writeTime: Math.floor(stats.mtimeMs) };
55
56
  } catch (e) {
56
57
  if ((e as { code?: string }).code === "ENOENT") return undefined;
57
58
  throw e;
@@ -342,7 +342,7 @@ export function chooseStartupConfig(config: { configured: RemoteConfig; probes:
342
342
  let { configured, probes, debugName } = config;
343
343
  let found = probes.find(x => x.responded);
344
344
  if (!found) {
345
- throw new Error(`Cannot initialize storage for ${debugName}: no source answered. ${probes.map(x => x.error).join(" | ")}`);
345
+ throw new Error(`Storage initialization failed - no source answered. For ${debugName}: ${probes.map(x => x.error).join(" | ")}`);
346
346
  }
347
347
  let existing = found.existing;
348
348
  let active = configured;
@@ -391,7 +391,7 @@ export function chooseStartupConfig(config: { configured: RemoteConfig; probes:
391
391
  export async function writeRoutingToAllStores(config: { configured: RemoteConfig; sources: SourceWrapper[]; debugName: string }): Promise<{ failures: string[]; total: number }> {
392
392
  let { configured, sources, debugName } = config;
393
393
  let routingData = serializeRemoteConfig(configured);
394
- let routingWriteTime = Date.now();
394
+ let routingWriteTime = Math.floor(Date.now());
395
395
  let targets: SourceWrapper[] = [];
396
396
  let seen = new Set<string>();
397
397
  for (let source of sources) {
@@ -19,7 +19,7 @@ import { RemoteStorageController, STORAGE_NOT_AUTHENTICATED } from "./storageCon
19
19
  import { SourceWrapper } from "./sourceWrapper";
20
20
  import { ChainState, ChainStateManager } from "./chainStartup";
21
21
  import { LogFileInfo, decodeLogFile, createLogSearcher } from "../StreamingLogs";
22
- import { formatTime } from "socket-function/src/formatting/format";
22
+ import { formatTime, formatDateTimeDetailed } from "socket-function/src/formatting/format";
23
23
 
24
24
  // How many extra full passes over the sources fallback dispatch makes when EVERY source in a pass failed, before the operation throws (see GetConfig.retries) - most requests shouldn't fail at all, so a couple of blanket retries buys availability for almost nothing
25
25
  const DEFAULT_FALLBACK_RETRIES = 3;
@@ -212,7 +212,7 @@ export class ArchivesChain implements IArchives {
212
212
  let target = state.sources.find(x => configWindowCurrent(x.config) && (config.route === undefined || routeContains(x.config.route, config.route)));
213
213
  try {
214
214
  if (!target) {
215
- throw new Error(`No source is the ${config.write && "write target" || "primary read source"} for ${this.getDebugName()}${config.route !== undefined && ` (route ${config.route})` || ""} (every source is outside its valid window or outside the key's route)`);
215
+ throw new Error(`No valid source covers this request. No source is the ${config.write && "write target" || "primary read source"} for ${this.getDebugName()}${config.route !== undefined && ` (route ${config.route})` || ""} (every source is outside its valid window or outside the key's route)`);
216
216
  }
217
217
  const primary = target;
218
218
  return await this.applySmartTimeout(config.timeout, primary, () => {
@@ -266,7 +266,7 @@ export class ArchivesChain implements IArchives {
266
266
  let result = await Promise.race([callPromise.then(value => ({ value })), delay(allowed).then(() => undefined)]);
267
267
  if (result) return result.value;
268
268
  abandon();
269
- throw new Error(`${SMART_TIMEOUT_MARKER} ${timeout.label || `Upload of ${timeout.uploadBytes} bytes`} to ${source.getDebugName()} timed out after ${Date.now() - start}ms (allowed ${Math.round(allowed)}ms: ${SMART_TIMEOUT_PROBE}ms base plus transfer at an assumed ${SMART_TIMEOUT_UPLOAD_BYTES_PER_SECOND} bytes/s)`);
269
+ throw new Error(`${SMART_TIMEOUT_MARKER} Upload timed out. ${timeout.label || `Upload of ${timeout.uploadBytes} bytes`} to ${source.getDebugName()} timed out after ${Date.now() - start}ms (allowed ${Math.round(allowed)}ms: ${SMART_TIMEOUT_PROBE}ms base plus transfer at an assumed ${SMART_TIMEOUT_UPLOAD_BYTES_PER_SECOND} bytes/s)`);
270
270
  }
271
271
  const path = timeout.path;
272
272
  if (path === undefined) return await callPromise;
@@ -284,7 +284,7 @@ export class ArchivesChain implements IArchives {
284
284
  }
285
285
  if (!info) {
286
286
  abandon();
287
- throw new Error(`${SMART_TIMEOUT_MARKER} Read of ${JSON.stringify(path)} from ${source.getDebugName()} timed out: no result after ${Date.now() - start}ms, and getInfo ${probeError && `failed (${probeError})` || `could not answer within ${SMART_TIMEOUT_PROBE}ms either`}`);
287
+ throw new Error(`${SMART_TIMEOUT_MARKER} Read timed out with no size probe. Read of ${JSON.stringify(path)} from ${source.getDebugName()}: no result after ${Date.now() - start}ms, and getInfo ${probeError && `failed (${probeError})` || `could not answer within ${SMART_TIMEOUT_PROBE}ms either`}`);
288
288
  }
289
289
  let allowed = Math.max(SMART_TIMEOUT_PROBE, info.size / SMART_TIMEOUT_DOWNLOAD_BYTES_PER_SECOND * 1000);
290
290
  let remaining = start + allowed - Date.now();
@@ -293,7 +293,7 @@ export class ArchivesChain implements IArchives {
293
293
  if (second) return second.value;
294
294
  }
295
295
  abandon();
296
- throw new Error(`${SMART_TIMEOUT_MARKER} Read of ${JSON.stringify(path)} (${info.size} bytes) from ${source.getDebugName()} timed out after ${Date.now() - start}ms (allowed ${Math.round(allowed)}ms from the call's start, at an assumed ${SMART_TIMEOUT_DOWNLOAD_BYTES_PER_SECOND} bytes/s)`);
296
+ throw new Error(`${SMART_TIMEOUT_MARKER} Read timed out. Read of ${JSON.stringify(path)} (${info.size} bytes) from ${source.getDebugName()} timed out after ${Date.now() - start}ms (allowed ${Math.round(allowed)}ms from the call's start, at an assumed ${SMART_TIMEOUT_DOWNLOAD_BYTES_PER_SECOND} bytes/s)`);
297
297
  }
298
298
 
299
299
  private lastConfigRefresh = 0;
@@ -517,7 +517,7 @@ export class ArchivesChain implements IArchives {
517
517
  public async getSyncStatus(): Promise<ArchivesSyncStatus> {
518
518
  let statuses = await this.runOnCovering(`The sync status check`, async archives => {
519
519
  if (!archives.getSyncStatus) {
520
- throw new Error(`${archives.getDebugName()} does not support getSyncStatus`);
520
+ throw new Error(`getSyncStatus is not supported: ${archives.getDebugName()} does not implement it`);
521
521
  }
522
522
  return await archives.getSyncStatus();
523
523
  });
@@ -544,7 +544,7 @@ export class ArchivesChain implements IArchives {
544
544
 
545
545
  public async set(fileName: string, data: Buffer, config?: SetConfig): Promise<string> {
546
546
  if (!data.length) {
547
- throw new Error(`set was called with an empty buffer for ${JSON.stringify(fileName)}: an empty file IS a deletion in this system and would read back as missing - call del instead`);
547
+ throw new Error(`Empty write refused: set was called with an empty buffer for ${JSON.stringify(fileName)}: an empty file IS a deletion in this system and would read back as missing - call del instead`);
548
548
  }
549
549
  if (fileName === ROUTING_FILE) {
550
550
  return await this.setRoutingConfig(data, config);
@@ -565,7 +565,7 @@ export class ArchivesChain implements IArchives {
565
565
  // Checked before the first node is written to, not just by each node as it arrives: every server would reject it anyway, and finding that out one node at a time is how a config write ends up half-applied
566
566
  assertValidRemoteConfig(parseRoutingData(data));
567
567
  let state = await this.state.getState();
568
- let writeTime = config?.lastModified || Date.now();
568
+ let writeTime = Math.floor(config?.lastModified || Date.now());
569
569
  let written: string[] = [];
570
570
  let errors: string[] = [];
571
571
  // One write per STORE, not per server: the write lands in the store the entry NAMES, so two entries sharing a URL but naming different stores are two separate deliveries - deduping by URL alone leaves the second store unconfigured forever
@@ -590,7 +590,7 @@ export class ArchivesChain implements IArchives {
590
590
  }));
591
591
  await this.state.refreshActiveConfig();
592
592
  if (errors.length) {
593
- throw new Error(`Storage routing config write for ${this.getDebugName()} failed on ${errors.length} of ${targets.length} stores (succeeded on: ${written.join(", ") || "none"}): ${errors.join(" | ")}`);
593
+ throw new Error(`Routing config write failed on some stores. For ${this.getDebugName()}: failed on ${errors.length} of ${targets.length} stores (succeeded on: ${written.join(", ") || "none"}): ${errors.join(" | ")}`);
594
594
  }
595
595
  return ROUTING_FILE;
596
596
  }
@@ -618,7 +618,7 @@ export class ArchivesChain implements IArchives {
618
618
  if (target && routeContains(target.config.route, toRoute)) {
619
619
  await this.request({ write: true, route: fromRoute }, async archives => {
620
620
  if (!archives.move) {
621
- throw new Error(`${archives.getDebugName()} does not support move (moving ${JSON.stringify(config.fromPath)} to ${JSON.stringify(config.toPath)})`);
621
+ throw new Error(`Move is not supported by this source: ${archives.getDebugName()} (moving ${JSON.stringify(config.fromPath)} to ${JSON.stringify(config.toPath)})`);
622
622
  }
623
623
  await archives.move(config);
624
624
  });
@@ -630,13 +630,13 @@ export class ArchivesChain implements IArchives {
630
630
  // Undefined is two cases (see copyArchiveFile) - asking the source which one keeps the error honest
631
631
  let sourceInfo = await this.getInfo(config.fromPath);
632
632
  if (sourceInfo) {
633
- throw new Error(`Cannot move ${JSON.stringify(config.fromPath)} (${sourceInfo.size} bytes at ${new Date(sourceInfo.writeTime).toISOString()}) to ${JSON.stringify(config.toPath)}: the destination already has a newer file, and the copy was refused rather than roll it back (${this.getDebugName()}) - the source is left untouched`);
633
+ throw new Error(`Move refused - a newer file exists at the destination. Cannot move ${JSON.stringify(config.fromPath)} (${sourceInfo.size} bytes at ${formatDateTimeDetailed(sourceInfo.writeTime)}) to ${JSON.stringify(config.toPath)}: the copy was refused rather than roll it back (${this.getDebugName()}) - the source is left untouched`);
634
634
  }
635
- throw new Error(`Cannot move ${JSON.stringify(config.fromPath)} to ${JSON.stringify(config.toPath)}: the source file does not exist on ${this.getDebugName()}`);
635
+ throw new Error(`Move source does not exist. Cannot move ${JSON.stringify(config.fromPath)} to ${JSON.stringify(config.toPath)}: not found on ${this.getDebugName()}`);
636
636
  }
637
637
  let confirmed = await this.getInfo(config.toPath);
638
638
  if (!confirmed) {
639
- throw new Error(`Not deleting ${JSON.stringify(config.fromPath)} after copying it to ${JSON.stringify(config.toPath)}: the destination does not report it (${this.getDebugName()}) - the file is left at the source`);
639
+ throw new Error(`Move copy could not be confirmed - the source is kept. Not deleting ${JSON.stringify(config.fromPath)} after copying it to ${JSON.stringify(config.toPath)}: the destination does not report it (${this.getDebugName()})`);
640
640
  }
641
641
  await this.del(config.fromPath);
642
642
  }
@@ -101,7 +101,7 @@ export async function detectDeployTakeover(): Promise<DeployTakeover> {
101
101
 
102
102
  export function setAltPort(port: number): void {
103
103
  if (!takeover) {
104
- throw new Error(`An alternate port (${port}) was taken without a detected deploy takeover - detectDeployTakeover must run first`);
104
+ throw new Error(`Alternate port taken without a detected deploy takeover: port ${port} - detectDeployTakeover must run first`);
105
105
  }
106
106
  takeover.altPort = port;
107
107
  // Needs to be enough after our startup time that the previous node has time to see it's going to be shut down and flush (and so we have time to start up), and enough before the kill time that nodes have time to notice we exist and prepare to connect to us - halfway between now and the kill time satisfies both
@@ -1,4 +1,4 @@
1
- "use strict";
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.unwrapDelayed = exports.asDelayed = exports.sourceWriteDelay = exports.ArchivesDelayed = exports.MAX_REMOTE_FAST_BUFFER = exports.DEFAULT_FAST_WRITE_DELAY = void 0;
4
4
  const batching_1 = require("socket-function/src/batching");
@@ -40,7 +40,7 @@ class ArchivesDelayed {
40
40
  }
41
41
  async set(fileName, data, config) {
42
42
  if (!data.length) {
43
- throw new Error(`set was called with an empty buffer for ${JSON.stringify(fileName)} on ${this.getDebugName()}: an empty file IS a deletion in this system and would read back as missing - call del instead`);
43
+ throw new Error(`Empty write refused: set was called with an empty buffer for ${JSON.stringify(fileName)} on ${this.getDebugName()}: an empty file IS a deletion in this system and would read back as missing - call del instead`);
44
44
  }
45
45
  return await this.buffer(fileName, data, config === null || config === void 0 ? void 0 : config.lastModified, config);
46
46
  }
@@ -49,7 +49,7 @@ class ArchivesDelayed {
49
49
  }
50
50
  // The shared engine of set and del - an empty buffer is exactly a deletion here
51
51
  async buffer(fileName, data, lastModified, config) {
52
- let writeTime = lastModified || Date.now();
52
+ let writeTime = Math.floor(lastModified || Date.now());
53
53
  let existing = this.pending.get(fileName);
54
54
  // An older write never overwrites a newer one (see IArchives.set) - including against a write still sitting here
55
55
  if (existing && writeTime < existing.writeTime)
@@ -181,7 +181,7 @@ class ArchivesDelayed {
181
181
  }
182
182
  async getSyncStatus() {
183
183
  if (!this.inner.getSyncStatus) {
184
- throw new Error(`${this.inner.getDebugName()} does not support getSyncStatus`);
184
+ throw new Error(`getSyncStatus is not supported: ${this.inner.getDebugName()} does not implement it`);
185
185
  }
186
186
  return await this.inner.getSyncStatus();
187
187
  }
@@ -216,5 +216,5 @@ function unwrapDelayed(source) {
216
216
  return source;
217
217
  }
218
218
  exports.unwrapDelayed = unwrapDelayed;
219
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXJjaGl2ZXNEZWxheWVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiQXJjaGl2ZXNEZWxheWVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJEQUErRDtBQU0vRCw4bEJBQThsQjtBQUU5bEIsaUpBQWlKO0FBQ2pKLE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7QUFDZixRQUFBLHdCQUF3QixHQUFHLElBQUksR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ3RELDhNQUE4TTtBQUNqTSxRQUFBLHNCQUFzQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7QUFVL0MsTUFBYSxlQUFlO0lBTXhCLFlBQ1csS0FBZ0I7SUFDdkIsd0hBQXdIO0lBQ2hILEtBQWE7UUFGZCxVQUFLLEdBQUwsS0FBSyxDQUFXO1FBRWYsVUFBSyxHQUFMLEtBQUssQ0FBUTtRQVJqQixZQUFPLEdBQUcsSUFBSSxHQUFHLEVBQXdCLENBQUM7UUFDMUMsWUFBTyxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO1FBUzlCLElBQUEsMEJBQWUsRUFBQyxVQUFVLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRUQsa0hBQWtIO0lBQzNHLGlCQUFpQixDQUFDLFdBQXlCO1FBQzlDLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQ25DLENBQUM7SUFFRCxvUUFBb1E7SUFDN1AsUUFBUSxDQUFDLEtBQWE7UUFDekIsSUFBSSxLQUFLLEtBQUssSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPO1FBQ2pDLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLEtBQUssSUFBSSxDQUFDLEtBQUssU0FBUyxLQUFLLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLGtCQUFrQixDQUFD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QjtJQUN2QyxJQUFJLE1BQU0sWUFBWSxlQUFlO1FBQUUsT0FBTyxNQUFNLENBQUM7SUFDckQsT0FBTyxTQUFTLENBQUM7QUFDckIsQ0FBQztBQUhELDhCQUdDO0FBRUQsK0NBQStDO0FBQy9DLFNBQWdCLGFBQWEsQ0FBQyxNQUFpQjtJQUMzQyxJQUFJLE1BQU0sWUFBWSxlQUFlO1FBQUUsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDO0lBQzNELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUM7QUFIRCxzQ0FHQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJ1bkluZmluaXRlUG9sbCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2JhdGNoaW5nXCI7XG5pbXBvcnQge1xuICAgIElBcmNoaXZlcywgQXJjaGl2ZUZpbGVJbmZvLCBBcmNoaXZlc0NvbmZpZywgQXJjaGl2ZXNTeW5jU3RhdHVzLCBDaGFuZ2VzQWZ0ZXJDb25maWcsIERlbENvbmZpZyxcbiAgICBGaW5kQ29uZmlnLCBHZXRDb25maWcsIEdldEluZm9Db25maWcsIFNldENvbmZpZywgU2V0TGFyZ2VGaWxlQ29uZmlnLCBTb3VyY2VDb25maWcsXG59IGZyb20gXCIuLi9JQXJjaGl2ZXNcIjtcblxuLy8gRmFzdCB3cml0ZXMgKHNlZSBzcGVjLm1kLCBcImZhc3Qgd3JpdGVzXCIpLCBhcyBhIHdyYXBwZXIgYXJvdW5kIE9ORSBzb3VyY2UgaW5zdGVhZCBvZiBhIGJ1ZmZlciBzbWVhcmVkIHRocm91Z2ggdGhlIHN0b3JlOiBhIHdyaXRlIHJldHVybnMgYXMgc29vbiBhcyBpdCBpcyBpbiBtZW1vcnksIGFuZCByZXBlYXRlZCB3cml0ZXMgdG8gdGhlIHNhbWUgcGF0aCBjb2xsYXBzZSBpbnRvIGEgc2luZ2xlIHdyaXRlIHRvIHRoZSB3cmFwcGVkIHNvdXJjZS4gRXZlcnkgcmVhZCBnb2VzIHRocm91Z2ggdGhlIHBlbmRpbmcgd3JpdGVzIGZpcnN0LCBzbyBhIGRlbGF5ZWQgd3JpdGUgaXMgc3RpbGwgcmVhZC15b3VyLXdyaXRlcyBmb3IgYW55b25lIHJlYWRpbmcgdGhyb3VnaCB0aGlzIHdyYXBwZXIuIEVhY2ggc291cmNlIGlzIHdyYXBwZWQgd2l0aCBpdHMgT1dOIGRlbGF5IC0gb3VyIG93biBkaXNrIGFuZCBvdXIgb3duIHN0b3JhZ2Ugc2VydmVycyB3YW50IGEgc2hvcnQgb25lIChjcm9zcy1ub2RlIHJlZHVuZGFuY3kgc2hvdWxkIG5vdCB3YWl0IG1pbnV0ZXMpLCBhbiBleHBlbnNpdmUgZXh0ZXJuYWwgc291cmNlIGxpa2UgYmFja2JsYXplIHdhbnRzIHRoZSBmdWxsIG9uZS5cblxuLy8gUGVuZGluZyB3cml0ZXMgYXJlIGNoZWNrZWQgZm9yIHRoZWlyIGR1ZSB0aW1lIHRoaXMgb2Z0ZW4gLSBmaW5lIGVub3VnaCB0aGF0IGEgZmx1c2ggbGFuZHMgY2xvc2UgdG8gaXRzIGRlbGF5IHJhdGhlciB0aGFuIG9uZSBjb2Fyc2UgdGljayBsYXRlclxuY29uc3QgRkxVU0hfUE9MTCA9IDEwMDAgKiAyO1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRkFTVF9XUklURV9ERUxBWSA9IDEwMDAgKiA2MCAqIDU7XG4vLyBUaGUgbW9zdCBhIGZhc3Qgd3JpdGUgaXMgaGVsZCBieSBvdXIgb3duIGRpc2sgb3Igb25lIG9mIG91ciBvd24gc3RvcmFnZSBzZXJ2ZXJzLCBob3dldmVyIGxhcmdlIHRoZSBjb25maWd1cmVkIHdyaXRlRGVsYXkgaXMgLSBjcm9zcy1ub2RlIHJlZHVuZGFuY3kgYW5kIHJlYWQteW91ci13cml0ZXMgYWNyb3NzIG5vZGVzIG11c3Qgbm90IHdhaXQgbWludXRlc1xuZXhwb3J0IGNvbnN0IE1BWF9SRU1PVEVfRkFTVF9CVUZGRVIgPSAxMDAwICogNTtcblxudHlwZSBQZW5kaW5nV3JpdGUgPSB7XG4gICAgLy8gQSB6ZXJvLWxlbmd0aCBidWZmZXIgaXMgYSBwZW5kaW5nIGRlbGV0aW9uIChhbiBlbXB0eSBmaWxlIElTIGEgbWlzc2luZyBmaWxlKVxuICAgIGRhdGE6IEJ1ZmZlcjtcbiAgICB3cml0ZVRpbWU6IG51bWJlcjtcbiAgICBkdWVBdDogbnVtYmVyO1xuICAgIGNvbmZpZz86IFNldENvbmZpZztcbn07XG5cbmV4cG9ydCBjbGFzcyBBcmNoaXZlc0RlbGF5ZWQgaW1wbGVtZW50cyBJQXJjaGl2ZXMge1xuICAgIHByaXZhdGUgcGVuZGluZyA9IG5ldyBNYXA8c3RyaW5nLCBQZW5kaW5nV3JpdGU+KCk7XG4gICAgcHJpdmF0ZSBzdG9wcGVkID0geyBzdG9wOiBmYWxzZSB9O1xuICAgIC8qKiBUaGUgaW5zdGFudCBldmVyeSBwZW5kaW5nIHdyaXRlIG11c3QgYmUgb24gdGhlIHNvdXJjZSBubyBtYXR0ZXIgaXRzIGRlbGF5IC0gb3VyIG93biB2YWxpZCB3aW5kb3cncyBlbmQsIG1pbnVzIHRoZSBmbHVzaCBtYXJnaW4gKHRoZSBuZXh0IHdpbmRvdydzIHNvdXJjZSBoYXMgdG8gZmluZCB0aGUgZGF0YSBvbiBoYW5kb2ZmKS4gVGhlIHN0b3JlIGJpbmRzIGl0OyB3aXRob3V0IGl0IHRoZXJlIGlzIG5vIGRlYWRsaW5lLCBvbmx5IHRoZSBkZWxheS4gKi9cbiAgICBwcml2YXRlIGZsdXNoQmVmb3JlPzogKCkgPT4gbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHB1YmxpYyBpbm5lcjogSUFyY2hpdmVzLFxuICAgICAgICAvLyBIb3cgbG9uZyBhIHdyaXRlIGlzIGhlbGQgaW4gbWVtb3J5IGJlZm9yZSBpdCByZWFjaGVzIGlubmVyLiBQb2xpY3ksIHNvIGl0IGNhbiBjaGFuZ2Ugb24gYSBjb25maWcgZWRpdCAtIHNlZSBzZXREZWxheS5cbiAgICAgICAgcHJpdmF0ZSBkZWxheTogbnVtYmVyLFxuICAgICkge1xuICAgICAgICBydW5JbmZpbml0ZVBvbGwoRkxVU0hfUE9MTCwgKCkgPT4gdGhpcy5mbHVzaER1ZSgpLCB0aGlzLnN0b3BwZWQpO1xuICAgIH1cblxuICAgIC8qKiBDYWxsZWQgYnkgdGhlIHN0b3JlIHRoYXQgb3ducyB0aGlzIHNvdXJjZTogZmFzdCB3cml0ZXMgYXJlIG5ldmVyIGRlbGF5ZWQgcGFzdCB0aGUgc3RvcmUncyBvd24gd3JpdGUgd2luZG93LiAqL1xuICAgIHB1YmxpYyBiaW5kRmx1c2hEZWFkbGluZShmbHVzaEJlZm9yZTogKCkgPT4gbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZmx1c2hCZWZvcmUgPSBmbHVzaEJlZm9yZTtcbiAgICB9XG5cbiAgICAvKiogVGhlIGNvbmZpZyBjaGFuZ2VkIHRoZSBkZWxheSAoZmFzdCB3cml0ZXMgdHVybmVkIG9uIG9yIG9mZiwgb3IgYSBkaWZmZXJlbnQgd3JpdGVEZWxheSkuIEFueXRoaW5nIGFscmVhZHkgcGVuZGluZyBrZWVwcyB0aGUgZHVlIHRpbWUgaXQgd2FzIGFjY2VwdGVkIHdpdGggLSBzaG9ydGVuaW5nIHRoZSBkZWxheSBtdXN0IG5vdCBzdHJhbmQgaXQsIGFuZCBsZW5ndGhlbmluZyBpdCBtdXN0IG5vdCBob2xkIGl0IGxvbmdlciB0aGFuIHByb21pc2VkLiAqL1xuICAgIHB1YmxpYyBzZXREZWxheShkZWxheTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGlmIChkZWxheSA9PT0gdGhpcy5kZWxheSkgcmV0dXJuO1xuICAgICAgICBjb25zb2xlLmxvZyhgV3JpdGUgZGVsYXkgY2hhbmdlZCBmb3IgJHt0aGlzLmlubmVyLmdldERlYnVnTmFtZSgpfTogJHt0aGlzLmRlbGF5fW1zIC0+ICR7ZGVsYXl9bXMgKCR7dGhpcy5wZW5kaW5nLnNpemV9IHdyaXRlcyBwZW5kaW5nKWApO1xuICAgICAgICB0aGlzLmRlbGF5ID0gZGVsYXk7XG4gICAgICAgIGlmIChkZWxheSA8PSAwKSB7XG4gICAgICAgICAgICB2b2lkIHRoaXMuZmx1c2godHJ1ZSkuY2F0Y2goKGU6IEVycm9yKSA9PiBjb25zb2xlLmVycm9yKGBGbHVzaGluZyAke3RoaXMuaW5uZXIuZ2V0RGVidWdOYW1lKCl9IGFmdGVyIGl0cyB3cml0ZSBkZWxheSB3YXMgdHVybmVkIG9mZiBmYWlsZWQ6ICR7ZS5zdGFjayA/PyBlfWApKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXREZWJ1Z05hbWUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGAke3RoaXMuaW5uZXIuZ2V0RGVidWdOYW1lKCl9ICh3cml0ZXMgZGVsYXllZCAke3RoaXMuZGVsYXl9bXMpYDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgaGFzV3JpdGVBY2Nlc3MoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmhhc1dyaXRlQWNjZXNzKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldChmaWxlTmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGNvbmZpZz86IFNldENvbmZpZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIGlmICghZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgc2V0IHdhcyBjYWxsZWQgd2l0aCBhbiBlbXB0eSBidWZmZXIgZm9yICR7SlNPTi5zdHJpbmdpZnkoZmlsZU5hbWUpfSBvbiAke3RoaXMuZ2V0RGVidWdOYW1lKCl9OiBhbiBlbXB0eSBmaWxlIElTIGEgZGVsZXRpb24gaW4gdGhpcyBzeXN0ZW0gYW5kIHdvdWxkIHJlYWQgYmFjayBhcyBtaXNzaW5nIC0gY2FsbCBkZWwgaW5zdGVhZGApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmJ1ZmZlcihmaWxlTmFtZSwgZGF0YSwgY29uZmlnPy5sYXN0TW9kaWZpZWQsIGNvbmZpZyk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGRlbChmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBEZWxDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5idWZmZXIoZmlsZU5hbWUsIEJ1ZmZlci5hbGxvYygwKSwgY29uZmlnPy5sYXN0TW9kaWZpZWQsIGNvbmZpZyk7XG4gICAgfVxuXG4gICAgLy8gVGhlIHNoYXJlZCBlbmdpbmUgb2Ygc2V0IGFuZCBkZWwgLSBhbiBlbXB0eSBidWZmZXIgaXMgZXhhY3RseSBhIGRlbGV0aW9uIGhlcmVcbiAgICBwcml2YXRlIGFzeW5jIGJ1ZmZlcihmaWxlTmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGxhc3RNb2RpZmllZDogbnVtYmVyIHwgdW5kZWZpbmVkLCBjb25maWc/OiBTZXRDb25maWcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICBsZXQgd3JpdGVUaW1lID0gbGFzdE1vZGlmaWVkIHx8IERhdGUubm93KCk7XG4gICAgICAgIGxldCBleGlzdGluZyA9IHRoaXMucGVuZGluZy5nZXQoZmlsZU5hbWUpO1xuICAgICAgICAvLyBBbiBvbGRlciB3cml0ZSBuZXZlciBvdmVyd3JpdGVzIGEgbmV3ZXIgb25lIChzZWUgSUFyY2hpdmVzLnNldCkgLSBpbmNsdWRpbmcgYWdhaW5zdCBhIHdyaXRlIHN0aWxsIHNpdHRpbmcgaGVyZVxuICAgICAgICBpZiAoZXhpc3RpbmcgJiYgd3JpdGVUaW1lIDwgZXhpc3Rpbmcud3JpdGVUaW1lKSByZXR1cm4gZmlsZU5hbWU7XG4gICAgICAgIGxldCBkdWVBdCA9IERhdGUubm93KCkgKyB0aGlzLmRlbGF5O1xuICAgICAgICBpZiAodGhpcy5kZWxheSA8PSAwIHx8IHRoaXMuZGVhZGxpbmVQYXNzZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nLmRlbGV0ZShmaWxlTmFtZSk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLndyaXRlKGZpbGVOYW1lLCB7IGRhdGEsIHdyaXRlVGltZSwgZHVlQXQsIGNvbmZpZyB9KTtcbiAgICAgICAgICAgIHJldHVybiBmaWxlTmFtZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgd3JpdGUgaXMgYWNjZXB0ZWQgdGhlIG1vbWVudCBpdCBpcyBpbiBtZW1vcnkgLSB0aGF0IElTIHRoZSBwb2ludCBvZiBhIGZhc3Qgd3JpdGVcbiAgICAgICAgdGhpcy5wZW5kaW5nLnNldChmaWxlTmFtZSwgeyBkYXRhLCB3cml0ZVRpbWUsIGR1ZUF0LCBjb25maWcgfSk7XG4gICAgICAgIHJldHVybiBmaWxlTmFtZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGRlYWRsaW5lUGFzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgZGVhZGxpbmUgPSB0aGlzLmZsdXNoQmVmb3JlPy4oKTtcbiAgICAgICAgaWYgKGRlYWRsaW5lID09PSB1bmRlZmluZWQpIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuIERhdGUubm93KCkgPj0gZGVhZGxpbmU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB3cml0ZShmaWxlTmFtZTogc3RyaW5nLCBlbnRyeTogUGVuZGluZ1dyaXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICghZW50cnkuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuaW5uZXIuZGVsKGZpbGVOYW1lLCB7IGxhc3RNb2RpZmllZDogZW50cnkud3JpdGVUaW1lLCBub0NoZWNrczogZW50cnkuY29uZmlnPy5ub0NoZWNrcywgaW50ZXJuYWw6IGVudHJ5LmNvbmZpZz8uaW50ZXJuYWwgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5pbm5lci5zZXQoZmlsZU5hbWUsIGVudHJ5LmRhdGEsIHsgLi4uZW50cnkuY29uZmlnLCBsYXN0TW9kaWZpZWQ6IGVudHJ5LndyaXRlVGltZSB9KTtcbiAgICB9XG5cbiAgICAvKiogV3JpdGVzIGV2ZXJ5dGhpbmcgZHVlIChpdHMgZGVsYXkgZWxhcHNlZCwgb3IgdGhlIHN0b3JlJ3Mgd2luZG93IGRlYWRsaW5lIHJlYWNoZWQpLiBmb3JjZSB3cml0ZXMgZXZlcnl0aGluZywgaG93ZXZlciByZWNlbnQgLSBzaHV0ZG93biBhbmQgd2luZG93IGhhbmRvZmZzIGNhbm5vdCBsZWF2ZSB3cml0ZXMgaW4gbWVtb3J5LiAqL1xuICAgIHB1YmxpYyBhc3luYyBmbHVzaChmb3JjZT86IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgIGxldCBkZWFkbGluZVJlYWNoZWQgPSBmb3JjZSB8fCB0aGlzLmRlYWRsaW5lUGFzc2VkKCk7XG4gICAgICAgIGZvciAobGV0IFtmaWxlTmFtZSwgZW50cnldIG9mIFsuLi50aGlzLnBlbmRpbmddKSB7XG4gICAgICAgICAgICBpZiAoIWRlYWRsaW5lUmVhY2hlZCAmJiBlbnRyeS5kdWVBdCA+IG5vdykgY29udGludWU7XG4gICAgICAgICAgICAvLyBPbmx5IGRyb3AgaXQgaWYgaXQgd2Fzbid0IG92ZXJ3cml0dGVuIHdoaWxlIHdlIHdlcmUgd3JpdGluZ1xuICAgICAgICAgICAgYXdhaXQgdGhpcy53cml0ZShmaWxlTmFtZSwgZW50cnkpO1xuICAgICAgICAgICAgaWYgKHRoaXMucGVuZGluZy5nZXQoZmlsZU5hbWUpID09PSBlbnRyeSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZy5kZWxldGUoZmlsZU5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBmbHVzaER1ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLnBlbmRpbmcuc2l6ZSkgcmV0dXJuO1xuICAgICAgICBhd2FpdCB0aGlzLmZsdXNoKCk7XG4gICAgfVxuXG4gICAgLyoqIFN0b3BzIHRoZSBmbHVzaCBsb29wLCBhZnRlciB3cml0aW5nIGV2ZXJ5dGhpbmcgc3RpbGwgcGVuZGluZy4gKi9cbiAgICBwdWJsaWMgYXN5bmMgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5zdG9wcGVkLnN0b3AgPSB0cnVlO1xuICAgICAgICBhd2FpdCB0aGlzLmZsdXNoKHRydWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXQoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0MihmaWxlTmFtZSwgY29uZmlnKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCAmJiByZXN1bHQuZGF0YSB8fCB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGdldDIoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTx7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlcjsgdXJsPzogc3RyaW5nIH0gfCB7IGRhdGE/OiB1bmRlZmluZWQ7IHdyaXRlVGltZT86IHVuZGVmaW5lZDsgc2l6ZT86IHVuZGVmaW5lZDsgdXJsOiBzdHJpbmcgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBsZXQgZW50cnkgPSB0aGlzLnBlbmRpbmcuZ2V0KGZpbGVOYW1lKTtcbiAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgICAvLyBBbiBlbXB0eSBmaWxlIElTIGEgbWlzc2luZyBmaWxlICh0b21ic3RvbmUpXG4gICAgICAgICAgICBpZiAoIWVudHJ5LmRhdGEubGVuZ3RoICYmICFjb25maWc/LmluY2x1ZGVUb21ic3RvbmVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgbGV0IGRhdGEgPSBlbnRyeS5kYXRhO1xuICAgICAgICAgICAgbGV0IHNpemUgPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCByYW5nZSA9IGNvbmZpZz8ucmFuZ2U7XG4gICAgICAgICAgICBpZiAocmFuZ2UpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zdWJhcnJheShNYXRoLm1pbihyYW5nZS5zdGFydCwgZGF0YS5sZW5ndGgpLCBNYXRoLm1pbihyYW5nZS5lbmQsIGRhdGEubGVuZ3RoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geyBkYXRhLCB3cml0ZVRpbWU6IGVudHJ5LndyaXRlVGltZSwgc2l6ZSB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmdldDIoZmlsZU5hbWUsIGNvbmZpZyk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGdldEluZm8oZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0SW5mb0NvbmZpZyk6IFByb21pc2U8eyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyOyB1cmw/OiBzdHJpbmcgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBsZXQgZW50cnkgPSB0aGlzLnBlbmRpbmcuZ2V0KGZpbGVOYW1lKTtcbiAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgICBpZiAoIWVudHJ5LmRhdGEubGVuZ3RoICYmICFjb25maWc/LmluY2x1ZGVUb21ic3RvbmVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmV0dXJuIHsgd3JpdGVUaW1lOiBlbnRyeS53cml0ZVRpbWUsIHNpemU6IGVudHJ5LmRhdGEubGVuZ3RoIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuaW5uZXIuZ2V0SW5mbyhmaWxlTmFtZSwgY29uZmlnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZmluZChwcmVmaXg6IHN0cmluZywgY29uZmlnPzogRmluZENvbmZpZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLmZpbmRJbmZvKHByZWZpeCwgY29uZmlnKSkubWFwKHggPT4geC5wYXRoKTtcbiAgICB9XG5cbiAgICAvKiogUGVuZGluZyB3cml0ZXMgYXJlIHBhcnQgb2YgdGhlIGxpc3Rpbmc6IGEgc2NhbiBvZiB0aGlzIHNvdXJjZSB0aGF0IGNvdWxkbid0IHNlZSB0aGVtIHdvdWxkIGNvbmNsdWRlIHRoZSBmaWxlcyBoYWQgdmFuaXNoZWQgZnJvbSBpdCwgYW5kIGRyb3AgdGhlbSBmcm9tIHRoZSBzY2FubmVyJ3MgaW5kZXguICovXG4gICAgcHVibGljIGFzeW5jIGZpbmRJbmZvKHByZWZpeDogc3RyaW5nLCBjb25maWc/OiBGaW5kQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT4ge1xuICAgICAgICBsZXQgaW5mb3MgPSBuZXcgTWFwPHN0cmluZywgQXJjaGl2ZUZpbGVJbmZvPigpO1xuICAgICAgICBmb3IgKGxldCBmaWxlIG9mIGF3YWl0IHRoaXMuaW5uZXIuZmluZEluZm8ocHJlZml4LCBjb25maWcpKSB7XG4gICAgICAgICAgICBpbmZvcy5zZXQoZmlsZS5wYXRoLCBmaWxlKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBbZmlsZU5hbWUsIGVudHJ5XSBvZiB0aGlzLnBlbmRpbmcpIHtcbiAgICAgICAgICAgIGlmICghZmlsZU5hbWUuc3RhcnRzV2l0aChwcmVmaXgpKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmICghZW50cnkuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBpbmZvcy5kZWxldGUoZmlsZU5hbWUpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5mb3Muc2V0KGZpbGVOYW1lLCB7IHBhdGg6IGZpbGVOYW1lLCBjcmVhdGVUaW1lOiBlbnRyeS53cml0ZVRpbWUsIHNpemU6IGVudHJ5LmRhdGEubGVuZ3RoIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbLi4uaW5mb3MudmFsdWVzKCldO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRDaGFuZ2VzQWZ0ZXIyKGNvbmZpZzogQ2hhbmdlc0FmdGVyQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT4ge1xuICAgICAgICBsZXQgY2hhbmdlcyA9IGF3YWl0IHRoaXMuaW5uZXIuZ2V0Q2hhbmdlc0FmdGVyMihjb25maWcpO1xuICAgICAgICBsZXQgc2VlbiA9IG5ldyBTZXQoY2hhbmdlcy5tYXAoeCA9PiB4LnBhdGgpKTtcbiAgICAgICAgZm9yIChsZXQgW2ZpbGVOYW1lLCBlbnRyeV0gb2YgdGhpcy5wZW5kaW5nKSB7XG4gICAgICAgICAgICBpZiAoZW50cnkud3JpdGVUaW1lIDw9IGNvbmZpZy50aW1lKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmIChzZWVuLmhhcyhmaWxlTmFtZSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgY2hhbmdlcy5wdXNoKHsgcGF0aDogZmlsZU5hbWUsIGNyZWF0ZVRpbWU6IGVudHJ5LndyaXRlVGltZSwgc2l6ZTogZW50cnkuZGF0YS5sZW5ndGggfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNoYW5nZXM7XG4gICAgfVxuXG4gICAgLyoqIE5ldmVyIGJ1ZmZlcmVkOiBhIGZpbGUgdG9vIGxhcmdlIHRvIGhvbGQgaW4gbWVtb3J5IGlzIGV4YWN0bHkgdGhlIGZpbGUgdGhhdCBtdXN0IG5vdCBzaXQgaW4gbWVtb3J5LiBBbnkgcGVuZGluZyB3cml0ZSBmb3IgdGhlIHBhdGggZ29lcyBmaXJzdCwgc28gdGhlIHR3byBsYW5kIGluIG9yZGVyLiAqL1xuICAgIHB1YmxpYyBhc3luYyBzZXRMYXJnZUZpbGUoY29uZmlnOiBTZXRMYXJnZUZpbGVDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbGV0IGVudHJ5ID0gdGhpcy5wZW5kaW5nLmdldChjb25maWcucGF0aCk7XG4gICAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nLmRlbGV0ZShjb25maWcucGF0aCk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLndyaXRlKGNvbmZpZy5wYXRoLCBlbnRyeSk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5pbm5lci5zZXRMYXJnZUZpbGUoY29uZmlnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0VVJMKHBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmdldFVSTChwYXRoKTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGdldENvbmZpZygpOiBQcm9taXNlPEFyY2hpdmVzQ29uZmlnPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmdldENvbmZpZygpO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZ2V0U3luY1N0YXR1cygpOiBQcm9taXNlPEFyY2hpdmVzU3luY1N0YXR1cz4ge1xuICAgICAgICBpZiAoIXRoaXMuaW5uZXIuZ2V0U3luY1N0YXR1cykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMuaW5uZXIuZ2V0RGVidWdOYW1lKCl9IGRvZXMgbm90IHN1cHBvcnQgZ2V0U3luY1N0YXR1c2ApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmdldFN5bmNTdGF0dXMoKTtcbiAgICB9XG59XG5cbi8qKiBIb3cgbG9uZyBhIHNvdXJjZSBtYXkgaG9sZCBhIHdyaXRlLiBPdXIgb3duIGRpc2sgYW5kIG91ciBvd24gc3RvcmFnZSBzZXJ2ZXJzIHRha2UgdGhlIFNIT1JUIGRlbGF5IGhvd2V2ZXIgbGFyZ2Ugd3JpdGVEZWxheSBpczogdGhleSBhcmUgd2hhdCBjcm9zcy1ub2RlIHJlYWRzIGFuZCByZWR1bmRhbmN5IGRlcGVuZCBvbiwgYW5kIG1ha2luZyB0aG9zZSB3YWl0IG1pbnV0ZXMgaXMgbm90IGEgdHJhZGUgYW55b25lIGFza2VkIGZvci4gRXZlcnl0aGluZyBlbHNlIChiYWNrYmxhemUpIHRha2VzIHRoZSBmdWxsIGRlbGF5LCB3aGljaCBpcyB3aGVyZSBjb2FsZXNjaW5nIGFjdHVhbGx5IHNhdmVzIG1vbmV5LiBOb3QgZmFzdCAtPiBubyBkZWxheSBhdCBhbGwsIGFuZCBubyB3cmFwcGVyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNvdXJjZVdyaXRlRGVsYXkoY29uZmlnOiB7IHNvdXJjZUNvbmZpZz86IFNvdXJjZUNvbmZpZzsgZmFzdD86IGJvb2xlYW47IHdyaXRlRGVsYXk/OiBudW1iZXIgfSk6IG51bWJlciB7XG4gICAgaWYgKCFjb25maWcuZmFzdCkgcmV0dXJuIDA7XG4gICAgbGV0IGRlbGF5ID0gY29uZmlnLndyaXRlRGVsYXk7XG4gICAgLy8gQSB3cml0ZURlbGF5IG9mIHplcm8gaXMgYSByZWFsIGNob2ljZSAobm8gZGVsYXkgYXQgYWxsKSwgc28gb25seSBhbiBvbWl0dGVkIGRlbGF5IGdldHMgdGhlIGRlZmF1bHRcbiAgICBpZiAoZGVsYXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBkZWxheSA9IERFRkFVTFRfRkFTVF9XUklURV9ERUxBWTtcbiAgICB9XG4gICAgaWYgKCFjb25maWcuc291cmNlQ29uZmlnIHx8IGNvbmZpZy5zb3VyY2VDb25maWcudHlwZSA9PT0gXCJyZW1vdGVcIikge1xuICAgICAgICByZXR1cm4gTWF0aC5taW4oZGVsYXksIE1BWF9SRU1PVEVfRkFTVF9CVUZGRVIpO1xuICAgIH1cbiAgICByZXR1cm4gZGVsYXk7XG59XG5cbi8qKiBUaGUgZGVsYXllZCB3cmFwcGVyIGFyb3VuZCBhIHNvdXJjZSwgd2hlbiBpdCBoYXMgb25lIC0gaG93IHRoZSBzdG9yZSByZWFjaGVzIHBhc3QgdGhlIGRlbGF5ICh0byB0aGUgcmVhbCBkaXNrIGZvciBsYXJnZSB1cGxvYWRzKSBhbmQgZmx1c2hlcyBvbiBzaHV0ZG93bi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc0RlbGF5ZWQoc291cmNlOiBJQXJjaGl2ZXMpOiBBcmNoaXZlc0RlbGF5ZWQgfCB1bmRlZmluZWQge1xuICAgIGlmIChzb3VyY2UgaW5zdGFuY2VvZiBBcmNoaXZlc0RlbGF5ZWQpIHJldHVybiBzb3VyY2U7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqIFRoZSBzb3VyY2UgaXRzZWxmLCBwYXN0IGFueSB3cml0ZSBkZWxheS4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bndyYXBEZWxheWVkKHNvdXJjZTogSUFyY2hpdmVzKTogSUFyY2hpdmVzIHtcbiAgICBpZiAoc291cmNlIGluc3RhbmNlb2YgQXJjaGl2ZXNEZWxheWVkKSByZXR1cm4gc291cmNlLmlubmVyO1xuICAgIHJldHVybiBzb3VyY2U7XG59XG4iXX0=
220
- /* _JS_SOURCE_HASH = "599bad59578df7b19474360b45242fa25254e4be30a3d523c48fe50478cdd76b"; */
219
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXJjaGl2ZXNEZWxheWVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiQXJjaGl2ZXNEZWxheWVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJEQUErRDtBQU0vRCw4bEJBQThsQjtBQUU5bEIsaUpBQWlKO0FBQ2pKLE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7QUFDZixRQUFBLHdCQUF3QixHQUFHLElBQUksR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ3RELDhNQUE4TTtBQUNqTSxRQUFBLHNCQUFzQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7QUFVL0MsTUFBYSxlQUFlO0lBTXhCLFlBQ1csS0FBZ0I7SUFDdkIsd0hBQXdIO0lBQ2hILEtBQWE7UUFGZCxVQUFLLEdBQUwsS0FBSyxDQUFXO1FBRWYsVUFBSyxHQUFMLEtBQUssQ0FBUTtRQVJqQixZQUFPLEdBQUcsSUFBSSxHQUFHLEVBQXdCLENBQUM7UUFDMUMsWUFBTyxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO1FBUzlCLElBQUEsMEJBQWUsRUFBQyxVQUFVLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRUQsa0hBQWtIO0lBQzNHLGlCQUFpQixDQUFDLFdBQXlCO1FBQzlDLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQ25DLENBQUM7SUFFRCxvUUFBb1E7SUFDN1AsUUFBUSxDQUFDLEtBQWE7UUFDekIsSUFBSSxLQUFLLEtBQUssSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPO1FBQ2pDLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLEtBQUssSUFBSSxDQUFDLEtBQUssU0FBUyxLQUFLLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLGtCQUFrQixDQUFD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O0FBQ2hLLFNBQWdCLFNBQVMsQ0FBQyxNQUFpQjtJQUN2QyxJQUFJLE1BQU0sWUFBWSxlQUFlO1FBQUUsT0FBTyxNQUFNLENBQUM7SUFDckQsT0FBTyxTQUFTLENBQUM7QUFDckIsQ0FBQztBQUhELDhCQUdDO0FBRUQsK0NBQStDO0FBQy9DLFNBQWdCLGFBQWEsQ0FBQyxNQUFpQjtJQUMzQyxJQUFJLE1BQU0sWUFBWSxlQUFlO1FBQUUsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDO0lBQzNELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUM7QUFIRCxzQ0FHQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJ1bkluZmluaXRlUG9sbCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2JhdGNoaW5nXCI7XG5pbXBvcnQge1xuICAgIElBcmNoaXZlcywgQXJjaGl2ZUZpbGVJbmZvLCBBcmNoaXZlc0NvbmZpZywgQXJjaGl2ZXNTeW5jU3RhdHVzLCBDaGFuZ2VzQWZ0ZXJDb25maWcsIERlbENvbmZpZyxcbiAgICBGaW5kQ29uZmlnLCBHZXRDb25maWcsIEdldEluZm9Db25maWcsIFNldENvbmZpZywgU2V0TGFyZ2VGaWxlQ29uZmlnLCBTb3VyY2VDb25maWcsXG59IGZyb20gXCIuLi9JQXJjaGl2ZXNcIjtcblxuLy8gRmFzdCB3cml0ZXMgKHNlZSBzcGVjLm1kLCBcImZhc3Qgd3JpdGVzXCIpLCBhcyBhIHdyYXBwZXIgYXJvdW5kIE9ORSBzb3VyY2UgaW5zdGVhZCBvZiBhIGJ1ZmZlciBzbWVhcmVkIHRocm91Z2ggdGhlIHN0b3JlOiBhIHdyaXRlIHJldHVybnMgYXMgc29vbiBhcyBpdCBpcyBpbiBtZW1vcnksIGFuZCByZXBlYXRlZCB3cml0ZXMgdG8gdGhlIHNhbWUgcGF0aCBjb2xsYXBzZSBpbnRvIGEgc2luZ2xlIHdyaXRlIHRvIHRoZSB3cmFwcGVkIHNvdXJjZS4gRXZlcnkgcmVhZCBnb2VzIHRocm91Z2ggdGhlIHBlbmRpbmcgd3JpdGVzIGZpcnN0LCBzbyBhIGRlbGF5ZWQgd3JpdGUgaXMgc3RpbGwgcmVhZC15b3VyLXdyaXRlcyBmb3IgYW55b25lIHJlYWRpbmcgdGhyb3VnaCB0aGlzIHdyYXBwZXIuIEVhY2ggc291cmNlIGlzIHdyYXBwZWQgd2l0aCBpdHMgT1dOIGRlbGF5IC0gb3VyIG93biBkaXNrIGFuZCBvdXIgb3duIHN0b3JhZ2Ugc2VydmVycyB3YW50IGEgc2hvcnQgb25lIChjcm9zcy1ub2RlIHJlZHVuZGFuY3kgc2hvdWxkIG5vdCB3YWl0IG1pbnV0ZXMpLCBhbiBleHBlbnNpdmUgZXh0ZXJuYWwgc291cmNlIGxpa2UgYmFja2JsYXplIHdhbnRzIHRoZSBmdWxsIG9uZS5cblxuLy8gUGVuZGluZyB3cml0ZXMgYXJlIGNoZWNrZWQgZm9yIHRoZWlyIGR1ZSB0aW1lIHRoaXMgb2Z0ZW4gLSBmaW5lIGVub3VnaCB0aGF0IGEgZmx1c2ggbGFuZHMgY2xvc2UgdG8gaXRzIGRlbGF5IHJhdGhlciB0aGFuIG9uZSBjb2Fyc2UgdGljayBsYXRlclxuY29uc3QgRkxVU0hfUE9MTCA9IDEwMDAgKiAyO1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRkFTVF9XUklURV9ERUxBWSA9IDEwMDAgKiA2MCAqIDU7XG4vLyBUaGUgbW9zdCBhIGZhc3Qgd3JpdGUgaXMgaGVsZCBieSBvdXIgb3duIGRpc2sgb3Igb25lIG9mIG91ciBvd24gc3RvcmFnZSBzZXJ2ZXJzLCBob3dldmVyIGxhcmdlIHRoZSBjb25maWd1cmVkIHdyaXRlRGVsYXkgaXMgLSBjcm9zcy1ub2RlIHJlZHVuZGFuY3kgYW5kIHJlYWQteW91ci13cml0ZXMgYWNyb3NzIG5vZGVzIG11c3Qgbm90IHdhaXQgbWludXRlc1xuZXhwb3J0IGNvbnN0IE1BWF9SRU1PVEVfRkFTVF9CVUZGRVIgPSAxMDAwICogNTtcblxudHlwZSBQZW5kaW5nV3JpdGUgPSB7XG4gICAgLy8gQSB6ZXJvLWxlbmd0aCBidWZmZXIgaXMgYSBwZW5kaW5nIGRlbGV0aW9uIChhbiBlbXB0eSBmaWxlIElTIGEgbWlzc2luZyBmaWxlKVxuICAgIGRhdGE6IEJ1ZmZlcjtcbiAgICB3cml0ZVRpbWU6IG51bWJlcjtcbiAgICBkdWVBdDogbnVtYmVyO1xuICAgIGNvbmZpZz86IFNldENvbmZpZztcbn07XG5cbmV4cG9ydCBjbGFzcyBBcmNoaXZlc0RlbGF5ZWQgaW1wbGVtZW50cyBJQXJjaGl2ZXMge1xuICAgIHByaXZhdGUgcGVuZGluZyA9IG5ldyBNYXA8c3RyaW5nLCBQZW5kaW5nV3JpdGU+KCk7XG4gICAgcHJpdmF0ZSBzdG9wcGVkID0geyBzdG9wOiBmYWxzZSB9O1xuICAgIC8qKiBUaGUgaW5zdGFudCBldmVyeSBwZW5kaW5nIHdyaXRlIG11c3QgYmUgb24gdGhlIHNvdXJjZSBubyBtYXR0ZXIgaXRzIGRlbGF5IC0gb3VyIG93biB2YWxpZCB3aW5kb3cncyBlbmQsIG1pbnVzIHRoZSBmbHVzaCBtYXJnaW4gKHRoZSBuZXh0IHdpbmRvdydzIHNvdXJjZSBoYXMgdG8gZmluZCB0aGUgZGF0YSBvbiBoYW5kb2ZmKS4gVGhlIHN0b3JlIGJpbmRzIGl0OyB3aXRob3V0IGl0IHRoZXJlIGlzIG5vIGRlYWRsaW5lLCBvbmx5IHRoZSBkZWxheS4gKi9cbiAgICBwcml2YXRlIGZsdXNoQmVmb3JlPzogKCkgPT4gbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHB1YmxpYyBpbm5lcjogSUFyY2hpdmVzLFxuICAgICAgICAvLyBIb3cgbG9uZyBhIHdyaXRlIGlzIGhlbGQgaW4gbWVtb3J5IGJlZm9yZSBpdCByZWFjaGVzIGlubmVyLiBQb2xpY3ksIHNvIGl0IGNhbiBjaGFuZ2Ugb24gYSBjb25maWcgZWRpdCAtIHNlZSBzZXREZWxheS5cbiAgICAgICAgcHJpdmF0ZSBkZWxheTogbnVtYmVyLFxuICAgICkge1xuICAgICAgICBydW5JbmZpbml0ZVBvbGwoRkxVU0hfUE9MTCwgKCkgPT4gdGhpcy5mbHVzaER1ZSgpLCB0aGlzLnN0b3BwZWQpO1xuICAgIH1cblxuICAgIC8qKiBDYWxsZWQgYnkgdGhlIHN0b3JlIHRoYXQgb3ducyB0aGlzIHNvdXJjZTogZmFzdCB3cml0ZXMgYXJlIG5ldmVyIGRlbGF5ZWQgcGFzdCB0aGUgc3RvcmUncyBvd24gd3JpdGUgd2luZG93LiAqL1xuICAgIHB1YmxpYyBiaW5kRmx1c2hEZWFkbGluZShmbHVzaEJlZm9yZTogKCkgPT4gbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZmx1c2hCZWZvcmUgPSBmbHVzaEJlZm9yZTtcbiAgICB9XG5cbiAgICAvKiogVGhlIGNvbmZpZyBjaGFuZ2VkIHRoZSBkZWxheSAoZmFzdCB3cml0ZXMgdHVybmVkIG9uIG9yIG9mZiwgb3IgYSBkaWZmZXJlbnQgd3JpdGVEZWxheSkuIEFueXRoaW5nIGFscmVhZHkgcGVuZGluZyBrZWVwcyB0aGUgZHVlIHRpbWUgaXQgd2FzIGFjY2VwdGVkIHdpdGggLSBzaG9ydGVuaW5nIHRoZSBkZWxheSBtdXN0IG5vdCBzdHJhbmQgaXQsIGFuZCBsZW5ndGhlbmluZyBpdCBtdXN0IG5vdCBob2xkIGl0IGxvbmdlciB0aGFuIHByb21pc2VkLiAqL1xuICAgIHB1YmxpYyBzZXREZWxheShkZWxheTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGlmIChkZWxheSA9PT0gdGhpcy5kZWxheSkgcmV0dXJuO1xuICAgICAgICBjb25zb2xlLmxvZyhgV3JpdGUgZGVsYXkgY2hhbmdlZCBmb3IgJHt0aGlzLmlubmVyLmdldERlYnVnTmFtZSgpfTogJHt0aGlzLmRlbGF5fW1zIC0+ICR7ZGVsYXl9bXMgKCR7dGhpcy5wZW5kaW5nLnNpemV9IHdyaXRlcyBwZW5kaW5nKWApO1xuICAgICAgICB0aGlzLmRlbGF5ID0gZGVsYXk7XG4gICAgICAgIGlmIChkZWxheSA8PSAwKSB7XG4gICAgICAgICAgICB2b2lkIHRoaXMuZmx1c2godHJ1ZSkuY2F0Y2goKGU6IEVycm9yKSA9PiBjb25zb2xlLmVycm9yKGBGbHVzaGluZyAke3RoaXMuaW5uZXIuZ2V0RGVidWdOYW1lKCl9IGFmdGVyIGl0cyB3cml0ZSBkZWxheSB3YXMgdHVybmVkIG9mZiBmYWlsZWQ6ICR7ZS5zdGFjayA/PyBlfWApKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXREZWJ1Z05hbWUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGAke3RoaXMuaW5uZXIuZ2V0RGVidWdOYW1lKCl9ICh3cml0ZXMgZGVsYXllZCAke3RoaXMuZGVsYXl9bXMpYDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgaGFzV3JpdGVBY2Nlc3MoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmhhc1dyaXRlQWNjZXNzKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldChmaWxlTmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGNvbmZpZz86IFNldENvbmZpZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIGlmICghZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRW1wdHkgd3JpdGUgcmVmdXNlZDogc2V0IHdhcyBjYWxsZWQgd2l0aCBhbiBlbXB0eSBidWZmZXIgZm9yICR7SlNPTi5zdHJpbmdpZnkoZmlsZU5hbWUpfSBvbiAke3RoaXMuZ2V0RGVidWdOYW1lKCl9OiBhbiBlbXB0eSBmaWxlIElTIGEgZGVsZXRpb24gaW4gdGhpcyBzeXN0ZW0gYW5kIHdvdWxkIHJlYWQgYmFjayBhcyBtaXNzaW5nIC0gY2FsbCBkZWwgaW5zdGVhZGApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmJ1ZmZlcihmaWxlTmFtZSwgZGF0YSwgY29uZmlnPy5sYXN0TW9kaWZpZWQsIGNvbmZpZyk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGRlbChmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBEZWxDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5idWZmZXIoZmlsZU5hbWUsIEJ1ZmZlci5hbGxvYygwKSwgY29uZmlnPy5sYXN0TW9kaWZpZWQsIGNvbmZpZyk7XG4gICAgfVxuXG4gICAgLy8gVGhlIHNoYXJlZCBlbmdpbmUgb2Ygc2V0IGFuZCBkZWwgLSBhbiBlbXB0eSBidWZmZXIgaXMgZXhhY3RseSBhIGRlbGV0aW9uIGhlcmVcbiAgICBwcml2YXRlIGFzeW5jIGJ1ZmZlcihmaWxlTmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGxhc3RNb2RpZmllZDogbnVtYmVyIHwgdW5kZWZpbmVkLCBjb25maWc/OiBTZXRDb25maWcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICBsZXQgd3JpdGVUaW1lID0gTWF0aC5mbG9vcihsYXN0TW9kaWZpZWQgfHwgRGF0ZS5ub3coKSk7XG4gICAgICAgIGxldCBleGlzdGluZyA9IHRoaXMucGVuZGluZy5nZXQoZmlsZU5hbWUpO1xuICAgICAgICAvLyBBbiBvbGRlciB3cml0ZSBuZXZlciBvdmVyd3JpdGVzIGEgbmV3ZXIgb25lIChzZWUgSUFyY2hpdmVzLnNldCkgLSBpbmNsdWRpbmcgYWdhaW5zdCBhIHdyaXRlIHN0aWxsIHNpdHRpbmcgaGVyZVxuICAgICAgICBpZiAoZXhpc3RpbmcgJiYgd3JpdGVUaW1lIDwgZXhpc3Rpbmcud3JpdGVUaW1lKSByZXR1cm4gZmlsZU5hbWU7XG4gICAgICAgIGxldCBkdWVBdCA9IERhdGUubm93KCkgKyB0aGlzLmRlbGF5O1xuICAgICAgICBpZiAodGhpcy5kZWxheSA8PSAwIHx8IHRoaXMuZGVhZGxpbmVQYXNzZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nLmRlbGV0ZShmaWxlTmFtZSk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLndyaXRlKGZpbGVOYW1lLCB7IGRhdGEsIHdyaXRlVGltZSwgZHVlQXQsIGNvbmZpZyB9KTtcbiAgICAgICAgICAgIHJldHVybiBmaWxlTmFtZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgd3JpdGUgaXMgYWNjZXB0ZWQgdGhlIG1vbWVudCBpdCBpcyBpbiBtZW1vcnkgLSB0aGF0IElTIHRoZSBwb2ludCBvZiBhIGZhc3Qgd3JpdGVcbiAgICAgICAgdGhpcy5wZW5kaW5nLnNldChmaWxlTmFtZSwgeyBkYXRhLCB3cml0ZVRpbWUsIGR1ZUF0LCBjb25maWcgfSk7XG4gICAgICAgIHJldHVybiBmaWxlTmFtZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGRlYWRsaW5lUGFzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgZGVhZGxpbmUgPSB0aGlzLmZsdXNoQmVmb3JlPy4oKTtcbiAgICAgICAgaWYgKGRlYWRsaW5lID09PSB1bmRlZmluZWQpIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuIERhdGUubm93KCkgPj0gZGVhZGxpbmU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB3cml0ZShmaWxlTmFtZTogc3RyaW5nLCBlbnRyeTogUGVuZGluZ1dyaXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICghZW50cnkuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuaW5uZXIuZGVsKGZpbGVOYW1lLCB7IGxhc3RNb2RpZmllZDogZW50cnkud3JpdGVUaW1lLCBub0NoZWNrczogZW50cnkuY29uZmlnPy5ub0NoZWNrcywgaW50ZXJuYWw6IGVudHJ5LmNvbmZpZz8uaW50ZXJuYWwgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5pbm5lci5zZXQoZmlsZU5hbWUsIGVudHJ5LmRhdGEsIHsgLi4uZW50cnkuY29uZmlnLCBsYXN0TW9kaWZpZWQ6IGVudHJ5LndyaXRlVGltZSB9KTtcbiAgICB9XG5cbiAgICAvKiogV3JpdGVzIGV2ZXJ5dGhpbmcgZHVlIChpdHMgZGVsYXkgZWxhcHNlZCwgb3IgdGhlIHN0b3JlJ3Mgd2luZG93IGRlYWRsaW5lIHJlYWNoZWQpLiBmb3JjZSB3cml0ZXMgZXZlcnl0aGluZywgaG93ZXZlciByZWNlbnQgLSBzaHV0ZG93biBhbmQgd2luZG93IGhhbmRvZmZzIGNhbm5vdCBsZWF2ZSB3cml0ZXMgaW4gbWVtb3J5LiAqL1xuICAgIHB1YmxpYyBhc3luYyBmbHVzaChmb3JjZT86IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgIGxldCBkZWFkbGluZVJlYWNoZWQgPSBmb3JjZSB8fCB0aGlzLmRlYWRsaW5lUGFzc2VkKCk7XG4gICAgICAgIGZvciAobGV0IFtmaWxlTmFtZSwgZW50cnldIG9mIFsuLi50aGlzLnBlbmRpbmddKSB7XG4gICAgICAgICAgICBpZiAoIWRlYWRsaW5lUmVhY2hlZCAmJiBlbnRyeS5kdWVBdCA+IG5vdykgY29udGludWU7XG4gICAgICAgICAgICAvLyBPbmx5IGRyb3AgaXQgaWYgaXQgd2Fzbid0IG92ZXJ3cml0dGVuIHdoaWxlIHdlIHdlcmUgd3JpdGluZ1xuICAgICAgICAgICAgYXdhaXQgdGhpcy53cml0ZShmaWxlTmFtZSwgZW50cnkpO1xuICAgICAgICAgICAgaWYgKHRoaXMucGVuZGluZy5nZXQoZmlsZU5hbWUpID09PSBlbnRyeSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZy5kZWxldGUoZmlsZU5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBmbHVzaER1ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLnBlbmRpbmcuc2l6ZSkgcmV0dXJuO1xuICAgICAgICBhd2FpdCB0aGlzLmZsdXNoKCk7XG4gICAgfVxuXG4gICAgLyoqIFN0b3BzIHRoZSBmbHVzaCBsb29wLCBhZnRlciB3cml0aW5nIGV2ZXJ5dGhpbmcgc3RpbGwgcGVuZGluZy4gKi9cbiAgICBwdWJsaWMgYXN5bmMgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5zdG9wcGVkLnN0b3AgPSB0cnVlO1xuICAgICAgICBhd2FpdCB0aGlzLmZsdXNoKHRydWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXQoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0MihmaWxlTmFtZSwgY29uZmlnKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCAmJiByZXN1bHQuZGF0YSB8fCB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGdldDIoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTx7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlcjsgdXJsPzogc3RyaW5nIH0gfCB7IGRhdGE/OiB1bmRlZmluZWQ7IHdyaXRlVGltZT86IHVuZGVmaW5lZDsgc2l6ZT86IHVuZGVmaW5lZDsgdXJsOiBzdHJpbmcgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBsZXQgZW50cnkgPSB0aGlzLnBlbmRpbmcuZ2V0KGZpbGVOYW1lKTtcbiAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgICAvLyBBbiBlbXB0eSBmaWxlIElTIGEgbWlzc2luZyBmaWxlICh0b21ic3RvbmUpXG4gICAgICAgICAgICBpZiAoIWVudHJ5LmRhdGEubGVuZ3RoICYmICFjb25maWc/LmluY2x1ZGVUb21ic3RvbmVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgbGV0IGRhdGEgPSBlbnRyeS5kYXRhO1xuICAgICAgICAgICAgbGV0IHNpemUgPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCByYW5nZSA9IGNvbmZpZz8ucmFuZ2U7XG4gICAgICAgICAgICBpZiAocmFuZ2UpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5zdWJhcnJheShNYXRoLm1pbihyYW5nZS5zdGFydCwgZGF0YS5sZW5ndGgpLCBNYXRoLm1pbihyYW5nZS5lbmQsIGRhdGEubGVuZ3RoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geyBkYXRhLCB3cml0ZVRpbWU6IGVudHJ5LndyaXRlVGltZSwgc2l6ZSB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmdldDIoZmlsZU5hbWUsIGNvbmZpZyk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGdldEluZm8oZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0SW5mb0NvbmZpZyk6IFByb21pc2U8eyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyOyB1cmw/OiBzdHJpbmcgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBsZXQgZW50cnkgPSB0aGlzLnBlbmRpbmcuZ2V0KGZpbGVOYW1lKTtcbiAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgICBpZiAoIWVudHJ5LmRhdGEubGVuZ3RoICYmICFjb25maWc/LmluY2x1ZGVUb21ic3RvbmVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmV0dXJuIHsgd3JpdGVUaW1lOiBlbnRyeS53cml0ZVRpbWUsIHNpemU6IGVudHJ5LmRhdGEubGVuZ3RoIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuaW5uZXIuZ2V0SW5mbyhmaWxlTmFtZSwgY29uZmlnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZmluZChwcmVmaXg6IHN0cmluZywgY29uZmlnPzogRmluZENvbmZpZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLmZpbmRJbmZvKHByZWZpeCwgY29uZmlnKSkubWFwKHggPT4geC5wYXRoKTtcbiAgICB9XG5cbiAgICAvKiogUGVuZGluZyB3cml0ZXMgYXJlIHBhcnQgb2YgdGhlIGxpc3Rpbmc6IGEgc2NhbiBvZiB0aGlzIHNvdXJjZSB0aGF0IGNvdWxkbid0IHNlZSB0aGVtIHdvdWxkIGNvbmNsdWRlIHRoZSBmaWxlcyBoYWQgdmFuaXNoZWQgZnJvbSBpdCwgYW5kIGRyb3AgdGhlbSBmcm9tIHRoZSBzY2FubmVyJ3MgaW5kZXguICovXG4gICAgcHVibGljIGFzeW5jIGZpbmRJbmZvKHByZWZpeDogc3RyaW5nLCBjb25maWc/OiBGaW5kQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT4ge1xuICAgICAgICBsZXQgaW5mb3MgPSBuZXcgTWFwPHN0cmluZywgQXJjaGl2ZUZpbGVJbmZvPigpO1xuICAgICAgICBmb3IgKGxldCBmaWxlIG9mIGF3YWl0IHRoaXMuaW5uZXIuZmluZEluZm8ocHJlZml4LCBjb25maWcpKSB7XG4gICAgICAgICAgICBpbmZvcy5zZXQoZmlsZS5wYXRoLCBmaWxlKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBbZmlsZU5hbWUsIGVudHJ5XSBvZiB0aGlzLnBlbmRpbmcpIHtcbiAgICAgICAgICAgIGlmICghZmlsZU5hbWUuc3RhcnRzV2l0aChwcmVmaXgpKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmICghZW50cnkuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBpbmZvcy5kZWxldGUoZmlsZU5hbWUpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5mb3Muc2V0KGZpbGVOYW1lLCB7IHBhdGg6IGZpbGVOYW1lLCBjcmVhdGVUaW1lOiBlbnRyeS53cml0ZVRpbWUsIHNpemU6IGVudHJ5LmRhdGEubGVuZ3RoIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbLi4uaW5mb3MudmFsdWVzKCldO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRDaGFuZ2VzQWZ0ZXIyKGNvbmZpZzogQ2hhbmdlc0FmdGVyQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT4ge1xuICAgICAgICBsZXQgY2hhbmdlcyA9IGF3YWl0IHRoaXMuaW5uZXIuZ2V0Q2hhbmdlc0FmdGVyMihjb25maWcpO1xuICAgICAgICBsZXQgc2VlbiA9IG5ldyBTZXQoY2hhbmdlcy5tYXAoeCA9PiB4LnBhdGgpKTtcbiAgICAgICAgZm9yIChsZXQgW2ZpbGVOYW1lLCBlbnRyeV0gb2YgdGhpcy5wZW5kaW5nKSB7XG4gICAgICAgICAgICBpZiAoZW50cnkud3JpdGVUaW1lIDw9IGNvbmZpZy50aW1lKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmIChzZWVuLmhhcyhmaWxlTmFtZSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgY2hhbmdlcy5wdXNoKHsgcGF0aDogZmlsZU5hbWUsIGNyZWF0ZVRpbWU6IGVudHJ5LndyaXRlVGltZSwgc2l6ZTogZW50cnkuZGF0YS5sZW5ndGggfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNoYW5nZXM7XG4gICAgfVxuXG4gICAgLyoqIE5ldmVyIGJ1ZmZlcmVkOiBhIGZpbGUgdG9vIGxhcmdlIHRvIGhvbGQgaW4gbWVtb3J5IGlzIGV4YWN0bHkgdGhlIGZpbGUgdGhhdCBtdXN0IG5vdCBzaXQgaW4gbWVtb3J5LiBBbnkgcGVuZGluZyB3cml0ZSBmb3IgdGhlIHBhdGggZ29lcyBmaXJzdCwgc28gdGhlIHR3byBsYW5kIGluIG9yZGVyLiAqL1xuICAgIHB1YmxpYyBhc3luYyBzZXRMYXJnZUZpbGUoY29uZmlnOiBTZXRMYXJnZUZpbGVDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbGV0IGVudHJ5ID0gdGhpcy5wZW5kaW5nLmdldChjb25maWcucGF0aCk7XG4gICAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nLmRlbGV0ZShjb25maWcucGF0aCk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLndyaXRlKGNvbmZpZy5wYXRoLCBlbnRyeSk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5pbm5lci5zZXRMYXJnZUZpbGUoY29uZmlnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0VVJMKHBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmdldFVSTChwYXRoKTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGdldENvbmZpZygpOiBQcm9taXNlPEFyY2hpdmVzQ29uZmlnPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmlubmVyLmdldENvbmZpZygpO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZ2V0U3luY1N0YXR1cygpOiBQcm9taXNlPEFyY2hpdmVzU3luY1N0YXR1cz4ge1xuICAgICAgICBpZiAoIXRoaXMuaW5uZXIuZ2V0U3luY1N0YXR1cykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBnZXRTeW5jU3RhdHVzIGlzIG5vdCBzdXBwb3J0ZWQ6ICR7dGhpcy5pbm5lci5nZXREZWJ1Z05hbWUoKX0gZG9lcyBub3QgaW1wbGVtZW50IGl0YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuaW5uZXIuZ2V0U3luY1N0YXR1cygpO1xuICAgIH1cbn1cblxuLyoqIEhvdyBsb25nIGEgc291cmNlIG1heSBob2xkIGEgd3JpdGUuIE91ciBvd24gZGlzayBhbmQgb3VyIG93biBzdG9yYWdlIHNlcnZlcnMgdGFrZSB0aGUgU0hPUlQgZGVsYXkgaG93ZXZlciBsYXJnZSB3cml0ZURlbGF5IGlzOiB0aGV5IGFyZSB3aGF0IGNyb3NzLW5vZGUgcmVhZHMgYW5kIHJlZHVuZGFuY3kgZGVwZW5kIG9uLCBhbmQgbWFraW5nIHRob3NlIHdhaXQgbWludXRlcyBpcyBub3QgYSB0cmFkZSBhbnlvbmUgYXNrZWQgZm9yLiBFdmVyeXRoaW5nIGVsc2UgKGJhY2tibGF6ZSkgdGFrZXMgdGhlIGZ1bGwgZGVsYXksIHdoaWNoIGlzIHdoZXJlIGNvYWxlc2NpbmcgYWN0dWFsbHkgc2F2ZXMgbW9uZXkuIE5vdCBmYXN0IC0+IG5vIGRlbGF5IGF0IGFsbCwgYW5kIG5vIHdyYXBwZXIuICovXG5leHBvcnQgZnVuY3Rpb24gc291cmNlV3JpdGVEZWxheShjb25maWc6IHsgc291cmNlQ29uZmlnPzogU291cmNlQ29uZmlnOyBmYXN0PzogYm9vbGVhbjsgd3JpdGVEZWxheT86IG51bWJlciB9KTogbnVtYmVyIHtcbiAgICBpZiAoIWNvbmZpZy5mYXN0KSByZXR1cm4gMDtcbiAgICBsZXQgZGVsYXkgPSBjb25maWcud3JpdGVEZWxheTtcbiAgICAvLyBBIHdyaXRlRGVsYXkgb2YgemVybyBpcyBhIHJlYWwgY2hvaWNlIChubyBkZWxheSBhdCBhbGwpLCBzbyBvbmx5IGFuIG9taXR0ZWQgZGVsYXkgZ2V0cyB0aGUgZGVmYXVsdFxuICAgIGlmIChkZWxheSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGRlbGF5ID0gREVGQVVMVF9GQVNUX1dSSVRFX0RFTEFZO1xuICAgIH1cbiAgICBpZiAoIWNvbmZpZy5zb3VyY2VDb25maWcgfHwgY29uZmlnLnNvdXJjZUNvbmZpZy50eXBlID09PSBcInJlbW90ZVwiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1pbihkZWxheSwgTUFYX1JFTU9URV9GQVNUX0JVRkZFUik7XG4gICAgfVxuICAgIHJldHVybiBkZWxheTtcbn1cblxuLyoqIFRoZSBkZWxheWVkIHdyYXBwZXIgYXJvdW5kIGEgc291cmNlLCB3aGVuIGl0IGhhcyBvbmUgLSBob3cgdGhlIHN0b3JlIHJlYWNoZXMgcGFzdCB0aGUgZGVsYXkgKHRvIHRoZSByZWFsIGRpc2sgZm9yIGxhcmdlIHVwbG9hZHMpIGFuZCBmbHVzaGVzIG9uIHNodXRkb3duLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzRGVsYXllZChzb3VyY2U6IElBcmNoaXZlcyk6IEFyY2hpdmVzRGVsYXllZCB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHNvdXJjZSBpbnN0YW5jZW9mIEFyY2hpdmVzRGVsYXllZCkgcmV0dXJuIHNvdXJjZTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKiogVGhlIHNvdXJjZSBpdHNlbGYsIHBhc3QgYW55IHdyaXRlIGRlbGF5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVud3JhcERlbGF5ZWQoc291cmNlOiBJQXJjaGl2ZXMpOiBJQXJjaGl2ZXMge1xuICAgIGlmIChzb3VyY2UgaW5zdGFuY2VvZiBBcmNoaXZlc0RlbGF5ZWQpIHJldHVybiBzb3VyY2UuaW5uZXI7XG4gICAgcmV0dXJuIHNvdXJjZTtcbn1cbiJdfQ==
220
+ /* _JS_SOURCE_HASH = "76b468d68766c130b5830bd17104c1634883ddda5b0d2f316fb63c7ba00ce218"; */