sliftutils 1.7.10 → 1.7.12

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 (84) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/examplestorage/exampleserver.ts +0 -2
  3. package/index.d.ts +301 -54
  4. package/misc/dist/environment.ts.cache +3 -3
  5. package/misc/dist/getSecret.ts.cache +139 -0
  6. package/misc/dist/strings.ts.cache +13 -0
  7. package/misc/dist/zip.ts.cache +9 -0
  8. package/misc/getSecret.ts +38 -16
  9. package/misc/https/cloudflareHelpers.d.ts +19 -0
  10. package/misc/https/cloudflareHelpers.ts +69 -0
  11. package/misc/https/dist/certs.ts.cache +115 -179
  12. package/misc/https/dist/cloudflareHelpers.ts.cache +68 -0
  13. package/misc/https/dist/dns.ts.cache +112 -100
  14. package/misc/https/dist/hostServer.ts.cache +130 -0
  15. package/misc/https/dist/httpsCerts.ts.cache +24 -5
  16. package/misc/https/dist/persistentLocalStorage.ts.cache +3 -2
  17. package/misc/https/dns.d.ts +41 -12
  18. package/misc/https/dns.ts +104 -101
  19. package/misc/https/hostServer.d.ts +0 -6
  20. package/misc/https/hostServer.ts +9 -5
  21. package/package.json +2 -2
  22. package/render-utils/dist/observer.tsx.cache +3 -2
  23. package/spec.txt +0 -90
  24. package/storage/ArchivesDisk.d.ts +2 -0
  25. package/storage/ArchivesDisk.ts +7 -3
  26. package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +1242 -0
  27. package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +513 -0
  28. package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +352 -0
  29. package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +306 -0
  30. package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +435 -0
  31. package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +58 -0
  32. package/storage/BulkDatabase2/dist/blockCache.ts.cache +179 -0
  33. package/storage/BulkDatabase2/dist/mergeLock.ts.cache +149 -0
  34. package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +101 -0
  35. package/storage/BulkDatabase2/dist/streamLog.ts.cache +227 -0
  36. package/storage/BulkDatabase2/dist/syncClient.ts.cache +104 -0
  37. package/storage/IArchives.d.ts +47 -15
  38. package/storage/IArchives.ts +86 -31
  39. package/storage/backblaze.d.ts +15 -0
  40. package/storage/backblaze.ts +199 -79
  41. package/storage/dist/ArchivesDisk.ts.cache +373 -0
  42. package/storage/dist/FileFolderAPI.tsx.cache +508 -65
  43. package/storage/dist/IArchives.ts.cache +44 -0
  44. package/storage/dist/IndexedDBFileFolderAPI.ts.cache +8 -2
  45. package/storage/dist/JSONStorage.ts.cache +6 -2
  46. package/storage/dist/PendingManager.tsx.cache +1 -1
  47. package/storage/dist/TransactionStorage.ts.cache +231 -92
  48. package/storage/dist/backblaze.ts.cache +797 -0
  49. package/storage/dist/fileSystemPointer.ts.cache +36 -3
  50. package/storage/dist/remoteFileStorage.ts.cache +495 -0
  51. package/storage/remoteStorage/ArchivesRemote.d.ts +5 -1
  52. package/storage/remoteStorage/ArchivesRemote.ts +28 -8
  53. package/storage/remoteStorage/ArchivesUrl.d.ts +2 -0
  54. package/storage/remoteStorage/ArchivesUrl.ts +16 -4
  55. package/storage/remoteStorage/blobStore.d.ts +63 -3
  56. package/storage/remoteStorage/blobStore.ts +419 -101
  57. package/storage/remoteStorage/createArchives.d.ts +31 -10
  58. package/storage/remoteStorage/createArchives.ts +470 -253
  59. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +197 -0
  60. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +85 -0
  61. package/storage/remoteStorage/dist/accessPage.tsx.cache +222 -0
  62. package/storage/remoteStorage/dist/blobStore.ts.cache +837 -0
  63. package/storage/remoteStorage/dist/cliArgs.ts.cache +16 -0
  64. package/storage/remoteStorage/dist/createArchives.ts.cache +610 -0
  65. package/storage/remoteStorage/dist/remoteConfig.ts.cache +206 -0
  66. package/storage/remoteStorage/dist/sourceWrapper.ts.cache +223 -0
  67. package/storage/remoteStorage/dist/storageController.ts.cache +500 -0
  68. package/storage/remoteStorage/dist/storageServer.ts.cache +106 -0
  69. package/storage/remoteStorage/dist/storageServerCli.ts.cache +39 -0
  70. package/storage/remoteStorage/dist/storageServerState.ts.cache +518 -0
  71. package/storage/remoteStorage/remoteConfig.d.ts +8 -0
  72. package/storage/remoteStorage/remoteConfig.ts +105 -5
  73. package/storage/remoteStorage/sourceWrapper.d.ts +41 -0
  74. package/storage/remoteStorage/sourceWrapper.ts +223 -0
  75. package/storage/remoteStorage/spec.md +31 -0
  76. package/storage/remoteStorage/storageController.d.ts +11 -0
  77. package/storage/remoteStorage/storageController.ts +109 -40
  78. package/storage/remoteStorage/storageServer.d.ts +0 -5
  79. package/storage/remoteStorage/storageServer.ts +17 -10
  80. package/storage/remoteStorage/storageServerCli.ts +0 -3
  81. package/storage/remoteStorage/storageServerState.d.ts +7 -1
  82. package/storage/remoteStorage/storageServerState.ts +230 -48
  83. package/testsite/server.ts +0 -2
  84. package/yarn.lock +11 -6
@@ -0,0 +1,68 @@
1
+ "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.cloudflareCall = exports.cloudflarePOSTCall = exports.cloudflareGETCall = exports.getCloudflareCreds = void 0;
4
+ const caching_1 = require("socket-function/src/caching");
5
+ const https_1 = require("socket-function/src/https");
6
+ const getSecret_1 = require("../getSecret");
7
+ exports.getCloudflareCreds = (0, caching_1.lazy)(async () => {
8
+ // Legacy global-key auth needs an email alongside the key, so prefer it when both secrets exist.
9
+ try {
10
+ let key = await (0, getSecret_1.getSecret)("cloudflare.json.key");
11
+ let email = await (0, getSecret_1.getSecret)("cloudflare.json.email");
12
+ return { key, email };
13
+ }
14
+ catch (_a) { }
15
+ // API token form. Deliberately NOT caught: if this fails too, getSecret's error (which names every place it looked) is the one the caller should see.
16
+ return { key: await (0, getSecret_1.getSecret)("cloudflare.json.key") };
17
+ });
18
+ function getAuthHeaders(creds) {
19
+ if (creds.email) {
20
+ return {
21
+ "X-Auth-Email": creds.email,
22
+ "X-Auth-User-Service-Key": creds.key,
23
+ "X-Auth-Key": creds.key,
24
+ };
25
+ }
26
+ return { "Authorization": `Bearer ${creds.key}` };
27
+ }
28
+ async function cloudflareGETCall(path, params) {
29
+ let url = new URL(`https://api.cloudflare.com/client/v4` + path);
30
+ for (let [key, value] of Object.entries(params || {})) {
31
+ url.searchParams.set(key, value);
32
+ }
33
+ let creds = await (0, exports.getCloudflareCreds)();
34
+ let result = await (0, https_1.httpsRequest)(url.toString(), [], "GET", undefined, {
35
+ headers: {
36
+ "Content-Type": "application/json",
37
+ ...getAuthHeaders(creds),
38
+ }
39
+ });
40
+ let result2 = JSON.parse(result.toString());
41
+ if (!result2.success) {
42
+ throw new Error(`Cloudflare call failed: ${result2.errors.map(x => x.message).join(", ")}`);
43
+ }
44
+ return result2.result;
45
+ }
46
+ exports.cloudflareGETCall = cloudflareGETCall;
47
+ async function cloudflarePOSTCall(path, params) {
48
+ return await cloudflareCall(path, Buffer.from(JSON.stringify(params)), "POST");
49
+ }
50
+ exports.cloudflarePOSTCall = cloudflarePOSTCall;
51
+ async function cloudflareCall(path, payload, method) {
52
+ let url = new URL(`https://api.cloudflare.com/client/v4` + path);
53
+ let creds = await (0, exports.getCloudflareCreds)();
54
+ let result = await (0, https_1.httpsRequest)(url.toString(), payload, method, undefined, {
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ ...getAuthHeaders(creds),
58
+ }
59
+ });
60
+ let result2 = JSON.parse(result.toString());
61
+ if (!result2.success) {
62
+ throw new Error(`Cloudflare call failed: ${result2.errors.map(x => x.message).join(", ")}`);
63
+ }
64
+ return result2.result;
65
+ }
66
+ exports.cloudflareCall = cloudflareCall;
67
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvdWRmbGFyZUhlbHBlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjbG91ZGZsYXJlSGVscGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5REFBbUQ7QUFDbkQscURBQXlEO0FBQ3pELDRDQUF5QztBQVE1QixRQUFBLGtCQUFrQixHQUFHLElBQUEsY0FBSSxFQUFDLEtBQUssSUFBOEIsRUFBRTtJQUN4RSxpR0FBaUc7SUFDakcsSUFBSSxDQUFDO1FBQ0QsSUFBSSxHQUFHLEdBQUcsTUFBTSxJQUFBLHFCQUFTLEVBQUMscUJBQXFCLENBQUMsQ0FBQztRQUNqRCxJQUFJLEtBQUssR0FBRyxNQUFNLElBQUEscUJBQVMsRUFBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3JELE9BQU8sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUFDLFdBQU0sQ0FBQyxDQUFDLENBQUM7SUFFWCxzSkFBc0o7SUFDdEosT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLElBQUEscUJBQVMsRUFBQyxxQkFBcUIsQ0FBQyxFQUFFLENBQUM7QUFDM0QsQ0FBQyxDQUFDLENBQUM7QUFFSCxTQUFTLGNBQWMsQ0FBQyxLQUFzQjtJQUMxQyxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNkLE9BQU87WUFDSCxjQUFjLEVBQUUsS0FBSyxDQUFDLEtBQUs7WUFDM0IseUJBQXlCLEVBQUUsS0FBSyxDQUFDLEdBQUc7WUFDcEMsWUFBWSxFQUFFLEtBQUssQ0FBQyxHQUFHO1NBQzFCLENBQUM7SUFDTixDQUFDO0lBQ0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxVQUFVLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDO0FBQ3RELENBQUM7QUFFTSxLQUFLLFVBQVUsaUJBQWlCLENBQUksSUFBWSxFQUFFLE1BQWtDO0lBQ3ZGLElBQUksR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLHNDQUFzQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2pFLEtBQUssSUFBSSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ3BELEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBQ0QsSUFBSSxLQUFLLEdBQUcsTUFBTSxJQUFBLDBCQUFrQixHQUFFLENBQUM7SUFDdkMsSUFBSSxNQUFNLEdBQUcsTUFBTSxJQUFBLG9CQUFZLEVBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFO1FBQ2xFLE9BQU8sRUFBRTtZQUNMLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDO1NBQzNCO0tBQ0osQ0FBQyxDQUFDO0lBQ0gsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQXVGLENBQUM7SUFDbEksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2hHLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQyxNQUFXLENBQUM7QUFDL0IsQ0FBQztBQWpCRCw4Q0FpQkM7QUFDTSxLQUFLLFVBQVUsa0JBQWtCLENBQUksSUFBWSxFQUFFLE1BQWtDO0lBQ3hGLE9BQU8sTUFBTSxjQUFjLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ25GLENBQUM7QUFGRCxnREFFQztBQUNNLEtBQUssVUFBVSxjQUFjLENBQUksSUFBWSxFQUFFLE9BQWUsRUFBRSxNQUFjO0lBQ2pGLElBQUksR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLHNDQUFzQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2pFLElBQUksS0FBSyxHQUFHLE1BQU0sSUFBQSwwQkFBa0IsR0FBRSxDQUFDO0lBQ3ZDLElBQUksTUFBTSxHQUFHLE1BQU0sSUFBQSxvQkFBWSxFQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRTtRQUN4RSxPQUFPLEVBQUU7WUFDTCxjQUFjLEVBQUUsa0JBQWtCO1lBQ2xDLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQztTQUMzQjtLQUNKLENBQUMsQ0FBQztJQUNILElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUF1RixDQUFDO0lBQ2xJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNoRyxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUMsTUFBVyxDQUFDO0FBQy9CLENBQUM7QUFkRCx3Q0FjQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGxhenkgfSBmcm9tIFwic29ja2V0LWZ1bmN0aW9uL3NyYy9jYWNoaW5nXCI7XG5pbXBvcnQgeyBodHRwc1JlcXVlc3QgfSBmcm9tIFwic29ja2V0LWZ1bmN0aW9uL3NyYy9odHRwc1wiO1xuaW1wb3J0IHsgZ2V0U2VjcmV0IH0gZnJvbSBcIi4uL2dldFNlY3JldFwiO1xuXG5leHBvcnQgdHlwZSBDbG91ZGZsYXJlQ3JlZHMgPSB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgLyoqIFNldCBmb3IgbGVnYWN5IGdsb2JhbCBBUEkga2V5cywgd2hpY2ggYXV0aCB2aWEgWC1BdXRoLUVtYWlsL1gtQXV0aC1LZXkuIEFic2VudCBmb3IgQVBJIHRva2Vucywgd2hpY2ggYXV0aCB2aWEgQXV0aG9yaXphdGlvbjogQmVhcmVyLiAqL1xuICAgIGVtYWlsPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldENsb3VkZmxhcmVDcmVkcyA9IGxhenkoYXN5bmMgKCk6IFByb21pc2U8Q2xvdWRmbGFyZUNyZWRzPiA9PiB7XG4gICAgLy8gTGVnYWN5IGdsb2JhbC1rZXkgYXV0aCBuZWVkcyBhbiBlbWFpbCBhbG9uZ3NpZGUgdGhlIGtleSwgc28gcHJlZmVyIGl0IHdoZW4gYm90aCBzZWNyZXRzIGV4aXN0LlxuICAgIHRyeSB7XG4gICAgICAgIGxldCBrZXkgPSBhd2FpdCBnZXRTZWNyZXQoXCJjbG91ZGZsYXJlLmpzb24ua2V5XCIpO1xuICAgICAgICBsZXQgZW1haWwgPSBhd2FpdCBnZXRTZWNyZXQoXCJjbG91ZGZsYXJlLmpzb24uZW1haWxcIik7XG4gICAgICAgIHJldHVybiB7IGtleSwgZW1haWwgfTtcbiAgICB9IGNhdGNoIHsgfVxuXG4gICAgLy8gQVBJIHRva2VuIGZvcm0uIERlbGliZXJhdGVseSBOT1QgY2F1Z2h0OiBpZiB0aGlzIGZhaWxzIHRvbywgZ2V0U2VjcmV0J3MgZXJyb3IgKHdoaWNoIG5hbWVzIGV2ZXJ5IHBsYWNlIGl0IGxvb2tlZCkgaXMgdGhlIG9uZSB0aGUgY2FsbGVyIHNob3VsZCBzZWUuXG4gICAgcmV0dXJuIHsga2V5OiBhd2FpdCBnZXRTZWNyZXQoXCJjbG91ZGZsYXJlLmpzb24ua2V5XCIpIH07XG59KTtcblxuZnVuY3Rpb24gZ2V0QXV0aEhlYWRlcnMoY3JlZHM6IENsb3VkZmxhcmVDcmVkcyk6IHsgW2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIH0ge1xuICAgIGlmIChjcmVkcy5lbWFpbCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgXCJYLUF1dGgtRW1haWxcIjogY3JlZHMuZW1haWwsXG4gICAgICAgICAgICBcIlgtQXV0aC1Vc2VyLVNlcnZpY2UtS2V5XCI6IGNyZWRzLmtleSxcbiAgICAgICAgICAgIFwiWC1BdXRoLUtleVwiOiBjcmVkcy5rZXksXG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB7IFwiQXV0aG9yaXphdGlvblwiOiBgQmVhcmVyICR7Y3JlZHMua2V5fWAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNsb3VkZmxhcmVHRVRDYWxsPFQ+KHBhdGg6IHN0cmluZywgcGFyYW1zPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSk6IFByb21pc2U8VD4ge1xuICAgIGxldCB1cmwgPSBuZXcgVVJMKGBodHRwczovL2FwaS5jbG91ZGZsYXJlLmNvbS9jbGllbnQvdjRgICsgcGF0aCk7XG4gICAgZm9yIChsZXQgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHBhcmFtcyB8fCB7fSkpIHtcbiAgICAgICAgdXJsLnNlYXJjaFBhcmFtcy5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgfVxuICAgIGxldCBjcmVkcyA9IGF3YWl0IGdldENsb3VkZmxhcmVDcmVkcygpO1xuICAgIGxldCByZXN1bHQgPSBhd2FpdCBodHRwc1JlcXVlc3QodXJsLnRvU3RyaW5nKCksIFtdLCBcIkdFVFwiLCB1bmRlZmluZWQsIHtcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgICAgICAuLi5nZXRBdXRoSGVhZGVycyhjcmVkcyksXG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBsZXQgcmVzdWx0MiA9IEpTT04ucGFyc2UocmVzdWx0LnRvU3RyaW5nKCkpIGFzIHsgcmVzdWx0OiB1bmtub3duOyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcnM6IHsgY29kZTogbnVtYmVyOyBtZXNzYWdlOiBzdHJpbmcgfVtdIH07XG4gICAgaWYgKCFyZXN1bHQyLnN1Y2Nlc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbG91ZGZsYXJlIGNhbGwgZmFpbGVkOiAke3Jlc3VsdDIuZXJyb3JzLm1hcCh4ID0+IHgubWVzc2FnZSkuam9pbihcIiwgXCIpfWApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0Mi5yZXN1bHQgYXMgVDtcbn1cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjbG91ZGZsYXJlUE9TVENhbGw8VD4ocGF0aDogc3RyaW5nLCBwYXJhbXM6IHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9KTogUHJvbWlzZTxUPiB7XG4gICAgcmV0dXJuIGF3YWl0IGNsb3VkZmxhcmVDYWxsKHBhdGgsIEJ1ZmZlci5mcm9tKEpTT04uc3RyaW5naWZ5KHBhcmFtcykpLCBcIlBPU1RcIik7XG59XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2xvdWRmbGFyZUNhbGw8VD4ocGF0aDogc3RyaW5nLCBwYXlsb2FkOiBCdWZmZXIsIG1ldGhvZDogc3RyaW5nKTogUHJvbWlzZTxUPiB7XG4gICAgbGV0IHVybCA9IG5ldyBVUkwoYGh0dHBzOi8vYXBpLmNsb3VkZmxhcmUuY29tL2NsaWVudC92NGAgKyBwYXRoKTtcbiAgICBsZXQgY3JlZHMgPSBhd2FpdCBnZXRDbG91ZGZsYXJlQ3JlZHMoKTtcbiAgICBsZXQgcmVzdWx0ID0gYXdhaXQgaHR0cHNSZXF1ZXN0KHVybC50b1N0cmluZygpLCBwYXlsb2FkLCBtZXRob2QsIHVuZGVmaW5lZCwge1xuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgICAgIC4uLmdldEF1dGhIZWFkZXJzKGNyZWRzKSxcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGxldCByZXN1bHQyID0gSlNPTi5wYXJzZShyZXN1bHQudG9TdHJpbmcoKSkgYXMgeyByZXN1bHQ6IHVua25vd247IHN1Y2Nlc3M6IGJvb2xlYW47IGVycm9yczogeyBjb2RlOiBudW1iZXI7IG1lc3NhZ2U6IHN0cmluZyB9W10gfTtcbiAgICBpZiAoIXJlc3VsdDIuc3VjY2Vzcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsb3VkZmxhcmUgY2FsbCBmYWlsZWQ6ICR7cmVzdWx0Mi5lcnJvcnMubWFwKHggPT4geC5tZXNzYWdlKS5qb2luKFwiLCBcIil9YCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQyLnJlc3VsdCBhcyBUO1xufVxuIl19
68
+ /* _JS_SOURCE_HASH = "52bb6b5727ee98c684a094288c4e01c175dc7cfe81d4ffe10996a39ee22ecf5d"; */
@@ -1,20 +1,50 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
- };
1
+ "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
5
2
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
- //exports.addRecord = exports.setRecord = exports.deleteRecord = exports.getRecords = exports.getRecordsRaw = void 0;
7
- const https_1 = require("socket-function/src/https");
3
+ //exports.addRecord = exports.setRecord = exports.deleteRecord = exports.getRecords = exports.batchRecords = exports.getRecordsRaw = exports.getZoneId = exports.hasDNSWritePermissions = exports.freshnessTime = void 0;
8
4
  const caching_1 = require("socket-function/src/caching");
9
- const fs_1 = __importDefault(require("fs"));
10
5
  const batching_1 = require("socket-function/src/batching");
11
6
  const SocketFunction_1 = require("socket-function/SocketFunction");
7
+ const misc_1 = require("socket-function/src/misc");
8
+ const logColors_1 = require("socket-function/src/formatting/logColors");
9
+ const cloudflareHelpers_1 = require("./cloudflareHelpers");
12
10
  const DNS_TTLSeconds = {
13
11
  "TXT": 60,
14
12
  "A": 60,
15
13
  };
16
- const getZoneId = (0, caching_1.cache)(async (rootDomain) => {
17
- let zones = await cloudflareGETCall("/zones", {});
14
+ const DNS_REFRESH_STALE_AFTER = misc_1.timeInDay;
15
+ // We stamp our own "last asserted" time into the record's comment, because Cloudflare's
16
+ // modified_on can only be moved by an actual content change - and re-asserting an already
17
+ // correct record has no content change to make (a create errors with 81058, a no-op edit
18
+ // doesn't bump the timestamp). Reading freshness from text we control sidesteps that entirely,
19
+ // and lets us refresh a stale-but-correct record in place instead of deleting and recreating it.
20
+ const FRESHNESS_REGEX = /<set on:[^>]*>/;
21
+ /** Strips any prior freshness tag and appends a new one, preserving other comment text. */
22
+ function stampFreshness(comment) {
23
+ let base = (comment !== null && comment !== void 0 ? comment : "").replace(FRESHNESS_REGEX, "").trim();
24
+ let stamp = `<set on: ${new Date().toString()}>`;
25
+ return base ? `${base} ${stamp}` : stamp;
26
+ }
27
+ /** Parses our tag back out; 0 (i.e. always stale) when it's absent or unparseable. */
28
+ function freshnessTime(comment) {
29
+ let match = FRESHNESS_REGEX.exec(comment !== null && comment !== void 0 ? comment : "");
30
+ if (!match)
31
+ return 0;
32
+ return new Date(match[0].replace("<set on:", "").replace(">", "").trim()).getTime() || 0;
33
+ }
34
+ exports.freshnessTime = freshnessTime;
35
+ exports.hasDNSWritePermissions = (0, caching_1.lazy)(async () => {
36
+ if (!(0, misc_1.isNode)())
37
+ return false;
38
+ try {
39
+ await (0, cloudflareHelpers_1.getCloudflareCreds)();
40
+ return true;
41
+ }
42
+ catch (_a) {
43
+ return false;
44
+ }
45
+ });
46
+ exports.getZoneId = (0, caching_1.cache)(async (rootDomain) => {
47
+ let zones = await (0, cloudflareHelpers_1.cloudflareGETCall)("/zones", {});
18
48
  let selected = zones.find(x => x.name === rootDomain);
19
49
  if (!selected) {
20
50
  throw new Error(`Could not find zone for ${rootDomain}. Found ${zones.map(x => x.name).join(", ")}`);
@@ -30,11 +60,35 @@ function getRootDomain(key) {
30
60
  async function getRecordsRaw(type, key) {
31
61
  if (key.endsWith("."))
32
62
  key = key.slice(0, -1);
33
- let zoneId = await getZoneId(getRootDomain(key));
34
- let results = await cloudflareGETCall(`/zones/${zoneId}/dns_records`);
35
- return results.filter(x => x.type === type && x.name === key);
63
+ let zoneId = await (0, exports.getZoneId)(getRootDomain(key));
64
+ let results = await (0, cloudflareHelpers_1.cloudflareGETCall)(`/zones/${zoneId}/dns_records`);
65
+ // DNS names are case-insensitive and Cloudflare returns them lowercased, so a mixed-case key
66
+ // (e.g. a machine id subdomain) would never match an exact-case compare - match lowercased.
67
+ let keyLower = key.toLowerCase();
68
+ return results.filter(x => x.type === type && x.name.toLowerCase() === keyLower);
36
69
  }
37
70
  exports.getRecordsRaw = getRecordsRaw;
71
+ /** Cloudflare's batch endpoint applies deletes, then patches, then posts in a single database
72
+ * transaction. We route edits (patches) through here because the standalone PATCH/PUT verbs
73
+ * aren't usable in our setup, and because it lets "remove others + assert target" happen
74
+ * without a window where the name resolves to nothing. */
75
+ async function batchRecords(zoneId, batch) {
76
+ let payload = {};
77
+ if (batch.deletes && batch.deletes.length > 0)
78
+ payload.deletes = batch.deletes;
79
+ if (batch.patches && batch.patches.length > 0)
80
+ payload.patches = batch.patches;
81
+ if (batch.posts && batch.posts.length > 0)
82
+ payload.posts = batch.posts;
83
+ try {
84
+ await (0, cloudflareHelpers_1.cloudflarePOSTCall)(`/zones/${zoneId}/dns_records/batch`, payload);
85
+ }
86
+ catch (error) {
87
+ console.error(`Error updating DNS records:`, { error: error, batch });
88
+ throw new Error(`Error updating DNS records. ${JSON.stringify(batch)}. Error: ${error}`);
89
+ }
90
+ }
91
+ exports.batchRecords = batchRecords;
38
92
  async function getRecords(type, key) {
39
93
  if (key.endsWith("."))
40
94
  key = key.slice(0, -1);
@@ -45,7 +99,7 @@ exports.getRecords = getRecords;
45
99
  async function deleteRecord(type, key, value) {
46
100
  if (key.endsWith("."))
47
101
  key = key.slice(0, -1);
48
- let zoneId = await getZoneId(getRootDomain(key));
102
+ let zoneId = await (0, exports.getZoneId)(getRootDomain(key));
49
103
  let prevValues = await getRecordsRaw(type, key);
50
104
  prevValues = prevValues.filter(x => x.content === value);
51
105
  if (prevValues.length === 0) {
@@ -56,111 +110,69 @@ async function deleteRecord(type, key, value) {
56
110
  }
57
111
  console.log(`Removing records of ${type} for ${key}, values ${JSON.stringify(prevValues.map(x => x.content))}`);
58
112
  for (let value of prevValues) {
59
- await cloudflareCall(`/zones/${zoneId}/dns_records/${value.id}`, Buffer.from([]), "DELETE");
113
+ await (0, cloudflareHelpers_1.cloudflareCall)(`/zones/${zoneId}/dns_records/${value.id}`, Buffer.from([]), "DELETE");
60
114
  }
61
115
  }
62
116
  exports.deleteRecord = deleteRecord;
63
- /** Removes all existing records (unless the record is already present) */
64
- async function setRecord(type, key, value, proxied) {
65
- let stack = new Error();
117
+ /** Removes all existing records (unless the record is already present and fresh) */
118
+ async function setRecord(type, key, value, proxied, staleAfter = DNS_REFRESH_STALE_AFTER) {
66
119
  if (key.endsWith("."))
67
120
  key = key.slice(0, -1);
68
- let zoneId = await getZoneId(getRootDomain(key));
121
+ let zoneId = await (0, exports.getZoneId)(getRootDomain(key));
69
122
  let prevValues = await getRecordsRaw(type, key);
70
- // NOTE: Apparently if we try to update by just changing proxied, cloudflare complains and
71
- // says "an identical record already exists", even though it doesn't, we changed the proxied value...
72
- if (prevValues.some(x => x.content === value))
123
+ let existing = prevValues.find(x => x.content === value);
124
+ let others = prevValues.filter(x => x.content !== value);
125
+ // Already correct and recently asserted - a prior run also cleaned up the other records,
126
+ // so there is nothing left to do.
127
+ if (existing && Date.now() - freshnessTime(existing.comment) < staleAfter)
73
128
  return;
74
- console.log(`Removing previous records of ${type} for ${key} ${JSON.stringify(prevValues.map(x => x.content))}`);
75
- let didDeletions = false;
76
- for (let value of prevValues) {
77
- didDeletions = true;
78
- await cloudflareCall(`/zones/${zoneId}/dns_records/${value.id}`, Buffer.from([]), "DELETE");
79
- }
80
- console.log(`Setting ${type} record for ${key} to ${value} (previously had ${JSON.stringify(prevValues.map(x => x.content))})`);
81
- const ttl = DNS_TTLSeconds[type] || 60;
82
- await cloudflarePOSTCall(`/zones/${zoneId}/dns_records`, {
83
- type: type,
84
- name: key,
85
- content: value,
86
- ttl,
87
- proxied: proxied === "proxied",
129
+ // A single atomic batch: drop the wrong records, and either refresh the existing record's
130
+ // comment in place or create it - so the name is never left resolving to nothing.
131
+ let ttl = DNS_TTLSeconds[type] || 60;
132
+ let comment = stampFreshness(existing === null || existing === void 0 ? void 0 : existing.comment);
133
+ console.log((0, logColors_1.magenta)(`Setting ${type} record for ${key} to ${value} (previously had ${JSON.stringify(prevValues.map(x => x.content))})`));
134
+ await batchRecords(zoneId, {
135
+ deletes: others.map(x => ({ id: x.id })),
136
+ patches: existing ? [{ id: existing.id, comment }] : [],
137
+ posts: existing ? [] : [{ type, name: key, content: value, ttl, proxied: proxied === "proxied", comment }],
88
138
  });
89
- // NOTE: Apparently... even if the record didn't exist, we still have to wait...
90
- console.log(`Waiting ${ttl} seconds for DNS to propagate...`);
91
- await (0, batching_1.delay)(ttl * 1000);
92
- console.log(`Done waiting for DNS to update.`);
139
+ // Only a brand new record needs to propagate; an in-place comment refresh doesn't change the answer.
140
+ if (!existing) {
141
+ console.log(`Waiting ${ttl} seconds for DNS to propagate...`);
142
+ for (let ttlLeft = ttl; ttlLeft > 0; ttlLeft--) {
143
+ await (0, batching_1.delay)(1000);
144
+ console.log(`${ttlLeft} seconds left...`);
145
+ }
146
+ console.log(`Done waiting for DNS to update.`);
147
+ }
93
148
  }
94
149
  exports.setRecord = setRecord;
95
150
  /** Keeps existing records */
96
- async function addRecord(type, key, value, proxied) {
151
+ async function addRecord(type, key, value, proxied, staleAfter = DNS_REFRESH_STALE_AFTER) {
97
152
  if (key.endsWith("."))
98
153
  key = key.slice(0, -1);
99
- let zoneId = await getZoneId(getRootDomain(key));
154
+ let zoneId = await (0, exports.getZoneId)(getRootDomain(key));
100
155
  let prevValues = await getRecordsRaw(type, key);
101
- // NOTE: Apparently if we try to update by just changing proxied, cloudflare complains and
102
- // says "an identical record already exists", even though it doesn't, we changed the proxied value...
103
- if (prevValues.some(x => x.content === value))
156
+ let existing = prevValues.find(x => x.content === value);
157
+ if (existing && Date.now() - freshnessTime(existing.comment) < staleAfter)
104
158
  return;
159
+ // Same single-batch flow as setRecord, minus the deletes (we keep sibling records here).
160
+ let ttl = DNS_TTLSeconds[type] || 60;
161
+ let comment = stampFreshness(existing === null || existing === void 0 ? void 0 : existing.comment);
105
162
  console.log(`Adding ${type} record for ${key} to ${value} (previously had ${JSON.stringify(prevValues.map(x => x.content))})`);
106
- const ttl = DNS_TTLSeconds[type] || 60;
107
- await cloudflarePOSTCall(`/zones/${zoneId}/dns_records`, {
108
- type: type,
109
- name: key,
110
- content: value,
111
- ttl,
112
- proxied: proxied === "proxied",
163
+ await batchRecords(zoneId, {
164
+ patches: existing ? [{ id: existing.id, comment }] : [],
165
+ posts: existing ? [] : [{ type, name: key, content: value, ttl, proxied: proxied === "proxied", comment }],
113
166
  });
167
+ if (existing)
168
+ return;
114
169
  console.log(`Waiting ${ttl} seconds for DNS to propagate...`);
115
- await (0, batching_1.delay)(ttl * 1000);
170
+ for (let ttlLeft = ttl; ttlLeft > 0; ttlLeft--) {
171
+ await (0, batching_1.delay)(1000);
172
+ console.log(`${ttlLeft} seconds left...`);
173
+ }
116
174
  console.log(`Done waiting for DNS to update.`);
117
175
  }
118
176
  exports.addRecord = addRecord;
119
- const getCloudflareCreds = (0, caching_1.lazy)(async () => {
120
- const path = "cloudflare.json";
121
- if (!fs_1.default.existsSync(path)) {
122
- throw new Error(`Must add cloudflare.json file to root of project.`);
123
- }
124
- let creds = JSON.parse(fs_1.default.readFileSync(path, "utf8"));
125
- return {
126
- key: creds.key,
127
- };
128
- });
129
- async function cloudflareGETCall(path, params) {
130
- let url = new URL(`https://api.cloudflare.com/client/v4` + path);
131
- for (let key in params) {
132
- url.searchParams.set(key, params[key]);
133
- }
134
- let creds = await getCloudflareCreds();
135
- let result = await (0, https_1.httpsRequest)(url.toString(), [], "GET", undefined, {
136
- headers: {
137
- "Content-Type": "application/json",
138
- "Authorization": `Bearer ${creds.key}`,
139
- }
140
- });
141
- let result2 = JSON.parse(result.toString());
142
- if (!result2.success) {
143
- throw new Error(`Cloudflare call failed: ${result2.errors.map(x => x.message).join(", ")}`);
144
- }
145
- return result2.result;
146
- }
147
- async function cloudflarePOSTCall(path, params) {
148
- return await cloudflareCall(path, Buffer.from(JSON.stringify(params)), "POST");
149
- }
150
- async function cloudflareCall(path, payload, method) {
151
- let url = new URL(`https://api.cloudflare.com/client/v4` + path);
152
- let creds = await getCloudflareCreds();
153
- let result = await (0, https_1.httpsRequest)(url.toString(), payload, method, undefined, {
154
- headers: {
155
- "Content-Type": "application/json",
156
- "Authorization": `Bearer ${creds.key}`,
157
- }
158
- });
159
- let result2 = JSON.parse(result.toString());
160
- if (!result2.success) {
161
- throw new Error(`Cloudflare call failed: ${result2.errors.map(x => x.message).join(", ")}`);
162
- }
163
- return result2.result;
164
- }
165
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZG5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHFEQUF5RDtBQUN6RCx5REFBMEQ7QUFDMUQsNENBQW9CO0FBQ3BCLDJEQUFxRDtBQUNyRCxtRUFBZ0U7QUFFaEUsTUFBTSxjQUFjLEdBQUc7SUFDbkIsS0FBSyxFQUFFLEVBQUU7SUFDVCxHQUFHLEVBQUUsRUFBRTtDQUNWLENBQUM7QUFFRixNQUFNLFNBQVMsR0FBRyxJQUFBLGVBQUssRUFBQyxLQUFLLEVBQUUsVUFBa0IsRUFBbUIsRUFBRTtJQUNsRSxJQUFJLEtBQUssR0FBRyxNQUFNLGlCQUFpQixDQUFpQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbEYsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssVUFBVSxDQUFDLENBQUM7SUFDdEQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ1osTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsVUFBVSxXQUFXLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6RyxDQUFDO0lBQ0QsT0FBTyxRQUFRLENBQUMsRUFBRSxDQUFDO0FBQ3ZCLENBQUMsQ0FBQyxDQUFDO0FBRUgsU0FBUyxhQUFhLENBQUMsR0FBVztJQUM5QixJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNwQixHQUFHLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFD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QUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDbkYsQ0FBQztBQUNELEtBQUssVUFBVSxjQUFjLENBQUksSUFBWSxFQUFFLE9BQWUsRUFBRSxNQUFjO0lBQzFFLElBQUksR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLHNDQUFzQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2pFLElBQUksS0FBSyxHQUFHLE1BQU0sa0JBQWtCLEVBQUUsQ0FBQztJQUN2QyxJQUFJLE1BQU0sR0FBRyxNQUFNLElBQUEsb0JBQVksRUFBQyxHQUFHLENBQUMsUUFBUSxFQUFFLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUU7UUFDeEUsT0FBTyxFQUFFO1lBQ0wsY0FBYyxFQUFFLGtCQUFrQjtZQUNsQyxlQUFlLEVBQUUsVUFBVSxLQUFLLENBQUMsR0FBRyxFQUFFO1NBQ3pDO0tBQ0osQ0FBQyxDQUFDO0lBQ0gsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQXVGLENBQUM7SUFDbEksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2hHLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQyxNQUFXLENBQUM7QUFDL0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGh0dHBzUmVxdWVzdCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2h0dHBzXCI7XG5pbXBvcnQgeyBjYWNoZSwgbGF6eSB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2NhY2hpbmdcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IGRlbGF5IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvYmF0Y2hpbmdcIjtcbmltcG9ydCB7IFNvY2tldEZ1bmN0aW9uIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9Tb2NrZXRGdW5jdGlvblwiO1xuXG5jb25zdCBETlNfVFRMU2Vjb25kcyA9IHtcbiAgICBcIlRYVFwiOiA2MCxcbiAgICBcIkFcIjogNjAsXG59O1xuXG5jb25zdCBnZXRab25lSWQgPSBjYWNoZShhc3luYyAocm9vdERvbWFpbjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgICBsZXQgem9uZXMgPSBhd2FpdCBjbG91ZGZsYXJlR0VUQ2FsbDx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZyB9W10+KFwiL3pvbmVzXCIsIHt9KTtcbiAgICBsZXQgc2VsZWN0ZWQgPSB6b25lcy5maW5kKHggPT4geC5uYW1lID09PSByb290RG9tYWluKTtcbiAgICBpZiAoIXNlbGVjdGVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGZpbmQgem9uZSBmb3IgJHtyb290RG9tYWlufS4gRm91bmQgJHt6b25lcy5tYXAoeCA9PiB4Lm5hbWUpLmpvaW4oXCIsIFwiKX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlbGVjdGVkLmlkO1xufSk7XG5cbmZ1bmN0aW9uIGdldFJvb3REb21haW4oa2V5OiBzdHJpbmcpIHtcbiAgICBpZiAoa2V5LmVuZHNXaXRoKFwiLlwiKSkge1xuICAgICAgICBrZXkgPSBrZXkuc2xpY2UoMCwgLTEpO1xuICAgIH1cbiAgICByZXR1cm4ga2V5LnNwbGl0KFwiLlwiKS5zbGljZSgtMikuam9pbihcIi5cIik7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRSZWNvcmRzUmF3KHR5cGU6IHN0cmluZywga2V5OiBzdHJpbmcpIHtcbiAgICBpZiAoa2V5LmVuZHNXaXRoKFwiLlwiKSkga2V5ID0ga2V5LnNsaWNlKDAsIC0xKTtcbiAgICBsZXQgem9uZUlkID0gYXdhaXQgZ2V0Wm9uZUlkKGdldFJvb3REb21haW4oa2V5KSk7XG4gICAgbGV0IHJlc3VsdHMgPSBhd2FpdCBjbG91ZGZsYXJlR0VUQ2FsbDx7XG4gICAgICAgIGlkOiBzdHJpbmc7XG4gICAgICAgIHR5cGU6IHN0cmluZztcbiAgICAgICAgbmFtZTogc3RyaW5nO1xuICAgICAgICBjb250ZW50OiBzdHJpbmc7XG4gICAgICAgIHByb3hpZWQ6IGJvb2xlYW47XG4gICAgfVtdPihgL3pvbmVzLyR7em9uZUlkfS9kbnNfcmVjb3Jkc2ApO1xuICAgIHJldHVybiByZXN1bHRzLmZpbHRlcih4ID0+IHgudHlwZSA9PT0gdHlwZSAmJiB4Lm5hbWUgPT09IGtleSk7XG59XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UmVjb3Jkcyh0eXBlOiBzdHJpbmcsIGtleTogc3RyaW5nKSB7XG4gICAgaWYgKGtleS5lbmRzV2l0aChcIi5cIikpIGtleSA9IGtleS5zbGljZSgwLCAtMSk7XG4gICAgbGV0IHJhdyA9IGF3YWl0IGdldFJlY29yZHNSYXcodHlwZSwga2V5KTtcbiAgICByZXR1cm4gcmF3Lm1hcCh4ID0+IHguY29udGVudCk7XG59XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVsZXRlUmVjb3JkKHR5cGU6IHN0cmluZywga2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpIHtcbiAgICBpZiAoa2V5LmVuZHNXaXRoKFwiLlwiKSkga2V5ID0ga2V5LnNsaWNlKDAsIC0xKTtcbiAgICBsZXQgem9uZUlkID0gYXdhaXQgZ2V0Wm9uZUlkKGdldFJvb3REb21haW4oa2V5KSk7XG4gICAgbGV0IHByZXZWYWx1ZXMgPSBhd2FpdCBnZXRSZWNvcmRzUmF3KHR5cGUsIGtleSk7XG4gICAgcHJldlZhbHVlcyA9IHByZXZWYWx1ZXMuZmlsdGVyKHggPT4geC5jb250ZW50ID09PSB2YWx1ZSk7XG4gICAgaWYgKHByZXZWYWx1ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGlmICghU29ja2V0RnVuY3Rpb24uc2lsZW50KSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgTm8gbmVlZCB0byBkZWxldGUgcmVjb3JkLCBpdCB3YXMgbm90IGZvdW5kLiAke0pTT04uc3RyaW5naWZ5KHZhbHVlKX0gdmFsdWUgd2FzIG5vdCBpbiAke3R5cGV9IGZvciAke2tleX0sIHZhbHVlcyAke0pTT04uc3RyaW5naWZ5KHByZXZWYWx1ZXMubWFwKHggPT4geC5jb250ZW50KSl9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKGBSZW1vdmluZyByZWNvcmRzIG9mICR7dHlwZX0gZm9yICR7a2V5fSwgdmFsdWVzICR7SlNPTi5zdHJpbmdpZnkocHJldlZhbHVlcy5tYXAoeCA9PiB4LmNvbnRlbnQpKX1gKTtcbiAgICBmb3IgKGxldCB2YWx1ZSBvZiBwcmV2VmFsdWVzKSB7XG4gICAgICAgIGF3YWl0IGNsb3VkZmxhcmVDYWxsKGAvem9uZXMvJHt6b25lSWR9L2Ruc19yZWNvcmRzLyR7dmFsdWUuaWR9YCwgQnVmZmVyLmZyb20oW10pLCBcIkRFTEVURVwiKTtcbiAgICB9XG59XG4vKiogUmVtb3ZlcyBhbGwgZXhpc3RpbmcgcmVjb3JkcyAodW5sZXNzIHRoZSByZWNvcmQgaXMgYWxyZWFkeSBwcmVzZW50KSAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNldFJlY29yZCh0eXBlOiBzdHJpbmcsIGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCBwcm94aWVkPzogXCJwcm94aWVkXCIpIHtcbiAgICBsZXQgc3RhY2sgPSBuZXcgRXJyb3IoKTtcbiAgICBpZiAoa2V5LmVuZHNXaXRoKFwiLlwiKSkga2V5ID0ga2V5LnNsaWNlKDAsIC0xKTtcbiAgICBsZXQgem9uZUlkID0gYXdhaXQgZ2V0Wm9uZUlkKGdldFJvb3REb21haW4oa2V5KSk7XG4gICAgbGV0IHByZXZWYWx1ZXMgPSBhd2FpdCBnZXRSZWNvcmRzUmF3KHR5cGUsIGtleSk7XG4gICAgLy8gTk9URTogQXBwYXJlbnRseSBpZiB3ZSB0cnkgdG8gdXBkYXRlIGJ5IGp1c3QgY2hhbmdpbmcgcHJveGllZCwgY2xvdWRmbGFyZSBjb21wbGFpbnMgYW5kXG4gICAgLy8gIHNheXMgXCJhbiBpZGVudGljYWwgcmVjb3JkIGFscmVhZHkgZXhpc3RzXCIsIGV2ZW4gdGhvdWdoIGl0IGRvZXNuJ3QsIHdlIGNoYW5nZWQgdGhlIHByb3hpZWQgdmFsdWUuLi5cbiAgICBpZiAocHJldlZhbHVlcy5zb21lKHggPT4geC5jb250ZW50ID09PSB2YWx1ZSkpIHJldHVybjtcblxuICAgIGNvbnNvbGUubG9nKGBSZW1vdmluZyBwcmV2aW91cyByZWNvcmRzIG9mICR7dHlwZX0gZm9yICR7a2V5fSAke0pTT04uc3RyaW5naWZ5KHByZXZWYWx1ZXMubWFwKHggPT4geC5jb250ZW50KSl9YCk7XG4gICAgbGV0IGRpZERlbGV0aW9ucyA9IGZhbHNlO1xuICAgIGZvciAobGV0IHZhbHVlIG9mIHByZXZWYWx1ZXMpIHtcbiAgICAgICAgZGlkRGVsZXRpb25zID0gdHJ1ZTtcbiAgICAgICAgYXdhaXQgY2xvdWRmbGFyZUNhbGwoYC96b25lcy8ke3pvbmVJZH0vZG5zX3JlY29yZHMvJHt2YWx1ZS5pZH1gLCBCdWZmZXIuZnJvbShbXSksIFwiREVMRVRFXCIpO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKGBTZXR0aW5nICR7dHlwZX0gcmVjb3JkIGZvciAke2tleX0gdG8gJHt2YWx1ZX0gKHByZXZpb3VzbHkgaGFkICR7SlNPTi5zdHJpbmdpZnkocHJldlZhbHVlcy5tYXAoeCA9PiB4LmNvbnRlbnQpKX0pYCk7XG4gICAgY29uc3QgdHRsID0gRE5TX1RUTFNlY29uZHNbdHlwZSBhcyBcIkFcIl0gfHwgNjA7XG4gICAgYXdhaXQgY2xvdWRmbGFyZVBPU1RDYWxsKGAvem9uZXMvJHt6b25lSWR9L2Ruc19yZWNvcmRzYCwge1xuICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICBuYW1lOiBrZXksXG4gICAgICAgIGNvbnRlbnQ6IHZhbHVlLFxuICAgICAgICB0dGwsXG4gICAgICAgIHByb3hpZWQ6IHByb3hpZWQgPT09IFwicHJveGllZFwiLFxuICAgIH0pO1xuICAgIC8vIE5PVEU6IEFwcGFyZW50bHkuLi4gZXZlbiBpZiB0aGUgcmVjb3JkIGRpZG4ndCBleGlzdCwgd2Ugc3RpbGwgaGF2ZSB0byB3YWl0Li4uXG4gICAgY29uc29sZS5sb2coYFdhaXRpbmcgJHt0dGx9IHNlY29uZHMgZm9yIEROUyB0byBwcm9wYWdhdGUuLi5gKTtcbiAgICBhd2FpdCBkZWxheSh0dGwgKiAxMDAwKTtcbiAgICBjb25zb2xlLmxvZyhgRG9uZSB3YWl0aW5nIGZvciBETlMgdG8gdXBkYXRlLmApO1xuXG59XG4vKiogS2VlcHMgZXhpc3RpbmcgcmVjb3JkcyAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFkZFJlY29yZCh0eXBlOiBzdHJpbmcsIGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCBwcm94aWVkPzogXCJwcm94aWVkXCIpIHtcbiAgICBpZiAoa2V5LmVuZHNXaXRoKFwiLlwiKSkga2V5ID0ga2V5LnNsaWNlKDAsIC0xKTtcbiAgICBsZXQgem9uZUlkID0gYXdhaXQgZ2V0Wm9uZUlkKGdldFJvb3REb21haW4oa2V5KSk7XG4gICAgbGV0IHByZXZWYWx1ZXMgPSBhd2FpdCBnZXRSZWNvcmRzUmF3KHR5cGUsIGtleSk7XG4gICAgLy8gTk9URTogQXBwYXJlbnRseSBpZiB3ZSB0cnkgdG8gdXBkYXRlIGJ5IGp1c3QgY2hhbmdpbmcgcHJveGllZCwgY2xvdWRmbGFyZSBjb21wbGFpbnMgYW5kXG4gICAgLy8gIHNheXMgXCJhbiBpZGVudGljYWwgcmVjb3JkIGFscmVhZHkgZXhpc3RzXCIsIGV2ZW4gdGhvdWdoIGl0IGRvZXNuJ3QsIHdlIGNoYW5nZWQgdGhlIHByb3hpZWQgdmFsdWUuLi5cbiAgICBpZiAocHJldlZhbHVlcy5zb21lKHggPT4geC5jb250ZW50ID09PSB2YWx1ZSkpIHJldHVybjtcbiAgICBjb25zb2xlLmxvZyhgQWRkaW5nICR7dHlwZX0gcmVjb3JkIGZvciAke2tleX0gdG8gJHt2YWx1ZX0gKHByZXZpb3VzbHkgaGFkICR7SlNPTi5zdHJpbmdpZnkocHJldlZhbHVlcy5tYXAoeCA9PiB4LmNvbnRlbnQpKX0pYCk7XG4gICAgY29uc3QgdHRsID0gRE5TX1RUTFNlY29uZHNbdHlwZSBhcyBcIkFcIl0gfHwgNjA7XG4gICAgYXdhaXQgY2xvdWRmbGFyZVBPU1RDYWxsKGAvem9uZXMvJHt6b25lSWR9L2Ruc19yZWNvcmRzYCwge1xuICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICBuYW1lOiBrZXksXG4gICAgICAgIGNvbnRlbnQ6IHZhbHVlLFxuICAgICAgICB0dGwsXG4gICAgICAgIHByb3hpZWQ6IHByb3hpZWQgPT09IFwicHJveGllZFwiLFxuICAgIH0pO1xuICAgIGNvbnNvbGUubG9nKGBXYWl0aW5nICR7dHRsfSBzZWNvbmRzIGZvciBETlMgdG8gcHJvcGFnYXRlLi4uYCk7XG4gICAgYXdhaXQgZGVsYXkodHRsICogMTAwMCk7XG4gICAgY29uc29sZS5sb2coYERvbmUgd2FpdGluZyBmb3IgRE5TIHRvIHVwZGF0ZS5gKTtcbn1cblxuXG5jb25zdCBnZXRDbG91ZGZsYXJlQ3JlZHMgPSBsYXp5KGFzeW5jICgpOiBQcm9taXNlPHsga2V5OiBzdHJpbmc7IH0+ID0+IHtcbiAgICBjb25zdCBwYXRoID0gXCJjbG91ZGZsYXJlLmpzb25cIjtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMocGF0aCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBNdXN0IGFkZCBjbG91ZGZsYXJlLmpzb24gZmlsZSB0byByb290IG9mIHByb2plY3QuYCk7XG4gICAgfVxuICAgIGxldCBjcmVkcyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHBhdGgsIFwidXRmOFwiKSkgYXMgeyBrZXk6IHN0cmluZzsgfTtcbiAgICByZXR1cm4ge1xuICAgICAgICBrZXk6IGNyZWRzLmtleSxcbiAgICB9O1xufSk7XG5cbmFzeW5jIGZ1bmN0aW9uIGNsb3VkZmxhcmVHRVRDYWxsPFQ+KHBhdGg6IHN0cmluZywgcGFyYW1zPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSk6IFByb21pc2U8VD4ge1xuICAgIGxldCB1cmwgPSBuZXcgVVJMKGBodHRwczovL2FwaS5jbG91ZGZsYXJlLmNvbS9jbGllbnQvdjRgICsgcGF0aCk7XG4gICAgZm9yIChsZXQga2V5IGluIHBhcmFtcykge1xuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLnNldChrZXksIHBhcmFtc1trZXldKTtcbiAgICB9XG4gICAgbGV0IGNyZWRzID0gYXdhaXQgZ2V0Q2xvdWRmbGFyZUNyZWRzKCk7XG4gICAgbGV0IHJlc3VsdCA9IGF3YWl0IGh0dHBzUmVxdWVzdCh1cmwudG9TdHJpbmcoKSwgW10sIFwiR0VUXCIsIHVuZGVmaW5lZCwge1xuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgICAgIFwiQXV0aG9yaXphdGlvblwiOiBgQmVhcmVyICR7Y3JlZHMua2V5fWAsXG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBsZXQgcmVzdWx0MiA9IEpTT04ucGFyc2UocmVzdWx0LnRvU3RyaW5nKCkpIGFzIHsgcmVzdWx0OiB1bmtub3duOyBzdWNjZXNzOiBib29sZWFuOyBlcnJvcnM6IHsgY29kZTogbnVtYmVyOyBtZXNzYWdlOiBzdHJpbmcgfVtdIH07XG4gICAgaWYgKCFyZXN1bHQyLnN1Y2Nlc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbG91ZGZsYXJlIGNhbGwgZmFpbGVkOiAke3Jlc3VsdDIuZXJyb3JzLm1hcCh4ID0+IHgubWVzc2FnZSkuam9pbihcIiwgXCIpfWApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0Mi5yZXN1bHQgYXMgVDtcbn1cbmFzeW5jIGZ1bmN0aW9uIGNsb3VkZmxhcmVQT1NUQ2FsbDxUPihwYXRoOiBzdHJpbmcsIHBhcmFtczogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0pOiBQcm9taXNlPFQ+IHtcbiAgICByZXR1cm4gYXdhaXQgY2xvdWRmbGFyZUNhbGwocGF0aCwgQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkocGFyYW1zKSksIFwiUE9TVFwiKTtcbn1cbmFzeW5jIGZ1bmN0aW9uIGNsb3VkZmxhcmVDYWxsPFQ+KHBhdGg6IHN0cmluZywgcGF5bG9hZDogQnVmZmVyLCBtZXRob2Q6IHN0cmluZyk6IFByb21pc2U8VD4ge1xuICAgIGxldCB1cmwgPSBuZXcgVVJMKGBodHRwczovL2FwaS5jbG91ZGZsYXJlLmNvbS9jbGllbnQvdjRgICsgcGF0aCk7XG4gICAgbGV0IGNyZWRzID0gYXdhaXQgZ2V0Q2xvdWRmbGFyZUNyZWRzKCk7XG4gICAgbGV0IHJlc3VsdCA9IGF3YWl0IGh0dHBzUmVxdWVzdCh1cmwudG9TdHJpbmcoKSwgcGF5bG9hZCwgbWV0aG9kLCB1bmRlZmluZWQsIHtcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgICAgICBcIkF1dGhvcml6YXRpb25cIjogYEJlYXJlciAke2NyZWRzLmtleX1gLFxuICAgICAgICB9XG4gICAgfSk7XG4gICAgbGV0IHJlc3VsdDIgPSBKU09OLnBhcnNlKHJlc3VsdC50b1N0cmluZygpKSBhcyB7IHJlc3VsdDogdW5rbm93bjsgc3VjY2VzczogYm9vbGVhbjsgZXJyb3JzOiB7IGNvZGU6IG51bWJlcjsgbWVzc2FnZTogc3RyaW5nIH1bXSB9O1xuICAgIGlmICghcmVzdWx0Mi5zdWNjZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2xvdWRmbGFyZSBjYWxsIGZhaWxlZDogJHtyZXN1bHQyLmVycm9ycy5tYXAoeCA9PiB4Lm1lc3NhZ2UpLmpvaW4oXCIsIFwiKX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDIucmVzdWx0IGFzIFQ7XG59Il19
166
- /* _JS_SOURCE_HASH = "23ba5542e3de4342e75c1b8db86679523e53f9535c85e9f1b8abd80af92a917c"; */
177
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZG5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlEQUEwRDtBQUMxRCwyREFBcUQ7QUFDckQsbUVBQWdFO0FBQ2hFLG1EQUE2RDtBQUM3RCx3RUFBbUU7QUFDbkUsMkRBQWdIO0FBRWhILE1BQU0sY0FBYyxHQUFHO0lBQ25CLEtBQUssRUFBRSxFQUFFO0lBQ1QsR0FBRyxFQUFFLEVBQUU7Q0FDVixDQUFDO0FBRUYsTUFBTSx1QkFBdUIsR0FBRyxnQkFBUyxDQUFDO0FBRTFDLHdGQUF3RjtBQUN4RiwyRkFBMkY7QUFDM0YsMEZBQTBGO0FBQzFGLGdHQUFnRztBQUNoRyxrR0FBa0c7QUFDbEcsTUFBTSxlQUFlLEdBQUcsZ0JBQWdCLENBQUM7QUFFekMsMkZBQTJGO0FBQzNGLFNBQVMsY0FBYyxDQUFDLE9BQWdCO0lBQ3BDLElBQUksSUFBSSxHQUFHLENBQUMsT0FBTyxhQUFQLE9BQU8sY0FBUCxPQUFPLEdBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMvRCxJQUFJLEtBQUssR0FBRyxZQUFZLElBQUksSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQztJQUNqRCxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztBQUM3QyxDQUFDO0FBQ0Qsc0ZBQXNGO0FBQ3RGLFNBQWdCLGFBQWEsQ0FBQyxPQUFnQjtJQUMxQyxJQUFJLEtBQUssR0FBRyxlQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sYUFBUCxPQUFPLGNBQVAsT0FBTyxHQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2hELElBQUksQ0FBQyxLQUFLO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDckIsT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxD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QUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMvSCxNQUFNLFlBQVksQ0FBQyxNQUFNLEVBQUU7UUFDdkIsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDdkQsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLE9BQU8sS0FBSyxTQUFTLEVBQUUsT0FBTyxFQUFFLENBQUM7S0FDN0csQ0FBQyxDQUFDO0lBQ0gsSUFBSSxRQUFRO1FBQUUsT0FBTztJQUNyQixPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsR0FBRyxrQ0FBa0MsQ0FBQyxDQUFDO0lBQzlELEtBQUssSUFBSSxPQUFPLEdBQUcsR0FBRyxFQUFFLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQztRQUM3QyxNQUFNLElBQUEsZ0JBQUssRUFBQyxJQUFJLENBQUMsQ0FBQztRQUNsQixPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsT0FBTyxrQkFBa0IsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7QUFDbkQsQ0FBQztBQXRCRCw4QkFzQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjYWNoZSwgbGF6eSB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2NhY2hpbmdcIjtcbmltcG9ydCB7IGRlbGF5IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvYmF0Y2hpbmdcIjtcbmltcG9ydCB7IFNvY2tldEZ1bmN0aW9uIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9Tb2NrZXRGdW5jdGlvblwiO1xuaW1wb3J0IHsgaXNOb2RlLCB0aW1lSW5EYXkgfSBmcm9tIFwic29ja2V0LWZ1bmN0aW9uL3NyYy9taXNjXCI7XG5pbXBvcnQgeyBtYWdlbnRhIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvZm9ybWF0dGluZy9sb2dDb2xvcnNcIjtcbmltcG9ydCB7IGNsb3VkZmxhcmVDYWxsLCBjbG91ZGZsYXJlR0VUQ2FsbCwgY2xvdWRmbGFyZVBPU1RDYWxsLCBnZXRDbG91ZGZsYXJlQ3JlZHMgfSBmcm9tIFwiLi9jbG91ZGZsYXJlSGVscGVyc1wiO1xuXG5jb25zdCBETlNfVFRMU2Vjb25kcyA9IHtcbiAgICBcIlRYVFwiOiA2MCxcbiAgICBcIkFcIjogNjAsXG59O1xuXG5jb25zdCBETlNfUkVGUkVTSF9TVEFMRV9BRlRFUiA9IHRpbWVJbkRheTtcblxuLy8gV2Ugc3RhbXAgb3VyIG93biBcImxhc3QgYXNzZXJ0ZWRcIiB0aW1lIGludG8gdGhlIHJlY29yZCdzIGNvbW1lbnQsIGJlY2F1c2UgQ2xvdWRmbGFyZSdzXG4vLyAgbW9kaWZpZWRfb24gY2FuIG9ubHkgYmUgbW92ZWQgYnkgYW4gYWN0dWFsIGNvbnRlbnQgY2hhbmdlIC0gYW5kIHJlLWFzc2VydGluZyBhbiBhbHJlYWR5XG4vLyAgY29ycmVjdCByZWNvcmQgaGFzIG5vIGNvbnRlbnQgY2hhbmdlIHRvIG1ha2UgKGEgY3JlYXRlIGVycm9ycyB3aXRoIDgxMDU4LCBhIG5vLW9wIGVkaXRcbi8vICBkb2Vzbid0IGJ1bXAgdGhlIHRpbWVzdGFtcCkuIFJlYWRpbmcgZnJlc2huZXNzIGZyb20gdGV4dCB3ZSBjb250cm9sIHNpZGVzdGVwcyB0aGF0IGVudGlyZWx5LFxuLy8gIGFuZCBsZXRzIHVzIHJlZnJlc2ggYSBzdGFsZS1idXQtY29ycmVjdCByZWNvcmQgaW4gcGxhY2UgaW5zdGVhZCBvZiBkZWxldGluZyBhbmQgcmVjcmVhdGluZyBpdC5cbmNvbnN0IEZSRVNITkVTU19SRUdFWCA9IC88c2V0IG9uOltePl0qPi87XG5cbi8qKiBTdHJpcHMgYW55IHByaW9yIGZyZXNobmVzcyB0YWcgYW5kIGFwcGVuZHMgYSBuZXcgb25lLCBwcmVzZXJ2aW5nIG90aGVyIGNvbW1lbnQgdGV4dC4gKi9cbmZ1bmN0aW9uIHN0YW1wRnJlc2huZXNzKGNvbW1lbnQ/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGxldCBiYXNlID0gKGNvbW1lbnQgPz8gXCJcIikucmVwbGFjZShGUkVTSE5FU1NfUkVHRVgsIFwiXCIpLnRyaW0oKTtcbiAgICBsZXQgc3RhbXAgPSBgPHNldCBvbjogJHtuZXcgRGF0ZSgpLnRvU3RyaW5nKCl9PmA7XG4gICAgcmV0dXJuIGJhc2UgPyBgJHtiYXNlfSAke3N0YW1wfWAgOiBzdGFtcDtcbn1cbi8qKiBQYXJzZXMgb3VyIHRhZyBiYWNrIG91dDsgMCAoaS5lLiBhbHdheXMgc3RhbGUpIHdoZW4gaXQncyBhYnNlbnQgb3IgdW5wYXJzZWFibGUuICovXG5leHBvcnQgZnVuY3Rpb24gZnJlc2huZXNzVGltZShjb21tZW50Pzogc3RyaW5nKTogbnVtYmVyIHtcbiAgICBsZXQgbWF0Y2ggPSBGUkVTSE5FU1NfUkVHRVguZXhlYyhjb21tZW50ID8/IFwiXCIpO1xuICAgIGlmICghbWF0Y2gpIHJldHVybiAwO1xuICAgIHJldHVybiBuZXcgRGF0ZShtYXRjaFswXS5yZXBsYWNlKFwiPHNldCBvbjpcIiwgXCJcIikucmVwbGFjZShcIj5cIiwgXCJcIikudHJpbSgpKS5nZXRUaW1lKCkgfHwgMDtcbn1cblxuZXhwb3J0IGNvbnN0IGhhc0ROU1dyaXRlUGVybWlzc2lvbnMgPSBsYXp5KGFzeW5jICgpID0+IHtcbiAgICBpZiAoIWlzTm9kZSgpKSByZXR1cm4gZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZ2V0Q2xvdWRmbGFyZUNyZWRzKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufSk7XG5cbmV4cG9ydCBjb25zdCBnZXRab25lSWQgPSBjYWNoZShhc3luYyAocm9vdERvbWFpbjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgICBsZXQgem9uZXMgPSBhd2FpdCBjbG91ZGZsYXJlR0VUQ2FsbDx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZyB9W10+KFwiL3pvbmVzXCIsIHt9KTtcbiAgICBsZXQgc2VsZWN0ZWQgPSB6b25lcy5maW5kKHggPT4geC5uYW1lID09PSByb290RG9tYWluKTtcbiAgICBpZiAoIXNlbGVjdGVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGZpbmQgem9uZSBmb3IgJHtyb290RG9tYWlufS4gRm91bmQgJHt6b25lcy5tYXAoeCA9PiB4Lm5hbWUpLmpvaW4oXCIsIFwiKX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlbGVjdGVkLmlkO1xufSk7XG5cbmZ1bmN0aW9uIGdldFJvb3REb21haW4oa2V5OiBzdHJpbmcpIHtcbiAgICBpZiAoa2V5LmVuZHNXaXRoKFwiLlwiKSkge1xuICAgICAgICBrZXkgPSBrZXkuc2xpY2UoMCwgLTEpO1xuICAgIH1cbiAgICByZXR1cm4ga2V5LnNwbGl0KFwiLlwiKS5zbGljZSgtMikuam9pbihcIi5cIik7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRSZWNvcmRzUmF3KHR5cGU6IHN0cmluZywga2V5OiBzdHJpbmcpIHtcbiAgICBpZiAoa2V5LmVuZHNXaXRoKFwiLlwiKSkga2V5ID0ga2V5LnNsaWNlKDAsIC0xKTtcbiAgICBsZXQgem9uZUlkID0gYXdhaXQgZ2V0Wm9uZUlkKGdldFJvb3REb21haW4oa2V5KSk7XG4gICAgbGV0IHJlc3VsdHMgPSBhd2FpdCBjbG91ZGZsYXJlR0VUQ2FsbDx7XG4gICAgICAgIGlkOiBzdHJpbmc7XG4gICAgICAgIHR5cGU6IHN0cmluZztcbiAgICAgICAgbmFtZTogc3RyaW5nO1xuICAgICAgICBjb250ZW50OiBzdHJpbmc7XG4gICAgICAgIHByb3hpZWQ6IGJvb2xlYW47XG4gICAgICAgIG1vZGlmaWVkX29uOiBzdHJpbmc7XG4gICAgICAgIC8vIE9taXR0ZWQgYnkgQ2xvdWRmbGFyZSB3aGVuIHRoZSByZWNvcmQgaGFzIG5vIGNvbW1lbnQuXG4gICAgICAgIGNvbW1lbnQ/OiBzdHJpbmc7XG4gICAgfVtdPihgL3pvbmVzLyR7em9uZUlkfS9kbnNfcmVjb3Jkc2ApO1xuICAgIC8vIEROUyBuYW1lcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZSBhbmQgQ2xvdWRmbGFyZSByZXR1cm5zIHRoZW0gbG93ZXJjYXNlZCwgc28gYSBtaXhlZC1jYXNlIGtleVxuICAgIC8vICAoZS5nLiBhIG1hY2hpbmUgaWQgc3ViZG9tYWluKSB3b3VsZCBuZXZlciBtYXRjaCBhbiBleGFjdC1jYXNlIGNvbXBhcmUgLSBtYXRjaCBsb3dlcmNhc2VkLlxuICAgIGxldCBrZXlMb3dlciA9IGtleS50b0xvd2VyQ2FzZSgpO1xuICAgIHJldHVybiByZXN1bHRzLmZpbHRlcih4ID0+IHgudHlwZSA9PT0gdHlwZSAmJiB4Lm5hbWUudG9Mb3dlckNhc2UoKSA9PT0ga2V5TG93ZXIpO1xufVxuXG4vKiogQ2xvdWRmbGFyZSdzIGJhdGNoIGVuZHBvaW50IGFwcGxpZXMgZGVsZXRlcywgdGhlbiBwYXRjaGVzLCB0aGVuIHBvc3RzIGluIGEgc2luZ2xlIGRhdGFiYXNlXG4gKiAgIHRyYW5zYWN0aW9uLiBXZSByb3V0ZSBlZGl0cyAocGF0Y2hlcykgdGhyb3VnaCBoZXJlIGJlY2F1c2UgdGhlIHN0YW5kYWxvbmUgUEFUQ0gvUFVUIHZlcmJzXG4gKiAgIGFyZW4ndCB1c2FibGUgaW4gb3VyIHNldHVwLCBhbmQgYmVjYXVzZSBpdCBsZXRzIFwicmVtb3ZlIG90aGVycyArIGFzc2VydCB0YXJnZXRcIiBoYXBwZW5cbiAqICAgd2l0aG91dCBhIHdpbmRvdyB3aGVyZSB0aGUgbmFtZSByZXNvbHZlcyB0byBub3RoaW5nLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJhdGNoUmVjb3Jkcyh6b25lSWQ6IHN0cmluZywgYmF0Y2g6IHtcbiAgICBkZWxldGVzPzogeyBpZDogc3RyaW5nIH1bXTtcbiAgICBwYXRjaGVzPzogeyBpZDogc3RyaW5nOyBjb21tZW50Pzogc3RyaW5nIH1bXTtcbiAgICBwb3N0cz86IHsgdHlwZTogc3RyaW5nOyBuYW1lOiBzdHJpbmc7IGNvbnRlbnQ6IHN0cmluZzsgdHRsOiBudW1iZXI7IHByb3hpZWQ6IGJvb2xlYW47IGNvbW1lbnQ/OiBzdHJpbmcgfVtdO1xufSkge1xuICAgIGxldCBwYXlsb2FkOiB7IFtrZXk6IHN0cmluZ106IHVua25vd24gfSA9IHt9O1xuICAgIGlmIChiYXRjaC5kZWxldGVzICYmIGJhdGNoLmRlbGV0ZXMubGVuZ3RoID4gMCkgcGF5bG9hZC5kZWxldGVzID0gYmF0Y2guZGVsZXRlcztcbiAgICBpZiAoYmF0Y2gucGF0Y2hlcyAmJiBiYXRjaC5wYXRjaGVzLmxlbmd0aCA+IDApIHBheWxvYWQucGF0Y2hlcyA9IGJhdGNoLnBhdGNoZXM7XG4gICAgaWYgKGJhdGNoLnBvc3RzICYmIGJhdGNoLnBvc3RzLmxlbmd0aCA+IDApIHBheWxvYWQucG9zdHMgPSBiYXRjaC5wb3N0cztcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBjbG91ZGZsYXJlUE9TVENhbGwoYC96b25lcy8ke3pvbmVJZH0vZG5zX3JlY29yZHMvYmF0Y2hgLCBwYXlsb2FkKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciB1cGRhdGluZyBETlMgcmVjb3JkczpgLCB7IGVycm9yOiBlcnJvciwgYmF0Y2ggfSk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgdXBkYXRpbmcgRE5TIHJlY29yZHMuICR7SlNPTi5zdHJpbmdpZnkoYmF0Y2gpfS4gRXJyb3I6ICR7ZXJyb3J9YCk7XG4gICAgfVxufVxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFJlY29yZHModHlwZTogc3RyaW5nLCBrZXk6IHN0cmluZykge1xuICAgIGlmIChrZXkuZW5kc1dpdGgoXCIuXCIpKSBrZXkgPSBrZXkuc2xpY2UoMCwgLTEpO1xuICAgIGxldCByYXcgPSBhd2FpdCBnZXRSZWNvcmRzUmF3KHR5cGUsIGtleSk7XG4gICAgcmV0dXJuIHJhdy5tYXAoeCA9PiB4LmNvbnRlbnQpO1xufVxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZVJlY29yZCh0eXBlOiBzdHJpbmcsIGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgaWYgKGtleS5lbmRzV2l0aChcIi5cIikpIGtleSA9IGtleS5zbGljZSgwLCAtMSk7XG4gICAgbGV0IHpvbmVJZCA9IGF3YWl0IGdldFpvbmVJZChnZXRSb290RG9tYWluKGtleSkpO1xuICAgIGxldCBwcmV2VmFsdWVzID0gYXdhaXQgZ2V0UmVjb3Jkc1Jhdyh0eXBlLCBrZXkpO1xuICAgIHByZXZWYWx1ZXMgPSBwcmV2VmFsdWVzLmZpbHRlcih4ID0+IHguY29udGVudCA9PT0gdmFsdWUpO1xuICAgIGlmIChwcmV2VmFsdWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBpZiAoIVNvY2tldEZ1bmN0aW9uLnNpbGVudCkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYE5vIG5lZWQgdG8gZGVsZXRlIHJlY29yZCwgaXQgd2FzIG5vdCBmb3VuZC4gJHtKU09OLnN0cmluZ2lmeSh2YWx1ZSl9IHZhbHVlIHdhcyBub3QgaW4gJHt0eXBlfSBmb3IgJHtrZXl9LCB2YWx1ZXMgJHtKU09OLnN0cmluZ2lmeShwcmV2VmFsdWVzLm1hcCh4ID0+IHguY29udGVudCkpfWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhgUmVtb3ZpbmcgcmVjb3JkcyBvZiAke3R5cGV9IGZvciAke2tleX0sIHZhbHVlcyAke0pTT04uc3RyaW5naWZ5KHByZXZWYWx1ZXMubWFwKHggPT4geC5jb250ZW50KSl9YCk7XG4gICAgZm9yIChsZXQgdmFsdWUgb2YgcHJldlZhbHVlcykge1xuICAgICAgICBhd2FpdCBjbG91ZGZsYXJlQ2FsbChgL3pvbmVzLyR7em9uZUlkfS9kbnNfcmVjb3Jkcy8ke3ZhbHVlLmlkfWAsIEJ1ZmZlci5mcm9tKFtdKSwgXCJERUxFVEVcIik7XG4gICAgfVxufVxuLyoqIFJlbW92ZXMgYWxsIGV4aXN0aW5nIHJlY29yZHMgKHVubGVzcyB0aGUgcmVjb3JkIGlzIGFscmVhZHkgcHJlc2VudCBhbmQgZnJlc2gpICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2V0UmVjb3JkKHR5cGU6IHN0cmluZywga2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIHByb3hpZWQ/OiBcInByb3hpZWRcIiwgc3RhbGVBZnRlciA9IEROU19SRUZSRVNIX1NUQUxFX0FGVEVSKSB7XG4gICAgaWYgKGtleS5lbmRzV2l0aChcIi5cIikpIGtleSA9IGtleS5zbGljZSgwLCAtMSk7XG4gICAgbGV0IHpvbmVJZCA9IGF3YWl0IGdldFpvbmVJZChnZXRSb290RG9tYWluKGtleSkpO1xuICAgIGxldCBwcmV2VmFsdWVzID0gYXdhaXQgZ2V0UmVjb3Jkc1Jhdyh0eXBlLCBrZXkpO1xuICAgIGxldCBleGlzdGluZyA9IHByZXZWYWx1ZXMuZmluZCh4ID0+IHguY29udGVudCA9PT0gdmFsdWUpO1xuICAgIGxldCBvdGhlcnMgPSBwcmV2VmFsdWVzLmZpbHRlcih4ID0+IHguY29udGVudCAhPT0gdmFsdWUpO1xuXG4gICAgLy8gQWxyZWFkeSBjb3JyZWN0IGFuZCByZWNlbnRseSBhc3NlcnRlZCAtIGEgcHJpb3IgcnVuIGFsc28gY2xlYW5lZCB1cCB0aGUgb3RoZXIgcmVjb3JkcyxcbiAgICAvLyAgc28gdGhlcmUgaXMgbm90aGluZyBsZWZ0IHRvIGRvLlxuICAgIGlmIChleGlzdGluZyAmJiBEYXRlLm5vdygpIC0gZnJlc2huZXNzVGltZShleGlzdGluZy5jb21tZW50KSA8IHN0YWxlQWZ0ZXIpIHJldHVybjtcblxuICAgIC8vIEEgc2luZ2xlIGF0b21pYyBiYXRjaDogZHJvcCB0aGUgd3JvbmcgcmVjb3JkcywgYW5kIGVpdGhlciByZWZyZXNoIHRoZSBleGlzdGluZyByZWNvcmQnc1xuICAgIC8vICBjb21tZW50IGluIHBsYWNlIG9yIGNyZWF0ZSBpdCAtIHNvIHRoZSBuYW1lIGlzIG5ldmVyIGxlZnQgcmVzb2x2aW5nIHRvIG5vdGhpbmcuXG4gICAgbGV0IHR0bCA9IEROU19UVExTZWNvbmRzW3R5cGUgYXMgXCJBXCJdIHx8IDYwO1xuICAgIGxldCBjb21tZW50ID0gc3RhbXBGcmVzaG5lc3MoZXhpc3Rpbmc/LmNvbW1lbnQpO1xuICAgIGNvbnNvbGUubG9nKG1hZ2VudGEoYFNldHRpbmcgJHt0eXBlfSByZWNvcmQgZm9yICR7a2V5fSB0byAke3ZhbHVlfSAocHJldmlvdXNseSBoYWQgJHtKU09OLnN0cmluZ2lmeShwcmV2VmFsdWVzLm1hcCh4ID0+IHguY29udGVudCkpfSlgKSk7XG4gICAgYXdhaXQgYmF0Y2hSZWNvcmRzKHpvbmVJZCwge1xuICAgICAgICBkZWxldGVzOiBvdGhlcnMubWFwKHggPT4gKHsgaWQ6IHguaWQgfSkpLFxuICAgICAgICBwYXRjaGVzOiBleGlzdGluZyA/IFt7IGlkOiBleGlzdGluZy5pZCwgY29tbWVudCB9XSA6IFtdLFxuICAgICAgICBwb3N0czogZXhpc3RpbmcgPyBbXSA6IFt7IHR5cGUsIG5hbWU6IGtleSwgY29udGVudDogdmFsdWUsIHR0bCwgcHJveGllZDogcHJveGllZCA9PT0gXCJwcm94aWVkXCIsIGNvbW1lbnQgfV0sXG4gICAgfSk7XG4gICAgLy8gT25seSBhIGJyYW5kIG5ldyByZWNvcmQgbmVlZHMgdG8gcHJvcGFnYXRlOyBhbiBpbi1wbGFjZSBjb21tZW50IHJlZnJlc2ggZG9lc24ndCBjaGFuZ2UgdGhlIGFuc3dlci5cbiAgICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBXYWl0aW5nICR7dHRsfSBzZWNvbmRzIGZvciBETlMgdG8gcHJvcGFnYXRlLi4uYCk7XG4gICAgICAgIGZvciAobGV0IHR0bExlZnQgPSB0dGw7IHR0bExlZnQgPiAwOyB0dGxMZWZ0LS0pIHtcbiAgICAgICAgICAgIGF3YWl0IGRlbGF5KDEwMDApO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYCR7dHRsTGVmdH0gc2Vjb25kcyBsZWZ0Li4uYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5sb2coYERvbmUgd2FpdGluZyBmb3IgRE5TIHRvIHVwZGF0ZS5gKTtcbiAgICB9XG59XG4vKiogS2VlcHMgZXhpc3RpbmcgcmVjb3JkcyAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFkZFJlY29yZCh0eXBlOiBzdHJpbmcsIGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCBwcm94aWVkPzogXCJwcm94aWVkXCIsIHN0YWxlQWZ0ZXIgPSBETlNfUkVGUkVTSF9TVEFMRV9BRlRFUikge1xuICAgIGlmIChrZXkuZW5kc1dpdGgoXCIuXCIpKSBrZXkgPSBrZXkuc2xpY2UoMCwgLTEpO1xuICAgIGxldCB6b25lSWQgPSBhd2FpdCBnZXRab25lSWQoZ2V0Um9vdERvbWFpbihrZXkpKTtcbiAgICBsZXQgcHJldlZhbHVlcyA9IGF3YWl0IGdldFJlY29yZHNSYXcodHlwZSwga2V5KTtcbiAgICBsZXQgZXhpc3RpbmcgPSBwcmV2VmFsdWVzLmZpbmQoeCA9PiB4LmNvbnRlbnQgPT09IHZhbHVlKTtcbiAgICBpZiAoZXhpc3RpbmcgJiYgRGF0ZS5ub3coKSAtIGZyZXNobmVzc1RpbWUoZXhpc3RpbmcuY29tbWVudCkgPCBzdGFsZUFmdGVyKSByZXR1cm47XG5cbiAgICAvLyBTYW1lIHNpbmdsZS1iYXRjaCBmbG93IGFzIHNldFJlY29yZCwgbWludXMgdGhlIGRlbGV0ZXMgKHdlIGtlZXAgc2libGluZyByZWNvcmRzIGhlcmUpLlxuICAgIGxldCB0dGwgPSBETlNfVFRMU2Vjb25kc1t0eXBlIGFzIFwiQVwiXSB8fCA2MDtcbiAgICBsZXQgY29tbWVudCA9IHN0YW1wRnJlc2huZXNzKGV4aXN0aW5nPy5jb21tZW50KTtcbiAgICBjb25zb2xlLmxvZyhgQWRkaW5nICR7dHlwZX0gcmVjb3JkIGZvciAke2tleX0gdG8gJHt2YWx1ZX0gKHByZXZpb3VzbHkgaGFkICR7SlNPTi5zdHJpbmdpZnkocHJldlZhbHVlcy5tYXAoeCA9PiB4LmNvbnRlbnQpKX0pYCk7XG4gICAgYXdhaXQgYmF0Y2hSZWNvcmRzKHpvbmVJZCwge1xuICAgICAgICBwYXRjaGVzOiBleGlzdGluZyA/IFt7IGlkOiBleGlzdGluZy5pZCwgY29tbWVudCB9XSA6IFtdLFxuICAgICAgICBwb3N0czogZXhpc3RpbmcgPyBbXSA6IFt7IHR5cGUsIG5hbWU6IGtleSwgY29udGVudDogdmFsdWUsIHR0bCwgcHJveGllZDogcHJveGllZCA9PT0gXCJwcm94aWVkXCIsIGNvbW1lbnQgfV0sXG4gICAgfSk7XG4gICAgaWYgKGV4aXN0aW5nKSByZXR1cm47XG4gICAgY29uc29sZS5sb2coYFdhaXRpbmcgJHt0dGx9IHNlY29uZHMgZm9yIEROUyB0byBwcm9wYWdhdGUuLi5gKTtcbiAgICBmb3IgKGxldCB0dGxMZWZ0ID0gdHRsOyB0dGxMZWZ0ID4gMDsgdHRsTGVmdC0tKSB7XG4gICAgICAgIGF3YWl0IGRlbGF5KDEwMDApO1xuICAgICAgICBjb25zb2xlLmxvZyhgJHt0dGxMZWZ0fSBzZWNvbmRzIGxlZnQuLi5gKTtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYERvbmUgd2FpdGluZyBmb3IgRE5TIHRvIHVwZGF0ZS5gKTtcbn1cbiJdfQ==
178
+ /* _JS_SOURCE_HASH = "c5c967d2080f9203936cb6843161d9d1428d624e422b935a1330611449b6cd7a"; */
@@ -0,0 +1,130 @@
1
+ "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
+ //exports.getFreshHTTPSCert = exports.hostServer = void 0;
7
+ const os_1 = __importDefault(require("os"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const SocketFunction_1 = require("socket-function/SocketFunction");
10
+ const misc_1 = require("socket-function/src/misc");
11
+ const batching_1 = require("socket-function/src/batching");
12
+ const networking_1 = require("socket-function/src/networking");
13
+ const logColors_1 = require("socket-function/src/formatting/logColors");
14
+ const certs_1 = require("./certs");
15
+ const httpsCerts_1 = require("./httpsCerts");
16
+ const dns_1 = require("./dns");
17
+ // Renew somewhere randomly between 40% and 60% of the way through the cert lifetime. The random threshold staggers parallel processes on the same machine, so usually one process renews early, and the others see the renewed cert on disk (we re-read the disk before every renewal check) and never renew themselves.
18
+ const RENEW_THRESHOLD_MIN = 0.4;
19
+ const RENEW_THRESHOLD_MAX = 0.6;
20
+ const CERT_CHECK_INTERVAL = misc_1.timeInMinute * 15;
21
+ // One threshold per process, so a process is consistently early or late relative to its siblings
22
+ const renewThreshold = RENEW_THRESHOLD_MIN + Math.random() * (RENEW_THRESHOLD_MAX - RENEW_THRESHOLD_MIN);
23
+ /** Hosts a SocketFunction server on a real domain, with an automatically created and renewed Let's Encrypt HTTPS certificate (cached in the home folder, shared between processes on the machine). Expose your controllers (and any RequireController setup) before calling this. Returns the mounted nodeId. */
24
+ async function hostServer(config) {
25
+ let { domain, port } = config;
26
+ // The identity CA always lives on the root domain (nodeIds are threadHash.machineHash.root.tld)
27
+ let rootDomain = domain.split(".").slice(-2).join(".");
28
+ await (0, certs_1.loadIdentityCA)(rootDomain);
29
+ if (config.setDNSRecord) {
30
+ let ip = config.publicIp || await (0, networking_1.getExternalIP)();
31
+ await (0, dns_1.setRecord)("A", domain, ip);
32
+ }
33
+ let keyCert = await getFreshHTTPSCert(domain);
34
+ let certListeners = [];
35
+ void runCertRenewalLoop(domain, newKeyCert => {
36
+ keyCert = newKeyCert;
37
+ for (let listener of certListeners) {
38
+ listener(newKeyCert);
39
+ }
40
+ });
41
+ let nodeId = await SocketFunction_1.SocketFunction.mount({
42
+ public: true,
43
+ autoForwardPort: true,
44
+ port,
45
+ ...(0, certs_1.getThreadKeyCert)(rootDomain),
46
+ SNICerts: {
47
+ [domain]: callback => {
48
+ callback(keyCert);
49
+ certListeners.push(callback);
50
+ },
51
+ [(0, certs_1.getOwnMachineId)(rootDomain) + "." + rootDomain]: async (callback) => {
52
+ let threadCert = await (0, certs_1.getThreadKeyCert)(rootDomain);
53
+ callback({
54
+ key: threadCert.key,
55
+ cert: threadCert.cert,
56
+ });
57
+ },
58
+ },
59
+ allowHostnames: config.allowHostnames,
60
+ });
61
+ console.log((0, logColors_1.magenta)(`Hosting https://${domain}:${port} (nodeId ${nodeId})`));
62
+ return nodeId;
63
+ }
64
+ exports.hostServer = hostServer;
65
+ function getCertDiskPath(domain) {
66
+ return os_1.default.homedir() + `/httpscert_${domain}.json`;
67
+ }
68
+ function readCertFromDisk(domain) {
69
+ try {
70
+ return JSON.parse(fs_1.default.readFileSync(getCertDiskPath(domain), "utf8"));
71
+ }
72
+ catch (_a) {
73
+ return undefined;
74
+ }
75
+ }
76
+ function getRenewTime(certPem, threshold) {
77
+ let certObj = (0, httpsCerts_1.parseCert)(certPem);
78
+ let start = +new Date(certObj.validity.notBefore);
79
+ let end = +new Date(certObj.validity.notAfter);
80
+ return start + (end - start) * threshold;
81
+ }
82
+ /** Returns the cached HTTPS cert for the domain, creating/renewing it first if it is past this process's renewal threshold. Reads the disk cache on every call, so a renewal done by a parallel process is picked up instead of renewing again. */
83
+ async function getFreshHTTPSCert(domain) {
84
+ let keyCert = readCertFromDisk(domain);
85
+ if (keyCert && getRenewTime(keyCert.cert, renewThreshold) > Date.now()) {
86
+ return keyCert;
87
+ }
88
+ if (keyCert) {
89
+ console.log((0, logColors_1.magenta)(`HTTPS cert for ${domain} is past ${(renewThreshold * 100).toFixed(0)}% of its lifetime, renewing`));
90
+ }
91
+ else {
92
+ console.log((0, logColors_1.magenta)(`No HTTPS cert on disk for ${domain}, creating one`));
93
+ }
94
+ let accountKey = await (0, httpsCerts_1.getAccountKey)(domain);
95
+ try {
96
+ keyCert = await (0, httpsCerts_1.generateCert)({ accountKey, domain, altDomains: ["*." + domain] });
97
+ }
98
+ catch (e) {
99
+ if (String(e).includes("authorization must be pending")) {
100
+ // Another process is mid-renewal. Wait for it to finish, then re-check the disk.
101
+ console.log(`Certificate authorization is pending in another process, waiting 2 minutes`);
102
+ await (0, batching_1.delay)(misc_1.timeInMinute * 2);
103
+ return await getFreshHTTPSCert(domain);
104
+ }
105
+ throw e;
106
+ }
107
+ fs_1.default.writeFileSync(getCertDiskPath(domain), JSON.stringify({ key: keyCert.key, cert: keyCert.cert }));
108
+ return { key: keyCert.key, cert: keyCert.cert };
109
+ }
110
+ exports.getFreshHTTPSCert = getFreshHTTPSCert;
111
+ async function runCertRenewalLoop(domain, onNewCert) {
112
+ var _a;
113
+ let lastCert = (_a = readCertFromDisk(domain)) === null || _a === void 0 ? void 0 : _a.cert;
114
+ while (true) {
115
+ await (0, batching_1.delay)(CERT_CHECK_INTERVAL);
116
+ try {
117
+ let keyCert = await getFreshHTTPSCert(domain);
118
+ if (keyCert.cert !== lastCert) {
119
+ lastCert = keyCert.cert;
120
+ console.log((0, logColors_1.magenta)(`HTTPS cert for ${domain} updated, applying to running server`));
121
+ onNewCert(keyCert);
122
+ }
123
+ }
124
+ catch (e) {
125
+ console.error(`Failed to check/renew HTTPS cert for ${domain}`, e);
126
+ }
127
+ }
128
+ }
129
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdFNlcnZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImhvc3RTZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsNENBQW9CO0FBQ3BCLDRDQUFvQjtBQUNwQixtRUFBZ0U7QUFDaEUsbURBQXdEO0FBQ3hELDJEQUFxRDtBQUNyRCwrREFBK0Q7QUFDL0Qsd0VBQW1FO0FBQ25FLG1DQUE0RTtBQUM1RSw2Q0FBc0U7QUFDdEUsK0JBQWtDO0FBRWxDLHlUQUF5VDtBQUN6VCxNQUFNLG1CQUFtQixHQUFHLEdBQUcsQ0FBQztBQUNoQyxNQUFNLG1CQUFtQixHQUFHLEdBQUcsQ0FBQztBQUNoQyxNQUFNLG1CQUFtQixHQUFHLG1CQUFZLEdBQUcsRUFBRSxDQUFDO0FBRTlDLGlHQUFpRztBQUNqRyxNQUFNLGNBQWMsR0FBRyxtQkFBbUIsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxtQkFBbUIsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO0FBY3pHLGlUQUFpVDtBQUMxUyxLQUFLLFVBQVUsVUFBVSxDQUFDLE1BQXdCO0lBQ3JELElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBQzlCLGdHQUFnRztJQUNoRyxJQUFJLFVBQVUsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2RCxNQUFNLElBQUEsc0JBQWMsRUFBQyxVQUFVLENBQUMsQ0FBQztJQUVqQyxJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN0QixJQUFJLEVBQUUsR0FBRyxNQUFNLENBQUMsUUFBUSxJQUFJLE1BQU0sSUFBQSwwQkFBYSxHQUFFLENBQUM7UUFDbEQsTUFBTSxJQUFBLGVBQVMsRUFBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLENB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QUMsQ0FBQztJQUNwRyxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNwRCxDQUFDO0FBeEJELDhDQXdCQztBQUVELEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxNQUFjLEVBQUUsU0FBMkQ7O0lBQ3pHLElBQUksUUFBUSxHQUFHLE1BQUEsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLDBDQUFFLElBQUksQ0FBQztJQUM5QyxPQUFPLElBQUksRUFBRSxDQUFDO1FBQ1YsTUFBTSxJQUFBLGdCQUFLLEVBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUM7WUFDRCxJQUFJLE9BQU8sR0FBRyxNQUFNLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzlDLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDNUIsUUFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0JBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBQSxtQkFBTyxFQUFDLGtCQUFrQixNQUFNLHNDQUFzQyxDQUFDLENBQUMsQ0FBQztnQkFDckYsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3ZCLENBQUM7UUFDTCxDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNULE9BQU8sQ0FBQyxLQUFLLENBQUMsd0NBQXdDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLENBQUM7SUFDTCxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IFNvY2tldEZ1bmN0aW9uIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9Tb2NrZXRGdW5jdGlvblwiO1xuaW1wb3J0IHsgdGltZUluTWludXRlIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuaW1wb3J0IHsgZGVsYXkgfSBmcm9tIFwic29ja2V0LWZ1bmN0aW9uL3NyYy9iYXRjaGluZ1wiO1xuaW1wb3J0IHsgZ2V0RXh0ZXJuYWxJUCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL25ldHdvcmtpbmdcIjtcbmltcG9ydCB7IG1hZ2VudGEgfSBmcm9tIFwic29ja2V0LWZ1bmN0aW9uL3NyYy9mb3JtYXR0aW5nL2xvZ0NvbG9yc1wiO1xuaW1wb3J0IHsgZ2V0T3duTWFjaGluZUlkLCBnZXRUaHJlYWRLZXlDZXJ0LCBsb2FkSWRlbnRpdHlDQSB9IGZyb20gXCIuL2NlcnRzXCI7XG5pbXBvcnQgeyBnZW5lcmF0ZUNlcnQsIGdldEFjY291bnRLZXksIHBhcnNlQ2VydCB9IGZyb20gXCIuL2h0dHBzQ2VydHNcIjtcbmltcG9ydCB7IHNldFJlY29yZCB9IGZyb20gXCIuL2Ruc1wiO1xuXG4vLyBSZW5ldyBzb21ld2hlcmUgcmFuZG9tbHkgYmV0d2VlbiA0MCUgYW5kIDYwJSBvZiB0aGUgd2F5IHRocm91Z2ggdGhlIGNlcnQgbGlmZXRpbWUuIFRoZSByYW5kb20gdGhyZXNob2xkIHN0YWdnZXJzIHBhcmFsbGVsIHByb2Nlc3NlcyBvbiB0aGUgc2FtZSBtYWNoaW5lLCBzbyB1c3VhbGx5IG9uZSBwcm9jZXNzIHJlbmV3cyBlYXJseSwgYW5kIHRoZSBvdGhlcnMgc2VlIHRoZSByZW5ld2VkIGNlcnQgb24gZGlzayAod2UgcmUtcmVhZCB0aGUgZGlzayBiZWZvcmUgZXZlcnkgcmVuZXdhbCBjaGVjaykgYW5kIG5ldmVyIHJlbmV3IHRoZW1zZWx2ZXMuXG5jb25zdCBSRU5FV19USFJFU0hPTERfTUlOID0gMC40O1xuY29uc3QgUkVORVdfVEhSRVNIT0xEX01BWCA9IDAuNjtcbmNvbnN0IENFUlRfQ0hFQ0tfSU5URVJWQUwgPSB0aW1lSW5NaW51dGUgKiAxNTtcblxuLy8gT25lIHRocmVzaG9sZCBwZXIgcHJvY2Vzcywgc28gYSBwcm9jZXNzIGlzIGNvbnNpc3RlbnRseSBlYXJseSBvciBsYXRlIHJlbGF0aXZlIHRvIGl0cyBzaWJsaW5nc1xuY29uc3QgcmVuZXdUaHJlc2hvbGQgPSBSRU5FV19USFJFU0hPTERfTUlOICsgTWF0aC5yYW5kb20oKSAqIChSRU5FV19USFJFU0hPTERfTUFYIC0gUkVORVdfVEhSRVNIT0xEX01JTik7XG5cbmV4cG9ydCB0eXBlIEhvc3RTZXJ2ZXJDb25maWcgPSB7XG4gICAgLyoqIEZ1bGwgZG9tYWluIHRvIGhvc3Qgb24gKGUuZy4gXCJ0ZXN0c2l0ZS5leGFtcGxlLmNvbVwiKS4gVGhlIEhUVFBTIGNlcnQgaXMgY3JlYXRlZCBmb3IgdGhpcyBkb21haW4gYW5kICouZG9tYWluLCBzbyB1c2luZyBhIHN1YmRvbWFpbiBuZXZlciB0b3VjaGVzIHRoZSByb290IGRvbWFpbiAoYmV5b25kIGl0cyBfYWNtZS1jaGFsbGVuZ2UgVFhUIHJlY29yZCkuICovXG4gICAgZG9tYWluOiBzdHJpbmc7XG4gICAgcG9ydDogbnVtYmVyO1xuXG4gICAgLy8gVE9ETzogRXZlbnR1YWxseSB3ZSBzaG91bGQgc3VwcG9ydCBydW5uaW5nIHdpdGhvdXQgQ2xvdWRmbGFyZSBBUEkgdG9rZW5zLiBJdCdzIGFubm95aW5nIHRob3VnaCBhcyB0aGUgdXNlciB3aWxsIGhhdmUgdG8gY3JlYXRlIGEgc2VsZi1zaWduZWQgY2VydGlmaWNhdGUgYW5kIHRoZW4gdGhleSdsbCBoYXZlIHRvIGdvIHRocm91Z2ggYW5kIHRydXN0IGl0IGV2ZXJ5d2hlcmUsIGFuZCBhIGxvdCBvZiB0aGUgc3R1ZmYgaXMgdHJhbnNwYXJlbnQsIGFuZCBzbyBpdCdsbCBoYXZlIHRvIGJlIG5vbi10cmFuc3BhcmVudCwgZ2V0dGluZyB0aGUgdXNlciB0byBnbyB0byB0aGUgcGFnZSB0aGF0IG93bnMgdGhlIGRvbWFpbiBhbmQgdHJ1c3QgaXQgZnJvbSB0aGVyZS4gSXQncyBtdWNoIGJldHRlciBqdXN0IG1ha2UgYSBDbG91ZGZsYXJlIGFjY291bnQuIFlvdSBjYW4gYnV5IGEgZG9tYWluIGZvciAkMTUgYSB5ZWFyLCBhbmQgdGhlbiB5b3UgY2FuIHVzZSBpdCBmb3IgR2l0SHViIHBhZ2VzIHRvIGhvc3QgeW91ciBvd24gc2l0ZSBhbmQgZG8gYWxsIGtpbmRzIG9mIHRoaW5ncyBqdXN0IGxpa2UgYW55IG90aGVyIHJlYWwgc2l0ZS5cbiAgICAvKiogQ3JlYXRlcyBhbiB1bnByb3hpZWQgQSByZWNvcmQgcG9pbnRpbmcgZG9tYWluIGF0IHRoaXMgbWFjaGluZSAocHVibGljSXAsIG9yIG91ciBkZXRlY3RlZCBleHRlcm5hbCBJUCkgKi9cbiAgICBzZXRETlNSZWNvcmQ/OiBib29sZWFuO1xuICAgIHB1YmxpY0lwPzogc3RyaW5nO1xuICAgIGFsbG93SG9zdG5hbWVzPzogc3RyaW5nW107XG59O1xuXG4vKiogSG9zdHMgYSBTb2NrZXRGdW5jdGlvbiBzZXJ2ZXIgb24gYSByZWFsIGRvbWFpbiwgd2l0aCBhbiBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQgYW5kIHJlbmV3ZWQgTGV0J3MgRW5jcnlwdCBIVFRQUyBjZXJ0aWZpY2F0ZSAoY2FjaGVkIGluIHRoZSBob21lIGZvbGRlciwgc2hhcmVkIGJldHdlZW4gcHJvY2Vzc2VzIG9uIHRoZSBtYWNoaW5lKS4gRXhwb3NlIHlvdXIgY29udHJvbGxlcnMgKGFuZCBhbnkgUmVxdWlyZUNvbnRyb2xsZXIgc2V0dXApIGJlZm9yZSBjYWxsaW5nIHRoaXMuIFJldHVybnMgdGhlIG1vdW50ZWQgbm9kZUlkLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhvc3RTZXJ2ZXIoY29uZmlnOiBIb3N0U2VydmVyQ29uZmlnKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBsZXQgeyBkb21haW4sIHBvcnQgfSA9IGNvbmZpZztcbiAgICAvLyBUaGUgaWRlbnRpdHkgQ0EgYWx3YXlzIGxpdmVzIG9uIHRoZSByb290IGRvbWFpbiAobm9kZUlkcyBhcmUgdGhyZWFkSGFzaC5tYWNoaW5lSGFzaC5yb290LnRsZClcbiAgICBsZXQgcm9vdERvbWFpbiA9IGRvbWFpbi5zcGxpdChcIi5cIikuc2xpY2UoLTIpLmpvaW4oXCIuXCIpO1xuICAgIGF3YWl0IGxvYWRJZGVudGl0eUNBKHJvb3REb21haW4pO1xuXG4gICAgaWYgKGNvbmZpZy5zZXRETlNSZWNvcmQpIHtcbiAgICAgICAgbGV0IGlwID0gY29uZmlnLnB1YmxpY0lwIHx8IGF3YWl0IGdldEV4dGVybmFsSVAoKTtcbiAgICAgICAgYXdhaXQgc2V0UmVjb3JkKFwiQVwiLCBkb21haW4sIGlwKTtcbiAgICB9XG5cbiAgICBsZXQga2V5Q2VydCA9IGF3YWl0IGdldEZyZXNoSFRUUFNDZXJ0KGRvbWFpbik7XG4gICAgbGV0IGNlcnRMaXN0ZW5lcnM6ICgodmFsdWU6IHsga2V5OiBzdHJpbmc7IGNlcnQ6IHN0cmluZyB9KSA9PiB2b2lkKVtdID0gW107XG4gICAgdm9pZCBydW5DZXJ0UmVuZXdhbExvb3AoZG9tYWluLCBuZXdLZXlDZXJ0ID0+IHtcbiAgICAgICAga2V5Q2VydCA9IG5ld0tleUNlcnQ7XG4gICAgICAgIGZvciAobGV0IGxpc3RlbmVyIG9mIGNlcnRMaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGxpc3RlbmVyKG5ld0tleUNlcnQpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBsZXQgbm9kZUlkID0gYXdhaXQgU29ja2V0RnVuY3Rpb24ubW91bnQoe1xuICAgICAgICBwdWJsaWM6IHRydWUsXG4gICAgICAgIGF1dG9Gb3J3YXJkUG9ydDogdHJ1ZSxcbiAgICAgICAgcG9ydCxcbiAgICAgICAgLi4uZ2V0VGhyZWFkS2V5Q2VydChyb290RG9tYWluKSxcbiAgICAgICAgU05JQ2VydHM6IHtcbiAgICAgICAgICAgIFtkb21haW5dOiBjYWxsYmFjayA9PiB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soa2V5Q2VydCk7XG4gICAgICAgICAgICAgICAgY2VydExpc3RlbmVycy5wdXNoKGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBbZ2V0T3duTWFjaGluZUlkKHJvb3REb21haW4pICsgXCIuXCIgKyByb290RG9tYWluXTogYXN5bmMgY2FsbGJhY2sgPT4ge1xuICAgICAgICAgICAgICAgIGxldCB0aHJlYWRDZXJ0ID0gYXdhaXQgZ2V0VGhyZWFkS2V5Q2VydChyb290RG9tYWluKTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgICAgICAgICAgIGtleTogdGhyZWFkQ2VydC5rZXksXG4gICAgICAgICAgICAgICAgICAgIGNlcnQ6IHRocmVhZENlcnQuY2VydCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGFsbG93SG9zdG5hbWVzOiBjb25maWcuYWxsb3dIb3N0bmFtZXMsXG4gICAgfSk7XG4gICAgY29uc29sZS5sb2cobWFnZW50YShgSG9zdGluZyBodHRwczovLyR7ZG9tYWlufToke3BvcnR9IChub2RlSWQgJHtub2RlSWR9KWApKTtcbiAgICByZXR1cm4gbm9kZUlkO1xufVxuXG5mdW5jdGlvbiBnZXRDZXJ0RGlza1BhdGgoZG9tYWluOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gb3MuaG9tZWRpcigpICsgYC9odHRwc2NlcnRfJHtkb21haW59Lmpzb25gO1xufVxuZnVuY3Rpb24gcmVhZENlcnRGcm9tRGlzayhkb21haW46IHN0cmluZyk6IHsga2V5OiBzdHJpbmc7IGNlcnQ6IHN0cmluZyB9IHwgdW5kZWZpbmVkIHtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoZ2V0Q2VydERpc2tQYXRoKGRvbWFpbiksIFwidXRmOFwiKSkgYXMgeyBrZXk6IHN0cmluZzsgY2VydDogc3RyaW5nIH07XG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxufVxuZnVuY3Rpb24gZ2V0UmVuZXdUaW1lKGNlcnRQZW06IHN0cmluZywgdGhyZXNob2xkOiBudW1iZXIpIHtcbiAgICBsZXQgY2VydE9iaiA9IHBhcnNlQ2VydChjZXJ0UGVtKTtcbiAgICBsZXQgc3RhcnQgPSArbmV3IERhdGUoY2VydE9iai52YWxpZGl0eS5ub3RCZWZvcmUpO1xuICAgIGxldCBlbmQgPSArbmV3IERhdGUoY2VydE9iai52YWxpZGl0eS5ub3RBZnRlcik7XG4gICAgcmV0dXJuIHN0YXJ0ICsgKGVuZCAtIHN0YXJ0KSAqIHRocmVzaG9sZDtcbn1cblxuLyoqIFJldHVybnMgdGhlIGNhY2hlZCBIVFRQUyBjZXJ0IGZvciB0aGUgZG9tYWluLCBjcmVhdGluZy9yZW5ld2luZyBpdCBmaXJzdCBpZiBpdCBpcyBwYXN0IHRoaXMgcHJvY2VzcydzIHJlbmV3YWwgdGhyZXNob2xkLiBSZWFkcyB0aGUgZGlzayBjYWNoZSBvbiBldmVyeSBjYWxsLCBzbyBhIHJlbmV3YWwgZG9uZSBieSBhIHBhcmFsbGVsIHByb2Nlc3MgaXMgcGlja2VkIHVwIGluc3RlYWQgb2YgcmVuZXdpbmcgYWdhaW4uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RnJlc2hIVFRQU0NlcnQoZG9tYWluOiBzdHJpbmcpOiBQcm9taXNlPHsga2V5OiBzdHJpbmc7IGNlcnQ6IHN0cmluZyB9PiB7XG4gICAgbGV0IGtleUNlcnQgPSByZWFkQ2VydEZyb21EaXNrKGRvbWFpbik7XG4gICAgaWYgKGtleUNlcnQgJiYgZ2V0UmVuZXdUaW1lKGtleUNlcnQuY2VydCwgcmVuZXdUaHJlc2hvbGQpID4gRGF0ZS5ub3coKSkge1xuICAgICAgICByZXR1cm4ga2V5Q2VydDtcbiAgICB9XG4gICAgaWYgKGtleUNlcnQpIHtcbiAgICAgICAgY29uc29sZS5sb2cobWFnZW50YShgSFRUUFMgY2VydCBmb3IgJHtkb21haW59IGlzIHBhc3QgJHsocmVuZXdUaHJlc2hvbGQgKiAxMDApLnRvRml4ZWQoMCl9JSBvZiBpdHMgbGlmZXRpbWUsIHJlbmV3aW5nYCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKG1hZ2VudGEoYE5vIEhUVFBTIGNlcnQgb24gZGlzayBmb3IgJHtkb21haW59LCBjcmVhdGluZyBvbmVgKSk7XG4gICAgfVxuICAgIGxldCBhY2NvdW50S2V5ID0gYXdhaXQgZ2V0QWNjb3VudEtleShkb21haW4pO1xuICAgIHRyeSB7XG4gICAgICAgIGtleUNlcnQgPSBhd2FpdCBnZW5lcmF0ZUNlcnQoeyBhY2NvdW50S2V5LCBkb21haW4sIGFsdERvbWFpbnM6IFtcIiouXCIgKyBkb21haW5dIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKFN0cmluZyhlKS5pbmNsdWRlcyhcImF1dGhvcml6YXRpb24gbXVzdCBiZSBwZW5kaW5nXCIpKSB7XG4gICAgICAgICAgICAvLyBBbm90aGVyIHByb2Nlc3MgaXMgbWlkLXJlbmV3YWwuIFdhaXQgZm9yIGl0IHRvIGZpbmlzaCwgdGhlbiByZS1jaGVjayB0aGUgZGlzay5cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBDZXJ0aWZpY2F0ZSBhdXRob3JpemF0aW9uIGlzIHBlbmRpbmcgaW4gYW5vdGhlciBwcm9jZXNzLCB3YWl0aW5nIDIgbWludXRlc2ApO1xuICAgICAgICAgICAgYXdhaXQgZGVsYXkodGltZUluTWludXRlICogMik7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZ2V0RnJlc2hIVFRQU0NlcnQoZG9tYWluKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlO1xuICAgIH1cbiAgICBmcy53cml0ZUZpbGVTeW5jKGdldENlcnREaXNrUGF0aChkb21haW4pLCBKU09OLnN0cmluZ2lmeSh7IGtleToga2V5Q2VydC5rZXksIGNlcnQ6IGtleUNlcnQuY2VydCB9KSk7XG4gICAgcmV0dXJuIHsga2V5OiBrZXlDZXJ0LmtleSwgY2VydDoga2V5Q2VydC5jZXJ0IH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1bkNlcnRSZW5ld2FsTG9vcChkb21haW46IHN0cmluZywgb25OZXdDZXJ0OiAoa2V5Q2VydDogeyBrZXk6IHN0cmluZzsgY2VydDogc3RyaW5nIH0pID0+IHZvaWQpIHtcbiAgICBsZXQgbGFzdENlcnQgPSByZWFkQ2VydEZyb21EaXNrKGRvbWFpbik/LmNlcnQ7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgYXdhaXQgZGVsYXkoQ0VSVF9DSEVDS19JTlRFUlZBTCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsZXQga2V5Q2VydCA9IGF3YWl0IGdldEZyZXNoSFRUUFNDZXJ0KGRvbWFpbik7XG4gICAgICAgICAgICBpZiAoa2V5Q2VydC5jZXJ0ICE9PSBsYXN0Q2VydCkge1xuICAgICAgICAgICAgICAgIGxhc3RDZXJ0ID0ga2V5Q2VydC5jZXJ0O1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKG1hZ2VudGEoYEhUVFBTIGNlcnQgZm9yICR7ZG9tYWlufSB1cGRhdGVkLCBhcHBseWluZyB0byBydW5uaW5nIHNlcnZlcmApKTtcbiAgICAgICAgICAgICAgICBvbk5ld0NlcnQoa2V5Q2VydCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEZhaWxlZCB0byBjaGVjay9yZW5ldyBIVFRQUyBjZXJ0IGZvciAke2RvbWFpbn1gLCBlKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiJdfQ==
130
+ /* _JS_SOURCE_HASH = "dd72b24e2faa495eba5199defbf9837017396303bc956d42151bc91c03df21a3"; */