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,495 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.testRemoteConnection = exports.getRemoteDirectoryHandle = void 0;
4
+ const typesafecss_1 = require("typesafecss");
5
+ // A remote server (remoteFileServer.js) exposed as a DirectoryWrapper — the SAME interface as the
6
+ // Node.js and File-System-Access handles. So getDirectoryHandle can return one of these and everything
7
+ // downstream (wrapHandle, navigation, BulkDatabase2) works unchanged; nothing else knows it's remote.
8
+ //
9
+ // Files here are immutable (written once) or append-only, so the range cache (raw compressed bytes, in
10
+ // ~1MB aligned chunks) is always valid — over the network latency dominates, so reading 1MB costs about
11
+ // the same as 64KB and far fewer round trips wins.
12
+ const EMPTY = Buffer.alloc(0);
13
+ const DEFAULT_CHUNK_BYTES = 1024 * 1024;
14
+ const DEFAULT_CACHE_BYTES = 128 * 1024 * 1024;
15
+ function enoent(p) {
16
+ return Object.assign(new Error(`File not found: ${p}`), { code: "ENOENT", name: "NotFoundError" });
17
+ }
18
+ function toArrayBuffer(b) {
19
+ return b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
20
+ }
21
+ const sleep = (ms) => new Promise(r => setTimeout(r, ms));
22
+ // A stat is cached this long, so the burst of size lookups during a single read pass is one request per
23
+ // file, not one per block. Short enough that an append by another writer shows up promptly; our own
24
+ // writes invalidate it immediately.
25
+ const INFO_TTL_MS = 2000;
26
+ // We keep at most this many bytes of read/write requests in flight at once (the rest queue), so a big
27
+ // read doesn't fire hundreds of MB of requests at the server simultaneously.
28
+ const MAX_INFLIGHT_BYTES = 64 * 1024 * 1024;
29
+ // A single read request fetches at most this much; large reads are split into this many concurrent
30
+ // requests (bounded by MAX_INFLIGHT_BYTES).
31
+ const DEFAULT_MAX_FETCH_BYTES = 4 * 1024 * 1024;
32
+ const STATS_LOG_INTERVAL_MS = 10 * 1000;
33
+ const RECV_WINDOW_MS = 60 * 1000;
34
+ function fmtBytes(n) {
35
+ if (n < 1024)
36
+ return n + "B";
37
+ if (n < 1024 * 1024)
38
+ return (n / 1024).toFixed(1) + "KB";
39
+ if (n < 1024 * 1024 * 1024)
40
+ return (n / 1024 / 1024).toFixed(1) + "MB";
41
+ return (n / 1024 / 1024 / 1024).toFixed(2) + "GB";
42
+ }
43
+ function makeWebSocket(url) {
44
+ if ((0, typesafecss_1.isNode)()) {
45
+ // `ws` is a Node dep; the eval hides it from the browser bundler (this branch never runs there).
46
+ const WS = eval("require")("ws");
47
+ return new WS(url, { rejectUnauthorized: false }); // self-signed cert
48
+ }
49
+ return new WebSocket(url);
50
+ }
51
+ // Binary frame: [u32 headerLen LE][header JSON][body bytes].
52
+ function encodeFrame(header, body) {
53
+ const h = Buffer.from(JSON.stringify(header), "utf8");
54
+ const len = Buffer.alloc(4);
55
+ len.writeUInt32LE(h.length, 0);
56
+ return Buffer.concat([len, h, body || EMPTY]);
57
+ }
58
+ function decodeFrame(buf) {
59
+ const headerLen = buf.readUInt32LE(0);
60
+ const header = JSON.parse(buf.subarray(4, 4 + headerLen).toString("utf8"));
61
+ return { header, body: buf.subarray(4 + headerLen) };
62
+ }
63
+ // One WebSocket to a remote server, multiplexing all ops over it. Requests are queued and only sent
64
+ // while < MAX_INFLIGHT_BYTES are outstanding; every 10s (when there's traffic) it logs the queue depth
65
+ // and throughput.
66
+ class Connection {
67
+ constructor(url, password, opts) {
68
+ var _a, _b;
69
+ this.url = url;
70
+ this.password = password;
71
+ this.opts = opts;
72
+ this.infoCache = new Map();
73
+ this.nextId = 1;
74
+ this.pending = new Map();
75
+ this.queue = [];
76
+ this.inFlightBytes = 0;
77
+ this.receivedTotal = 0;
78
+ this.recvWindow = [];
79
+ this.url = url.replace(/\/+$/, "");
80
+ this.wsUrl = this.url.replace(/^http/, "ws"); // https→wss, http→ws
81
+ this.host = (() => { try {
82
+ return new URL(this.url).host;
83
+ }
84
+ catch (_a) {
85
+ return this.url;
86
+ } })();
87
+ this.cache = new RangeCache(opts.chunkBytes || DEFAULT_CHUNK_BYTES, opts.cacheBytes || DEFAULT_CACHE_BYTES, opts.maxFetchBytes || DEFAULT_MAX_FETCH_BYTES);
88
+ this.statsTimer = setInterval(() => this.logStats(), STATS_LOG_INTERVAL_MS);
89
+ (_b = (_a = this.statsTimer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
90
+ }
91
+ close() {
92
+ var _a;
93
+ clearInterval(this.statsTimer);
94
+ try {
95
+ (_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
96
+ }
97
+ catch ( /* */_b) { /* */ }
98
+ this.ws = undefined;
99
+ this.connecting = undefined;
100
+ }
101
+ logStats() {
102
+ const now = Date.now();
103
+ this.recvWindow = this.recvWindow.filter(e => now - e.t < RECV_WINDOW_MS);
104
+ if (this.inFlightBytes === 0 && this.queue.length === 0)
105
+ return; // only when there's traffic
106
+ const recv60 = this.recvWindow.reduce((a, e) => a + e.n, 0);
107
+ const queuedBytes = this.queue.reduce((a, q) => a + q.bytes, 0);
108
+ console.log(`[remote ${this.host}] outstanding ${fmtBytes(this.inFlightBytes)} (${this.pending.size} req), queued ${fmtBytes(queuedBytes)} (${this.queue.length} req), recv/60s ${fmtBytes(recv60)}, recv total ${fmtBytes(this.receivedTotal)}`);
109
+ }
110
+ ensureConnected() {
111
+ if (this.ws && this.ws.readyState === 1)
112
+ return Promise.resolve();
113
+ if (this.connecting)
114
+ return this.connecting;
115
+ this.connecting = new Promise((resolve, reject) => {
116
+ let authed = false;
117
+ const ws = makeWebSocket(this.wsUrl);
118
+ ws.binaryType = "arraybuffer";
119
+ this.ws = ws;
120
+ ws.onopen = () => ws.send(encodeFrame({ id: 0, op: "auth", password: this.password }));
121
+ ws.onmessage = (ev) => {
122
+ const buf = Buffer.isBuffer(ev.data) ? ev.data : Buffer.from(ev.data);
123
+ const { header } = decodeFrame(buf);
124
+ if (!authed && header.id === 0) {
125
+ if (header.status === 200) {
126
+ authed = true;
127
+ resolve();
128
+ }
129
+ else {
130
+ reject(new Error("remote: authentication failed"));
131
+ try {
132
+ ws.close();
133
+ }
134
+ catch ( /* */_a) { /* */ }
135
+ }
136
+ return;
137
+ }
138
+ this.onMessage(buf);
139
+ };
140
+ ws.onerror = () => { if (!authed)
141
+ reject(new Error("remote: websocket connection error")); };
142
+ ws.onclose = () => {
143
+ if (!authed)
144
+ reject(new Error("remote: connection closed before authenticating"));
145
+ this.handleDisconnect();
146
+ };
147
+ });
148
+ // Let a failed connection be retried next time.
149
+ this.connecting.catch(() => { this.ws = undefined; this.connecting = undefined; });
150
+ return this.connecting;
151
+ }
152
+ onMessage(buf) {
153
+ const { header, body } = decodeFrame(buf);
154
+ const p = this.pending.get(header.id);
155
+ if (!p)
156
+ return;
157
+ this.pending.delete(header.id);
158
+ this.inFlightBytes -= p.bytes;
159
+ this.receivedTotal += body.length;
160
+ if (this.opts.stats)
161
+ this.opts.stats.bytesFetched += body.length;
162
+ this.recvWindow.push({ t: Date.now(), n: body.length });
163
+ p.resolve({ status: header.status, body });
164
+ this.drain();
165
+ }
166
+ handleDisconnect() {
167
+ const err = new Error("remote: websocket disconnected");
168
+ for (const p of this.pending.values())
169
+ p.reject(err);
170
+ for (const q of this.queue)
171
+ q.reject(err);
172
+ this.pending.clear();
173
+ this.queue = [];
174
+ this.inFlightBytes = 0;
175
+ this.ws = undefined;
176
+ this.connecting = undefined;
177
+ }
178
+ drain() {
179
+ while (this.queue.length && this.ws && this.ws.readyState === 1) {
180
+ const next = this.queue[0];
181
+ if (this.inFlightBytes > 0 && this.inFlightBytes + next.bytes > MAX_INFLIGHT_BYTES)
182
+ break; // hold the queue
183
+ this.queue.shift();
184
+ this.inFlightBytes += next.bytes;
185
+ this.pending.set(next.id, { resolve: next.resolve, reject: next.reject, bytes: next.bytes });
186
+ if (this.opts.stats)
187
+ this.opts.stats.requestCount++;
188
+ this.ws.send(next.frame);
189
+ }
190
+ }
191
+ // Sends one request over the WebSocket (queued + throttled). `bytes` is the expected payload size,
192
+ // used for the in-flight cap.
193
+ async request(op, params, body, bytes) {
194
+ if (this.opts.latencyMs)
195
+ await sleep(this.opts.latencyMs);
196
+ await this.ensureConnected();
197
+ const id = this.nextId++;
198
+ const frame = encodeFrame({ id, op, ...params }, body);
199
+ return new Promise((resolve, reject) => {
200
+ this.queue.push({ id, frame, bytes: Math.max(bytes, body ? body.length : 0, 1), resolve, reject });
201
+ this.drain();
202
+ });
203
+ }
204
+ async stat(path) {
205
+ const cached = this.infoCache.get(path);
206
+ if (cached && Date.now() - cached.at < INFO_TTL_MS)
207
+ return cached.stat;
208
+ const r = await this.request("info", { path }, undefined, 256);
209
+ let stat;
210
+ if (r.status === 404)
211
+ stat = undefined;
212
+ else if (r.status !== 200)
213
+ throw new Error(`remote info failed (${r.status})`);
214
+ else
215
+ stat = JSON.parse(r.body.toString("utf8"));
216
+ this.infoCache.set(path, { stat, at: Date.now() });
217
+ return stat;
218
+ }
219
+ async list(path) {
220
+ const r = await this.request("list", { path }, undefined, 4096);
221
+ if (r.status !== 200)
222
+ throw new Error(`remote list failed (${r.status})`);
223
+ return JSON.parse(r.body.toString("utf8"));
224
+ }
225
+ async read(path, start, end) {
226
+ var _a;
227
+ return (_a = (await this.cache.read(this, path, start, end))) !== null && _a !== void 0 ? _a : EMPTY;
228
+ }
229
+ async readServer(path, start, end) {
230
+ const r = await this.request("read", { path, start, end }, undefined, end - start);
231
+ if (r.status === 404)
232
+ return undefined;
233
+ if (r.status !== 200)
234
+ throw new Error(`remote read failed (${r.status})`);
235
+ return r.body;
236
+ }
237
+ async append(path, body) {
238
+ const r = await this.request("append", { path }, body, body.length);
239
+ if (r.status !== 200)
240
+ throw new Error(`remote append failed (${r.status})`);
241
+ this.infoCache.delete(path); // append-only keeps existing bytes; only the size changed
242
+ }
243
+ async set(path, body) {
244
+ const r = await this.request("set", { path }, body, body.length);
245
+ if (r.status !== 200)
246
+ throw new Error(`remote set failed (${r.status})`);
247
+ this.cache.invalidate(path);
248
+ this.infoCache.delete(path);
249
+ }
250
+ async remove(path) {
251
+ const r = await this.request("remove", { path }, undefined, 256);
252
+ if (r.status !== 200)
253
+ throw new Error(`remote remove failed (${r.status})`);
254
+ this.cache.invalidate(path);
255
+ this.infoCache.delete(path);
256
+ }
257
+ }
258
+ // Caches the longest-known prefix of each aligned chunk per path. Valid because files are immutable or
259
+ // append-only (the bytes at an offset never change). It only does range reads — it doesn't care what
260
+ // the files are.
261
+ class RangeCache {
262
+ constructor(chunkBytes, budget, maxFetchBytes) {
263
+ this.chunkBytes = chunkBytes;
264
+ this.budget = budget;
265
+ this.maxFetchBytes = maxFetchBytes;
266
+ this.chunks = new Map(); // path + "" + chunkIndex, insertion-ordered (LRU)
267
+ this.bytes = 0;
268
+ }
269
+ key(path, c) { return path + "" + c; }
270
+ peek(path, c) {
271
+ const k = this.key(path, c);
272
+ const v = this.chunks.get(k);
273
+ if (v) {
274
+ this.chunks.delete(k);
275
+ this.chunks.set(k, v);
276
+ }
277
+ return v;
278
+ }
279
+ store(path, c, buf) {
280
+ const k = this.key(path, c);
281
+ const ex = this.chunks.get(k);
282
+ if (ex && ex.length >= buf.length) {
283
+ this.chunks.delete(k);
284
+ this.chunks.set(k, ex);
285
+ return;
286
+ }
287
+ if (ex)
288
+ this.bytes -= ex.length;
289
+ this.chunks.delete(k);
290
+ this.chunks.set(k, buf);
291
+ this.bytes += buf.length;
292
+ while (this.bytes > this.budget && this.chunks.size > 0) {
293
+ const oldest = this.chunks.keys().next().value;
294
+ this.bytes -= this.chunks.get(oldest).length;
295
+ this.chunks.delete(oldest);
296
+ }
297
+ }
298
+ invalidate(path) {
299
+ const prefix = path + "";
300
+ for (const k of [...this.chunks.keys()])
301
+ if (k.startsWith(prefix)) {
302
+ this.bytes -= this.chunks.get(k).length;
303
+ this.chunks.delete(k);
304
+ }
305
+ }
306
+ async read(conn, path, start, end) {
307
+ if (end <= start)
308
+ return EMPTY;
309
+ const CHUNK = this.chunkBytes;
310
+ const maxRunChunks = Math.max(1, Math.floor(this.maxFetchBytes / CHUNK));
311
+ const firstChunk = Math.floor(start / CHUNK);
312
+ const lastChunk = Math.floor((end - 1) / CHUNK);
313
+ // Collect the chunks we don't have deeply enough into bounded contiguous runs (each <= maxFetchBytes).
314
+ const runs = [];
315
+ let runFrom = -1;
316
+ for (let c = firstChunk; c <= lastChunk; c++) {
317
+ const cStart = c * CHUNK;
318
+ const needEnd = Math.min(end, cStart + CHUNK) - cStart;
319
+ const have = this.peek(path, c);
320
+ if (!have || have.length < needEnd) {
321
+ if (runFrom < 0)
322
+ runFrom = c;
323
+ if (c - runFrom + 1 >= maxRunChunks) {
324
+ runs.push({ from: runFrom, to: c });
325
+ runFrom = -1;
326
+ }
327
+ }
328
+ else if (runFrom >= 0) {
329
+ runs.push({ from: runFrom, to: c - 1 });
330
+ runFrom = -1;
331
+ }
332
+ }
333
+ if (runFrom >= 0)
334
+ runs.push({ from: runFrom, to: lastChunk });
335
+ // Fetch all runs concurrently; the connection's queue caps total in-flight bytes.
336
+ let missingFile = false;
337
+ await Promise.all(runs.map(async (run) => {
338
+ const bytes = await conn.readServer(path, run.from * CHUNK, (run.to + 1) * CHUNK);
339
+ if (bytes === undefined) {
340
+ missingFile = true;
341
+ return;
342
+ }
343
+ for (let c = run.from; c <= run.to; c++) {
344
+ const off = (c - run.from) * CHUNK;
345
+ if (off >= bytes.length)
346
+ break;
347
+ this.store(path, c, bytes.subarray(off, Math.min(off + CHUNK, bytes.length)));
348
+ }
349
+ }));
350
+ if (missingFile)
351
+ return undefined;
352
+ const parts = [];
353
+ for (let c = firstChunk; c <= lastChunk; c++) {
354
+ const cStart = c * CHUNK;
355
+ const from = Math.max(start, cStart) - cStart;
356
+ const to = Math.min(end, cStart + CHUNK) - cStart;
357
+ const chunk = this.peek(path, c);
358
+ if (!chunk || chunk.length < to) {
359
+ if (chunk && chunk.length > from)
360
+ parts.push(chunk.subarray(from, chunk.length));
361
+ break;
362
+ }
363
+ parts.push(chunk.subarray(from, to));
364
+ }
365
+ return parts.length === 1 ? parts[0] : Buffer.concat(parts);
366
+ }
367
+ }
368
+ const joinPath = (base, key) => (base ? base + "/" + key : key);
369
+ const baseName = (p) => p.split("/").filter(Boolean).pop() || "";
370
+ class RemoteFileWrapper {
371
+ // `stat` is supplied when the parent already statted us (avoids a second /info). `createIntent` means
372
+ // this was opened with create:true, so a missing file reads as empty (it'll be created on write).
373
+ constructor(conn, filePath, stat, createIntent = false) {
374
+ this.conn = conn;
375
+ this.filePath = filePath;
376
+ this.stat = stat;
377
+ this.createIntent = createIntent;
378
+ // Mirror the native FileSystemFileHandle shape so code written against it works unchanged.
379
+ this.kind = "file";
380
+ }
381
+ get name() { return baseName(this.filePath); }
382
+ async getFile() {
383
+ var _a;
384
+ let stat = (_a = this.stat) !== null && _a !== void 0 ? _a : await this.conn.stat(this.filePath);
385
+ if (!stat) {
386
+ if (!this.createIntent)
387
+ throw enoent(this.filePath);
388
+ stat = { size: 0, lastModified: Date.now(), dir: false };
389
+ }
390
+ const conn = this.conn, filePath = this.filePath, size = stat.size;
391
+ return {
392
+ size, lastModified: stat.lastModified,
393
+ async arrayBuffer() { return toArrayBuffer(await conn.read(filePath, 0, size)); },
394
+ slice(start, end) {
395
+ return { async arrayBuffer() { return toArrayBuffer(await conn.read(filePath, start, end)); } };
396
+ },
397
+ };
398
+ }
399
+ async getURL() {
400
+ // HTTPS URL into the server's range-capable /media endpoint. The token rides in the query because a
401
+ // <video>/<img> element can't send an Authorization header.
402
+ return `${this.conn.url}/media?path=${encodeURIComponent(this.filePath)}&token=${encodeURIComponent(this.conn.password)}`;
403
+ }
404
+ async createWritable(config) {
405
+ const conn = this.conn, filePath = this.filePath, append = !!(config === null || config === void 0 ? void 0 : config.keepExistingData);
406
+ const chunks = [];
407
+ return {
408
+ async seek() { },
409
+ async write(value) { chunks.push(value); },
410
+ async close() {
411
+ const body = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
412
+ if (append)
413
+ await conn.append(filePath, body);
414
+ else
415
+ await conn.set(filePath, body);
416
+ },
417
+ };
418
+ }
419
+ }
420
+ class RemoteDirectoryWrapper {
421
+ constructor(conn, dirPath) {
422
+ this.conn = conn;
423
+ this.dirPath = dirPath;
424
+ // Mirror the native FileSystemDirectoryHandle shape (name/kind/entries) so code written against the
425
+ // native API — e.g. recursive walks using `handle.entries()` — works the same over the network.
426
+ this.kind = "directory";
427
+ this.isRemote = true;
428
+ }
429
+ get name() { return baseName(this.dirPath); }
430
+ get fullPath() { return this.dirPath; }
431
+ async removeEntry(key) {
432
+ await this.conn.remove(joinPath(this.dirPath, key));
433
+ }
434
+ async getFileHandle(key, options) {
435
+ const p = joinPath(this.dirPath, key);
436
+ if (options === null || options === void 0 ? void 0 : options.create)
437
+ return new RemoteFileWrapper(this.conn, p, undefined, true);
438
+ const stat = await this.conn.stat(p); // matches the File API: throw if missing
439
+ if (!stat || stat.dir)
440
+ throw enoent(p);
441
+ return new RemoteFileWrapper(this.conn, p, stat, false);
442
+ }
443
+ async getDirectoryHandle(key, options) {
444
+ const p = joinPath(this.dirPath, key);
445
+ if (!(options === null || options === void 0 ? void 0 : options.create)) {
446
+ const stat = await this.conn.stat(p);
447
+ if (!stat || !stat.dir)
448
+ throw enoent(p);
449
+ }
450
+ return new RemoteDirectoryWrapper(this.conn, p); // dirs are created lazily on first write
451
+ }
452
+ // Each entry is itself a real handle (a sub-wrapper), so a recursive walk over .entries() keeps
453
+ // working at every level — exactly like the native API.
454
+ async *[Symbol.asyncIterator]() {
455
+ const entries = await this.conn.list(this.dirPath);
456
+ for (const e of entries) {
457
+ const childPath = joinPath(this.dirPath, e.name);
458
+ yield [e.name, e.dir ? new RemoteDirectoryWrapper(this.conn, childPath) : new RemoteFileWrapper(this.conn, childPath)];
459
+ }
460
+ }
461
+ entries() { return this[Symbol.asyncIterator](); }
462
+ keys() { return mapAsync(this[Symbol.asyncIterator](), ([name]) => name); }
463
+ values() { return mapAsync(this[Symbol.asyncIterator](), ([, handle]) => handle); }
464
+ }
465
+ async function* mapAsync(it, fn) {
466
+ for await (const v of it)
467
+ yield fn(v);
468
+ }
469
+ // A DirectoryWrapper rooted at a remote server. Drop-in for the Node / File-API handles.
470
+ function getRemoteDirectoryHandle(url, password, options = {}) {
471
+ return new RemoteDirectoryWrapper(new Connection(url, password, options), "");
472
+ }
473
+ exports.getRemoteDirectoryHandle = getRemoteDirectoryHandle;
474
+ // Verifies a server is reachable and the password works — by opening the WebSocket, authenticating, and
475
+ // listing the root. Distinguishes "connected" / "wrong password" / "couldn't reach it" (the last usually
476
+ // meaning the self-signed cert isn't trusted yet in the browser, since the socket just fails to open).
477
+ async function testRemoteConnection(url, password, options = {}) {
478
+ const conn = new Connection(url, password, options);
479
+ try {
480
+ await conn.list("");
481
+ return { status: "ok" };
482
+ }
483
+ catch (e) {
484
+ const msg = (e === null || e === void 0 ? void 0 : e.message) || String(e);
485
+ if (/auth/i.test(msg))
486
+ return { status: "unauthorized" };
487
+ return { status: "unreachable", error: msg };
488
+ }
489
+ finally {
490
+ conn.close();
491
+ }
492
+ }
493
+ exports.testRemoteConnection = testRemoteConnection;
494
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3RlRmlsZVN0b3JhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJyZW1vdGVGaWxlU3RvcmFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBcUM7QUFHckMsa0dBQWtHO0FBQ2xHLHVHQUF1RztBQUN2RyxzR0FBc0c7QUFDdEcsRUFBRTtBQUNGLHVHQUF1RztBQUN2Ryx3R0FBd0c7QUFDeEcsbURBQW1EO0FBRW5ELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDOUIsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ3hDLE1BQU0sbUJBQW1CLEdBQUcsR0FBRyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFVOUMsU0FBUyxNQUFNLENBQUMsQ0FBUztJQUNyQixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsbUJBQW1CLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsQ0FBQyxDQUFDO0FBQ3ZHLENBQUM7QUFDRCxTQUFTLGFBQWEsQ0FBQyxDQUFTO0lBQzVCLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxVQUFVLENBQWdCLENBQUM7QUFDcEYsQ0FBQztBQUNELE1BQU0sS0FBSyxHQUFHLENBQUMsRUFBVSxFQUFFLEVBQUUsQ0FBQyxJQUFJLE9BQU8sQ0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUl4RSx3R0FBd0c7QUFDeEcsb0dBQW9HO0FBQ3BHLG9DQUFvQztBQUNwQyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUM7QUFDekIsc0dBQXNHO0FBQ3RHLDZFQUE2RTtBQUM3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RSxDQUFTLElBQUksT0FBTyxJQUFJLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsSUFBSSxDQUFDLElBQVksRUFBRSxDQUFTO1FBQ2hDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVCLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxFQUFFLENBQUM7WUFBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUFDLENBQUM7UUFDeEQsT0FBTyxDQUFDLENBQUM7SUFDYixDQUFDO0lBQ08sS0FBSyxDQUFDLElBQVksRUFBRSxDQUFTLEVBQUUsR0FBVztRQUM5QyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1QixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QixJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQUMsT0FBTztRQUFDLENBQUM7UUFDN0YsSUFBSSxFQUFFO1lBQUUsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsTUFBTSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RCLElBQUksQ0FBQyxNQUFNLENB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O1FBQ1AsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2pCLENBQUM7QUFDTCxDQUFDO0FBWkQsb0RBWUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc05vZGUgfSBmcm9tIFwidHlwZXNhZmVjc3NcIjtcbmltcG9ydCB0eXBlIHsgRGlyZWN0b3J5V3JhcHBlciwgRmlsZVdyYXBwZXIgfSBmcm9tIFwiLi9GaWxlRm9sZGVyQVBJXCI7XG5cbi8vIEEgcmVtb3RlIHNlcnZlciAocmVtb3RlRmlsZVNlcnZlci5qcykgZXhwb3NlZCBhcyBhIERpcmVjdG9yeVdyYXBwZXIg4oCUIHRoZSBTQU1FIGludGVyZmFjZSBhcyB0aGVcbi8vIE5vZGUuanMgYW5kIEZpbGUtU3lzdGVtLUFjY2VzcyBoYW5kbGVzLiBTbyBnZXREaXJlY3RvcnlIYW5kbGUgY2FuIHJldHVybiBvbmUgb2YgdGhlc2UgYW5kIGV2ZXJ5dGhpbmdcbi8vIGRvd25zdHJlYW0gKHdyYXBIYW5kbGUsIG5hdmlnYXRpb24sIEJ1bGtEYXRhYmFzZTIpIHdvcmtzIHVuY2hhbmdlZDsgbm90aGluZyBlbHNlIGtub3dzIGl0J3MgcmVtb3RlLlxuLy9cbi8vIEZpbGVzIGhlcmUgYXJlIGltbXV0YWJsZSAod3JpdHRlbiBvbmNlKSBvciBhcHBlbmQtb25seSwgc28gdGhlIHJhbmdlIGNhY2hlIChyYXcgY29tcHJlc3NlZCBieXRlcywgaW5cbi8vIH4xTUIgYWxpZ25lZCBjaHVua3MpIGlzIGFsd2F5cyB2YWxpZCDigJQgb3ZlciB0aGUgbmV0d29yayBsYXRlbmN5IGRvbWluYXRlcywgc28gcmVhZGluZyAxTUIgY29zdHMgYWJvdXRcbi8vIHRoZSBzYW1lIGFzIDY0S0IgYW5kIGZhciBmZXdlciByb3VuZCB0cmlwcyB3aW5zLlxuXG5jb25zdCBFTVBUWSA9IEJ1ZmZlci5hbGxvYygwKTtcbmNvbnN0IERFRkFVTFRfQ0hVTktfQllURVMgPSAxMDI0ICogMTAyNDtcbmNvbnN0IERFRkFVTFRfQ0FDSEVfQllURVMgPSAxMjggKiAxMDI0ICogMTAyNDtcblxuZXhwb3J0IHR5cGUgUmVtb3RlT3B0aW9ucyA9IHtcbiAgICBjaHVua0J5dGVzPzogbnVtYmVyO1xuICAgIGNhY2hlQnl0ZXM/OiBudW1iZXI7XG4gICAgbWF4RmV0Y2hCeXRlcz86IG51bWJlcjsgICAgICAvLyBjYXAgcGVyIHJlYWQgcmVxdWVzdDsgbGFyZ2UgcmVhZHMgc3BsaXQgaW50byB0aGlzIG1hbnkgYnl0ZXMgZWFjaFxuICAgIGxhdGVuY3lNcz86IG51bWJlcjsgICAgICAgICAgLy8gYXJ0aWZpY2lhbCBwZXItcmVxdWVzdCBkZWxheSwgZm9yIHNpbXVsYXRpbmcgbmV0d29yayBsYXRlbmN5IGluIHRlc3RzXG4gICAgc3RhdHM/OiB7IHJlcXVlc3RDb3VudDogbnVtYmVyOyBieXRlc0ZldGNoZWQ6IG51bWJlciB9O1xufTtcblxuZnVuY3Rpb24gZW5vZW50KHA6IHN0cmluZyk6IEVycm9yIHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoYEZpbGUgbm90IGZvdW5kOiAke3B9YCksIHsgY29kZTogXCJFTk9FTlRcIiwgbmFtZTogXCJOb3RGb3VuZEVycm9yXCIgfSk7XG59XG5mdW5jdGlvbiB0b0FycmF5QnVmZmVyKGI6IEJ1ZmZlcik6IEFycmF5QnVmZmVyIHtcbiAgICByZXR1cm4gYi5idWZmZXIuc2xpY2UoYi5ieXRlT2Zmc2V0LCBiLmJ5dGVPZmZzZXQgKyBiLmJ5dGVMZW5ndGgpIGFzIEFycmF5QnVmZmVyO1xufVxuY29uc3Qgc2xlZXAgPSAobXM6IG51bWJlcikgPT4gbmV3IFByb21pc2U8dm9pZD4ociA9PiBzZXRUaW1lb3V0KHIsIG1zKSk7XG5cbnR5cGUgU3RhdCA9IHsgc2l6ZTogbnVtYmVyOyBsYXN0TW9kaWZpZWQ6IG51bWJlcjsgZGlyOiBib29sZWFuIH07XG5cbi8vIEEgc3RhdCBpcyBjYWNoZWQgdGhpcyBsb25nLCBzbyB0aGUgYnVyc3Qgb2Ygc2l6ZSBsb29rdXBzIGR1cmluZyBhIHNpbmdsZSByZWFkIHBhc3MgaXMgb25lIHJlcXVlc3QgcGVyXG4vLyBmaWxlLCBub3Qgb25lIHBlciBibG9jay4gU2hvcnQgZW5vdWdoIHRoYXQgYW4gYXBwZW5kIGJ5IGFub3RoZXIgd3JpdGVyIHNob3dzIHVwIHByb21wdGx5OyBvdXIgb3duXG4vLyB3cml0ZXMgaW52YWxpZGF0ZSBpdCBpbW1lZGlhdGVseS5cbmNvbnN0IElORk9fVFRMX01TID0gMjAwMDtcbi8vIFdlIGtlZXAgYXQgbW9zdCB0aGlzIG1hbnkgYnl0ZXMgb2YgcmVhZC93cml0ZSByZXF1ZXN0cyBpbiBmbGlnaHQgYXQgb25jZSAodGhlIHJlc3QgcXVldWUpLCBzbyBhIGJpZ1xuLy8gcmVhZCBkb2Vzbid0IGZpcmUgaHVuZHJlZHMgb2YgTUIgb2YgcmVxdWVzdHMgYXQgdGhlIHNlcnZlciBzaW11bHRhbmVvdXNseS5cbmNvbnN0IE1BWF9JTkZMSUdIVF9CWVRFUyA9IDY0ICogMTAyNCAqIDEwMjQ7XG4vLyBBIHNpbmdsZSByZWFkIHJlcXVlc3QgZmV0Y2hlcyBhdCBtb3N0IHRoaXMgbXVjaDsgbGFyZ2UgcmVhZHMgYXJlIHNwbGl0IGludG8gdGhpcyBtYW55IGNvbmN1cnJlbnRcbi8vIHJlcXVlc3RzIChib3VuZGVkIGJ5IE1BWF9JTkZMSUdIVF9CWVRFUykuXG5jb25zdCBERUZBVUxUX01BWF9GRVRDSF9CWVRFUyA9IDQgKiAxMDI0ICogMTAyNDtcbmNvbnN0IFNUQVRTX0xPR19JTlRFUlZBTF9NUyA9IDEwICogMTAwMDtcbmNvbnN0IFJFQ1ZfV0lORE9XX01TID0gNjAgKiAxMDAwO1xuXG5mdW5jdGlvbiBmbXRCeXRlcyhuOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGlmIChuIDwgMTAyNCkgcmV0dXJuIG4gKyBcIkJcIjtcbiAgICBpZiAobiA8IDEwMjQgKiAxMDI0KSByZXR1cm4gKG4gLyAxMDI0KS50b0ZpeGVkKDEpICsgXCJLQlwiO1xuICAgIGlmIChuIDwgMTAyNCAqIDEwMjQgKiAxMDI0KSByZXR1cm4gKG4gLyAxMDI0IC8gMTAyNCkudG9GaXhlZCgxKSArIFwiTUJcIjtcbiAgICByZXR1cm4gKG4gLyAxMDI0IC8gMTAyNCAvIDEwMjQpLnRvRml4ZWQoMikgKyBcIkdCXCI7XG59XG5cbi8vIE1pbmltYWwgV2ViU29ja2V0IHN1cmZhY2UgY29tbW9uIHRvIHRoZSBicm93c2VyJ3MgV2ViU29ja2V0IGFuZCB0aGUgYHdzYCBwYWNrYWdlLlxudHlwZSBXU0xpa2UgPSB7XG4gICAgcmVhZHlTdGF0ZTogbnVtYmVyO1xuICAgIGJpbmFyeVR5cGU6IHN0cmluZztcbiAgICBzZW5kKGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkO1xuICAgIGNsb3NlKCk6IHZvaWQ7XG4gICAgb25vcGVuOiAoKCkgPT4gdm9pZCkgfCBudWxsO1xuICAgIG9ubWVzc2FnZTogKChldjogeyBkYXRhOiBBcnJheUJ1ZmZlciB8IEJ1ZmZlciB9KSA9PiB2b2lkKSB8IG51bGw7XG4gICAgb25jbG9zZTogKCgpID0+IHZvaWQpIHwgbnVsbDtcbiAgICBvbmVycm9yOiAoKGU6IHVua25vd24pID0+IHZvaWQpIHwgbnVsbDtcbn07XG5mdW5jdGlvbiBtYWtlV2ViU29ja2V0KHVybDogc3RyaW5nKTogV1NMaWtlIHtcbiAgICBpZiAoaXNOb2RlKCkpIHtcbiAgICAgICAgLy8gYHdzYCBpcyBhIE5vZGUgZGVwOyB0aGUgZXZhbCBoaWRlcyBpdCBmcm9tIHRoZSBicm93c2VyIGJ1bmRsZXIgKHRoaXMgYnJhbmNoIG5ldmVyIHJ1bnMgdGhlcmUpLlxuICAgICAgICBjb25zdCBXUyA9IChldmFsKFwicmVxdWlyZVwiKSBhcyBOb2RlUmVxdWlyZSkoXCJ3c1wiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBXUyh1cmwsIHsgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZSB9KSBhcyBXU0xpa2U7IC8vIHNlbGYtc2lnbmVkIGNlcnRcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBXZWJTb2NrZXQodXJsKSBhcyB1bmtub3duIGFzIFdTTGlrZTtcbn1cblxuLy8gQmluYXJ5IGZyYW1lOiBbdTMyIGhlYWRlckxlbiBMRV1baGVhZGVyIEpTT05dW2JvZHkgYnl0ZXNdLlxuZnVuY3Rpb24gZW5jb2RlRnJhbWUoaGVhZGVyOiBvYmplY3QsIGJvZHk/OiBCdWZmZXIpOiBCdWZmZXIge1xuICAgIGNvbnN0IGggPSBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShoZWFkZXIpLCBcInV0ZjhcIik7XG4gICAgY29uc3QgbGVuID0gQnVmZmVyLmFsbG9jKDQpO1xuICAgIGxlbi53cml0ZVVJbnQzMkxFKGgubGVuZ3RoLCAwKTtcbiAgICByZXR1cm4gQnVmZmVyLmNvbmNhdChbbGVuLCBoLCBib2R5IHx8IEVNUFRZXSk7XG59XG5mdW5jdGlvbiBkZWNvZGVGcmFtZShidWY6IEJ1ZmZlcik6IHsgaGVhZGVyOiBhbnk7IGJvZHk6IEJ1ZmZlciB9IHtcbiAgICBjb25zdCBoZWFkZXJMZW4gPSBidWYucmVhZFVJbnQzMkxFKDApO1xuICAgIGNvbnN0IGhlYWRlciA9IEpTT04ucGFyc2UoYnVmLnN1YmFycmF5KDQsIDQgKyBoZWFkZXJMZW4pLnRvU3RyaW5nKFwidXRmOFwiKSk7XG4gICAgcmV0dXJuIHsgaGVhZGVyLCBib2R5OiBidWYuc3ViYXJyYXkoNCArIGhlYWRlckxlbikgfTtcbn1cblxudHlwZSBRdWV1ZWRSZXF1ZXN0ID0geyBpZDogbnVtYmVyOyBmcmFtZTogQnVmZmVyOyBieXRlczogbnVtYmVyOyByZXNvbHZlOiAocjogeyBzdGF0dXM6IG51bWJlcjsgYm9keTogQnVmZmVyIH0pID0+IHZvaWQ7IHJlamVjdDogKGU6IEVycm9yKSA9PiB2b2lkIH07XG5cbi8vIE9uZSBXZWJTb2NrZXQgdG8gYSByZW1vdGUgc2VydmVyLCBtdWx0aXBsZXhpbmcgYWxsIG9wcyBvdmVyIGl0LiBSZXF1ZXN0cyBhcmUgcXVldWVkIGFuZCBvbmx5IHNlbnRcbi8vIHdoaWxlIDwgTUFYX0lORkxJR0hUX0JZVEVTIGFyZSBvdXRzdGFuZGluZzsgZXZlcnkgMTBzICh3aGVuIHRoZXJlJ3MgdHJhZmZpYykgaXQgbG9ncyB0aGUgcXVldWUgZGVwdGhcbi8vIGFuZCB0aHJvdWdocHV0LlxuY2xhc3MgQ29ubmVjdGlvbiB7XG4gICAgcHJpdmF0ZSBjYWNoZTogUmFuZ2VDYWNoZTtcbiAgICBwcml2YXRlIGluZm9DYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCB7IHN0YXQ6IFN0YXQgfCB1bmRlZmluZWQ7IGF0OiBudW1iZXIgfT4oKTtcblxuICAgIHByaXZhdGUgd3M6IFdTTGlrZSB8IHVuZGVmaW5lZDtcbiAgICBwcml2YXRlIGNvbm5lY3Rpbmc6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQ7XG4gICAgcHJpdmF0ZSBuZXh0SWQgPSAxO1xuICAgIHByaXZhdGUgcGVuZGluZyA9IG5ldyBNYXA8bnVtYmVyLCB7IHJlc29sdmU6IChyOiB7IHN0YXR1czogbnVtYmVyOyBib2R5OiBCdWZmZXIgfSkgPT4gdm9pZDsgcmVqZWN0OiAoZTogRXJyb3IpID0+IHZvaWQ7IGJ5dGVzOiBudW1iZXIgfT4oKTtcbiAgICBwcml2YXRlIHF1ZXVlOiBRdWV1ZWRSZXF1ZXN0W10gPSBbXTtcbiAgICBwcml2YXRlIGluRmxpZ2h0Qnl0ZXMgPSAwO1xuXG4gICAgcHJpdmF0ZSByZWNlaXZlZFRvdGFsID0gMDtcbiAgICBwcml2YXRlIHJlY3ZXaW5kb3c6IHsgdDogbnVtYmVyOyBuOiBudW1iZXIgfVtdID0gW107XG4gICAgcHJpdmF0ZSB3c1VybDogc3RyaW5nO1xuICAgIHByaXZhdGUgaG9zdDogc3RyaW5nO1xuICAgIHByaXZhdGUgc3RhdHNUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+O1xuXG4gICAgY29uc3RydWN0b3IocHVibGljIHVybDogc3RyaW5nLCBwdWJsaWMgcGFzc3dvcmQ6IHN0cmluZywgcHJpdmF0ZSBvcHRzOiBSZW1vdGVPcHRpb25zKSB7XG4gICAgICAgIHRoaXMudXJsID0gdXJsLnJlcGxhY2UoL1xcLyskLywgXCJcIik7XG4gICAgICAgIHRoaXMud3NVcmwgPSB0aGlzLnVybC5yZXBsYWNlKC9eaHR0cC8sIFwid3NcIik7IC8vIGh0dHBz4oaSd3NzLCBodHRw4oaSd3NcbiAgICAgICAgdGhpcy5ob3N0ID0gKCgpID0+IHsgdHJ5IHsgcmV0dXJuIG5ldyBVUkwodGhpcy51cmwpLmhvc3Q7IH0gY2F0Y2ggeyByZXR1cm4gdGhpcy51cmw7IH0gfSkoKTtcbiAgICAgICAgdGhpcy5jYWNoZSA9IG5ldyBSYW5nZUNhY2hlKG9wdHMuY2h1bmtCeXRlcyB8fCBERUZBVUxUX0NIVU5LX0JZVEVTLCBvcHRzLmNhY2hlQnl0ZXMgfHwgREVGQVVMVF9DQUNIRV9CWVRFUywgb3B0cy5tYXhGZXRjaEJ5dGVzIHx8IERFRkFVTFRfTUFYX0ZFVENIX0JZVEVTKTtcbiAgICAgICAgdGhpcy5zdGF0c1RpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4gdGhpcy5sb2dTdGF0cygpLCBTVEFUU19MT0dfSU5URVJWQUxfTVMpO1xuICAgICAgICAodGhpcy5zdGF0c1RpbWVyIGFzIHsgdW5yZWY/OiAoKSA9PiB2b2lkIH0pLnVucmVmPy4oKTtcbiAgICB9XG5cbiAgICBjbG9zZSgpIHtcbiAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLnN0YXRzVGltZXIpO1xuICAgICAgICB0cnkgeyB0aGlzLndzPy5jbG9zZSgpOyB9IGNhdGNoIHsgLyogKi8gfVxuICAgICAgICB0aGlzLndzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmNvbm5lY3RpbmcgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2dTdGF0cygpIHtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdGhpcy5yZWN2V2luZG93ID0gdGhpcy5yZWN2V2luZG93LmZpbHRlcihlID0+IG5vdyAtIGUudCA8IFJFQ1ZfV0lORE9XX01TKTtcbiAgICAgICAgaWYgKHRoaXMuaW5GbGlnaHRCeXRlcyA9PT0gMCAmJiB0aGlzLnF1ZXVlLmxlbmd0aCA9PT0gMCkgcmV0dXJuOyAvLyBvbmx5IHdoZW4gdGhlcmUncyB0cmFmZmljXG4gICAgICAgIGNvbnN0IHJlY3Y2MCA9IHRoaXMucmVjdldpbmRvdy5yZWR1Y2UoKGEsIGUpID0+IGEgKyBlLm4sIDApO1xuICAgICAgICBjb25zdCBxdWV1ZWRCeXRlcyA9IHRoaXMucXVldWUucmVkdWNlKChhLCBxKSA9PiBhICsgcS5ieXRlcywgMCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBbcmVtb3RlICR7dGhpcy5ob3N0fV0gb3V0c3RhbmRpbmcgJHtmbXRCeXRlcyh0aGlzLmluRmxpZ2h0Qnl0ZXMpfSAoJHt0aGlzLnBlbmRpbmcuc2l6ZX0gcmVxKSwgcXVldWVkICR7Zm10Qnl0ZXMocXVldWVkQnl0ZXMpfSAoJHt0aGlzLnF1ZXVlLmxlbmd0aH0gcmVxKSwgcmVjdi82MHMgJHtmbXRCeXRlcyhyZWN2NjApfSwgcmVjdiB0b3RhbCAke2ZtdEJ5dGVzKHRoaXMucmVjZWl2ZWRUb3RhbCl9YCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBlbnN1cmVDb25uZWN0ZWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLndzICYmIHRoaXMud3MucmVhZHlTdGF0ZSA9PT0gMSkgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICBpZiAodGhpcy5jb25uZWN0aW5nKSByZXR1cm4gdGhpcy5jb25uZWN0aW5nO1xuICAgICAgICB0aGlzLmNvbm5lY3RpbmcgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgYXV0aGVkID0gZmFsc2U7XG4gICAgICAgICAgICBjb25zdCB3cyA9IG1ha2VXZWJTb2NrZXQodGhpcy53c1VybCk7XG4gICAgICAgICAgICB3cy5iaW5hcnlUeXBlID0gXCJhcnJheWJ1ZmZlclwiO1xuICAgICAgICAgICAgdGhpcy53cyA9IHdzO1xuICAgICAgICAgICAgd3Mub25vcGVuID0gKCkgPT4gd3Muc2VuZChlbmNvZGVGcmFtZSh7IGlkOiAwLCBvcDogXCJhdXRoXCIsIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkIH0pKTtcbiAgICAgICAgICAgIHdzLm9ubWVzc2FnZSA9IChldikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJ1ZiA9IEJ1ZmZlci5pc0J1ZmZlcihldi5kYXRhKSA/IGV2LmRhdGEgYXMgQnVmZmVyIDogQnVmZmVyLmZyb20oZXYuZGF0YSBhcyBBcnJheUJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBoZWFkZXIgfSA9IGRlY29kZUZyYW1lKGJ1Zik7XG4gICAgICAgICAgICAgICAgaWYgKCFhdXRoZWQgJiYgaGVhZGVyLmlkID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChoZWFkZXIuc3RhdHVzID09PSAyMDApIHsgYXV0aGVkID0gdHJ1ZTsgcmVzb2x2ZSgpOyB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgeyByZWplY3QobmV3IEVycm9yKFwicmVtb3RlOiBhdXRoZW50aWNhdGlvbiBmYWlsZWRcIikpOyB0cnkgeyB3cy5jbG9zZSgpOyB9IGNhdGNoIHsgLyogKi8gfSB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5vbk1lc3NhZ2UoYnVmKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB3cy5vbmVycm9yID0gKCkgPT4geyBpZiAoIWF1dGhlZCkgcmVqZWN0KG5ldyBFcnJvcihcInJlbW90ZTogd2Vic29ja2V0IGNvbm5lY3Rpb24gZXJyb3JcIikpOyB9O1xuICAgICAgICAgICAgd3Mub25jbG9zZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWF1dGhlZCkgcmVqZWN0KG5ldyBFcnJvcihcInJlbW90ZTogY29ubmVjdGlvbiBjbG9zZWQgYmVmb3JlIGF1dGhlbnRpY2F0aW5nXCIpKTtcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZURpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBMZXQgYSBmYWlsZWQgY29ubmVjdGlvbiBiZSByZXRyaWVkIG5leHQgdGltZS5cbiAgICAgICAgdGhpcy5jb25uZWN0aW5nLmNhdGNoKCgpID0+IHsgdGhpcy53cyA9IHVuZGVmaW5lZDsgdGhpcy5jb25uZWN0aW5nID0gdW5kZWZpbmVkOyB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGluZztcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uTWVzc2FnZShidWY6IEJ1ZmZlcikge1xuICAgICAgICBjb25zdCB7IGhlYWRlciwgYm9keSB9ID0gZGVjb2RlRnJhbWUoYnVmKTtcbiAgICAgICAgY29uc3QgcCA9IHRoaXMucGVuZGluZy5nZXQoaGVhZGVyLmlkKTtcbiAgICAgICAgaWYgKCFwKSByZXR1cm47XG4gICAgICAgIHRoaXMucGVuZGluZy5kZWxldGUoaGVhZGVyLmlkKTtcbiAgICAgICAgdGhpcy5pbkZsaWdodEJ5dGVzIC09IHAuYnl0ZXM7XG4gICAgICAgIHRoaXMucmVjZWl2ZWRUb3RhbCArPSBib2R5Lmxlbmd0aDtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zdGF0cykgdGhpcy5vcHRzLnN0YXRzLmJ5dGVzRmV0Y2hlZCArPSBib2R5Lmxlbmd0aDtcbiAgICAgICAgdGhpcy5yZWN2V2luZG93LnB1c2goeyB0OiBEYXRlLm5vdygpLCBuOiBib2R5Lmxlbmd0aCB9KTtcbiAgICAgICAgcC5yZXNvbHZlKHsgc3RhdHVzOiBoZWFkZXIuc3RhdHVzLCBib2R5IH0pO1xuICAgICAgICB0aGlzLmRyYWluKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVEaXNjb25uZWN0KCkge1xuICAgICAgICBjb25zdCBlcnIgPSBuZXcgRXJyb3IoXCJyZW1vdGU6IHdlYnNvY2tldCBkaXNjb25uZWN0ZWRcIik7XG4gICAgICAgIGZvciAoY29uc3QgcCBvZiB0aGlzLnBlbmRpbmcudmFsdWVzKCkpIHAucmVqZWN0KGVycik7XG4gICAgICAgIGZvciAoY29uc3QgcSBvZiB0aGlzLnF1ZXVlKSBxLnJlamVjdChlcnIpO1xuICAgICAgICB0aGlzLnBlbmRpbmcuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5xdWV1ZSA9IFtdO1xuICAgICAgICB0aGlzLmluRmxpZ2h0Qnl0ZXMgPSAwO1xuICAgICAgICB0aGlzLndzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmNvbm5lY3RpbmcgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBkcmFpbigpIHtcbiAgICAgICAgd2hpbGUgKHRoaXMucXVldWUubGVuZ3RoICYmIHRoaXMud3MgJiYgdGhpcy53cy5yZWFkeVN0YXRlID09PSAxKSB7XG4gICAgICAgICAgICBjb25zdCBuZXh0ID0gdGhpcy5xdWV1ZVswXTtcbiAgICAgICAgICAgIGlmICh0aGlzLmluRmxpZ2h0Qnl0ZXMgPiAwICYmIHRoaXMuaW5GbGlnaHRCeXRlcyArIG5leHQuYnl0ZXMgPiBNQVhfSU5GTElHSFRfQllURVMpIGJyZWFrOyAvLyBob2xkIHRoZSBxdWV1ZVxuICAgICAgICAgICAgdGhpcy5xdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgdGhpcy5pbkZsaWdodEJ5dGVzICs9IG5leHQuYnl0ZXM7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmcuc2V0KG5leHQuaWQsIHsgcmVzb2x2ZTogbmV4dC5yZXNvbHZlLCByZWplY3Q6IG5leHQucmVqZWN0LCBieXRlczogbmV4dC5ieXRlcyB9KTtcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdHMuc3RhdHMpIHRoaXMub3B0cy5zdGF0cy5yZXF1ZXN0Q291bnQrKztcbiAgICAgICAgICAgIHRoaXMud3Muc2VuZChuZXh0LmZyYW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFNlbmRzIG9uZSByZXF1ZXN0IG92ZXIgdGhlIFdlYlNvY2tldCAocXVldWVkICsgdGhyb3R0bGVkKS4gYGJ5dGVzYCBpcyB0aGUgZXhwZWN0ZWQgcGF5bG9hZCBzaXplLFxuICAgIC8vIHVzZWQgZm9yIHRoZSBpbi1mbGlnaHQgY2FwLlxuICAgIHByaXZhdGUgYXN5bmMgcmVxdWVzdChvcDogc3RyaW5nLCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBib2R5OiBCdWZmZXIgfCB1bmRlZmluZWQsIGJ5dGVzOiBudW1iZXIpOiBQcm9taXNlPHsgc3RhdHVzOiBudW1iZXI7IGJvZHk6IEJ1ZmZlciB9PiB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMubGF0ZW5jeU1zKSBhd2FpdCBzbGVlcCh0aGlzLm9wdHMubGF0ZW5jeU1zKTtcbiAgICAgICAgYXdhaXQgdGhpcy5lbnN1cmVDb25uZWN0ZWQoKTtcbiAgICAgICAgY29uc3QgaWQgPSB0aGlzLm5leHRJZCsrO1xuICAgICAgICBjb25zdCBmcmFtZSA9IGVuY29kZUZyYW1lKHsgaWQsIG9wLCAuLi5wYXJhbXMgfSwgYm9keSk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnF1ZXVlLnB1c2goeyBpZCwgZnJhbWUsIGJ5dGVzOiBNYXRoLm1heChieXRlcywgYm9keSA/IGJvZHkubGVuZ3RoIDogMCwgMSksIHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgICAgIHRoaXMuZHJhaW4oKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgc3RhdChwYXRoOiBzdHJpbmcpOiBQcm9taXNlPFN0YXQgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgY29uc3QgY2FjaGVkID0gdGhpcy5pbmZvQ2FjaGUuZ2V0KHBhdGgpO1xuICAgICAgICBpZiAoY2FjaGVkICYmIERhdGUubm93KCkgLSBjYWNoZWQuYXQgPCBJTkZPX1RUTF9NUykgcmV0dXJuIGNhY2hlZC5zdGF0O1xuICAgICAgICBjb25zdCByID0gYXdhaXQgdGhpcy5yZXF1ZXN0KFwiaW5mb1wiLCB7IHBhdGggfSwgdW5kZWZpbmVkLCAyNTYpO1xuICAgICAgICBsZXQgc3RhdDogU3RhdCB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHIuc3RhdHVzID09PSA0MDQpIHN0YXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGVsc2UgaWYgKHIuc3RhdHVzICE9PSAyMDApIHRocm93IG5ldyBFcnJvcihgcmVtb3RlIGluZm8gZmFpbGVkICgke3Iuc3RhdHVzfSlgKTtcbiAgICAgICAgZWxzZSBzdGF0ID0gSlNPTi5wYXJzZShyLmJvZHkudG9TdHJpbmcoXCJ1dGY4XCIpKSBhcyBTdGF0O1xuICAgICAgICB0aGlzLmluZm9DYWNoZS5zZXQocGF0aCwgeyBzdGF0LCBhdDogRGF0ZS5ub3coKSB9KTtcbiAgICAgICAgcmV0dXJuIHN0YXQ7XG4gICAgfVxuICAgIGFzeW5jIGxpc3QocGF0aDogc3RyaW5nKTogUHJvbWlzZTx7IG5hbWU6IHN0cmluZzsgZGlyOiBib29sZWFuIH1bXT4ge1xuICAgICAgICBjb25zdCByID0gYXdhaXQgdGhpcy5yZXF1ZXN0KFwibGlzdFwiLCB7IHBhdGggfSwgdW5kZWZpbmVkLCA0MDk2KTtcbiAgICAgICAgaWYgKHIuc3RhdHVzICE9PSAyMDApIHRocm93IG5ldyBFcnJvcihgcmVtb3RlIGxpc3QgZmFpbGVkICgke3Iuc3RhdHVzfSlgKTtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2Uoci5ib2R5LnRvU3RyaW5nKFwidXRmOFwiKSk7XG4gICAgfVxuICAgIGFzeW5jIHJlYWQocGF0aDogc3RyaW5nLCBzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcik6IFByb21pc2U8QnVmZmVyPiB7XG4gICAgICAgIHJldHVybiAoYXdhaXQgdGhpcy5jYWNoZS5yZWFkKHRoaXMsIHBhdGgsIHN0YXJ0LCBlbmQpKSA/PyBFTVBUWTtcbiAgICB9XG4gICAgYXN5bmMgcmVhZFNlcnZlcihwYXRoOiBzdHJpbmcsIHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgY29uc3QgciA9IGF3YWl0IHRoaXMucmVxdWVzdChcInJlYWRcIiwgeyBwYXRoLCBzdGFydCwgZW5kIH0sIHVuZGVmaW5lZCwgZW5kIC0gc3RhcnQpO1xuICAgICAgICBpZiAoci5zdGF0dXMgPT09IDQwNCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHIuc3RhdHVzICE9PSAyMDApIHRocm93IG5ldyBFcnJvcihgcmVtb3RlIHJlYWQgZmFpbGVkICgke3Iuc3RhdHVzfSlgKTtcbiAgICAgICAgcmV0dXJuIHIuYm9keTtcbiAgICB9XG4gICAgYXN5bmMgYXBwZW5kKHBhdGg6IHN0cmluZywgYm9keTogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHIgPSBhd2FpdCB0aGlzLnJlcXVlc3QoXCJhcHBlbmRcIiwgeyBwYXRoIH0sIGJvZHksIGJvZHkubGVuZ3RoKTtcbiAgICAgICAgaWYgKHIuc3RhdHVzICE9PSAyMDApIHRocm93IG5ldyBFcnJvcihgcmVtb3RlIGFwcGVuZCBmYWlsZWQgKCR7ci5zdGF0dXN9KWApO1xuICAgICAgICB0aGlzLmluZm9DYWNoZS5kZWxldGUocGF0aCk7IC8vIGFwcGVuZC1vbmx5IGtlZXBzIGV4aXN0aW5nIGJ5dGVzOyBvbmx5IHRoZSBzaXplIGNoYW5nZWRcbiAgICB9XG4gICAgYXN5bmMgc2V0KHBhdGg6IHN0cmluZywgYm9keTogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHIgPSBhd2FpdCB0aGlzLnJlcXVlc3QoXCJzZXRcIiwgeyBwYXRoIH0sIGJvZHksIGJvZHkubGVuZ3RoKTtcbiAgICAgICAgaWYgKHIuc3RhdHVzICE9PSAyMDApIHRocm93IG5ldyBFcnJvcihgcmVtb3RlIHNldCBmYWlsZWQgKCR7ci5zdGF0dXN9KWApO1xuICAgICAgICB0aGlzLmNhY2hlLmludmFsaWRhdGUocGF0aCk7XG4gICAgICAgIHRoaXMuaW5mb0NhY2hlLmRlbGV0ZShwYXRoKTtcbiAgICB9XG4gICAgYXN5bmMgcmVtb3ZlKHBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCByID0gYXdhaXQgdGhpcy5yZXF1ZXN0KFwicmVtb3ZlXCIsIHsgcGF0aCB9LCB1bmRlZmluZWQsIDI1Nik7XG4gICAgICAgIGlmIChyLnN0YXR1cyAhPT0gMjAwKSB0aHJvdyBuZXcgRXJyb3IoYHJlbW90ZSByZW1vdmUgZmFpbGVkICgke3Iuc3RhdHVzfSlgKTtcbiAgICAgICAgdGhpcy5jYWNoZS5pbnZhbGlkYXRlKHBhdGgpO1xuICAgICAgICB0aGlzLmluZm9DYWNoZS5kZWxldGUocGF0aCk7XG4gICAgfVxufVxuXG4vLyBDYWNoZXMgdGhlIGxvbmdlc3Qta25vd24gcHJlZml4IG9mIGVhY2ggYWxpZ25lZCBjaHVuayBwZXIgcGF0aC4gVmFsaWQgYmVjYXVzZSBmaWxlcyBhcmUgaW1tdXRhYmxlIG9yXG4vLyBhcHBlbmQtb25seSAodGhlIGJ5dGVzIGF0IGFuIG9mZnNldCBuZXZlciBjaGFuZ2UpLiBJdCBvbmx5IGRvZXMgcmFuZ2UgcmVhZHMg4oCUIGl0IGRvZXNuJ3QgY2FyZSB3aGF0XG4vLyB0aGUgZmlsZXMgYXJlLlxuY2xhc3MgUmFuZ2VDYWNoZSB7XG4gICAgcHJpdmF0ZSBjaHVua3MgPSBuZXcgTWFwPHN0cmluZywgQnVmZmVyPigpOyAvLyBwYXRoICsgXCJcdTAwMDFcIiArIGNodW5rSW5kZXgsIGluc2VydGlvbi1vcmRlcmVkIChMUlUpXG4gICAgcHJpdmF0ZSBieXRlcyA9IDA7XG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjaHVua0J5dGVzOiBudW1iZXIsIHByaXZhdGUgYnVkZ2V0OiBudW1iZXIsIHByaXZhdGUgbWF4RmV0Y2hCeXRlczogbnVtYmVyKSB7IH1cbiAgICBwcml2YXRlIGtleShwYXRoOiBzdHJpbmcsIGM6IG51bWJlcikgeyByZXR1cm4gcGF0aCArIFwiXHUwMDAxXCIgKyBjOyB9XG4gICAgcHJpdmF0ZSBwZWVrKHBhdGg6IHN0cmluZywgYzogbnVtYmVyKTogQnVmZmVyIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgY29uc3QgayA9IHRoaXMua2V5KHBhdGgsIGMpO1xuICAgICAgICBjb25zdCB2ID0gdGhpcy5jaHVua3MuZ2V0KGspO1xuICAgICAgICBpZiAodikgeyB0aGlzLmNodW5rcy5kZWxldGUoayk7IHRoaXMuY2h1bmtzLnNldChrLCB2KTsgfVxuICAgICAgICByZXR1cm4gdjtcbiAgICB9XG4gICAgcHJpdmF0ZSBzdG9yZShwYXRoOiBzdHJpbmcsIGM6IG51bWJlciwgYnVmOiBCdWZmZXIpIHtcbiAgICAgICAgY29uc3QgayA9IHRoaXMua2V5KHBhdGgsIGMpO1xuICAgICAgICBjb25zdCBleCA9IHRoaXMuY2h1bmtzLmdldChrKTtcbiAgICAgICAgaWYgKGV4ICYmIGV4Lmxlbmd0aCA+PSBidWYubGVuZ3RoKSB7IHRoaXMuY2h1bmtzLmRlbGV0ZShrKTsgdGhpcy5jaHVua3Muc2V0KGssIGV4KTsgcmV0dXJuOyB9XG4gICAgICAgIGlmIChleCkgdGhpcy5ieXRlcyAtPSBleC5sZW5ndGg7XG4gICAgICAgIHRoaXMuY2h1bmtzLmRlbGV0ZShrKTtcbiAgICAgICAgdGhpcy5jaHVua3Muc2V0KGssIGJ1Zik7XG4gICAgICAgIHRoaXMuYnl0ZXMgKz0gYnVmLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKHRoaXMuYnl0ZXMgPiB0aGlzLmJ1ZGdldCAmJiB0aGlzLmNodW5rcy5zaXplID4gMCkge1xuICAgICAgICAgICAgY29uc3Qgb2xkZXN0ID0gdGhpcy5jaHVua3Mua2V5cygpLm5leHQoKS52YWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgICAgICB0aGlzLmJ5dGVzIC09ICh0aGlzLmNodW5rcy5nZXQob2xkZXN0KSBhcyBCdWZmZXIpLmxlbmd0aDtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzLmRlbGV0ZShvbGRlc3QpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGludmFsaWRhdGUocGF0aDogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHByZWZpeCA9IHBhdGggKyBcIlx1MDAwMVwiO1xuICAgICAgICBmb3IgKGNvbnN0IGsgb2YgWy4uLnRoaXMuY2h1bmtzLmtleXMoKV0pIGlmIChrLnN0YXJ0c1dpdGgocHJlZml4KSkgeyB0aGlzLmJ5dGVzIC09ICh0aGlzLmNodW5rcy5nZXQoaykgYXMgQnVmZmVyKS5sZW5ndGg7IHRoaXMuY2h1bmtzLmRlbGV0ZShrKTsgfVxuICAgIH1cbiAgICBhc3luYyByZWFkKGNvbm46IENvbm5lY3Rpb24sIHBhdGg6IHN0cmluZywgc3RhcnQ6IG51bWJlciwgZW5kOiBudW1iZXIpOiBQcm9taXNlPEJ1ZmZlciB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBpZiAoZW5kIDw9IHN0YXJ0KSByZXR1cm4gRU1QVFk7XG4gICAgICAgIGNvbnN0IENIVU5LID0gdGhpcy5jaHVua0J5dGVzO1xuICAgICAgICBjb25zdCBtYXhSdW5DaHVua3MgPSBNYXRoLm1heCgxLCBNYXRoLmZsb29yKHRoaXMubWF4RmV0Y2hCeXRlcyAvIENIVU5LKSk7XG4gICAgICAgIGNvbnN0IGZpcnN0Q2h1bmsgPSBNYXRoLmZsb29yKHN0YXJ0IC8gQ0hVTkspO1xuICAgICAgICBjb25zdCBsYXN0Q2h1bmsgPSBNYXRoLmZsb29yKChlbmQgLSAxKSAvIENIVU5LKTtcbiAgICAgICAgLy8gQ29sbGVjdCB0aGUgY2h1bmtzIHdlIGRvbid0IGhhdmUgZGVlcGx5IGVub3VnaCBpbnRvIGJvdW5kZWQgY29udGlndW91cyBydW5zIChlYWNoIDw9IG1heEZldGNoQnl0ZXMpLlxuICAgICAgICBjb25zdCBydW5zOiB7IGZyb206IG51bWJlcjsgdG86IG51bWJlciB9W10gPSBbXTtcbiAgICAgICAgbGV0IHJ1bkZyb20gPSAtMTtcbiAgICAgICAgZm9yIChsZXQgYyA9IGZpcnN0Q2h1bms7IGMgPD0gbGFzdENodW5rOyBjKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGNTdGFydCA9IGMgKiBDSFVOSztcbiAgICAgICAgICAgIGNvbnN0IG5lZWRFbmQgPSBNYXRoLm1pbihlbmQsIGNTdGFydCArIENIVU5LKSAtIGNTdGFydDtcbiAgICAgICAgICAgIGNvbnN0IGhhdmUgPSB0aGlzLnBlZWsocGF0aCwgYyk7XG4gICAgICAgICAgICBpZiAoIWhhdmUgfHwgaGF2ZS5sZW5ndGggPCBuZWVkRW5kKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJ1bkZyb20gPCAwKSBydW5Gcm9tID0gYztcbiAgICAgICAgICAgICAgICBpZiAoYyAtIHJ1bkZyb20gKyAxID49IG1heFJ1bkNodW5rcykgeyBydW5zLnB1c2goeyBmcm9tOiBydW5Gcm9tLCB0bzogYyB9KTsgcnVuRnJvbSA9IC0xOyB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHJ1bkZyb20gPj0gMCkge1xuICAgICAgICAgICAgICAgIHJ1bnMucHVzaCh7IGZyb206IHJ1bkZyb20sIHRvOiBjIC0gMSB9KTtcbiAgICAgICAgICAgICAgICBydW5Gcm9tID0gLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJ1bkZyb20gPj0gMCkgcnVucy5wdXNoKHsgZnJvbTogcnVuRnJvbSwgdG86IGxhc3RDaHVuayB9KTtcbiAgICAgICAgLy8gRmV0Y2ggYWxsIHJ1bnMgY29uY3VycmVudGx5OyB0aGUgY29ubmVjdGlvbidzIHF1ZXVlIGNhcHMgdG90YWwgaW4tZmxpZ2h0IGJ5dGVzLlxuICAgICAgICBsZXQgbWlzc2luZ0ZpbGUgPSBmYWxzZTtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocnVucy5tYXAoYXN5bmMgcnVuID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJ5dGVzID0gYXdhaXQgY29ubi5yZWFkU2VydmVyKHBhdGgsIHJ1bi5mcm9tICogQ0hVTkssIChydW4udG8gKyAxKSAqIENIVU5LKTtcbiAgICAgICAgICAgIGlmIChieXRlcyA9PT0gdW5kZWZpbmVkKSB7IG1pc3NpbmdGaWxlID0gdHJ1ZTsgcmV0dXJuOyB9XG4gICAgICAgICAgICBmb3IgKGxldCBjID0gcnVuLmZyb207IGMgPD0gcnVuLnRvOyBjKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvZmYgPSAoYyAtIHJ1bi5mcm9tKSAqIENIVU5LO1xuICAgICAgICAgICAgICAgIGlmIChvZmYgPj0gYnl0ZXMubGVuZ3RoKSBicmVhaztcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3JlKHBhdGgsIGMsIGJ5dGVzLnN1YmFycmF5KG9mZiwgTWF0aC5taW4ob2ZmICsgQ0hVTkssIGJ5dGVzLmxlbmd0aCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkpO1xuICAgICAgICBpZiAobWlzc2luZ0ZpbGUpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHBhcnRzOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgICBmb3IgKGxldCBjID0gZmlyc3RDaHVuazsgYyA8PSBsYXN0Q2h1bms7IGMrKykge1xuICAgICAgICAgICAgY29uc3QgY1N0YXJ0ID0gYyAqIENIVU5LO1xuICAgICAgICAgICAgY29uc3QgZnJvbSA9IE1hdGgubWF4KHN0YXJ0LCBjU3RhcnQpIC0gY1N0YXJ0O1xuICAgICAgICAgICAgY29uc3QgdG8gPSBNYXRoLm1pbihlbmQsIGNTdGFydCArIENIVU5LKSAtIGNTdGFydDtcbiAgICAgICAgICAgIGNvbnN0IGNodW5rID0gdGhpcy5wZWVrKHBhdGgsIGMpO1xuICAgICAgICAgICAgaWYgKCFjaHVuayB8fCBjaHVuay5sZW5ndGggPCB0bykgeyBpZiAoY2h1bmsgJiYgY2h1bmsubGVuZ3RoID4gZnJvbSkgcGFydHMucHVzaChjaHVuay5zdWJhcnJheShmcm9tLCBjaHVuay5sZW5ndGgpKTsgYnJlYWs7IH1cbiAgICAgICAgICAgIHBhcnRzLnB1c2goY2h1bmsuc3ViYXJyYXkoZnJvbSwgdG8pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFydHMubGVuZ3RoID09PSAxID8gcGFydHNbMF0gOiBCdWZmZXIuY29uY2F0KHBhcnRzKTtcbiAgICB9XG59XG5cbmNvbnN0IGpvaW5QYXRoID0gKGJhc2U6IHN0cmluZywga2V5OiBzdHJpbmcpID0+IChiYXNlID8gYmFzZSArIFwiL1wiICsga2V5IDoga2V5KTtcbmNvbnN0IGJhc2VOYW1lID0gKHA6IHN0cmluZykgPT4gcC5zcGxpdChcIi9cIikuZmlsdGVyKEJvb2xlYW4pLnBvcCgpIHx8IFwiXCI7XG5cbmNsYXNzIFJlbW90ZUZpbGVXcmFwcGVyIGltcGxlbWVudHMgRmlsZVdyYXBwZXIge1xuICAgIC8vIGBzdGF0YCBpcyBzdXBwbGllZCB3aGVuIHRoZSBwYXJlbnQgYWxyZWFkeSBzdGF0dGVkIHVzIChhdm9pZHMgYSBzZWNvbmQgL2luZm8pLiBgY3JlYXRlSW50ZW50YCBtZWFuc1xuICAgIC8vIHRoaXMgd2FzIG9wZW5lZCB3aXRoIGNyZWF0ZTp0cnVlLCBzbyBhIG1pc3NpbmcgZmlsZSByZWFkcyBhcyBlbXB0eSAoaXQnbGwgYmUgY3JlYXRlZCBvbiB3cml0ZSkuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb25uOiBDb25uZWN0aW9uLCBwcml2YXRlIGZpbGVQYXRoOiBzdHJpbmcsIHByaXZhdGUgc3RhdD86IFN0YXQsIHByaXZhdGUgY3JlYXRlSW50ZW50ID0gZmFsc2UpIHsgfVxuICAgIC8vIE1pcnJvciB0aGUgbmF0aXZlIEZpbGVTeXN0ZW1GaWxlSGFuZGxlIHNoYXBlIHNvIGNvZGUgd3JpdHRlbiBhZ2FpbnN0IGl0IHdvcmtzIHVuY2hhbmdlZC5cbiAgICByZWFkb25seSBraW5kID0gXCJmaWxlXCIgYXMgY29uc3Q7XG4gICAgZ2V0IG5hbWUoKSB7IHJldHVybiBiYXNlTmFtZSh0aGlzLmZpbGVQYXRoKTsgfVxuICAgIGFzeW5jIGdldEZpbGUoKSB7XG4gICAgICAgIGxldCBzdGF0ID0gdGhpcy5zdGF0ID8/IGF3YWl0IHRoaXMuY29ubi5zdGF0KHRoaXMuZmlsZVBhdGgpO1xuICAgICAgICBpZiAoIXN0YXQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jcmVhdGVJbnRlbnQpIHRocm93IGVub2VudCh0aGlzLmZpbGVQYXRoKTtcbiAgICAgICAgICAgIHN0YXQgPSB7IHNpemU6IDAsIGxhc3RNb2RpZmllZDogRGF0ZS5ub3coKSwgZGlyOiBmYWxzZSB9O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNvbm4gPSB0aGlzLmNvbm4sIGZpbGVQYXRoID0gdGhpcy5maWxlUGF0aCwgc2l6ZSA9IHN0YXQuc2l6ZTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNpemUsIGxhc3RNb2RpZmllZDogc3RhdC5sYXN0TW9kaWZpZWQsXG4gICAgICAgICAgICBhc3luYyBhcnJheUJ1ZmZlcigpIHsgcmV0dXJuIHRvQXJyYXlCdWZmZXIoYXdhaXQgY29ubi5yZWFkKGZpbGVQYXRoLCAwLCBzaXplKSk7IH0sXG4gICAgICAgICAgICBzbGljZShzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGFzeW5jIGFycmF5QnVmZmVyKCkgeyByZXR1cm4gdG9BcnJheUJ1ZmZlcihhd2FpdCBjb25uLnJlYWQoZmlsZVBhdGgsIHN0YXJ0LCBlbmQpKTsgfSB9O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0VVJMKCkge1xuICAgICAgICAvLyBIVFRQUyBVUkwgaW50byB0aGUgc2VydmVyJ3MgcmFuZ2UtY2FwYWJsZSAvbWVkaWEgZW5kcG9pbnQuIFRoZSB0b2tlbiByaWRlcyBpbiB0aGUgcXVlcnkgYmVjYXVzZSBhXG4gICAgICAgIC8vIDx2aWRlbz4vPGltZz4gZWxlbWVudCBjYW4ndCBzZW5kIGFuIEF1dGhvcml6YXRpb24gaGVhZGVyLlxuICAgICAgICByZXR1cm4gYCR7dGhpcy5jb25uLnVybH0vbWVkaWE/cGF0aD0ke2VuY29kZVVSSUNvbXBvbmVudCh0aGlzLmZpbGVQYXRoKX0mdG9rZW49JHtlbmNvZGVVUklDb21wb25lbnQodGhpcy5jb25uLnBhc3N3b3JkKX1gO1xuICAgIH1cbiAgICBhc3luYyBjcmVhdGVXcml0YWJsZShjb25maWc/OiB7IGtlZXBFeGlzdGluZ0RhdGE/OiBib29sZWFuIH0pIHtcbiAgICAgICAgY29uc3QgY29ubiA9IHRoaXMuY29ubiwgZmlsZVBhdGggPSB0aGlzLmZpbGVQYXRoLCBhcHBlbmQgPSAhIWNvbmZpZz8ua2VlcEV4aXN0aW5nRGF0YTtcbiAgICAgICAgY29uc3QgY2h1bmtzOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYXN5bmMgc2VlaygpIHsgLyogdGhlIHNlcnZlciBhcHBlbmRzIHRvIHRoZSBlbmQgLyBvdmVyd3JpdGVzIHRoZSB3aG9sZSBmaWxlOyBvZmZzZXQgdW51c2VkICovIH0sXG4gICAgICAgICAgICBhc3luYyB3cml0ZSh2YWx1ZTogQnVmZmVyKSB7IGNodW5rcy5wdXNoKHZhbHVlKTsgfSxcbiAgICAgICAgICAgIGFzeW5jIGNsb3NlKCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJvZHkgPSBjaHVua3MubGVuZ3RoID09PSAxID8gY2h1bmtzWzBdIDogQnVmZmVyLmNvbmNhdChjaHVua3MpO1xuICAgICAgICAgICAgICAgIGlmIChhcHBlbmQpIGF3YWl0IGNvbm4uYXBwZW5kKGZpbGVQYXRoLCBib2R5KTsgZWxzZSBhd2FpdCBjb25uLnNldChmaWxlUGF0aCwgYm9keSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgIH1cbn1cblxuY2xhc3MgUmVtb3RlRGlyZWN0b3J5V3JhcHBlciBpbXBsZW1lbnRzIERpcmVjdG9yeVdyYXBwZXIge1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgY29ubjogQ29ubmVjdGlvbiwgcHJpdmF0ZSBkaXJQYXRoOiBzdHJpbmcpIHsgfVxuICAgIC8vIE1pcnJvciB0aGUgbmF0aXZlIEZpbGVTeXN0ZW1EaXJlY3RvcnlIYW5kbGUgc2hhcGUgKG5hbWUva2luZC9lbnRyaWVzKSBzbyBjb2RlIHdyaXR0ZW4gYWdhaW5zdCB0aGVcbiAgICAvLyBuYXRpdmUgQVBJIOKAlCBlLmcuIHJlY3Vyc2l2ZSB3YWxrcyB1c2luZyBgaGFuZGxlLmVudHJpZXMoKWAg4oCUIHdvcmtzIHRoZSBzYW1lIG92ZXIgdGhlIG5ldHdvcmsuXG4gICAgcmVhZG9ubHkga2luZCA9IFwiZGlyZWN0b3J5XCIgYXMgY29uc3Q7XG4gICAgcmVhZG9ubHkgaXNSZW1vdGUgPSB0cnVlO1xuICAgIGdldCBuYW1lKCkgeyByZXR1cm4gYmFzZU5hbWUodGhpcy5kaXJQYXRoKTsgfVxuICAgIGdldCBmdWxsUGF0aCgpIHsgcmV0dXJuIHRoaXMuZGlyUGF0aDsgfVxuICAgIGFzeW5jIHJlbW92ZUVudHJ5KGtleTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IHRoaXMuY29ubi5yZW1vdmUoam9pblBhdGgodGhpcy5kaXJQYXRoLCBrZXkpKTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0RmlsZUhhbmRsZShrZXk6IHN0cmluZywgb3B0aW9ucz86IHsgY3JlYXRlPzogYm9vbGVhbiB9KTogUHJvbWlzZTxSZW1vdGVGaWxlV3JhcHBlcj4ge1xuICAgICAgICBjb25zdCBwID0gam9pblBhdGgodGhpcy5kaXJQYXRoLCBrZXkpO1xuICAgICAgICBpZiAob3B0aW9ucz8uY3JlYXRlKSByZXR1cm4gbmV3IFJlbW90ZUZpbGVXcmFwcGVyKHRoaXMuY29ubiwgcCwgdW5kZWZpbmVkLCB0cnVlKTtcbiAgICAgICAgY29uc3Qgc3RhdCA9IGF3YWl0IHRoaXMuY29ubi5zdGF0KHApOyAgICAgICAgICAgICAgICAgLy8gbWF0Y2hlcyB0aGUgRmlsZSBBUEk6IHRocm93IGlmIG1pc3NpbmdcbiAgICAgICAgaWYgKCFzdGF0IHx8IHN0YXQuZGlyKSB0aHJvdyBlbm9lbnQocCk7XG4gICAgICAgIHJldHVybiBuZXcgUmVtb3RlRmlsZVdyYXBwZXIodGhpcy5jb25uLCBwLCBzdGF0LCBmYWxzZSk7XG4gICAgfVxuICAgIGFzeW5jIGdldERpcmVjdG9yeUhhbmRsZShrZXk6IHN0cmluZywgb3B0aW9ucz86IHsgY3JlYXRlPzogYm9vbGVhbiB9KTogUHJvbWlzZTxSZW1vdGVEaXJlY3RvcnlXcmFwcGVyPiB7XG4gICAgICAgIGNvbnN0IHAgPSBqb2luUGF0aCh0aGlzLmRpclBhdGgsIGtleSk7XG4gICAgICAgIGlmICghb3B0aW9ucz8uY3JlYXRlKSB7XG4gICAgICAgICAgICBjb25zdCBzdGF0ID0gYXdhaXQgdGhpcy5jb25uLnN0YXQocCk7XG4gICAgICAgICAgICBpZiAoIXN0YXQgfHwgIXN0YXQuZGlyKSB0aHJvdyBlbm9lbnQocCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBSZW1vdGVEaXJlY3RvcnlXcmFwcGVyKHRoaXMuY29ubiwgcCk7ICAgICAgIC8vIGRpcnMgYXJlIGNyZWF0ZWQgbGF6aWx5IG9uIGZpcnN0IHdyaXRlXG4gICAgfVxuICAgIC8vIEVhY2ggZW50cnkgaXMgaXRzZWxmIGEgcmVhbCBoYW5kbGUgKGEgc3ViLXdyYXBwZXIpLCBzbyBhIHJlY3Vyc2l2ZSB3YWxrIG92ZXIgLmVudHJpZXMoKSBrZWVwc1xuICAgIC8vIHdvcmtpbmcgYXQgZXZlcnkgbGV2ZWwg4oCUIGV4YWN0bHkgbGlrZSB0aGUgbmF0aXZlIEFQSS5cbiAgICBhc3luYyAqW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpOiBBc3luY0l0ZXJhYmxlSXRlcmF0b3I8W3N0cmluZywgUmVtb3RlRmlsZVdyYXBwZXIgfCBSZW1vdGVEaXJlY3RvcnlXcmFwcGVyXT4ge1xuICAgICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgdGhpcy5jb25uLmxpc3QodGhpcy5kaXJQYXRoKTtcbiAgICAgICAgZm9yIChjb25zdCBlIG9mIGVudHJpZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNoaWxkUGF0aCA9IGpvaW5QYXRoKHRoaXMuZGlyUGF0aCwgZS5uYW1lKTtcbiAgICAgICAgICAgIHlpZWxkIFtlLm5hbWUsIGUuZGlyID8gbmV3IFJlbW90ZURpcmVjdG9yeVdyYXBwZXIodGhpcy5jb25uLCBjaGlsZFBhdGgpIDogbmV3IFJlbW90ZUZpbGVXcmFwcGVyKHRoaXMuY29ubiwgY2hpbGRQYXRoKV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgZW50cmllcygpIHsgcmV0dXJuIHRoaXNbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk7IH1cbiAgICBrZXlzKCkgeyByZXR1cm4gbWFwQXN5bmModGhpc1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKSwgKFtuYW1lXSkgPT4gbmFtZSk7IH1cbiAgICB2YWx1ZXMoKSB7IHJldHVybiBtYXBBc3luYyh0aGlzW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpLCAoWywgaGFuZGxlXSkgPT4gaGFuZGxlKTsgfVxufVxuXG5hc3luYyBmdW5jdGlvbiogbWFwQXN5bmM8VCwgVT4oaXQ6IEFzeW5jSXRlcmFibGVJdGVyYXRvcjxUPiwgZm46ICh2OiBUKSA9PiBVKTogQXN5bmNJdGVyYWJsZUl0ZXJhdG9yPFU+IHtcbiAgICBmb3IgYXdhaXQgKGNvbnN0IHYgb2YgaXQpIHlpZWxkIGZuKHYpO1xufVxuXG4vLyBBIERpcmVjdG9yeVdyYXBwZXIgcm9vdGVkIGF0IGEgcmVtb3RlIHNlcnZlci4gRHJvcC1pbiBmb3IgdGhlIE5vZGUgLyBGaWxlLUFQSSBoYW5kbGVzLlxuZXhwb3J0IGZ1bmN0aW9uIGdldFJlbW90ZURpcmVjdG9yeUhhbmRsZSh1cmw6IHN0cmluZywgcGFzc3dvcmQ6IHN0cmluZywgb3B0aW9uczogUmVtb3RlT3B0aW9ucyA9IHt9KTogRGlyZWN0b3J5V3JhcHBlciB7XG4gICAgcmV0dXJuIG5ldyBSZW1vdGVEaXJlY3RvcnlXcmFwcGVyKG5ldyBDb25uZWN0aW9uKHVybCwgcGFzc3dvcmQsIG9wdGlvbnMpLCBcIlwiKTtcbn1cblxuZXhwb3J0IHR5cGUgUmVtb3RlQ29ubmVjdFJlc3VsdCA9IHsgc3RhdHVzOiBcIm9rXCIgfSB8IHsgc3RhdHVzOiBcInVuYXV0aG9yaXplZFwiIH0gfCB7IHN0YXR1czogXCJ1bnJlYWNoYWJsZVwiOyBlcnJvcjogc3RyaW5nIH07XG5cbi8vIFZlcmlmaWVzIGEgc2VydmVyIGlzIHJlYWNoYWJsZSBhbmQgdGhlIHBhc3N3b3JkIHdvcmtzIOKAlCBieSBvcGVuaW5nIHRoZSBXZWJTb2NrZXQsIGF1dGhlbnRpY2F0aW5nLCBhbmRcbi8vIGxpc3RpbmcgdGhlIHJvb3QuIERpc3Rpbmd1aXNoZXMgXCJjb25uZWN0ZWRcIiAvIFwid3JvbmcgcGFzc3dvcmRcIiAvIFwiY291bGRuJ3QgcmVhY2ggaXRcIiAodGhlIGxhc3QgdXN1YWxseVxuLy8gbWVhbmluZyB0aGUgc2VsZi1zaWduZWQgY2VydCBpc24ndCB0cnVzdGVkIHlldCBpbiB0aGUgYnJvd3Nlciwgc2luY2UgdGhlIHNvY2tldCBqdXN0IGZhaWxzIHRvIG9wZW4pLlxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3RSZW1vdGVDb25uZWN0aW9uKHVybDogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nLCBvcHRpb25zOiBSZW1vdGVPcHRpb25zID0ge30pOiBQcm9taXNlPFJlbW90ZUNvbm5lY3RSZXN1bHQ+IHtcbiAgICBjb25zdCBjb25uID0gbmV3IENvbm5lY3Rpb24odXJsLCBwYXNzd29yZCwgb3B0aW9ucyk7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgY29ubi5saXN0KFwiXCIpO1xuICAgICAgICByZXR1cm4geyBzdGF0dXM6IFwib2tcIiB9O1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc3QgbXNnID0gKGUgYXMgRXJyb3IpPy5tZXNzYWdlIHx8IFN0cmluZyhlKTtcbiAgICAgICAgaWYgKC9hdXRoL2kudGVzdChtc2cpKSByZXR1cm4geyBzdGF0dXM6IFwidW5hdXRob3JpemVkXCIgfTtcbiAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBcInVucmVhY2hhYmxlXCIsIGVycm9yOiBtc2cgfTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBjb25uLmNsb3NlKCk7XG4gICAgfVxufVxuIl19
495
+ /* _JS_SOURCE_HASH = "0ef349c55f3de629df041c02cbf7acac8b46362cc303e14843c801382938c8b6"; */