sliftutils 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursorrules +2 -0
- package/.gitignore +38 -0
- package/assets/icon128.png +0 -0
- package/assets/icon16.png +0 -0
- package/assets/icon48.png +0 -0
- package/build-electron/assets/icon128.png +0 -0
- package/build-electron/assets/icon16.png +0 -0
- package/build-electron/assets/icon48.png +0 -0
- package/build-electron/electron/electronIndex.html +12 -0
- package/build-electron/electronMain.js +5185 -0
- package/build-electron/electronRenderer.js +20852 -0
- package/build-extension/assets/icon128.png +0 -0
- package/build-extension/assets/icon16.png +0 -0
- package/build-extension/assets/icon48.png +0 -0
- package/build-extension/extBackground.js +5246 -0
- package/build-extension/extContentScript.js +5243 -0
- package/build-extension/manifest.json +29 -0
- package/build-nodejs/server.js +198610 -0
- package/build-web/assets/icon128.png +0 -0
- package/build-web/assets/icon16.png +0 -0
- package/build-web/assets/icon48.png +0 -0
- package/build-web/browser.js +199266 -0
- package/build-web/web/index.html +32 -0
- package/builders/dist/electronBuild.ts.cache +105 -0
- package/builders/dist/extensionBuild.ts.cache +146 -0
- package/builders/dist/generateIndexDts.ts.cache +74 -0
- package/builders/dist/hotReload.ts.cache +93 -0
- package/builders/dist/nodeJSBuild.ts.cache +29 -0
- package/builders/dist/watch.ts.cache +163 -0
- package/builders/dist/webBuild.ts.cache +81 -0
- package/builders/generateIndexDts.ts +63 -0
- package/bundler/dist/bundleEntry.ts.cache +48 -0
- package/bundler/dist/bundleEntryCaller.ts.cache +18 -0
- package/bundler/dist/bundleRequire.ts.cache +246 -0
- package/bundler/dist/bundleWrapper.ts.cache +101 -0
- package/bundler/dist/bundler.ts.cache +66 -0
- package/bundler/dist/sourceMaps.ts.cache +210 -0
- package/dist/electronMain.ts.cache +27 -0
- package/dist/electronRenderer.tsx.cache +62 -0
- package/electron/dist/electronMain.ts.cache +26 -0
- package/electron/dist/electronRenderer.tsx.cache +64 -0
- package/extension/dist/extBackground.ts.cache +20 -0
- package/extension/dist/extContentScript.ts.cache +17 -0
- package/index.d.ts +46 -0
- package/misc/dist/environment.ts.cache +50 -0
- package/misc/dist/fs.ts.cache +29 -0
- package/misc/environment.d.ts +8 -0
- package/misc/fs.d.ts +1 -0
- package/misc/getSecret.d.ts +8 -0
- package/misc/getSecret.ts +0 -4
- package/misc/types.d.ts +1 -0
- package/misc/zip.d.ts +7 -0
- package/nodejs/dist/exampleFile.ts.cache +11 -0
- package/nodejs/dist/server.ts.cache +15 -0
- package/package.json +8 -3
- package/render-utils/SyncedController.d.ts +1 -0
- package/render-utils/dist/observer.tsx.cache +33 -0
- package/storage/dist/CachedStorage.ts.cache +31 -0
- package/storage/dist/DelayedStorage.ts.cache +35 -0
- package/storage/dist/DiskCollection.ts.cache +241 -0
- package/storage/dist/FileFolderAPI.tsx.cache +345 -0
- package/storage/dist/IndexedDBFileFolderAPI.ts.cache +142 -0
- package/storage/dist/JSONStorage.ts.cache +38 -0
- package/storage/dist/PendingManager.tsx.cache +73 -0
- package/storage/dist/PendingStorage.ts.cache +49 -0
- package/storage/dist/PrivateFileSystemStorage.ts.cache +178 -0
- package/storage/dist/StorageObservable.ts.cache +120 -0
- package/storage/dist/TransactionStorage.ts.cache +421 -0
- package/storage/dist/fileSystemPointer.ts.cache +77 -0
- package/tsconfig.declarations.json +3 -1
- package/web/dist/browser.tsx.cache +66 -0
- package/yarn.lock +1752 -0
- package/builders/generateIndexDts.js +0 -50
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
3
|
+
//exports.TransactionStorage = void 0;
|
|
4
|
+
const misc_1 = require("socket-function/src/misc");
|
|
5
|
+
const zip_1 = require("../misc/zip");
|
|
6
|
+
const batching_1 = require("socket-function/src/batching");
|
|
7
|
+
const format_1 = require("socket-function/src/formatting/format");
|
|
8
|
+
const PendingManager_1 = require("./PendingManager");
|
|
9
|
+
const buildFlag_1 = require("../../buildFlag");
|
|
10
|
+
/*
|
|
11
|
+
// Spec:
|
|
12
|
+
// - Zip individual large values
|
|
13
|
+
// - Stores a transaction log
|
|
14
|
+
// - Transaction log has a header, which is JSON, for things such as "zipped"
|
|
15
|
+
// - Transaction log uses length prefixed values, with a special 8 bytes to denote the end,
|
|
16
|
+
// and 8 for the start.
|
|
17
|
+
// - When transaction log is iterated on, if the bytes at the end (using the length prefix)
|
|
18
|
+
// don't match the end bytes OR the start bytes are wrong, we skip the start bytes,
|
|
19
|
+
// and iterating until we find new start bytes that match our special bytes. Then we try
|
|
20
|
+
// to read these values.
|
|
21
|
+
// - Each transaction entry has a byte for flags, one bit which denotes if the value is zipped or not.
|
|
22
|
+
// - Compresses the log after there are 3X entries than keys (and > 100)
|
|
23
|
+
// - Both dedupe keys, and zip
|
|
24
|
+
// - Assumes all files in rawStorage ending with .tx are transaction logs
|
|
25
|
+
// - Names files like `${generation}.tx`
|
|
26
|
+
// - When compressing, we increment the generation, and write to a new file, and delete
|
|
27
|
+
// any generations that are older than the new one
|
|
28
|
+
// - On reading, we read from all generation files that exist, in case some are corrupted
|
|
29
|
+
// - On load, loads in all transaction logs, and stores all values in a Map<string, Buffer>
|
|
30
|
+
// - On writes immediately updates the in memory Map, and then writes to the transaction log
|
|
31
|
+
// - Caches the last transaction file name in memory
|
|
32
|
+
// - Makes sure all file system writes (but not Map updates) are done with fileLockSection,
|
|
33
|
+
// so they never overlap.
|
|
34
|
+
// - Buffers pending appends in memory, so they can written all at once (after the first one
|
|
35
|
+
// is blocking in fileLockSection).
|
|
36
|
+
|
|
37
|
+
UPDATE now we use chunks, because append is too slow.
|
|
38
|
+
|
|
39
|
+
IMPORTANT! If there are multiple writers, we clobber writes from other writers when we compress
|
|
40
|
+
*/
|
|
41
|
+
const FILE_CHUNK_SIZE = 1024 * 1024;
|
|
42
|
+
const FILE_ZIP_THRESHOLD = 16 * 1024 * 1024;
|
|
43
|
+
const ZIP_THRESHOLD = 4096;
|
|
44
|
+
const START_BYTES = Buffer.from([236, 49, 112, 121, 27, 127, 227, 63]);
|
|
45
|
+
const END_BYTES = Buffer.from([220, 111, 243, 202, 200, 79, 213, 63]);
|
|
46
|
+
// Delay writes, so we batch better, and thrash the disk less
|
|
47
|
+
const WRITE_DELAY = 500;
|
|
48
|
+
const fileLockSection = (0, batching_1.runInSerial)(async (fnc) => {
|
|
49
|
+
await fnc();
|
|
50
|
+
});
|
|
51
|
+
const CHUNK_EXT = ".chunk";
|
|
52
|
+
const ourId = Date.now() + Math.random();
|
|
53
|
+
class TransactionStorage {
|
|
54
|
+
constructor(rawStorage, debugName, writeDelay = WRITE_DELAY) {
|
|
55
|
+
this.rawStorage = rawStorage;
|
|
56
|
+
this.debugName = debugName;
|
|
57
|
+
this.writeDelay = writeDelay;
|
|
58
|
+
this.cache = new Map();
|
|
59
|
+
this.currentChunk = 0;
|
|
60
|
+
this.currentChunkSize = 0;
|
|
61
|
+
this.entryCount = 0;
|
|
62
|
+
this.init = this.loadAllTransactions();
|
|
63
|
+
this.pendingAppends = [];
|
|
64
|
+
this.extraAppends = 0;
|
|
65
|
+
this.updatePendingAppends = (0, misc_1.throttleFunction)(100, async () => {
|
|
66
|
+
let appendCount = this.pendingAppends.length + this.extraAppends;
|
|
67
|
+
let group = `Transaction (${this.debugName})`;
|
|
68
|
+
//console.log(`Update pending appends ${group}: ${appendCount}`);
|
|
69
|
+
if (!appendCount) {
|
|
70
|
+
(0, PendingManager_1.setPending)(group, "");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
(0, PendingManager_1.setPending)(group, `Pending appends: ${appendCount}`);
|
|
74
|
+
});
|
|
75
|
+
this.compressing = false;
|
|
76
|
+
TransactionStorage.allStorage.push(this);
|
|
77
|
+
}
|
|
78
|
+
// Helps get rid of parse errors which constantly log. Also, uses less space
|
|
79
|
+
static async compressAll() {
|
|
80
|
+
for (let storage of TransactionStorage.allStorage) {
|
|
81
|
+
await storage.compressTransactionLog(true);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
getChunk(chunk) { return `${chunk}_${ourId}${CHUNK_EXT}`; }
|
|
85
|
+
async get(key) {
|
|
86
|
+
await this.init;
|
|
87
|
+
const value = this.cache.get(key);
|
|
88
|
+
if (value && value.isZipped && value.value) {
|
|
89
|
+
value.value = await zip_1.Zip.gunzip(value.value);
|
|
90
|
+
value.isZipped = false;
|
|
91
|
+
}
|
|
92
|
+
return value === null || value === void 0 ? void 0 : value.value;
|
|
93
|
+
}
|
|
94
|
+
async set(key, value) {
|
|
95
|
+
if (this.init)
|
|
96
|
+
await this.init;
|
|
97
|
+
// Time is set on disk write, as Date.now() is too slow
|
|
98
|
+
let entry = { key, value, isZipped: false, time: 0 };
|
|
99
|
+
this.cache.set(key, entry);
|
|
100
|
+
if (value.length >= ZIP_THRESHOLD) {
|
|
101
|
+
value = await zip_1.Zip.gzip(value);
|
|
102
|
+
entry.value = value;
|
|
103
|
+
entry.isZipped = true;
|
|
104
|
+
}
|
|
105
|
+
await this.pushAppend(entry);
|
|
106
|
+
}
|
|
107
|
+
async remove(key) {
|
|
108
|
+
if (this.init)
|
|
109
|
+
await this.init;
|
|
110
|
+
this.cache.delete(key);
|
|
111
|
+
await this.pushAppend({ key, value: undefined, isZipped: false, time: 0 });
|
|
112
|
+
}
|
|
113
|
+
async getInfo(key) {
|
|
114
|
+
await this.init;
|
|
115
|
+
const value = this.cache.get(key);
|
|
116
|
+
if (!(value === null || value === void 0 ? void 0 : value.value))
|
|
117
|
+
return undefined;
|
|
118
|
+
return { size: value.value.length, lastModified: value.time };
|
|
119
|
+
}
|
|
120
|
+
async pushAppend(entry) {
|
|
121
|
+
this.entryCount++;
|
|
122
|
+
this.pendingAppends.push(entry);
|
|
123
|
+
void this.updatePendingAppends();
|
|
124
|
+
if (this.pendingWrite)
|
|
125
|
+
return this.pendingWrite;
|
|
126
|
+
this.pendingWrite = fileLockSection(async () => {
|
|
127
|
+
// Delay to allow batching, and deduping
|
|
128
|
+
await new Promise(resolve => setTimeout(resolve, this.writeDelay));
|
|
129
|
+
let curAppends = this.pendingAppends;
|
|
130
|
+
this.pendingAppends = [];
|
|
131
|
+
this.pendingWrite = undefined;
|
|
132
|
+
{
|
|
133
|
+
let appendsDeduped = new Map();
|
|
134
|
+
for (const entry of curAppends) {
|
|
135
|
+
appendsDeduped.set(entry.key, entry);
|
|
136
|
+
}
|
|
137
|
+
curAppends = Array.from(appendsDeduped.values());
|
|
138
|
+
}
|
|
139
|
+
this.extraAppends += curAppends.length;
|
|
140
|
+
void this.updatePendingAppends();
|
|
141
|
+
if (curAppends.length === 0)
|
|
142
|
+
return;
|
|
143
|
+
try {
|
|
144
|
+
let time = Date.now();
|
|
145
|
+
for (let entry of curAppends) {
|
|
146
|
+
entry.time = time;
|
|
147
|
+
}
|
|
148
|
+
let newSum = 0;
|
|
149
|
+
let buffers = [];
|
|
150
|
+
for (const entry of curAppends) {
|
|
151
|
+
let buffer = this.serializeTransactionEntry(entry);
|
|
152
|
+
buffers.push(buffer);
|
|
153
|
+
newSum += buffer.length;
|
|
154
|
+
}
|
|
155
|
+
let newChunks = this.chunkBuffers(buffers);
|
|
156
|
+
for (let chunk of newChunks) {
|
|
157
|
+
let file = this.getChunk(this.currentChunk);
|
|
158
|
+
if (!await this.rawStorage.get(file)) {
|
|
159
|
+
let { header, headerBuffer } = this.getHeader(false);
|
|
160
|
+
await this.rawStorage.set(file, headerBuffer);
|
|
161
|
+
}
|
|
162
|
+
let content = chunk.buffer;
|
|
163
|
+
await this.rawStorage.append(file, content);
|
|
164
|
+
this.currentChunkSize += content.length;
|
|
165
|
+
if (this.currentChunkSize >= FILE_CHUNK_SIZE) {
|
|
166
|
+
this.currentChunk++;
|
|
167
|
+
this.currentChunkSize = 0;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
await this.compressTransactionLog();
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
this.extraAppends -= curAppends.length;
|
|
174
|
+
void this.updatePendingAppends();
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
await this.pendingWrite;
|
|
178
|
+
}
|
|
179
|
+
async getKeys() {
|
|
180
|
+
if (this.init)
|
|
181
|
+
await this.init;
|
|
182
|
+
return Array.from(this.cache.keys());
|
|
183
|
+
}
|
|
184
|
+
async loadAllTransactions() {
|
|
185
|
+
if ((0, buildFlag_1.isInBuild)())
|
|
186
|
+
return;
|
|
187
|
+
let time = Date.now();
|
|
188
|
+
const keys = await this.rawStorage.getKeys();
|
|
189
|
+
const transactionFiles = keys.filter(key => key.endsWith(CHUNK_EXT));
|
|
190
|
+
(0, misc_1.sort)(transactionFiles, x => parseInt(x));
|
|
191
|
+
let size = 0;
|
|
192
|
+
for (const file of transactionFiles) {
|
|
193
|
+
let chunk = parseInt(file);
|
|
194
|
+
let curSize = await this.loadTransactionFile(file);
|
|
195
|
+
if (chunk >= this.currentChunk) {
|
|
196
|
+
this.currentChunk = chunk;
|
|
197
|
+
this.currentChunkSize = curSize;
|
|
198
|
+
}
|
|
199
|
+
size += curSize;
|
|
200
|
+
}
|
|
201
|
+
time = Date.now() - time;
|
|
202
|
+
if (time > 50) {
|
|
203
|
+
console.log(`Loaded ${this.debugName} in ${(0, format_1.formatTime)(time)}, ${(0, format_1.formatNumber)(this.cache.size)} keys, ${(0, format_1.formatNumber)(size)}B`);
|
|
204
|
+
}
|
|
205
|
+
this.init = undefined;
|
|
206
|
+
}
|
|
207
|
+
async loadTransactionFile(filename) {
|
|
208
|
+
const fullFile = await this.rawStorage.get(filename);
|
|
209
|
+
if (!fullFile)
|
|
210
|
+
return 0;
|
|
211
|
+
if (fullFile.length < 4) {
|
|
212
|
+
//console.error(`Transaction in ${this.debugName} file ${filename} is too small, skipping`);
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
let headerSize = fullFile.readUInt32LE(0);
|
|
216
|
+
let headerBuffer = fullFile.slice(4, 4 + headerSize);
|
|
217
|
+
let header;
|
|
218
|
+
try {
|
|
219
|
+
header = JSON.parse(headerBuffer.toString());
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
console.error(`Failed to parse header of transaction file in ${this.debugName}, ${filename}`);
|
|
223
|
+
return 0;
|
|
224
|
+
}
|
|
225
|
+
let content = fullFile.slice(4 + headerSize);
|
|
226
|
+
if (header.zipped) {
|
|
227
|
+
content = await zip_1.Zip.gunzip(content);
|
|
228
|
+
}
|
|
229
|
+
let offset = 0;
|
|
230
|
+
let entries = [];
|
|
231
|
+
while (offset < content.length) {
|
|
232
|
+
if (!content.slice(offset, offset + START_BYTES.length).equals(START_BYTES)) {
|
|
233
|
+
let s = offset;
|
|
234
|
+
while (offset < content.length && !content.slice(offset, offset + START_BYTES.length).equals(START_BYTES)) {
|
|
235
|
+
offset++;
|
|
236
|
+
}
|
|
237
|
+
let len = offset - s;
|
|
238
|
+
console.warn(`Found bad bytes in ${filename}, skipping ${len} bytes at offset ${s}. Total file bytes ${content.length}, read ${entries.length} entries`);
|
|
239
|
+
if (offset >= content.length)
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
let entryObj;
|
|
243
|
+
try {
|
|
244
|
+
entryObj = this.readTransactionEntry(content, offset);
|
|
245
|
+
}
|
|
246
|
+
catch (e) {
|
|
247
|
+
if (e.message.includes("Read past end of buffer")) {
|
|
248
|
+
offset += 1;
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
throw e;
|
|
252
|
+
}
|
|
253
|
+
if (!entryObj) {
|
|
254
|
+
console.warn(`Failed to read transaction entry in in ${this.debugName}, file ${filename} at offset ${offset}, skipping bad bytes, reading remainder of file`);
|
|
255
|
+
offset++;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
this.entryCount++;
|
|
259
|
+
let { entry } = entryObj;
|
|
260
|
+
offset = entryObj.offset;
|
|
261
|
+
entries.push(entry);
|
|
262
|
+
if (entry.value === undefined) {
|
|
263
|
+
this.cache.delete(entry.key);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
let prev = this.cache.get(entry.key);
|
|
267
|
+
if (prev && (prev.time > entry.time)) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
this.cache.set(entry.key, entry);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return fullFile.length;
|
|
274
|
+
}
|
|
275
|
+
readTransactionEntry(buffer, offset) {
|
|
276
|
+
function readSlice(count) {
|
|
277
|
+
const slice = buffer.slice(offset, offset + count);
|
|
278
|
+
if (slice.length < count)
|
|
279
|
+
throw new Error(`Read past end of buffer at offset ${offset}/${buffer.length}`);
|
|
280
|
+
offset += count;
|
|
281
|
+
return slice;
|
|
282
|
+
}
|
|
283
|
+
if (!readSlice(START_BYTES.length).equals(START_BYTES))
|
|
284
|
+
return undefined;
|
|
285
|
+
const keyLength = readSlice(4).readUInt32LE(0);
|
|
286
|
+
const valueLength = readSlice(4).readUInt32LE(0);
|
|
287
|
+
const time = readSlice(8).readDoubleLE(0);
|
|
288
|
+
const flags = readSlice(1).readUInt8(0);
|
|
289
|
+
const key = readSlice(keyLength).toString();
|
|
290
|
+
let value = readSlice(valueLength);
|
|
291
|
+
if (!readSlice(END_BYTES.length).equals(END_BYTES))
|
|
292
|
+
return undefined;
|
|
293
|
+
let isZipped = (flags & 1) === 1;
|
|
294
|
+
let isDelete = (flags & 2) === 2;
|
|
295
|
+
let entry = { key, value, isZipped, time };
|
|
296
|
+
if (isDelete) {
|
|
297
|
+
entry.value = undefined;
|
|
298
|
+
}
|
|
299
|
+
return { entry, offset };
|
|
300
|
+
}
|
|
301
|
+
// TODO: Make this directly go from TransactionEntry[] to Buffer, by pre-allocating, so it is more efficient
|
|
302
|
+
serializeTransactionEntry(entry) {
|
|
303
|
+
var _a;
|
|
304
|
+
let keyBuffer = Buffer.from(entry.key);
|
|
305
|
+
const buffer = Buffer.alloc(START_BYTES.length + 4 + 4 + 8 + 1 + keyBuffer.length + (((_a = entry.value) === null || _a === void 0 ? void 0 : _a.length) || 0) + END_BYTES.length);
|
|
306
|
+
let offset = 0;
|
|
307
|
+
START_BYTES.copy(buffer, offset);
|
|
308
|
+
offset += START_BYTES.length;
|
|
309
|
+
buffer.writeUInt32LE(keyBuffer.length, offset);
|
|
310
|
+
offset += 4;
|
|
311
|
+
buffer.writeUInt32LE(entry.value ? entry.value.length : 0, offset);
|
|
312
|
+
offset += 4;
|
|
313
|
+
buffer.writeDoubleLE(entry.time, offset);
|
|
314
|
+
offset += 8;
|
|
315
|
+
let flags = 0;
|
|
316
|
+
if (entry.isZipped)
|
|
317
|
+
flags |= 1;
|
|
318
|
+
if (entry.value === undefined)
|
|
319
|
+
flags |= 2;
|
|
320
|
+
buffer.writeUInt8(flags, offset);
|
|
321
|
+
offset += 1;
|
|
322
|
+
keyBuffer.copy(buffer, offset);
|
|
323
|
+
offset += keyBuffer.length;
|
|
324
|
+
if (entry.value) {
|
|
325
|
+
entry.value.copy(buffer, offset);
|
|
326
|
+
offset += entry.value.length;
|
|
327
|
+
}
|
|
328
|
+
END_BYTES.copy(buffer, offset);
|
|
329
|
+
offset += END_BYTES.length;
|
|
330
|
+
return buffer;
|
|
331
|
+
}
|
|
332
|
+
getHeader(zip) {
|
|
333
|
+
const header = { zipped: zip };
|
|
334
|
+
let headerBuffer = Buffer.from(JSON.stringify(header));
|
|
335
|
+
let headerSize = Buffer.alloc(4);
|
|
336
|
+
headerSize.writeUInt32LE(headerBuffer.length, 0);
|
|
337
|
+
return { header, headerBuffer: Buffer.concat([headerSize, headerBuffer]) };
|
|
338
|
+
}
|
|
339
|
+
chunkBuffers(buffers) {
|
|
340
|
+
let newChunks = [];
|
|
341
|
+
newChunks.push({ buffers: [], size: 0 });
|
|
342
|
+
for (const buffer of buffers) {
|
|
343
|
+
if (newChunks[newChunks.length - 1].size + buffer.length >= FILE_CHUNK_SIZE) {
|
|
344
|
+
newChunks.push({ buffers: [], size: 0 });
|
|
345
|
+
}
|
|
346
|
+
newChunks[newChunks.length - 1].buffers.push(buffer);
|
|
347
|
+
newChunks[newChunks.length - 1].size += buffer.length;
|
|
348
|
+
}
|
|
349
|
+
return newChunks.map(x => ({ buffer: Buffer.concat(x.buffers), size: x.size }));
|
|
350
|
+
}
|
|
351
|
+
async compressTransactionLog(force) {
|
|
352
|
+
if (this.compressing)
|
|
353
|
+
return;
|
|
354
|
+
this.compressing = true;
|
|
355
|
+
let existingDiskEntries = await this.rawStorage.getKeys();
|
|
356
|
+
existingDiskEntries = existingDiskEntries.filter(x => x.endsWith(CHUNK_EXT));
|
|
357
|
+
let compressNow = force || (this.entryCount > 100 && this.entryCount > this.cache.size * 3
|
|
358
|
+
// NOTE: This compress check breaks down if we only have very large values, but... those
|
|
359
|
+
// don't work ANYWAYS (it is better to use one file per value instead).
|
|
360
|
+
// - Maybe we should throw, or at least warn, on sets of value > 1MB,
|
|
361
|
+
// at which point they should just use a file per value
|
|
362
|
+
|| existingDiskEntries.length > Math.max(10, Math.ceil(this.entryCount / 1000))
|
|
363
|
+
|| existingDiskEntries.length > 1000 * 10);
|
|
364
|
+
if (!compressNow)
|
|
365
|
+
return;
|
|
366
|
+
console.log(`Compressing ${this.debugName} transaction log, ${this.entryCount} entries, ${this.cache.size} keys`);
|
|
367
|
+
// Load off disk, in case there are other writes. We still race with them, but at least
|
|
368
|
+
// this reduces the race condition considerably
|
|
369
|
+
(0, misc_1.sort)(existingDiskEntries, x => parseInt(x));
|
|
370
|
+
for (let entry of existingDiskEntries) {
|
|
371
|
+
await this.loadTransactionFile(entry);
|
|
372
|
+
}
|
|
373
|
+
this.entryCount = this.cache.size;
|
|
374
|
+
let nextStart = Math.max(...existingDiskEntries.map(x => parseInt(x))) + 1;
|
|
375
|
+
let buffers = [];
|
|
376
|
+
for (const entry of this.cache.values()) {
|
|
377
|
+
let buffer = this.serializeTransactionEntry(entry);
|
|
378
|
+
buffers.push(buffer);
|
|
379
|
+
}
|
|
380
|
+
let newChunks = this.chunkBuffers(buffers);
|
|
381
|
+
let curChunk = nextStart;
|
|
382
|
+
for (let chunk of newChunks) {
|
|
383
|
+
let file = this.getChunk(curChunk++);
|
|
384
|
+
let content = chunk.buffer;
|
|
385
|
+
let { header, headerBuffer } = this.getHeader(
|
|
386
|
+
// AND, never compress the last one, otherwise we can't append to it!
|
|
387
|
+
content.length >= FILE_ZIP_THRESHOLD && chunk !== newChunks[newChunks.length - 1]);
|
|
388
|
+
if (header.zipped) {
|
|
389
|
+
content = await zip_1.Zip.gzip(content);
|
|
390
|
+
}
|
|
391
|
+
let buffer = Buffer.concat([headerBuffer, content]);
|
|
392
|
+
await this.rawStorage.set(file, buffer);
|
|
393
|
+
}
|
|
394
|
+
// This is the ONLY time we can delete old files, as we know for sure the new file has all of our data.
|
|
395
|
+
// Any future readers won't know this, unless they write it themselves (or unless they audit it against
|
|
396
|
+
// the other generations, which is annoying).
|
|
397
|
+
for (const file of existingDiskEntries) {
|
|
398
|
+
await this.rawStorage.remove(file);
|
|
399
|
+
}
|
|
400
|
+
this.currentChunk = curChunk;
|
|
401
|
+
}
|
|
402
|
+
async reset() {
|
|
403
|
+
await fileLockSection(async () => {
|
|
404
|
+
let existingDiskEntries = await this.rawStorage.getKeys();
|
|
405
|
+
existingDiskEntries = existingDiskEntries.filter(x => x.endsWith(CHUNK_EXT));
|
|
406
|
+
try {
|
|
407
|
+
await Promise.allSettled(existingDiskEntries.map(x => this.rawStorage.remove(x)));
|
|
408
|
+
}
|
|
409
|
+
catch (_a) { }
|
|
410
|
+
this.pendingAppends = [];
|
|
411
|
+
this.cache.clear();
|
|
412
|
+
this.currentChunk = 0;
|
|
413
|
+
this.currentChunkSize = 0;
|
|
414
|
+
this.entryCount = 0;
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
exports.TransactionStorage = TransactionStorage;
|
|
419
|
+
TransactionStorage.allStorage = [];
|
|
420
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJhbnNhY3Rpb25TdG9yYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiVHJhbnNhY3Rpb25TdG9yYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1EQUE4RTtBQUU5RSxxQ0FBa0M7QUFDbEMsMkRBQTJEO0FBQzNELGtFQUFpRjtBQUNqRixxREFBOEM7QUFDOUMsK0NBQTRDO0FBRTVDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUE4QkU7QUFHRixNQUFNLGVBQWUsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBRXBDLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFFNUMsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDO0FBQzNCLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUN2RSxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDdEUsNkRBQTZEO0FBQzdELE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQztBQWF4QixNQUFNLGVBQWUsR0FBRyxJQUFBLHNCQUFXLEVBQUMsS0FBSyxFQUFFLEdBQXdCLEVBQUUsRUFBRTtJQUNuRSxNQUFNLEdBQUcsRUFBRSxDQUFDO0FBQ2hCLENBQUMsQ0FBQyxDQUFDO0FBRUgsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDO0FBQzNCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7QUFFekMsTUFB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RyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3RGLENBQUM7WUFBQyxXQUFNLENBQUMsQ0FBQyxDQUFDO1lBRVgsSUFBSSxDQUFDLGNBQWMsR0FBRyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQztZQUN0QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO1lBQzFCLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQzs7QUE5WkwsZ0RBK1pDO0FBelprQiw2QkFBVSxHQUF5QixFQUFFLEFBQTNCLENBQTRCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUHJvbWlzZU9iaiwgc29ydCwgdGhyb3R0bGVGdW5jdGlvbiB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL21pc2NcIjtcbmltcG9ydCB7IElTdG9yYWdlLCBJU3RvcmFnZVJhdyB9IGZyb20gXCIuL0lTdG9yYWdlXCI7XG5pbXBvcnQgeyBaaXAgfSBmcm9tIFwiLi4vbWlzYy96aXBcIjtcbmltcG9ydCB7IHJ1bkluU2VyaWFsIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvYmF0Y2hpbmdcIjtcbmltcG9ydCB7IGZvcm1hdE51bWJlciwgZm9ybWF0VGltZSB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2Zvcm1hdHRpbmcvZm9ybWF0XCI7XG5pbXBvcnQgeyBzZXRQZW5kaW5nIH0gZnJvbSBcIi4vUGVuZGluZ01hbmFnZXJcIjtcbmltcG9ydCB7IGlzSW5CdWlsZCB9IGZyb20gXCIuLi8uLi9idWlsZEZsYWdcIjtcblxuLypcbi8vIFNwZWM6XG4vLyAgICAgIC0gWmlwIGluZGl2aWR1YWwgbGFyZ2UgdmFsdWVzXG4vLyAgICAgIC0gU3RvcmVzIGEgdHJhbnNhY3Rpb24gbG9nXG4vLyAgICAgICAgICAtIFRyYW5zYWN0aW9uIGxvZyBoYXMgYSBoZWFkZXIsIHdoaWNoIGlzIEpTT04sIGZvciB0aGluZ3Mgc3VjaCBhcyBcInppcHBlZFwiXG4vLyAgICAgICAgICAtIFRyYW5zYWN0aW9uIGxvZyB1c2VzIGxlbmd0aCBwcmVmaXhlZCB2YWx1ZXMsIHdpdGggYSBzcGVjaWFsIDggYnl0ZXMgdG8gZGVub3RlIHRoZSBlbmQsXG4vLyAgICAgICAgICAgICAgYW5kIDggZm9yIHRoZSBzdGFydC5cbi8vICAgICAgICAgIC0gV2hlbiB0cmFuc2FjdGlvbiBsb2cgaXMgaXRlcmF0ZWQgb24sIGlmIHRoZSBieXRlcyBhdCB0aGUgZW5kICh1c2luZyB0aGUgbGVuZ3RoIHByZWZpeClcbi8vICAgICAgICAgICAgICBkb24ndCBtYXRjaCB0aGUgZW5kIGJ5dGVzIE9SIHRoZSBzdGFydCBieXRlcyBhcmUgd3JvbmcsIHdlIHNraXAgdGhlIHN0YXJ0IGJ5dGVzLFxuLy8gICAgICAgICAgICAgIGFuZCBpdGVyYXRpbmcgdW50aWwgd2UgZmluZCBuZXcgc3RhcnQgYnl0ZXMgdGhhdCBtYXRjaCBvdXIgc3BlY2lhbCBieXRlcy4gVGhlbiB3ZSB0cnlcbi8vICAgICAgICAgICAgICB0byByZWFkIHRoZXNlIHZhbHVlcy5cbi8vICAgICAgICAgIC0gRWFjaCB0cmFuc2FjdGlvbiBlbnRyeSBoYXMgYSBieXRlIGZvciBmbGFncywgb25lIGJpdCB3aGljaCBkZW5vdGVzIGlmIHRoZSB2YWx1ZSBpcyB6aXBwZWQgb3Igbm90LlxuLy8gICAgICAtIENvbXByZXNzZXMgdGhlIGxvZyBhZnRlciB0aGVyZSBhcmUgM1ggZW50cmllcyB0aGFuIGtleXMgKGFuZCA+IDEwMClcbi8vICAgICAgICAgIC0gQm90aCBkZWR1cGUga2V5cywgYW5kIHppcFxuLy8gICAgICAtIEFzc3VtZXMgYWxsIGZpbGVzIGluIHJhd1N0b3JhZ2UgZW5kaW5nIHdpdGggLnR4IGFyZSB0cmFuc2FjdGlvbiBsb2dzXG4vLyAgICAgIC0gTmFtZXMgZmlsZXMgbGlrZSBgJHtnZW5lcmF0aW9ufS50eGBcbi8vICAgICAgICAgIC0gV2hlbiBjb21wcmVzc2luZywgd2UgaW5jcmVtZW50IHRoZSBnZW5lcmF0aW9uLCBhbmQgd3JpdGUgdG8gYSBuZXcgZmlsZSwgYW5kIGRlbGV0ZVxuLy8gICAgICAgICAgICAgIGFueSBnZW5lcmF0aW9ucyB0aGF0IGFyZSBvbGRlciB0aGFuIHRoZSBuZXcgb25lXG4vLyAgICAgICAgICAtIE9uIHJlYWRpbmcsIHdlIHJlYWQgZnJvbSBhbGwgZ2VuZXJhdGlvbiBmaWxlcyB0aGF0IGV4aXN0LCBpbiBjYXNlIHNvbWUgYXJlIGNvcnJ1cHRlZFxuLy8gICAgICAtIE9uIGxvYWQsIGxvYWRzIGluIGFsbCB0cmFuc2FjdGlvbiBsb2dzLCBhbmQgc3RvcmVzIGFsbCB2YWx1ZXMgaW4gYSBNYXA8c3RyaW5nLCBCdWZmZXI+XG4vLyAgICAgIC0gT24gd3JpdGVzIGltbWVkaWF0ZWx5IHVwZGF0ZXMgdGhlIGluIG1lbW9yeSBNYXAsIGFuZCB0aGVuIHdyaXRlcyB0byB0aGUgdHJhbnNhY3Rpb24gbG9nXG4vLyAgICAgIC0gQ2FjaGVzIHRoZSBsYXN0IHRyYW5zYWN0aW9uIGZpbGUgbmFtZSBpbiBtZW1vcnlcbi8vICAgICAgLSBNYWtlcyBzdXJlIGFsbCBmaWxlIHN5c3RlbSB3cml0ZXMgKGJ1dCBub3QgTWFwIHVwZGF0ZXMpIGFyZSBkb25lIHdpdGggZmlsZUxvY2tTZWN0aW9uLFxuLy8gICAgICAgICAgc28gdGhleSBuZXZlciBvdmVybGFwLlxuLy8gICAgICAtIEJ1ZmZlcnMgcGVuZGluZyBhcHBlbmRzIGluIG1lbW9yeSwgc28gdGhleSBjYW4gd3JpdHRlbiBhbGwgYXQgb25jZSAoYWZ0ZXIgdGhlIGZpcnN0IG9uZVxuLy8gICAgICAgICAgaXMgYmxvY2tpbmcgaW4gZmlsZUxvY2tTZWN0aW9uKS5cblxuVVBEQVRFIG5vdyB3ZSB1c2UgY2h1bmtzLCBiZWNhdXNlIGFwcGVuZCBpcyB0b28gc2xvdy5cblxuSU1QT1JUQU5UISBJZiB0aGVyZSBhcmUgbXVsdGlwbGUgd3JpdGVycywgd2UgY2xvYmJlciB3cml0ZXMgZnJvbSBvdGhlciB3cml0ZXJzIHdoZW4gd2UgY29tcHJlc3NcbiovXG5cblxuY29uc3QgRklMRV9DSFVOS19TSVpFID0gMTAyNCAqIDEwMjQ7XG5cbmNvbnN0IEZJTEVfWklQX1RIUkVTSE9MRCA9IDE2ICogMTAyNCAqIDEwMjQ7XG5cbmNvbnN0IFpJUF9USFJFU0hPTEQgPSA0MDk2O1xuY29uc3QgU1RBUlRfQllURVMgPSBCdWZmZXIuZnJvbShbMjM2LCA0OSwgMTEyLCAxMjEsIDI3LCAxMjcsIDIyNywgNjNdKTtcbmNvbnN0IEVORF9CWVRFUyA9IEJ1ZmZlci5mcm9tKFsyMjAsIDExMSwgMjQzLCAyMDIsIDIwMCwgNzksIDIxMywgNjNdKTtcbi8vIERlbGF5IHdyaXRlcywgc28gd2UgYmF0Y2ggYmV0dGVyLCBhbmQgdGhyYXNoIHRoZSBkaXNrIGxlc3NcbmNvbnN0IFdSSVRFX0RFTEFZID0gNTAwO1xuXG5pbnRlcmZhY2UgVHJhbnNhY3Rpb25FbnRyeSB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgdmFsdWU6IEJ1ZmZlciB8IHVuZGVmaW5lZDtcbiAgICBpc1ppcHBlZDogYm9vbGVhbjtcbiAgICB0aW1lOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBUcmFuc2FjdGlvbkhlYWRlciB7XG4gICAgemlwcGVkOiBib29sZWFuO1xufVxuXG5jb25zdCBmaWxlTG9ja1NlY3Rpb24gPSBydW5JblNlcmlhbChhc3luYyAoZm5jOiAoKSA9PiBQcm9taXNlPHZvaWQ+KSA9PiB7XG4gICAgYXdhaXQgZm5jKCk7XG59KTtcblxuY29uc3QgQ0hVTktfRVhUID0gXCIuY2h1bmtcIjtcbmNvbnN0IG91cklkID0gRGF0ZS5ub3coKSArIE1hdGgucmFuZG9tKCk7XG5cbmV4cG9ydCBjbGFzcyBUcmFuc2FjdGlvblN0b3JhZ2UgaW1wbGVtZW50cyBJU3RvcmFnZTxCdWZmZXI+IHtcbiAgICBwdWJsaWMgY2FjaGU6IE1hcDxzdHJpbmcsIFRyYW5zYWN0aW9uRW50cnk+ID0gbmV3IE1hcCgpO1xuICAgIHByaXZhdGUgY3VycmVudENodW5rID0gMDtcbiAgICBwcml2YXRlIGN1cnJlbnRDaHVua1NpemUgPSAwO1xuICAgIHByaXZhdGUgZW50cnlDb3VudCA9IDA7XG5cbiAgICBwcml2YXRlIHN0YXRpYyBhbGxTdG9yYWdlOiBUcmFuc2FjdGlvblN0b3JhZ2VbXSA9IFtdO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgcmF3U3RvcmFnZTogSVN0b3JhZ2VSYXcsXG4gICAgICAgIHByaXZhdGUgZGVidWdOYW1lOiBzdHJpbmcsXG4gICAgICAgIHByaXZhdGUgd3JpdGVEZWxheSA9IFdSSVRFX0RFTEFZXG4gICAgKSB7XG4gICAgICAgIFRyYW5zYWN0aW9uU3RvcmFnZS5hbGxTdG9yYWdlLnB1c2godGhpcyk7XG4gICAgfVxuICAgIC8vIEhlbHBzIGdldCByaWQgb2YgcGFyc2UgZXJyb3JzIHdoaWNoIGNvbnN0YW50bHkgbG9nLiBBbHNvLCB1c2VzIGxlc3Mgc3BhY2VcbiAgICBwdWJsaWMgc3RhdGljIGFzeW5jIGNvbXByZXNzQWxsKCkge1xuICAgICAgICBmb3IgKGxldCBzdG9yYWdlIG9mIFRyYW5zYWN0aW9uU3RvcmFnZS5hbGxTdG9yYWdlKSB7XG4gICAgICAgICAgICBhd2FpdCBzdG9yYWdlLmNvbXByZXNzVHJhbnNhY3Rpb25Mb2codHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXQ6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQgPSB0aGlzLmxvYWRBbGxUcmFuc2FjdGlvbnMoKTtcblxuICAgIHByaXZhdGUgZ2V0Q2h1bmsoY2h1bms6IG51bWJlcikgeyByZXR1cm4gYCR7Y2h1bmt9XyR7b3VySWR9JHtDSFVOS19FWFR9YDsgfVxuXG4gICAgcHVibGljIGFzeW5jIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPiB7XG4gICAgICAgIGF3YWl0IHRoaXMuaW5pdDtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLmNhY2hlLmdldChrZXkpO1xuICAgICAgICBpZiAodmFsdWUgJiYgdmFsdWUuaXNaaXBwZWQgJiYgdmFsdWUudmFsdWUpIHtcbiAgICAgICAgICAgIHZhbHVlLnZhbHVlID0gYXdhaXQgWmlwLmd1bnppcCh2YWx1ZS52YWx1ZSk7XG4gICAgICAgICAgICB2YWx1ZS5pc1ppcHBlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZT8udmFsdWU7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldChrZXk6IHN0cmluZywgdmFsdWU6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5pbml0KSBhd2FpdCB0aGlzLmluaXQ7XG5cbiAgICAgICAgLy8gVGltZSBpcyBzZXQgb24gZGlzayB3cml0ZSwgYXMgRGF0ZS5ub3coKSBpcyB0b28gc2xvd1xuICAgICAgICBsZXQgZW50cnk6IFRyYW5zYWN0aW9uRW50cnkgPSB7IGtleSwgdmFsdWUsIGlzWmlwcGVkOiBmYWxzZSwgdGltZTogMCB9O1xuICAgICAgICB0aGlzLmNhY2hlLnNldChrZXksIGVudHJ5KTtcblxuICAgICAgICBpZiAodmFsdWUubGVuZ3RoID49IFpJUF9USFJFU0hPTEQpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYXdhaXQgWmlwLmd6aXAodmFsdWUpO1xuICAgICAgICAgICAgZW50cnkudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIGVudHJ5LmlzWmlwcGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLnB1c2hBcHBlbmQoZW50cnkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZW1vdmUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHRoaXMuaW5pdCkgYXdhaXQgdGhpcy5pbml0O1xuICAgICAgICB0aGlzLmNhY2hlLmRlbGV0ZShrZXkpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMucHVzaEFwcGVuZCh7IGtleSwgdmFsdWU6IHVuZGVmaW5lZCwgaXNaaXBwZWQ6IGZhbHNlLCB0aW1lOiAwIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRJbmZvKGtleTogc3RyaW5nKTogUHJvbWlzZTx7IHNpemU6IG51bWJlcjsgbGFzdE1vZGlmaWVkOiBudW1iZXIgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBhd2FpdCB0aGlzLmluaXQ7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5jYWNoZS5nZXQoa2V5KTtcbiAgICAgICAgaWYgKCF2YWx1ZT8udmFsdWUpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiB7IHNpemU6IHZhbHVlLnZhbHVlLmxlbmd0aCwgbGFzdE1vZGlmaWVkOiB2YWx1ZS50aW1lIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwZW5kaW5nQXBwZW5kczogVHJhbnNhY3Rpb25FbnRyeVtdID0gW107XG4gICAgcHJpdmF0ZSBleHRyYUFwcGVuZHMgPSAwO1xuICAgIHByaXZhdGUgcGVuZGluZ1dyaXRlOiBQcm9taXNlPHZvaWQ+IHwgdW5kZWZpbmVkO1xuICAgIGFzeW5jIHB1c2hBcHBlbmQoZW50cnk6IFRyYW5zYWN0aW9uRW50cnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5lbnRyeUNvdW50Kys7XG4gICAgICAgIHRoaXMucGVuZGluZ0FwcGVuZHMucHVzaChlbnRyeSk7XG4gICAgICAgIHZvaWQgdGhpcy51cGRhdGVQZW5kaW5nQXBwZW5kcygpO1xuICAgICAgICBpZiAodGhpcy5wZW5kaW5nV3JpdGUpIHJldHVybiB0aGlzLnBlbmRpbmdXcml0ZTtcbiAgICAgICAgdGhpcy5wZW5kaW5nV3JpdGUgPSBmaWxlTG9ja1NlY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgLy8gRGVsYXkgdG8gYWxsb3cgYmF0Y2hpbmcsIGFuZCBkZWR1cGluZ1xuICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIHRoaXMud3JpdGVEZWxheSkpO1xuICAgICAgICAgICAgbGV0IGN1ckFwcGVuZHMgPSB0aGlzLnBlbmRpbmdBcHBlbmRzO1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nQXBwZW5kcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nV3JpdGUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbGV0IGFwcGVuZHNEZWR1cGVkOiBNYXA8c3RyaW5nLCBUcmFuc2FjdGlvbkVudHJ5PiA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGN1ckFwcGVuZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgYXBwZW5kc0RlZHVwZWQuc2V0KGVudHJ5LmtleSwgZW50cnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjdXJBcHBlbmRzID0gQXJyYXkuZnJvbShhcHBlbmRzRGVkdXBlZC52YWx1ZXMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmV4dHJhQXBwZW5kcyArPSBjdXJBcHBlbmRzLmxlbmd0aDtcbiAgICAgICAgICAgIHZvaWQgdGhpcy51cGRhdGVQZW5kaW5nQXBwZW5kcygpO1xuICAgICAgICAgICAgaWYgKGN1ckFwcGVuZHMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgbGV0IHRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGVudHJ5IG9mIGN1ckFwcGVuZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgZW50cnkudGltZSA9IHRpbWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IG5ld1N1bSA9IDA7XG4gICAgICAgICAgICAgICAgbGV0IGJ1ZmZlcnM6IEJ1ZmZlcltdID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBjdXJBcHBlbmRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBidWZmZXIgPSB0aGlzLnNlcmlhbGl6ZVRyYW5zYWN0aW9uRW50cnkoZW50cnkpO1xuICAgICAgICAgICAgICAgICAgICBidWZmZXJzLnB1c2goYnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgbmV3U3VtICs9IGJ1ZmZlci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IG5ld0NodW5rcyA9IHRoaXMuY2h1bmtCdWZmZXJzKGJ1ZmZlcnMpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNodW5rIG9mIG5ld0NodW5rcykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZmlsZSA9IHRoaXMuZ2V0Q2h1bmsodGhpcy5jdXJyZW50Q2h1bmspO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWF3YWl0IHRoaXMucmF3U3RvcmFnZS5nZXQoZmlsZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7IGhlYWRlciwgaGVhZGVyQnVmZmVyIH0gPSB0aGlzLmdldEhlYWRlcihmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJhd1N0b3JhZ2Uuc2V0KGZpbGUsIGhlYWRlckJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbnRlbnQgPSBjaHVuay5idWZmZXI7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucmF3U3RvcmFnZS5hcHBlbmQoZmlsZSwgY29udGVudCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudENodW5rU2l6ZSArPSBjb250ZW50Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudENodW5rU2l6ZSA+PSBGSUxFX0NIVU5LX1NJWkUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudENodW5rKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRDaHVua1NpemUgPSAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jb21wcmVzc1RyYW5zYWN0aW9uTG9nKCk7XG4gICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXh0cmFBcHBlbmRzIC09IGN1ckFwcGVuZHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZvaWQgdGhpcy51cGRhdGVQZW5kaW5nQXBwZW5kcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgdGhpcy5wZW5kaW5nV3JpdGU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVQZW5kaW5nQXBwZW5kcyA9IHRocm90dGxlRnVuY3Rpb24oMTAwLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGxldCBhcHBlbmRDb3VudCA9IHRoaXMucGVuZGluZ0FwcGVuZHMubGVuZ3RoICsgdGhpcy5leHRyYUFwcGVuZHM7XG4gICAgICAgIGxldCBncm91cCA9IGBUcmFuc2FjdGlvbiAoJHt0aGlzLmRlYnVnTmFtZX0pYDtcbiAgICAgICAgLy9jb25zb2xlLmxvZyhgVXBkYXRlIHBlbmRpbmcgYXBwZW5kcyAke2dyb3VwfTogJHthcHBlbmRDb3VudH1gKTtcbiAgICAgICAgaWYgKCFhcHBlbmRDb3VudCkge1xuICAgICAgICAgICAgc2V0UGVuZGluZyhncm91cCwgXCJcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc2V0UGVuZGluZyhncm91cCwgYFBlbmRpbmcgYXBwZW5kczogJHthcHBlbmRDb3VudH1gKTtcbiAgICB9KTtcblxuICAgIHB1YmxpYyBhc3luYyBnZXRLZXlzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgICAgaWYgKHRoaXMuaW5pdCkgYXdhaXQgdGhpcy5pbml0O1xuICAgICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLmNhY2hlLmtleXMoKSk7XG4gICAgfVxuXG5cbiAgICBwcml2YXRlIGFzeW5jIGxvYWRBbGxUcmFuc2FjdGlvbnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmIChpc0luQnVpbGQoKSkgcmV0dXJuO1xuICAgICAgICBsZXQgdGltZSA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IGtleXMgPSBhd2FpdCB0aGlzLnJhd1N0b3JhZ2UuZ2V0S2V5cygpO1xuICAgICAgICBjb25zdCB0cmFuc2FjdGlvbkZpbGVzID0ga2V5cy5maWx0ZXIoa2V5ID0+IGtleS5lbmRzV2l0aChDSFVOS19FWFQpKTtcblxuICAgICAgICBzb3J0KHRyYW5zYWN0aW9uRmlsZXMsIHggPT4gcGFyc2VJbnQoeCkpO1xuXG4gICAgICAgIGxldCBzaXplID0gMDtcbiAgICAgICAgZm9yIChjb25zdCBmaWxlIG9mIHRyYW5zYWN0aW9uRmlsZXMpIHtcbiAgICAgICAgICAgIGxldCBjaHVuayA9IHBhcnNlSW50KGZpbGUpO1xuICAgICAgICAgICAgbGV0IGN1clNpemUgPSBhd2FpdCB0aGlzLmxvYWRUcmFuc2FjdGlvbkZpbGUoZmlsZSk7XG4gICAgICAgICAgICBpZiAoY2h1bmsgPj0gdGhpcy5jdXJyZW50Q2h1bmspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRDaHVuayA9IGNodW5rO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudENodW5rU2l6ZSA9IGN1clNpemU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaXplICs9IGN1clNpemU7XG4gICAgICAgIH1cbiAgICAgICAgdGltZSA9IERhdGUubm93KCkgLSB0aW1lO1xuICAgICAgICBpZiAodGltZSA+IDUwKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgTG9hZGVkICR7dGhpcy5kZWJ1Z05hbWV9IGluICR7Zm9ybWF0VGltZSh0aW1lKX0sICR7Zm9ybWF0TnVtYmVyKHRoaXMuY2FjaGUuc2l6ZSl9IGtleXMsICR7Zm9ybWF0TnVtYmVyKHNpemUpfUJgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW5pdCA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGxvYWRUcmFuc2FjdGlvbkZpbGUoZmlsZW5hbWU6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgICAgIGNvbnN0IGZ1bGxGaWxlID0gYXdhaXQgdGhpcy5yYXdTdG9yYWdlLmdldChmaWxlbmFtZSk7XG4gICAgICAgIGlmICghZnVsbEZpbGUpIHJldHVybiAwO1xuICAgICAgICBpZiAoZnVsbEZpbGUubGVuZ3RoIDwgNCkge1xuICAgICAgICAgICAgLy9jb25zb2xlLmVycm9yKGBUcmFuc2FjdGlvbiBpbiAke3RoaXMuZGVidWdOYW1lfSBmaWxlICR7ZmlsZW5hbWV9IGlzIHRvbyBzbWFsbCwgc2tpcHBpbmdgKTtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIGxldCBoZWFkZXJTaXplID0gZnVsbEZpbGUucmVhZFVJbnQzMkxFKDApO1xuICAgICAgICBsZXQgaGVhZGVyQnVmZmVyID0gZnVsbEZpbGUuc2xpY2UoNCwgNCArIGhlYWRlclNpemUpO1xuICAgICAgICBsZXQgaGVhZGVyOiBUcmFuc2FjdGlvbkhlYWRlcjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGhlYWRlciA9IEpTT04ucGFyc2UoaGVhZGVyQnVmZmVyLnRvU3RyaW5nKCkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBGYWlsZWQgdG8gcGFyc2UgaGVhZGVyIG9mIHRyYW5zYWN0aW9uIGZpbGUgaW4gJHt0aGlzLmRlYnVnTmFtZX0sICR7ZmlsZW5hbWV9YCk7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgY29udGVudCA9IGZ1bGxGaWxlLnNsaWNlKDQgKyBoZWFkZXJTaXplKTtcbiAgICAgICAgaWYgKGhlYWRlci56aXBwZWQpIHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBhd2FpdCBaaXAuZ3VuemlwKGNvbnRlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG9mZnNldCA9IDA7XG4gICAgICAgIGxldCBlbnRyaWVzOiBUcmFuc2FjdGlvbkVudHJ5W10gPSBbXTtcbiAgICAgICAgd2hpbGUgKG9mZnNldCA8IGNvbnRlbnQubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIWNvbnRlbnQuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBTVEFSVF9CWVRFUy5sZW5ndGgpLmVxdWFscyhTVEFSVF9CWVRFUykpIHtcbiAgICAgICAgICAgICAgICBsZXQgcyA9IG9mZnNldDtcbiAgICAgICAgICAgICAgICB3aGlsZSAob2Zmc2V0IDwgY29udGVudC5sZW5ndGggJiYgIWNvbnRlbnQuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBTVEFSVF9CWVRFUy5sZW5ndGgpLmVxdWFscyhTVEFSVF9CWVRFUykpIHtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBsZW4gPSBvZmZzZXQgLSBzO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgRm91bmQgYmFkIGJ5dGVzIGluICR7ZmlsZW5hbWV9LCBza2lwcGluZyAke2xlbn0gYnl0ZXMgYXQgb2Zmc2V0ICR7c30uIFRvdGFsIGZpbGUgYnl0ZXMgJHtjb250ZW50Lmxlbmd0aH0sIHJlYWQgJHtlbnRyaWVzLmxlbmd0aH0gZW50cmllc2ApO1xuICAgICAgICAgICAgICAgIGlmIChvZmZzZXQgPj0gY29udGVudC5sZW5ndGgpIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGVudHJ5T2JqOiB7IGVudHJ5OiBUcmFuc2FjdGlvbkVudHJ5LCBvZmZzZXQ6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBlbnRyeU9iaiA9IHRoaXMucmVhZFRyYW5zYWN0aW9uRW50cnkoY29udGVudCwgb2Zmc2V0KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICAgIGlmIChlLm1lc3NhZ2UuaW5jbHVkZXMoXCJSZWFkIHBhc3QgZW5kIG9mIGJ1ZmZlclwiKSkge1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXQgKz0gMTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWVudHJ5T2JqKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBGYWlsZWQgdG8gcmVhZCB0cmFuc2FjdGlvbiBlbnRyeSBpbiBpbiAke3RoaXMuZGVidWdOYW1lfSwgZmlsZSAke2ZpbGVuYW1lfSBhdCBvZmZzZXQgJHtvZmZzZXR9LCBza2lwcGluZyBiYWQgYnl0ZXMsIHJlYWRpbmcgcmVtYWluZGVyIG9mIGZpbGVgKTtcbiAgICAgICAgICAgICAgICBvZmZzZXQrKztcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW50cnlDb3VudCsrO1xuICAgICAgICAgICAgbGV0IHsgZW50cnkgfSA9IGVudHJ5T2JqO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZW50cnlPYmoub2Zmc2V0O1xuICAgICAgICAgICAgZW50cmllcy5wdXNoKGVudHJ5KTtcblxuICAgICAgICAgICAgaWYgKGVudHJ5LnZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhY2hlLmRlbGV0ZShlbnRyeS5rZXkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgcHJldiA9IHRoaXMuY2FjaGUuZ2V0KGVudHJ5LmtleSk7XG4gICAgICAgICAgICAgICAgaWYgKHByZXYgJiYgKHByZXYudGltZSA+IGVudHJ5LnRpbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmNhY2hlLnNldChlbnRyeS5rZXksIGVudHJ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVsbEZpbGUubGVuZ3RoO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVhZFRyYW5zYWN0aW9uRW50cnkoYnVmZmVyOiBCdWZmZXIsIG9mZnNldDogbnVtYmVyKToge1xuICAgICAgICBlbnRyeTogVHJhbnNhY3Rpb25FbnRyeTtcbiAgICAgICAgb2Zmc2V0OiBudW1iZXI7XG4gICAgfSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGZ1bmN0aW9uIHJlYWRTbGljZShjb3VudDogbnVtYmVyKSB7XG4gICAgICAgICAgICBjb25zdCBzbGljZSA9IGJ1ZmZlci5zbGljZShvZmZzZXQsIG9mZnNldCArIGNvdW50KTtcbiAgICAgICAgICAgIGlmIChzbGljZS5sZW5ndGggPCBjb3VudCkgdGhyb3cgbmV3IEVycm9yKGBSZWFkIHBhc3QgZW5kIG9mIGJ1ZmZlciBhdCBvZmZzZXQgJHtvZmZzZXR9LyR7YnVmZmVyLmxlbmd0aH1gKTtcbiAgICAgICAgICAgIG9mZnNldCArPSBjb3VudDtcbiAgICAgICAgICAgIHJldHVybiBzbGljZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXJlYWRTbGljZShTVEFSVF9CWVRFUy5sZW5ndGgpLmVxdWFscyhTVEFSVF9CWVRFUykpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgICAgY29uc3Qga2V5TGVuZ3RoID0gcmVhZFNsaWNlKDQpLnJlYWRVSW50MzJMRSgwKTtcbiAgICAgICAgY29uc3QgdmFsdWVMZW5ndGggPSByZWFkU2xpY2UoNCkucmVhZFVJbnQzMkxFKDApO1xuICAgICAgICBjb25zdCB0aW1lID0gcmVhZFNsaWNlKDgpLnJlYWREb3VibGVMRSgwKTtcbiAgICAgICAgY29uc3QgZmxhZ3MgPSByZWFkU2xpY2UoMSkucmVhZFVJbnQ4KDApO1xuXG4gICAgICAgIGNvbnN0IGtleSA9IHJlYWRTbGljZShrZXlMZW5ndGgpLnRvU3RyaW5nKCk7XG4gICAgICAgIGxldCB2YWx1ZSA9IHJlYWRTbGljZSh2YWx1ZUxlbmd0aCk7XG5cbiAgICAgICAgaWYgKCFyZWFkU2xpY2UoRU5EX0JZVEVTLmxlbmd0aCkuZXF1YWxzKEVORF9CWVRFUykpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgICAgbGV0IGlzWmlwcGVkID0gKGZsYWdzICYgMSkgPT09IDE7XG4gICAgICAgIGxldCBpc0RlbGV0ZSA9IChmbGFncyAmIDIpID09PSAyO1xuXG4gICAgICAgIGxldCBlbnRyeTogVHJhbnNhY3Rpb25FbnRyeSA9IHsga2V5LCB2YWx1ZSwgaXNaaXBwZWQsIHRpbWUgfTtcbiAgICAgICAgaWYgKGlzRGVsZXRlKSB7XG4gICAgICAgICAgICBlbnRyeS52YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBlbnRyeSwgb2Zmc2V0IH07XG4gICAgfVxuXG4gICAgLy8gVE9ETzogTWFrZSB0aGlzIGRpcmVjdGx5IGdvIGZyb20gVHJhbnNhY3Rpb25FbnRyeVtdIHRvIEJ1ZmZlciwgYnkgcHJlLWFsbG9jYXRpbmcsIHNvIGl0IGlzIG1vcmUgZWZmaWNpZW50XG4gICAgcHJpdmF0ZSBzZXJpYWxpemVUcmFuc2FjdGlvbkVudHJ5KGVudHJ5OiBUcmFuc2FjdGlvbkVudHJ5KTogQnVmZmVyIHtcbiAgICAgICAgbGV0IGtleUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGVudHJ5LmtleSk7XG4gICAgICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhcbiAgICAgICAgICAgIFNUQVJUX0JZVEVTLmxlbmd0aCArIDQgKyA0ICsgOCArIDEgKyBrZXlCdWZmZXIubGVuZ3RoICsgKGVudHJ5LnZhbHVlPy5sZW5ndGggfHwgMCkgKyBFTkRfQllURVMubGVuZ3RoXG4gICAgICAgICk7XG4gICAgICAgIGxldCBvZmZzZXQgPSAwO1xuXG4gICAgICAgIFNUQVJUX0JZVEVTLmNvcHkoYnVmZmVyLCBvZmZzZXQpO1xuICAgICAgICBvZmZzZXQgKz0gU1RBUlRfQllURVMubGVuZ3RoO1xuXG4gICAgICAgIGJ1ZmZlci53cml0ZVVJbnQzMkxFKGtleUJ1ZmZlci5sZW5ndGgsIG9mZnNldCk7XG4gICAgICAgIG9mZnNldCArPSA0O1xuXG4gICAgICAgIGJ1ZmZlci53cml0ZVVJbnQzMkxFKGVudHJ5LnZhbHVlID8gZW50cnkudmFsdWUubGVuZ3RoIDogMCwgb2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0ICs9IDQ7XG5cbiAgICAgICAgYnVmZmVyLndyaXRlRG91YmxlTEUoZW50cnkudGltZSwgb2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0ICs9IDg7XG5cbiAgICAgICAgbGV0IGZsYWdzID0gMDtcbiAgICAgICAgaWYgKGVudHJ5LmlzWmlwcGVkKSBmbGFncyB8PSAxO1xuICAgICAgICBpZiAoZW50cnkudmFsdWUgPT09IHVuZGVmaW5lZCkgZmxhZ3MgfD0gMjtcbiAgICAgICAgYnVmZmVyLndyaXRlVUludDgoZmxhZ3MsIG9mZnNldCk7XG4gICAgICAgIG9mZnNldCArPSAxO1xuXG4gICAgICAgIGtleUJ1ZmZlci5jb3B5KGJ1ZmZlciwgb2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0ICs9IGtleUJ1ZmZlci5sZW5ndGg7XG5cbiAgICAgICAgaWYgKGVudHJ5LnZhbHVlKSB7XG4gICAgICAgICAgICBlbnRyeS52YWx1ZS5jb3B5KGJ1ZmZlciwgb2Zmc2V0KTtcbiAgICAgICAgICAgIG9mZnNldCArPSBlbnRyeS52YWx1ZS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBFTkRfQllURVMuY29weShidWZmZXIsIG9mZnNldCk7XG4gICAgICAgIG9mZnNldCArPSBFTkRfQllURVMubGVuZ3RoO1xuXG4gICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRIZWFkZXIoemlwOiBib29sZWFuKSB7XG4gICAgICAgIGNvbnN0IGhlYWRlcjogVHJhbnNhY3Rpb25IZWFkZXIgPSB7IHppcHBlZDogemlwIH07XG4gICAgICAgIGxldCBoZWFkZXJCdWZmZXIgPSBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShoZWFkZXIpKTtcbiAgICAgICAgbGV0IGhlYWRlclNpemUgPSBCdWZmZXIuYWxsb2MoNCk7XG4gICAgICAgIGhlYWRlclNpemUud3JpdGVVSW50MzJMRShoZWFkZXJCdWZmZXIubGVuZ3RoLCAwKTtcbiAgICAgICAgcmV0dXJuIHsgaGVhZGVyLCBoZWFkZXJCdWZmZXI6IEJ1ZmZlci5jb25jYXQoW2hlYWRlclNpemUsIGhlYWRlckJ1ZmZlcl0pIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjaHVua0J1ZmZlcnMoYnVmZmVyczogQnVmZmVyW10pIHtcbiAgICAgICAgbGV0IG5ld0NodW5rczoge1xuICAgICAgICAgICAgYnVmZmVyczogQnVmZmVyW107XG4gICAgICAgICAgICBzaXplOiBudW1iZXI7XG4gICAgICAgIH1bXSA9IFtdO1xuICAgICAgICBuZXdDaHVua3MucHVzaCh7IGJ1ZmZlcnM6IFtdLCBzaXplOiAwIH0pO1xuICAgICAgICBmb3IgKGNvbnN0IGJ1ZmZlciBvZiBidWZmZXJzKSB7XG4gICAgICAgICAgICBpZiAobmV3Q2h1bmtzW25ld0NodW5rcy5sZW5ndGggLSAxXS5zaXplICsgYnVmZmVyLmxlbmd0aCA+PSBGSUxFX0NIVU5LX1NJWkUpIHtcbiAgICAgICAgICAgICAgICBuZXdDaHVua3MucHVzaCh7IGJ1ZmZlcnM6IFtdLCBzaXplOiAwIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3Q2h1bmtzW25ld0NodW5rcy5sZW5ndGggLSAxXS5idWZmZXJzLnB1c2goYnVmZmVyKTtcbiAgICAgICAgICAgIG5ld0NodW5rc1tuZXdDaHVua3MubGVuZ3RoIC0gMV0uc2l6ZSArPSBidWZmZXIubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXdDaHVua3MubWFwKHggPT4gKHsgYnVmZmVyOiBCdWZmZXIuY29uY2F0KHguYnVmZmVycyksIHNpemU6IHguc2l6ZSB9KSk7XG4gICAgfVxuXG5cbiAgICBwcml2YXRlIGNvbXByZXNzaW5nID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBhc3luYyBjb21wcmVzc1RyYW5zYWN0aW9uTG9nKGZvcmNlPzogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5jb21wcmVzc2luZykgcmV0dXJuO1xuICAgICAgICB0aGlzLmNvbXByZXNzaW5nID0gdHJ1ZTtcblxuICAgICAgICBsZXQgZXhpc3RpbmdEaXNrRW50cmllcyA9IGF3YWl0IHRoaXMucmF3U3RvcmFnZS5nZXRLZXlzKCk7XG4gICAgICAgIGV4aXN0aW5nRGlza0VudHJpZXMgPSBleGlzdGluZ0Rpc2tFbnRyaWVzLmZpbHRlcih4ID0+IHguZW5kc1dpdGgoQ0hVTktfRVhUKSk7XG4gICAgICAgIGxldCBjb21wcmVzc05vdyA9IGZvcmNlIHx8IChcbiAgICAgICAgICAgIHRoaXMuZW50cnlDb3VudCA+IDEwMCAmJiB0aGlzLmVudHJ5Q291bnQgPiB0aGlzLmNhY2hlLnNpemUgKiAzXG4gICAgICAgICAgICAvLyBOT1RFOiBUaGlzIGNvbXByZXNzIGNoZWNrIGJyZWFrcyBkb3duIGlmIHdlIG9ubHkgaGF2ZSB2ZXJ5IGxhcmdlIHZhbHVlcywgYnV0Li4uIHRob3NlXG4gICAgICAgICAgICAvLyAgZG9uJ3Qgd29yayBBTllXQVlTIChpdCBpcyBiZXR0ZXIgdG8gdXNlIG9uZSBmaWxlIHBlciB2YWx1ZSBpbnN0ZWFkKS5cbiAgICAgICAgICAgIC8vICAtIE1heWJlIHdlIHNob3VsZCB0aHJvdywgb3IgYXQgbGVhc3Qgd2Fybiwgb24gc2V0cyBvZiB2YWx1ZSA+IDFNQixcbiAgICAgICAgICAgIC8vICAgICAgYXQgd2hpY2ggcG9pbnQgdGhleSBzaG91bGQganVzdCB1c2UgYSBmaWxlIHBlciB2YWx1ZVxuICAgICAgICAgICAgfHwgZXhpc3RpbmdEaXNrRW50cmllcy5sZW5ndGggPiBNYXRoLm1heCgxMCwgTWF0aC5jZWlsKHRoaXMuZW50cnlDb3VudCAvIDEwMDApKVxuICAgICAgICAgICAgfHwgZXhpc3RpbmdEaXNrRW50cmllcy5sZW5ndGggPiAxMDAwICogMTBcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFjb21wcmVzc05vdykgcmV0dXJuO1xuICAgICAgICBjb25zb2xlLmxvZyhgQ29tcHJlc3NpbmcgJHt0aGlzLmRlYnVnTmFtZX0gdHJhbnNhY3Rpb24gbG9nLCAke3RoaXMuZW50cnlDb3VudH0gZW50cmllcywgJHt0aGlzLmNhY2hlLnNpemV9IGtleXNgKTtcblxuICAgICAgICAvLyBMb2FkIG9mZiBkaXNrLCBpbiBjYXNlIHRoZXJlIGFyZSBvdGhlciB3cml0ZXMuIFdlIHN0aWxsIHJhY2Ugd2l0aCB0aGVtLCBidXQgYXQgbGVhc3RcbiAgICAgICAgLy8gIHRoaXMgcmVkdWNlcyB0aGUgcmFjZSBjb25kaXRpb24gY29uc2lkZXJhYmx5XG5cbiAgICAgICAgc29ydChleGlzdGluZ0Rpc2tFbnRyaWVzLCB4ID0+IHBhcnNlSW50KHgpKTtcbiAgICAgICAgZm9yIChsZXQgZW50cnkgb2YgZXhpc3RpbmdEaXNrRW50cmllcykge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5sb2FkVHJhbnNhY3Rpb25GaWxlKGVudHJ5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZW50cnlDb3VudCA9IHRoaXMuY2FjaGUuc2l6ZTtcblxuICAgICAgICBsZXQgbmV4dFN0YXJ0ID0gTWF0aC5tYXgoLi4uZXhpc3RpbmdEaXNrRW50cmllcy5tYXAoeCA9PiBwYXJzZUludCh4KSkpICsgMTtcblxuICAgICAgICBsZXQgYnVmZmVyczogQnVmZmVyW10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiB0aGlzLmNhY2hlLnZhbHVlcygpKSB7XG4gICAgICAgICAgICBsZXQgYnVmZmVyID0gdGhpcy5zZXJpYWxpemVUcmFuc2FjdGlvbkVudHJ5KGVudHJ5KTtcbiAgICAgICAgICAgIGJ1ZmZlcnMucHVzaChidWZmZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5ld0NodW5rcyA9IHRoaXMuY2h1bmtCdWZmZXJzKGJ1ZmZlcnMpO1xuXG4gICAgICAgIGxldCBjdXJDaHVuayA9IG5leHRTdGFydDtcbiAgICAgICAgZm9yIChsZXQgY2h1bmsgb2YgbmV3Q2h1bmtzKSB7XG4gICAgICAgICAgICBsZXQgZmlsZSA9IHRoaXMuZ2V0Q2h1bmsoY3VyQ2h1bmsrKyk7XG4gICAgICAgICAgICBsZXQgY29udGVudCA9IGNodW5rLmJ1ZmZlcjtcbiAgICAgICAgICAgIGxldCB7IGhlYWRlciwgaGVhZGVyQnVmZmVyIH0gPSB0aGlzLmdldEhlYWRlcihcbiAgICAgICAgICAgICAgICAvLyBBTkQsIG5ldmVyIGNvbXByZXNzIHRoZSBsYXN0IG9uZSwgb3RoZXJ3aXNlIHdlIGNhbid0IGFwcGVuZCB0byBpdCFcbiAgICAgICAgICAgICAgICBjb250ZW50Lmxlbmd0aCA+PSBGSUxFX1pJUF9USFJFU0hPTEQgJiYgY2h1bmsgIT09IG5ld0NodW5rc1tuZXdDaHVua3MubGVuZ3RoIC0gMV1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoaGVhZGVyLnppcHBlZCkge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBhd2FpdCBaaXAuZ3ppcChjb250ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBidWZmZXIgPSBCdWZmZXIuY29uY2F0KFtoZWFkZXJCdWZmZXIsIGNvbnRlbnRdKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmF3U3RvcmFnZS5zZXQoZmlsZSwgYnVmZmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoaXMgaXMgdGhlIE9OTFkgdGltZSB3ZSBjYW4gZGVsZXRlIG9sZCBmaWxlcywgYXMgd2Uga25vdyBmb3Igc3VyZSB0aGUgbmV3IGZpbGUgaGFzIGFsbCBvZiBvdXIgZGF0YS5cbiAgICAgICAgLy8gIEFueSBmdXR1cmUgcmVhZGVycyB3b24ndCBrbm93IHRoaXMsIHVubGVzcyB0aGV5IHdyaXRlIGl0IHRoZW1zZWx2ZXMgKG9yIHVubGVzcyB0aGV5IGF1ZGl0IGl0IGFnYWluc3RcbiAgICAgICAgLy8gICAgICB0aGUgb3RoZXIgZ2VuZXJhdGlvbnMsIHdoaWNoIGlzIGFubm95aW5nKS5cbiAgICAgICAgZm9yIChjb25zdCBmaWxlIG9mIGV4aXN0aW5nRGlza0VudHJpZXMpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmF3U3RvcmFnZS5yZW1vdmUoZmlsZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmN1cnJlbnRDaHVuayA9IGN1ckNodW5rO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZXNldCgpIHtcbiAgICAgICAgYXdhaXQgZmlsZUxvY2tTZWN0aW9uKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGxldCBleGlzdGluZ0Rpc2tFbnRyaWVzID0gYXdhaXQgdGhpcy5yYXdTdG9yYWdlLmdldEtleXMoKTtcbiAgICAgICAgICAgIGV4aXN0aW5nRGlza0VudHJpZXMgPSBleGlzdGluZ0Rpc2tFbnRyaWVzLmZpbHRlcih4ID0+IHguZW5kc1dpdGgoQ0hVTktfRVhUKSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGV4aXN0aW5nRGlza0VudHJpZXMubWFwKHggPT4gdGhpcy5yYXdTdG9yYWdlLnJlbW92ZSh4KSkpO1xuICAgICAgICAgICAgfSBjYXRjaCB7IH1cblxuICAgICAgICAgICAgdGhpcy5wZW5kaW5nQXBwZW5kcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5jYWNoZS5jbGVhcigpO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2h1bmsgPSAwO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2h1bmtTaXplID0gMDtcbiAgICAgICAgICAgIHRoaXMuZW50cnlDb3VudCA9IDA7XG4gICAgICAgIH0pO1xuICAgIH1cbn0iXX0=
|
|
421
|
+
/* _JS_SOURCE_HASH = "d6b565522e0199b1511007a3ea7bb1eef1a46c338996c583da6090466f49bf59"; */
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
3
|
+
//exports.getFileSystemPointer = exports.deleteFileSystemPointer = exports.storeFileSystemPointer = void 0;
|
|
4
|
+
const caching_1 = require("socket-function/src/caching");
|
|
5
|
+
const misc_1 = require("socket-function/src/misc");
|
|
6
|
+
const objectStoreName = "fileSystemPointerDB";
|
|
7
|
+
const db = (0, caching_1.lazy)(async () => {
|
|
8
|
+
let db = indexedDB.open("fileSystemPointerDB_f298e962-bd8a-46b9-8098-25db633f4ed3", 1);
|
|
9
|
+
db.addEventListener("upgradeneeded", () => {
|
|
10
|
+
db.result.createObjectStore(objectStoreName, {});
|
|
11
|
+
});
|
|
12
|
+
await new Promise(resolve => db.addEventListener("success", resolve));
|
|
13
|
+
return db.result;
|
|
14
|
+
});
|
|
15
|
+
async function getTransaction() {
|
|
16
|
+
let database = await db();
|
|
17
|
+
if (!database)
|
|
18
|
+
return undefined;
|
|
19
|
+
return database.transaction(objectStoreName, "readwrite").objectStore(objectStoreName);
|
|
20
|
+
}
|
|
21
|
+
async function write(key, value) {
|
|
22
|
+
let transaction = await getTransaction();
|
|
23
|
+
if (!transaction)
|
|
24
|
+
return;
|
|
25
|
+
let req = transaction.put(value, key);
|
|
26
|
+
await new Promise((resolve, reject) => {
|
|
27
|
+
req.addEventListener("success", resolve);
|
|
28
|
+
req.addEventListener("error", reject);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async function read(key) {
|
|
32
|
+
let transaction = await getTransaction();
|
|
33
|
+
if (!transaction)
|
|
34
|
+
return;
|
|
35
|
+
let req = transaction.get(key);
|
|
36
|
+
await new Promise((resolve, reject) => {
|
|
37
|
+
req.addEventListener("success", resolve);
|
|
38
|
+
req.addEventListener("error", reject);
|
|
39
|
+
});
|
|
40
|
+
return req.result;
|
|
41
|
+
}
|
|
42
|
+
async function storeFileSystemPointer(config) {
|
|
43
|
+
await config.handle.requestPermission({ mode: config.mode });
|
|
44
|
+
let key = (0, misc_1.nextId)() + "_" + config.mode;
|
|
45
|
+
await write(key, config.handle);
|
|
46
|
+
return key;
|
|
47
|
+
}
|
|
48
|
+
exports.storeFileSystemPointer = storeFileSystemPointer;
|
|
49
|
+
async function deleteFileSystemPointer(pointer) {
|
|
50
|
+
let transaction = await getTransaction();
|
|
51
|
+
if (!transaction)
|
|
52
|
+
return;
|
|
53
|
+
let req = transaction.delete(pointer);
|
|
54
|
+
await new Promise((resolve, reject) => {
|
|
55
|
+
req.addEventListener("success", resolve);
|
|
56
|
+
req.addEventListener("error", reject);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
exports.deleteFileSystemPointer = deleteFileSystemPointer;
|
|
60
|
+
async function getFileSystemPointer(config) {
|
|
61
|
+
const handle = await read(config.pointer);
|
|
62
|
+
if (!handle)
|
|
63
|
+
return;
|
|
64
|
+
let mode = config.pointer.split("_").at(-1);
|
|
65
|
+
return {
|
|
66
|
+
async onUserActivation(modeOverride) {
|
|
67
|
+
let testMode = await handle.queryPermission({ mode: mode });
|
|
68
|
+
if (testMode !== mode) {
|
|
69
|
+
await handle.requestPermission({ mode: modeOverride !== null && modeOverride !== void 0 ? modeOverride : mode });
|
|
70
|
+
}
|
|
71
|
+
return handle;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
exports.getFileSystemPointer = getFileSystemPointer;
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZVN5c3RlbVBvaW50ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJmaWxlU3lzdGVtUG9pbnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5REFBbUQ7QUFDbkQsbURBQWtEO0FBRWxELE1BQU0sZUFBZSxHQUFHLHFCQUFxQixDQUFDO0FBQzlDLE1BQU0sRUFBRSxHQUFHLElBQUEsY0FBSSxFQUFDLEtBQUssSUFBSSxFQUFFO0lBQ3ZCLElBQUksRUFBRSxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsMERBQTBELEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkYsRUFBRSxDQUFDLGdCQUFnQixDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUU7UUFDdEMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckQsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQztBQUNyQixDQUFDLENBQUMsQ0FBQztBQUNILEtBQUssVUFBVSxjQUFjO0lBQ3pCLElBQUksUUFBUSxHQUFHLE1BQU0sRUFBRSxFQUFFLENBQUM7SUFDMUIsSUFBSSxDQUFDLFFBQVE7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUNoQyxPQUFPLFFBQVEsQ0FBQyxXQUFXLENBQUMsZUFBZSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUMzRixDQUFDO0FBQ0QsS0FBSyxVQUFVLEtBQUssQ0FBQyxHQUFXLEVBQUUsS0FBdUQ7SUFDckYsSUFBSSxXQUFXLEdBQUcsTUFBTSxjQUFjLEVBQUUsQ0FBQztJQUN6QyxJQUFJLENBQUMsV0FBVztRQUFFLE9BQU87SUFDekIsSUFBSSxHQUFHLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDdEMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNsQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDMUMsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDO0FBQ0QsS0FBSyxVQUFVLElBQUksQ0FBQyxHQUFXO0lBQzNCLElBQUksV0FBVyxHQUFHLE1BQU0sY0FBYyxFQUFFLENBQUM7SUFDekMsSUFBSSxDQUFDLFdBQVc7UUFBRSxPQUFPO0lBQ3pCLElBQUksR0FBRyxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDL0IsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNsQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUM7QUFDdEIsQ0FBQztBQUdNLEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxNQUc1QztJQUNHLE1BQU8sTUFBTSxDQUFDLE1BQWMsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0RSxJQUFJLEdBQUcsR0FBRyxJQUFBLGFBQU0sR0FBRSxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQ3ZDLE1BQU0sS0FBSyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEMsT0FBTyxHQUFHLENBQUM7QUFDZixDQUFDO0FBUkQsd0RBUUM7QUFDTSxLQUFLLFVBQVUsdUJBQXVCLENBQUMsT0FBMEI7SUFDcEUsSUFBSSxXQUFXLEdBQUcsTUFBTSxjQUFjLEVBQUUsQ0FBQztJQUN6QyxJQUFJLENBQUMsV0FBVztRQUFFLE9BQU87SUFDekIsSUFBSSxHQUFHLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0QyxNQUFNLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ2xDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDekMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxQyxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUFSRCwwREFRQztBQUVNLEtBQUssVUFBVSxvQkFBb0IsQ0FBQyxNQUUxQztJQVNHLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxQyxJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU87SUFDcEIsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUMsT0FBTztRQUNILEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZO1lBQy9CLElBQUksUUFBUSxHQUFHLE1BQU8sTUFBYyxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ3JFLElBQUksUUFBUSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUNwQixNQUFPLE1BQWMsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLElBQUksRUFBRSxZQUFZLGFBQVosWUFBWSxjQUFaLFlBQVksR0FBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQzVFLENBQUM7WUFDRCxPQUFPLE1BQU0sQ0FBQztRQUNsQixDQUFDO0tBQ0osQ0FBQztBQUNOLENBQUM7QUF2QkQsb0RBdUJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbGF6eSB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2NhY2hpbmdcIjtcbmltcG9ydCB7IG5leHRJZCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL21pc2NcIjtcblxuY29uc3Qgb2JqZWN0U3RvcmVOYW1lID0gXCJmaWxlU3lzdGVtUG9pbnRlckRCXCI7XG5jb25zdCBkYiA9IGxhenkoYXN5bmMgKCkgPT4ge1xuICAgIGxldCBkYiA9IGluZGV4ZWREQi5vcGVuKFwiZmlsZVN5c3RlbVBvaW50ZXJEQl9mMjk4ZTk2Mi1iZDhhLTQ2YjktODA5OC0yNWRiNjMzZjRlZDNcIiwgMSk7XG4gICAgZGIuYWRkRXZlbnRMaXN0ZW5lcihcInVwZ3JhZGVuZWVkZWRcIiwgKCkgPT4ge1xuICAgICAgICBkYi5yZXN1bHQuY3JlYXRlT2JqZWN0U3RvcmUob2JqZWN0U3RvcmVOYW1lLCB7fSk7XG4gICAgfSk7XG4gICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBkYi5hZGRFdmVudExpc3RlbmVyKFwic3VjY2Vzc1wiLCByZXNvbHZlKSk7XG4gICAgcmV0dXJuIGRiLnJlc3VsdDtcbn0pO1xuYXN5bmMgZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb24oKSB7XG4gICAgbGV0IGRhdGFiYXNlID0gYXdhaXQgZGIoKTtcbiAgICBpZiAoIWRhdGFiYXNlKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBkYXRhYmFzZS50cmFuc2FjdGlvbihvYmplY3RTdG9yZU5hbWUsIFwicmVhZHdyaXRlXCIpLm9iamVjdFN0b3JlKG9iamVjdFN0b3JlTmFtZSk7XG59XG5hc3luYyBmdW5jdGlvbiB3cml0ZShrZXk6IHN0cmluZywgdmFsdWU6IEZpbGVTeXN0ZW1GaWxlSGFuZGxlIHwgRmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZSkge1xuICAgIGxldCB0cmFuc2FjdGlvbiA9IGF3YWl0IGdldFRyYW5zYWN0aW9uKCk7XG4gICAgaWYgKCF0cmFuc2FjdGlvbikgcmV0dXJuO1xuICAgIGxldCByZXEgPSB0cmFuc2FjdGlvbi5wdXQodmFsdWUsIGtleSk7XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICByZXEuYWRkRXZlbnRMaXN0ZW5lcihcInN1Y2Nlc3NcIiwgcmVzb2x2ZSk7XG4gICAgICAgIHJlcS5hZGRFdmVudExpc3RlbmVyKFwiZXJyb3JcIiwgcmVqZWN0KTtcbiAgICB9KTtcbn1cbmFzeW5jIGZ1bmN0aW9uIHJlYWQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPEZpbGVTeXN0ZW1GaWxlSGFuZGxlIHwgRmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZSB8IHVuZGVmaW5lZD4ge1xuICAgIGxldCB0cmFuc2FjdGlvbiA9IGF3YWl0IGdldFRyYW5zYWN0aW9uKCk7XG4gICAgaWYgKCF0cmFuc2FjdGlvbikgcmV0dXJuO1xuICAgIGxldCByZXEgPSB0cmFuc2FjdGlvbi5nZXQoa2V5KTtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHJlcS5hZGRFdmVudExpc3RlbmVyKFwic3VjY2Vzc1wiLCByZXNvbHZlKTtcbiAgICAgICAgcmVxLmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCByZWplY3QpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXEucmVzdWx0O1xufVxuXG5leHBvcnQgdHlwZSBGaWxlU3lzdGVtUG9pbnRlciA9IHN0cmluZztcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdG9yZUZpbGVTeXN0ZW1Qb2ludGVyKGNvbmZpZzoge1xuICAgIG1vZGU6IFwicmVhZFwiIHwgXCJyZWFkd3JpdGVcIjtcbiAgICBoYW5kbGU6IEZpbGVTeXN0ZW1GaWxlSGFuZGxlIHwgRmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZTtcbn0pOiBQcm9taXNlPEZpbGVTeXN0ZW1Qb2ludGVyPiB7XG4gICAgYXdhaXQgKGNvbmZpZy5oYW5kbGUgYXMgYW55KS5yZXF1ZXN0UGVybWlzc2lvbih7IG1vZGU6IGNvbmZpZy5tb2RlIH0pO1xuICAgIGxldCBrZXkgPSBuZXh0SWQoKSArIFwiX1wiICsgY29uZmlnLm1vZGU7XG4gICAgYXdhaXQgd3JpdGUoa2V5LCBjb25maWcuaGFuZGxlKTtcbiAgICByZXR1cm4ga2V5O1xufVxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZUZpbGVTeXN0ZW1Qb2ludGVyKHBvaW50ZXI6IEZpbGVTeXN0ZW1Qb2ludGVyKSB7XG4gICAgbGV0IHRyYW5zYWN0aW9uID0gYXdhaXQgZ2V0VHJhbnNhY3Rpb24oKTtcbiAgICBpZiAoIXRyYW5zYWN0aW9uKSByZXR1cm47XG4gICAgbGV0IHJlcSA9IHRyYW5zYWN0aW9uLmRlbGV0ZShwb2ludGVyKTtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHJlcS5hZGRFdmVudExpc3RlbmVyKFwic3VjY2Vzc1wiLCByZXNvbHZlKTtcbiAgICAgICAgcmVxLmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCByZWplY3QpO1xuICAgIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RmlsZVN5c3RlbVBvaW50ZXIoY29uZmlnOiB7XG4gICAgcG9pbnRlcjogRmlsZVN5c3RlbVBvaW50ZXI7XG59KTogUHJvbWlzZTx7XG4gICAgLy8gTk9URTogV2UgaGF2ZSB0byBjYWxsIHJlcXVlc3RQZXJtaXNzaW9uLCBzby4uLiB1c2VyIGFjdGl2YXRpb24gaXMgcmVxdWlyZWQgKGFzIGluLFxuICAgIC8vICB0aGlzIG5lZWQgdG8gYmUgY2FsbGVkIGluc2lkZSBvZiBhIGJ1dHRvbikuXG4gICAgLy8gSU1QT1JUQU5UISBJbiBzb21lIGNpcmN1bXN0YW5jZXMgdXNlciBhY3RpdmF0aW9uIGlzIG5vdCByZXF1aXJlZCAod2l0aCBtdWx0aXBsZSB0YWJzLFxuICAgIC8vICAgICAgYW5kIHBvdGVudGlhbGx5IHdpdGggaHR0cHM6Ly9kZXZlbG9wZXIuY2hyb21lLmNvbS9ibG9nL3BlcnNpc3RlbnQtcGVybWlzc2lvbnMtZm9yLXRoZS1maWxlLXN5c3RlbS1hY2Nlc3MtYXBpKSxcbiAgICAvLyAgICAgIHNvLi4uIHRyeWluZyB0byBjYWxsIG9uVXNlckFjdGl2YXRpb24gaW1tbWVkaWF0ZWx5IGlzIGEgZ29vZCBpZGVhIChhbHRob3VnaCBpdCBtaWdodCB0aHJvdykuXG4gICAgb25Vc2VyQWN0aXZhdGlvbihtb2RlT3ZlcnJpZGU/OiBcInJlYWRcIiB8IFwicmVhZHdyaXRlXCIpOiBQcm9taXNlPEZpbGVTeXN0ZW1GaWxlSGFuZGxlIHwgRmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZT5cbn0gfCB1bmRlZmluZWRcbj4ge1xuICAgIGNvbnN0IGhhbmRsZSA9IGF3YWl0IHJlYWQoY29uZmlnLnBvaW50ZXIpO1xuICAgIGlmICghaGFuZGxlKSByZXR1cm47XG4gICAgbGV0IG1vZGUgPSBjb25maWcucG9pbnRlci5zcGxpdChcIl9cIikuYXQoLTEpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGFzeW5jIG9uVXNlckFjdGl2YXRpb24obW9kZU92ZXJyaWRlKSB7XG4gICAgICAgICAgICBsZXQgdGVzdE1vZGUgPSBhd2FpdCAoaGFuZGxlIGFzIGFueSkucXVlcnlQZXJtaXNzaW9uKHsgbW9kZTogbW9kZSB9KTtcbiAgICAgICAgICAgIGlmICh0ZXN0TW9kZSAhPT0gbW9kZSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IChoYW5kbGUgYXMgYW55KS5yZXF1ZXN0UGVybWlzc2lvbih7IG1vZGU6IG1vZGVPdmVycmlkZSA/PyBtb2RlIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZTtcbiAgICAgICAgfVxuICAgIH07XG59Il19
|
|
77
|
+
/* _JS_SOURCE_HASH = "48ea788e6857a9aab2e957d5ebef940a9cec94997aaf61e8855616fc40d95197"; */
|