From 804978c8d2dce2e46cf1aca7e07ab894e22673ac Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 11 Oct 2023 00:17:38 -0400 Subject: [PATCH 01/34] feat: implement a nodes list for clients --- src/index.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 4729a1a..8ec5e97 100644 --- a/src/index.js +++ b/src/index.js @@ -12,6 +12,8 @@ class Saturn { * @param {string} [opts.cdnURL=saturn.ms] * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] + * @param {string} [opts.orchUrl] + * @param {import('./utils/storage.js').Storage} [opts.storage] */ constructor (opts = {}) { this.opts = Object.assign({}, { @@ -19,15 +21,21 @@ class Saturn { cdnURL: 'saturn.ms', logURL: 'https://twb3qukm2i654i3tnvx36char40aymqq.lambda-url.us-west-2.on.aws/', connectTimeout: 5_000, - downloadTimeout: 0 + downloadTimeout: 0, + orchUrl: 'https://orchestrator.strn.pl/nodes?maxNodes=100' }, opts) this.logs = [] + this.storage = this.opts.storage + this.nodes = [] + this.nodesListKey = 'saturn-nodes' this.reportingLogs = process?.env?.NODE_ENV !== 'development' this.hasPerformanceAPI = typeof window !== 'undefined' && window?.performance if (this.reportingLogs && this.hasPerformanceAPI) { this._monitorPerformanceBuffer() } + + this._loadNodes(this.opts) } /** @@ -272,6 +280,63 @@ class Saturn { performance.clearResourceTimings() } } + + getNodes () { + return this.nodes + } + + _setNodes (nodes) { + this.nodes = nodes + } + + async _loadNodes (opts) { + let origin = opts.orchUrl + + let cachedNodesList + if (this.storage && this.storage.check()) { + cachedNodesList = this.storage.get(this.nodesListKey) + } + + if (!origin.startsWith('http')) { + origin = `https://${origin}` + } + + const url = new URL(origin) + const controller = new AbortController() + const options = Object.assign({}, { method: 'GET' }, this.opts) + + const connectTimeout = setTimeout(() => { + controller.abort() + }, options.connectTimeout) + + const orchestatorResponse = await fetch(url.href, { signal: controller.signal, ...options }) + const orchNodesList = orchestatorResponse.json() + clearTimeout(connectTimeout) + + // This promise races fetching nodes list from the orchestrator and + // and the provided storage object (localStorage, sessionStorage, etc.) + // to insure we have a fallback set as quick as possible + let result + if (cachedNodesList) { + result = await Promise.race([orchNodesList, cachedNodesList]) + } else { + result = await orchNodesList + } + + let nodes + // if the orchestrator responds first then always refresh and ignore the cached list. + if (result === await orchNodesList) { + nodes = result + this.nodes = nodes + } else { + nodes = result + this.nodes = nodes && JSON.parse(nodes) + // We still want to retrieve the latest list from the orchestrator and update the cache. + nodes = await orchNodesList + this._setNodes(nodes) + } + cachedNodesList && this.storage.set(this.nodesListKey, JSON.stringify(nodes)) + } } export default Saturn From f4d1844bd35834f89413f60a9c936d27a9e043ed Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 11 Oct 2023 00:18:06 -0400 Subject: [PATCH 02/34] feat: implement a storage interface using indexedDb --- src/utils/storage.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/utils/storage.js diff --git a/src/utils/storage.js b/src/utils/storage.js new file mode 100644 index 0000000..aab80df --- /dev/null +++ b/src/utils/storage.js @@ -0,0 +1,36 @@ +import { openDB } from 'idb' + +const DEFAULT_IDB_VERSION = 1 +const DEFAULT_IDB_STORAGE_NAME = 'saturn-db' +const DEFAULT_SATURN_STORAGE_NAME = 'saturn-client' + +/** + * @typedef {object} Storage + * @property {function():boolean} check - Checks if the provided Storage is accessible + * @property {function(string):Promise} get - Retrieves the value associated with the key. + * @property {function(string,any):Promise} set - Sets a new value for the key. + * @property {function(string):Promise} delete - Deletes the value associated with the key. + */ + +/** + * @function indexedDbStorage + * @returns {Storage} + */ +export function indexedDbStorage () { + const indexedDbExists = window?.indexedDB + let dbPromise + if (indexedDbExists) { + dbPromise = openDB(DEFAULT_IDB_STORAGE_NAME, DEFAULT_IDB_VERSION, { + upgrade (db) { + db.createObjectStore(DEFAULT_SATURN_STORAGE_NAME) + } + }) + } + + return { + check: () => Boolean(indexedDbExists), + get: async (key) => indexedDbExists && (await dbPromise).get(DEFAULT_SATURN_STORAGE_NAME, key), + set: async (key, value) => indexedDbExists && (await dbPromise).put(DEFAULT_SATURN_STORAGE_NAME, value, key), + delete: async (key) => indexedDbExists && (await dbPromise).delete(DEFAULT_SATURN_STORAGE_NAME, key) + } +} From 894d16d4ab1aa676e4edee096ae1e8c285468f62 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 11 Oct 2023 00:18:19 -0400 Subject: [PATCH 03/34] feat: implement a test suite for fallback --- package-lock.json | 1633 ++++++++++++++++++++++++++++++++++++++--- package.json | 2 + test/fallback.spec.js | 109 +++ test/index.spec.js | 4 +- test/test-utils.js | 89 +++ 5 files changed, 1728 insertions(+), 109 deletions(-) create mode 100644 test/fallback.spec.js create mode 100644 test/test-utils.js diff --git a/package-lock.json b/package-lock.json index 84f9b3f..9fccf4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,9 @@ "@ipld/dag-pb": "^2.1.18", "@multiformats/blake2": "^1.0.11", "browser-readablestream-to-it": "^2.0.4", + "idb": "^7.1.1", "ipfs-unixfs-exporter": "https://gitpkg.now.sh/filecoin-saturn/js-ipfs-unixfs/packages/ipfs-unixfs-exporter?build", + "msw": "^1.3.2", "multiformats": "^12.1.1" }, "devDependencies": { @@ -231,6 +233,44 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@mswjs/cookies": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.2.tgz", + "integrity": "sha512-mlN83YSrcFgk7Dm1Mys40DLssI1KdJji2CMKN8eOlBqsTADYzj2+jWzsANsUTFbxDMWPD5e9bfA1RGqBpS3O1g==", + "dependencies": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.17.10", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.17.10.tgz", + "integrity": "sha512-N8x7eSLGcmUFNWZRxT1vsHvypzIRgQYdG0rJey/rZCy6zT/30qDt8Joj7FxzGNLSwXbeZqJOMqDurp7ra4hgbw==", + "dependencies": { + "@open-draft/until": "^1.0.3", + "@types/debug": "^4.1.7", + "@xmldom/xmldom": "^0.8.3", + "debug": "^4.3.3", + "headers-polyfill": "3.2.5", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.2.4", + "web-encoding": "^1.1.5" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@mswjs/interceptors/node_modules/strict-event-emitter": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.8.tgz", + "integrity": "sha512-KDf/ujU8Zud3YaLtMCcTI4xkZlZVIYxTLr+XIULexP+77EEVWixeXroLUXQXiVtH4XH2W7jr/3PT1v3zBuvc3A==", + "dependencies": { + "events": "^3.3.0" + } + }, "node_modules/@multiformats/blake2": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/@multiformats/blake2/-/blake2-1.0.13.tgz", @@ -293,6 +333,11 @@ "node": ">= 8" } }, + "node_modules/@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==" + }, "node_modules/@phenomnomnominal/tsquery": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-4.2.0.tgz", @@ -359,6 +404,19 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/debug": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", + "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/eslint": { "version": "8.4.6", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", @@ -385,6 +443,11 @@ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, + "node_modules/@types/js-levenshtein": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz", + "integrity": "sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==" + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -397,11 +460,24 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/ms": { + "version": "0.7.32", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz", + "integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==" + }, "node_modules/@types/node": { "version": "18.8.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz", "integrity": "sha512-0os9vz6BpGwxGe9LOhgP/ncvYN5Tx1fNcd2TM3rD/aCGBkysb+ZWpXEocG24h6ZzOi13+VB8HndAQFezsSOw1w==" }, + "node_modules/@types/set-cookie-parser": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.4.tgz", + "integrity": "sha512-xCfTC/eL/GmvMC24b42qJpYSTdCIBwWcfskDF80ztXtnU6pKXyvuZP2EConb2K9ps0s7gMhCa0P1foy7wiItMA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", @@ -802,6 +878,14 @@ } } }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -814,6 +898,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "node_modules/acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", @@ -869,11 +959,35 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -882,7 +996,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -893,6 +1006,18 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -945,12 +1070,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", @@ -970,7 +1143,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -1011,6 +1183,29 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -1031,7 +1226,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -1077,7 +1271,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1093,7 +1286,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -1101,6 +1293,48 @@ "node": ">=8" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -1110,11 +1344,40 @@ "node": ">=6.0" } }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", + "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -1124,6 +1387,14 @@ "node": ">=12" } }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -1142,7 +1413,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -1153,8 +1423,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colorette": { "version": "2.0.19", @@ -1183,6 +1452,14 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1201,7 +1478,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -1220,6 +1496,17 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -1269,8 +1556,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/enhanced-resolve": { "version": "5.10.0", @@ -1376,7 +1662,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -2052,11 +2337,23 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2121,6 +2418,28 @@ "reusify": "^1.0.4" } }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2137,7 +2456,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2177,17 +2495,37 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -2220,7 +2558,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -2229,7 +2566,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -2328,6 +2664,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -2340,6 +2687,14 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "node_modules/graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/hamt-sharding": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/hamt-sharding/-/hamt-sharding-3.0.2.tgz", @@ -2357,7 +2712,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -2378,7 +2732,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2399,7 +2752,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2411,7 +2763,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -2422,6 +2773,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/headers-polyfill": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.2.5.tgz", + "integrity": "sha512-tUCGvt191vNSQgttSyJoibR+VO+I6+iCHIUdhzEMJKE+EAL8BwCN7fUOZlY4ofOelNHsK+gEjxB/B+9N3EWtdA==" + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -2497,8 +2888,45 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/interface-blockstore": { "version": "5.2.5", @@ -2621,6 +3049,21 @@ "cborg": "cli.js" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -2633,6 +3076,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -2653,7 +3107,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2692,7 +3145,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -2701,16 +3153,28 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -2718,6 +3182,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -2730,11 +3202,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -2824,6 +3300,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -2942,6 +3443,14 @@ "node": ">= 10.13.0" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-sdsl": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", @@ -3042,12 +3551,32 @@ "node": ">=8" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -3114,6 +3643,14 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3135,8 +3672,63 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/msw": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/msw/-/msw-1.3.2.tgz", + "integrity": "sha512-wKLhFPR+NitYTkQl5047pia0reNGgf0P6a1eTnA5aNlripmiz0sabMvvHcicE8kQ3/gZcI0YiPFWmYfowfm3lA==", + "hasInstallScript": true, + "dependencies": { + "@mswjs/cookies": "^0.2.2", + "@mswjs/interceptors": "^0.17.10", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/js-levenshtein": "^1.1.1", + "chalk": "^4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.2", + "graphql": "^16.8.1", + "headers-polyfill": "3.2.5", + "inquirer": "^8.2.0", + "is-node-process": "^1.2.0", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.7", + "outvariant": "^1.4.0", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.4.3", + "type-fest": "^2.19.0", + "yargs": "^17.3.1" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.4.x <= 5.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/multiformats": { "version": "12.1.1", @@ -3155,6 +3747,11 @@ "node": ">=8.0.0" } }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3167,12 +3764,39 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -3235,6 +3859,20 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -3252,6 +3890,41 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/outvariant": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.0.tgz", + "integrity": "sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==" + }, "node_modules/p-defer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.0.tgz", @@ -3370,6 +4043,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -3389,7 +4067,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -3500,6 +4177,30 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/rechoir": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", @@ -3545,7 +4246,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3597,6 +4297,18 @@ "node": ">=8" } }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3622,6 +4334,14 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3645,11 +4365,18 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -3679,6 +4406,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "node_modules/schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", @@ -3721,6 +4453,11 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" + }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -3768,6 +4505,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3823,11 +4565,23 @@ "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", "dev": true }, + "node_modules/strict-event-emitter": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.4.6.tgz", + "integrity": "sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3869,7 +4623,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3992,11 +4745,26 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -4004,6 +4772,11 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -4019,8 +4792,7 @@ "node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -4089,7 +4861,7 @@ "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true, + "devOptional": true, "peer": true, "bin": { "tsc": "bin/tsc", @@ -4169,6 +4941,23 @@ "punycode": "^2.1.0" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/varint": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", @@ -4187,6 +4976,30 @@ "node": ">=10.13.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, "node_modules/webpack": { "version": "5.74.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", @@ -4312,6 +5125,15 @@ "node": ">=10.13.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4343,6 +5165,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", @@ -4362,7 +5202,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4385,7 +5224,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -4400,7 +5238,6 @@ "version": "17.6.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -4418,7 +5255,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -4614,6 +5450,40 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@mswjs/cookies": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.2.tgz", + "integrity": "sha512-mlN83YSrcFgk7Dm1Mys40DLssI1KdJji2CMKN8eOlBqsTADYzj2+jWzsANsUTFbxDMWPD5e9bfA1RGqBpS3O1g==", + "requires": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + } + }, + "@mswjs/interceptors": { + "version": "0.17.10", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.17.10.tgz", + "integrity": "sha512-N8x7eSLGcmUFNWZRxT1vsHvypzIRgQYdG0rJey/rZCy6zT/30qDt8Joj7FxzGNLSwXbeZqJOMqDurp7ra4hgbw==", + "requires": { + "@open-draft/until": "^1.0.3", + "@types/debug": "^4.1.7", + "@xmldom/xmldom": "^0.8.3", + "debug": "^4.3.3", + "headers-polyfill": "3.2.5", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.2.4", + "web-encoding": "^1.1.5" + }, + "dependencies": { + "strict-event-emitter": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.8.tgz", + "integrity": "sha512-KDf/ujU8Zud3YaLtMCcTI4xkZlZVIYxTLr+XIULexP+77EEVWixeXroLUXQXiVtH4XH2W7jr/3PT1v3zBuvc3A==", + "requires": { + "events": "^3.3.0" + } + } + } + }, "@multiformats/blake2": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/@multiformats/blake2/-/blake2-1.0.13.tgz", @@ -4665,6 +5535,11 @@ "fastq": "^1.6.0" } }, + "@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==" + }, "@phenomnomnominal/tsquery": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-4.2.0.tgz", @@ -4728,6 +5603,19 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "@types/debug": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", + "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", + "requires": { + "@types/ms": "*" + } + }, "@types/eslint": { "version": "8.4.6", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", @@ -4754,6 +5642,11 @@ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, + "@types/js-levenshtein": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz", + "integrity": "sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==" + }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -4766,11 +5659,24 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/ms": { + "version": "0.7.32", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz", + "integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==" + }, "@types/node": { "version": "18.8.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz", "integrity": "sha512-0os9vz6BpGwxGe9LOhgP/ncvYN5Tx1fNcd2TM3rD/aCGBkysb+ZWpXEocG24h6ZzOi13+VB8HndAQFezsSOw1w==" }, + "@types/set-cookie-parser": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.4.tgz", + "integrity": "sha512-xCfTC/eL/GmvMC24b42qJpYSTdCIBwWcfskDF80ztXtnU6pKXyvuZP2EConb2K9ps0s7gMhCa0P1foy7wiItMA==", + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", @@ -5059,6 +5965,11 @@ "dev": true, "requires": {} }, + "@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==" + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -5071,6 +5982,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", @@ -5110,21 +6027,43 @@ "dev": true, "requires": {} }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + } + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -5162,12 +6101,37 @@ "es-shim-unscopables": "^1.0.0" } }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", @@ -5187,7 +6151,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -5209,6 +6172,15 @@ "update-browserslist-db": "^1.0.9" } }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -5229,7 +6201,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -5256,7 +6227,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -5266,30 +6236,81 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } } } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", + "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==" + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + }, "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" + }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -5305,7 +6326,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -5313,8 +6333,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "colorette": { "version": "2.0.19", @@ -5340,6 +6359,11 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -5355,7 +6379,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -5366,6 +6389,14 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "requires": { + "clone": "^1.0.2" + } + }, "define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -5403,8 +6434,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "enhanced-resolve": { "version": "5.10.0", @@ -5488,8 +6518,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-string-regexp": { "version": "4.0.0", @@ -5967,8 +6996,17 @@ "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } }, "fast-deep-equal": { "version": "3.1.3", @@ -6027,6 +7065,21 @@ "reusify": "^1.0.4" } }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + } + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -6040,7 +7093,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -6071,17 +7123,30 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "function.prototype.name": { "version": "1.1.5", @@ -6104,14 +7169,12 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -6180,6 +7243,14 @@ "slash": "^3.0.0" } }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -6192,6 +7263,11 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==" + }, "hamt-sharding": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/hamt-sharding/-/hamt-sharding-3.0.2.tgz", @@ -6205,7 +7281,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -6219,8 +7294,7 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-property-descriptors": { "version": "1.0.0", @@ -6234,18 +7308,39 @@ "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "requires": { "has-symbols": "^1.0.2" } }, + "headers-polyfill": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.2.5.tgz", + "integrity": "sha512-tUCGvt191vNSQgttSyJoibR+VO+I6+iCHIUdhzEMJKE+EAL8BwCN7fUOZlY4ofOelNHsK+gEjxB/B+9N3EWtdA==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -6299,8 +7394,41 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "dependencies": { + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } }, "interface-blockstore": { "version": "5.2.5", @@ -6390,6 +7518,15 @@ } } }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -6399,6 +7536,14 @@ "has-bigints": "^1.0.1" } }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -6412,8 +7557,7 @@ "is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, "is-core-module": { "version": "2.10.0", @@ -6436,35 +7580,49 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, + "is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-number-object": { "version": "1.0.7", @@ -6521,6 +7679,19 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "requires": { + "which-typed-array": "^1.1.11" + } + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -6618,6 +7789,11 @@ "supports-color": "^8.0.0" } }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==" + }, "js-sdsl": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", @@ -6697,12 +7873,26 @@ "p-locate": "^4.1.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -6754,6 +7944,11 @@ "mime-db": "1.52.0" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6772,8 +7967,40 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "msw": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/msw/-/msw-1.3.2.tgz", + "integrity": "sha512-wKLhFPR+NitYTkQl5047pia0reNGgf0P6a1eTnA5aNlripmiz0sabMvvHcicE8kQ3/gZcI0YiPFWmYfowfm3lA==", + "requires": { + "@mswjs/cookies": "^0.2.2", + "@mswjs/interceptors": "^0.17.10", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/js-levenshtein": "^1.1.1", + "chalk": "^4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.2", + "graphql": "^16.8.1", + "headers-polyfill": "3.2.5", + "inquirer": "^8.2.0", + "is-node-process": "^1.2.0", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.7", + "outvariant": "^1.4.0", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.4.3", + "type-fest": "^2.19.0", + "yargs": "^17.3.1" + }, + "dependencies": { + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==" + } + } }, "multiformats": { "version": "12.1.1", @@ -6785,6 +8012,11 @@ "resolved": "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", "integrity": "sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==" }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6797,12 +8029,25 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, "object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -6847,6 +8092,14 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -6861,6 +8114,32 @@ "word-wrap": "^1.2.3" } }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" + }, + "outvariant": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.0.tgz", + "integrity": "sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==" + }, "p-defer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.0.tgz", @@ -6937,6 +8216,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -6952,8 +8236,7 @@ "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pkg-dir": { "version": "4.2.0", @@ -7024,6 +8307,24 @@ "safe-buffer": "^5.1.0" } }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, "rechoir": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", @@ -7053,8 +8354,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, "requireindex": { "version": "1.2.0", @@ -7088,6 +8388,15 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -7103,6 +8412,11 @@ "glob": "^7.1.3" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7112,11 +8426,18 @@ "queue-microtask": "^1.2.2" } }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-regex-test": { "version": "1.0.0", @@ -7129,6 +8450,11 @@ "is-regex": "^1.1.4" } }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", @@ -7158,6 +8484,11 @@ "randombytes": "^2.1.0" } }, + "set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" + }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -7193,6 +8524,11 @@ "object-inspect": "^1.9.0" } }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7242,11 +8578,23 @@ "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", "dev": true }, + "strict-event-emitter": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.4.6.tgz", + "integrity": "sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7279,7 +8627,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -7348,15 +8695,32 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -7372,8 +8736,7 @@ "tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "tsutils": { "version": "3.21.0", @@ -7421,7 +8784,7 @@ "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true, + "devOptional": true, "peer": true }, "uint8arraylist": { @@ -7471,6 +8834,23 @@ "punycode": "^2.1.0" } }, + "util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "varint": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", @@ -7486,6 +8866,28 @@ "graceful-fs": "^4.1.2" } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "requires": { + "defaults": "^1.0.3" + } + }, + "web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "requires": { + "@zxing/text-encoding": "0.9.0", + "util": "^0.12.3" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, "webpack": { "version": "5.74.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", @@ -7562,6 +8964,15 @@ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7584,6 +8995,18 @@ "is-symbol": "^1.0.3" } }, + "which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", @@ -7600,7 +9023,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7616,8 +9038,7 @@ "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yallist": { "version": "4.0.0", @@ -7629,7 +9050,6 @@ "version": "17.6.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", - "dev": true, "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -7643,8 +9063,7 @@ "yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" }, "yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index 0970456..9001fe4 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,9 @@ "@ipld/dag-pb": "^2.1.18", "@multiformats/blake2": "^1.0.11", "browser-readablestream-to-it": "^2.0.4", + "idb": "^7.1.1", "ipfs-unixfs-exporter": "https://gitpkg.now.sh/filecoin-saturn/js-ipfs-unixfs/packages/ipfs-unixfs-exporter?build", + "msw": "^1.3.2", "multiformats": "^12.1.1" }, "devDependencies": { diff --git a/test/fallback.spec.js b/test/fallback.spec.js new file mode 100644 index 0000000..f9ddcb2 --- /dev/null +++ b/test/fallback.spec.js @@ -0,0 +1,109 @@ +import assert from 'node:assert/strict' +import { describe, mock, test } from 'node:test' + +import Saturn from '#src/index.js' +import { generateNodes, getMockServer, mockOrchHandler } from './test-utils.js' + +const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' +const TEST_NODES_LIST_KEY = 'saturn-nodes' +const TEST_ORIGIN_DOMAIN = 'saturn.ms' + +describe('Client Fallback', () => { + test('Nodes are loaded from the orchestrator if no storage is passed', async (t) => { + const handlers = [ + mockOrchHandler(2, TEST_DEFAULT_ORCH, TEST_ORIGIN_DOMAIN) + ] + const server = getMockServer(handlers) + server.listen() + + const expectedNodes = generateNodes(2, TEST_ORIGIN_DOMAIN) + + // No Storage is injected + const saturn = new Saturn() + const mockOpts = { orchUrl: TEST_DEFAULT_ORCH } + + await saturn._loadNodes(mockOpts) + + // Assert that the loaded nodes are the expected ones. + assert.deepEqual(saturn.nodes, expectedNodes) + + server.close() + }) + + test('Storage is invoked correctly when supplied', async (t) => { + const handlers = [ + mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms') + ] + const server = getMockServer(handlers) + server.listen() + + const expectedNodes = generateNodes(2, TEST_ORIGIN_DOMAIN) + + // Mocking storage object + const mockStorage = { + check: () => true, + get: async (key) => { return null }, + set: async (key, value) => { return null } + } + t.mock.method(mockStorage, 'get') + t.mock.method(mockStorage, 'check') + t.mock.method(mockStorage, 'set') + + const saturn = new Saturn({ storage: mockStorage }) + + // Mocking options + const mockOpts = { orchUrl: TEST_DEFAULT_ORCH } + + await saturn._loadNodes(mockOpts) + + // Assert that all the storage methods were called twice. + assert.strictEqual(mockStorage.check.mock.calls.length, 2) + assert.strictEqual(mockStorage.set.mock.calls.length, 2) + assert.strictEqual(mockStorage.get.mock.calls.length, 2) + + // Assert that the set method was invoked with the correct params. + assert.deepStrictEqual(mockStorage.set.mock.calls[0].arguments, [TEST_NODES_LIST_KEY, JSON.stringify(expectedNodes)]) + + assert.deepEqual(saturn.nodes, expectedNodes) + + server.close() + mock.reset() + }) + + test('Storage is loaded first when the orch is slower', async (t) => { + const handlers = [ + mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms', 4000) + ] + const server = getMockServer(handlers) + server.listen() + + const expectedNodes = generateNodes(4, TEST_ORIGIN_DOMAIN) + + // Mocking storage object + const mockStorage = { + check: () => true, + get: async (key) => { return Promise.resolve(JSON.stringify(expectedNodes.slice(2, 4))) }, + set: async (key, value) => { return null } + } + t.mock.method(mockStorage, 'get') + t.mock.method(mockStorage, 'check') + t.mock.method(mockStorage, 'set') + + const saturn = new Saturn({ storage: mockStorage }) + + // Mocking options + const mockOpts = { orchUrl: TEST_DEFAULT_ORCH } + + await saturn._loadNodes(mockOpts) + + // Assert that all the storage methods were called twice. + assert.strictEqual(mockStorage.check.mock.calls.length, 2) + assert.strictEqual(mockStorage.set.mock.calls.length, 2) + assert.strictEqual(mockStorage.get.mock.calls.length, 2) + + // Assert that the set method was invoked with the correct params. + assert.deepStrictEqual(mockStorage.set.mock.calls[0].arguments, [TEST_NODES_LIST_KEY, JSON.stringify(expectedNodes.slice(0, 2))]) + + assert.deepEqual(saturn.nodes, expectedNodes.slice(0, 2)) + }) +}) diff --git a/test/index.spec.js b/test/index.spec.js index 12fef35..b21b622d 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -9,7 +9,7 @@ const TEST_CID = 'QmXjYBY478Cno4jzdCcPy4NcJYFrwHZ51xaCP8vUwN9MGm' describe('Saturn client', () => { describe('constructor', () => { it('should work w/o custom client ID', () => { - new Saturn() + new Saturn() // eslint-disable-line }) it('should work with custom client ID', () => { @@ -61,7 +61,7 @@ describe('Saturn client', () => { client.reportingLogs = true it('should create a log on fetch success', async () => { - for await (const _ of client.fetchContent(TEST_CID)) {} + for await (const _ of client.fetchContent(TEST_CID)) {} // eslint-disable-line const log = client.logs.pop() diff --git a/test/test-utils.js b/test/test-utils.js new file mode 100644 index 0000000..e7d6a10 --- /dev/null +++ b/test/test-utils.js @@ -0,0 +1,89 @@ + +// mocks.js + +import { rest } from 'msw' +import { setupServer } from 'msw/node' +const HTTP_STATUS_OK = 200 + +/** + * + * @typedef {object} Node + * @property {string} ip + * @property {string} weight + * @property {number} distance + * @property {string} url + */ + +/** + * Generates sets of nodes based on orchestrator response. Nodes are generated deteriministically. + * + * @param {integer} count + * @param {string} originDomain - saturn origin domain + * @returns {[]Node} + */ +export function generateNodes (count, originDomain) { + const nodes = [] + for (let i = 0; i < count; i++) { + const nodeIp = `node${i}` + const node = { + ip: nodeIp, + weight: i, + distance: 100, + url: `https://${nodeIp}.${originDomain}` + } + nodes.push(node) + } + return nodes +} + +/** + * Generates a mock handler to mimick Saturn's orchestrator /nodes endpoint. + * + * @param {integer} count - amount of nodes + * @param {string} orchUrl - orchestratorUrl + * @param {string} originDomain - saturn origin domain + * @param {number} delay - request delay in ms + * @returns {RestHandler} + */ +export function mockOrchHandler (count, orchUrl, originDomain, delay) { + if (!orchUrl.startsWith('http')) { + orchUrl = `https://${orchUrl}` + } + + const nodes = generateNodes(count, originDomain) + return rest.get(orchUrl, (req, res, ctx) => { + return res( + ctx.status(HTTP_STATUS_OK), + ctx.delay(delay || 0), + ctx.json(nodes) + ) + }) +} + +/** + * Generates mock servers to act as L1 nodes. + * + * @param {integer} count - amount of nodes to mock + * @param {string} originDomain - saturn origin domain. + * @returns {RestHandler[]} + */ +export function mockNodesHandlers (count, originDomain) { + const nodes = generateNodes(count, originDomain) + + const handlers = nodes.map((node) => { + return rest.get(node.url, (req, res, ctx) => { + return res( + ctx.status(HTTP_STATUS_OK), + ctx.json({ data: 'Test Block' }) + ) + }) + }) + return handlers +} + +/** + * @param {Function[]} handlers - amount of nodes to mock + */ +export function getMockServer (handlers) { + return setupServer(...handlers) +} From 7009c7a9f28145c256d2a75b197ad40b773caa02 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 11 Oct 2023 10:27:07 -0400 Subject: [PATCH 04/34] fix: remove unused code --- src/index.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/index.js b/src/index.js index 8ec5e97..e7fd5c1 100644 --- a/src/index.js +++ b/src/index.js @@ -281,14 +281,6 @@ class Saturn { } } - getNodes () { - return this.nodes - } - - _setNodes (nodes) { - this.nodes = nodes - } - async _loadNodes (opts) { let origin = opts.orchUrl @@ -333,7 +325,7 @@ class Saturn { this.nodes = nodes && JSON.parse(nodes) // We still want to retrieve the latest list from the orchestrator and update the cache. nodes = await orchNodesList - this._setNodes(nodes) + this.nodes = nodes } cachedNodesList && this.storage.set(this.nodesListKey, JSON.stringify(nodes)) } From 3336a87607d6c48400597cbc618a87103e757a8b Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 11 Oct 2023 10:50:02 -0400 Subject: [PATCH 05/34] fix: eslint an jsdoc --- .eslintrc | 14 ++++++++++++++ src/index.js | 4 +++- src/utils/storage.js | 2 ++ test/fallback.spec.js | 8 +++++--- test/test-utils.js | 18 +++++++++--------- 5 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 .eslintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..a5041e9 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,14 @@ +{ + "plugins": [ + "jsdoc", + "promise" + ], + "extends": "ipfs", + "parserOptions": { + "sourceType": "module", + "ecmaVersion": "latest" + }, + "rules": { + "jsdoc/no-undefined-types": 1 + }, +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index e7fd5c1..646db75 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,5 @@ +// @ts-check + import { CID } from 'multiformats' import { extractVerifiedContent } from './utils/car.js' @@ -327,7 +329,7 @@ class Saturn { nodes = await orchNodesList this.nodes = nodes } - cachedNodesList && this.storage.set(this.nodesListKey, JSON.stringify(nodes)) + cachedNodesList && this.storage?.set(this.nodesListKey, JSON.stringify(nodes)) } } diff --git a/src/utils/storage.js b/src/utils/storage.js index aab80df..95554f5 100644 --- a/src/utils/storage.js +++ b/src/utils/storage.js @@ -1,3 +1,5 @@ +// @ts-check + import { openDB } from 'idb' const DEFAULT_IDB_VERSION = 1 diff --git a/test/fallback.spec.js b/test/fallback.spec.js index f9ddcb2..fbe39d9 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -1,7 +1,8 @@ + import assert from 'node:assert/strict' import { describe, mock, test } from 'node:test' -import Saturn from '#src/index.js' +import Saturn from '../src/index.js' import { generateNodes, getMockServer, mockOrchHandler } from './test-utils.js' const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' @@ -42,8 +43,9 @@ describe('Client Fallback', () => { // Mocking storage object const mockStorage = { check: () => true, - get: async (key) => { return null }, - set: async (key, value) => { return null } + get: async (key) => null, + set: async (key, value) => null, + delete: async (key) => null } t.mock.method(mockStorage, 'get') t.mock.method(mockStorage, 'check') diff --git a/test/test-utils.js b/test/test-utils.js index e7d6a10..a1132b7 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -1,7 +1,7 @@ -// mocks.js +// @ts-check -import { rest } from 'msw' +import { RestHandler, rest } from 'msw' import { setupServer } from 'msw/node' const HTTP_STATUS_OK = 200 @@ -9,7 +9,7 @@ const HTTP_STATUS_OK = 200 * * @typedef {object} Node * @property {string} ip - * @property {string} weight + * @property {number} weight * @property {number} distance * @property {string} url */ @@ -17,9 +17,9 @@ const HTTP_STATUS_OK = 200 /** * Generates sets of nodes based on orchestrator response. Nodes are generated deteriministically. * - * @param {integer} count + * @param {number} count * @param {string} originDomain - saturn origin domain - * @returns {[]Node} + * @returns {Node[]} */ export function generateNodes (count, originDomain) { const nodes = [] @@ -39,13 +39,13 @@ export function generateNodes (count, originDomain) { /** * Generates a mock handler to mimick Saturn's orchestrator /nodes endpoint. * - * @param {integer} count - amount of nodes + * @param {number} count - amount of nodes * @param {string} orchUrl - orchestratorUrl * @param {string} originDomain - saturn origin domain * @param {number} delay - request delay in ms * @returns {RestHandler} */ -export function mockOrchHandler (count, orchUrl, originDomain, delay) { +export function mockOrchHandler (count, orchUrl, originDomain, delay = 0) { if (!orchUrl.startsWith('http')) { orchUrl = `https://${orchUrl}` } @@ -63,7 +63,7 @@ export function mockOrchHandler (count, orchUrl, originDomain, delay) { /** * Generates mock servers to act as L1 nodes. * - * @param {integer} count - amount of nodes to mock + * @param {number} count - amount of nodes to mock * @param {string} originDomain - saturn origin domain. * @returns {RestHandler[]} */ @@ -82,7 +82,7 @@ export function mockNodesHandlers (count, originDomain) { } /** - * @param {Function[]} handlers - amount of nodes to mock + * @param {RestHandler[]} handlers - amount of nodes to mock */ export function getMockServer (handlers) { return setupServer(...handlers) From 696cd8a90040612f9a45f123b30d37e88f571146 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 11 Oct 2023 11:30:03 -0400 Subject: [PATCH 06/34] fix: formatting and consistency --- src/index.js | 8 ++++---- test/fallback.spec.js | 6 +++--- test/test-utils.js | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/index.js b/src/index.js index 646db75..8097854 100644 --- a/src/index.js +++ b/src/index.js @@ -14,7 +14,7 @@ class Saturn { * @param {string} [opts.cdnURL=saturn.ms] * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] - * @param {string} [opts.orchUrl] + * @param {string} [opts.orchURL] * @param {import('./utils/storage.js').Storage} [opts.storage] */ constructor (opts = {}) { @@ -22,9 +22,9 @@ class Saturn { clientId: randomUUID(), cdnURL: 'saturn.ms', logURL: 'https://twb3qukm2i654i3tnvx36char40aymqq.lambda-url.us-west-2.on.aws/', + orchURL: 'https://orchestrator.strn.pl/nodes?maxNodes=100', connectTimeout: 5_000, - downloadTimeout: 0, - orchUrl: 'https://orchestrator.strn.pl/nodes?maxNodes=100' + downloadTimeout: 0 }, opts) this.logs = [] @@ -284,7 +284,7 @@ class Saturn { } async _loadNodes (opts) { - let origin = opts.orchUrl + let origin = opts.orchURL let cachedNodesList if (this.storage && this.storage.check()) { diff --git a/test/fallback.spec.js b/test/fallback.spec.js index fbe39d9..07d6919 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -21,7 +21,7 @@ describe('Client Fallback', () => { // No Storage is injected const saturn = new Saturn() - const mockOpts = { orchUrl: TEST_DEFAULT_ORCH } + const mockOpts = { orchURL: TEST_DEFAULT_ORCH } await saturn._loadNodes(mockOpts) @@ -54,7 +54,7 @@ describe('Client Fallback', () => { const saturn = new Saturn({ storage: mockStorage }) // Mocking options - const mockOpts = { orchUrl: TEST_DEFAULT_ORCH } + const mockOpts = { orchURL: TEST_DEFAULT_ORCH } await saturn._loadNodes(mockOpts) @@ -94,7 +94,7 @@ describe('Client Fallback', () => { const saturn = new Saturn({ storage: mockStorage }) // Mocking options - const mockOpts = { orchUrl: TEST_DEFAULT_ORCH } + const mockOpts = { orchURL: TEST_DEFAULT_ORCH } await saturn._loadNodes(mockOpts) diff --git a/test/test-utils.js b/test/test-utils.js index a1132b7..37483aa 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -40,18 +40,18 @@ export function generateNodes (count, originDomain) { * Generates a mock handler to mimick Saturn's orchestrator /nodes endpoint. * * @param {number} count - amount of nodes - * @param {string} orchUrl - orchestratorUrl + * @param {string} orchURL - orchestratorUrl * @param {string} originDomain - saturn origin domain * @param {number} delay - request delay in ms * @returns {RestHandler} */ -export function mockOrchHandler (count, orchUrl, originDomain, delay = 0) { - if (!orchUrl.startsWith('http')) { - orchUrl = `https://${orchUrl}` +export function mockOrchHandler (count, orchURL, originDomain, delay = 0) { + if (!orchURL.startsWith('http')) { + orchURL = `https://${orchURL}` } const nodes = generateNodes(count, originDomain) - return rest.get(orchUrl, (req, res, ctx) => { + return rest.get(orchURL, (req, res, ctx) => { return res( ctx.status(HTTP_STATUS_OK), ctx.delay(delay || 0), From a3dec560b219df92fdad04aa65079f427ee877ea Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 11 Oct 2023 11:33:41 -0400 Subject: [PATCH 07/34] fix: indexDbCheck --- src/utils/storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/storage.js b/src/utils/storage.js index 95554f5..0c2954e 100644 --- a/src/utils/storage.js +++ b/src/utils/storage.js @@ -19,7 +19,7 @@ const DEFAULT_SATURN_STORAGE_NAME = 'saturn-client' * @returns {Storage} */ export function indexedDbStorage () { - const indexedDbExists = window?.indexedDB + const indexedDbExists = (typeof window !== 'undefined') && window?.indexedDB let dbPromise if (indexedDbExists) { dbPromise = openDB(DEFAULT_IDB_STORAGE_NAME, DEFAULT_IDB_VERSION, { From 8dec1c79c99f4242abcb421c77c93329adf57121 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 11 Oct 2023 22:40:25 -0400 Subject: [PATCH 08/34] chore: change storage implementation --- package-lock.json | 2 +- src/index.js | 4 ++-- src/utils/storage.js | 38 -------------------------------------- test/fallback.spec.js | 14 ++++---------- 4 files changed, 7 insertions(+), 51 deletions(-) delete mode 100644 src/utils/storage.js diff --git a/package-lock.json b/package-lock.json index 045a70c..ff38489 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9072,4 +9072,4 @@ "dev": true } } -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index c561b22..e4d1ea4 100644 --- a/src/index.js +++ b/src/index.js @@ -18,7 +18,7 @@ class Saturn { * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] * @param {string} [opts.orchURL] - * @param {import('./utils/storage.js').Storage} [opts.storage] + * @param {import('./storage/index.js').Storage} [opts.storage] */ constructor (opts = {}) { this.opts = Object.assign({}, { @@ -308,7 +308,7 @@ class Saturn { let origin = opts.orchURL let cachedNodesList - if (this.storage && this.storage.check()) { + if (this.storage) { cachedNodesList = this.storage.get(this.nodesListKey) } diff --git a/src/utils/storage.js b/src/utils/storage.js deleted file mode 100644 index 0c2954e..0000000 --- a/src/utils/storage.js +++ /dev/null @@ -1,38 +0,0 @@ -// @ts-check - -import { openDB } from 'idb' - -const DEFAULT_IDB_VERSION = 1 -const DEFAULT_IDB_STORAGE_NAME = 'saturn-db' -const DEFAULT_SATURN_STORAGE_NAME = 'saturn-client' - -/** - * @typedef {object} Storage - * @property {function():boolean} check - Checks if the provided Storage is accessible - * @property {function(string):Promise} get - Retrieves the value associated with the key. - * @property {function(string,any):Promise} set - Sets a new value for the key. - * @property {function(string):Promise} delete - Deletes the value associated with the key. - */ - -/** - * @function indexedDbStorage - * @returns {Storage} - */ -export function indexedDbStorage () { - const indexedDbExists = (typeof window !== 'undefined') && window?.indexedDB - let dbPromise - if (indexedDbExists) { - dbPromise = openDB(DEFAULT_IDB_STORAGE_NAME, DEFAULT_IDB_VERSION, { - upgrade (db) { - db.createObjectStore(DEFAULT_SATURN_STORAGE_NAME) - } - }) - } - - return { - check: () => Boolean(indexedDbExists), - get: async (key) => indexedDbExists && (await dbPromise).get(DEFAULT_SATURN_STORAGE_NAME, key), - set: async (key, value) => indexedDbExists && (await dbPromise).put(DEFAULT_SATURN_STORAGE_NAME, value, key), - delete: async (key) => indexedDbExists && (await dbPromise).delete(DEFAULT_SATURN_STORAGE_NAME, key) - } -} diff --git a/test/fallback.spec.js b/test/fallback.spec.js index 07d6919..2776d4c 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -8,7 +8,7 @@ import { generateNodes, getMockServer, mockOrchHandler } from './test-utils.js' const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' const TEST_NODES_LIST_KEY = 'saturn-nodes' const TEST_ORIGIN_DOMAIN = 'saturn.ms' - +const CLIENT_KEY = 'key' describe('Client Fallback', () => { test('Nodes are loaded from the orchestrator if no storage is passed', async (t) => { const handlers = [ @@ -20,7 +20,7 @@ describe('Client Fallback', () => { const expectedNodes = generateNodes(2, TEST_ORIGIN_DOMAIN) // No Storage is injected - const saturn = new Saturn() + const saturn = new Saturn({ clientKey: CLIENT_KEY }) const mockOpts = { orchURL: TEST_DEFAULT_ORCH } await saturn._loadNodes(mockOpts) @@ -42,16 +42,14 @@ describe('Client Fallback', () => { // Mocking storage object const mockStorage = { - check: () => true, get: async (key) => null, set: async (key, value) => null, delete: async (key) => null } t.mock.method(mockStorage, 'get') - t.mock.method(mockStorage, 'check') t.mock.method(mockStorage, 'set') - const saturn = new Saturn({ storage: mockStorage }) + const saturn = new Saturn({ storage: mockStorage, clientKey: CLIENT_KEY }) // Mocking options const mockOpts = { orchURL: TEST_DEFAULT_ORCH } @@ -59,7 +57,6 @@ describe('Client Fallback', () => { await saturn._loadNodes(mockOpts) // Assert that all the storage methods were called twice. - assert.strictEqual(mockStorage.check.mock.calls.length, 2) assert.strictEqual(mockStorage.set.mock.calls.length, 2) assert.strictEqual(mockStorage.get.mock.calls.length, 2) @@ -83,15 +80,13 @@ describe('Client Fallback', () => { // Mocking storage object const mockStorage = { - check: () => true, get: async (key) => { return Promise.resolve(JSON.stringify(expectedNodes.slice(2, 4))) }, set: async (key, value) => { return null } } t.mock.method(mockStorage, 'get') - t.mock.method(mockStorage, 'check') t.mock.method(mockStorage, 'set') - const saturn = new Saturn({ storage: mockStorage }) + const saturn = new Saturn({ storage: mockStorage, clientKey: CLIENT_KEY }) // Mocking options const mockOpts = { orchURL: TEST_DEFAULT_ORCH } @@ -99,7 +94,6 @@ describe('Client Fallback', () => { await saturn._loadNodes(mockOpts) // Assert that all the storage methods were called twice. - assert.strictEqual(mockStorage.check.mock.calls.length, 2) assert.strictEqual(mockStorage.set.mock.calls.length, 2) assert.strictEqual(mockStorage.get.mock.calls.length, 2) From b0dc673cf2d8142fdbac444d9c7057420dea5dcc Mon Sep 17 00:00:00 2001 From: ameanasad Date: Thu, 12 Oct 2023 10:02:00 -0400 Subject: [PATCH 09/34] enhancement: simplify node loading --- src/index.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/index.js b/src/index.js index e4d1ea4..a6c037f 100644 --- a/src/index.js +++ b/src/index.js @@ -331,25 +331,21 @@ class Saturn { // This promise races fetching nodes list from the orchestrator and // and the provided storage object (localStorage, sessionStorage, etc.) // to insure we have a fallback set as quick as possible - let result + let nodes if (cachedNodesList) { - result = await Promise.race([orchNodesList, cachedNodesList]) + nodes = await Promise.race([orchNodesList, cachedNodesList]) } else { - result = await orchNodesList + nodes = await orchNodesList } - let nodes - // if the orchestrator responds first then always refresh and ignore the cached list. - if (result === await orchNodesList) { - nodes = result - this.nodes = nodes - } else { - nodes = result - this.nodes = nodes && JSON.parse(nodes) - // We still want to retrieve the latest list from the orchestrator and update the cache. - nodes = await orchNodesList + // let nodes + if (nodes === await cachedNodesList) { + nodes = nodes && JSON.parse(nodes) this.nodes = nodes } + + nodes = await orchNodesList + this.nodes = nodes cachedNodesList && this.storage?.set(this.nodesListKey, JSON.stringify(nodes)) } } From 78651fc31917bdf8f3dc303531f9f491fea76807 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Thu, 12 Oct 2023 11:28:34 -0400 Subject: [PATCH 10/34] naive fallback implementation --- src/index.js | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index a6c037f..23184a3 100644 --- a/src/index.js +++ b/src/index.js @@ -45,7 +45,7 @@ class Saturn { this._monitorPerformanceBuffer() } - this._loadNodes(this.opts) + this.loadNodes = this._loadNodes(this.opts) } /** @@ -115,6 +115,38 @@ class Saturn { return { res, log } } + async * fetchContentWithFallback (cidPath, opts = {}, origins) { + if (this.nodes.length === 0) { + await this.loadNodes + } + let lastError = null + // we use this to checkpoint at which chunk a request failed. + // this is temporary until range requests are supported. + let lastChunk = 0 + for (const origin of this.nodes) { + opts.url = origin + try { + let chunkCount = 0 + const byteChunks = await this.fetchContent(cidPath, opts) + for await (const chunk of byteChunks) { + // avoid sending duplicate chunks. + if (chunkCount >= lastChunk) { + yield chunk + chunkCount += 1 + } + lastChunk += 1 + } + return + } catch (err) { + lastError = err + } + } + + if (lastError) { + throw new Error(`All attempts to fetch content have failed. Last error: ${lastError.message}`) + } + } + /** * * @param {string} cidPath @@ -154,6 +186,7 @@ class Saturn { * @param {('car'|'raw')} [opts.format] * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] + * @param origin * @returns {Promise} */ async fetchContentBuffer (cidPath, opts = {}) { @@ -171,7 +204,7 @@ class Saturn { * @returns {URL} */ createRequestURL (cidPath, opts) { - let origin = opts.cdnURL + let origin = opts.url if (!origin.startsWith('http')) { origin = `https://${origin}` } @@ -338,12 +371,13 @@ class Saturn { nodes = await orchNodesList } - // let nodes + // if storage returns first, update based on cached storage. if (nodes === await cachedNodesList) { nodes = nodes && JSON.parse(nodes) this.nodes = nodes } + // we always want to update from the orchestrator regardless. nodes = await orchNodesList this.nodes = nodes cachedNodesList && this.storage?.set(this.nodesListKey, JSON.stringify(nodes)) From d15c0ad20f928b5fc00c06b8d14c1248cbbee9d6 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Thu, 12 Oct 2023 11:36:55 -0400 Subject: [PATCH 11/34] modify fallback --- src/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/index.js b/src/index.js index 23184a3..4bb09f2 100644 --- a/src/index.js +++ b/src/index.js @@ -122,19 +122,19 @@ class Saturn { let lastError = null // we use this to checkpoint at which chunk a request failed. // this is temporary until range requests are supported. - let lastChunk = 0 + let byteCountCheckpoint = 0 for (const origin of this.nodes) { opts.url = origin try { - let chunkCount = 0 + let byteCount = 0 const byteChunks = await this.fetchContent(cidPath, opts) for await (const chunk of byteChunks) { - // avoid sending duplicate chunks. - if (chunkCount >= lastChunk) { + // avoid sending duplicate chunks + if (byteCount >= byteCountCheckpoint) { yield chunk - chunkCount += 1 + byteCount += chunk.length } - lastChunk += 1 + byteCountCheckpoint += chunk.length } return } catch (err) { From 29e8da1550e07506a2d4b41961f0bb46cfee4a79 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Thu, 12 Oct 2023 11:39:46 -0400 Subject: [PATCH 12/34] fix formatting and typos --- src/index.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/index.js b/src/index.js index 4bb09f2..535b36c 100644 --- a/src/index.js +++ b/src/index.js @@ -45,7 +45,7 @@ class Saturn { this._monitorPerformanceBuffer() } - this.loadNodes = this._loadNodes(this.opts) + this.loadNodesPromise = this._loadNodes(this.opts) } /** @@ -117,7 +117,7 @@ class Saturn { async * fetchContentWithFallback (cidPath, opts = {}, origins) { if (this.nodes.length === 0) { - await this.loadNodes + await this.loadNodesPromise } let lastError = null // we use this to checkpoint at which chunk a request failed. @@ -340,9 +340,9 @@ class Saturn { async _loadNodes (opts) { let origin = opts.orchURL - let cachedNodesList + let cacheNodesListPromise if (this.storage) { - cachedNodesList = this.storage.get(this.nodesListKey) + cacheNodesListPromise = this.storage.get(this.nodesListKey) } if (!origin.startsWith('http')) { @@ -357,22 +357,22 @@ class Saturn { controller.abort() }, options.connectTimeout) - const orchestatorResponse = await fetch(url.href, { signal: controller.signal, ...options }) - const orchNodesList = orchestatorResponse.json() + const orchResponse = await fetch(url.href, { signal: controller.signal, ...options }) + const orchNodesList = orchResponse.json() clearTimeout(connectTimeout) // This promise races fetching nodes list from the orchestrator and // and the provided storage object (localStorage, sessionStorage, etc.) // to insure we have a fallback set as quick as possible let nodes - if (cachedNodesList) { - nodes = await Promise.race([orchNodesList, cachedNodesList]) + if (cacheNodesListPromise) { + nodes = await Promise.race([orchNodesList, cacheNodesListPromise]) } else { nodes = await orchNodesList } // if storage returns first, update based on cached storage. - if (nodes === await cachedNodesList) { + if (nodes === await cacheNodesListPromise) { nodes = nodes && JSON.parse(nodes) this.nodes = nodes } @@ -380,7 +380,7 @@ class Saturn { // we always want to update from the orchestrator regardless. nodes = await orchNodesList this.nodes = nodes - cachedNodesList && this.storage?.set(this.nodesListKey, JSON.stringify(nodes)) + cacheNodesListPromise && this.storage?.set(this.nodesListKey, JSON.stringify(nodes)) } } From 194ce708ef3e1e41f8ec228ce82ea7838d3f46bb Mon Sep 17 00:00:00 2001 From: ameanasad Date: Thu, 12 Oct 2023 11:40:18 -0400 Subject: [PATCH 13/34] typos --- src/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index 535b36c..ee01cd0 100644 --- a/src/index.js +++ b/src/index.js @@ -358,7 +358,7 @@ class Saturn { }, options.connectTimeout) const orchResponse = await fetch(url.href, { signal: controller.signal, ...options }) - const orchNodesList = orchResponse.json() + const orchNodesListPromise = orchResponse.json() clearTimeout(connectTimeout) // This promise races fetching nodes list from the orchestrator and @@ -366,9 +366,9 @@ class Saturn { // to insure we have a fallback set as quick as possible let nodes if (cacheNodesListPromise) { - nodes = await Promise.race([orchNodesList, cacheNodesListPromise]) + nodes = await Promise.race([orchNodesListPromise, cacheNodesListPromise]) } else { - nodes = await orchNodesList + nodes = await orchNodesListPromise } // if storage returns first, update based on cached storage. @@ -378,7 +378,7 @@ class Saturn { } // we always want to update from the orchestrator regardless. - nodes = await orchNodesList + nodes = await orchNodesListPromise this.nodes = nodes cacheNodesListPromise && this.storage?.set(this.nodesListKey, JSON.stringify(nodes)) } From 1d97dc9903e8973393d2f125b581864e6d0e01ae Mon Sep 17 00:00:00 2001 From: Amean Asad Date: Thu, 12 Oct 2023 14:38:04 -0400 Subject: [PATCH 14/34] Update .eslintrc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Diego Rodríguez Baquero --- .eslintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index a5041e9..b0f6e0b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,4 +11,4 @@ "rules": { "jsdoc/no-undefined-types": 1 }, -} \ No newline at end of file +} From 84a1b8ea5b6eeaed027f98a3d9ba88fd9cf38377 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Thu, 12 Oct 2023 15:13:36 -0400 Subject: [PATCH 15/34] enhancement: edit storage impl --- src/index.js | 3 +-- test/fallback.spec.js | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/index.js b/src/index.js index ee01cd0..56f268d 100644 --- a/src/index.js +++ b/src/index.js @@ -373,14 +373,13 @@ class Saturn { // if storage returns first, update based on cached storage. if (nodes === await cacheNodesListPromise) { - nodes = nodes && JSON.parse(nodes) this.nodes = nodes } // we always want to update from the orchestrator regardless. nodes = await orchNodesListPromise this.nodes = nodes - cacheNodesListPromise && this.storage?.set(this.nodesListKey, JSON.stringify(nodes)) + cacheNodesListPromise && this.storage?.set(this.nodesListKey, nodes) } } diff --git a/test/fallback.spec.js b/test/fallback.spec.js index 2776d4c..2af4cbd 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -61,7 +61,7 @@ describe('Client Fallback', () => { assert.strictEqual(mockStorage.get.mock.calls.length, 2) // Assert that the set method was invoked with the correct params. - assert.deepStrictEqual(mockStorage.set.mock.calls[0].arguments, [TEST_NODES_LIST_KEY, JSON.stringify(expectedNodes)]) + assert.deepStrictEqual(mockStorage.set.mock.calls[0].arguments, [TEST_NODES_LIST_KEY, expectedNodes]) assert.deepEqual(saturn.nodes, expectedNodes) @@ -80,7 +80,7 @@ describe('Client Fallback', () => { // Mocking storage object const mockStorage = { - get: async (key) => { return Promise.resolve(JSON.stringify(expectedNodes.slice(2, 4))) }, + get: async (key) => { return Promise.resolve(expectedNodes.slice(2, 4)) }, set: async (key, value) => { return null } } t.mock.method(mockStorage, 'get') @@ -98,7 +98,7 @@ describe('Client Fallback', () => { assert.strictEqual(mockStorage.get.mock.calls.length, 2) // Assert that the set method was invoked with the correct params. - assert.deepStrictEqual(mockStorage.set.mock.calls[0].arguments, [TEST_NODES_LIST_KEY, JSON.stringify(expectedNodes.slice(0, 2))]) + assert.deepStrictEqual(mockStorage.set.mock.calls[0].arguments, [TEST_NODES_LIST_KEY, expectedNodes.slice(0, 2)]) assert.deepEqual(saturn.nodes, expectedNodes.slice(0, 2)) }) From f688406e0af48485e208dcb1e23ce389f1b06047 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Thu, 12 Oct 2023 16:12:19 -0400 Subject: [PATCH 16/34] enhancement: deal with overlapping byte chunks --- src/index.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 56f268d..bbab533 100644 --- a/src/index.js +++ b/src/index.js @@ -130,11 +130,17 @@ class Saturn { const byteChunks = await this.fetchContent(cidPath, opts) for await (const chunk of byteChunks) { // avoid sending duplicate chunks - if (byteCount >= byteCountCheckpoint) { - yield chunk + if (byteCount < byteCountCheckpoint) { + // checks for overlapping chunks + const remainingBytes = byteCountCheckpoint - byteCount + if (remainingBytes < chunk.length) { + yield chunk.slice(remainingBytes) + } byteCount += chunk.length + } else { + yield chunk + byteCountCheckpoint += chunk.length } - byteCountCheckpoint += chunk.length } return } catch (err) { From 5b7c215760d0c7bfffeade68b1ad4265b60fbd9e Mon Sep 17 00:00:00 2001 From: ameanasad Date: Fri, 13 Oct 2023 22:46:17 -0400 Subject: [PATCH 17/34] feat: add fallback test suite --- package.json | 4 +- src/index.js | 19 ++-- src/utils/url.js | 15 ++++ test/car.spec.js | 20 +---- test/fallback.spec.js | 196 +++++++++++++++++++++++++++++++++++++++++- test/test-utils.js | 59 ++++++++++++- 6 files changed, 279 insertions(+), 34 deletions(-) create mode 100644 src/utils/url.js diff --git a/package.json b/package.json index c30bf27..e3efdc8 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "src/index.js", "type": "module", "scripts": { - "test": "NODE_ENV=development node --test test/", + "test": "NODE_ENV=development TESTING=true node --test test/", "build": "webpack --mode production", "prepack": "npm run build" }, @@ -54,4 +54,4 @@ "publishConfig": { "access": "public" } -} +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index bbab533..4770c68 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,7 @@ import { asAsyncIterable, asyncIteratorToBuffer } from './utils/itr.js' import { randomUUID } from './utils/uuid.js' import { memoryStorage } from './storage/index.js' import { getJWT } from './utils/jwt.js' +import { parseUrl } from './utils/url.js' class Saturn { /** @@ -26,6 +27,7 @@ class Saturn { cdnURL: 'saturn.ms', logURL: 'https://twb3qukm2i654i3tnvx36char40aymqq.lambda-url.us-west-2.on.aws/', orchURL: 'https://orchestrator.strn.pl/nodes?maxNodes=100', + authURL: 'https://saturn.auth', connectTimeout: 5_000, downloadTimeout: 0 }, opts) @@ -62,10 +64,8 @@ class Saturn { CID.parse(cid) const jwt = await getJWT(this.opts, this.storage) - const options = Object.assign({}, this.opts, { format: 'car', jwt }, opts) const url = this.createRequestURL(cidPath, options) - const log = { url, startTime: new Date() @@ -82,10 +82,9 @@ class Saturn { Authorization: 'Bearer ' + options.jwt } } - let res try { - res = await fetch(url, { signal: controller.signal, ...options }) + res = await fetch(parseUrl(url), { signal: controller.signal, ...options }) clearTimeout(connectTimeout) @@ -115,16 +114,17 @@ class Saturn { return { res, log } } - async * fetchContentWithFallback (cidPath, opts = {}, origins) { + async * fetchContentWithFallback (cidPath, opts = {}) { if (this.nodes.length === 0) { await this.loadNodesPromise } + let lastError = null // we use this to checkpoint at which chunk a request failed. // this is temporary until range requests are supported. let byteCountCheckpoint = 0 for (const origin of this.nodes) { - opts.url = origin + opts.url = origin.url try { let byteCount = 0 const byteChunks = await this.fetchContent(cidPath, opts) @@ -136,11 +136,11 @@ class Saturn { if (remainingBytes < chunk.length) { yield chunk.slice(remainingBytes) } - byteCount += chunk.length } else { yield chunk byteCountCheckpoint += chunk.length } + byteCount += chunk.length } return } catch (err) { @@ -210,7 +210,7 @@ class Saturn { * @returns {URL} */ createRequestURL (cidPath, opts) { - let origin = opts.url + let origin = opts.url || opts.cdnURL if (!origin.startsWith('http')) { origin = `https://${origin}` } @@ -363,7 +363,7 @@ class Saturn { controller.abort() }, options.connectTimeout) - const orchResponse = await fetch(url.href, { signal: controller.signal, ...options }) + const orchResponse = await fetch(parseUrl(url), { signal: controller.signal, ...options }) const orchNodesListPromise = orchResponse.json() clearTimeout(connectTimeout) @@ -381,7 +381,6 @@ class Saturn { if (nodes === await cacheNodesListPromise) { this.nodes = nodes } - // we always want to update from the orchestrator regardless. nodes = await orchNodesListPromise this.nodes = nodes diff --git a/src/utils/url.js b/src/utils/url.js new file mode 100644 index 0000000..eb36ba8 --- /dev/null +++ b/src/utils/url.js @@ -0,0 +1,15 @@ +// @ts-check + +/** + * + * @param {URL} url + * @returns {URL|string} + */ +export function parseUrl (url) { + // This is a temp function to resolve URLs for mock testing + // See issue here: https://github.com/mswjs/msw/issues/1597 + if (process.env.TESTING) { + return url.href + } + return url +} diff --git a/test/car.spec.js b/test/car.spec.js index 15d981f..02e9c1b 100644 --- a/test/car.spec.js +++ b/test/car.spec.js @@ -1,28 +1,13 @@ import assert from 'node:assert/strict' import fs from 'node:fs' import { describe, it } from 'node:test' -import { resolve, dirname } from 'node:path' -import { fileURLToPath } from 'node:url' +import { getFixturePath, concatChunks } from './test-utils.js' import { CarReader, CarWriter } from '@ipld/car' import { CID } from 'multiformats/cid' import { extractVerifiedContent } from '#src/utils/car.js' -const __dirname = dirname(fileURLToPath(import.meta.url)) - -function getFixturePath (filename) { - return resolve(__dirname, `./fixtures/${filename}`) -} - -async function concatChunks (itr) { - const arr = [] - for await (const chunk of itr) { - arr.push(chunk) - } - return new Uint8Array(...arr) -} - describe('CAR Verification', () => { it('should extract content from a valid CAR', async () => { const cidPath = @@ -149,8 +134,7 @@ describe('CAR Verification', () => { await assert.rejects( async () => { - for await (const _ of extractVerifiedContent(cidPath, out)) { - } + for await (const _ of extractVerifiedContent(cidPath, out)) {} }, { name: 'VerificationError', diff --git a/test/fallback.spec.js b/test/fallback.spec.js index 2af4cbd..e6aaf7a 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -3,7 +3,7 @@ import assert from 'node:assert/strict' import { describe, mock, test } from 'node:test' import Saturn from '../src/index.js' -import { generateNodes, getMockServer, mockOrchHandler } from './test-utils.js' +import { concatChunks, generateNodes, getMockServer, mockJWT, mockNodesHandlers, mockOrchHandler } from './test-utils.js' const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' const TEST_NODES_LIST_KEY = 'saturn-nodes' @@ -71,7 +71,7 @@ describe('Client Fallback', () => { test('Storage is loaded first when the orch is slower', async (t) => { const handlers = [ - mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms', 4000) + mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms', 1000) ] const server = getMockServer(handlers) server.listen() @@ -101,5 +101,197 @@ describe('Client Fallback', () => { assert.deepStrictEqual(mockStorage.set.mock.calls[0].arguments, [TEST_NODES_LIST_KEY, expectedNodes.slice(0, 2)]) assert.deepEqual(saturn.nodes, expectedNodes.slice(0, 2)) + server.close() + mock.reset() + }) + + test('Content Fallback fetches a cid properly', async (t) => { + const handlers = [ + mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms'), + mockJWT('saturn.auth'), + ...mockNodesHandlers(2, TEST_ORIGIN_DOMAIN) + ] + const server = getMockServer(handlers) + server.listen() + + const expectedNodes = generateNodes(2, TEST_ORIGIN_DOMAIN) + + // Mocking storage object + const mockStorage = { + get: async (key) => { return Promise.resolve(expectedNodes.slice(2, 4)) }, + set: async (key, value) => { return null } + } + t.mock.method(mockStorage, 'get') + t.mock.method(mockStorage, 'set') + + const saturn = new Saturn({ storage: mockStorage, clientKey: CLIENT_KEY, clientId: 'test' }) + + const cid = saturn.fetchContentWithFallback('bafkreifjjcie6lypi6ny7amxnfftagclbuxndqonfipmb64f2km2devei4', { url: 'node1.saturn.ms' }) + + const buffer = await concatChunks(cid) + const actualContent = String.fromCharCode(...buffer) + const expectedContent = 'hello world\n' + + assert.strictEqual(actualContent, expectedContent) + server.close() + mock.reset() + }) + + test('should fetch content from the first node successfully', async () => { + const handlers = [ + mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms'), + mockJWT('saturn.auth'), + ...mockNodesHandlers(2, TEST_ORIGIN_DOMAIN) + ] + + const server = getMockServer(handlers) + server.listen() + const saturn = new Saturn({ clientKey: CLIENT_KEY, clientId: 'test' }) + + const fetchContentMock = mock.fn(async function * (cidPath, opts) { + yield Buffer.from('chunk1') + yield Buffer.from('chunk2') + }) + saturn.fetchContent = fetchContentMock + const content = await saturn.fetchContentWithFallback('some-cid-path') + + const buffer = await concatChunks(content) + const expectedContent = new Uint8Array([...Buffer.from('chunk1'), ...Buffer.from('chunk2')]) + + assert.deepEqual(buffer, expectedContent) + assert.strictEqual(fetchContentMock.mock.calls.length, 1) + server.close() + mock.reset() + }) + + test('should try all nodes and fail if all nodes fail', async () => { + const numNodes = 3 + const handlers = [ + mockOrchHandler(numNodes, TEST_DEFAULT_ORCH, 'saturn.ms'), + mockJWT('saturn.auth'), + ...mockNodesHandlers(numNodes, TEST_ORIGIN_DOMAIN) + ] + + const server = getMockServer(handlers) + server.listen() + const saturn = new Saturn({ clientKey: CLIENT_KEY, clientId: 'test' }) + + const fetchContentMock = mock.fn(async function * (cidPath, opts) { throw new Error('Fetch error') }) // eslint-disable-line + saturn.fetchContent = fetchContentMock + + let error + try { + for await (const _ of saturn.fetchContentWithFallback('some-cid-path')) { // eslint-disable-line + // This loop body shouldn't be reached. + } + } catch (e) { + error = e + } + + assert(error) + assert.strictEqual(error.message, 'All attempts to fetch content have failed. Last error: Fetch error') + assert.strictEqual(fetchContentMock.mock.calls.length, numNodes) // Assuming 3 nodes. + server.close() + mock.reset() + }) + + test('Handles fallback with chunk overlap correctly', async () => { + const numNodes = 3 + const handlers = [ + mockOrchHandler(numNodes, TEST_DEFAULT_ORCH, 'saturn.ms'), + mockJWT('saturn.auth'), + ...mockNodesHandlers(numNodes, TEST_ORIGIN_DOMAIN) + ] + + const server = getMockServer(handlers) + server.listen() + const saturn = new Saturn({ clientKey: CLIENT_KEY, clientId: 'test' }) + + let callCount = 0 + const fetchContentMock = mock.fn(async function * (cidPath, opts) { + callCount++ + if (callCount === 1) { + throw new Error('First call error') + } + if (callCount === 2) { + yield Buffer.from('chunk1-overlap') + yield Buffer.from('chunk2') + } + }) + + saturn.fetchContent = fetchContentMock + + const content = saturn.fetchContentWithFallback('some-cid-path') + const buffer = await concatChunks(content) + const expectedContent = new Uint8Array([ + ...Buffer.from('chunk1-overlap'), + ...Buffer.from('chunk2') + ]) + + assert.deepEqual(buffer, expectedContent) + assert.strictEqual(fetchContentMock.mock.calls.length, 2) + server.close() + mock.reset() + }) + + test('should handle byte chunk overlaps correctly', async () => { + const numNodes = 3 + const handlers = [ + mockOrchHandler(numNodes, TEST_DEFAULT_ORCH, 'saturn.ms'), + mockJWT('saturn.auth'), + ...mockNodesHandlers(numNodes, TEST_ORIGIN_DOMAIN) + ] + + const server = getMockServer(handlers) + server.listen() + const saturn = new Saturn({ clientKey: CLIENT_KEY, clientId: 'test' }) + + let callCount = 0 + let fetchContentMock = mock.fn(async function * (cidPath, opts) { + callCount++ + if (callCount === 1) { + yield Buffer.from('chunk1-overlap') + throw new Error('First call error') + } + if (callCount === 2) { + yield Buffer.from('chunk1-overlap') + yield Buffer.from('chunk2') + } + }) + + saturn.fetchContent = fetchContentMock + const expectedContent = new Uint8Array([ + ...Buffer.from('chunk1-overlap'), + ...Buffer.from('chunk2') + ]) + let content = saturn.fetchContentWithFallback('some-cid-path') + let buffer = await concatChunks(content) + + assert.deepEqual(buffer, expectedContent) + assert.strictEqual(fetchContentMock.mock.calls.length, 2) + + callCount = 0 + fetchContentMock = mock.fn(async function * (cidPath, opts) { + callCount++ + if (callCount === 1) { + yield Buffer.from('chunk1-') + yield Buffer.from('overlap') + throw new Error('First call error') + } + if (callCount === 2) { + yield Buffer.from('chunk1-overlap') + yield Buffer.from('chunk2') + } + }) + + saturn.fetchContent = fetchContentMock + + content = await saturn.fetchContentWithFallback('some-cid-path') + buffer = await concatChunks(content) + assert.deepEqual(buffer, expectedContent) + assert.strictEqual(fetchContentMock.mock.calls.length, 2) + + server.close() + mock.reset() }) }) diff --git a/test/test-utils.js b/test/test-utils.js index 37483aa..f119125 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -3,7 +3,13 @@ import { RestHandler, rest } from 'msw' import { setupServer } from 'msw/node' +import { resolve, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' + +import fs from 'fs' const HTTP_STATUS_OK = 200 +const __dirname = dirname(fileURLToPath(import.meta.url)) +process.env.TESTING = 'true' /** * @@ -60,6 +66,35 @@ export function mockOrchHandler (count, orchURL, originDomain, delay = 0) { }) } +/** + * Generates a mock handler to mimick Saturn's orchestrator /nodes endpoint. + * + * @param {string} authURL - orchestratorUrl + * @returns {RestHandler} + */ +export function mockJWT (authURL) { + if (!authURL.startsWith('http')) { + authURL = `https://${authURL}` + } + return rest.get(authURL, (req, res, ctx) => { + const clientKey = req.url.searchParams.get('clientKey') + if (clientKey) { + return res( + ctx.json({ + token: 'MOCK_JWT_TOKEN' + }) + ) + } else { + return res( + ctx.json({ + token: null, + message: 'Failed to refresh jwt' + }) + ) + } + }) +} + /** * Generates mock servers to act as L1 nodes. * @@ -71,16 +106,36 @@ export function mockNodesHandlers (count, originDomain) { const nodes = generateNodes(count, originDomain) const handlers = nodes.map((node) => { - return rest.get(node.url, (req, res, ctx) => { + const url = `${node.url}/ipfs/:cid` + return rest.get(url, (req, res, ctx) => { + const filepath = getFixturePath('hello.car') + const fileContents = fs.readFileSync(filepath) return res( ctx.status(HTTP_STATUS_OK), - ctx.json({ data: 'Test Block' }) + ctx.body(fileContents) ) }) }) return handlers } +export function getFixturePath (filename) { + return resolve(__dirname, `./fixtures/${filename}`) +} + +export async function concatChunks (itr) { + const arr = [] + for await (const chunk of itr) { + if (chunk instanceof Uint8Array) { + arr.push(...chunk) + } else { + const uInt8ArrayChunk = new Uint8Array(chunk) + arr.push(...uInt8ArrayChunk) + } + } + return new Uint8Array(arr) +} + /** * @param {RestHandler[]} handlers - amount of nodes to mock */ From 6068a90f5b3f562988b03b9d5ffbbde49e819d9a Mon Sep 17 00:00:00 2001 From: ameanasad Date: Sun, 15 Oct 2023 19:44:52 -0400 Subject: [PATCH 18/34] fix: tests running --- src/index.js | 2 -- test/fallback.spec.js | 18 +++++++++--------- test/index.spec.js | 31 +++++++++++++++++++++++++------ test/test-utils.js | 5 +++++ 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/index.js b/src/index.js index 4770c68..ad31308 100644 --- a/src/index.js +++ b/src/index.js @@ -62,7 +62,6 @@ class Saturn { async fetchCID (cidPath, opts = {}) { const [cid] = (cidPath ?? '').split('/') CID.parse(cid) - const jwt = await getJWT(this.opts, this.storage) const options = Object.assign({}, this.opts, { format: 'car', jwt }, opts) const url = this.createRequestURL(cidPath, options) @@ -243,7 +242,6 @@ class Saturn { */ reportLogs (log) { if (!this.reportingLogs) return - this.logs.push(log) this.reportLogsTimeout && clearTimeout(this.reportLogsTimeout) this.reportLogsTimeout = setTimeout(this._reportLogs.bind(this), 3_000) diff --git a/test/fallback.spec.js b/test/fallback.spec.js index e6aaf7a..341ba96 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -3,7 +3,7 @@ import assert from 'node:assert/strict' import { describe, mock, test } from 'node:test' import Saturn from '../src/index.js' -import { concatChunks, generateNodes, getMockServer, mockJWT, mockNodesHandlers, mockOrchHandler } from './test-utils.js' +import { concatChunks, generateNodes, getMockServer, mockJWT, mockNodesHandlers, mockOrchHandler, MSW_SERVER_OPTS } from './test-utils.js' const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' const TEST_NODES_LIST_KEY = 'saturn-nodes' @@ -15,7 +15,7 @@ describe('Client Fallback', () => { mockOrchHandler(2, TEST_DEFAULT_ORCH, TEST_ORIGIN_DOMAIN) ] const server = getMockServer(handlers) - server.listen() + server.listen(MSW_SERVER_OPTS) const expectedNodes = generateNodes(2, TEST_ORIGIN_DOMAIN) @@ -36,7 +36,7 @@ describe('Client Fallback', () => { mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms') ] const server = getMockServer(handlers) - server.listen() + server.listen(MSW_SERVER_OPTS) const expectedNodes = generateNodes(2, TEST_ORIGIN_DOMAIN) @@ -74,7 +74,7 @@ describe('Client Fallback', () => { mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms', 1000) ] const server = getMockServer(handlers) - server.listen() + server.listen(MSW_SERVER_OPTS) const expectedNodes = generateNodes(4, TEST_ORIGIN_DOMAIN) @@ -112,7 +112,7 @@ describe('Client Fallback', () => { ...mockNodesHandlers(2, TEST_ORIGIN_DOMAIN) ] const server = getMockServer(handlers) - server.listen() + server.listen(MSW_SERVER_OPTS) const expectedNodes = generateNodes(2, TEST_ORIGIN_DOMAIN) @@ -145,7 +145,7 @@ describe('Client Fallback', () => { ] const server = getMockServer(handlers) - server.listen() + server.listen(MSW_SERVER_OPTS) const saturn = new Saturn({ clientKey: CLIENT_KEY, clientId: 'test' }) const fetchContentMock = mock.fn(async function * (cidPath, opts) { @@ -173,7 +173,7 @@ describe('Client Fallback', () => { ] const server = getMockServer(handlers) - server.listen() + server.listen(MSW_SERVER_OPTS) const saturn = new Saturn({ clientKey: CLIENT_KEY, clientId: 'test' }) const fetchContentMock = mock.fn(async function * (cidPath, opts) { throw new Error('Fetch error') }) // eslint-disable-line @@ -204,7 +204,7 @@ describe('Client Fallback', () => { ] const server = getMockServer(handlers) - server.listen() + server.listen(MSW_SERVER_OPTS) const saturn = new Saturn({ clientKey: CLIENT_KEY, clientId: 'test' }) let callCount = 0 @@ -243,7 +243,7 @@ describe('Client Fallback', () => { ] const server = getMockServer(handlers) - server.listen() + server.listen(MSW_SERVER_OPTS) const saturn = new Saturn({ clientKey: CLIENT_KEY, clientId: 'test' }) let callCount = 0 diff --git a/test/index.spec.js b/test/index.spec.js index 6f43b97..c71bd93 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,8 +1,9 @@ import assert from 'node:assert/strict' import { randomUUID } from 'node:crypto' -import { describe, it } from 'node:test' +import { describe, it, before, after } from 'node:test' import Saturn from '#src/index.js' +import { getMockServer, mockJWT, MSW_SERVER_OPTS } from './test-utils.js' const TEST_CID = 'QmXjYBY478Cno4jzdCcPy4NcJYFrwHZ51xaCP8vUwN9MGm' @@ -11,7 +12,7 @@ const clientKey = 'abc123' describe('Saturn client', () => { describe('constructor', () => { it('should work w/o custom client ID', () => { - new Saturn({ clientKey }) + new Saturn({ clientKey }) // eslint-disable-line }) it('should work with custom client ID', () => { @@ -39,7 +40,17 @@ describe('Saturn client', () => { describe('Fetch a CID', () => { const client = new Saturn({ clientKey }) + const handlers = [ + mockJWT('saturn.auth') + ] + const server = getMockServer(handlers) + before(() => { + server.listen(MSW_SERVER_OPTS) + }) + after(() => { + server.close() + }) it('should fetch test CID', async () => { const { res } = await client.fetchCID(TEST_CID) assert(res instanceof Response) @@ -59,10 +70,19 @@ describe('Saturn client', () => { }) describe('Logging', () => { - const client = new Saturn({ clientKey }) - client.reportingLogs = true - + const handlers = [ + mockJWT('saturn.auth') + ] + const server = getMockServer(handlers) + const client = new Saturn({ clientKey, clientId: 'tesd' }) + before(() => { + server.listen(MSW_SERVER_OPTS) + }) + after(() => { + server.close() + }) it('should create a log on fetch success', async () => { + client.reportingLogs = true for await (const _ of client.fetchContent(TEST_CID)) {} // eslint-disable-line const log = client.logs.pop() @@ -76,7 +96,6 @@ describe('Saturn client', () => { it('should create a log on fetch network error', async () => { await assert.rejects(client.fetchContentBuffer(TEST_CID, { connectTimeout: 1 })) - const log = client.logs.pop() assert.strictEqual(log.error, 'This operation was aborted') }) diff --git a/test/test-utils.js b/test/test-utils.js index f119125..3cb291a 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -7,7 +7,9 @@ import { resolve, dirname } from 'node:path' import { fileURLToPath } from 'node:url' import fs from 'fs' + const HTTP_STATUS_OK = 200 + const __dirname = dirname(fileURLToPath(import.meta.url)) process.env.TESTING = 'true' @@ -136,6 +138,9 @@ export async function concatChunks (itr) { return new Uint8Array(arr) } +export const MSW_SERVER_OPTS = { + onUnhandledRequest: 'bypass' +} /** * @param {RestHandler[]} handlers - amount of nodes to mock */ From 2c3cc79a5480755c13a64adaa38e8e2fb9e19a7c Mon Sep 17 00:00:00 2001 From: ameanasad Date: Sun, 15 Oct 2023 20:06:09 -0400 Subject: [PATCH 19/34] cleanup content fetch with fallback --- src/index.js | 37 +++++++++++++++++++++---------------- test/fallback.spec.js | 2 +- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/index.js b/src/index.js index ad31308..d52bc8e 100644 --- a/src/index.js +++ b/src/index.js @@ -122,25 +122,30 @@ class Saturn { // we use this to checkpoint at which chunk a request failed. // this is temporary until range requests are supported. let byteCountCheckpoint = 0 + + const fetchContent = async function * () { + let byteCount = 0 + const byteChunks = await this.fetchContent(cidPath, opts) + for await (const chunk of byteChunks) { + // avoid sending duplicate chunks + if (byteCount < byteCountCheckpoint) { + // checks for overlapping chunks + const remainingBytes = byteCountCheckpoint - byteCount + if (remainingBytes < chunk.length) { + yield chunk.slice(remainingBytes) + } + } else { + yield chunk + byteCountCheckpoint += chunk.length + } + byteCount += chunk.length + } + }.bind(this) + for (const origin of this.nodes) { opts.url = origin.url try { - let byteCount = 0 - const byteChunks = await this.fetchContent(cidPath, opts) - for await (const chunk of byteChunks) { - // avoid sending duplicate chunks - if (byteCount < byteCountCheckpoint) { - // checks for overlapping chunks - const remainingBytes = byteCountCheckpoint - byteCount - if (remainingBytes < chunk.length) { - yield chunk.slice(remainingBytes) - } - } else { - yield chunk - byteCountCheckpoint += chunk.length - } - byteCount += chunk.length - } + yield * fetchContent() return } catch (err) { lastError = err diff --git a/test/fallback.spec.js b/test/fallback.spec.js index 341ba96..fe666d9 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -190,7 +190,7 @@ describe('Client Fallback', () => { assert(error) assert.strictEqual(error.message, 'All attempts to fetch content have failed. Last error: Fetch error') - assert.strictEqual(fetchContentMock.mock.calls.length, numNodes) // Assuming 3 nodes. + assert.strictEqual(fetchContentMock.mock.calls.length, numNodes) server.close() mock.reset() }) From 4cf0c0083a7273dbc05029c3aa84c004445b9bb3 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Sun, 15 Oct 2023 21:47:36 -0400 Subject: [PATCH 20/34] add initial origin fetch to fallback --- src/index.js | 26 +++++++++++++++----------- src/utils/url.js | 14 ++++++++++++++ test/fallback.spec.js | 6 ++++-- test/test-utils.js | 33 +++++++++++++++++++++++++++------ 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/index.js b/src/index.js index d52bc8e..356384a 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,7 @@ import { asAsyncIterable, asyncIteratorToBuffer } from './utils/itr.js' import { randomUUID } from './utils/uuid.js' import { memoryStorage } from './storage/index.js' import { getJWT } from './utils/jwt.js' -import { parseUrl } from './utils/url.js' +import { parseUrl, addHttpPrefix } from './utils/url.js' class Saturn { /** @@ -114,10 +114,6 @@ class Saturn { } async * fetchContentWithFallback (cidPath, opts = {}) { - if (this.nodes.length === 0) { - await this.loadNodesPromise - } - let lastError = null // we use this to checkpoint at which chunk a request failed. // this is temporary until range requests are supported. @@ -142,6 +138,18 @@ class Saturn { } }.bind(this) + if (this.nodes.length === 0) { + // fetch from origin in the case that no nodes are loaded + opts.url = this.opts.cdnURL + try { + yield * fetchContent() + return + } catch (err) { + lastError = err + await this.loadNodesPromise + } + } + for (const origin of this.nodes) { opts.url = origin.url try { @@ -215,9 +223,7 @@ class Saturn { */ createRequestURL (cidPath, opts) { let origin = opts.url || opts.cdnURL - if (!origin.startsWith('http')) { - origin = `https://${origin}` - } + origin = addHttpPrefix(origin) const url = new URL(`${origin}/ipfs/${cidPath}`) url.searchParams.set('format', opts.format) @@ -354,9 +360,7 @@ class Saturn { cacheNodesListPromise = this.storage.get(this.nodesListKey) } - if (!origin.startsWith('http')) { - origin = `https://${origin}` - } + origin = addHttpPrefix(origin) const url = new URL(origin) const controller = new AbortController() diff --git a/src/utils/url.js b/src/utils/url.js index eb36ba8..b58b7b5 100644 --- a/src/utils/url.js +++ b/src/utils/url.js @@ -13,3 +13,17 @@ export function parseUrl (url) { } return url } + +/** + * + * @param {string} url + * @returns {string} + */ +export function addHttpPrefix (url) { + // This is a temp function to resolve URLs for mock testing + // See issue here: https://github.com/mswjs/msw/issues/1597 + if (!url.startsWith('http')) { + url = `https://${url}` + } + return url +} diff --git a/test/fallback.spec.js b/test/fallback.spec.js index fe666d9..0237424 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -3,7 +3,7 @@ import assert from 'node:assert/strict' import { describe, mock, test } from 'node:test' import Saturn from '../src/index.js' -import { concatChunks, generateNodes, getMockServer, mockJWT, mockNodesHandlers, mockOrchHandler, MSW_SERVER_OPTS } from './test-utils.js' +import { concatChunks, generateNodes, getMockServer, mockJWT, mockNodesHandlers, mockOrchHandler, mockSaturnOriginHandler, MSW_SERVER_OPTS } from './test-utils.js' const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' const TEST_NODES_LIST_KEY = 'saturn-nodes' @@ -109,6 +109,7 @@ describe('Client Fallback', () => { const handlers = [ mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms'), mockJWT('saturn.auth'), + mockSaturnOriginHandler(TEST_ORIGIN_DOMAIN, 0, true), ...mockNodesHandlers(2, TEST_ORIGIN_DOMAIN) ] const server = getMockServer(handlers) @@ -190,7 +191,7 @@ describe('Client Fallback', () => { assert(error) assert.strictEqual(error.message, 'All attempts to fetch content have failed. Last error: Fetch error') - assert.strictEqual(fetchContentMock.mock.calls.length, numNodes) + assert.strictEqual(fetchContentMock.mock.calls.length, numNodes + 1) server.close() mock.reset() }) @@ -288,6 +289,7 @@ describe('Client Fallback', () => { content = await saturn.fetchContentWithFallback('some-cid-path') buffer = await concatChunks(content) + assert.deepEqual(buffer, expectedContent) assert.strictEqual(fetchContentMock.mock.calls.length, 2) diff --git a/test/test-utils.js b/test/test-utils.js index 3cb291a..db26837 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -7,6 +7,7 @@ import { resolve, dirname } from 'node:path' import { fileURLToPath } from 'node:url' import fs from 'fs' +import { addHttpPrefix } from '../src/utils/url.js' const HTTP_STATUS_OK = 200 @@ -44,6 +45,30 @@ export function generateNodes (count, originDomain) { return nodes } +/** + * Generates a mock handler to mimick Saturn's orchestrator /nodes endpoint. + * + * @param {string} cdnURL - orchestratorUrl + * @param {number} delay - request delay in ms + * @param {boolean} error + * @returns {RestHandler} + */ +export function mockSaturnOriginHandler (cdnURL, delay = 0, error = false) { + cdnURL = addHttpPrefix(cdnURL) + return rest.get(cdnURL, (req, res, ctx) => { + if (error) { + throw Error('Simulated Error') + } + const filepath = getFixturePath('hello.car') + const fileContents = fs.readFileSync(filepath) + return res( + ctx.delay(delay), + ctx.status(HTTP_STATUS_OK), + ctx.body(fileContents) + ) + }) +} + /** * Generates a mock handler to mimick Saturn's orchestrator /nodes endpoint. * @@ -54,9 +79,7 @@ export function generateNodes (count, originDomain) { * @returns {RestHandler} */ export function mockOrchHandler (count, orchURL, originDomain, delay = 0) { - if (!orchURL.startsWith('http')) { - orchURL = `https://${orchURL}` - } + orchURL = addHttpPrefix(orchURL) const nodes = generateNodes(count, originDomain) return rest.get(orchURL, (req, res, ctx) => { @@ -75,9 +98,7 @@ export function mockOrchHandler (count, orchURL, originDomain, delay = 0) { * @returns {RestHandler} */ export function mockJWT (authURL) { - if (!authURL.startsWith('http')) { - authURL = `https://${authURL}` - } + authURL = addHttpPrefix(authURL) return rest.get(authURL, (req, res, ctx) => { const clientKey = req.url.searchParams.get('clientKey') if (clientKey) { From d81038f422db1d67ea02ba72726837f7428375e4 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Mon, 16 Oct 2023 09:53:14 -0400 Subject: [PATCH 21/34] formatting and file re-org --- src/client.js | 408 ++++++++++++++++++++++++++++++++++++++++++ src/index.js | 401 +---------------------------------------- test/fallback.spec.js | 2 +- 3 files changed, 412 insertions(+), 399 deletions(-) create mode 100644 src/client.js diff --git a/src/client.js b/src/client.js new file mode 100644 index 0000000..b61f305 --- /dev/null +++ b/src/client.js @@ -0,0 +1,408 @@ +// @ts-check + +import { CID } from 'multiformats' + +import { extractVerifiedContent } from './utils/car.js' +import { asAsyncIterable, asyncIteratorToBuffer } from './utils/itr.js' +import { randomUUID } from './utils/uuid.js' +import { memoryStorage } from './storage/index.js' +import { getJWT } from './utils/jwt.js' +import { parseUrl, addHttpPrefix } from './utils/url.js' + +export class Saturn { + /** + * + * @param {object} [opts={}] + * @param {string} [opts.clientKey] + * @param {string} [opts.clientId=randomUUID()] + * @param {string} [opts.cdnURL=saturn.ms] + * @param {number} [opts.connectTimeout=5000] + * @param {number} [opts.downloadTimeout=0] + * @param {string} [opts.orchURL] + * @param {import('./storage/index.js').Storage} [opts.storage] + */ + constructor (opts = {}) { + this.opts = Object.assign({}, { + clientId: randomUUID(), + cdnURL: 'saturn.ms', + logURL: 'https://twb3qukm2i654i3tnvx36char40aymqq.lambda-url.us-west-2.on.aws/', + orchURL: 'https://orchestrator.strn.pl/nodes?maxNodes=100', + authURL: 'https://saturn.auth', + connectTimeout: 5_000, + downloadTimeout: 0 + }, opts) + + if (!this.opts.clientKey) { + throw new Error('clientKey is required') + } + + this.logs = [] + this.nodes = [] + this.nodesListKey = 'saturn-nodes' + this.storage = this.opts.storage || memoryStorage() + this.reportingLogs = process?.env?.NODE_ENV !== 'development' + this.hasPerformanceAPI = typeof window !== 'undefined' && window?.performance + this.isBrowser = typeof window !== 'undefined' + if (this.reportingLogs && this.hasPerformanceAPI) { + this._monitorPerformanceBuffer() + } + + this.loadNodesPromise = this._loadNodes(this.opts) + } + + /** + * + * @param {string} cidPath + * @param {object} [opts={}] + * @param {('car'|'raw')} [opts.format] + * @param {number} [opts.connectTimeout=5000] + * @param {number} [opts.downloadTimeout=0] + * @returns {Promise} + */ + async fetchCID (cidPath, opts = {}) { + const [cid] = (cidPath ?? '').split('/') + CID.parse(cid) + const jwt = await getJWT(this.opts, this.storage) + const options = Object.assign({}, this.opts, { format: 'car', jwt }, opts) + const url = this.createRequestURL(cidPath, options) + const log = { + url, + startTime: new Date() + } + + const controller = new AbortController() + const connectTimeout = setTimeout(() => { + controller.abort() + }, options.connectTimeout) + + if (!this.isBrowser) { + options.headers = { + ...(options.headers || {}), + Authorization: 'Bearer ' + options.jwt + } + } + let res + try { + res = await fetch(parseUrl(url), { signal: controller.signal, ...options }) + + clearTimeout(connectTimeout) + + const { headers } = res + log.ttfbMs = new Date() - log.startTime + log.httpStatusCode = res.status + log.cacheHit = headers.get('saturn-cache-status') === 'HIT' + log.nodeId = headers.get('saturn-node-id') + log.requestId = headers.get('saturn-transfer-id') + log.httpProtocol = headers.get('quic-status') + + if (!res.ok) { + throw new Error( + `Non OK response received: ${res.status} ${res.statusText}` + ) + } + } catch (err) { + if (!res) { + log.error = err.message + } + // Report now if error, otherwise report after download is done. + this._finalizeLog(log) + + throw err + } + + return { res, log } + } + + /** + * + * @param {string} cidPath + * @param {object} [opts={}] + * @param {('car'|'raw')} [opts.format] + * @param {string} [opts.url] + * @param {number} [opts.connectTimeout=5000] + * @param {number} [opts.downloadTimeout=0] + * @returns {Promise>} + */ + async * fetchContentWithFallback (cidPath, opts = {}) { + let lastError = null + // we use this to checkpoint at which chunk a request failed. + // this is temporary until range requests are supported. + let byteCountCheckpoint = 0 + + const fetchContent = async function * () { + let byteCount = 0 + const byteChunks = await this.fetchContent(cidPath, opts) + for await (const chunk of byteChunks) { + // avoid sending duplicate chunks + if (byteCount < byteCountCheckpoint) { + // checks for overlapping chunks + const remainingBytes = byteCountCheckpoint - byteCount + if (remainingBytes < chunk.length) { + yield chunk.slice(remainingBytes) + } + } else { + yield chunk + byteCountCheckpoint += chunk.length + } + byteCount += chunk.length + } + }.bind(this) + + if (this.nodes.length === 0) { + // fetch from origin in the case that no nodes are loaded + opts.url = this.opts.cdnURL + try { + yield * fetchContent() + return + } catch (err) { + lastError = err + await this.loadNodesPromise + } + } + + for (const origin of this.nodes) { + opts.url = origin.url + try { + yield * fetchContent() + return + } catch (err) { + lastError = err + } + } + + if (lastError) { + throw new Error(`All attempts to fetch content have failed. Last error: ${lastError.message}`) + } + } + + /** + * + * @param {string} cidPath + * @param {object} [opts={}] + * @param {('car'|'raw')} [opts.format] + * @param {number} [opts.connectTimeout=5000] + * @param {number} [opts.downloadTimeout=0] + * @returns {Promise>} + */ + async * fetchContent (cidPath, opts = {}) { + const { res, log } = await this.fetchCID(cidPath, opts) + + async function * metricsIterable (itr) { + log.numBytesSent = 0 + + for await (const chunk of itr) { + log.numBytesSent += chunk.length + yield chunk + } + } + + try { + const itr = metricsIterable(asAsyncIterable(res.body)) + yield * extractVerifiedContent(cidPath, itr) + } catch (err) { + log.error = err.message + throw err + } finally { + this._finalizeLog(log) + } + } + + /** + * + * @param {string} cidPath + * @param {object} [opts={}] + * @param {('car'|'raw')} [opts.format] + * @param {number} [opts.connectTimeout=5000] + * @param {number} [opts.downloadTimeout=0] + * @param origin + * @returns {Promise} + */ + async fetchContentBuffer (cidPath, opts = {}) { + return await asyncIteratorToBuffer(this.fetchContent(cidPath, opts)) + } + + async * extractVerifiedContent (cidPath, carStream) { + yield * extractVerifiedContent(cidPath, carStream) + } + + /** + * + * @param {string} cidPath + * @param {object} [opts={}] + * @returns {URL} + */ + createRequestURL (cidPath, opts) { + let origin = opts.url || opts.cdnURL + origin = addHttpPrefix(origin) + const url = new URL(`${origin}/ipfs/${cidPath}`) + + url.searchParams.set('format', opts.format) + if (opts.format === 'car') { + url.searchParams.set('dag-scope', 'entity') + } + + if (this.isBrowser) { + url.searchParams.set('jwt', opts.jwt) + } + + return url + } + + /** + * + * @param {object} log + */ + _finalizeLog (log) { + log.requestDurationSec = (new Date() - log.startTime) / 1000 + this.reportLogs(log) + } + + /** + * + * @param {object} log + */ + reportLogs (log) { + if (!this.reportingLogs) return + this.logs.push(log) + this.reportLogsTimeout && clearTimeout(this.reportLogsTimeout) + this.reportLogsTimeout = setTimeout(this._reportLogs.bind(this), 3_000) + } + + async _reportLogs () { + if (!this.logs.length) { + return + } + + const bandwidthLogs = this.hasPerformanceAPI + ? this._matchLogsWithPerformanceMetrics(this.logs) + : this.logs + + await fetch( + this.opts.logURL, + { + method: 'POST', + body: JSON.stringify({ bandwidthLogs, logSender: this.opts.logSender }) + } + ) + + this.logs = [] + this._clearPerformanceBuffer() + } + + /** + * + * @param {Array} logs + */ + _matchLogsWithPerformanceMetrics (logs) { + return logs + .map(log => ({ ...log, ...this._getPerformanceMetricsForLog(log) })) + .filter(log => !log.isFromBrowserCache) + .map(log => { + const { isFromBrowserCache: _, ...cleanLog } = log + return cleanLog + }) + } + + /** + * + * @param {object} log + * @returns {object} + */ + _getPerformanceMetricsForLog (log) { + const metrics = {} + + // URL is the best differentiator available, though there can be multiple entries per URL. + // It's a good enough heuristic. + const entry = performance + .getEntriesByType('resource') + .find((r) => r.name === log.url.href) + + if (entry) { + const dnsStart = entry.domainLookupStart + const dnsEnd = entry.domainLookupEnd + const hasDnsMetrics = dnsEnd > 0 && dnsStart > 0 + + if (hasDnsMetrics) { + metrics.dnsTimeMs = Math.round(dnsEnd - dnsStart) + metrics.ttfbAfterDnsMs = Math.round( + entry.responseStart - entry.requestStart + ) + } + + if (entry.nextHopProtocol) { + metrics.httpProtocol = entry.nextHopProtocol + } + + metrics.isFromBrowserCache = ( + entry.deliveryType === 'cache' || + (log.httpStatusCode && entry.transferSize === 0) + ) + } + + return metrics + } + + _monitorPerformanceBuffer () { + // Using static method prevents multiple unnecessary listeners. + performance.addEventListener('resourcetimingbufferfull', Saturn._setResourceBufferSize) + } + + static _setResourceBufferSize () { + const increment = 250 + const maxSize = 1000 + const size = performance.getEntriesByType('resource').length + const newSize = Math.min(size + increment, maxSize) + + performance.setResourceTimingBufferSize(newSize) + } + + _clearPerformanceBuffer () { + if (this.hasPerformanceAPI) { + performance.clearResourceTimings() + } + } + + async _loadNodes (opts) { + let origin = opts.orchURL + + let cacheNodesListPromise + if (this.storage) { + cacheNodesListPromise = this.storage.get(this.nodesListKey) + } + + origin = addHttpPrefix(origin) + + const url = new URL(origin) + const controller = new AbortController() + const options = Object.assign({}, { method: 'GET' }, this.opts) + + const connectTimeout = setTimeout(() => { + controller.abort() + }, options.connectTimeout) + + const orchResponse = await fetch(parseUrl(url), { signal: controller.signal, ...options }) + const orchNodesListPromise = orchResponse.json() + clearTimeout(connectTimeout) + + // This promise races fetching nodes list from the orchestrator and + // and the provided storage object (localStorage, sessionStorage, etc.) + // to insure we have a fallback set as quick as possible + let nodes + if (cacheNodesListPromise) { + nodes = await Promise.race([orchNodesListPromise, cacheNodesListPromise]) + } else { + nodes = await orchNodesListPromise + } + + // if storage returns first, update based on cached storage. + if (nodes === await cacheNodesListPromise) { + this.nodes = nodes + } + // we always want to update from the orchestrator regardless. + nodes = await orchNodesListPromise + this.nodes = nodes + cacheNodesListPromise && this.storage?.set(this.nodesListKey, nodes) + } +} + +export default Saturn diff --git a/src/index.js b/src/index.js index 356384a..e032132 100644 --- a/src/index.js +++ b/src/index.js @@ -1,398 +1,3 @@ -// @ts-check - -import { CID } from 'multiformats' - -import { extractVerifiedContent } from './utils/car.js' -import { asAsyncIterable, asyncIteratorToBuffer } from './utils/itr.js' -import { randomUUID } from './utils/uuid.js' -import { memoryStorage } from './storage/index.js' -import { getJWT } from './utils/jwt.js' -import { parseUrl, addHttpPrefix } from './utils/url.js' - -class Saturn { - /** - * - * @param {object} [opts={}] - * @param {string} [opts.clientKey] - * @param {string} [opts.clientId=randomUUID()] - * @param {string} [opts.cdnURL=saturn.ms] - * @param {number} [opts.connectTimeout=5000] - * @param {number} [opts.downloadTimeout=0] - * @param {string} [opts.orchURL] - * @param {import('./storage/index.js').Storage} [opts.storage] - */ - constructor (opts = {}) { - this.opts = Object.assign({}, { - clientId: randomUUID(), - cdnURL: 'saturn.ms', - logURL: 'https://twb3qukm2i654i3tnvx36char40aymqq.lambda-url.us-west-2.on.aws/', - orchURL: 'https://orchestrator.strn.pl/nodes?maxNodes=100', - authURL: 'https://saturn.auth', - connectTimeout: 5_000, - downloadTimeout: 0 - }, opts) - - if (!this.opts.clientKey) { - throw new Error('clientKey is required') - } - - this.logs = [] - this.nodes = [] - this.nodesListKey = 'saturn-nodes' - this.storage = this.opts.storage || memoryStorage() - this.reportingLogs = process?.env?.NODE_ENV !== 'development' - this.hasPerformanceAPI = typeof window !== 'undefined' && window?.performance - this.isBrowser = typeof window !== 'undefined' - if (this.reportingLogs && this.hasPerformanceAPI) { - this._monitorPerformanceBuffer() - } - - this.loadNodesPromise = this._loadNodes(this.opts) - } - - /** - * - * @param {string} cidPath - * @param {object} [opts={}] - * @param {('car'|'raw')} [opts.format] - * @param {number} [opts.connectTimeout=5000] - * @param {number} [opts.downloadTimeout=0] - * @returns {Promise} - */ - async fetchCID (cidPath, opts = {}) { - const [cid] = (cidPath ?? '').split('/') - CID.parse(cid) - const jwt = await getJWT(this.opts, this.storage) - const options = Object.assign({}, this.opts, { format: 'car', jwt }, opts) - const url = this.createRequestURL(cidPath, options) - const log = { - url, - startTime: new Date() - } - - const controller = new AbortController() - const connectTimeout = setTimeout(() => { - controller.abort() - }, options.connectTimeout) - - if (!this.isBrowser) { - options.headers = { - ...(options.headers || {}), - Authorization: 'Bearer ' + options.jwt - } - } - let res - try { - res = await fetch(parseUrl(url), { signal: controller.signal, ...options }) - - clearTimeout(connectTimeout) - - const { headers } = res - log.ttfbMs = new Date() - log.startTime - log.httpStatusCode = res.status - log.cacheHit = headers.get('saturn-cache-status') === 'HIT' - log.nodeId = headers.get('saturn-node-id') - log.requestId = headers.get('saturn-transfer-id') - log.httpProtocol = headers.get('quic-status') - - if (!res.ok) { - throw new Error( - `Non OK response received: ${res.status} ${res.statusText}` - ) - } - } catch (err) { - if (!res) { - log.error = err.message - } - // Report now if error, otherwise report after download is done. - this._finalizeLog(log) - - throw err - } - - return { res, log } - } - - async * fetchContentWithFallback (cidPath, opts = {}) { - let lastError = null - // we use this to checkpoint at which chunk a request failed. - // this is temporary until range requests are supported. - let byteCountCheckpoint = 0 - - const fetchContent = async function * () { - let byteCount = 0 - const byteChunks = await this.fetchContent(cidPath, opts) - for await (const chunk of byteChunks) { - // avoid sending duplicate chunks - if (byteCount < byteCountCheckpoint) { - // checks for overlapping chunks - const remainingBytes = byteCountCheckpoint - byteCount - if (remainingBytes < chunk.length) { - yield chunk.slice(remainingBytes) - } - } else { - yield chunk - byteCountCheckpoint += chunk.length - } - byteCount += chunk.length - } - }.bind(this) - - if (this.nodes.length === 0) { - // fetch from origin in the case that no nodes are loaded - opts.url = this.opts.cdnURL - try { - yield * fetchContent() - return - } catch (err) { - lastError = err - await this.loadNodesPromise - } - } - - for (const origin of this.nodes) { - opts.url = origin.url - try { - yield * fetchContent() - return - } catch (err) { - lastError = err - } - } - - if (lastError) { - throw new Error(`All attempts to fetch content have failed. Last error: ${lastError.message}`) - } - } - - /** - * - * @param {string} cidPath - * @param {object} [opts={}] - * @param {('car'|'raw')} [opts.format] - * @param {number} [opts.connectTimeout=5000] - * @param {number} [opts.downloadTimeout=0] - * @returns {Promise>} - */ - async * fetchContent (cidPath, opts = {}) { - const { res, log } = await this.fetchCID(cidPath, opts) - - async function * metricsIterable (itr) { - log.numBytesSent = 0 - - for await (const chunk of itr) { - log.numBytesSent += chunk.length - yield chunk - } - } - - try { - const itr = metricsIterable(asAsyncIterable(res.body)) - yield * extractVerifiedContent(cidPath, itr) - } catch (err) { - log.error = err.message - throw err - } finally { - this._finalizeLog(log) - } - } - - /** - * - * @param {string} cidPath - * @param {object} [opts={}] - * @param {('car'|'raw')} [opts.format] - * @param {number} [opts.connectTimeout=5000] - * @param {number} [opts.downloadTimeout=0] - * @param origin - * @returns {Promise} - */ - async fetchContentBuffer (cidPath, opts = {}) { - return await asyncIteratorToBuffer(this.fetchContent(cidPath, opts)) - } - - async * extractVerifiedContent (cidPath, carStream) { - yield * extractVerifiedContent(cidPath, carStream) - } - - /** - * - * @param {string} cidPath - * @param {object} [opts={}] - * @returns {URL} - */ - createRequestURL (cidPath, opts) { - let origin = opts.url || opts.cdnURL - origin = addHttpPrefix(origin) - const url = new URL(`${origin}/ipfs/${cidPath}`) - - url.searchParams.set('format', opts.format) - if (opts.format === 'car') { - url.searchParams.set('dag-scope', 'entity') - } - - if (this.isBrowser) { - url.searchParams.set('jwt', opts.jwt) - } - - return url - } - - /** - * - * @param {object} log - */ - _finalizeLog (log) { - log.requestDurationSec = (new Date() - log.startTime) / 1000 - this.reportLogs(log) - } - - /** - * - * @param {object} log - */ - reportLogs (log) { - if (!this.reportingLogs) return - this.logs.push(log) - this.reportLogsTimeout && clearTimeout(this.reportLogsTimeout) - this.reportLogsTimeout = setTimeout(this._reportLogs.bind(this), 3_000) - } - - async _reportLogs () { - if (!this.logs.length) { - return - } - - const bandwidthLogs = this.hasPerformanceAPI - ? this._matchLogsWithPerformanceMetrics(this.logs) - : this.logs - - await fetch( - this.opts.logURL, - { - method: 'POST', - body: JSON.stringify({ bandwidthLogs, logSender: this.opts.logSender }) - } - ) - - this.logs = [] - this._clearPerformanceBuffer() - } - - /** - * - * @param {Array} logs - */ - _matchLogsWithPerformanceMetrics (logs) { - return logs - .map(log => ({ ...log, ...this._getPerformanceMetricsForLog(log) })) - .filter(log => !log.isFromBrowserCache) - .map(log => { - const { isFromBrowserCache: _, ...cleanLog } = log - return cleanLog - }) - } - - /** - * - * @param {object} log - * @returns {object} - */ - _getPerformanceMetricsForLog (log) { - const metrics = {} - - // URL is the best differentiator available, though there can be multiple entries per URL. - // It's a good enough heuristic. - const entry = performance - .getEntriesByType('resource') - .find((r) => r.name === log.url.href) - - if (entry) { - const dnsStart = entry.domainLookupStart - const dnsEnd = entry.domainLookupEnd - const hasDnsMetrics = dnsEnd > 0 && dnsStart > 0 - - if (hasDnsMetrics) { - metrics.dnsTimeMs = Math.round(dnsEnd - dnsStart) - metrics.ttfbAfterDnsMs = Math.round( - entry.responseStart - entry.requestStart - ) - } - - if (entry.nextHopProtocol) { - metrics.httpProtocol = entry.nextHopProtocol - } - - metrics.isFromBrowserCache = ( - entry.deliveryType === 'cache' || - (log.httpStatusCode && entry.transferSize === 0) - ) - } - - return metrics - } - - _monitorPerformanceBuffer () { - // Using static method prevents multiple unnecessary listeners. - performance.addEventListener('resourcetimingbufferfull', Saturn._setResourceBufferSize) - } - - static _setResourceBufferSize () { - const increment = 250 - const maxSize = 1000 - const size = performance.getEntriesByType('resource').length - const newSize = Math.min(size + increment, maxSize) - - performance.setResourceTimingBufferSize(newSize) - } - - _clearPerformanceBuffer () { - if (this.hasPerformanceAPI) { - performance.clearResourceTimings() - } - } - - async _loadNodes (opts) { - let origin = opts.orchURL - - let cacheNodesListPromise - if (this.storage) { - cacheNodesListPromise = this.storage.get(this.nodesListKey) - } - - origin = addHttpPrefix(origin) - - const url = new URL(origin) - const controller = new AbortController() - const options = Object.assign({}, { method: 'GET' }, this.opts) - - const connectTimeout = setTimeout(() => { - controller.abort() - }, options.connectTimeout) - - const orchResponse = await fetch(parseUrl(url), { signal: controller.signal, ...options }) - const orchNodesListPromise = orchResponse.json() - clearTimeout(connectTimeout) - - // This promise races fetching nodes list from the orchestrator and - // and the provided storage object (localStorage, sessionStorage, etc.) - // to insure we have a fallback set as quick as possible - let nodes - if (cacheNodesListPromise) { - nodes = await Promise.race([orchNodesListPromise, cacheNodesListPromise]) - } else { - nodes = await orchNodesListPromise - } - - // if storage returns first, update based on cached storage. - if (nodes === await cacheNodesListPromise) { - this.nodes = nodes - } - // we always want to update from the orchestrator regardless. - nodes = await orchNodesListPromise - this.nodes = nodes - cacheNodesListPromise && this.storage?.set(this.nodesListKey, nodes) - } -} - -export default Saturn +export { Saturn } from './client.js' +export * from './storage/index.js' +export * from './utils/car.js' diff --git a/test/fallback.spec.js b/test/fallback.spec.js index 0237424..91ae952 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -2,7 +2,7 @@ import assert from 'node:assert/strict' import { describe, mock, test } from 'node:test' -import Saturn from '../src/index.js' +import { Saturn } from '#src/index.js' import { concatChunks, generateNodes, getMockServer, mockJWT, mockNodesHandlers, mockOrchHandler, mockSaturnOriginHandler, MSW_SERVER_OPTS } from './test-utils.js' const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' From a1ecd5071f6380cc751ff93abda1650206aa4f22 Mon Sep 17 00:00:00 2001 From: Amean Asad Date: Mon, 16 Oct 2023 10:09:10 -0400 Subject: [PATCH 22/34] feat: merge main into fallback branch (#22) * Abort on error (#19) * feat: use controller from options if exists. abort fetch if error occurs. * test: check if external abort controller is used * build: move build output to dist/ folder * fix: newline * 0.1.1 * Build exports (#20) * chore: rename file * feat: add new entrypoint with exports. Switch Saturn to named export * build: expose entire module instead of just the default export * docs: update README * 0.2.0 * feat: include worker scopes when checking for browser runtime (#21) * 0.3.0 --------- Co-authored-by: Eric Guan --- .gitignore | 1 + README.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/client.js | 27 +++++++++++++-------------- src/storage/indexed-db-storage.js | 2 +- src/utils/jwt.js | 2 +- src/utils/runtime.js | 15 +++++++++++++++ strn.min.js | 1 - test/fallback.spec.js | 13 +++++++------ test/index.spec.js | 22 +++++++++++++++++----- webpack.config.cjs | 5 ++--- 12 files changed, 61 insertions(+), 35 deletions(-) create mode 100644 src/utils/runtime.js delete mode 100644 strn.min.js diff --git a/.gitignore b/.gitignore index c2658d7..b947077 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules/ +dist/ diff --git a/README.md b/README.md index 534c4da..29609ac 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ npm install @filecoin-saturn/js-client ## Usage ```js -import Saturn from '@filecoin-saturn/js-client' +import { Saturn } from '@filecoin-saturn/js-client' const client = new Saturn() diff --git a/package-lock.json b/package-lock.json index ff38489..50191c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@filecoin-saturn/js-client", - "version": "0.1.0", + "version": "0.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@filecoin-saturn/js-client", - "version": "0.1.0", + "version": "0.3.0", "license": "(MIT OR Apache-2.0)", "dependencies": { "@ipld/car": "^4.1.5", diff --git a/package.json b/package.json index e3efdc8..fd92aa9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@filecoin-saturn/js-client", - "version": "0.1.0", + "version": "0.3.0", "description": "Filecoin Saturn Client", "homepage": "https://github.com/filecoin-saturn/js-client", "main": "src/index.js", diff --git a/src/client.js b/src/client.js index b61f305..87a3a3f 100644 --- a/src/client.js +++ b/src/client.js @@ -8,6 +8,7 @@ import { randomUUID } from './utils/uuid.js' import { memoryStorage } from './storage/index.js' import { getJWT } from './utils/jwt.js' import { parseUrl, addHttpPrefix } from './utils/url.js' +import { isBrowserContext } from './utils/runtime.js' export class Saturn { /** @@ -27,7 +28,7 @@ export class Saturn { cdnURL: 'saturn.ms', logURL: 'https://twb3qukm2i654i3tnvx36char40aymqq.lambda-url.us-west-2.on.aws/', orchURL: 'https://orchestrator.strn.pl/nodes?maxNodes=100', - authURL: 'https://saturn.auth', + authURL: 'https://fz3dyeyxmebszwhuiky7vggmsu0rlkoy.lambda-url.us-west-2.on.aws/', connectTimeout: 5_000, downloadTimeout: 0 }, opts) @@ -46,7 +47,7 @@ export class Saturn { if (this.reportingLogs && this.hasPerformanceAPI) { this._monitorPerformanceBuffer() } - + this.storage = this.opts.storage || memoryStorage() this.loadNodesPromise = this._loadNodes(this.opts) } @@ -62,20 +63,23 @@ export class Saturn { async fetchCID (cidPath, opts = {}) { const [cid] = (cidPath ?? '').split('/') CID.parse(cid) + const jwt = await getJWT(this.opts, this.storage) + const options = Object.assign({}, this.opts, { format: 'car', jwt }, opts) const url = this.createRequestURL(cidPath, options) + const log = { url, startTime: new Date() } - const controller = new AbortController() + const controller = options.controller ?? new AbortController() const connectTimeout = setTimeout(() => { controller.abort() }, options.connectTimeout) - if (!this.isBrowser) { + if (!isBrowserContext) { options.headers = { ...(options.headers || {}), Authorization: 'Bearer ' + options.jwt @@ -110,7 +114,7 @@ export class Saturn { throw err } - return { res, log } + return { res, controller, log } } /** @@ -185,7 +189,7 @@ export class Saturn { * @returns {Promise>} */ async * fetchContent (cidPath, opts = {}) { - const { res, log } = await this.fetchCID(cidPath, opts) + const { res, controller, log } = await this.fetchCID(cidPath, opts) async function * metricsIterable (itr) { log.numBytesSent = 0 @@ -201,6 +205,8 @@ export class Saturn { yield * extractVerifiedContent(cidPath, itr) } catch (err) { log.error = err.message + controller.abort() + throw err } finally { this._finalizeLog(log) @@ -214,17 +220,12 @@ export class Saturn { * @param {('car'|'raw')} [opts.format] * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] - * @param origin * @returns {Promise} */ async fetchContentBuffer (cidPath, opts = {}) { return await asyncIteratorToBuffer(this.fetchContent(cidPath, opts)) } - async * extractVerifiedContent (cidPath, carStream) { - yield * extractVerifiedContent(cidPath, carStream) - } - /** * * @param {string} cidPath @@ -241,7 +242,7 @@ export class Saturn { url.searchParams.set('dag-scope', 'entity') } - if (this.isBrowser) { + if (isBrowserContext) { url.searchParams.set('jwt', opts.jwt) } @@ -404,5 +405,3 @@ export class Saturn { cacheNodesListPromise && this.storage?.set(this.nodesListKey, nodes) } } - -export default Saturn diff --git a/src/storage/indexed-db-storage.js b/src/storage/indexed-db-storage.js index 477ff1d..fa2437b 100644 --- a/src/storage/indexed-db-storage.js +++ b/src/storage/indexed-db-storage.js @@ -11,7 +11,7 @@ const DEFAULT_SATURN_STORAGE_NAME = 'saturn-client' * @returns {import('./index.js').Storage} */ export function indexedDbStorage () { - const indexedDbExists = (typeof window !== 'undefined') && window?.indexedDB + const indexedDbExists = (typeof self !== 'undefined') && self?.indexedDB let dbPromise if (indexedDbExists) { dbPromise = openDB(DEFAULT_IDB_STORAGE_NAME, DEFAULT_IDB_VERSION, { diff --git a/src/utils/jwt.js b/src/utils/jwt.js index ca72262..522a6a7 100644 --- a/src/utils/jwt.js +++ b/src/utils/jwt.js @@ -16,7 +16,7 @@ export function isJwtValid (jwt) { * @param {object} opts * @param {string} opts.clientKey * @param {string} opts.authURL - * @param {import('./utils/storage.js').Storage} storage + * @param {import('../storage/index.js').Storage} storage * @returns {Promise} */ export async function getJWT (opts, storage) { diff --git a/src/utils/runtime.js b/src/utils/runtime.js new file mode 100644 index 0000000..1f7c69f --- /dev/null +++ b/src/utils/runtime.js @@ -0,0 +1,15 @@ +export const isBrowser = + typeof window !== 'undefined' && typeof window.document !== 'undefined' + +export const isServiceWorker = typeof ServiceWorkerGlobalScope !== 'undefined' + +export const isWebWorker = typeof DedicatedWorkerGlobalScope !== 'undefined' + +export const isSharedWorker = typeof SharedWorkerGlobalScope !== 'undefined' + +export const isBrowserContext = isBrowser || isServiceWorker || isWebWorker || isSharedWorker + +export const isNode = + typeof process !== 'undefined' && + process.versions != null && + process.versions.node != null diff --git a/strn.min.js b/strn.min.js deleted file mode 100644 index 184436d..0000000 --- a/strn.min.js +++ /dev/null @@ -1 +0,0 @@ -var Saturn;(()=>{var __webpack_modules__={537:e=>{"use strict";e.exports=function(e,t){for(var r=new Array(arguments.length-1),n=0,o=2,i=!0;o{"use strict";var r=t;r.length=function(e){var t=e.length;if(!t)return 0;for(var r=0;--t%4>1&&"="===e.charAt(t);)++r;return Math.ceil(3*e.length)/4-r};for(var n=new Array(64),o=new Array(123),i=0;i<64;)o[n[i]=i<26?i+65:i<52?i+71:i<62?i-4:i-59|43]=i++;r.encode=function(e,t,r){for(var o,i=null,s=[],a=0,c=0;t>2],o=(3&u)<<4,c=1;break;case 1:s[a++]=n[o|u>>4],o=(15&u)<<2,c=2;break;case 2:s[a++]=n[o|u>>6],s[a++]=n[63&u],c=0}a>8191&&((i||(i=[])).push(String.fromCharCode.apply(String,s)),a=0)}return c&&(s[a++]=n[o],s[a++]=61,1===c&&(s[a++]=61)),i?(a&&i.push(String.fromCharCode.apply(String,s.slice(0,a))),i.join("")):String.fromCharCode.apply(String,s.slice(0,a))};var s="invalid encoding";r.decode=function(e,t,r){for(var n,i=r,a=0,c=0;c1)break;if(void 0===(u=o[u]))throw Error(s);switch(a){case 0:n=u,a=1;break;case 1:t[r++]=n<<2|(48&u)>>4,n=u,a=2;break;case 2:t[r++]=(15&n)<<4|(60&u)>>2,n=u,a=3;break;case 3:t[r++]=(3&n)<<6|u,a=0}}if(1===a)throw Error(s);return r-i},r.test=function(e){return/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)}},211:e=>{"use strict";function t(){this._listeners={}}e.exports=t,t.prototype.on=function(e,t,r){return(this._listeners[e]||(this._listeners[e]=[])).push({fn:t,ctx:r||this}),this},t.prototype.off=function(e,t){if(void 0===e)this._listeners={};else if(void 0===t)this._listeners[e]=[];else for(var r=this._listeners[e],n=0;n{"use strict";function t(e){return"undefined"!=typeof Float32Array?function(){var t=new Float32Array([-0]),r=new Uint8Array(t.buffer),n=128===r[3];function o(e,n,o){t[0]=e,n[o]=r[0],n[o+1]=r[1],n[o+2]=r[2],n[o+3]=r[3]}function i(e,n,o){t[0]=e,n[o]=r[3],n[o+1]=r[2],n[o+2]=r[1],n[o+3]=r[0]}function s(e,n){return r[0]=e[n],r[1]=e[n+1],r[2]=e[n+2],r[3]=e[n+3],t[0]}function a(e,n){return r[3]=e[n],r[2]=e[n+1],r[1]=e[n+2],r[0]=e[n+3],t[0]}e.writeFloatLE=n?o:i,e.writeFloatBE=n?i:o,e.readFloatLE=n?s:a,e.readFloatBE=n?a:s}():function(){function t(e,t,r,n){var o=t<0?1:0;if(o&&(t=-t),0===t)e(1/t>0?0:2147483648,r,n);else if(isNaN(t))e(2143289344,r,n);else if(t>34028234663852886e22)e((o<<31|2139095040)>>>0,r,n);else if(t<11754943508222875e-54)e((o<<31|Math.round(t/1401298464324817e-60))>>>0,r,n);else{var i=Math.floor(Math.log(t)/Math.LN2);e((o<<31|i+127<<23|8388607&Math.round(t*Math.pow(2,-i)*8388608))>>>0,r,n)}}function s(e,t,r){var n=e(t,r),o=2*(n>>31)+1,i=n>>>23&255,s=8388607&n;return 255===i?s?NaN:o*(1/0):0===i?1401298464324817e-60*o*s:o*Math.pow(2,i-150)*(s+8388608)}e.writeFloatLE=t.bind(null,r),e.writeFloatBE=t.bind(null,n),e.readFloatLE=s.bind(null,o),e.readFloatBE=s.bind(null,i)}(),"undefined"!=typeof Float64Array?function(){var t=new Float64Array([-0]),r=new Uint8Array(t.buffer),n=128===r[7];function o(e,n,o){t[0]=e,n[o]=r[0],n[o+1]=r[1],n[o+2]=r[2],n[o+3]=r[3],n[o+4]=r[4],n[o+5]=r[5],n[o+6]=r[6],n[o+7]=r[7]}function i(e,n,o){t[0]=e,n[o]=r[7],n[o+1]=r[6],n[o+2]=r[5],n[o+3]=r[4],n[o+4]=r[3],n[o+5]=r[2],n[o+6]=r[1],n[o+7]=r[0]}function s(e,n){return r[0]=e[n],r[1]=e[n+1],r[2]=e[n+2],r[3]=e[n+3],r[4]=e[n+4],r[5]=e[n+5],r[6]=e[n+6],r[7]=e[n+7],t[0]}function a(e,n){return r[7]=e[n],r[6]=e[n+1],r[5]=e[n+2],r[4]=e[n+3],r[3]=e[n+4],r[2]=e[n+5],r[1]=e[n+6],r[0]=e[n+7],t[0]}e.writeDoubleLE=n?o:i,e.writeDoubleBE=n?i:o,e.readDoubleLE=n?s:a,e.readDoubleBE=n?a:s}():function(){function t(e,t,r,n,o,i){var s=n<0?1:0;if(s&&(n=-n),0===n)e(0,o,i+t),e(1/n>0?0:2147483648,o,i+r);else if(isNaN(n))e(0,o,i+t),e(2146959360,o,i+r);else if(n>17976931348623157e292)e(0,o,i+t),e((s<<31|2146435072)>>>0,o,i+r);else{var a;if(n<22250738585072014e-324)e((a=n/5e-324)>>>0,o,i+t),e((s<<31|a/4294967296)>>>0,o,i+r);else{var c=Math.floor(Math.log(n)/Math.LN2);1024===c&&(c=1023),e(4503599627370496*(a=n*Math.pow(2,-c))>>>0,o,i+t),e((s<<31|c+1023<<20|1048576*a&1048575)>>>0,o,i+r)}}}function s(e,t,r,n,o){var i=e(n,o+t),s=e(n,o+r),a=2*(s>>31)+1,c=s>>>20&2047,u=4294967296*(1048575&s)+i;return 2047===c?u?NaN:a*(1/0):0===c?5e-324*a*u:a*Math.pow(2,c-1075)*(u+4503599627370496)}e.writeDoubleLE=t.bind(null,r,0,4),e.writeDoubleBE=t.bind(null,n,4,0),e.readDoubleLE=s.bind(null,o,0,4),e.readDoubleBE=s.bind(null,i,4,0)}(),e}function r(e,t,r){t[r]=255&e,t[r+1]=e>>>8&255,t[r+2]=e>>>16&255,t[r+3]=e>>>24}function n(e,t,r){t[r]=e>>>24,t[r+1]=e>>>16&255,t[r+2]=e>>>8&255,t[r+3]=255&e}function o(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0}function i(e,t){return(e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3])>>>0}e.exports=t(t)},199:module=>{"use strict";function inquire(moduleName){try{var mod=eval("quire".replace(/^/,"re"))(moduleName);if(mod&&(mod.length||Object.keys(mod).length))return mod}catch(e){}return null}module.exports=inquire},662:e=>{"use strict";e.exports=function(e,t,r){var n=r||8192,o=n>>>1,i=null,s=n;return function(r){if(r<1||r>o)return e(r);s+r>n&&(i=e(n),s=0);var a=t.call(i,s,s+=r);return 7&s&&(s=1+(7|s)),a}}},997:(e,t)=>{"use strict";var r=t;r.length=function(e){for(var t=0,r=0,n=0;n191&&n<224?i[s++]=(31&n)<<6|63&e[t++]:n>239&&n<365?(n=((7&n)<<18|(63&e[t++])<<12|(63&e[t++])<<6|63&e[t++])-65536,i[s++]=55296+(n>>10),i[s++]=56320+(1023&n)):i[s++]=(15&n)<<12|(63&e[t++])<<6|63&e[t++],s>8191&&((o||(o=[])).push(String.fromCharCode.apply(String,i)),s=0);return o?(s&&o.push(String.fromCharCode.apply(String,i.slice(0,s))),o.join("")):String.fromCharCode.apply(String,i.slice(0,s))},r.write=function(e,t,r){for(var n,o,i=r,s=0;s>6|192,t[r++]=63&n|128):55296==(64512&n)&&56320==(64512&(o=e.charCodeAt(s+1)))?(n=65536+((1023&n)<<10)+(1023&o),++s,t[r++]=n>>18|240,t[r++]=n>>12&63|128,t[r++]=n>>6&63|128,t[r++]=63&n|128):(t[r++]=n>>12|224,t[r++]=n>>6&63|128,t[r++]=63&n|128);return r-i}},442:(e,t,r)=>{const n=r(488);function o(e,t,r){const n=e[t]+e[r];let o=e[t+1]+e[r+1];n>=4294967296&&o++,e[t]=n,e[t+1]=o}function i(e,t,r,n){let o=e[t]+r;r<0&&(o+=4294967296);let i=e[t+1]+n;o>=4294967296&&i++,e[t]=o,e[t+1]=i}function s(e,t){return e[t]^e[t+1]<<8^e[t+2]<<16^e[t+3]<<24}function a(e,t,r,n,s,a){const c=f[s],u=f[s+1],l=f[a],d=f[a+1];o(h,e,t),i(h,e,c,u);let p=h[n]^h[e],w=h[n+1]^h[e+1];h[n]=w,h[n+1]=p,o(h,r,n),p=h[t]^h[r],w=h[t+1]^h[r+1],h[t]=p>>>24^w<<8,h[t+1]=w>>>24^p<<8,o(h,e,t),i(h,e,l,d),p=h[n]^h[e],w=h[n+1]^h[e+1],h[n]=p>>>16^w<<16,h[n+1]=w>>>16^p<<16,o(h,r,n),p=h[t]^h[r],w=h[t+1]^h[r+1],h[t]=w>>>31^p<<1,h[t+1]=p>>>31^w<<1}const c=new Uint32Array([4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225]),u=new Uint8Array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3].map((function(e){return 2*e}))),h=new Uint32Array(32),f=new Uint32Array(32);function l(e,t){let r=0;for(r=0;r<16;r++)h[r]=e.h[r],h[r+16]=c[r];for(h[24]=h[24]^e.t,h[25]=h[25]^e.t/4294967296,t&&(h[28]=~h[28],h[29]=~h[29]),r=0;r<32;r++)f[r]=s(e.b,4*r);for(r=0;r<12;r++)a(0,8,16,24,u[16*r+0],u[16*r+1]),a(2,10,18,26,u[16*r+2],u[16*r+3]),a(4,12,20,28,u[16*r+4],u[16*r+5]),a(6,14,22,30,u[16*r+6],u[16*r+7]),a(0,10,20,30,u[16*r+8],u[16*r+9]),a(2,12,22,24,u[16*r+10],u[16*r+11]),a(4,14,16,26,u[16*r+12],u[16*r+13]),a(6,8,18,28,u[16*r+14],u[16*r+15]);for(r=0;r<16;r++)e.h[r]=e.h[r]^h[r]^h[r+16]}const d=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);function p(e,t,r,n){if(0===e||e>64)throw new Error("Illegal output length, expected 0 < length <= 64");if(t&&t.length>64)throw new Error("Illegal key, expected Uint8Array with 0 < length <= 64");if(r&&16!==r.length)throw new Error("Illegal salt, expected Uint8Array with length is 16");if(n&&16!==n.length)throw new Error("Illegal personal, expected Uint8Array with length is 16");const o={b:new Uint8Array(128),h:new Uint32Array(16),t:0,c:0,outlen:e};d.fill(0),d[0]=e,t&&(d[1]=t.length),d[2]=1,d[3]=1,r&&d.set(r,32),n&&d.set(n,48);for(let e=0;e<16;e++)o.h[e]=c[e]^s(d,4*e);return t&&(w(o,t),o.c=128),o}function w(e,t){for(let r=0;r>2]>>8*(3&r);return t}function y(e,t,r,o,i){r=r||64,e=n.normalizeInput(e),o&&(o=n.normalizeInput(o)),i&&(i=n.normalizeInput(i));const s=p(r,t,o,i);return w(s,e),b(s)}e.exports={blake2b:y,blake2bHex:function(e,t,r,o,i){const s=y(e,t,r,o,i);return n.toHex(s)},blake2bInit:p,blake2bUpdate:w,blake2bFinal:b}},297:(e,t,r)=>{const n=r(488);function o(e,t){return e[t]^e[t+1]<<8^e[t+2]<<16^e[t+3]<<24}function i(e,t,r,n,o,i){u[e]=u[e]+u[t]+o,u[n]=s(u[n]^u[e],16),u[r]=u[r]+u[n],u[t]=s(u[t]^u[r],12),u[e]=u[e]+u[t]+i,u[n]=s(u[n]^u[e],8),u[r]=u[r]+u[n],u[t]=s(u[t]^u[r],7)}function s(e,t){return e>>>t^e<<32-t}const a=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),c=new Uint8Array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0]),u=new Uint32Array(16),h=new Uint32Array(16);function f(e,t){let r=0;for(r=0;r<8;r++)u[r]=e.h[r],u[r+8]=a[r];for(u[12]^=e.t,u[13]^=e.t/4294967296,t&&(u[14]=~u[14]),r=0;r<16;r++)h[r]=o(e.b,4*r);for(r=0;r<10;r++)i(0,4,8,12,h[c[16*r+0]],h[c[16*r+1]]),i(1,5,9,13,h[c[16*r+2]],h[c[16*r+3]]),i(2,6,10,14,h[c[16*r+4]],h[c[16*r+5]]),i(3,7,11,15,h[c[16*r+6]],h[c[16*r+7]]),i(0,5,10,15,h[c[16*r+8]],h[c[16*r+9]]),i(1,6,11,12,h[c[16*r+10]],h[c[16*r+11]]),i(2,7,8,13,h[c[16*r+12]],h[c[16*r+13]]),i(3,4,9,14,h[c[16*r+14]],h[c[16*r+15]]);for(r=0;r<8;r++)e.h[r]^=u[r]^u[r+8]}function l(e,t){if(!(e>0&&e<=32))throw new Error("Incorrect output length, should be in [1, 32]");const r=t?t.length:0;if(t&&!(r>0&&r<=32))throw new Error("Incorrect key length, should be in [1, 32]");const n={h:new Uint32Array(a),b:new Uint8Array(64),c:0,t:0,outlen:e};return n.h[0]^=16842752^r<<8^e,r>0&&(d(n,t),n.c=64),n}function d(e,t){for(let r=0;r>2]>>8*(3&r)&255;return t}function w(e,t,r){r=r||32,e=n.normalizeInput(e);const o=l(r,t);return d(o,e),p(o)}e.exports={blake2s:w,blake2sHex:function(e,t,r){const o=w(e,t,r);return n.toHex(o)},blake2sInit:l,blake2sUpdate:d,blake2sFinal:p}},191:(e,t,r)=>{const n=r(442),o=r(297);e.exports={blake2b:n.blake2b,blake2bHex:n.blake2bHex,blake2bInit:n.blake2bInit,blake2bUpdate:n.blake2bUpdate,blake2bFinal:n.blake2bFinal,blake2s:o.blake2s,blake2sHex:o.blake2sHex,blake2sInit:o.blake2sInit,blake2sUpdate:o.blake2sUpdate,blake2sFinal:o.blake2sFinal}},488:e=>{function t(e){return(4294967296+e).toString(16).substring(1)}e.exports={normalizeInput:function(e){let t;if(e instanceof Uint8Array)t=e;else{if("string"!=typeof e)throw new Error("Input must be an string, Buffer or Uint8Array");t=(new TextEncoder).encode(e)}return t},toHex:function(e){return Array.prototype.map.call(e,(function(e){return(e<16?"0":"")+e.toString(16)})).join("")},debugPrint:function(e,r,n){let o="\n"+e+" = ";for(let i=0;i{"use strict";function t(e,t){for(const r in t)Object.defineProperty(e,r,{value:t[r],enumerable:!0,configurable:!0});return e}e.exports=function(e,r,n){if(!e||"string"==typeof e)throw new TypeError("Please pass an Error to err-code");n||(n={}),"object"==typeof r&&(n=r,r=""),r&&(n.code=r);try{return t(e,n)}catch(r){n.message=e.message,n.stack=e.stack;const o=function(){};return o.prototype=Object.create(Object.getPrototypeOf(e)),t(new o,n)}}},729:e=>{"use strict";var t=Object.prototype.hasOwnProperty,r="~";function n(){}function o(e,t,r){this.fn=e,this.context=t,this.once=r||!1}function i(e,t,n,i,s){if("function"!=typeof n)throw new TypeError("The listener must be a function");var a=new o(n,i||e,s),c=r?r+t:t;return e._events[c]?e._events[c].fn?e._events[c]=[e._events[c],a]:e._events[c].push(a):(e._events[c]=a,e._eventsCount++),e}function s(e,t){0==--e._eventsCount?e._events=new n:delete e._events[t]}function a(){this._events=new n,this._eventsCount=0}Object.create&&(n.prototype=Object.create(null),(new n).__proto__||(r=!1)),a.prototype.eventNames=function(){var e,n,o=[];if(0===this._eventsCount)return o;for(n in e=this._events)t.call(e,n)&&o.push(r?n.slice(1):n);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(e)):o},a.prototype.listeners=function(e){var t=r?r+e:e,n=this._events[t];if(!n)return[];if(n.fn)return[n.fn];for(var o=0,i=n.length,s=new Array(i);o{e.exports=r(27)},27:function(e,t){!function(r,n){"use strict";var o={version:"3.0.0",x86:{},x64:{},inputValidation:!0};function i(e){if(!Array.isArray(e)&&!ArrayBuffer.isView(e))return!1;for(var t=0;t255)return!1;return!0}function s(e,t){return(65535&e)*t+(((e>>>16)*t&65535)<<16)}function a(e,t){return e<>>32-t}function c(e){return e=s(e^=e>>>16,2246822507),(e=s(e^=e>>>13,3266489909))^e>>>16}function u(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var r=[0,0,0,0];return r[3]+=e[3]+t[3],r[2]+=r[3]>>>16,r[3]&=65535,r[2]+=e[2]+t[2],r[1]+=r[2]>>>16,r[2]&=65535,r[1]+=e[1]+t[1],r[0]+=r[1]>>>16,r[1]&=65535,r[0]+=e[0]+t[0],r[0]&=65535,[r[0]<<16|r[1],r[2]<<16|r[3]]}function h(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var r=[0,0,0,0];return r[3]+=e[3]*t[3],r[2]+=r[3]>>>16,r[3]&=65535,r[2]+=e[2]*t[3],r[1]+=r[2]>>>16,r[2]&=65535,r[2]+=e[3]*t[2],r[1]+=r[2]>>>16,r[2]&=65535,r[1]+=e[1]*t[3],r[0]+=r[1]>>>16,r[1]&=65535,r[1]+=e[2]*t[2],r[0]+=r[1]>>>16,r[1]&=65535,r[1]+=e[3]*t[1],r[0]+=r[1]>>>16,r[1]&=65535,r[0]+=e[0]*t[3]+e[1]*t[2]+e[2]*t[1]+e[3]*t[0],r[0]&=65535,[r[0]<<16|r[1],r[2]<<16|r[3]]}function f(e,t){return 32==(t%=64)?[e[1],e[0]]:t<32?[e[0]<>>32-t,e[1]<>>32-t]:(t-=32,[e[1]<>>32-t,e[0]<>>32-t])}function l(e,t){return 0==(t%=64)?e:t<32?[e[0]<>>32-t,e[1]<>>1]),e=d(e=h(e,[4283543511,3981806797]),[0,e[0]>>>1]),d(e=h(e,[3301882366,444984403]),[0,e[0]>>>1])}o.x86.hash32=function(e,t){if(o.inputValidation&&!i(e))return n;t=t||0;for(var r=e.length%4,u=e.length-r,h=t,f=0,l=3432918353,d=461845907,p=0;p>>0},o.x86.hash128=function(e,t){if(o.inputValidation&&!i(e))return n;t=t||0;for(var r=e.length%16,u=e.length-r,h=t,f=t,l=t,d=t,p=0,w=0,b=0,y=0,g=597399067,m=2869860233,v=951274213,_=2716044179,k=0;k>>0).toString(16)).slice(-8)+("00000000"+(f>>>0).toString(16)).slice(-8)+("00000000"+(l>>>0).toString(16)).slice(-8)+("00000000"+(d>>>0).toString(16)).slice(-8)},o.x64.hash128=function(e,t){if(o.inputValidation&&!i(e))return n;t=t||0;for(var r=e.length%16,s=e.length-r,a=[0,t],c=[0,t],w=[0,0],b=[0,0],y=[2277735313,289559509],g=[1291169091,658871167],m=0;m>>0).toString(16)).slice(-8)+("00000000"+(a[1]>>>0).toString(16)).slice(-8)+("00000000"+(c[0]>>>0).toString(16)).slice(-8)+("00000000"+(c[1]>>>0).toString(16)).slice(-8)},e.exports&&(t=e.exports=o),t.murmurHash3=o}()},408:(e,t,r)=>{"use strict";e.exports=c;var n,o=r(693),i=o.LongBits,s=o.utf8;function a(e,t){return RangeError("index out of range: "+e.pos+" + "+(t||1)+" > "+e.len)}function c(e){this.buf=e,this.pos=0,this.len=e.length}var u,h="undefined"!=typeof Uint8Array?function(e){if(e instanceof Uint8Array||Array.isArray(e))return new c(e);throw Error("illegal buffer")}:function(e){if(Array.isArray(e))return new c(e);throw Error("illegal buffer")},f=function(){return o.Buffer?function(e){return(c.create=function(e){return o.Buffer.isBuffer(e)?new n(e):h(e)})(e)}:h};function l(){var e=new i(0,0),t=0;if(!(this.len-this.pos>4)){for(;t<3;++t){if(this.pos>=this.len)throw a(this);if(e.lo=(e.lo|(127&this.buf[this.pos])<<7*t)>>>0,this.buf[this.pos++]<128)return e}return e.lo=(e.lo|(127&this.buf[this.pos++])<<7*t)>>>0,e}for(;t<4;++t)if(e.lo=(e.lo|(127&this.buf[this.pos])<<7*t)>>>0,this.buf[this.pos++]<128)return e;if(e.lo=(e.lo|(127&this.buf[this.pos])<<28)>>>0,e.hi=(e.hi|(127&this.buf[this.pos])>>4)>>>0,this.buf[this.pos++]<128)return e;if(t=0,this.len-this.pos>4){for(;t<5;++t)if(e.hi=(e.hi|(127&this.buf[this.pos])<<7*t+3)>>>0,this.buf[this.pos++]<128)return e}else for(;t<5;++t){if(this.pos>=this.len)throw a(this);if(e.hi=(e.hi|(127&this.buf[this.pos])<<7*t+3)>>>0,this.buf[this.pos++]<128)return e}throw Error("invalid varint encoding")}function d(e,t){return(e[t-4]|e[t-3]<<8|e[t-2]<<16|e[t-1]<<24)>>>0}function p(){if(this.pos+8>this.len)throw a(this,8);return new i(d(this.buf,this.pos+=4),d(this.buf,this.pos+=4))}c.create=f(),c.prototype._slice=o.Array.prototype.subarray||o.Array.prototype.slice,c.prototype.uint32=(u=4294967295,function(){if(u=(127&this.buf[this.pos])>>>0,this.buf[this.pos++]<128)return u;if(u=(u|(127&this.buf[this.pos])<<7)>>>0,this.buf[this.pos++]<128)return u;if(u=(u|(127&this.buf[this.pos])<<14)>>>0,this.buf[this.pos++]<128)return u;if(u=(u|(127&this.buf[this.pos])<<21)>>>0,this.buf[this.pos++]<128)return u;if(u=(u|(15&this.buf[this.pos])<<28)>>>0,this.buf[this.pos++]<128)return u;if((this.pos+=5)>this.len)throw this.pos=this.len,a(this,10);return u}),c.prototype.int32=function(){return 0|this.uint32()},c.prototype.sint32=function(){var e=this.uint32();return e>>>1^-(1&e)|0},c.prototype.bool=function(){return 0!==this.uint32()},c.prototype.fixed32=function(){if(this.pos+4>this.len)throw a(this,4);return d(this.buf,this.pos+=4)},c.prototype.sfixed32=function(){if(this.pos+4>this.len)throw a(this,4);return 0|d(this.buf,this.pos+=4)},c.prototype.float=function(){if(this.pos+4>this.len)throw a(this,4);var e=o.float.readFloatLE(this.buf,this.pos);return this.pos+=4,e},c.prototype.double=function(){if(this.pos+8>this.len)throw a(this,4);var e=o.float.readDoubleLE(this.buf,this.pos);return this.pos+=8,e},c.prototype.bytes=function(){var e=this.uint32(),t=this.pos,r=this.pos+e;if(r>this.len)throw a(this,e);if(this.pos+=e,Array.isArray(this.buf))return this.buf.slice(t,r);if(t===r){var n=o.Buffer;return n?n.alloc(0):new this.buf.constructor(0)}return this._slice.call(this.buf,t,r)},c.prototype.string=function(){var e=this.bytes();return s.read(e,0,e.length)},c.prototype.skip=function(e){if("number"==typeof e){if(this.pos+e>this.len)throw a(this,e);this.pos+=e}else do{if(this.pos>=this.len)throw a(this)}while(128&this.buf[this.pos++]);return this},c.prototype.skipType=function(e){switch(e){case 0:this.skip();break;case 1:this.skip(8);break;case 2:this.skip(this.uint32());break;case 3:for(;4!=(e=7&this.uint32());)this.skipType(e);break;case 5:this.skip(4);break;default:throw Error("invalid wire type "+e+" at offset "+this.pos)}return this},c._configure=function(e){n=e,c.create=f(),n._configure();var t=o.Long?"toLong":"toNumber";o.merge(c.prototype,{int64:function(){return l.call(this)[t](!1)},uint64:function(){return l.call(this)[t](!0)},sint64:function(){return l.call(this).zzDecode()[t](!1)},fixed64:function(){return p.call(this)[t](!0)},sfixed64:function(){return p.call(this)[t](!1)}})}},593:(e,t,r)=>{"use strict";e.exports=i;var n=r(408);(i.prototype=Object.create(n.prototype)).constructor=i;var o=r(693);function i(e){n.call(this,e)}i._configure=function(){o.Buffer&&(i.prototype._slice=o.Buffer.prototype.slice)},i.prototype.string=function(){var e=this.uint32();return this.buf.utf8Slice?this.buf.utf8Slice(this.pos,this.pos=Math.min(this.pos+e,this.len)):this.buf.toString("utf-8",this.pos,this.pos=Math.min(this.pos+e,this.len))},i._configure()},630:(e,t,r)=>{"use strict";e.exports=o;var n=r(693);function o(e,t){this.lo=e>>>0,this.hi=t>>>0}var i=o.zero=new o(0,0);i.toNumber=function(){return 0},i.zzEncode=i.zzDecode=function(){return this},i.length=function(){return 1};var s=o.zeroHash="\0\0\0\0\0\0\0\0";o.fromNumber=function(e){if(0===e)return i;var t=e<0;t&&(e=-e);var r=e>>>0,n=(e-r)/4294967296>>>0;return t&&(n=~n>>>0,r=~r>>>0,++r>4294967295&&(r=0,++n>4294967295&&(n=0))),new o(r,n)},o.from=function(e){if("number"==typeof e)return o.fromNumber(e);if(n.isString(e)){if(!n.Long)return o.fromNumber(parseInt(e,10));e=n.Long.fromString(e)}return e.low||e.high?new o(e.low>>>0,e.high>>>0):i},o.prototype.toNumber=function(e){if(!e&&this.hi>>>31){var t=1+~this.lo>>>0,r=~this.hi>>>0;return t||(r=r+1>>>0),-(t+4294967296*r)}return this.lo+4294967296*this.hi},o.prototype.toLong=function(e){return n.Long?new n.Long(0|this.lo,0|this.hi,Boolean(e)):{low:0|this.lo,high:0|this.hi,unsigned:Boolean(e)}};var a=String.prototype.charCodeAt;o.fromHash=function(e){return e===s?i:new o((a.call(e,0)|a.call(e,1)<<8|a.call(e,2)<<16|a.call(e,3)<<24)>>>0,(a.call(e,4)|a.call(e,5)<<8|a.call(e,6)<<16|a.call(e,7)<<24)>>>0)},o.prototype.toHash=function(){return String.fromCharCode(255&this.lo,this.lo>>>8&255,this.lo>>>16&255,this.lo>>>24,255&this.hi,this.hi>>>8&255,this.hi>>>16&255,this.hi>>>24)},o.prototype.zzEncode=function(){var e=this.hi>>31;return this.hi=((this.hi<<1|this.lo>>>31)^e)>>>0,this.lo=(this.lo<<1^e)>>>0,this},o.prototype.zzDecode=function(){var e=-(1&this.lo);return this.lo=((this.lo>>>1|this.hi<<31)^e)>>>0,this.hi=(this.hi>>>1^e)>>>0,this},o.prototype.length=function(){var e=this.lo,t=(this.lo>>>28|this.hi<<4)>>>0,r=this.hi>>>24;return 0===r?0===t?e<16384?e<128?1:2:e<2097152?3:4:t<16384?t<128?5:6:t<2097152?7:8:r<128?9:10}},693:function(e,t,r){"use strict";var n=t;function o(e,t,r){for(var n=Object.keys(t),o=0;o0)},n.Buffer=function(){try{var e=n.inquire("buffer").Buffer;return e.prototype.utf8Write?e:null}catch(e){return null}}(),n._Buffer_from=null,n._Buffer_allocUnsafe=null,n.newBuffer=function(e){return"number"==typeof e?n.Buffer?n._Buffer_allocUnsafe(e):new n.Array(e):n.Buffer?n._Buffer_from(e):"undefined"==typeof Uint8Array?e:new Uint8Array(e)},n.Array="undefined"!=typeof Uint8Array?Uint8Array:Array,n.Long=n.global.dcodeIO&&n.global.dcodeIO.Long||n.global.Long||n.inquire("long"),n.key2Re=/^true|false|0|1$/,n.key32Re=/^-?(?:0|[1-9][0-9]*)$/,n.key64Re=/^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/,n.longToHash=function(e){return e?n.LongBits.from(e).toHash():n.LongBits.zeroHash},n.longFromHash=function(e,t){var r=n.LongBits.fromHash(e);return n.Long?n.Long.fromBits(r.lo,r.hi,t):r.toNumber(Boolean(t))},n.merge=o,n.lcFirst=function(e){return e.charAt(0).toLowerCase()+e.substring(1)},n.newError=i,n.ProtocolError=i("ProtocolError"),n.oneOfGetter=function(e){for(var t={},r=0;r-1;--r)if(1===t[e[r]]&&void 0!==this[e[r]]&&null!==this[e[r]])return e[r]}},n.oneOfSetter=function(e){return function(t){for(var r=0;r{"use strict";e.exports=f;var n,o=r(693),i=o.LongBits,s=o.base64,a=o.utf8;function c(e,t,r){this.fn=e,this.len=t,this.next=void 0,this.val=r}function u(){}function h(e){this.head=e.head,this.tail=e.tail,this.len=e.len,this.next=e.states}function f(){this.len=0,this.head=new c(u,0,0),this.tail=this.head,this.states=null}var l=function(){return o.Buffer?function(){return(f.create=function(){return new n})()}:function(){return new f}};function d(e,t,r){t[r]=255&e}function p(e,t){this.len=e,this.next=void 0,this.val=t}function w(e,t,r){for(;e.hi;)t[r++]=127&e.lo|128,e.lo=(e.lo>>>7|e.hi<<25)>>>0,e.hi>>>=7;for(;e.lo>127;)t[r++]=127&e.lo|128,e.lo=e.lo>>>7;t[r++]=e.lo}function b(e,t,r){t[r]=255&e,t[r+1]=e>>>8&255,t[r+2]=e>>>16&255,t[r+3]=e>>>24}f.create=l(),f.alloc=function(e){return new o.Array(e)},o.Array!==Array&&(f.alloc=o.pool(f.alloc,o.Array.prototype.subarray)),f.prototype._push=function(e,t,r){return this.tail=this.tail.next=new c(e,t,r),this.len+=t,this},p.prototype=Object.create(c.prototype),p.prototype.fn=function(e,t,r){for(;e>127;)t[r++]=127&e|128,e>>>=7;t[r]=e},f.prototype.uint32=function(e){return this.len+=(this.tail=this.tail.next=new p((e>>>=0)<128?1:e<16384?2:e<2097152?3:e<268435456?4:5,e)).len,this},f.prototype.int32=function(e){return e<0?this._push(w,10,i.fromNumber(e)):this.uint32(e)},f.prototype.sint32=function(e){return this.uint32((e<<1^e>>31)>>>0)},f.prototype.uint64=function(e){var t=i.from(e);return this._push(w,t.length(),t)},f.prototype.int64=f.prototype.uint64,f.prototype.sint64=function(e){var t=i.from(e).zzEncode();return this._push(w,t.length(),t)},f.prototype.bool=function(e){return this._push(d,1,e?1:0)},f.prototype.fixed32=function(e){return this._push(b,4,e>>>0)},f.prototype.sfixed32=f.prototype.fixed32,f.prototype.fixed64=function(e){var t=i.from(e);return this._push(b,4,t.lo)._push(b,4,t.hi)},f.prototype.sfixed64=f.prototype.fixed64,f.prototype.float=function(e){return this._push(o.float.writeFloatLE,4,e)},f.prototype.double=function(e){return this._push(o.float.writeDoubleLE,8,e)};var y=o.Array.prototype.set?function(e,t,r){t.set(e,r)}:function(e,t,r){for(var n=0;n>>0;if(!t)return this._push(d,1,0);if(o.isString(e)){var r=f.alloc(t=s.length(e));s.decode(e,r,0),e=r}return this.uint32(t)._push(y,t,e)},f.prototype.string=function(e){var t=a.length(e);return t?this.uint32(t)._push(a.write,t,e):this._push(d,1,0)},f.prototype.fork=function(){return this.states=new h(this),this.head=this.tail=new c(u,0,0),this.len=0,this},f.prototype.reset=function(){return this.states?(this.head=this.states.head,this.tail=this.states.tail,this.len=this.states.len,this.states=this.states.next):(this.head=this.tail=new c(u,0,0),this.len=0),this},f.prototype.ldelim=function(){var e=this.head,t=this.tail,r=this.len;return this.reset().uint32(r),r&&(this.tail.next=e.next,this.tail=t,this.len+=r),this},f.prototype.finish=function(){for(var e=this.head.next,t=this.constructor.alloc(this.len),r=0;e;)e.fn(e.val,t,r),r+=e.len,e=e.next;return t},f._configure=function(e){n=e,f.create=l(),n._configure()}},155:(e,t,r)=>{"use strict";e.exports=i;var n=r(173);(i.prototype=Object.create(n.prototype)).constructor=i;var o=r(693);function i(){n.call(this)}function s(e,t,r){e.length<40?o.utf8.write(e,t,r):t.utf8Write?t.utf8Write(e,r):t.write(e,r)}i._configure=function(){i.alloc=o._Buffer_allocUnsafe,i.writeBytesBuffer=o.Buffer&&o.Buffer.prototype instanceof Uint8Array&&"set"===o.Buffer.prototype.set.name?function(e,t,r){t.set(e,r)}:function(e,t,r){if(e.copy)e.copy(t,r,0,e.length);else for(var n=0;n>>0;return this.uint32(t),t&&this._push(i.writeBytesBuffer,t,e),this},i.prototype.string=function(e){var t=o.Buffer.byteLength(e);return this.uint32(t),t&&this._push(s,t,e),this},i._configure()},544:e=>{"use strict";function t(e,t){return e+r(t)}function r(e){let t=e;return t-=t>>1&1431655765,t=(858993459&t)+(t>>2&858993459),16843009*(t+(t>>4)&252645135)>>24}function n(e,t){return e[0]-t[0]}function o(e){return e[1]}e.exports=class{constructor(){this._bitArrays=[],this._data=[],this._length=0,this._changedLength=!1,this._changedData=!1}set(e,t){let r=this._internalPositionFor(e,!1);if(void 0===t)-1!==r&&(this._unsetInternalPos(r),this._unsetBit(e),this._changedLength=!0,this._changedData=!0);else{let n=!1;-1===r?(r=this._data.length,this._setBit(e),this._changedData=!0):n=!0,this._setInternalPos(r,e,t,n),this._changedLength=!0}}unset(e){this.set(e,void 0)}get(e){this._sortData();const t=this._internalPositionFor(e,!0);if(-1!==t)return this._data[t][1]}push(e){return this.set(this.length,e),this.length}get length(){if(this._sortData(),this._changedLength){const e=this._data[this._data.length-1];this._length=e?e[0]+1:0,this._changedLength=!1}return this._length}forEach(e){let t=0;for(;t=this._bitArrays.length)return-1;const i=this._bitArrays[o],s=e-7*o;return(i&1<0?this._bitArrays.slice(0,o).reduce(t,0)+r(i&~(4294967295<=t)o.push(i);else if(o[0][0]<=t)o.unshift(i);else{const e=Math.round(o.length/2);this._data=o.slice(0,e).concat(i).concat(o.slice(e))}else this._data.push(i);this._changedData=!0,this._changedLength=!0}}_unsetInternalPos(e){this._data.splice(e,1)}_sortData(){this._changedData&&this._data.sort(n),this._changedData=!1}bitField(){const e=[];let t,r=8,n=0,o=0;const i=this._bitArrays.slice();for(;i.length||n;){0===n&&(t=i.shift(),n=7);const s=Math.min(n,r);o|=(t&~(255<>>=s,n-=s,r-=s,r&&(n||i.length)||(e.push(o),o=0,r=8)}for(var s=e.length-1;s>0&&0===e[s];s--)e.pop();return e}compactArray(){return this._sortData(),this._data.map(o)}}},988:e=>{e.exports=function e(t,r){var n,o=0,i=0,s=r=r||0,a=t.length;do{if(s>=a||i>49)throw e.bytes=0,new RangeError("Could not decode varint");n=t[s++],o+=i<28?(127&n)<=128);return e.bytes=s-r,o}},312:e=>{e.exports=function e(r,n,o){if(Number.MAX_SAFE_INTEGER&&r>Number.MAX_SAFE_INTEGER)throw e.bytes=0,new RangeError("Could not encode varint");n=n||[];for(var i=o=o||0;r>=t;)n[o++]=255&r|128,r/=128;for(;-128&r;)n[o++]=255&r|128,r>>>=7;return n[o]=0|r,e.bytes=o-i+1,n};var t=Math.pow(2,31)},676:(e,t,r)=>{e.exports={encode:r(312),decode:r(988),encodingLength:r(82)}},82:e=>{var t=Math.pow(2,7),r=Math.pow(2,14),n=Math.pow(2,21),o=Math.pow(2,28),i=Math.pow(2,35),s=Math.pow(2,42),a=Math.pow(2,49),c=Math.pow(2,56),u=Math.pow(2,63);e.exports=function(e){return e{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};(()=>{"use strict";__webpack_require__.d(__webpack_exports__,{default:()=>Nh});var e={};__webpack_require__.r(e),__webpack_require__.d(e,{coerce:()=>k,empty:()=>g,equals:()=>_,fromHex:()=>v,fromString:()=>x,isBinary:()=>E,toHex:()=>m,toString:()=>C});var t={};__webpack_require__.r(t),__webpack_require__.d(t,{base32:()=>P,base32hex:()=>M,base32hexpad:()=>$,base32hexpadupper:()=>F,base32hexupper:()=>j,base32pad:()=>L,base32padupper:()=>R,base32upper:()=>z,base32z:()=>V});var r={};__webpack_require__.r(r),__webpack_require__.d(r,{base58btc:()=>H,base58flickr:()=>q});var n={};__webpack_require__.r(n),__webpack_require__.d(n,{code:()=>mn,decode:()=>_n,encode:()=>vn,name:()=>gn});var o={};__webpack_require__.r(o),__webpack_require__.d(o,{code:()=>Ko,createLink:()=>Wo,createNode:()=>Go,decode:()=>Xo,encode:()=>Qo,name:()=>Jo,prepare:()=>Ho,validate:()=>qo});var i={};__webpack_require__.r(i),__webpack_require__.d(i,{code:()=>Gi,decode:()=>Ji,encode:()=>Wi,name:()=>qi});var s={};__webpack_require__.r(s),__webpack_require__.d(s,{code:()=>ya,decode:()=>ma,encode:()=>ga,name:()=>ba});var a={};__webpack_require__.r(a),__webpack_require__.d(a,{identity:()=>_a});var c={};__webpack_require__.r(c),__webpack_require__.d(c,{base10:()=>Ja});var u={};__webpack_require__.r(u),__webpack_require__.d(u,{base16:()=>Ka,base16upper:()=>Qa});var h={};__webpack_require__.r(h),__webpack_require__.d(h,{base2:()=>Xa});var f={};__webpack_require__.r(f),__webpack_require__.d(f,{base256emoji:()=>tc});var l={};__webpack_require__.r(l),__webpack_require__.d(l,{base36:()=>rc,base36upper:()=>nc});var d={};__webpack_require__.r(d),__webpack_require__.d(d,{base64:()=>oc,base64pad:()=>ic,base64url:()=>sc,base64urlpad:()=>ac});var p={};__webpack_require__.r(p),__webpack_require__.d(p,{base8:()=>cc});var w={};__webpack_require__.r(w),__webpack_require__.d(w,{identity:()=>uc});var b={};__webpack_require__.r(b),__webpack_require__.d(b,{code:()=>dc,decode:()=>wc,encode:()=>pc,name:()=>lc});var y={};__webpack_require__.r(y),__webpack_require__.d(y,{sha256:()=>yc,sha512:()=>gc});const g=new Uint8Array(0),m=e=>e.reduce(((e,t)=>e+t.toString(16).padStart(2,"0")),""),v=e=>{const t=e.match(/../g);return t?new Uint8Array(t.map((e=>parseInt(e,16)))):g},_=(e,t)=>{if(e===t)return!0;if(e.byteLength!==t.byteLength)return!1;for(let r=0;r{if(e instanceof Uint8Array&&"Uint8Array"===e.constructor.name)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Unknown type, must be binary type")},E=e=>e instanceof ArrayBuffer||ArrayBuffer.isView(e),x=e=>(new TextEncoder).encode(e),C=e=>(new TextDecoder).decode(e);const A=function(e,t){if(e.length>=255)throw new TypeError("Alphabet too long");for(var r=new Uint8Array(256),n=0;n>>0,s=new Uint8Array(i);e[t];){var h=r[e.charCodeAt(t)];if(255===h)return;for(var f=0,l=i-1;(0!==h||f>>0,s[l]=h%256>>>0,h=h/256>>>0;if(0!==h)throw new Error("Non-zero carry");o=f,t++}if(" "!==e[t]){for(var d=i-o;d!==i&&0===s[d];)d++;for(var p=new Uint8Array(n+(i-d)),w=n;d!==i;)p[w++]=s[d++];return p}}}return{encode:function(t){if(t instanceof Uint8Array||(ArrayBuffer.isView(t)?t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength):Array.isArray(t)&&(t=Uint8Array.from(t))),!(t instanceof Uint8Array))throw new TypeError("Expected Uint8Array");if(0===t.length)return"";for(var r=0,n=0,o=0,i=t.length;o!==i&&0===t[o];)o++,r++;for(var s=(i-o)*h+1>>>0,u=new Uint8Array(s);o!==i;){for(var f=t[o],l=0,d=s-1;(0!==f||l>>0,u[d]=f%a>>>0,f=f/a>>>0;if(0!==f)throw new Error("Non-zero carry");n=l,o++}for(var p=s-n;p!==s&&0===u[p];)p++;for(var w=c.repeat(r);pnew S({...e.decoders||{[e.prefix]:e},...t.decoders||{[t.prefix]:t}});class T{constructor(e,t,r,n){this.name=e,this.prefix=t,this.baseEncode=r,this.baseDecode=n,this.encoder=new B(e,t,r),this.decoder=new I(e,t,n)}encode(e){return this.encoder.encode(e)}decode(e){return this.decoder.decode(e)}}const U=({name:e,prefix:t,encode:r,decode:n})=>new T(e,t,r,n),N=({prefix:e,name:t,alphabet:r})=>{const{encode:n,decode:o}=A(r,t);return U({prefix:e,name:t,encode:n,decode:e=>k(o(e))})},O=({name:e,prefix:t,bitsPerChar:r,alphabet:n})=>U({prefix:t,name:e,encode:e=>((e,t,r)=>{const n="="===t[t.length-1],o=(1<r;)s-=r,i+=t[o&a>>s];if(s&&(i+=t[o&a<((e,t,r,n)=>{const o={};for(let e=0;e=8&&(a-=8,s[u++]=255&c>>a)}if(a>=r||255&c<<8-a)throw new SyntaxError("Unexpected end of data");return s})(t,n,r,e)}),P=O({prefix:"b",name:"base32",alphabet:"abcdefghijklmnopqrstuvwxyz234567",bitsPerChar:5}),z=O({prefix:"B",name:"base32upper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",bitsPerChar:5}),L=O({prefix:"c",name:"base32pad",alphabet:"abcdefghijklmnopqrstuvwxyz234567=",bitsPerChar:5}),R=O({prefix:"C",name:"base32padupper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",bitsPerChar:5}),M=O({prefix:"v",name:"base32hex",alphabet:"0123456789abcdefghijklmnopqrstuv",bitsPerChar:5}),j=O({prefix:"V",name:"base32hexupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV",bitsPerChar:5}),$=O({prefix:"t",name:"base32hexpad",alphabet:"0123456789abcdefghijklmnopqrstuv=",bitsPerChar:5}),F=O({prefix:"T",name:"base32hexpadupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV=",bitsPerChar:5}),V=O({prefix:"h",name:"base32z",alphabet:"ybndrfg8ejkmcpqxot1uwisza345h769",bitsPerChar:5}),H=N({name:"base58btc",prefix:"z",alphabet:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"}),q=N({name:"base58flickr",prefix:"Z",alphabet:"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"});var G=Math.pow(2,31),W=Math.pow(2,7),J=Math.pow(2,14),K=Math.pow(2,21),Q=Math.pow(2,28),X=Math.pow(2,35),Z=Math.pow(2,42),Y=Math.pow(2,49),ee=Math.pow(2,56),te=Math.pow(2,63);const re={encode:function e(t,r,n){r=r||[];for(var o=n=n||0;t>=G;)r[n++]=255&t|128,t/=128;for(;-128&t;)r[n++]=255&t|128,t>>>=7;return r[n]=0|t,e.bytes=n-o+1,r},decode:function e(t,r){var n,o=0,i=0,s=r=r||0,a=t.length;do{if(s>=a)throw e.bytes=0,new RangeError("Could not decode varint");n=t[s++],o+=i<28?(127&n)<=128);return e.bytes=s-r,o},encodingLength:function(e){return e[re.decode(e,t),re.decode.bytes],oe=(e,t,r=0)=>(re.encode(e,t,r),t),ie=e=>re.encodingLength(e),se=(e,t)=>{const r=t.byteLength,n=ie(e),o=n+ie(r),i=new Uint8Array(o+r);return oe(e,i,0),oe(r,i,n),i.set(t,o),new ce(e,r,t,i)},ae=e=>{const t=k(e),[r,n]=ne(t),[o,i]=ne(t.subarray(n)),s=t.subarray(n+i);if(s.byteLength!==o)throw new Error("Incorrect length");return new ce(r,o,s,t)};class ce{constructor(e,t,r,n){this.code=e,this.size=t,this.digest=r,this.bytes=n}}const ue=(e,t)=>{const{bytes:r,version:n}=e;return 0===n?pe(r,fe(e),t||H.encoder):we(r,fe(e),t||P.encoder)},he=new WeakMap,fe=e=>{const t=he.get(e);if(null==t){const t=new Map;return he.set(e,t),t}return t};class le{constructor(e,t,r,n){this.code=t,this.version=e,this.multihash=r,this.bytes=n,this["/"]=n}get asCID(){return this}get byteOffset(){return this.bytes.byteOffset}get byteLength(){return this.bytes.byteLength}toV0(){switch(this.version){case 0:return this;case 1:{const{code:e,multihash:t}=this;if(e!==be)throw new Error("Cannot convert a non dag-pb CID to CIDv0");if(t.code!==ye)throw new Error("Cannot convert non sha2-256 multihash CID to CIDv0");return le.createV0(t)}default:throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`)}}toV1(){switch(this.version){case 0:{const{code:e,digest:t}=this.multihash,r=se(e,t);return le.createV1(this.code,r)}case 1:return this;default:throw Error(`Can not convert CID version ${this.version} to version 1. This is a bug please report`)}}equals(e){return le.equals(this,e)}static equals(e,t){const r=t;return r&&e.code===r.code&&e.version===r.version&&((e,t)=>{if(e===t)return!0;{const r=t;return e.code===r.code&&e.size===r.size&&r.bytes instanceof Uint8Array&&_(e.bytes,r.bytes)}})(e.multihash,r.multihash)}toString(e){return ue(this,e)}toJSON(){return{"/":ue(this)}}link(){return this}get[Symbol.toStringTag](){return"CID"}[Symbol.for("nodejs.util.inspect.custom")](){return`CID(${this.toString()})`}static asCID(e){if(null==e)return null;const t=e;if(t instanceof le)return t;if(null!=t["/"]&&t["/"]===t.bytes||t.asCID===t){const{version:e,code:r,multihash:n,bytes:o}=t;return new le(e,r,n,o||ge(e,r,n.bytes))}if(!0===t[me]){const{version:e,multihash:r,code:n}=t,o=ae(r);return le.create(e,n,o)}return null}static create(e,t,r){if("number"!=typeof t)throw new Error("String codecs are no longer supported");if(!(r.bytes instanceof Uint8Array))throw new Error("Invalid digest");switch(e){case 0:if(t!==be)throw new Error(`Version 0 CID must use dag-pb (code: ${be}) block encoding`);return new le(e,t,r,r.bytes);case 1:{const n=ge(e,t,r.bytes);return new le(e,t,r,n)}default:throw new Error("Invalid version")}}static createV0(e){return le.create(0,be,e)}static createV1(e,t){return le.create(1,e,t)}static decode(e){const[t,r]=le.decodeFirst(e);if(r.length)throw new Error("Incorrect length");return t}static decodeFirst(e){const t=le.inspectBytes(e),r=t.size-t.multihashSize,n=k(e.subarray(r,r+t.multihashSize));if(n.byteLength!==t.multihashSize)throw new Error("Incorrect length");const o=n.subarray(t.multihashSize-t.digestSize),i=new ce(t.multihashCode,t.digestSize,o,n);return[0===t.version?le.createV0(i):le.createV1(t.codec,i),e.subarray(t.size)]}static inspectBytes(e){let t=0;const r=()=>{const[r,n]=ne(e.subarray(t));return t+=n,r};let n=r(),o=be;if(18===n?(n=0,t=0):o=r(),0!==n&&1!==n)throw new RangeError(`Invalid CID version ${n}`);const i=t,s=r(),a=r(),c=t+a;return{version:n,codec:o,multihashCode:s,digestSize:a,multihashSize:c-i,size:c}}static parse(e,t){const[r,n]=de(e,t),o=le.decode(n);if(0===o.version&&"Q"!==e[0])throw Error("Version 0 CID string must not include multibase prefix");return fe(o).set(r,e),o}}const de=(e,t)=>{switch(e[0]){case"Q":{const r=t||H;return[H.prefix,r.decode(`${H.prefix}${e}`)]}case H.prefix:{const r=t||H;return[H.prefix,r.decode(e)]}case P.prefix:{const r=t||P;return[P.prefix,r.decode(e)]}default:if(null==t)throw Error("To parse non base32 or base58btc encoded CID multibase decoder must be provided");return[e[0],t.decode(e)]}},pe=(e,t,r)=>{const{prefix:n}=r;if(n!==H.prefix)throw Error(`Cannot string encode V0 in ${r.name} encoding`);const o=t.get(n);if(null==o){const o=r.encode(e).slice(1);return t.set(n,o),o}return o},we=(e,t,r)=>{const{prefix:n}=r,o=t.get(n);if(null==o){const o=r.encode(e);return t.set(n,o),o}return o},be=112,ye=18,ge=(e,t,r)=>{const n=ie(e),o=n+ie(t),i=new Uint8Array(o+r.byteLength);return oe(e,i,0),oe(t,i,n),i.set(r,o),i},me=Symbol.for("@ipld/js-cid/CID"),ve=({name:e,code:t,encode:r})=>new _e(e,t,r);class _e{constructor(e,t,r){this.name=e,this.code=t,this.encode=r}digest(e){if(e instanceof Uint8Array){const t=this.encode(e);return t instanceof Uint8Array?se(this.code,t):t.then((e=>se(this.code,e)))}throw Error("Unknown type, must be binary type")}}var ke=__webpack_require__(676),Ee=Math.pow(2,31),xe=Math.pow(2,7),Ce=Math.pow(2,14),Ae=Math.pow(2,21),Be=Math.pow(2,28),Ie=Math.pow(2,35),Se=Math.pow(2,42),De=Math.pow(2,49),Te=Math.pow(2,56),Ue=Math.pow(2,63);const Ne={encode:function e(t,r,n){r=r||[];for(var o=n=n||0;t>=Ee;)r[n++]=255&t|128,t/=128;for(;-128&t;)r[n++]=255&t|128,t>>>=7;return r[n]=0|t,e.bytes=n-o+1,r},decode:function e(t,r){var n,o=0,i=0,s=r=r||0,a=t.length;do{if(s>=a)throw e.bytes=0,new RangeError("Could not decode varint");n=t[s++],o+=i<28?(127&n)<=128);return e.bytes=s-r,o},encodingLength:function(e){return e[Ne.decode(e,t),Ne.decode.bytes],Pe=(e,t,r=0)=>(Ne.encode(e,t,r),t),ze=e=>Ne.encodingLength(e),Le=(new Uint8Array(0),e=>{if(e instanceof Uint8Array&&"Uint8Array"===e.constructor.name)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Unknown type, must be binary type")}),Re=e=>{const t=Le(e),[r,n]=Oe(t),[o,i]=Oe(t.subarray(n)),s=t.subarray(n+i);if(s.byteLength!==o)throw new Error("Incorrect length");return new Me(r,o,s,t)};class Me{constructor(e,t,r,n){this.code=e,this.size=t,this.digest=r,this.bytes=n}}const je=function(e,t){if(e.length>=255)throw new TypeError("Alphabet too long");for(var r=new Uint8Array(256),n=0;n>>0,s=new Uint8Array(i);e[t];){var h=r[e.charCodeAt(t)];if(255===h)return;for(var f=0,l=i-1;(0!==h||f>>0,s[l]=h%256>>>0,h=h/256>>>0;if(0!==h)throw new Error("Non-zero carry");o=f,t++}if(" "!==e[t]){for(var d=i-o;d!==i&&0===s[d];)d++;for(var p=new Uint8Array(n+(i-d)),w=n;d!==i;)p[w++]=s[d++];return p}}}return{encode:function(t){if(t instanceof Uint8Array||(ArrayBuffer.isView(t)?t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength):Array.isArray(t)&&(t=Uint8Array.from(t))),!(t instanceof Uint8Array))throw new TypeError("Expected Uint8Array");if(0===t.length)return"";for(var r=0,n=0,o=0,i=t.length;o!==i&&0===t[o];)o++,r++;for(var s=(i-o)*h+1>>>0,u=new Uint8Array(s);o!==i;){for(var f=t[o],l=0,d=s-1;(0!==f||l>>0,u[d]=f%a>>>0,f=f/a>>>0;if(0!==f)throw new Error("Non-zero carry");n=l,o++}for(var p=s-n;p!==s&&0===u[p];)p++;for(var w=c.repeat(r);pnew Ve({...e.decoders||{[e.prefix]:e},...t.decoders||{[t.prefix]:t}});class qe{constructor(e,t,r,n){this.name=e,this.prefix=t,this.baseEncode=r,this.baseDecode=n,this.encoder=new $e(e,t,r),this.decoder=new Fe(e,t,n)}encode(e){return this.encoder.encode(e)}decode(e){return this.decoder.decode(e)}}const Ge=({name:e,prefix:t,encode:r,decode:n})=>new qe(e,t,r,n),We=({prefix:e,name:t,alphabet:r})=>{const{encode:n,decode:o}=je(r,t);return Ge({prefix:e,name:t,encode:n,decode:e=>Le(o(e))})},Je=({name:e,prefix:t,bitsPerChar:r,alphabet:n})=>Ge({prefix:t,name:e,encode:e=>((e,t,r)=>{const n="="===t[t.length-1],o=(1<r;)s-=r,i+=t[o&a>>s];if(s&&(i+=t[o&a<((e,t,r,n)=>{const o={};for(let e=0;e=8&&(a-=8,s[u++]=255&c>>a)}if(a>=r||255&c<<8-a)throw new SyntaxError("Unexpected end of data");return s})(t,n,r,e)}),Ke=We({name:"base58btc",prefix:"z",alphabet:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"}),Qe=(We({name:"base58flickr",prefix:"Z",alphabet:"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"}),Je({prefix:"b",name:"base32",alphabet:"abcdefghijklmnopqrstuvwxyz234567",bitsPerChar:5}));Je({prefix:"B",name:"base32upper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",bitsPerChar:5}),Je({prefix:"c",name:"base32pad",alphabet:"abcdefghijklmnopqrstuvwxyz234567=",bitsPerChar:5}),Je({prefix:"C",name:"base32padupper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",bitsPerChar:5}),Je({prefix:"v",name:"base32hex",alphabet:"0123456789abcdefghijklmnopqrstuv",bitsPerChar:5}),Je({prefix:"V",name:"base32hexupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV",bitsPerChar:5}),Je({prefix:"t",name:"base32hexpad",alphabet:"0123456789abcdefghijklmnopqrstuv=",bitsPerChar:5}),Je({prefix:"T",name:"base32hexpadupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV=",bitsPerChar:5}),Je({prefix:"h",name:"base32z",alphabet:"ybndrfg8ejkmcpqxot1uwisza345h769",bitsPerChar:5});class Xe{constructor(e,t,r,n){this.code=t,this.version=e,this.multihash=r,this.bytes=n,this.byteOffset=n.byteOffset,this.byteLength=n.byteLength,this.asCID=this,this._baseCache=new Map,Object.defineProperties(this,{byteOffset:st,byteLength:st,code:it,version:it,multihash:it,bytes:it,_baseCache:st,asCID:st})}toV0(){if(0===this.version)return this;{const{code:e,multihash:t}=this;if(e!==tt)throw new Error("Cannot convert a non dag-pb CID to CIDv0");if(t.code!==rt)throw new Error("Cannot convert non sha2-256 multihash CID to CIDv0");return Xe.createV0(t)}}toV1(){switch(this.version){case 0:{const{code:e,digest:t}=this.multihash,r=((e,t)=>{const r=t.byteLength,n=ze(e),o=n+ze(r),i=new Uint8Array(o+r);return Pe(e,i,0),Pe(r,i,n),i.set(t,o),new Me(e,r,t,i)})(e,t);return Xe.createV1(this.code,r)}case 1:return this;default:throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`)}}equals(e){return e&&this.code===e.code&&this.version===e.version&&((t=this.multihash)===(r=e.multihash)||t.code===r.code&&t.size===r.size&&((e,t)=>{if(e===t)return!0;if(e.byteLength!==t.byteLength)return!1;for(let r=0;r{const[r,n]=Oe(e.subarray(t));return t+=n,r};let n=r(),o=tt;if(18===n?(n=0,t=0):1===n&&(o=r()),0!==n&&1!==n)throw new RangeError(`Invalid CID version ${n}`);const i=t,s=r(),a=r(),c=t+a;return{version:n,codec:o,multihashCode:s,digestSize:a,multihashSize:c-i,size:c}}static parse(e,t){const[r,n]=Ze(e,t),o=Xe.decode(n);return o._baseCache.set(r,e),o}}const Ze=(e,t)=>{switch(e[0]){case"Q":{const r=t||Ke;return[Ke.prefix,r.decode(`${Ke.prefix}${e}`)]}case Ke.prefix:{const r=t||Ke;return[Ke.prefix,r.decode(e)]}case Qe.prefix:{const r=t||Qe;return[Qe.prefix,r.decode(e)]}default:if(null==t)throw Error("To parse non base32 or base58btc encoded CID multibase decoder must be provided");return[e[0],t.decode(e)]}},Ye=(e,t,r)=>{const{prefix:n}=r;if(n!==Ke.prefix)throw Error(`Cannot string encode V0 in ${r.name} encoding`);const o=t.get(n);if(null==o){const o=r.encode(e).slice(1);return t.set(n,o),o}return o},et=(e,t,r)=>{const{prefix:n}=r,o=t.get(n);if(null==o){const o=r.encode(e);return t.set(n,o),o}return o},tt=112,rt=18,nt=(e,t,r)=>{const n=ze(e),o=n+ze(t),i=new Uint8Array(o+r.byteLength);return Pe(e,i,0),Pe(t,i,n),i.set(r,o),i},ot=Symbol.for("@ipld/js-cid/CID"),it={writable:!1,configurable:!1,enumerable:!0},st={writable:!1,enumerable:!1,configurable:!1},at=(e,t)=>{if(!e.test("0.0.0-dev"))throw new Error(t);console.warn(t)},ct="CID.isCID(v) is deprecated and will be removed in the next major release.\nFollowing code pattern:\n\nif (CID.isCID(value)) {\n doSomethingWithCID(value)\n}\n\nIs replaced with:\n\nconst cid = CID.asCID(value)\nif (cid) {\n // Make sure to use cid instead of value\n doSomethingWithCID(cid)\n}\n",ut=["string","number","bigint","symbol"],ht=["Function","Generator","AsyncGenerator","GeneratorFunction","AsyncGeneratorFunction","AsyncFunction","Observable","Array","Buffer","Object","RegExp","Date","Error","Map","Set","WeakMap","WeakSet","ArrayBuffer","SharedArrayBuffer","DataView","Promise","URL","HTMLElement","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Uint16Array","Int32Array","Uint32Array","Float32Array","Float64Array","BigInt64Array","BigUint64Array"];class ft{constructor(e,t,r){this.major=e,this.majorEncoded=e<<5,this.name=t,this.terminal=r}toString(){return`Type[${this.major}].${this.name}`}compare(e){return this.majore.major?1:0}}ft.uint=new ft(0,"uint",!0),ft.negint=new ft(1,"negint",!0),ft.bytes=new ft(2,"bytes",!0),ft.string=new ft(3,"string",!0),ft.array=new ft(4,"array",!1),ft.map=new ft(5,"map",!1),ft.tag=new ft(6,"tag",!1),ft.float=new ft(7,"float",!0),ft.false=new ft(7,"false",!0),ft.true=new ft(7,"true",!0),ft.null=new ft(7,"null",!0),ft.undefined=new ft(7,"undefined",!0),ft.break=new ft(7,"break",!0);class lt{constructor(e,t,r){this.type=e,this.value=t,this.encodedLength=r,this.encodedBytes=void 0,this.byteValue=void 0}toString(){return`Token[${this.type}].${this.value}`}}const dt=globalThis.process&&!globalThis.process.browser&&globalThis.Buffer&&"function"==typeof globalThis.Buffer.isBuffer,pt=new TextDecoder,wt=new TextEncoder;function bt(e){return dt&&globalThis.Buffer.isBuffer(e)}function yt(e){return e instanceof Uint8Array?bt(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):e:Uint8Array.from(e)}const gt=dt?(e,t,r)=>r-t>64?globalThis.Buffer.from(e.subarray(t,r)).toString("utf8"):Ct(e,t,r):(e,t,r)=>r-t>64?pt.decode(e.subarray(t,r)):Ct(e,t,r),mt=dt?e=>e.length>64?globalThis.Buffer.from(e):xt(e):e=>e.length>64?wt.encode(e):xt(e),vt=e=>Uint8Array.from(e),_t=dt?(e,t,r)=>bt(e)?new Uint8Array(e.subarray(t,r)):e.slice(t,r):(e,t,r)=>e.slice(t,r),kt=dt?(e,t)=>(e=e.map((e=>e instanceof Uint8Array?e:globalThis.Buffer.from(e))),yt(globalThis.Buffer.concat(e,t))):(e,t)=>{const r=new Uint8Array(t);let n=0;for(let t of e)n+t.length>r.length&&(t=t.subarray(0,r.length-n)),r.set(t,n),n+=t.length;return r},Et=dt?e=>globalThis.Buffer.allocUnsafe(e):e=>new Uint8Array(e);function xt(e,t=1/0){let r;const n=e.length;let o=null;const i=[];for(let s=0;s55295&&r<57344){if(!o){if(r>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(s+1===n){(t-=3)>-1&&i.push(239,191,189);continue}o=r;continue}if(r<56320){(t-=3)>-1&&i.push(239,191,189),o=r;continue}r=65536+(o-55296<<10|r-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,r<128){if((t-=1)<0)break;i.push(r)}else if(r<2048){if((t-=2)<0)break;i.push(r>>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;i.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return i}function Ct(e,t,r){const n=[];for(;t239?4:o>223?3:o>191?2:1;if(t+s<=r){let r,n,a,c;switch(s){case 1:o<128&&(i=o);break;case 2:r=e[t+1],128==(192&r)&&(c=(31&o)<<6|63&r,c>127&&(i=c));break;case 3:r=e[t+1],n=e[t+2],128==(192&r)&&128==(192&n)&&(c=(15&o)<<12|(63&r)<<6|63&n,c>2047&&(c<55296||c>57343)&&(i=c));break;case 4:r=e[t+1],n=e[t+2],a=e[t+3],128==(192&r)&&128==(192&n)&&128==(192&a)&&(c=(15&o)<<18|(63&r)<<12|(63&n)<<6|63&a,c>65535&&c<1114112&&(i=c))}}null===i?(i=65533,s=1):i>65535&&(i-=65536,n.push(i>>>10&1023|55296),i=56320|1023&i),n.push(i),t+=s}return At(n)}function At(e){const t=e.length;if(t<=4096)return String.fromCharCode.apply(String,e);let r="",n=0;for(;nr.length/2?(t=this.cursor===r.length?r:r.subarray(0,this.cursor),this._initReuseChunk=null,this.chunks=[]):t=_t(r,0,this.cursor)}else t=kt(this.chunks,this.cursor);return e&&this.reset(),t}}const It=[];function St(e,t,r){if(e.length-t>>8,255&n])}else if(r>>24&255,n>>>16&255,n>>>8&255,255&n])}else{const n=BigInt(r);if(!(n>BigInt(32)&BigInt(4294967295));r[8]=255&o,o>>=8,r[7]=255&o,o>>=8,r[6]=255&o,o>>=8,r[5]=255&o,r[4]=255&i,i>>=8,r[3]=255&i,i>>=8,r[2]=255&i,i>>=8,r[1]=255&i,e.push(r)}}}Pt.encodedSize=function(e){return zt.encodedSize(e.value)},zt.encodedSize=function(e){return et.value?1:0};const Lt=BigInt(-1),Rt=BigInt(1);function Mt(e,t){const r=t.value,n="bigint"==typeof r?r*Lt-Rt:-1*r-1;zt(e,t.type.majorEncoded,n)}function jt(e,t,r,n){St(e,t,r+n);const o=_t(e,t+r,t+r+n);return new lt(ft.bytes,o,r+n)}function $t(e,t,r,n){return jt(e,t,1,r)}function Ft(e){return void 0===e.encodedBytes&&(e.encodedBytes=e.type===ft.string?mt(e.value):e.value),e.encodedBytes}function Vt(e,t){const r=Ft(t);zt(e,t.type.majorEncoded,r.length),e.push(r)}function Ht(e,t,r,n,o){const i=r+n;St(e,t,i);const s=new lt(ft.string,gt(e,t+r,t+i),i);return!0===o.retainStringBytes&&(s.byteValue=_t(e,t+r,t+i)),s}function qt(e,t,r,n){return Ht(e,t,1,r,n)}Mt.encodedSize=function(e){const t=e.value,r="bigint"==typeof t?t*Lt-Rt:-1*t-1;return rt.value?-1:0},Vt.encodedSize=function(e){const t=Ft(e);return zt.encodedSize(t.length)+t.length},Vt.compareTokens=function(e,t){return r=Ft(e),n=Ft(t),r.lengthn.length?1:function(e,t){if(bt(e)&&bt(t))return e.compare(t);for(let r=0;r>23,n=8388607&t;if(255===r)or.setUint16(0,31744,!1);else if(0===r)or.setUint16(0,(2147483648&e)>>16|n>>13,!1);else{const e=r-127;e<-24?or.setUint16(0,0):e<-14?or.setUint16(0,(2147483648&t)>>16|1<<24+e,!1):or.setUint16(0,(2147483648&t)>>16|e+15<<10|n>>13,!1)}}}function ar(e,t){if(e.length-t<2)throw new Error("CBOR decode error: not enough data for float16");const r=(e[t]<<8)+e[t+1];if(31744===r)return 1/0;if(64512===r)return-1/0;if(32256===r)return NaN;const n=r>>10&31,o=1023&r;let i;return i=0===n?o*2**-24:31!==n?(o+1024)*2**(n-25):0===o?1/0:NaN,32768&r?-i:i}function cr(e){or.setFloat32(0,e,!1)}function ur(e,t){if(e.length-t<4)throw new Error("CBOR decode error: not enough data for float32");const r=(e.byteOffset||0)+t;return new DataView(e.buffer,r,4).getFloat32(0,!1)}function hr(e,t){if(e.length-t<8)throw new Error("CBOR decode error: not enough data for float64");const r=(e.byteOffset||0)+t;return new DataView(e.buffer,r,8).getFloat64(0,!1)}function fr(e,t,r){throw new Error(`CBOR decode error: encountered invalid minor (${r}) for major ${e[t]>>>5}`)}function lr(e){return()=>{throw new Error(`CBOR decode error: ${e}`)}}rr.compareTokens=Pt.compareTokens;const dr=[];for(let e=0;e<=23;e++)dr[e]=fr;dr[24]=function(e,t,r,n){return new lt(ft.uint,Tt(e,t+1,n),2)},dr[25]=function(e,t,r,n){return new lt(ft.uint,Ut(e,t+1,n),3)},dr[26]=function(e,t,r,n){return new lt(ft.uint,Nt(e,t+1,n),5)},dr[27]=function(e,t,r,n){return new lt(ft.uint,Ot(e,t+1,n),9)},dr[28]=fr,dr[29]=fr,dr[30]=fr,dr[31]=fr;for(let e=32;e<=55;e++)dr[e]=fr;dr[56]=function(e,t,r,n){return new lt(ft.negint,-1-Tt(e,t+1,n),2)},dr[57]=function(e,t,r,n){return new lt(ft.negint,-1-Ut(e,t+1,n),3)},dr[58]=function(e,t,r,n){return new lt(ft.negint,-1-Nt(e,t+1,n),5)},dr[59]=function(e,t,r,n){const o=Ot(e,t+1,n);if("bigint"!=typeof o){const e=-1-o;if(e>=Number.MIN_SAFE_INTEGER)return new lt(ft.negint,e,9)}if(!0!==n.allowBigInt)throw new Error("CBOR decode error: integers outside of the safe integer range are not supported");return new lt(ft.negint,Lt-BigInt(o),9)},dr[60]=fr,dr[61]=fr,dr[62]=fr,dr[63]=fr;for(let e=64;e<=87;e++)dr[e]=$t;dr[88]=function(e,t,r,n){return jt(e,t,2,Tt(e,t+1,n))},dr[89]=function(e,t,r,n){return jt(e,t,3,Ut(e,t+1,n))},dr[90]=function(e,t,r,n){return jt(e,t,5,Nt(e,t+1,n))},dr[91]=function(e,t,r,n){const o=Ot(e,t+1,n);if("bigint"==typeof o)throw new Error("CBOR decode error: 64-bit integer bytes lengths not supported");return jt(e,t,9,o)},dr[92]=fr,dr[93]=fr,dr[94]=fr,dr[95]=lr("indefinite length bytes/strings are not supported");for(let e=96;e<=119;e++)dr[e]=qt;dr[120]=function(e,t,r,n){return Ht(e,t,2,Tt(e,t+1,n),n)},dr[121]=function(e,t,r,n){return Ht(e,t,3,Ut(e,t+1,n),n)},dr[122]=function(e,t,r,n){return Ht(e,t,5,Nt(e,t+1,n),n)},dr[123]=function(e,t,r,n){const o=Ot(e,t+1,n);if("bigint"==typeof o)throw new Error("CBOR decode error: 64-bit integer string lengths not supported");return Ht(e,t,9,o,n)},dr[124]=fr,dr[125]=fr,dr[126]=fr,dr[127]=lr("indefinite length bytes/strings are not supported");for(let e=128;e<=151;e++)dr[e]=Jt;dr[152]=function(e,t,r,n){return Wt(0,0,2,Tt(e,t+1,n))},dr[153]=function(e,t,r,n){return Wt(0,0,3,Ut(e,t+1,n))},dr[154]=function(e,t,r,n){return Wt(0,0,5,Nt(e,t+1,n))},dr[155]=function(e,t,r,n){const o=Ot(e,t+1,n);if("bigint"==typeof o)throw new Error("CBOR decode error: 64-bit integer array lengths not supported");return Wt(0,0,9,o)},dr[156]=fr,dr[157]=fr,dr[158]=fr,dr[159]=function(e,t,r,n){if(!1===n.allowIndefinite)throw new Error("CBOR decode error: indefinite length items not allowed");return Wt(0,0,1,1/0)};for(let e=160;e<=183;e++)dr[e]=Xt;dr[184]=function(e,t,r,n){return Qt(0,0,2,Tt(e,t+1,n))},dr[185]=function(e,t,r,n){return Qt(0,0,3,Ut(e,t+1,n))},dr[186]=function(e,t,r,n){return Qt(0,0,5,Nt(e,t+1,n))},dr[187]=function(e,t,r,n){const o=Ot(e,t+1,n);if("bigint"==typeof o)throw new Error("CBOR decode error: 64-bit integer map lengths not supported");return Qt(0,0,9,o)},dr[188]=fr,dr[189]=fr,dr[190]=fr,dr[191]=function(e,t,r,n){if(!1===n.allowIndefinite)throw new Error("CBOR decode error: indefinite length items not allowed");return Qt(0,0,1,1/0)};for(let e=192;e<=215;e++)dr[e]=Yt;dr[216]=function(e,t,r,n){return new lt(ft.tag,Tt(e,t+1,n),2)},dr[217]=function(e,t,r,n){return new lt(ft.tag,Ut(e,t+1,n),3)},dr[218]=function(e,t,r,n){return new lt(ft.tag,Nt(e,t+1,n),5)},dr[219]=function(e,t,r,n){return new lt(ft.tag,Ot(e,t+1,n),9)},dr[220]=fr,dr[221]=fr,dr[222]=fr,dr[223]=fr;for(let e=224;e<=243;e++)dr[e]=lr("simple values are not supported");dr[244]=fr,dr[245]=fr,dr[246]=fr,dr[247]=function(e,t,r,n){if(!1===n.allowUndefined)throw new Error("CBOR decode error: undefined values are not supported");return!0===n.coerceUndefinedToNull?new lt(ft.null,null,1):new lt(ft.undefined,void 0,1)},dr[248]=lr("simple values are not supported"),dr[249]=function(e,t,r,n){return tr(ar(e,t+1),3,n)},dr[250]=function(e,t,r,n){return tr(ur(e,t+1),5,n)},dr[251]=function(e,t,r,n){return tr(hr(e,t+1),9,n)},dr[252]=fr,dr[253]=fr,dr[254]=fr,dr[255]=function(e,t,r,n){if(!1===n.allowIndefinite)throw new Error("CBOR decode error: indefinite length items not allowed");return new lt(ft.break,void 0,1)};const pr=[];for(let e=0;e<24;e++)pr[e]=new lt(ft.uint,e,1);for(let e=-1;e>=-24;e--)pr[31-e]=new lt(ft.negint,e,1);pr[64]=new lt(ft.bytes,new Uint8Array(0),1),pr[96]=new lt(ft.string,"",1),pr[128]=new lt(ft.array,0,1),pr[160]=new lt(ft.map,0,1),pr[244]=new lt(ft.false,!1,1),pr[245]=new lt(ft.true,!0,1),pr[246]=new lt(ft.null,null,1);const wr={float64:!1,mapSorter:function(e,t){const r=Array.isArray(e[0])?e[0][0]:e[0],n=Array.isArray(t[0])?t[0][0]:t[0];if(r.type!==n.type)return r.type.compare(n.type);const o=r.type.major,i=br[o].compareTokens(r,n);return 0===i&&console.warn("WARNING: complex key types used, CBOR key sorting guarantees are gone"),i},quickEncodeToken:function(e){switch(e.type){case ft.false:return vt([244]);case ft.true:return vt([245]);case ft.null:return vt([246]);case ft.bytes:return e.value.length?void 0:vt([64]);case ft.string:return""===e.value?vt([96]):void 0;case ft.array:return 0===e.value?vt([128]):void 0;case ft.map:return 0===e.value?vt([160]):void 0;case ft.uint:return e.value<24?vt([Number(e.value)]):void 0;case ft.negint:if(e.value>=-24)return vt([31-Number(e.value)])}}},br=function(){const e=[];return e[ft.uint.major]=Pt,e[ft.negint.major]=Mt,e[ft.bytes.major]=Vt,e[ft.string.major]=Gt,e[ft.array.major]=Kt,e[ft.map.major]=Zt,e[ft.tag.major]=er,e[ft.float.major]=rr,e}(),yr=new Bt;class gr{constructor(e,t){this.obj=e,this.parent=t}includes(e){let t=this;do{if(t.obj===e)return!0}while(t=t.parent);return!1}static createCheck(e,t){if(e&&e.includes(t))throw new Error("CBOR encode error: object contains circular references");return new gr(t,e)}}const mr={null:new lt(ft.null,null),undefined:new lt(ft.undefined,void 0),true:new lt(ft.true,!0),false:new lt(ft.false,!1),emptyArray:new lt(ft.array,0),emptyMap:new lt(ft.map,0)},vr={number:(e,t,r,n)=>Number.isInteger(e)&&Number.isSafeInteger(e)?new lt(e>=0?ft.uint:ft.negint,e):new lt(ft.float,e),bigint:(e,t,r,n)=>e>=BigInt(0)?new lt(ft.uint,e):new lt(ft.negint,e),Uint8Array:(e,t,r,n)=>new lt(ft.bytes,e),string:(e,t,r,n)=>new lt(ft.string,e),boolean:(e,t,r,n)=>e?mr.true:mr.false,null:(e,t,r,n)=>mr.null,undefined:(e,t,r,n)=>mr.undefined,ArrayBuffer:(e,t,r,n)=>new lt(ft.bytes,new Uint8Array(e)),DataView:(e,t,r,n)=>new lt(ft.bytes,new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),Array(e,t,r,n){if(!e.length)return!0===r.addBreakTokens?[mr.emptyArray,new lt(ft.break)]:mr.emptyArray;n=gr.createCheck(n,e);const o=[];let i=0;for(const t of e)o[i++]=_r(t,r,n);return r.addBreakTokens?[new lt(ft.array,e.length),o,new lt(ft.break)]:[new lt(ft.array,e.length),o]},Object(e,t,r,n){const o="Object"!==t,i=o?e.keys():Object.keys(e),s=o?e.size:i.length;if(!s)return!0===r.addBreakTokens?[mr.emptyMap,new lt(ft.break)]:mr.emptyMap;n=gr.createCheck(n,e);const a=[];let c=0;for(const t of i)a[c++]=[_r(t,r,n),_r(o?e.get(t):e[t],r,n)];return function(e,t){t.mapSorter&&e.sort(t.mapSorter)}(a,r),r.addBreakTokens?[new lt(ft.map,s),a,new lt(ft.break)]:[new lt(ft.map,s),a]}};vr.Map=vr.Object,vr.Buffer=vr.Uint8Array;for(const e of"Uint8Clamped Uint16 Uint32 Int8 Int16 Int32 BigUint64 BigInt64 Float32 Float64".split(" "))vr[`${e}Array`]=vr.DataView;function _r(e,t={},r){const n=function(e){if(null===e)return"null";if(void 0===e)return"undefined";if(!0===e||!1===e)return"boolean";const t=typeof e;if(ut.includes(t))return t;if("function"===t)return"Function";if(Array.isArray(e))return"Array";if(function(e){return e&&e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer.call(null,e)}(e))return"Buffer";const r=function(e){const t=Object.prototype.toString.call(e).slice(8,-1);if(ht.includes(t))return t}(e);return r||"Object"}(e),o=t&&t.typeEncoders&&t.typeEncoders[n]||vr[n];if("function"==typeof o){const i=o(e,n,t,r);if(null!=i)return i}const i=vr[n];if(!i)throw new Error(`CBOR encode error: unsupported type: ${n}`);return i(e,n,t,r)}function kr(e,t,r,n){if(Array.isArray(t))for(const o of t)kr(e,o,r,n);else r[t.type.major](e,t,n)}function Er(e,t,r){const n=_r(e,r);if(!Array.isArray(n)&&r.quickEncodeToken){const e=r.quickEncodeToken(n);if(e)return e;const o=t[n.type.major];if(o.encodedSize){const e=o.encodedSize(n,r),t=new Bt(e);if(o(t,n,r),1!==t.chunks.length)throw new Error(`Unexpected error: pre-calculated length for ${n} was wrong`);return yt(t.chunks[0])}}return yr.reset(),kr(yr,n,t,r),yr.toBytes(!0)}const xr={strict:!1,allowIndefinite:!0,allowUndefined:!0,allowBigInt:!0};class Cr{constructor(e,t={}){this.pos=0,this.data=e,this.options=t}done(){return this.pos>=this.data.length}next(){const e=this.data[this.pos];let t=pr[e];if(void 0===t){const r=dr[e];if(!r)throw new Error(`CBOR decode error: no decoder for major type ${e>>>5} (byte 0x${e.toString(16).padStart(2,"0")})`);const n=31&e;t=r(this.data,this.pos,n,this.options)}return this.pos+=t.encodedLength,t}}const Ar=Symbol.for("DONE"),Br=Symbol.for("BREAK");function Ir(e,t){if(e.done())return Ar;const r=e.next();if(r.type===ft.break)return Br;if(r.type.terminal)return r.value;if(r.type===ft.array)return function(e,t,r){const n=[];for(let o=0;o=Dr;)r[n++]=255&t|128,t/=128;for(;-128&t;)r[n++]=255&t|128,t>>>=7;return r[n]=0|t,e.bytes=n-o+1,r},decode:function e(t,r){var n,o=0,i=0,s=r=r||0,a=t.length;do{if(s>=a)throw e.bytes=0,new RangeError("Could not decode varint");n=t[s++],o+=i<28?(127&n)<=128);return e.bytes=s-r,o},encodingLength:function(e){return e[jr.decode(e,t),jr.decode.bytes],Fr=(e,t,r=0)=>(jr.encode(e,t,r),t),Vr=e=>jr.encodingLength(e),Hr=(new Uint8Array(0),e=>{if(e instanceof Uint8Array&&"Uint8Array"===e.constructor.name)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Unknown type, must be binary type")});class qr{constructor(e,t,r,n){this.code=e,this.size=t,this.digest=r,this.bytes=n}}const Gr=function(e,t){if(e.length>=255)throw new TypeError("Alphabet too long");for(var r=new Uint8Array(256),n=0;n>>0,s=new Uint8Array(i);e[t];){var h=r[e.charCodeAt(t)];if(255===h)return;for(var f=0,l=i-1;(0!==h||f>>0,s[l]=h%256>>>0,h=h/256>>>0;if(0!==h)throw new Error("Non-zero carry");o=f,t++}if(" "!==e[t]){for(var d=i-o;d!==i&&0===s[d];)d++;for(var p=new Uint8Array(n+(i-d)),w=n;d!==i;)p[w++]=s[d++];return p}}}return{encode:function(t){if(t instanceof Uint8Array||(ArrayBuffer.isView(t)?t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength):Array.isArray(t)&&(t=Uint8Array.from(t))),!(t instanceof Uint8Array))throw new TypeError("Expected Uint8Array");if(0===t.length)return"";for(var r=0,n=0,o=0,i=t.length;o!==i&&0===t[o];)o++,r++;for(var s=(i-o)*h+1>>>0,u=new Uint8Array(s);o!==i;){for(var f=t[o],l=0,d=s-1;(0!==f||l>>0,u[d]=f%a>>>0,f=f/a>>>0;if(0!==f)throw new Error("Non-zero carry");n=l,o++}for(var p=s-n;p!==s&&0===u[p];)p++;for(var w=c.repeat(r);pnew Kr({...e.decoders||{[e.prefix]:e},...t.decoders||{[t.prefix]:t}});class Xr{constructor(e,t,r,n){this.name=e,this.prefix=t,this.baseEncode=r,this.baseDecode=n,this.encoder=new Wr(e,t,r),this.decoder=new Jr(e,t,n)}encode(e){return this.encoder.encode(e)}decode(e){return this.decoder.decode(e)}}const Zr=({name:e,prefix:t,encode:r,decode:n})=>new Xr(e,t,r,n),Yr=({prefix:e,name:t,alphabet:r})=>{const{encode:n,decode:o}=Gr(r,t);return Zr({prefix:e,name:t,encode:n,decode:e=>Hr(o(e))})},en=({name:e,prefix:t,bitsPerChar:r,alphabet:n})=>Zr({prefix:t,name:e,encode:e=>((e,t,r)=>{const n="="===t[t.length-1],o=(1<r;)s-=r,i+=t[o&a>>s];if(s&&(i+=t[o&a<((e,t,r,n)=>{const o={};for(let e=0;e=8&&(a-=8,s[u++]=255&c>>a)}if(a>=r||255&c<<8-a)throw new SyntaxError("Unexpected end of data");return s})(t,n,r,e)}),tn=Yr({name:"base58btc",prefix:"z",alphabet:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"}),rn=(Yr({name:"base58flickr",prefix:"Z",alphabet:"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"}),en({prefix:"b",name:"base32",alphabet:"abcdefghijklmnopqrstuvwxyz234567",bitsPerChar:5}));en({prefix:"B",name:"base32upper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",bitsPerChar:5}),en({prefix:"c",name:"base32pad",alphabet:"abcdefghijklmnopqrstuvwxyz234567=",bitsPerChar:5}),en({prefix:"C",name:"base32padupper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",bitsPerChar:5}),en({prefix:"v",name:"base32hex",alphabet:"0123456789abcdefghijklmnopqrstuv",bitsPerChar:5}),en({prefix:"V",name:"base32hexupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV",bitsPerChar:5}),en({prefix:"t",name:"base32hexpad",alphabet:"0123456789abcdefghijklmnopqrstuv=",bitsPerChar:5}),en({prefix:"T",name:"base32hexpadupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV=",bitsPerChar:5}),en({prefix:"h",name:"base32z",alphabet:"ybndrfg8ejkmcpqxot1uwisza345h769",bitsPerChar:5});class nn{constructor(e,t,r,n){this.code=t,this.version=e,this.multihash=r,this.bytes=n,this.byteOffset=n.byteOffset,this.byteLength=n.byteLength,this.asCID=this,this._baseCache=new Map,Object.defineProperties(this,{byteOffset:dn,byteLength:dn,code:ln,version:ln,multihash:ln,bytes:ln,_baseCache:dn,asCID:dn})}toV0(){if(0===this.version)return this;{const{code:e,multihash:t}=this;if(e!==cn)throw new Error("Cannot convert a non dag-pb CID to CIDv0");if(t.code!==un)throw new Error("Cannot convert non sha2-256 multihash CID to CIDv0");return nn.createV0(t)}}toV1(){switch(this.version){case 0:{const{code:e,digest:t}=this.multihash,r=((e,t)=>{const r=t.byteLength,n=Vr(e),o=n+Vr(r),i=new Uint8Array(o+r);return Fr(e,i,0),Fr(r,i,n),i.set(t,o),new qr(e,r,t,i)})(e,t);return nn.createV1(this.code,r)}case 1:return this;default:throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`)}}equals(e){return e&&this.code===e.code&&this.version===e.version&&((t=this.multihash)===(r=e.multihash)||t.code===r.code&&t.size===r.size&&((e,t)=>{if(e===t)return!0;if(e.byteLength!==t.byteLength)return!1;for(let r=0;r{const t=Hr(e),[r,n]=$r(t),[o,i]=$r(t.subarray(n)),s=t.subarray(n+i);if(s.byteLength!==o)throw new Error("Incorrect length");return new qr(r,o,s,t)})(r);return nn.create(t,n,o)}return null}static create(e,t,r){if("number"!=typeof t)throw new Error("String codecs are no longer supported");switch(e){case 0:if(t!==cn)throw new Error(`Version 0 CID must use dag-pb (code: ${cn}) block encoding`);return new nn(e,t,r,r.bytes);case 1:{const n=hn(e,t,r.bytes);return new nn(e,t,r,n)}default:throw new Error("Invalid version")}}static createV0(e){return nn.create(0,cn,e)}static createV1(e,t){return nn.create(1,e,t)}static decode(e){const[t,r]=nn.decodeFirst(e);if(r.length)throw new Error("Incorrect length");return t}static decodeFirst(e){const t=nn.inspectBytes(e),r=t.size-t.multihashSize,n=Hr(e.subarray(r,r+t.multihashSize));if(n.byteLength!==t.multihashSize)throw new Error("Incorrect length");const o=n.subarray(t.multihashSize-t.digestSize),i=new qr(t.multihashCode,t.digestSize,o,n);return[0===t.version?nn.createV0(i):nn.createV1(t.codec,i),e.subarray(t.size)]}static inspectBytes(e){let t=0;const r=()=>{const[r,n]=$r(e.subarray(t));return t+=n,r};let n=r(),o=cn;if(18===n?(n=0,t=0):1===n&&(o=r()),0!==n&&1!==n)throw new RangeError(`Invalid CID version ${n}`);const i=t,s=r(),a=r(),c=t+a;return{version:n,codec:o,multihashCode:s,digestSize:a,multihashSize:c-i,size:c}}static parse(e,t){const[r,n]=on(e,t),o=nn.decode(n);return o._baseCache.set(r,e),o}}const on=(e,t)=>{switch(e[0]){case"Q":{const r=t||tn;return[tn.prefix,r.decode(`${tn.prefix}${e}`)]}case tn.prefix:{const r=t||tn;return[tn.prefix,r.decode(e)]}case rn.prefix:{const r=t||rn;return[rn.prefix,r.decode(e)]}default:if(null==t)throw Error("To parse non base32 or base58btc encoded CID multibase decoder must be provided");return[e[0],t.decode(e)]}},sn=(e,t,r)=>{const{prefix:n}=r;if(n!==tn.prefix)throw Error(`Cannot string encode V0 in ${r.name} encoding`);const o=t.get(n);if(null==o){const o=r.encode(e).slice(1);return t.set(n,o),o}return o},an=(e,t,r)=>{const{prefix:n}=r,o=t.get(n);if(null==o){const o=r.encode(e);return t.set(n,o),o}return o},cn=112,un=18,hn=(e,t,r)=>{const n=Vr(e),o=n+Vr(t),i=new Uint8Array(o+r.byteLength);return Fr(e,i,0),Fr(t,i,n),i.set(r,o),i},fn=Symbol.for("@ipld/js-cid/CID"),ln={writable:!1,configurable:!1,enumerable:!0},dn={writable:!1,enumerable:!1,configurable:!1},pn=(e,t)=>{if(!e.test("0.0.0-dev"))throw new Error(t);console.warn(t)},wn="CID.isCID(v) is deprecated and will be removed in the next major release.\nFollowing code pattern:\n\nif (CID.isCID(value)) {\n doSomethingWithCID(value)\n}\n\nIs replaced with:\n\nconst cid = CID.asCID(value)\nif (cid) {\n // Make sure to use cid instead of value\n doSomethingWithCID(cid)\n}\n",bn={float64:!0,typeEncoders:{Object:function(e){if(e.asCID!==e)return null;const t=nn.asCID(e);if(!t)return null;const r=new Uint8Array(t.bytes.byteLength+1);return r.set(t.bytes,1),[new lt(ft.tag,42),new lt(ft.bytes,r)]},undefined:function(){throw new Error("`undefined` is not supported by the IPLD Data Model and cannot be encoded")},number:function(e){if(Number.isNaN(e))throw new Error("`NaN` is not supported by the IPLD Data Model and cannot be encoded");if(e===1/0||e===-1/0)throw new Error("`Infinity` and `-Infinity` is not supported by the IPLD Data Model and cannot be encoded");return null}}},yn={allowIndefinite:!1,coerceUndefinedToNull:!0,allowNaN:!1,allowInfinity:!1,allowBigInt:!0,strict:!0,useMaps:!1,tags:[]};yn.tags[42]=function(e){if(0!==e[0])throw new Error("Invalid CID for CBOR tag 42; expected leading 0x00");return nn.decode(e.subarray(1))};const gn="dag-cbor",mn=113,vn=e=>{return t=e,r=bn,r=Object.assign({},wr,r),Er(t,br,r);var t,r},_n=e=>Sr(e,yn),kn={Null:e=>null===e,Int:e=>Number.isInteger(e),Float:e=>"number"==typeof e&&Number.isFinite(e),String:e=>"string"==typeof e,Bool:e=>"boolean"==typeof e,Bytes:e=>e instanceof Uint8Array,Link:e=>!kn.Null(e)&&"object"==typeof e&&e.asCID===e,List:e=>Array.isArray(e),Map:e=>!kn.Null(e)&&"object"==typeof e&&e.asCID!==e&&!kn.List(e)&&!kn.Bytes(e)},En={Int:kn.Int,"CarHeader > version":e=>En.Int(e),"CarHeader > roots (anon) > valueType (anon)":kn.Link,"CarHeader > roots (anon)":e=>kn.List(e)&&Array.prototype.every.call(e,En["CarHeader > roots (anon) > valueType (anon)"]),"CarHeader > roots":e=>En["CarHeader > roots (anon)"](e),CarHeader:e=>{const t=e&&Object.keys(e);return kn.Map(e)&&["version"].every((e=>t.includes(e)))&&Object.entries(e).every((([e,t])=>En["CarHeader > "+e]&&En["CarHeader > "+e](t)))}},xn=En.CarHeader;async function Cn(e){const t=await e.upTo(8);if(!t.length)throw new Error("Unexpected end of data");const r=ke.decode(t);return e.seek(ke.decode.bytes),r}async function An(e,t){const r=await Cn(e);if(0===r)throw new Error("Invalid CAR header (zero length)");const n=await e.exactly(r);e.seek(r);const o=_n(n);if(!xn(o))throw new Error("Invalid CAR header format");if(1!==o.version&&2!==o.version||void 0!==t&&o.version!==t)throw new Error(`Invalid CAR version: ${o.version}${void 0!==t?` (expected ${t})`:""}`);const i=Array.isArray(o.roots);if(1===o.version&&!i||2===o.version&&i)throw new Error("Invalid CAR header format");if(1===o.version)return o;const s=await async function(e){const t=await e.exactly(40),r=new DataView(t.buffer,t.byteOffset,t.byteLength);let n=0;const o={version:2,characteristics:[r.getBigUint64(n,!0),r.getBigUint64(n+=8,!0)],dataOffset:Number(r.getBigUint64(n+=8,!0)),dataSize:Number(r.getBigUint64(n+=8,!0)),indexOffset:Number(r.getBigUint64(n+=8,!0))};return e.seek(40),o}(e);e.seek(s.dataOffset-e.pos);const a=await An(e,1);return Object.assign(a,s)}async function Bn(e){const t=await e.exactly(2);if(18===t[0]&&32===t[1]){const t=await e.exactly(34);e.seek(34);const r=Re(t);return Xe.create(0,112,r)}const r=await Cn(e);if(1!==r)throw new Error(`Unexpected CID version (${r})`);const n=await Cn(e),o=await async function(e){const t=await e.upTo(8);ke.decode(t);const r=ke.decode.bytes,n=ke.decode(t.subarray(ke.decode.bytes)),o=r+ke.decode.bytes+n,i=await e.exactly(o);return e.seek(o),i}(e),i=Re(o);return Xe.create(r,n,i)}async function In(e){const t=e.pos;let r=await Cn(e);if(0===r)throw new Error("Invalid CAR section (zero length)");return r+=e.pos-t,{cid:await Bn(e),length:r,blockLength:r-Number(e.pos-t)}}async function Sn(e){const{cid:t,blockLength:r}=await In(e),n=await e.exactly(r);return e.seek(r),{bytes:n,cid:t}}async function Dn(e){const t=e.pos,{cid:r,length:n,blockLength:o}=await In(e),i={cid:r,length:n,blockLength:o,offset:t,blockOffset:e.pos};return e.seek(i.blockLength),i}function Tn(e){const t=(async()=>{const t=await An(e);if(2===t.version){const r=e.pos-t.dataOffset;e=function(e,t){let r=0;return{async upTo(n){let o=await e.upTo(n);return o.length+r>t&&(o=o.subarray(0,t-r)),o},async exactly(n){const o=await e.exactly(n);if(o.length+r>t)throw new Error("Unexpected end of data");return o},seek(t){r+=t,e.seek(t)},get pos(){return e.pos}}}(e,t.dataSize-r)}return t})();return{header:()=>t,async*blocks(){for(await t;(await e.upTo(8)).length>0;)yield await Sn(e)},async*blocksIndex(){for(await t;(await e.upTo(8)).length>0;)yield await Dn(e)}}}class Un{constructor(e,t,r){this._version=e,this._roots=t,this._iterator=r}get version(){return this._version}async getRoots(){return this._roots}[Symbol.asyncIterator](){return this._iterator}static async fromBytes(e){if(!(e instanceof Uint8Array))throw new TypeError("fromBytes() requires a Uint8Array");return decodeIndexerComplete(bytesReader(e))}static async fromIterable(e){if(!e||"function"!=typeof e[Symbol.asyncIterator])throw new TypeError("fromIterable() requires an async iterable");return decodeIndexerComplete(asyncIterableReader(e))}}class Nn{constructor(e,t,r){this._version=e,this._roots=t,this._iterable=r,this._decoded=!1}get version(){return this._version}async getRoots(){return this._roots}}class On extends Nn{[Symbol.asyncIterator](){if(this._decoded)throw new Error("Cannot decode more than once");if(!this._iterable)throw new Error("Block iterable not found");return this._decoded=!0,this._iterable[Symbol.asyncIterator]()}static async fromBytes(e){const{version:t,roots:r,iterator:n}=await zn(e);return new On(t,r,n)}static async fromIterable(e){const{version:t,roots:r,iterator:n}=await Ln(e);return new On(t,r,n)}}class Pn extends(null){[Symbol.asyncIterator](){if(this._decoded)throw new Error("Cannot decode more than once");if(!this._iterable)throw new Error("Block iterable not found");this._decoded=!0;const e=this._iterable[Symbol.asyncIterator]();return{async next(){const t=await e.next();return t.done?t:{done:!1,value:t.value.cid}}}}static async fromBytes(e){const{version:t,roots:r,iterator:n}=await zn(e);return new Pn(t,r,n)}static async fromIterable(e){const{version:t,roots:r,iterator:n}=await Ln(e);return new Pn(t,r,n)}}async function zn(e){if(!(e instanceof Uint8Array))throw new TypeError("fromBytes() requires a Uint8Array");return Rn(function(e){let t=0;return{upTo:async r=>e.subarray(t,t+Math.min(r,e.length-t)),async exactly(r){if(r>e.length-t)throw new Error("Unexpected end of data");return e.subarray(t,t+r)},seek(e){t+=e},get pos(){return t}}}(e))}async function Ln(e){if(!e||"function"!=typeof e[Symbol.asyncIterator])throw new TypeError("fromIterable() requires an async iterable");return Rn(function(e){const t=e[Symbol.asyncIterator]();return function(e){let t=0,r=0,n=0,o=new Uint8Array(0);const i=async t=>{r=o.length-n;const i=[o.subarray(n)];for(;rr&&i.push(t.subarray(-r)):i.push(t),r+=t.length}o=new Uint8Array(i.reduce(((e,t)=>e+t.length),0));let s=0;for(const e of i)o.set(e,s),s+=e.length;n=0};return{upTo:async e=>(o.length-n=jn;)r[n++]=255&t|128,t/=128;for(;-128&t;)r[n++]=255&t|128,t>>>=7;return r[n]=0|t,e.bytes=n-o+1,r},decode:function e(t,r){var n,o=0,i=0,s=r=r||0,a=t.length;do{if(s>=a)throw e.bytes=0,new RangeError("Could not decode varint");n=t[s++],o+=i<28?(127&n)<=128);return e.bytes=s-r,o},encodingLength:function(e){return e<$n?1:e[Qn.decode(e,t),Qn.decode.bytes],Zn=(e,t,r=0)=>(Qn.encode(e,t,r),t),Yn=e=>Qn.encodingLength(e),eo=(new Uint8Array(0),e=>{if(e instanceof Uint8Array&&"Uint8Array"===e.constructor.name)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Unknown type, must be binary type")});class to{constructor(e,t,r,n){this.code=e,this.size=t,this.digest=r,this.bytes=n}}const ro=function(e,t){if(e.length>=255)throw new TypeError("Alphabet too long");for(var r=new Uint8Array(256),n=0;n>>0,s=new Uint8Array(i);e[t];){var h=r[e.charCodeAt(t)];if(255===h)return;for(var f=0,l=i-1;(0!==h||f>>0,s[l]=h%256>>>0,h=h/256>>>0;if(0!==h)throw new Error("Non-zero carry");o=f,t++}if(" "!==e[t]){for(var d=i-o;d!==i&&0===s[d];)d++;for(var p=new Uint8Array(n+(i-d)),w=n;d!==i;)p[w++]=s[d++];return p}}}return{encode:function(t){if(t instanceof Uint8Array||(ArrayBuffer.isView(t)?t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength):Array.isArray(t)&&(t=Uint8Array.from(t))),!(t instanceof Uint8Array))throw new TypeError("Expected Uint8Array");if(0===t.length)return"";for(var r=0,n=0,o=0,i=t.length;o!==i&&0===t[o];)o++,r++;for(var s=(i-o)*h+1>>>0,u=new Uint8Array(s);o!==i;){for(var f=t[o],l=0,d=s-1;(0!==f||l>>0,u[d]=f%a>>>0,f=f/a>>>0;if(0!==f)throw new Error("Non-zero carry");n=l,o++}for(var p=s-n;p!==s&&0===u[p];)p++;for(var w=c.repeat(r);pnew io({...e.decoders||{[e.prefix]:e},...t.decoders||{[t.prefix]:t}});class ao{constructor(e,t,r,n){this.name=e,this.prefix=t,this.baseEncode=r,this.baseDecode=n,this.encoder=new no(e,t,r),this.decoder=new oo(e,t,n)}encode(e){return this.encoder.encode(e)}decode(e){return this.decoder.decode(e)}}const co=({name:e,prefix:t,encode:r,decode:n})=>new ao(e,t,r,n),uo=({prefix:e,name:t,alphabet:r})=>{const{encode:n,decode:o}=ro(r,t);return co({prefix:e,name:t,encode:n,decode:e=>eo(o(e))})},ho=({name:e,prefix:t,bitsPerChar:r,alphabet:n})=>co({prefix:t,name:e,encode:e=>((e,t,r)=>{const n="="===t[t.length-1],o=(1<r;)s-=r,i+=t[o&a>>s];if(s&&(i+=t[o&a<((e,t,r,n)=>{const o={};for(let e=0;e=8&&(a-=8,s[u++]=255&c>>a)}if(a>=r||255&c<<8-a)throw new SyntaxError("Unexpected end of data");return s})(t,n,r,e)}),fo=uo({name:"base58btc",prefix:"z",alphabet:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"}),lo=(uo({name:"base58flickr",prefix:"Z",alphabet:"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"}),ho({prefix:"b",name:"base32",alphabet:"abcdefghijklmnopqrstuvwxyz234567",bitsPerChar:5}));ho({prefix:"B",name:"base32upper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",bitsPerChar:5}),ho({prefix:"c",name:"base32pad",alphabet:"abcdefghijklmnopqrstuvwxyz234567=",bitsPerChar:5}),ho({prefix:"C",name:"base32padupper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",bitsPerChar:5}),ho({prefix:"v",name:"base32hex",alphabet:"0123456789abcdefghijklmnopqrstuv",bitsPerChar:5}),ho({prefix:"V",name:"base32hexupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV",bitsPerChar:5}),ho({prefix:"t",name:"base32hexpad",alphabet:"0123456789abcdefghijklmnopqrstuv=",bitsPerChar:5}),ho({prefix:"T",name:"base32hexpadupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV=",bitsPerChar:5}),ho({prefix:"h",name:"base32z",alphabet:"ybndrfg8ejkmcpqxot1uwisza345h769",bitsPerChar:5});class po{constructor(e,t,r,n){this.code=t,this.version=e,this.multihash=r,this.bytes=n,this.byteOffset=n.byteOffset,this.byteLength=n.byteLength,this.asCID=this,this._baseCache=new Map,Object.defineProperties(this,{byteOffset:Eo,byteLength:Eo,code:ko,version:ko,multihash:ko,bytes:ko,_baseCache:Eo,asCID:Eo})}toV0(){if(0===this.version)return this;{const{code:e,multihash:t}=this;if(e!==go)throw new Error("Cannot convert a non dag-pb CID to CIDv0");if(t.code!==mo)throw new Error("Cannot convert non sha2-256 multihash CID to CIDv0");return po.createV0(t)}}toV1(){switch(this.version){case 0:{const{code:e,digest:t}=this.multihash,r=((e,t)=>{const r=t.byteLength,n=Yn(e),o=n+Yn(r),i=new Uint8Array(o+r);return Zn(e,i,0),Zn(r,i,n),i.set(t,o),new to(e,r,t,i)})(e,t);return po.createV1(this.code,r)}case 1:return this;default:throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`)}}equals(e){return e&&this.code===e.code&&this.version===e.version&&((t=this.multihash)===(r=e.multihash)||t.code===r.code&&t.size===r.size&&((e,t)=>{if(e===t)return!0;if(e.byteLength!==t.byteLength)return!1;for(let r=0;r{const t=eo(e),[r,n]=Xn(t),[o,i]=Xn(t.subarray(n)),s=t.subarray(n+i);if(s.byteLength!==o)throw new Error("Incorrect length");return new to(r,o,s,t)})(r);return po.create(t,n,o)}return null}static create(e,t,r){if("number"!=typeof t)throw new Error("String codecs are no longer supported");switch(e){case 0:if(t!==go)throw new Error(`Version 0 CID must use dag-pb (code: ${go}) block encoding`);return new po(e,t,r,r.bytes);case 1:{const n=vo(e,t,r.bytes);return new po(e,t,r,n)}default:throw new Error("Invalid version")}}static createV0(e){return po.create(0,go,e)}static createV1(e,t){return po.create(1,e,t)}static decode(e){const[t,r]=po.decodeFirst(e);if(r.length)throw new Error("Incorrect length");return t}static decodeFirst(e){const t=po.inspectBytes(e),r=t.size-t.multihashSize,n=eo(e.subarray(r,r+t.multihashSize));if(n.byteLength!==t.multihashSize)throw new Error("Incorrect length");const o=n.subarray(t.multihashSize-t.digestSize),i=new to(t.multihashCode,t.digestSize,o,n);return[0===t.version?po.createV0(i):po.createV1(t.codec,i),e.subarray(t.size)]}static inspectBytes(e){let t=0;const r=()=>{const[r,n]=Xn(e.subarray(t));return t+=n,r};let n=r(),o=go;if(18===n?(n=0,t=0):1===n&&(o=r()),0!==n&&1!==n)throw new RangeError(`Invalid CID version ${n}`);const i=t,s=r(),a=r(),c=t+a;return{version:n,codec:o,multihashCode:s,digestSize:a,multihashSize:c-i,size:c}}static parse(e,t){const[r,n]=wo(e,t),o=po.decode(n);return o._baseCache.set(r,e),o}}const wo=(e,t)=>{switch(e[0]){case"Q":{const r=t||fo;return[fo.prefix,r.decode(`${fo.prefix}${e}`)]}case fo.prefix:{const r=t||fo;return[fo.prefix,r.decode(e)]}case lo.prefix:{const r=t||lo;return[lo.prefix,r.decode(e)]}default:if(null==t)throw Error("To parse non base32 or base58btc encoded CID multibase decoder must be provided");return[e[0],t.decode(e)]}},bo=(e,t,r)=>{const{prefix:n}=r;if(n!==fo.prefix)throw Error(`Cannot string encode V0 in ${r.name} encoding`);const o=t.get(n);if(null==o){const o=r.encode(e).slice(1);return t.set(n,o),o}return o},yo=(e,t,r)=>{const{prefix:n}=r,o=t.get(n);if(null==o){const o=r.encode(e);return t.set(n,o),o}return o},go=112,mo=18,vo=(e,t,r)=>{const n=Yn(e),o=n+Yn(t),i=new Uint8Array(o+r.byteLength);return Zn(e,i,0),Zn(t,i,n),i.set(r,o),i},_o=Symbol.for("@ipld/js-cid/CID"),ko={writable:!1,configurable:!1,enumerable:!0},Eo={writable:!1,enumerable:!1,configurable:!1},xo=(e,t)=>{if(!e.test("0.0.0-dev"))throw new Error(t);console.warn(t)},Co="CID.isCID(v) is deprecated and will be removed in the next major release.\nFollowing code pattern:\n\nif (CID.isCID(value)) {\n doSomethingWithCID(value)\n}\n\nIs replaced with:\n\nconst cid = CID.asCID(value)\nif (cid) {\n // Make sure to use cid instead of value\n doSomethingWithCID(cid)\n}\n",Ao=new TextDecoder;function Bo(e,t){let r=0;for(let n=0;;n+=7){if(n>=64)throw new Error("protobuf: varint overflow");if(t>=e.length)throw new Error("protobuf: unexpected end of data");const o=e[t++];if(r+=n<28?(127&o)<e.length)throw new Error("protobuf: unexpected end of data");return[e.subarray(t,n),n]}function So(e,t){let r;return[r,t]=Bo(e,t),[7&r,r>>3,t]}function Do(e){const t={},r=e.length;let n=0;for(;nr)throw new Error("protobuf: (PBLink) unexpected end of data");return t}const To=new TextEncoder,Uo=2**32;function No(e,t){let r=t.length;if("number"==typeof e.Tsize){if(e.Tsize<0)throw new Error("Tsize cannot be negative");if(!Number.isSafeInteger(e.Tsize))throw new Error("Tsize too large for encoding");r=Po(t,r,e.Tsize)-1,t[r]=24}if("string"==typeof e.Name){const n=To.encode(e.Name);r-=n.length,t.set(n,r),r=Po(t,r,n.length)-1,t[r]=18}return e.Hash&&(r-=e.Hash.length,t.set(e.Hash,r),r=Po(t,r,e.Hash.length)-1,t[r]=10),t.length-r}function Oo(e){let t=0;if(e.Hash){const r=e.Hash.length;t+=1+r+zo(r)}if("string"==typeof e.Name){const r=To.encode(e.Name).length;t+=1+r+zo(r)}return"number"==typeof e.Tsize&&(t+=1+zo(e.Tsize)),t}function Po(e,t,r){const n=t-=zo(r);for(;r>=2147483648;)e[t++]=127&r|128,r/=128;for(;r>=128;)e[t++]=127&r|128,r>>>=7;return e[t]=r,n}function zo(e){return e%2==0&&e++,Math.floor((function(e){let t=0;return e>=Uo&&(e=Math.floor(e/Uo),t=32),e>=65536&&(e>>>=16,t+=16),e>=256&&(e>>>=8,t+=8),t+Lo[e]}(e)+6)/7)}const Lo=[0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8],Ro=["Data","Links"],Mo=["Hash","Name","Tsize"],jo=new TextEncoder;function $o(e,t){if(e===t)return 0;const r=e.Name?jo.encode(e.Name):[],n=t.Name?jo.encode(t.Name):[];let o=r.length,i=n.length;for(let e=0,t=Math.min(o,i);e!t.includes(e)))}function Vo(e){if("object"==typeof e.asCID){const t=po.asCID(e);if(!t)throw new TypeError("Invalid DAG-PB form");return{Hash:t}}if("object"!=typeof e||Array.isArray(e))throw new TypeError("Invalid DAG-PB form");const t={};if(e.Hash){let r=po.asCID(e.Hash);try{r||("string"==typeof e.Hash?r=po.parse(e.Hash):e.Hash instanceof Uint8Array&&(r=po.decode(e.Hash)))}catch(e){throw new TypeError(`Invalid DAG-PB form: ${e.message}`)}r&&(t.Hash=r)}if(!t.Hash)throw new TypeError("Invalid DAG-PB form");return"string"==typeof e.Name&&(t.Name=e.Name),"number"==typeof e.Tsize&&(t.Tsize=e.Tsize),t}function Ho(e){if((e instanceof Uint8Array||"string"==typeof e)&&(e={Data:e}),"object"!=typeof e||Array.isArray(e))throw new TypeError("Invalid DAG-PB form");const t={};if(void 0!==e.Data)if("string"==typeof e.Data)t.Data=jo.encode(e.Data);else{if(!(e.Data instanceof Uint8Array))throw new TypeError("Invalid DAG-PB form");t.Data=e.Data}if(void 0!==e.Links){if(!Array.isArray(e.Links))throw new TypeError("Invalid DAG-PB form");t.Links=e.Links.map(Vo),t.Links.sort($o)}else t.Links=[];return t}function qo(e){if(!e||"object"!=typeof e||Array.isArray(e))throw new TypeError("Invalid DAG-PB form");if(!Fo(e,Ro))throw new TypeError("Invalid DAG-PB form (extraneous properties)");if(void 0!==e.Data&&!(e.Data instanceof Uint8Array))throw new TypeError("Invalid DAG-PB form (Data must be a Uint8Array)");if(!Array.isArray(e.Links))throw new TypeError("Invalid DAG-PB form (Links must be an array)");for(let t=0;t0&&-1===$o(r,e.Links[t-1]))throw new TypeError("Invalid DAG-PB form (links must be sorted by Name bytes)")}}function Go(e,t=[]){return Ho({Data:e,Links:t})}function Wo(e,t,r){return Vo({Hash:r,Name:e,Tsize:t})}const Jo="dag-pb",Ko=112;function Qo(e){qo(e);const t={};return e.Links&&(t.Links=e.Links.map((e=>{const t={};return e.Hash&&(t.Hash=e.Hash.bytes),void 0!==e.Name&&(t.Name=e.Name),void 0!==e.Tsize&&(t.Tsize=e.Tsize),t}))),e.Data&&(t.Data=e.Data),function(e){const t=function(e){let t=0;if(e.Data){const r=e.Data.length;t+=1+r+zo(r)}if(e.Links)for(const r of e.Links){const e=Oo(r);t+=1+e+zo(e)}return t}(e),r=new Uint8Array(t);let n=t;if(e.Data&&(n-=e.Data.length,r.set(e.Data,n),n=Po(r,n,e.Data.length)-1,r[n]=10),e.Links)for(let t=e.Links.length-1;t>=0;t--){const o=No(e.Links[t],r.subarray(0,n));n-=o,n=Po(r,n,o)-1,r[n]=18}return r}(t)}function Xo(e){const t=function(e){const t=e.length;let r,n,o=0,i=!1;for(;ot)throw new Error("protobuf: (PBNode) unexpected end of data");const s={};return n&&(s.Data=n),s.Links=r||[],s}(e),r={};return t.Data&&(r.Data=t.Data),t.Links&&(r.Links=t.Links.map((e=>{const t={};try{t.Hash=po.decode(e.Hash)}catch(e){}if(!t.Hash)throw new Error("Invalid Hash field found in link, expected CID");return void 0!==e.Name&&(t.Name=e.Name),void 0!==e.Tsize&&(t.Tsize=e.Tsize),t}))),r}var Zo=Math.pow(2,31),Yo=Math.pow(2,7),ei=Math.pow(2,14),ti=Math.pow(2,21),ri=Math.pow(2,28),ni=Math.pow(2,35),oi=Math.pow(2,42),ii=Math.pow(2,49),si=Math.pow(2,56),ai=Math.pow(2,63);const ci={encode:function e(t,r,n){r=r||[];for(var o=n=n||0;t>=Zo;)r[n++]=255&t|128,t/=128;for(;-128&t;)r[n++]=255&t|128,t>>>=7;return r[n]=0|t,e.bytes=n-o+1,r},decode:function e(t,r){var n,o=0,i=0,s=r=r||0,a=t.length;do{if(s>=a)throw e.bytes=0,new RangeError("Could not decode varint");n=t[s++],o+=i<28?(127&n)<=128);return e.bytes=s-r,o},encodingLength:function(e){return e[ci.decode(e,t),ci.decode.bytes],hi=(e,t,r=0)=>(ci.encode(e,t,r),t),fi=e=>ci.encodingLength(e),li=(new Uint8Array(0),e=>{if(e instanceof Uint8Array&&"Uint8Array"===e.constructor.name)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Unknown type, must be binary type")});class di{constructor(e,t,r,n){this.code=e,this.size=t,this.digest=r,this.bytes=n}}const pi=function(e,t){if(e.length>=255)throw new TypeError("Alphabet too long");for(var r=new Uint8Array(256),n=0;n>>0,s=new Uint8Array(i);e[t];){var h=r[e.charCodeAt(t)];if(255===h)return;for(var f=0,l=i-1;(0!==h||f>>0,s[l]=h%256>>>0,h=h/256>>>0;if(0!==h)throw new Error("Non-zero carry");o=f,t++}if(" "!==e[t]){for(var d=i-o;d!==i&&0===s[d];)d++;for(var p=new Uint8Array(n+(i-d)),w=n;d!==i;)p[w++]=s[d++];return p}}}return{encode:function(t){if(t instanceof Uint8Array||(ArrayBuffer.isView(t)?t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength):Array.isArray(t)&&(t=Uint8Array.from(t))),!(t instanceof Uint8Array))throw new TypeError("Expected Uint8Array");if(0===t.length)return"";for(var r=0,n=0,o=0,i=t.length;o!==i&&0===t[o];)o++,r++;for(var s=(i-o)*h+1>>>0,u=new Uint8Array(s);o!==i;){for(var f=t[o],l=0,d=s-1;(0!==f||l>>0,u[d]=f%a>>>0,f=f/a>>>0;if(0!==f)throw new Error("Non-zero carry");n=l,o++}for(var p=s-n;p!==s&&0===u[p];)p++;for(var w=c.repeat(r);pnew yi({...e.decoders||{[e.prefix]:e},...t.decoders||{[t.prefix]:t}});class mi{constructor(e,t,r,n){this.name=e,this.prefix=t,this.baseEncode=r,this.baseDecode=n,this.encoder=new wi(e,t,r),this.decoder=new bi(e,t,n)}encode(e){return this.encoder.encode(e)}decode(e){return this.decoder.decode(e)}}const vi=({name:e,prefix:t,encode:r,decode:n})=>new mi(e,t,r,n),_i=({prefix:e,name:t,alphabet:r})=>{const{encode:n,decode:o}=pi(r,t);return vi({prefix:e,name:t,encode:n,decode:e=>li(o(e))})},ki=({name:e,prefix:t,bitsPerChar:r,alphabet:n})=>vi({prefix:t,name:e,encode:e=>((e,t,r)=>{const n="="===t[t.length-1],o=(1<r;)s-=r,i+=t[o&a>>s];if(s&&(i+=t[o&a<((e,t,r,n)=>{const o={};for(let e=0;e=8&&(a-=8,s[u++]=255&c>>a)}if(a>=r||255&c<<8-a)throw new SyntaxError("Unexpected end of data");return s})(t,n,r,e)}),Ei=_i({name:"base58btc",prefix:"z",alphabet:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"}),xi=(_i({name:"base58flickr",prefix:"Z",alphabet:"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"}),ki({prefix:"b",name:"base32",alphabet:"abcdefghijklmnopqrstuvwxyz234567",bitsPerChar:5}));ki({prefix:"B",name:"base32upper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",bitsPerChar:5}),ki({prefix:"c",name:"base32pad",alphabet:"abcdefghijklmnopqrstuvwxyz234567=",bitsPerChar:5}),ki({prefix:"C",name:"base32padupper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",bitsPerChar:5}),ki({prefix:"v",name:"base32hex",alphabet:"0123456789abcdefghijklmnopqrstuv",bitsPerChar:5}),ki({prefix:"V",name:"base32hexupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV",bitsPerChar:5}),ki({prefix:"t",name:"base32hexpad",alphabet:"0123456789abcdefghijklmnopqrstuv=",bitsPerChar:5}),ki({prefix:"T",name:"base32hexpadupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV=",bitsPerChar:5}),ki({prefix:"h",name:"base32z",alphabet:"ybndrfg8ejkmcpqxot1uwisza345h769",bitsPerChar:5});class Ci{constructor(e,t,r,n){this.code=t,this.version=e,this.multihash=r,this.bytes=n,this.byteOffset=n.byteOffset,this.byteLength=n.byteLength,this.asCID=this,this._baseCache=new Map,Object.defineProperties(this,{byteOffset:Oi,byteLength:Oi,code:Ni,version:Ni,multihash:Ni,bytes:Ni,_baseCache:Oi,asCID:Oi})}toV0(){if(0===this.version)return this;{const{code:e,multihash:t}=this;if(e!==Si)throw new Error("Cannot convert a non dag-pb CID to CIDv0");if(t.code!==Di)throw new Error("Cannot convert non sha2-256 multihash CID to CIDv0");return Ci.createV0(t)}}toV1(){switch(this.version){case 0:{const{code:e,digest:t}=this.multihash,r=((e,t)=>{const r=t.byteLength,n=fi(e),o=n+fi(r),i=new Uint8Array(o+r);return hi(e,i,0),hi(r,i,n),i.set(t,o),new di(e,r,t,i)})(e,t);return Ci.createV1(this.code,r)}case 1:return this;default:throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`)}}equals(e){return e&&this.code===e.code&&this.version===e.version&&((t=this.multihash)===(r=e.multihash)||t.code===r.code&&t.size===r.size&&((e,t)=>{if(e===t)return!0;if(e.byteLength!==t.byteLength)return!1;for(let r=0;r{const t=li(e),[r,n]=ui(t),[o,i]=ui(t.subarray(n)),s=t.subarray(n+i);if(s.byteLength!==o)throw new Error("Incorrect length");return new di(r,o,s,t)})(r);return Ci.create(t,n,o)}return null}static create(e,t,r){if("number"!=typeof t)throw new Error("String codecs are no longer supported");switch(e){case 0:if(t!==Si)throw new Error(`Version 0 CID must use dag-pb (code: ${Si}) block encoding`);return new Ci(e,t,r,r.bytes);case 1:{const n=Ti(e,t,r.bytes);return new Ci(e,t,r,n)}default:throw new Error("Invalid version")}}static createV0(e){return Ci.create(0,Si,e)}static createV1(e,t){return Ci.create(1,e,t)}static decode(e){const[t,r]=Ci.decodeFirst(e);if(r.length)throw new Error("Incorrect length");return t}static decodeFirst(e){const t=Ci.inspectBytes(e),r=t.size-t.multihashSize,n=li(e.subarray(r,r+t.multihashSize));if(n.byteLength!==t.multihashSize)throw new Error("Incorrect length");const o=n.subarray(t.multihashSize-t.digestSize),i=new di(t.multihashCode,t.digestSize,o,n);return[0===t.version?Ci.createV0(i):Ci.createV1(t.codec,i),e.subarray(t.size)]}static inspectBytes(e){let t=0;const r=()=>{const[r,n]=ui(e.subarray(t));return t+=n,r};let n=r(),o=Si;if(18===n?(n=0,t=0):1===n&&(o=r()),0!==n&&1!==n)throw new RangeError(`Invalid CID version ${n}`);const i=t,s=r(),a=r(),c=t+a;return{version:n,codec:o,multihashCode:s,digestSize:a,multihashSize:c-i,size:c}}static parse(e,t){const[r,n]=Ai(e,t),o=Ci.decode(n);return o._baseCache.set(r,e),o}}const Ai=(e,t)=>{switch(e[0]){case"Q":{const r=t||Ei;return[Ei.prefix,r.decode(`${Ei.prefix}${e}`)]}case Ei.prefix:{const r=t||Ei;return[Ei.prefix,r.decode(e)]}case xi.prefix:{const r=t||xi;return[xi.prefix,r.decode(e)]}default:if(null==t)throw Error("To parse non base32 or base58btc encoded CID multibase decoder must be provided");return[e[0],t.decode(e)]}},Bi=(e,t,r)=>{const{prefix:n}=r;if(n!==Ei.prefix)throw Error(`Cannot string encode V0 in ${r.name} encoding`);const o=t.get(n);if(null==o){const o=r.encode(e).slice(1);return t.set(n,o),o}return o},Ii=(e,t,r)=>{const{prefix:n}=r,o=t.get(n);if(null==o){const o=r.encode(e);return t.set(n,o),o}return o},Si=112,Di=18,Ti=(e,t,r)=>{const n=fi(e),o=n+fi(t),i=new Uint8Array(o+r.byteLength);return hi(e,i,0),hi(t,i,n),i.set(r,o),i},Ui=Symbol.for("@ipld/js-cid/CID"),Ni={writable:!1,configurable:!1,enumerable:!0},Oi={writable:!1,enumerable:!1,configurable:!1},Pi=(e,t)=>{if(!e.test("0.0.0-dev"))throw new Error(t);console.warn(t)},zi="CID.isCID(v) is deprecated and will be removed in the next major release.\nFollowing code pattern:\n\nif (CID.isCID(value)) {\n doSomethingWithCID(value)\n}\n\nIs replaced with:\n\nconst cid = CID.asCID(value)\nif (cid) {\n // Make sure to use cid instead of value\n doSomethingWithCID(cid)\n}\n",Li=ki({prefix:"m",name:"base64",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",bitsPerChar:6});ki({prefix:"M",name:"base64pad",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",bitsPerChar:6}),ki({prefix:"u",name:"base64url",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",bitsPerChar:6}),ki({prefix:"U",name:"base64urlpad",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",bitsPerChar:6});class Ri extends Array{constructor(){super(),this.inRecursive=[]}prefix(e){const t=this.inRecursive[this.inRecursive.length-1];t&&(t.type===ft.array&&(t.elements++,1!==t.elements&&e.push([44])),t.type===ft.map&&(t.elements++,1!==t.elements&&(t.elements%2==1?e.push([44]):e.push([58]))))}[ft.uint.major](e,t){this.prefix(e);const r=String(t.value),n=[];for(let e=0;e32?yt(r):r)}[ft.array.major](e,t){this.prefix(e),this.inRecursive.push({type:ft.array,elements:0}),e.push([91])}[ft.map.major](e,t){this.prefix(e),this.inRecursive.push({type:ft.map,elements:0}),e.push([123])}[ft.tag.major](e,t){}[ft.float.major](e,t){if("break"===t.type.name){const t=this.inRecursive.pop();if(t){if(t.type===ft.array)e.push([93]);else{if(t.type!==ft.map)throw new Error("Unexpected recursive type; this should not happen!");e.push([125])}return}throw new Error("Unexpected break; this should not happen!")}if(void 0===t.value)throw new Error("CBOR encode error: unsupported type: undefined");if(this.prefix(e),"true"===t.type.name)return void e.push([116,114,117,101]);if("false"===t.type.name)return void e.push([102,97,108,115,101]);if("null"===t.type.name)return void e.push([110,117,108,108]);const r=String(t.value),n=[];let o=!1;for(let e=0;en)return 1;throw new Error("CBOR encode error: unexpected duplicate map keys, this is not supported")}};class ji{constructor(e,t={}){this.pos=0,this.data=e,this.options=t,this.modeStack=["value"],this.lastToken=""}done(){return this.pos>=this.data.length}ch(){return this.data[this.pos]}currentMode(){return this.modeStack[this.modeStack.length-1]}skipWhitespace(){let e=this.ch();for(;32===e||9===e||13===e||10===e;)e=this.data[++this.pos]}expect(e){if(this.data.length-this.pos{for(;!this.done();){const t=this.ch();if(!e.includes(t))break;this.pos++}};if(45===this.ch()&&(t=!0,this.pos++),48===this.ch()){if(this.pos++,46!==this.ch())return new lt(ft.uint,0,this.pos-e);this.pos++,r=!0}if(n([48,49,50,51,52,53,54,55,56,57]),t&&this.pos===e+1)throw new Error(`CBOR decode error: unexpected token at position ${this.pos}`);if(!this.done()&&46===this.ch()){if(r)throw new Error(`CBOR decode error: unexpected token at position ${this.pos}`);r=!0,this.pos++,n([48,49,50,51,52,53,54,55,56,57])}this.done()||101!==this.ch()&&69!==this.ch()||(r=!0,this.pos++,this.done()||43!==this.ch()&&45!==this.ch()||this.pos++,n([48,49,50,51,52,53,54,55,56,57]));const o=String.fromCharCode.apply(null,this.data.subarray(e,this.pos)),i=parseFloat(o);return r?new lt(ft.float,i,this.pos-e):!0!==this.options.allowBigInt||Number.isSafeInteger(i)?new lt(i>=0?ft.uint:ft.negint,i,this.pos-e):new lt(i>=0?ft.uint:ft.negint,BigInt(o),this.pos-e)}parseString(){if(34!==this.ch())throw new Error(`CBOR decode error: unexpected character at position ${this.pos}; this shouldn't happen`);this.pos++;for(let e=this.pos,t=0;e=128)break;if(34===r){const r=String.fromCharCode.apply(null,this.data.subarray(this.pos,e));return this.pos=e+1,new lt(ft.string,r,t)}}const e=this.pos,t=[],r=()=>{if(this.pos+4>=this.data.length)throw new Error(`CBOR decode error: unexpected end of unicode escape sequence at position ${this.pos}`);let e=0;for(let t=0;t<4;t++){let t=this.ch();if(t>=48&&t<=57)t-=48;else if(t>=97&&t<=102)t=t-97+10;else{if(!(t>=65&&t<=70))throw new Error(`CBOR decode error: unexpected unicode escape character at position ${this.pos}`);t=t-65+10}e=16*e+t,this.pos++}return e},n=()=>{const e=this.ch();let r,n,o,i,s=null,a=e>239?4:e>223?3:e>191?2:1;if(this.pos+a>this.data.length)throw new Error(`CBOR decode error: unexpected unicode sequence at position ${this.pos}`);switch(a){case 1:e<128&&(s=e);break;case 2:r=this.data[this.pos+1],128==(192&r)&&(i=(31&e)<<6|63&r,i>127&&(s=i));break;case 3:r=this.data[this.pos+1],n=this.data[this.pos+2],128==(192&r)&&128==(192&n)&&(i=(15&e)<<12|(63&r)<<6|63&n,i>2047&&(i<55296||i>57343)&&(s=i));break;case 4:r=this.data[this.pos+1],n=this.data[this.pos+2],o=this.data[this.pos+3],128==(192&r)&&128==(192&n)&&128==(192&o)&&(i=(15&e)<<18|(63&r)<<12|(63&n)<<6|63&o,i>65535&&i<1114112&&(s=i))}null===s?(s=65533,a=1):s>65535&&(s-=65536,t.push(s>>>10&1023|55296),s=56320|1023&s),t.push(s),this.pos+=a};for(;!this.done();){const o=this.ch();let i;switch(o){case 92:if(this.pos++,this.done())throw new Error(`CBOR decode error: unexpected string termination at position ${this.pos}`);switch(i=this.ch(),this.pos++,i){case 34:case 39:case 92:case 47:t.push(i);break;case 98:t.push(8);break;case 116:t.push(9);break;case 110:t.push(10);break;case 102:t.push(12);break;case 114:t.push(13);break;case 117:t.push(r());break;default:throw new Error(`CBOR decode error: unexpected string escape character at position ${this.pos}`)}break;case 34:return this.pos++,new lt(ft.string,At(t),this.pos-e);default:if(o<32)throw new Error(`CBOR decode error: invalid control character at position ${this.pos}`);o<128?(t.push(o),this.pos++):n()}}throw new Error(`CBOR decode error: unexpected end of string at position ${this.pos}`)}parseValue(){switch(this.ch()){case 123:return this.modeStack.push("obj-start"),this.pos++,new lt(ft.map,1/0,1);case 91:return this.modeStack.push("array-start"),this.pos++,new lt(ft.array,1/0,1);case 34:return this.parseString();case 110:return this.expect([110,117,108,108]),new lt(ft.null,null,4);case 102:return this.expect([102,97,108,115,101]),new lt(ft.false,!1,5);case 116:return this.expect([116,114,117,101]),new lt(ft.true,!0,4);case 45:case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return this.parseNumber();default:throw new Error(`CBOR decode error: unexpected character at position ${this.pos}`)}}next(){switch(this.skipWhitespace(),this.currentMode()){case"value":return this.modeStack.pop(),this.parseValue();case"array-value":if(this.modeStack.pop(),93===this.ch())return this.pos++,this.skipWhitespace(),new lt(ft.break,void 0,1);if(44!==this.ch())throw new Error(`CBOR decode error: unexpected character at position ${this.pos}, was expecting array delimiter but found '${String.fromCharCode(this.ch())}'`);return this.pos++,this.modeStack.push("array-value"),this.skipWhitespace(),this.parseValue();case"array-start":return this.modeStack.pop(),93===this.ch()?(this.pos++,this.skipWhitespace(),new lt(ft.break,void 0,1)):(this.modeStack.push("array-value"),this.skipWhitespace(),this.parseValue());case"obj-key":if(125===this.ch())return this.modeStack.pop(),this.pos++,this.skipWhitespace(),new lt(ft.break,void 0,1);if(44!==this.ch())throw new Error(`CBOR decode error: unexpected character at position ${this.pos}, was expecting object delimiter but found '${String.fromCharCode(this.ch())}'`);this.pos++,this.skipWhitespace();case"obj-start":{if(this.modeStack.pop(),125===this.ch())return this.pos++,this.skipWhitespace(),new lt(ft.break,void 0,1);const e=this.parseString();if(this.skipWhitespace(),58!==this.ch())throw new Error(`CBOR decode error: unexpected character at position ${this.pos}, was expecting key/value delimiter ':' but found '${String.fromCharCode(this.ch())}'`);return this.pos++,this.modeStack.push("obj-value"),e}case"obj-value":return this.modeStack.pop(),this.modeStack.push("obj-key"),this.skipWhitespace(),this.parseValue();default:throw new Error(`CBOR decode error: unexpected parse state at position ${this.pos}; this shouldn't happen`)}}}function $i(e){const t=Li.encode(e).slice(1);return[new lt(ft.map,1/0,1),new lt(ft.string,"/",1),new lt(ft.map,1/0,1),new lt(ft.string,"bytes",5),new lt(ft.string,t,t.length),new lt(ft.break,void 0,1),new lt(ft.break,void 0,1)]}const Fi={typeEncoders:{Object:function(e){if(e.asCID!==e)return null;const t=Ci.asCID(e);if(!t)return null;const r=t.toString();return[new lt(ft.map,1/0,1),new lt(ft.string,"/",1),new lt(ft.string,r,r.length),new lt(ft.break,void 0,1)]},Uint8Array:$i,Buffer:$i,undefined:function(){throw new Error("`undefined` is not supported by the IPLD Data Model and cannot be encoded")},number:function(e){if(Number.isNaN(e))throw new Error("`NaN` is not supported by the IPLD Data Model and cannot be encoded");if(e===1/0||e===-1/0)throw new Error("`Infinity` and `-Infinity` is not supported by the IPLD Data Model and cannot be encoded");return null}}};class Vi extends ji{constructor(e,t){super(e,t),this.tokenBuffer=[]}done(){return 0===this.tokenBuffer.length&&super.done()}_next(){return this.tokenBuffer.length>0?this.tokenBuffer.pop():super.next()}next(){const e=this._next();if(e.type===ft.map){const e=this._next();if(e.type===ft.string&&"/"===e.value){const e=this._next();if(e.type===ft.string){if(this._next().type!==ft.break)throw new Error("Invalid encoded CID form");return this.tokenBuffer.push(e),new lt(ft.tag,42,0)}if(e.type===ft.map){const e=this._next();if(e.type===ft.string&&"bytes"===e.value){const e=this._next();if(e.type===ft.string){for(let e=0;e<2;e++)if(this._next().type!==ft.break)throw new Error("Invalid encoded Bytes form");const t=Li.decode(`m${e.value}`);return new lt(ft.bytes,t,e.value.length)}this.tokenBuffer.push(e)}this.tokenBuffer.push(e)}this.tokenBuffer.push(e)}this.tokenBuffer.push(e)}return e}}const Hi={allowIndefinite:!1,allowUndefined:!1,allowNaN:!1,allowInfinity:!1,allowBigInt:!0,strict:!0,useMaps:!1,tags:[]};Hi.tags[42]=Ci.parse;const qi="dag-json",Gi=297,Wi=e=>{return t=e,r=Fi,r=Object.assign({},Mi,r),Er(t,new Ri,r);var t,r},Ji=e=>function(e,t){return Sr(e,t=Object.assign({tokenizer:new ji(e,t)},t))}(e,Object.assign(Hi,{tokenizer:new Vi(e,Hi)}));var Ki=__webpack_require__(114);const Qi=["string","number","bigint","symbol"],Xi=["Function","Generator","AsyncGenerator","GeneratorFunction","AsyncGeneratorFunction","AsyncFunction","Observable","Array","Buffer","Object","RegExp","Date","Error","Map","Set","WeakMap","WeakSet","ArrayBuffer","SharedArrayBuffer","DataView","Promise","URL","HTMLElement","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Uint16Array","Int32Array","Uint32Array","Float32Array","Float64Array","BigInt64Array","BigUint64Array"];class Zi{constructor(e,t,r){this.major=e,this.majorEncoded=e<<5,this.name=t,this.terminal=r}toString(){return`Type[${this.major}].${this.name}`}compare(e){return this.majore.major?1:0}}Zi.uint=new Zi(0,"uint",!0),Zi.negint=new Zi(1,"negint",!0),Zi.bytes=new Zi(2,"bytes",!0),Zi.string=new Zi(3,"string",!0),Zi.array=new Zi(4,"array",!1),Zi.map=new Zi(5,"map",!1),Zi.tag=new Zi(6,"tag",!1),Zi.float=new Zi(7,"float",!0),Zi.false=new Zi(7,"false",!0),Zi.true=new Zi(7,"true",!0),Zi.null=new Zi(7,"null",!0),Zi.undefined=new Zi(7,"undefined",!0),Zi.break=new Zi(7,"break",!0);class Yi{constructor(e,t,r){this.type=e,this.value=t,this.encodedLength=r,this.encodedBytes=void 0,this.byteValue=void 0}toString(){return`Token[${this.type}].${this.value}`}}const es=globalThis.process&&!globalThis.process.browser&&globalThis.Buffer&&"function"==typeof globalThis.Buffer.isBuffer,ts=new TextDecoder,rs=new TextEncoder;function ns(e){return es&&globalThis.Buffer.isBuffer(e)}const os=es?(e,t,r)=>r-t>64?globalThis.Buffer.from(e.subarray(t,r)).toString("utf8"):hs(e,t,r):(e,t,r)=>r-t>64?ts.decode(e.subarray(t,r)):hs(e,t,r),is=es?e=>e.length>64?globalThis.Buffer.from(e):us(e):e=>e.length>64?rs.encode(e):us(e),ss=es?(e,t,r)=>ns(e)?new Uint8Array(e.subarray(t,r)):e.slice(t,r):(e,t,r)=>e.slice(t,r),as=es?(e,t)=>(e=e.map((e=>e instanceof Uint8Array?e:globalThis.Buffer.from(e))),function(e){return e instanceof Uint8Array?ns(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):e:Uint8Array.from(e)}(globalThis.Buffer.concat(e,t))):(e,t)=>{const r=new Uint8Array(t);let n=0;for(let t of e)n+t.length>r.length&&(t=t.subarray(0,r.length-n)),r.set(t,n),n+=t.length;return r},cs=es?e=>globalThis.Buffer.allocUnsafe(e):e=>new Uint8Array(e);function us(e){const t=[];let r=0;for(let n=0;n>6|192,t[r++]=63&o|128):55296==(64512&o)&&n+1>18|240,t[r++]=o>>12&63|128,t[r++]=o>>6&63|128,t[r++]=63&o|128):(t[r++]=o>>12|224,t[r++]=o>>6&63|128,t[r++]=63&o|128)}return t}function hs(e,t,r){const n=[];for(;t239?4:o>223?3:o>191?2:1;if(t+s<=r){let r,n,a,c;switch(s){case 1:o<128&&(i=o);break;case 2:r=e[t+1],128==(192&r)&&(c=(31&o)<<6|63&r,c>127&&(i=c));break;case 3:r=e[t+1],n=e[t+2],128==(192&r)&&128==(192&n)&&(c=(15&o)<<12|(63&r)<<6|63&n,c>2047&&(c<55296||c>57343)&&(i=c));break;case 4:r=e[t+1],n=e[t+2],a=e[t+3],128==(192&r)&&128==(192&n)&&128==(192&a)&&(c=(15&o)<<18|(63&r)<<12|(63&n)<<6|63&a,c>65535&&c<1114112&&(i=c))}}null===i?(i=65533,s=1):i>65535&&(i-=65536,n.push(i>>>10&1023|55296),i=56320|1023&i),n.push(i),t+=s}return function(e){const t=e.length;if(t<=fs)return String.fromCharCode.apply(String,e);let r="",n=0;for(;n>>8,255&n])}else if(r>>24&255,n>>>16&255,n>>>8&255,255&n])}else{const n=BigInt(r);if(!(n>BigInt(32)&BigInt(4294967295));r[8]=255&o,o>>=8,r[7]=255&o,o>>=8,r[6]=255&o,o>>=8,r[5]=255&o,r[4]=255&i,i>>=8,r[3]=255&i,i>>=8,r[2]=255&i,i>>=8,r[1]=255&i,e.push(r)}}}ms.encodedSize=function(e){return vs.encodedSize(e.value)},vs.encodedSize=function(e){return et.value?1:0};const _s=BigInt(-1),ks=BigInt(1);function Es(e,t){const r=t.value,n="bigint"==typeof r?r*_s-ks:-1*r-1;vs(e,t.type.majorEncoded,n)}function xs(e,t,r,n){ds(e,t,r+n);const o=ss(e,t+r,t+r+n);return new Yi(Zi.bytes,o,r+n)}function Cs(e,t,r,n){return xs(e,t,1,r)}function As(e){return void 0===e.encodedBytes&&(e.encodedBytes=e.type===Zi.string?is(e.value):e.value),e.encodedBytes}function Bs(e,t){const r=As(t);vs(e,t.type.majorEncoded,r.length),e.push(r)}function Is(e,t,r,n,o){const i=r+n;ds(e,t,i);const s=new Yi(Zi.string,os(e,t+r,t+i),i);return!0===o.retainStringBytes&&(s.byteValue=ss(e,t+r,t+i)),s}function Ss(e,t,r,n){return Is(e,t,1,r,n)}Es.encodedSize=function(e){const t=e.value,r="bigint"==typeof t?t*_s-ks:-1*t-1;return rt.value?-1:0},Bs.encodedSize=function(e){const t=As(e);return vs.encodedSize(t.length)+t.length},Bs.compareTokens=function(e,t){return r=As(e),n=As(t),r.lengthn.length?1:function(e,t){if(ns(e)&&ns(t))return e.compare(t);for(let r=0;r>23,n=8388607&t;if(255===r)Fs.setUint16(0,31744,!1);else if(0===r)Fs.setUint16(0,(2147483648&e)>>16|n>>13,!1);else{const e=r-127;e<-24?Fs.setUint16(0,0):e<-14?Fs.setUint16(0,(2147483648&t)>>16|1<<24+e,!1):Fs.setUint16(0,(2147483648&t)>>16|e+15<<10|n>>13,!1)}}}function qs(e,t){if(e.length-t<2)throw new Error("CBOR decode error: not enough data for float16");const r=(e[t]<<8)+e[t+1];if(31744===r)return 1/0;if(64512===r)return-1/0;if(32256===r)return NaN;const n=r>>10&31,o=1023&r;let i;return i=0===n?o*2**-24:31!==n?(o+1024)*2**(n-25):0===o?1/0:NaN,32768&r?-i:i}function Gs(e){Fs.setFloat32(0,e,!1)}function Ws(e,t){if(e.length-t<4)throw new Error("CBOR decode error: not enough data for float32");const r=(e.byteOffset||0)+t;return new DataView(e.buffer,r,4).getFloat32(0,!1)}function Js(e,t){if(e.length-t<8)throw new Error("CBOR decode error: not enough data for float64");const r=(e.byteOffset||0)+t;return new DataView(e.buffer,r,8).getFloat64(0,!1)}function Ks(e,t,r){throw new Error(`CBOR decode error: encountered invalid minor (${r}) for major ${e[t]>>>5}`)}function Qs(e){return()=>{throw new Error(`CBOR decode error: ${e}`)}}js.compareTokens=ms.compareTokens;const Xs=[];for(let e=0;e<=23;e++)Xs[e]=Ks;Xs[24]=function(e,t,r,n){return new Yi(Zi.uint,ws(e,t+1,n),2)},Xs[25]=function(e,t,r,n){return new Yi(Zi.uint,bs(e,t+1,n),3)},Xs[26]=function(e,t,r,n){return new Yi(Zi.uint,ys(e,t+1,n),5)},Xs[27]=function(e,t,r,n){return new Yi(Zi.uint,gs(e,t+1,n),9)},Xs[28]=Ks,Xs[29]=Ks,Xs[30]=Ks,Xs[31]=Ks;for(let e=32;e<=55;e++)Xs[e]=Ks;Xs[56]=function(e,t,r,n){return new Yi(Zi.negint,-1-ws(e,t+1,n),2)},Xs[57]=function(e,t,r,n){return new Yi(Zi.negint,-1-bs(e,t+1,n),3)},Xs[58]=function(e,t,r,n){return new Yi(Zi.negint,-1-ys(e,t+1,n),5)},Xs[59]=function(e,t,r,n){const o=gs(e,t+1,n);if("bigint"!=typeof o){const e=-1-o;if(e>=Number.MIN_SAFE_INTEGER)return new Yi(Zi.negint,e,9)}if(!0!==n.allowBigInt)throw new Error("CBOR decode error: integers outside of the safe integer range are not supported");return new Yi(Zi.negint,_s-BigInt(o),9)},Xs[60]=Ks,Xs[61]=Ks,Xs[62]=Ks,Xs[63]=Ks;for(let e=64;e<=87;e++)Xs[e]=Cs;Xs[88]=function(e,t,r,n){return xs(e,t,2,ws(e,t+1,n))},Xs[89]=function(e,t,r,n){return xs(e,t,3,bs(e,t+1,n))},Xs[90]=function(e,t,r,n){return xs(e,t,5,ys(e,t+1,n))},Xs[91]=function(e,t,r,n){const o=gs(e,t+1,n);if("bigint"==typeof o)throw new Error("CBOR decode error: 64-bit integer bytes lengths not supported");return xs(e,t,9,o)},Xs[92]=Ks,Xs[93]=Ks,Xs[94]=Ks,Xs[95]=Qs("indefinite length bytes/strings are not supported");for(let e=96;e<=119;e++)Xs[e]=Ss;Xs[120]=function(e,t,r,n){return Is(e,t,2,ws(e,t+1,n),n)},Xs[121]=function(e,t,r,n){return Is(e,t,3,bs(e,t+1,n),n)},Xs[122]=function(e,t,r,n){return Is(e,t,5,ys(e,t+1,n),n)},Xs[123]=function(e,t,r,n){const o=gs(e,t+1,n);if("bigint"==typeof o)throw new Error("CBOR decode error: 64-bit integer string lengths not supported");return Is(e,t,9,o,n)},Xs[124]=Ks,Xs[125]=Ks,Xs[126]=Ks,Xs[127]=Qs("indefinite length bytes/strings are not supported");for(let e=128;e<=151;e++)Xs[e]=Us;Xs[152]=function(e,t,r,n){return Ts(0,0,2,ws(e,t+1,n))},Xs[153]=function(e,t,r,n){return Ts(0,0,3,bs(e,t+1,n))},Xs[154]=function(e,t,r,n){return Ts(0,0,5,ys(e,t+1,n))},Xs[155]=function(e,t,r,n){const o=gs(e,t+1,n);if("bigint"==typeof o)throw new Error("CBOR decode error: 64-bit integer array lengths not supported");return Ts(0,0,9,o)},Xs[156]=Ks,Xs[157]=Ks,Xs[158]=Ks,Xs[159]=function(e,t,r,n){if(!1===n.allowIndefinite)throw new Error("CBOR decode error: indefinite length items not allowed");return Ts(0,0,1,1/0)};for(let e=160;e<=183;e++)Xs[e]=Ps;Xs[184]=function(e,t,r,n){return Os(0,0,2,ws(e,t+1,n))},Xs[185]=function(e,t,r,n){return Os(0,0,3,bs(e,t+1,n))},Xs[186]=function(e,t,r,n){return Os(0,0,5,ys(e,t+1,n))},Xs[187]=function(e,t,r,n){const o=gs(e,t+1,n);if("bigint"==typeof o)throw new Error("CBOR decode error: 64-bit integer map lengths not supported");return Os(0,0,9,o)},Xs[188]=Ks,Xs[189]=Ks,Xs[190]=Ks,Xs[191]=function(e,t,r,n){if(!1===n.allowIndefinite)throw new Error("CBOR decode error: indefinite length items not allowed");return Os(0,0,1,1/0)};for(let e=192;e<=215;e++)Xs[e]=Ls;Xs[216]=function(e,t,r,n){return new Yi(Zi.tag,ws(e,t+1,n),2)},Xs[217]=function(e,t,r,n){return new Yi(Zi.tag,bs(e,t+1,n),3)},Xs[218]=function(e,t,r,n){return new Yi(Zi.tag,ys(e,t+1,n),5)},Xs[219]=function(e,t,r,n){return new Yi(Zi.tag,gs(e,t+1,n),9)},Xs[220]=Ks,Xs[221]=Ks,Xs[222]=Ks,Xs[223]=Ks;for(let e=224;e<=243;e++)Xs[e]=Qs("simple values are not supported");Xs[244]=Ks,Xs[245]=Ks,Xs[246]=Ks,Xs[247]=function(e,t,r,n){if(!1===n.allowUndefined)throw new Error("CBOR decode error: undefined values are not supported");return!0===n.coerceUndefinedToNull?new Yi(Zi.null,null,1):new Yi(Zi.undefined,void 0,1)},Xs[248]=Qs("simple values are not supported"),Xs[249]=function(e,t,r,n){return Ms(qs(e,t+1),3,n)},Xs[250]=function(e,t,r,n){return Ms(Ws(e,t+1),5,n)},Xs[251]=function(e,t,r,n){return Ms(Js(e,t+1),9,n)},Xs[252]=Ks,Xs[253]=Ks,Xs[254]=Ks,Xs[255]=function(e,t,r,n){if(!1===n.allowIndefinite)throw new Error("CBOR decode error: indefinite length items not allowed");return new Yi(Zi.break,void 0,1)};const Zs=[];for(let e=0;e<24;e++)Zs[e]=new Yi(Zi.uint,e,1);for(let e=-1;e>=-24;e--)Zs[31-e]=new Yi(Zi.negint,e,1);Zs[64]=new Yi(Zi.bytes,new Uint8Array(0),1),Zs[96]=new Yi(Zi.string,"",1),Zs[128]=new Yi(Zi.array,0,1),Zs[160]=new Yi(Zi.map,0,1),Zs[244]=new Yi(Zi.false,!1,1),Zs[245]=new Yi(Zi.true,!0,1),Zs[246]=new Yi(Zi.null,null,1),function(){const e=[];e[Zi.uint.major]=ms,e[Zi.negint.major]=Es,e[Zi.bytes.major]=Bs,e[Zi.string.major]=Ds,e[Zi.array.major]=Ns,e[Zi.map.major]=zs,e[Zi.tag.major]=Rs,e[Zi.float.major]=js}(),new class{constructor(e=256){this.chunkSize=e,this.cursor=0,this.maxCursor=-1,this.chunks=[],this._initReuseChunk=null}reset(){this.cursor=0,this.maxCursor=-1,this.chunks.length&&(this.chunks=[]),null!==this._initReuseChunk&&(this.chunks.push(this._initReuseChunk),this.maxCursor=this._initReuseChunk.length-1)}push(e){let t=this.chunks[this.chunks.length-1];if(this.cursor+e.length<=this.maxCursor+1){const r=t.length-(this.maxCursor-this.cursor)-1;t.set(e,r)}else{if(t){const e=t.length-(this.maxCursor-this.cursor)-1;er.length/2?(t=this.cursor===r.length?r:r.subarray(0,this.cursor),this._initReuseChunk=null,this.chunks=[]):t=ss(r,0,this.cursor)}else t=as(this.chunks,this.cursor);return e&&this.reset(),t}};class Ys{constructor(e,t){this.obj=e,this.parent=t}includes(e){let t=this;do{if(t.obj===e)return!0}while(t=t.parent);return!1}static createCheck(e,t){if(e&&e.includes(t))throw new Error("CBOR encode error: object contains circular references");return new Ys(t,e)}}const ea={null:new Yi(Zi.null,null),undefined:new Yi(Zi.undefined,void 0),true:new Yi(Zi.true,!0),false:new Yi(Zi.false,!1),emptyArray:new Yi(Zi.array,0),emptyMap:new Yi(Zi.map,0)},ta={number:(e,t,r,n)=>Number.isInteger(e)&&Number.isSafeInteger(e)?new Yi(e>=0?Zi.uint:Zi.negint,e):new Yi(Zi.float,e),bigint:(e,t,r,n)=>e>=BigInt(0)?new Yi(Zi.uint,e):new Yi(Zi.negint,e),Uint8Array:(e,t,r,n)=>new Yi(Zi.bytes,e),string:(e,t,r,n)=>new Yi(Zi.string,e),boolean:(e,t,r,n)=>e?ea.true:ea.false,null:(e,t,r,n)=>ea.null,undefined:(e,t,r,n)=>ea.undefined,ArrayBuffer:(e,t,r,n)=>new Yi(Zi.bytes,new Uint8Array(e)),DataView:(e,t,r,n)=>new Yi(Zi.bytes,new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),Array(e,t,r,n){if(!e.length)return!0===r.addBreakTokens?[ea.emptyArray,new Yi(Zi.break)]:ea.emptyArray;n=Ys.createCheck(n,e);const o=[];let i=0;for(const t of e)o[i++]=ra(t,r,n);return r.addBreakTokens?[new Yi(Zi.array,e.length),o,new Yi(Zi.break)]:[new Yi(Zi.array,e.length),o]},Object(e,t,r,n){const o="Object"!==t,i=o?e.keys():Object.keys(e),s=o?e.size:i.length;if(!s)return!0===r.addBreakTokens?[ea.emptyMap,new Yi(Zi.break)]:ea.emptyMap;n=Ys.createCheck(n,e);const a=[];let c=0;for(const t of i)a[c++]=[ra(t,r,n),ra(o?e.get(t):e[t],r,n)];return function(e,t){t.mapSorter&&e.sort(t.mapSorter)}(a,r),r.addBreakTokens?[new Yi(Zi.map,s),a,new Yi(Zi.break)]:[new Yi(Zi.map,s),a]}};ta.Map=ta.Object,ta.Buffer=ta.Uint8Array;for(const e of"Uint8Clamped Uint16 Uint32 Int8 Int16 Int32 BigUint64 BigInt64 Float32 Float64".split(" "))ta[`${e}Array`]=ta.DataView;function ra(e,t={},r){const n=function(e){if(null===e)return"null";if(void 0===e)return"undefined";if(!0===e||!1===e)return"boolean";const t=typeof e;if(Qi.includes(t))return t;if("function"===t)return"Function";if(Array.isArray(e))return"Array";if(function(e){return e&&e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer.call(null,e)}(e))return"Buffer";const r=function(e){const t=Object.prototype.toString.call(e).slice(8,-1);if(Xi.includes(t))return t}(e);return r||"Object"}(e),o=t&&t.typeEncoders&&t.typeEncoders[n]||ta[n];if("function"==typeof o){const i=o(e,n,t,r);if(null!=i)return i}const i=ta[n];if(!i)throw new Error(`CBOR encode error: unsupported type: ${n}`);return i(e,n,t,r)}const na={strict:!1,allowIndefinite:!0,allowUndefined:!0,allowBigInt:!0};class oa{constructor(e,t={}){this._pos=0,this.data=e,this.options=t}pos(){return this._pos}done(){return this._pos>=this.data.length}next(){const e=this.data[this._pos];let t=Zs[e];if(void 0===t){const r=Xs[e];if(!r)throw new Error(`CBOR decode error: no decoder for major type ${e>>>5} (byte 0x${e.toString(16).padStart(2,"0")})`);const n=31&e;t=r(this.data,this._pos,n,this.options)}return this._pos+=t.encodedLength,t}}const ia=Symbol.for("DONE"),sa=Symbol.for("BREAK");function aa(e,t){if(e.done())return ia;const r=e.next();if(r.type===Zi.break)return sa;if(r.type.terminal)return r.value;if(r.type===Zi.array)return function(e,t,r){const n=[];for(let o=0;o0)throw new Error("CBOR decode error: too many terminals, data makes no sense");return r}const ua={allowIndefinite:!1,coerceUndefinedToNull:!0,allowNaN:!1,allowInfinity:!1,allowBigInt:!0,strict:!0,useMaps:!1,rejectDuplicateMapKeys:!0,tags:[]};ua.tags[42]=function(e){if(0!==e[0])throw new Error("Invalid CID for CBOR tag 42; expected leading 0x00");return le.decode(e.subarray(1))};const ha=new TextDecoder;function fa(e,t){let r=0;for(let n=0;;n+=7){if(n>=64)throw new Error("protobuf: varint overflow");if(t>=e.length)throw new Error("protobuf: unexpected end of data");const o=e[t++];if(r+=n<28?(127&o)<e.length)throw new Error("protobuf: unexpected end of data");return[e.subarray(t,n),n]}function da(e,t){let r;return[r,t]=fa(e,t),[7&r,r>>3,t]}function pa(e){const t={},r=e.length;let n=0;for(;nr)throw new Error("protobuf: (PBLink) unexpected end of data");return t}function wa(e){const t=function(e){const t=e.length;let r,n,o=0,i=!1;for(;ot)throw new Error("protobuf: (PBNode) unexpected end of data");const s={};return n&&(s.Data=n),s.Links=r||[],s}(e),r={};return t.Data&&(r.Data=t.Data),t.Links&&(r.Links=t.Links.map((e=>{const t={};try{t.Hash=le.decode(e.Hash)}catch(e){}if(!t.Hash)throw new Error("Invalid Hash field found in link, expected CID");return void 0!==e.Name&&(t.Name=e.Name),void 0!==e.Tsize&&(t.Tsize=e.Tsize),t}))),r}new TextEncoder,new TextEncoder;const ba="raw",ya=85,ga=e=>k(e),ma=e=>k(e),va=k,_a={code:0,name:"identity",encode:va,digest:e=>se(0,va(e))};class ka extends Event{constructor(e,t){super(e),this.detail=t}}const Ea=function(e,t,r,n){const o=BigInt(e.length),i=BigInt(t+o);return r>=i||n=t&&n=t&&r{const n=BigInt(e),o=BigInt(t??0);let i=BigInt(r);if(i!==n&&(i=o+i),i>n&&(i=n),o<0n)throw Ki(new Error("Offset must be greater than or equal to 0"),"ERR_INVALID_PARAMS");if(o>n)throw Ki(new Error("Offset must be less than the file size"),"ERR_INVALID_PARAMS");if(i<0n)throw Ki(new Error("Length must be greater than or equal to 0"),"ERR_INVALID_PARAMS");if(i>n)throw Ki(new Error("Length must be less than the file size"),"ERR_INVALID_PARAMS");return{start:o,end:i}};var Ca=__webpack_require__(408),Aa=__webpack_require__(593),Ba=__webpack_require__(693),Ia=__webpack_require__(173),Sa=__webpack_require__(155);Ba._configure(),Ca._configure(Aa),Ia._configure(Sa);const Da=["uint64","int64","sint64","fixed64","sfixed64"];function Ta(e,t){const r=function(e){return function(e){for(const t of Da){if(null==e[t])continue;const r=e[t];e[t]=function(){return BigInt(r.call(this).toString())}}return e}(new Ca(e))}(e instanceof Uint8Array?e:e.subarray());return t.decode(r)}function Ua(e,t){const r=function(e){for(const t of Da){if(null==e[t])continue;const r=e[t];e[t]=function(e){return r.call(this,e.toString())}}return e}(Ia.create());return t.encode(e,r,{lengthDelimited:!1}),r.finish()}var Na,Oa,Pa,za;function La(e,t,r,n){return{name:e,type:t,encode:r,decode:n}}function Ra(e,t){return La("message",Na.LENGTH_DELIMITED,e,t)}!function(e){e[e.VARINT=0]="VARINT",e[e.BIT64=1]="BIT64",e[e.LENGTH_DELIMITED=2]="LENGTH_DELIMITED",e[e.START_GROUP=3]="START_GROUP",e[e.END_GROUP=4]="END_GROUP",e[e.BIT32=5]="BIT32"}(Na||(Na={})),function(e){let t,r,n;!function(e){e.Raw="Raw",e.Directory="Directory",e.File="File",e.Metadata="Metadata",e.Symlink="Symlink",e.HAMTShard="HAMTShard"}(t=e.DataType||(e.DataType={})),function(e){e[e.Raw=0]="Raw",e[e.Directory=1]="Directory",e[e.File=2]="File",e[e.Metadata=3]="Metadata",e[e.Symlink=4]="Symlink",e[e.HAMTShard=5]="HAMTShard"}(r||(r={})),function(e){e.codec=()=>function(e){function t(t){if(null==e[t.toString()])throw new Error("Invalid enum value");return e[t]}return La("enum",Na.VARINT,(function(e,r){const n=t(e);r.int32(n)}),(function(e){return t(e.int32())}))}(r)}(t=e.DataType||(e.DataType={})),e.codec=()=>(null==n&&(n=Ra(((t,r,n={})=>{if(!1!==n.lengthDelimited&&r.fork(),null!=t.Type&&(r.uint32(8),e.DataType.codec().encode(t.Type,r)),null!=t.Data&&(r.uint32(18),r.bytes(t.Data)),null!=t.filesize&&(r.uint32(24),r.uint64(t.filesize)),null!=t.blocksizes)for(const e of t.blocksizes)r.uint32(32),r.uint64(e);null!=t.hashType&&(r.uint32(40),r.uint64(t.hashType)),null!=t.fanout&&(r.uint32(48),r.uint64(t.fanout)),null!=t.mode&&(r.uint32(56),r.uint32(t.mode)),null!=t.mtime&&(r.uint32(66),Pa.codec().encode(t.mtime,r)),!1!==n.lengthDelimited&&r.ldelim()}),((t,r)=>{const n={blocksizes:[]},o=null==r?t.len:t.pos+r;for(;t.pos>>3){case 1:n.Type=e.DataType.codec().decode(t);break;case 2:n.Data=t.bytes();break;case 3:n.filesize=t.uint64();break;case 4:n.blocksizes.push(t.uint64());break;case 5:n.hashType=t.uint64();break;case 6:n.fanout=t.uint64();break;case 7:n.mode=t.uint32();break;case 8:n.mtime=Pa.codec().decode(t,t.uint32());break;default:t.skipType(7&r)}}return n}))),n),e.encode=t=>Ua(t,e.codec()),e.decode=t=>Ta(t,e.codec())}(Oa||(Oa={})),function(e){let t;e.codec=()=>(null==t&&(t=Ra(((e,t,r={})=>{!1!==r.lengthDelimited&&t.fork(),null!=e.Seconds&&(t.uint32(8),t.int64(e.Seconds)),null!=e.FractionalNanoseconds&&(t.uint32(21),t.fixed32(e.FractionalNanoseconds)),!1!==r.lengthDelimited&&t.ldelim()}),((e,t)=>{const r={},n=null==t?e.len:e.pos+t;for(;e.pos>>3){case 1:r.Seconds=e.int64();break;case 2:r.FractionalNanoseconds=e.fixed32();break;default:e.skipType(7&t)}}return r}))),t),e.encode=t=>Ua(t,e.codec()),e.decode=t=>Ta(t,e.codec())}(Pa||(Pa={})),function(e){let t;e.codec=()=>(null==t&&(t=Ra(((e,t,r={})=>{!1!==r.lengthDelimited&&t.fork(),null!=e.MimeType&&(t.uint32(10),t.string(e.MimeType)),!1!==r.lengthDelimited&&t.ldelim()}),((e,t)=>{const r={},n=null==t?e.len:e.pos+t;for(;e.pos>>3==1?r.MimeType=e.string():e.skipType(7&t)}return r}))),t),e.encode=t=>Ua(t,e.codec()),e.decode=t=>Ta(t,e.codec())}(za||(za={}));const Ma={Raw:"raw",Directory:"directory",File:"file",Metadata:"metadata",Symlink:"symlink",HAMTShard:"hamt-sharded-directory"},ja=["directory","hamt-sharded-directory"],$a=parseInt("0644",8),Fa=parseInt("0755",8);class Va{static unmarshal(e){const t=Oa.decode(e),r=new Va({type:Ma[null!=t.Type?t.Type.toString():"File"],data:t.Data,blockSizes:t.blocksizes,mode:t.mode,mtime:null!=t.mtime?{secs:t.mtime.Seconds??0n,nsecs:t.mtime.FractionalNanoseconds}:void 0,fanout:t.fanout});return r._originalMode=t.mode??0,r}type;data;blockSizes;hashType;fanout;mtime;_mode;_originalMode;constructor(e={type:"file"}){const{type:t,data:r,blockSizes:n,hashType:o,fanout:i,mtime:s,mode:a}=e;if(null!=t&&!Object.values(Ma).includes(t))throw Ki(new Error("Type: "+t+" is not valid"),"ERR_INVALID_TYPE");this.type=t??"file",this.data=r,this.hashType=o,this.fanout=i,this.blockSizes=n??[],this._originalMode=0,this.mode=a,this.mtime=s}set mode(e){this._mode=null==e?this.isDirectory()?Fa:$a:4095&e}get mode(){return this._mode}isDirectory(){return ja.includes(this.type)}addBlockSize(e){this.blockSizes.push(e)}removeBlockSize(e){this.blockSizes.splice(e,1)}fileSize(){if(this.isDirectory())return 0n;let e=0n;return this.blockSizes.forEach((t=>{e+=t})),null!=this.data&&(e+=BigInt(this.data.length)),e}marshal(){let e;switch(this.type){case"raw":e=Oa.DataType.Raw;break;case"directory":e=Oa.DataType.Directory;break;case"file":e=Oa.DataType.File;break;case"metadata":e=Oa.DataType.Metadata;break;case"symlink":e=Oa.DataType.Symlink;break;case"hamt-sharded-directory":e=Oa.DataType.HAMTShard;break;default:throw Ki(new Error(`Type: ${e} is not valid`),"ERR_INVALID_TYPE")}let t,r,n=this.data;return null!=this.data&&0!==this.data.length||(n=void 0),null!=this.mode&&(t=4294963200&this._originalMode|(this.mode??0),t!==$a||this.isDirectory()||(t=void 0),t===Fa&&this.isDirectory()&&(t=void 0)),null!=this.mtime&&(r={Seconds:this.mtime.secs,FractionalNanoseconds:this.mtime.nsecs}),Oa.encode({Type:e,Data:n,filesize:this.isDirectory()?void 0:this.fileSize(),blocksizes:this.blockSizes,hashType:this.hashType,fanout:this.fanout,mode:t,mtime:r})}}var Ha=__webpack_require__(469);ve({name:"murmur3-32",code:35,encode:e=>function(e){const t=new Array(4);for(let r=0;r<4;r++)t[r]=255&e,e>>=8;return new Uint8Array(t)}(Ha.x86.hash32(e))});const qa=ve({name:"murmur3-128",code:34,encode:e=>v(Ha.x64.hash128(e))});ve({name:"murmur3-x64-64",code:34,encode:e=>v(Ha.x64.hash128(e)).subarray(0,8)});var Ga=__webpack_require__(544);function Wa(e){return null!=globalThis.Buffer?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):e}const Ja=N({prefix:"9",name:"base10",alphabet:"0123456789"}),Ka=O({prefix:"f",name:"base16",alphabet:"0123456789abcdef",bitsPerChar:4}),Qa=O({prefix:"F",name:"base16upper",alphabet:"0123456789ABCDEF",bitsPerChar:4}),Xa=O({prefix:"0",name:"base2",alphabet:"01",bitsPerChar:1}),Za=Array.from("🚀🪐☄🛰🌌🌑🌒🌓🌔🌕🌖🌗🌘🌍🌏🌎🐉☀💻🖥💾💿😂❤😍🤣😊🙏💕😭😘👍😅👏😁🔥🥰💔💖💙😢🤔😆🙄💪😉☺👌🤗💜😔😎😇🌹🤦🎉💞✌✨🤷😱😌🌸🙌😋💗💚😏💛🙂💓🤩😄😀🖤😃💯🙈👇🎶😒🤭❣😜💋👀😪😑💥🙋😞😩😡🤪👊🥳😥🤤👉💃😳✋😚😝😴🌟😬🙃🍀🌷😻😓⭐✅🥺🌈😈🤘💦✔😣🏃💐☹🎊💘😠☝😕🌺🎂🌻😐🖕💝🙊😹🗣💫💀👑🎵🤞😛🔴😤🌼😫⚽🤙☕🏆🤫👈😮🙆🍻🍃🐶💁😲🌿🧡🎁⚡🌞🎈❌✊👋😰🤨😶🤝🚶💰🍓💢🤟🙁🚨💨🤬✈🎀🍺🤓😙💟🌱😖👶🥴▶➡❓💎💸⬇😨🌚🦋😷🕺⚠🙅😟😵👎🤲🤠🤧📌🔵💅🧐🐾🍒😗🤑🌊🤯🐷☎💧😯💆👆🎤🙇🍑❄🌴💣🐸💌📍🥀🤢👅💡💩👐📸👻🤐🤮🎼🥵🚩🍎🍊👼💍📣🥂"),Ya=Za.reduce(((e,t,r)=>(e[r]=t,e)),[]),ec=Za.reduce(((e,t,r)=>(e[t.codePointAt(0)]=r,e)),[]),tc=U({prefix:"🚀",name:"base256emoji",encode:function(e){return e.reduce(((e,t)=>e+Ya[t]),"")},decode:function(e){const t=[];for(const r of e){const e=ec[r.codePointAt(0)];if(void 0===e)throw new Error(`Non-base256emoji character: ${r}`);t.push(e)}return new Uint8Array(t)}}),rc=N({prefix:"k",name:"base36",alphabet:"0123456789abcdefghijklmnopqrstuvwxyz"}),nc=N({prefix:"K",name:"base36upper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"}),oc=O({prefix:"m",name:"base64",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",bitsPerChar:6}),ic=O({prefix:"M",name:"base64pad",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",bitsPerChar:6}),sc=O({prefix:"u",name:"base64url",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",bitsPerChar:6}),ac=O({prefix:"U",name:"base64urlpad",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",bitsPerChar:6}),cc=O({prefix:"7",name:"base8",alphabet:"01234567",bitsPerChar:3}),uc=U({prefix:"\0",name:"identity",encode:e=>C(e),decode:e=>x(e)}),hc=new TextEncoder,fc=new TextDecoder,lc="json",dc=512,pc=e=>hc.encode(JSON.stringify(e)),wc=e=>JSON.parse(fc.decode(e)),bc=e=>async t=>new Uint8Array(await crypto.subtle.digest(e,t)),yc=ve({name:"sha2-256",code:18,encode:bc("SHA-256")}),gc=ve({name:"sha2-512",code:19,encode:bc("SHA-512")}),mc={...w,...h,...p,...c,...u,...t,...l,...r,...d,...f};function vc(e=0){return null!=globalThis.Buffer?.allocUnsafe?Wa(globalThis.Buffer.allocUnsafe(e)):new Uint8Array(e)}function _c(e,t,r,n){return{name:e,prefix:t,encoder:{name:e,prefix:t,encode:r},decoder:{decode:n}}}const kc=_c("utf8","u",(e=>"u"+new TextDecoder("utf8").decode(e)),(e=>(new TextEncoder).encode(e.substring(1)))),Ec=_c("ascii","a",(e=>{let t="a";for(let r=0;r{const t=vc((e=e.substring(1)).length);for(let r=0;rt instanceof Cc?e+t.leafCount():e+1),0)}childrenCount(){return this._children.length}onlyChild(){return this._children.get(0)}*eachLeafSeries(){const e=this._children.compactArray();for(const t of e)t instanceof Cc?yield*t.eachLeafSeries():yield t}serialize(e,t){return t(this._children.reduce(((r,n,o)=>(null!=n&&(n instanceof Cc?r.push(n.serialize(e,t)):r.push(e(n,o))),r)),[]))}async asyncTransform(e,t){return await Sc(this,e,t)}toJSON(){return this.serialize(Bc,Ic)}prettyPrint(){return JSON.stringify(this.toJSON(),null," ")}tableSize(){return Math.pow(2,this._options.bits)}async _findChild(e){const t=await this._findPlace(e),r=t.bucket._at(t.pos);if(!(r instanceof Cc))return null!=r&&r.key===e?r:void 0}async _findPlace(e){const t=this._options.hash("string"==typeof e?function(e,t="utf8"){const r=xc[t];if(null==r)throw new Error(`Unsupported encoding "${t}"`);return"utf8"!==t&&"utf-8"!==t||null==globalThis.Buffer||null==globalThis.Buffer.from?r.decoder.decode(`${r.prefix}${e}`):Wa(globalThis.Buffer.from(e,"utf-8"))}(e):e),r=await t.take(this._options.bits),n=this._children.get(r);return n instanceof Cc?await n._findPlace(t):{bucket:this,pos:r,hash:t,existingChild:n}}async _findNewBucketAndPos(e){const t=await this._findPlace(e);if(null!=t.existingChild&&t.existingChild.key!==e){const e=new Cc(this._options,t.bucket,t.pos);t.bucket._putObjectAt(t.pos,e);const r=await e._findPlace(t.existingChild.hash);return r.bucket._putAt(r,t.existingChild.key,t.existingChild.value),await e._findNewBucketAndPos(t.hash)}return t}_putAt(e,t,r){this._putObjectAt(e.pos,{key:t,value:r,hash:e.hash})}_putObjectAt(e,t){null==this._children.get(e)&&this._popCount++,this._children.set(e,t)}_delAt(e){if(-1===e)throw new Error("Invalid position");null!=this._children.get(e)&&this._popCount--,this._children.unset(e),this._level()}_level(){if(null!=this._parent&&this._popCount<=1)if(1===this._popCount){const e=this._children.find(Ac);if(null!=e&&!(e instanceof Cc)){const t=e.hash;t.untake(this._options.bits);const r={pos:this._posAtParent,hash:t,bucket:this._parent};this._parent._putAt(r,e.key,e.value)}}else this._parent._delAt(this._posAtParent)}_at(e){return this._children.get(e)}}function Ac(e){return Boolean(e)}function Bc(e,t){return e.key}function Ic(e){return e}async function Sc(e,t,r){const n=[];for(const o of e._children.compactArray())if(o instanceof Cc)await Sc(o,t,r);else{const r=await t(o);n.push({bitField:e._children.bitField(),children:r})}return await r(n)}const Dc=[255,254,252,248,240,224,192,128],Tc=[1,3,7,15,31,63,127,255];class Uc{constructor(e){this._value=e,this._currentBytePos=e.length-1,this._currentBitPos=7}availableBits(){return this._currentBitPos+1+8*this._currentBytePos}totalBits(){return 8*this._value.length}take(e){let t=e,r=0;for(;t>0&&this._haveBits();){const e=this._value[this._currentBytePos],n=this._currentBitPos+1,o=Math.min(n,t);r=(r<7;)this._currentBitPos-=8,this._currentBytePos+=1}_haveBits(){return this._currentBytePos>=0}}function Nc(e,t,r){const n=function(e,t){return Dc[e]&Tc[Math.min(t+e-1,7)]}(t,r);return(e&n)>>>t}function Oc(e){return function(t){return t instanceof Pc?t:new Pc(t,e)}}class Pc{constructor(e,t){if(!(e instanceof Uint8Array))throw new Error("can only hash Uint8Arrays");this._value=e,this._hashFn=t,this._depth=-1,this._availableBits=0,this._currentBufferIndex=0,this._buffers=[]}async take(e){let t=e;for(;this._availableBits0;){const e=this._buffers[this._currentBufferIndex],n=Math.min(e.availableBits(),t);r=(r<0;){const e=this._buffers[this._currentBufferIndex],r=Math.min(e.totalBits()-e.availableBits(),t);e.untake(r),t-=r,this._availableBits+=r,this._currentBufferIndex>0&&e.totalBits()===e.availableBits()&&(this._depth--,this._currentBufferIndex--)}}async _produceMoreBits(){this._depth++;const e=this._depth>0?function(e,t){null==t&&(t=e.reduce(((e,t)=>e+t.length),0));const r=vc(t);let n=0;for(const t of e)r.set(t,n),n+=t.length;return Wa(r)}([this._value,Uint8Array.from([this._depth])]):this._value,t=await this._hashFn(e),r=new Uc(t);this._buffers.push(r),this._availableBits+=r.availableBits()}}const zc=async function(e){return(await qa.encode(e)).slice(0,8).reverse()},Lc=(e,t)=>e.toString(16).toUpperCase().padStart(t,"0").substring(0,t),Rc=async(e,t,r,n,o)=>{if(null==n){if(null==e.Data)throw Ki(new Error("no data in PBNode"),"ERR_NOT_UNIXFS");let t;try{t=Va.unmarshal(e.Data)}catch(e){throw Ki(e,"ERR_NOT_UNIXFS")}if("hamt-sharded-directory"!==t.type)throw Ki(new Error("not a HAMT"),"ERR_NOT_UNIXFS");if(null==t.fanout)throw Ki(new Error("missing fanout"),"ERR_NOT_UNIXFS");const r=function(e){if(null==e||null==e.hashFn)throw new Error("please define an options.hashFn");const t={bits:e.bits??8,hash:Oc(e.hashFn)};return new Cc(t)}({hashFn:zc,bits:Math.log2(Number(t.fanout))});n={rootBucket:r,hamtDepth:1,lastBucket:r}}const i=(n.lastBucket.tableSize()-1).toString(16).length;await(async(e,t,r)=>{const n=(t.tableSize()-1).toString(16).length;await Promise.all(e.map((async e=>{if(null==e.Name)throw new Error("Unexpected Link without a Name");if(e.Name.length!==n)await r.put(e.Name.substring(2),!0);else{const n=parseInt(e.Name,16);t._putObjectAt(n,new Cc({hash:r._options.hash,bits:r._options.bits},t,n))}})))})(e.Links,n.lastBucket,n.rootBucket);const s=await n.rootBucket._findNewBucketAndPos(t);let a=Lc(s.pos,i);const c=(e=>{let t=e.bucket;const r=[];for(;null!=t._parent;)r.push(t),t=t._parent;return r.push(t),r.reverse()})(s);c.length>n.hamtDepth&&(n.lastBucket=c[n.hamtDepth],a=Lc(n.lastBucket._posAtParent,i));const u=e.Links.find((e=>{if(null==e.Name)return!1;const r=e.Name.substring(0,i),n=e.Name.substring(i);return r===a&&(""===n||n===t)}));if(null!=u)return null!=u.Name&&u.Name.substring(i)===t?u.Hash:(n.hamtDepth++,e=wa(await r.get(u.Hash,o)),Rc(e,t,r,n,o))},Mc=Rc,jc=function(e){const[t,r]=null!=e[Symbol.asyncIterator]?[e[Symbol.asyncIterator](),Symbol.asyncIterator]:[e[Symbol.iterator](),Symbol.iterator],n=[];return{peek:()=>t.next(),push:e=>{n.push(e)},next:()=>n.length>0?{done:!1,value:n.shift()}:t.next(),[r](){return this}}},$c=function(e,t){if(null!=e[Symbol.asyncIterator])return async function*(){for await(const r of e)yield t(r)}();const r=jc(e),{value:n,done:o}=r.next();if(!0===o)return function*(){}();const i=t(n);if("function"==typeof i.then)return async function*(){yield await i;for await(const e of r)yield t(e)}();const s=t;return function*(){yield i;for(const e of r)yield s(e)}()};function Fc(){const e={};return e.promise=new Promise(((t,r)=>{e.resolve=t,e.reject=r})),e}const Vc=globalThis.CustomEvent??Event;async function*Hc(e,t={}){let r=t.concurrency??1/0;r<1&&(r=1/0);const n=null!=t.ordered&&t.ordered,o=new EventTarget,i=[];let s,a=Fc(),c=Fc(),u=!1,h=!1;function f(){return n?i[0]?.done:Boolean(i.find((e=>e.done)))}function*l(){for(;i.length>0&&i[0].done;){const e=i[0];if(i.shift(),!e.ok)throw h=!0,a.resolve(),e.err;yield e.value,a.resolve()}}function*d(){for(;f();)for(let e=0;e{c.resolve()})),Promise.resolve().then((async()=>{try{for await(const t of e){if(i.length===r&&(a=Fc(),await a.promise),h)break;const e={done:!1};i.push(e),t().then((t=>{e.done=!0,e.ok=!0,e.value=t,o.dispatchEvent(new Vc("task-complete"))}),(t=>{e.done=!0,e.err=t,o.dispatchEvent(new Vc("task-complete"))}))}u=!0,o.dispatchEvent(new Vc("task-complete"))}catch(e){s=e,o.dispatchEvent(new Vc("task-complete"))}}));;){if(f()||(c=Fc(),await c.promise),null!=s)throw s;if(n?yield*l():yield*d(),u&&0===i.length)break}}class qc{buffer;mask;top;btm;next;constructor(e){if(!(e>0)||0!=(e-1&e))throw new Error("Max size for a FixedFIFO should be a power of two");this.buffer=new Array(e),this.mask=e-1,this.top=0,this.btm=0,this.next=null}push(e){return void 0===this.buffer[this.top]&&(this.buffer[this.top]=e,this.top=this.top+1&this.mask,!0)}shift(){const e=this.buffer[this.btm];if(void 0!==e)return this.buffer[this.btm]=void 0,this.btm=this.btm+1&this.mask,e}isEmpty(){return void 0===this.buffer[this.btm]}}class Gc{size;hwm;head;tail;constructor(e={}){this.hwm=e.splitLimit??16,this.head=new qc(this.hwm),this.tail=this.head,this.size=0}calculateSize(e){return null!=e?.byteLength?e.byteLength:1}push(e){if(null!=e?.value&&(this.size+=this.calculateSize(e.value)),!this.head.push(e)){const t=this.head;this.head=t.next=new qc(2*this.head.buffer.length),this.head.push(e)}}shift(){let e=this.tail.shift();if(void 0===e&&null!=this.tail.next){const t=this.tail.next;this.tail.next=null,this.tail=t,e=this.tail.shift()}return null!=e?.value&&(this.size-=this.calculateSize(e.value)),e}isEmpty(){return this.head.isEmpty()}}class Wc extends Error{type;code;constructor(e,t){super(e??"The operation was aborted"),this.type="aborted",this.code=t??"ABORT_ERR"}}function Jc(e={}){return function(e,t){let r,n,o,i=(t=t??{}).onEnd,s=new Gc,a=Fc();const c=e=>null!=n?n(e):(s.push(e),r),u=e=>{if(o)return r;if(!0!==t?.objectMode&&null==e?.byteLength)throw new Error("objectMode was not true but tried to push non-Uint8Array value");return c({done:!1,value:e})},h=e=>o?r:(o=!0,null!=e?(e=>(s=new Gc,null!=n?n({error:e}):(s.push({error:e}),r)))(e):c({done:!0}));if(r={[Symbol.asyncIterator](){return this},next:async()=>{try{return s.isEmpty()?o?{done:!0}:await new Promise(((t,o)=>{n=i=>{n=null,s.push(i);try{t(e(s))}catch(e){o(e)}return r}})):e(s)}finally{s.isEmpty()&&queueMicrotask((()=>{a.resolve(),a=Fc()}))}},return:()=>(s=new Gc,h(),{done:!0}),throw:e=>(h(e),{done:!0}),push:u,end:h,get readableLength(){return s.size},onEmpty:async e=>{const t=e?.signal;if(t?.throwIfAborted(),s.isEmpty())return;let r,n;null!=t&&(r=new Promise(((e,r)=>{n=()=>{r(new Wc)},t.addEventListener("abort",n)})));try{await Promise.race([a.promise,r])}finally{null!=n&&null!=t&&t?.removeEventListener("abort",n)}}},null==i)return r;const f=r;return r={[Symbol.asyncIterator](){return this},next:()=>f.next(),throw:e=>(f.throw(e),null!=i&&(i(e),i=void 0),{done:!0}),return:()=>(f.return(),null!=i&&(i(),i=void 0),{done:!0}),push:u,end:e=>(f.end(e),null!=i&&(i(e),i=void 0),r),get readableLength(){return f.readableLength}},r}((e=>{const t=e.shift();if(null==t)return{done:!0};if(null!=t.error)throw t.error;return{done:!0===t.done,value:t.value}}),e)}function Kc(e,...t){if(null==e)throw new Error("Empty pipeline");if(Yc(e)){const t=e;e=()=>t.source}else if(Zc(e)||Xc(e)){const t=e;e=()=>t}const r=[e,...t];if(r.length>1&&Yc(r[r.length-1])&&(r[r.length-1]=r[r.length-1].sink),r.length>2)for(let e=1;e{let t;for(;e.length>0;)t=e.shift()(t);return t},Xc=e=>null!=e?.[Symbol.asyncIterator],Zc=e=>null!=e?.[Symbol.iterator],Yc=e=>null!=e&&null!=e.sink&&null!=e.source,eu=e=>t=>{const r=e.sink(t);if(null!=r?.then){const t=Jc({objectMode:!0});let n;r.then((()=>{t.end()}),(e=>{t.end(e)}));const o=e.source;if(Xc(o))n=async function*(){yield*o,t.end()};else{if(!Zc(o))throw new Error("Unknown duplex source type - must be Iterable or AsyncIterable");n=function*(){yield*o,t.end()}}return function(...e){const t=[];for(const r of e)null==r[Symbol.asyncIterator]&&t.push(r);return t.length===e.length?function*(){for(const e of t)yield*e}():async function*(){const t=Jc({objectMode:!0});Promise.resolve().then((async()=>{try{await Promise.all(e.map((async e=>{for await(const r of e)t.push(r)}))),t.end()}catch(e){t.end(e)}})),yield*t}()}(t,n())}return e.source};var tu=__webpack_require__(729);class ru extends Error{constructor(e){super(e),this.name="TimeoutError"}}class nu extends Error{constructor(e){super(),this.name="AbortError",this.message=e}}const ou=e=>void 0===globalThis.DOMException?new nu(e):new DOMException(e),iu=e=>{const t=void 0===e.reason?ou("This operation was aborted."):e.reason;return t instanceof Error?t:ou(t)};var su,au=function(e,t,r,n){if("a"===r&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)};su=new WeakMap;const cu=class{constructor(){su.set(this,[])}enqueue(e,t){const r={priority:(t={priority:0,...t}).priority,run:e};if(this.size&&au(this,su,"f")[this.size-1].priority>=t.priority)return void au(this,su,"f").push(r);const n=function(e,t,r){let n=0,o=e.length;for(;o>0;){const r=Math.trunc(o/2);let s=n+r;i=e[s],t.priority-i.priority<=0?(n=++s,o-=r+1):o=r}var i;return n}(au(this,su,"f"),r);au(this,su,"f").splice(n,0,r)}dequeue(){const e=au(this,su,"f").shift();return null==e?void 0:e.run}filter(e){return au(this,su,"f").filter((t=>t.priority===e.priority)).map((e=>e.run))}get size(){return au(this,su,"f").length}};var uu,hu,fu,lu,du,pu,wu,bu,yu,gu,mu,vu,_u,ku,Eu,xu,Cu,Au,Bu,Iu,Su,Du,Tu,Uu,Nu,Ou,Pu=function(e,t,r,n,o){if("m"===n)throw new TypeError("Private method is not writable");if("a"===n&&!o)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===n?o.call(e,r):o?o.value=r:t.set(e,r),r},zu=function(e,t,r,n){if("a"===r&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)};class Lu extends Error{}hu=new WeakMap,fu=new WeakMap,lu=new WeakMap,du=new WeakMap,pu=new WeakMap,wu=new WeakMap,bu=new WeakMap,yu=new WeakMap,gu=new WeakMap,mu=new WeakMap,vu=new WeakMap,_u=new WeakMap,ku=new WeakMap,Eu=new WeakMap,uu=new WeakSet,xu=function(){return zu(this,fu,"f")||zu(this,lu,"f"){zu(this,uu,"m",Bu).call(this)}),t),"f"),!0;Pu(this,lu,zu(this,hu,"f")?zu(this,vu,"f"):0,"f")}return!1},Su=function(){if(0===zu(this,gu,"f").size)return zu(this,bu,"f")&&clearInterval(zu(this,bu,"f")),Pu(this,bu,void 0,"f"),this.emit("empty"),0===zu(this,vu,"f")&&this.emit("idle"),!1;if(!zu(this,ku,"f")){const e=!zu(this,uu,"a",Iu);if(zu(this,uu,"a",xu)&&zu(this,uu,"a",Cu)){const t=zu(this,gu,"f").dequeue();return!!t&&(this.emit("active"),t(),e&&zu(this,uu,"m",Du).call(this),!0)}}return!1},Du=function(){zu(this,fu,"f")||void 0!==zu(this,bu,"f")||(Pu(this,bu,setInterval((()=>{zu(this,uu,"m",Tu).call(this)}),zu(this,pu,"f")),"f"),Pu(this,wu,Date.now()+zu(this,pu,"f"),"f"))},Tu=function(){0===zu(this,lu,"f")&&0===zu(this,vu,"f")&&zu(this,bu,"f")&&(clearInterval(zu(this,bu,"f")),Pu(this,bu,void 0,"f")),Pu(this,lu,zu(this,hu,"f")?zu(this,vu,"f"):0,"f"),zu(this,uu,"m",Uu).call(this)},Uu=function(){for(;zu(this,uu,"m",Su).call(this););},Nu=async function(e){return new Promise(((t,r)=>{e.addEventListener("abort",(()=>{r(new Lu("The task was aborted."))}),{once:!0})}))},Ou=async function(e,t){return new Promise((r=>{const n=()=>{t&&!t()||(this.off(e,n),r())};this.on(e,n)}))};const Ru=class extends tu{constructor(e){var t,r,n,o;if(super(),uu.add(this),hu.set(this,void 0),fu.set(this,void 0),lu.set(this,0),du.set(this,void 0),pu.set(this,void 0),wu.set(this,0),bu.set(this,void 0),yu.set(this,void 0),gu.set(this,void 0),mu.set(this,void 0),vu.set(this,0),_u.set(this,void 0),ku.set(this,void 0),Eu.set(this,void 0),Object.defineProperty(this,"timeout",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),!("number"==typeof(e={carryoverConcurrencyCount:!1,intervalCap:Number.POSITIVE_INFINITY,interval:0,concurrency:Number.POSITIVE_INFINITY,autoStart:!0,queueClass:cu,...e}).intervalCap&&e.intervalCap>=1))throw new TypeError(`Expected \`intervalCap\` to be a number from 1 and up, got \`${null!==(r=null===(t=e.intervalCap)||void 0===t?void 0:t.toString())&&void 0!==r?r:""}\` (${typeof e.intervalCap})`);if(void 0===e.interval||!(Number.isFinite(e.interval)&&e.interval>=0))throw new TypeError(`Expected \`interval\` to be a finite number >= 0, got \`${null!==(o=null===(n=e.interval)||void 0===n?void 0:n.toString())&&void 0!==o?o:""}\` (${typeof e.interval})`);Pu(this,hu,e.carryoverConcurrencyCount,"f"),Pu(this,fu,e.intervalCap===Number.POSITIVE_INFINITY||0===e.interval,"f"),Pu(this,du,e.intervalCap,"f"),Pu(this,pu,e.interval,"f"),Pu(this,gu,new e.queueClass,"f"),Pu(this,mu,e.queueClass,"f"),this.concurrency=e.concurrency,this.timeout=e.timeout,Pu(this,Eu,!0===e.throwOnTimeout,"f"),Pu(this,ku,!1===e.autoStart,"f")}get concurrency(){return zu(this,_u,"f")}set concurrency(e){if(!("number"==typeof e&&e>=1))throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${e}\` (${typeof e})`);Pu(this,_u,e,"f"),zu(this,uu,"m",Uu).call(this)}async add(e,t={}){return t={timeout:this.timeout,throwOnTimeout:zu(this,Eu,"f"),...t},new Promise(((r,n)=>{zu(this,gu,"f").enqueue((async()=>{var o,i,s;Pu(this,vu,(i=zu(this,vu,"f"),++i),"f"),Pu(this,lu,(s=zu(this,lu,"f"),++s),"f");try{if(null===(o=t.signal)||void 0===o?void 0:o.aborted)throw new Lu("The task was aborted.");let n=e({signal:t.signal});t.timeout&&(n=function(e,t,r,n){let o;const i=new Promise(((i,s)=>{if("number"!=typeof t||1!==Math.sign(t))throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${t}\``);if(t!==Number.POSITIVE_INFINITY){if((n={customTimers:{setTimeout,clearTimeout},...n}).signal){const{signal:e}=n;e.aborted&&s(iu(e)),e.addEventListener("abort",(()=>{s(iu(e))}))}o=n.customTimers.setTimeout.call(void 0,(()=>{const n=r instanceof Error?r:new ru(`Promise timed out after ${t} milliseconds`);"function"==typeof e.cancel&&e.cancel(),s(n)}),t),(async()=>{try{i(await e)}catch(e){s(e)}finally{n.customTimers.clearTimeout.call(void 0,o)}})()}else i(e)}));return i.clear=()=>{clearTimeout(o),o=void 0},i}(Promise.resolve(n),t.timeout)),t.signal&&(n=Promise.race([n,zu(this,uu,"m",Nu).call(this,t.signal)]));const i=await n;r(i),this.emit("completed",i)}catch(e){if(e instanceof ru&&!t.throwOnTimeout)return void r();n(e),this.emit("error",e)}finally{zu(this,uu,"m",Au).call(this)}}),t),this.emit("add"),zu(this,uu,"m",Su).call(this)}))}async addAll(e,t){return Promise.all(e.map((async e=>this.add(e,t))))}start(){return zu(this,ku,"f")?(Pu(this,ku,!1,"f"),zu(this,uu,"m",Uu).call(this),this):this}pause(){Pu(this,ku,!0,"f")}clear(){Pu(this,gu,new(zu(this,mu,"f")),"f")}async onEmpty(){0!==zu(this,gu,"f").size&&await zu(this,uu,"m",Ou).call(this,"empty")}async onSizeLessThan(e){zu(this,gu,"f").sizezu(this,gu,"f").size=s&&o=s&&i<=u||ou)&&c.push({link:r,blockStart:n}),(n=u)>i)break}await Kc(c,(t=>$c(t,(t=>async()=>{const r=await e.get(t.link.Hash,s);return{...t,block:r}}))),(e=>Hc(e,{ordered:!0})),(async t=>{for await(const{link:n,block:a,blockStart:c}of t){let t;switch(n.Hash.code){case 112:t=wa(a);break;case ya:t=a;break;default:return void r.end(Ki(new Error(`Unsupported codec: ${n.Hash.code}`),"ERR_NOT_UNIXFS"))}const u=new Ru({concurrency:1});u.on("error",(e=>{r.end(e)})),u.add((async()=>{s.onProgress?.(new ka("unixfs:exporter:walk:file",{cid:n.Hash})),await Mu(e,t,r,c,o,i,s)})),await u.onIdle()}})),n>=i&&r.end()}const ju=(e,t,r,n,o,i,s)=>async function*(n={}){const o=r.fileSize();if(void 0===o)throw new Error("File was a directory");const{start:i,end:a}=xa(o,n.offset,n.length);if(0n===a)return;let c=0n;const u=a-i,h=Jc();n.onProgress?.(new ka("unixfs:exporter:walk:file",{cid:e})),Mu(s,t,h,0n,i,a,n).catch((e=>{h.end(e)}));for await(const e of h)if(null!=e){if(c+=BigInt(e.byteLength),c>u)throw h.end(),Ki(new Error("Read too many bytes - the file size reported by the UnixFS data in the root node may be incorrect"),"ERR_OVER_READ");c===u&&h.end(),n.onProgress?.(new ka("unixfs:exporter:progress:unixfs:file",{bytesRead:c,totalBytes:u,fileSize:o})),yield e}if(c$c(s,(s=>async()=>{const a=null!=s.Name?s.Name.substring(c):null;if(null!=a&&""!==a){const e=await r(s.Hash,a,`${t}/${a}`,[],n+1,o,i);return{entries:null==e.entry?[]:[e.entry]}}{const a=await o.get(s.Hash,i);return e=wa(a),i.onProgress?.(new ka("unixfs:exporter:walk:hamt-sharded-directory",{cid:s.Hash})),{entries:$u(e,t,r,n,o,i)}}}))),(e=>Hc(e,{ordered:!0})));for await(const{entries:e}of u)yield*e}const Fu={raw:ju,file:ju,directory:(e,t,r,n,o,i,s)=>async function*(r={}){const a=r.offset??0,c=r.length??t.Links.length,u=t.Links.slice(a,c);r.onProgress?.(new ka("unixfs:exporter:walk:directory",{cid:e})),yield*Kc(u,(e=>$c(e,(e=>async()=>{const t=e.Name??"",a=`${n}/${t}`;return(await o(e.Hash,t,a,[],i+1,s,r)).entry}))),(e=>Hc(e,{ordered:!0})),(e=>function(e,t){if(null!=e[Symbol.asyncIterator])return async function*(){for await(const r of e)await t(r)&&(yield r)}();const r=jc(e),{value:n,done:o}=r.next();if(!0===o)return function*(){}();const i=t(n);if("function"==typeof i.then)return async function*(){await i&&(yield n);for await(const e of r)await t(e)&&(yield e)}();const s=t;return function*(){!0===i&&(yield n);for(const e of r)s(e)&&(yield e)}()}(e,(e=>null!=e))))},"hamt-sharded-directory":(e,t,r,n,o,i,s)=>function(r={}){return r.onProgress?.(new ka("unixfs:exporter:walk:hamt-sharded-directory",{cid:e})),$u(t,n,o,i,s,r)},metadata:(e,t,r,n,o,i,s)=>()=>[],symlink:(e,t,r,n,o,i,s)=>()=>[]},Vu={112:async(e,t,r,n,o,i,s,a)=>{const c=wa(await s.get(e,a));let u,h;if(null==t&&(t=e.toString()),null==c.Data)throw Ki(new Error("no data in PBNode"),"ERR_NOT_UNIXFS");try{u=Va.unmarshal(c.Data)}catch(e){throw Ki(e,"ERR_NOT_UNIXFS")}if(null==r&&(r=t),n.length>0){let e;if(e="hamt-sharded-directory"===u?.type?await Mc(c,n[0],s):((e,t)=>e.Links.find((e=>e.Name===t))?.Hash)(c,n[0]),null==e)throw Ki(new Error("file does not exist"),"ERR_NOT_FOUND");const t=n.shift();h={cid:e,toResolve:n,name:t??"",path:`${r}/${t}`}}const f=Fu[u.type](e,c,u,r,o,i,s);if(null==f)throw Ki(new Error("could not find content exporter"),"ERR_NOT_FOUND");return u.isDirectory()?{entry:{type:"directory",name:t,path:r,cid:e,content:f,unixfs:u,depth:i,node:c,size:u.fileSize()},next:h}:{entry:{type:"file",name:t,path:r,cid:e,content:f,unixfs:u,depth:i,node:c,size:u.fileSize()},next:h}},[ya]:async(e,t,r,n,o,i,s,a)=>{if(n.length>0)throw Ki(new Error(`No link named ${r} found in raw node ${e}`),"ERR_NOT_FOUND");const c=await s.get(e,a);return{entry:{type:"raw",name:t,path:r,cid:e,content:(u=c,async function*(e={}){const{start:t,end:r}=xa(u.length,e.offset,e.length),n=Ea(u,0n,t,r);e.onProgress?.(new ka("unixfs:exporter:progress:raw",{bytesRead:BigInt(n.byteLength),totalBytes:r-t,fileSize:BigInt(u.byteLength)})),yield n}),depth:i,size:BigInt(c.length),node:c}};var u},113:async(e,t,r,n,o,i,s,a)=>{const c=await s.get(e,a),u=ca(c,ua);let h=u,f=r;for(;n.length>0;){const o=n[0];if(!(o in h))throw Ki(new Error(`No property named ${o} found in cbor node ${e}`),"ERR_NO_PROP");{n.shift(),f=`${f}/${o}`;const s=le.asCID(h[o]);if(null!=s)return{entry:{type:"object",name:t,path:r,cid:e,node:c,depth:i,size:BigInt(c.length),content:async function*(){yield u}},next:{cid:s,name:o,path:f,toResolve:n}};h=h[o]}}return{entry:{type:"object",name:t,path:r,cid:e,node:c,depth:i,size:BigInt(c.length),content:async function*(){yield u}}}},[_a.code]:async(e,t,r,n,o,i,s,a)=>{if(n.length>0)throw Ki(new Error(`No link named ${r} found in raw node ${e}`),"ERR_NOT_FOUND");const c=ae(e.multihash.bytes);return{entry:{type:"identity",name:t,path:r,cid:e,content:(u=c.digest,async function*(e={}){const{start:t,end:r}=xa(u.length,e.offset,e.length),n=Ea(u,0n,t,r);e.onProgress?.(new ka("unixfs:exporter:progress:identity",{bytesRead:BigInt(n.byteLength),totalBytes:r-t,fileSize:BigInt(u.byteLength)})),yield n}),depth:i,size:BigInt(c.digest.length),node:c.digest}};var u}},Hu=async(e,t,r,n,o,i,s)=>{const a=Vu[e.code];if(null==a)throw Ki(new Error(`No resolver for code ${e.code}`),"ERR_NO_RESOLVER");return a(e,t,r,n,Hu,o,i,s)},qu=Hu;async function Gu(e,t,r={}){const n=await function(e){if(null!=e[Symbol.asyncIterator])return(async()=>{let t;for await(const r of e)t=r;return t})();let t;for(const r of e)t=r;return t}(async function*(e,t,r={}){let{cid:n,toResolve:o}=(e=>{if(e instanceof Uint8Array)return{cid:le.decode(e),toResolve:[]};const t=le.asCID(e);if(null!=t)return{cid:t,toResolve:[]};if("string"==typeof e){0===e.indexOf("/ipfs/")&&(e=e.substring(6));const t=((e="")=>(e.trim().match(/([^\\^/]|\\\/)+/g)??[]).filter(Boolean))(e);return{cid:le.parse(t[0]),toResolve:t.slice(1)}}throw Ki(new Error(`Unknown path type ${e}`),"ERR_BAD_PATH")})(e),i=n.toString(),s=i;const a=o.length;for(;;){const c=await qu(n,i,s,o,a,t,r);if(null==c.entry&&null==c.next)throw Ki(new Error(`Could not resolve ${e}`),"ERR_NOT_FOUND");if(null!=c.entry&&(yield c.entry),null==c.next)return;o=c.next.toResolve,n=c.next.cid,i=c.next.name,s=c.next.path}}(e,t,r));if(null==n)throw Ki(new Error(`Could not resolve ${e}`),"ERR_NOT_FOUND");return n}var Wu=__webpack_require__(191);new Uint8Array(0);const Ju=e=>{if(e instanceof Uint8Array&&"Uint8Array"===e.constructor.name)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Unknown type, must be binary type")};var Ku=Math.pow(2,31),Qu=Math.pow(2,7),Xu=Math.pow(2,14),Zu=Math.pow(2,21),Yu=Math.pow(2,28),eh=Math.pow(2,35),th=Math.pow(2,42),rh=Math.pow(2,49),nh=Math.pow(2,56),oh=Math.pow(2,63);const ih=function e(t,r,n){r=r||[];for(var o=n=n||0;t>=Ku;)r[n++]=255&t|128,t/=128;for(;-128&t;)r[n++]=255&t|128,t>>>=7;return r[n]=0|t,e.bytes=n-o+1,r},sh=function(e){return e(ih(e,t,r),t),ch=e=>sh(e),uh=(e,t)=>{const r=t.byteLength,n=ch(e),o=n+ch(r),i=new Uint8Array(o+r);return ah(e,i,0),ah(r,i,n),i.set(t,o),new hh(e,r,t,i)};class hh{constructor(e,t,r,n){this.code=e,this.size=t,this.digest=r,this.bytes=n}}const fh=({name:e,code:t,encode:r})=>new lh(e,t,r);class lh{constructor(e,t,r){this.name=e,this.code=t,this.encode=r}digest(e){if(e instanceof Uint8Array){const t=this.encode(e);return t instanceof Uint8Array?uh(this.code,t):t.then((e=>uh(this.code,e)))}throw Error("Unknown type, must be binary type")}}const dh=function(e,t){if(e.length>=255)throw new TypeError("Alphabet too long");for(var r=new Uint8Array(256),n=0;n>>0,s=new Uint8Array(i);e[t];){var h=r[e.charCodeAt(t)];if(255===h)return;for(var f=0,l=i-1;(0!==h||f>>0,s[l]=h%256>>>0,h=h/256>>>0;if(0!==h)throw new Error("Non-zero carry");o=f,t++}if(" "!==e[t]){for(var d=i-o;d!==i&&0===s[d];)d++;for(var p=new Uint8Array(n+(i-d)),w=n;d!==i;)p[w++]=s[d++];return p}}}return{encode:function(t){if(t instanceof Uint8Array||(ArrayBuffer.isView(t)?t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength):Array.isArray(t)&&(t=Uint8Array.from(t))),!(t instanceof Uint8Array))throw new TypeError("Expected Uint8Array");if(0===t.length)return"";for(var r=0,n=0,o=0,i=t.length;o!==i&&0===t[o];)o++,r++;for(var s=(i-o)*h+1>>>0,u=new Uint8Array(s);o!==i;){for(var f=t[o],l=0,d=s-1;(0!==f||l>>0,u[d]=f%a>>>0,f=f/a>>>0;if(0!==f)throw new Error("Non-zero carry");n=l,o++}for(var p=s-n;p!==s&&0===u[p];)p++;for(var w=c.repeat(r);pnew bh({...e.decoders||{[e.prefix]:e},...t.decoders||{[t.prefix]:t}});class gh{constructor(e,t,r,n){this.name=e,this.prefix=t,this.baseEncode=r,this.baseDecode=n,this.encoder=new ph(e,t,r),this.decoder=new wh(e,t,n)}encode(e){return this.encoder.encode(e)}decode(e){return this.decoder.decode(e)}}const mh=({name:e,prefix:t,encode:r,decode:n})=>new gh(e,t,r,n),vh=({prefix:e,name:t,alphabet:r})=>{const{encode:n,decode:o}=dh(r,t);return mh({prefix:e,name:t,encode:n,decode:e=>Ju(o(e))})},_h=({name:e,prefix:t,bitsPerChar:r,alphabet:n})=>mh({prefix:t,name:e,encode:e=>((e,t,r)=>{const n="="===t[t.length-1],o=(1<r;)s-=r,i+=t[o&a>>s];if(s&&(i+=t[o&a<((e,t,r,n)=>{const o={};for(let e=0;e=8&&(a-=8,s[u++]=255&c>>a)}if(a>=r||255&c<<8-a)throw new SyntaxError("Unexpected end of data");return s})(t,n,r,e)});vh({name:"base58btc",prefix:"z",alphabet:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"}),vh({name:"base58flickr",prefix:"Z",alphabet:"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"}),_h({prefix:"b",name:"base32",alphabet:"abcdefghijklmnopqrstuvwxyz234567",bitsPerChar:5}),_h({prefix:"B",name:"base32upper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",bitsPerChar:5}),_h({prefix:"c",name:"base32pad",alphabet:"abcdefghijklmnopqrstuvwxyz234567=",bitsPerChar:5}),_h({prefix:"C",name:"base32padupper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",bitsPerChar:5}),_h({prefix:"v",name:"base32hex",alphabet:"0123456789abcdefghijklmnopqrstuv",bitsPerChar:5}),_h({prefix:"V",name:"base32hexupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV",bitsPerChar:5}),_h({prefix:"t",name:"base32hexpad",alphabet:"0123456789abcdefghijklmnopqrstuv=",bitsPerChar:5}),_h({prefix:"T",name:"base32hexpadupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV=",bitsPerChar:5}),_h({prefix:"h",name:"base32z",alphabet:"ybndrfg8ejkmcpqxot1uwisza345h769",bitsPerChar:5});class kh{constructor(e,t,r,n){this.code=t,this.version=e,this.multihash=r,this.bytes=n,this.byteOffset=n.byteOffset,this.byteLength=n.byteLength,this.asCID=this,this._baseCache=new Map,Object.defineProperties(this,{byteOffset:node_modules_multiformats_esm_src_cid_hidden,byteLength:node_modules_multiformats_esm_src_cid_hidden,code:multiformats_esm_src_cid_readonly,version:multiformats_esm_src_cid_readonly,multihash:multiformats_esm_src_cid_readonly,bytes:multiformats_esm_src_cid_readonly,_baseCache:node_modules_multiformats_esm_src_cid_hidden,asCID:node_modules_multiformats_esm_src_cid_hidden})}toV0(){if(0===this.version)return this;{const{code:e,multihash:t}=this;if(e!==node_modules_multiformats_esm_src_cid_DAG_PB_CODE)throw new Error("Cannot convert a non dag-pb CID to CIDv0");if(t.code!==node_modules_multiformats_esm_src_cid_SHA_256_CODE)throw new Error("Cannot convert non sha2-256 multihash CID to CIDv0");return kh.createV0(t)}}toV1(){switch(this.version){case 0:{const{code:e,digest:t}=this.multihash,r=Digest.create(e,t);return kh.createV1(this.code,r)}case 1:return this;default:throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`)}}equals(e){return e&&this.code===e.code&&this.version===e.version&&Digest.equals(this.multihash,e.multihash)}toString(e){const{bytes:t,version:r,_baseCache:n}=this;return 0===r?node_modules_multiformats_esm_src_cid_toStringV0(t,n,e||base58btc.encoder):node_modules_multiformats_esm_src_cid_toStringV1(t,n,e||base32.encoder)}toJSON(){return{code:this.code,version:this.version,hash:this.multihash.bytes}}get[Symbol.toStringTag](){return"CID"}[Symbol.for("nodejs.util.inspect.custom")](){return"CID("+this.toString()+")"}static isCID(e){return multiformats_esm_src_cid_deprecate(/^0\.0/,multiformats_esm_src_cid_IS_CID_DEPRECATION),!(!e||!e[node_modules_multiformats_esm_src_cid_cidSymbol]&&e.asCID!==e)}get toBaseEncodedString(){throw new Error("Deprecated, use .toString()")}get codec(){throw new Error('"codec" property is deprecated, use integer "code" property instead')}get buffer(){throw new Error("Deprecated .buffer property, use .bytes to get Uint8Array instead")}get multibaseName(){throw new Error('"multibaseName" property is deprecated')}get prefix(){throw new Error('"prefix" property is deprecated')}static asCID(e){if(e instanceof kh)return e;if(null!=e&&e.asCID===e){const{version:t,code:r,multihash:n,bytes:o}=e;return new kh(t,r,n,o||node_modules_multiformats_esm_src_cid_encodeCID(t,r,n.bytes))}if(null!=e&&!0===e[node_modules_multiformats_esm_src_cid_cidSymbol]){const{version:t,multihash:r,code:n}=e,o=Digest.decode(r);return kh.create(t,n,o)}return null}static create(e,t,r){if("number"!=typeof t)throw new Error("String codecs are no longer supported");switch(e){case 0:if(t!==node_modules_multiformats_esm_src_cid_DAG_PB_CODE)throw new Error(`Version 0 CID must use dag-pb (code: ${node_modules_multiformats_esm_src_cid_DAG_PB_CODE}) block encoding`);return new kh(e,t,r,r.bytes);case 1:{const n=node_modules_multiformats_esm_src_cid_encodeCID(e,t,r.bytes);return new kh(e,t,r,n)}default:throw new Error("Invalid version")}}static createV0(e){return kh.create(0,node_modules_multiformats_esm_src_cid_DAG_PB_CODE,e)}static createV1(e,t){return kh.create(1,e,t)}static decode(e){const[t,r]=kh.decodeFirst(e);if(r.length)throw new Error("Incorrect length");return t}static decodeFirst(e){const t=kh.inspectBytes(e),r=t.size-t.multihashSize,n=coerce(e.subarray(r,r+t.multihashSize));if(n.byteLength!==t.multihashSize)throw new Error("Incorrect length");const o=n.subarray(t.multihashSize-t.digestSize),i=new Digest.Digest(t.multihashCode,t.digestSize,o,n);return[0===t.version?kh.createV0(i):kh.createV1(t.codec,i),e.subarray(t.size)]}static inspectBytes(e){const t=()=>{const[t,r]=varint.decode(e.subarray(0));return t};let r=t(),n=node_modules_multiformats_esm_src_cid_DAG_PB_CODE;if(18===r||1===r&&t(),0!==r&&1!==r)throw new RangeError(`Invalid CID version ${r}`);const o=t(),i=t(),s=0+i;return{version:r,codec:n,multihashCode:o,digestSize:i,multihashSize:s-0,size:s}}static parse(e,t){const[r,n]=node_modules_multiformats_esm_src_cid_parseCIDtoBytes(e,t),o=kh.decode(n);return o._baseCache.set(r,e),o}}Symbol.for("@ipld/js-cid/CID");const{blake2b:Eh}=Wu,xh=(fh({name:"blake2b-8",code:45569,encode:e=>Ju(Eh(e,void 0,1))}),fh({name:"blake2b-16",code:45570,encode:e=>Ju(Eh(e,void 0,2))}),fh({name:"blake2b-24",code:45571,encode:e=>Ju(Eh(e,void 0,3))}),fh({name:"blake2b-32",code:45572,encode:e=>Ju(Eh(e,void 0,4))}),fh({name:"blake2b-40",code:45573,encode:e=>Ju(Eh(e,void 0,5))}),fh({name:"blake2b-48",code:45574,encode:e=>Ju(Eh(e,void 0,6))}),fh({name:"blake2b-56",code:45575,encode:e=>Ju(Eh(e,void 0,7))}),fh({name:"blake2b-64",code:45576,encode:e=>Ju(Eh(e,void 0,8))}),fh({name:"blake2b-72",code:45577,encode:e=>Ju(Eh(e,void 0,9))}),fh({name:"blake2b-80",code:45578,encode:e=>Ju(Eh(e,void 0,10))}),fh({name:"blake2b-88",code:45579,encode:e=>Ju(Eh(e,void 0,11))}),fh({name:"blake2b-96",code:45580,encode:e=>Ju(Eh(e,void 0,12))}),fh({name:"blake2b-104",code:45581,encode:e=>Ju(Eh(e,void 0,13))}),fh({name:"blake2b-112",code:45582,encode:e=>Ju(Eh(e,void 0,14))}),fh({name:"blake2b-120",code:45583,encode:e=>Ju(Eh(e,void 0,15))}),fh({name:"blake2b-128",code:45584,encode:e=>Ju(Eh(e,void 0,16))}),fh({name:"blake2b-136",code:45585,encode:e=>Ju(Eh(e,void 0,17))}),fh({name:"blake2b-144",code:45586,encode:e=>Ju(Eh(e,void 0,18))}),fh({name:"blake2b-152",code:45587,encode:e=>Ju(Eh(e,void 0,19))}),fh({name:"blake2b-160",code:45588,encode:e=>Ju(Eh(e,void 0,20))}),fh({name:"blake2b-168",code:45589,encode:e=>Ju(Eh(e,void 0,21))}),fh({name:"blake2b-176",code:45590,encode:e=>Ju(Eh(e,void 0,22))}),fh({name:"blake2b-184",code:45591,encode:e=>Ju(Eh(e,void 0,23))}),fh({name:"blake2b-192",code:45592,encode:e=>Ju(Eh(e,void 0,24))}),fh({name:"blake2b-200",code:45593,encode:e=>Ju(Eh(e,void 0,25))}),fh({name:"blake2b-208",code:45594,encode:e=>Ju(Eh(e,void 0,26))}),fh({name:"blake2b-216",code:45595,encode:e=>Ju(Eh(e,void 0,27))}),fh({name:"blake2b-224",code:45596,encode:e=>Ju(Eh(e,void 0,28))}),fh({name:"blake2b-232",code:45597,encode:e=>Ju(Eh(e,void 0,29))}),fh({name:"blake2b-240",code:45598,encode:e=>Ju(Eh(e,void 0,30))}),fh({name:"blake2b-248",code:45599,encode:e=>Ju(Eh(e,void 0,31))}),fh({name:"blake2b-256",code:45600,encode:e=>Ju(Eh(e,void 0,32))}));function Ch(e){return Symbol.asyncIterator in e?e:async function*(e,t={}){const r=e.getReader();try{for(;;){const e=await r.read();if(e.done)return;yield e.value}}finally{!0!==t.preventCancel&&await r.cancel(),r.releaseLock()}}(e)}fh({name:"blake2b-264",code:45601,encode:e=>Ju(Eh(e,void 0,33))}),fh({name:"blake2b-272",code:45602,encode:e=>Ju(Eh(e,void 0,34))}),fh({name:"blake2b-280",code:45603,encode:e=>Ju(Eh(e,void 0,35))}),fh({name:"blake2b-288",code:45604,encode:e=>Ju(Eh(e,void 0,36))}),fh({name:"blake2b-296",code:45605,encode:e=>Ju(Eh(e,void 0,37))}),fh({name:"blake2b-304",code:45606,encode:e=>Ju(Eh(e,void 0,38))}),fh({name:"blake2b-312",code:45607,encode:e=>Ju(Eh(e,void 0,39))}),fh({name:"blake2b-320",code:45608,encode:e=>Ju(Eh(e,void 0,40))}),fh({name:"blake2b-328",code:45609,encode:e=>Ju(Eh(e,void 0,41))}),fh({name:"blake2b-336",code:45610,encode:e=>Ju(Eh(e,void 0,42))}),fh({name:"blake2b-344",code:45611,encode:e=>Ju(Eh(e,void 0,43))}),fh({name:"blake2b-352",code:45612,encode:e=>Ju(Eh(e,void 0,44))}),fh({name:"blake2b-360",code:45613,encode:e=>Ju(Eh(e,void 0,45))}),fh({name:"blake2b-368",code:45614,encode:e=>Ju(Eh(e,void 0,46))}),fh({name:"blake2b-376",code:45615,encode:e=>Ju(Eh(e,void 0,47))}),fh({name:"blake2b-384",code:45616,encode:e=>Ju(Eh(e,void 0,48))}),fh({name:"blake2b-392",code:45617,encode:e=>Ju(Eh(e,void 0,49))}),fh({name:"blake2b-400",code:45618,encode:e=>Ju(Eh(e,void 0,50))}),fh({name:"blake2b-408",code:45619,encode:e=>Ju(Eh(e,void 0,51))}),fh({name:"blake2b-416",code:45620,encode:e=>Ju(Eh(e,void 0,52))}),fh({name:"blake2b-424",code:45621,encode:e=>Ju(Eh(e,void 0,53))}),fh({name:"blake2b-432",code:45622,encode:e=>Ju(Eh(e,void 0,54))}),fh({name:"blake2b-440",code:45623,encode:e=>Ju(Eh(e,void 0,55))}),fh({name:"blake2b-448",code:45624,encode:e=>Ju(Eh(e,void 0,56))}),fh({name:"blake2b-456",code:45625,encode:e=>Ju(Eh(e,void 0,57))}),fh({name:"blake2b-464",code:45626,encode:e=>Ju(Eh(e,void 0,58))}),fh({name:"blake2b-472",code:45627,encode:e=>Ju(Eh(e,void 0,59))}),fh({name:"blake2b-480",code:45628,encode:e=>Ju(Eh(e,void 0,60))}),fh({name:"blake2b-488",code:45629,encode:e=>Ju(Eh(e,void 0,61))}),fh({name:"blake2b-496",code:45630,encode:e=>Ju(Eh(e,void 0,62))}),fh({name:"blake2b-504",code:45631,encode:e=>Ju(Eh(e,void 0,63))}),fh({name:"blake2b-512",code:45632,encode:e=>Ju(Eh(e,void 0,64))});class Ah extends Error{constructor(e){super(e),this.name="VerificationError"}}class Bh extends Error{constructor(e){super(e),this.name="TimeoutError"}}class Ih{constructor(e,t={}){this.carItr=e,this.getBlockTimeout=t.getBlockTimeout??1e4}static async fromStream(e){const t=(await On.fromIterable(Ch(e)))[Symbol.asyncIterator]();return new Ih(t)}async get(e,t){if((e="string"==typeof e?le.parse(e):e).multihash.code===_a.code)return e.multihash.digest;const{value:r,done:n}=await function(e,t,r){let n;const o=new Promise(((e,o)=>{n=setTimeout((()=>{const e=new Error("Promise timed out");o(r||e)}),t)}));return Promise.race([e,o]).finally((()=>clearTimeout(n)))}(this.carItr.next(),this.getBlockTimeout,new Bh(`get block ${e} timed out`));if(!r&&n)throw new Ah("CAR file has no more blocks.");const{cid:o,bytes:i}=r;if(await async function(e,t){const{code:r,digest:n}=e.multihash;if(!Dh[e.code])throw new Ah(`Unexpected codec: 0x${e.code.toString(16)}`);if(!Th[r])throw new Ah(`Unexpected multihash code: 0x${r.toString(16)}`);if(r!==_a.code&&n.length<20)throw new Ah("Hashes must be at least 20 bytes long");if(r!==_a.code&&n.length>128)throw new Ah("Hashes must be at most 128 bytes long");const o=await Th[r].digest(t);if(Sh(o.digest)!==Sh(n))throw new Ah(`Mismatch: digest of bytes (${Sh(o)}) does not match digest in CID (${Sh(n)})`)}(o,i),!e.equals(o))throw new Ah(`received block with cid ${o}, expected ${e}`);return i}}const{toHex:Sh}=e,Dh={[mn]:n,[Ko]:o,[Gi]:i,[ya]:s,[dc]:b},Th={[_a.code]:_a,[yc.code]:yc,[xh.code]:ve(xh)};async function*Uh(e,t){const r=await Ih.fromStream(t),n=await Gu(e,r);for await(const e of n.content())yield e}const Nh=class{constructor(e={}){this.opts=Object.assign({},{clientId:"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})),cdnURL:"saturn.ms",connectTimeout:5e3,downloadTimeout:0},e),this.reportingLogs=!0,this.logs=[]}async fetchCID(e,t={}){const[r]=e.split("/");le.parse(r);const n=Object.assign({},this.opts,{format:"car"},t),o=this.createRequestURL(e,n),i={url:o,range:null,startTime:new Date,numBytesSent:0},s=new AbortController,a=setTimeout((()=>{s.abort()}),n.connectTimeout);let c;try{c=await fetch(o,{signal:s.signal}),clearTimeout(a);const{headers:e}=c;if(i.ttfbMs=new Date-i.startTime,i.httpStatusCode=c.status,i.cacheHit="HIT"===e.get("saturn-cache-status"),i.nodeId=e.get("saturn-node-id"),i.transferId=e.get("saturn-transfer-id"),i.httpProtocol=e.get("quic-status"),!c.ok)throw new Error(`Non OK response received: ${c.status} ${c.statusText}`)}catch(e){throw i.ifNetworkError=e.message,this._finalizeLog(i),e}finally{this._addPerformanceAPIMetrics(i)}return{res:c,log:i}}async*fetchContent(e,t={}){const{res:r,log:n}=await this.fetchCID(e,t);try{const t=async function*(e){for await(const t of e)n.numBytesSent+=t.length,yield t}(Ch(r.body));yield*Uh(e,t)}catch(e){throw e instanceof Ah&&(n.verificationError=e.message),e}finally{this._finalizeLog(n)}}async fetchContentBuffer(e,t={}){return await async function(e){const t=[];let r=0;for await(const n of e){const e=new Uint8Array(n);t.push(e),r+=e.byteLength}const n=new Uint8Array(r);let o=0;for(const e of t)n.set(e,o),o+=e.byteLength;return n}(this.fetchContent(e,t))}async*extractVerifiedContent(e,t){yield*Uh(e,t)}createRequestURL(e,t){let r=t.cdnURL;r.startsWith("http")||(r=`https://${r}`);const n=new URL(`${r}/ipfs/${e}`);return n.searchParams.set("format",t.format),"car"===t.format&&n.searchParams.set("dag-scope","entity"),n}_finalizeLog(e){e.requestDurationSec=(new Date-e.startTime)/1e3,this.reportLogs(e)}reportLogs(e){this.reportingLogs&&(this.logs.push(e),this.reportLogsTimeout&&clearTimeout(this.reportLogsTimeout),this.reportLogsTimeout=setTimeout(this._reportLogs.bind(this),3e3))}async _reportLogs(){this.logs.length&&(await fetch("https://twb3qukm2i654i3tnvx36char40aymqq.lambda-url.us-west-2.on.aws/",{method:"POST",body:JSON.stringify({bandwidthLogs:this.logs})}),this.logs=[])}_addPerformanceAPIMetrics(e){if("undefined"!=typeof window&&window?.performance){const t=performance.getEntriesByType("resource").find((t=>t.name===e.url.href));if(t){const r=t.domainLookupStart,n=t.domainLookupEnd;n>0&&r>0&&(e.dnsTimeMs=Math.round(n-r),e.ttfbAfterDnsMs=Math.round(t.responseStart-t.requestStart)),null===e.httpProtocol&&t.nextHopProtocol&&(e.httpProtocol=t.nextHopProtocol)}}}}})(),Saturn=__webpack_exports__.default})(); \ No newline at end of file diff --git a/test/fallback.spec.js b/test/fallback.spec.js index 91ae952..d228a77 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -7,6 +7,7 @@ import { concatChunks, generateNodes, getMockServer, mockJWT, mockNodesHandlers, const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' const TEST_NODES_LIST_KEY = 'saturn-nodes' +const TEST_AUTH = 'https://fz3dyeyxmebszwhuiky7vggmsu0rlkoy.lambda-url.us-west-2.on.aws/' const TEST_ORIGIN_DOMAIN = 'saturn.ms' const CLIENT_KEY = 'key' describe('Client Fallback', () => { @@ -108,7 +109,7 @@ describe('Client Fallback', () => { test('Content Fallback fetches a cid properly', async (t) => { const handlers = [ mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms'), - mockJWT('saturn.auth'), + mockJWT(TEST_AUTH), mockSaturnOriginHandler(TEST_ORIGIN_DOMAIN, 0, true), ...mockNodesHandlers(2, TEST_ORIGIN_DOMAIN) ] @@ -141,7 +142,7 @@ describe('Client Fallback', () => { test('should fetch content from the first node successfully', async () => { const handlers = [ mockOrchHandler(2, TEST_DEFAULT_ORCH, 'saturn.ms'), - mockJWT('saturn.auth'), + mockJWT(TEST_AUTH), ...mockNodesHandlers(2, TEST_ORIGIN_DOMAIN) ] @@ -169,7 +170,7 @@ describe('Client Fallback', () => { const numNodes = 3 const handlers = [ mockOrchHandler(numNodes, TEST_DEFAULT_ORCH, 'saturn.ms'), - mockJWT('saturn.auth'), + mockJWT(TEST_AUTH), ...mockNodesHandlers(numNodes, TEST_ORIGIN_DOMAIN) ] @@ -192,15 +193,15 @@ describe('Client Fallback', () => { assert(error) assert.strictEqual(error.message, 'All attempts to fetch content have failed. Last error: Fetch error') assert.strictEqual(fetchContentMock.mock.calls.length, numNodes + 1) - server.close() mock.reset() + server.close() }) test('Handles fallback with chunk overlap correctly', async () => { const numNodes = 3 const handlers = [ mockOrchHandler(numNodes, TEST_DEFAULT_ORCH, 'saturn.ms'), - mockJWT('saturn.auth'), + mockJWT(TEST_AUTH), ...mockNodesHandlers(numNodes, TEST_ORIGIN_DOMAIN) ] @@ -239,7 +240,7 @@ describe('Client Fallback', () => { const numNodes = 3 const handlers = [ mockOrchHandler(numNodes, TEST_DEFAULT_ORCH, 'saturn.ms'), - mockJWT('saturn.auth'), + mockJWT(TEST_AUTH), ...mockNodesHandlers(numNodes, TEST_ORIGIN_DOMAIN) ] diff --git a/test/index.spec.js b/test/index.spec.js index c71bd93..65935e3 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,12 +1,11 @@ import assert from 'node:assert/strict' import { randomUUID } from 'node:crypto' import { describe, it, before, after } from 'node:test' - -import Saturn from '#src/index.js' import { getMockServer, mockJWT, MSW_SERVER_OPTS } from './test-utils.js' +import { Saturn } from '#src/index.js' const TEST_CID = 'QmXjYBY478Cno4jzdCcPy4NcJYFrwHZ51xaCP8vUwN9MGm' - +const TEST_AUTH = 'https://fz3dyeyxmebszwhuiky7vggmsu0rlkoy.lambda-url.us-west-2.on.aws/' const clientKey = 'abc123' describe('Saturn client', () => { @@ -41,7 +40,7 @@ describe('Saturn client', () => { describe('Fetch a CID', () => { const client = new Saturn({ clientKey }) const handlers = [ - mockJWT('saturn.auth') + mockJWT(TEST_AUTH) ] const server = getMockServer(handlers) @@ -64,6 +63,19 @@ describe('Saturn client', () => { await assert.rejects(client.fetchCID(TEST_CID, { connectTimeout: 1 })) }) + it('should use external abort controller', async () => { + const controller = new AbortController() + setTimeout(() => controller.abort(), 5) + + await assert.rejects( + client.fetchCID(TEST_CID, { controller }), + { + name: 'AbortError', + message: 'This operation was aborted' + } + ) + }) + it.skip('should fail when exceeding download timeout', async () => { await assert.rejects(client.fetchCID(`${TEST_CID}/blah`, { downloadTimeout: 1 })) }) @@ -71,7 +83,7 @@ describe('Saturn client', () => { describe('Logging', () => { const handlers = [ - mockJWT('saturn.auth') + mockJWT(TEST_AUTH) ] const server = getMockServer(handlers) const client = new Saturn({ clientKey, clientId: 'tesd' }) diff --git a/webpack.config.cjs b/webpack.config.cjs index c937875..7f20f01 100644 --- a/webpack.config.cjs +++ b/webpack.config.cjs @@ -4,12 +4,11 @@ module.exports = { target: 'web', entry: './src/index.js', output: { - filename: 'strn.min.js', + filename: 'dist/strn.min.js', path: path.resolve(__dirname), library: { - name: 'Saturn', + name: 'SaturnModule', type: 'var', - export: 'default', } } }; From d2c5c376fe09006c31ce27af1c00e442a60f3114 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Mon, 16 Oct 2023 10:34:41 -0400 Subject: [PATCH 23/34] load nodes on first success --- src/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.js b/src/client.js index b92b331..639f6d6 100644 --- a/src/client.js +++ b/src/client.js @@ -388,7 +388,7 @@ export class Saturn { // to insure we have a fallback set as quick as possible let nodes if (cacheNodesListPromise) { - nodes = await Promise.race([orchNodesListPromise, cacheNodesListPromise]) + nodes = await Promise.any([orchNodesListPromise, cacheNodesListPromise]) } else { nodes = await orchNodesListPromise } From e0065d881f10dea44f4892672bba0b86abb06387 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Mon, 16 Oct 2023 11:22:55 -0400 Subject: [PATCH 24/34] add fallback limit --- src/client.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/client.js b/src/client.js index 639f6d6..53456a8 100644 --- a/src/client.js +++ b/src/client.js @@ -20,6 +20,7 @@ export class Saturn { * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] * @param {string} [opts.orchURL] + * @param {number} [opts.fallbackLimit] * @param {import('./storage/index.js').Storage} [opts.storage] */ constructor (opts = {}) { @@ -29,6 +30,7 @@ export class Saturn { logURL: 'https://twb3qukm2i654i3tnvx36char40aymqq.lambda-url.us-west-2.on.aws/', orchURL: 'https://orchestrator.strn.pl/nodes?maxNodes=100', authURL: 'https://fz3dyeyxmebszwhuiky7vggmsu0rlkoy.lambda-url.us-west-2.on.aws/', + fallbackLimit: 5, connectTimeout: 5_000, downloadTimeout: 0 }, opts) @@ -162,7 +164,11 @@ export class Saturn { } } + let fallbackCount = 0 for (const origin of this.nodes) { + if (fallbackCount > this.opts.fallbackLimit) { + return + } opts.url = origin.url try { yield * fetchContent() @@ -170,6 +176,7 @@ export class Saturn { } catch (err) { lastError = err } + fallbackCount += 1 } if (lastError) { From 109019be0f889a5b6df36904aa73d8bf0924c028 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Tue, 17 Oct 2023 14:25:38 -0400 Subject: [PATCH 25/34] fix: fallback bug --- src/client.js | 1 + src/utils/url.js | 2 +- test/fallback.spec.js | 10 +++++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/client.js b/src/client.js index 53456a8..ac12f0f 100644 --- a/src/client.js +++ b/src/client.js @@ -143,6 +143,7 @@ export class Saturn { const remainingBytes = byteCountCheckpoint - byteCount if (remainingBytes < chunk.length) { yield chunk.slice(remainingBytes) + byteCountCheckpoint += chunk.length - remainingBytes } } else { yield chunk diff --git a/src/utils/url.js b/src/utils/url.js index b58b7b5..5a86335 100644 --- a/src/utils/url.js +++ b/src/utils/url.js @@ -9,7 +9,7 @@ export function parseUrl (url) { // This is a temp function to resolve URLs for mock testing // See issue here: https://github.com/mswjs/msw/issues/1597 if (process.env.TESTING) { - return url.href + return url.toJSON() } return url } diff --git a/test/fallback.spec.js b/test/fallback.spec.js index d228a77..cda4e68 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -5,7 +5,7 @@ import { describe, mock, test } from 'node:test' import { Saturn } from '#src/index.js' import { concatChunks, generateNodes, getMockServer, mockJWT, mockNodesHandlers, mockOrchHandler, mockSaturnOriginHandler, MSW_SERVER_OPTS } from './test-utils.js' -const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes?maxNodes=100' +const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl/nodes' const TEST_NODES_LIST_KEY = 'saturn-nodes' const TEST_AUTH = 'https://fz3dyeyxmebszwhuiky7vggmsu0rlkoy.lambda-url.us-west-2.on.aws/' const TEST_ORIGIN_DOMAIN = 'saturn.ms' @@ -277,10 +277,14 @@ describe('Client Fallback', () => { callCount++ if (callCount === 1) { yield Buffer.from('chunk1-') - yield Buffer.from('overlap') throw new Error('First call error') } if (callCount === 2) { + yield Buffer.from('chunk1') + yield Buffer.from('-overlap') + throw new Error('Second call error') + } + if (callCount === 3) { yield Buffer.from('chunk1-overlap') yield Buffer.from('chunk2') } @@ -292,7 +296,7 @@ describe('Client Fallback', () => { buffer = await concatChunks(content) assert.deepEqual(buffer, expectedContent) - assert.strictEqual(fetchContentMock.mock.calls.length, 2) + assert.strictEqual(fetchContentMock.mock.calls.length, 3) server.close() mock.reset() From b84ce4a240fa632ef016fd25fb32cda9fc5c258b Mon Sep 17 00:00:00 2001 From: ameanasad Date: Tue, 17 Oct 2023 14:31:19 -0400 Subject: [PATCH 26/34] put eslint settings in package.json --- .eslintrc | 14 -------------- package.json | 11 +++++++++-- 2 files changed, 9 insertions(+), 16 deletions(-) delete mode 100644 .eslintrc diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index b0f6e0b..0000000 --- a/.eslintrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "plugins": [ - "jsdoc", - "promise" - ], - "extends": "ipfs", - "parserOptions": { - "sourceType": "module", - "ecmaVersion": "latest" - }, - "rules": { - "jsdoc/no-undefined-types": 1 - }, -} diff --git a/package.json b/package.json index fd92aa9..b9c49c8 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,17 @@ "webpack-cli": "^4.10.0" }, "eslintConfig": { + "plugins": [ + "jsdoc", + "promise" + ], "extends": "ipfs", "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" + "sourceType": "module", + "ecmaVersion": "latest" + }, + "rules": { + "jsdoc/no-undefined-types": 1 } }, "imports": { From 7731fe8e2b3ed2ab403bd9afb31c9aec5785dfe8 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Tue, 17 Oct 2023 15:10:34 -0400 Subject: [PATCH 27/34] add nodesListKey as static --- src/client.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.js b/src/client.js index ac12f0f..f22bc12 100644 --- a/src/client.js +++ b/src/client.js @@ -11,6 +11,7 @@ import { parseUrl, addHttpPrefix } from './utils/url.js' import { isBrowserContext } from './utils/runtime.js' export class Saturn { + static nodesListKey = 'saturn-nodes' /** * * @param {object} [opts={}] @@ -41,7 +42,6 @@ export class Saturn { this.logs = [] this.nodes = [] - this.nodesListKey = 'saturn-nodes' this.reportingLogs = process?.env?.NODE_ENV !== 'development' this.hasPerformanceAPI = isBrowserContext && self?.performance if (this.reportingLogs && this.hasPerformanceAPI) { @@ -374,7 +374,7 @@ export class Saturn { let cacheNodesListPromise if (this.storage) { - cacheNodesListPromise = this.storage.get(this.nodesListKey) + cacheNodesListPromise = this.storage.get(Saturn.nodesListKey) } origin = addHttpPrefix(origin) @@ -408,6 +408,6 @@ export class Saturn { // we always want to update from the orchestrator regardless. nodes = await orchNodesListPromise this.nodes = nodes - cacheNodesListPromise && this.storage?.set(this.nodesListKey, nodes) + cacheNodesListPromise && this.storage?.set(Saturn.nodesListKey, nodes) } } From e0fcfd87a39ceab52f12d62346c8b67a57d34045 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 18 Oct 2023 16:04:40 -0400 Subject: [PATCH 28/34] fix: resolve process in browser --- src/client.js | 2 +- src/utils/url.js | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/client.js b/src/client.js index f22bc12..255bcfb 100644 --- a/src/client.js +++ b/src/client.js @@ -408,6 +408,6 @@ export class Saturn { // we always want to update from the orchestrator regardless. nodes = await orchNodesListPromise this.nodes = nodes - cacheNodesListPromise && this.storage?.set(Saturn.nodesListKey, nodes) + this.storage?.set(Saturn.nodesListKey, nodes) } } diff --git a/src/utils/url.js b/src/utils/url.js index 5a86335..30c52c4 100644 --- a/src/utils/url.js +++ b/src/utils/url.js @@ -6,11 +6,14 @@ * @returns {URL|string} */ export function parseUrl (url) { - // This is a temp function to resolve URLs for mock testing + try { + // This is a temp function to resolve URLs for mock testing // See issue here: https://github.com/mswjs/msw/issues/1597 - if (process.env.TESTING) { - return url.toJSON() - } + if (process?.env?.TESTING) { + return url.toJSON() + } + } catch (e) {} + return url } From 489842af80f1273867a8a96c34e23a260033672d Mon Sep 17 00:00:00 2001 From: ameanasad Date: Mon, 23 Oct 2023 15:03:57 -0400 Subject: [PATCH 29/34] feat: add fetching with a race --- src/client.js | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/src/client.js b/src/client.js index cec592f..dad91cb 100644 --- a/src/client.js +++ b/src/client.js @@ -51,6 +51,103 @@ export class Saturn { this.loadNodesPromise = this._loadNodes(this.opts) } + /** + * + * @param {string} cidPath + * @param {object} [opts={}] + * @param {('car'|'raw')} [opts.format] + * @param {number} [opts.connectTimeout=5000] + * @param {number} [opts.downloadTimeout=0] + * @returns {Promise} + */ + async fetchCIDWithRace (cidPath, opts = {}) { + const [cid] = (cidPath ?? '').split('/') + CID.parse(cid) + + const jwt = await getJWT(this.opts, this.storage) + + const options = Object.assign({}, this.opts, { format: 'car', jwt }, opts) + + if (!isBrowserContext) { + options.headers = { + ...(options.headers || {}), + Authorization: 'Bearer ' + options.jwt + } + } + + const origins = options.origins + const controllers = [] + + const createFetchPromise = async (origin) => { + options.url = origin + const url = this.createRequestURL(cidPath, options) + + const controller = new AbortController() + controllers.push(controller) + const connectTimeout = setTimeout(() => { + controller.abort() + }, options.connectTimeout) + + try { + res = await fetch(parseUrl(url), { signal: controller.signal, ...options }) + clearTimeout(connectTimeout) + return { res, url, controller } + } catch (err) { + throw new Error( + `Non OK response received: ${res.status} ${res.statusText}` + ) + } + } + + const abortSlowResponses = async (res, controllers) => { + return controllers.forEach((controller) => { + if (res.controller !== controller) { + controller.abort('Request race unsuccessful') + } + }) + } + + const fetchPromises = Promise.any(origins.map((origin) => createFetchPromise(origin))) + + const log = { + startTime: new Date() + } + + let res + let controller + try { + const promiseRes = await fetchPromises + res = promiseRes.res + controller = res.controller + abortSlowResponses(res, controllers) + + const { headers } = res + log.url = promiseRes.url + log.ttfbMs = new Date() - log.startTime + log.httpStatusCode = res.status + log.cacheHit = headers.get('saturn-cache-status') === 'HIT' + log.nodeId = headers.get('saturn-node-id') + log.requestId = headers.get('saturn-transfer-id') + log.httpProtocol = headers.get('quic-status') + + if (!res.ok) { + throw new Error( + `Non OK response received: ${res.status} ${res.statusText}` + ) + } + } catch (err) { + if (!res) { + log.error = err.message + } + // Report now if error, otherwise report after download is done. + this._finalizeLog(log) + + throw err + } + + return { res, controller, log } + } + /** * * @param {string} cidPath From 9de35fc800713a31175286760c72e2e0213bf923 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Mon, 23 Oct 2023 15:59:17 -0400 Subject: [PATCH 30/34] enhancement: add backward compatibility for racing --- src/client.js | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/client.js b/src/client.js index dad91cb..3e38c05 100644 --- a/src/client.js +++ b/src/client.js @@ -12,6 +12,7 @@ import { isBrowserContext } from './utils/runtime.js' export class Saturn { static nodesListKey = 'saturn-nodes' + static defaultRaceCount = 3 /** * * @param {object} [opts={}] @@ -99,7 +100,7 @@ export class Saturn { } } - const abortSlowResponses = async (res, controllers) => { + const abortRemainingFetches = async (res, controllers) => { return controllers.forEach((controller) => { if (res.controller !== controller) { controller.abort('Request race unsuccessful') @@ -113,16 +114,14 @@ export class Saturn { startTime: new Date() } - let res - let controller + let res, url, controller try { - const promiseRes = await fetchPromises - res = promiseRes.res - controller = res.controller - abortSlowResponses(res, controllers) + ({ res, url, controller } = await fetchPromises) + + abortRemainingFetches(res, controllers) const { headers } = res - log.url = promiseRes.url + log.url = url log.ttfbMs = new Date() - log.startTime log.httpStatusCode = res.status log.cacheHit = headers.get('saturn-cache-status') === 'HIT' @@ -263,11 +262,13 @@ export class Saturn { } let fallbackCount = 0 - for (const origin of this.nodes) { + const nodes = this.nodes + for (let i = 0; i < nodes.length; i++) { if (fallbackCount > this.opts.fallbackLimit) { return } - opts.url = origin.url + const origins = nodes.slice(i, i + Saturn.defaultRaceCount) + opts.origins = origins try { yield * fetchContent() return @@ -285,14 +286,21 @@ export class Saturn { /** * * @param {string} cidPath + * @param {boolean} race * @param {object} [opts={}] * @param {('car'|'raw')} [opts.format] * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] * @returns {Promise>} */ - async * fetchContent (cidPath, opts = {}) { - const { res, controller, log } = await this.fetchCID(cidPath, opts) + async * fetchContent (cidPath, race = false, opts = {}) { + let res, controller, log + + if (race) { + ({ res, controller, log } = await this.fetchCIDWithRace(cidPath, opts)) + } else { + ({ res, controller, log } = await this.fetchCID(cidPath, opts)) + } async function * metricsIterable (itr) { log.numBytesSent = 0 @@ -336,7 +344,7 @@ export class Saturn { * @returns {URL} */ createRequestURL (cidPath, opts) { - let origin = opts.url || opts.cdnURL + let origin = opts.url || opts.origins[0] || opts.cdnURL origin = addHttpPrefix(origin) const url = new URL(`${origin}/ipfs/${cidPath}`) From c06a2b60c2dfea5bee5bfc07d86961830d3360dc Mon Sep 17 00:00:00 2001 From: ameanasad Date: Tue, 24 Oct 2023 11:44:44 -0400 Subject: [PATCH 31/34] tests and cleanup --- src/client.js | 20 ++++++++----- test/fallback.spec.js | 69 ++++++++++++++++++++++++++++++++++++++++++- test/test-utils.js | 13 ++++++-- 3 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/client.js b/src/client.js index 3e38c05..2185c85 100644 --- a/src/client.js +++ b/src/client.js @@ -164,7 +164,6 @@ export class Saturn { const options = Object.assign({}, this.opts, { format: 'car', jwt }, opts) const url = this.createRequestURL(cidPath, options) - const log = { url, startTime: new Date() @@ -218,6 +217,7 @@ export class Saturn { * @param {string} cidPath * @param {object} [opts={}] * @param {('car'|'raw')} [opts.format] + * @param {boolean} [opts.raceNodes] * @param {string} [opts.url] * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] @@ -267,8 +267,13 @@ export class Saturn { if (fallbackCount > this.opts.fallbackLimit) { return } - const origins = nodes.slice(i, i + Saturn.defaultRaceCount) - opts.origins = origins + if (opts.raceNodes) { + const origins = nodes.slice(i, i + Saturn.defaultRaceCount).map((node) => node.url) + opts.origins = origins + } else { + opts.url = nodes[i].url + } + try { yield * fetchContent() return @@ -286,17 +291,17 @@ export class Saturn { /** * * @param {string} cidPath - * @param {boolean} race * @param {object} [opts={}] * @param {('car'|'raw')} [opts.format] + * @param {boolean} [opts.raceNodes] * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] * @returns {Promise>} */ - async * fetchContent (cidPath, race = false, opts = {}) { + async * fetchContent (cidPath, opts = {}) { let res, controller, log - if (race) { + if (opts.raceNodes) { ({ res, controller, log } = await this.fetchCIDWithRace(cidPath, opts)) } else { ({ res, controller, log } = await this.fetchCID(cidPath, opts)) @@ -329,6 +334,7 @@ export class Saturn { * @param {string} cidPath * @param {object} [opts={}] * @param {('car'|'raw')} [opts.format] + * @param {boolean} [opts.raceNodes] * @param {number} [opts.connectTimeout=5000] * @param {number} [opts.downloadTimeout=0] * @returns {Promise} @@ -344,7 +350,7 @@ export class Saturn { * @returns {URL} */ createRequestURL (cidPath, opts) { - let origin = opts.url || opts.origins[0] || opts.cdnURL + let origin = opts.url || (opts.origins && opts.origins[0]) || opts.cdnURL origin = addHttpPrefix(origin) const url = new URL(`${origin}/ipfs/${cidPath}`) diff --git a/test/fallback.spec.js b/test/fallback.spec.js index cda4e68..b806eb2 100644 --- a/test/fallback.spec.js +++ b/test/fallback.spec.js @@ -128,7 +128,74 @@ describe('Client Fallback', () => { const saturn = new Saturn({ storage: mockStorage, clientKey: CLIENT_KEY, clientId: 'test' }) - const cid = saturn.fetchContentWithFallback('bafkreifjjcie6lypi6ny7amxnfftagclbuxndqonfipmb64f2km2devei4', { url: 'node1.saturn.ms' }) + const cid = saturn.fetchContentWithFallback('bafkreifjjcie6lypi6ny7amxnfftagclbuxndqonfipmb64f2km2devei4') + + const buffer = await concatChunks(cid) + const actualContent = String.fromCharCode(...buffer) + const expectedContent = 'hello world\n' + + assert.strictEqual(actualContent, expectedContent) + server.close() + mock.reset() + }) + + test('Content Fallback fetches a cid properly with race', async (t) => { + const handlers = [ + mockOrchHandler(5, TEST_DEFAULT_ORCH, 'saturn.ms'), + mockJWT(TEST_AUTH), + mockSaturnOriginHandler(TEST_ORIGIN_DOMAIN, 0, true), + ...mockNodesHandlers(5, TEST_ORIGIN_DOMAIN) + ] + const server = getMockServer(handlers) + server.listen(MSW_SERVER_OPTS) + + const expectedNodes = generateNodes(3, TEST_ORIGIN_DOMAIN) + + // Mocking storage object + const mockStorage = { + get: async (key) => expectedNodes, + set: async (key, value) => { return null } + } + t.mock.method(mockStorage, 'get') + t.mock.method(mockStorage, 'set') + + const saturn = new Saturn({ storage: mockStorage, clientKey: CLIENT_KEY, clientId: 'test' }) + // const origins = + + const cid = saturn.fetchContentWithFallback('bafkreifjjcie6lypi6ny7amxnfftagclbuxndqonfipmb64f2km2devei4', { raceNodes: true }) + + const buffer = await concatChunks(cid) + const actualContent = String.fromCharCode(...buffer) + const expectedContent = 'hello world\n' + + assert.strictEqual(actualContent, expectedContent) + server.close() + mock.reset() + }) + + test('Content Fallback with race fetches from consecutive nodes on failure', async (t) => { + const handlers = [ + mockOrchHandler(5, TEST_DEFAULT_ORCH, 'saturn.ms'), + mockJWT(TEST_AUTH), + mockSaturnOriginHandler(TEST_ORIGIN_DOMAIN, 0, true), + ...mockNodesHandlers(5, TEST_ORIGIN_DOMAIN, 2) + ] + const server = getMockServer(handlers) + server.listen(MSW_SERVER_OPTS) + + const expectedNodes = generateNodes(5, TEST_ORIGIN_DOMAIN) + + // Mocking storage object + const mockStorage = { + get: async (key) => expectedNodes, + set: async (key, value) => { return null } + } + t.mock.method(mockStorage, 'get') + t.mock.method(mockStorage, 'set') + + const saturn = new Saturn({ storage: mockStorage, clientKey: CLIENT_KEY, clientId: 'test' }) + + const cid = saturn.fetchContentWithFallback('bafkreifjjcie6lypi6ny7amxnfftagclbuxndqonfipmb64f2km2devei4', { raceNodes: true }) const buffer = await concatChunks(cid) const actualContent = String.fromCharCode(...buffer) diff --git a/test/test-utils.js b/test/test-utils.js index db26837..d51f2d3 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -123,14 +123,23 @@ export function mockJWT (authURL) { * * @param {number} count - amount of nodes to mock * @param {string} originDomain - saturn origin domain. + * @param {number} failures * @returns {RestHandler[]} */ -export function mockNodesHandlers (count, originDomain) { +export function mockNodesHandlers (count, originDomain, failures = 0) { + if (failures > count) { + throw Error('failures number cannot exceed node count') + } const nodes = generateNodes(count, originDomain) - const handlers = nodes.map((node) => { + const handlers = nodes.map((node, idx) => { const url = `${node.url}/ipfs/:cid` return rest.get(url, (req, res, ctx) => { + if (idx < failures) { + return res( + ctx.status(504) + ) + } const filepath = getFixturePath('hello.car') const fileContents = fs.readFileSync(filepath) return res( From 7249aeae33b5c504f4c48ab33d77d33857be1e8c Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 25 Oct 2023 09:17:24 -0400 Subject: [PATCH 32/34] fixes and enhancements --- src/client.js | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/client.js b/src/client.js index 31054fa..398ca14 100644 --- a/src/client.js +++ b/src/client.js @@ -80,8 +80,8 @@ export class Saturn { const controllers = [] const createFetchPromise = async (origin) => { - options.url = origin - const url = this.createRequestURL(cidPath, options) + const fetchOptions = { ...options, url: origin } + const url = this.createRequestURL(cidPath, fetchOptions) const controller = new AbortController() controllers.push(controller) @@ -100,9 +100,9 @@ export class Saturn { } } - const abortRemainingFetches = async (res, controllers) => { + const abortRemainingFetches = async (successController, controllers) => { return controllers.forEach((controller) => { - if (res.controller !== controller) { + if (successController !== controller) { controller.abort('Request race unsuccessful') } }) @@ -110,7 +110,7 @@ export class Saturn { const fetchPromises = Promise.any(origins.map((origin) => createFetchPromise(origin))) - const log = { + let log = { startTime: new Date() } @@ -118,16 +118,8 @@ export class Saturn { try { ({ res, url, controller } = await fetchPromises) - abortRemainingFetches(res, controllers) - - const { headers } = res - log.url = url - log.ttfbMs = new Date() - log.startTime - log.httpStatusCode = res.status - log.cacheHit = headers.get('saturn-cache-status') === 'HIT' - log.nodeId = headers.get('saturn-node-id') - log.requestId = headers.get('saturn-transfer-id') - log.httpProtocol = headers.get('quic-status') + abortRemainingFetches(controller, controllers) + log = Object.assign(log, this._generateLog(res, log), { url }) if (!res.ok) { throw new Error( @@ -147,6 +139,21 @@ export class Saturn { return { res, controller, log } } + _generateLog (res, log) { + const { headers } = res + log.httpStatusCode = res.status + log.cacheHit = headers.get('saturn-cache-status') === 'HIT' + log.nodeId = headers.get('saturn-node-id') + log.requestId = headers.get('saturn-transfer-id') + log.httpProtocol = headers.get('quic-status') + + if (res.ok) { + log.ttfbMs = new Date() - log.startTime + } + + return log + } + /** * * @param {string} cidPath @@ -164,7 +171,7 @@ export class Saturn { const options = Object.assign({}, this.opts, { format: 'car', jwt }, opts) const url = this.createRequestURL(cidPath, options) - const log = { + let log = { url, startTime: new Date() } @@ -186,13 +193,7 @@ export class Saturn { clearTimeout(connectTimeout) - const { headers } = res - log.ttfbMs = new Date() - log.startTime - log.httpStatusCode = res.status - log.cacheHit = headers.get('saturn-cache-status') === 'HIT' - log.nodeId = headers.get('saturn-node-id') - log.requestId = headers.get('saturn-transfer-id') - log.httpProtocol = headers.get('quic-status') + log = Object.assign(log, this._generateLog(res, log)) if (!res.ok) { throw new Error( From 57697d2c9f588e363e9a171d9086306c89e9f13a Mon Sep 17 00:00:00 2001 From: ameanasad Date: Wed, 25 Oct 2023 09:23:52 -0400 Subject: [PATCH 33/34] add typings --- src/client.js | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/client.js b/src/client.js index 398ca14..e9dc5dc 100644 --- a/src/client.js +++ b/src/client.js @@ -139,21 +139,6 @@ export class Saturn { return { res, controller, log } } - _generateLog (res, log) { - const { headers } = res - log.httpStatusCode = res.status - log.cacheHit = headers.get('saturn-cache-status') === 'HIT' - log.nodeId = headers.get('saturn-node-id') - log.requestId = headers.get('saturn-transfer-id') - log.httpProtocol = headers.get('quic-status') - - if (res.ok) { - log.ttfbMs = new Date() - log.startTime - } - - return log - } - /** * * @param {string} cidPath @@ -213,6 +198,26 @@ export class Saturn { return { res, controller, log } } + /** + * @param {Response} res + * @param {object} log + * @returns {object} + */ + _generateLog (res, log) { + const { headers } = res + log.httpStatusCode = res.status + log.cacheHit = headers.get('saturn-cache-status') === 'HIT' + log.nodeId = headers.get('saturn-node-id') + log.requestId = headers.get('saturn-transfer-id') + log.httpProtocol = headers.get('quic-status') + + if (res.ok) { + log.ttfbMs = new Date() - log.startTime + } + + return log + } + /** * * @param {string} cidPath From 7d0b34e3aa2723658cd448bfe3f7f5b6cd738b66 Mon Sep 17 00:00:00 2001 From: ameanasad Date: Thu, 26 Oct 2023 11:52:09 -0400 Subject: [PATCH 34/34] add typings --- src/client.js | 9 +++++++++ src/types.js | 14 ++++++++++++++ test/test-utils.js | 7 +------ 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 src/types.js diff --git a/src/client.js b/src/client.js index dbac4ae..6b9328f 100644 --- a/src/client.js +++ b/src/client.js @@ -11,6 +11,9 @@ import { parseUrl, addHttpPrefix } from './utils/url.js' import { isBrowserContext } from './utils/runtime.js' const MAX_NODE_WEIGHT = 100 +/** + * @typedef {import('./types.js').Node} Node + */ export class Saturn { static nodesListKey = 'saturn-nodes' @@ -488,6 +491,12 @@ export class Saturn { } } + /** + * Sorts nodes based on normalized distance and weights. Distance is prioritized for sorting. + * + * @param {Node[]} nodes + * @returns {Node[]} + */ _sortNodes (nodes) { // Determine the maximum distance for normalization const maxDistance = Math.max(...nodes.map(node => node.distance)) diff --git a/src/types.js b/src/types.js new file mode 100644 index 0000000..82bc95d --- /dev/null +++ b/src/types.js @@ -0,0 +1,14 @@ + +/** + * @module types */ + +/** + * + * @typedef {object} Node + * @property {string} ip + * @property {number} weight + * @property {number} distance + * @property {string} url + */ + +export {} diff --git a/test/test-utils.js b/test/test-utils.js index cc6419e..95b852f 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -16,12 +16,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url)) process.env.TESTING = 'true' /** - * - * @typedef {object} Node - * @property {string} ip - * @property {number} weight - * @property {number} distance - * @property {string} url + * @typedef {import('../src/types.js').Node} Node */ /**