sliftutils 1.7.10 → 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.
- package/examplestorage/exampleserver.ts +0 -2
- package/index.d.ts +290 -54
- package/misc/dist/environment.ts.cache +3 -3
- package/misc/dist/getSecret.ts.cache +139 -0
- package/misc/dist/strings.ts.cache +13 -0
- package/misc/dist/zip.ts.cache +9 -0
- package/misc/getSecret.ts +38 -16
- package/misc/https/cloudflareHelpers.d.ts +19 -0
- package/misc/https/cloudflareHelpers.ts +69 -0
- package/misc/https/dist/certs.ts.cache +115 -179
- package/misc/https/dist/cloudflareHelpers.ts.cache +68 -0
- package/misc/https/dist/dns.ts.cache +112 -100
- package/misc/https/dist/hostServer.ts.cache +130 -0
- package/misc/https/dist/httpsCerts.ts.cache +24 -5
- package/misc/https/dist/persistentLocalStorage.ts.cache +3 -2
- package/misc/https/dns.d.ts +41 -12
- package/misc/https/dns.ts +104 -101
- package/misc/https/hostServer.d.ts +0 -6
- package/misc/https/hostServer.ts +9 -5
- package/package.json +2 -2
- package/render-utils/dist/observer.tsx.cache +3 -2
- package/spec.txt +0 -90
- package/storage/ArchivesDisk.d.ts +2 -0
- package/storage/ArchivesDisk.ts +7 -3
- package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +1242 -0
- package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +513 -0
- package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +352 -0
- package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +306 -0
- package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +435 -0
- package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +58 -0
- package/storage/BulkDatabase2/dist/blockCache.ts.cache +179 -0
- package/storage/BulkDatabase2/dist/mergeLock.ts.cache +149 -0
- package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +101 -0
- package/storage/BulkDatabase2/dist/streamLog.ts.cache +227 -0
- package/storage/BulkDatabase2/dist/syncClient.ts.cache +104 -0
- package/storage/IArchives.d.ts +47 -15
- package/storage/IArchives.ts +86 -31
- package/storage/backblaze.d.ts +15 -0
- package/storage/backblaze.ts +199 -79
- package/storage/dist/ArchivesDisk.ts.cache +373 -0
- package/storage/dist/FileFolderAPI.tsx.cache +508 -65
- package/storage/dist/IArchives.ts.cache +44 -0
- package/storage/dist/IndexedDBFileFolderAPI.ts.cache +8 -2
- package/storage/dist/JSONStorage.ts.cache +6 -2
- package/storage/dist/PendingManager.tsx.cache +1 -1
- package/storage/dist/TransactionStorage.ts.cache +231 -92
- package/storage/dist/backblaze.ts.cache +797 -0
- package/storage/dist/fileSystemPointer.ts.cache +36 -3
- package/storage/dist/remoteFileStorage.ts.cache +495 -0
- package/storage/remoteStorage/ArchivesRemote.d.ts +5 -1
- package/storage/remoteStorage/ArchivesRemote.ts +28 -8
- package/storage/remoteStorage/ArchivesUrl.d.ts +2 -0
- package/storage/remoteStorage/ArchivesUrl.ts +16 -4
- package/storage/remoteStorage/blobStore.d.ts +52 -3
- package/storage/remoteStorage/blobStore.ts +414 -101
- package/storage/remoteStorage/createArchives.d.ts +31 -10
- package/storage/remoteStorage/createArchives.ts +470 -253
- package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +197 -0
- package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +85 -0
- package/storage/remoteStorage/dist/accessPage.tsx.cache +222 -0
- package/storage/remoteStorage/dist/blobStore.ts.cache +837 -0
- package/storage/remoteStorage/dist/cliArgs.ts.cache +16 -0
- package/storage/remoteStorage/dist/createArchives.ts.cache +610 -0
- package/storage/remoteStorage/dist/remoteConfig.ts.cache +206 -0
- package/storage/remoteStorage/dist/sourceWrapper.ts.cache +223 -0
- package/storage/remoteStorage/dist/storageController.ts.cache +500 -0
- package/storage/remoteStorage/dist/storageServer.ts.cache +106 -0
- package/storage/remoteStorage/dist/storageServerCli.ts.cache +39 -0
- package/storage/remoteStorage/dist/storageServerState.ts.cache +518 -0
- package/storage/remoteStorage/remoteConfig.d.ts +8 -0
- package/storage/remoteStorage/remoteConfig.ts +105 -5
- package/storage/remoteStorage/sourceWrapper.d.ts +41 -0
- package/storage/remoteStorage/sourceWrapper.ts +223 -0
- package/storage/remoteStorage/spec.md +31 -0
- package/storage/remoteStorage/storageController.d.ts +11 -0
- package/storage/remoteStorage/storageController.ts +109 -40
- package/storage/remoteStorage/storageServer.d.ts +0 -5
- package/storage/remoteStorage/storageServer.ts +17 -10
- package/storage/remoteStorage/storageServerCli.ts +0 -3
- package/storage/remoteStorage/storageServerState.d.ts +7 -1
- package/storage/remoteStorage/storageServerState.ts +230 -48
- package/testsite/server.ts +0 -2
- 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"; */
|
|
@@ -28,6 +28,8 @@ export declare class ArchivesRemote implements IArchives {
|
|
|
28
28
|
private controller;
|
|
29
29
|
private lastDeniedLog;
|
|
30
30
|
getDebugName(): string;
|
|
31
|
+
isConnected(): boolean;
|
|
32
|
+
ping(): Promise<void>;
|
|
31
33
|
private authenticate;
|
|
32
34
|
private callAuthed;
|
|
33
35
|
waitingForAccess(): Promise<{
|
|
@@ -35,7 +37,8 @@ export declare class ArchivesRemote implements IArchives {
|
|
|
35
37
|
machineId: string;
|
|
36
38
|
ip: string;
|
|
37
39
|
} | undefined>;
|
|
38
|
-
|
|
40
|
+
hasWriteAccess(): Promise<boolean>;
|
|
41
|
+
private registerAccessRequest;
|
|
39
42
|
private call;
|
|
40
43
|
get(fileName: string, config?: {
|
|
41
44
|
range?: {
|
|
@@ -51,6 +54,7 @@ export declare class ArchivesRemote implements IArchives {
|
|
|
51
54
|
}): Promise<{
|
|
52
55
|
data: Buffer;
|
|
53
56
|
writeTime: number;
|
|
57
|
+
size: number;
|
|
54
58
|
} | undefined>;
|
|
55
59
|
set(fileName: string, data: Buffer, config?: {
|
|
56
60
|
lastModified?: number;
|