sliftutils 1.7.9 → 1.7.11

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 (92) hide show
  1. package/bin/storageserver.js +4 -0
  2. package/{teststorage → examplestorage}/browser.tsx +18 -22
  3. package/{teststorage/server.ts → examplestorage/exampleserver.ts} +4 -6
  4. package/index.d.ts +770 -84
  5. package/misc/dist/environment.ts.cache +3 -3
  6. package/misc/dist/getSecret.ts.cache +139 -0
  7. package/misc/dist/strings.ts.cache +13 -0
  8. package/misc/dist/zip.ts.cache +9 -0
  9. package/misc/getSecret.ts +38 -16
  10. package/misc/https/cloudflareHelpers.d.ts +19 -0
  11. package/misc/https/cloudflareHelpers.ts +69 -0
  12. package/misc/https/dist/certs.ts.cache +115 -179
  13. package/misc/https/dist/cloudflareHelpers.ts.cache +68 -0
  14. package/misc/https/dist/dns.ts.cache +112 -100
  15. package/misc/https/dist/hostServer.ts.cache +130 -0
  16. package/misc/https/dist/httpsCerts.ts.cache +24 -5
  17. package/misc/https/dist/persistentLocalStorage.ts.cache +3 -2
  18. package/misc/https/dns.d.ts +41 -8
  19. package/misc/https/dns.ts +104 -106
  20. package/misc/https/hostServer.d.ts +0 -3
  21. package/misc/https/hostServer.ts +12 -8
  22. package/package.json +3 -2
  23. package/render-utils/dist/observer.tsx.cache +3 -2
  24. package/spec.txt +0 -55
  25. package/storage/ArchivesDisk.d.ts +67 -0
  26. package/storage/ArchivesDisk.ts +369 -0
  27. package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +1242 -0
  28. package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +513 -0
  29. package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +352 -0
  30. package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +306 -0
  31. package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +435 -0
  32. package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +58 -0
  33. package/storage/BulkDatabase2/dist/blockCache.ts.cache +179 -0
  34. package/storage/BulkDatabase2/dist/mergeLock.ts.cache +149 -0
  35. package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +101 -0
  36. package/storage/BulkDatabase2/dist/streamLog.ts.cache +227 -0
  37. package/storage/BulkDatabase2/dist/syncClient.ts.cache +104 -0
  38. package/storage/IArchives.d.ts +127 -1
  39. package/storage/IArchives.ts +201 -1
  40. package/storage/backblaze.d.ts +29 -2
  41. package/storage/backblaze.ts +214 -78
  42. package/storage/dist/ArchivesDisk.ts.cache +373 -0
  43. package/storage/dist/FileFolderAPI.tsx.cache +508 -65
  44. package/storage/dist/IArchives.ts.cache +44 -0
  45. package/storage/dist/IndexedDBFileFolderAPI.ts.cache +8 -2
  46. package/storage/dist/JSONStorage.ts.cache +6 -2
  47. package/storage/dist/PendingManager.tsx.cache +1 -1
  48. package/storage/dist/TransactionStorage.ts.cache +231 -92
  49. package/storage/dist/backblaze.ts.cache +797 -0
  50. package/storage/dist/fileSystemPointer.ts.cache +36 -3
  51. package/storage/dist/remoteFileStorage.ts.cache +495 -0
  52. package/storage/remoteStorage/ArchivesRemote.d.ts +34 -18
  53. package/storage/remoteStorage/ArchivesRemote.ts +85 -65
  54. package/storage/remoteStorage/ArchivesUrl.d.ts +48 -0
  55. package/storage/remoteStorage/ArchivesUrl.ts +86 -0
  56. package/storage/remoteStorage/accessPage.tsx +111 -28
  57. package/storage/remoteStorage/blobStore.d.ts +128 -25
  58. package/storage/remoteStorage/blobStore.ts +757 -290
  59. package/storage/remoteStorage/cliArgs.d.ts +1 -0
  60. package/storage/remoteStorage/cliArgs.ts +9 -0
  61. package/storage/remoteStorage/createArchives.d.ts +85 -0
  62. package/storage/remoteStorage/createArchives.ts +612 -0
  63. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +197 -0
  64. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +85 -0
  65. package/storage/remoteStorage/dist/accessPage.tsx.cache +222 -0
  66. package/storage/remoteStorage/dist/blobStore.ts.cache +837 -0
  67. package/storage/remoteStorage/dist/cliArgs.ts.cache +16 -0
  68. package/storage/remoteStorage/dist/createArchives.ts.cache +610 -0
  69. package/storage/remoteStorage/dist/remoteConfig.ts.cache +206 -0
  70. package/storage/remoteStorage/dist/sourceWrapper.ts.cache +223 -0
  71. package/storage/remoteStorage/dist/storageController.ts.cache +500 -0
  72. package/storage/remoteStorage/dist/storageServer.ts.cache +106 -0
  73. package/storage/remoteStorage/dist/storageServerCli.ts.cache +39 -0
  74. package/storage/remoteStorage/dist/storageServerState.ts.cache +518 -0
  75. package/storage/remoteStorage/grantAccess.js +4 -0
  76. package/storage/remoteStorage/grantAccessCli.d.ts +1 -0
  77. package/storage/remoteStorage/grantAccessCli.ts +27 -0
  78. package/storage/remoteStorage/remoteConfig.d.ts +29 -0
  79. package/storage/remoteStorage/remoteConfig.ts +194 -0
  80. package/storage/remoteStorage/sourceWrapper.d.ts +41 -0
  81. package/storage/remoteStorage/sourceWrapper.ts +223 -0
  82. package/storage/remoteStorage/spec.md +31 -0
  83. package/storage/remoteStorage/storageController.d.ts +30 -27
  84. package/storage/remoteStorage/storageController.ts +297 -159
  85. package/storage/remoteStorage/storageServer.d.ts +6 -0
  86. package/storage/remoteStorage/storageServer.ts +88 -94
  87. package/storage/remoteStorage/storageServerCli.d.ts +1 -0
  88. package/storage/remoteStorage/storageServerCli.ts +38 -0
  89. package/storage/remoteStorage/storageServerState.d.ts +43 -0
  90. package/storage/remoteStorage/storageServerState.ts +540 -0
  91. package/testsite/server.ts +0 -2
  92. package/yarn.lock +11 -6
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.blockCache = exports.BlockCache = exports.encodeCompressedBlocks = void 0;
4
+ const LZ4_1 = require("socket-function/src/lz4/LZ4");
5
+ // Block-aligned, promise-deduped, decompressing range cache for BulkDatabase2's on-disk files.
6
+ //
7
+ // On-disk format (produced by encodeCompressedBlocks): the logical (uncompressed) bulk buffer is
8
+ // split into fixed BLOCK_SIZE blocks; each block is LZ4-compressed unless that wouldn't shrink it by
9
+ // at least 2x, in which case it's stored raw. The file starts with a JSON index mapping each block to
10
+ // its stored length + a compressed flag, so a reader can seek straight to any block:
11
+ //
12
+ // [u32 indexLength][index JSON][block 0 stored bytes][block 1 stored bytes]...
13
+ //
14
+ // The cache presents a *logical* getRange (over uncompressed bytes) so BulkDatabase2's reader is
15
+ // oblivious to compression. It reads compressed bytes via the underlying getRange, decompresses, and
16
+ // caches the uncompressed blocks. Reads are promise-deduped and contiguous missing blocks are
17
+ // coalesced into one underlying read. Files are immutable, so cached blocks are valid forever.
18
+ //
19
+ // Per-block compression mainly helps slow storage (HDD): fewer bytes off disk per block, at the cost
20
+ // of a fast in-memory LZ4 decompress.
21
+ const BLOCK_SIZE = 256 * 1024;
22
+ const MAX_BLOCKS = Math.floor((512 * 1024 * 1024) / BLOCK_SIZE);
23
+ const MIN_COMPRESSION_RATIO = 2;
24
+ const EMPTY = Buffer.alloc(0);
25
+ // Writes a logical bulk buffer in the compressed-block format described above.
26
+ function encodeCompressedBlocks(data) {
27
+ let blocks = [];
28
+ let storedParts = [];
29
+ let blockCount = Math.ceil(data.length / BLOCK_SIZE);
30
+ for (let i = 0; i < blockCount; i++) {
31
+ let raw = data.subarray(i * BLOCK_SIZE, Math.min((i + 1) * BLOCK_SIZE, data.length));
32
+ let compressed = LZ4_1.LZ4.compress(raw);
33
+ // Only keep the compressed form if it shrinks the block by at least MIN_COMPRESSION_RATIO.
34
+ if (compressed.length * MIN_COMPRESSION_RATIO <= raw.length) {
35
+ storedParts.push(compressed);
36
+ blocks.push({ len: compressed.length, c: 1 });
37
+ }
38
+ else {
39
+ storedParts.push(raw);
40
+ blocks.push({ len: raw.length, c: 0 });
41
+ }
42
+ }
43
+ let indexBuf = Buffer.from(JSON.stringify({ uncompressedSize: data.length, blockSize: BLOCK_SIZE, blocks }), "utf8");
44
+ let prefix = Buffer.alloc(4);
45
+ prefix.writeUInt32LE(indexBuf.length, 0);
46
+ return Buffer.concat([prefix, indexBuf, ...storedParts]);
47
+ }
48
+ exports.encodeCompressedBlocks = encodeCompressedBlocks;
49
+ class BlockCache {
50
+ constructor() {
51
+ // Uncompressed blocks; insertion order is LRU order (re-inserted on access).
52
+ this.blocks = new Map();
53
+ // Parsed file index per fileId (small; not subject to the block LRU).
54
+ this.indexes = new Map();
55
+ }
56
+ clear() {
57
+ this.blocks.clear();
58
+ this.indexes.clear();
59
+ }
60
+ evict(fileId) {
61
+ this.indexes.delete(fileId);
62
+ const prefix = fileId + ":";
63
+ for (const key of this.blocks.keys())
64
+ if (key.startsWith(prefix))
65
+ this.blocks.delete(key);
66
+ }
67
+ touch(key, value) {
68
+ this.blocks.delete(key);
69
+ this.blocks.set(key, value);
70
+ while (this.blocks.size > MAX_BLOCKS) {
71
+ let oldest = this.blocks.keys().next().value;
72
+ if (oldest === undefined)
73
+ break;
74
+ this.blocks.delete(oldest);
75
+ }
76
+ }
77
+ // Reads + validates the file index. Rejects the WHOLE file if it isn't exactly the size its index
78
+ // implies — a truncated/partial write (e.g. a crash mid-write) is detected here rather than
79
+ // silently returning corrupted values for the rows near the end.
80
+ async readIndex(rawGetRange, fileSize) {
81
+ let head = await rawGetRange(0, 4);
82
+ if (head.length < 4)
83
+ throw new Error(`bulk file too short for an index header (${fileSize} bytes)`);
84
+ let indexLength = head.readUInt32LE(0);
85
+ if (indexLength <= 0 || 4 + indexLength > fileSize) {
86
+ throw new Error(`bulk file index length ${indexLength} is invalid for a ${fileSize}-byte file`);
87
+ }
88
+ let indexBuf = await rawGetRange(4, 4 + indexLength);
89
+ let parsed = JSON.parse(indexBuf.toString("utf8"));
90
+ let dataBase = 4 + indexLength;
91
+ let offsets = [];
92
+ let offset = dataBase;
93
+ for (let block of parsed.blocks) {
94
+ offsets.push(offset);
95
+ offset += block.len;
96
+ }
97
+ // The blocks must account for exactly the rest of the file. Any mismatch means the file is
98
+ // truncated or otherwise corrupt — reject it entirely.
99
+ if (offset !== fileSize) {
100
+ throw new Error(`bulk file is ${fileSize} bytes but its index implies ${offset} (truncated/corrupt)`);
101
+ }
102
+ return { ...parsed, offsets };
103
+ }
104
+ // Opens an immutable file: reads + validates its index (cached) and returns the logical
105
+ // (uncompressed) size plus a logical getRange that the caller can use exactly like an
106
+ // uncompressed file. `fileSize` is the actual on-disk byte length, used to detect truncation.
107
+ async open(fileId, fileSize, rawGetRange) {
108
+ let indexPromise = this.indexes.get(fileId);
109
+ if (!indexPromise) {
110
+ indexPromise = this.readIndex(rawGetRange, fileSize);
111
+ this.indexes.set(fileId, indexPromise);
112
+ }
113
+ let index = await indexPromise;
114
+ return { uncompressedSize: index.uncompressedSize, getRange: this.makeGetRange(fileId, index, rawGetRange) };
115
+ }
116
+ makeGetRange(fileId, index, rawGetRange) {
117
+ let blockSize = index.blockSize;
118
+ return async (start, end) => {
119
+ if (end <= start)
120
+ return EMPTY;
121
+ let firstBlock = Math.floor(start / blockSize);
122
+ let lastBlock = Math.floor((end - 1) / blockSize);
123
+ let parts = [];
124
+ let block = firstBlock;
125
+ while (block <= lastBlock) {
126
+ let key = `${fileId}:${block}`;
127
+ let cached = this.blocks.get(key);
128
+ if (cached) {
129
+ this.touch(key, cached);
130
+ parts.push(await cached);
131
+ block++;
132
+ continue;
133
+ }
134
+ // Coalesce a run of consecutive missing blocks into one underlying (compressed) read.
135
+ let runStart = block;
136
+ let runEnd = block + 1;
137
+ while (runEnd <= lastBlock && !this.blocks.has(`${fileId}:${runEnd}`))
138
+ runEnd++;
139
+ let compStart = index.offsets[runStart];
140
+ let lastMeta = index.blocks[runEnd - 1];
141
+ let compEnd = index.offsets[runEnd - 1] + lastMeta.len;
142
+ let runCompressed = rawGetRange(compStart, compEnd);
143
+ // Hold this run's promises locally. Registering them in the LRU can evict earlier
144
+ // blocks of the same run (or of a concurrent run) before we get to await them, so
145
+ // reading them back out of the cache would silently drop blocks and return a short
146
+ // buffer. We still register in the LRU so concurrent reads dedupe onto them.
147
+ let runPromises = [];
148
+ for (let i = runStart; i < runEnd; i++) {
149
+ let meta = index.blocks[i];
150
+ let relOffset = index.offsets[i] - compStart;
151
+ let blockPromise = runCompressed.then(buf => {
152
+ let stored = buf.subarray(relOffset, relOffset + meta.len);
153
+ if (meta.c)
154
+ return LZ4_1.LZ4.decompress(stored);
155
+ return stored;
156
+ });
157
+ runPromises.push(blockPromise);
158
+ this.touch(`${fileId}:${i}`, blockPromise);
159
+ }
160
+ for (let promise of runPromises)
161
+ parts.push(await promise);
162
+ block = runEnd;
163
+ }
164
+ let combined = parts.length === 1 && parts[0] || Buffer.concat(parts);
165
+ let sliceStart = start - firstBlock * blockSize;
166
+ // A short combined buffer means we lost blocks; subarray would clamp and hand back
167
+ // truncated data that every caller treats as valid. Fail loudly instead.
168
+ if (combined.length < sliceStart + (end - start)) {
169
+ throw new Error(`Expected ${sliceStart + (end - start)} bytes of blocks for range [${start}, ${end}) of ${fileId}, was ${combined.length}`);
170
+ }
171
+ return combined.subarray(sliceStart, sliceStart + (end - start));
172
+ };
173
+ }
174
+ }
175
+ exports.BlockCache = BlockCache;
176
+ // Shared across every BulkDatabase2 collection/file (the 512MB budget is global).
177
+ exports.blockCache = new BlockCache();
178
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tDYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImJsb2NrQ2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQWtEO0FBRWxELCtGQUErRjtBQUMvRixFQUFFO0FBQ0YsaUdBQWlHO0FBQ2pHLHFHQUFxRztBQUNyRyxzR0FBc0c7QUFDdEcscUZBQXFGO0FBQ3JGLEVBQUU7QUFDRixpRkFBaUY7QUFDakYsRUFBRTtBQUNGLGlHQUFpRztBQUNqRyxxR0FBcUc7QUFDckcsOEZBQThGO0FBQzlGLCtGQUErRjtBQUMvRixFQUFFO0FBQ0YscUdBQXFHO0FBQ3JHLHNDQUFzQztBQUV0QyxNQUFNLFVBQVUsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDO0FBQzlCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDO0FBQ2hFLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDO0FBRWhDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFXLENBQUM7QUFheEMsK0VBQStFO0FBQy9FLFNBQWdCLHNCQUFzQixDQUFDLElBQVk7SUFDL0MsSUFBSSxNQUFNLEdBQWdCLEVBQUUsQ0FBQztJQUM3QixJQUFJLFdBQVcsR0FBYSxFQUFFLENBQUM7SUFDL0IsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxDQUFDO0lBQ3JELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNsQyxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxVQUFVLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENB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O1lBQ2hELG1GQUFtRjtZQUNuRix5RUFBeUU7WUFDekUsSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLFVBQVUsR0FBRyxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUMvQyxNQUFNLElBQUksS0FBSyxDQUFDLFlBQVksVUFBVSxHQUFHLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQywrQkFBK0IsS0FBSyxLQUFLLEdBQUcsUUFBUSxNQUFNLFNBQVMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDaEosQ0FBQztZQUNELE9BQU8sUUFBUSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsVUFBVSxHQUFHLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDckUsQ0FBQyxDQUFDO0lBQ04sQ0FBQztDQUNKO0FBM0hELGdDQTJIQztBQUVELGtGQUFrRjtBQUNyRSxRQUFBLFVBQVUsR0FBRyxJQUFJLFVBQVUsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTFo0IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbHo0L0xaNFwiO1xuXG4vLyBCbG9jay1hbGlnbmVkLCBwcm9taXNlLWRlZHVwZWQsIGRlY29tcHJlc3NpbmcgcmFuZ2UgY2FjaGUgZm9yIEJ1bGtEYXRhYmFzZTIncyBvbi1kaXNrIGZpbGVzLlxuLy9cbi8vIE9uLWRpc2sgZm9ybWF0IChwcm9kdWNlZCBieSBlbmNvZGVDb21wcmVzc2VkQmxvY2tzKTogdGhlIGxvZ2ljYWwgKHVuY29tcHJlc3NlZCkgYnVsayBidWZmZXIgaXNcbi8vIHNwbGl0IGludG8gZml4ZWQgQkxPQ0tfU0laRSBibG9ja3M7IGVhY2ggYmxvY2sgaXMgTFo0LWNvbXByZXNzZWQgdW5sZXNzIHRoYXQgd291bGRuJ3Qgc2hyaW5rIGl0IGJ5XG4vLyBhdCBsZWFzdCAyeCwgaW4gd2hpY2ggY2FzZSBpdCdzIHN0b3JlZCByYXcuIFRoZSBmaWxlIHN0YXJ0cyB3aXRoIGEgSlNPTiBpbmRleCBtYXBwaW5nIGVhY2ggYmxvY2sgdG9cbi8vIGl0cyBzdG9yZWQgbGVuZ3RoICsgYSBjb21wcmVzc2VkIGZsYWcsIHNvIGEgcmVhZGVyIGNhbiBzZWVrIHN0cmFpZ2h0IHRvIGFueSBibG9jazpcbi8vXG4vLyAgIFt1MzIgaW5kZXhMZW5ndGhdW2luZGV4IEpTT05dW2Jsb2NrIDAgc3RvcmVkIGJ5dGVzXVtibG9jayAxIHN0b3JlZCBieXRlc10uLi5cbi8vXG4vLyBUaGUgY2FjaGUgcHJlc2VudHMgYSAqbG9naWNhbCogZ2V0UmFuZ2UgKG92ZXIgdW5jb21wcmVzc2VkIGJ5dGVzKSBzbyBCdWxrRGF0YWJhc2UyJ3MgcmVhZGVyIGlzXG4vLyBvYmxpdmlvdXMgdG8gY29tcHJlc3Npb24uIEl0IHJlYWRzIGNvbXByZXNzZWQgYnl0ZXMgdmlhIHRoZSB1bmRlcmx5aW5nIGdldFJhbmdlLCBkZWNvbXByZXNzZXMsIGFuZFxuLy8gY2FjaGVzIHRoZSB1bmNvbXByZXNzZWQgYmxvY2tzLiBSZWFkcyBhcmUgcHJvbWlzZS1kZWR1cGVkIGFuZCBjb250aWd1b3VzIG1pc3NpbmcgYmxvY2tzIGFyZVxuLy8gY29hbGVzY2VkIGludG8gb25lIHVuZGVybHlpbmcgcmVhZC4gRmlsZXMgYXJlIGltbXV0YWJsZSwgc28gY2FjaGVkIGJsb2NrcyBhcmUgdmFsaWQgZm9yZXZlci5cbi8vXG4vLyBQZXItYmxvY2sgY29tcHJlc3Npb24gbWFpbmx5IGhlbHBzIHNsb3cgc3RvcmFnZSAoSEREKTogZmV3ZXIgYnl0ZXMgb2ZmIGRpc2sgcGVyIGJsb2NrLCBhdCB0aGUgY29zdFxuLy8gb2YgYSBmYXN0IGluLW1lbW9yeSBMWjQgZGVjb21wcmVzcy5cblxuY29uc3QgQkxPQ0tfU0laRSA9IDI1NiAqIDEwMjQ7XG5jb25zdCBNQVhfQkxPQ0tTID0gTWF0aC5mbG9vcigoNTEyICogMTAyNCAqIDEwMjQpIC8gQkxPQ0tfU0laRSk7XG5jb25zdCBNSU5fQ09NUFJFU1NJT05fUkFUSU8gPSAyO1xuXG5jb25zdCBFTVBUWSA9IEJ1ZmZlci5hbGxvYygwKSBhcyBCdWZmZXI7XG5cbmV4cG9ydCB0eXBlIEdldFJhbmdlID0gKHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKSA9PiBQcm9taXNlPEJ1ZmZlcj47XG5cbnR5cGUgQmxvY2tNZXRhID0geyBsZW46IG51bWJlcjsgYzogMCB8IDEgfTtcbnR5cGUgRmlsZUluZGV4ID0ge1xuICAgIHVuY29tcHJlc3NlZFNpemU6IG51bWJlcjtcbiAgICBibG9ja1NpemU6IG51bWJlcjtcbiAgICBibG9ja3M6IEJsb2NrTWV0YVtdO1xuICAgIC8vIFN0b3JlZCBieXRlIG9mZnNldCBvZiBlYWNoIGJsb2NrIChvZmZzZXRzW2ldLi5vZmZzZXRzW2ldK2Jsb2Nrc1tpXS5sZW4pLCBmaWxsZWQgaW4gb24gcGFyc2UuXG4gICAgb2Zmc2V0czogbnVtYmVyW107XG59O1xuXG4vLyBXcml0ZXMgYSBsb2dpY2FsIGJ1bGsgYnVmZmVyIGluIHRoZSBjb21wcmVzc2VkLWJsb2NrIGZvcm1hdCBkZXNjcmliZWQgYWJvdmUuXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlQ29tcHJlc3NlZEJsb2NrcyhkYXRhOiBCdWZmZXIpOiBCdWZmZXIge1xuICAgIGxldCBibG9ja3M6IEJsb2NrTWV0YVtdID0gW107XG4gICAgbGV0IHN0b3JlZFBhcnRzOiBCdWZmZXJbXSA9IFtdO1xuICAgIGxldCBibG9ja0NvdW50ID0gTWF0aC5jZWlsKGRhdGEubGVuZ3RoIC8gQkxPQ0tfU0laRSk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBibG9ja0NvdW50OyBpKyspIHtcbiAgICAgICAgbGV0IHJhdyA9IGRhdGEuc3ViYXJyYXkoaSAqIEJMT0NLX1NJWkUsIE1hdGgubWluKChpICsgMSkgKiBCTE9DS19TSVpFLCBkYXRhLmxlbmd0aCkpO1xuICAgICAgICBsZXQgY29tcHJlc3NlZCA9IExaNC5jb21wcmVzcyhyYXcpO1xuICAgICAgICAvLyBPbmx5IGtlZXAgdGhlIGNvbXByZXNzZWQgZm9ybSBpZiBpdCBzaHJpbmtzIHRoZSBibG9jayBieSBhdCBsZWFzdCBNSU5fQ09NUFJFU1NJT05fUkFUSU8uXG4gICAgICAgIGlmIChjb21wcmVzc2VkLmxlbmd0aCAqIE1JTl9DT01QUkVTU0lPTl9SQVRJTyA8PSByYXcubGVuZ3RoKSB7XG4gICAgICAgICAgICBzdG9yZWRQYXJ0cy5wdXNoKGNvbXByZXNzZWQpO1xuICAgICAgICAgICAgYmxvY2tzLnB1c2goeyBsZW46IGNvbXByZXNzZWQubGVuZ3RoLCBjOiAxIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RvcmVkUGFydHMucHVzaChyYXcpO1xuICAgICAgICAgICAgYmxvY2tzLnB1c2goeyBsZW46IHJhdy5sZW5ndGgsIGM6IDAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgbGV0IGluZGV4QnVmID0gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkoeyB1bmNvbXByZXNzZWRTaXplOiBkYXRhLmxlbmd0aCwgYmxvY2tTaXplOiBCTE9DS19TSVpFLCBibG9ja3MgfSksIFwidXRmOFwiKTtcbiAgICBsZXQgcHJlZml4ID0gQnVmZmVyLmFsbG9jKDQpO1xuICAgIHByZWZpeC53cml0ZVVJbnQzMkxFKGluZGV4QnVmLmxlbmd0aCwgMCk7XG4gICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoW3ByZWZpeCwgaW5kZXhCdWYsIC4uLnN0b3JlZFBhcnRzXSk7XG59XG5cbmV4cG9ydCBjbGFzcyBCbG9ja0NhY2hlIHtcbiAgICAvLyBVbmNvbXByZXNzZWQgYmxvY2tzOyBpbnNlcnRpb24gb3JkZXIgaXMgTFJVIG9yZGVyIChyZS1pbnNlcnRlZCBvbiBhY2Nlc3MpLlxuICAgIHByaXZhdGUgYmxvY2tzID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8QnVmZmVyPj4oKTtcbiAgICAvLyBQYXJzZWQgZmlsZSBpbmRleCBwZXIgZmlsZUlkIChzbWFsbDsgbm90IHN1YmplY3QgdG8gdGhlIGJsb2NrIExSVSkuXG4gICAgcHJpdmF0ZSBpbmRleGVzID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8RmlsZUluZGV4Pj4oKTtcblxuICAgIHB1YmxpYyBjbGVhcigpIHtcbiAgICAgICAgdGhpcy5ibG9ja3MuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5pbmRleGVzLmNsZWFyKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGV2aWN0KGZpbGVJZDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuaW5kZXhlcy5kZWxldGUoZmlsZUlkKTtcbiAgICAgICAgY29uc3QgcHJlZml4ID0gZmlsZUlkICsgXCI6XCI7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIHRoaXMuYmxvY2tzLmtleXMoKSkgaWYgKGtleS5zdGFydHNXaXRoKHByZWZpeCkpIHRoaXMuYmxvY2tzLmRlbGV0ZShrZXkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgdG91Y2goa2V5OiBzdHJpbmcsIHZhbHVlOiBQcm9taXNlPEJ1ZmZlcj4pIHtcbiAgICAgICAgdGhpcy5ibG9ja3MuZGVsZXRlKGtleSk7XG4gICAgICAgIHRoaXMuYmxvY2tzLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgd2hpbGUgKHRoaXMuYmxvY2tzLnNpemUgPiBNQVhfQkxPQ0tTKSB7XG4gICAgICAgICAgICBsZXQgb2xkZXN0ID0gdGhpcy5ibG9ja3Mua2V5cygpLm5leHQoKS52YWx1ZTtcbiAgICAgICAgICAgIGlmIChvbGRlc3QgPT09IHVuZGVmaW5lZCkgYnJlYWs7XG4gICAgICAgICAgICB0aGlzLmJsb2Nrcy5kZWxldGUob2xkZXN0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlYWRzICsgdmFsaWRhdGVzIHRoZSBmaWxlIGluZGV4LiBSZWplY3RzIHRoZSBXSE9MRSBmaWxlIGlmIGl0IGlzbid0IGV4YWN0bHkgdGhlIHNpemUgaXRzIGluZGV4XG4gICAgLy8gaW1wbGllcyDigJQgYSB0cnVuY2F0ZWQvcGFydGlhbCB3cml0ZSAoZS5nLiBhIGNyYXNoIG1pZC13cml0ZSkgaXMgZGV0ZWN0ZWQgaGVyZSByYXRoZXIgdGhhblxuICAgIC8vIHNpbGVudGx5IHJldHVybmluZyBjb3JydXB0ZWQgdmFsdWVzIGZvciB0aGUgcm93cyBuZWFyIHRoZSBlbmQuXG4gICAgcHJpdmF0ZSBhc3luYyByZWFkSW5kZXgocmF3R2V0UmFuZ2U6IEdldFJhbmdlLCBmaWxlU2l6ZTogbnVtYmVyKTogUHJvbWlzZTxGaWxlSW5kZXg+IHtcbiAgICAgICAgbGV0IGhlYWQgPSBhd2FpdCByYXdHZXRSYW5nZSgwLCA0KTtcbiAgICAgICAgaWYgKGhlYWQubGVuZ3RoIDwgNCkgdGhyb3cgbmV3IEVycm9yKGBidWxrIGZpbGUgdG9vIHNob3J0IGZvciBhbiBpbmRleCBoZWFkZXIgKCR7ZmlsZVNpemV9IGJ5dGVzKWApO1xuICAgICAgICBsZXQgaW5kZXhMZW5ndGggPSBoZWFkLnJlYWRVSW50MzJMRSgwKTtcbiAgICAgICAgaWYgKGluZGV4TGVuZ3RoIDw9IDAgfHwgNCArIGluZGV4TGVuZ3RoID4gZmlsZVNpemUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgYnVsayBmaWxlIGluZGV4IGxlbmd0aCAke2luZGV4TGVuZ3RofSBpcyBpbnZhbGlkIGZvciBhICR7ZmlsZVNpemV9LWJ5dGUgZmlsZWApO1xuICAgICAgICB9XG4gICAgICAgIGxldCBpbmRleEJ1ZiA9IGF3YWl0IHJhd0dldFJhbmdlKDQsIDQgKyBpbmRleExlbmd0aCk7XG4gICAgICAgIGxldCBwYXJzZWQgPSBKU09OLnBhcnNlKGluZGV4QnVmLnRvU3RyaW5nKFwidXRmOFwiKSkgYXMgeyB1bmNvbXByZXNzZWRTaXplOiBudW1iZXI7IGJsb2NrU2l6ZTogbnVtYmVyOyBibG9ja3M6IEJsb2NrTWV0YVtdIH07XG4gICAgICAgIGxldCBkYXRhQmFzZSA9IDQgKyBpbmRleExlbmd0aDtcbiAgICAgICAgbGV0IG9mZnNldHM6IG51bWJlcltdID0gW107XG4gICAgICAgIGxldCBvZmZzZXQgPSBkYXRhQmFzZTtcbiAgICAgICAgZm9yIChsZXQgYmxvY2sgb2YgcGFyc2VkLmJsb2Nrcykge1xuICAgICAgICAgICAgb2Zmc2V0cy5wdXNoKG9mZnNldCk7XG4gICAgICAgICAgICBvZmZzZXQgKz0gYmxvY2subGVuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRoZSBibG9ja3MgbXVzdCBhY2NvdW50IGZvciBleGFjdGx5IHRoZSByZXN0IG9mIHRoZSBmaWxlLiBBbnkgbWlzbWF0Y2ggbWVhbnMgdGhlIGZpbGUgaXNcbiAgICAgICAgLy8gdHJ1bmNhdGVkIG9yIG90aGVyd2lzZSBjb3JydXB0IOKAlCByZWplY3QgaXQgZW50aXJlbHkuXG4gICAgICAgIGlmIChvZmZzZXQgIT09IGZpbGVTaXplKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGJ1bGsgZmlsZSBpcyAke2ZpbGVTaXplfSBieXRlcyBidXQgaXRzIGluZGV4IGltcGxpZXMgJHtvZmZzZXR9ICh0cnVuY2F0ZWQvY29ycnVwdClgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyAuLi5wYXJzZWQsIG9mZnNldHMgfTtcbiAgICB9XG5cbiAgICAvLyBPcGVucyBhbiBpbW11dGFibGUgZmlsZTogcmVhZHMgKyB2YWxpZGF0ZXMgaXRzIGluZGV4IChjYWNoZWQpIGFuZCByZXR1cm5zIHRoZSBsb2dpY2FsXG4gICAgLy8gKHVuY29tcHJlc3NlZCkgc2l6ZSBwbHVzIGEgbG9naWNhbCBnZXRSYW5nZSB0aGF0IHRoZSBjYWxsZXIgY2FuIHVzZSBleGFjdGx5IGxpa2UgYW5cbiAgICAvLyB1bmNvbXByZXNzZWQgZmlsZS4gYGZpbGVTaXplYCBpcyB0aGUgYWN0dWFsIG9uLWRpc2sgYnl0ZSBsZW5ndGgsIHVzZWQgdG8gZGV0ZWN0IHRydW5jYXRpb24uXG4gICAgcHVibGljIGFzeW5jIG9wZW4oZmlsZUlkOiBzdHJpbmcsIGZpbGVTaXplOiBudW1iZXIsIHJhd0dldFJhbmdlOiBHZXRSYW5nZSk6IFByb21pc2U8eyB1bmNvbXByZXNzZWRTaXplOiBudW1iZXI7IGdldFJhbmdlOiBHZXRSYW5nZSB9PiB7XG4gICAgICAgIGxldCBpbmRleFByb21pc2UgPSB0aGlzLmluZGV4ZXMuZ2V0KGZpbGVJZCk7XG4gICAgICAgIGlmICghaW5kZXhQcm9taXNlKSB7XG4gICAgICAgICAgICBpbmRleFByb21pc2UgPSB0aGlzLnJlYWRJbmRleChyYXdHZXRSYW5nZSwgZmlsZVNpemUpO1xuICAgICAgICAgICAgdGhpcy5pbmRleGVzLnNldChmaWxlSWQsIGluZGV4UHJvbWlzZSk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGluZGV4ID0gYXdhaXQgaW5kZXhQcm9taXNlO1xuICAgICAgICByZXR1cm4geyB1bmNvbXByZXNzZWRTaXplOiBpbmRleC51bmNvbXByZXNzZWRTaXplLCBnZXRSYW5nZTogdGhpcy5tYWtlR2V0UmFuZ2UoZmlsZUlkLCBpbmRleCwgcmF3R2V0UmFuZ2UpIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtYWtlR2V0UmFuZ2UoZmlsZUlkOiBzdHJpbmcsIGluZGV4OiBGaWxlSW5kZXgsIHJhd0dldFJhbmdlOiBHZXRSYW5nZSk6IEdldFJhbmdlIHtcbiAgICAgICAgbGV0IGJsb2NrU2l6ZSA9IGluZGV4LmJsb2NrU2l6ZTtcbiAgICAgICAgcmV0dXJuIGFzeW5jIChzdGFydCwgZW5kKSA9PiB7XG4gICAgICAgICAgICBpZiAoZW5kIDw9IHN0YXJ0KSByZXR1cm4gRU1QVFk7XG4gICAgICAgICAgICBsZXQgZmlyc3RCbG9jayA9IE1hdGguZmxvb3Ioc3RhcnQgLyBibG9ja1NpemUpO1xuICAgICAgICAgICAgbGV0IGxhc3RCbG9jayA9IE1hdGguZmxvb3IoKGVuZCAtIDEpIC8gYmxvY2tTaXplKTtcblxuICAgICAgICAgICAgbGV0IHBhcnRzOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgICAgICAgbGV0IGJsb2NrID0gZmlyc3RCbG9jaztcbiAgICAgICAgICAgIHdoaWxlIChibG9jayA8PSBsYXN0QmxvY2spIHtcbiAgICAgICAgICAgICAgICBsZXQga2V5ID0gYCR7ZmlsZUlkfToke2Jsb2NrfWA7XG4gICAgICAgICAgICAgICAgbGV0IGNhY2hlZCA9IHRoaXMuYmxvY2tzLmdldChrZXkpO1xuICAgICAgICAgICAgICAgIGlmIChjYWNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50b3VjaChrZXksIGNhY2hlZCk7XG4gICAgICAgICAgICAgICAgICAgIHBhcnRzLnB1c2goYXdhaXQgY2FjaGVkKTtcbiAgICAgICAgICAgICAgICAgICAgYmxvY2srKztcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIENvYWxlc2NlIGEgcnVuIG9mIGNvbnNlY3V0aXZlIG1pc3NpbmcgYmxvY2tzIGludG8gb25lIHVuZGVybHlpbmcgKGNvbXByZXNzZWQpIHJlYWQuXG4gICAgICAgICAgICAgICAgbGV0IHJ1blN0YXJ0ID0gYmxvY2s7XG4gICAgICAgICAgICAgICAgbGV0IHJ1bkVuZCA9IGJsb2NrICsgMTtcbiAgICAgICAgICAgICAgICB3aGlsZSAocnVuRW5kIDw9IGxhc3RCbG9jayAmJiAhdGhpcy5ibG9ja3MuaGFzKGAke2ZpbGVJZH06JHtydW5FbmR9YCkpIHJ1bkVuZCsrO1xuICAgICAgICAgICAgICAgIGxldCBjb21wU3RhcnQgPSBpbmRleC5vZmZzZXRzW3J1blN0YXJ0XTtcbiAgICAgICAgICAgICAgICBsZXQgbGFzdE1ldGEgPSBpbmRleC5ibG9ja3NbcnVuRW5kIC0gMV07XG4gICAgICAgICAgICAgICAgbGV0IGNvbXBFbmQgPSBpbmRleC5vZmZzZXRzW3J1bkVuZCAtIDFdICsgbGFzdE1ldGEubGVuO1xuICAgICAgICAgICAgICAgIGxldCBydW5Db21wcmVzc2VkID0gcmF3R2V0UmFuZ2UoY29tcFN0YXJ0LCBjb21wRW5kKTtcbiAgICAgICAgICAgICAgICAvLyBIb2xkIHRoaXMgcnVuJ3MgcHJvbWlzZXMgbG9jYWxseS4gUmVnaXN0ZXJpbmcgdGhlbSBpbiB0aGUgTFJVIGNhbiBldmljdCBlYXJsaWVyXG4gICAgICAgICAgICAgICAgLy8gYmxvY2tzIG9mIHRoZSBzYW1lIHJ1biAob3Igb2YgYSBjb25jdXJyZW50IHJ1bikgYmVmb3JlIHdlIGdldCB0byBhd2FpdCB0aGVtLCBzb1xuICAgICAgICAgICAgICAgIC8vIHJlYWRpbmcgdGhlbSBiYWNrIG91dCBvZiB0aGUgY2FjaGUgd291bGQgc2lsZW50bHkgZHJvcCBibG9ja3MgYW5kIHJldHVybiBhIHNob3J0XG4gICAgICAgICAgICAgICAgLy8gYnVmZmVyLiBXZSBzdGlsbCByZWdpc3RlciBpbiB0aGUgTFJVIHNvIGNvbmN1cnJlbnQgcmVhZHMgZGVkdXBlIG9udG8gdGhlbS5cbiAgICAgICAgICAgICAgICBsZXQgcnVuUHJvbWlzZXM6IFByb21pc2U8QnVmZmVyPltdID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IHJ1blN0YXJ0OyBpIDwgcnVuRW5kOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG1ldGEgPSBpbmRleC5ibG9ja3NbaV07XG4gICAgICAgICAgICAgICAgICAgIGxldCByZWxPZmZzZXQgPSBpbmRleC5vZmZzZXRzW2ldIC0gY29tcFN0YXJ0O1xuICAgICAgICAgICAgICAgICAgICBsZXQgYmxvY2tQcm9taXNlID0gcnVuQ29tcHJlc3NlZC50aGVuKGJ1ZiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RvcmVkID0gYnVmLnN1YmFycmF5KHJlbE9mZnNldCwgcmVsT2Zmc2V0ICsgbWV0YS5sZW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1ldGEuYykgcmV0dXJuIExaNC5kZWNvbXByZXNzKHN0b3JlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RvcmVkO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcnVuUHJvbWlzZXMucHVzaChibG9ja1Byb21pc2UpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRvdWNoKGAke2ZpbGVJZH06JHtpfWAsIGJsb2NrUHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAobGV0IHByb21pc2Ugb2YgcnVuUHJvbWlzZXMpIHBhcnRzLnB1c2goYXdhaXQgcHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgYmxvY2sgPSBydW5FbmQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjb21iaW5lZCA9IHBhcnRzLmxlbmd0aCA9PT0gMSAmJiBwYXJ0c1swXSB8fCBCdWZmZXIuY29uY2F0KHBhcnRzKTtcbiAgICAgICAgICAgIGxldCBzbGljZVN0YXJ0ID0gc3RhcnQgLSBmaXJzdEJsb2NrICogYmxvY2tTaXplO1xuICAgICAgICAgICAgLy8gQSBzaG9ydCBjb21iaW5lZCBidWZmZXIgbWVhbnMgd2UgbG9zdCBibG9ja3M7IHN1YmFycmF5IHdvdWxkIGNsYW1wIGFuZCBoYW5kIGJhY2tcbiAgICAgICAgICAgIC8vIHRydW5jYXRlZCBkYXRhIHRoYXQgZXZlcnkgY2FsbGVyIHRyZWF0cyBhcyB2YWxpZC4gRmFpbCBsb3VkbHkgaW5zdGVhZC5cbiAgICAgICAgICAgIGlmIChjb21iaW5lZC5sZW5ndGggPCBzbGljZVN0YXJ0ICsgKGVuZCAtIHN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHtzbGljZVN0YXJ0ICsgKGVuZCAtIHN0YXJ0KX0gYnl0ZXMgb2YgYmxvY2tzIGZvciByYW5nZSBbJHtzdGFydH0sICR7ZW5kfSkgb2YgJHtmaWxlSWR9LCB3YXMgJHtjb21iaW5lZC5sZW5ndGh9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29tYmluZWQuc3ViYXJyYXkoc2xpY2VTdGFydCwgc2xpY2VTdGFydCArIChlbmQgLSBzdGFydCkpO1xuICAgICAgICB9O1xuICAgIH1cbn1cblxuLy8gU2hhcmVkIGFjcm9zcyBldmVyeSBCdWxrRGF0YWJhc2UyIGNvbGxlY3Rpb24vZmlsZSAodGhlIDUxMk1CIGJ1ZGdldCBpcyBnbG9iYWwpLlxuZXhwb3J0IGNvbnN0IGJsb2NrQ2FjaGUgPSBuZXcgQmxvY2tDYWNoZSgpO1xuIl19
179
+ /* _JS_SOURCE_HASH = "9a96e6fce74c45d2fc49828b785a0df0b264d6ff85be9746eacf6c58d523ce37"; */
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ // Best-effort "only one tab merges this collection at a time" guard. This is purely an efficiency
3
+ // measure: correctness does NOT depend on it. Reads resolve by per-row write-time, merges write new
4
+ // files before deleting consumed ones, and a duplicate-heavy region gets re-merged — so two tabs
5
+ // merging at once only waste work and briefly duplicate data, never corrupt or lose it. The lock just
6
+ // stops that wasted work. It uses localStorage (shared across same-origin tabs) and is a no-op where
7
+ // localStorage is unavailable (Node) — there concurrent merges are harmless, which the Node stress
8
+ // tests exercise. localStorage has no atomic compare-and-swap, so we write-then-reread to shrink the
9
+ // race window, and a TTL frees a lock left behind by a tab that crashed or closed mid-merge.
10
+ //
11
+ // File-lock layer (see acquireMergeFileLock at the bottom): for cross-PROCESS safety (different
12
+ // browsers, different machines pointing at the same remote storage), we ALSO write a `.merge-lock`
13
+ // file inside the collection's storage with our ID. The protocol is check-write-wait-recheck — last
14
+ // writer wins after the 15s settle window. The localStorage lock above covers same-origin tabs; this
15
+ // covers everything else (separate processes, remote shared storage).
16
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
17
+ exports.releaseMergeFileLock = exports.startMergeFileLockHeartbeat = exports.tryAcquireMergeFileLock = exports.peekMergeFileLock = exports.releaseMergeLock = exports.peekMergeLock = exports.tryAcquireMergeLock = void 0;
18
+ const LOCK_TTL_MS = 30 * 1000;
19
+ function parseLockToken(token) {
20
+ const colon = token.lastIndexOf(":");
21
+ if (colon < 0)
22
+ return undefined;
23
+ const time = parseInt(token.slice(colon + 1), 10);
24
+ if (!Number.isFinite(time))
25
+ return undefined;
26
+ return { holderId: token.slice(0, colon), time };
27
+ }
28
+ function getLocalStorage() {
29
+ try {
30
+ return typeof localStorage !== "undefined" ? localStorage : undefined;
31
+ }
32
+ catch (_a) {
33
+ return undefined; // accessing localStorage can throw (e.g. disabled cookies)
34
+ }
35
+ }
36
+ function lockKey(collection) {
37
+ return "bulkDatabase2-merge:" + collection;
38
+ }
39
+ // Returns true if we now hold the lock (or there's no localStorage to coordinate through, in which case
40
+ // we proceed — concurrent merges are harmless). Returns false only if a DIFFERENT holder has a fresh
41
+ // lock. Re-stamping our own lock always succeeds, so this doubles as a heartbeat: call it periodically
42
+ // during a long, spaced-out merge to keep the lock alive (and detect if another tab took it over).
43
+ function tryAcquireMergeLock(collection, holderId) {
44
+ const ls = getLocalStorage();
45
+ if (!ls)
46
+ return true;
47
+ const key = lockKey(collection);
48
+ const now = Date.now();
49
+ const existing = ls.getItem(key);
50
+ if (existing && !existing.startsWith(holderId + ":")) {
51
+ const parsed = parseLockToken(existing);
52
+ if (parsed && now - parsed.time < LOCK_TTL_MS)
53
+ return false;
54
+ }
55
+ const token = holderId + ":" + now;
56
+ ls.setItem(key, token);
57
+ // Re-read to catch a racing setItem from another tab (best-effort, not atomic).
58
+ return ls.getItem(key) === token;
59
+ }
60
+ exports.tryAcquireMergeLock = tryAcquireMergeLock;
61
+ // Non-mutating look at the tab lock: who holds it and how long until it goes stale (negative = already
62
+ // stale). For logging why a merge was skipped.
63
+ function peekMergeLock(collection) {
64
+ const ls = getLocalStorage();
65
+ if (!ls)
66
+ return undefined;
67
+ const existing = ls.getItem(lockKey(collection));
68
+ if (!existing)
69
+ return undefined;
70
+ const parsed = parseLockToken(existing);
71
+ if (!parsed)
72
+ return undefined;
73
+ return { holderId: parsed.holderId, expiresInMs: parsed.time + LOCK_TTL_MS - Date.now() };
74
+ }
75
+ exports.peekMergeLock = peekMergeLock;
76
+ function releaseMergeLock(collection, holderId) {
77
+ const ls = getLocalStorage();
78
+ if (!ls)
79
+ return;
80
+ const key = lockKey(collection);
81
+ const existing = ls.getItem(key);
82
+ if (existing && existing.startsWith(holderId + ":"))
83
+ ls.removeItem(key);
84
+ }
85
+ exports.releaseMergeLock = releaseMergeLock;
86
+ // ── File-based lock (cross-process / shared storage) ──────────────────────────────────────────────
87
+ const FILE_LOCK_KEY = ".merge-lock";
88
+ const FILE_LOCK_TTL_MS = 5 * 60 * 1000;
89
+ const FILE_LOCK_SETTLE_MS = 15 * 1000;
90
+ const FILE_LOCK_HEARTBEAT_MS = 2 * 60 * 1000;
91
+ async function readMergeFileLock(storage) {
92
+ try {
93
+ const buf = await storage.get(FILE_LOCK_KEY);
94
+ if (!buf)
95
+ return undefined;
96
+ return parseLockToken(buf.toString("utf8"));
97
+ }
98
+ catch (_a) {
99
+ return undefined;
100
+ }
101
+ }
102
+ // Non-mutating look at the cross-process lock file (see peekMergeLock).
103
+ async function peekMergeFileLock(storage) {
104
+ const existing = await readMergeFileLock(storage);
105
+ if (!existing)
106
+ return undefined;
107
+ return { holderId: existing.holderId, expiresInMs: existing.time + FILE_LOCK_TTL_MS - Date.now() };
108
+ }
109
+ exports.peekMergeFileLock = peekMergeFileLock;
110
+ async function writeMergeFileLock(storage, holderId, time) {
111
+ await storage.set(FILE_LOCK_KEY, Buffer.from(`${holderId}:${time}`, "utf8"));
112
+ }
113
+ // Acquire the cross-process file lock. Resolves to true ONLY if, after writing our ID and waiting
114
+ // FILE_LOCK_SETTLE_MS for concurrent writers to settle, the file still names us. Caller must
115
+ // releaseMergeFileLock() on the same storage + holderId when done.
116
+ async function tryAcquireMergeFileLock(storage, holderId) {
117
+ const now = Date.now();
118
+ const existing = await readMergeFileLock(storage);
119
+ if (existing && existing.holderId !== holderId && now - existing.time < FILE_LOCK_TTL_MS)
120
+ return false;
121
+ await writeMergeFileLock(storage, holderId, now);
122
+ await new Promise(r => setTimeout(r, FILE_LOCK_SETTLE_MS));
123
+ const after = await readMergeFileLock(storage);
124
+ return !!after && after.holderId === holderId;
125
+ }
126
+ exports.tryAcquireMergeFileLock = tryAcquireMergeFileLock;
127
+ // Keep the lock fresh. The merge might run longer than FILE_LOCK_TTL_MS; without periodic re-stamping,
128
+ // another process would see the lock as stale and acquire it. Returns a stop function the caller calls
129
+ // in `finally`. Heartbeat is best-effort: a failed write is logged but not propagated.
130
+ function startMergeFileLockHeartbeat(storage, holderId) {
131
+ var _a, _b;
132
+ const interval = setInterval(() => {
133
+ void writeMergeFileLock(storage, holderId, Date.now()).catch(() => { });
134
+ }, FILE_LOCK_HEARTBEAT_MS);
135
+ (_b = (_a = interval).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
136
+ return () => clearInterval(interval);
137
+ }
138
+ exports.startMergeFileLockHeartbeat = startMergeFileLockHeartbeat;
139
+ async function releaseMergeFileLock(storage, holderId) {
140
+ try {
141
+ const existing = await readMergeFileLock(storage);
142
+ if (existing && existing.holderId === holderId)
143
+ await storage.remove(FILE_LOCK_KEY);
144
+ }
145
+ catch ( /* ignore */_a) { /* ignore */ }
146
+ }
147
+ exports.releaseMergeFileLock = releaseMergeFileLock;
148
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVyZ2VMb2NrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWVyZ2VMb2NrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxrR0FBa0c7QUFDbEcsb0dBQW9HO0FBQ3BHLGlHQUFpRztBQUNqRyxzR0FBc0c7QUFDdEcscUdBQXFHO0FBQ3JHLG1HQUFtRztBQUNuRyxxR0FBcUc7QUFDckcsNkZBQTZGO0FBQzdGLEVBQUU7QUFDRixnR0FBZ0c7QUFDaEcsbUdBQW1HO0FBQ25HLG9HQUFvRztBQUNwRyxxR0FBcUc7QUFDckcsc0VBQXNFOzs7QUFJdEUsTUFBTSxXQUFXLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUk5QixTQUFTLGNBQWMsQ0FBQyxLQUFhO0lBQ2pDLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsSUFBSSxLQUFLLEdBQUcsQ0FBQztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ2hDLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsRCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUM3QyxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDO0FBQ3JELENBQUM7QUFFRCxTQUFTLGVBQWU7SUFDcEIsSUFBSSxDQUFDO1FBQ0QsT0FBTyxPQUFPLFlBQVksS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQzFFLENBQUM7SUFBQyxXQUFNLENBQUM7UUFDTCxPQUFPLFNBQVMsQ0FBQyxDQUFDLDJEQUEyRDtJQUNqRixDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMs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QUMsUUFBUSxLQUFLLFFBQVE7WUFBRSxNQUFNLE9BQU8sQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDeEYsQ0FBQztJQUFDLFFBQVEsWUFBWSxJQUFkLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUM1QixDQUFDO0FBTEQsb0RBS0MiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBCZXN0LWVmZm9ydCBcIm9ubHkgb25lIHRhYiBtZXJnZXMgdGhpcyBjb2xsZWN0aW9uIGF0IGEgdGltZVwiIGd1YXJkLiBUaGlzIGlzIHB1cmVseSBhbiBlZmZpY2llbmN5XG4vLyBtZWFzdXJlOiBjb3JyZWN0bmVzcyBkb2VzIE5PVCBkZXBlbmQgb24gaXQuIFJlYWRzIHJlc29sdmUgYnkgcGVyLXJvdyB3cml0ZS10aW1lLCBtZXJnZXMgd3JpdGUgbmV3XG4vLyBmaWxlcyBiZWZvcmUgZGVsZXRpbmcgY29uc3VtZWQgb25lcywgYW5kIGEgZHVwbGljYXRlLWhlYXZ5IHJlZ2lvbiBnZXRzIHJlLW1lcmdlZCDigJQgc28gdHdvIHRhYnNcbi8vIG1lcmdpbmcgYXQgb25jZSBvbmx5IHdhc3RlIHdvcmsgYW5kIGJyaWVmbHkgZHVwbGljYXRlIGRhdGEsIG5ldmVyIGNvcnJ1cHQgb3IgbG9zZSBpdC4gVGhlIGxvY2sganVzdFxuLy8gc3RvcHMgdGhhdCB3YXN0ZWQgd29yay4gSXQgdXNlcyBsb2NhbFN0b3JhZ2UgKHNoYXJlZCBhY3Jvc3Mgc2FtZS1vcmlnaW4gdGFicykgYW5kIGlzIGEgbm8tb3Agd2hlcmVcbi8vIGxvY2FsU3RvcmFnZSBpcyB1bmF2YWlsYWJsZSAoTm9kZSkg4oCUIHRoZXJlIGNvbmN1cnJlbnQgbWVyZ2VzIGFyZSBoYXJtbGVzcywgd2hpY2ggdGhlIE5vZGUgc3RyZXNzXG4vLyB0ZXN0cyBleGVyY2lzZS4gbG9jYWxTdG9yYWdlIGhhcyBubyBhdG9taWMgY29tcGFyZS1hbmQtc3dhcCwgc28gd2Ugd3JpdGUtdGhlbi1yZXJlYWQgdG8gc2hyaW5rIHRoZVxuLy8gcmFjZSB3aW5kb3csIGFuZCBhIFRUTCBmcmVlcyBhIGxvY2sgbGVmdCBiZWhpbmQgYnkgYSB0YWIgdGhhdCBjcmFzaGVkIG9yIGNsb3NlZCBtaWQtbWVyZ2UuXG4vL1xuLy8gRmlsZS1sb2NrIGxheWVyIChzZWUgYWNxdWlyZU1lcmdlRmlsZUxvY2sgYXQgdGhlIGJvdHRvbSk6IGZvciBjcm9zcy1QUk9DRVNTIHNhZmV0eSAoZGlmZmVyZW50XG4vLyBicm93c2VycywgZGlmZmVyZW50IG1hY2hpbmVzIHBvaW50aW5nIGF0IHRoZSBzYW1lIHJlbW90ZSBzdG9yYWdlKSwgd2UgQUxTTyB3cml0ZSBhIGAubWVyZ2UtbG9ja2Bcbi8vIGZpbGUgaW5zaWRlIHRoZSBjb2xsZWN0aW9uJ3Mgc3RvcmFnZSB3aXRoIG91ciBJRC4gVGhlIHByb3RvY29sIGlzIGNoZWNrLXdyaXRlLXdhaXQtcmVjaGVjayDigJQgbGFzdFxuLy8gd3JpdGVyIHdpbnMgYWZ0ZXIgdGhlIDE1cyBzZXR0bGUgd2luZG93LiBUaGUgbG9jYWxTdG9yYWdlIGxvY2sgYWJvdmUgY292ZXJzIHNhbWUtb3JpZ2luIHRhYnM7IHRoaXNcbi8vIGNvdmVycyBldmVyeXRoaW5nIGVsc2UgKHNlcGFyYXRlIHByb2Nlc3NlcywgcmVtb3RlIHNoYXJlZCBzdG9yYWdlKS5cblxuaW1wb3J0IHR5cGUgeyBGaWxlU3RvcmFnZSB9IGZyb20gXCIuLi9GaWxlRm9sZGVyQVBJXCI7XG5cbmNvbnN0IExPQ0tfVFRMX01TID0gMzAgKiAxMDAwO1xuXG5leHBvcnQgdHlwZSBNZXJnZUxvY2tJbmZvID0geyBob2xkZXJJZDogc3RyaW5nOyBleHBpcmVzSW5NczogbnVtYmVyIH07XG5cbmZ1bmN0aW9uIHBhcnNlTG9ja1Rva2VuKHRva2VuOiBzdHJpbmcpOiB7IGhvbGRlcklkOiBzdHJpbmc7IHRpbWU6IG51bWJlciB9IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjb2xvbiA9IHRva2VuLmxhc3RJbmRleE9mKFwiOlwiKTtcbiAgICBpZiAoY29sb24gPCAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHRpbWUgPSBwYXJzZUludCh0b2tlbi5zbGljZShjb2xvbiArIDEpLCAxMCk7XG4gICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUodGltZSkpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHsgaG9sZGVySWQ6IHRva2VuLnNsaWNlKDAsIGNvbG9uKSwgdGltZSB9O1xufVxuXG5mdW5jdGlvbiBnZXRMb2NhbFN0b3JhZ2UoKTogU3RvcmFnZSB8IHVuZGVmaW5lZCB7XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBsb2NhbFN0b3JhZ2UgIT09IFwidW5kZWZpbmVkXCIgPyBsb2NhbFN0b3JhZ2UgOiB1bmRlZmluZWQ7XG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7IC8vIGFjY2Vzc2luZyBsb2NhbFN0b3JhZ2UgY2FuIHRocm93IChlLmcuIGRpc2FibGVkIGNvb2tpZXMpXG4gICAgfVxufVxuXG5mdW5jdGlvbiBsb2NrS2V5KGNvbGxlY3Rpb246IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFwiYnVsa0RhdGFiYXNlMi1tZXJnZTpcIiArIGNvbGxlY3Rpb247XG59XG5cbi8vIFJldHVybnMgdHJ1ZSBpZiB3ZSBub3cgaG9sZCB0aGUgbG9jayAob3IgdGhlcmUncyBubyBsb2NhbFN0b3JhZ2UgdG8gY29vcmRpbmF0ZSB0aHJvdWdoLCBpbiB3aGljaCBjYXNlXG4vLyB3ZSBwcm9jZWVkIOKAlCBjb25jdXJyZW50IG1lcmdlcyBhcmUgaGFybWxlc3MpLiBSZXR1cm5zIGZhbHNlIG9ubHkgaWYgYSBESUZGRVJFTlQgaG9sZGVyIGhhcyBhIGZyZXNoXG4vLyBsb2NrLiBSZS1zdGFtcGluZyBvdXIgb3duIGxvY2sgYWx3YXlzIHN1Y2NlZWRzLCBzbyB0aGlzIGRvdWJsZXMgYXMgYSBoZWFydGJlYXQ6IGNhbGwgaXQgcGVyaW9kaWNhbGx5XG4vLyBkdXJpbmcgYSBsb25nLCBzcGFjZWQtb3V0IG1lcmdlIHRvIGtlZXAgdGhlIGxvY2sgYWxpdmUgKGFuZCBkZXRlY3QgaWYgYW5vdGhlciB0YWIgdG9vayBpdCBvdmVyKS5cbmV4cG9ydCBmdW5jdGlvbiB0cnlBY3F1aXJlTWVyZ2VMb2NrKGNvbGxlY3Rpb246IHN0cmluZywgaG9sZGVySWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGxzID0gZ2V0TG9jYWxTdG9yYWdlKCk7XG4gICAgaWYgKCFscykgcmV0dXJuIHRydWU7XG4gICAgY29uc3Qga2V5ID0gbG9ja0tleShjb2xsZWN0aW9uKTtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IGV4aXN0aW5nID0gbHMuZ2V0SXRlbShrZXkpO1xuICAgIGlmIChleGlzdGluZyAmJiAhZXhpc3Rpbmcuc3RhcnRzV2l0aChob2xkZXJJZCArIFwiOlwiKSkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUxvY2tUb2tlbihleGlzdGluZyk7XG4gICAgICAgIGlmIChwYXJzZWQgJiYgbm93IC0gcGFyc2VkLnRpbWUgPCBMT0NLX1RUTF9NUykgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCB0b2tlbiA9IGhvbGRlcklkICsgXCI6XCIgKyBub3c7XG4gICAgbHMuc2V0SXRlbShrZXksIHRva2VuKTtcbiAgICAvLyBSZS1yZWFkIHRvIGNhdGNoIGEgcmFjaW5nIHNldEl0ZW0gZnJvbSBhbm90aGVyIHRhYiAoYmVzdC1lZmZvcnQsIG5vdCBhdG9taWMpLlxuICAgIHJldHVybiBscy5nZXRJdGVtKGtleSkgPT09IHRva2VuO1xufVxuXG4vLyBOb24tbXV0YXRpbmcgbG9vayBhdCB0aGUgdGFiIGxvY2s6IHdobyBob2xkcyBpdCBhbmQgaG93IGxvbmcgdW50aWwgaXQgZ29lcyBzdGFsZSAobmVnYXRpdmUgPSBhbHJlYWR5XG4vLyBzdGFsZSkuIEZvciBsb2dnaW5nIHdoeSBhIG1lcmdlIHdhcyBza2lwcGVkLlxuZXhwb3J0IGZ1bmN0aW9uIHBlZWtNZXJnZUxvY2soY29sbGVjdGlvbjogc3RyaW5nKTogTWVyZ2VMb2NrSW5mbyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbHMgPSBnZXRMb2NhbFN0b3JhZ2UoKTtcbiAgICBpZiAoIWxzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGV4aXN0aW5nID0gbHMuZ2V0SXRlbShsb2NrS2V5KGNvbGxlY3Rpb24pKTtcbiAgICBpZiAoIWV4aXN0aW5nKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlTG9ja1Rva2VuKGV4aXN0aW5nKTtcbiAgICBpZiAoIXBhcnNlZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4geyBob2xkZXJJZDogcGFyc2VkLmhvbGRlcklkLCBleHBpcmVzSW5NczogcGFyc2VkLnRpbWUgKyBMT0NLX1RUTF9NUyAtIERhdGUubm93KCkgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbGVhc2VNZXJnZUxvY2soY29sbGVjdGlvbjogc3RyaW5nLCBob2xkZXJJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbHMgPSBnZXRMb2NhbFN0b3JhZ2UoKTtcbiAgICBpZiAoIWxzKSByZXR1cm47XG4gICAgY29uc3Qga2V5ID0gbG9ja0tleShjb2xsZWN0aW9uKTtcbiAgICBjb25zdCBleGlzdGluZyA9IGxzLmdldEl0ZW0oa2V5KTtcbiAgICBpZiAoZXhpc3RpbmcgJiYgZXhpc3Rpbmcuc3RhcnRzV2l0aChob2xkZXJJZCArIFwiOlwiKSkgbHMucmVtb3ZlSXRlbShrZXkpO1xufVxuXG4vLyDilIDilIAgRmlsZS1iYXNlZCBsb2NrIChjcm9zcy1wcm9jZXNzIC8gc2hhcmVkIHN0b3JhZ2UpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuY29uc3QgRklMRV9MT0NLX0tFWSA9IFwiLm1lcmdlLWxvY2tcIjtcbmNvbnN0IEZJTEVfTE9DS19UVExfTVMgPSA1ICogNjAgKiAxMDAwO1xuY29uc3QgRklMRV9MT0NLX1NFVFRMRV9NUyA9IDE1ICogMTAwMDtcbmNvbnN0IEZJTEVfTE9DS19IRUFSVEJFQVRfTVMgPSAyICogNjAgKiAxMDAwO1xuXG5hc3luYyBmdW5jdGlvbiByZWFkTWVyZ2VGaWxlTG9jayhzdG9yYWdlOiBGaWxlU3RvcmFnZSk6IFByb21pc2U8eyBob2xkZXJJZDogc3RyaW5nOyB0aW1lOiBudW1iZXIgfSB8IHVuZGVmaW5lZD4ge1xuICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGJ1ZiA9IGF3YWl0IHN0b3JhZ2UuZ2V0KEZJTEVfTE9DS19LRVkpO1xuICAgICAgICBpZiAoIWJ1ZikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIHBhcnNlTG9ja1Rva2VuKGJ1Zi50b1N0cmluZyhcInV0ZjhcIikpO1xuICAgIH0gY2F0Y2ggeyByZXR1cm4gdW5kZWZpbmVkOyB9XG59XG5cbi8vIE5vbi1tdXRhdGluZyBsb29rIGF0IHRoZSBjcm9zcy1wcm9jZXNzIGxvY2sgZmlsZSAoc2VlIHBlZWtNZXJnZUxvY2spLlxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBlZWtNZXJnZUZpbGVMb2NrKHN0b3JhZ2U6IEZpbGVTdG9yYWdlKTogUHJvbWlzZTxNZXJnZUxvY2tJbmZvIHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCByZWFkTWVyZ2VGaWxlTG9jayhzdG9yYWdlKTtcbiAgICBpZiAoIWV4aXN0aW5nKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7IGhvbGRlcklkOiBleGlzdGluZy5ob2xkZXJJZCwgZXhwaXJlc0luTXM6IGV4aXN0aW5nLnRpbWUgKyBGSUxFX0xPQ0tfVFRMX01TIC0gRGF0ZS5ub3coKSB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiB3cml0ZU1lcmdlRmlsZUxvY2soc3RvcmFnZTogRmlsZVN0b3JhZ2UsIGhvbGRlcklkOiBzdHJpbmcsIHRpbWU6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHN0b3JhZ2Uuc2V0KEZJTEVfTE9DS19LRVksIEJ1ZmZlci5mcm9tKGAke2hvbGRlcklkfToke3RpbWV9YCwgXCJ1dGY4XCIpIGFzIEJ1ZmZlcik7XG59XG5cbi8vIEFjcXVpcmUgdGhlIGNyb3NzLXByb2Nlc3MgZmlsZSBsb2NrLiBSZXNvbHZlcyB0byB0cnVlIE9OTFkgaWYsIGFmdGVyIHdyaXRpbmcgb3VyIElEIGFuZCB3YWl0aW5nXG4vLyBGSUxFX0xPQ0tfU0VUVExFX01TIGZvciBjb25jdXJyZW50IHdyaXRlcnMgdG8gc2V0dGxlLCB0aGUgZmlsZSBzdGlsbCBuYW1lcyB1cy4gQ2FsbGVyIG11c3Rcbi8vIHJlbGVhc2VNZXJnZUZpbGVMb2NrKCkgb24gdGhlIHNhbWUgc3RvcmFnZSArIGhvbGRlcklkIHdoZW4gZG9uZS5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB0cnlBY3F1aXJlTWVyZ2VGaWxlTG9jayhzdG9yYWdlOiBGaWxlU3RvcmFnZSwgaG9sZGVySWQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCByZWFkTWVyZ2VGaWxlTG9jayhzdG9yYWdlKTtcbiAgICBpZiAoZXhpc3RpbmcgJiYgZXhpc3RpbmcuaG9sZGVySWQgIT09IGhvbGRlcklkICYmIG5vdyAtIGV4aXN0aW5nLnRpbWUgPCBGSUxFX0xPQ0tfVFRMX01TKSByZXR1cm4gZmFsc2U7XG4gICAgYXdhaXQgd3JpdGVNZXJnZUZpbGVMb2NrKHN0b3JhZ2UsIGhvbGRlcklkLCBub3cpO1xuICAgIGF3YWl0IG5ldyBQcm9taXNlKHIgPT4gc2V0VGltZW91dChyLCBGSUxFX0xPQ0tfU0VUVExFX01TKSk7XG4gICAgY29uc3QgYWZ0ZXIgPSBhd2FpdCByZWFkTWVyZ2VGaWxlTG9jayhzdG9yYWdlKTtcbiAgICByZXR1cm4gISFhZnRlciAmJiBhZnRlci5ob2xkZXJJZCA9PT0gaG9sZGVySWQ7XG59XG5cbi8vIEtlZXAgdGhlIGxvY2sgZnJlc2guIFRoZSBtZXJnZSBtaWdodCBydW4gbG9uZ2VyIHRoYW4gRklMRV9MT0NLX1RUTF9NUzsgd2l0aG91dCBwZXJpb2RpYyByZS1zdGFtcGluZyxcbi8vIGFub3RoZXIgcHJvY2VzcyB3b3VsZCBzZWUgdGhlIGxvY2sgYXMgc3RhbGUgYW5kIGFjcXVpcmUgaXQuIFJldHVybnMgYSBzdG9wIGZ1bmN0aW9uIHRoZSBjYWxsZXIgY2FsbHNcbi8vIGluIGBmaW5hbGx5YC4gSGVhcnRiZWF0IGlzIGJlc3QtZWZmb3J0OiBhIGZhaWxlZCB3cml0ZSBpcyBsb2dnZWQgYnV0IG5vdCBwcm9wYWdhdGVkLlxuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0TWVyZ2VGaWxlTG9ja0hlYXJ0YmVhdChzdG9yYWdlOiBGaWxlU3RvcmFnZSwgaG9sZGVySWQ6IHN0cmluZyk6ICgpID0+IHZvaWQge1xuICAgIGNvbnN0IGludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICB2b2lkIHdyaXRlTWVyZ2VGaWxlTG9jayhzdG9yYWdlLCBob2xkZXJJZCwgRGF0ZS5ub3coKSkuY2F0Y2goKCkgPT4geyAvKiBiZXN0LWVmZm9ydCAqLyB9KTtcbiAgICB9LCBGSUxFX0xPQ0tfSEVBUlRCRUFUX01TKTtcbiAgICAoaW50ZXJ2YWwgYXMgeyB1bnJlZj86ICgpID0+IHZvaWQgfSkudW5yZWY/LigpO1xuICAgIHJldHVybiAoKSA9PiBjbGVhckludGVydmFsKGludGVydmFsKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbGVhc2VNZXJnZUZpbGVMb2NrKHN0b3JhZ2U6IEZpbGVTdG9yYWdlLCBob2xkZXJJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCByZWFkTWVyZ2VGaWxlTG9jayhzdG9yYWdlKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nICYmIGV4aXN0aW5nLmhvbGRlcklkID09PSBob2xkZXJJZCkgYXdhaXQgc3RvcmFnZS5yZW1vdmUoRklMRV9MT0NLX0tFWSk7XG4gICAgfSBjYXRjaCB7IC8qIGlnbm9yZSAqLyB9XG59XG4iXX0=
149
+ /* _JS_SOURCE_HASH = "2aac3ba2f7436a4c1d62546c0460b7653a910453df0d38de41be658805d69ee3"; */
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ // Deletion markers: how a merge retires the input files it consumed WITHOUT deleting them inline.
3
+ //
4
+ // The old approach deleted consumed inputs on a 15-min timer. If the tab closed before the timer fired
5
+ // the inputs survived AND were still read — so the next merge re-merged the same duplicates, forever
6
+ // (the "1739 files, 155GB, 99% duplicate" loop). Markers fix both halves: the consumed inputs are
7
+ // EXCLUDED from reads the moment the marker exists (so they're never re-merged), and their physical
8
+ // deletion is driven off the marker on a later read instead of an in-process timer.
9
+ //
10
+ // A marker names the input files it wants gone (`deleteFiles`) and the output files that supersede them
11
+ // (`replacedBy`). On every read we:
12
+ // 1) exclude every `deleteFiles` entry from the active file set (unconditionally — that's the loop fix);
13
+ // 2) delete a marker's `deleteFiles` once its `replacedBy` outputs all exist OR the marker is older than
14
+ // the grace window (a crash-safety floor so a marker whose outputs never landed still gets cleaned);
15
+ // 3) once a marker's `deleteFiles` are all gone, and the marker has aged past the grace window, delete
16
+ // the marker itself (kept around briefly so a concurrent reader still excludes the files consistently).
17
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
18
+ exports.processDeleteMarkers = exports.markerExclusions = exports.readDeleteMarkers = exports.writeDeleteMarker = exports.isMarkerFile = void 0;
19
+ const logColors_1 = require("socket-function/src/formatting/logColors");
20
+ const MARKER_PREFIX = ".delete-marker_";
21
+ const MARKER_GRACE_MS = 5 * 60 * 1000;
22
+ function isMarkerFile(name) {
23
+ return name.startsWith(MARKER_PREFIX);
24
+ }
25
+ exports.isMarkerFile = isMarkerFile;
26
+ async function writeDeleteMarker(storage, config) {
27
+ const time = Date.now();
28
+ const name = `${MARKER_PREFIX}${time}_${Math.random().toString(36).slice(2, 10)}`;
29
+ const body = JSON.stringify({ deleteFiles: config.deleteFiles, replacedBy: config.replacedBy, time });
30
+ await storage.set(name, Buffer.from(body, "utf8"));
31
+ }
32
+ exports.writeDeleteMarker = writeDeleteMarker;
33
+ async function readDeleteMarkers(storage, allNames) {
34
+ const markerNames = allNames.filter(isMarkerFile);
35
+ const markers = await Promise.all(markerNames.map(async (fileName) => {
36
+ try {
37
+ const buf = await storage.get(fileName);
38
+ if (!buf)
39
+ return undefined;
40
+ const parsed = JSON.parse(buf.toString("utf8"));
41
+ if (!Array.isArray(parsed.deleteFiles) || !Array.isArray(parsed.replacedBy))
42
+ return undefined;
43
+ return {
44
+ fileName,
45
+ deleteFiles: parsed.deleteFiles,
46
+ replacedBy: parsed.replacedBy,
47
+ time: typeof parsed.time === "number" ? parsed.time : 0,
48
+ };
49
+ }
50
+ catch (_a) {
51
+ return undefined;
52
+ }
53
+ }));
54
+ return markers.filter((m) => !!m);
55
+ }
56
+ exports.readDeleteMarkers = readDeleteMarkers;
57
+ // The set of files that any marker wants deleted — these must be dropped from the active read set.
58
+ function markerExclusions(markers) {
59
+ const excluded = new Set();
60
+ for (const m of markers)
61
+ for (const n of m.deleteFiles)
62
+ excluded.add(n);
63
+ return excluded;
64
+ }
65
+ exports.markerExclusions = markerExclusions;
66
+ // Act on each marker (see file header). Idempotent and best-effort: every removal is guarded, so two
67
+ // processes (or two reads) running this at once just race to the same already-correct end state.
68
+ async function processDeleteMarkers(name, storage, markers, allNames) {
69
+ const present = new Set(allNames);
70
+ const now = Date.now();
71
+ for (const marker of markers) {
72
+ const stillPresent = marker.deleteFiles.filter(n => present.has(n));
73
+ if (!stillPresent.length) {
74
+ // The files this marker retired are gone; once it's aged past the grace window, retire the marker too.
75
+ if (now - marker.time > MARKER_GRACE_MS) {
76
+ try {
77
+ await storage.remove(marker.fileName);
78
+ }
79
+ catch ( /* already gone */_a) { /* already gone */ }
80
+ }
81
+ continue;
82
+ }
83
+ const replacedExists = marker.replacedBy.length > 0 && marker.replacedBy.every(n => present.has(n));
84
+ if (replacedExists || now - marker.time > MARKER_GRACE_MS) {
85
+ const reason = replacedExists ? `replacements landed` : `marker aged ${Math.round((now - marker.time) / 1000)}s`;
86
+ let deleted = 0;
87
+ for (const n of stillPresent) {
88
+ try {
89
+ await storage.remove(n);
90
+ deleted++;
91
+ }
92
+ catch ( /* already gone */_b) { /* already gone */ }
93
+ }
94
+ if (deleted)
95
+ console.log(`${(0, logColors_1.blue)(name)} ${(0, logColors_1.magenta)("retire")}: deleted ${deleted} merged-away input file(s) (${reason})`);
96
+ }
97
+ }
98
+ }
99
+ exports.processDeleteMarkers = processDeleteMarkers;
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVyZ2VNYXJrZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWVyZ2VNYXJrZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxrR0FBa0c7QUFDbEcsRUFBRTtBQUNGLHVHQUF1RztBQUN2RyxxR0FBcUc7QUFDckcsa0dBQWtHO0FBQ2xHLG9HQUFvRztBQUNwRyxvRkFBb0Y7QUFDcEYsRUFBRTtBQUNGLHdHQUF3RztBQUN4RyxvQ0FBb0M7QUFDcEMsMkdBQTJHO0FBQzNHLDJHQUEyRztBQUMzRywwR0FBMEc7QUFDMUcseUdBQXlHO0FBQ3pHLDZHQUE2Rzs7O0FBRzdHLHdFQUF5RTtBQUV6RSxNQUFNLGFBQWEsR0FBRyxpQkFBaUIsQ0FBQztBQUN4QyxNQUFNLGVBQWUsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQVN0QyxTQUFnQixZQUFZLENBQUMsSUFBWTtJQUNyQyxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDMUMsQ0FBQztBQUZELG9DQUVDO0FBRU0sS0FBSyxVQUFVLGlCQUFpQixDQUFDLE9BQW9CLEVBQUUsTUFBdUQ7SUFDakgsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3hCLE1BQU0sSUFBSSxHQUFHLEdBQUcsYUFBYSxHQUFHLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUNsRixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0RyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBVyxDQUFDLENBQUM7QUFDakUsQ0FBQztBQUxELDhDQUtDO0FBRU0sS0FBSyxVQUFVLGlCQUFpQixDQUFDLE9BQW9CLEVBQUUsUUFBa0I7SUFDNUUsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNsRCxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFxQyxFQUFFO1FBQ3BHLElBQUksQ0FBQztZQUNELE1BQU0sR0FBRyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN4QyxJQUFJLENBQUMsR0FBRztnQkFBRSxPQUFPLFNBQVMsQ0FBQztZQUMzQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQW9FLENBQUM7WUFDbkgsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDO2dCQUFFLE9BQU8sU0FBUyxDQUFDO1lBQzlGLE9BQU87Z0JBQ0gsUUFBUTtnQkFDUixXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQXVCO2dCQUMzQyxVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQXNCO2dCQUN6QyxJQUFJLEVBQUUsT0FBTyxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUMxRCxDQUFDO1FBQ04sQ0FBQztRQUFDLFdBQU0sQ0FBQztZQUNMLE9BQU8sU0FBUyxDQUFDO1FBQ3JCLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ0osT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFxQixFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3pELENBQUM7QUFuQkQsOENBbUJDO0FBRUQsbUdBQW1HO0FBQ25HLFNBQWdCLGdCQUFnQixDQUFDLE9BQXVCO0lBQ3BELE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDbkMsS0FBSyxNQUFNLENBQUMsSUFBSSxPQUFPO1FBQUUsS0FBSyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsV0FBVztZQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEUsT0FBTyxRQUFRLENBQUM7QUFDcEIsQ0FBQztBQUpELDRDQUlDO0FBRUQscUdBQXFHO0FBQ3JHLGlHQUFpRztBQUMxRixLQUFLLFVBQVUsb0JBQW9CLENBQUMsSUFBWSxFQUFFLE9BQW9CLEVBQUUsT0FBdUIsRUFBRSxRQUFrQjtJQUN0SCxNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNsQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDdkIsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUMzQixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3ZCLHVHQUF1RztZQUN2RyxJQUFJLEdBQUcsR0FBRyxNQUFNLENBQUMsSUFBSSxHQUFHLGVBQWUsRUFBRSxDQUFDO2dCQUN0QyxJQUFJLENBQUM7b0JBQUMsTUFBTSxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFBQyxDQUFDO2dCQUFDLFFBQVEsa0JBQWtCLElBQXBCLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1lBQy9FLENBQUM7WUFDRCxTQUFTO1FBQ2IsQ0FBQztRQUNELE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRyxJQUFJLGNBQWMsSUFBSSxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksR0FBRyxlQUFlLEVBQUUsQ0FBQztZQUN4RCxNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxlQUFlLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7WUFDakgsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO1lBQ2hCLEtBQUssTUFBTSxDQUFDLElBQUksWUFBWSxFQUFFLENBQUM7Z0JBQzNCLElBQUksQ0FBQztvQkFBQyxNQUFNLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQUMsQ0FBQztnQkFBQyxRQUFRLGtCQUFrQixJQUFwQixDQUFDLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUM1RSxDQUFDO1lBQ0QsSUFBSSxPQUFPO2dCQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFBLGdCQUFJLEVBQUMsSUFBSSxDQUFDLElBQUksSUFBQSxtQkFBTyxFQUFDLFFBQVEsQ0FBQyxhQUFhLE9BQU8sK0JBQStCLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDN0gsQ0FBQztJQUNMLENBQUM7QUFDTCxDQUFDO0FBdEJELG9EQXNCQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIERlbGV0aW9uIG1hcmtlcnM6IGhvdyBhIG1lcmdlIHJldGlyZXMgdGhlIGlucHV0IGZpbGVzIGl0IGNvbnN1bWVkIFdJVEhPVVQgZGVsZXRpbmcgdGhlbSBpbmxpbmUuXG4vL1xuLy8gVGhlIG9sZCBhcHByb2FjaCBkZWxldGVkIGNvbnN1bWVkIGlucHV0cyBvbiBhIDE1LW1pbiB0aW1lci4gSWYgdGhlIHRhYiBjbG9zZWQgYmVmb3JlIHRoZSB0aW1lciBmaXJlZFxuLy8gdGhlIGlucHV0cyBzdXJ2aXZlZCBBTkQgd2VyZSBzdGlsbCByZWFkIOKAlCBzbyB0aGUgbmV4dCBtZXJnZSByZS1tZXJnZWQgdGhlIHNhbWUgZHVwbGljYXRlcywgZm9yZXZlclxuLy8gKHRoZSBcIjE3MzkgZmlsZXMsIDE1NUdCLCA5OSUgZHVwbGljYXRlXCIgbG9vcCkuIE1hcmtlcnMgZml4IGJvdGggaGFsdmVzOiB0aGUgY29uc3VtZWQgaW5wdXRzIGFyZVxuLy8gRVhDTFVERUQgZnJvbSByZWFkcyB0aGUgbW9tZW50IHRoZSBtYXJrZXIgZXhpc3RzIChzbyB0aGV5J3JlIG5ldmVyIHJlLW1lcmdlZCksIGFuZCB0aGVpciBwaHlzaWNhbFxuLy8gZGVsZXRpb24gaXMgZHJpdmVuIG9mZiB0aGUgbWFya2VyIG9uIGEgbGF0ZXIgcmVhZCBpbnN0ZWFkIG9mIGFuIGluLXByb2Nlc3MgdGltZXIuXG4vL1xuLy8gQSBtYXJrZXIgbmFtZXMgdGhlIGlucHV0IGZpbGVzIGl0IHdhbnRzIGdvbmUgKGBkZWxldGVGaWxlc2ApIGFuZCB0aGUgb3V0cHV0IGZpbGVzIHRoYXQgc3VwZXJzZWRlIHRoZW1cbi8vIChgcmVwbGFjZWRCeWApLiBPbiBldmVyeSByZWFkIHdlOlxuLy8gICAxKSBleGNsdWRlIGV2ZXJ5IGBkZWxldGVGaWxlc2AgZW50cnkgZnJvbSB0aGUgYWN0aXZlIGZpbGUgc2V0ICh1bmNvbmRpdGlvbmFsbHkg4oCUIHRoYXQncyB0aGUgbG9vcCBmaXgpO1xuLy8gICAyKSBkZWxldGUgYSBtYXJrZXIncyBgZGVsZXRlRmlsZXNgIG9uY2UgaXRzIGByZXBsYWNlZEJ5YCBvdXRwdXRzIGFsbCBleGlzdCBPUiB0aGUgbWFya2VyIGlzIG9sZGVyIHRoYW5cbi8vICAgICAgdGhlIGdyYWNlIHdpbmRvdyAoYSBjcmFzaC1zYWZldHkgZmxvb3Igc28gYSBtYXJrZXIgd2hvc2Ugb3V0cHV0cyBuZXZlciBsYW5kZWQgc3RpbGwgZ2V0cyBjbGVhbmVkKTtcbi8vICAgMykgb25jZSBhIG1hcmtlcidzIGBkZWxldGVGaWxlc2AgYXJlIGFsbCBnb25lLCBhbmQgdGhlIG1hcmtlciBoYXMgYWdlZCBwYXN0IHRoZSBncmFjZSB3aW5kb3csIGRlbGV0ZVxuLy8gICAgICB0aGUgbWFya2VyIGl0c2VsZiAoa2VwdCBhcm91bmQgYnJpZWZseSBzbyBhIGNvbmN1cnJlbnQgcmVhZGVyIHN0aWxsIGV4Y2x1ZGVzIHRoZSBmaWxlcyBjb25zaXN0ZW50bHkpLlxuXG5pbXBvcnQgdHlwZSB7IEZpbGVTdG9yYWdlIH0gZnJvbSBcIi4uL0ZpbGVGb2xkZXJBUElcIjtcbmltcG9ydCB7IGJsdWUsIG1hZ2VudGEgfSBmcm9tIFwic29ja2V0LWZ1bmN0aW9uL3NyYy9mb3JtYXR0aW5nL2xvZ0NvbG9yc1wiO1xuXG5jb25zdCBNQVJLRVJfUFJFRklYID0gXCIuZGVsZXRlLW1hcmtlcl9cIjtcbmNvbnN0IE1BUktFUl9HUkFDRV9NUyA9IDUgKiA2MCAqIDEwMDA7XG5cbmV4cG9ydCB0eXBlIERlbGV0ZU1hcmtlciA9IHtcbiAgICBmaWxlTmFtZTogc3RyaW5nO1xuICAgIGRlbGV0ZUZpbGVzOiBzdHJpbmdbXTtcbiAgICByZXBsYWNlZEJ5OiBzdHJpbmdbXTtcbiAgICB0aW1lOiBudW1iZXI7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gaXNNYXJrZXJGaWxlKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBuYW1lLnN0YXJ0c1dpdGgoTUFSS0VSX1BSRUZJWCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZURlbGV0ZU1hcmtlcihzdG9yYWdlOiBGaWxlU3RvcmFnZSwgY29uZmlnOiB7IGRlbGV0ZUZpbGVzOiBzdHJpbmdbXTsgcmVwbGFjZWRCeTogc3RyaW5nW10gfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IG5hbWUgPSBgJHtNQVJLRVJfUFJFRklYfSR7dGltZX1fJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyLCAxMCl9YDtcbiAgICBjb25zdCBib2R5ID0gSlNPTi5zdHJpbmdpZnkoeyBkZWxldGVGaWxlczogY29uZmlnLmRlbGV0ZUZpbGVzLCByZXBsYWNlZEJ5OiBjb25maWcucmVwbGFjZWRCeSwgdGltZSB9KTtcbiAgICBhd2FpdCBzdG9yYWdlLnNldChuYW1lLCBCdWZmZXIuZnJvbShib2R5LCBcInV0ZjhcIikgYXMgQnVmZmVyKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWREZWxldGVNYXJrZXJzKHN0b3JhZ2U6IEZpbGVTdG9yYWdlLCBhbGxOYW1lczogc3RyaW5nW10pOiBQcm9taXNlPERlbGV0ZU1hcmtlcltdPiB7XG4gICAgY29uc3QgbWFya2VyTmFtZXMgPSBhbGxOYW1lcy5maWx0ZXIoaXNNYXJrZXJGaWxlKTtcbiAgICBjb25zdCBtYXJrZXJzID0gYXdhaXQgUHJvbWlzZS5hbGwobWFya2VyTmFtZXMubWFwKGFzeW5jIChmaWxlTmFtZSk6IFByb21pc2U8RGVsZXRlTWFya2VyIHwgdW5kZWZpbmVkPiA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBidWYgPSBhd2FpdCBzdG9yYWdlLmdldChmaWxlTmFtZSk7XG4gICAgICAgICAgICBpZiAoIWJ1ZikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoYnVmLnRvU3RyaW5nKFwidXRmOFwiKSkgYXMgeyBkZWxldGVGaWxlcz86IHVua25vd247IHJlcGxhY2VkQnk/OiB1bmtub3duOyB0aW1lPzogdW5rbm93biB9O1xuICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHBhcnNlZC5kZWxldGVGaWxlcykgfHwgIUFycmF5LmlzQXJyYXkocGFyc2VkLnJlcGxhY2VkQnkpKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmaWxlTmFtZSxcbiAgICAgICAgICAgICAgICBkZWxldGVGaWxlczogcGFyc2VkLmRlbGV0ZUZpbGVzIGFzIHN0cmluZ1tdLFxuICAgICAgICAgICAgICAgIHJlcGxhY2VkQnk6IHBhcnNlZC5yZXBsYWNlZEJ5IGFzIHN0cmluZ1tdLFxuICAgICAgICAgICAgICAgIHRpbWU6IHR5cGVvZiBwYXJzZWQudGltZSA9PT0gXCJudW1iZXJcIiA/IHBhcnNlZC50aW1lIDogMCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH0pKTtcbiAgICByZXR1cm4gbWFya2Vycy5maWx0ZXIoKG0pOiBtIGlzIERlbGV0ZU1hcmtlciA9PiAhIW0pO1xufVxuXG4vLyBUaGUgc2V0IG9mIGZpbGVzIHRoYXQgYW55IG1hcmtlciB3YW50cyBkZWxldGVkIOKAlCB0aGVzZSBtdXN0IGJlIGRyb3BwZWQgZnJvbSB0aGUgYWN0aXZlIHJlYWQgc2V0LlxuZXhwb3J0IGZ1bmN0aW9uIG1hcmtlckV4Y2x1c2lvbnMobWFya2VyczogRGVsZXRlTWFya2VyW10pOiBTZXQ8c3RyaW5nPiB7XG4gICAgY29uc3QgZXhjbHVkZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IG0gb2YgbWFya2VycykgZm9yIChjb25zdCBuIG9mIG0uZGVsZXRlRmlsZXMpIGV4Y2x1ZGVkLmFkZChuKTtcbiAgICByZXR1cm4gZXhjbHVkZWQ7XG59XG5cbi8vIEFjdCBvbiBlYWNoIG1hcmtlciAoc2VlIGZpbGUgaGVhZGVyKS4gSWRlbXBvdGVudCBhbmQgYmVzdC1lZmZvcnQ6IGV2ZXJ5IHJlbW92YWwgaXMgZ3VhcmRlZCwgc28gdHdvXG4vLyBwcm9jZXNzZXMgKG9yIHR3byByZWFkcykgcnVubmluZyB0aGlzIGF0IG9uY2UganVzdCByYWNlIHRvIHRoZSBzYW1lIGFscmVhZHktY29ycmVjdCBlbmQgc3RhdGUuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0RlbGV0ZU1hcmtlcnMobmFtZTogc3RyaW5nLCBzdG9yYWdlOiBGaWxlU3RvcmFnZSwgbWFya2VyczogRGVsZXRlTWFya2VyW10sIGFsbE5hbWVzOiBzdHJpbmdbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHByZXNlbnQgPSBuZXcgU2V0KGFsbE5hbWVzKTtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGZvciAoY29uc3QgbWFya2VyIG9mIG1hcmtlcnMpIHtcbiAgICAgICAgY29uc3Qgc3RpbGxQcmVzZW50ID0gbWFya2VyLmRlbGV0ZUZpbGVzLmZpbHRlcihuID0+IHByZXNlbnQuaGFzKG4pKTtcbiAgICAgICAgaWYgKCFzdGlsbFByZXNlbnQubGVuZ3RoKSB7XG4gICAgICAgICAgICAvLyBUaGUgZmlsZXMgdGhpcyBtYXJrZXIgcmV0aXJlZCBhcmUgZ29uZTsgb25jZSBpdCdzIGFnZWQgcGFzdCB0aGUgZ3JhY2Ugd2luZG93LCByZXRpcmUgdGhlIG1hcmtlciB0b28uXG4gICAgICAgICAgICBpZiAobm93IC0gbWFya2VyLnRpbWUgPiBNQVJLRVJfR1JBQ0VfTVMpIHtcbiAgICAgICAgICAgICAgICB0cnkgeyBhd2FpdCBzdG9yYWdlLnJlbW92ZShtYXJrZXIuZmlsZU5hbWUpOyB9IGNhdGNoIHsgLyogYWxyZWFkeSBnb25lICovIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJlcGxhY2VkRXhpc3RzID0gbWFya2VyLnJlcGxhY2VkQnkubGVuZ3RoID4gMCAmJiBtYXJrZXIucmVwbGFjZWRCeS5ldmVyeShuID0+IHByZXNlbnQuaGFzKG4pKTtcbiAgICAgICAgaWYgKHJlcGxhY2VkRXhpc3RzIHx8IG5vdyAtIG1hcmtlci50aW1lID4gTUFSS0VSX0dSQUNFX01TKSB7XG4gICAgICAgICAgICBjb25zdCByZWFzb24gPSByZXBsYWNlZEV4aXN0cyA/IGByZXBsYWNlbWVudHMgbGFuZGVkYCA6IGBtYXJrZXIgYWdlZCAke01hdGgucm91bmQoKG5vdyAtIG1hcmtlci50aW1lKSAvIDEwMDApfXNgO1xuICAgICAgICAgICAgbGV0IGRlbGV0ZWQgPSAwO1xuICAgICAgICAgICAgZm9yIChjb25zdCBuIG9mIHN0aWxsUHJlc2VudCkge1xuICAgICAgICAgICAgICAgIHRyeSB7IGF3YWl0IHN0b3JhZ2UucmVtb3ZlKG4pOyBkZWxldGVkKys7IH0gY2F0Y2ggeyAvKiBhbHJlYWR5IGdvbmUgKi8gfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRlbGV0ZWQpIGNvbnNvbGUubG9nKGAke2JsdWUobmFtZSl9ICR7bWFnZW50YShcInJldGlyZVwiKX06IGRlbGV0ZWQgJHtkZWxldGVkfSBtZXJnZWQtYXdheSBpbnB1dCBmaWxlKHMpICgke3JlYXNvbn0pYCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=
101
+ /* _JS_SOURCE_HASH = "77027f83d4d551a0568e2117f614c13ae4cac060aa7870e7357bbda2526ff717"; */