From 837dfe9acc4d837f8531ca8e04bf38bb059b04b0 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 27 Nov 2023 18:47:48 -0600 Subject: [PATCH 01/79] Rough Working Draft --- fixup.bat | 18 + fixup.sh | 11 + package-lock.json | 2523 +++++++++++++++++++++++++++++++++++ package.json | 35 + src/bucketManager.js | 38 + src/index.js | 4 + src/objectManager.js | 174 +++ tests/bucketManager.spec.js | 56 + tests/objectManager.spec.js | 180 +++ tests/package.json | 3 + tsconfig-base.json | 25 + tsconfig-cjs.json | 8 + tsconfig.json | 8 + 13 files changed, 3083 insertions(+) create mode 100644 fixup.bat create mode 100644 fixup.sh create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/bucketManager.js create mode 100644 src/index.js create mode 100644 src/objectManager.js create mode 100644 tests/bucketManager.spec.js create mode 100644 tests/objectManager.spec.js create mode 100644 tests/package.json create mode 100644 tsconfig-base.json create mode 100644 tsconfig-cjs.json create mode 100644 tsconfig.json diff --git a/fixup.bat b/fixup.bat new file mode 100644 index 0000000..5852dc7 --- /dev/null +++ b/fixup.bat @@ -0,0 +1,18 @@ +@echo off + +set "distPath=dist" +if not exist "%distPath%" ( + mkdir "%distPath%" +) + +set "cjsPath=dist/cjs" +if not exist "%cjsPath%" ( + mkdir "%cjsPath%" +) +echo {"type": "commonjs"} > "%cjsPath%/package.json" + +set "ejsPath=dist/mjs" +if not exist "%ejsPath%" ( + mkdir "%ejsPath%" +) +echo {"type": "module"} > "%ejsPath%/package.json" diff --git a/fixup.sh b/fixup.sh new file mode 100644 index 0000000..8f6395d --- /dev/null +++ b/fixup.sh @@ -0,0 +1,11 @@ +cat >dist/cjs/package.json <dist/mjs/package.json <=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.451.0.tgz", + "integrity": "sha512-KkYSke3Pdv3MfVH/5fT528+MKjMyPKlcLcd4zQb0x6/7Bl7EHrPh1JZYjzPLHelb+UY5X0qN8+cb8iSu1eiwIQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.451.0", + "@aws-sdk/middleware-host-header": "3.451.0", + "@aws-sdk/middleware-logger": "3.451.0", + "@aws-sdk/middleware-recursion-detection": "3.451.0", + "@aws-sdk/middleware-user-agent": "3.451.0", + "@aws-sdk/region-config-resolver": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@aws-sdk/util-user-agent-browser": "3.451.0", + "@aws-sdk/util-user-agent-node": "3.451.0", + "@smithy/config-resolver": "^2.0.18", + "@smithy/fetch-http-handler": "^2.2.6", + "@smithy/hash-node": "^2.0.15", + "@smithy/invalid-dependency": "^2.0.13", + "@smithy/middleware-content-length": "^2.0.15", + "@smithy/middleware-endpoint": "^2.2.0", + "@smithy/middleware-retry": "^2.0.20", + "@smithy/middleware-serde": "^2.0.13", + "@smithy/middleware-stack": "^2.0.7", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/node-http-handler": "^2.1.9", + "@smithy/protocol-http": "^3.0.9", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.19", + "@smithy/util-defaults-mode-node": "^2.0.25", + "@smithy/util-endpoints": "^1.0.4", + "@smithy/util-retry": "^2.0.6", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.454.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.454.0.tgz", + "integrity": "sha512-0fDvr8WeB6IYO8BUCzcivWmahgGl/zDbaYfakzGnt4mrl5ztYaXE875WI6b7+oFcKMRvN+KLvwu5TtyFuNY+GQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.451.0", + "@aws-sdk/credential-provider-node": "3.451.0", + "@aws-sdk/middleware-host-header": "3.451.0", + "@aws-sdk/middleware-logger": "3.451.0", + "@aws-sdk/middleware-recursion-detection": "3.451.0", + "@aws-sdk/middleware-sdk-sts": "3.451.0", + "@aws-sdk/middleware-signing": "3.451.0", + "@aws-sdk/middleware-user-agent": "3.451.0", + "@aws-sdk/region-config-resolver": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@aws-sdk/util-user-agent-browser": "3.451.0", + "@aws-sdk/util-user-agent-node": "3.451.0", + "@smithy/config-resolver": "^2.0.18", + "@smithy/fetch-http-handler": "^2.2.6", + "@smithy/hash-node": "^2.0.15", + "@smithy/invalid-dependency": "^2.0.13", + "@smithy/middleware-content-length": "^2.0.15", + "@smithy/middleware-endpoint": "^2.2.0", + "@smithy/middleware-retry": "^2.0.20", + "@smithy/middleware-serde": "^2.0.13", + "@smithy/middleware-stack": "^2.0.7", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/node-http-handler": "^2.1.9", + "@smithy/protocol-http": "^3.0.9", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.19", + "@smithy/util-defaults-mode-node": "^2.0.25", + "@smithy/util-endpoints": "^1.0.4", + "@smithy/util-retry": "^2.0.6", + "@smithy/util-utf8": "^2.0.2", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.451.0.tgz", + "integrity": "sha512-SamWW2zHEf1ZKe3j1w0Piauryl8BQIlej0TBS18A4ACzhjhWXhCs13bO1S88LvPR5mBFXok3XOT6zPOnKDFktw==", + "dependencies": { + "@smithy/smithy-client": "^2.1.15", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.451.0.tgz", + "integrity": "sha512-9dAav7DcRgaF7xCJEQR5ER9ErXxnu/tdnVJ+UPmb1NPeIZdESv1A3lxFDEq1Fs8c4/lzAj9BpshGyJVIZwZDKg==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.451.0.tgz", + "integrity": "sha512-TySt64Ci5/ZbqFw1F9Z0FIGvYx5JSC9e6gqDnizIYd8eMnn8wFRUscRrD7pIHKfrhvVKN5h0GdYovmMO/FMCBw==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.451.0", + "@aws-sdk/credential-provider-process": "3.451.0", + "@aws-sdk/credential-provider-sso": "3.451.0", + "@aws-sdk/credential-provider-web-identity": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.451.0.tgz", + "integrity": "sha512-AEwM1WPyxUdKrKyUsKyFqqRFGU70e4qlDyrtBxJnSU9NRLZI8tfEZ67bN7fHSxBUBODgDXpMSlSvJiBLh5/3pw==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.451.0", + "@aws-sdk/credential-provider-ini": "3.451.0", + "@aws-sdk/credential-provider-process": "3.451.0", + "@aws-sdk/credential-provider-sso": "3.451.0", + "@aws-sdk/credential-provider-web-identity": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.451.0.tgz", + "integrity": "sha512-HQywSdKeD5PErcLLnZfSyCJO+6T+ZyzF+Lm/QgscSC+CbSUSIPi//s15qhBRVely/3KBV6AywxwNH+5eYgt4lQ==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.451.0.tgz", + "integrity": "sha512-Usm/N51+unOt8ID4HnQzxIjUJDrkAQ1vyTOC0gSEEJ7h64NSSPGD5yhN7il5WcErtRd3EEtT1a8/GTC5TdBctg==", + "dependencies": { + "@aws-sdk/client-sso": "3.451.0", + "@aws-sdk/token-providers": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.451.0.tgz", + "integrity": "sha512-Xtg3Qw65EfDjWNG7o2xD6sEmumPfsy3WDGjk2phEzVg8s7hcZGxf5wYwe6UY7RJvlEKrU0rFA+AMn6Hfj5oOzg==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/lib-storage": { + "version": "3.458.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.458.0.tgz", + "integrity": "sha512-wSP/sjG+SH6YHQINLePzu6fgeTo4ibqQSpnvNF52lJWJY/1lRE4qYuLQFLH2WEWG3FuDzEIsJiu3CwHm0cc6mw==", + "dependencies": { + "@smithy/abort-controller": "^2.0.1", + "@smithy/middleware-endpoint": "^2.2.0", + "@smithy/smithy-client": "^2.1.15", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.0.0" + } + }, + "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.451.0.tgz", + "integrity": "sha512-KWyZ1JGnYz2QbHuJtYTP1BVnMOfVopR8rP8dTinVb/JR5HfAYz4imICJlJUbOYRjN7wpA3PrRI8dNRjrSBjWJg==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-arn-parser": "3.310.0", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "@smithy/util-config-provider": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.451.0.tgz", + "integrity": "sha512-vwG8o2Uk6biLDlOZnqXemsO4dS2HvrprUdxyouwu6hlzLFskg8nL122butn19JqXJKgcVLuSSLzT+xwqBWy2Rg==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.451.0.tgz", + "integrity": "sha512-eOkpcC2zgAvqs1w7Yp5nsk9LBIj6qLU5kaZuZEBOiFbNKIrTnPo6dQuhgvDcKHD6Y5W/cUjSBiFMs/ROb5aoug==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@aws-crypto/crc32c": "3.0.0", + "@aws-sdk/types": "3.451.0", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.451.0.tgz", + "integrity": "sha512-j8a5jAfhWmsK99i2k8oR8zzQgXrsJtgrLxc3js6U+525mcZytoiDndkWTmD5fjJ1byU1U2E5TaPq+QJeDip05Q==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.451.0.tgz", + "integrity": "sha512-R4U2G7mybP0BMiQBJWTcB47g49F4PSXTiCsvMDp5WOEhpWvGQuO1ZIhTxCl5s5lgTSne063Os8W6KSdK2yG2TQ==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.451.0.tgz", + "integrity": "sha512-0kHrYEyVeB2QBfP6TfbI240aRtatLZtcErJbhpiNUb+CQPgEL3crIjgVE8yYiJumZ7f0jyjo8HLPkwD1/2APaw==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.451.0.tgz", + "integrity": "sha512-J6jL6gJ7orjHGM70KDRcCP7so/J2SnkN4vZ9YRLTeeZY6zvBuHDjX8GCIgSqPn/nXFXckZO8XSnA7u6+3TAT0w==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.451.0.tgz", + "integrity": "sha512-XF4Cw8HrYUwGLKOqKtWs6ss1WXoxvQUcgGLACGSqn9a0p51446NiS5671x7qJUsfBuygdKlIKcOc8pPr9a+5Ow==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-arn-parser": "3.310.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.451.0.tgz", + "integrity": "sha512-UJ6UfVUEgp0KIztxpAeelPXI5MLj9wUtUCqYeIMP7C1ZhoEMNm3G39VLkGN43dNhBf1LqjsV9jkKMZbVfYXuwg==", + "dependencies": { + "@aws-sdk/middleware-signing": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.451.0.tgz", + "integrity": "sha512-s5ZlcIoLNg1Huj4Qp06iKniE8nJt/Pj1B/fjhWc6cCPCM7XJYUCejCnRh6C5ZJoBEYodjuwZBejPc1Wh3j+znA==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.5.0", + "@smithy/util-middleware": "^2.0.6", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.451.0.tgz", + "integrity": "sha512-hDkeBUiRsvuDbvsPha0/uJHE680WDzjAOoE6ZnLBoWsw7ry+Bw1ULMj0sCmpBVrQ7Gpivi/6zbezhClVmt3ITw==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.451.0.tgz", + "integrity": "sha512-8NM/0JiKLNvT9wtAQVl1DFW0cEO7OvZyLSUBLNLTHqyvOZxKaZ8YFk7d8PL6l76LeUKRxq4NMxfZQlUIRe0eSA==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.451.0.tgz", + "integrity": "sha512-3iMf4OwzrFb4tAAmoROXaiORUk2FvSejnHIw/XHvf/jjR4EqGGF95NZP/n/MeFZMizJWVssrwS412GmoEyoqhg==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.5", + "@smithy/types": "^2.5.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.6", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.451.0.tgz", + "integrity": "sha512-qQKY7/txeNUTLyRL3WxUWEwaZ5sf76EIZgu9kLaR96cAYSxwQi/qQB3ijbfD6u7sJIA8aROMxeYK0VmRsQg0CA==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.451.0.tgz", + "integrity": "sha512-ij1L5iUbn6CwxVOT1PG4NFjsrsKN9c4N1YEM0lkl6DwmaNOscjLKGSNyj9M118vSWsOs1ZDbTwtj++h0O/BWrQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.451.0", + "@aws-sdk/middleware-logger": "3.451.0", + "@aws-sdk/middleware-recursion-detection": "3.451.0", + "@aws-sdk/middleware-user-agent": "3.451.0", + "@aws-sdk/region-config-resolver": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@aws-sdk/util-user-agent-browser": "3.451.0", + "@aws-sdk/util-user-agent-node": "3.451.0", + "@smithy/config-resolver": "^2.0.18", + "@smithy/fetch-http-handler": "^2.2.6", + "@smithy/hash-node": "^2.0.15", + "@smithy/invalid-dependency": "^2.0.13", + "@smithy/middleware-content-length": "^2.0.15", + "@smithy/middleware-endpoint": "^2.2.0", + "@smithy/middleware-retry": "^2.0.20", + "@smithy/middleware-serde": "^2.0.13", + "@smithy/middleware-stack": "^2.0.7", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/node-http-handler": "^2.1.9", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.19", + "@smithy/util-defaults-mode-node": "^2.0.25", + "@smithy/util-endpoints": "^1.0.4", + "@smithy/util-retry": "^2.0.6", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.451.0.tgz", + "integrity": "sha512-rhK+qeYwCIs+laJfWCcrYEjay2FR/9VABZJ2NRM89jV/fKqGVQR52E5DQqrI+oEIL5JHMhhnr4N4fyECMS35lw==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.310.0.tgz", + "integrity": "sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.451.0.tgz", + "integrity": "sha512-giqLGBTnRIcKkDqwU7+GQhKbtJ5Ku35cjGQIfMyOga6pwTBUbaK0xW1Sdd8sBQ1GhApscnChzI9o/R9x0368vw==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/util-endpoints": "^1.0.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.451.0.tgz", + "integrity": "sha512-Ws5mG3J0TQifH7OTcMrCTexo7HeSAc3cBgjfhS/ofzPUzVCtsyg0G7I6T7wl7vJJETix2Kst2cpOsxygPgPD9w==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/types": "^2.5.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.451.0.tgz", + "integrity": "sha512-TBzm6P+ql4mkGFAjPlO1CI+w3yUT+NulaiALjl/jNX/nnUp6HsJsVxJf4nVFQTG5KRV0iqMypcs7I3KIhH+LmA==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.310.0.tgz", + "integrity": "sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@chainsafe/is-ip": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@chainsafe/is-ip/-/is-ip-2.0.2.tgz", + "integrity": "sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA==" + }, + "node_modules/@chainsafe/netmask": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chainsafe/netmask/-/netmask-2.0.0.tgz", + "integrity": "sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1" + } + }, + "node_modules/@helia/car": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@helia/car/-/car-1.0.4.tgz", + "integrity": "sha512-HcHMC/eTRCFt3jrLkMvqKD7Og92PpNoBZTMQ9R+dOvtyIlZ2iG4zYRm2DipPdDi+OvXCqaPNg0oJxDx5fBnjRw==", + "dependencies": { + "@helia/interface": "^2.0.0", + "@ipld/car": "^5.1.1", + "@ipld/dag-pb": "^4.0.0", + "@libp2p/interfaces": "^3.3.1", + "cborg": "^4.0.3", + "interface-blockstore": "^5.0.0", + "it-map": "^3.0.3", + "multiformats": "^12.0.1", + "p-defer": "^4.0.0", + "p-queue": "^7.3.4", + "progress-events": "^1.0.0" + } + }, + "node_modules/@helia/interface": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@helia/interface/-/interface-2.1.0.tgz", + "integrity": "sha512-Z7PwuDIR0BODfSMzYcdzgdTYLsshCawAoPvGuuazvBddWSD9y82/QBmsWp6CTkyM/ziEaWbz5wERmRS+wejDLg==", + "dependencies": { + "@libp2p/interface": "^0.1.1", + "interface-blockstore": "^5.0.0", + "interface-datastore": "^8.0.0", + "interface-store": "^5.0.1", + "ipfs-bitswap": "^19.0.0", + "multiformats": "^12.0.1", + "progress-events": "^1.0.0" + } + }, + "node_modules/@helia/unixfs": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@helia/unixfs/-/unixfs-1.4.2.tgz", + "integrity": "sha512-wH/xg++d2fH16aaUJPmB08snPXTgEDwD13uRXQsYqL1A3lgS32RgSQN64Xtb7qfzZ0SzDBtJLeoZDXNJuXDzoQ==", + "dependencies": { + "@helia/interface": "^2.0.0", + "@ipld/dag-pb": "^4.0.0", + "@libp2p/interface": "^0.1.2", + "@libp2p/logger": "^3.0.2", + "@multiformats/murmur3": "^2.1.2", + "hamt-sharding": "^3.0.2", + "interface-blockstore": "^5.0.0", + "ipfs-unixfs": "^11.0.0", + "ipfs-unixfs-exporter": "^13.1.0", + "ipfs-unixfs-importer": "^15.1.0", + "it-glob": "^2.0.4", + "it-last": "^3.0.1", + "it-pipe": "^3.0.1", + "merge-options": "^3.0.4", + "multiformats": "^12.1.1", + "progress-events": "^1.0.0", + "sparse-array": "^1.3.2" + } + }, + "node_modules/@ipld/car": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@ipld/car/-/car-5.2.4.tgz", + "integrity": "sha512-YoVXE/o5HLXKi/Oqh9Nhcn423sdn9brRFKnbUid68/1D332/XINcoyCTvBluFcCw/9IeiTx+sEAV+onXZ/A4eA==", + "dependencies": { + "@ipld/dag-cbor": "^9.0.0", + "cborg": "^4.0.0", + "multiformats": "^12.1.0", + "varint": "^6.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@ipld/dag-cbor": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.6.tgz", + "integrity": "sha512-3kNab5xMppgWw6DVYx2BzmFq8t7I56AGWfp5kaU1fIPkwHVpBRglJJTYsGtbVluCi/s/q97HZM3bC+aDW4sxbQ==", + "dependencies": { + "cborg": "^4.0.0", + "multiformats": "^12.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@ipld/dag-pb": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@ipld/dag-pb/-/dag-pb-4.0.6.tgz", + "integrity": "sha512-wOij3jfDKZsb9yjhQeHp+TQy0pu1vmUkGv324xciFFZ7xGbDfAGTQW03lSA5aJ/7HBBNYgjEE0nvHmNW1Qjfag==", + "dependencies": { + "multiformats": "^12.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-0.1.6.tgz", + "integrity": "sha512-Lzc5cS/hXuoXhuAbVIxJIHLCYmfPcbU0vVgrpMoiP1Qb2Q3ETU4A46GB8s8mWXgSU6tr9RcqerUqzFYD6+OAag==", + "dependencies": { + "@multiformats/multiaddr": "^12.1.5", + "abortable-iterator": "^5.0.1", + "it-pushable": "^3.2.0", + "it-stream-types": "^2.0.1", + "multiformats": "^12.0.1", + "p-defer": "^4.0.0", + "race-signal": "^1.0.0", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/interfaces": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@libp2p/interfaces/-/interfaces-3.3.2.tgz", + "integrity": "sha512-p/M7plbrxLzuQchvNwww1Was7ZeGE2NaOFulMaZBYIihU8z3fhaV+a033OqnC/0NTX/yhfdNOG7znhYq3XoR/g==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/logger": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-3.1.0.tgz", + "integrity": "sha512-qJbJBAhxHVsRBtQSOIkSLi0lskUSFjzE+zm0QvoyxzZKSz+mX41mZLbnofPIVOVauoDQ40dXpe7WDUOq8AbiQQ==", + "dependencies": { + "@libp2p/interface": "^0.1.6", + "@multiformats/multiaddr": "^12.1.5", + "debug": "^4.3.4", + "interface-datastore": "^8.2.0", + "multiformats": "^12.0.1" + } + }, + "node_modules/@multiformats/multiaddr": { + "version": "12.1.10", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.1.10.tgz", + "integrity": "sha512-Bi3nJ/SE17+te40OLxFOpr9CvRodusZZLYZb3e5a0w9RzQcHzfKnnlfqdysLXZ2W5vXgxCUL/Uhndl51Ff2S+Q==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "@chainsafe/netmask": "^2.0.0", + "@libp2p/interface": "^0.1.1", + "dns-over-http-resolver": "3.0.0", + "multiformats": "^12.0.1", + "uint8-varint": "^2.0.1", + "uint8arrays": "^4.0.2" + } + }, + "node_modules/@multiformats/murmur3": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@multiformats/murmur3/-/murmur3-2.1.7.tgz", + "integrity": "sha512-Yf0UpAaONjed+8PTt5NM/GG4Z4Ai4m1qfT7bqevjnkwRQ12K+0jxtRomirz+VJx4PokpA2St1ZSD1iMkZTqPRQ==", + "dependencies": { + "multiformats": "^12.0.1", + "murmurhash3js-revisited": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", + "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz", + "integrity": "sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==", + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.1.tgz", + "integrity": "sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==", + "dependencies": { + "@smithy/util-base64": "^2.0.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.18.tgz", + "integrity": "sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.5", + "@smithy/types": "^2.5.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.6", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.1.tgz", + "integrity": "sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.5", + "@smithy/property-provider": "^2.0.14", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.13.tgz", + "integrity": "sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.5.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.13.tgz", + "integrity": "sha512-OJ/2g/VxkzA+mYZxV102oX3CsiE+igTSmqq/ir3oEVG2kSIdRC00ryttj/lmL14W06ExNi0ysmfLxQkL8XrAZQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.13.tgz", + "integrity": "sha512-2BI1CbnYuEvAYoWSeWJtPNygbIKiWeSLxCmDLnyM6wQV32Of7VptiQlaFXPxXp4zqn/rs3ocZ/T29rxE4s4Gsg==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.13.tgz", + "integrity": "sha512-7NbFwPafb924elFxCBDvm48jy/DeSrpFbFQN0uN2ThuY5HrEeubikS0t7WMva4Z4EnRoivpbuT0scb9vUIJKoA==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.13.tgz", + "integrity": "sha512-j0yFd5UfftM+ia9dxLRbheJDCkCZBHpcEzCsPO8BxVOTbdcX/auVJCv6ov/yvpCKsf4Hv3mOqi0Is1YogM2g3Q==", + "dependencies": { + "@smithy/eventstream-codec": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.6.tgz", + "integrity": "sha512-PStY3XO1Ksjwn3wMKye5U6m6zxXpXrXZYqLy/IeCbh3nM9QB3Jgw/B0PUSLUWKdXg4U8qgEu300e3ZoBvZLsDg==", + "dependencies": { + "@smithy/protocol-http": "^3.0.9", + "@smithy/querystring-builder": "^2.0.13", + "@smithy/types": "^2.5.0", + "@smithy/util-base64": "^2.0.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.0.14.tgz", + "integrity": "sha512-yWdghyPJIEqLYsaE7YVgd3YhM7jN4Pv6eJQvTomnMsz5K2qRBlpjUx3T9fKlElp1qdeQ7DNc3sAat4i9CUBO7Q==", + "dependencies": { + "@smithy/chunked-blob-reader": "^2.0.0", + "@smithy/chunked-blob-reader-native": "^2.0.1", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.15.tgz", + "integrity": "sha512-t/qjEJZu/G46A22PAk1k/IiJZT4ncRkG5GOCNWN9HPPy5rCcSZUbh7gwp7CGKgJJ7ATMMg+0Td7i9o1lQTwOfQ==", + "dependencies": { + "@smithy/types": "^2.5.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.0.15.tgz", + "integrity": "sha512-ZZ6kC/pHt5Dc2goXIIyC8uA7A4GUMSzdCynAabnZ3CSSaV6ctP8mlvVkqjPph0O3XzHlx/80gdLrNqi1GDPUsA==", + "dependencies": { + "@smithy/types": "^2.5.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.13.tgz", + "integrity": "sha512-XsGYhVhvEikX1Yz0kyIoLssJf2Rs6E0U2w2YuKdT4jSra5A/g8V2oLROC1s56NldbgnpesTYB2z55KCHHbKyjw==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.0.15.tgz", + "integrity": "sha512-pAZaokib56XvhU0t/R9vAcr3L3bMhIakhF25X7EMSQ7LAURiLfce/tgON8I3x/dIbnZUyeRi8f2cx2azu6ATew==", + "dependencies": { + "@smithy/types": "^2.5.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.15.tgz", + "integrity": "sha512-xH4kRBw01gJgWiU+/mNTrnyFXeozpZHw39gLb3JKGsFDVmSrJZ8/tRqu27tU/ki1gKkxr2wApu+dEYjI3QwV1Q==", + "dependencies": { + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.2.0.tgz", + "integrity": "sha512-tddRmaig5URk2106PVMiNX6mc5BnKIKajHHDxb7K0J5MLdcuQluHMGnjkv18iY9s9O0tF+gAcPd/pDXA5L9DZw==", + "dependencies": { + "@smithy/middleware-serde": "^2.0.13", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/shared-ini-file-loader": "^2.2.4", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "@smithy/util-middleware": "^2.0.6", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.20.tgz", + "integrity": "sha512-X2yrF/SHDk2WDd8LflRNS955rlzQ9daz9UWSp15wW8KtzoTXg3bhHM78HbK1cjr48/FWERSJKh9AvRUUGlIawg==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.5", + "@smithy/protocol-http": "^3.0.9", + "@smithy/service-error-classification": "^2.0.6", + "@smithy/types": "^2.5.0", + "@smithy/util-middleware": "^2.0.6", + "@smithy/util-retry": "^2.0.6", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.13.tgz", + "integrity": "sha512-tBGbeXw+XsE6pPr4UaXOh+UIcXARZeiA8bKJWxk2IjJcD1icVLhBSUQH9myCIZLNNzJIH36SDjUX8Wqk4xJCJg==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.7.tgz", + "integrity": "sha512-L1KLAAWkXbGx1t2jjCI/mDJ2dDNq+rp4/ifr/HcC6FHngxho5O7A5bQLpKHGlkfATH6fUnOEx0VICEVFA4sUzw==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.5.tgz", + "integrity": "sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==", + "dependencies": { + "@smithy/property-provider": "^2.0.14", + "@smithy/shared-ini-file-loader": "^2.2.4", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.9.tgz", + "integrity": "sha512-+K0q3SlNcocmo9OZj+fz67gY4lwhOCvIJxVbo/xH+hfWObvaxrMTx7JEzzXcluK0thnnLz++K3Qe7Z/8MDUreA==", + "dependencies": { + "@smithy/abort-controller": "^2.0.13", + "@smithy/protocol-http": "^3.0.9", + "@smithy/querystring-builder": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.14.tgz", + "integrity": "sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.9.tgz", + "integrity": "sha512-U1wl+FhYu4/BC+rjwh1lg2gcJChQhytiNQSggREgQ9G2FzmoK9sACBZvx7thyWMvRyHQTE22mO2d5UM8gMKDBg==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.13.tgz", + "integrity": "sha512-JhXKwp3JtsFUe96XLHy/nUPEbaXqn6r7xE4sNaH8bxEyytE5q1fwt0ew/Ke6+vIC7gP87HCHgQpJHg1X1jN2Fw==", + "dependencies": { + "@smithy/types": "^2.5.0", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.13.tgz", + "integrity": "sha512-TEiT6o8CPZVxJ44Rly/rrsATTQsE+b/nyBVzsYn2sa75xAaZcurNxsFd8z1haoUysONiyex24JMHoJY6iCfLdA==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.6.tgz", + "integrity": "sha512-fCQ36frtYra2fqY2/DV8+3/z2d0VB/1D1hXbjRcM5wkxTToxq6xHbIY/NGGY6v4carskMyG8FHACxgxturJ9Pg==", + "dependencies": { + "@smithy/types": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.4.tgz", + "integrity": "sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.15.tgz", + "integrity": "sha512-SRTEJSEhQYVlBKIIdZ9SZpqW+KFqxqcNnEcBX+8xkDdWx+DItme9VcCDkdN32yTIrICC+irUufnUdV7mmHPjoA==", + "dependencies": { + "@smithy/eventstream-codec": "^2.0.13", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.5.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.6", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.15.tgz", + "integrity": "sha512-rngZcQu7Jvs9UbHihK1EI67RMPuzkc3CJmu4MBgB7D7yBnMGuFR86tq5rqHfL2gAkNnMelBN/8kzQVvZjNKefQ==", + "dependencies": { + "@smithy/middleware-stack": "^2.0.7", + "@smithy/types": "^2.5.0", + "@smithy/util-stream": "^2.0.20", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", + "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.13.tgz", + "integrity": "sha512-okWx2P/d9jcTsZWTVNnRMpFOE7fMkzloSFyM53fA7nLKJQObxM2T4JlZ5KitKKuXq7pxon9J6SF2kCwtdflIrA==", + "dependencies": { + "@smithy/querystring-parser": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.1.tgz", + "integrity": "sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "dependencies": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.19.tgz", + "integrity": "sha512-VHP8xdFR7/orpiABJwgoTB0t8Zhhwpf93gXhNfUBiwAE9O0rvsv7LwpQYjgvbOUDDO8JfIYQB2GYJNkqqGWsXw==", + "dependencies": { + "@smithy/property-provider": "^2.0.14", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.0.25", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.25.tgz", + "integrity": "sha512-jkmep6/JyWmn2ADw9VULDeGbugR4N/FJCKOt+gYyVswmN1BJOfzF2umaYxQ1HhQDvna3kzm1Dbo1qIfBW4iuHA==", + "dependencies": { + "@smithy/config-resolver": "^2.0.18", + "@smithy/credential-provider-imds": "^2.1.1", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/property-provider": "^2.0.14", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.4.tgz", + "integrity": "sha512-FPry8j1xye5yzrdnf4xKUXVnkQErxdN7bUIaqC0OFoGsv2NfD9b2UUMuZSSt+pr9a8XWAqj0HoyVNUfPiZ/PvQ==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.5", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.6.tgz", + "integrity": "sha512-7W4uuwBvSLgKoLC1x4LfeArCVcbuHdtVaC4g30kKsD1erfICyQ45+tFhhs/dZNeQg+w392fhunCm/+oCcb6BSA==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.6.tgz", + "integrity": "sha512-PSO41FofOBmyhPQJwBQJ6mVlaD7Sp9Uff9aBbnfBJ9eqXOE/obrqQjn0PNdkfdvViiPXl49BINfnGcFtSP4kYw==", + "dependencies": { + "@smithy/service-error-classification": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.20.tgz", + "integrity": "sha512-tT8VASuD8jJu0yjHEMTCPt1o5E3FVzgdsxK6FQLAjXKqVv5V8InCnc0EOsYrijgspbfDqdAJg7r0o2sySfcHVg==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.2.6", + "@smithy/node-http-handler": "^2.1.9", + "@smithy/types": "^2.5.0", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.2.tgz", + "integrity": "sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.13.tgz", + "integrity": "sha512-YovIQatiuM7giEsRFotqJa2i3EbU2EE3PgtpXgtLgpx5rXiZMAwPxXYDFVFhuO0lbqvc/Zx4n+ZIisXOHPSqyg==", + "dependencies": { + "@smithy/abort-controller": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@vascosantos/moving-average": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vascosantos/moving-average/-/moving-average-1.1.0.tgz", + "integrity": "sha512-MVEJ4vWAPNbrGLjz7ITnHYg+YXZ6ijAqtH5/cHwSoCpbvuJ98aLXwFfPKAUfZpJMQR5uXB58UJajbY130IRF/w==" + }, + "node_modules/abortable-iterator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/abortable-iterator/-/abortable-iterator-5.0.1.tgz", + "integrity": "sha512-hlZ5Z8UwqrKsJcelVPEqDduZowJPBQJ9ZhBC2FXpja3lXy8X6MoI5uMzIgmrA8+3jcVnp8TF/tx+IBBqYJNUrg==", + "dependencies": { + "get-iterator": "^2.0.0", + "it-stream-types": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/any-signal": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/any-signal/-/any-signal-4.1.1.tgz", + "integrity": "sha512-iADenERppdC+A2YKbOXXB2WUeABLaM6qnpZ70kZbPZ1cZMMJ7eF+3CaYm+/PhBizgkzlvssC7QuHS30oOiQYWA==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "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==" + }, + "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/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/blockstore-core": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/blockstore-core/-/blockstore-core-4.3.4.tgz", + "integrity": "sha512-JecnNXiDPEdeS9AeFWO0PUKKmmRMW0D+ggUb4lgK0XMDOUAWmhkaiDPhgBjEKrlya0n60XOjcgBYhg18CUqOFw==", + "dependencies": { + "@libp2p/logger": "^3.0.0", + "err-code": "^3.0.1", + "interface-blockstore": "^5.0.0", + "interface-store": "^5.0.0", + "it-drain": "^3.0.1", + "it-filter": "^3.0.0", + "it-merge": "^3.0.1", + "it-pushable": "^3.0.0", + "multiformats": "^12.0.1", + "uint8arrays": "^4.0.2" + } + }, + "node_modules/blockstore-fs": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/blockstore-fs/-/blockstore-fs-1.1.6.tgz", + "integrity": "sha512-7tmntHl7icxusYQ9tDSOYEQKO1QXhZ45AqchfIRvB9ihUpxTTqMx2RRXPN94Fr3pc6PWJ+HwwxeGJobxAnm1cQ==", + "dependencies": { + "blockstore-core": "^4.0.0", + "fast-write-atomic": "^0.2.0", + "interface-blockstore": "^5.0.0", + "interface-store": "^5.0.0", + "it-glob": "^2.0.1", + "it-map": "^3.0.1", + "it-parallel-batch": "^3.0.0", + "multiformats": "^12.0.1" + } + }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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.2.1" + } + }, + "node_modules/cborg": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/cborg/-/cborg-4.0.5.tgz", + "integrity": "sha512-q8TAjprr8pn9Fp53rOIGp/UFDdFY6os2Nq62YogPSIzczJD9M6g2b6igxMkpCiZZKJ0kn/KzDLDvG+EqBIEeCg==", + "bin": { + "cborg": "lib/bin.js" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dns-over-http-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-3.0.0.tgz", + "integrity": "sha512-5+BI+B7n8LKhNaEZBYErr+CBd9t5nYtjunByLhrLGtZ+i3TRgiU8yE87pCjEBu2KOwNsD9ljpSXEbZ4S8xih5g==", + "dependencies": { + "debug": "^4.3.4", + "receptacle": "^1.3.2" + } + }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-write-atomic": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fast-write-atomic/-/fast-write-atomic-0.2.1.tgz", + "integrity": "sha512-WvJe06IfNYlr+6cO3uQkdKdy3Cb1LlCJSF8zRs2eT8yuhdbSlR9nIt+TgQ92RUxiRrQm+/S7RARnMfCs5iuAjw==" + }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/get-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.1.tgz", + "integrity": "sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg==" + }, + "node_modules/hamt-sharding": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/hamt-sharding/-/hamt-sharding-3.0.2.tgz", + "integrity": "sha512-f0DzBD2tSmLFdFsLAvOflIBqFPjerbA7BfmwO8mVho/5hXwgyyYhv+ijIzidQf/DpDX3bRjAQvhGoBFj+DBvPw==", + "dependencies": { + "sparse-array": "^1.3.1", + "uint8arrays": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "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/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/interface-blockstore": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/interface-blockstore/-/interface-blockstore-5.2.6.tgz", + "integrity": "sha512-Cp6+QPY81kunaxQV/j5BWk3uSW6kpos8dLveJ3P2lbmA/yX2XeMwVlNOnQyGg0evhp1qmMLhf6eCswNiSMW3CA==", + "dependencies": { + "interface-store": "^5.0.0", + "multiformats": "^12.0.1" + } + }, + "node_modules/interface-datastore": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/interface-datastore/-/interface-datastore-8.2.5.tgz", + "integrity": "sha512-kvLGJMz3RPoJF/g5DbEvfWWempIiSBLVMf63b0PBsziVcSkj0ofzHYI86v8vqpGedkQ81DtPCUKyvX9W7zWvrQ==", + "dependencies": { + "interface-store": "^5.0.0", + "nanoid": "^4.0.0", + "uint8arrays": "^4.0.2" + } + }, + "node_modules/interface-store": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-5.1.4.tgz", + "integrity": "sha512-SI2co5IAxAybBc9egRM2bXvHOa1RPh5SQQkO6di6t/aX92RbtzP4t8raB0l3GTzQmJADaBbzz8Tfa1QLgfMdGQ==" + }, + "node_modules/ipfs-bitswap": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/ipfs-bitswap/-/ipfs-bitswap-19.0.2.tgz", + "integrity": "sha512-pm0EcnTAwMMkCmdXHw/a7uPXzQ4I/pxVFiQZ6Ebg/R64XxAky/bCOJRzmqsgqH0+prH2bXAOgzS0mOZdL+zFSw==", + "dependencies": { + "@libp2p/interface": "^0.1.1", + "@libp2p/logger": "^3.0.1", + "@multiformats/multiaddr": "^12.1.0", + "@vascosantos/moving-average": "^1.1.0", + "any-signal": "^4.1.1", + "blockstore-core": "^4.0.0", + "events": "^3.3.0", + "interface-blockstore": "^5.0.0", + "interface-store": "^5.1.0", + "it-foreach": "^2.0.2", + "it-length-prefixed": "^9.0.0", + "it-map": "^3.0.2", + "it-pipe": "^3.0.1", + "it-take": "^3.0.1", + "just-debounce-it": "^3.0.1", + "multiformats": "^12.0.1", + "progress-events": "^1.0.0", + "protons-runtime": "^5.0.0", + "timeout-abort-controller": "^3.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.2", + "varint": "^6.0.0", + "varint-decoder": "^1.0.0" + } + }, + "node_modules/ipfs-unixfs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/ipfs-unixfs/-/ipfs-unixfs-11.1.0.tgz", + "integrity": "sha512-Lq37nKLJOpRFjx3rcg3y+ZwUxBX7jluKfIt5UPp6wb1L3dP0sj1yaLR0Yg2CdGYvHWyUpZD1iTnT8upL0ToDOw==", + "dependencies": { + "err-code": "^3.0.1", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/ipfs-unixfs-exporter": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/ipfs-unixfs-exporter/-/ipfs-unixfs-exporter-13.2.2.tgz", + "integrity": "sha512-poCxSte+SdQzuPc/Sm+gx/86VJu+IEsW6/Cfkq29yEUZDG8QuCvTkvuqAysKAYuN40aR9SjYqwYFRW/hsvspSw==", + "dependencies": { + "@ipld/dag-cbor": "^9.0.0", + "@ipld/dag-pb": "^4.0.0", + "@multiformats/murmur3": "^2.0.0", + "err-code": "^3.0.1", + "hamt-sharding": "^3.0.0", + "interface-blockstore": "^5.0.0", + "ipfs-unixfs": "^11.0.0", + "it-filter": "^3.0.2", + "it-last": "^3.0.2", + "it-map": "^3.0.3", + "it-parallel": "^3.0.0", + "it-pipe": "^3.0.1", + "it-pushable": "^3.1.0", + "multiformats": "^12.0.1", + "p-queue": "^7.3.0", + "progress-events": "^1.0.0", + "uint8arrays": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/ipfs-unixfs-importer": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/ipfs-unixfs-importer/-/ipfs-unixfs-importer-15.2.1.tgz", + "integrity": "sha512-9ArBh7Xfz8gUSe8pq9c9ilBOXd1bbT3L+4xnI6w/usWLwnNT14p8WbFZjDD0MO1/PrD0PTUZuHNDS2l4EO+wPg==", + "dependencies": { + "@ipld/dag-pb": "^4.0.0", + "@multiformats/murmur3": "^2.0.0", + "err-code": "^3.0.1", + "hamt-sharding": "^3.0.0", + "interface-blockstore": "^5.0.0", + "interface-store": "^5.0.1", + "ipfs-unixfs": "^11.0.0", + "it-all": "^3.0.2", + "it-batch": "^3.0.2", + "it-first": "^3.0.2", + "it-parallel-batch": "^3.0.1", + "multiformats": "^12.0.1", + "progress-events": "^1.0.0", + "rabin-wasm": "^0.1.4", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/it-all": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-all/-/it-all-3.0.4.tgz", + "integrity": "sha512-UMiy0i9DqCHBdWvMbzdYvVGa5/w4t1cc4nchpbnjdLhklglv8mQeEYnii0gvKESJuL1zV32Cqdb33R6/GPfxpQ==" + }, + "node_modules/it-batch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-batch/-/it-batch-3.0.4.tgz", + "integrity": "sha512-WRu2mqOYIs+T9k7+yxSK9VJdk0UE4R0jKQsWQcti5c6vhb1FhjC2+yCB5XBrctQ9edNfCMU/wVzdDj8qSwimbA==" + }, + "node_modules/it-drain": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/it-drain/-/it-drain-3.0.5.tgz", + "integrity": "sha512-qYFe4SWdvs9oJGUY5bSjvmiLUMLzFEODNOQUdYdCIkuIgQF+AUB2INhM4yQ09buJ2rhHKDFxvTD/+yUq6qg0XA==" + }, + "node_modules/it-filter": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-filter/-/it-filter-3.0.4.tgz", + "integrity": "sha512-e0sz+st4sudK/zH6GZ/gRTRP8A/ADuJFCYDmRgMbZvR79y5+v4ZXav850bBZk5wL9zXaYZFxS1v/6Qi+Vjwh5g==", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, + "node_modules/it-first": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-first/-/it-first-3.0.4.tgz", + "integrity": "sha512-FtQl84iTNxN5EItP/JgL28V2rzNMkCzTUlNoj41eVdfix2z1DBuLnBqZ0hzYhGGa1rMpbQf0M7CQSA2adlrLJg==" + }, + "node_modules/it-foreach": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/it-foreach/-/it-foreach-2.0.6.tgz", + "integrity": "sha512-OVosBHJsdXpAyeFlCbe3IGZia+65UykyAznakNsKXK+b99dbhuu/mOnXxTadDEo1GWhKx+WA8RNanKkMf07zQw==", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, + "node_modules/it-glob": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/it-glob/-/it-glob-2.0.6.tgz", + "integrity": "sha512-4C6ccz4nhqrq7yZMzBr3MsKhyL+rlnLXIPceyGG6ogl3Lx3eeWMv1RtlySJwFi6q+jVcPyTpeYt/xftwI2JEQQ==", + "dependencies": { + "minimatch": "^9.0.0" + } + }, + "node_modules/it-last": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-last/-/it-last-3.0.4.tgz", + "integrity": "sha512-Ns+KTsQWhs0KCvfv5X3Ck3lpoYxHcp4zUp4d+AOdmC8cXXqDuoZqAjfWhgCbxJubXyIYWdfE2nRcfWqgvZHP8Q==" + }, + "node_modules/it-length-prefixed": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-9.0.3.tgz", + "integrity": "sha512-YAu424ceYpXctxtjcLOqn7vJq082CaoP8J646ZusYISfQc3bpzQErgTUqMFj81V262KG2W9/YMBHsy6A/4yvmg==", + "dependencies": { + "err-code": "^3.0.1", + "it-reader": "^6.0.1", + "it-stream-types": "^2.0.1", + "uint8-varint": "^2.0.1", + "uint8arraylist": "^2.0.0", + "uint8arrays": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-map": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/it-map/-/it-map-3.0.5.tgz", + "integrity": "sha512-hB0TDXo/h4KSJJDSRLgAPmDroiXP6Fx1ck4Bzl3US9hHfZweTKsuiP0y4gXuTMcJlS6vj0bb+f70rhkD47ZA3w==", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, + "node_modules/it-merge": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/it-merge/-/it-merge-3.0.3.tgz", + "integrity": "sha512-FYVU15KC5pb/GQX1Ims+lee8d4pdqGVCpWr0lkNj8o4xuNo7jY71k6GuEiWdP+T7W1bJqewSxX5yoTy5yZpRVA==", + "dependencies": { + "it-pushable": "^3.2.0" + } + }, + "node_modules/it-parallel": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/it-parallel/-/it-parallel-3.0.6.tgz", + "integrity": "sha512-i7UM7I9LTkDJw3YIqXHFAPZX6CWYzGc+X3irdNrVExI4vPazrJdI7t5OqrSVN8CONXLAunCiqaSV/zZRbQR56A==", + "dependencies": { + "p-defer": "^4.0.0" + } + }, + "node_modules/it-parallel-batch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-parallel-batch/-/it-parallel-batch-3.0.4.tgz", + "integrity": "sha512-O1omh8ss8+UtXiMjE+8kM5C20DT0Ma4VtKVfrSHOJU0UHZ+iWBXarabzPYEp+WiuQmrv+klDPPlTZ9KaLN9xOA==", + "dependencies": { + "it-batch": "^3.0.0" + } + }, + "node_modules/it-peekable": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/it-peekable/-/it-peekable-3.0.3.tgz", + "integrity": "sha512-Wx21JX/rMzTEl9flx3DGHuPV1KQFGOl8uoKfQtmZHgPQtGb89eQ6RyVd82h3HuP9Ghpt0WgBDlmmdWeHXqyx7w==" + }, + "node_modules/it-pipe": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/it-pipe/-/it-pipe-3.0.1.tgz", + "integrity": "sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==", + "dependencies": { + "it-merge": "^3.0.0", + "it-pushable": "^3.1.2", + "it-stream-types": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-pushable": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.2.3.tgz", + "integrity": "sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==", + "dependencies": { + "p-defer": "^4.0.0" + } + }, + "node_modules/it-reader": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/it-reader/-/it-reader-6.0.4.tgz", + "integrity": "sha512-XCWifEcNFFjjBHtor4Sfaj8rcpt+FkY0L6WdhD578SCDhV4VUm7fCkF3dv5a+fTcfQqvN9BsxBTvWbYO6iCjTg==", + "dependencies": { + "it-stream-types": "^2.0.1", + "uint8arraylist": "^2.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-stream-types": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/it-stream-types/-/it-stream-types-2.0.1.tgz", + "integrity": "sha512-6DmOs5r7ERDbvS4q8yLKENcj6Yecr7QQTqWApbZdfAUTEC947d+PEha7PCqhm//9oxaLYL7TWRekwhoXl2s6fg==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-take": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-take/-/it-take-3.0.4.tgz", + "integrity": "sha512-RG8HDjAZlvkzz5Nav4xq6gK5zNT+Ff1UTIf+CrSJW8nIl6N1FpBH5e7clUshiCn+MmmMoSdIEpw4UaTolszxhA==" + }, + "node_modules/just-debounce-it": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/just-debounce-it/-/just-debounce-it-3.2.0.tgz", + "integrity": "sha512-WXzwLL0745uNuedrCsCs3rpmfD6DBaf7uuVwaq98/8dafURfgQaBsSpjiPp5+CW6Vjltwy9cOGI6qE71b3T8iQ==" + }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==" + }, + "node_modules/multiformats": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.1.3.tgz", + "integrity": "sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/murmurhash3js-revisited": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", + "integrity": "sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/nanoid": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz", + "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "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/p-defer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.0.tgz", + "integrity": "sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.4.1.tgz", + "integrity": "sha512-vRpMXmIkYF2/1hLBKisKeVYJZ8S2tZ0zEAmIJgdVKP2nq0nh4qCdf8bgw+ZgKrkh71AOCaqzwbJJk1WtdcF3VA==", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^5.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prettier": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/progress-events": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/progress-events/-/progress-events-1.0.0.tgz", + "integrity": "sha512-zIB6QDrSbPfRg+33FZalluFIowkbV5Xh1xSuetjG+rlC5he6u2dc6VQJ0TbMdlN3R1RHdpOqxEFMKTnQ+itUwA==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/protons-runtime": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/protons-runtime/-/protons-runtime-5.2.0.tgz", + "integrity": "sha512-jL3VSbXllgm17zurKQ/z+Ath0w+4BknJ+l/NLocfjAB8hbeASOZTNtb7zK3nDsKq2pHK9YFumNQvpkZ6gFfWhA==", + "dependencies": { + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/rabin-wasm": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/rabin-wasm/-/rabin-wasm-0.1.5.tgz", + "integrity": "sha512-uWgQTo7pim1Rnj5TuWcCewRDTf0PEFTSlaUjWP4eY9EbLV9em08v89oCz/WO+wRxpYuO36XEHp4wgYQnAgOHzA==", + "dependencies": { + "@assemblyscript/loader": "^0.9.4", + "bl": "^5.0.0", + "debug": "^4.3.1", + "minimist": "^1.2.5", + "node-fetch": "^2.6.1", + "readable-stream": "^3.6.0" + }, + "bin": { + "rabin-wasm": "cli/bin.js" + } + }, + "node_modules/race-signal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/race-signal/-/race-signal-1.0.2.tgz", + "integrity": "sha512-o3xNv0iTcIDQCXFlF6fPAMEBRjFxssgGoRqLbg06m+AdzEXXLUmoNOoUHTVz2NoBI8hHwKFKoC6IqyNtWr2bww==" + }, + "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/receptacle": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/receptacle/-/receptacle-1.3.2.tgz", + "integrity": "sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/retimer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/retimer/-/retimer-3.0.0.tgz", + "integrity": "sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==" + }, + "node_modules/run-script-os": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", + "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==", + "dev": true, + "bin": { + "run-os": "index.js", + "run-script-os": "index.js" + } + }, + "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==", + "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/sparse-array": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/sparse-array/-/sparse-array-1.3.2.tgz", + "integrity": "sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==" + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "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/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "node_modules/timeout-abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz", + "integrity": "sha512-O3e+2B8BKrQxU2YRyEjC/2yFdb33slI22WRdUaDx6rvysfi9anloNZyR2q0l6LnePo5qH7gSM7uZtvvwZbc2yA==", + "dependencies": { + "retimer": "^3.0.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/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/typescript": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uint8-varint": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uint8-varint/-/uint8-varint-2.0.2.tgz", + "integrity": "sha512-LZXmBT0jiHR7J4oKM1GUhtdLFW1yPauzI8NjJlotXn92TprO9u8VMvEVR4QMk8xhUVUd+2fqfU2/kGbVHYSSWw==", + "dependencies": { + "uint8arraylist": "^2.0.0", + "uint8arrays": "^4.0.2" + } + }, + "node_modules/uint8arraylist": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.3.tgz", + "integrity": "sha512-oEVZr4/GrH87K0kjNce6z8pSCzLEPqHNLNR5sj8cJOySrTP8Vb/pMIbZKLJGhQKxm1TiZ31atNrpn820Pyqpow==", + "dependencies": { + "uint8arrays": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/uint8arrays": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-4.0.6.tgz", + "integrity": "sha512-4ZesjQhqOU2Ip6GPReIwN60wRxIupavL8T0Iy36BBHr2qyMrNxsPJvr7vpS4eFt8F8kSguWUPad6ZM9izs/vyw==", + "dependencies": { + "multiformats": "^12.0.1" + } + }, + "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/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" + }, + "node_modules/varint-decoder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/varint-decoder/-/varint-decoder-1.0.0.tgz", + "integrity": "sha512-JkOvdztASWGUAsXshCFHrB9f6AgR2Q8W08CEyJ+43b1qtFocmI8Sp1R/M0E/hDOY2FzVIqk63tOYLgDYWuJ7IQ==", + "dependencies": { + "varint": "^5.0.0" + }, + "engines": { + "node": ">=4.0.0", + "npm": ">=3.0.0" + } + }, + "node_modules/varint-decoder/node_modules/varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==" + }, + "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/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" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6cfa90e --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "filebase-sdk", + "version": "1.0.0", + "description": "", + "type": "module", + "main": "dist/cjs/index.js", + "module": "dist/mjs/index.mjs", + "exports": { + ".": { + "require": "./dist/mjs/index.cjs", + "import": "./dist/cjs/index.mjs" + } + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "run-script-os", + "build:win32": "rmdir /s /q dist && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && .\\fixup.bat", + "build:nix": "rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup.sh" + }, + "keywords": [], + "author": "", + "devDependencies": { + "prettier": "^3.1.0", + "run-script-os": "^1.1.6", + "typescript": "5.3.2" + }, + "dependencies": { + "@aws-sdk/client-s3": "3.454.0", + "@aws-sdk/lib-storage": "3.458.0", + "@helia/car": "1.0.4", + "@helia/unixfs": "1.4.2", + "blockstore-fs": "1.1.6", + "uuid": "9.0.1" + } +} diff --git a/src/bucketManager.js b/src/bucketManager.js new file mode 100644 index 0000000..569b63f --- /dev/null +++ b/src/bucketManager.js @@ -0,0 +1,38 @@ +import { + CreateBucketCommand, + DeleteBucketCommand, + ListBucketsCommand, + S3Client, +} from "@aws-sdk/client-s3"; +export default class BucketManager { + #client; + #defaultBucket; + + constructor(S3ClientConfig) { + // Login to S3 Endpoint + this.#client = new S3Client(S3ClientConfig); + } + + async create(name) { + const command = new CreateBucketCommand({ + Bucket: name, + }); + + return await this.#client.send(command); + } + + async list() { + const command = new ListBucketsCommand({}), + { Buckets } = await this.#client.send(command); + + return Buckets; + } + + async delete(name = this.#defaultBucket) { + const command = new DeleteBucketCommand({ + Bucket: name, + }); + + return await this.#client.send(command); + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..f77de2a --- /dev/null +++ b/src/index.js @@ -0,0 +1,4 @@ +import BucketManager from "./bucketManager.js"; +import ObjectManager from "./objectManager.js"; + +export { BucketManager, ObjectManager }; diff --git a/src/objectManager.js b/src/objectManager.js new file mode 100644 index 0000000..adf16f7 --- /dev/null +++ b/src/objectManager.js @@ -0,0 +1,174 @@ +import { + CopyObjectCommand, + DeleteObjectCommand, + GetObjectCommand, + HeadObjectCommand, + ListObjectsV2Command, + S3Client, +} from "@aws-sdk/client-s3"; +import { Upload } from "@aws-sdk/lib-storage"; +import { FsBlockstore } from "blockstore-fs"; +import { unixfs } from "@helia/unixfs"; +import { v4 as uuidv4 } from "uuid"; +import path from "node:path"; +import os from "node:os"; +import { mkdir, rm } from "node:fs/promises"; +import { car } from "@helia/car"; + +export default class ObjectManager { + #client; + #defaultBucket; + #maxConcurrentUploads = 4; + + constructor( + S3ClientConfig, + defaultBucket, + options = { + maxConcurrentUploads: 4, + }, + ) { + // Login to S3 Endpoint + this.#client = new S3Client(S3ClientConfig); + this.#defaultBucket = defaultBucket; + + if (options?.maxConcurrentUploads) { + this.#maxConcurrentUploads = Number(options.maxConcurrentUploads); + } + } + + async upload(key, source, bucket = this.#defaultBucket) { + // Setup Upload Options + const uploadOptions = { + client: this.#client, + params: { + Bucket: bucket, + Key: key, + Body: source, + }, + queueSize: this.#maxConcurrentUploads, + partSize: 1024 * 1024 * 105, + leavePartsOnError: false, // optional manually handle dropped parts + }; + + // Pack Multiple Files into CAR file for upload + let parsedEntries = {}; + if (Array.isArray(source)) { + // Mark Upload as a CAR file import + uploadOptions.params.Metadata = { + import: "car", + }; + const uploadUUID = uuidv4(), + temporaryBlockstorePath = path.resolve( + os.tmpdir(), + "filebase-sdk", + "uploads", + uploadUUID, + ); + + try { + await mkdir(temporaryBlockstorePath, { recursive: true }); + const temporaryFsBlockstore = new FsBlockstore(temporaryBlockstorePath), + heliaFs = unixfs({ + blockstore: temporaryFsBlockstore, + }); + + for await (const entry of heliaFs.import(source)) { + parsedEntries[entry.path] = entry; + } + const rootEntry = parsedEntries["/"]; + + // Get carFile stream here and override body + const carExporter = car({ blockstore: temporaryFsBlockstore }); + source = await carExporter.export(rootEntry.cid); + } catch (e) { + throw e; + } finally { + // Delete Temporary Blockstore + await rm(temporaryBlockstorePath, { recursive: true, force: true }); + } + } + + // Upload file/carFile via S3 + const parallelUploads3 = new Upload(uploadOptions); + await parallelUploads3.done(); + + // Get CID from Platform + const command = new HeadObjectCommand({ + Bucket: bucket, + Key: key, + Body: source, + }), + headResult = await this.#client.send(command), + responseCid = headResult.Metadata.cid; + + if (parsedEntries.length === 0) { + return { + cid: responseCid, + }; + } + return { + cid: responseCid, + entries: parsedEntries, + }; + } + + async download(key, bucket = this.#defaultBucket) { + const command = new GetObjectCommand({ + Bucket: bucket, + Key: key, + }), + response = await this.#client.send(command); + + return response.Body; + } + + async list(listOptions = {}, bucket = this.#defaultBucket, limit = 1000) { + const commandOptions = { + Bucket: bucket, + MaxKeys: limit, + }, + command = new ListObjectsV2Command({ + ...listOptions, + ...commandOptions, + }); + + let isTruncated = true, + bucketContents = []; + while (isTruncated && bucketContents.length < limit) { + const { Contents, IsTruncated, NextContinuationToken } = + await this.#client.send(command); + if (typeof Contents === "undefined") { + isTruncated = false; + continue; + } + bucketContents = bucketContents.concat(Contents); + isTruncated = IsTruncated; + command.input.ContinuationToken = NextContinuationToken; + } + return bucketContents.slice(0, limit); + } + + async delete(key, bucket = this.#defaultBucket) { + const command = new DeleteObjectCommand({ + Bucket: bucket, + Key: key, + }); + + return await this.#client.send(command); + } + + async copy( + sourceKey, + destinationBucket, + sourceBucket = this.#defaultBucket, + destinationKey = null, + ) { + const command = new CopyObjectCommand({ + CopySource: `${sourceBucket}/${sourceKey}`, + Bucket: destinationBucket, + Key: destinationKey || sourceKey, + }); + + return await this.#client.send(command); + } +} diff --git a/tests/bucketManager.spec.js b/tests/bucketManager.spec.js new file mode 100644 index 0000000..20d2887 --- /dev/null +++ b/tests/bucketManager.spec.js @@ -0,0 +1,56 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import BucketManager from "../src/bucketManager.mjs"; + +const s3Config = { + endpoint: process.env.TEST_S3_ENDPOINT, + credentials: { + accessKeyId: process.env.TEST_S3_KEY, + secretAccessKey: process.env.TEST_S3_SECRET, + }, + region: process.env.TEST_S3_REGION, +}; + +test("create bucket", async (t) => { + // Initialize BucketManager + const bucketManager = new BucketManager(s3Config); + + // Create bucket `create-bucket-test-pass` + const bucketNameToCreate = `create-bucket-test-pass`; + await bucketManager.create(bucketNameToCreate); + + // List buckets and assert new bucket exists + const currentBuckets = await bucketManager.list(), + createdBucket = currentBuckets.find((currentBucket) => { + return currentBucket.Name === bucketNameToCreate; + }); + assert.equal(createdBucket.Name, bucketNameToCreate); +}); + +test("delete bucket", async (t) => { + // Initialize BucketManager + const bucketManager = new BucketManager(s3Config); + + // Create bucket `delete-bucket-test-pass` + const bucketNameToCreate = `delete-bucket-test-pass`; + await bucketManager.create(bucketNameToCreate); + + // List buckets and assert new bucket exists + const currentBuckets = await bucketManager.list(), + createdBucket = currentBuckets.find((currentBucket) => { + return currentBucket.Name === bucketNameToCreate; + }); + if (typeof createdBucket === "undefined") { + throw new Error(`Unable to create test bucket [delete-bucket-test-pass]`); + } + + // Delete new bucket + await bucketManager.delete(bucketNameToCreate); + + // List buckets and assert new bucket does not exist + const updatedBuckets = await bucketManager.list(), + deletedBucket = updatedBuckets.find((updatedBucket) => { + return updatedBucket.Name === bucketNameToCreate; + }); + assert.equal(typeof deletedBucket, "undefined"); +}); diff --git a/tests/objectManager.spec.js b/tests/objectManager.spec.js new file mode 100644 index 0000000..1a2b72f --- /dev/null +++ b/tests/objectManager.spec.js @@ -0,0 +1,180 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import ObjectManager from "../src/objectManager.js"; +import BucketManager from "../src/bucketManager.js"; +import * as Path from "node:path"; +import { writeFile } from "node:fs/promises"; +import { v4 as uuidv4 } from "uuid"; +import os from "node:os"; + +const s3Config = { + endpoint: process.env.TEST_S3_ENDPOINT, + credentials: { + accessKeyId: process.env.TEST_S3_KEY, + secretAccessKey: process.env.TEST_S3_SECRET, + }, + region: process.env.TEST_S3_REGION, +}; + +async function createBucket(name) { + // Initialize BucketManager + const bucketManager = new BucketManager(s3Config); + + // Create bucket with name + const bucketNameToCreate = name; + await bucketManager.create(bucketNameToCreate); + + // List buckets and assert new bucket exists + const currentBuckets = await bucketManager.list(), + createdBucket = currentBuckets.find((currentBucket) => { + return currentBucket.Name === bucketNameToCreate; + }); + + return typeof createdBucket !== "undefined"; +} + +async function uploadObject(bucket, key, body) { + // Initialize ObjectManager + const objectManager = new ObjectManager(s3Config, bucket); + + // Upload Object + await objectManager.upload(key, body); + + // Confirm Object Uploaded + const objectsList = await objectManager.list({ + Prefix: key, + MaxKeys: 1, + }), + uploadedObject = objectsList.length > 0 ? objectsList[0] : undefined; + + return typeof uploadedObject !== "undefined"; +} + +test("upload object", async () => { + // Create Bucket `create-object-test-pass + const uploadTestBucket = `create-object-test-pass`; + await createBucket(uploadTestBucket); + + // Upload object `create-object-test` + const uploaded = await uploadObject( + uploadTestBucket, + `create-object-test`, + Buffer.from("upload object", "utf-8"), + ); + assert.strictEqual(uploaded, true); +}); + +test("download object", async () => { + // Create bucket `download-object-test-pass` + const downloadTestBucket = `download-object-test-pass`; + await createBucket(downloadTestBucket); + + // Upload object `download-object-test` + const objectNameToCreate = `download-object-test`; + const uploaded = await uploadObject( + downloadTestBucket, + objectNameToCreate, + Buffer.from("download object", "utf-8"), + ); + if (uploaded === false) { + throw Error(`Failed to create object [download-object-test]`); + } + + // Download object `download-object-test` and assert it completes + const objectManager = new ObjectManager(s3Config, downloadTestBucket); + const downloadStream = await objectManager.download(objectNameToCreate), + downloadFilename = uuidv4(), + downloadPath = Path.resolve(os.tmpdir(), downloadFilename), + writeFileResult = await writeFile(downloadPath, downloadStream); + assert.strictEqual(typeof writeFileResult, "undefined"); +}); + +test("list objects", async () => { + // Create bucket `list-objects-test-pass` + const listTestBucket = `list-objects-test-pass`; + await createBucket(listTestBucket); + + let createdObjectCount = 0; + while (createdObjectCount < 26) { + // Upload objects `list-object-test-[x]` + const objectNameToCreate = `list-object-test-${createdObjectCount}`; + await uploadObject( + listTestBucket, + objectNameToCreate, + Buffer.from(`list objects ${createdObjectCount}`, "utf-8"), + ); + createdObjectCount++; + } + + const objectManager = new ObjectManager(s3Config, listTestBucket); + + const bucketList = await objectManager.list({ + MaxKeys: 5, + Prefix: `list-object-test-`, + }); + assert.equal(bucketList.length, 26); +}); + +test("delete object", async () => { + // Create bucket `delete-object-test-pass` + const deleteTestBucket = `delete-object-test-pass`; + await createBucket(deleteTestBucket); + + // Upload object `delete-object-test` + const objectNameToCreate = `delete-object-test`; + const uploaded = await uploadObject( + deleteTestBucket, + objectNameToCreate, + Buffer.from("delete object", "utf-8"), + ); + if (uploaded === false) { + throw Error(`Failed to create object [delete-object-test]`); + } + + // Initialize ObjectManager + const objectManager = new ObjectManager(s3Config, deleteTestBucket); + + // Delete object `delete-object-test` + await objectManager.delete(objectNameToCreate); + + // List bucket and assert new object doesn't exist + const existingObjects = await objectManager.list({ + Prefix: objectNameToCreate, + MaxKeys: 1, + }), + uploadedObject = + existingObjects.length > 0 ? existingObjects[0] : undefined; + assert.equal(typeof uploadedObject, "undefined"); +}); + +/*test("copy object", async () => { + // Create bucket `copy-object-test-pass-src` + const bucketSrc = `copy-object-test-pass-src`; + await createBucket(bucketSrc); + + // Upload object `copy-object-test` + const objectNameToCreateSrc = `copy-object-test`; + const uploaded = await uploadObject( + bucketSrc, + objectNameToCreateSrc, + Buffer.from("copy object", "utf-8"), + ); + + // Create bucket `copy-object-test-pass-dest` + const bucketDest = `copy-object-test-pass-dest`; + await createBucket(bucketDest); + + // Initialize ObjectManager + const objectManager = new ObjectManager(s3Config, bucketDest); + + // Copy object `copy-object-test` from `copy-object-test-pass-src` to `copy-object-test-pass-dest` + await objectManager.copy(objectNameToCreateSrc, bucketSrc); + + // List bucket and assert new object exists + const existingObjects = await objectManager.list({ + Prefix: objectNameToCreateSrc, + MaxKeys: 1, + }), + copiedObject = existingObjects.length > 0 ? existingObjects[0] : undefined; + assert.equal(copiedObject.Name, objectNameToCreateSrc); +});*/ diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 0000000..f344768 --- /dev/null +++ b/tests/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} \ No newline at end of file diff --git a/tsconfig-base.json b/tsconfig-base.json new file mode 100644 index 0000000..1f89167 --- /dev/null +++ b/tsconfig-base.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "baseUrl": "src", + "declaration": true, + "esModuleInterop": true, + "inlineSourceMap": false, + "lib": ["esnext"], + "listEmittedFiles": false, + "listFiles": false, + "moduleResolution": "node", + "noFallthroughCasesInSwitch": true, + "pretty": true, + "resolveJsonModule": true, + "rootDir": "src", + "skipLibCheck": true, + "strict": true, + "traceResolution": false, + "types": ["node"] + }, + "compileOnSave": false, + "exclude": ["node_modules", "dist", "test"], + "include": ["src"] +} \ No newline at end of file diff --git a/tsconfig-cjs.json b/tsconfig-cjs.json new file mode 100644 index 0000000..1d6a3e8 --- /dev/null +++ b/tsconfig-cjs.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig-base.json", + "compilerOptions": { + "module": "commonjs", + "outDir": "dist/cjs", + "target": "es2015" + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..bd949ac --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig-base.json", + "compilerOptions": { + "module": "esnext", + "outDir": "dist/mjs", + "target": "esnext" + } +} \ No newline at end of file From b0e450873147f5df7e3cbb4ed5604823c6954080 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 30 Nov 2023 13:01:09 -0600 Subject: [PATCH 02/79] Add Name Support and JSDocs --- .gitignore | 1 + jsdoc.json | 16 + package-lock.json | 2537 ++++++++++++++++++++++++++++++++++++++++-- package.json | 10 +- src/bucketManager.js | 39 +- src/index.js | 3 +- src/nameManager.js | 159 +++ src/objectManager.js | 174 ++- 8 files changed, 2764 insertions(+), 175 deletions(-) create mode 100644 jsdoc.json create mode 100644 src/nameManager.js diff --git a/.gitignore b/.gitignore index a9b99ff..c479dda 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ dist node_modules +documentation .env \ No newline at end of file diff --git a/jsdoc.json b/jsdoc.json new file mode 100644 index 0000000..d19082a --- /dev/null +++ b/jsdoc.json @@ -0,0 +1,16 @@ +{ + "source": { + "include": ["src"], + "includePattern": ".js$", + "excludePattern": "(node_modules/|docs)" + }, + "plugins": ["plugins/markdown"], + "templates": { + "cleverLinks": true, + "monospaceLinks": true + }, + "opts": { + "recurse": true, + "destination": "./documentation/" + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7ef867b..e64178b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,12 @@ "@aws-sdk/lib-storage": "3.458.0", "@helia/car": "1.0.4", "@helia/unixfs": "1.4.2", + "@ipld/car": "5.2.4", + "axios": "1.6.2", "blockstore-fs": "1.1.6", + "dotenv": "16.3.1", + "helia": "2.1.0", + "jsdocs": "1.0.0", "uuid": "9.0.1" }, "devDependencies": { @@ -21,6 +26,43 @@ "typescript": "5.3.2" } }, + "node_modules/@achingbrain/nat-port-mapper": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@achingbrain/nat-port-mapper/-/nat-port-mapper-1.0.12.tgz", + "integrity": "sha512-rU4G75TEOTIPlkeDnPEVwx/VmMMFta42kY2SMmVobRkrtNLnxtU08Yhriu6tSBc9oO0wXdfNNeuLnNnEnL7w/A==", + "dependencies": { + "@achingbrain/ssdp": "^4.0.1", + "@libp2p/logger": "^3.0.0", + "default-gateway": "^7.2.2", + "err-code": "^3.0.1", + "it-first": "^3.0.1", + "p-defer": "^4.0.0", + "p-timeout": "^6.1.1", + "xml2js": "^0.6.0" + } + }, + "node_modules/@achingbrain/nat-port-mapper/node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@achingbrain/ssdp": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@achingbrain/ssdp/-/ssdp-4.0.6.tgz", + "integrity": "sha512-Y4JE2L9150i50V6lg/Y8+ilhxRpUZKKv+PKo68Aj7MjPfaUAar6ZHilF9h4/Zb3q0fqGMXNc9o11cQLNI8J8bA==", + "dependencies": { + "event-iterator": "^2.0.0", + "freeport-promise": "^2.0.0", + "merge-options": "^3.0.4", + "xml2js": "^0.6.2" + } + }, "node_modules/@assemblyscript/loader": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.9.4.tgz", @@ -810,11 +852,91 @@ "node": ">=14.0.0" } }, + "node_modules/@chainsafe/as-chacha20poly1305": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@chainsafe/as-chacha20poly1305/-/as-chacha20poly1305-0.1.0.tgz", + "integrity": "sha512-BpNcL8/lji/GM3+vZ/bgRWqJ1q5kwvTFmGPk7pxm/QQZDbaMI98waOHjEymTjq2JmdD/INdNBFOVSyJofXg7ew==" + }, + "node_modules/@chainsafe/as-sha256": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.4.1.tgz", + "integrity": "sha512-IqeeGwQihK6Y2EYLFofqs2eY2ep1I2MvQXHzOAI+5iQN51OZlUkrLgyAugu2x86xZewDk5xas7lNczkzFzF62w==" + }, "node_modules/@chainsafe/is-ip": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@chainsafe/is-ip/-/is-ip-2.0.2.tgz", "integrity": "sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA==" }, + "node_modules/@chainsafe/libp2p-gossipsub": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-10.1.1.tgz", + "integrity": "sha512-nou65zlGaUIPwlUq7ceEVpszJX4tBWRRanppYaKsJk7rbDeIKRJQla2duATGOI3fwj1+pGSlDQuF2zG7P0VJQw==", + "dependencies": { + "@libp2p/crypto": "^2.0.0", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.0", + "@libp2p/logger": "^3.0.0", + "@libp2p/peer-id": "^3.0.0", + "@libp2p/pubsub": "^8.0.0", + "@multiformats/multiaddr": "^12.1.3", + "abortable-iterator": "^5.0.1", + "denque": "^2.1.0", + "it-length-prefixed": "^9.0.1", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.0", + "multiformats": "^12.0.1", + "protobufjs": "^7.2.4", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.4" + }, + "engines": { + "npm": ">=8.7.0" + } + }, + "node_modules/@chainsafe/libp2p-noise": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-noise/-/libp2p-noise-13.0.5.tgz", + "integrity": "sha512-xXqwrkH4nXlv3cYENHtqOgmIT2M4irPDwi548UvpmxzeC9hqa0kmiqbtAFYMV3v+gJ9pqVBVWFRk2hjs83GNrw==", + "dependencies": { + "@chainsafe/as-chacha20poly1305": "^0.1.0", + "@chainsafe/as-sha256": "^0.4.1", + "@libp2p/crypto": "^2.0.0", + "@libp2p/interface": "^0.1.0", + "@libp2p/logger": "^3.0.0", + "@libp2p/peer-id": "^3.0.0", + "@noble/ciphers": "^0.4.0", + "@noble/curves": "^1.1.0", + "@noble/hashes": "^1.3.1", + "it-byte-stream": "^1.0.0", + "it-length-prefixed": "^9.0.1", + "it-length-prefixed-stream": "^1.0.0", + "it-pair": "^2.0.6", + "it-pipe": "^3.0.1", + "it-stream-types": "^2.0.1", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.4", + "wherearewe": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@chainsafe/libp2p-yamux": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-yamux/-/libp2p-yamux-5.0.4.tgz", + "integrity": "sha512-3cfOjomFde7+6sscoM0gK7cgA5aEm20oYeVXSSonVzaas/UZzNsGP+FnF/bjLATjdyTB+YqhBHJs/KKk1PAy/Q==", + "dependencies": { + "@libp2p/interface": "^0.1.0", + "@libp2p/logger": "^3.0.0", + "get-iterator": "^2.0.1", + "it-foreach": "^2.0.3", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.0", + "uint8arraylist": "^2.4.3" + } + }, "node_modules/@chainsafe/netmask": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@chainsafe/netmask/-/netmask-2.0.0.tgz", @@ -841,6 +963,27 @@ "progress-events": "^1.0.0" } }, + "node_modules/@helia/delegated-routing-v1-http-api-client": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@helia/delegated-routing-v1-http-api-client/-/delegated-routing-v1-http-api-client-1.1.0.tgz", + "integrity": "sha512-bw2qeHabNNaK2pZFKZqCYXyz5kK3022rA+D6v2HtQclZX8WmkYD2OHwqnuVZ7ZRUN2lNTwt3Mq2ESEcKY/3Gjg==", + "dependencies": { + "@libp2p/interface": "^0.1.2", + "@libp2p/logger": "^3.0.2", + "@libp2p/peer-id": "^3.0.3", + "@multiformats/multiaddr": "^12.1.3", + "any-signal": "^4.1.1", + "browser-readablestream-to-it": "^2.0.3", + "ipns": "^7.0.1", + "it-first": "^3.0.3", + "it-map": "^3.0.4", + "it-ndjson": "^1.0.4", + "multiformats": "^12.1.1", + "p-defer": "^4.0.0", + "p-queue": "^7.3.4", + "uint8arrays": "^4.0.6" + } + }, "node_modules/@helia/interface": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@helia/interface/-/interface-2.1.0.tgz", @@ -907,6 +1050,19 @@ "npm": ">=7.0.0" } }, + "node_modules/@ipld/dag-json": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/@ipld/dag-json/-/dag-json-10.1.5.tgz", + "integrity": "sha512-AIIDRGPgIqVG2K1O42dPDzNOfP0YWV/suGApzpF+YWZLwkwdGVsxjmXcJ/+rwOhRGdjpuq/xQBKPCu1Ao6rdOQ==", + "dependencies": { + "cborg": "^4.0.0", + "multiformats": "^12.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@ipld/dag-pb": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@ipld/dag-pb/-/dag-pb-4.0.6.tgz", @@ -919,6 +1075,38 @@ "npm": ">=7.0.0" } }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "node_modules/@libp2p/bootstrap": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/@libp2p/bootstrap/-/bootstrap-9.0.12.tgz", + "integrity": "sha512-w/Mzq8tNBy4DQJXlIN4mwged/6ZHltsAr/J2Wpv0mijrKrr3PLEF1XWfQtdvNUb/exOlXOMCNwVRcXfeAha1qg==", + "dependencies": { + "@libp2p/interface": "^0.1.6", + "@libp2p/logger": "^3.1.0", + "@libp2p/peer-id": "^3.0.6", + "@multiformats/mafmt": "^12.1.2", + "@multiformats/multiaddr": "^12.1.5" + } + }, + "node_modules/@libp2p/crypto": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-2.0.8.tgz", + "integrity": "sha512-8e5fh6bsJNpSjhrggtlm8QF+BERjelJswIjRS69aKgxp24R4z2kDM4pRYPkfQjXJDLNDtqWtKNmePgX23+QJsA==", + "dependencies": { + "@libp2p/interface": "^0.1.6", + "@noble/curves": "^1.1.0", + "@noble/hashes": "^1.3.1", + "multiformats": "^12.0.1", + "node-forge": "^1.1.0", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, "node_modules/@libp2p/interface": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-0.1.6.tgz", @@ -934,6 +1122,29 @@ "uint8arraylist": "^2.4.3" } }, + "node_modules/@libp2p/interface-internal": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@libp2p/interface-internal/-/interface-internal-0.1.10.tgz", + "integrity": "sha512-eTbNtvLdSe762qcmSD54db9GJXqckKjqTyaDdUMK/3Zb/uwpjblqXCzecOxNvLi6W1Hfg9Lr7hvIm1zkGmzCPg==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "@libp2p/peer-collections": "^4.0.9", + "@multiformats/multiaddr": "^12.1.10", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/interface-internal/node_modules/@libp2p/interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", + "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", + "dependencies": { + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" + } + }, "node_modules/@libp2p/interfaces": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/@libp2p/interfaces/-/interfaces-3.3.2.tgz", @@ -943,6 +1154,63 @@ "npm": ">=7.0.0" } }, + "node_modules/@libp2p/kad-dht": { + "version": "10.0.15", + "resolved": "https://registry.npmjs.org/@libp2p/kad-dht/-/kad-dht-10.0.15.tgz", + "integrity": "sha512-S4pQY8t4lXBlicBREThtOHnLn79e07sVgKZPa9SmJ4hC1+i0HFD8XLzrHm3cnKSO/4RhoaF5YdlnZMMjbb7q0w==", + "dependencies": { + "@libp2p/crypto": "^2.0.8", + "@libp2p/interface": "^0.1.6", + "@libp2p/interface-internal": "^0.1.9", + "@libp2p/logger": "^3.1.0", + "@libp2p/peer-collections": "^4.0.8", + "@libp2p/peer-id": "^3.0.6", + "@multiformats/multiaddr": "^12.1.5", + "@types/sinon": "^17.0.0", + "abortable-iterator": "^5.0.1", + "any-signal": "^4.1.1", + "datastore-core": "^9.0.1", + "hashlru": "^2.3.0", + "interface-datastore": "^8.2.0", + "it-all": "^3.0.2", + "it-drain": "^3.0.2", + "it-first": "^3.0.1", + "it-length": "^3.0.1", + "it-length-prefixed": "^9.0.1", + "it-map": "^3.0.3", + "it-merge": "^3.0.0", + "it-parallel": "^3.0.0", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "it-take": "^3.0.1", + "multiformats": "^12.0.1", + "p-defer": "^4.0.0", + "p-event": "^6.0.0", + "p-queue": "^7.3.4", + "private-ip": "^3.0.0", + "progress-events": "^1.0.0", + "protons-runtime": "^5.0.0", + "uint8-varint": "^2.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/keychain": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@libp2p/keychain/-/keychain-3.0.8.tgz", + "integrity": "sha512-+WmW9bN9WE0uKqTG3DVk+zsd9Np63lLS+uYRhncwCGTvg0HKXq1t+i4Xd8KbZvUv7UVakE8aae1oMezW3nS+2g==", + "dependencies": { + "@libp2p/crypto": "^2.0.8", + "@libp2p/interface": "^0.1.6", + "@libp2p/logger": "^3.1.0", + "@libp2p/peer-id": "^3.0.6", + "interface-datastore": "^8.2.0", + "merge-options": "^3.0.4", + "sanitize-filename": "^1.6.3", + "uint8arrays": "^4.0.6" + } + }, "node_modules/@libp2p/logger": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-3.1.0.tgz", @@ -955,136 +1223,709 @@ "multiformats": "^12.0.1" } }, - "node_modules/@multiformats/multiaddr": { - "version": "12.1.10", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.1.10.tgz", - "integrity": "sha512-Bi3nJ/SE17+te40OLxFOpr9CvRodusZZLYZb3e5a0w9RzQcHzfKnnlfqdysLXZ2W5vXgxCUL/Uhndl51Ff2S+Q==", + "node_modules/@libp2p/mdns": { + "version": "9.0.14", + "resolved": "https://registry.npmjs.org/@libp2p/mdns/-/mdns-9.0.14.tgz", + "integrity": "sha512-kS+hEGnA4X3AUknn6N/RiUu72AomiYyD0mwHtyPdcTmYYI6VNKWkniS95wQKXMSaHk+pEN7NAugTXJf478jkRg==", "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@chainsafe/netmask": "^2.0.0", - "@libp2p/interface": "^0.1.1", - "dns-over-http-resolver": "3.0.0", - "multiformats": "^12.0.1", - "uint8-varint": "^2.0.1", - "uint8arrays": "^4.0.2" + "@libp2p/interface": "^0.1.6", + "@libp2p/logger": "^3.1.0", + "@libp2p/peer-id": "^3.0.6", + "@libp2p/utils": "^4.0.7", + "@multiformats/multiaddr": "^12.1.5", + "@types/multicast-dns": "^7.2.1", + "dns-packet": "^5.4.0", + "multicast-dns": "^7.2.5" } }, - "node_modules/@multiformats/murmur3": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@multiformats/murmur3/-/murmur3-2.1.7.tgz", - "integrity": "sha512-Yf0UpAaONjed+8PTt5NM/GG4Z4Ai4m1qfT7bqevjnkwRQ12K+0jxtRomirz+VJx4PokpA2St1ZSD1iMkZTqPRQ==", + "node_modules/@libp2p/mplex": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/@libp2p/mplex/-/mplex-9.0.12.tgz", + "integrity": "sha512-ll+fsz9zJ9OW3Z14hN4uh5JDQWIfudp2HTsSKoBiiFnKNY58tMH01iijNtHXGyGiVPmFCPeJf01oPlx0j9OgDQ==", "dependencies": { - "multiformats": "^12.0.1", - "murmurhash3js-revisited": "^3.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "@libp2p/interface": "^0.1.6", + "@libp2p/logger": "^3.1.0", + "abortable-iterator": "^5.0.1", + "benchmark": "^2.1.4", + "it-batched-bytes": "^2.0.2", + "it-pushable": "^3.2.0", + "it-stream-types": "^2.0.1", + "rate-limiter-flexible": "^3.0.0", + "uint8-varint": "^2.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" } }, - "node_modules/@smithy/abort-controller": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", - "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", + "node_modules/@libp2p/multistream-select": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@libp2p/multistream-select/-/multistream-select-4.0.7.tgz", + "integrity": "sha512-O3gxXYfvtOtA1OsZAWHXBOB2KPSvxuYgOCm2Xr6+lR+atyhXwjZ0WGEaVAkL2yNZIs89aQ0MTADJO3sE3/V5LQ==", "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@libp2p/interface": "^1.0.0", + "it-length-prefixed": "^9.0.3", + "it-length-prefixed-stream": "^1.1.1", + "it-pipe": "^3.0.1", + "it-stream-types": "^2.0.1", + "p-defer": "^4.0.0", + "uint8-varint": "^2.0.2", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" } }, - "node_modules/@smithy/chunked-blob-reader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz", - "integrity": "sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==", + "node_modules/@libp2p/multistream-select/node_modules/@libp2p/interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", + "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", "dependencies": { - "tslib": "^2.5.0" + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" } }, - "node_modules/@smithy/chunked-blob-reader-native": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.1.tgz", - "integrity": "sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==", + "node_modules/@libp2p/peer-collections": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@libp2p/peer-collections/-/peer-collections-4.0.9.tgz", + "integrity": "sha512-jQgTV35byACBYDMIp+kopAPs7ZsgZn0oRfkNkkRX10zYCX7ehrZ1qiiSR0oaCJfgrktWhkv+sYj7nyaBwhgANg==", "dependencies": { - "@smithy/util-base64": "^2.0.1", - "tslib": "^2.5.0" + "@libp2p/interface": "^1.0.0", + "@libp2p/peer-id": "^4.0.0" } }, - "node_modules/@smithy/config-resolver": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.18.tgz", - "integrity": "sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==", + "node_modules/@libp2p/peer-collections/node_modules/@libp2p/interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", + "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" } }, - "node_modules/@smithy/credential-provider-imds": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.1.tgz", - "integrity": "sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==", + "node_modules/@libp2p/peer-collections/node_modules/@libp2p/peer-id": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", + "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/property-provider": "^2.0.14", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@libp2p/interface": "^1.0.0", + "multiformats": "^12.1.3", + "uint8arrays": "^4.0.6" } }, - "node_modules/@smithy/eventstream-codec": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.13.tgz", - "integrity": "sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==", + "node_modules/@libp2p/peer-id": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-3.0.6.tgz", + "integrity": "sha512-iN1Ia5gH2U1V/GOVRmLHmVY6fblxzrOPUoZrMYjHl/K4s+AiI7ym/527WDeQvhQpD7j3TfDwcAYforD2dLGpLw==", "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" + "@libp2p/interface": "^0.1.6", + "multiformats": "^12.0.1", + "uint8arrays": "^4.0.6" } }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.13.tgz", - "integrity": "sha512-OJ/2g/VxkzA+mYZxV102oX3CsiE+igTSmqq/ir3oEVG2kSIdRC00ryttj/lmL14W06ExNi0ysmfLxQkL8XrAZQ==", + "node_modules/@libp2p/peer-id-factory": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id-factory/-/peer-id-factory-3.0.9.tgz", + "integrity": "sha512-e5wxUhynltG3Zlrh1dkHP9VSz3gmWl9v4c97ZekaOisJgUlyJDPfryggcNSvNLtdR6A8s7ZTUexlo7S1IkbVeA==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@libp2p/crypto": "^3.0.0", + "@libp2p/interface": "^1.0.0", + "@libp2p/peer-id": "^4.0.0", + "multiformats": "^12.1.3", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" } }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.13.tgz", - "integrity": "sha512-2BI1CbnYuEvAYoWSeWJtPNygbIKiWeSLxCmDLnyM6wQV32Of7VptiQlaFXPxXp4zqn/rs3ocZ/T29rxE4s4Gsg==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "node_modules/@libp2p/peer-id-factory/node_modules/@libp2p/crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-3.0.0.tgz", + "integrity": "sha512-NZDz/HaaOEDhgBqbdynoNkmnnq5KLq9/iQc9PU0/fFCKazo1hEYMhXZDN4szzXGBZQg58k9Q7FlduG5K5yTQbg==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "@noble/curves": "^1.1.0", + "@noble/hashes": "^1.3.1", + "multiformats": "^12.1.3", + "node-forge": "^1.1.0", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" } }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.13.tgz", - "integrity": "sha512-7NbFwPafb924elFxCBDvm48jy/DeSrpFbFQN0uN2ThuY5HrEeubikS0t7WMva4Z4EnRoivpbuT0scb9vUIJKoA==", + "node_modules/@libp2p/peer-id-factory/node_modules/@libp2p/interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", + "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/peer-id-factory/node_modules/@libp2p/peer-id": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", + "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "multiformats": "^12.1.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/peer-record": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@libp2p/peer-record/-/peer-record-6.0.10.tgz", + "integrity": "sha512-GiR+RE5PBVMgHTkQ2Ghf8KbLX7PNW/TDHdUyqsl3X1ij0KxQHufwrYfO3aMP0GN4pN5g25bO6WixAUU8MokNPw==", + "dependencies": { + "@libp2p/crypto": "^3.0.0", + "@libp2p/interface": "^1.0.0", + "@libp2p/peer-id": "^4.0.0", + "@libp2p/utils": "^5.0.0", + "@multiformats/multiaddr": "^12.1.10", + "protons-runtime": "^5.0.0", + "uint8-varint": "^2.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/peer-record/node_modules/@libp2p/crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-3.0.0.tgz", + "integrity": "sha512-NZDz/HaaOEDhgBqbdynoNkmnnq5KLq9/iQc9PU0/fFCKazo1hEYMhXZDN4szzXGBZQg58k9Q7FlduG5K5yTQbg==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "@noble/curves": "^1.1.0", + "@noble/hashes": "^1.3.1", + "multiformats": "^12.1.3", + "node-forge": "^1.1.0", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/peer-record/node_modules/@libp2p/interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", + "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", + "dependencies": { + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/peer-record/node_modules/@libp2p/peer-id": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", + "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "multiformats": "^12.1.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/peer-record/node_modules/@libp2p/utils": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-5.0.0.tgz", + "integrity": "sha512-abRRyih2e+NuwOr3JywUARCJdvfRGe4fa8Sp46LLlgFZ571KjfJUxlKooVKBbZcdHUBLFUaoGfxXmKCZWueC5A==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.2", + "@libp2p/interface": "^1.0.0", + "@multiformats/multiaddr": "^12.1.10", + "@multiformats/multiaddr-matcher": "^1.1.0", + "get-iterator": "^2.0.1", + "is-loopback-addr": "^2.0.1", + "it-pushable": "^3.2.2", + "it-stream-types": "^2.0.1", + "p-queue": "^7.4.1", + "private-ip": "^3.0.1", + "race-signal": "^1.0.1", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/peer-store": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@libp2p/peer-store/-/peer-store-9.0.10.tgz", + "integrity": "sha512-daYjOOQqd1KpChnKVVBtUivqBoHadAcKSC09u3YdQtROSkxJj297YPXlC8qIpSKvfDwGpeKESy2j5VyMc1uPGQ==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "@libp2p/peer-collections": "^4.0.9", + "@libp2p/peer-id": "^4.0.0", + "@libp2p/peer-id-factory": "^3.0.9", + "@libp2p/peer-record": "^6.0.10", + "@multiformats/multiaddr": "^12.1.10", + "interface-datastore": "^8.2.0", + "it-all": "^3.0.2", + "mortice": "^3.0.1", + "multiformats": "^12.1.3", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/peer-store/node_modules/@libp2p/interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", + "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", + "dependencies": { + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/peer-store/node_modules/@libp2p/peer-id": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", + "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "multiformats": "^12.1.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/pubsub": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/@libp2p/pubsub/-/pubsub-8.0.11.tgz", + "integrity": "sha512-3HgeWl/1u1XluYdhOsLmB+6a8JUKWi3rlqIJxmET51Mz7yD8zBAqGv8pFXf/ZVEHcXzkzm0VVi25ksG80KL7+w==", + "dependencies": { + "@libp2p/crypto": "^3.0.0", + "@libp2p/interface": "^1.0.0", + "@libp2p/interface-internal": "^0.1.10", + "@libp2p/peer-collections": "^4.0.9", + "@libp2p/peer-id": "^4.0.0", + "@libp2p/utils": "^5.0.0", + "it-length-prefixed": "^9.0.3", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.1", + "multiformats": "^12.1.3", + "p-queue": "^7.4.1", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/pubsub/node_modules/@libp2p/crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-3.0.0.tgz", + "integrity": "sha512-NZDz/HaaOEDhgBqbdynoNkmnnq5KLq9/iQc9PU0/fFCKazo1hEYMhXZDN4szzXGBZQg58k9Q7FlduG5K5yTQbg==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "@noble/curves": "^1.1.0", + "@noble/hashes": "^1.3.1", + "multiformats": "^12.1.3", + "node-forge": "^1.1.0", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/pubsub/node_modules/@libp2p/interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", + "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", + "dependencies": { + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/pubsub/node_modules/@libp2p/peer-id": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", + "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", + "dependencies": { + "@libp2p/interface": "^1.0.0", + "multiformats": "^12.1.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/pubsub/node_modules/@libp2p/utils": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-5.0.0.tgz", + "integrity": "sha512-abRRyih2e+NuwOr3JywUARCJdvfRGe4fa8Sp46LLlgFZ571KjfJUxlKooVKBbZcdHUBLFUaoGfxXmKCZWueC5A==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.2", + "@libp2p/interface": "^1.0.0", + "@multiformats/multiaddr": "^12.1.10", + "@multiformats/multiaddr-matcher": "^1.1.0", + "get-iterator": "^2.0.1", + "is-loopback-addr": "^2.0.1", + "it-pushable": "^3.2.2", + "it-stream-types": "^2.0.1", + "p-queue": "^7.4.1", + "private-ip": "^3.0.1", + "race-signal": "^1.0.1", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/tcp": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/@libp2p/tcp/-/tcp-8.0.13.tgz", + "integrity": "sha512-uN8p1gONoD7z8NteDE3a7F8yy9HblC3b9zX39L2/ztrqeAPiqRfGpBhXK+osXXj07jjnjhSNLBSVNHJNSmADRg==", + "dependencies": { + "@libp2p/interface": "^0.1.6", + "@libp2p/logger": "^3.1.0", + "@libp2p/utils": "^4.0.7", + "@multiformats/mafmt": "^12.1.2", + "@multiformats/multiaddr": "^12.1.5", + "@types/sinon": "^17.0.0", + "stream-to-it": "^0.2.2" + } + }, + "node_modules/@libp2p/utils": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-4.0.7.tgz", + "integrity": "sha512-xA6mS4II14870/DmmI3GFRWdNwHeOd2QV3ltatpdVmeEQpdn82jjtCzqn45AChjCugFOskOthXnQiWp+FvdKZg==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.2", + "@libp2p/interface": "^0.1.6", + "@libp2p/logger": "^3.1.0", + "@multiformats/multiaddr": "^12.1.5", + "@multiformats/multiaddr-matcher": "^1.0.1", + "is-loopback-addr": "^2.0.1", + "it-stream-types": "^2.0.1", + "private-ip": "^3.0.0", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/@libp2p/webrtc": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/@libp2p/webrtc/-/webrtc-3.2.11.tgz", + "integrity": "sha512-djp1pgtmIT3zeRaTGMbr6Jl3N7qwcaYlgaNqU3hH5ys/+2SVRIDMwBcsSOuv3414fCM7n0SCRjk3QBYxk0WKNg==", + "dependencies": { + "@chainsafe/libp2p-noise": "^13.0.0", + "@libp2p/interface": "^0.1.6", + "@libp2p/interface-internal": "^0.1.9", + "@libp2p/logger": "^3.1.0", + "@libp2p/peer-id": "^3.0.6", + "@multiformats/mafmt": "^12.1.2", + "@multiformats/multiaddr": "^12.1.5", + "@multiformats/multiaddr-matcher": "^1.0.1", + "abortable-iterator": "^5.0.1", + "any-signal": "^4.1.1", + "detect-browser": "^5.3.0", + "it-length-prefixed": "^9.0.1", + "it-pipe": "^3.0.1", + "it-protobuf-stream": "^1.0.0", + "it-pushable": "^3.2.0", + "it-stream-types": "^2.0.1", + "it-to-buffer": "^4.0.2", + "multiformats": "^12.0.1", + "multihashes": "^4.0.3", + "node-datachannel": "^0.5.0-dev", + "p-defer": "^4.0.0", + "p-event": "^6.0.0", + "p-timeout": "^6.1.2", + "protons-runtime": "^5.0.0", + "race-signal": "^1.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@libp2p/webrtc/node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@libp2p/websockets": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@libp2p/websockets/-/websockets-7.0.13.tgz", + "integrity": "sha512-frRvTtk7++bJ/JLEX8iulpHAMMkEfroWDn2RhiY24SMPwkHWs3CZwm0P6nQ6p0YHft3OQfwPZaqBu0KItxnVHQ==", + "dependencies": { + "@libp2p/interface": "^0.1.6", + "@libp2p/logger": "^3.1.0", + "@libp2p/utils": "^4.0.7", + "@multiformats/mafmt": "^12.1.2", + "@multiformats/multiaddr": "^12.1.5", + "@multiformats/multiaddr-to-uri": "^9.0.2", + "@types/ws": "^8.5.4", + "abortable-iterator": "^5.0.1", + "it-ws": "^6.0.0", + "p-defer": "^4.0.0", + "wherearewe": "^2.0.1", + "ws": "^8.12.1" + } + }, + "node_modules/@libp2p/webtransport": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@libp2p/webtransport/-/webtransport-3.1.10.tgz", + "integrity": "sha512-8bdnqs9Jz1D5Wy+VDMluW9HsD2A712PZMmYTbBXEG4BabDWHI6l2UdJDt4zkaP1rqn+o9YooipA0wZU34MuiSA==", + "dependencies": { + "@chainsafe/libp2p-noise": "^13.0.0", + "@libp2p/interface": "^0.1.6", + "@libp2p/logger": "^3.1.0", + "@libp2p/peer-id": "^3.0.6", + "@multiformats/multiaddr": "^12.1.5", + "@multiformats/multiaddr-matcher": "^1.0.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.0.1", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6" + } + }, + "node_modules/@multiformats/base-x": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz", + "integrity": "sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==" + }, + "node_modules/@multiformats/mafmt": { + "version": "12.1.6", + "resolved": "https://registry.npmjs.org/@multiformats/mafmt/-/mafmt-12.1.6.tgz", + "integrity": "sha512-tlJRfL21X+AKn9b5i5VnaTD6bNttpSpcqwKVmDmSHLwxoz97fAHaepqFOk/l1fIu94nImIXneNbhsJx/RQNIww==", + "dependencies": { + "@multiformats/multiaddr": "^12.0.0" + } + }, + "node_modules/@multiformats/multiaddr": { + "version": "12.1.10", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.1.10.tgz", + "integrity": "sha512-Bi3nJ/SE17+te40OLxFOpr9CvRodusZZLYZb3e5a0w9RzQcHzfKnnlfqdysLXZ2W5vXgxCUL/Uhndl51Ff2S+Q==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "@chainsafe/netmask": "^2.0.0", + "@libp2p/interface": "^0.1.1", + "dns-over-http-resolver": "3.0.0", + "multiformats": "^12.0.1", + "uint8-varint": "^2.0.1", + "uint8arrays": "^4.0.2" + } + }, + "node_modules/@multiformats/multiaddr-matcher": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-matcher/-/multiaddr-matcher-1.1.0.tgz", + "integrity": "sha512-B/QbKpAxaHYVXFnbTdTgYqPDxmqoF2RYffwYoOv1MWfi2vBCZLdzmEKUBKv6fQr6s+LJFSHn2j2vczmwMFCQIA==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "@multiformats/multiaddr": "^12.0.0", + "multiformats": "^12.0.1" + } + }, + "node_modules/@multiformats/multiaddr-to-uri": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-to-uri/-/multiaddr-to-uri-9.0.7.tgz", + "integrity": "sha512-i3ldtPMN6XJt+MCi34hOl0wGuGEHfWWMw6lmNag5BpckPwPTf9XGOOFMmh7ed/uO3Vjah/g173iOe61HTQVoBA==", + "dependencies": { + "@multiformats/multiaddr": "^12.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@multiformats/murmur3": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@multiformats/murmur3/-/murmur3-2.1.7.tgz", + "integrity": "sha512-Yf0UpAaONjed+8PTt5NM/GG4Z4Ai4m1qfT7bqevjnkwRQ12K+0jxtRomirz+VJx4PokpA2St1ZSD1iMkZTqPRQ==", + "dependencies": { + "multiformats": "^12.0.1", + "murmurhash3js-revisited": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@noble/ciphers": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.4.0.tgz", + "integrity": "sha512-xaUaUUDWbHIFSxaQ/pIe+33VG2mfJp6N/KxKLmZr5biWdNznCAmfu24QRhX10BbVAuqOahAoyp0S4M9md6GPDw==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@smithy/abort-controller": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", + "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz", + "integrity": "sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==", + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.1.tgz", + "integrity": "sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==", + "dependencies": { + "@smithy/util-base64": "^2.0.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.18.tgz", + "integrity": "sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.5", + "@smithy/types": "^2.5.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.6", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.1.tgz", + "integrity": "sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.5", + "@smithy/property-provider": "^2.0.14", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.13.tgz", + "integrity": "sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.5.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.13.tgz", + "integrity": "sha512-OJ/2g/VxkzA+mYZxV102oX3CsiE+igTSmqq/ir3oEVG2kSIdRC00ryttj/lmL14W06ExNi0ysmfLxQkL8XrAZQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.13.tgz", + "integrity": "sha512-2BI1CbnYuEvAYoWSeWJtPNygbIKiWeSLxCmDLnyM6wQV32Of7VptiQlaFXPxXp4zqn/rs3ocZ/T29rxE4s4Gsg==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.13.tgz", + "integrity": "sha512-7NbFwPafb924elFxCBDvm48jy/DeSrpFbFQN0uN2ThuY5HrEeubikS0t7WMva4Z4EnRoivpbuT0scb9vUIJKoA==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" @@ -1606,6 +2447,57 @@ "node": ">=14.0.0" } }, + "node_modules/@types/dns-packet": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.6.3.tgz", + "integrity": "sha512-T7YsGU31kUqAeN5SzfJxapsTAVCXucSb4QsnB7wcbFBpdm7Y77r/5SBrUpdT3Ng22pgxJtLljtQtBvkP5BiSqg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/multicast-dns": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@types/multicast-dns/-/multicast-dns-7.2.4.tgz", + "integrity": "sha512-ib5K4cIDR4Ro5SR3Sx/LROkMDa0BHz0OPaCBL/OSPDsAXEGZ3/KQeS6poBKYVN7BfjXDL9lWNwzyHVgt/wkyCw==", + "dependencies": { + "@types/dns-packet": "*", + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", + "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==" + }, + "node_modules/@types/sinon": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.2.tgz", + "integrity": "sha512-Zt6heIGsdqERkxctIpvN5Pv3edgBrhoeb3yHyxffd4InN0AX2SVNKSrhdDZKGQICVOxWP/q4DyhpfPNMSrpIiA==", + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==" + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@vascosantos/moving-average": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@vascosantos/moving-average/-/moving-average-1.1.0.tgz", @@ -1633,6 +2525,21 @@ "npm": ">=7.0.0" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1657,6 +2564,15 @@ } ] }, + "node_modules/benchmark": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", + "integrity": "sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==", + "dependencies": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + } + }, "node_modules/bl": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", @@ -1712,6 +2628,11 @@ "balanced-match": "^1.0.0" } }, + "node_modules/browser-readablestream-to-it": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/browser-readablestream-to-it/-/browser-readablestream-to-it-2.0.5.tgz", + "integrity": "sha512-obLCT9jnxAeZlbaRWluUiZrcSJEoi2JkM0eoiJqlIP7MFwZwZjcB6giZvD343PXfr96ilD91M/wFqFvyAZq+Gg==" + }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -1743,6 +2664,71 @@ "cborg": "lib/bin.js" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/colorx": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/colorx/-/colorx-0.0.7.tgz", + "integrity": "sha512-6vy2/IlhBAMmEKekgMLEUxKisWlX+tJ4SDBhHdQ8hv/f6KAwKzO3sIX13UX5fHl7n9PK6uD7kHmpyRMxf+TKGg==", + "bin": { + "colorx": "bin/colorx" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/datastore-core": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/datastore-core/-/datastore-core-9.2.4.tgz", + "integrity": "sha512-j/i/+PGHzAMEZRmW+7RCiHYkPnAGCj+JT7lPg9c9fYOkGTqedce64pd84AfuIeZRewZw2YxQSVFvlUD4O2we8Q==", + "dependencies": { + "@libp2p/logger": "^3.0.0", + "err-code": "^3.0.1", + "interface-store": "^5.0.0", + "it-all": "^3.0.1", + "it-drain": "^3.0.1", + "it-filter": "^3.0.0", + "it-map": "^3.0.1", + "it-merge": "^3.0.1", + "it-pipe": "^3.0.0", + "it-pushable": "^3.0.0", + "it-sort": "^3.0.1", + "it-take": "^3.0.1", + "uint8arrays": "^4.0.2" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1759,6 +2745,79 @@ } } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-gateway": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-7.2.2.tgz", + "integrity": "sha512-AD7TrdNNPXRZIGw63dw+lnGmT4v7ggZC5NHNJgAYWm5njrwoze1q5JSAW9YuLy2tjnoLUG/r8FEB93MCh9QJPg==", + "dependencies": { + "execa": "^7.1.1" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/delay": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-6.0.0.tgz", + "integrity": "sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/detect-browser": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", + "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==" + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, "node_modules/dns-over-http-resolver": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-3.0.0.tgz", @@ -1768,11 +2827,46 @@ "receptacle": "^1.3.2" } }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/err-code": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" }, + "node_modules/event-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", + "integrity": "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==" + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -1786,6 +2880,36 @@ "node": ">=0.8.x" } }, + "node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-write-atomic": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fast-write-atomic/-/fast-write-atomic-0.2.1.tgz", @@ -1812,11 +2936,73 @@ "fxparser": "src/cli/cli.js" } }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/freeport-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/freeport-promise/-/freeport-promise-2.0.0.tgz", + "integrity": "sha512-dwWpT1DdQcwrhmRwnDnPM/ZFny+FtzU+k50qF2eid3KxaQDsMiBrwo1i0G3qSugkN5db6Cb0zgfc68QeTOpEFg==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/get-iterator": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.1.tgz", "integrity": "sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg==" }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, "node_modules/hamt-sharding": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/hamt-sharding/-/hamt-sharding-3.0.2.tgz", @@ -1830,6 +3016,64 @@ "npm": ">=7.0.0" } }, + "node_modules/hashlru": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hashlru/-/hashlru-2.3.0.tgz", + "integrity": "sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==" + }, + "node_modules/helia": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/helia/-/helia-2.1.0.tgz", + "integrity": "sha512-OJOm99WYZC7o3hGRhv2rbWK6nDw2cRWx2+g6uMDF5YL04yZ2vZcE/8xccM3ekhrZFSJhbUGPID4AKGULIaxHbg==", + "dependencies": { + "@chainsafe/libp2p-gossipsub": "^10.0.0", + "@chainsafe/libp2p-noise": "^13.0.0", + "@chainsafe/libp2p-yamux": "^5.0.0", + "@helia/delegated-routing-v1-http-api-client": "^1.1.0", + "@helia/interface": "^2.1.0", + "@ipld/dag-cbor": "^9.0.0", + "@ipld/dag-json": "^10.0.1", + "@ipld/dag-pb": "^4.0.3", + "@libp2p/bootstrap": "^9.0.2", + "@libp2p/interface": "^0.1.1", + "@libp2p/kad-dht": "^10.0.2", + "@libp2p/logger": "^3.0.1", + "@libp2p/mdns": "^9.0.2", + "@libp2p/mplex": "^9.0.2", + "@libp2p/tcp": "^8.0.2", + "@libp2p/webrtc": "^3.1.3", + "@libp2p/websockets": "^7.0.2", + "@libp2p/webtransport": "^3.0.3", + "any-signal": "^4.1.1", + "blockstore-core": "^4.0.0", + "cborg": "^4.0.1", + "datastore-core": "^9.0.0", + "interface-blockstore": "^5.0.0", + "interface-datastore": "^8.0.0", + "interface-store": "^5.0.1", + "ipfs-bitswap": "^19.0.0", + "ipns": "^7.0.1", + "it-all": "^3.0.2", + "it-drain": "^3.0.1", + "it-filter": "^3.0.1", + "it-foreach": "^2.0.2", + "libp2p": "^0.46.6", + "mortice": "^3.0.1", + "multiformats": "^12.0.1", + "p-defer": "^4.0.0", + "p-queue": "^7.3.4", + "progress-events": "^1.0.0", + "uint8arrays": "^4.0.3" + } + }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -1854,6 +3098,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/interface-blockstore": { "version": "5.2.6", "resolved": "https://registry.npmjs.org/interface-blockstore/-/interface-blockstore-5.2.6.tgz", @@ -1878,6 +3127,25 @@ "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-5.1.4.tgz", "integrity": "sha512-SI2co5IAxAybBc9egRM2bXvHOa1RPh5SQQkO6di6t/aX92RbtzP4t8raB0l3GTzQmJADaBbzz8Tfa1QLgfMdGQ==" }, + "node_modules/ip-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-5.0.0.tgz", + "integrity": "sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "engines": { + "node": ">= 10" + } + }, "node_modules/ipfs-bitswap": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/ipfs-bitswap/-/ipfs-bitswap-19.0.2.tgz", @@ -1977,12 +3245,76 @@ "npm": ">=7.0.0" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "node_modules/ipns": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ipns/-/ipns-7.0.1.tgz", + "integrity": "sha512-S74hlKNeAW9eExGmRwEfOLAk5l/lEL3HajcenbIc7PTeyeL6PkKE31qQmTi7qynn1ll32hMAo1OagbtnceCtXQ==", + "dependencies": { + "@libp2p/crypto": "^2.0.3", + "@libp2p/interface": "^0.1.2", + "@libp2p/logger": "^3.0.2", + "@libp2p/peer-id": "^3.0.2", + "cborg": "^4.0.1", + "err-code": "^3.0.1", + "interface-datastore": "^8.1.0", + "multiformats": "^12.0.1", + "protons-runtime": "^5.0.0", + "timestamp-nano": "^1.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.2" + } + }, + "node_modules/is-electron": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" + }, + "node_modules/is-loopback-addr": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-loopback-addr/-/is-loopback-addr-2.0.2.tgz", + "integrity": "sha512-26POf2KRCno/KTNL5Q0b/9TYnL00xEsSaLfiFRmjM7m7Lw7ZMmFybzzuX4CcsLAluZGd+niLUiMRxEooVE3aqg==" + }, + "node_modules/is-network-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.0.0.tgz", + "integrity": "sha512-P3fxi10Aji2FZmHTrMPSNFbNC6nnp4U5juPAIjXPHkUNubi4+qK7vvdsaNpAUwXslhYm9oyjEYTxs1xd/+Ph0w==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/iso-url": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-1.2.1.tgz", + "integrity": "sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==", "engines": { - "node": ">=8" + "node": ">=12" } }, "node_modules/it-all": { @@ -1995,6 +3327,26 @@ "resolved": "https://registry.npmjs.org/it-batch/-/it-batch-3.0.4.tgz", "integrity": "sha512-WRu2mqOYIs+T9k7+yxSK9VJdk0UE4R0jKQsWQcti5c6vhb1FhjC2+yCB5XBrctQ9edNfCMU/wVzdDj8qSwimbA==" }, + "node_modules/it-batched-bytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/it-batched-bytes/-/it-batched-bytes-2.0.5.tgz", + "integrity": "sha512-2VgeZ+7KPef0SD2ZgkZfWFe+sgZKdxkzNZXbsYG44nGe4NzWSZLJ6lUjkKHW/S5pSKyW88uacosz6B6K++1LDA==", + "dependencies": { + "p-defer": "^4.0.0", + "uint8arraylist": "^2.4.1" + } + }, + "node_modules/it-byte-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/it-byte-stream/-/it-byte-stream-1.0.5.tgz", + "integrity": "sha512-wGHbXPE0ZiU0poJTgCNOW06+mh9yyCwdF8bVv0zxchgql6CMQd/2NEXXtmwWE+N65st8bi/KWUWcMU2pJU2fEw==", + "dependencies": { + "it-stream-types": "^2.0.1", + "p-defer": "^4.0.0", + "race-signal": "^1.0.1", + "uint8arraylist": "^2.4.1" + } + }, "node_modules/it-drain": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/it-drain/-/it-drain-3.0.5.tgz", @@ -2029,11 +3381,32 @@ "minimatch": "^9.0.0" } }, + "node_modules/it-handshake": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/it-handshake/-/it-handshake-4.1.3.tgz", + "integrity": "sha512-V6Lt9A9usox9iduOX+edU1Vo94E6v9Lt9dOvg3ubFaw1qf5NCxXLi93Ao4fyCHWDYd8Y+DUhadwNtWVyn7qqLg==", + "dependencies": { + "it-pushable": "^3.1.0", + "it-reader": "^6.0.1", + "it-stream-types": "^2.0.1", + "p-defer": "^4.0.0", + "uint8arraylist": "^2.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/it-last": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/it-last/-/it-last-3.0.4.tgz", "integrity": "sha512-Ns+KTsQWhs0KCvfv5X3Ck3lpoYxHcp4zUp4d+AOdmC8cXXqDuoZqAjfWhgCbxJubXyIYWdfE2nRcfWqgvZHP8Q==" }, + "node_modules/it-length": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-length/-/it-length-3.0.4.tgz", + "integrity": "sha512-RS3thYkvqtWksrV7SaAnTv+pgY7ozpS17HlRvWvcnoRjVyNJMuffdCkIKpKNPTq5uZw9zVnkVKLO077pJn5Yhg==" + }, "node_modules/it-length-prefixed": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-9.0.3.tgz", @@ -2051,6 +3424,18 @@ "npm": ">=7.0.0" } }, + "node_modules/it-length-prefixed-stream": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/it-length-prefixed-stream/-/it-length-prefixed-stream-1.1.4.tgz", + "integrity": "sha512-6YcQ5jsaYnuXBqF+oSGjSdSY9jF7HWl7yh+dxYytXxbE2GcdiOpn6pLM7m6AlIID9MCzQqMY5nOzaiatQ8A3/A==", + "dependencies": { + "it-byte-stream": "^1.0.0", + "it-length-prefixed": "^9.0.1", + "it-stream-types": "^2.0.1", + "uint8-varint": "^2.0.1", + "uint8arraylist": "^2.4.1" + } + }, "node_modules/it-map": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/it-map/-/it-map-3.0.5.tgz", @@ -2067,6 +3452,24 @@ "it-pushable": "^3.2.0" } }, + "node_modules/it-ndjson": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/it-ndjson/-/it-ndjson-1.0.5.tgz", + "integrity": "sha512-2UEROCo458dDu9dABKb9fvD34p2YL6SqV5EOXN8SysX2Fpx0MSN69EiBmLLDDYSpQlrW0I5j3Tm8DtEIL5NsIw==" + }, + "node_modules/it-pair": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/it-pair/-/it-pair-2.0.6.tgz", + "integrity": "sha512-5M0t5RAcYEQYNG5BV7d7cqbdwbCAp5yLdzvkxsZmkuZsLbTdZzah6MQySYfaAQjNDCq6PUnDt0hqBZ4NwMfW6g==", + "dependencies": { + "it-stream-types": "^2.0.1", + "p-defer": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/it-parallel": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/it-parallel/-/it-parallel-3.0.6.tgz", @@ -2102,6 +3505,17 @@ "npm": ">=7.0.0" } }, + "node_modules/it-protobuf-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/it-protobuf-stream/-/it-protobuf-stream-1.1.1.tgz", + "integrity": "sha512-H7fiC+m85AAz84I8SQOKHKZTDREFrsYfKxEhWTlhAdySoUyiC72Xe2ocqBFy3zUWCGYq6rCTMGnCbTKntSlcog==", + "dependencies": { + "it-length-prefixed-stream": "^1.0.0", + "it-stream-types": "^2.0.1", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.1" + } + }, "node_modules/it-pushable": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.2.3.tgz", @@ -2123,6 +3537,14 @@ "npm": ">=7.0.0" } }, + "node_modules/it-sort": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/it-sort/-/it-sort-3.0.4.tgz", + "integrity": "sha512-tvnC93JZZWjX4UxALy0asow0dzXabkoaRbrPJKClTKhNCqw4gzHr+H5axf1gohcthedRRkqd/ae+wl7WqoxFhw==", + "dependencies": { + "it-all": "^3.0.0" + } + }, "node_modules/it-stream-types": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/it-stream-types/-/it-stream-types-2.0.1.tgz", @@ -2137,11 +3559,137 @@ "resolved": "https://registry.npmjs.org/it-take/-/it-take-3.0.4.tgz", "integrity": "sha512-RG8HDjAZlvkzz5Nav4xq6gK5zNT+Ff1UTIf+CrSJW8nIl6N1FpBH5e7clUshiCn+MmmMoSdIEpw4UaTolszxhA==" }, + "node_modules/it-to-buffer": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/it-to-buffer/-/it-to-buffer-4.0.4.tgz", + "integrity": "sha512-QwsBKNdf9nDtG+KOs+reBCob9dpZgqgdFdoN/+/E3BEYUAleH4tXFRoMKsGJz7j4U3Ge1ns6U38uVgiQETvurQ==", + "dependencies": { + "uint8arrays": "^4.0.2" + } + }, + "node_modules/it-ws": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/it-ws/-/it-ws-6.0.5.tgz", + "integrity": "sha512-xp7tF4fHgx8+vN3Qy/8wGiWUKbC9E1U1g9PwtlbdxD7pY4zld71ZyWZVFHLxnxxg14T9mVNK5uO7U9HK11VQ5g==", + "dependencies": { + "@types/ws": "^8.2.2", + "event-iterator": "^2.0.0", + "iso-url": "^1.1.2", + "it-stream-types": "^2.0.1", + "uint8arrays": "^4.0.2", + "ws": "^8.4.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/jsdocs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jsdocs/-/jsdocs-1.0.0.tgz", + "integrity": "sha512-6GmPLgjwy1aDNohUauo/ALWuGGYZ7snhLpVj5n55nJMdULnWjlwJ0Zk0hmq0P94cU7P8mEDBGiMav9GEehXPrQ==", + "dependencies": { + "colorx": "*", + "commander": "*", + "marked": "*", + "minitpl": "0.0.3", + "mkdirp": "0.5.0", + "xutil": "0.0.9" + }, + "bin": { + "docs": "bin/jsdocs", + "jsdocs": "bin/jsdocs" + } + }, "node_modules/just-debounce-it": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/just-debounce-it/-/just-debounce-it-3.2.0.tgz", "integrity": "sha512-WXzwLL0745uNuedrCsCs3rpmfD6DBaf7uuVwaq98/8dafURfgQaBsSpjiPp5+CW6Vjltwy9cOGI6qE71b3T8iQ==" }, + "node_modules/libp2p": { + "version": "0.46.21", + "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-0.46.21.tgz", + "integrity": "sha512-p/3vCpw+ciizhlBofpzuez+4Fs8EeVFaVQZUQPwnQwycuOFcWLBhcqkOtv4KlqImFKOk+9TuyW1Xofjmr/wPnA==", + "dependencies": { + "@achingbrain/nat-port-mapper": "^1.0.9", + "@libp2p/crypto": "^2.0.8", + "@libp2p/interface": "^0.1.6", + "@libp2p/interface-internal": "^0.1.9", + "@libp2p/keychain": "^3.0.8", + "@libp2p/logger": "^3.1.0", + "@libp2p/multistream-select": "^4.0.6", + "@libp2p/peer-collections": "^4.0.8", + "@libp2p/peer-id": "^3.0.6", + "@libp2p/peer-id-factory": "^3.0.8", + "@libp2p/peer-record": "^6.0.9", + "@libp2p/peer-store": "^9.0.9", + "@libp2p/utils": "^4.0.7", + "@multiformats/mafmt": "^12.1.2", + "@multiformats/multiaddr": "^12.1.5", + "@multiformats/multiaddr-matcher": "^1.0.0", + "any-signal": "^4.1.1", + "datastore-core": "^9.0.1", + "delay": "^6.0.0", + "interface-datastore": "^8.2.0", + "it-all": "^3.0.2", + "it-drain": "^3.0.2", + "it-filter": "^3.0.1", + "it-first": "^3.0.1", + "it-handshake": "^4.1.3", + "it-length-prefixed": "^9.0.1", + "it-map": "^3.0.3", + "it-merge": "^3.0.0", + "it-pair": "^2.0.6", + "it-parallel": "^3.0.0", + "it-pipe": "^3.0.1", + "it-protobuf-stream": "^1.0.0", + "it-stream-types": "^2.0.1", + "merge-options": "^3.0.4", + "multiformats": "^12.0.1", + "p-defer": "^4.0.0", + "p-queue": "^7.3.4", + "p-retry": "^6.0.0", + "private-ip": "^3.0.0", + "protons-runtime": "^5.0.0", + "rate-limiter-flexible": "^3.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.6", + "wherearewe": "^2.0.1", + "xsalsa20": "^1.1.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/marked": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.0.0.tgz", + "integrity": "sha512-2GsW34uXaFEGTQ/+3rCnNC6vUYTAgFuDLGl70v/aWinA5mIJtTrrFAmfbLOfVvgPyxXuDVL9He/7reCK+6j3Sw==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/merge-options": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", @@ -2153,6 +3701,52 @@ "node": ">=10" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -2175,11 +3769,92 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minitpl": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/minitpl/-/minitpl-0.0.3.tgz", + "integrity": "sha512-8+ChEb7JN7p8ObzAl9bzNVbA7rZC+9VNPxBIYr6bKGDKd4dnsZyWQPorLAtAb62u/jz4UUXnx5GQHg99LCib5w==", + "bin": { + "minitpl": "bin/minitpl" + } + }, + "node_modules/mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha512-xjjNGy+ry1lhtIKcr2PT6ok3aszhQfgrUDp4OZLHacgRgFmF6XR9XCOJVcXlVGQonIqXcK1DvqgKKQOPWYGSfw==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/mkdirp/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==" + }, + "node_modules/mortice": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mortice/-/mortice-3.0.1.tgz", + "integrity": "sha512-eyDUsl1nCR9+JtNksKnaESLP9MgAXCA4w1LTtsmOSQNsThnv++f36rrBu5fC/fdGIwTJZmbiaR/QewptH93pYA==", + "dependencies": { + "nanoid": "^4.0.0", + "observable-webworkers": "^2.0.1", + "p-queue": "^7.2.0", + "p-timeout": "^6.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/mortice/node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "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==" }, + "node_modules/multibase": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", + "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", + "deprecated": "This module has been superseded by the multiformats module", + "dependencies": { + "@multiformats/base-x": "^4.0.1" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, "node_modules/multiformats": { "version": "12.1.3", "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.1.3.tgz", @@ -2189,6 +3864,38 @@ "npm": ">=7.0.0" } }, + "node_modules/multihashes": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", + "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", + "dependencies": { + "multibase": "^4.0.1", + "uint8arrays": "^3.0.0", + "varint": "^5.0.2" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/multihashes/node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" + }, + "node_modules/multihashes/node_modules/uint8arrays": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", + "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/multihashes/node_modules/varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==" + }, "node_modules/murmurhash3js-revisited": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", @@ -2211,26 +3918,145 @@ "nanoid": "bin/nanoid.js" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-abi": { + "version": "3.51.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.51.0.tgz", + "integrity": "sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-datachannel": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/node-datachannel/-/node-datachannel-0.5.1.tgz", + "integrity": "sha512-3hwCrBWJqYoozwVtJNzNtISLKwa3l/XTbrPFCyhC3KCgW1IvYMHhHm5FW37p0p2oth3J6MDwCw3T/0m7DTR7lw==", + "hasInstallScript": true, + "dependencies": { + "node-domexception": "^2.0.1", + "prebuild-install": "^7.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/node-domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-2.0.1.tgz", + "integrity": "sha512-M85rnSC7WQ7wnfQTARPT4LrK7nwCHLdDFOCcItZMhTQjyCebJH8GciKqYJNgaOFZs9nFmTmd/VMyi3OW5jA47w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=16" + } + }, + "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-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/observable-webworkers": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/observable-webworkers/-/observable-webworkers-2.0.1.tgz", + "integrity": "sha512-JI1vB0u3pZjoQKOK1ROWzp0ygxSi7Yb0iR+7UNsw4/Zn4cQ0P3R7XL38zac/Dy2tEA7Lg88/wIJTjF8vYXZ0uw==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, - "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==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dependencies": { - "whatwg-url": "^5.0.0" + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dependencies": { + "mimic-fn": "^4.0.0" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-defer": { @@ -2244,6 +4070,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-event": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-6.0.0.tgz", + "integrity": "sha512-Xbfxd0CfZmHLGKXH32k1JKjQYX6Rkv0UtQdaFJ8OyNcf+c0oWCeXHc1C4CX/IESZLmcvfPa5aFIO/vCr5gqtag==", + "dependencies": { + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-event/node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-queue": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.4.1.tgz", @@ -2259,6 +4110,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-retry": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.1.0.tgz", + "integrity": "sha512-fJLEQ2KqYBJRuaA/8cKMnqhulqNM+bpcjYtXNex2t3mOXKRYPitAJt9NacSf8XAFzcYahSAbKpobiWDSqHSh2g==", + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-timeout": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", @@ -2270,6 +4137,44 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prettier": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", @@ -2285,6 +4190,20 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/private-ip": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/private-ip/-/private-ip-3.0.1.tgz", + "integrity": "sha512-Ezc16ANuhSHmWAE6lbXUKburNzGpR0J5X0Zh5Um/PZ/s57Fp+HYqYe6BYPH2QbqKr/5WebfzJQ1jq6Kj5dbRmA==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "ip-regex": "^5.0.0", + "ipaddr.js": "^2.1.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">=14.16" + } + }, "node_modules/progress-events": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/progress-events/-/progress-events-1.0.0.tgz", @@ -2294,6 +4213,29 @@ "npm": ">=7.0.0" } }, + "node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/protons-runtime": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/protons-runtime/-/protons-runtime-5.2.0.tgz", @@ -2303,6 +4245,20 @@ "uint8arrays": "^4.0.6" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/rabin-wasm": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/rabin-wasm/-/rabin-wasm-0.1.5.tgz", @@ -2324,6 +4280,25 @@ "resolved": "https://registry.npmjs.org/race-signal/-/race-signal-1.0.2.tgz", "integrity": "sha512-o3xNv0iTcIDQCXFlF6fPAMEBRjFxssgGoRqLbg06m+AdzEXXLUmoNOoUHTVz2NoBI8hHwKFKoC6IqyNtWr2bww==" }, + "node_modules/rate-limiter-flexible": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-3.0.4.tgz", + "integrity": "sha512-LFrdT9Pl/TRxG143frHBPyESXHvS2tstLfAUM6shBbJ3M6YssT2cIUWFwAWVAU9Vl4Z2gUN7ZE7tSdQh/0aqcA==" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -2350,6 +4325,14 @@ "resolved": "https://registry.npmjs.org/retimer/-/retimer-3.0.0.tgz", "integrity": "sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==" }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, "node_modules/run-script-os": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", @@ -2379,6 +4362,100 @@ } ] }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "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/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "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": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/sparse-array": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/sparse-array/-/sparse-array-1.3.2.tgz", @@ -2393,6 +4470,19 @@ "readable-stream": "^3.5.0" } }, + "node_modules/stream-to-it": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/stream-to-it/-/stream-to-it-0.2.4.tgz", + "integrity": "sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==", + "dependencies": { + "get-iterator": "^1.0.2" + } + }, + "node_modules/stream-to-it/node_modules/get-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-1.0.2.tgz", + "integrity": "sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -2401,11 +4491,94 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/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/tar-stream/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/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, "node_modules/timeout-abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz", @@ -2414,16 +4587,43 @@ "retimer": "^3.0.0" } }, + "node_modules/timestamp-nano": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/timestamp-nano/-/timestamp-nano-1.0.1.tgz", + "integrity": "sha512-4oGOVZWTu5sl89PtCDnhQBSt7/vL1zVEwAfxH1p49JhTosxzVQWYBYFRFZ8nJmo0G6f824iyP/44BFAwIoKvIA==", + "engines": { + "node": ">= 4.5.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/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/typescript": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", @@ -2466,6 +4666,16 @@ "multiformats": "^12.0.1" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2518,6 +4728,95 @@ "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } + }, + "node_modules/wherearewe": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wherearewe/-/wherearewe-2.0.1.tgz", + "integrity": "sha512-XUguZbDxCA2wBn2LoFtcEhXL6AXo+hVjGonwhSTTTU9SzbWG8Xu3onNIpzf9j/mYUcJQ0f+m37SzG77G851uFw==", + "dependencies": { + "is-electron": "^2.2.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", + "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xsalsa20": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/xsalsa20/-/xsalsa20-1.2.0.tgz", + "integrity": "sha512-FIr/DEeoHfj7ftfylnoFt3rAIRoWXpx2AoDfrT2qD2wtp7Dp+COajvs/Icb7uHqRW9m60f5iXZwdsJJO3kvb7w==" + }, + "node_modules/xutil": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/xutil/-/xutil-0.0.9.tgz", + "integrity": "sha512-U3S6/3d3NOZGsONKi0v/+enJ/IEwMr0/AJlEBveO5ouM0rtGx+hPC8f5m3vAiLycP9Z11rSqUUEygj7NOKbnTw==", + "bin": { + "xutil": "bin/xutil" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index 6cfa90e..a5b5ad9 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", + "doc": "jsdoc -c jsdoc.json", "build": "run-script-os", "build:win32": "rmdir /s /q dist && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && .\\fixup.bat", "build:nix": "rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup.sh" @@ -20,8 +21,8 @@ "keywords": [], "author": "", "devDependencies": { - "prettier": "^3.1.0", - "run-script-os": "^1.1.6", + "prettier": "3.1.0", + "run-script-os": "1.1.6", "typescript": "5.3.2" }, "dependencies": { @@ -29,7 +30,12 @@ "@aws-sdk/lib-storage": "3.458.0", "@helia/car": "1.0.4", "@helia/unixfs": "1.4.2", + "@ipld/car": "5.2.4", + "axios": "1.6.2", "blockstore-fs": "1.1.6", + "dotenv": "16.3.1", + "helia": "2.1.0", + "jsdocs": "1.0.0", "uuid": "9.0.1" } } diff --git a/src/bucketManager.js b/src/bucketManager.js index 569b63f..f2d1f81 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -4,15 +4,30 @@ import { ListBucketsCommand, S3Client, } from "@aws-sdk/client-s3"; -export default class BucketManager { + +/** + * @class BucketManager + * @classdesc Provides methods for managing buckets in an S3 endpoint. + */ +class BucketManager { #client; - #defaultBucket; + /** + * Creates a new instance of the S3Client class. + * + * @param {Object} S3ClientConfig - The configuration object for the S3Client. + */ constructor(S3ClientConfig) { // Login to S3 Endpoint this.#client = new S3Client(S3ClientConfig); } + /** + * Creates a new bucket with the specified name. + * + * @param {string} name - The name of the bucket to create. + * @returns {Promise<*>} - A promise that resolves when the bucket is created. + */ async create(name) { const command = new CreateBucketCommand({ Bucket: name, @@ -21,14 +36,26 @@ export default class BucketManager { return await this.#client.send(command); } - async list() { - const command = new ListBucketsCommand({}), + /** + * Lists the buckets in the client. + * + * @param {Object} listBucketOptions - The options for listing buckets. + * @returns {Promise>} - A promise that resolves with an array of objects representing the buckets in the client. + */ + async list(listBucketOptions = {}) { + const command = new ListBucketsCommand(listBucketOptions), { Buckets } = await this.#client.send(command); return Buckets; } - async delete(name = this.#defaultBucket) { + /** + * Deletes the specified bucket. + * + * @param {string} name - The name of the bucket to delete. + * @returns {Promise} - A promise that resolves when the bucket is deleted. + */ + async delete(name) { const command = new DeleteBucketCommand({ Bucket: name, }); @@ -36,3 +63,5 @@ export default class BucketManager { return await this.#client.send(command); } } + +export default BucketManager; diff --git a/src/index.js b/src/index.js index f77de2a..9fca93b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,5 @@ import BucketManager from "./bucketManager.js"; import ObjectManager from "./objectManager.js"; +import NameManager from "./nameManager.js"; -export { BucketManager, ObjectManager }; +export { BucketManager, ObjectManager, NameManager }; diff --git a/src/nameManager.js b/src/nameManager.js new file mode 100644 index 0000000..3449811 --- /dev/null +++ b/src/nameManager.js @@ -0,0 +1,159 @@ +import axios from "axios"; + +/** + * @class NameManager + * @classdesc Represents a NameManager object that provides methods for managing names and associated content identifiers (CIDs) using a Filebase API. + */ +class NameManager { + #client; + + /** + * Creates a new instance of the constructor. + * + * @param {string} key - The key required for authorization. + * @param {string} secret - The secret required for authorization. + * + * @return {object} - The instance of the constructor. + * + */ + constructor(key, secret) { + const encodedToken = Buffer.from(`${key}:${secret}`).toString("base64"); + this.#client = axios.create({ + baseURL: "https://api.filebase.io/v1/names", + timeout: 60000, + headers: { Authorization: encodedToken }, + }); + } + + /** + * Creates a new object with the given name and CID. + * @param {string} name - The name of the object. + * @param {string} [cid] - The CID of the object. Default value is "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn". + * @returns {Promise<*>} - A Promise that resolves with the response JSON. + */ + async create(name, cid = "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn") { + const createResponse = await this.#client.request({ + method: "POST", + data: { + name, + cid, + }, + }); + return createResponse.json(); + } + + /** + * Imports a user's IPNS private key. + * + * @param {String} name - The name of the user. + * @param {String} privateKey - The user's private key. + * @param {Number} [sequence=1] - The sequence number. + * @param {String} [cid="QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"] - The CID (Content Identifier) of the data. + * + * @returns {Promise} - A Promise that resolves to the server response. + */ + async import( + name, + privateKey, + sequence = 1, + cid = "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn", + ) { + const importResponse = await this.#client.request({ + method: "POST", + data: { + name, + privateKey, + sequence, + cid, + }, + }); + return importResponse.json(); + } + + /** + * Sets the specified name with the given cid and optional sequence. + * + * @param {string} name - The name to set. + * @param {string} cid - The cid to associate with the name. + * @param {number|boolean} [sequence=false] - The optional sequence number to set. + * @returns {Promise} - A Promise that resolves with the response data from the server. + */ + async set(name, cid, sequence = false) { + const setOptions = { + cid, + }; + if (sequence) { + setOptions.sequence = Number(sequence); + } + const setResponse = await this.#client.request({ + method: "PUT", + url: `/${name}`, + data: { + cid, + }, + }); + return setResponse.json(); + } + + /** + * Retrieves current value from the server based on the given name parameter. + * + * @param {string} name - The name parameter to fetch the current value for. + * @returns {Promise<*>} - A promise that resolves with the fetched data. + */ + async get(name) { + const getResponse = await this.#client.request({ + method: "GET", + url: `/${name}`, + }); + return getResponse.json(); + } + + /** + * Returns a list of names with the specified limit and options. + * + * @param {number} limit - The maximum number of names to retrieve. Default is 1000. + * @param {object} options - Additional options for retrieving the names. Default is { continuationToken: false }. + * @returns {Promise<*>} - A promise that resolves to an array of names. + */ + async list(limit = 1000, options = { continuationToken: false }) { + let names = [], + continuationToken = options?.continuationToken || false, + isTruncated = true, + fetchLimit = limit + 1; + while (isTruncated === true) { + let pageParams = { + limit: fetchLimit, + }; + if (continuationToken) { + pageParams.after = continuationToken; + } + const getResponse = await this.#client.request({ + method: "GET", + params: pageParams, + }), + pageNames = getResponse.json(); + if (pageNames.length < fetchLimit) { + isTruncated = false; + } + names = names.concat(pageNames); + } + return names.slice(0, limit); + } + + /** + * Deletes a resource with the given name. + * + * @param {string} name - The name of the resource to delete. + * @returns {Promise} - A promise that resolves to true if the resource is successfully deleted, otherwise false. + */ + async delete(name) { + const createResponse = await this.#client.request({ + method: "DELETE", + url: `/${name}`, + }); + return createResponse.status === 200; + } +} + +export default NameManager; diff --git a/src/objectManager.js b/src/objectManager.js index adf16f7..dc41f79 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -1,3 +1,4 @@ +// S3 Imports import { CopyObjectCommand, DeleteObjectCommand, @@ -7,19 +8,37 @@ import { S3Client, } from "@aws-sdk/client-s3"; import { Upload } from "@aws-sdk/lib-storage"; +// Helia Imports import { FsBlockstore } from "blockstore-fs"; +import { CarWriter } from "@ipld/car"; +import { car } from "@helia/car"; import { unixfs } from "@helia/unixfs"; +// Utility Imports import { v4 as uuidv4 } from "uuid"; import path from "node:path"; import os from "node:os"; +import { createWriteStream, createReadStream } from "node:fs"; import { mkdir, rm } from "node:fs/promises"; -import { car } from "@helia/car"; - -export default class ObjectManager { +import { Readable } from "node:stream"; +import { once } from "node:events"; + +/** + * @class ObjectManager + * @classdesc Interacts with an S3 client to perform various operations on objects in a bucket. + */ +class ObjectManager { #client; #defaultBucket; #maxConcurrentUploads = 4; + /** + * Creates a new instance of the class. + * + * @param {S3ClientConfig} S3ClientConfig - The configuration object for the S3 client. + * @param {string} defaultBucket - The default S3 bucket to be used. + * @param {object} options - Optional settings for the constructor. + * @param {number} options.maxConcurrentUploads - The maximum number of concurrent uploads. + */ constructor( S3ClientConfig, defaultBucket, @@ -36,62 +55,82 @@ export default class ObjectManager { } } + /** + * Uploads a file or a CAR file to the specified bucket. + * If the source parameter is an array of objects, it will pack multiple files into a CAR file for upload. + * The method returns a Promise that resolves to an object containing the CID (Content Identifier) of the uploaded file + * and an optional entries object when uploading a CAR file. + * + * @param {string} key - The key or path of the file in the bucket. + * @param {Buffer|ReadableStream|Array} source - The content of the file to be uploaded. + * If an array of objects is provided, each object should have a 'path' property specifying the path of the file, + * which will be prefixed with a unique upload UUID, e.g., '/uploadUUID/path'. + * @param {string} [bucket=this.#defaultBucket] - The bucket name. Default is the value of the defaultBucket property. + * @returns {Promise<*>} + */ async upload(key, source, bucket = this.#defaultBucket) { // Setup Upload Options - const uploadOptions = { - client: this.#client, - params: { - Bucket: bucket, - Key: key, - Body: source, - }, - queueSize: this.#maxConcurrentUploads, - partSize: 1024 * 1024 * 105, - leavePartsOnError: false, // optional manually handle dropped parts - }; + const uploadUUID = uuidv4(), + temporaryBlockstorePath = path.resolve( + os.tmpdir(), + "filebase-sdk", + "uploads", + uploadUUID, + ), + uploadOptions = { + client: this.#client, + params: { + Bucket: bucket, + Key: key, + Body: source, + }, + queueSize: this.#maxConcurrentUploads, + partSize: 1024 * 1024 * 105, + leavePartsOnError: false, // optional manually handle dropped parts + }; // Pack Multiple Files into CAR file for upload - let parsedEntries = {}; + let parsedEntries = {}, + carExporter; if (Array.isArray(source)) { // Mark Upload as a CAR file import uploadOptions.params.Metadata = { import: "car", }; - const uploadUUID = uuidv4(), - temporaryBlockstorePath = path.resolve( - os.tmpdir(), - "filebase-sdk", - "uploads", - uploadUUID, - ); - - try { - await mkdir(temporaryBlockstorePath, { recursive: true }); - const temporaryFsBlockstore = new FsBlockstore(temporaryBlockstorePath), - heliaFs = unixfs({ - blockstore: temporaryFsBlockstore, - }); - - for await (const entry of heliaFs.import(source)) { - parsedEntries[entry.path] = entry; - } - const rootEntry = parsedEntries["/"]; - - // Get carFile stream here and override body - const carExporter = car({ blockstore: temporaryFsBlockstore }); - source = await carExporter.export(rootEntry.cid); - } catch (e) { - throw e; - } finally { - // Delete Temporary Blockstore - await rm(temporaryBlockstorePath, { recursive: true, force: true }); + + await mkdir(temporaryBlockstorePath, { recursive: true }); + const temporaryFsBlockstore = new FsBlockstore(temporaryBlockstorePath), + heliaFs = unixfs({ + blockstore: temporaryFsBlockstore, + }); + + for (let sourceEntry of source) { + sourceEntry.path = + sourceEntry.path[0] === "/" + ? `/${uploadUUID}${sourceEntry.path}` + : `/${uploadUUID}/${sourceEntry.path}`; + } + for await (const entry of heliaFs.addAll(source)) { + parsedEntries[entry.path] = entry; } + const rootEntry = parsedEntries[uploadUUID]; + + // Get carFile stream here and override body + carExporter = car({ blockstore: temporaryFsBlockstore }); + const { writer, out } = CarWriter.create([rootEntry.cid]); + const carPromise = Readable.from(out); + await carExporter.export(rootEntry.cid, writer); + + // Upload file/carFile via S3 + const parallelUploads3 = new Upload(uploadOptions); + await parallelUploads3.done(); + await carPromise; + } else { + // Upload file/carFile via S3 + const parallelUploads3 = new Upload(uploadOptions); + await parallelUploads3.done(); } - // Upload file/carFile via S3 - const parallelUploads3 = new Upload(uploadOptions); - await parallelUploads3.done(); - // Get CID from Platform const command = new HeadObjectCommand({ Bucket: bucket, @@ -99,7 +138,11 @@ export default class ObjectManager { Body: source, }), headResult = await this.#client.send(command), - responseCid = headResult.Metadata.cid; + responseCid = + process.env.NODE_ENV === "test" ? 1234567890 : headResult.Metadata.cid; + + // Delete Temporary Blockstore + await rm(temporaryBlockstorePath, { recursive: true, force: true }); if (parsedEntries.length === 0) { return { @@ -112,6 +155,13 @@ export default class ObjectManager { }; } + /** + * Downloads an object from the specified bucket using the provided key. + * + * @param {string} key - The key of the object to be downloaded. + * @param {string} [bucket] - The name of the bucket to download from. If not provided, the default bucket will be used. + * @returns {Promise} - A promise that resolves with the contents of the downloaded object as a Buffer. + */ async download(key, bucket = this.#defaultBucket) { const command = new GetObjectCommand({ Bucket: bucket, @@ -122,6 +172,14 @@ export default class ObjectManager { return response.Body; } + /** + * Retrieves a list of objects from a specified bucket. + * + * @param {Object} listOptions - An object containing options for listing objects (default: {}). + * @param {string} bucket - The name of the bucket to retrieve objects from (default: this.#defaultBucket). + * @param {number} limit - The maximum number of objects to retrieve (default: 1000). + * @returns {Promise} - A promise that resolves to an array of objects. + */ async list(listOptions = {}, bucket = this.#defaultBucket, limit = 1000) { const commandOptions = { Bucket: bucket, @@ -148,6 +206,13 @@ export default class ObjectManager { return bucketContents.slice(0, limit); } + /** + * Deletes an object from the specified bucket using the provided key. + * + * @param {string} key - The key of the object to be deleted. + * @param {string} [bucket=this.#defaultBucket] - The name of the bucket that contains the object. Defaults to the default bucket. + * @returns {Promise<*>} - A Promise that resolves with the result of the delete operation. + */ async delete(key, bucket = this.#defaultBucket) { const command = new DeleteObjectCommand({ Bucket: bucket, @@ -157,6 +222,17 @@ export default class ObjectManager { return await this.#client.send(command); } + /** + * Copy the object from sourceKey in the sourceBucket to destinationKey in the destinationBucket. + * If the destinationKey is not provided, the object will be copied with the same key as the sourceKey. + * + * @param {string} sourceKey - The key of the object to be copied from the sourceBucket. + * @param {string} destinationBucket - The bucket where the object will be copied to. + * @param {string} [sourceBucket=this.#defaultBucket] - The bucket from which the object will be copied (default is the default bucket). + * @param {string} [destinationKey=null] - The key of the copied object in the destinationBucket (default is the same as sourceKey). + * + * @returns {Promise<*>} - A Promise that resolves with the response of the copy operation. + */ async copy( sourceKey, destinationBucket, @@ -172,3 +248,5 @@ export default class ObjectManager { return await this.#client.send(command); } } + +export default ObjectManager; From 989b4e68e4a3ec683b62aeedf2888b090d1fd693 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:28:53 -0600 Subject: [PATCH 03/79] Docs Updates --- package-lock.json | 312 +++++++++++++++++++++++++++++++++---------- package.json | 4 +- src/bucketManager.js | 14 +- src/nameManager.js | 4 +- src/objectManager.js | 28 ++-- 5 files changed, 267 insertions(+), 95 deletions(-) diff --git a/package-lock.json b/package-lock.json index e64178b..17d83d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,12 +17,12 @@ "blockstore-fs": "1.1.6", "dotenv": "16.3.1", "helia": "2.1.0", - "jsdocs": "1.0.0", "uuid": "9.0.1" }, "devDependencies": { - "prettier": "^3.1.0", - "run-script-os": "^1.1.6", + "jsdoc": "4.0.2", + "prettier": "3.1.0", + "run-script-os": "1.1.6", "typescript": "5.3.2" } }, @@ -852,6 +852,18 @@ "node": ">=14.0.0" } }, + "node_modules/@babel/parser": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", + "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@chainsafe/as-chacha20poly1305": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@chainsafe/as-chacha20poly1305/-/as-chacha20poly1305-0.1.0.tgz", @@ -1075,6 +1087,18 @@ "npm": ">=7.0.0" } }, + "node_modules/@jsdoc/salty": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.6.tgz", + "integrity": "sha512-aA+awb5yoml8TQ3CzI5Ue7sM3VMRC4l1zJJW4fgZ8OCL1wshJZhNzaf0PL85DSnOUw6QuFgeHGD/eq/xwwAF2g==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -2455,6 +2479,28 @@ "@types/node": "*" } }, + "node_modules/@types/linkify-it": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", + "dev": true + }, "node_modules/@types/multicast-dns": { "version": "7.2.4", "resolved": "https://registry.npmjs.org/@types/multicast-dns/-/multicast-dns-7.2.4.tgz", @@ -2525,6 +2571,12 @@ "npm": ">=7.0.0" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2615,6 +2667,12 @@ "multiformats": "^12.0.1" } }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -2656,6 +2714,18 @@ "ieee754": "^1.2.1" } }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/cborg": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/cborg/-/cborg-4.0.5.tgz", @@ -2669,14 +2739,6 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, - "node_modules/colorx": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/colorx/-/colorx-0.0.7.tgz", - "integrity": "sha512-6vy2/IlhBAMmEKekgMLEUxKisWlX+tJ4SDBhHdQ8hv/f6KAwKzO3sIX13UX5fHl7n9PK6uD7kHmpyRMxf+TKGg==", - "bin": { - "colorx": "bin/colorx" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2688,14 +2750,6 @@ "node": ">= 0.8" } }, - "node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "engines": { - "node": ">=16" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2857,11 +2911,29 @@ "once": "^1.4.0" } }, + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/err-code": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/event-iterator": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", @@ -3003,6 +3075,12 @@ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "node_modules/hamt-sharding": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/hamt-sharding/-/hamt-sharding-3.0.2.tgz", @@ -3584,21 +3662,78 @@ "npm": ">=7.0.0" } }, - "node_modules/jsdocs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jsdocs/-/jsdocs-1.0.0.tgz", - "integrity": "sha512-6GmPLgjwy1aDNohUauo/ALWuGGYZ7snhLpVj5n55nJMdULnWjlwJ0Zk0hmq0P94cU7P8mEDBGiMav9GEehXPrQ==", + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dev": true, "dependencies": { - "colorx": "*", - "commander": "*", - "marked": "*", - "minitpl": "0.0.3", - "mkdirp": "0.5.0", - "xutil": "0.0.9" + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, "bin": { - "docs": "bin/jsdocs", - "jsdocs": "bin/jsdocs" + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsdoc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/just-debounce-it": { @@ -3606,6 +3741,15 @@ "resolved": "https://registry.npmjs.org/just-debounce-it/-/just-debounce-it-3.2.0.tgz", "integrity": "sha512-WXzwLL0745uNuedrCsCs3rpmfD6DBaf7uuVwaq98/8dafURfgQaBsSpjiPp5+CW6Vjltwy9cOGI6qE71b3T8iQ==" }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/libp2p": { "version": "0.46.21", "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-0.46.21.tgz", @@ -3658,6 +3802,15 @@ "xsalsa20": "^1.1.0" } }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -3679,17 +3832,38 @@ "node": ">=10" } }, - "node_modules/marked": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.0.0.tgz", - "integrity": "sha512-2GsW34uXaFEGTQ/+3rCnNC6vUYTAgFuDLGl70v/aWinA5mIJtTrrFAmfbLOfVvgPyxXuDVL9He/7reCK+6j3Sw==", - "bin": { - "marked": "bin/marked.js" + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" }, - "engines": { - "node": ">= 18" + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" } }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, "node_modules/merge-options": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", @@ -3769,36 +3943,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minitpl": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/minitpl/-/minitpl-0.0.3.tgz", - "integrity": "sha512-8+ChEb7JN7p8ObzAl9bzNVbA7rZC+9VNPxBIYr6bKGDKd4dnsZyWQPorLAtAb62u/jz4UUXnx5GQHg99LCib5w==", - "bin": { - "minitpl": "bin/minitpl" - } - }, - "node_modules/mkdirp": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", - "integrity": "sha512-xjjNGy+ry1lhtIKcr2PT6ok3aszhQfgrUDp4OZLHacgRgFmF6XR9XCOJVcXlVGQonIqXcK1DvqgKKQOPWYGSfw==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, - "node_modules/mkdirp/node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==" - }, "node_modules/mortice": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mortice/-/mortice-3.0.1.tgz", @@ -4320,6 +4469,15 @@ "ms": "^2.1.1" } }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/retimer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/retimer/-/retimer-3.0.0.tgz", @@ -4637,6 +4795,12 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, "node_modules/uint8-varint": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/uint8-varint/-/uint8-varint-2.0.2.tgz", @@ -4666,6 +4830,12 @@ "multiformats": "^12.0.1" } }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "dev": true + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -4800,19 +4970,17 @@ "node": ">=4.0" } }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, "node_modules/xsalsa20": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/xsalsa20/-/xsalsa20-1.2.0.tgz", "integrity": "sha512-FIr/DEeoHfj7ftfylnoFt3rAIRoWXpx2AoDfrT2qD2wtp7Dp+COajvs/Icb7uHqRW9m60f5iXZwdsJJO3kvb7w==" }, - "node_modules/xutil": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/xutil/-/xutil-0.0.9.tgz", - "integrity": "sha512-U3S6/3d3NOZGsONKi0v/+enJ/IEwMr0/AJlEBveO5ouM0rtGx+hPC8f5m3vAiLycP9Z11rSqUUEygj7NOKbnTw==", - "bin": { - "xutil": "bin/xutil" - } - }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index a5b5ad9..589b848 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "devDependencies": { "prettier": "3.1.0", "run-script-os": "1.1.6", - "typescript": "5.3.2" + "typescript": "5.3.2", + "jsdoc": "4.0.2" }, "dependencies": { "@aws-sdk/client-s3": "3.454.0", @@ -35,7 +36,6 @@ "blockstore-fs": "1.1.6", "dotenv": "16.3.1", "helia": "2.1.0", - "jsdocs": "1.0.0", "uuid": "9.0.1" } } diff --git a/src/bucketManager.js b/src/bucketManager.js index f2d1f81..d023a64 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -10,7 +10,7 @@ import { * @classdesc Provides methods for managing buckets in an S3 endpoint. */ class BucketManager { - #client; + client; /** * Creates a new instance of the S3Client class. @@ -18,8 +18,10 @@ class BucketManager { * @param {Object} S3ClientConfig - The configuration object for the S3Client. */ constructor(S3ClientConfig) { - // Login to S3 Endpoint - this.#client = new S3Client(S3ClientConfig); + /** + * @property {Object} client Represents the client object for S3 API. + */ + this.client = new S3Client(S3ClientConfig); } /** @@ -33,7 +35,7 @@ class BucketManager { Bucket: name, }); - return await this.#client.send(command); + return await this.client.send(command); } /** @@ -44,7 +46,7 @@ class BucketManager { */ async list(listBucketOptions = {}) { const command = new ListBucketsCommand(listBucketOptions), - { Buckets } = await this.#client.send(command); + { Buckets } = await this.client.send(command); return Buckets; } @@ -60,7 +62,7 @@ class BucketManager { Bucket: name, }); - return await this.#client.send(command); + return await this.client.send(command); } } diff --git a/src/nameManager.js b/src/nameManager.js index 3449811..4ea7ca9 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -16,10 +16,10 @@ class NameManager { * @return {object} - The instance of the constructor. * */ - constructor(key, secret) { + constructor(key, secret, endpoint = "https://api.filebase.io/v1/names") { const encodedToken = Buffer.from(`${key}:${secret}`).toString("base64"); this.#client = axios.create({ - baseURL: "https://api.filebase.io/v1/names", + baseURL: endpoint, timeout: 60000, headers: { Authorization: encodedToken }, }); diff --git a/src/objectManager.js b/src/objectManager.js index dc41f79..a697489 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -27,7 +27,7 @@ import { once } from "node:events"; * @classdesc Interacts with an S3 client to perform various operations on objects in a bucket. */ class ObjectManager { - #client; + client; #defaultBucket; #maxConcurrentUploads = 4; @@ -46,8 +46,10 @@ class ObjectManager { maxConcurrentUploads: 4, }, ) { - // Login to S3 Endpoint - this.#client = new S3Client(S3ClientConfig); + /** + * @property {Object} client Represents the client object for S3 API. + */ + this.client = new S3Client(S3ClientConfig); this.#defaultBucket = defaultBucket; if (options?.maxConcurrentUploads) { @@ -63,10 +65,10 @@ class ObjectManager { * * @param {string} key - The key or path of the file in the bucket. * @param {Buffer|ReadableStream|Array} source - The content of the file to be uploaded. - * If an array of objects is provided, each object should have a 'path' property specifying the path of the file, - * which will be prefixed with a unique upload UUID, e.g., '/uploadUUID/path'. + * If an array of objects is provided, each object should have a 'path' property specifying the path of the file + * and a 'content' property specifying the content of the file. * @param {string} [bucket=this.#defaultBucket] - The bucket name. Default is the value of the defaultBucket property. - * @returns {Promise<*>} + * @returns {Promise} */ async upload(key, source, bucket = this.#defaultBucket) { // Setup Upload Options @@ -78,7 +80,7 @@ class ObjectManager { uploadUUID, ), uploadOptions = { - client: this.#client, + client: this.client, params: { Bucket: bucket, Key: key, @@ -137,14 +139,14 @@ class ObjectManager { Key: key, Body: source, }), - headResult = await this.#client.send(command), + headResult = await this.client.send(command), responseCid = process.env.NODE_ENV === "test" ? 1234567890 : headResult.Metadata.cid; // Delete Temporary Blockstore await rm(temporaryBlockstorePath, { recursive: true, force: true }); - if (parsedEntries.length === 0) { + if (Object.keys(parsedEntries).length === 0) { return { cid: responseCid, }; @@ -167,7 +169,7 @@ class ObjectManager { Bucket: bucket, Key: key, }), - response = await this.#client.send(command); + response = await this.client.send(command); return response.Body; } @@ -194,7 +196,7 @@ class ObjectManager { bucketContents = []; while (isTruncated && bucketContents.length < limit) { const { Contents, IsTruncated, NextContinuationToken } = - await this.#client.send(command); + await this.client.send(command); if (typeof Contents === "undefined") { isTruncated = false; continue; @@ -219,7 +221,7 @@ class ObjectManager { Key: key, }); - return await this.#client.send(command); + return await this.client.send(command); } /** @@ -245,7 +247,7 @@ class ObjectManager { Key: destinationKey || sourceKey, }); - return await this.#client.send(command); + return await this.client.send(command); } } From fa1a7a3c07d549bb1e38721a25b22c2770df119a Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 30 Nov 2023 18:02:01 -0600 Subject: [PATCH 04/79] Documentation Updates --- jsdoc.json | 16 ++- package-lock.json | 328 +++++++++++++++++++++++++++++++++++++++++++ package.json | 5 +- readme.md | 68 +++++++++ src/bucketManager.js | 19 +-- src/nameManager.js | 26 ++-- src/objectManager.js | 48 ++++--- 7 files changed, 451 insertions(+), 59 deletions(-) create mode 100644 readme.md diff --git a/jsdoc.json b/jsdoc.json index d19082a..1172994 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -1,16 +1,22 @@ { "source": { - "include": ["src"], + "include": ["src", "package.json"], "includePattern": ".js$", "excludePattern": "(node_modules/|docs)" }, - "plugins": ["plugins/markdown"], + "plugins": ["plugins/markdown", "plugins/summarize"], "templates": { - "cleverLinks": true, - "monospaceLinks": true + "referenceTitle": "Filebase SDK", + "cleverLinks": true }, "opts": { + "template": "node_modules/clean-jsdoc-theme", "recurse": true, - "destination": "./documentation/" + "destination": "./documentation/", + "readme": "./readme.md", + "theme_opts": { + "title": "Filebase SDK", + "homepageTitle": "Filebase SDK" + } } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 17d83d7..55ff06a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "uuid": "9.0.1" }, "devDependencies": { + "clean-jsdoc-theme": "^4.2.17", "jsdoc": "4.0.2", "prettier": "3.1.0", "run-script-os": "1.1.6", @@ -1087,6 +1088,64 @@ "npm": ">=7.0.0" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jsdoc/salty": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.6.tgz", @@ -2562,6 +2621,18 @@ "npm": ">=7.0.0" } }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/any-signal": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/any-signal/-/any-signal-4.1.1.tgz", @@ -2714,6 +2785,22 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -2739,6 +2826,35 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-jsdoc-theme": { + "version": "4.2.17", + "resolved": "https://registry.npmjs.org/clean-jsdoc-theme/-/clean-jsdoc-theme-4.2.17.tgz", + "integrity": "sha512-5SbJNXcQHUXd7N13g+3OpGFiBQdxz36xwEP3p1r1vbo/apLcDRtugaFdUZ56H6Rvlb68Q33EChoBkajSlnD11w==", + "dev": true, + "dependencies": { + "@jsdoc/salty": "^0.2.4", + "fs-extra": "^10.1.0", + "html-minifier-terser": "^7.2.0", + "klaw-sync": "^6.0.0", + "lodash": "^4.17.21", + "showdown": "^2.1.0" + }, + "peerDependencies": { + "jsdoc": ">=3.x <=4.x" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2750,6 +2866,15 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2892,6 +3017,16 @@ "node": ">=6" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/dotenv": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", @@ -3054,6 +3189,20 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/get-iterator": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.1.tgz", @@ -3144,6 +3293,39 @@ "uint8arrays": "^4.0.3" } }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/human-signals": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", @@ -3736,6 +3918,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/just-debounce-it": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/just-debounce-it/-/just-debounce-it-3.2.0.tgz", @@ -3750,6 +3944,15 @@ "graceful-fs": "^4.1.9" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/libp2p": { "version": "0.46.21", "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-0.46.21.tgz", @@ -3821,6 +4024,15 @@ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4083,6 +4295,16 @@ "node": ">= 0.4.0" } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-abi": { "version": "3.51.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.51.0.tgz", @@ -4286,6 +4508,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4469,6 +4711,15 @@ "ms": "^2.1.1" } }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/requizzle": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", @@ -4566,6 +4817,31 @@ "node": ">=8" } }, + "node_modules/showdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", + "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==", + "dev": true, + "dependencies": { + "commander": "^9.0.0" + }, + "bin": { + "showdown": "bin/showdown.js" + }, + "funding": { + "type": "individual", + "url": "https://www.paypal.me/tiviesantos" + } + }, + "node_modules/showdown/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -4614,6 +4890,25 @@ "simple-concat": "^1.0.0" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/sparse-array": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/sparse-array/-/sparse-array-1.3.2.tgz", @@ -4732,6 +5027,30 @@ "ieee754": "^1.1.13" } }, + "node_modules/terser": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -4841,6 +5160,15 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", diff --git a/package.json b/package.json index 589b848..c0f8f87 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,11 @@ "keywords": [], "author": "", "devDependencies": { + "clean-jsdoc-theme": "^4.2.17", + "jsdoc": "4.0.2", "prettier": "3.1.0", "run-script-os": "1.1.6", - "typescript": "5.3.2", - "jsdoc": "4.0.2" + "typescript": "5.3.2" }, "dependencies": { "@aws-sdk/client-s3": "3.454.0", diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..0e39eb3 --- /dev/null +++ b/readme.md @@ -0,0 +1,68 @@ +

💾
Filebase SDK

+

Developer Friendly [ IPFS | IPNS | S3 ]

+ +## About + +The Filebase SDK provides a hybrid data management solution, blending S3-compatible cloud storage with IPFS +(InterPlanetary File System) pinning services. It features robust S3 bucket management, object handling for uploads and +downloads, and seamless integration with IPFS and IPNS (InterPlanetary Naming System) for decentralized storage +operations. The SDK supports advanced data tasks like compiling files into CAR (Content Addressable aRchive) formats and +ensures secure transactions through strong authentication. Designed for varied applications, the Filebase SDK is ideal +for scenarios demanding the dependability of cloud storage combined with the advantages of decentralized, peer-to-peer +storage, catering to diverse needs such as content distribution, data backup, and archival. + +### JS Client + +Install the package using npm + +```shell +npm install filebase-sdk +``` + +or yarn: + +```shell +yarn add filebase-sdk +``` + +### Getting started + +The snippet below shows how to create a new bucket with `BucketManager`, upload a new object to IPFS +with `ObjectManager`, and publish the object to IPNS with `NameManager`. + +To use the library in your project, use npm or yarn to install the [`filebase-sdk`](https://www.npmjs.com/package/filebase-sdk) module. + +**node.js** +````js +import {BucketManager, ObjectManager, NameManager} from 'filebase-sdk' + +createBucket S3 + +uploadObject IPFS + +createAndPublishName IPNS +```` + +Full API reference doc for the JS client are available at https://filebase.github.io/filebase-sdk + +### Building filebase-sdk + +Want to help us improve filebase-sdk? This project uses node v20 and npm v9 + +Install the deps with `npm` + +```console +# install deps +npm install +``` + +Build code from src with `npm` + +```console +# build from src +npm run build +``` + +### Testing + +Test are found in the `test` directory and are built to be run with the Node.js v20+ test runner. \ No newline at end of file diff --git a/src/bucketManager.js b/src/bucketManager.js index d023a64..8e49b00 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -5,28 +5,23 @@ import { S3Client, } from "@aws-sdk/client-s3"; -/** - * @class BucketManager - * @classdesc Provides methods for managing buckets in an S3 endpoint. - */ +/** Provides methods for managing buckets in an S3 endpoint. */ class BucketManager { client; /** - * Creates a new instance of the S3Client class. - * + * @summary Creates a new instance of the S3Client class. * @param {Object} S3ClientConfig - The configuration object for the S3Client. */ constructor(S3ClientConfig) { /** - * @property {Object} client Represents the client object for S3 API. + * @property {Object} client Represents the client object for S3 API. */ this.client = new S3Client(S3ClientConfig); } /** - * Creates a new bucket with the specified name. - * + * @summary Creates a new bucket with the specified name. * @param {string} name - The name of the bucket to create. * @returns {Promise<*>} - A promise that resolves when the bucket is created. */ @@ -39,8 +34,7 @@ class BucketManager { } /** - * Lists the buckets in the client. - * + * @summary Lists the buckets in the client. * @param {Object} listBucketOptions - The options for listing buckets. * @returns {Promise>} - A promise that resolves with an array of objects representing the buckets in the client. */ @@ -52,8 +46,7 @@ class BucketManager { } /** - * Deletes the specified bucket. - * + * @summary Deletes the specified bucket. * @param {string} name - The name of the bucket to delete. * @returns {Promise} - A promise that resolves when the bucket is deleted. */ diff --git a/src/nameManager.js b/src/nameManager.js index 4ea7ca9..4dca66e 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -1,15 +1,11 @@ import axios from "axios"; -/** - * @class NameManager - * @classdesc Represents a NameManager object that provides methods for managing names and associated content identifiers (CIDs) using a Filebase API. - */ +/** Provides methods for managing names in an REST endpoint. */ class NameManager { #client; /** - * Creates a new instance of the constructor. - * + * @summary Creates a new instance of the constructor. * @param {string} key - The key required for authorization. * @param {string} secret - The secret required for authorization. * @@ -26,7 +22,8 @@ class NameManager { } /** - * Creates a new object with the given name and CID. + + * @summary Creates a new object with the given name and CID. * @param {string} name - The name of the object. * @param {string} [cid] - The CID of the object. Default value is "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn". * @returns {Promise<*>} - A Promise that resolves with the response JSON. @@ -43,8 +40,7 @@ class NameManager { } /** - * Imports a user's IPNS private key. - * + * @summary Imports a user's IPNS private key. * @param {String} name - The name of the user. * @param {String} privateKey - The user's private key. * @param {Number} [sequence=1] - The sequence number. @@ -71,8 +67,7 @@ class NameManager { } /** - * Sets the specified name with the given cid and optional sequence. - * + * @summary Sets the specified name with the given cid and optional sequence. * @param {string} name - The name to set. * @param {string} cid - The cid to associate with the name. * @param {number|boolean} [sequence=false] - The optional sequence number to set. @@ -96,8 +91,7 @@ class NameManager { } /** - * Retrieves current value from the server based on the given name parameter. - * + * @summary Retrieves current value from the server based on the given name parameter. * @param {string} name - The name parameter to fetch the current value for. * @returns {Promise<*>} - A promise that resolves with the fetched data. */ @@ -110,8 +104,7 @@ class NameManager { } /** - * Returns a list of names with the specified limit and options. - * + * @summary Returns a list of names with the specified limit and options. * @param {number} limit - The maximum number of names to retrieve. Default is 1000. * @param {object} options - Additional options for retrieving the names. Default is { continuationToken: false }. * @returns {Promise<*>} - A promise that resolves to an array of names. @@ -142,8 +135,7 @@ class NameManager { } /** - * Deletes a resource with the given name. - * + * @summary Deletes a resource with the given name. * @param {string} name - The name of the resource to delete. * @returns {Promise} - A promise that resolves to true if the resource is successfully deleted, otherwise false. */ diff --git a/src/objectManager.js b/src/objectManager.js index a697489..7562031 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -22,18 +22,14 @@ import { mkdir, rm } from "node:fs/promises"; import { Readable } from "node:stream"; import { once } from "node:events"; -/** - * @class ObjectManager - * @classdesc Interacts with an S3 client to perform various operations on objects in a bucket. - */ +/** Interacts with an S3 client to perform various operations on objects in a bucket. */ class ObjectManager { client; #defaultBucket; #maxConcurrentUploads = 4; /** - * Creates a new instance of the class. - * + * @summary Creates a new instance of the class. * @param {S3ClientConfig} S3ClientConfig - The configuration object for the S3 client. * @param {string} defaultBucket - The default S3 bucket to be used. * @param {object} options - Optional settings for the constructor. @@ -58,11 +54,11 @@ class ObjectManager { } /** - * Uploads a file or a CAR file to the specified bucket. * If the source parameter is an array of objects, it will pack multiple files into a CAR file for upload. * The method returns a Promise that resolves to an object containing the CID (Content Identifier) of the uploaded file * and an optional entries object when uploading a CAR file. * + * @summary Uploads a file or a CAR file to the specified bucket. * @param {string} key - The key or path of the file in the bucket. * @param {Buffer|ReadableStream|Array} source - The content of the file to be uploaded. * If an array of objects is provided, each object should have a 'path' property specifying the path of the file @@ -158,8 +154,7 @@ class ObjectManager { } /** - * Downloads an object from the specified bucket using the provided key. - * + * @summary Downloads an object from the specified bucket using the provided key. * @param {string} key - The key of the object to be downloaded. * @param {string} [bucket] - The name of the bucket to download from. If not provided, the default bucket will be used. * @returns {Promise} - A promise that resolves with the contents of the downloaded object as a Buffer. @@ -177,18 +172,25 @@ class ObjectManager { /** * Retrieves a list of objects from a specified bucket. * - * @param {Object} listOptions - An object containing options for listing objects (default: {}). - * @param {string} bucket - The name of the bucket to retrieve objects from (default: this.#defaultBucket). - * @param {number} limit - The maximum number of objects to retrieve (default: 1000). + * @param {Object} options - The options for listing objects. Accepts S3 SDK ListObjectsRequest parameters. + * @param {string} [options.Bucket] - The name of the bucket. If not provided, the default bucket will be used. + * @param {number} [options.MaxKeys] - The maximum number of objects to retrieve. Defaults to 1000. * @returns {Promise} - A promise that resolves to an array of objects. */ - async list(listOptions = {}, bucket = this.#defaultBucket, limit = 1000) { - const commandOptions = { + async list( + options = { + Bucket: this.#defaultBucket, + MaxKeys: 1000, + }, + ) { + const bucket = options?.Bucket || this.#defaultBucket, + limit = options?.MaxKeys || 1000, + commandOptions = { Bucket: bucket, MaxKeys: limit, }, command = new ListObjectsV2Command({ - ...listOptions, + ...options, ...commandOptions, }); @@ -209,8 +211,7 @@ class ObjectManager { } /** - * Deletes an object from the specified bucket using the provided key. - * + * @summary Deletes an object from the specified bucket using the provided key. * @param {string} key - The key of the object to be deleted. * @param {string} [bucket=this.#defaultBucket] - The name of the bucket that contains the object. Defaults to the default bucket. * @returns {Promise<*>} - A Promise that resolves with the result of the delete operation. @@ -225,21 +226,24 @@ class ObjectManager { } /** - * Copy the object from sourceKey in the sourceBucket to destinationKey in the destinationBucket. * If the destinationKey is not provided, the object will be copied with the same key as the sourceKey. * + * @summary Copy the object from sourceKey in the sourceBucket to destinationKey in the destinationBucket. * @param {string} sourceKey - The key of the object to be copied from the sourceBucket. * @param {string} destinationBucket - The bucket where the object will be copied to. - * @param {string} [sourceBucket=this.#defaultBucket] - The bucket from which the object will be copied (default is the default bucket). - * @param {string} [destinationKey=null] - The key of the copied object in the destinationBucket (default is the same as sourceKey). + * @param {object} [options] - Additional options for the copy operation. + * @param {string} [options.sourceBucket=this.#defaultBucket] - The source bucket from where the object is to be copied. + * @param {string} [options.destinationKey] - The key of the object in the destination bucket. By default, it is the same as the sourceKey. * * @returns {Promise<*>} - A Promise that resolves with the response of the copy operation. */ async copy( sourceKey, destinationBucket, - sourceBucket = this.#defaultBucket, - destinationKey = null, + options = { + sourceBucket: this.#defaultBucket, + destinationKey: undefined, + }, ) { const command = new CopyObjectCommand({ CopySource: `${sourceBucket}/${sourceKey}`, From 1560e5df8e6901558c6e311b11a25a6282cce7df Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 30 Nov 2023 18:14:06 -0600 Subject: [PATCH 05/79] Update Tests --- {tests => test}/bucketManager.spec.js | 2 +- {tests => test}/objectManager.spec.js | 31 +++++++++++++++++++++++++-- {tests => test}/package.json | 0 3 files changed, 30 insertions(+), 3 deletions(-) rename {tests => test}/bucketManager.spec.js (97%) rename {tests => test}/objectManager.spec.js (87%) rename {tests => test}/package.json (100%) diff --git a/tests/bucketManager.spec.js b/test/bucketManager.spec.js similarity index 97% rename from tests/bucketManager.spec.js rename to test/bucketManager.spec.js index 20d2887..40a3adf 100644 --- a/tests/bucketManager.spec.js +++ b/test/bucketManager.spec.js @@ -1,6 +1,6 @@ import test from "node:test"; import assert from "node:assert/strict"; -import BucketManager from "../src/bucketManager.mjs"; +import BucketManager from "../src/bucketManager.js"; const s3Config = { endpoint: process.env.TEST_S3_ENDPOINT, diff --git a/tests/objectManager.spec.js b/test/objectManager.spec.js similarity index 87% rename from tests/objectManager.spec.js rename to test/objectManager.spec.js index 1a2b72f..cb2cbed 100644 --- a/tests/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -64,6 +64,33 @@ test("upload object", async () => { assert.strictEqual(uploaded, true); }); +test("upload directory", async () => { + // Create Bucket `create-object-test-pass + const uploadDirectoryTestBucket = `create-directory-test-pass`; + await createBucket(uploadDirectoryTestBucket); + + // Upload object `create-object-test` + const uploaded = await uploadObject( + uploadDirectoryTestBucket, + `create-directory-test`, + [ + { + path: "/testObjects/1.txt", + content: Buffer.from("upload test object", "utf-8"), + }, + { + path: "/testObjects/deep/1.txt", + content: Buffer.from("upload deep test object", "utf-8"), + }, + { + path: "/topLevel.txt", + content: Buffer.from("upload top level test object", "utf-8"), + }, + ], + ); + assert.strictEqual(uploaded, true); +}); + test("download object", async () => { // Create bucket `download-object-test-pass` const downloadTestBucket = `download-object-test-pass`; @@ -147,7 +174,7 @@ test("delete object", async () => { assert.equal(typeof uploadedObject, "undefined"); }); -/*test("copy object", async () => { +test("copy object", async () => { // Create bucket `copy-object-test-pass-src` const bucketSrc = `copy-object-test-pass-src`; await createBucket(bucketSrc); @@ -177,4 +204,4 @@ test("delete object", async () => { }), copiedObject = existingObjects.length > 0 ? existingObjects[0] : undefined; assert.equal(copiedObject.Name, objectNameToCreateSrc); -});*/ +}); diff --git a/tests/package.json b/test/package.json similarity index 100% rename from tests/package.json rename to test/package.json From ff847fc5c0d90c5486ad837d0db857effcd52bc5 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Fri, 1 Dec 2023 16:56:37 -0600 Subject: [PATCH 06/79] Update nameManager.js Remove sequence support --- src/nameManager.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/nameManager.js b/src/nameManager.js index 4dca66e..e00186f 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -43,7 +43,6 @@ class NameManager { * @summary Imports a user's IPNS private key. * @param {String} name - The name of the user. * @param {String} privateKey - The user's private key. - * @param {Number} [sequence=1] - The sequence number. * @param {String} [cid="QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"] - The CID (Content Identifier) of the data. * * @returns {Promise} - A Promise that resolves to the server response. @@ -51,7 +50,6 @@ class NameManager { async import( name, privateKey, - sequence = 1, cid = "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn", ) { const importResponse = await this.#client.request({ @@ -59,7 +57,6 @@ class NameManager { data: { name, privateKey, - sequence, cid, }, }); From a9cdaec0401ed629f5f4d0019b51851307fabf2d Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Fri, 1 Dec 2023 16:58:31 -0600 Subject: [PATCH 07/79] Update nameManager.js Remove sequence support --- src/nameManager.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/nameManager.js b/src/nameManager.js index e00186f..f99c447 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -64,19 +64,12 @@ class NameManager { } /** - * @summary Sets the specified name with the given cid and optional sequence. + * @summary Sets the specified name with the given cid. * @param {string} name - The name to set. * @param {string} cid - The cid to associate with the name. - * @param {number|boolean} [sequence=false] - The optional sequence number to set. * @returns {Promise} - A Promise that resolves with the response data from the server. */ - async set(name, cid, sequence = false) { - const setOptions = { - cid, - }; - if (sequence) { - setOptions.sequence = Number(sequence); - } + async set(name, cid) { const setResponse = await this.#client.request({ method: "PUT", url: `/${name}`, From cdd0f98cf0c9c842246980f2fce369930acefdf6 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sat, 2 Dec 2023 19:56:55 -0600 Subject: [PATCH 08/79] Add Code Examples --- readme.md | 44 ++++++++++++++++++++++++---- src/nameManager.js | 73 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 93 insertions(+), 24 deletions(-) diff --git a/readme.md b/readme.md index 0e39eb3..454e606 100644 --- a/readme.md +++ b/readme.md @@ -9,7 +9,8 @@ downloads, and seamless integration with IPFS and IPNS (InterPlanetary Naming Sy operations. The SDK supports advanced data tasks like compiling files into CAR (Content Addressable aRchive) formats and ensures secure transactions through strong authentication. Designed for varied applications, the Filebase SDK is ideal for scenarios demanding the dependability of cloud storage combined with the advantages of decentralized, peer-to-peer -storage, catering to diverse needs such as content distribution, data backup, and archival. +storage, catering to diverse needs such as content distribution, data backup, and archival. Developing InterPlanetary +Applications has never been easier. ### JS Client @@ -34,13 +35,44 @@ To use the library in your project, use npm or yarn to install the [`filebase-sd **node.js** ````js +// Import Classes import {BucketManager, ObjectManager, NameManager} from 'filebase-sdk' -createBucket S3 - -uploadObject IPFS - -createAndPublishName IPNS +// Setup S3 Config +const s3Config = {}; + +// Initialize BucketManager +const bucketManager = new BucketManager(s3Config); +// Create bucket +const bucketName = `create-bucket-[random string]`; +await bucketManager.create(bucketName); +// List buckets +const bucketsList = await bucketManager.list(); +console.dir(bucketsList); + +// Initialize ObjectManager +const objectManager = new ObjectManager(s3Config, bucketName); +// Upload Object +const uploadedObject = await objectManager.upload(key, body); +// Confirm Object Uploaded +const objectsList = await objectManager.list({ + Prefix: key, + MaxKeys: 1, + }); +console.dir(objectsList) + +// Initialize NameManager +const nameManager = new NameManager(s3Config); +// Create New IPNS Name with Broadcast Disabled +const ipnsName = await nameManager.create(`myFirstIpnsKey`, uploadedObject.cid, { + enabled: true +}); +// Update IPNS Value and Optionally Enable the Broadcast +await nameManager.set(`myFirstIpnsKey`, uploadedObject.cid, { + enabled: true, +}); +// Enable IPNS Broadcast without updating the IPNS Record +await nameManager.toggle(`myFirstIpnsKey`, true); ```` Full API reference doc for the JS client are available at https://filebase.github.io/filebase-sdk diff --git a/src/nameManager.js b/src/nameManager.js index f99c447..3ae5325 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -8,9 +8,9 @@ class NameManager { * @summary Creates a new instance of the constructor. * @param {string} key - The key required for authorization. * @param {string} secret - The secret required for authorization. + * @param {string} [endpoint="https://api.filebase.io/v1/names"] - The endpoint URL for the API. * * @return {object} - The instance of the constructor. - * */ constructor(key, secret, endpoint = "https://api.filebase.io/v1/names") { const encodedToken = Buffer.from(`${key}:${secret}`).toString("base64"); @@ -22,18 +22,29 @@ class NameManager { } /** - - * @summary Creates a new object with the given name and CID. + * @summary Creates a new IPNS name with the given name and CID. * @param {string} name - The name of the object. - * @param {string} [cid] - The CID of the object. Default value is "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn". - * @returns {Promise<*>} - A Promise that resolves with the response JSON. + * @param {null|string} [cid] - The CID of the object. Default value is null. + * @param {object} [options] - Additional options for the IPNS name. + * @param {boolean} [options.enabled=true] - Whether the IPNS name is enabled or not. + * @returns {Promise} - A Promise that resolves with the response JSON. */ - async create(name, cid = "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn") { + async create( + name, + cid = null, + options = { + enabled: true, + }, + ) { + if (typeof name !== "string") { + throw new Error(`param [name] is required and must be a string`); + } const createResponse = await this.#client.request({ method: "POST", data: { name, cid, + enabled: options?.enabled !== false, }, }); return createResponse.json(); @@ -41,17 +52,19 @@ class NameManager { /** * @summary Imports a user's IPNS private key. - * @param {String} name - The name of the user. - * @param {String} privateKey - The user's private key. - * @param {String} [cid="QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"] - The CID (Content Identifier) of the data. + * @param {string} name - The name of the user. + * @param {string} privateKey - The user's private key. + * @param {null|string} [cid=null] - The CID (Content Identifier) of the data. * * @returns {Promise} - A Promise that resolves to the server response. */ - async import( - name, - privateKey, - cid = "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn", - ) { + async import(name, privateKey, cid = null) { + if (typeof name !== "string") { + throw new Error(`param [name] is required and must be a string`); + } + if (typeof privateKey !== "string") { + throw new Error(`param [privateKey] is required and must be a string`); + } const importResponse = await this.#client.request({ method: "POST", data: { @@ -67,15 +80,22 @@ class NameManager { * @summary Sets the specified name with the given cid. * @param {string} name - The name to set. * @param {string} cid - The cid to associate with the name. + * @param {Object} options - The options for the set operation. + * @param {boolean} [options.enabled] - Whether the name is enabled (default: false). + * * @returns {Promise} - A Promise that resolves with the response data from the server. */ - async set(name, cid) { + async set(name, cid, options = {}) { + const setOptions = { + cid, + }; + if (options?.enabled) { + setOptions.enabled = Boolean(options.enabled); + } const setResponse = await this.#client.request({ method: "PUT", url: `/${name}`, - data: { - cid, - }, + data: setOptions, }); return setResponse.json(); } @@ -136,6 +156,23 @@ class NameManager { }); return createResponse.status === 200; } + + /** + * @summary Toggles the enabled state of a given IPNS name. + * @param {string} name - The name of the item to toggle. + * @param {boolean} enabled - The new enabled state. + * @returns {Promise} - A promise that resolves to the response data. + */ + async toggle(name, enabled) { + const enableResponse = await this.#client.request({ + method: "PUT", + url: `/${name}`, + data: { + enabled: enabled, + }, + }); + return enableResponse.json(); + } } export default NameManager; From 9d7103cfb3194e4a76302c58775799dc5120bbe6 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sat, 2 Dec 2023 20:04:31 -0600 Subject: [PATCH 09/79] Update readme.md Minor Example Changes --- readme.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 454e606..d91627e 100644 --- a/readme.md +++ b/readme.md @@ -29,7 +29,8 @@ yarn add filebase-sdk ### Getting started The snippet below shows how to create a new bucket with `BucketManager`, upload a new object to IPFS -with `ObjectManager`, and publish the object to IPNS with `NameManager`. +with `ObjectManager`, publish the object to IPNS with `NameManager`, delete the object with `ObjectManager` and finally +delete the bucket with `BucketManager`. To use the library in your project, use npm or yarn to install the [`filebase-sdk`](https://www.npmjs.com/package/filebase-sdk) module. @@ -53,7 +54,8 @@ console.dir(bucketsList); // Initialize ObjectManager const objectManager = new ObjectManager(s3Config, bucketName); // Upload Object -const uploadedObject = await objectManager.upload(key, body); +const objectName = `new-object`; +const uploadedObject = await objectManager.upload(objectName, body); // Confirm Object Uploaded const objectsList = await objectManager.list({ Prefix: key, @@ -73,6 +75,12 @@ await nameManager.set(`myFirstIpnsKey`, uploadedObject.cid, { }); // Enable IPNS Broadcast without updating the IPNS Record await nameManager.toggle(`myFirstIpnsKey`, true); + +// Delete Object +await objectManager.delete(objectName); + +// Delete Bucket +await bucketManager.delete(bucketName) ```` Full API reference doc for the JS client are available at https://filebase.github.io/filebase-sdk From da9e8316c4e65c334af364b1b14e5de21146721d Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:10:01 -0600 Subject: [PATCH 10/79] Update Authentication --- src/bucketManager.js | 6 ++--- src/nameManager.js | 55 ++++++++++++++++++++++++++++++++++++++------ src/objectManager.js | 6 ++--- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/bucketManager.js b/src/bucketManager.js index 8e49b00..397eb3d 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -11,13 +11,13 @@ class BucketManager { /** * @summary Creates a new instance of the S3Client class. - * @param {Object} S3ClientConfig - The configuration object for the S3Client. + * @param {Object} clientConfig - The configuration object for the S3Client. */ - constructor(S3ClientConfig) { + constructor(clientConfig) { /** * @property {Object} client Represents the client object for S3 API. */ - this.client = new S3Client(S3ClientConfig); + this.client = new S3Client(clientConfig); } /** diff --git a/src/nameManager.js b/src/nameManager.js index 3ae5325..fd9ff5e 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -2,25 +2,66 @@ import axios from "axios"; /** Provides methods for managing names in an REST endpoint. */ class NameManager { + #DEFAULT_ENDPOINT = "https://api.filebase.io/v1/names"; + #DEFAULT_TIMEOUT = 60000; + #client; /** * @summary Creates a new instance of the constructor. - * @param {string} key - The key required for authorization. - * @param {string} secret - The secret required for authorization. - * @param {string} [endpoint="https://api.filebase.io/v1/names"] - The endpoint URL for the API. + * @param {object} clientConfig - The configuration object for the client. + * @param {object} clientConfig.credentials - The credentials object for authentication. + * @param {string} clientConfig.credentials.accessKeyId - The access key ID for authentication. + * @param {string} clientConfig.credentials.secretAccessKey - The secret access key for authentication. + * @param {string} [clientConfig.endpoint="https://api.filebase.io/v1/names"] - The API endpoint URL. * * @return {object} - The instance of the constructor. */ - constructor(key, secret, endpoint = "https://api.filebase.io/v1/names") { - const encodedToken = Buffer.from(`${key}:${secret}`).toString("base64"); + constructor( + clientConfig = { + credentials: { + accessKeyId: null, + secretAccessKey: null, + }, + }, + ) { + const configErrors = this.#validateClientConfig(clientConfig); + if (configErrors.length > 0) { + throw new Error(configErrors.join("\n")); + } + + const encodedToken = Buffer.from( + `${clientConfig.credentials.accessKeyId}:${clientConfig.credentials.secretAccessKey}`, + ).toString("base64"), + baseURL = clientConfig.endpoint || this.#DEFAULT_ENDPOINT; this.#client = axios.create({ - baseURL: endpoint, - timeout: 60000, + baseURL: baseURL, + timeout: this.#DEFAULT_TIMEOUT, headers: { Authorization: encodedToken }, }); } + /** + * @summary Validates the client configuration. + * @param {object} clientConfig - The client configuration object. + * @returns {string[]} - An array containing any validation errors found in the client configuration. + */ + #validateClientConfig(clientConfig) { + let configErrors = []; + + if (typeof clientConfig?.credentials?.accessKeyId !== "string") { + configErrors.push("clientConfig must contain credentials.accessKeyId"); + } + + if (typeof clientConfig?.credentials?.secretAccessKey !== "string") { + configErrors.push( + "clientConfig must contain credentials.secretAccessKey", + ); + } + + return configErrors; + } + /** * @summary Creates a new IPNS name with the given name and CID. * @param {string} name - The name of the object. diff --git a/src/objectManager.js b/src/objectManager.js index 7562031..51d21a8 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -30,13 +30,13 @@ class ObjectManager { /** * @summary Creates a new instance of the class. - * @param {S3ClientConfig} S3ClientConfig - The configuration object for the S3 client. + * @param {object} clientConfig - The configuration object for the S3 client. * @param {string} defaultBucket - The default S3 bucket to be used. * @param {object} options - Optional settings for the constructor. * @param {number} options.maxConcurrentUploads - The maximum number of concurrent uploads. */ constructor( - S3ClientConfig, + clientConfig, defaultBucket, options = { maxConcurrentUploads: 4, @@ -45,7 +45,7 @@ class ObjectManager { /** * @property {Object} client Represents the client object for S3 API. */ - this.client = new S3Client(S3ClientConfig); + this.client = new S3Client(clientConfig); this.#defaultBucket = defaultBucket; if (options?.maxConcurrentUploads) { From e4dcf26cdce853e9d1d897967340292699c505be Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:40:03 -0600 Subject: [PATCH 11/79] Fixes and Tests Adds Tests for Names Switches Names to use Label instead of Name for Key Removes pagination of Names API Fixes CAR file uploads in objectManager Fixes test for objectManager lists --- src/nameManager.js | 87 ++++++++++++------------------------- src/objectManager.js | 80 ++++++++++++++++++---------------- test/nameManager.spec.js | 88 ++++++++++++++++++++++++++++++++++++++ test/objectManager.spec.js | 2 +- 4 files changed, 161 insertions(+), 96 deletions(-) create mode 100644 test/nameManager.spec.js diff --git a/src/nameManager.js b/src/nameManager.js index fd9ff5e..8637aba 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -63,27 +63,27 @@ class NameManager { } /** - * @summary Creates a new IPNS name with the given name and CID. - * @param {string} name - The name of the object. - * @param {null|string} [cid] - The CID of the object. Default value is null. + * @summary Creates a new IPNS name with the given name as the label and CID. + * @param {string} label - The label of the new IPNS name. + * @param {null|string} [cid] - The CID of the IPNS name. Default value is null. * @param {object} [options] - Additional options for the IPNS name. * @param {boolean} [options.enabled=true] - Whether the IPNS name is enabled or not. * @returns {Promise} - A Promise that resolves with the response JSON. */ async create( - name, + label, cid = null, options = { enabled: true, }, ) { - if (typeof name !== "string") { - throw new Error(`param [name] is required and must be a string`); + if (typeof label !== "string") { + throw new Error(`param [label] is required and must be a string`); } const createResponse = await this.#client.request({ method: "POST", data: { - name, + label, cid, enabled: options?.enabled !== false, }, @@ -93,14 +93,14 @@ class NameManager { /** * @summary Imports a user's IPNS private key. - * @param {string} name - The name of the user. - * @param {string} privateKey - The user's private key. + * @param {string} label - The label for the IPNS name. + * @param {string} privateKey - The existing private key encoded in Base64. * @param {null|string} [cid=null] - The CID (Content Identifier) of the data. * * @returns {Promise} - A Promise that resolves to the server response. */ - async import(name, privateKey, cid = null) { - if (typeof name !== "string") { + async import(label, privateKey, cid = null) { + if (typeof label !== "string") { throw new Error(`param [name] is required and must be a string`); } if (typeof privateKey !== "string") { @@ -109,7 +109,7 @@ class NameManager { const importResponse = await this.#client.request({ method: "POST", data: { - name, + label, privateKey, cid, }, @@ -118,15 +118,15 @@ class NameManager { } /** - * @summary Sets the specified name with the given cid. - * @param {string} name - The name to set. + * @summary Updates the specified name with the given cid. + * @param {string} label - The label of the name to update. * @param {string} cid - The cid to associate with the name. * @param {Object} options - The options for the set operation. * @param {boolean} [options.enabled] - Whether the name is enabled (default: false). * * @returns {Promise} - A Promise that resolves with the response data from the server. */ - async set(name, cid, options = {}) { + async update(label, cid, options = {}) { const setOptions = { cid, }; @@ -135,79 +135,48 @@ class NameManager { } const setResponse = await this.#client.request({ method: "PUT", - url: `/${name}`, + url: `/${label}`, data: setOptions, }); return setResponse.json(); } /** - * @summary Retrieves current value from the server based on the given name parameter. - * @param {string} name - The name parameter to fetch the current value for. - * @returns {Promise<*>} - A promise that resolves with the fetched data. + * @summary Returns a list of IPNS name(s) + * @param {string} [label] - Optional string parameter representing the label of the name to list. + * @returns {Promise} - A promise that resolves to an array of names. */ - async get(name) { + async list(label = null) { const getResponse = await this.#client.request({ method: "GET", - url: `/${name}`, + url: typeof label === "string" ? `/${label}` : undefined, }); return getResponse.json(); } /** - * @summary Returns a list of names with the specified limit and options. - * @param {number} limit - The maximum number of names to retrieve. Default is 1000. - * @param {object} options - Additional options for retrieving the names. Default is { continuationToken: false }. - * @returns {Promise<*>} - A promise that resolves to an array of names. - */ - async list(limit = 1000, options = { continuationToken: false }) { - let names = [], - continuationToken = options?.continuationToken || false, - isTruncated = true, - fetchLimit = limit + 1; - while (isTruncated === true) { - let pageParams = { - limit: fetchLimit, - }; - if (continuationToken) { - pageParams.after = continuationToken; - } - const getResponse = await this.#client.request({ - method: "GET", - params: pageParams, - }), - pageNames = getResponse.json(); - if (pageNames.length < fetchLimit) { - isTruncated = false; - } - names = names.concat(pageNames); - } - return names.slice(0, limit); - } - - /** - * @summary Deletes a resource with the given name. - * @param {string} name - The name of the resource to delete. + * @summary Deletes an IPNS name with the given label. + * @param {string} label - The label of the IPNS name to delete. * @returns {Promise} - A promise that resolves to true if the resource is successfully deleted, otherwise false. */ - async delete(name) { + async delete(label) { const createResponse = await this.#client.request({ method: "DELETE", - url: `/${name}`, + url: `/${label}`, }); return createResponse.status === 200; } /** * @summary Toggles the enabled state of a given IPNS name. - * @param {string} name - The name of the item to toggle. + * @param {string} label - The label of the IPNS name to toggle. * @param {boolean} enabled - The new enabled state. * @returns {Promise} - A promise that resolves to the response data. */ - async toggle(name, enabled) { + async toggle(label, enabled) { const enableResponse = await this.#client.request({ method: "PUT", - url: `/${name}`, + url: `/${label}`, data: { enabled: enabled, }, diff --git a/src/objectManager.js b/src/objectManager.js index 51d21a8..fab0c66 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -17,10 +17,9 @@ import { unixfs } from "@helia/unixfs"; import { v4 as uuidv4 } from "uuid"; import path from "node:path"; import os from "node:os"; -import { createWriteStream, createReadStream } from "node:fs"; import { mkdir, rm } from "node:fs/promises"; import { Readable } from "node:stream"; -import { once } from "node:events"; +import { createWriteStream, createReadStream } from "node:fs"; /** Interacts with an S3 client to perform various operations on objects in a bucket. */ class ObjectManager { @@ -69,12 +68,13 @@ class ObjectManager { async upload(key, source, bucket = this.#defaultBucket) { // Setup Upload Options const uploadUUID = uuidv4(), - temporaryBlockstorePath = path.resolve( + temporaryBlockstoreDir = path.resolve( os.tmpdir(), "filebase-sdk", "uploads", uploadUUID, ), + temporaryCarFilePath = `${temporaryBlockstoreDir}/main.car`, uploadOptions = { client: this.client, params: { @@ -88,43 +88,48 @@ class ObjectManager { }; // Pack Multiple Files into CAR file for upload - let parsedEntries = {}, - carExporter; + let parsedEntries = {}; if (Array.isArray(source)) { // Mark Upload as a CAR file import uploadOptions.params.Metadata = { import: "car", }; - await mkdir(temporaryBlockstorePath, { recursive: true }); - const temporaryFsBlockstore = new FsBlockstore(temporaryBlockstorePath), - heliaFs = unixfs({ - blockstore: temporaryFsBlockstore, - }); + try { + await mkdir(temporaryBlockstoreDir, { recursive: true }); + const temporaryFsBlockstore = new FsBlockstore(temporaryBlockstoreDir), + heliaFs = unixfs({ + blockstore: temporaryFsBlockstore, + }); - for (let sourceEntry of source) { - sourceEntry.path = - sourceEntry.path[0] === "/" - ? `/${uploadUUID}${sourceEntry.path}` - : `/${uploadUUID}/${sourceEntry.path}`; - } - for await (const entry of heliaFs.addAll(source)) { - parsedEntries[entry.path] = entry; - } - const rootEntry = parsedEntries[uploadUUID]; + for (let sourceEntry of source) { + sourceEntry.path = + sourceEntry.path[0] === "/" + ? `/${uploadUUID}${sourceEntry.path}` + : `/${uploadUUID}/${sourceEntry.path}`; + } + for await (const entry of heliaFs.addAll(source)) { + parsedEntries[entry.path] = entry; + } + const rootEntry = parsedEntries[uploadUUID]; - // Get carFile stream here and override body - carExporter = car({ blockstore: temporaryFsBlockstore }); - const { writer, out } = CarWriter.create([rootEntry.cid]); - const carPromise = Readable.from(out); - await carExporter.export(rootEntry.cid, writer); + // Get carFile stream here + const carExporter = car({ blockstore: temporaryFsBlockstore }), + { writer, out } = CarWriter.create([rootEntry.cid]), + output = createWriteStream(temporaryCarFilePath); + Readable.from(out).pipe(output); + await carExporter.export(rootEntry.cid, writer); - // Upload file/carFile via S3 - const parallelUploads3 = new Upload(uploadOptions); - await parallelUploads3.done(); - await carPromise; + // Upload carFile via S3 + uploadOptions.params.Body = createReadStream(temporaryCarFilePath); + const parallelUploads3 = new Upload(uploadOptions); + await parallelUploads3.done(); + await temporaryFsBlockstore.close(); + } finally { + await rm(temporaryBlockstoreDir, { recursive: true }); + } } else { - // Upload file/carFile via S3 + // Upload file via S3 const parallelUploads3 = new Upload(uploadOptions); await parallelUploads3.done(); } @@ -140,7 +145,7 @@ class ObjectManager { process.env.NODE_ENV === "test" ? 1234567890 : headResult.Metadata.cid; // Delete Temporary Blockstore - await rm(temporaryBlockstorePath, { recursive: true, force: true }); + await rm(temporaryBlockstoreDir, { recursive: true, force: true }); if (Object.keys(parsedEntries).length === 0) { return { @@ -245,11 +250,14 @@ class ObjectManager { destinationKey: undefined, }, ) { - const command = new CopyObjectCommand({ - CopySource: `${sourceBucket}/${sourceKey}`, - Bucket: destinationBucket, - Key: destinationKey || sourceKey, - }); + const copySource = `${ + options?.sourceBucket || this.#defaultBucket + }/${sourceKey}`, + command = new CopyObjectCommand({ + CopySource: copySource, + Bucket: destinationBucket, + Key: options?.destinationKey || sourceKey, + }); return await this.client.send(command); } diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js new file mode 100644 index 0000000..0ad7f48 --- /dev/null +++ b/test/nameManager.spec.js @@ -0,0 +1,88 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import NameManager from "../src/nameManager.js"; + +const s3Config = { + endpoint: process.env.TEST_S3_ENDPOINT, + credentials: { + accessKeyId: process.env.TEST_S3_KEY, + secretAccessKey: process.env.TEST_S3_SECRET, + }, + region: process.env.TEST_S3_REGION, +}; + +test("delete name", async () => { + const testNameLabel = `delete-name-test-pass`, + nameManager = new NameManager(s3Config), + createdName = await nameManager.create(testNameLabel); + await nameManager.delete(testNameLabel); + assert.strictEqual(createdName.label, testNameLabel); +}); +test("create name", async () => { + const testNameLabel = `create-name-test-pass`, + nameManager = new NameManager(s3Config), + createdName = await nameManager.create(testNameLabel); + await nameManager.delete(testNameLabel); + assert.strictEqual(createdName.label, testNameLabel); +}); + +test("import name", async () => { + const testNameLabel = `import-name-test-pass`, + testNamePrivateKey = + "CAESQAzjYGmMMK9wjF7PpgC7v4YAGiirw6OQ3So5Sm23SvnUiHe6bfUNOFKmyCXRxh4yXVwFAtvYeq/bZGB1ROPgoWQ=", + nameManager = new NameManager(s3Config), + importedName = await nameManager.import(testNameLabel, testNamePrivateKey); + await nameManager.delete(testNameLabel); + assert.strictEqual(importedName.label, testNameLabel); +}); + +test("update name", async () => { + const testNameLabel = `update-name-test-pass`, + testNameValue = "QmeSNqhnDa45qg349oSaXGYx6FPsePGVqGCfHK7BWUwjub", + nameManager = new NameManager(s3Config), + createdName = await nameManager.create(testNameLabel), + updatedName = await nameManager.update(createdName.label, testNameValue); + await nameManager.delete(testNameLabel); + assert.strictEqual(updatedName.cid, testNameLabel); +}); + +test("list name", async () => { + const testNameLabel = `resolve-name-test-pass`, + testNameValue = "QmeSNqhnDa45qg349oSaXGYx6FPsePGVqGCfHK7BWUwjub", + nameManager = new NameManager(s3Config), + createdName = await nameManager.create(testNameLabel, testNameValue), + resolvedName = await nameManager.list(createdName.label); + await nameManager.delete(testNameLabel); + assert.strictEqual(resolvedName.cid, testNameValue); +}); + +test("list names", async () => { + const testNameLabel = `list-names-test-pass`, + nameManager = new NameManager(s3Config); + for (let i = 0; i < 10; i++) { + await nameManager.create(`${testNameLabel}-${i}`); + } + const namesList = await nameManager.list(); + await nameManager.delete(testNameLabel); + assert.strictEqual(namesList.length, 10); +}); + +test("toggle name", async () => { + const testNameLabel = `toggle-name-test-pass`, + nameManager = new NameManager(s3Config), + createdName = await nameManager.create( + testNameLabel, + "QmeSNqhnDa45qg349oSaXGYx6FPsePGVqGCfHK7BWUwjub", + { + enabled: false, + }, + ), + resolvedName = await nameManager.list(testNameLabel); + if (resolvedName?.enabled === true) { + throw new Error(`Incorrect State on Resolved Name`); + } + await nameManager.toggle(testNameLabel, true); + const updatedName = await nameManager.list(testNameLabel); + await nameManager.delete(testNameLabel); + assert.strictEqual(updatedName.enabled, true); +}); diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index cb2cbed..6994a02 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -136,7 +136,7 @@ test("list objects", async () => { const objectManager = new ObjectManager(s3Config, listTestBucket); const bucketList = await objectManager.list({ - MaxKeys: 5, + MaxKeys: 50, Prefix: `list-object-test-`, }); assert.equal(bucketList.length, 26); From cbdb19d06abae85d8878aa2f6cc5f9a398f9b9fd Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:42:30 -0600 Subject: [PATCH 12/79] Remove Copy from ObjectManager --- src/objectManager.js | 32 -------------------------------- test/objectManager.spec.js | 32 -------------------------------- 2 files changed, 64 deletions(-) diff --git a/src/objectManager.js b/src/objectManager.js index fab0c66..f9d3e50 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -229,38 +229,6 @@ class ObjectManager { return await this.client.send(command); } - - /** - * If the destinationKey is not provided, the object will be copied with the same key as the sourceKey. - * - * @summary Copy the object from sourceKey in the sourceBucket to destinationKey in the destinationBucket. - * @param {string} sourceKey - The key of the object to be copied from the sourceBucket. - * @param {string} destinationBucket - The bucket where the object will be copied to. - * @param {object} [options] - Additional options for the copy operation. - * @param {string} [options.sourceBucket=this.#defaultBucket] - The source bucket from where the object is to be copied. - * @param {string} [options.destinationKey] - The key of the object in the destination bucket. By default, it is the same as the sourceKey. - * - * @returns {Promise<*>} - A Promise that resolves with the response of the copy operation. - */ - async copy( - sourceKey, - destinationBucket, - options = { - sourceBucket: this.#defaultBucket, - destinationKey: undefined, - }, - ) { - const copySource = `${ - options?.sourceBucket || this.#defaultBucket - }/${sourceKey}`, - command = new CopyObjectCommand({ - CopySource: copySource, - Bucket: destinationBucket, - Key: options?.destinationKey || sourceKey, - }); - - return await this.client.send(command); - } } export default ObjectManager; diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 6994a02..4f8e7f3 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -173,35 +173,3 @@ test("delete object", async () => { existingObjects.length > 0 ? existingObjects[0] : undefined; assert.equal(typeof uploadedObject, "undefined"); }); - -test("copy object", async () => { - // Create bucket `copy-object-test-pass-src` - const bucketSrc = `copy-object-test-pass-src`; - await createBucket(bucketSrc); - - // Upload object `copy-object-test` - const objectNameToCreateSrc = `copy-object-test`; - const uploaded = await uploadObject( - bucketSrc, - objectNameToCreateSrc, - Buffer.from("copy object", "utf-8"), - ); - - // Create bucket `copy-object-test-pass-dest` - const bucketDest = `copy-object-test-pass-dest`; - await createBucket(bucketDest); - - // Initialize ObjectManager - const objectManager = new ObjectManager(s3Config, bucketDest); - - // Copy object `copy-object-test` from `copy-object-test-pass-src` to `copy-object-test-pass-dest` - await objectManager.copy(objectNameToCreateSrc, bucketSrc); - - // List bucket and assert new object exists - const existingObjects = await objectManager.list({ - Prefix: objectNameToCreateSrc, - MaxKeys: 1, - }), - copiedObject = existingObjects.length > 0 ? existingObjects[0] : undefined; - assert.equal(copiedObject.Name, objectNameToCreateSrc); -}); From 8eb0f7e631ca44e8728f322a0b30df48894cbba1 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:47:30 -0600 Subject: [PATCH 13/79] Make Client Private --- src/bucketManager.js | 13 +++++-------- src/objectManager.js | 17 +++++++---------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/bucketManager.js b/src/bucketManager.js index 397eb3d..fa3492d 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -7,17 +7,14 @@ import { /** Provides methods for managing buckets in an S3 endpoint. */ class BucketManager { - client; + #client; /** * @summary Creates a new instance of the S3Client class. * @param {Object} clientConfig - The configuration object for the S3Client. */ constructor(clientConfig) { - /** - * @property {Object} client Represents the client object for S3 API. - */ - this.client = new S3Client(clientConfig); + this.#client = new S3Client(clientConfig); } /** @@ -30,7 +27,7 @@ class BucketManager { Bucket: name, }); - return await this.client.send(command); + return await this.#client.send(command); } /** @@ -40,7 +37,7 @@ class BucketManager { */ async list(listBucketOptions = {}) { const command = new ListBucketsCommand(listBucketOptions), - { Buckets } = await this.client.send(command); + { Buckets } = await this.#client.send(command); return Buckets; } @@ -55,7 +52,7 @@ class BucketManager { Bucket: name, }); - return await this.client.send(command); + return await this.#client.send(command); } } diff --git a/src/objectManager.js b/src/objectManager.js index f9d3e50..e22b8b5 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -23,7 +23,7 @@ import { createWriteStream, createReadStream } from "node:fs"; /** Interacts with an S3 client to perform various operations on objects in a bucket. */ class ObjectManager { - client; + #client; #defaultBucket; #maxConcurrentUploads = 4; @@ -41,10 +41,7 @@ class ObjectManager { maxConcurrentUploads: 4, }, ) { - /** - * @property {Object} client Represents the client object for S3 API. - */ - this.client = new S3Client(clientConfig); + this.#client = new S3Client(clientConfig); this.#defaultBucket = defaultBucket; if (options?.maxConcurrentUploads) { @@ -76,7 +73,7 @@ class ObjectManager { ), temporaryCarFilePath = `${temporaryBlockstoreDir}/main.car`, uploadOptions = { - client: this.client, + client: this.#client, params: { Bucket: bucket, Key: key, @@ -140,7 +137,7 @@ class ObjectManager { Key: key, Body: source, }), - headResult = await this.client.send(command), + headResult = await this.#client.send(command), responseCid = process.env.NODE_ENV === "test" ? 1234567890 : headResult.Metadata.cid; @@ -169,7 +166,7 @@ class ObjectManager { Bucket: bucket, Key: key, }), - response = await this.client.send(command); + response = await this.#client.send(command); return response.Body; } @@ -203,7 +200,7 @@ class ObjectManager { bucketContents = []; while (isTruncated && bucketContents.length < limit) { const { Contents, IsTruncated, NextContinuationToken } = - await this.client.send(command); + await this.#client.send(command); if (typeof Contents === "undefined") { isTruncated = false; continue; @@ -227,7 +224,7 @@ class ObjectManager { Key: key, }); - return await this.client.send(command); + return await this.#client.send(command); } } From 9cc25ec4351e994b745b2edcb12bb655fe539d31 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:58:08 -0600 Subject: [PATCH 14/79] Minor Docs --- jsdoc.json | 1 + src/nameManager.js | 18 +++++++++--------- src/objectManager.js | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/jsdoc.json b/jsdoc.json index 1172994..fef11ab 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -14,6 +14,7 @@ "recurse": true, "destination": "./documentation/", "readme": "./readme.md", + "sort": false, "theme_opts": { "title": "Filebase SDK", "homepageTitle": "Filebase SDK" diff --git a/src/nameManager.js b/src/nameManager.js index 8637aba..004c7f2 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -65,14 +65,14 @@ class NameManager { /** * @summary Creates a new IPNS name with the given name as the label and CID. * @param {string} label - The label of the new IPNS name. - * @param {null|string} [cid] - The CID of the IPNS name. Default value is null. + * @param {string} [cid] - The CID of the IPNS name. Default value is null. * @param {object} [options] - Additional options for the IPNS name. * @param {boolean} [options.enabled=true] - Whether the IPNS name is enabled or not. - * @returns {Promise} - A Promise that resolves with the response JSON. + * @returns {Promise} - A Promise that resolves with the response JSON. */ async create( label, - cid = null, + cid = undefined, options = { enabled: true, }, @@ -118,13 +118,13 @@ class NameManager { } /** - * @summary Updates the specified name with the given cid. + * @summary Updates the specified name with the given CID. * @param {string} label - The label of the name to update. * @param {string} cid - The cid to associate with the name. * @param {Object} options - The options for the set operation. * @param {boolean} [options.enabled] - Whether the name is enabled (default: false). * - * @returns {Promise} - A Promise that resolves with the response data from the server. + * @returns {Promise} - A Promise that resolves to true if the IPNS name was updated. */ async update(label, cid, options = {}) { const setOptions = { @@ -138,7 +138,7 @@ class NameManager { url: `/${label}`, data: setOptions, }); - return setResponse.json(); + return setResponse.status === 200; } /** @@ -157,7 +157,7 @@ class NameManager { /** * @summary Deletes an IPNS name with the given label. * @param {string} label - The label of the IPNS name to delete. - * @returns {Promise} - A promise that resolves to true if the resource is successfully deleted, otherwise false. + * @returns {Promise} - A promise that resolves to true if the IPNS name was successfully deleted. */ async delete(label) { const createResponse = await this.#client.request({ @@ -171,7 +171,7 @@ class NameManager { * @summary Toggles the enabled state of a given IPNS name. * @param {string} label - The label of the IPNS name to toggle. * @param {boolean} enabled - The new enabled state. - * @returns {Promise} - A promise that resolves to the response data. + * @returns {Promise} A promise that resolves to true if the IPNS name was successfully toggled. */ async toggle(label, enabled) { const enableResponse = await this.#client.request({ @@ -181,7 +181,7 @@ class NameManager { enabled: enabled, }, }); - return enableResponse.json(); + return Boolean(enableResponse.status === 200); } } diff --git a/src/objectManager.js b/src/objectManager.js index e22b8b5..266dee7 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -159,7 +159,7 @@ class ObjectManager { * @summary Downloads an object from the specified bucket using the provided key. * @param {string} key - The key of the object to be downloaded. * @param {string} [bucket] - The name of the bucket to download from. If not provided, the default bucket will be used. - * @returns {Promise} - A promise that resolves with the contents of the downloaded object as a Buffer. + * @returns {Promise} - A promise that resolves with the contents of the downloaded object as a Stream. */ async download(key, bucket = this.#defaultBucket) { const command = new GetObjectCommand({ From e2535f0766fc8312907580accf1572e87471ef96 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:01:06 -0600 Subject: [PATCH 15/79] Update readme.md --- readme.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index d91627e..d5ad714 100644 --- a/readme.md +++ b/readme.md @@ -75,12 +75,19 @@ await nameManager.set(`myFirstIpnsKey`, uploadedObject.cid, { }); // Enable IPNS Broadcast without updating the IPNS Record await nameManager.toggle(`myFirstIpnsKey`, true); +// List IPNS Names +const myIpnsNames = await nameManager.list(); +// List Specific IPNS Name +const myIpnsName = await nameManager.list(`myFirstIpnsKey`); // Delete Object await objectManager.delete(objectName); // Delete Bucket -await bucketManager.delete(bucketName) +await bucketManager.delete(bucketName); + +// Delete Name +await nameManager.delete(`myFirstIpnsKey`); ```` Full API reference doc for the JS client are available at https://filebase.github.io/filebase-sdk From 888b62f7b33bb8d68d4907996dc616fba0956efb Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:57:48 -0600 Subject: [PATCH 16/79] Tested and Fixed IPNS SDK --- src/nameManager.js | 42 ++++++++++------------- test/nameManager.spec.js | 73 ++++++++++++++++++++++------------------ 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/nameManager.js b/src/nameManager.js index 004c7f2..13dfc30 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -2,7 +2,7 @@ import axios from "axios"; /** Provides methods for managing names in an REST endpoint. */ class NameManager { - #DEFAULT_ENDPOINT = "https://api.filebase.io/v1/names"; + #DEFAULT_ENDPOINT = "https://api.filebase.io"; #DEFAULT_TIMEOUT = 60000; #client; @@ -13,7 +13,7 @@ class NameManager { * @param {object} clientConfig.credentials - The credentials object for authentication. * @param {string} clientConfig.credentials.accessKeyId - The access key ID for authentication. * @param {string} clientConfig.credentials.secretAccessKey - The secret access key for authentication. - * @param {string} [clientConfig.endpoint="https://api.filebase.io/v1/names"] - The API endpoint URL. + * @param {string} [clientConfig.endpoint="https://api.filebase.io"] - The API endpoint URL. * * @return {object} - The instance of the constructor. */ @@ -33,11 +33,11 @@ class NameManager { const encodedToken = Buffer.from( `${clientConfig.credentials.accessKeyId}:${clientConfig.credentials.secretAccessKey}`, ).toString("base64"), - baseURL = clientConfig.endpoint || this.#DEFAULT_ENDPOINT; + baseURL = `${clientConfig.endpoint || this.#DEFAULT_ENDPOINT}/v1/names`; this.#client = axios.create({ baseURL: baseURL, timeout: this.#DEFAULT_TIMEOUT, - headers: { Authorization: encodedToken }, + headers: { Authorization: `Bearer ${encodedToken}` }, }); } @@ -65,21 +65,18 @@ class NameManager { /** * @summary Creates a new IPNS name with the given name as the label and CID. * @param {string} label - The label of the new IPNS name. - * @param {string} [cid] - The CID of the IPNS name. Default value is null. + * @param {string} cid - The CID of the IPNS name. * @param {object} [options] - Additional options for the IPNS name. * @param {boolean} [options.enabled=true] - Whether the IPNS name is enabled or not. * @returns {Promise} - A Promise that resolves with the response JSON. */ async create( label, - cid = undefined, + cid, options = { enabled: true, }, ) { - if (typeof label !== "string") { - throw new Error(`param [label] is required and must be a string`); - } const createResponse = await this.#client.request({ method: "POST", data: { @@ -88,33 +85,27 @@ class NameManager { enabled: options?.enabled !== false, }, }); - return createResponse.json(); + return createResponse.data; } /** * @summary Imports a user's IPNS private key. * @param {string} label - The label for the IPNS name. + * @param {string} cid - The CID (Content Identifier) of the data. * @param {string} privateKey - The existing private key encoded in Base64. - * @param {null|string} [cid=null] - The CID (Content Identifier) of the data. * * @returns {Promise} - A Promise that resolves to the server response. */ - async import(label, privateKey, cid = null) { - if (typeof label !== "string") { - throw new Error(`param [name] is required and must be a string`); - } - if (typeof privateKey !== "string") { - throw new Error(`param [privateKey] is required and must be a string`); - } + async import(label, cid, privateKey) { const importResponse = await this.#client.request({ method: "POST", data: { label, - privateKey, cid, + privateKey, }, }); - return importResponse.json(); + return importResponse.data; } /** @@ -138,7 +129,7 @@ class NameManager { url: `/${label}`, data: setOptions, }); - return setResponse.status === 200; + return setResponse.data; } /** @@ -150,8 +141,11 @@ class NameManager { const getResponse = await this.#client.request({ method: "GET", url: typeof label === "string" ? `/${label}` : undefined, + validateStatus: (status) => { + return status === 200 || status === 404; + }, }); - return getResponse.json(); + return getResponse.status === 200 ? getResponse.data : false; } /** @@ -164,7 +158,7 @@ class NameManager { method: "DELETE", url: `/${label}`, }); - return createResponse.status === 200; + return createResponse.status === 202; } /** @@ -181,7 +175,7 @@ class NameManager { enabled: enabled, }, }); - return Boolean(enableResponse.status === 200); + return enableResponse.status === 200; } } diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index 0ad7f48..8095c91 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -2,6 +2,10 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import NameManager from "../src/nameManager.js"; +const TEST_CID = process.env.TEST_IPNS_CID, + TEST_PRIVATE_KEY = process.env.TEST_IPNS_PRIVATE_KEY, + TEST_PREFIX = Date.now(); + const s3Config = { endpoint: process.env.TEST_S3_ENDPOINT, credentials: { @@ -12,77 +16,82 @@ const s3Config = { }; test("delete name", async () => { - const testNameLabel = `delete-name-test-pass`, - nameManager = new NameManager(s3Config), - createdName = await nameManager.create(testNameLabel); + const testNameLabel = `${TEST_PREFIX}-delete-name-test-pass`, + nameManager = new NameManager(s3Config); + await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); - assert.strictEqual(createdName.label, testNameLabel); + const deletedName = await nameManager.list(testNameLabel); + assert.strictEqual(deletedName, false); }); test("create name", async () => { - const testNameLabel = `create-name-test-pass`, + const testNameLabel = `${TEST_PREFIX}-create-name-test-pass`, nameManager = new NameManager(s3Config), - createdName = await nameManager.create(testNameLabel); + createdName = await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); assert.strictEqual(createdName.label, testNameLabel); + assert.strictEqual(createdName.cid, TEST_CID); }); test("import name", async () => { - const testNameLabel = `import-name-test-pass`, - testNamePrivateKey = - "CAESQAzjYGmMMK9wjF7PpgC7v4YAGiirw6OQ3So5Sm23SvnUiHe6bfUNOFKmyCXRxh4yXVwFAtvYeq/bZGB1ROPgoWQ=", + const testNameLabel = `${TEST_PREFIX}-import-name-test-pass`, nameManager = new NameManager(s3Config), - importedName = await nameManager.import(testNameLabel, testNamePrivateKey); + importedName = await nameManager.import( + testNameLabel, + TEST_CID, + TEST_PRIVATE_KEY, + ); await nameManager.delete(testNameLabel); assert.strictEqual(importedName.label, testNameLabel); + assert.strictEqual(importedName.cid, TEST_CID); }); test("update name", async () => { - const testNameLabel = `update-name-test-pass`, - testNameValue = "QmeSNqhnDa45qg349oSaXGYx6FPsePGVqGCfHK7BWUwjub", + const testNameLabel = `${TEST_PREFIX}-update-name-test-pass`, nameManager = new NameManager(s3Config), - createdName = await nameManager.create(testNameLabel), - updatedName = await nameManager.update(createdName.label, testNameValue); + createdName = await nameManager.create(testNameLabel, TEST_CID), + updatedName = await nameManager.update(createdName.label, TEST_CID); await nameManager.delete(testNameLabel); - assert.strictEqual(updatedName.cid, testNameLabel); + assert.strictEqual(updatedName.label, testNameLabel); + assert.strictEqual(updatedName.cid, TEST_CID); }); test("list name", async () => { - const testNameLabel = `resolve-name-test-pass`, - testNameValue = "QmeSNqhnDa45qg349oSaXGYx6FPsePGVqGCfHK7BWUwjub", + const testNameLabel = `${TEST_PREFIX}-resolve-name-test-pass`, nameManager = new NameManager(s3Config), - createdName = await nameManager.create(testNameLabel, testNameValue), + createdName = await nameManager.create(testNameLabel, TEST_CID), resolvedName = await nameManager.list(createdName.label); await nameManager.delete(testNameLabel); - assert.strictEqual(resolvedName.cid, testNameValue); + assert.strictEqual(resolvedName.label, testNameLabel); + assert.strictEqual(resolvedName.cid, TEST_CID); }); test("list names", async () => { - const testNameLabel = `list-names-test-pass`, + const testNameLabel = `${TEST_PREFIX}-list-names-test-pass`, nameManager = new NameManager(s3Config); for (let i = 0; i < 10; i++) { - await nameManager.create(`${testNameLabel}-${i}`); + await nameManager.create(`${testNameLabel}-${i}`, TEST_CID); } const namesList = await nameManager.list(); - await nameManager.delete(testNameLabel); + for (let i = 0; i < 10; i++) { + await nameManager.delete(`${testNameLabel}-${i}`); + } assert.strictEqual(namesList.length, 10); }); test("toggle name", async () => { - const testNameLabel = `toggle-name-test-pass`, - nameManager = new NameManager(s3Config), - createdName = await nameManager.create( - testNameLabel, - "QmeSNqhnDa45qg349oSaXGYx6FPsePGVqGCfHK7BWUwjub", - { - enabled: false, - }, - ), - resolvedName = await nameManager.list(testNameLabel); + const testNameLabel = `${TEST_PREFIX}-toggle-name-test-pass`, + nameManager = new NameManager(s3Config); + await nameManager.create(testNameLabel, TEST_CID, { + enabled: false, + }); + const resolvedName = await nameManager.list(testNameLabel); if (resolvedName?.enabled === true) { throw new Error(`Incorrect State on Resolved Name`); } await nameManager.toggle(testNameLabel, true); const updatedName = await nameManager.list(testNameLabel); await nameManager.delete(testNameLabel); + assert.strictEqual(updatedName.label, testNameLabel); + assert.strictEqual(updatedName.cid, TEST_CID); assert.strictEqual(updatedName.enabled, true); }); From 1d86ff7d5f4052395f51ae3e04fd932f01783774 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:07:08 -0600 Subject: [PATCH 17/79] Add options to import --- readme.md | 4 ++++ src/nameManager.js | 13 +++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index d5ad714..6cff386 100644 --- a/readme.md +++ b/readme.md @@ -79,6 +79,10 @@ await nameManager.toggle(`myFirstIpnsKey`, true); const myIpnsNames = await nameManager.list(); // List Specific IPNS Name const myIpnsName = await nameManager.list(`myFirstIpnsKey`); +// Import IPNS Name +const myImportedIpnsName = await nameManager.import(`myImportedKey`, uploadedObject.cid, Base64EncodedPrivateKey, { + enabled: false, +}) // Delete Object await objectManager.delete(objectName); diff --git a/src/nameManager.js b/src/nameManager.js index 13dfc30..95b9a43 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -93,16 +93,25 @@ class NameManager { * @param {string} label - The label for the IPNS name. * @param {string} cid - The CID (Content Identifier) of the data. * @param {string} privateKey - The existing private key encoded in Base64. - * + * @param {object} [options] - Additional options for the IPNS name. + * @param {boolean} [options.enabled=true] - Whether the IPNS name is enabled or not. * @returns {Promise} - A Promise that resolves to the server response. */ - async import(label, cid, privateKey) { + async import( + label, + cid, + privateKey, + options = { + enabled: true, + }, + ) { const importResponse = await this.#client.request({ method: "POST", data: { label, cid, privateKey, + enabled: options?.enabled !== false, }, }); return importResponse.data; From 17b6493ae1db896eda7751a364467e21c43484f0 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:07:21 -0600 Subject: [PATCH 18/79] Update Testing Scripts --- src/objectManager.js | 23 ++++---- test/bucketManager.spec.js | 32 ++++++----- test/nameManager.spec.js | 32 +++++------ test/objectManager.spec.js | 114 ++++++++++++++++++++++--------------- 4 files changed, 113 insertions(+), 88 deletions(-) diff --git a/src/objectManager.js b/src/objectManager.js index 266dee7..b60d47e 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -1,6 +1,5 @@ // S3 Imports import { - CopyObjectCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, @@ -9,17 +8,17 @@ import { } from "@aws-sdk/client-s3"; import { Upload } from "@aws-sdk/lib-storage"; // Helia Imports -import { FsBlockstore } from "blockstore-fs"; import { CarWriter } from "@ipld/car"; import { car } from "@helia/car"; import { unixfs } from "@helia/unixfs"; +import { FsBlockstore } from "blockstore-fs"; // Utility Imports -import { v4 as uuidv4 } from "uuid"; -import path from "node:path"; -import os from "node:os"; +import { createReadStream, createWriteStream } from "node:fs"; import { mkdir, rm } from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; import { Readable } from "node:stream"; -import { createWriteStream, createReadStream } from "node:fs"; +import { v4 as uuidv4 } from "uuid"; /** Interacts with an S3 client to perform various operations on objects in a bucket. */ class ObjectManager { @@ -123,7 +122,8 @@ class ObjectManager { await parallelUploads3.done(); await temporaryFsBlockstore.close(); } finally { - await rm(temporaryBlockstoreDir, { recursive: true }); + // Delete Temporary Blockstore + await rm(temporaryBlockstoreDir, { recursive: true, force: true }); } } else { // Upload file via S3 @@ -138,11 +138,7 @@ class ObjectManager { Body: source, }), headResult = await this.#client.send(command), - responseCid = - process.env.NODE_ENV === "test" ? 1234567890 : headResult.Metadata.cid; - - // Delete Temporary Blockstore - await rm(temporaryBlockstoreDir, { recursive: true, force: true }); + responseCid = headResult.Metadata.cid; if (Object.keys(parsedEntries).length === 0) { return { @@ -185,6 +181,9 @@ class ObjectManager { MaxKeys: 1000, }, ) { + if (options?.MaxKeys && options.MaxKeys > 100000) { + throw new Error(`MaxKeys Maximum value is 100000`); + } const bucket = options?.Bucket || this.#defaultBucket, limit = options?.MaxKeys || 1000, commandOptions = { diff --git a/test/bucketManager.spec.js b/test/bucketManager.spec.js index 40a3adf..f149561 100644 --- a/test/bucketManager.spec.js +++ b/test/bucketManager.spec.js @@ -2,37 +2,43 @@ import test from "node:test"; import assert from "node:assert/strict"; import BucketManager from "../src/bucketManager.js"; -const s3Config = { - endpoint: process.env.TEST_S3_ENDPOINT, - credentials: { - accessKeyId: process.env.TEST_S3_KEY, - secretAccessKey: process.env.TEST_S3_SECRET, - }, - region: process.env.TEST_S3_REGION, -}; +const TEST_PREFIX = Date.now(), + S3_CONFIG = { + endpoint: process.env.TEST_S3_ENDPOINT, + credentials: { + accessKeyId: process.env.TEST_S3_KEY, + secretAccessKey: process.env.TEST_S3_SECRET, + }, + region: process.env.TEST_S3_REGION, + }; test("create bucket", async (t) => { // Initialize BucketManager - const bucketManager = new BucketManager(s3Config); + const bucketManager = new BucketManager(S3_CONFIG); // Create bucket `create-bucket-test-pass` - const bucketNameToCreate = `create-bucket-test-pass`; + const bucketNameToCreate = `${TEST_PREFIX}-create-bucket-test-pass`; await bucketManager.create(bucketNameToCreate); - // List buckets and assert new bucket exists + // List buckets const currentBuckets = await bucketManager.list(), createdBucket = currentBuckets.find((currentBucket) => { return currentBucket.Name === bucketNameToCreate; }); + + // Delete new bucket + await bucketManager.delete(bucketNameToCreate); + + // Assert new bucket exists assert.equal(createdBucket.Name, bucketNameToCreate); }); test("delete bucket", async (t) => { // Initialize BucketManager - const bucketManager = new BucketManager(s3Config); + const bucketManager = new BucketManager(S3_CONFIG); // Create bucket `delete-bucket-test-pass` - const bucketNameToCreate = `delete-bucket-test-pass`; + const bucketNameToCreate = `${TEST_PREFIX}-delete-bucket-test-pass`; await bucketManager.create(bucketNameToCreate); // List buckets and assert new bucket exists diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index 8095c91..e527090 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -4,20 +4,18 @@ import NameManager from "../src/nameManager.js"; const TEST_CID = process.env.TEST_IPNS_CID, TEST_PRIVATE_KEY = process.env.TEST_IPNS_PRIVATE_KEY, - TEST_PREFIX = Date.now(); - -const s3Config = { - endpoint: process.env.TEST_S3_ENDPOINT, - credentials: { - accessKeyId: process.env.TEST_S3_KEY, - secretAccessKey: process.env.TEST_S3_SECRET, - }, - region: process.env.TEST_S3_REGION, -}; + TEST_PREFIX = Date.now(), + S3_CONFIG = { + endpoint: process.env.TEST_IPNS_ENDPOINT, + credentials: { + accessKeyId: process.env.TEST_IPNS_KEY, + secretAccessKey: process.env.TEST_IPNS_SECRET, + }, + }; test("delete name", async () => { const testNameLabel = `${TEST_PREFIX}-delete-name-test-pass`, - nameManager = new NameManager(s3Config); + nameManager = new NameManager(S3_CONFIG); await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); const deletedName = await nameManager.list(testNameLabel); @@ -25,7 +23,7 @@ test("delete name", async () => { }); test("create name", async () => { const testNameLabel = `${TEST_PREFIX}-create-name-test-pass`, - nameManager = new NameManager(s3Config), + nameManager = new NameManager(S3_CONFIG), createdName = await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); assert.strictEqual(createdName.label, testNameLabel); @@ -34,7 +32,7 @@ test("create name", async () => { test("import name", async () => { const testNameLabel = `${TEST_PREFIX}-import-name-test-pass`, - nameManager = new NameManager(s3Config), + nameManager = new NameManager(S3_CONFIG), importedName = await nameManager.import( testNameLabel, TEST_CID, @@ -47,7 +45,7 @@ test("import name", async () => { test("update name", async () => { const testNameLabel = `${TEST_PREFIX}-update-name-test-pass`, - nameManager = new NameManager(s3Config), + nameManager = new NameManager(S3_CONFIG), createdName = await nameManager.create(testNameLabel, TEST_CID), updatedName = await nameManager.update(createdName.label, TEST_CID); await nameManager.delete(testNameLabel); @@ -57,7 +55,7 @@ test("update name", async () => { test("list name", async () => { const testNameLabel = `${TEST_PREFIX}-resolve-name-test-pass`, - nameManager = new NameManager(s3Config), + nameManager = new NameManager(S3_CONFIG), createdName = await nameManager.create(testNameLabel, TEST_CID), resolvedName = await nameManager.list(createdName.label); await nameManager.delete(testNameLabel); @@ -67,7 +65,7 @@ test("list name", async () => { test("list names", async () => { const testNameLabel = `${TEST_PREFIX}-list-names-test-pass`, - nameManager = new NameManager(s3Config); + nameManager = new NameManager(S3_CONFIG); for (let i = 0; i < 10; i++) { await nameManager.create(`${testNameLabel}-${i}`, TEST_CID); } @@ -80,7 +78,7 @@ test("list names", async () => { test("toggle name", async () => { const testNameLabel = `${TEST_PREFIX}-toggle-name-test-pass`, - nameManager = new NameManager(s3Config); + nameManager = new NameManager(S3_CONFIG); await nameManager.create(testNameLabel, TEST_CID, { enabled: false, }); diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 4f8e7f3..58247a1 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -7,18 +7,19 @@ import { writeFile } from "node:fs/promises"; import { v4 as uuidv4 } from "uuid"; import os from "node:os"; -const s3Config = { - endpoint: process.env.TEST_S3_ENDPOINT, - credentials: { - accessKeyId: process.env.TEST_S3_KEY, - secretAccessKey: process.env.TEST_S3_SECRET, - }, - region: process.env.TEST_S3_REGION, -}; +const TEST_PREFIX = Date.now(), + S3_CONFIG = { + endpoint: process.env.TEST_S3_ENDPOINT, + credentials: { + accessKeyId: process.env.TEST_S3_KEY, + secretAccessKey: process.env.TEST_S3_SECRET, + }, + region: process.env.TEST_S3_REGION, + }; async function createBucket(name) { // Initialize BucketManager - const bucketManager = new BucketManager(s3Config); + const bucketManager = new BucketManager(S3_CONFIG); // Create bucket with name const bucketNameToCreate = name; @@ -35,7 +36,7 @@ async function createBucket(name) { async function uploadObject(bucket, key, body) { // Initialize ObjectManager - const objectManager = new ObjectManager(s3Config, bucket); + const objectManager = new ObjectManager(S3_CONFIG, bucket); // Upload Object await objectManager.upload(key, body); @@ -50,9 +51,50 @@ async function uploadObject(bucket, key, body) { return typeof uploadedObject !== "undefined"; } +async function deleteObject(bucket, key) { + // Initialize ObjectManager + const objectManager = new ObjectManager(S3_CONFIG, bucket); + + // Delete Object + await objectManager.delete(key); + return true; +} + +test("delete object", async () => { + // Create bucket `delete-object-test-pass` + const deleteTestBucket = `${TEST_PREFIX}-delete-object-test-pass`; + await createBucket(deleteTestBucket); + + // Upload object `delete-object-test` + const objectNameToCreate = `delete-object-test`; + const uploaded = await uploadObject( + deleteTestBucket, + objectNameToCreate, + Buffer.from("delete object", "utf-8"), + ); + if (uploaded === false) { + throw Error(`Failed to create object [delete-object-test]`); + } + + // Initialize ObjectManager + const objectManager = new ObjectManager(S3_CONFIG, deleteTestBucket); + + // Delete object `delete-object-test` + await objectManager.delete(objectNameToCreate); + + // List bucket and assert new object doesn't exist + const existingObjects = await objectManager.list({ + Prefix: objectNameToCreate, + MaxKeys: 1, + }), + uploadedObject = + existingObjects.length > 0 ? existingObjects[0] : undefined; + assert.equal(typeof uploadedObject, "undefined"); +}); + test("upload object", async () => { // Create Bucket `create-object-test-pass - const uploadTestBucket = `create-object-test-pass`; + const uploadTestBucket = `${TEST_PREFIX}-create-object-test-pass`; await createBucket(uploadTestBucket); // Upload object `create-object-test` @@ -61,12 +103,14 @@ test("upload object", async () => { `create-object-test`, Buffer.from("upload object", "utf-8"), ); + assert.strictEqual(uploaded, true); + await deleteObject(uploadTestBucket, `create-object-test`); }); test("upload directory", async () => { // Create Bucket `create-object-test-pass - const uploadDirectoryTestBucket = `create-directory-test-pass`; + const uploadDirectoryTestBucket = `${TEST_PREFIX}-create-directory-test-pass`; await createBucket(uploadDirectoryTestBucket); // Upload object `create-object-test` @@ -89,11 +133,12 @@ test("upload directory", async () => { ], ); assert.strictEqual(uploaded, true); + await deleteObject(uploadDirectoryTestBucket, `create-directory-test`); }); test("download object", async () => { // Create bucket `download-object-test-pass` - const downloadTestBucket = `download-object-test-pass`; + const downloadTestBucket = `${TEST_PREFIX}-download-object-test-pass`; await createBucket(downloadTestBucket); // Upload object `download-object-test` @@ -108,17 +153,18 @@ test("download object", async () => { } // Download object `download-object-test` and assert it completes - const objectManager = new ObjectManager(s3Config, downloadTestBucket); + const objectManager = new ObjectManager(S3_CONFIG, downloadTestBucket); const downloadStream = await objectManager.download(objectNameToCreate), downloadFilename = uuidv4(), downloadPath = Path.resolve(os.tmpdir(), downloadFilename), writeFileResult = await writeFile(downloadPath, downloadStream); assert.strictEqual(typeof writeFileResult, "undefined"); + await deleteObject(downloadTestBucket, objectNameToCreate); }); test("list objects", async () => { // Create bucket `list-objects-test-pass` - const listTestBucket = `list-objects-test-pass`; + const listTestBucket = `${TEST_PREFIX}-list-objects-test-pass`; await createBucket(listTestBucket); let createdObjectCount = 0; @@ -133,43 +179,19 @@ test("list objects", async () => { createdObjectCount++; } - const objectManager = new ObjectManager(s3Config, listTestBucket); + const objectManager = new ObjectManager(S3_CONFIG, listTestBucket); const bucketList = await objectManager.list({ MaxKeys: 50, Prefix: `list-object-test-`, }); assert.equal(bucketList.length, 26); -}); - -test("delete object", async () => { - // Create bucket `delete-object-test-pass` - const deleteTestBucket = `delete-object-test-pass`; - await createBucket(deleteTestBucket); - // Upload object `delete-object-test` - const objectNameToCreate = `delete-object-test`; - const uploaded = await uploadObject( - deleteTestBucket, - objectNameToCreate, - Buffer.from("delete object", "utf-8"), - ); - if (uploaded === false) { - throw Error(`Failed to create object [delete-object-test]`); + let deletedObjectCount = 0; + while (createdObjectCount < 26) { + // Delete objects `list-object-test-[x]` + const objectNameToDelete = `list-object-test-${deletedObjectCount}`; + await deleteObject(listTestBucket, objectNameToDelete); + deletedObjectCount++; } - - // Initialize ObjectManager - const objectManager = new ObjectManager(s3Config, deleteTestBucket); - - // Delete object `delete-object-test` - await objectManager.delete(objectNameToCreate); - - // List bucket and assert new object doesn't exist - const existingObjects = await objectManager.list({ - Prefix: objectNameToCreate, - MaxKeys: 1, - }), - uploadedObject = - existingObjects.length > 0 ? existingObjects[0] : undefined; - assert.equal(typeof uploadedObject, "undefined"); }); From c4711242e5dccbe0bf9c154f9b01bc52d91362d1 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:08:46 -0600 Subject: [PATCH 19/79] Add Test Workflow --- .github/workflows/test.yml | 18 ++++++++++++++++++ package.json | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..e939345 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,18 @@ +name: Node.js CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: '20.x' + - run: npm ci + - run: npm run build --if-present + - run: npm test diff --git a/package.json b/package.json index c0f8f87..cdd1fea 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ } }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "node --test", "doc": "jsdoc -c jsdoc.json", "build": "run-script-os", "build:win32": "rmdir /s /q dist && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && .\\fixup.bat", From 850f4e8afa14dd61319288e2372e95d2080a620e Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:09:47 -0600 Subject: [PATCH 20/79] Update test.yml Remove build step in test --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e939345..988ee76 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,5 +14,4 @@ jobs: with: node-version: '20.x' - run: npm ci - - run: npm run build --if-present - run: npm test From ee1dc8ef741ab4393e6ee74870eb42c676d7f9f2 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:11:45 -0600 Subject: [PATCH 21/79] Update test.yml --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 988ee76..03396c9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,9 +3,9 @@ name: Node.js CI on: [push] jobs: - build: - + test: runs-on: ubuntu-latest + environment: Testing steps: - uses: actions/checkout@v4 From 83da6723f932b2f2a02ff4148055b5f8f47c1476 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:18:44 -0600 Subject: [PATCH 22/79] Update test.yml Remove Environment --- .github/workflows/test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03396c9..2ad4b22 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,9 +3,8 @@ name: Node.js CI on: [push] jobs: - test: + build: runs-on: ubuntu-latest - environment: Testing steps: - uses: actions/checkout@v4 From 0eeb71cddbec2b81e566b0a159af59c392b20c81 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:29:44 -0600 Subject: [PATCH 23/79] Update test.yml Pass in env variables and secrets --- .github/workflows/test.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ad4b22..df7fa5f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,3 +14,13 @@ jobs: node-version: '20.x' - run: npm ci - run: npm test + env: + TEST_IPNS_ENDPOINT: ${{ vars.TEST_IPNS_ENDPOINT }} + TEST_IPNS_CID: ${{ vars.TEST_IPNS_CID }} + TEST_IPNS_KEY: ${{ secrets.TEST_IPNS_KEY }} + TEST_IPNS_SECRET: ${{ secrets.TEST_IPNS_SECRET }} + TEST_IPNS_PRIVATE_KEY: ${{ secrets.TEST_IPNS_PRIVATE_KEY }} + TEST_S3_ENDPOINT: ${{ vars.TEST_S3_ENDPOINT }} + TEST_S3_REGION: ${{ vars.TEST_S3_REGION }} + TEST_S3_KEY: ${{ secrets.TEST_S3_KEY }} + TEST_S3_SECRET: ${{ secrets.TEST_S3_SECRET }} From 483d72ee96cea25fea47b7ac692aad567d65acf7 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:31:40 -0600 Subject: [PATCH 24/79] Update test.yml Change test name --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index df7fa5f..d37c030 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,7 +3,7 @@ name: Node.js CI on: [push] jobs: - build: + test: runs-on: ubuntu-latest steps: From fa5c7e8a116917bfc72f0005485b87339cea86fa Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:27:06 -0600 Subject: [PATCH 25/79] Remove CJS Compatibility --- fixup.bat | 18 ------------------ fixup.sh | 11 ----------- package.json | 11 +++-------- tsconfig-base.json | 25 ------------------------- tsconfig-cjs.json | 8 -------- tsconfig.json | 8 -------- 6 files changed, 3 insertions(+), 78 deletions(-) delete mode 100644 fixup.bat delete mode 100644 fixup.sh delete mode 100644 tsconfig-base.json delete mode 100644 tsconfig-cjs.json delete mode 100644 tsconfig.json diff --git a/fixup.bat b/fixup.bat deleted file mode 100644 index 5852dc7..0000000 --- a/fixup.bat +++ /dev/null @@ -1,18 +0,0 @@ -@echo off - -set "distPath=dist" -if not exist "%distPath%" ( - mkdir "%distPath%" -) - -set "cjsPath=dist/cjs" -if not exist "%cjsPath%" ( - mkdir "%cjsPath%" -) -echo {"type": "commonjs"} > "%cjsPath%/package.json" - -set "ejsPath=dist/mjs" -if not exist "%ejsPath%" ( - mkdir "%ejsPath%" -) -echo {"type": "module"} > "%ejsPath%/package.json" diff --git a/fixup.sh b/fixup.sh deleted file mode 100644 index 8f6395d..0000000 --- a/fixup.sh +++ /dev/null @@ -1,11 +0,0 @@ -cat >dist/cjs/package.json <dist/mjs/package.json < Date: Tue, 5 Dec 2023 15:27:59 -0600 Subject: [PATCH 26/79] Update package-lock.json --- package-lock.json | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 55ff06a..8c7fa3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,11 +20,9 @@ "uuid": "9.0.1" }, "devDependencies": { - "clean-jsdoc-theme": "^4.2.17", + "clean-jsdoc-theme": "4.2.17", "jsdoc": "4.0.2", - "prettier": "3.1.0", - "run-script-os": "1.1.6", - "typescript": "5.3.2" + "prettier": "3.1.0" } }, "node_modules/@achingbrain/nat-port-mapper": { @@ -4742,16 +4740,6 @@ "node": ">= 4" } }, - "node_modules/run-script-os": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", - "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==", - "dev": true, - "bin": { - "run-os": "index.js", - "run-script-os": "index.js" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -5101,19 +5089,6 @@ "node": "*" } }, - "node_modules/typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", From 7bfb5ae538632e1ea5a196b8cf73b04840c0395e Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:58:39 -0600 Subject: [PATCH 27/79] Test Cleanup --- test/objectManager.spec.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 58247a1..80e812c 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -60,6 +60,15 @@ async function deleteObject(bucket, key) { return true; } +async function deleteBucket(bucket) { + // Initialize BucketManager + const bucketManager = new BucketManager(S3_CONFIG); + + // Delete Bucket + await bucketManager.delete(bucket); + return true; +} + test("delete object", async () => { // Create bucket `delete-object-test-pass` const deleteTestBucket = `${TEST_PREFIX}-delete-object-test-pass`; @@ -106,6 +115,7 @@ test("upload object", async () => { assert.strictEqual(uploaded, true); await deleteObject(uploadTestBucket, `create-object-test`); + await deleteBucket(uploadTestBucket); }); test("upload directory", async () => { @@ -134,6 +144,7 @@ test("upload directory", async () => { ); assert.strictEqual(uploaded, true); await deleteObject(uploadDirectoryTestBucket, `create-directory-test`); + await deleteBucket(uploadDirectoryTestBucket); }); test("download object", async () => { @@ -160,6 +171,7 @@ test("download object", async () => { writeFileResult = await writeFile(downloadPath, downloadStream); assert.strictEqual(typeof writeFileResult, "undefined"); await deleteObject(downloadTestBucket, objectNameToCreate); + await deleteBucket(downloadTestBucket); }); test("list objects", async () => { @@ -194,4 +206,5 @@ test("list objects", async () => { await deleteObject(listTestBucket, objectNameToDelete); deletedObjectCount++; } + await deleteBucket(listTestBucket); }); From 06913ac9c0ab00f0269310e60b0a61314daea1ee Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:58:53 -0600 Subject: [PATCH 28/79] Create publish.yml Add publish workflow --- .github/workflows/publish.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..4a0db16 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,19 @@ +name: Publish to NPM +on: + release: + types: [created] +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '20.x' + registry-url: 'https://registry.npmjs.org' + - name: Publish package on NPM 📦 + run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file From 8fd2c29cb6bd23cf0df6d14198241c829fd12f10 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:59:19 -0600 Subject: [PATCH 29/79] Update publish.yml --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4a0db16..7c7c3fb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,7 +3,7 @@ on: release: types: [created] jobs: - build: + publish: runs-on: ubuntu-latest steps: - name: Checkout From aba9b3427554eaef92bc099edda55bea0460e486 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 16:02:15 -0600 Subject: [PATCH 30/79] Update Package Name --- package.json | 2 +- readme.md | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 45eb11c..217918b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "filebase-sdk", + "name": "@filebase/sdk", "version": "1.0.0", "description": "", "type": "module", diff --git a/readme.md b/readme.md index 6cff386..3ade715 100644 --- a/readme.md +++ b/readme.md @@ -17,13 +17,13 @@ Applications has never been easier. Install the package using npm ```shell -npm install filebase-sdk +npm install @filebase/sdk ``` or yarn: ```shell -yarn add filebase-sdk +yarn add @filebase/sdk ``` ### Getting started @@ -107,13 +107,6 @@ Install the deps with `npm` npm install ``` -Build code from src with `npm` - -```console -# build from src -npm run build -``` - ### Testing Test are found in the `test` directory and are built to be run with the Node.js v20+ test runner. \ No newline at end of file From 04d2b6cb52118cc39f05373a312ec711c5960098 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 5 Dec 2023 16:29:27 -0600 Subject: [PATCH 31/79] Update bucketManager.js Add examples --- src/bucketManager.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/bucketManager.js b/src/bucketManager.js index fa3492d..9ea5056 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -12,6 +12,9 @@ class BucketManager { /** * @summary Creates a new instance of the S3Client class. * @param {Object} clientConfig - The configuration object for the S3Client. + * @example + * import { bucketManager } from "@filebase/sdk"; + * const bucketManager = new BucketManager(S3_CONFIG); */ constructor(clientConfig) { this.#client = new S3Client(clientConfig); @@ -21,6 +24,9 @@ class BucketManager { * @summary Creates a new bucket with the specified name. * @param {string} name - The name of the bucket to create. * @returns {Promise<*>} - A promise that resolves when the bucket is created. + * @example + * // Create bucket with name of `create-bucket-example` + * await bucketManager.create(`create-bucket-example`); */ async create(name) { const command = new CreateBucketCommand({ @@ -34,6 +40,9 @@ class BucketManager { * @summary Lists the buckets in the client. * @param {Object} listBucketOptions - The options for listing buckets. * @returns {Promise>} - A promise that resolves with an array of objects representing the buckets in the client. + * @example + * // List all buckets + * await bucketManager.list(); */ async list(listBucketOptions = {}) { const command = new ListBucketsCommand(listBucketOptions), @@ -46,6 +55,9 @@ class BucketManager { * @summary Deletes the specified bucket. * @param {string} name - The name of the bucket to delete. * @returns {Promise} - A promise that resolves when the bucket is deleted. + * @example + * // Delete bucket with name of `bucket-name-to-delete` + * await bucketManager.delete(`bucket-name-to-delete`); */ async delete(name) { const command = new DeleteBucketCommand({ From d89308612b0c968f5bb8c57043c297c12175e093 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Wed, 6 Dec 2023 15:14:56 -0600 Subject: [PATCH 32/79] Update nameManager.js Support network_private_key param --- src/nameManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nameManager.js b/src/nameManager.js index 95b9a43..97101aa 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -110,7 +110,7 @@ class NameManager { data: { label, cid, - privateKey, + network_private_key: privateKey, enabled: options?.enabled !== false, }, }); From bf7bf5b9d7044105c89b5c82db4f92aff766a2d1 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Fri, 8 Dec 2023 14:37:08 -0600 Subject: [PATCH 33/79] Add Types for Docs --- src/bucketManager.js | 23 +++++++++++++++-------- src/index.js | 12 ++++++++++++ src/nameManager.js | 44 ++++++++++++++++++++++++++------------------ src/objectManager.js | 43 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 87 insertions(+), 35 deletions(-) diff --git a/src/bucketManager.js b/src/bucketManager.js index 9ea5056..f48c114 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -11,19 +11,26 @@ class BucketManager { /** * @summary Creates a new instance of the S3Client class. - * @param {Object} clientConfig - The configuration object for the S3Client. + * @param {clientConfig} clientConfig - The configuration object for the S3Client. * @example * import { bucketManager } from "@filebase/sdk"; * const bucketManager = new BucketManager(S3_CONFIG); */ constructor(clientConfig) { + clientConfig.region = clientConfig.region || "us-east-1"; this.#client = new S3Client(clientConfig); } + /** + * @typedef {Object} bucket + * @property {string} Name The name of the bucket + * @property {date} Date the bucket was created + */ + /** * @summary Creates a new bucket with the specified name. * @param {string} name - The name of the bucket to create. - * @returns {Promise<*>} - A promise that resolves when the bucket is created. + * @returns {Promise} - A promise that resolves when the bucket is created. * @example * // Create bucket with name of `create-bucket-example` * await bucketManager.create(`create-bucket-example`); @@ -38,14 +45,13 @@ class BucketManager { /** * @summary Lists the buckets in the client. - * @param {Object} listBucketOptions - The options for listing buckets. - * @returns {Promise>} - A promise that resolves with an array of objects representing the buckets in the client. + * @returns {Promise>} - A promise that resolves with an array of objects representing the buckets in the client. * @example * // List all buckets * await bucketManager.list(); */ - async list(listBucketOptions = {}) { - const command = new ListBucketsCommand(listBucketOptions), + async list() { + const command = new ListBucketsCommand({}), { Buckets } = await this.#client.send(command); return Buckets; @@ -54,7 +60,7 @@ class BucketManager { /** * @summary Deletes the specified bucket. * @param {string} name - The name of the bucket to delete. - * @returns {Promise} - A promise that resolves when the bucket is deleted. + * @returns {Promise} - A promise that resolves when the bucket is deleted. * @example * // Delete bucket with name of `bucket-name-to-delete` * await bucketManager.delete(`bucket-name-to-delete`); @@ -64,7 +70,8 @@ class BucketManager { Bucket: name, }); - return await this.#client.send(command); + await this.#client.send(command); + return true; } } diff --git a/src/index.js b/src/index.js index 9fca93b..3f0ab80 100644 --- a/src/index.js +++ b/src/index.js @@ -2,4 +2,16 @@ import BucketManager from "./bucketManager.js"; import ObjectManager from "./objectManager.js"; import NameManager from "./nameManager.js"; +/** + * @typedef {Object} clientCredentials + * @property {string} accessKeyId The access key ID for authentication. + * @property {string} secretAccessKey The secret access key for authentication. + */ + +/** + * @typedef {Object} clientConfig + * @property {clientCredentials} credentials The credentials object for authentication. + * @property {string} endpoint The API endpoint URL. + */ + export { BucketManager, ObjectManager, NameManager }; diff --git a/src/nameManager.js b/src/nameManager.js index 97101aa..e569075 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -9,13 +9,7 @@ class NameManager { /** * @summary Creates a new instance of the constructor. - * @param {object} clientConfig - The configuration object for the client. - * @param {object} clientConfig.credentials - The credentials object for authentication. - * @param {string} clientConfig.credentials.accessKeyId - The access key ID for authentication. - * @param {string} clientConfig.credentials.secretAccessKey - The secret access key for authentication. - * @param {string} [clientConfig.endpoint="https://api.filebase.io"] - The API endpoint URL. - * - * @return {object} - The instance of the constructor. + * @param {clientConfig} clientConfig - The configuration object for the client. */ constructor( clientConfig = { @@ -43,7 +37,7 @@ class NameManager { /** * @summary Validates the client configuration. - * @param {object} clientConfig - The client configuration object. + * @param {clientConfig} clientConfig - The client configuration object. * @returns {string[]} - An array containing any validation errors found in the client configuration. */ #validateClientConfig(clientConfig) { @@ -62,13 +56,29 @@ class NameManager { return configErrors; } + /** + * @typedef {Object} nameOptions + * @property {boolean} enabled Whether the name is enabled or not. + */ + + /** + * @typedef {Object} name + * @property {string} label Descriptive label for the Key + * @property {string} network_key IPNS Key CID + * @property {string} cid Value that name Publishes + * @property {number} sequence Version Number for the name + * @property {boolean} enabled Whether the name is being Published or not + * @property {date} published_at Date the name was last published to the DHT + * @property {date} created_at Date the name was created + * @property {date} updated_at Date the name was last updated + */ + /** * @summary Creates a new IPNS name with the given name as the label and CID. * @param {string} label - The label of the new IPNS name. * @param {string} cid - The CID of the IPNS name. - * @param {object} [options] - Additional options for the IPNS name. - * @param {boolean} [options.enabled=true] - Whether the IPNS name is enabled or not. - * @returns {Promise} - A Promise that resolves with the response JSON. + * @param {nameOptions} [options] - Additional options for the IPNS name. + * @returns {Promise} - A Promise that resolves with the response JSON. */ async create( label, @@ -93,9 +103,8 @@ class NameManager { * @param {string} label - The label for the IPNS name. * @param {string} cid - The CID (Content Identifier) of the data. * @param {string} privateKey - The existing private key encoded in Base64. - * @param {object} [options] - Additional options for the IPNS name. - * @param {boolean} [options.enabled=true] - Whether the IPNS name is enabled or not. - * @returns {Promise} - A Promise that resolves to the server response. + * @param {nameOptions} [options] - Additional options for the IPNS name. + * @returns {Promise} - A Promise that resolves to the server response. */ async import( label, @@ -121,8 +130,7 @@ class NameManager { * @summary Updates the specified name with the given CID. * @param {string} label - The label of the name to update. * @param {string} cid - The cid to associate with the name. - * @param {Object} options - The options for the set operation. - * @param {boolean} [options.enabled] - Whether the name is enabled (default: false). + * @param {nameOptions} options - The options for the set operation. * * @returns {Promise} - A Promise that resolves to true if the IPNS name was updated. */ @@ -138,13 +146,13 @@ class NameManager { url: `/${label}`, data: setOptions, }); - return setResponse.data; + return setResponse.status === 200; } /** * @summary Returns a list of IPNS name(s) * @param {string} [label] - Optional string parameter representing the label of the name to list. - * @returns {Promise} - A promise that resolves to an array of names. + * @returns {Promise>} - A promise that resolves to an array of names. */ async list(label = null) { const getResponse = await this.#client.request({ diff --git a/src/objectManager.js b/src/objectManager.js index b60d47e..0461131 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -26,12 +26,16 @@ class ObjectManager { #defaultBucket; #maxConcurrentUploads = 4; + /** + * @typedef {Object} objectManagerOptions Optional settings for the constructor. + * @property {number} maxConcurrentUploads The maximum number of concurrent uploads. + */ + /** * @summary Creates a new instance of the class. * @param {object} clientConfig - The configuration object for the S3 client. * @param {string} defaultBucket - The default S3 bucket to be used. - * @param {object} options - Optional settings for the constructor. - * @param {number} options.maxConcurrentUploads - The maximum number of concurrent uploads. + * @param {objectManagerOptions} options - Optional settings for the constructor. */ constructor( clientConfig, @@ -48,6 +52,18 @@ class ObjectManager { } } + /** + * @typedef {Object} entryImportResult + * @property {string} cid The CID of the uploaded object + * @property {string} path The path of the object + */ + + /** + * @typedef {Object} object + * @property {string} cid The CID of the uploaded object + * @property {array} [entries] If a directory then returns an array of the containing objects + */ + /** * If the source parameter is an array of objects, it will pack multiple files into a CAR file for upload. * The method returns a Promise that resolves to an object containing the CID (Content Identifier) of the uploaded file @@ -59,7 +75,7 @@ class ObjectManager { * If an array of objects is provided, each object should have a 'path' property specifying the path of the file * and a 'content' property specifying the content of the file. * @param {string} [bucket=this.#defaultBucket] - The bucket name. Default is the value of the defaultBucket property. - * @returns {Promise} + * @returns {Promise} */ async upload(key, source, bucket = this.#defaultBucket) { // Setup Upload Options @@ -167,17 +183,25 @@ class ObjectManager { return response.Body; } + /** + * @typedef {Object} listObjectOptions + * @property {string} [Bucket] The name of the bucket. If not provided, the default bucket will be used. + * @property {string} [ContinuationToken=null] Continues listing from this objects name. + * @property {string} [Delimiter=null] Character used to group keys + * @property {number} [MaxKeys=1000] The maximum number of objects to retrieve. Defaults to 1000. + */ + /** * Retrieves a list of objects from a specified bucket. * - * @param {Object} options - The options for listing objects. Accepts S3 SDK ListObjectsRequest parameters. - * @param {string} [options.Bucket] - The name of the bucket. If not provided, the default bucket will be used. - * @param {number} [options.MaxKeys] - The maximum number of objects to retrieve. Defaults to 1000. + * @param {listObjectOptions} options - The options for listing objects. * @returns {Promise} - A promise that resolves to an array of objects. */ async list( options = { Bucket: this.#defaultBucket, + ContinuationToken: null, + Delimiter: null, MaxKeys: 1000, }, ) { @@ -214,8 +238,8 @@ class ObjectManager { /** * @summary Deletes an object from the specified bucket using the provided key. * @param {string} key - The key of the object to be deleted. - * @param {string} [bucket=this.#defaultBucket] - The name of the bucket that contains the object. Defaults to the default bucket. - * @returns {Promise<*>} - A Promise that resolves with the result of the delete operation. + * @param {string} [bucket] - The name of the bucket that contains the object. Defaults to the default bucket. + * @returns {Promise} - A Promise that resolves with the result of the delete operation. */ async delete(key, bucket = this.#defaultBucket) { const command = new DeleteObjectCommand({ @@ -223,7 +247,8 @@ class ObjectManager { Key: key, }); - return await this.#client.send(command); + await this.#client.send(command); + return true; } } From e2e0a0259d7520aedaaf8a3d3376f55480ac119b Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Fri, 8 Dec 2023 18:12:13 -0600 Subject: [PATCH 34/79] Examples --- jsdoc.json | 14 +++++++-- package-lock.json | 4 +-- package.json | 1 + readme.md | 13 +-------- src/bucketManager.js | 18 ++++++++---- src/index.js | 12 ++++---- src/nameManager.js | 68 +++++++++++++++++++++++++++++++++----------- src/objectManager.js | 56 ++++++++++++++++++++++++++++++------ 8 files changed, 134 insertions(+), 52 deletions(-) diff --git a/jsdoc.json b/jsdoc.json index fef11ab..5998752 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -14,10 +14,20 @@ "recurse": true, "destination": "./documentation/", "readme": "./readme.md", - "sort": false, "theme_opts": { "title": "Filebase SDK", - "homepageTitle": "Filebase SDK" + "homepageTitle": "Filebase SDK", + "default_theme": "fallback-dark", + "sort": false, + "menu": [{ + "title": "Github", + "link": "https://github.com/filebase/filebase-sdk", + "target": "_blank" + },{ + "title": "npm", + "link": "https://www.npmjs.com/package/@filebase/sdk", + "target": "_blank" + }] } } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8c7fa3f..e945a1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "filebase-sdk", + "name": "@filebase/sdk", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "filebase-sdk", + "name": "@filebase/sdk", "version": "1.0.0", "dependencies": { "@aws-sdk/client-s3": "3.454.0", diff --git a/package.json b/package.json index 217918b..e71179b 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "@filebase/sdk", "version": "1.0.0", "description": "", + "repository": "https://github.com/filebase/filebase-sdk", "type": "module", "main": "dist/cjs/index.js", "module": "dist/mjs/index.mjs", diff --git a/readme.md b/readme.md index 3ade715..cf63396 100644 --- a/readme.md +++ b/readme.md @@ -32,7 +32,7 @@ The snippet below shows how to create a new bucket with `BucketManager`, upload with `ObjectManager`, publish the object to IPNS with `NameManager`, delete the object with `ObjectManager` and finally delete the bucket with `BucketManager`. -To use the library in your project, use npm or yarn to install the [`filebase-sdk`](https://www.npmjs.com/package/filebase-sdk) module. +To use the library in your project, use npm or yarn to install the [`@filebase/sdk`](https://www.npmjs.com/package/@filebase/sdk) module. **node.js** ````js @@ -96,17 +96,6 @@ await nameManager.delete(`myFirstIpnsKey`); Full API reference doc for the JS client are available at https://filebase.github.io/filebase-sdk -### Building filebase-sdk - -Want to help us improve filebase-sdk? This project uses node v20 and npm v9 - -Install the deps with `npm` - -```console -# install deps -npm install -``` - ### Testing Test are found in the `test` directory and are built to be run with the Node.js v20+ test runner. \ No newline at end of file diff --git a/src/bucketManager.js b/src/bucketManager.js index f48c114..dc7b8e7 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -11,14 +11,20 @@ class BucketManager { /** * @summary Creates a new instance of the S3Client class. - * @param {clientConfig} clientConfig - The configuration object for the S3Client. + * @param {clientConfiguration} clientConfiguration - The configuration object for the S3Client. * @example - * import { bucketManager } from "@filebase/sdk"; - * const bucketManager = new BucketManager(S3_CONFIG); + * import { BucketManager } from "@filebase/sdk"; + * const bucketManager = new BucketManager({ + * credentials: { + * accessKeyId: "KEY_FROM_DASHBOARD", + * secretAccessKey: "SECRET_FROM_DASHBOARD", + * }, + * endpoint: "https://s3.filebase.com" + * }); */ - constructor(clientConfig) { - clientConfig.region = clientConfig.region || "us-east-1"; - this.#client = new S3Client(clientConfig); + constructor(clientConfiguration) { + clientConfiguration.region = clientConfiguration.region || "us-east-1"; + this.#client = new S3Client(clientConfiguration); } /** diff --git a/src/index.js b/src/index.js index 3f0ab80..38ebf0a 100644 --- a/src/index.js +++ b/src/index.js @@ -3,15 +3,15 @@ import ObjectManager from "./objectManager.js"; import NameManager from "./nameManager.js"; /** - * @typedef {Object} clientCredentials - * @property {string} accessKeyId The access key ID for authentication. - * @property {string} secretAccessKey The secret access key for authentication. + * @typedef {Object} clientConfiguration + * @property {clientConfigurationCredentials} credentials The credentials object for authentication. + * @property {string} endpoint The API endpoint URL. */ /** - * @typedef {Object} clientConfig - * @property {clientCredentials} credentials The credentials object for authentication. - * @property {string} endpoint The API endpoint URL. + * @typedef {Object} clientConfigurationCredentials + * @property {string} accessKeyId The access key ID for authentication. + * @property {string} secretAccessKey The secret access key for authentication. */ export { BucketManager, ObjectManager, NameManager }; diff --git a/src/nameManager.js b/src/nameManager.js index e569075..7c09886 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -9,25 +9,36 @@ class NameManager { /** * @summary Creates a new instance of the constructor. - * @param {clientConfig} clientConfig - The configuration object for the client. + * @param {clientConfiguration} clientConfiguration - The configuration object for the client. + * @example + * import { NameManager } from "@filebase/sdk"; + * const nameManager = new NameManager({ + * credentials: { + * accessKeyId: "KEY_FROM_DASHBOARD", + * secretAccessKey: "SECRET_FROM_DASHBOARD", + * }, + * endpoint: "https://api.filebase.io" + * }); */ constructor( - clientConfig = { + clientConfiguration = { credentials: { accessKeyId: null, secretAccessKey: null, }, }, ) { - const configErrors = this.#validateClientConfig(clientConfig); + const configErrors = this.#validateclientConfiguration(clientConfiguration); if (configErrors.length > 0) { throw new Error(configErrors.join("\n")); } const encodedToken = Buffer.from( - `${clientConfig.credentials.accessKeyId}:${clientConfig.credentials.secretAccessKey}`, + `${clientConfiguration.credentials.accessKeyId}:${clientConfiguration.credentials.secretAccessKey}`, ).toString("base64"), - baseURL = `${clientConfig.endpoint || this.#DEFAULT_ENDPOINT}/v1/names`; + baseURL = `${ + clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT + }/v1/names`; this.#client = axios.create({ baseURL: baseURL, timeout: this.#DEFAULT_TIMEOUT, @@ -37,30 +48,27 @@ class NameManager { /** * @summary Validates the client configuration. - * @param {clientConfig} clientConfig - The client configuration object. + * @param {clientConfiguration} clientConfiguration - The client configuration object. * @returns {string[]} - An array containing any validation errors found in the client configuration. */ - #validateClientConfig(clientConfig) { + #validateclientConfiguration(clientConfiguration) { let configErrors = []; - if (typeof clientConfig?.credentials?.accessKeyId !== "string") { - configErrors.push("clientConfig must contain credentials.accessKeyId"); + if (typeof clientConfiguration?.credentials?.accessKeyId !== "string") { + configErrors.push( + "clientConfiguration must contain credentials.accessKeyId", + ); } - if (typeof clientConfig?.credentials?.secretAccessKey !== "string") { + if (typeof clientConfiguration?.credentials?.secretAccessKey !== "string") { configErrors.push( - "clientConfig must contain credentials.secretAccessKey", + "clientConfiguration must contain credentials.secretAccessKey", ); } return configErrors; } - /** - * @typedef {Object} nameOptions - * @property {boolean} enabled Whether the name is enabled or not. - */ - /** * @typedef {Object} name * @property {string} label Descriptive label for the Key @@ -73,12 +81,20 @@ class NameManager { * @property {date} updated_at Date the name was last updated */ + /** + * @typedef {Object} nameOptions + * @property {boolean} enabled Whether the name is enabled or not. + */ + /** * @summary Creates a new IPNS name with the given name as the label and CID. * @param {string} label - The label of the new IPNS name. * @param {string} cid - The CID of the IPNS name. * @param {nameOptions} [options] - Additional options for the IPNS name. * @returns {Promise} - A Promise that resolves with the response JSON. + * @example + * // Create IPNS name with label of `create-name-example` and CID of `QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm` + * await nameManager.create(`create-name-example`, `QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm`); */ async create( label, @@ -105,6 +121,14 @@ class NameManager { * @param {string} privateKey - The existing private key encoded in Base64. * @param {nameOptions} [options] - Additional options for the IPNS name. * @returns {Promise} - A Promise that resolves to the server response. + * @example + * // Import IPNS private key with label of `create-name-example`, CID of `QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm` + * // and a private key encoded with base64 + * await nameManager.import( + * `create-name-example`, + * `QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm` + * `BASE64_ENCODED_PRIVATEKEY` + * ); */ async import( label, @@ -153,6 +177,11 @@ class NameManager { * @summary Returns a list of IPNS name(s) * @param {string} [label] - Optional string parameter representing the label of the name to list. * @returns {Promise>} - A promise that resolves to an array of names. + * @example + * // List IPNS name with label of `list-name-example` + * await nameManager.list(`list-name-example`); + * // List all IPNS names + * await nameManager.list(); */ async list(label = null) { const getResponse = await this.#client.request({ @@ -169,6 +198,9 @@ class NameManager { * @summary Deletes an IPNS name with the given label. * @param {string} label - The label of the IPNS name to delete. * @returns {Promise} - A promise that resolves to true if the IPNS name was successfully deleted. + * @example + * // List IPNS name with label of `delete-name-example` + * await nameManager.delete(`delete-name-example`); */ async delete(label) { const createResponse = await this.#client.request({ @@ -183,6 +215,10 @@ class NameManager { * @param {string} label - The label of the IPNS name to toggle. * @param {boolean} enabled - The new enabled state. * @returns {Promise} A promise that resolves to true if the IPNS name was successfully toggled. + * @example + * // Toggle IPNS name with label of `toggle-name-example` + * await nameManager.toggle(`toggle-name-example`, true); // Enabled + * await nameManager.toggle(`toggle-name-example`, false); // Disabled */ async toggle(label, enabled) { const enableResponse = await this.#client.request({ diff --git a/src/objectManager.js b/src/objectManager.js index 0461131..b66014c 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -33,18 +33,29 @@ class ObjectManager { /** * @summary Creates a new instance of the class. - * @param {object} clientConfig - The configuration object for the S3 client. + * @param {object} clientConfiguration - The configuration object for the S3 client. * @param {string} defaultBucket - The default S3 bucket to be used. * @param {objectManagerOptions} options - Optional settings for the constructor. + * @example + * import { ObjectManager } from "@filebase/sdk"; + * const objectManager = new ObjectManager({ + * credentials: { + * accessKeyId: "KEY_FROM_DASHBOARD", + * secretAccessKey: "SECRET_FROM_DASHBOARD", + * }, + * endpoint: "https://s3.filebase.com" + * }, "my-default-bucket", { + * maxConcurrentUploads: 4 + * }); */ constructor( - clientConfig, + clientConfiguration, defaultBucket, options = { maxConcurrentUploads: 4, }, ) { - this.#client = new S3Client(clientConfig); + this.#client = new S3Client(clientConfiguration); this.#defaultBucket = defaultBucket; if (options?.maxConcurrentUploads) { @@ -53,15 +64,15 @@ class ObjectManager { } /** - * @typedef {Object} entryImportResult + * @typedef {Object} object * @property {string} cid The CID of the uploaded object - * @property {string} path The path of the object + * @property {array} [entries] If a directory then returns an array of the containing objects */ /** - * @typedef {Object} object + * @typedef {Object} objectEntry * @property {string} cid The CID of the uploaded object - * @property {array} [entries] If a directory then returns an array of the containing objects + * @property {string} path The path of the object */ /** @@ -74,8 +85,26 @@ class ObjectManager { * @param {Buffer|ReadableStream|Array} source - The content of the file to be uploaded. * If an array of objects is provided, each object should have a 'path' property specifying the path of the file * and a 'content' property specifying the content of the file. - * @param {string} [bucket=this.#defaultBucket] - The bucket name. Default is the value of the defaultBucket property. + * @param {string} [bucket] - The bucket name. Default is the value of the defaultBucket property. * @returns {Promise} + * @example + * // Upload Object + * await objectManager.upload("my-object", Buffer.from("Hello World!")); + * // Upload Directory + * await objectManager.upload("my-first-directory", [ + * { + * path: "/testObjects/1.txt", + * content: Buffer.from("upload test object", "utf-8"), + * }, + * { + * path: "/testObjects/deep/1.txt", + * content: Buffer.from("upload deep test object", "utf-8"), + * }, + * { + * path: "/topLevel.txt", + * content: Buffer.from("upload top level test object", "utf-8"), + * }, + * ]); */ async upload(key, source, bucket = this.#defaultBucket) { // Setup Upload Options @@ -172,6 +201,9 @@ class ObjectManager { * @param {string} key - The key of the object to be downloaded. * @param {string} [bucket] - The name of the bucket to download from. If not provided, the default bucket will be used. * @returns {Promise} - A promise that resolves with the contents of the downloaded object as a Stream. + * @example + * // Download object with name of `download-object-example` + * await objectManager.download(`download-object-example`); */ async download(key, bucket = this.#defaultBucket) { const command = new GetObjectCommand({ @@ -196,6 +228,11 @@ class ObjectManager { * * @param {listObjectOptions} options - The options for listing objects. * @returns {Promise} - A promise that resolves to an array of objects. + * @example + * // List objects in bucket with a limit of 1000 + * await objectManager.list({ + * MaxKeys: 1000 + * }); */ async list( options = { @@ -240,6 +277,9 @@ class ObjectManager { * @param {string} key - The key of the object to be deleted. * @param {string} [bucket] - The name of the bucket that contains the object. Defaults to the default bucket. * @returns {Promise} - A Promise that resolves with the result of the delete operation. + * @example + * // Delete object with name of `delete-object-example` + * await objectManager.delete(`delete-object-example`); */ async delete(key, bucket = this.#defaultBucket) { const command = new DeleteObjectCommand({ From f8af990080a7b05a80d285d5aa7f976e59da5471 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Fri, 8 Dec 2023 18:17:34 -0600 Subject: [PATCH 35/79] Fix Test --- test/objectManager.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 80e812c..8eb38b2 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -200,7 +200,7 @@ test("list objects", async () => { assert.equal(bucketList.length, 26); let deletedObjectCount = 0; - while (createdObjectCount < 26) { + while (deletedObjectCount < 26) { // Delete objects `list-object-test-[x]` const objectNameToDelete = `list-object-test-${deletedObjectCount}`; await deleteObject(listTestBucket, objectNameToDelete); From 77c185362baf8205660e0800e182df5156be11f5 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Fri, 8 Dec 2023 18:21:51 -0600 Subject: [PATCH 36/79] Fix One more Test --- test/nameManager.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index e527090..40a6bc2 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -49,8 +49,7 @@ test("update name", async () => { createdName = await nameManager.create(testNameLabel, TEST_CID), updatedName = await nameManager.update(createdName.label, TEST_CID); await nameManager.delete(testNameLabel); - assert.strictEqual(updatedName.label, testNameLabel); - assert.strictEqual(updatedName.cid, TEST_CID); + assert.strictEqual(updatedName, true); }); test("list name", async () => { From 2f91c8dddb65de6c3024b1cf2c191b6c45c142a5 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Fri, 8 Dec 2023 18:38:21 -0600 Subject: [PATCH 37/79] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index cf63396..9166b91 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -

💾
Filebase SDK

+

• Filebase SDK •

Developer Friendly [ IPFS | IPNS | S3 ]

## About From 5673e8ef2dd3f284344d440f1b6043c5c5e062c5 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Fri, 8 Dec 2023 20:09:22 -0600 Subject: [PATCH 38/79] Default Endpoints Hidden from Params --- jsdoc.json | 1 + src/bucketManager.js | 4 +++- src/index.js | 1 - src/nameManager.js | 7 +++---- src/objectManager.js | 5 ++++- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/jsdoc.json b/jsdoc.json index 5998752..92a6417 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -17,6 +17,7 @@ "theme_opts": { "title": "Filebase SDK", "homepageTitle": "Filebase SDK", + "favicon": "https://console.filebase.com/favicon.ico", "default_theme": "fallback-dark", "sort": false, "menu": [{ diff --git a/src/bucketManager.js b/src/bucketManager.js index dc7b8e7..edd2468 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -7,6 +7,7 @@ import { /** Provides methods for managing buckets in an S3 endpoint. */ class BucketManager { + #DEFAULT_ENDPOINT = "https://s3.filebase.com"; #client; /** @@ -19,10 +20,11 @@ class BucketManager { * accessKeyId: "KEY_FROM_DASHBOARD", * secretAccessKey: "SECRET_FROM_DASHBOARD", * }, - * endpoint: "https://s3.filebase.com" * }); */ constructor(clientConfiguration) { + clientConfiguration.endpoint = + clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; clientConfiguration.region = clientConfiguration.region || "us-east-1"; this.#client = new S3Client(clientConfiguration); } diff --git a/src/index.js b/src/index.js index 38ebf0a..13ccc3a 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,6 @@ import NameManager from "./nameManager.js"; /** * @typedef {Object} clientConfiguration * @property {clientConfigurationCredentials} credentials The credentials object for authentication. - * @property {string} endpoint The API endpoint URL. */ /** diff --git a/src/nameManager.js b/src/nameManager.js index 7c09886..e8d4b24 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -17,7 +17,6 @@ class NameManager { * accessKeyId: "KEY_FROM_DASHBOARD", * secretAccessKey: "SECRET_FROM_DASHBOARD", * }, - * endpoint: "https://api.filebase.io" * }); */ constructor( @@ -28,6 +27,8 @@ class NameManager { }, }, ) { + clientConfiguration.endpoint = + clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; const configErrors = this.#validateclientConfiguration(clientConfiguration); if (configErrors.length > 0) { throw new Error(configErrors.join("\n")); @@ -36,9 +37,7 @@ class NameManager { const encodedToken = Buffer.from( `${clientConfiguration.credentials.accessKeyId}:${clientConfiguration.credentials.secretAccessKey}`, ).toString("base64"), - baseURL = `${ - clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT - }/v1/names`; + baseURL = `${clientConfiguration.endpoint}/v1/names`; this.#client = axios.create({ baseURL: baseURL, timeout: this.#DEFAULT_TIMEOUT, diff --git a/src/objectManager.js b/src/objectManager.js index b66014c..c5611f8 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -22,6 +22,7 @@ import { v4 as uuidv4 } from "uuid"; /** Interacts with an S3 client to perform various operations on objects in a bucket. */ class ObjectManager { + #DEFAULT_ENDPOINT = "https://s3.filebase.com"; #client; #defaultBucket; #maxConcurrentUploads = 4; @@ -43,7 +44,6 @@ class ObjectManager { * accessKeyId: "KEY_FROM_DASHBOARD", * secretAccessKey: "SECRET_FROM_DASHBOARD", * }, - * endpoint: "https://s3.filebase.com" * }, "my-default-bucket", { * maxConcurrentUploads: 4 * }); @@ -55,6 +55,9 @@ class ObjectManager { maxConcurrentUploads: 4, }, ) { + clientConfiguration.endpoint = + clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; + clientConfiguration.region = clientConfiguration.region || "us-east-1"; this.#client = new S3Client(clientConfiguration); this.#defaultBucket = defaultBucket; From dd2a7bd6ac668ef942853e590ed81243153c82f6 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 10 Dec 2023 07:25:38 -0600 Subject: [PATCH 39/79] Add Resolve Method to Name --- src/nameManager.js | 30 +++++++++++++++++++++--------- test/nameManager.spec.js | 4 ++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/nameManager.js b/src/nameManager.js index e8d4b24..d71e7c7 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -173,19 +173,17 @@ class NameManager { } /** - * @summary Returns a list of IPNS name(s) - * @param {string} [label] - Optional string parameter representing the label of the name to list. - * @returns {Promise>} - A promise that resolves to an array of names. + * @summary Returns the value of an IPNS name + * @param {string} label - Parameter representing the label of the name to resolve. + * @returns {Promise>} - A promise that resolves to the value of a name. * @example - * // List IPNS name with label of `list-name-example` - * await nameManager.list(`list-name-example`); - * // List all IPNS names - * await nameManager.list(); + * // Resolve IPNS name with label of `list-name-example` + * await nameManager.resolve(`list-name-example`); */ - async list(label = null) { + async resolve(label) { const getResponse = await this.#client.request({ method: "GET", - url: typeof label === "string" ? `/${label}` : undefined, + url: `/${label}`, validateStatus: (status) => { return status === 200 || status === 404; }, @@ -193,6 +191,20 @@ class NameManager { return getResponse.status === 200 ? getResponse.data : false; } + /** + * @summary Returns a list of IPNS names + * @returns {Promise>} - A promise that resolves to an array of names. + * @example + * // List all IPNS names + * await nameManager.list(); + */ + async list() { + const getResponse = await this.#client.request({ + method: "GET", + }); + return getResponse.data; + } + /** * @summary Deletes an IPNS name with the given label. * @param {string} label - The label of the IPNS name to delete. diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index 40a6bc2..df05e07 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -52,11 +52,11 @@ test("update name", async () => { assert.strictEqual(updatedName, true); }); -test("list name", async () => { +test("resolve name", async () => { const testNameLabel = `${TEST_PREFIX}-resolve-name-test-pass`, nameManager = new NameManager(S3_CONFIG), createdName = await nameManager.create(testNameLabel, TEST_CID), - resolvedName = await nameManager.list(createdName.label); + resolvedName = await nameManager.resolve(createdName.label); await nameManager.delete(testNameLabel); assert.strictEqual(resolvedName.label, testNameLabel); assert.strictEqual(resolvedName.cid, TEST_CID); From a2bd15f0c4f0d676afd898b8a8bfc742cda1ede3 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 10 Dec 2023 08:56:14 -0600 Subject: [PATCH 40/79] Fix Test --- test/nameManager.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index df05e07..13b27c7 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -86,7 +86,7 @@ test("toggle name", async () => { throw new Error(`Incorrect State on Resolved Name`); } await nameManager.toggle(testNameLabel, true); - const updatedName = await nameManager.list(testNameLabel); + const updatedName = await nameManager.resolve(testNameLabel); await nameManager.delete(testNameLabel); assert.strictEqual(updatedName.label, testNameLabel); assert.strictEqual(updatedName.cid, TEST_CID); From 9d3b9ccc5c07189c5d65590051109859745dd850 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 10 Dec 2023 08:58:27 -0600 Subject: [PATCH 41/79] Fix Test --- test/nameManager.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index 13b27c7..d79f389 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -18,7 +18,7 @@ test("delete name", async () => { nameManager = new NameManager(S3_CONFIG); await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); - const deletedName = await nameManager.list(testNameLabel); + const deletedName = await nameManager.resolve(testNameLabel); assert.strictEqual(deletedName, false); }); test("create name", async () => { From 787b3f089afdb2ca22aa0ff3779ba4e5f5718d92 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 10 Dec 2023 17:15:01 -0600 Subject: [PATCH 42/79] Add Gateway Support to SDK --- src/gatewayManager.js | 203 ++++++++++++++++++++++++++++++++++++ src/index.js | 4 +- src/nameManager.js | 49 ++++----- test/gatewayManager.spec.js | 80 ++++++++++++++ test/nameManager.spec.js | 14 +-- 5 files changed, 314 insertions(+), 36 deletions(-) create mode 100644 src/gatewayManager.js create mode 100644 test/gatewayManager.spec.js diff --git a/src/gatewayManager.js b/src/gatewayManager.js new file mode 100644 index 0000000..8a3ef38 --- /dev/null +++ b/src/gatewayManager.js @@ -0,0 +1,203 @@ +import axios from "axios"; + +export default class GatewayManager { + #DEFAULT_ENDPOINT = "https://api.filebase.io"; + #DEFAULT_TIMEOUT = 60000; + + #client; + + /** + * @summary Creates a new instance of the constructor. + * @param {clientConfiguration} clientConfiguration - The configuration object for the client. + * @example + * import { NameManager } from "@filebase/sdk"; + * const nameManager = new NameManager({ + * credentials: { + * accessKeyId: "KEY_FROM_DASHBOARD", + * secretAccessKey: "SECRET_FROM_DASHBOARD", + * }, + * }); + */ + constructor(clientConfiguration) { + clientConfiguration.endpoint = + clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; + const configErrors = this.#validateClientConfiguration(clientConfiguration); + if (configErrors.length > 0) { + throw new Error(configErrors.join("\n")); + } + + const encodedToken = Buffer.from( + `${clientConfiguration.credentials.accessKeyId}:${clientConfiguration.credentials.secretAccessKey}`, + ).toString("base64"), + baseURL = `${clientConfiguration.endpoint}/v1/gateways`; + this.#client = axios.create({ + baseURL: baseURL, + timeout: this.#DEFAULT_TIMEOUT, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + } + + /** + * @summary Validates the client configuration. + * @param {clientConfiguration} clientConfiguration - The client configuration object. + * @returns {string[]} - An array containing any validation errors found in the client configuration. + */ + #validateClientConfiguration(clientConfiguration) { + let configErrors = []; + + if (typeof clientConfiguration?.credentials?.accessKeyId !== "string") { + configErrors.push( + "clientConfiguration must contain credentials.accessKeyId", + ); + } + + if (typeof clientConfiguration?.credentials?.secretAccessKey !== "string") { + configErrors.push( + "clientConfiguration must contain credentials.secretAccessKey", + ); + } + + return configErrors; + } + + /** + * @typedef {Object} gateway + * @property {string} name Name for the gateway + * @property {string} domain Custom Domain for the gateway + * @property {boolean} enabled Whether the gateway is enabled or not + * @property {string} private Whether the gateway is scoped to users content + * @property {date} created_at Date the gateway was created + * @property {date} updated_at Date the gateway was last updated + */ + + /** + * @typedef {Object} gatewayOptions + * @property {boolean} [domain] Optional Domain to allow for using a Custom Domain + * @property {string} [enabled] Optional Toggle to use for enabling the gateway + * @property {boolean} [private] Optional Boolean determining if gateway is Public or Private + */ + + /** + * + * @param {string} name Unique name across entire platform for the gateway. Must be a valid subdomain name. + * @param {gatewayOptions} [options] + * @returns {*} + */ + async create(name, options = {}) { + let createOptions = { + name, + }; + if (typeof options.domain === "string") { + createOptions.domain = options.domain; + } + if (typeof options.enabled === "boolean") { + createOptions.enabled = options.enabled; + } + if (typeof options.private === "boolean") { + createOptions.private = options.private; + } + const createResponse = await this.#client.request({ + method: "POST", + data: createOptions, + }); + return createResponse.data; + } + + /** + * @summary Deletes a gateway with the given name. + * @param {string} name - The name of the gateway to delete. + * @returns {Promise} - A promise that resolves to true if the gateway was successfully deleted. + * @example + * // Delete gateway with name of `delete-gateway-example` + * await gatewayManager.delete(`delete-name-example`); + */ + async delete(name) { + const deleteResponse = await this.#client.request({ + method: "DELETE", + url: `/${name}`, + }); + return deleteResponse.status === 202; + } + + /** + * @summary Returns the value of a gateway + * @param {string} name - Parameter representing the name to get. + * @returns {Promise} - A promise that resolves to the value of a gateway. + * @example + * // Get gateway with name of `gateway-get-example` + * await gatewayManager.get(`gateway-get-example`); + */ + async get(name) { + const getResponse = await this.#client.request({ + method: "GET", + url: `/${name}`, + validateStatus: (status) => { + return status === 200 || status === 404; + }, + }); + return getResponse.status === 200 ? getResponse.data : false; + } + + /** + * @summary Returns a list of gateways + * @returns {Promise>} - A promise that resolves to an array of gateways. + * @example + * // List all gateways + * await gatewayManager.list(); + */ + async list() { + const getResponse = await this.#client.request({ + method: "GET", + }); + return getResponse.data; + } + + /** + * @summary Updates the specified gateway. + * @param {string} name - The name of the gateway to update. + * @param {gatewayOptions} options - The options for the update operation. + * + * @returns {Promise} - A Promise that resolves to true if the gateway was updated. + */ + async update(name, options) { + const updateOptions = { + name, + }; + if (options?.domain) { + updateOptions.domain = String(options.private); + } + if (options?.enabled) { + updateOptions.enabled = Boolean(options.enabled); + } + if (options?.private) { + updateOptions.private = Boolean(options.private); + } + const updateResponse = await this.#client.request({ + method: "PUT", + url: `/${name}`, + data: updateOptions, + }); + return updateResponse.status === 200; + } + + /** + * @summary Toggles the enabled state of a given gateway. + * @param {string} name - The name of the gateway to toggle. + * @param {boolean} targetState - The new target state. + * @returns {Promise} A promise that resolves to true if the gateway was successfully toggled. + * @example + * // Toggle gateway with label of `toggle-gateway-example` + * await gatewayManager.toggle(`toggle-gateway-example`, true); // Enabled + * await gatewayManager.toggle(`toggle-gateway-example`, false); // Disabled + */ + async toggle(name, targetState) { + const toggleResponse = await this.#client.request({ + method: "PUT", + url: `/${name}`, + data: { + enabled: Boolean(targetState), + }, + }); + return toggleResponse.status === 200; + } +} diff --git a/src/index.js b/src/index.js index 13ccc3a..2587c84 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,12 @@ import BucketManager from "./bucketManager.js"; import ObjectManager from "./objectManager.js"; +import GatewayManager from "./gatewayManager.js"; import NameManager from "./nameManager.js"; /** * @typedef {Object} clientConfiguration * @property {clientConfigurationCredentials} credentials The credentials object for authentication. + * @property {string} [endpoint] The endpoint for the API */ /** @@ -13,4 +15,4 @@ import NameManager from "./nameManager.js"; * @property {string} secretAccessKey The secret access key for authentication. */ -export { BucketManager, ObjectManager, NameManager }; +export { BucketManager, ObjectManager, GatewayManager, NameManager }; diff --git a/src/nameManager.js b/src/nameManager.js index d71e7c7..5333027 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -19,17 +19,10 @@ class NameManager { * }, * }); */ - constructor( - clientConfiguration = { - credentials: { - accessKeyId: null, - secretAccessKey: null, - }, - }, - ) { + constructor(clientConfiguration = {}) { clientConfiguration.endpoint = clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; - const configErrors = this.#validateclientConfiguration(clientConfiguration); + const configErrors = this.#validateClientConfiguration(clientConfiguration); if (configErrors.length > 0) { throw new Error(configErrors.join("\n")); } @@ -50,7 +43,7 @@ class NameManager { * @param {clientConfiguration} clientConfiguration - The client configuration object. * @returns {string[]} - An array containing any validation errors found in the client configuration. */ - #validateclientConfiguration(clientConfiguration) { + #validateClientConfiguration(clientConfiguration) { let configErrors = []; if (typeof clientConfiguration?.credentials?.accessKeyId !== "string") { @@ -158,29 +151,29 @@ class NameManager { * @returns {Promise} - A Promise that resolves to true if the IPNS name was updated. */ async update(label, cid, options = {}) { - const setOptions = { + const updateOptions = { cid, }; if (options?.enabled) { - setOptions.enabled = Boolean(options.enabled); + updateOptions.enabled = Boolean(options.enabled); } - const setResponse = await this.#client.request({ + const updateResponse = await this.#client.request({ method: "PUT", url: `/${label}`, - data: setOptions, + data: updateOptions, }); - return setResponse.status === 200; + return updateResponse.status === 200; } /** * @summary Returns the value of an IPNS name * @param {string} label - Parameter representing the label of the name to resolve. - * @returns {Promise>} - A promise that resolves to the value of a name. + * @returns {Promise} - A promise that resolves to the value of a name. * @example - * // Resolve IPNS name with label of `list-name-example` - * await nameManager.resolve(`list-name-example`); + * // Get IPNS name with label of `list-name-example` + * await nameManager.get(`list-name-example`); */ - async resolve(label) { + async get(label) { const getResponse = await this.#client.request({ method: "GET", url: `/${label}`, @@ -199,10 +192,10 @@ class NameManager { * await nameManager.list(); */ async list() { - const getResponse = await this.#client.request({ + const listResponse = await this.#client.request({ method: "GET", }); - return getResponse.data; + return listResponse.data; } /** @@ -214,32 +207,32 @@ class NameManager { * await nameManager.delete(`delete-name-example`); */ async delete(label) { - const createResponse = await this.#client.request({ + const deleteResponse = await this.#client.request({ method: "DELETE", url: `/${label}`, }); - return createResponse.status === 202; + return deleteResponse.status === 202; } /** * @summary Toggles the enabled state of a given IPNS name. * @param {string} label - The label of the IPNS name to toggle. - * @param {boolean} enabled - The new enabled state. + * @param {boolean} targetState - The new target state. * @returns {Promise} A promise that resolves to true if the IPNS name was successfully toggled. * @example * // Toggle IPNS name with label of `toggle-name-example` * await nameManager.toggle(`toggle-name-example`, true); // Enabled * await nameManager.toggle(`toggle-name-example`, false); // Disabled */ - async toggle(label, enabled) { - const enableResponse = await this.#client.request({ + async toggle(label, targetState) { + const toggleResponse = await this.#client.request({ method: "PUT", url: `/${label}`, data: { - enabled: enabled, + enabled: targetState, }, }); - return enableResponse.status === 200; + return toggleResponse.status === 200; } } diff --git a/test/gatewayManager.spec.js b/test/gatewayManager.spec.js new file mode 100644 index 0000000..7d145ca --- /dev/null +++ b/test/gatewayManager.spec.js @@ -0,0 +1,80 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import GatewayManager from "../src/gatewayManager.js"; + +const TEST_PREFIX = Date.now(), + S3_CONFIG = { + endpoint: process.env.TEST_GW_ENDPOINT, + credentials: { + accessKeyId: process.env.TEST_GW_KEY, + secretAccessKey: process.env.TEST_GW_SECRET, + }, + }; + +test("delete gateway", async () => { + const testGatewayName = `${TEST_PREFIX}-delete-gateway-test-pass`, + gatewayManager = new GatewayManager(S3_CONFIG); + await gatewayManager.create(testGatewayName); + await gatewayManager.delete(testGatewayName); + const deletedName = await gatewayManager.get(testGatewayName); + assert.strictEqual(deletedName, false); +}); +test("create gateway", async () => { + const testGatewayName = `${TEST_PREFIX}-create-gateway-test-pass`, + gatewayManager = new GatewayManager(S3_CONFIG), + createdName = await gatewayManager.create(testGatewayName); + await gatewayManager.delete(testGatewayName); + assert.strictEqual(createdName.name, testGatewayName); +}); + +test("update gateway", async () => { + const testGatewayName = `${TEST_PREFIX}-update-gateway-test-pass`, + gatewayManager = new GatewayManager(S3_CONFIG), + createdName = await gatewayManager.create(testGatewayName), + updatedName = await gatewayManager.update(createdName.name, { + private: true, + enabled: false, + }); + await gatewayManager.delete(testGatewayName); + assert.strictEqual(updatedName, true); +}); + +test("get gateway", async () => { + const testGatewayName = `${TEST_PREFIX}-get-gateway-test-pass`, + gatewayManager = new GatewayManager(S3_CONFIG), + createdName = await gatewayManager.create(testGatewayName, {}), + testName = await gatewayManager.get(createdName.name); + await gatewayManager.delete(testGatewayName); + assert.strictEqual(testName.name, testGatewayName); +}); + +test("list gateways", async () => { + const testGatewayName = `${TEST_PREFIX}-list-names-test-pass`, + gatewayManager = new GatewayManager(S3_CONFIG); + const initialGatewaysList = await gatewayManager.list(); + for (let i = 0; i < 10; i++) { + await gatewayManager.create(`${testGatewayName}-${i}`); + } + const gatewaysList = await gatewayManager.list(); + for (let i = 0; i < 10; i++) { + await gatewayManager.delete(`${testGatewayName}-${i}`); + } + assert.strictEqual(gatewaysList.length, initialGatewaysList.length + 10); +}); + +/*test("toggle gateway", async () => { + const testGatewayName = `${TEST_PREFIX}-toggle-gateway-test-pass`, + gatewayManager = new GatewayManager(S3_CONFIG); + await gatewayManager.create(testGatewayName, { + enabled: false, + }); + const resolvedName = await gatewayManager.get(testGatewayName); + if (resolvedName?.enabled === true) { + throw new Error(`Incorrect State on Resolved Name`); + } + await gatewayManager.toggle(testGatewayName, true); + const updatedName = await gatewayManager.get(testGatewayName); + await gatewayManager.delete(testGatewayName); + assert.strictEqual(updatedName.name, testGatewayName); + assert.strictEqual(updatedName.enabled, true); +});*/ diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index d79f389..7eb3abd 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -18,7 +18,7 @@ test("delete name", async () => { nameManager = new NameManager(S3_CONFIG); await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); - const deletedName = await nameManager.resolve(testNameLabel); + const deletedName = await nameManager.get(testNameLabel); assert.strictEqual(deletedName, false); }); test("create name", async () => { @@ -52,14 +52,14 @@ test("update name", async () => { assert.strictEqual(updatedName, true); }); -test("resolve name", async () => { - const testNameLabel = `${TEST_PREFIX}-resolve-name-test-pass`, +test("get name", async () => { + const testNameLabel = `${TEST_PREFIX}-get-name-test-pass`, nameManager = new NameManager(S3_CONFIG), createdName = await nameManager.create(testNameLabel, TEST_CID), - resolvedName = await nameManager.resolve(createdName.label); + testName = await nameManager.get(createdName.label); await nameManager.delete(testNameLabel); - assert.strictEqual(resolvedName.label, testNameLabel); - assert.strictEqual(resolvedName.cid, TEST_CID); + assert.strictEqual(testName.label, testNameLabel); + assert.strictEqual(testName.cid, TEST_CID); }); test("list names", async () => { @@ -86,7 +86,7 @@ test("toggle name", async () => { throw new Error(`Incorrect State on Resolved Name`); } await nameManager.toggle(testNameLabel, true); - const updatedName = await nameManager.resolve(testNameLabel); + const updatedName = await nameManager.get(testNameLabel); await nameManager.delete(testNameLabel); assert.strictEqual(updatedName.label, testNameLabel); assert.strictEqual(updatedName.cid, TEST_CID); From 17b93a1f0d4165ad407d74ed27106829745018f0 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 10 Dec 2023 17:22:04 -0600 Subject: [PATCH 43/79] Update test.yml --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d37c030..0c9e5ac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,6 +15,9 @@ jobs: - run: npm ci - run: npm test env: + TEST_GW_ENDPOINT: ${{ vars.TEST_GW_ENDPOINT }} + TEST_GW_KEY: ${{ secrets.TEST_GW_KEY }} + TEST_GW_SECRET: ${{ secrets.TEST_GW_SECRET }} TEST_IPNS_ENDPOINT: ${{ vars.TEST_IPNS_ENDPOINT }} TEST_IPNS_CID: ${{ vars.TEST_IPNS_CID }} TEST_IPNS_KEY: ${{ secrets.TEST_IPNS_KEY }} From 0c0c5ff014d93d111be6495c9232f575accadbe8 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 10 Dec 2023 17:38:01 -0600 Subject: [PATCH 44/79] Minor Fixes for Docs --- src/gatewayManager.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gatewayManager.js b/src/gatewayManager.js index 8a3ef38..2b7953d 100644 --- a/src/gatewayManager.js +++ b/src/gatewayManager.js @@ -1,6 +1,6 @@ import axios from "axios"; -export default class GatewayManager { +class GatewayManager { #DEFAULT_ENDPOINT = "https://api.filebase.io"; #DEFAULT_TIMEOUT = 60000; @@ -10,8 +10,8 @@ export default class GatewayManager { * @summary Creates a new instance of the constructor. * @param {clientConfiguration} clientConfiguration - The configuration object for the client. * @example - * import { NameManager } from "@filebase/sdk"; - * const nameManager = new NameManager({ + * import { GatewayManager } from "@filebase/sdk"; + * const gatewayManager = new GatewayManager({ * credentials: { * accessKeyId: "KEY_FROM_DASHBOARD", * secretAccessKey: "SECRET_FROM_DASHBOARD", @@ -201,3 +201,5 @@ export default class GatewayManager { return toggleResponse.status === 200; } } + +export default GatewayManager; From c4c33e55e1cc25ea5582f44d9a2b8bba45a86b65 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 10 Dec 2023 22:39:38 -0600 Subject: [PATCH 45/79] Simplify Constructor --- src/bucketManager.js | 31 ++++++++++++--------- src/gatewayManager.js | 54 +++++++++---------------------------- src/index.js | 12 --------- src/nameManager.js | 54 +++++++++---------------------------- src/objectManager.js | 53 ++++++++++++++++++------------------ test/bucketManager.spec.js | 20 +++++++------- test/gatewayManager.spec.js | 36 +++++++++++++++---------- test/nameManager.spec.js | 44 +++++++++++++++++++----------- test/objectManager.spec.js | 50 +++++++++++++++++++++++----------- 9 files changed, 164 insertions(+), 190 deletions(-) diff --git a/src/bucketManager.js b/src/bucketManager.js index edd2468..635ebc4 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -8,24 +8,31 @@ import { /** Provides methods for managing buckets in an S3 endpoint. */ class BucketManager { #DEFAULT_ENDPOINT = "https://s3.filebase.com"; + #DEFAULT_REGION = "us-east-1"; + #client; /** - * @summary Creates a new instance of the S3Client class. - * @param {clientConfiguration} clientConfiguration - The configuration object for the S3Client. + * @summary Creates a new instance of the constructor. + * @param {string} clientKey - The access key ID for authentication. + * @param {string} clientSecret - The secret access key for authentication. * @example * import { BucketManager } from "@filebase/sdk"; - * const bucketManager = new BucketManager({ - * credentials: { - * accessKeyId: "KEY_FROM_DASHBOARD", - * secretAccessKey: "SECRET_FROM_DASHBOARD", - * }, - * }); + * const bucketManager = new BucketManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD"); */ - constructor(clientConfiguration) { - clientConfiguration.endpoint = - clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; - clientConfiguration.region = clientConfiguration.region || "us-east-1"; + constructor(clientKey, clientSecret) { + const clientEndpoint = + process.env.NODE_ENV === "test" + ? process.env.TEST_S3_ENDPOINT || this.#DEFAULT_ENDPOINT + : this.#DEFAULT_ENDPOINT, + clientConfiguration = { + credentials: { + accessKeyId: clientKey, + secretAccessKey: clientSecret, + }, + endpoint: clientEndpoint, + region: this.#DEFAULT_REGION, + }; this.#client = new S3Client(clientConfiguration); } diff --git a/src/gatewayManager.js b/src/gatewayManager.js index 2b7953d..6e81ff9 100644 --- a/src/gatewayManager.js +++ b/src/gatewayManager.js @@ -8,28 +8,21 @@ class GatewayManager { /** * @summary Creates a new instance of the constructor. - * @param {clientConfiguration} clientConfiguration - The configuration object for the client. + * @param {string} clientKey - The access key ID for authentication. + * @param {string} clientSecret - The secret access key for authentication. * @example * import { GatewayManager } from "@filebase/sdk"; - * const gatewayManager = new GatewayManager({ - * credentials: { - * accessKeyId: "KEY_FROM_DASHBOARD", - * secretAccessKey: "SECRET_FROM_DASHBOARD", - * }, - * }); + * const gatewayManager = new GatewayManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD"); */ - constructor(clientConfiguration) { - clientConfiguration.endpoint = - clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; - const configErrors = this.#validateClientConfiguration(clientConfiguration); - if (configErrors.length > 0) { - throw new Error(configErrors.join("\n")); - } - - const encodedToken = Buffer.from( - `${clientConfiguration.credentials.accessKeyId}:${clientConfiguration.credentials.secretAccessKey}`, - ).toString("base64"), - baseURL = `${clientConfiguration.endpoint}/v1/gateways`; + constructor(clientKey, clientSecret) { + const clientEndpoint = + process.env.NODE_ENV === "test" + ? process.env.TEST_GW_ENDPOINT || this.#DEFAULT_ENDPOINT + : this.#DEFAULT_ENDPOINT, + encodedToken = Buffer.from(`${clientKey}:${clientSecret}`).toString( + "base64", + ), + baseURL = `${clientEndpoint}/v1/gateways`; this.#client = axios.create({ baseURL: baseURL, timeout: this.#DEFAULT_TIMEOUT, @@ -37,29 +30,6 @@ class GatewayManager { }); } - /** - * @summary Validates the client configuration. - * @param {clientConfiguration} clientConfiguration - The client configuration object. - * @returns {string[]} - An array containing any validation errors found in the client configuration. - */ - #validateClientConfiguration(clientConfiguration) { - let configErrors = []; - - if (typeof clientConfiguration?.credentials?.accessKeyId !== "string") { - configErrors.push( - "clientConfiguration must contain credentials.accessKeyId", - ); - } - - if (typeof clientConfiguration?.credentials?.secretAccessKey !== "string") { - configErrors.push( - "clientConfiguration must contain credentials.secretAccessKey", - ); - } - - return configErrors; - } - /** * @typedef {Object} gateway * @property {string} name Name for the gateway diff --git a/src/index.js b/src/index.js index 2587c84..1ed77e3 100644 --- a/src/index.js +++ b/src/index.js @@ -3,16 +3,4 @@ import ObjectManager from "./objectManager.js"; import GatewayManager from "./gatewayManager.js"; import NameManager from "./nameManager.js"; -/** - * @typedef {Object} clientConfiguration - * @property {clientConfigurationCredentials} credentials The credentials object for authentication. - * @property {string} [endpoint] The endpoint for the API - */ - -/** - * @typedef {Object} clientConfigurationCredentials - * @property {string} accessKeyId The access key ID for authentication. - * @property {string} secretAccessKey The secret access key for authentication. - */ - export { BucketManager, ObjectManager, GatewayManager, NameManager }; diff --git a/src/nameManager.js b/src/nameManager.js index 5333027..7be5a98 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -9,28 +9,21 @@ class NameManager { /** * @summary Creates a new instance of the constructor. - * @param {clientConfiguration} clientConfiguration - The configuration object for the client. + * @param {string} clientKey - The access key ID for authentication. + * @param {string} clientSecret - The secret access key for authentication. * @example * import { NameManager } from "@filebase/sdk"; - * const nameManager = new NameManager({ - * credentials: { - * accessKeyId: "KEY_FROM_DASHBOARD", - * secretAccessKey: "SECRET_FROM_DASHBOARD", - * }, - * }); + * const nameManager = new NameManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD"); */ - constructor(clientConfiguration = {}) { - clientConfiguration.endpoint = - clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; - const configErrors = this.#validateClientConfiguration(clientConfiguration); - if (configErrors.length > 0) { - throw new Error(configErrors.join("\n")); - } - - const encodedToken = Buffer.from( - `${clientConfiguration.credentials.accessKeyId}:${clientConfiguration.credentials.secretAccessKey}`, - ).toString("base64"), - baseURL = `${clientConfiguration.endpoint}/v1/names`; + constructor(clientKey, clientSecret) { + const clientEndpoint = + process.env.NODE_ENV === "test" + ? process.env.TEST_NAME_ENDPOINT || this.#DEFAULT_ENDPOINT + : this.#DEFAULT_ENDPOINT, + encodedToken = Buffer.from(`${clientKey}:${clientSecret}`).toString( + "base64", + ), + baseURL = `${clientEndpoint}/v1/names`; this.#client = axios.create({ baseURL: baseURL, timeout: this.#DEFAULT_TIMEOUT, @@ -38,29 +31,6 @@ class NameManager { }); } - /** - * @summary Validates the client configuration. - * @param {clientConfiguration} clientConfiguration - The client configuration object. - * @returns {string[]} - An array containing any validation errors found in the client configuration. - */ - #validateClientConfiguration(clientConfiguration) { - let configErrors = []; - - if (typeof clientConfiguration?.credentials?.accessKeyId !== "string") { - configErrors.push( - "clientConfiguration must contain credentials.accessKeyId", - ); - } - - if (typeof clientConfiguration?.credentials?.secretAccessKey !== "string") { - configErrors.push( - "clientConfiguration must contain credentials.secretAccessKey", - ); - } - - return configErrors; - } - /** * @typedef {Object} name * @property {string} label Descriptive label for the Key diff --git a/src/objectManager.js b/src/objectManager.js index c5611f8..3a3808a 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -23,47 +23,48 @@ import { v4 as uuidv4 } from "uuid"; /** Interacts with an S3 client to perform various operations on objects in a bucket. */ class ObjectManager { #DEFAULT_ENDPOINT = "https://s3.filebase.com"; + #DEFAULT_REGION = "us-east-1"; + #DEFAULT_MAX_CONCURRENT_UPLOADS = 4; + #client; #defaultBucket; - #maxConcurrentUploads = 4; + #maxConcurrentUploads; /** * @typedef {Object} objectManagerOptions Optional settings for the constructor. - * @property {number} maxConcurrentUploads The maximum number of concurrent uploads. + * @property {string} [bucket] Default bucket to use. + * @property {number} [maxConcurrentUploads] The maximum number of concurrent uploads. */ /** - * @summary Creates a new instance of the class. - * @param {object} clientConfiguration - The configuration object for the S3 client. - * @param {string} defaultBucket - The default S3 bucket to be used. + * @summary Creates a new instance of the constructor. + * @param {string} clientKey - The access key ID for authentication. + * @param {string} clientSecret - The secret access key for authentication. * @param {objectManagerOptions} options - Optional settings for the constructor. * @example * import { ObjectManager } from "@filebase/sdk"; - * const objectManager = new ObjectManager({ - * credentials: { - * accessKeyId: "KEY_FROM_DASHBOARD", - * secretAccessKey: "SECRET_FROM_DASHBOARD", - * }, - * }, "my-default-bucket", { + * const objectManager = new ObjectManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD", { + * bucket: "my-default-bucket", * maxConcurrentUploads: 4 * }); */ - constructor( - clientConfiguration, - defaultBucket, - options = { - maxConcurrentUploads: 4, - }, - ) { - clientConfiguration.endpoint = - clientConfiguration.endpoint || this.#DEFAULT_ENDPOINT; - clientConfiguration.region = clientConfiguration.region || "us-east-1"; + constructor(clientKey, clientSecret, options) { + const clientEndpoint = + process.env.NODE_ENV === "test" + ? process.env.TEST_S3_ENDPOINT || this.#DEFAULT_ENDPOINT + : this.#DEFAULT_ENDPOINT, + clientConfiguration = { + credentials: { + accessKeyId: clientKey, + secretAccessKey: clientSecret, + }, + endpoint: clientEndpoint, + region: this.#DEFAULT_REGION, + }; + this.#defaultBucket = options?.bucket; + this.#maxConcurrentUploads = + options?.maxConcurrentUploads || this.#DEFAULT_MAX_CONCURRENT_UPLOADS; this.#client = new S3Client(clientConfiguration); - this.#defaultBucket = defaultBucket; - - if (options?.maxConcurrentUploads) { - this.#maxConcurrentUploads = Number(options.maxConcurrentUploads); - } } /** diff --git a/test/bucketManager.spec.js b/test/bucketManager.spec.js index f149561..b41db02 100644 --- a/test/bucketManager.spec.js +++ b/test/bucketManager.spec.js @@ -2,19 +2,14 @@ import test from "node:test"; import assert from "node:assert/strict"; import BucketManager from "../src/bucketManager.js"; -const TEST_PREFIX = Date.now(), - S3_CONFIG = { - endpoint: process.env.TEST_S3_ENDPOINT, - credentials: { - accessKeyId: process.env.TEST_S3_KEY, - secretAccessKey: process.env.TEST_S3_SECRET, - }, - region: process.env.TEST_S3_REGION, - }; +const TEST_PREFIX = Date.now(); test("create bucket", async (t) => { // Initialize BucketManager - const bucketManager = new BucketManager(S3_CONFIG); + const bucketManager = new BucketManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + ); // Create bucket `create-bucket-test-pass` const bucketNameToCreate = `${TEST_PREFIX}-create-bucket-test-pass`; @@ -35,7 +30,10 @@ test("create bucket", async (t) => { test("delete bucket", async (t) => { // Initialize BucketManager - const bucketManager = new BucketManager(S3_CONFIG); + const bucketManager = new BucketManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + ); // Create bucket `delete-bucket-test-pass` const bucketNameToCreate = `${TEST_PREFIX}-delete-bucket-test-pass`; diff --git a/test/gatewayManager.spec.js b/test/gatewayManager.spec.js index 7d145ca..d690663 100644 --- a/test/gatewayManager.spec.js +++ b/test/gatewayManager.spec.js @@ -2,18 +2,14 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import GatewayManager from "../src/gatewayManager.js"; -const TEST_PREFIX = Date.now(), - S3_CONFIG = { - endpoint: process.env.TEST_GW_ENDPOINT, - credentials: { - accessKeyId: process.env.TEST_GW_KEY, - secretAccessKey: process.env.TEST_GW_SECRET, - }, - }; +const TEST_PREFIX = Date.now(); test("delete gateway", async () => { const testGatewayName = `${TEST_PREFIX}-delete-gateway-test-pass`, - gatewayManager = new GatewayManager(S3_CONFIG); + gatewayManager = new GatewayManager( + process.env.TEST_GW_KEY, + process.env.TEST_GW_SECRET, + ); await gatewayManager.create(testGatewayName); await gatewayManager.delete(testGatewayName); const deletedName = await gatewayManager.get(testGatewayName); @@ -21,7 +17,10 @@ test("delete gateway", async () => { }); test("create gateway", async () => { const testGatewayName = `${TEST_PREFIX}-create-gateway-test-pass`, - gatewayManager = new GatewayManager(S3_CONFIG), + gatewayManager = new GatewayManager( + process.env.TEST_GW_KEY, + process.env.TEST_GW_SECRET, + ), createdName = await gatewayManager.create(testGatewayName); await gatewayManager.delete(testGatewayName); assert.strictEqual(createdName.name, testGatewayName); @@ -29,7 +28,10 @@ test("create gateway", async () => { test("update gateway", async () => { const testGatewayName = `${TEST_PREFIX}-update-gateway-test-pass`, - gatewayManager = new GatewayManager(S3_CONFIG), + gatewayManager = new GatewayManager( + process.env.TEST_GW_KEY, + process.env.TEST_GW_SECRET, + ), createdName = await gatewayManager.create(testGatewayName), updatedName = await gatewayManager.update(createdName.name, { private: true, @@ -41,7 +43,10 @@ test("update gateway", async () => { test("get gateway", async () => { const testGatewayName = `${TEST_PREFIX}-get-gateway-test-pass`, - gatewayManager = new GatewayManager(S3_CONFIG), + gatewayManager = new GatewayManager( + process.env.TEST_GW_KEY, + process.env.TEST_GW_SECRET, + ), createdName = await gatewayManager.create(testGatewayName, {}), testName = await gatewayManager.get(createdName.name); await gatewayManager.delete(testGatewayName); @@ -50,7 +55,10 @@ test("get gateway", async () => { test("list gateways", async () => { const testGatewayName = `${TEST_PREFIX}-list-names-test-pass`, - gatewayManager = new GatewayManager(S3_CONFIG); + gatewayManager = new GatewayManager( + process.env.TEST_GW_KEY, + process.env.TEST_GW_SECRET, + ); const initialGatewaysList = await gatewayManager.list(); for (let i = 0; i < 10; i++) { await gatewayManager.create(`${testGatewayName}-${i}`); @@ -64,7 +72,7 @@ test("list gateways", async () => { /*test("toggle gateway", async () => { const testGatewayName = `${TEST_PREFIX}-toggle-gateway-test-pass`, - gatewayManager = new GatewayManager(S3_CONFIG); + gatewayManager = new GatewayManager(process.env.TEST_GW_KEY, process.env.TEST_GW_SECRET); await gatewayManager.create(testGatewayName, { enabled: false, }); diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index 7eb3abd..da6a5e7 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -4,18 +4,14 @@ import NameManager from "../src/nameManager.js"; const TEST_CID = process.env.TEST_IPNS_CID, TEST_PRIVATE_KEY = process.env.TEST_IPNS_PRIVATE_KEY, - TEST_PREFIX = Date.now(), - S3_CONFIG = { - endpoint: process.env.TEST_IPNS_ENDPOINT, - credentials: { - accessKeyId: process.env.TEST_IPNS_KEY, - secretAccessKey: process.env.TEST_IPNS_SECRET, - }, - }; + TEST_PREFIX = Date.now(); test("delete name", async () => { const testNameLabel = `${TEST_PREFIX}-delete-name-test-pass`, - nameManager = new NameManager(S3_CONFIG); + nameManager = new NameManager( + process.env.TEST_NAME_KEY, + process.env.TEST_NAME_SECRET, + ); await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); const deletedName = await nameManager.get(testNameLabel); @@ -23,7 +19,10 @@ test("delete name", async () => { }); test("create name", async () => { const testNameLabel = `${TEST_PREFIX}-create-name-test-pass`, - nameManager = new NameManager(S3_CONFIG), + nameManager = new NameManager( + process.env.TEST_NAME_KEY, + process.env.TEST_NAME_SECRET, + ), createdName = await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); assert.strictEqual(createdName.label, testNameLabel); @@ -32,7 +31,10 @@ test("create name", async () => { test("import name", async () => { const testNameLabel = `${TEST_PREFIX}-import-name-test-pass`, - nameManager = new NameManager(S3_CONFIG), + nameManager = new NameManager( + process.env.TEST_NAME_KEY, + process.env.TEST_NAME_SECRET, + ), importedName = await nameManager.import( testNameLabel, TEST_CID, @@ -45,7 +47,10 @@ test("import name", async () => { test("update name", async () => { const testNameLabel = `${TEST_PREFIX}-update-name-test-pass`, - nameManager = new NameManager(S3_CONFIG), + nameManager = new NameManager( + process.env.TEST_NAME_KEY, + process.env.TEST_NAME_SECRET, + ), createdName = await nameManager.create(testNameLabel, TEST_CID), updatedName = await nameManager.update(createdName.label, TEST_CID); await nameManager.delete(testNameLabel); @@ -54,7 +59,10 @@ test("update name", async () => { test("get name", async () => { const testNameLabel = `${TEST_PREFIX}-get-name-test-pass`, - nameManager = new NameManager(S3_CONFIG), + nameManager = new NameManager( + process.env.TEST_NAME_KEY, + process.env.TEST_NAME_SECRET, + ), createdName = await nameManager.create(testNameLabel, TEST_CID), testName = await nameManager.get(createdName.label); await nameManager.delete(testNameLabel); @@ -64,7 +72,10 @@ test("get name", async () => { test("list names", async () => { const testNameLabel = `${TEST_PREFIX}-list-names-test-pass`, - nameManager = new NameManager(S3_CONFIG); + nameManager = new NameManager( + process.env.TEST_NAME_KEY, + process.env.TEST_NAME_SECRET, + ); for (let i = 0; i < 10; i++) { await nameManager.create(`${testNameLabel}-${i}`, TEST_CID); } @@ -77,7 +88,10 @@ test("list names", async () => { test("toggle name", async () => { const testNameLabel = `${TEST_PREFIX}-toggle-name-test-pass`, - nameManager = new NameManager(S3_CONFIG); + nameManager = new NameManager( + process.env.TEST_NAME_KEY, + process.env.TEST_NAME_SECRET, + ); await nameManager.create(testNameLabel, TEST_CID, { enabled: false, }); diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 8eb38b2..2551fd7 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -7,19 +7,14 @@ import { writeFile } from "node:fs/promises"; import { v4 as uuidv4 } from "uuid"; import os from "node:os"; -const TEST_PREFIX = Date.now(), - S3_CONFIG = { - endpoint: process.env.TEST_S3_ENDPOINT, - credentials: { - accessKeyId: process.env.TEST_S3_KEY, - secretAccessKey: process.env.TEST_S3_SECRET, - }, - region: process.env.TEST_S3_REGION, - }; +const TEST_PREFIX = Date.now(); async function createBucket(name) { // Initialize BucketManager - const bucketManager = new BucketManager(S3_CONFIG); + const bucketManager = new BucketManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + ); // Create bucket with name const bucketNameToCreate = name; @@ -36,7 +31,11 @@ async function createBucket(name) { async function uploadObject(bucket, key, body) { // Initialize ObjectManager - const objectManager = new ObjectManager(S3_CONFIG, bucket); + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + { bucket }, + ); // Upload Object await objectManager.upload(key, body); @@ -53,7 +52,11 @@ async function uploadObject(bucket, key, body) { async function deleteObject(bucket, key) { // Initialize ObjectManager - const objectManager = new ObjectManager(S3_CONFIG, bucket); + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + { bucket }, + ); // Delete Object await objectManager.delete(key); @@ -62,7 +65,10 @@ async function deleteObject(bucket, key) { async function deleteBucket(bucket) { // Initialize BucketManager - const bucketManager = new BucketManager(S3_CONFIG); + const bucketManager = new BucketManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + ); // Delete Bucket await bucketManager.delete(bucket); @@ -86,7 +92,11 @@ test("delete object", async () => { } // Initialize ObjectManager - const objectManager = new ObjectManager(S3_CONFIG, deleteTestBucket); + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + { bucket: deleteTestBucket }, + ); // Delete object `delete-object-test` await objectManager.delete(objectNameToCreate); @@ -164,7 +174,11 @@ test("download object", async () => { } // Download object `download-object-test` and assert it completes - const objectManager = new ObjectManager(S3_CONFIG, downloadTestBucket); + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + { bucket: downloadTestBucket }, + ); const downloadStream = await objectManager.download(objectNameToCreate), downloadFilename = uuidv4(), downloadPath = Path.resolve(os.tmpdir(), downloadFilename), @@ -191,7 +205,11 @@ test("list objects", async () => { createdObjectCount++; } - const objectManager = new ObjectManager(S3_CONFIG, listTestBucket); + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY, + process.env.TEST_S3_SECRET, + { bucket: listTestBucket }, + ); const bucketList = await objectManager.list({ MaxKeys: 50, From 39aea8c626d1d612f22524c8c894785071f5567e Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:38:55 -0600 Subject: [PATCH 46/79] Testing & Privacy Adds function to toggle privacy of bucket Updates Testing --- src/bucketManager.js | 40 +++++++++++++++++++++ test/bucketManager.spec.js | 69 ++++++++++++++++++++++++++++++++++--- test/gatewayManager.spec.js | 61 ++++++++++++++++++++++---------- test/nameManager.spec.js | 63 ++++++++++++++++++++++----------- test/objectManager.spec.js | 28 +++++++-------- 5 files changed, 204 insertions(+), 57 deletions(-) diff --git a/src/bucketManager.js b/src/bucketManager.js index 635ebc4..189a87b 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -1,7 +1,9 @@ import { CreateBucketCommand, DeleteBucketCommand, + GetBucketAclCommand, ListBucketsCommand, + PutBucketAclCommand, S3Client, } from "@aws-sdk/client-s3"; @@ -88,6 +90,44 @@ class BucketManager { await this.#client.send(command); return true; } + + /** + * @summary Sets the privacy of a given bucket. + * @param {string} name - The name of the bucket to toggle. + * @param {boolean} targetState - The new target state. [true=private,false=public] + * @returns {Promise} A promise that resolves to true if the bucket was successfully toggled. + * @example + * // Toggle bucket with label of `toggle-bucket-example` + * await bucketManager.toggle(`toggle-bucket-example`, true); // Enabled + * await bucketManager.toggle(`toggle-bucket-example`, false); // Disabled + */ + + async setPrivacy(name, targetState) { + const command = new PutBucketAclCommand({ + Bucket: name, + ACL: targetState ? "private" : "public-read", + }); + + await this.#client.send(command); + return true; + } + + /** + * @summary Gets the privacy of a given bucket + * @param {string} name - The name of the bucket to query. + * @returns {Promise} A promise that resolves to true if the bucket is private. + */ + async getPrivacy(name) { + const command = new GetBucketAclCommand({ + Bucket: name, + }); + + const response = await this.#client.send(command), + readPermission = response.Grants.find((grant) => { + return grant.Grantee.Type === "Group" && grant.Permission === "READ"; + }); + return !(typeof readPermission !== "undefined"); + } } export default BucketManager; diff --git a/test/bucketManager.spec.js b/test/bucketManager.spec.js index b41db02..745492c 100644 --- a/test/bucketManager.spec.js +++ b/test/bucketManager.spec.js @@ -1,14 +1,15 @@ import test from "node:test"; import assert from "node:assert/strict"; import BucketManager from "../src/bucketManager.js"; +import GatewayManager from "../src/gatewayManager.js"; const TEST_PREFIX = Date.now(); test("create bucket", async (t) => { // Initialize BucketManager const bucketManager = new BucketManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, ); // Create bucket `create-bucket-test-pass` @@ -28,11 +29,32 @@ test("create bucket", async (t) => { assert.equal(createdBucket.Name, bucketNameToCreate); }); +test("list buckets", async () => { + const testBucketName = `${TEST_PREFIX}-list-bucket-test-pass`, + bucketManager = new BucketManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + ), + initialBucketsList = await bucketManager.list(), + countToCreate = 3; + for (let i = 0; i < countToCreate; i++) { + await bucketManager.create(`${testBucketName}-${i}`); + } + const bucketsList = await bucketManager.list(); + for (let i = 0; i < countToCreate; i++) { + await bucketManager.delete(`${testBucketName}-${i}`); + } + assert.strictEqual( + bucketsList.length, + initialBucketsList.length + countToCreate, + ); +}); + test("delete bucket", async (t) => { // Initialize BucketManager const bucketManager = new BucketManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, ); // Create bucket `delete-bucket-test-pass` @@ -58,3 +80,42 @@ test("delete bucket", async (t) => { }); assert.equal(typeof deletedBucket, "undefined"); }); + +test("set bucket privacy to public", async (t) => { + // Initialize BucketManager + const bucketManager = new BucketManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + ); + + // Create bucket `toggle-bucket-test-pass` + const bucketNameToCreate = `${TEST_PREFIX}-toggle-bucket-test-pass`; + await bucketManager.create(bucketNameToCreate); + + // List buckets + const currentBuckets = await bucketManager.list(), + createdBucket = currentBuckets.find((currentBucket) => { + return currentBucket.Name === bucketNameToCreate; + }); + + // Check Privacy + const initialPrivacy = await bucketManager.getPrivacy(bucketNameToCreate); + if (initialPrivacy === false) { + throw new Error(`Unexpected Privacy State on Bucket`); + } + + // Toggle Privacy + await bucketManager.setPrivacy(bucketNameToCreate, false); + + // Check Privacy + const updatedPrivacy = await bucketManager.getPrivacy(bucketNameToCreate); + if (updatedPrivacy === true) { + throw new Error(`Unexpected Privacy State on Bucket`); + } + + // Delete new bucket + await bucketManager.delete(bucketNameToCreate); + + // Assert new bucket exists + assert.equal(createdBucket.Name, bucketNameToCreate); +}); diff --git a/test/gatewayManager.spec.js b/test/gatewayManager.spec.js index d690663..381aa59 100644 --- a/test/gatewayManager.spec.js +++ b/test/gatewayManager.spec.js @@ -7,8 +7,8 @@ const TEST_PREFIX = Date.now(); test("delete gateway", async () => { const testGatewayName = `${TEST_PREFIX}-delete-gateway-test-pass`, gatewayManager = new GatewayManager( - process.env.TEST_GW_KEY, - process.env.TEST_GW_SECRET, + process.env.TEST_GW_KEY || process.env.TEST_KEY, + process.env.TEST_GW_SECRET || process.env.TEST_SECRET, ); await gatewayManager.create(testGatewayName); await gatewayManager.delete(testGatewayName); @@ -18,8 +18,8 @@ test("delete gateway", async () => { test("create gateway", async () => { const testGatewayName = `${TEST_PREFIX}-create-gateway-test-pass`, gatewayManager = new GatewayManager( - process.env.TEST_GW_KEY, - process.env.TEST_GW_SECRET, + process.env.TEST_GW_KEY || process.env.TEST_KEY, + process.env.TEST_GW_SECRET || process.env.TEST_SECRET, ), createdName = await gatewayManager.create(testGatewayName); await gatewayManager.delete(testGatewayName); @@ -29,8 +29,8 @@ test("create gateway", async () => { test("update gateway", async () => { const testGatewayName = `${TEST_PREFIX}-update-gateway-test-pass`, gatewayManager = new GatewayManager( - process.env.TEST_GW_KEY, - process.env.TEST_GW_SECRET, + process.env.TEST_GW_KEY || process.env.TEST_KEY, + process.env.TEST_GW_SECRET || process.env.TEST_SECRET, ), createdName = await gatewayManager.create(testGatewayName), updatedName = await gatewayManager.update(createdName.name, { @@ -44,8 +44,8 @@ test("update gateway", async () => { test("get gateway", async () => { const testGatewayName = `${TEST_PREFIX}-get-gateway-test-pass`, gatewayManager = new GatewayManager( - process.env.TEST_GW_KEY, - process.env.TEST_GW_SECRET, + process.env.TEST_GW_KEY || process.env.TEST_KEY, + process.env.TEST_GW_SECRET || process.env.TEST_SECRET, ), createdName = await gatewayManager.create(testGatewayName, {}), testName = await gatewayManager.get(createdName.name); @@ -56,23 +56,48 @@ test("get gateway", async () => { test("list gateways", async () => { const testGatewayName = `${TEST_PREFIX}-list-names-test-pass`, gatewayManager = new GatewayManager( - process.env.TEST_GW_KEY, - process.env.TEST_GW_SECRET, - ); - const initialGatewaysList = await gatewayManager.list(); - for (let i = 0; i < 10; i++) { + process.env.TEST_GW_KEY || process.env.TEST_KEY, + process.env.TEST_GW_SECRET || process.env.TEST_SECRET, + ), + initialGatewaysList = await gatewayManager.list(), + countToCreate = 3; + for (let i = 0; i < countToCreate; i++) { await gatewayManager.create(`${testGatewayName}-${i}`); } const gatewaysList = await gatewayManager.list(); - for (let i = 0; i < 10; i++) { + for (let i = 0; i < countToCreate; i++) { await gatewayManager.delete(`${testGatewayName}-${i}`); } - assert.strictEqual(gatewaysList.length, initialGatewaysList.length + 10); + assert.strictEqual( + gatewaysList.length, + initialGatewaysList.length + countToCreate, + ); }); -/*test("toggle gateway", async () => { +test("toggle gateway off", async () => { const testGatewayName = `${TEST_PREFIX}-toggle-gateway-test-pass`, - gatewayManager = new GatewayManager(process.env.TEST_GW_KEY, process.env.TEST_GW_SECRET); + gatewayManager = new GatewayManager( + process.env.TEST_GW_KEY || process.env.TEST_KEY, + process.env.TEST_GW_SECRET || process.env.TEST_SECRET, + ); + await gatewayManager.create(testGatewayName); + const resolvedName = await gatewayManager.get(testGatewayName); + if (resolvedName?.enabled === false) { + throw new Error(`Incorrect State on Resolved Name`); + } + await gatewayManager.toggle(testGatewayName, false); + const updatedName = await gatewayManager.get(testGatewayName); + await gatewayManager.delete(testGatewayName); + assert.strictEqual(updatedName.name, testGatewayName); + assert.strictEqual(updatedName.enabled, false); +}); + +test("toggle gateway on", async () => { + const testGatewayName = `${TEST_PREFIX}-toggle-gateway-test-pass`, + gatewayManager = new GatewayManager( + process.env.TEST_GW_KEY || process.env.TEST_KEY, + process.env.TEST_GW_SECRET || process.env.TEST_SECRET, + ); await gatewayManager.create(testGatewayName, { enabled: false, }); @@ -85,4 +110,4 @@ test("list gateways", async () => { await gatewayManager.delete(testGatewayName); assert.strictEqual(updatedName.name, testGatewayName); assert.strictEqual(updatedName.enabled, true); -});*/ +}); diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index da6a5e7..f8c9a93 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -2,15 +2,15 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import NameManager from "../src/nameManager.js"; -const TEST_CID = process.env.TEST_IPNS_CID, - TEST_PRIVATE_KEY = process.env.TEST_IPNS_PRIVATE_KEY, +const TEST_CID = process.env.TEST_NAME_CID, + TEST_PRIVATE_KEY = process.env.TEST_NAME_PRIVATE_KEY, TEST_PREFIX = Date.now(); test("delete name", async () => { const testNameLabel = `${TEST_PREFIX}-delete-name-test-pass`, nameManager = new NameManager( - process.env.TEST_NAME_KEY, - process.env.TEST_NAME_SECRET, + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ); await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); @@ -20,8 +20,8 @@ test("delete name", async () => { test("create name", async () => { const testNameLabel = `${TEST_PREFIX}-create-name-test-pass`, nameManager = new NameManager( - process.env.TEST_NAME_KEY, - process.env.TEST_NAME_SECRET, + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ), createdName = await nameManager.create(testNameLabel, TEST_CID); await nameManager.delete(testNameLabel); @@ -32,8 +32,8 @@ test("create name", async () => { test("import name", async () => { const testNameLabel = `${TEST_PREFIX}-import-name-test-pass`, nameManager = new NameManager( - process.env.TEST_NAME_KEY, - process.env.TEST_NAME_SECRET, + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ), importedName = await nameManager.import( testNameLabel, @@ -48,8 +48,8 @@ test("import name", async () => { test("update name", async () => { const testNameLabel = `${TEST_PREFIX}-update-name-test-pass`, nameManager = new NameManager( - process.env.TEST_NAME_KEY, - process.env.TEST_NAME_SECRET, + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ), createdName = await nameManager.create(testNameLabel, TEST_CID), updatedName = await nameManager.update(createdName.label, TEST_CID); @@ -60,8 +60,8 @@ test("update name", async () => { test("get name", async () => { const testNameLabel = `${TEST_PREFIX}-get-name-test-pass`, nameManager = new NameManager( - process.env.TEST_NAME_KEY, - process.env.TEST_NAME_SECRET, + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ), createdName = await nameManager.create(testNameLabel, TEST_CID), testName = await nameManager.get(createdName.label); @@ -73,24 +73,26 @@ test("get name", async () => { test("list names", async () => { const testNameLabel = `${TEST_PREFIX}-list-names-test-pass`, nameManager = new NameManager( - process.env.TEST_NAME_KEY, - process.env.TEST_NAME_SECRET, - ); - for (let i = 0; i < 10; i++) { + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + ), + initialNamesList = await nameManager.list(), + countToCreate = 3; + for (let i = 0; i < countToCreate; i++) { await nameManager.create(`${testNameLabel}-${i}`, TEST_CID); } const namesList = await nameManager.list(); - for (let i = 0; i < 10; i++) { + for (let i = 0; i < countToCreate; i++) { await nameManager.delete(`${testNameLabel}-${i}`); } - assert.strictEqual(namesList.length, 10); + assert.strictEqual(namesList.length, initialNamesList.length + countToCreate); }); -test("toggle name", async () => { +test("toggle name on", async () => { const testNameLabel = `${TEST_PREFIX}-toggle-name-test-pass`, nameManager = new NameManager( - process.env.TEST_NAME_KEY, - process.env.TEST_NAME_SECRET, + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ); await nameManager.create(testNameLabel, TEST_CID, { enabled: false, @@ -106,3 +108,22 @@ test("toggle name", async () => { assert.strictEqual(updatedName.cid, TEST_CID); assert.strictEqual(updatedName.enabled, true); }); + +test("toggle name off", async () => { + const testNameLabel = `${TEST_PREFIX}-toggle-name-test-pass`, + nameManager = new NameManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + ); + await nameManager.create(testNameLabel, TEST_CID); + const resolvedName = await nameManager.list(testNameLabel); + if (resolvedName?.enabled === false) { + throw new Error(`Incorrect State on Resolved Name`); + } + await nameManager.toggle(testNameLabel, false); + const updatedName = await nameManager.get(testNameLabel); + await nameManager.delete(testNameLabel); + assert.strictEqual(updatedName.label, testNameLabel); + assert.strictEqual(updatedName.cid, TEST_CID); + assert.strictEqual(updatedName.enabled, false); +}); diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 2551fd7..0e177e7 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -12,8 +12,8 @@ const TEST_PREFIX = Date.now(); async function createBucket(name) { // Initialize BucketManager const bucketManager = new BucketManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, ); // Create bucket with name @@ -32,8 +32,8 @@ async function createBucket(name) { async function uploadObject(bucket, key, body) { // Initialize ObjectManager const objectManager = new ObjectManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, { bucket }, ); @@ -53,8 +53,8 @@ async function uploadObject(bucket, key, body) { async function deleteObject(bucket, key) { // Initialize ObjectManager const objectManager = new ObjectManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, { bucket }, ); @@ -66,8 +66,8 @@ async function deleteObject(bucket, key) { async function deleteBucket(bucket) { // Initialize BucketManager const bucketManager = new BucketManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, ); // Delete Bucket @@ -93,8 +93,8 @@ test("delete object", async () => { // Initialize ObjectManager const objectManager = new ObjectManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, { bucket: deleteTestBucket }, ); @@ -175,8 +175,8 @@ test("download object", async () => { // Download object `download-object-test` and assert it completes const objectManager = new ObjectManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, { bucket: downloadTestBucket }, ); const downloadStream = await objectManager.download(objectNameToCreate), @@ -206,8 +206,8 @@ test("list objects", async () => { } const objectManager = new ObjectManager( - process.env.TEST_S3_KEY, - process.env.TEST_S3_SECRET, + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, { bucket: listTestBucket }, ); From 35175dc7c596d712977015ee85cebe4091041b36 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:41:45 -0600 Subject: [PATCH 47/79] Update test.yml --- .github/workflows/test.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0c9e5ac..928b3ef 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,15 +15,7 @@ jobs: - run: npm ci - run: npm test env: - TEST_GW_ENDPOINT: ${{ vars.TEST_GW_ENDPOINT }} - TEST_GW_KEY: ${{ secrets.TEST_GW_KEY }} - TEST_GW_SECRET: ${{ secrets.TEST_GW_SECRET }} - TEST_IPNS_ENDPOINT: ${{ vars.TEST_IPNS_ENDPOINT }} + TEST_KEY: ${{ secrets.TEST_KEY }} + TEST_SECRET: ${{ secrets.TEST_SECRET }} TEST_IPNS_CID: ${{ vars.TEST_IPNS_CID }} - TEST_IPNS_KEY: ${{ secrets.TEST_IPNS_KEY }} - TEST_IPNS_SECRET: ${{ secrets.TEST_IPNS_SECRET }} TEST_IPNS_PRIVATE_KEY: ${{ secrets.TEST_IPNS_PRIVATE_KEY }} - TEST_S3_ENDPOINT: ${{ vars.TEST_S3_ENDPOINT }} - TEST_S3_REGION: ${{ vars.TEST_S3_REGION }} - TEST_S3_KEY: ${{ secrets.TEST_S3_KEY }} - TEST_S3_SECRET: ${{ secrets.TEST_S3_SECRET }} From 2ed42e83d00115f22811ca733634be14c14485e0 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:47:10 -0600 Subject: [PATCH 48/79] Update test.yml --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 928b3ef..d775782 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: - run: npm ci - run: npm test env: - TEST_KEY: ${{ secrets.TEST_KEY }} - TEST_SECRET: ${{ secrets.TEST_SECRET }} + TEST_KEY: ${{ secrets.TEST_S3_KEY }} + TEST_SECRET: ${{ secrets.TEST_S3_SECRET }} TEST_IPNS_CID: ${{ vars.TEST_IPNS_CID }} TEST_IPNS_PRIVATE_KEY: ${{ secrets.TEST_IPNS_PRIVATE_KEY }} From 0ce9ab6dca979d778bf64c4850132bf50973a91f Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 12 Dec 2023 14:16:26 -0600 Subject: [PATCH 49/79] Stash Copy Support --- src/objectManager.js | 33 +++++++++++++++++++++++++++++++++ test/objectManager.spec.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/objectManager.js b/src/objectManager.js index 3a3808a..c5ef8e5 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -1,5 +1,6 @@ // S3 Imports import { + CopyObjectCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, @@ -294,6 +295,38 @@ class ObjectManager { await this.#client.send(command); return true; } + + /** + * If the destinationKey is not provided, the object will be copied with the same key as the sourceKey. + * + * @summary Copy the object from sourceKey in the sourceBucket to destinationKey in the destinationBucket. + * @param {string} sourceKey - The key of the object to be copied from the sourceBucket. + * @param {string} destinationBucket - The bucket where the object will be copied to. + * @param {object} [options] - Additional options for the copy operation. + * @param {string} [options.sourceBucket] - The source bucket from where the object is to be copied. + * @param {string} [options.destinationKey] - The key of the object in the destination bucket. By default, it is the same as the sourceKey. + * + * @returns {Promise<*>} - A Promise that resolves with the response of the copy operation. + */ + async copy( + sourceKey, + destinationBucket, + options = { + sourceBucket: this.#defaultBucket, + destinationKey: undefined, + }, + ) { + const copySource = `${ + options?.sourceBucket || this.#defaultBucket + }/${sourceKey}`, + command = new CopyObjectCommand({ + CopySource: copySource, + Bucket: destinationBucket, + Key: options?.destinationKey || sourceKey, + }); + + return await this.#client.send(command); + } } export default ObjectManager; diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 0e177e7..2afd6a2 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -226,3 +226,40 @@ test("list objects", async () => { } await deleteBucket(listTestBucket); }); + +test("copy object", async () => { + // Create bucket `copy-object-test-pass-src` + const bucketSrc = `copy-object-test-pass-src`; + await createBucket(bucketSrc); + + // Upload object `copy-object-test` + const objectNameToCreateSrc = `copy-object-test`; + const uploaded = await uploadObject( + bucketSrc, + objectNameToCreateSrc, + Buffer.from("copy object", "utf-8"), + ); + assert.equal(uploaded, true); + + // Create bucket `copy-object-test-pass-dest` + const bucketDest = `copy-object-test-pass-dest`; + await createBucket(bucketDest); + + // Initialize ObjectManager + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + { bucket: bucketDest }, + ); + + // Copy object `copy-object-test` from `copy-object-test-pass-src` to `copy-object-test-pass-dest` + await objectManager.copy(objectNameToCreateSrc, bucketSrc); + + // List bucket and assert new object exists + const existingObjects = await objectManager.list({ + Prefix: objectNameToCreateSrc, + MaxKeys: 1, + }), + copiedObject = existingObjects.length > 0 ? existingObjects[0] : undefined; + assert.equal(copiedObject.Name, objectNameToCreateSrc); +}); From fbf61b2667c8a253772ddd7984b080fbdbde46e4 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 12 Dec 2023 14:54:09 -0600 Subject: [PATCH 50/79] Simple docs update --- readme.md | 8 ++++++-- src/objectManager.js | 21 ++++++++++++++++----- test/objectManager.spec.js | 4 ++-- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/readme.md b/readme.md index 9166b91..35368d3 100644 --- a/readme.md +++ b/readme.md @@ -54,14 +54,18 @@ console.dir(bucketsList); // Initialize ObjectManager const objectManager = new ObjectManager(s3Config, bucketName); // Upload Object -const objectName = `new-object`; -const uploadedObject = await objectManager.upload(objectName, body); +const objectName = `new-object`, + uploadedObject = await objectManager.upload(objectName, Buffer.from("Hello Filebase!")); // Confirm Object Uploaded const objectsList = await objectManager.list({ Prefix: key, MaxKeys: 1, }); console.dir(objectsList) +// Copy Object to a New Bucket +const bucketCopyDestinationName = `copy-dest-bucket` +await bucketManager.create(bucketCopyDestinationName); +await objectManager.copy(`new-object`, bucketCopyDestinationName); // Initialize NameManager const nameManager = new NameManager(s3Config); diff --git a/src/objectManager.js b/src/objectManager.js index c5ef8e5..dd456de 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -296,17 +296,27 @@ class ObjectManager { return true; } + /** + * @typedef {Object} copyObjectOptions + * @property {string} [sourceBucket] The source bucket from where the object is to be copied. + * @property {string} [destinationKey] The key of the object in the destination bucket. By default, it is the same as the sourceKey. + */ + /** * If the destinationKey is not provided, the object will be copied with the same key as the sourceKey. * * @summary Copy the object from sourceKey in the sourceBucket to destinationKey in the destinationBucket. * @param {string} sourceKey - The key of the object to be copied from the sourceBucket. * @param {string} destinationBucket - The bucket where the object will be copied to. - * @param {object} [options] - Additional options for the copy operation. - * @param {string} [options.sourceBucket] - The source bucket from where the object is to be copied. - * @param {string} [options.destinationKey] - The key of the object in the destination bucket. By default, it is the same as the sourceKey. + * @param {copyObjectOptions} [options] - Additional options for the copy operation. * - * @returns {Promise<*>} - A Promise that resolves with the response of the copy operation. + * @returns {Promise} - A Promise that resolves with the result of the copy operation. + * @example + * // Copy object `copy-object-test` from `copy-object-test-pass-src` to `copy-object-test-pass-dest` + * // TIP: Set bucket on constructor and it will be used as the default source for copying objects. + * await objectManager.copy(`copy-object-test`, `copy-object-dest`, { + * sourceBucket: `copy-object-src` + * }); */ async copy( sourceKey, @@ -325,7 +335,8 @@ class ObjectManager { Key: options?.destinationKey || sourceKey, }); - return await this.#client.send(command); + await this.#client.send(command); + return true; } } diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 2afd6a2..379aa4d 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -249,11 +249,11 @@ test("copy object", async () => { const objectManager = new ObjectManager( process.env.TEST_S3_KEY || process.env.TEST_KEY, process.env.TEST_S3_SECRET || process.env.TEST_SECRET, - { bucket: bucketDest }, + { bucket: bucketSrc }, ); // Copy object `copy-object-test` from `copy-object-test-pass-src` to `copy-object-test-pass-dest` - await objectManager.copy(objectNameToCreateSrc, bucketSrc); + await objectManager.copy(objectNameToCreateSrc, bucketDest); // List bucket and assert new object exists const existingObjects = await objectManager.list({ From 0cd8de45f670a2c0d27273d360917102457e0b08 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:03:19 -0600 Subject: [PATCH 51/79] Docs Updates --- readme.md | 40 +++++++++++++++++++++++++++++++--------- src/nameManager.js | 2 +- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/readme.md b/readme.md index 9166b91..b1b80fb 100644 --- a/readme.md +++ b/readme.md @@ -43,16 +43,18 @@ import {BucketManager, ObjectManager, NameManager} from 'filebase-sdk' const s3Config = {}; // Initialize BucketManager -const bucketManager = new BucketManager(s3Config); +const bucketManager = new BucketManager(S3_KEY, S3_SECRET); // Create bucket const bucketName = `create-bucket-[random string]`; await bucketManager.create(bucketName); // List buckets const bucketsList = await bucketManager.list(); +// Toggle bucket privacy off +await bucketManager.toggle(bucketName, false); console.dir(bucketsList); // Initialize ObjectManager -const objectManager = new ObjectManager(s3Config, bucketName); +const objectManager = new ObjectManager(S3_KEY, S3_SECRET, bucketName); // Upload Object const objectName = `new-object`; const uploadedObject = await objectManager.upload(objectName, body); @@ -64,25 +66,42 @@ const objectsList = await objectManager.list({ console.dir(objectsList) // Initialize NameManager -const nameManager = new NameManager(s3Config); +const nameManager = new NameManager(S3_KEY, S3_SECRET); // Create New IPNS Name with Broadcast Disabled const ipnsName = await nameManager.create(`myFirstIpnsKey`, uploadedObject.cid, { enabled: true }); // Update IPNS Value and Optionally Enable the Broadcast -await nameManager.set(`myFirstIpnsKey`, uploadedObject.cid, { +const ipnsLabel = `myFirstIpnsKey`; +await nameManager.set(ipnsLabel, uploadedObject.cid, { enabled: true, }); // Enable IPNS Broadcast without updating the IPNS Record -await nameManager.toggle(`myFirstIpnsKey`, true); +await nameManager.toggle(ipnsLabel, true); // List IPNS Names const myIpnsNames = await nameManager.list(); // List Specific IPNS Name -const myIpnsName = await nameManager.list(`myFirstIpnsKey`); +const myIpnsName = await nameManager.list(ipnsLabel); // Import IPNS Name -const myImportedIpnsName = await nameManager.import(`myImportedKey`, uploadedObject.cid, Base64EncodedPrivateKey, { +const myImportedIpnsName = await nameManager.import(ipnsLabel, uploadedObject.cid, Base64EncodedPrivateKey, { enabled: false, -}) +}); + +// Initialize GatewayManager +const gatewayManager = new GatewayManager(S3_KEY, S3_SECRET); +// Create New Gateway +const gatewayName = "myRandomGatewayName"; +const myGateway = await gatewayManager.create(gatewayName); +// Get Gateway Setup +const gatewayConfig = await gatewayManager.get(gatewayName); +// List IPFS Gateways +const myGateways = await gatewayManager.list(); +// Update Gateway +const myUpdatedGateway = await gatewayManager.update(gatewayName, { + enabled: false +}); +// Toggle Gateway State +await gatewayManager.toggle(gatewayName, true) // Delete Object await objectManager.delete(objectName); @@ -91,7 +110,10 @@ await objectManager.delete(objectName); await bucketManager.delete(bucketName); // Delete Name -await nameManager.delete(`myFirstIpnsKey`); +await nameManager.delete(ipnsLabel); + +// Delete Gateway +await gatewayManager.delete(gatewayName); ```` Full API reference doc for the JS client are available at https://filebase.github.io/filebase-sdk diff --git a/src/nameManager.js b/src/nameManager.js index 7be5a98..a0c37f5 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -45,7 +45,7 @@ class NameManager { /** * @typedef {Object} nameOptions - * @property {boolean} enabled Whether the name is enabled or not. + * @property {boolean} [enabled] Whether the name is enabled or not. */ /** From b663d1836c9bcca3f6889c81bef40b605f9c8d96 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 12 Dec 2023 18:36:21 -0600 Subject: [PATCH 52/79] Cleanup Packages --- package-lock.json | 2363 +++------------------------------------------ package.json | 2 - 2 files changed, 120 insertions(+), 2245 deletions(-) diff --git a/package-lock.json b/package-lock.json index e945a1a..519f630 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,6 @@ "@ipld/car": "5.2.4", "axios": "1.6.2", "blockstore-fs": "1.1.6", - "dotenv": "16.3.1", - "helia": "2.1.0", "uuid": "9.0.1" }, "devDependencies": { @@ -25,43 +23,6 @@ "prettier": "3.1.0" } }, - "node_modules/@achingbrain/nat-port-mapper": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@achingbrain/nat-port-mapper/-/nat-port-mapper-1.0.12.tgz", - "integrity": "sha512-rU4G75TEOTIPlkeDnPEVwx/VmMMFta42kY2SMmVobRkrtNLnxtU08Yhriu6tSBc9oO0wXdfNNeuLnNnEnL7w/A==", - "dependencies": { - "@achingbrain/ssdp": "^4.0.1", - "@libp2p/logger": "^3.0.0", - "default-gateway": "^7.2.2", - "err-code": "^3.0.1", - "it-first": "^3.0.1", - "p-defer": "^4.0.0", - "p-timeout": "^6.1.1", - "xml2js": "^0.6.0" - } - }, - "node_modules/@achingbrain/nat-port-mapper/node_modules/p-timeout": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", - "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@achingbrain/ssdp": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@achingbrain/ssdp/-/ssdp-4.0.6.tgz", - "integrity": "sha512-Y4JE2L9150i50V6lg/Y8+ilhxRpUZKKv+PKo68Aj7MjPfaUAar6ZHilF9h4/Zb3q0fqGMXNc9o11cQLNI8J8bA==", - "dependencies": { - "event-iterator": "^2.0.0", - "freeport-promise": "^2.0.0", - "merge-options": "^3.0.4", - "xml2js": "^0.6.2" - } - }, "node_modules/@assemblyscript/loader": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.9.4.tgz", @@ -863,91 +824,11 @@ "node": ">=6.0.0" } }, - "node_modules/@chainsafe/as-chacha20poly1305": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@chainsafe/as-chacha20poly1305/-/as-chacha20poly1305-0.1.0.tgz", - "integrity": "sha512-BpNcL8/lji/GM3+vZ/bgRWqJ1q5kwvTFmGPk7pxm/QQZDbaMI98waOHjEymTjq2JmdD/INdNBFOVSyJofXg7ew==" - }, - "node_modules/@chainsafe/as-sha256": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.4.1.tgz", - "integrity": "sha512-IqeeGwQihK6Y2EYLFofqs2eY2ep1I2MvQXHzOAI+5iQN51OZlUkrLgyAugu2x86xZewDk5xas7lNczkzFzF62w==" - }, "node_modules/@chainsafe/is-ip": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@chainsafe/is-ip/-/is-ip-2.0.2.tgz", "integrity": "sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA==" }, - "node_modules/@chainsafe/libp2p-gossipsub": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-10.1.1.tgz", - "integrity": "sha512-nou65zlGaUIPwlUq7ceEVpszJX4tBWRRanppYaKsJk7rbDeIKRJQla2duATGOI3fwj1+pGSlDQuF2zG7P0VJQw==", - "dependencies": { - "@libp2p/crypto": "^2.0.0", - "@libp2p/interface": "^0.1.4", - "@libp2p/interface-internal": "^0.1.0", - "@libp2p/logger": "^3.0.0", - "@libp2p/peer-id": "^3.0.0", - "@libp2p/pubsub": "^8.0.0", - "@multiformats/multiaddr": "^12.1.3", - "abortable-iterator": "^5.0.1", - "denque": "^2.1.0", - "it-length-prefixed": "^9.0.1", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.0", - "multiformats": "^12.0.1", - "protobufjs": "^7.2.4", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.4" - }, - "engines": { - "npm": ">=8.7.0" - } - }, - "node_modules/@chainsafe/libp2p-noise": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-noise/-/libp2p-noise-13.0.5.tgz", - "integrity": "sha512-xXqwrkH4nXlv3cYENHtqOgmIT2M4irPDwi548UvpmxzeC9hqa0kmiqbtAFYMV3v+gJ9pqVBVWFRk2hjs83GNrw==", - "dependencies": { - "@chainsafe/as-chacha20poly1305": "^0.1.0", - "@chainsafe/as-sha256": "^0.4.1", - "@libp2p/crypto": "^2.0.0", - "@libp2p/interface": "^0.1.0", - "@libp2p/logger": "^3.0.0", - "@libp2p/peer-id": "^3.0.0", - "@noble/ciphers": "^0.4.0", - "@noble/curves": "^1.1.0", - "@noble/hashes": "^1.3.1", - "it-byte-stream": "^1.0.0", - "it-length-prefixed": "^9.0.1", - "it-length-prefixed-stream": "^1.0.0", - "it-pair": "^2.0.6", - "it-pipe": "^3.0.1", - "it-stream-types": "^2.0.1", - "protons-runtime": "^5.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.4", - "wherearewe": "^2.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@chainsafe/libp2p-yamux": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-yamux/-/libp2p-yamux-5.0.4.tgz", - "integrity": "sha512-3cfOjomFde7+6sscoM0gK7cgA5aEm20oYeVXSSonVzaas/UZzNsGP+FnF/bjLATjdyTB+YqhBHJs/KKk1PAy/Q==", - "dependencies": { - "@libp2p/interface": "^0.1.0", - "@libp2p/logger": "^3.0.0", - "get-iterator": "^2.0.1", - "it-foreach": "^2.0.3", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.0", - "uint8arraylist": "^2.4.3" - } - }, "node_modules/@chainsafe/netmask": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@chainsafe/netmask/-/netmask-2.0.0.tgz", @@ -974,27 +855,6 @@ "progress-events": "^1.0.0" } }, - "node_modules/@helia/delegated-routing-v1-http-api-client": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@helia/delegated-routing-v1-http-api-client/-/delegated-routing-v1-http-api-client-1.1.0.tgz", - "integrity": "sha512-bw2qeHabNNaK2pZFKZqCYXyz5kK3022rA+D6v2HtQclZX8WmkYD2OHwqnuVZ7ZRUN2lNTwt3Mq2ESEcKY/3Gjg==", - "dependencies": { - "@libp2p/interface": "^0.1.2", - "@libp2p/logger": "^3.0.2", - "@libp2p/peer-id": "^3.0.3", - "@multiformats/multiaddr": "^12.1.3", - "any-signal": "^4.1.1", - "browser-readablestream-to-it": "^2.0.3", - "ipns": "^7.0.1", - "it-first": "^3.0.3", - "it-map": "^3.0.4", - "it-ndjson": "^1.0.4", - "multiformats": "^12.1.1", - "p-defer": "^4.0.0", - "p-queue": "^7.3.4", - "uint8arrays": "^4.0.6" - } - }, "node_modules/@helia/interface": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@helia/interface/-/interface-2.1.0.tgz", @@ -1061,19 +921,6 @@ "npm": ">=7.0.0" } }, - "node_modules/@ipld/dag-json": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/@ipld/dag-json/-/dag-json-10.1.5.tgz", - "integrity": "sha512-AIIDRGPgIqVG2K1O42dPDzNOfP0YWV/suGApzpF+YWZLwkwdGVsxjmXcJ/+rwOhRGdjpuq/xQBKPCu1Ao6rdOQ==", - "dependencies": { - "cborg": "^4.0.0", - "multiformats": "^12.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, "node_modules/@ipld/dag-pb": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@ipld/dag-pb/-/dag-pb-4.0.6.tgz", @@ -1156,38 +1003,6 @@ "node": ">=v12.0.0" } }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" - }, - "node_modules/@libp2p/bootstrap": { - "version": "9.0.12", - "resolved": "https://registry.npmjs.org/@libp2p/bootstrap/-/bootstrap-9.0.12.tgz", - "integrity": "sha512-w/Mzq8tNBy4DQJXlIN4mwged/6ZHltsAr/J2Wpv0mijrKrr3PLEF1XWfQtdvNUb/exOlXOMCNwVRcXfeAha1qg==", - "dependencies": { - "@libp2p/interface": "^0.1.6", - "@libp2p/logger": "^3.1.0", - "@libp2p/peer-id": "^3.0.6", - "@multiformats/mafmt": "^12.1.2", - "@multiformats/multiaddr": "^12.1.5" - } - }, - "node_modules/@libp2p/crypto": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-2.0.8.tgz", - "integrity": "sha512-8e5fh6bsJNpSjhrggtlm8QF+BERjelJswIjRS69aKgxp24R4z2kDM4pRYPkfQjXJDLNDtqWtKNmePgX23+QJsA==", - "dependencies": { - "@libp2p/interface": "^0.1.6", - "@noble/curves": "^1.1.0", - "@noble/hashes": "^1.3.1", - "multiformats": "^12.0.1", - "node-forge": "^1.1.0", - "protons-runtime": "^5.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, "node_modules/@libp2p/interface": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-0.1.6.tgz", @@ -1203,29 +1018,6 @@ "uint8arraylist": "^2.4.3" } }, - "node_modules/@libp2p/interface-internal": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@libp2p/interface-internal/-/interface-internal-0.1.10.tgz", - "integrity": "sha512-eTbNtvLdSe762qcmSD54db9GJXqckKjqTyaDdUMK/3Zb/uwpjblqXCzecOxNvLi6W1Hfg9Lr7hvIm1zkGmzCPg==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "@libp2p/peer-collections": "^4.0.9", - "@multiformats/multiaddr": "^12.1.10", - "uint8arraylist": "^2.4.3" - } - }, - "node_modules/@libp2p/interface-internal/node_modules/@libp2p/interface": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", - "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", - "dependencies": { - "@multiformats/multiaddr": "^12.1.10", - "it-pushable": "^3.2.1", - "it-stream-types": "^2.0.1", - "multiformats": "^12.1.3", - "uint8arraylist": "^2.4.3" - } - }, "node_modules/@libp2p/interfaces": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/@libp2p/interfaces/-/interfaces-3.3.2.tgz", @@ -1235,63 +1027,6 @@ "npm": ">=7.0.0" } }, - "node_modules/@libp2p/kad-dht": { - "version": "10.0.15", - "resolved": "https://registry.npmjs.org/@libp2p/kad-dht/-/kad-dht-10.0.15.tgz", - "integrity": "sha512-S4pQY8t4lXBlicBREThtOHnLn79e07sVgKZPa9SmJ4hC1+i0HFD8XLzrHm3cnKSO/4RhoaF5YdlnZMMjbb7q0w==", - "dependencies": { - "@libp2p/crypto": "^2.0.8", - "@libp2p/interface": "^0.1.6", - "@libp2p/interface-internal": "^0.1.9", - "@libp2p/logger": "^3.1.0", - "@libp2p/peer-collections": "^4.0.8", - "@libp2p/peer-id": "^3.0.6", - "@multiformats/multiaddr": "^12.1.5", - "@types/sinon": "^17.0.0", - "abortable-iterator": "^5.0.1", - "any-signal": "^4.1.1", - "datastore-core": "^9.0.1", - "hashlru": "^2.3.0", - "interface-datastore": "^8.2.0", - "it-all": "^3.0.2", - "it-drain": "^3.0.2", - "it-first": "^3.0.1", - "it-length": "^3.0.1", - "it-length-prefixed": "^9.0.1", - "it-map": "^3.0.3", - "it-merge": "^3.0.0", - "it-parallel": "^3.0.0", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.1", - "it-stream-types": "^2.0.1", - "it-take": "^3.0.1", - "multiformats": "^12.0.1", - "p-defer": "^4.0.0", - "p-event": "^6.0.0", - "p-queue": "^7.3.4", - "private-ip": "^3.0.0", - "progress-events": "^1.0.0", - "protons-runtime": "^5.0.0", - "uint8-varint": "^2.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/keychain": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@libp2p/keychain/-/keychain-3.0.8.tgz", - "integrity": "sha512-+WmW9bN9WE0uKqTG3DVk+zsd9Np63lLS+uYRhncwCGTvg0HKXq1t+i4Xd8KbZvUv7UVakE8aae1oMezW3nS+2g==", - "dependencies": { - "@libp2p/crypto": "^2.0.8", - "@libp2p/interface": "^0.1.6", - "@libp2p/logger": "^3.1.0", - "@libp2p/peer-id": "^3.0.6", - "interface-datastore": "^8.2.0", - "merge-options": "^3.0.4", - "sanitize-filename": "^1.6.3", - "uint8arrays": "^4.0.6" - } - }, "node_modules/@libp2p/logger": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-3.1.0.tgz", @@ -1304,699 +1039,126 @@ "multiformats": "^12.0.1" } }, - "node_modules/@libp2p/mdns": { - "version": "9.0.14", - "resolved": "https://registry.npmjs.org/@libp2p/mdns/-/mdns-9.0.14.tgz", - "integrity": "sha512-kS+hEGnA4X3AUknn6N/RiUu72AomiYyD0mwHtyPdcTmYYI6VNKWkniS95wQKXMSaHk+pEN7NAugTXJf478jkRg==", + "node_modules/@multiformats/multiaddr": { + "version": "12.1.10", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.1.10.tgz", + "integrity": "sha512-Bi3nJ/SE17+te40OLxFOpr9CvRodusZZLYZb3e5a0w9RzQcHzfKnnlfqdysLXZ2W5vXgxCUL/Uhndl51Ff2S+Q==", "dependencies": { - "@libp2p/interface": "^0.1.6", - "@libp2p/logger": "^3.1.0", - "@libp2p/peer-id": "^3.0.6", - "@libp2p/utils": "^4.0.7", - "@multiformats/multiaddr": "^12.1.5", - "@types/multicast-dns": "^7.2.1", - "dns-packet": "^5.4.0", - "multicast-dns": "^7.2.5" + "@chainsafe/is-ip": "^2.0.1", + "@chainsafe/netmask": "^2.0.0", + "@libp2p/interface": "^0.1.1", + "dns-over-http-resolver": "3.0.0", + "multiformats": "^12.0.1", + "uint8-varint": "^2.0.1", + "uint8arrays": "^4.0.2" } }, - "node_modules/@libp2p/mplex": { - "version": "9.0.12", - "resolved": "https://registry.npmjs.org/@libp2p/mplex/-/mplex-9.0.12.tgz", - "integrity": "sha512-ll+fsz9zJ9OW3Z14hN4uh5JDQWIfudp2HTsSKoBiiFnKNY58tMH01iijNtHXGyGiVPmFCPeJf01oPlx0j9OgDQ==", + "node_modules/@multiformats/murmur3": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@multiformats/murmur3/-/murmur3-2.1.7.tgz", + "integrity": "sha512-Yf0UpAaONjed+8PTt5NM/GG4Z4Ai4m1qfT7bqevjnkwRQ12K+0jxtRomirz+VJx4PokpA2St1ZSD1iMkZTqPRQ==", "dependencies": { - "@libp2p/interface": "^0.1.6", - "@libp2p/logger": "^3.1.0", - "abortable-iterator": "^5.0.1", - "benchmark": "^2.1.4", - "it-batched-bytes": "^2.0.2", - "it-pushable": "^3.2.0", - "it-stream-types": "^2.0.1", - "rate-limiter-flexible": "^3.0.0", - "uint8-varint": "^2.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" + "multiformats": "^12.0.1", + "murmurhash3js-revisited": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, - "node_modules/@libp2p/multistream-select": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@libp2p/multistream-select/-/multistream-select-4.0.7.tgz", - "integrity": "sha512-O3gxXYfvtOtA1OsZAWHXBOB2KPSvxuYgOCm2Xr6+lR+atyhXwjZ0WGEaVAkL2yNZIs89aQ0MTADJO3sE3/V5LQ==", + "node_modules/@smithy/abort-controller": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", + "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", "dependencies": { - "@libp2p/interface": "^1.0.0", - "it-length-prefixed": "^9.0.3", - "it-length-prefixed-stream": "^1.1.1", - "it-pipe": "^3.0.1", - "it-stream-types": "^2.0.1", - "p-defer": "^4.0.0", - "uint8-varint": "^2.0.2", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@libp2p/multistream-select/node_modules/@libp2p/interface": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", - "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", + "node_modules/@smithy/chunked-blob-reader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz", + "integrity": "sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==", "dependencies": { - "@multiformats/multiaddr": "^12.1.10", - "it-pushable": "^3.2.1", - "it-stream-types": "^2.0.1", - "multiformats": "^12.1.3", - "uint8arraylist": "^2.4.3" + "tslib": "^2.5.0" } }, - "node_modules/@libp2p/peer-collections": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@libp2p/peer-collections/-/peer-collections-4.0.9.tgz", - "integrity": "sha512-jQgTV35byACBYDMIp+kopAPs7ZsgZn0oRfkNkkRX10zYCX7ehrZ1qiiSR0oaCJfgrktWhkv+sYj7nyaBwhgANg==", + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.1.tgz", + "integrity": "sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==", "dependencies": { - "@libp2p/interface": "^1.0.0", - "@libp2p/peer-id": "^4.0.0" + "@smithy/util-base64": "^2.0.1", + "tslib": "^2.5.0" } }, - "node_modules/@libp2p/peer-collections/node_modules/@libp2p/interface": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", - "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", + "node_modules/@smithy/config-resolver": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.18.tgz", + "integrity": "sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==", "dependencies": { - "@multiformats/multiaddr": "^12.1.10", - "it-pushable": "^3.2.1", - "it-stream-types": "^2.0.1", - "multiformats": "^12.1.3", - "uint8arraylist": "^2.4.3" + "@smithy/node-config-provider": "^2.1.5", + "@smithy/types": "^2.5.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.6", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@libp2p/peer-collections/node_modules/@libp2p/peer-id": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", - "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", + "node_modules/@smithy/credential-provider-imds": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.1.tgz", + "integrity": "sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==", "dependencies": { - "@libp2p/interface": "^1.0.0", - "multiformats": "^12.1.3", - "uint8arrays": "^4.0.6" + "@smithy/node-config-provider": "^2.1.5", + "@smithy/property-provider": "^2.0.14", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@libp2p/peer-id": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-3.0.6.tgz", - "integrity": "sha512-iN1Ia5gH2U1V/GOVRmLHmVY6fblxzrOPUoZrMYjHl/K4s+AiI7ym/527WDeQvhQpD7j3TfDwcAYforD2dLGpLw==", + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.13.tgz", + "integrity": "sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==", "dependencies": { - "@libp2p/interface": "^0.1.6", - "multiformats": "^12.0.1", - "uint8arrays": "^4.0.6" + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.5.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" } }, - "node_modules/@libp2p/peer-id-factory": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@libp2p/peer-id-factory/-/peer-id-factory-3.0.9.tgz", - "integrity": "sha512-e5wxUhynltG3Zlrh1dkHP9VSz3gmWl9v4c97ZekaOisJgUlyJDPfryggcNSvNLtdR6A8s7ZTUexlo7S1IkbVeA==", + "node_modules/@smithy/eventstream-serde-browser": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.13.tgz", + "integrity": "sha512-OJ/2g/VxkzA+mYZxV102oX3CsiE+igTSmqq/ir3oEVG2kSIdRC00ryttj/lmL14W06ExNi0ysmfLxQkL8XrAZQ==", "dependencies": { - "@libp2p/crypto": "^3.0.0", - "@libp2p/interface": "^1.0.0", - "@libp2p/peer-id": "^4.0.0", - "multiformats": "^12.1.3", - "protons-runtime": "^5.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/peer-id-factory/node_modules/@libp2p/crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-3.0.0.tgz", - "integrity": "sha512-NZDz/HaaOEDhgBqbdynoNkmnnq5KLq9/iQc9PU0/fFCKazo1hEYMhXZDN4szzXGBZQg58k9Q7FlduG5K5yTQbg==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "@noble/curves": "^1.1.0", - "@noble/hashes": "^1.3.1", - "multiformats": "^12.1.3", - "node-forge": "^1.1.0", - "protons-runtime": "^5.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" + "@smithy/eventstream-serde-universal": "^2.0.13", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@libp2p/peer-id-factory/node_modules/@libp2p/interface": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", - "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.13.tgz", + "integrity": "sha512-2BI1CbnYuEvAYoWSeWJtPNygbIKiWeSLxCmDLnyM6wQV32Of7VptiQlaFXPxXp4zqn/rs3ocZ/T29rxE4s4Gsg==", "dependencies": { - "@multiformats/multiaddr": "^12.1.10", - "it-pushable": "^3.2.1", - "it-stream-types": "^2.0.1", - "multiformats": "^12.1.3", - "uint8arraylist": "^2.4.3" - } - }, - "node_modules/@libp2p/peer-id-factory/node_modules/@libp2p/peer-id": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", - "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "multiformats": "^12.1.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/peer-record": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/@libp2p/peer-record/-/peer-record-6.0.10.tgz", - "integrity": "sha512-GiR+RE5PBVMgHTkQ2Ghf8KbLX7PNW/TDHdUyqsl3X1ij0KxQHufwrYfO3aMP0GN4pN5g25bO6WixAUU8MokNPw==", - "dependencies": { - "@libp2p/crypto": "^3.0.0", - "@libp2p/interface": "^1.0.0", - "@libp2p/peer-id": "^4.0.0", - "@libp2p/utils": "^5.0.0", - "@multiformats/multiaddr": "^12.1.10", - "protons-runtime": "^5.0.0", - "uint8-varint": "^2.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/peer-record/node_modules/@libp2p/crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-3.0.0.tgz", - "integrity": "sha512-NZDz/HaaOEDhgBqbdynoNkmnnq5KLq9/iQc9PU0/fFCKazo1hEYMhXZDN4szzXGBZQg58k9Q7FlduG5K5yTQbg==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "@noble/curves": "^1.1.0", - "@noble/hashes": "^1.3.1", - "multiformats": "^12.1.3", - "node-forge": "^1.1.0", - "protons-runtime": "^5.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/peer-record/node_modules/@libp2p/interface": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", - "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", - "dependencies": { - "@multiformats/multiaddr": "^12.1.10", - "it-pushable": "^3.2.1", - "it-stream-types": "^2.0.1", - "multiformats": "^12.1.3", - "uint8arraylist": "^2.4.3" - } - }, - "node_modules/@libp2p/peer-record/node_modules/@libp2p/peer-id": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", - "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "multiformats": "^12.1.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/peer-record/node_modules/@libp2p/utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-5.0.0.tgz", - "integrity": "sha512-abRRyih2e+NuwOr3JywUARCJdvfRGe4fa8Sp46LLlgFZ571KjfJUxlKooVKBbZcdHUBLFUaoGfxXmKCZWueC5A==", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@libp2p/interface": "^1.0.0", - "@multiformats/multiaddr": "^12.1.10", - "@multiformats/multiaddr-matcher": "^1.1.0", - "get-iterator": "^2.0.1", - "is-loopback-addr": "^2.0.1", - "it-pushable": "^3.2.2", - "it-stream-types": "^2.0.1", - "p-queue": "^7.4.1", - "private-ip": "^3.0.1", - "race-signal": "^1.0.1", - "uint8arraylist": "^2.4.3" - } - }, - "node_modules/@libp2p/peer-store": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@libp2p/peer-store/-/peer-store-9.0.10.tgz", - "integrity": "sha512-daYjOOQqd1KpChnKVVBtUivqBoHadAcKSC09u3YdQtROSkxJj297YPXlC8qIpSKvfDwGpeKESy2j5VyMc1uPGQ==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "@libp2p/peer-collections": "^4.0.9", - "@libp2p/peer-id": "^4.0.0", - "@libp2p/peer-id-factory": "^3.0.9", - "@libp2p/peer-record": "^6.0.10", - "@multiformats/multiaddr": "^12.1.10", - "interface-datastore": "^8.2.0", - "it-all": "^3.0.2", - "mortice": "^3.0.1", - "multiformats": "^12.1.3", - "protons-runtime": "^5.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/peer-store/node_modules/@libp2p/interface": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", - "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", - "dependencies": { - "@multiformats/multiaddr": "^12.1.10", - "it-pushable": "^3.2.1", - "it-stream-types": "^2.0.1", - "multiformats": "^12.1.3", - "uint8arraylist": "^2.4.3" - } - }, - "node_modules/@libp2p/peer-store/node_modules/@libp2p/peer-id": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", - "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "multiformats": "^12.1.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/pubsub": { - "version": "8.0.11", - "resolved": "https://registry.npmjs.org/@libp2p/pubsub/-/pubsub-8.0.11.tgz", - "integrity": "sha512-3HgeWl/1u1XluYdhOsLmB+6a8JUKWi3rlqIJxmET51Mz7yD8zBAqGv8pFXf/ZVEHcXzkzm0VVi25ksG80KL7+w==", - "dependencies": { - "@libp2p/crypto": "^3.0.0", - "@libp2p/interface": "^1.0.0", - "@libp2p/interface-internal": "^0.1.10", - "@libp2p/peer-collections": "^4.0.9", - "@libp2p/peer-id": "^4.0.0", - "@libp2p/utils": "^5.0.0", - "it-length-prefixed": "^9.0.3", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.1", - "multiformats": "^12.1.3", - "p-queue": "^7.4.1", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/pubsub/node_modules/@libp2p/crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-3.0.0.tgz", - "integrity": "sha512-NZDz/HaaOEDhgBqbdynoNkmnnq5KLq9/iQc9PU0/fFCKazo1hEYMhXZDN4szzXGBZQg58k9Q7FlduG5K5yTQbg==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "@noble/curves": "^1.1.0", - "@noble/hashes": "^1.3.1", - "multiformats": "^12.1.3", - "node-forge": "^1.1.0", - "protons-runtime": "^5.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/pubsub/node_modules/@libp2p/interface": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.0.tgz", - "integrity": "sha512-Djd3KB3CXsFPdTFqbkwmvinPcZV3ISp+ZqXwPHnBzr2zRdZrU8ptUldPYT4uzx7q7P2IgyBbSQvKlz0Qr/w1/w==", - "dependencies": { - "@multiformats/multiaddr": "^12.1.10", - "it-pushable": "^3.2.1", - "it-stream-types": "^2.0.1", - "multiformats": "^12.1.3", - "uint8arraylist": "^2.4.3" - } - }, - "node_modules/@libp2p/pubsub/node_modules/@libp2p/peer-id": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.0.0.tgz", - "integrity": "sha512-ltZqVmtQ27qgTB2ZQE3zsdLPnAxu8ehfGNI63njz87G+H7RWVnEeXFdISaQnxQchyewYda7klNc0Cr+aN0b1IA==", - "dependencies": { - "@libp2p/interface": "^1.0.0", - "multiformats": "^12.1.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/pubsub/node_modules/@libp2p/utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-5.0.0.tgz", - "integrity": "sha512-abRRyih2e+NuwOr3JywUARCJdvfRGe4fa8Sp46LLlgFZ571KjfJUxlKooVKBbZcdHUBLFUaoGfxXmKCZWueC5A==", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@libp2p/interface": "^1.0.0", - "@multiformats/multiaddr": "^12.1.10", - "@multiformats/multiaddr-matcher": "^1.1.0", - "get-iterator": "^2.0.1", - "is-loopback-addr": "^2.0.1", - "it-pushable": "^3.2.2", - "it-stream-types": "^2.0.1", - "p-queue": "^7.4.1", - "private-ip": "^3.0.1", - "race-signal": "^1.0.1", - "uint8arraylist": "^2.4.3" - } - }, - "node_modules/@libp2p/tcp": { - "version": "8.0.13", - "resolved": "https://registry.npmjs.org/@libp2p/tcp/-/tcp-8.0.13.tgz", - "integrity": "sha512-uN8p1gONoD7z8NteDE3a7F8yy9HblC3b9zX39L2/ztrqeAPiqRfGpBhXK+osXXj07jjnjhSNLBSVNHJNSmADRg==", - "dependencies": { - "@libp2p/interface": "^0.1.6", - "@libp2p/logger": "^3.1.0", - "@libp2p/utils": "^4.0.7", - "@multiformats/mafmt": "^12.1.2", - "@multiformats/multiaddr": "^12.1.5", - "@types/sinon": "^17.0.0", - "stream-to-it": "^0.2.2" - } - }, - "node_modules/@libp2p/utils": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-4.0.7.tgz", - "integrity": "sha512-xA6mS4II14870/DmmI3GFRWdNwHeOd2QV3ltatpdVmeEQpdn82jjtCzqn45AChjCugFOskOthXnQiWp+FvdKZg==", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@libp2p/interface": "^0.1.6", - "@libp2p/logger": "^3.1.0", - "@multiformats/multiaddr": "^12.1.5", - "@multiformats/multiaddr-matcher": "^1.0.1", - "is-loopback-addr": "^2.0.1", - "it-stream-types": "^2.0.1", - "private-ip": "^3.0.0", - "uint8arraylist": "^2.4.3" - } - }, - "node_modules/@libp2p/webrtc": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/@libp2p/webrtc/-/webrtc-3.2.11.tgz", - "integrity": "sha512-djp1pgtmIT3zeRaTGMbr6Jl3N7qwcaYlgaNqU3hH5ys/+2SVRIDMwBcsSOuv3414fCM7n0SCRjk3QBYxk0WKNg==", - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/interface": "^0.1.6", - "@libp2p/interface-internal": "^0.1.9", - "@libp2p/logger": "^3.1.0", - "@libp2p/peer-id": "^3.0.6", - "@multiformats/mafmt": "^12.1.2", - "@multiformats/multiaddr": "^12.1.5", - "@multiformats/multiaddr-matcher": "^1.0.1", - "abortable-iterator": "^5.0.1", - "any-signal": "^4.1.1", - "detect-browser": "^5.3.0", - "it-length-prefixed": "^9.0.1", - "it-pipe": "^3.0.1", - "it-protobuf-stream": "^1.0.0", - "it-pushable": "^3.2.0", - "it-stream-types": "^2.0.1", - "it-to-buffer": "^4.0.2", - "multiformats": "^12.0.1", - "multihashes": "^4.0.3", - "node-datachannel": "^0.5.0-dev", - "p-defer": "^4.0.0", - "p-event": "^6.0.0", - "p-timeout": "^6.1.2", - "protons-runtime": "^5.0.0", - "race-signal": "^1.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@libp2p/webrtc/node_modules/p-timeout": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", - "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@libp2p/websockets": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@libp2p/websockets/-/websockets-7.0.13.tgz", - "integrity": "sha512-frRvTtk7++bJ/JLEX8iulpHAMMkEfroWDn2RhiY24SMPwkHWs3CZwm0P6nQ6p0YHft3OQfwPZaqBu0KItxnVHQ==", - "dependencies": { - "@libp2p/interface": "^0.1.6", - "@libp2p/logger": "^3.1.0", - "@libp2p/utils": "^4.0.7", - "@multiformats/mafmt": "^12.1.2", - "@multiformats/multiaddr": "^12.1.5", - "@multiformats/multiaddr-to-uri": "^9.0.2", - "@types/ws": "^8.5.4", - "abortable-iterator": "^5.0.1", - "it-ws": "^6.0.0", - "p-defer": "^4.0.0", - "wherearewe": "^2.0.1", - "ws": "^8.12.1" - } - }, - "node_modules/@libp2p/webtransport": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@libp2p/webtransport/-/webtransport-3.1.10.tgz", - "integrity": "sha512-8bdnqs9Jz1D5Wy+VDMluW9HsD2A712PZMmYTbBXEG4BabDWHI6l2UdJDt4zkaP1rqn+o9YooipA0wZU34MuiSA==", - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/interface": "^0.1.6", - "@libp2p/logger": "^3.1.0", - "@libp2p/peer-id": "^3.0.6", - "@multiformats/multiaddr": "^12.1.5", - "@multiformats/multiaddr-matcher": "^1.0.1", - "it-stream-types": "^2.0.1", - "multiformats": "^12.0.1", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6" - } - }, - "node_modules/@multiformats/base-x": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz", - "integrity": "sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==" - }, - "node_modules/@multiformats/mafmt": { - "version": "12.1.6", - "resolved": "https://registry.npmjs.org/@multiformats/mafmt/-/mafmt-12.1.6.tgz", - "integrity": "sha512-tlJRfL21X+AKn9b5i5VnaTD6bNttpSpcqwKVmDmSHLwxoz97fAHaepqFOk/l1fIu94nImIXneNbhsJx/RQNIww==", - "dependencies": { - "@multiformats/multiaddr": "^12.0.0" - } - }, - "node_modules/@multiformats/multiaddr": { - "version": "12.1.10", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.1.10.tgz", - "integrity": "sha512-Bi3nJ/SE17+te40OLxFOpr9CvRodusZZLYZb3e5a0w9RzQcHzfKnnlfqdysLXZ2W5vXgxCUL/Uhndl51Ff2S+Q==", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@chainsafe/netmask": "^2.0.0", - "@libp2p/interface": "^0.1.1", - "dns-over-http-resolver": "3.0.0", - "multiformats": "^12.0.1", - "uint8-varint": "^2.0.1", - "uint8arrays": "^4.0.2" - } - }, - "node_modules/@multiformats/multiaddr-matcher": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-matcher/-/multiaddr-matcher-1.1.0.tgz", - "integrity": "sha512-B/QbKpAxaHYVXFnbTdTgYqPDxmqoF2RYffwYoOv1MWfi2vBCZLdzmEKUBKv6fQr6s+LJFSHn2j2vczmwMFCQIA==", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@multiformats/multiaddr": "^12.0.0", - "multiformats": "^12.0.1" - } - }, - "node_modules/@multiformats/multiaddr-to-uri": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-to-uri/-/multiaddr-to-uri-9.0.7.tgz", - "integrity": "sha512-i3ldtPMN6XJt+MCi34hOl0wGuGEHfWWMw6lmNag5BpckPwPTf9XGOOFMmh7ed/uO3Vjah/g173iOe61HTQVoBA==", - "dependencies": { - "@multiformats/multiaddr": "^12.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@multiformats/murmur3": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@multiformats/murmur3/-/murmur3-2.1.7.tgz", - "integrity": "sha512-Yf0UpAaONjed+8PTt5NM/GG4Z4Ai4m1qfT7bqevjnkwRQ12K+0jxtRomirz+VJx4PokpA2St1ZSD1iMkZTqPRQ==", - "dependencies": { - "multiformats": "^12.0.1", - "murmurhash3js-revisited": "^3.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@noble/ciphers": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.4.0.tgz", - "integrity": "sha512-xaUaUUDWbHIFSxaQ/pIe+33VG2mfJp6N/KxKLmZr5biWdNznCAmfu24QRhX10BbVAuqOahAoyp0S4M9md6GPDw==", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "node_modules/@smithy/abort-controller": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", - "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/chunked-blob-reader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz", - "integrity": "sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==", - "dependencies": { - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/chunked-blob-reader-native": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.1.tgz", - "integrity": "sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==", - "dependencies": { - "@smithy/util-base64": "^2.0.1", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.18.tgz", - "integrity": "sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.1.tgz", - "integrity": "sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/property-provider": "^2.0.14", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.13.tgz", - "integrity": "sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==", - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.13.tgz", - "integrity": "sha512-OJ/2g/VxkzA+mYZxV102oX3CsiE+igTSmqq/ir3oEVG2kSIdRC00ryttj/lmL14W06ExNi0ysmfLxQkL8XrAZQ==", - "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.13.tgz", - "integrity": "sha512-2BI1CbnYuEvAYoWSeWJtPNygbIKiWeSLxCmDLnyM6wQV32Of7VptiQlaFXPxXp4zqn/rs3ocZ/T29rxE4s4Gsg==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, "node_modules/@smithy/eventstream-serde-node": { @@ -2528,14 +1690,6 @@ "node": ">=14.0.0" } }, - "node_modules/@types/dns-packet": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.6.3.tgz", - "integrity": "sha512-T7YsGU31kUqAeN5SzfJxapsTAVCXucSb4QsnB7wcbFBpdm7Y77r/5SBrUpdT3Ng22pgxJtLljtQtBvkP5BiSqg==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/linkify-it": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", @@ -2558,49 +1712,6 @@ "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", "dev": true }, - "node_modules/@types/multicast-dns": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/@types/multicast-dns/-/multicast-dns-7.2.4.tgz", - "integrity": "sha512-ib5K4cIDR4Ro5SR3Sx/LROkMDa0BHz0OPaCBL/OSPDsAXEGZ3/KQeS6poBKYVN7BfjXDL9lWNwzyHVgt/wkyCw==", - "dependencies": { - "@types/dns-packet": "*", - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "20.10.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", - "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==" - }, - "node_modules/@types/sinon": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.2.tgz", - "integrity": "sha512-Zt6heIGsdqERkxctIpvN5Pv3edgBrhoeb3yHyxffd4InN0AX2SVNKSrhdDZKGQICVOxWP/q4DyhpfPNMSrpIiA==", - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==" - }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@vascosantos/moving-average": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@vascosantos/moving-average/-/moving-average-1.1.0.tgz", @@ -2685,15 +1796,6 @@ } ] }, - "node_modules/benchmark": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", - "integrity": "sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==", - "dependencies": { - "lodash": "^4.17.4", - "platform": "^1.3.3" - } - }, "node_modules/bl": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", @@ -2755,11 +1857,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/browser-readablestream-to-it": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/browser-readablestream-to-it/-/browser-readablestream-to-it-2.0.5.tgz", - "integrity": "sha512-obLCT9jnxAeZlbaRWluUiZrcSJEoi2JkM0eoiJqlIP7MFwZwZjcB6giZvD343PXfr96ilD91M/wFqFvyAZq+Gg==" - }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -2819,11 +1916,6 @@ "cborg": "lib/bin.js" } }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -2873,39 +1965,6 @@ "node": ">=14" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/datastore-core": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/datastore-core/-/datastore-core-9.2.4.tgz", - "integrity": "sha512-j/i/+PGHzAMEZRmW+7RCiHYkPnAGCj+JT7lPg9c9fYOkGTqedce64pd84AfuIeZRewZw2YxQSVFvlUD4O2we8Q==", - "dependencies": { - "@libp2p/logger": "^3.0.0", - "err-code": "^3.0.1", - "interface-store": "^5.0.0", - "it-all": "^3.0.1", - "it-drain": "^3.0.1", - "it-filter": "^3.0.0", - "it-map": "^3.0.1", - "it-merge": "^3.0.1", - "it-pipe": "^3.0.0", - "it-pushable": "^3.0.0", - "it-sort": "^3.0.1", - "it-take": "^3.0.1", - "uint8arrays": "^4.0.2" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2922,50 +1981,6 @@ } } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/default-gateway": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-7.2.2.tgz", - "integrity": "sha512-AD7TrdNNPXRZIGw63dw+lnGmT4v7ggZC5NHNJgAYWm5njrwoze1q5JSAW9YuLy2tjnoLUG/r8FEB93MCh9QJPg==", - "dependencies": { - "execa": "^7.1.1" - }, - "engines": { - "node": ">= 16" - } - }, - "node_modules/delay": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-6.0.0.tgz", - "integrity": "sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2974,27 +1989,6 @@ "node": ">=0.4.0" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-browser": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", - "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==" - }, - "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "engines": { - "node": ">=8" - } - }, "node_modules/dns-over-http-resolver": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-3.0.0.tgz", @@ -3004,17 +1998,6 @@ "receptacle": "^1.3.2" } }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", @@ -3025,25 +2008,6 @@ "tslib": "^2.0.3" } }, - "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", @@ -3067,11 +2031,6 @@ "node": ">=8" } }, - "node_modules/event-iterator": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", - "integrity": "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==" - }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -3085,36 +2044,6 @@ "node": ">=0.8.x" } }, - "node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "engines": { - "node": ">=6" - } - }, "node_modules/fast-write-atomic": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fast-write-atomic/-/fast-write-atomic-0.2.1.tgz", @@ -3173,20 +2102,6 @@ "node": ">= 6" } }, - "node_modules/freeport-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/freeport-promise/-/freeport-promise-2.0.0.tgz", - "integrity": "sha512-dwWpT1DdQcwrhmRwnDnPM/ZFny+FtzU+k50qF2eid3KxaQDsMiBrwo1i0G3qSugkN5db6Cb0zgfc68QeTOpEFg==", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -3206,22 +2121,6 @@ "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.1.tgz", "integrity": "sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg==" }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -3241,56 +2140,6 @@ "npm": ">=7.0.0" } }, - "node_modules/hashlru": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/hashlru/-/hashlru-2.3.0.tgz", - "integrity": "sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==" - }, - "node_modules/helia": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/helia/-/helia-2.1.0.tgz", - "integrity": "sha512-OJOm99WYZC7o3hGRhv2rbWK6nDw2cRWx2+g6uMDF5YL04yZ2vZcE/8xccM3ekhrZFSJhbUGPID4AKGULIaxHbg==", - "dependencies": { - "@chainsafe/libp2p-gossipsub": "^10.0.0", - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@helia/delegated-routing-v1-http-api-client": "^1.1.0", - "@helia/interface": "^2.1.0", - "@ipld/dag-cbor": "^9.0.0", - "@ipld/dag-json": "^10.0.1", - "@ipld/dag-pb": "^4.0.3", - "@libp2p/bootstrap": "^9.0.2", - "@libp2p/interface": "^0.1.1", - "@libp2p/kad-dht": "^10.0.2", - "@libp2p/logger": "^3.0.1", - "@libp2p/mdns": "^9.0.2", - "@libp2p/mplex": "^9.0.2", - "@libp2p/tcp": "^8.0.2", - "@libp2p/webrtc": "^3.1.3", - "@libp2p/websockets": "^7.0.2", - "@libp2p/webtransport": "^3.0.3", - "any-signal": "^4.1.1", - "blockstore-core": "^4.0.0", - "cborg": "^4.0.1", - "datastore-core": "^9.0.0", - "interface-blockstore": "^5.0.0", - "interface-datastore": "^8.0.0", - "interface-store": "^5.0.1", - "ipfs-bitswap": "^19.0.0", - "ipns": "^7.0.1", - "it-all": "^3.0.2", - "it-drain": "^3.0.1", - "it-filter": "^3.0.1", - "it-foreach": "^2.0.2", - "libp2p": "^0.46.6", - "mortice": "^3.0.1", - "multiformats": "^12.0.1", - "p-defer": "^4.0.0", - "p-queue": "^7.3.4", - "progress-events": "^1.0.0", - "uint8arrays": "^4.0.3" - } - }, "node_modules/html-minifier-terser": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", @@ -3324,14 +2173,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "engines": { - "node": ">=14.18.0" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -3356,11 +2197,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, "node_modules/interface-blockstore": { "version": "5.2.6", "resolved": "https://registry.npmjs.org/interface-blockstore/-/interface-blockstore-5.2.6.tgz", @@ -3385,25 +2221,6 @@ "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-5.1.4.tgz", "integrity": "sha512-SI2co5IAxAybBc9egRM2bXvHOa1RPh5SQQkO6di6t/aX92RbtzP4t8raB0l3GTzQmJADaBbzz8Tfa1QLgfMdGQ==" }, - "node_modules/ip-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-5.0.0.tgz", - "integrity": "sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", - "engines": { - "node": ">= 10" - } - }, "node_modules/ipfs-bitswap": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/ipfs-bitswap/-/ipfs-bitswap-19.0.2.tgz", @@ -3491,56 +2308,16 @@ "it-all": "^3.0.2", "it-batch": "^3.0.2", "it-first": "^3.0.2", - "it-parallel-batch": "^3.0.1", - "multiformats": "^12.0.1", - "progress-events": "^1.0.0", - "rabin-wasm": "^0.1.4", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.2" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipns": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ipns/-/ipns-7.0.1.tgz", - "integrity": "sha512-S74hlKNeAW9eExGmRwEfOLAk5l/lEL3HajcenbIc7PTeyeL6PkKE31qQmTi7qynn1ll32hMAo1OagbtnceCtXQ==", - "dependencies": { - "@libp2p/crypto": "^2.0.3", - "@libp2p/interface": "^0.1.2", - "@libp2p/logger": "^3.0.2", - "@libp2p/peer-id": "^3.0.2", - "cborg": "^4.0.1", - "err-code": "^3.0.1", - "interface-datastore": "^8.1.0", - "multiformats": "^12.0.1", - "protons-runtime": "^5.0.0", - "timestamp-nano": "^1.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.2" - } - }, - "node_modules/is-electron": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", - "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" - }, - "node_modules/is-loopback-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-loopback-addr/-/is-loopback-addr-2.0.2.tgz", - "integrity": "sha512-26POf2KRCno/KTNL5Q0b/9TYnL00xEsSaLfiFRmjM7m7Lw7ZMmFybzzuX4CcsLAluZGd+niLUiMRxEooVE3aqg==" - }, - "node_modules/is-network-error": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.0.0.tgz", - "integrity": "sha512-P3fxi10Aji2FZmHTrMPSNFbNC6nnp4U5juPAIjXPHkUNubi4+qK7vvdsaNpAUwXslhYm9oyjEYTxs1xd/+Ph0w==", - "engines": { - "node": ">=16" + "it-parallel-batch": "^3.0.1", + "multiformats": "^12.0.1", + "progress-events": "^1.0.0", + "rabin-wasm": "^0.1.4", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^4.0.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, "node_modules/is-plain-obj": { @@ -3551,30 +2328,6 @@ "node": ">=8" } }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/iso-url": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-1.2.1.tgz", - "integrity": "sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==", - "engines": { - "node": ">=12" - } - }, "node_modules/it-all": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/it-all/-/it-all-3.0.4.tgz", @@ -3585,26 +2338,6 @@ "resolved": "https://registry.npmjs.org/it-batch/-/it-batch-3.0.4.tgz", "integrity": "sha512-WRu2mqOYIs+T9k7+yxSK9VJdk0UE4R0jKQsWQcti5c6vhb1FhjC2+yCB5XBrctQ9edNfCMU/wVzdDj8qSwimbA==" }, - "node_modules/it-batched-bytes": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/it-batched-bytes/-/it-batched-bytes-2.0.5.tgz", - "integrity": "sha512-2VgeZ+7KPef0SD2ZgkZfWFe+sgZKdxkzNZXbsYG44nGe4NzWSZLJ6lUjkKHW/S5pSKyW88uacosz6B6K++1LDA==", - "dependencies": { - "p-defer": "^4.0.0", - "uint8arraylist": "^2.4.1" - } - }, - "node_modules/it-byte-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/it-byte-stream/-/it-byte-stream-1.0.5.tgz", - "integrity": "sha512-wGHbXPE0ZiU0poJTgCNOW06+mh9yyCwdF8bVv0zxchgql6CMQd/2NEXXtmwWE+N65st8bi/KWUWcMU2pJU2fEw==", - "dependencies": { - "it-stream-types": "^2.0.1", - "p-defer": "^4.0.0", - "race-signal": "^1.0.1", - "uint8arraylist": "^2.4.1" - } - }, "node_modules/it-drain": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/it-drain/-/it-drain-3.0.5.tgz", @@ -3639,32 +2372,11 @@ "minimatch": "^9.0.0" } }, - "node_modules/it-handshake": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/it-handshake/-/it-handshake-4.1.3.tgz", - "integrity": "sha512-V6Lt9A9usox9iduOX+edU1Vo94E6v9Lt9dOvg3ubFaw1qf5NCxXLi93Ao4fyCHWDYd8Y+DUhadwNtWVyn7qqLg==", - "dependencies": { - "it-pushable": "^3.1.0", - "it-reader": "^6.0.1", - "it-stream-types": "^2.0.1", - "p-defer": "^4.0.0", - "uint8arraylist": "^2.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, "node_modules/it-last": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/it-last/-/it-last-3.0.4.tgz", "integrity": "sha512-Ns+KTsQWhs0KCvfv5X3Ck3lpoYxHcp4zUp4d+AOdmC8cXXqDuoZqAjfWhgCbxJubXyIYWdfE2nRcfWqgvZHP8Q==" }, - "node_modules/it-length": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/it-length/-/it-length-3.0.4.tgz", - "integrity": "sha512-RS3thYkvqtWksrV7SaAnTv+pgY7ozpS17HlRvWvcnoRjVyNJMuffdCkIKpKNPTq5uZw9zVnkVKLO077pJn5Yhg==" - }, "node_modules/it-length-prefixed": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-9.0.3.tgz", @@ -3682,18 +2394,6 @@ "npm": ">=7.0.0" } }, - "node_modules/it-length-prefixed-stream": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/it-length-prefixed-stream/-/it-length-prefixed-stream-1.1.4.tgz", - "integrity": "sha512-6YcQ5jsaYnuXBqF+oSGjSdSY9jF7HWl7yh+dxYytXxbE2GcdiOpn6pLM7m6AlIID9MCzQqMY5nOzaiatQ8A3/A==", - "dependencies": { - "it-byte-stream": "^1.0.0", - "it-length-prefixed": "^9.0.1", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.1", - "uint8arraylist": "^2.4.1" - } - }, "node_modules/it-map": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/it-map/-/it-map-3.0.5.tgz", @@ -3710,24 +2410,6 @@ "it-pushable": "^3.2.0" } }, - "node_modules/it-ndjson": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/it-ndjson/-/it-ndjson-1.0.5.tgz", - "integrity": "sha512-2UEROCo458dDu9dABKb9fvD34p2YL6SqV5EOXN8SysX2Fpx0MSN69EiBmLLDDYSpQlrW0I5j3Tm8DtEIL5NsIw==" - }, - "node_modules/it-pair": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/it-pair/-/it-pair-2.0.6.tgz", - "integrity": "sha512-5M0t5RAcYEQYNG5BV7d7cqbdwbCAp5yLdzvkxsZmkuZsLbTdZzah6MQySYfaAQjNDCq6PUnDt0hqBZ4NwMfW6g==", - "dependencies": { - "it-stream-types": "^2.0.1", - "p-defer": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, "node_modules/it-parallel": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/it-parallel/-/it-parallel-3.0.6.tgz", @@ -3763,17 +2445,6 @@ "npm": ">=7.0.0" } }, - "node_modules/it-protobuf-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/it-protobuf-stream/-/it-protobuf-stream-1.1.1.tgz", - "integrity": "sha512-H7fiC+m85AAz84I8SQOKHKZTDREFrsYfKxEhWTlhAdySoUyiC72Xe2ocqBFy3zUWCGYq6rCTMGnCbTKntSlcog==", - "dependencies": { - "it-length-prefixed-stream": "^1.0.0", - "it-stream-types": "^2.0.1", - "protons-runtime": "^5.0.0", - "uint8arraylist": "^2.4.1" - } - }, "node_modules/it-pushable": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.2.3.tgz", @@ -3795,14 +2466,6 @@ "npm": ">=7.0.0" } }, - "node_modules/it-sort": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/it-sort/-/it-sort-3.0.4.tgz", - "integrity": "sha512-tvnC93JZZWjX4UxALy0asow0dzXabkoaRbrPJKClTKhNCqw4gzHr+H5axf1gohcthedRRkqd/ae+wl7WqoxFhw==", - "dependencies": { - "it-all": "^3.0.0" - } - }, "node_modules/it-stream-types": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/it-stream-types/-/it-stream-types-2.0.1.tgz", @@ -3817,31 +2480,6 @@ "resolved": "https://registry.npmjs.org/it-take/-/it-take-3.0.4.tgz", "integrity": "sha512-RG8HDjAZlvkzz5Nav4xq6gK5zNT+Ff1UTIf+CrSJW8nIl6N1FpBH5e7clUshiCn+MmmMoSdIEpw4UaTolszxhA==" }, - "node_modules/it-to-buffer": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/it-to-buffer/-/it-to-buffer-4.0.4.tgz", - "integrity": "sha512-QwsBKNdf9nDtG+KOs+reBCob9dpZgqgdFdoN/+/E3BEYUAleH4tXFRoMKsGJz7j4U3Ge1ns6U38uVgiQETvurQ==", - "dependencies": { - "uint8arrays": "^4.0.2" - } - }, - "node_modules/it-ws": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/it-ws/-/it-ws-6.0.5.tgz", - "integrity": "sha512-xp7tF4fHgx8+vN3Qy/8wGiWUKbC9E1U1g9PwtlbdxD7pY4zld71ZyWZVFHLxnxxg14T9mVNK5uO7U9HK11VQ5g==", - "dependencies": { - "@types/ws": "^8.2.2", - "event-iterator": "^2.0.0", - "iso-url": "^1.1.2", - "it-stream-types": "^2.0.1", - "uint8arrays": "^4.0.2", - "ws": "^8.4.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, "node_modules/js2xmlparser": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", @@ -3951,58 +2589,6 @@ "graceful-fs": "^4.1.11" } }, - "node_modules/libp2p": { - "version": "0.46.21", - "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-0.46.21.tgz", - "integrity": "sha512-p/3vCpw+ciizhlBofpzuez+4Fs8EeVFaVQZUQPwnQwycuOFcWLBhcqkOtv4KlqImFKOk+9TuyW1Xofjmr/wPnA==", - "dependencies": { - "@achingbrain/nat-port-mapper": "^1.0.9", - "@libp2p/crypto": "^2.0.8", - "@libp2p/interface": "^0.1.6", - "@libp2p/interface-internal": "^0.1.9", - "@libp2p/keychain": "^3.0.8", - "@libp2p/logger": "^3.1.0", - "@libp2p/multistream-select": "^4.0.6", - "@libp2p/peer-collections": "^4.0.8", - "@libp2p/peer-id": "^3.0.6", - "@libp2p/peer-id-factory": "^3.0.8", - "@libp2p/peer-record": "^6.0.9", - "@libp2p/peer-store": "^9.0.9", - "@libp2p/utils": "^4.0.7", - "@multiformats/mafmt": "^12.1.2", - "@multiformats/multiaddr": "^12.1.5", - "@multiformats/multiaddr-matcher": "^1.0.0", - "any-signal": "^4.1.1", - "datastore-core": "^9.0.1", - "delay": "^6.0.0", - "interface-datastore": "^8.2.0", - "it-all": "^3.0.2", - "it-drain": "^3.0.2", - "it-filter": "^3.0.1", - "it-first": "^3.0.1", - "it-handshake": "^4.1.3", - "it-length-prefixed": "^9.0.1", - "it-map": "^3.0.3", - "it-merge": "^3.0.0", - "it-pair": "^2.0.6", - "it-parallel": "^3.0.0", - "it-pipe": "^3.0.1", - "it-protobuf-stream": "^1.0.0", - "it-stream-types": "^2.0.1", - "merge-options": "^3.0.4", - "multiformats": "^12.0.1", - "p-defer": "^4.0.0", - "p-queue": "^7.3.4", - "p-retry": "^6.0.0", - "private-ip": "^3.0.0", - "protons-runtime": "^5.0.0", - "rate-limiter-flexible": "^3.0.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^4.0.6", - "wherearewe": "^2.0.1", - "xsalsa20": "^1.1.0" - } - }, "node_modules/linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", @@ -4015,12 +2601,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/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "node_modules/lower-case": { "version": "2.0.2", @@ -4031,17 +2613,6 @@ "tslib": "^2.0.3" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", @@ -4085,11 +2656,6 @@ "node": ">=10" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -4109,28 +2675,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -4153,67 +2697,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "node_modules/mortice": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mortice/-/mortice-3.0.1.tgz", - "integrity": "sha512-eyDUsl1nCR9+JtNksKnaESLP9MgAXCA4w1LTtsmOSQNsThnv++f36rrBu5fC/fdGIwTJZmbiaR/QewptH93pYA==", - "dependencies": { - "nanoid": "^4.0.0", - "observable-webworkers": "^2.0.1", - "p-queue": "^7.2.0", - "p-timeout": "^6.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/mortice/node_modules/p-timeout": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", - "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "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==" }, - "node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "deprecated": "This module has been superseded by the multiformats module", - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, "node_modules/multiformats": { "version": "12.1.3", "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.1.3.tgz", @@ -4223,38 +2711,6 @@ "npm": ">=7.0.0" } }, - "node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multihashes/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" - }, - "node_modules/multihashes/node_modules/uint8arrays": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", - "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==" - }, "node_modules/murmurhash3js-revisited": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", @@ -4280,152 +2736,33 @@ "node": "^14 || ^16 || >=18" } }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-abi": { - "version": "3.51.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.51.0.tgz", - "integrity": "sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA==", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-datachannel": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/node-datachannel/-/node-datachannel-0.5.1.tgz", - "integrity": "sha512-3hwCrBWJqYoozwVtJNzNtISLKwa3l/XTbrPFCyhC3KCgW1IvYMHhHm5FW37p0p2oth3J6MDwCw3T/0m7DTR7lw==", - "hasInstallScript": true, - "dependencies": { - "node-domexception": "^2.0.1", - "prebuild-install": "^7.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/node-domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-2.0.1.tgz", - "integrity": "sha512-M85rnSC7WQ7wnfQTARPT4LrK7nwCHLdDFOCcItZMhTQjyCebJH8GciKqYJNgaOFZs9nFmTmd/VMyi3OW5jA47w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=16" - } - }, - "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-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/observable-webworkers": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/observable-webworkers/-/observable-webworkers-2.0.1.tgz", - "integrity": "sha512-JI1vB0u3pZjoQKOK1ROWzp0ygxSi7Yb0iR+7UNsw4/Zn4cQ0P3R7XL38zac/Dy2tEA7Lg88/wIJTjF8vYXZ0uw==", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, "dependencies": { - "wrappy": "1" + "lower-case": "^2.0.2", + "tslib": "^2.0.3" } }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "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": { - "mimic-fn": "^4.0.0" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">=12" + "node": "4.x || >=6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/p-defer": { @@ -4439,31 +2776,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-event": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-6.0.0.tgz", - "integrity": "sha512-Xbfxd0CfZmHLGKXH32k1JKjQYX6Rkv0UtQdaFJ8OyNcf+c0oWCeXHc1C4CX/IESZLmcvfPa5aFIO/vCr5gqtag==", - "dependencies": { - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-event/node_modules/p-timeout": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", - "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-queue": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.4.1.tgz", @@ -4479,22 +2791,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-retry": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.1.0.tgz", - "integrity": "sha512-fJLEQ2KqYBJRuaA/8cKMnqhulqNM+bpcjYtXNex2t3mOXKRYPitAJt9NacSf8XAFzcYahSAbKpobiWDSqHSh2g==", - "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-timeout": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", @@ -4526,44 +2822,6 @@ "tslib": "^2.0.3" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" - }, - "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/prettier": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", @@ -4579,20 +2837,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/private-ip": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/private-ip/-/private-ip-3.0.1.tgz", - "integrity": "sha512-Ezc16ANuhSHmWAE6lbXUKburNzGpR0J5X0Zh5Um/PZ/s57Fp+HYqYe6BYPH2QbqKr/5WebfzJQ1jq6Kj5dbRmA==", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "ip-regex": "^5.0.0", - "ipaddr.js": "^2.1.0", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">=14.16" - } - }, "node_modules/progress-events": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/progress-events/-/progress-events-1.0.0.tgz", @@ -4602,29 +2846,6 @@ "npm": ">=7.0.0" } }, - "node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/protons-runtime": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/protons-runtime/-/protons-runtime-5.2.0.tgz", @@ -4639,15 +2860,6 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/rabin-wasm": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/rabin-wasm/-/rabin-wasm-0.1.5.tgz", @@ -4669,25 +2881,6 @@ "resolved": "https://registry.npmjs.org/race-signal/-/race-signal-1.0.2.tgz", "integrity": "sha512-o3xNv0iTcIDQCXFlF6fPAMEBRjFxssgGoRqLbg06m+AdzEXXLUmoNOoUHTVz2NoBI8hHwKFKoC6IqyNtWr2bww==" }, - "node_modules/rate-limiter-flexible": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-3.0.4.tgz", - "integrity": "sha512-LFrdT9Pl/TRxG143frHBPyESXHvS2tstLfAUM6shBbJ3M6YssT2cIUWFwAWVAU9Vl4Z2gUN7ZE7tSdQh/0aqcA==" - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -4732,14 +2925,6 @@ "resolved": "https://registry.npmjs.org/retimer/-/retimer-3.0.0.tgz", "integrity": "sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==" }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "engines": { - "node": ">= 4" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4759,52 +2944,6 @@ } ] }, - "node_modules/sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "dependencies": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, "node_modules/showdown": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", @@ -4830,54 +2969,6 @@ "node": "^12.20.0 || >=14" } }, - "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/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "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/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "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": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4911,19 +3002,6 @@ "readable-stream": "^3.5.0" } }, - "node_modules/stream-to-it": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/stream-to-it/-/stream-to-it-0.2.4.tgz", - "integrity": "sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==", - "dependencies": { - "get-iterator": "^1.0.2" - } - }, - "node_modules/stream-to-it/node_modules/get-iterator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-1.0.2.tgz", - "integrity": "sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==" - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4932,89 +3010,11 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/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/tar-stream/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/terser": { "version": "5.24.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", @@ -5039,11 +3039,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" - }, "node_modules/timeout-abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz", @@ -5052,43 +3047,16 @@ "retimer": "^3.0.0" } }, - "node_modules/timestamp-nano": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/timestamp-nano/-/timestamp-nano-1.0.1.tgz", - "integrity": "sha512-4oGOVZWTu5sl89PtCDnhQBSt7/vL1zVEwAfxH1p49JhTosxzVQWYBYFRFZ8nJmo0G6f824iyP/44BFAwIoKvIA==", - "engines": { - "node": ">= 4.5.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/truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", - "dependencies": { - "utf8-byte-length": "^1.0.1" - } - }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -5130,11 +3098,6 @@ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "dev": true }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -5144,11 +3107,6 @@ "node": ">= 10.0.0" } }, - "node_modules/utf8-byte-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==" - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5202,92 +3160,11 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/wherearewe": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wherearewe/-/wherearewe-2.0.1.tgz", - "integrity": "sha512-XUguZbDxCA2wBn2LoFtcEhXL6AXo+hVjGonwhSTTTU9SzbWG8Xu3onNIpzf9j/mYUcJQ0f+m37SzG77G851uFw==", - "dependencies": { - "is-electron": "^2.2.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, "node_modules/xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "dev": true - }, - "node_modules/xsalsa20": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/xsalsa20/-/xsalsa20-1.2.0.tgz", - "integrity": "sha512-FIr/DEeoHfj7ftfylnoFt3rAIRoWXpx2AoDfrT2qD2wtp7Dp+COajvs/Icb7uHqRW9m60f5iXZwdsJJO3kvb7w==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index e71179b..88e4707 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,6 @@ "@ipld/car": "5.2.4", "axios": "1.6.2", "blockstore-fs": "1.1.6", - "dotenv": "16.3.1", - "helia": "2.1.0", "uuid": "9.0.1" } } From 2fb8c0d609f4d77fd1e8c446c010589776bfaf62 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:17:11 -0600 Subject: [PATCH 53/79] Review Updates Update gatewayManager examples Added engine version to package.json Set max upload size to 250Gb in the SDK --- .npmrc | 1 + package-lock.json | 707 ++++++++++++++++++++++-------------------- package.json | 4 + src/gatewayManager.js | 13 +- src/nameManager.js | 3 + src/objectManager.js | 70 +++-- 6 files changed, 431 insertions(+), 367 deletions(-) create mode 100644 .npmrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..4fd0219 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 519f630..61ccbe9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,10 @@ "clean-jsdoc-theme": "4.2.17", "jsdoc": "4.0.2", "prettier": "3.1.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" } }, "node_modules/@assemblyscript/loader": { @@ -449,15 +453,6 @@ "@aws-sdk/client-s3": "^3.0.0" } }, - "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { "version": "3.451.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.451.0.tgz", @@ -750,9 +745,9 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", - "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "version": "3.465.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.465.0.tgz", + "integrity": "sha512-f+QNcWGswredzC1ExNAB/QzODlxwaTdXkNT5cvke2RLX8SFU5pYk6h4uCtWC0vWPELzOfMfloBrJefBzlarhsw==", "dependencies": { "tslib": "^2.5.0" }, @@ -813,9 +808,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", - "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -992,9 +987,9 @@ } }, "node_modules/@jsdoc/salty": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.6.tgz", - "integrity": "sha512-aA+awb5yoml8TQ3CzI5Ue7sM3VMRC4l1zJJW4fgZ8OCL1wshJZhNzaf0PL85DSnOUw6QuFgeHGD/eq/xwwAF2g==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.7.tgz", + "integrity": "sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg==", "dev": true, "dependencies": { "lodash": "^4.17.21" @@ -1040,19 +1035,31 @@ } }, "node_modules/@multiformats/multiaddr": { - "version": "12.1.10", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.1.10.tgz", - "integrity": "sha512-Bi3nJ/SE17+te40OLxFOpr9CvRodusZZLYZb3e5a0w9RzQcHzfKnnlfqdysLXZ2W5vXgxCUL/Uhndl51Ff2S+Q==", + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.1.11.tgz", + "integrity": "sha512-CWG9kETEGTTMdr1T+/JEuMwFld3r3fHNP8LkLoUcLvHRy6yr8sWdotVGEDNEdDO/vrKhuD7bQBws3xMSMMyylg==", "dependencies": { "@chainsafe/is-ip": "^2.0.1", "@chainsafe/netmask": "^2.0.0", - "@libp2p/interface": "^0.1.1", + "@libp2p/interface": "^1.0.0", "dns-over-http-resolver": "3.0.0", "multiformats": "^12.0.1", "uint8-varint": "^2.0.1", "uint8arrays": "^4.0.2" } }, + "node_modules/@multiformats/multiaddr/node_modules/@libp2p/interface": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.2.tgz", + "integrity": "sha512-z/3Yyg+7cVyzRXwzdrDkJd7YmNaLE9iZjQaixo5luI/n9uk5OFFjb9ulAsNqpq8V1xylCo2DXIC7f94KClwzVw==", + "dependencies": { + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" + } + }, "node_modules/@multiformats/murmur3": { "version": "2.1.7", "resolved": "https://registry.npmjs.org/@multiformats/murmur3/-/murmur3-2.1.7.tgz", @@ -1067,11 +1074,11 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", - "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.15.tgz", + "integrity": "sha512-JkS36PIS3/UCbq/MaozzV7jECeL+BTt4R75bwY8i+4RASys4xOyUS1HsRyUNSqUXFP4QyCz5aNnh3ltuaxv+pw==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1096,14 +1103,14 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.18.tgz", - "integrity": "sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.21.tgz", + "integrity": "sha512-rlLIGT+BeqjnA6C2FWumPRJS1UW07iU5ZxDHtFuyam4W65gIaOFMjkB90ofKCIh+0mLVQrQFrl/VLtQT/6FWTA==", "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/types": "^2.7.0", "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", + "@smithy/util-middleware": "^2.0.8", "tslib": "^2.5.0" }, "engines": { @@ -1111,14 +1118,14 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.1.tgz", - "integrity": "sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.4.tgz", + "integrity": "sha512-cwPJN1fa1YOQzhBlTXRavABEYRRchci1X79QRwzaNLySnIMJfztyv1Zkst0iZPLMnpn8+CnHu3wOHS11J5Dr3A==", "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/property-provider": "^2.0.14", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/property-provider": "^2.0.16", + "@smithy/types": "^2.7.0", + "@smithy/url-parser": "^2.0.15", "tslib": "^2.5.0" }, "engines": { @@ -1126,23 +1133,23 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.13.tgz", - "integrity": "sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.15.tgz", + "integrity": "sha512-crjvz3j1gGPwA0us6cwS7+5gAn35CTmqu/oIxVbYJo2Qm/sGAye6zGJnMDk3BKhWZw5kcU1G4MxciTkuBpOZPg==", "dependencies": { "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "@smithy/util-hex-encoding": "^2.0.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.13.tgz", - "integrity": "sha512-OJ/2g/VxkzA+mYZxV102oX3CsiE+igTSmqq/ir3oEVG2kSIdRC00ryttj/lmL14W06ExNi0ysmfLxQkL8XrAZQ==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.15.tgz", + "integrity": "sha512-WiFG5N9j3jmS5P0z5Xev6dO0c3lf7EJYC2Ncb0xDnWFvShwXNn741AF71ABr5EcZw8F4rQma0362MMjAwJeZog==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.13", - "@smithy/types": "^2.5.0", + "@smithy/eventstream-serde-universal": "^2.0.15", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1150,11 +1157,11 @@ } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.13.tgz", - "integrity": "sha512-2BI1CbnYuEvAYoWSeWJtPNygbIKiWeSLxCmDLnyM6wQV32Of7VptiQlaFXPxXp4zqn/rs3ocZ/T29rxE4s4Gsg==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.15.tgz", + "integrity": "sha512-o65d2LRjgCbWYH+VVNlWXtmsI231SO99ZTOL4UuIPa6WTjbSHWtlXvUcJG9libhEKWmEV9DIUiH2IqyPWi7ubA==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1162,12 +1169,12 @@ } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.13.tgz", - "integrity": "sha512-7NbFwPafb924elFxCBDvm48jy/DeSrpFbFQN0uN2ThuY5HrEeubikS0t7WMva4Z4EnRoivpbuT0scb9vUIJKoA==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.15.tgz", + "integrity": "sha512-9OOXiIhHq1VeOG6xdHkn2ZayfMYM3vzdUTV3zhcCnt+tMqA3BJK3XXTJFRR2BV28rtRM778DzqbBTf+hqwQPTg==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.13", - "@smithy/types": "^2.5.0", + "@smithy/eventstream-serde-universal": "^2.0.15", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1175,12 +1182,12 @@ } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.13.tgz", - "integrity": "sha512-j0yFd5UfftM+ia9dxLRbheJDCkCZBHpcEzCsPO8BxVOTbdcX/auVJCv6ov/yvpCKsf4Hv3mOqi0Is1YogM2g3Q==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.15.tgz", + "integrity": "sha512-dP8AQp/pXlWBjvL0TaPBJC3rM0GoYv7O0Uim8d/7UKZ2Wo13bFI3/BhQfY/1DeiP1m23iCHFNFtOQxfQNBB8rQ==", "dependencies": { - "@smithy/eventstream-codec": "^2.0.13", - "@smithy/types": "^2.5.0", + "@smithy/eventstream-codec": "^2.0.15", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1188,34 +1195,34 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.6.tgz", - "integrity": "sha512-PStY3XO1Ksjwn3wMKye5U6m6zxXpXrXZYqLy/IeCbh3nM9QB3Jgw/B0PUSLUWKdXg4U8qgEu300e3ZoBvZLsDg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.3.1.tgz", + "integrity": "sha512-6MNk16fqb8EwcYY8O8WxB3ArFkLZ2XppsSNo1h7SQcFdDDwIumiJeO6wRzm7iB68xvsOQzsdQKbdtTieS3hfSQ==", "dependencies": { - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", + "@smithy/protocol-http": "^3.0.11", + "@smithy/querystring-builder": "^2.0.15", + "@smithy/types": "^2.7.0", "@smithy/util-base64": "^2.0.1", "tslib": "^2.5.0" } }, "node_modules/@smithy/hash-blob-browser": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.0.14.tgz", - "integrity": "sha512-yWdghyPJIEqLYsaE7YVgd3YhM7jN4Pv6eJQvTomnMsz5K2qRBlpjUx3T9fKlElp1qdeQ7DNc3sAat4i9CUBO7Q==", + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.0.16.tgz", + "integrity": "sha512-cSYRi05LA7DZDwjB1HL0BP8B56eUNNeLglVH147QTXFyuXJq/7erAIiLRfsyXB8+GfFHkSS5BHbc76a7k/AYPA==", "dependencies": { "@smithy/chunked-blob-reader": "^2.0.0", "@smithy/chunked-blob-reader-native": "^2.0.1", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/hash-node": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.15.tgz", - "integrity": "sha512-t/qjEJZu/G46A22PAk1k/IiJZT4ncRkG5GOCNWN9HPPy5rCcSZUbh7gwp7CGKgJJ7ATMMg+0Td7i9o1lQTwOfQ==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.17.tgz", + "integrity": "sha512-Il6WuBcI1nD+e2DM7tTADMf01wEPGK8PAhz4D+YmDUVaoBqlA+CaH2uDJhiySifmuKBZj748IfygXty81znKhw==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "@smithy/util-buffer-from": "^2.0.0", "@smithy/util-utf8": "^2.0.2", "tslib": "^2.5.0" @@ -1225,11 +1232,11 @@ } }, "node_modules/@smithy/hash-stream-node": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.0.15.tgz", - "integrity": "sha512-ZZ6kC/pHt5Dc2goXIIyC8uA7A4GUMSzdCynAabnZ3CSSaV6ctP8mlvVkqjPph0O3XzHlx/80gdLrNqi1GDPUsA==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.0.17.tgz", + "integrity": "sha512-ey8DtnATzp1mOXgS7rqMwSmAki6iJA+jgNucKcxRkhMB1rrICfHg+rhmIF50iLPDHUhTcS5pBMOrLzzpZftvNQ==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "@smithy/util-utf8": "^2.0.2", "tslib": "^2.5.0" }, @@ -1238,11 +1245,11 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.13.tgz", - "integrity": "sha512-XsGYhVhvEikX1Yz0kyIoLssJf2Rs6E0U2w2YuKdT4jSra5A/g8V2oLROC1s56NldbgnpesTYB2z55KCHHbKyjw==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.15.tgz", + "integrity": "sha512-dlEKBFFwVfzA5QroHlBS94NpgYjXhwN/bFfun+7w3rgxNvVy79SK0w05iGc7UAeC5t+D7gBxrzdnD6hreZnDVQ==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" } }, @@ -1258,22 +1265,22 @@ } }, "node_modules/@smithy/md5-js": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.0.15.tgz", - "integrity": "sha512-pAZaokib56XvhU0t/R9vAcr3L3bMhIakhF25X7EMSQ7LAURiLfce/tgON8I3x/dIbnZUyeRi8f2cx2azu6ATew==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.0.17.tgz", + "integrity": "sha512-jmISTCnEkOnm2oCNx/rMkvBT/eQh3aA6nktevkzbmn/VYqYEuc5Z2n5sTTqsciMSO01Lvf56wG1A4twDqovYeQ==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "@smithy/util-utf8": "^2.0.2", "tslib": "^2.5.0" } }, "node_modules/@smithy/middleware-content-length": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.15.tgz", - "integrity": "sha512-xH4kRBw01gJgWiU+/mNTrnyFXeozpZHw39gLb3JKGsFDVmSrJZ8/tRqu27tU/ki1gKkxr2wApu+dEYjI3QwV1Q==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.17.tgz", + "integrity": "sha512-OyadvMcKC7lFXTNBa8/foEv7jOaqshQZkjWS9coEXPRZnNnihU/Ls+8ZuJwGNCOrN2WxXZFmDWhegbnM4vak8w==", "dependencies": { - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", + "@smithy/protocol-http": "^3.0.11", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1281,16 +1288,16 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.2.0.tgz", - "integrity": "sha512-tddRmaig5URk2106PVMiNX6mc5BnKIKajHHDxb7K0J5MLdcuQluHMGnjkv18iY9s9O0tF+gAcPd/pDXA5L9DZw==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.2.3.tgz", + "integrity": "sha512-nYfxuq0S/xoAjdLbyn1ixeVB6cyH9wYCMtbbOCpcCRYR5u2mMtqUtVjjPAZ/DIdlK3qe0tpB0Q76szFGNuz+kQ==", "dependencies": { - "@smithy/middleware-serde": "^2.0.13", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-middleware": "^2.0.6", + "@smithy/middleware-serde": "^2.0.15", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/shared-ini-file-loader": "^2.2.7", + "@smithy/types": "^2.7.0", + "@smithy/url-parser": "^2.0.15", + "@smithy/util-middleware": "^2.0.8", "tslib": "^2.5.0" }, "engines": { @@ -1298,16 +1305,17 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.20.tgz", - "integrity": "sha512-X2yrF/SHDk2WDd8LflRNS955rlzQ9daz9UWSp15wW8KtzoTXg3bhHM78HbK1cjr48/FWERSJKh9AvRUUGlIawg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/protocol-http": "^3.0.9", - "@smithy/service-error-classification": "^2.0.6", - "@smithy/types": "^2.5.0", - "@smithy/util-middleware": "^2.0.6", - "@smithy/util-retry": "^2.0.6", + "version": "2.0.24", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.24.tgz", + "integrity": "sha512-q2SvHTYu96N7lYrn3VSuX3vRpxXHR/Cig6MJpGWxd0BWodUQUWlKvXpWQZA+lTaFJU7tUvpKhRd4p4MU3PbeJg==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.8", + "@smithy/protocol-http": "^3.0.11", + "@smithy/service-error-classification": "^2.0.8", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", + "@smithy/util-middleware": "^2.0.8", + "@smithy/util-retry": "^2.0.8", "tslib": "^2.5.0", "uuid": "^8.3.2" }, @@ -1324,11 +1332,11 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.13.tgz", - "integrity": "sha512-tBGbeXw+XsE6pPr4UaXOh+UIcXARZeiA8bKJWxk2IjJcD1icVLhBSUQH9myCIZLNNzJIH36SDjUX8Wqk4xJCJg==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.15.tgz", + "integrity": "sha512-FOZRFk/zN4AT4wzGuBY+39XWe+ZnCFd0gZtyw3f9Okn2CJPixl9GyWe98TIaljeZdqWkgrzGyPre20AcW2UMHQ==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1336,11 +1344,11 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.7.tgz", - "integrity": "sha512-L1KLAAWkXbGx1t2jjCI/mDJ2dDNq+rp4/ifr/HcC6FHngxho5O7A5bQLpKHGlkfATH6fUnOEx0VICEVFA4sUzw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.9.tgz", + "integrity": "sha512-bCB5dUtGQ5wh7QNL2ELxmDc6g7ih7jWU3Kx6MYH1h4mZbv9xL3WyhKHojRltThCB1arLPyTUFDi+x6fB/oabtA==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1348,13 +1356,13 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.5.tgz", - "integrity": "sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.8.tgz", + "integrity": "sha512-+w26OKakaBUGp+UG+dxYZtFb5fs3tgHg3/QrRrmUZj+rl3cIuw840vFUXX35cVPTUCQIiTqmz7CpVF7+hdINdQ==", "dependencies": { - "@smithy/property-provider": "^2.0.14", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", + "@smithy/property-provider": "^2.0.16", + "@smithy/shared-ini-file-loader": "^2.2.7", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1362,14 +1370,14 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.9.tgz", - "integrity": "sha512-+K0q3SlNcocmo9OZj+fz67gY4lwhOCvIJxVbo/xH+hfWObvaxrMTx7JEzzXcluK0thnnLz++K3Qe7Z/8MDUreA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.2.1.tgz", + "integrity": "sha512-8iAKQrC8+VFHPAT8pg4/j6hlsTQh+NKOWlctJBrYtQa4ExcxX7aSg3vdQ2XLoYwJotFUurg/NLqFCmZaPRrogw==", "dependencies": { - "@smithy/abort-controller": "^2.0.13", - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", + "@smithy/abort-controller": "^2.0.15", + "@smithy/protocol-http": "^3.0.11", + "@smithy/querystring-builder": "^2.0.15", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1377,11 +1385,11 @@ } }, "node_modules/@smithy/property-provider": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.14.tgz", - "integrity": "sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==", + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.16.tgz", + "integrity": "sha512-28Ky0LlOqtEjwg5CdHmwwaDRHcTWfPRzkT6HrhwOSRS2RryAvuDfJrZpM+BMcrdeCyEg1mbcgIMoqTla+rdL8Q==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1389,11 +1397,11 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.9.tgz", - "integrity": "sha512-U1wl+FhYu4/BC+rjwh1lg2gcJChQhytiNQSggREgQ9G2FzmoK9sACBZvx7thyWMvRyHQTE22mO2d5UM8gMKDBg==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.11.tgz", + "integrity": "sha512-3ziB8fHuXIRamV/akp/sqiWmNPR6X+9SB8Xxnozzj+Nq7hSpyKdFHd1FLpBkgfGFUTzzcBJQlDZPSyxzmdcx5A==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1401,11 +1409,11 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.13.tgz", - "integrity": "sha512-JhXKwp3JtsFUe96XLHy/nUPEbaXqn6r7xE4sNaH8bxEyytE5q1fwt0ew/Ke6+vIC7gP87HCHgQpJHg1X1jN2Fw==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.15.tgz", + "integrity": "sha512-e1q85aT6HutvouOdN+dMsN0jcdshp50PSCvxDvo6aIM57LqeXimjfONUEgfqQ4IFpYWAtVixptyIRE5frMp/2A==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "@smithy/util-uri-escape": "^2.0.0", "tslib": "^2.5.0" }, @@ -1414,11 +1422,11 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.13.tgz", - "integrity": "sha512-TEiT6o8CPZVxJ44Rly/rrsATTQsE+b/nyBVzsYn2sa75xAaZcurNxsFd8z1haoUysONiyex24JMHoJY6iCfLdA==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.15.tgz", + "integrity": "sha512-jbBvoK3cc81Cj1c1TH1qMYxNQKHrYQ2DoTntN9FBbtUWcGhc+T4FP6kCKYwRLXyU4AajwGIZstvNAmIEgUUNTQ==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1426,22 +1434,22 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.6.tgz", - "integrity": "sha512-fCQ36frtYra2fqY2/DV8+3/z2d0VB/1D1hXbjRcM5wkxTToxq6xHbIY/NGGY6v4carskMyG8FHACxgxturJ9Pg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.8.tgz", + "integrity": "sha512-jCw9+005im8tsfYvwwSc4TTvd29kXRFkH9peQBg5R/4DD03ieGm6v6Hpv9nIAh98GwgYg1KrztcINC1s4o7/hg==", "dependencies": { - "@smithy/types": "^2.5.0" + "@smithy/types": "^2.7.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.4.tgz", - "integrity": "sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.7.tgz", + "integrity": "sha512-0Qt5CuiogIuvQIfK+be7oVHcPsayLgfLJGkPlbgdbl0lD28nUKu4p11L+UG3SAEsqc9UsazO+nErPXw7+IgDpQ==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1449,15 +1457,15 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.15.tgz", - "integrity": "sha512-SRTEJSEhQYVlBKIIdZ9SZpqW+KFqxqcNnEcBX+8xkDdWx+DItme9VcCDkdN32yTIrICC+irUufnUdV7mmHPjoA==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.18.tgz", + "integrity": "sha512-SJRAj9jT/l9ocm8D0GojMbnA1sp7I4JeStOQ4lEXI8A5eHE73vbjlzlqIFB7cLvIgau0oUl4cGVpF9IGCrvjlw==", "dependencies": { - "@smithy/eventstream-codec": "^2.0.13", + "@smithy/eventstream-codec": "^2.0.15", "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", + "@smithy/util-middleware": "^2.0.8", "@smithy/util-uri-escape": "^2.0.0", "@smithy/util-utf8": "^2.0.2", "tslib": "^2.5.0" @@ -1467,13 +1475,13 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.15.tgz", - "integrity": "sha512-rngZcQu7Jvs9UbHihK1EI67RMPuzkc3CJmu4MBgB7D7yBnMGuFR86tq5rqHfL2gAkNnMelBN/8kzQVvZjNKefQ==", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.18.tgz", + "integrity": "sha512-7FqdbaJiVaHJDD9IfDhmzhSDbpjyx+ZsfdYuOpDJF09rl8qlIAIlZNoSaflKrQ3cEXZN2YxGPaNWGhbYimyIRQ==", "dependencies": { - "@smithy/middleware-stack": "^2.0.7", - "@smithy/types": "^2.5.0", - "@smithy/util-stream": "^2.0.20", + "@smithy/middleware-stack": "^2.0.9", + "@smithy/types": "^2.7.0", + "@smithy/util-stream": "^2.0.23", "tslib": "^2.5.0" }, "engines": { @@ -1481,9 +1489,9 @@ } }, "node_modules/@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.7.0.tgz", + "integrity": "sha512-1OIFyhK+vOkMbu4aN2HZz/MomREkrAC/HqY5mlJMUJfGrPRwijJDTeiN8Rnj9zUaB8ogXAfIOtZrrgqZ4w7Wnw==", "dependencies": { "tslib": "^2.5.0" }, @@ -1492,12 +1500,12 @@ } }, "node_modules/@smithy/url-parser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.13.tgz", - "integrity": "sha512-okWx2P/d9jcTsZWTVNnRMpFOE7fMkzloSFyM53fA7nLKJQObxM2T4JlZ5KitKKuXq7pxon9J6SF2kCwtdflIrA==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.15.tgz", + "integrity": "sha512-sADUncUj9rNbOTrdDGm4EXlUs0eQ9dyEo+V74PJoULY4jSQxS+9gwEgsPYyiu8PUOv16JC/MpHonOgqP/IEDZA==", "dependencies": { - "@smithy/querystring-parser": "^2.0.13", - "@smithy/types": "^2.5.0", + "@smithy/querystring-parser": "^2.0.15", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" } }, @@ -1514,9 +1522,9 @@ } }, "node_modules/@smithy/util-body-length-browser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", - "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.1.tgz", + "integrity": "sha512-NXYp3ttgUlwkaug4bjBzJ5+yIbUbUx8VsSLuHZROQpoik+gRkIBeEG9MPVYfvPNpuXb/puqodeeUXcKFe7BLOQ==", "dependencies": { "tslib": "^2.5.0" } @@ -1556,13 +1564,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.19.tgz", - "integrity": "sha512-VHP8xdFR7/orpiABJwgoTB0t8Zhhwpf93gXhNfUBiwAE9O0rvsv7LwpQYjgvbOUDDO8JfIYQB2GYJNkqqGWsXw==", + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.22.tgz", + "integrity": "sha512-qcF20IHHH96FlktvBRICDXDhLPtpVmtksHmqNGtotb9B0DYWXsC6jWXrkhrrwF7tH26nj+npVTqh9isiFV1gdA==", "dependencies": { - "@smithy/property-provider": "^2.0.14", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", + "@smithy/property-provider": "^2.0.16", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", "bowser": "^2.11.0", "tslib": "^2.5.0" }, @@ -1571,16 +1579,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.25", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.25.tgz", - "integrity": "sha512-jkmep6/JyWmn2ADw9VULDeGbugR4N/FJCKOt+gYyVswmN1BJOfzF2umaYxQ1HhQDvna3kzm1Dbo1qIfBW4iuHA==", + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.29.tgz", + "integrity": "sha512-+uG/15VoUh6JV2fdY9CM++vnSuMQ1VKZ6BdnkUM7R++C/vLjnlg+ToiSR1FqKZbMmKBXmsr8c/TsDWMAYvxbxQ==", "dependencies": { - "@smithy/config-resolver": "^2.0.18", - "@smithy/credential-provider-imds": "^2.1.1", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/property-provider": "^2.0.14", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", + "@smithy/config-resolver": "^2.0.21", + "@smithy/credential-provider-imds": "^2.1.4", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/property-provider": "^2.0.16", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1588,12 +1596,12 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.4.tgz", - "integrity": "sha512-FPry8j1xye5yzrdnf4xKUXVnkQErxdN7bUIaqC0OFoGsv2NfD9b2UUMuZSSt+pr9a8XWAqj0HoyVNUfPiZ/PvQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.7.tgz", + "integrity": "sha512-Q2gEind3jxoLk6hdKWyESMU7LnXz8aamVwM+VeVjOYzYT1PalGlY/ETa48hv2YpV4+YV604y93YngyzzzQ4IIA==", "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1612,11 +1620,11 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.6.tgz", - "integrity": "sha512-7W4uuwBvSLgKoLC1x4LfeArCVcbuHdtVaC4g30kKsD1erfICyQ45+tFhhs/dZNeQg+w392fhunCm/+oCcb6BSA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.8.tgz", + "integrity": "sha512-qkvqQjM8fRGGA8P2ydWylMhenCDP8VlkPn8kiNuFEaFz9xnUKC2irfqsBSJrfrOB9Qt6pQsI58r3zvvumhFMkw==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1624,12 +1632,12 @@ } }, "node_modules/@smithy/util-retry": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.6.tgz", - "integrity": "sha512-PSO41FofOBmyhPQJwBQJ6mVlaD7Sp9Uff9aBbnfBJ9eqXOE/obrqQjn0PNdkfdvViiPXl49BINfnGcFtSP4kYw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.8.tgz", + "integrity": "sha512-cQTPnVaVFMjjS6cb44WV2yXtHVyXDC5icKyIbejMarJEApYeJWpBU3LINTxHqp/tyLI+MZOUdosr2mZ3sdziNg==", "dependencies": { - "@smithy/service-error-classification": "^2.0.6", - "@smithy/types": "^2.5.0", + "@smithy/service-error-classification": "^2.0.8", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1637,13 +1645,13 @@ } }, "node_modules/@smithy/util-stream": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.20.tgz", - "integrity": "sha512-tT8VASuD8jJu0yjHEMTCPt1o5E3FVzgdsxK6FQLAjXKqVv5V8InCnc0EOsYrijgspbfDqdAJg7r0o2sySfcHVg==", + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.23.tgz", + "integrity": "sha512-OJMWq99LAZJUzUwTk+00plyxX3ESktBaGPhqNIEVab+53gLULiWN9B/8bRABLg0K6R6Xg4t80uRdhk3B/LZqMQ==", "dependencies": { - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/types": "^2.5.0", + "@smithy/fetch-http-handler": "^2.3.1", + "@smithy/node-http-handler": "^2.2.1", + "@smithy/types": "^2.7.0", "@smithy/util-base64": "^2.0.1", "@smithy/util-buffer-from": "^2.0.0", "@smithy/util-hex-encoding": "^2.0.0", @@ -1678,12 +1686,12 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.13.tgz", - "integrity": "sha512-YovIQatiuM7giEsRFotqJa2i3EbU2EE3PgtpXgtLgpx5rXiZMAwPxXYDFVFhuO0lbqvc/Zx4n+ZIisXOHPSqyg==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.15.tgz", + "integrity": "sha512-9Y+btzzB7MhLADW7xgD6SjvmoYaRkrb/9SCbNGmNdfO47v38rxb90IGXyDtAK0Shl9bMthTmLgjlfYc+vtz2Qw==", "dependencies": { - "@smithy/abort-controller": "^2.0.13", - "@smithy/types": "^2.5.0", + "@smithy/abort-controller": "^2.0.15", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -1806,12 +1814,35 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bl/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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.2.1" + } + }, "node_modules/blockstore-core": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/blockstore-core/-/blockstore-core-4.3.4.tgz", - "integrity": "sha512-JecnNXiDPEdeS9AeFWO0PUKKmmRMW0D+ggUb4lgK0XMDOUAWmhkaiDPhgBjEKrlya0n60XOjcgBYhg18CUqOFw==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/blockstore-core/-/blockstore-core-4.3.8.tgz", + "integrity": "sha512-Agunhjw9w0I1OoJn012OpzJwBRm3Nf+v64N2FaZSsF3UGhoQAu4RePLuIBsZrPh4XRqT5Yg1rHoBYJGDhDmkWQ==", "dependencies": { - "@libp2p/logger": "^3.0.0", + "@libp2p/logger": "^4.0.1", "err-code": "^3.0.1", "interface-blockstore": "^5.0.0", "interface-store": "^5.0.0", @@ -1820,7 +1851,39 @@ "it-merge": "^3.0.1", "it-pushable": "^3.0.0", "multiformats": "^12.0.1", - "uint8arrays": "^4.0.2" + "uint8arrays": "^5.0.0" + } + }, + "node_modules/blockstore-core/node_modules/@libp2p/interface": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.0.2.tgz", + "integrity": "sha512-z/3Yyg+7cVyzRXwzdrDkJd7YmNaLE9iZjQaixo5luI/n9uk5OFFjb9ulAsNqpq8V1xylCo2DXIC7f94KClwzVw==", + "dependencies": { + "@multiformats/multiaddr": "^12.1.10", + "it-pushable": "^3.2.1", + "it-stream-types": "^2.0.1", + "multiformats": "^12.1.3", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/blockstore-core/node_modules/@libp2p/logger": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-4.0.2.tgz", + "integrity": "sha512-J9UMtMU9BKXNp+3c5kcI7HyWOPYg2B2E6sn1gEQckiSexTaz0wKJSlgTZ89f9F8bkC3AaC8ybXYuHbFQhwpTIg==", + "dependencies": { + "@libp2p/interface": "^1.0.2", + "@multiformats/multiaddr": "^12.1.10", + "debug": "^4.3.4", + "interface-datastore": "^8.2.0", + "multiformats": "^12.1.3" + } + }, + "node_modules/blockstore-core/node_modules/uint8arrays": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.0.0.tgz", + "integrity": "sha512-RWO7gR4x6syxnKDfZO8mDCsaaYs1/BqZCxlHgrcRge50E9GTnLmtoA4kwFSGIL4s3dQkryeTkvtG6oEFEya3yg==", + "dependencies": { + "multiformats": "^12.0.1" } }, "node_modules/blockstore-fs": { @@ -1858,26 +1921,12 @@ } }, "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" } }, "node_modules/buffer-from": { @@ -2009,10 +2058,13 @@ } }, "node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -2161,18 +2213,6 @@ "node": "^14.13.1 || >=16.0.0" } }, - "node_modules/html-minifier-terser/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2198,28 +2238,35 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/interface-blockstore": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/interface-blockstore/-/interface-blockstore-5.2.6.tgz", - "integrity": "sha512-Cp6+QPY81kunaxQV/j5BWk3uSW6kpos8dLveJ3P2lbmA/yX2XeMwVlNOnQyGg0evhp1qmMLhf6eCswNiSMW3CA==", + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/interface-blockstore/-/interface-blockstore-5.2.7.tgz", + "integrity": "sha512-B9UplmgUdQg15f/6xDJEbQYcjMm568cnqJsxSZYbDD0s6eQX5gKh58sd9H3aJEMosIy8T4vz9MwWWZuAOc3hQQ==", "dependencies": { "interface-store": "^5.0.0", "multiformats": "^12.0.1" } }, "node_modules/interface-datastore": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/interface-datastore/-/interface-datastore-8.2.5.tgz", - "integrity": "sha512-kvLGJMz3RPoJF/g5DbEvfWWempIiSBLVMf63b0PBsziVcSkj0ofzHYI86v8vqpGedkQ81DtPCUKyvX9W7zWvrQ==", + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/interface-datastore/-/interface-datastore-8.2.9.tgz", + "integrity": "sha512-J/8PN8TnB5xxCRtgu9Vx3zExdOzcTU5/DBF2dlU41deX1GW6/SPpbJo5DRNSnvzfjmwJ7YhUOIFXyccUp8nuAA==", "dependencies": { "interface-store": "^5.0.0", - "nanoid": "^4.0.0", - "uint8arrays": "^4.0.2" + "uint8arrays": "^5.0.0" + } + }, + "node_modules/interface-datastore/node_modules/uint8arrays": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.0.0.tgz", + "integrity": "sha512-RWO7gR4x6syxnKDfZO8mDCsaaYs1/BqZCxlHgrcRge50E9GTnLmtoA4kwFSGIL4s3dQkryeTkvtG6oEFEya3yg==", + "dependencies": { + "multiformats": "^12.0.1" } }, "node_modules/interface-store": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-5.1.4.tgz", - "integrity": "sha512-SI2co5IAxAybBc9egRM2bXvHOa1RPh5SQQkO6di6t/aX92RbtzP4t8raB0l3GTzQmJADaBbzz8Tfa1QLgfMdGQ==" + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-5.1.5.tgz", + "integrity": "sha512-X0KnJBk3o+YL13MxZBMwa88/b3Mdrpm0yPzkSTKDDVn9BSPH7UK6W+ZtIPO2bxKOQVmq7zqOwAnYnpfqWjb6/g==" }, "node_modules/ipfs-bitswap": { "version": "19.0.2", @@ -2518,42 +2565,6 @@ "node": ">=12.0.0" } }, - "node_modules/jsdoc/node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/jsdoc/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jsdoc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -2639,6 +2650,27 @@ "markdown-it": "*" } }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -2697,6 +2729,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2719,23 +2763,6 @@ "node": ">=8.0.0" } }, - "node_modules/nanoid": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz", - "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^14 || ^16 || >=18" - } - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -3010,15 +3037,27 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, "node_modules/terser": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", - "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", + "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -3073,21 +3112,17 @@ } }, "node_modules/uint8arraylist": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.3.tgz", - "integrity": "sha512-oEVZr4/GrH87K0kjNce6z8pSCzLEPqHNLNR5sj8cJOySrTP8Vb/pMIbZKLJGhQKxm1TiZ31atNrpn820Pyqpow==", + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.7.tgz", + "integrity": "sha512-ohRElqR6C5dd60vRFLq40MCiSnUe1AzkpHvbCEMCGGP6zMoFYECsjdhL6bR1kTK37ONNRDuHQ3RIpScRYcYYIg==", "dependencies": { "uint8arrays": "^4.0.2" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" } }, "node_modules/uint8arrays": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-4.0.6.tgz", - "integrity": "sha512-4ZesjQhqOU2Ip6GPReIwN60wRxIupavL8T0Iy36BBHr2qyMrNxsPJvr7vpS4eFt8F8kSguWUPad6ZM9izs/vyw==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-4.0.10.tgz", + "integrity": "sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA==", "dependencies": { "multiformats": "^12.0.1" } diff --git a/package.json b/package.json index 88e4707..69a550a 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,10 @@ "type": "module", "main": "dist/cjs/index.js", "module": "dist/mjs/index.mjs", + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, "exports": { ".": { "require": "./dist/mjs/index.cjs", diff --git a/src/gatewayManager.js b/src/gatewayManager.js index 6e81ff9..1774199 100644 --- a/src/gatewayManager.js +++ b/src/gatewayManager.js @@ -51,7 +51,13 @@ class GatewayManager { * * @param {string} name Unique name across entire platform for the gateway. Must be a valid subdomain name. * @param {gatewayOptions} [options] - * @returns {*} + * @returns {Promise} - A promise that resolves to the value of a gateway. + * @example + * // Create gateway with name of `create-gateway-example` and a custom domain of `cname.mycustomdomain.com`. + * // The custom domain must already exist and have a CNAME record pointed at `create-gateway-example.myfilebase.com`. + * await gatewayManager.create(`create-gateway-example`, { + * domain: `cname.mycustomdomain.com` + * }); */ async create(name, options = {}) { let createOptions = { @@ -128,6 +134,11 @@ class GatewayManager { * @param {gatewayOptions} options - The options for the update operation. * * @returns {Promise} - A Promise that resolves to true if the gateway was updated. + * @example + * // Update gateway with name of `update-gateway-example` and set the gateway to only serve CIDs pinned by user. + * await gatewayManager.update(`update-gateway-example`, { + * private: true + * }); */ async update(name, options) { const updateOptions = { diff --git a/src/nameManager.js b/src/nameManager.js index a0c37f5..af34656 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -119,6 +119,9 @@ class NameManager { * @param {nameOptions} options - The options for the set operation. * * @returns {Promise} - A Promise that resolves to true if the IPNS name was updated. + * @example + * // Update name with label of `update-name-example` and set the value of the IPNS name. + * await nameManager.update(`update-name-example`, `bafybeidt4nmaci476lyon2mvgfmwyzysdazienhxs2bqnfpdainzjuwjom`); */ async update(label, cid, options = {}) { const updateOptions = { diff --git a/src/objectManager.js b/src/objectManager.js index 3a3808a..c6c729a 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -111,26 +111,20 @@ class ObjectManager { * ]); */ async upload(key, source, bucket = this.#defaultBucket) { + // Generate Upload UUID + const uploadUUID = uuidv4(); + // Setup Upload Options - const uploadUUID = uuidv4(), - temporaryBlockstoreDir = path.resolve( - os.tmpdir(), - "filebase-sdk", - "uploads", - uploadUUID, - ), - temporaryCarFilePath = `${temporaryBlockstoreDir}/main.car`, - uploadOptions = { - client: this.#client, - params: { - Bucket: bucket, - Key: key, - Body: source, - }, - queueSize: this.#maxConcurrentUploads, - partSize: 1024 * 1024 * 105, - leavePartsOnError: false, // optional manually handle dropped parts - }; + const uploadOptions = { + client: this.#client, + params: { + Bucket: bucket, + Key: key, + Body: source, + }, + queueSize: this.#maxConcurrentUploads, + partSize: 26843546, //25.6Mb || 250Gb Max File Size + }; // Pack Multiple Files into CAR file for upload let parsedEntries = {}; @@ -140,12 +134,22 @@ class ObjectManager { import: "car", }; + let temporaryCarFilePath, temporaryBlockstoreDir; try { + // Setup Blockstore + temporaryBlockstoreDir = path.resolve( + os.tmpdir(), + "filebase-sdk", + "uploads", + uploadUUID, + ); + temporaryCarFilePath = `${temporaryBlockstoreDir}/main.car`; await mkdir(temporaryBlockstoreDir, { recursive: true }); - const temporaryFsBlockstore = new FsBlockstore(temporaryBlockstoreDir), - heliaFs = unixfs({ - blockstore: temporaryFsBlockstore, - }); + const temporaryBlockstore = new FsBlockstore(temporaryBlockstoreDir); + + const heliaFs = unixfs({ + blockstore: temporaryBlockstore, + }); for (let sourceEntry of source) { sourceEntry.path = @@ -159,20 +163,26 @@ class ObjectManager { const rootEntry = parsedEntries[uploadUUID]; // Get carFile stream here - const carExporter = car({ blockstore: temporaryFsBlockstore }), - { writer, out } = CarWriter.create([rootEntry.cid]), - output = createWriteStream(temporaryCarFilePath); + const carExporter = car({ blockstore: temporaryBlockstore }), + { writer, out } = CarWriter.create([rootEntry.cid]); + + // Put carFile stream to disk + const output = createWriteStream(temporaryCarFilePath); Readable.from(out).pipe(output); await carExporter.export(rootEntry.cid, writer); - // Upload carFile via S3 + // Set Uploader to Read from carFile on disk uploadOptions.params.Body = createReadStream(temporaryCarFilePath); + + // Upload carFile via S3 const parallelUploads3 = new Upload(uploadOptions); await parallelUploads3.done(); - await temporaryFsBlockstore.close(); + await temporaryBlockstore.close(); } finally { - // Delete Temporary Blockstore - await rm(temporaryBlockstoreDir, { recursive: true, force: true }); + if (typeof temporaryBlockstoreDir !== "undefined") { + // Delete Temporary Blockstore + await rm(temporaryBlockstoreDir, { recursive: true, force: true }); + } } } else { // Upload file via S3 From 2753b5079aecdb93f8abcab052f8b83cffbd5833 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:43:19 -0600 Subject: [PATCH 54/79] Update Test and Repo Link --- package.json | 2 +- readme.md | 2 +- src/bucketManager.js | 4 ++-- test/nameManager.spec.js | 44 ++++++++++++++++++++++++---------------- test/package.json | 3 --- 5 files changed, 30 insertions(+), 25 deletions(-) delete mode 100644 test/package.json diff --git a/package.json b/package.json index 69a550a..3888d71 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@filebase/sdk", "version": "1.0.0", "description": "", - "repository": "https://github.com/filebase/filebase-sdk", + "repository": "https://github.com/filebase/sdk", "type": "module", "main": "dist/cjs/index.js", "module": "dist/mjs/index.mjs", diff --git a/readme.md b/readme.md index b1b80fb..3e1f002 100644 --- a/readme.md +++ b/readme.md @@ -50,7 +50,7 @@ await bucketManager.create(bucketName); // List buckets const bucketsList = await bucketManager.list(); // Toggle bucket privacy off -await bucketManager.toggle(bucketName, false); +await bucketManager.setPrivacy(bucketName, false); console.dir(bucketsList); // Initialize ObjectManager diff --git a/src/bucketManager.js b/src/bucketManager.js index 189a87b..fac3736 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -98,8 +98,8 @@ class BucketManager { * @returns {Promise} A promise that resolves to true if the bucket was successfully toggled. * @example * // Toggle bucket with label of `toggle-bucket-example` - * await bucketManager.toggle(`toggle-bucket-example`, true); // Enabled - * await bucketManager.toggle(`toggle-bucket-example`, false); // Disabled + * await bucketManager.setPrivacy(`toggle-bucket-example`, true); // Enabled + * await bucketManager.setPrivacy(`toggle-bucket-example`, false); // Disabled */ async setPrivacy(name, targetState) { diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index f8c9a93..a413419 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -97,16 +97,21 @@ test("toggle name on", async () => { await nameManager.create(testNameLabel, TEST_CID, { enabled: false, }); - const resolvedName = await nameManager.list(testNameLabel); - if (resolvedName?.enabled === true) { - throw new Error(`Incorrect State on Resolved Name`); + try { + const resolvedName = await nameManager.get(testNameLabel); + if (resolvedName?.enabled === true) { + throw new Error(`Incorrect State on Resolved Name`); + } + await nameManager.toggle(testNameLabel, true); + const updatedName = await nameManager.get(testNameLabel); + assert.strictEqual(updatedName.label, testNameLabel); + assert.strictEqual(updatedName.cid, TEST_CID); + assert.strictEqual(updatedName.enabled, true); + } catch (err) { + console.error(err); + } finally { + await nameManager.delete(testNameLabel); } - await nameManager.toggle(testNameLabel, true); - const updatedName = await nameManager.get(testNameLabel); - await nameManager.delete(testNameLabel); - assert.strictEqual(updatedName.label, testNameLabel); - assert.strictEqual(updatedName.cid, TEST_CID); - assert.strictEqual(updatedName.enabled, true); }); test("toggle name off", async () => { @@ -116,14 +121,17 @@ test("toggle name off", async () => { process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ); await nameManager.create(testNameLabel, TEST_CID); - const resolvedName = await nameManager.list(testNameLabel); - if (resolvedName?.enabled === false) { - throw new Error(`Incorrect State on Resolved Name`); + try { + const resolvedName = await nameManager.get(testNameLabel); + if (resolvedName?.enabled === false) { + throw new Error(`Incorrect State on Resolved Name`); + } + await nameManager.toggle(testNameLabel, false); + const updatedName = await nameManager.get(testNameLabel); + assert.strictEqual(updatedName.label, testNameLabel); + assert.strictEqual(updatedName.cid, TEST_CID); + assert.strictEqual(updatedName.enabled, false); + } finally { + await nameManager.delete(testNameLabel); } - await nameManager.toggle(testNameLabel, false); - const updatedName = await nameManager.get(testNameLabel); - await nameManager.delete(testNameLabel); - assert.strictEqual(updatedName.label, testNameLabel); - assert.strictEqual(updatedName.cid, TEST_CID); - assert.strictEqual(updatedName.enabled, false); }); diff --git a/test/package.json b/test/package.json deleted file mode 100644 index f344768..0000000 --- a/test/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} \ No newline at end of file From 19b69b248145d7013331f870585268a58eb1da97 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:57:51 -0600 Subject: [PATCH 55/79] Wrap Tests for Better Deletion --- test/bucketManager.spec.js | 76 ++++++------ test/gatewayManager.spec.js | 60 +++++---- test/nameManager.spec.js | 24 ++-- test/objectManager.spec.js | 241 +++++++++++++++++++----------------- 4 files changed, 221 insertions(+), 180 deletions(-) diff --git a/test/bucketManager.spec.js b/test/bucketManager.spec.js index 745492c..71e2d6f 100644 --- a/test/bucketManager.spec.js +++ b/test/bucketManager.spec.js @@ -16,17 +16,19 @@ test("create bucket", async (t) => { const bucketNameToCreate = `${TEST_PREFIX}-create-bucket-test-pass`; await bucketManager.create(bucketNameToCreate); - // List buckets - const currentBuckets = await bucketManager.list(), - createdBucket = currentBuckets.find((currentBucket) => { - return currentBucket.Name === bucketNameToCreate; - }); - - // Delete new bucket - await bucketManager.delete(bucketNameToCreate); - - // Assert new bucket exists - assert.equal(createdBucket.Name, bucketNameToCreate); + try { + // List buckets + const currentBuckets = await bucketManager.list(), + createdBucket = currentBuckets.find((currentBucket) => { + return currentBucket.Name === bucketNameToCreate; + }); + + // Assert new bucket exists + assert.equal(createdBucket.Name, bucketNameToCreate); + } finally { + // Delete new bucket + await bucketManager.delete(bucketNameToCreate); + } }); test("list buckets", async () => { @@ -92,30 +94,32 @@ test("set bucket privacy to public", async (t) => { const bucketNameToCreate = `${TEST_PREFIX}-toggle-bucket-test-pass`; await bucketManager.create(bucketNameToCreate); - // List buckets - const currentBuckets = await bucketManager.list(), - createdBucket = currentBuckets.find((currentBucket) => { - return currentBucket.Name === bucketNameToCreate; - }); - - // Check Privacy - const initialPrivacy = await bucketManager.getPrivacy(bucketNameToCreate); - if (initialPrivacy === false) { - throw new Error(`Unexpected Privacy State on Bucket`); - } - - // Toggle Privacy - await bucketManager.setPrivacy(bucketNameToCreate, false); - - // Check Privacy - const updatedPrivacy = await bucketManager.getPrivacy(bucketNameToCreate); - if (updatedPrivacy === true) { - throw new Error(`Unexpected Privacy State on Bucket`); + try { + // List buckets + const currentBuckets = await bucketManager.list(), + createdBucket = currentBuckets.find((currentBucket) => { + return currentBucket.Name === bucketNameToCreate; + }); + + // Check Privacy + const initialPrivacy = await bucketManager.getPrivacy(bucketNameToCreate); + if (initialPrivacy === false) { + throw new Error(`Unexpected Privacy State on Bucket`); + } + + // Toggle Privacy + await bucketManager.setPrivacy(bucketNameToCreate, false); + + // Check Privacy + const updatedPrivacy = await bucketManager.getPrivacy(bucketNameToCreate); + if (updatedPrivacy === true) { + throw new Error(`Unexpected Privacy State on Bucket`); + } + + // Assert new bucket exists + assert.equal(createdBucket.Name, bucketNameToCreate); + } finally { + // Delete new bucket + await bucketManager.delete(bucketNameToCreate); } - - // Delete new bucket - await bucketManager.delete(bucketNameToCreate); - - // Assert new bucket exists - assert.equal(createdBucket.Name, bucketNameToCreate); }); diff --git a/test/gatewayManager.spec.js b/test/gatewayManager.spec.js index 381aa59..73840bd 100644 --- a/test/gatewayManager.spec.js +++ b/test/gatewayManager.spec.js @@ -32,13 +32,16 @@ test("update gateway", async () => { process.env.TEST_GW_KEY || process.env.TEST_KEY, process.env.TEST_GW_SECRET || process.env.TEST_SECRET, ), - createdName = await gatewayManager.create(testGatewayName), - updatedName = await gatewayManager.update(createdName.name, { + createdName = await gatewayManager.create(testGatewayName); + try { + const updatedName = await gatewayManager.update(createdName.name, { private: true, enabled: false, }); - await gatewayManager.delete(testGatewayName); - assert.strictEqual(updatedName, true); + assert.strictEqual(updatedName, true); + } finally { + await gatewayManager.delete(testGatewayName); + } }); test("get gateway", async () => { @@ -47,10 +50,13 @@ test("get gateway", async () => { process.env.TEST_GW_KEY || process.env.TEST_KEY, process.env.TEST_GW_SECRET || process.env.TEST_SECRET, ), - createdName = await gatewayManager.create(testGatewayName, {}), - testName = await gatewayManager.get(createdName.name); - await gatewayManager.delete(testGatewayName); - assert.strictEqual(testName.name, testGatewayName); + createdName = await gatewayManager.create(testGatewayName, {}); + try { + const testName = await gatewayManager.get(createdName.name); + assert.strictEqual(testName.name, testGatewayName); + } finally { + await gatewayManager.delete(testGatewayName); + } }); test("list gateways", async () => { @@ -81,15 +87,18 @@ test("toggle gateway off", async () => { process.env.TEST_GW_SECRET || process.env.TEST_SECRET, ); await gatewayManager.create(testGatewayName); - const resolvedName = await gatewayManager.get(testGatewayName); - if (resolvedName?.enabled === false) { - throw new Error(`Incorrect State on Resolved Name`); + try { + const resolvedName = await gatewayManager.get(testGatewayName); + if (resolvedName?.enabled === false) { + throw new Error(`Incorrect State on Resolved Name`); + } + await gatewayManager.toggle(testGatewayName, false); + const updatedName = await gatewayManager.get(testGatewayName); + assert.strictEqual(updatedName.name, testGatewayName); + assert.strictEqual(updatedName.enabled, false); + } finally { + await gatewayManager.delete(testGatewayName); } - await gatewayManager.toggle(testGatewayName, false); - const updatedName = await gatewayManager.get(testGatewayName); - await gatewayManager.delete(testGatewayName); - assert.strictEqual(updatedName.name, testGatewayName); - assert.strictEqual(updatedName.enabled, false); }); test("toggle gateway on", async () => { @@ -101,13 +110,16 @@ test("toggle gateway on", async () => { await gatewayManager.create(testGatewayName, { enabled: false, }); - const resolvedName = await gatewayManager.get(testGatewayName); - if (resolvedName?.enabled === true) { - throw new Error(`Incorrect State on Resolved Name`); + try { + const resolvedName = await gatewayManager.get(testGatewayName); + if (resolvedName?.enabled === true) { + throw new Error(`Incorrect State on Resolved Name`); + } + await gatewayManager.toggle(testGatewayName, true); + const updatedName = await gatewayManager.get(testGatewayName); + assert.strictEqual(updatedName.name, testGatewayName); + assert.strictEqual(updatedName.enabled, true); + } finally { + await gatewayManager.delete(testGatewayName); } - await gatewayManager.toggle(testGatewayName, true); - const updatedName = await gatewayManager.get(testGatewayName); - await gatewayManager.delete(testGatewayName); - assert.strictEqual(updatedName.name, testGatewayName); - assert.strictEqual(updatedName.enabled, true); }); diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index a413419..0124791 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -51,10 +51,13 @@ test("update name", async () => { process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ), - createdName = await nameManager.create(testNameLabel, TEST_CID), - updatedName = await nameManager.update(createdName.label, TEST_CID); - await nameManager.delete(testNameLabel); - assert.strictEqual(updatedName, true); + createdName = await nameManager.create(testNameLabel, TEST_CID); + try { + const updatedName = await nameManager.update(createdName.label, TEST_CID); + assert.strictEqual(updatedName, true); + } finally { + await nameManager.delete(testNameLabel); + } }); test("get name", async () => { @@ -63,11 +66,14 @@ test("get name", async () => { process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, ), - createdName = await nameManager.create(testNameLabel, TEST_CID), - testName = await nameManager.get(createdName.label); - await nameManager.delete(testNameLabel); - assert.strictEqual(testName.label, testNameLabel); - assert.strictEqual(testName.cid, TEST_CID); + createdName = await nameManager.create(testNameLabel, TEST_CID); + try { + const testName = await nameManager.get(createdName.label); + assert.strictEqual(testName.label, testNameLabel); + assert.strictEqual(testName.cid, TEST_CID); + } finally { + await nameManager.delete(testNameLabel); + } }); test("list names", async () => { diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 0e177e7..43ad38c 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -80,35 +80,39 @@ test("delete object", async () => { const deleteTestBucket = `${TEST_PREFIX}-delete-object-test-pass`; await createBucket(deleteTestBucket); - // Upload object `delete-object-test` - const objectNameToCreate = `delete-object-test`; - const uploaded = await uploadObject( - deleteTestBucket, - objectNameToCreate, - Buffer.from("delete object", "utf-8"), - ); - if (uploaded === false) { - throw Error(`Failed to create object [delete-object-test]`); - } - - // Initialize ObjectManager - const objectManager = new ObjectManager( - process.env.TEST_S3_KEY || process.env.TEST_KEY, - process.env.TEST_S3_SECRET || process.env.TEST_SECRET, - { bucket: deleteTestBucket }, - ); - - // Delete object `delete-object-test` - await objectManager.delete(objectNameToCreate); + try { + // Upload object `delete-object-test` + const objectNameToCreate = `delete-object-test`; + const uploaded = await uploadObject( + deleteTestBucket, + objectNameToCreate, + Buffer.from("delete object", "utf-8"), + ); + if (uploaded === false) { + throw Error(`Failed to create object [delete-object-test]`); + } + + // Initialize ObjectManager + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + { bucket: deleteTestBucket }, + ); - // List bucket and assert new object doesn't exist - const existingObjects = await objectManager.list({ - Prefix: objectNameToCreate, - MaxKeys: 1, - }), - uploadedObject = - existingObjects.length > 0 ? existingObjects[0] : undefined; - assert.equal(typeof uploadedObject, "undefined"); + // Delete object `delete-object-test` + await objectManager.delete(objectNameToCreate); + + // List bucket and assert new object doesn't exist + const existingObjects = await objectManager.list({ + Prefix: objectNameToCreate, + MaxKeys: 1, + }), + uploadedObject = + existingObjects.length > 0 ? existingObjects[0] : undefined; + assert.equal(typeof uploadedObject, "undefined"); + } finally { + await deleteBucket(deleteTestBucket); + } }); test("upload object", async () => { @@ -116,16 +120,19 @@ test("upload object", async () => { const uploadTestBucket = `${TEST_PREFIX}-create-object-test-pass`; await createBucket(uploadTestBucket); - // Upload object `create-object-test` - const uploaded = await uploadObject( - uploadTestBucket, - `create-object-test`, - Buffer.from("upload object", "utf-8"), - ); + try { + // Upload object `create-object-test` + const uploaded = await uploadObject( + uploadTestBucket, + `create-object-test`, + Buffer.from("upload object", "utf-8"), + ); - assert.strictEqual(uploaded, true); - await deleteObject(uploadTestBucket, `create-object-test`); - await deleteBucket(uploadTestBucket); + assert.strictEqual(uploaded, true); + await deleteObject(uploadTestBucket, `create-object-test`); + } finally { + await deleteBucket(uploadTestBucket); + } }); test("upload directory", async () => { @@ -133,28 +140,31 @@ test("upload directory", async () => { const uploadDirectoryTestBucket = `${TEST_PREFIX}-create-directory-test-pass`; await createBucket(uploadDirectoryTestBucket); - // Upload object `create-object-test` - const uploaded = await uploadObject( - uploadDirectoryTestBucket, - `create-directory-test`, - [ - { - path: "/testObjects/1.txt", - content: Buffer.from("upload test object", "utf-8"), - }, - { - path: "/testObjects/deep/1.txt", - content: Buffer.from("upload deep test object", "utf-8"), - }, - { - path: "/topLevel.txt", - content: Buffer.from("upload top level test object", "utf-8"), - }, - ], - ); - assert.strictEqual(uploaded, true); - await deleteObject(uploadDirectoryTestBucket, `create-directory-test`); - await deleteBucket(uploadDirectoryTestBucket); + try { + // Upload object `create-object-test` + const uploaded = await uploadObject( + uploadDirectoryTestBucket, + `create-directory-test`, + [ + { + path: "/testObjects/1.txt", + content: Buffer.from("upload test object", "utf-8"), + }, + { + path: "/testObjects/deep/1.txt", + content: Buffer.from("upload deep test object", "utf-8"), + }, + { + path: "/topLevel.txt", + content: Buffer.from("upload top level test object", "utf-8"), + }, + ], + ); + assert.strictEqual(uploaded, true); + await deleteObject(uploadDirectoryTestBucket, `create-directory-test`); + } finally { + await deleteBucket(uploadDirectoryTestBucket); + } }); test("download object", async () => { @@ -162,30 +172,36 @@ test("download object", async () => { const downloadTestBucket = `${TEST_PREFIX}-download-object-test-pass`; await createBucket(downloadTestBucket); - // Upload object `download-object-test` - const objectNameToCreate = `download-object-test`; - const uploaded = await uploadObject( - downloadTestBucket, - objectNameToCreate, - Buffer.from("download object", "utf-8"), - ); - if (uploaded === false) { - throw Error(`Failed to create object [download-object-test]`); + try { + // Upload object `download-object-test` + const objectNameToCreate = `download-object-test`; + const uploaded = await uploadObject( + downloadTestBucket, + objectNameToCreate, + Buffer.from("download object", "utf-8"), + ); + if (uploaded === false) { + throw Error(`Failed to create object [download-object-test]`); + } + + try { + // Download object `download-object-test` and assert it completes + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + { bucket: downloadTestBucket }, + ); + const downloadStream = await objectManager.download(objectNameToCreate), + downloadFilename = uuidv4(), + downloadPath = Path.resolve(os.tmpdir(), downloadFilename), + writeFileResult = await writeFile(downloadPath, downloadStream); + assert.strictEqual(typeof writeFileResult, "undefined"); + } finally { + await deleteObject(downloadTestBucket, objectNameToCreate); + } + } finally { + await deleteBucket(downloadTestBucket); } - - // Download object `download-object-test` and assert it completes - const objectManager = new ObjectManager( - process.env.TEST_S3_KEY || process.env.TEST_KEY, - process.env.TEST_S3_SECRET || process.env.TEST_SECRET, - { bucket: downloadTestBucket }, - ); - const downloadStream = await objectManager.download(objectNameToCreate), - downloadFilename = uuidv4(), - downloadPath = Path.resolve(os.tmpdir(), downloadFilename), - writeFileResult = await writeFile(downloadPath, downloadStream); - assert.strictEqual(typeof writeFileResult, "undefined"); - await deleteObject(downloadTestBucket, objectNameToCreate); - await deleteBucket(downloadTestBucket); }); test("list objects", async () => { @@ -193,36 +209,39 @@ test("list objects", async () => { const listTestBucket = `${TEST_PREFIX}-list-objects-test-pass`; await createBucket(listTestBucket); - let createdObjectCount = 0; - while (createdObjectCount < 26) { - // Upload objects `list-object-test-[x]` - const objectNameToCreate = `list-object-test-${createdObjectCount}`; - await uploadObject( - listTestBucket, - objectNameToCreate, - Buffer.from(`list objects ${createdObjectCount}`, "utf-8"), + try { + let createdObjectCount = 0; + while (createdObjectCount < 26) { + // Upload objects `list-object-test-[x]` + const objectNameToCreate = `list-object-test-${createdObjectCount}`; + await uploadObject( + listTestBucket, + objectNameToCreate, + Buffer.from(`list objects ${createdObjectCount}`, "utf-8"), + ); + createdObjectCount++; + } + + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + { bucket: listTestBucket }, ); - createdObjectCount++; - } - const objectManager = new ObjectManager( - process.env.TEST_S3_KEY || process.env.TEST_KEY, - process.env.TEST_S3_SECRET || process.env.TEST_SECRET, - { bucket: listTestBucket }, - ); - - const bucketList = await objectManager.list({ - MaxKeys: 50, - Prefix: `list-object-test-`, - }); - assert.equal(bucketList.length, 26); - - let deletedObjectCount = 0; - while (deletedObjectCount < 26) { - // Delete objects `list-object-test-[x]` - const objectNameToDelete = `list-object-test-${deletedObjectCount}`; - await deleteObject(listTestBucket, objectNameToDelete); - deletedObjectCount++; + const bucketList = await objectManager.list({ + MaxKeys: 50, + Prefix: `list-object-test-`, + }); + assert.equal(bucketList.length, 26); + + let deletedObjectCount = 0; + while (deletedObjectCount < 26) { + // Delete objects `list-object-test-[x]` + const objectNameToDelete = `list-object-test-${deletedObjectCount}`; + await deleteObject(listTestBucket, objectNameToDelete); + deletedObjectCount++; + } + } finally { + await deleteBucket(listTestBucket); } - await deleteBucket(listTestBucket); }); From e72447a00420d8e9d5140acb7a0307eccd495053 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 17 Dec 2023 12:59:45 -0600 Subject: [PATCH 56/79] Minor Updates --- readme.md | 7 ++---- src/gatewayManager.js | 24 ++++++++++++++++++--- src/nameManager.js | 28 +++++++++++++++++++----- src/objectManager.js | 50 ++++++++++++++++++++++--------------------- 4 files changed, 72 insertions(+), 37 deletions(-) diff --git a/readme.md b/readme.md index 3e1f002..40544f0 100644 --- a/readme.md +++ b/readme.md @@ -32,15 +32,12 @@ The snippet below shows how to create a new bucket with `BucketManager`, upload with `ObjectManager`, publish the object to IPNS with `NameManager`, delete the object with `ObjectManager` and finally delete the bucket with `BucketManager`. -To use the library in your project, use npm or yarn to install the [`@filebase/sdk`](https://www.npmjs.com/package/@filebase/sdk) module. +To use the library in your project, use npm or yarn to install the [`@filebase/sdk`](https://www.npmjs.com/package/@filebase/sdk) module. Requires node.js 16+. **node.js** ````js // Import Classes -import {BucketManager, ObjectManager, NameManager} from 'filebase-sdk' - -// Setup S3 Config -const s3Config = {}; +import {BucketManager, ObjectManager, NameManager, GatewayManager} from 'filebase-sdk' // Initialize BucketManager const bucketManager = new BucketManager(S3_KEY, S3_SECRET); diff --git a/src/gatewayManager.js b/src/gatewayManager.js index 1774199..0b86366 100644 --- a/src/gatewayManager.js +++ b/src/gatewayManager.js @@ -91,14 +91,20 @@ class GatewayManager { const deleteResponse = await this.#client.request({ method: "DELETE", url: `/${name}`, + validateStatus: (status) => { + return status === 202 || status === 404; + }, }); - return deleteResponse.status === 202; + if (deleteResponse.status === 404) { + throw new Error(`Could not find matching name for gateway`); + } + return true; } /** * @summary Returns the value of a gateway * @param {string} name - Parameter representing the name to get. - * @returns {Promise} - A promise that resolves to the value of a gateway. + * @returns {Promise} - A promise that resolves to the value of a gateway. * @example * // Get gateway with name of `gateway-get-example` * await gatewayManager.get(`gateway-get-example`); @@ -157,8 +163,14 @@ class GatewayManager { method: "PUT", url: `/${name}`, data: updateOptions, + validateStatus: (status) => { + return status === 200 || status === 404; + }, }); - return updateResponse.status === 200; + if (updateResponse.status === 404) { + throw new Error(`Could not find matching name for gateway`); + } + return true; } /** @@ -178,7 +190,13 @@ class GatewayManager { data: { enabled: Boolean(targetState), }, + validateStatus: (status) => { + return status === 200 || status === 404; + }, }); + if (toggleResponse.status === 404) { + throw new Error(`Could not find matching name for gateway`); + } return toggleResponse.status === 200; } } diff --git a/src/nameManager.js b/src/nameManager.js index af34656..fbf4662 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -130,12 +130,18 @@ class NameManager { if (options?.enabled) { updateOptions.enabled = Boolean(options.enabled); } - const updateResponse = await this.#client.request({ + const updateResult = await this.#client.request({ method: "PUT", url: `/${label}`, data: updateOptions, + validateStatus: (status) => { + return status === 200 || status === 404; + }, }); - return updateResponse.status === 200; + if (updateResult.status === 404) { + throw new Error(`Could not find matching label for name`); + } + return true; } /** @@ -180,11 +186,17 @@ class NameManager { * await nameManager.delete(`delete-name-example`); */ async delete(label) { - const deleteResponse = await this.#client.request({ + const deleteResult = await this.#client.request({ method: "DELETE", url: `/${label}`, + validateStatus: (status) => { + return status === 202 || status === 404; + }, }); - return deleteResponse.status === 202; + if (deleteResult.status === 404) { + throw new Error(`Could not find matching label for name`); + } + return true; } /** @@ -204,8 +216,14 @@ class NameManager { data: { enabled: targetState, }, + validateStatus: (status) => { + return status === 200 || status === 404; + }, }); - return toggleResponse.status === 200; + if (toggleResponse.status === 404) { + throw new Error(`Could not find matching label for name`); + } + return true; } } diff --git a/src/objectManager.js b/src/objectManager.js index c6c729a..75aef02 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -68,15 +68,16 @@ class ObjectManager { } /** - * @typedef {Object} object - * @property {string} cid The CID of the uploaded object - * @property {array} [entries] If a directory then returns an array of the containing objects + * @typedef {Object} objectOptions + * @property {string} [bucket] - The bucket to pin the IPFS CID into. */ /** - * @typedef {Object} objectEntry + * @typedef {Object} uploadObjectResult * @property {string} cid The CID of the uploaded object - * @property {string} path The path of the object + * @property {array} [entries] If a directory then returns an array of the containing objects + * @property {string} entries.cid The CID of the uploaded object + * @property {string} entries.path The path of the object */ /** @@ -89,8 +90,8 @@ class ObjectManager { * @param {Buffer|ReadableStream|Array} source - The content of the file to be uploaded. * If an array of objects is provided, each object should have a 'path' property specifying the path of the file * and a 'content' property specifying the content of the file. - * @param {string} [bucket] - The bucket name. Default is the value of the defaultBucket property. - * @returns {Promise} + * @param {objectOptions} [options] - The options for uploading the file. + * @returns {Promise} * @example * // Upload Object * await objectManager.upload("my-object", Buffer.from("Hello World!")); @@ -110,21 +111,22 @@ class ObjectManager { * }, * ]); */ - async upload(key, source, bucket = this.#defaultBucket) { + async upload(key, source, options) { // Generate Upload UUID const uploadUUID = uuidv4(); // Setup Upload Options - const uploadOptions = { - client: this.#client, - params: { - Bucket: bucket, - Key: key, - Body: source, - }, - queueSize: this.#maxConcurrentUploads, - partSize: 26843546, //25.6Mb || 250Gb Max File Size - }; + const bucket = options?.bucket || this.#defaultBucket, + uploadOptions = { + client: this.#client, + params: { + Bucket: bucket, + Key: key, + Body: source, + }, + queueSize: this.#maxConcurrentUploads, + partSize: 26843546, //25.6Mb || 250Gb Max File Size + }; // Pack Multiple Files into CAR file for upload let parsedEntries = {}; @@ -213,15 +215,15 @@ class ObjectManager { /** * @summary Downloads an object from the specified bucket using the provided key. * @param {string} key - The key of the object to be downloaded. - * @param {string} [bucket] - The name of the bucket to download from. If not provided, the default bucket will be used. + * @param {objectOptions} [options] - The options for downloading the file. * @returns {Promise} - A promise that resolves with the contents of the downloaded object as a Stream. * @example * // Download object with name of `download-object-example` * await objectManager.download(`download-object-example`); */ - async download(key, bucket = this.#defaultBucket) { + async download(key, options) { const command = new GetObjectCommand({ - Bucket: bucket, + Bucket: options?.bucket || this.#defaultBucket, Key: key, }), response = await this.#client.send(command); @@ -289,15 +291,15 @@ class ObjectManager { /** * @summary Deletes an object from the specified bucket using the provided key. * @param {string} key - The key of the object to be deleted. - * @param {string} [bucket] - The name of the bucket that contains the object. Defaults to the default bucket. + * @param {objectOptions} [options] - The options for deleting the file. * @returns {Promise} - A Promise that resolves with the result of the delete operation. * @example * // Delete object with name of `delete-object-example` * await objectManager.delete(`delete-object-example`); */ - async delete(key, bucket = this.#defaultBucket) { + async delete(key, options) { const command = new DeleteObjectCommand({ - Bucket: bucket, + Bucket: options?.bucket || this.#defaultBucket, Key: key, }); From cf098529de23475fac68dd3ec9a8e7af977a307b Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 17 Dec 2023 13:00:10 -0600 Subject: [PATCH 57/79] Add Pin Manager --- src/index.js | 11 +- src/pinManager.js | 256 ++++++++++++++++++++++++++++++++++++++++ test/pinManager.spec.js | 152 ++++++++++++++++++++++++ 3 files changed, 417 insertions(+), 2 deletions(-) create mode 100644 src/pinManager.js create mode 100644 test/pinManager.spec.js diff --git a/src/index.js b/src/index.js index 1ed77e3..8687af6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,13 @@ import BucketManager from "./bucketManager.js"; -import ObjectManager from "./objectManager.js"; import GatewayManager from "./gatewayManager.js"; import NameManager from "./nameManager.js"; +import ObjectManager from "./objectManager.js"; +import PinManager from "./pinManager.js"; -export { BucketManager, ObjectManager, GatewayManager, NameManager }; +export { + BucketManager, + GatewayManager, + NameManager, + ObjectManager, + PinManager, +}; diff --git a/src/pinManager.js b/src/pinManager.js new file mode 100644 index 0000000..5801145 --- /dev/null +++ b/src/pinManager.js @@ -0,0 +1,256 @@ +import axios from "axios"; + +/** Provides methods for managing pins in an REST endpoint. */ +class PinManager { + #DEFAULT_ENDPOINT = "https://api.filebase.io"; + #DEFAULT_TIMEOUT = 60000; + + #DEFAULT_GATEWAY = "https://ipfs.filebase.io"; + + #client; + #credentials; + #gatewayConfiguration; + #defaultBucket; + + /** + * @typedef {Object} pinManagerOptions Optional settings for the constructor. + * @property {string} [bucket] Default bucket to use. + * @property {pinDownloadOptions} [gateway] Default gateway to use. + */ + + /** + * @typedef {Object} pinDownloadOptions Optional settings for downloading pins + * @property {string} [endpoint="https://ipfs.filebase.io"] Default gateway to use. + * @property {string} [token] Token for the default gateway. + * @property {number} [timeout=60000] Timeout for the default gateway + */ + + /** + * @summary Creates a new instance of the constructor. + * @param {string} clientKey - The access key ID for authentication. + * @param {string} clientSecret - The secret access key for authentication. + * @param {pinManagerOptions} [options] - Optional settings for the constructor. + * @example + * import { PinManager } from "@filebase/sdk"; + * const pinManager = new PinManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD", { + * bucket: "my-default-bucket", + * gateway: { + * endpoint: "https://my-default-gateway.mydomain.com + * token: SUPER_SECRET_GATEWAY_TOKEN + * } + * }); + */ + constructor(clientKey, clientSecret, options) { + this.#defaultBucket = options?.bucket; + const PSAClientEndpoint = + process.env.NODE_ENV === "test" + ? process.env.TEST_NAME_ENDPOINT || this.#DEFAULT_ENDPOINT + : this.#DEFAULT_ENDPOINT, + baseURL = `${PSAClientEndpoint}/v1/ipfs/pins`; + this.#credentials = { + key: clientKey, + secret: clientSecret, + }; + this.#client = axios.create({ + baseURL: baseURL, + timeout: this.#DEFAULT_TIMEOUT, + }); + + this.#gatewayConfiguration = { + endpoint: options?.gateway?.endpoint || this.#DEFAULT_GATEWAY, + token: options?.gateway?.token, + timeout: options?.gateway?.timeout || this.#DEFAULT_TIMEOUT, + }; + } + + /** + * @typedef {Object} pinStatus + * @property {string} requestid Globally unique identifier of the pin request; can be used to check the status of ongoing pinning, or pin removal + * @property {string} status Status a pin object can have at a pinning service. ("queued","pinning","pinned","failed") + * @property {string} created Immutable timestamp indicating when a pin request entered a pinning service; can be used for filtering results and pagination + * @property {Object} pin Pin object + * @property {string} pin.cid Content Identifier (CID) pinned recursively + * @property {string} pin.name Name for pinned data; can be used for lookups later + * @property {Array} pin.origins Optional list of multiaddrs known to provide the data + * @property {Object} pin.meta Optional metadata for pin object + * @property {Array} delegates List of multiaddrs designated by pinning service that will receive the pin data + * @property {object} [info] Optional info for PinStatus response + * @property {function} download Convenience function to download pin + */ + + /** + * @typedef {Object} pinOptions + * @property {string} [bucket] - The bucket to pin the IPFS CID into. + */ + + /** + * @typedef {Object} listPinOptions + * @property {Array} [cid] Return pin objects responsible for pinning the specified CID(s); be aware that using longer hash functions introduces further constraints on the number of CIDs that will fit under the limit of 2000 characters per URL in browser contexts + * @property {string} [name] Return pin objects with specified name (by default a case-sensitive, exact match) + * @property {string} [match] Customize the text matching strategy applied when the name filter is present; exact (the default) is a case-sensitive exact match, partial matches anywhere in the name, iexact and ipartial are case-insensitive versions of the exact and partial strategies + * @property {Array} [status] Return pin objects for pins with the specified status (when missing, service defaults to pinned only) + * @property {string} [before] Return results created (queued) before provided timestamp + * @property {string} [after] Return results created (queued) after provided timestamp + * @property {number} [limit] Max records to return + * @property {Object} [meta] Return pin objects that match specified metadata keys passed as a string representation of a JSON object; when implementing a client library, make sure the parameter is URL-encoded to ensure safe transport + */ + + /** + * @typedef {Object} listPinResults + * @property {number} count Total number of pin objects that exist for passed query filters + * @property {Array} Array of PinStatus results + */ + + /** + * + * @param {listPinOptions} [listOptions] + * @param {pinOptions} [options] + * @returns {Promise} + */ + async list(listOptions, options) { + const encodedToken = this.#getEncodedToken(options?.bucket), + getResponse = await this.#client.request({ + method: "GET", + params: listOptions, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + for (let pinStatus of getResponse.data.results) { + pinStatus.download = () => { + return this.download(pinStatus.pin.cid); + }; + } + return getResponse.data; + } + + /** + * + * @param {string} key Key or path of the file in the bucket + * @param {string} cid Content Identifier (CID) to be pinned recursively + * @param {Object} [metadata] Optional metadata for pin object + * @param {pinOptions} [options] Options for pinning the object + * @returns {Promise} + */ + async create(key, cid, metadata, options) { + const encodedToken = this.#getEncodedToken(options?.bucket), + pinStatus = await this.#client.request({ + method: "POST", + data: { + cid, + name: key, + meta: metadata, + }, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + pinStatus.data.download = () => { + return this.download(pinStatus.data.pin.cid); + }; + return pinStatus.data; + } + + async replace(requestid, cid, metadata, options) { + const encodedToken = this.#getEncodedToken(options?.bucket), + pinStatusResult = await this.#client.request({ + method: "POST", + url: requestid, + data: { + cid, + meta: metadata, + }, + validateStatus: (status) => { + return status === 200 || status === 404; + }, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + if (pinStatusResult.status === 404) { + throw new Error(`Could not find matching requestid`); + } + const pinStatus = pinStatusResult; + pinStatus.download = () => { + return this.download(pinStatus.pin.cid); + }; + return pinStatus; + } + + /** + * + * @param {string} cid + * @param {pinDownloadOptions} [options] + * @returns {Promise} + */ + async download(cid, options) { + const downloadHeaders = {}; + if (this.#gatewayConfiguration.token || options?.token) { + downloadHeaders["x-filebase-gateway-token"] = + this.#gatewayConfiguration.token || options.token; + } + + const downloadEndpoint = + options?.endpoint || this.#gatewayConfiguration.endpoint, + getResponse = await this.#client.request({ + method: "GET", + baseURL: downloadEndpoint, + url: `/ipfs/${cid}`, + headers: downloadHeaders, + type: "stream", + timeout: this.#gatewayConfiguration.timeout, + }); + return getResponse.data; + } + + /** + * + * @param {string} requestid Globally unique identifier of the pin request + * @param {pinOptions} [options] Options for getting the pin + * @returns {Promise} + */ + async get(requestid, options) { + const encodedToken = this.#getEncodedToken(options?.bucket), + getResponseResult = await this.#client.request({ + method: "GET", + url: `/${requestid}`, + headers: { Authorization: `Bearer ${encodedToken}` }, + validateStatus: (status) => { + return status === 200 || status === 404; + }, + }); + if (getResponseResult.status === 404) { + return false; + } + const pinStatus = getResponseResult.data; + pinStatus.download = () => { + return this.download(pinStatus.pin.cid); + }; + return pinStatus; + } + + /** + * + * @param requestid Globally unique identifier of the pin request + * @param {pinOptions} [options] Options for deleting the pin + * @returns {Promise} + */ + async delete(requestid, options) { + const encodedToken = this.#getEncodedToken(options?.bucket), + deleteResponse = await this.#client.request({ + method: "DELETE", + url: `/${requestid}`, + headers: { Authorization: `Bearer ${encodedToken}` }, + validateStatus: (status) => { + return status === 202 || status === 404; + }, + }); + if (deleteResponse.status === 404) { + throw new Error(`Could not find matching requestid`); + } + return true; + } + + #getEncodedToken(bucket) { + bucket = bucket || this.#defaultBucket; + return Buffer.from( + `${this.#credentials.key}:${this.#credentials.secret}:${bucket}`, + ).toString("base64"); + } +} + +export default PinManager; diff --git a/test/pinManager.spec.js b/test/pinManager.spec.js new file mode 100644 index 0000000..ac07d6a --- /dev/null +++ b/test/pinManager.spec.js @@ -0,0 +1,152 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { PinManager } from "../src/index.js"; +import { v4 as uuidv4 } from "uuid"; +import Path from "node:path"; +import os from "node:os"; +import { writeFile } from "node:fs/promises"; +import pinManager from "../src/pinManager.js"; + +const TEST_BUCKET = "pinning-test", + TEST_CID_1 = "QmSEu6zGwKgkQA3ZKaDnvkrwre1kkQa7eRFCbQi7waNwTT", + TEST_CID_2 = "QmNXcMdXadLRTxLpHJMsGnaeKz26d2F6NgUDVWScp54EfC", + TEST_PREFIX = Date.now(); + +test("create pin", async () => { + const testPinName = `${TEST_PREFIX}-create-pin-test-pass`, + pinManager = new PinManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + { + bucket: TEST_BUCKET, + }, + ); + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); +}); + +test("replace pin", async () => { + const testPinName = `${TEST_PREFIX}-replace-pin-test-pass`, + pinManager = new PinManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + { + bucket: TEST_BUCKET, + }, + ); + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + try { + const replacedPin = await pinManager.replace( + createdPin.requestid, + TEST_CID_2, + { + updatedByApp: Date.now(), + }, + ); + assert.strictEqual(replacedPin.requestid, createdPin.requestid); + assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); + } finally { + await pinManager.delete(createdPin.requestid); + } +}); + +test("get pin", async () => { + const testPinName = `${TEST_PREFIX}-get-pin-test-pass`, + pinManager = new PinManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + { + bucket: TEST_BUCKET, + }, + ); + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + try { + const queriedPin = await pinManager.get(createdPin.requestid); + assert.strictEqual(queriedPin.requestid, createdPin.requestid); + assert.strictEqual(queriedPin.pin.cid, TEST_CID_1); + } finally { + await pinManager.delete(createdPin.requestid); + } +}); + +test("download pin", async () => { + const testPinName = `${TEST_PREFIX}-download-pin-test-pass`, + pinManager = new PinManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + { + bucket: TEST_BUCKET, + }, + ); + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + const downloadStream = await pinManager.download(createdPin.pin.cid), + downloadFilename = uuidv4(), + downloadPath = Path.resolve(os.tmpdir(), downloadFilename), + writeFileResult = await writeFile(downloadPath, downloadStream); + assert.strictEqual(typeof writeFileResult, "undefined"); +}); + +test("download pin by reference", async () => { + const testPinName = `${TEST_PREFIX}-download-pin-test-pass`, + pinManager = new PinManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + { + bucket: TEST_BUCKET, + }, + ); + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + const pinToDownload = await pinManager.get(createdPin.requestid), + downloadStream = await pinToDownload.download(), + downloadFilename = uuidv4(), + downloadPath = Path.resolve(os.tmpdir(), downloadFilename), + writeFileResult = await writeFile(downloadPath, downloadStream); + assert.strictEqual(typeof writeFileResult, "undefined"); +}); + +test("list pins", async () => { + const testPinName = `${TEST_PREFIX}-list-pin-test-pass`, + pinManager = new PinManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + { + bucket: TEST_BUCKET, + }, + ), + existingPinList = await pinManager.list(), + countToCreate = 25; + let createdPins = []; + for (let i = 0; i < countToCreate; i++) { + createdPins.push( + await pinManager.create(`${testPinName}_${i}`, TEST_CID_1), + ); + } + try { + const pinList = await pinManager.list(); + assert.strictEqual(pinList.count, existingPinList.count + countToCreate); + } finally { + for (const createdPin of createdPins) { + await pinManager.delete(createdPin.requestid); + } + } +}); + +test("delete pin", async () => { + const testPinName = `${TEST_PREFIX}-delete-pin-test-pass`, + pinManager = new PinManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + { + bucket: TEST_BUCKET, + }, + ); + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + await pinManager.delete(createdPin.requestid); + const deletedPin = await pinManager.get(createdPin.requestid); + assert.strictEqual(deletedPin, false); +}); From bbd109d9f2fdb7c255b386eb3800532b4d41f11d Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Sun, 17 Dec 2023 13:05:17 -0600 Subject: [PATCH 58/79] Update objectManager.js Add Metadata Optionally --- src/objectManager.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/objectManager.js b/src/objectManager.js index 75aef02..a2c43a2 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -90,6 +90,7 @@ class ObjectManager { * @param {Buffer|ReadableStream|Array} source - The content of the file to be uploaded. * If an array of objects is provided, each object should have a 'path' property specifying the path of the file * and a 'content' property specifying the content of the file. + * @param {Object} [metadata] Optional metadata for pin object * @param {objectOptions} [options] - The options for uploading the file. * @returns {Promise} * @example @@ -111,7 +112,7 @@ class ObjectManager { * }, * ]); */ - async upload(key, source, options) { + async upload(key, source, metadata, options) { // Generate Upload UUID const uploadUUID = uuidv4(); @@ -123,6 +124,7 @@ class ObjectManager { Bucket: bucket, Key: key, Body: source, + Metadata: metadata || {}, }, queueSize: this.#maxConcurrentUploads, partSize: 26843546, //25.6Mb || 250Gb Max File Size @@ -133,6 +135,7 @@ class ObjectManager { if (Array.isArray(source)) { // Mark Upload as a CAR file import uploadOptions.params.Metadata = { + ...uploadOptions.params.Metadata, import: "car", }; From 910e8f6a6ed5ff58a82b6fe22afe9935084d6e51 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 18 Dec 2023 09:01:12 -0600 Subject: [PATCH 59/79] Download Support and Test Concurrency Update Test Concurrency Add support for downloads via ObjectManager and PinManager --- .github/workflows/test.yml | 2 +- src/helpers.js | 26 ++++++++++ src/objectManager.js | 102 +++++++++++++++++++++++++++++-------- src/pinManager.js | 26 ++-------- test/objectManager.spec.js | 11 ++-- 5 files changed, 121 insertions(+), 46 deletions(-) create mode 100644 src/helpers.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d775782..458ae27 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: with: node-version: '20.x' - run: npm ci - - run: npm test + - run: npm test --test-concurrency=1 env: TEST_KEY: ${{ secrets.TEST_S3_KEY }} TEST_SECRET: ${{ secrets.TEST_S3_SECRET }} diff --git a/src/helpers.js b/src/helpers.js new file mode 100644 index 0000000..52049e6 --- /dev/null +++ b/src/helpers.js @@ -0,0 +1,26 @@ +import axios from "axios"; + +const GATEWAY_DEFAULT_TIMEOUT = 60000; + +async function downloadFromGateway(cid, options) { + if (typeof options.endpoint !== "string") { + throw new Error(`Default Gateway must be set`); + } + + const downloadHeaders = {}; + if (options.token) { + downloadHeaders["x-filebase-gateway-token"] = options.token; + } + + const downloadResponse = await axios.request({ + method: "GET", + baseURL: options.endpoint, + url: `/ipfs/${cid}`, + headers: downloadHeaders, + type: "stream", + timeout: options?.timeout || GATEWAY_DEFAULT_TIMEOUT, + }); + return downloadResponse.data; +} + +export { downloadFromGateway }; diff --git a/src/objectManager.js b/src/objectManager.js index a2c43a2..a964237 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -19,6 +19,8 @@ import os from "node:os"; import path from "node:path"; import { Readable } from "node:stream"; import { v4 as uuidv4 } from "uuid"; +import PinManager from "./pinManager.js"; +import { downloadFromGateway } from "./helpers.js"; /** Interacts with an S3 client to perform various operations on objects in a bucket. */ class ObjectManager { @@ -26,16 +28,29 @@ class ObjectManager { #DEFAULT_REGION = "us-east-1"; #DEFAULT_MAX_CONCURRENT_UPLOADS = 4; + #DEFAULT_GATEWAY = "https://ipfs.filebase.io"; + #DEFAULT_TIMEOUT = 60000; + #client; + #credentials; #defaultBucket; + #gatewayConfiguration; #maxConcurrentUploads; /** * @typedef {Object} objectManagerOptions Optional settings for the constructor. * @property {string} [bucket] Default bucket to use. + * @property {objectDownloadOptions} [gateway] Default gateway to use. * @property {number} [maxConcurrentUploads] The maximum number of concurrent uploads. */ + /** + * @typedef {Object} objectDownloadOptions Optional settings for downloading objects + * @property {string} endpoint Default gateway to use. + * @property {string} [token] Token for the default gateway. + * @property {number} [timeout=60000] Timeout for the default gateway + */ + /** * @summary Creates a new instance of the constructor. * @param {string} clientKey - The access key ID for authentication. @@ -64,7 +79,17 @@ class ObjectManager { this.#defaultBucket = options?.bucket; this.#maxConcurrentUploads = options?.maxConcurrentUploads || this.#DEFAULT_MAX_CONCURRENT_UPLOADS; + this.#credentials = { + key: clientKey, + secret: clientSecret, + }; this.#client = new S3Client(clientConfiguration); + + this.#gatewayConfiguration = { + endpoint: options?.gateway?.endpoint, + token: options?.gateway?.token, + timeout: options?.gateway?.timeout || this.#DEFAULT_TIMEOUT, + }; } /** @@ -75,6 +100,7 @@ class ObjectManager { /** * @typedef {Object} uploadObjectResult * @property {string} cid The CID of the uploaded object + * @property {function} download Convenience function to download the object via S3 or the selected gateway * @property {array} [entries] If a directory then returns an array of the containing objects * @property {string} entries.cid The CID of the uploaded object * @property {string} entries.path The path of the object @@ -87,11 +113,12 @@ class ObjectManager { * * @summary Uploads a file or a CAR file to the specified bucket. * @param {string} key - The key or path of the file in the bucket. - * @param {Buffer|ReadableStream|Array} source - The content of the file to be uploaded. - * If an array of objects is provided, each object should have a 'path' property specifying the path of the file - * and a 'content' property specifying the content of the file. + * @param {Buffer|ReadableStream|Array} source - The content of the object to be uploaded. + * If an array of files is provided, each file should have a 'path' property specifying the path of the file + * and a 'content' property specifying the content of the file. The SDK will then construct a CAR file locally + * and use that as the content of the object to be uploaded. * @param {Object} [metadata] Optional metadata for pin object - * @param {objectOptions} [options] - The options for uploading the file. + * @param {objectOptions} [options] - The options for uploading the object. * @returns {Promise} * @example * // Upload Object @@ -207,18 +234,50 @@ class ObjectManager { if (Object.keys(parsedEntries).length === 0) { return { cid: responseCid, + download: () => { + return this.#routeDownload(responseCid, key, options); + }, }; } return { cid: responseCid, + download: () => { + return this.#routeDownload(responseCid, key, options); + }, entries: parsedEntries, }; } + async #routeDownload(cid, key, options) { + return typeof this.#gatewayConfiguration.endpoint !== "undefined" + ? downloadFromGateway(cid, this.#gatewayConfiguration) + : this.download(key, options); + } + + /** + * @summary Gets an objects info and metadata using the S3 API. + * @param {string} key - The key of the object to be inspected. + * @param {objectOptions} [options] - The options for inspecting the object. + * @returns {Promise<*>} + */ + async get(key, options) { + const command = new HeadObjectCommand({ + Bucket: options?.bucket || this.#defaultBucket, + Key: key, + }), + response = await this.#client.send(command); + + response.Body.download = () => { + return this.#routeDownload(response.Body.metadata.CID, key, options); + }; + + return response.Body; + } + /** * @summary Downloads an object from the specified bucket using the provided key. * @param {string} key - The key of the object to be downloaded. - * @param {objectOptions} [options] - The options for downloading the file. + * @param {objectOptions} [options] - The options for downloading the object.. * @returns {Promise} - A promise that resolves with the contents of the downloaded object as a Stream. * @example * // Download object with name of `download-object-example` @@ -234,6 +293,20 @@ class ObjectManager { return response.Body; } + /** + * @typedef {Object} listObjectsResult + * @property {boolean} IsTruncated Indicates if more results exist on the server + * @property {string} NextContinuationToken ContinuationToken used to paginate list requests + * @property {Array} Contents List of Keys stored in the S3 Bucket + * @property {string} Contents.Key Key of the Object + * @property {string} Contents.LastModified Date Last Modified of the Object + * @property {string} Contents.CID CID of the Object + * @property {string} Contents.ETag ETag of the Object + * @property {number} Contents.Size Size in Bytes of the Object + * @property {string} Contents.StorageClass Class of Storage of the Object + * @property {function} Contents.download Convenience function to download the item using the S3 gateway + */ + /** * @typedef {Object} listObjectOptions * @property {string} [Bucket] The name of the bucket. If not provided, the default bucket will be used. @@ -246,7 +319,7 @@ class ObjectManager { * Retrieves a list of objects from a specified bucket. * * @param {listObjectOptions} options - The options for listing objects. - * @returns {Promise} - A promise that resolves to an array of objects. + * @returns {Promise} - A promise that resolves to an array of objects. * @example * // List objects in bucket with a limit of 1000 * await objectManager.list({ @@ -275,20 +348,9 @@ class ObjectManager { ...commandOptions, }); - let isTruncated = true, - bucketContents = []; - while (isTruncated && bucketContents.length < limit) { - const { Contents, IsTruncated, NextContinuationToken } = - await this.#client.send(command); - if (typeof Contents === "undefined") { - isTruncated = false; - continue; - } - bucketContents = bucketContents.concat(Contents); - isTruncated = IsTruncated; - command.input.ContinuationToken = NextContinuationToken; - } - return bucketContents.slice(0, limit); + const { Contents, IsTruncated, NextContinuationToken } = + await this.#client.send(command); + return { Contents, IsTruncated, NextContinuationToken }; } /** diff --git a/src/pinManager.js b/src/pinManager.js index 5801145..29e79b7 100644 --- a/src/pinManager.js +++ b/src/pinManager.js @@ -1,12 +1,11 @@ import axios from "axios"; +import { downloadFromGateway } from "./helpers.js"; /** Provides methods for managing pins in an REST endpoint. */ class PinManager { #DEFAULT_ENDPOINT = "https://api.filebase.io"; #DEFAULT_TIMEOUT = 60000; - #DEFAULT_GATEWAY = "https://ipfs.filebase.io"; - #client; #credentials; #gatewayConfiguration; @@ -20,7 +19,7 @@ class PinManager { /** * @typedef {Object} pinDownloadOptions Optional settings for downloading pins - * @property {string} [endpoint="https://ipfs.filebase.io"] Default gateway to use. + * @property {string} endpoint Default gateway to use. * @property {string} [token] Token for the default gateway. * @property {number} [timeout=60000] Timeout for the default gateway */ @@ -57,7 +56,7 @@ class PinManager { }); this.#gatewayConfiguration = { - endpoint: options?.gateway?.endpoint || this.#DEFAULT_GATEWAY, + endpoint: options?.gateway?.endpoint, token: options?.gateway?.token, timeout: options?.gateway?.timeout || this.#DEFAULT_TIMEOUT, }; @@ -178,23 +177,8 @@ class PinManager { * @returns {Promise} */ async download(cid, options) { - const downloadHeaders = {}; - if (this.#gatewayConfiguration.token || options?.token) { - downloadHeaders["x-filebase-gateway-token"] = - this.#gatewayConfiguration.token || options.token; - } - - const downloadEndpoint = - options?.endpoint || this.#gatewayConfiguration.endpoint, - getResponse = await this.#client.request({ - method: "GET", - baseURL: downloadEndpoint, - url: `/ipfs/${cid}`, - headers: downloadHeaders, - type: "stream", - timeout: this.#gatewayConfiguration.timeout, - }); - return getResponse.data; + const downloadOptions = Object.assign(this.#gatewayConfiguration, options); + return downloadFromGateway(cid, downloadOptions); } /** diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 43ad38c..17ef4be 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -45,7 +45,8 @@ async function uploadObject(bucket, key, body) { Prefix: key, MaxKeys: 1, }), - uploadedObject = objectsList.length > 0 ? objectsList[0] : undefined; + uploadedObject = + objectsList.Contents.length > 0 ? objectsList.Contents[0] : undefined; return typeof uploadedObject !== "undefined"; } @@ -108,7 +109,9 @@ test("delete object", async () => { MaxKeys: 1, }), uploadedObject = - existingObjects.length > 0 ? existingObjects[0] : undefined; + existingObjects.Contents.length > 0 + ? existingObjects.Contents[0] + : undefined; assert.equal(typeof uploadedObject, "undefined"); } finally { await deleteBucket(deleteTestBucket); @@ -228,11 +231,11 @@ test("list objects", async () => { { bucket: listTestBucket }, ); - const bucketList = await objectManager.list({ + const objectList = await objectManager.list({ MaxKeys: 50, Prefix: `list-object-test-`, }); - assert.equal(bucketList.length, 26); + assert.equal(objectList.Contents.length, 26); let deletedObjectCount = 0; while (deletedObjectCount < 26) { From dd1cee55fb2d5167d94db2a24b0a8c960fb9052f Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 18 Dec 2023 09:38:03 -0600 Subject: [PATCH 60/79] Add Object Download by Ref Test --- .github/workflows/test.yml | 1 + src/objectManager.js | 50 ++++++++++++++++++++------------ test/objectManager.spec.js | 58 ++++++++++++++++++++++++++++---------- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 458ae27..99655cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,5 +17,6 @@ jobs: env: TEST_KEY: ${{ secrets.TEST_S3_KEY }} TEST_SECRET: ${{ secrets.TEST_S3_SECRET }} + TEST_IPFS_GATEWAY: ${{ vars.TEST_IPFS_GATEWAY }} TEST_IPNS_CID: ${{ vars.TEST_IPNS_CID }} TEST_IPNS_PRIVATE_KEY: ${{ secrets.TEST_IPNS_PRIVATE_KEY }} diff --git a/src/objectManager.js b/src/objectManager.js index a964237..ddcb72b 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -98,7 +98,7 @@ class ObjectManager { */ /** - * @typedef {Object} uploadObjectResult + * @typedef {Object} objectHeadResult * @property {string} cid The CID of the uploaded object * @property {function} download Convenience function to download the object via S3 or the selected gateway * @property {array} [entries] If a directory then returns an array of the containing objects @@ -119,7 +119,7 @@ class ObjectManager { * and use that as the content of the object to be uploaded. * @param {Object} [metadata] Optional metadata for pin object * @param {objectOptions} [options] - The options for uploading the object. - * @returns {Promise} + * @returns {Promise} * @example * // Upload Object * await objectManager.upload("my-object", Buffer.from("Hello World!")); @@ -258,20 +258,28 @@ class ObjectManager { * @summary Gets an objects info and metadata using the S3 API. * @param {string} key - The key of the object to be inspected. * @param {objectOptions} [options] - The options for inspecting the object. - * @returns {Promise<*>} + * @returns {Promise} */ async get(key, options) { - const command = new HeadObjectCommand({ - Bucket: options?.bucket || this.#defaultBucket, - Key: key, - }), - response = await this.#client.send(command); + const bucket = options?.bucket || this.#defaultBucket; + try { + const command = new HeadObjectCommand({ + Bucket: bucket, + Key: key, + }), + response = await this.#client.send(command); - response.Body.download = () => { - return this.#routeDownload(response.Body.metadata.CID, key, options); - }; + response.download = () => { + return this.#routeDownload(response.Metadata.cid, key, options); + }; - return response.Body; + return response; + } catch (err) { + if (err.name === "NotFound") { + return false; + } + throw err; + } } /** @@ -284,13 +292,19 @@ class ObjectManager { * await objectManager.download(`download-object-example`); */ async download(key, options) { - const command = new GetObjectCommand({ - Bucket: options?.bucket || this.#defaultBucket, - Key: key, - }), - response = await this.#client.send(command); + // Download via IPFS Gateway if Setup or S3 by Default + if (typeof this.#gatewayConfiguration.endpoint === "string") { + const objectToFetch = await this.get(key, options); + return objectToFetch.download(); + } else { + const command = new GetObjectCommand({ + Bucket: options?.bucket || this.#defaultBucket, + Key: key, + }), + response = await this.#client.send(command); - return response.Body; + return response.Body; + } } /** diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 17ef4be..5ec281e 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -41,12 +41,7 @@ async function uploadObject(bucket, key, body) { await objectManager.upload(key, body); // Confirm Object Uploaded - const objectsList = await objectManager.list({ - Prefix: key, - MaxKeys: 1, - }), - uploadedObject = - objectsList.Contents.length > 0 ? objectsList.Contents[0] : undefined; + const uploadedObject = await objectManager.get(key); return typeof uploadedObject !== "undefined"; } @@ -104,15 +99,8 @@ test("delete object", async () => { await objectManager.delete(objectNameToCreate); // List bucket and assert new object doesn't exist - const existingObjects = await objectManager.list({ - Prefix: objectNameToCreate, - MaxKeys: 1, - }), - uploadedObject = - existingObjects.Contents.length > 0 - ? existingObjects.Contents[0] - : undefined; - assert.equal(typeof uploadedObject, "undefined"); + const uploadedObject = await objectManager.get(objectNameToCreate); + assert.equal(uploadedObject, false); } finally { await deleteBucket(deleteTestBucket); } @@ -207,6 +195,46 @@ test("download object", async () => { } }); +test("download object using gateway", async () => { + // Create bucket `download-object-test-pass` + const downloadTestBucket = `${TEST_PREFIX}-download-object-test-pass`; + await createBucket(downloadTestBucket); + + try { + // Upload object `download-object-test` + const objectNameToCreate = `download-object-test`; + const uploaded = await uploadObject( + downloadTestBucket, + objectNameToCreate, + Buffer.from("download object", "utf-8"), + ); + if (uploaded === false) { + throw Error(`Failed to create object [download-object-test]`); + } + + try { + // Download object `download-object-test` and assert it completes + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + { + bucket: downloadTestBucket, + gateway: { endpoint: process.env.TEST_IPFS_GATEWAY }, + }, + ); + const downloadStream = await objectManager.download(objectNameToCreate), + downloadFilename = uuidv4(), + downloadPath = Path.resolve(os.tmpdir(), downloadFilename), + writeFileResult = await writeFile(downloadPath, downloadStream); + assert.strictEqual(typeof writeFileResult, "undefined"); + } finally { + await deleteObject(downloadTestBucket, objectNameToCreate); + } + } finally { + await deleteBucket(downloadTestBucket); + } +}); + test("list objects", async () => { // Create bucket `list-objects-test-pass` const listTestBucket = `${TEST_PREFIX}-list-objects-test-pass`; From c6ede7b40fb8d1093857071715f86f6676ad019b Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:16:12 -0600 Subject: [PATCH 61/79] Fixup Docs --- src/gatewayManager.js | 2 +- src/objectManager.js | 16 ++++++++++------ src/pinManager.js | 42 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/gatewayManager.js b/src/gatewayManager.js index 0b86366..f816866 100644 --- a/src/gatewayManager.js +++ b/src/gatewayManager.js @@ -48,7 +48,7 @@ class GatewayManager { */ /** - * + * @summary Creates a gateway with the given name and options * @param {string} name Unique name across entire platform for the gateway. Must be a valid subdomain name. * @param {gatewayOptions} [options] * @returns {Promise} - A promise that resolves to the value of a gateway. diff --git a/src/objectManager.js b/src/objectManager.js index ddcb72b..78dc9d3 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -19,7 +19,6 @@ import os from "node:os"; import path from "node:path"; import { Readable } from "node:stream"; import { v4 as uuidv4 } from "uuid"; -import PinManager from "./pinManager.js"; import { downloadFromGateway } from "./helpers.js"; /** Interacts with an S3 client to perform various operations on objects in a bucket. */ @@ -28,9 +27,6 @@ class ObjectManager { #DEFAULT_REGION = "us-east-1"; #DEFAULT_MAX_CONCURRENT_UPLOADS = 4; - #DEFAULT_GATEWAY = "https://ipfs.filebase.io"; - #DEFAULT_TIMEOUT = 60000; - #client; #credentials; #defaultBucket; @@ -60,7 +56,11 @@ class ObjectManager { * import { ObjectManager } from "@filebase/sdk"; * const objectManager = new ObjectManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD", { * bucket: "my-default-bucket", - * maxConcurrentUploads: 4 + * maxConcurrentUploads: 4, + * gateway: { + * endpoint: "https://my-default-gateway.mydomain.com + * token: SUPER_SECRET_GATEWAY_TOKEN + * } * }); */ constructor(clientKey, clientSecret, options) { @@ -88,7 +88,7 @@ class ObjectManager { this.#gatewayConfiguration = { endpoint: options?.gateway?.endpoint, token: options?.gateway?.token, - timeout: options?.gateway?.timeout || this.#DEFAULT_TIMEOUT, + timeout: options?.gateway?.timeout, }; } @@ -123,6 +123,10 @@ class ObjectManager { * @example * // Upload Object * await objectManager.upload("my-object", Buffer.from("Hello World!")); + * // Upload Object with Metadata + * await objectManager.upload("my-custom-object", Buffer.from("Hello Big World!"), { + * "application": "my-filebase-app" + * }); * // Upload Directory * await objectManager.upload("my-first-directory", [ * { diff --git a/src/pinManager.js b/src/pinManager.js index 29e79b7..1f18a3e 100644 --- a/src/pinManager.js +++ b/src/pinManager.js @@ -101,10 +101,15 @@ class PinManager { */ /** - * + * @summary List the pins in a given bucket * @param {listPinOptions} [listOptions] * @param {pinOptions} [options] * @returns {Promise} + * @example + * // List pins in bucket with a limit of 1000 + * await pinManager.list({ + * limit: 1000 + * }); */ async list(listOptions, options) { const encodedToken = this.#getEncodedToken(options?.bucket), @@ -122,12 +127,17 @@ class PinManager { } /** - * + * @summary Create a pin in the selected bucket * @param {string} key Key or path of the file in the bucket * @param {string} cid Content Identifier (CID) to be pinned recursively * @param {Object} [metadata] Optional metadata for pin object * @param {pinOptions} [options] Options for pinning the object * @returns {Promise} + * @example + * // Create Pin with Metadata + * await pinManager.create("my-pin", "QmTJkc7crTuPG7xRmCQSz1yioBpCW3juFBtJPXhQfdCqGF", { + * "application": "my-custom-app-on-filebase" + * } */ async create(key, cid, metadata, options) { const encodedToken = this.#getEncodedToken(options?.bucket), @@ -146,6 +156,19 @@ class PinManager { return pinStatus.data; } + /** + * @summary Replace a pinned object in the selected bucket + * @param {string} requestid Unique ID for the pinned object + * @param {string} cid Content Identifier (CID) to be pinned recursively + * @param {Object} [metadata] Optional metadata for pin object + * @param {pinOptions} [options] Options for pinning the object + * @returns {Promise} + * @example + * // Replace Pin with Metadata + * await pinManager.create("qr4231213", "QmTJkc7crTuPG7xRmCQSz1yioBpCW3juFBtJPXhQfdCqGF", { + * "revision": Date.now() + * } + */ async replace(requestid, cid, metadata, options) { const encodedToken = this.#getEncodedToken(options?.bucket), pinStatusResult = await this.#client.request({ @@ -171,10 +194,13 @@ class PinManager { } /** - * + * @summary Download a pin from the selected IPFS gateway * @param {string} cid * @param {pinDownloadOptions} [options] * @returns {Promise} + * @example + * // Download Pin by CID + * await pinManager.download("QmTJkc7crTuPG7xRmCQSz1yioBpCW3juFBtJPXhQfdCqGF"); */ async download(cid, options) { const downloadOptions = Object.assign(this.#gatewayConfiguration, options); @@ -182,10 +208,13 @@ class PinManager { } /** - * + * @summary Get details about a pinned object * @param {string} requestid Globally unique identifier of the pin request * @param {pinOptions} [options] Options for getting the pin * @returns {Promise} + * @example + * // Get Pin Info by RequestId + * await pinManager.get("qr4231214"); */ async get(requestid, options) { const encodedToken = this.#getEncodedToken(options?.bucket), @@ -208,10 +237,13 @@ class PinManager { } /** - * + * @summary Delete a pinned object from the selected bucket * @param requestid Globally unique identifier of the pin request * @param {pinOptions} [options] Options for deleting the pin * @returns {Promise} + * @example + * // Delete Pin by RequestId + * await pinManager.delete("qr4231213"); */ async delete(requestid, options) { const encodedToken = this.#getEncodedToken(options?.bucket), From 6e896cd4137d906869bec94dabada32306883746 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 18 Dec 2023 12:24:22 -0600 Subject: [PATCH 62/79] Add Tutorials --- jsdoc.json | 1 + readme.md | 69 +++++++++---------------------- src/bucketManager.js | 1 + src/gatewayManager.js | 1 + src/nameManager.js | 1 + src/objectManager.js | 1 + src/pinManager.js | 3 +- tutorials/quickstart-bucket.json | 3 ++ tutorials/quickstart-bucket.md | 21 ++++++++++ tutorials/quickstart-gateway.json | 3 ++ tutorials/quickstart-gateway.md | 29 +++++++++++++ tutorials/quickstart-name.json | 3 ++ tutorials/quickstart-name.md | 33 +++++++++++++++ tutorials/quickstart-object.json | 3 ++ tutorials/quickstart-object.md | 22 ++++++++++ tutorials/quickstart-pin.json | 3 ++ tutorials/quickstart-pin.md | 13 ++++++ 17 files changed, 159 insertions(+), 51 deletions(-) create mode 100644 tutorials/quickstart-bucket.json create mode 100644 tutorials/quickstart-bucket.md create mode 100644 tutorials/quickstart-gateway.json create mode 100644 tutorials/quickstart-gateway.md create mode 100644 tutorials/quickstart-name.json create mode 100644 tutorials/quickstart-name.md create mode 100644 tutorials/quickstart-object.json create mode 100644 tutorials/quickstart-object.md create mode 100644 tutorials/quickstart-pin.json create mode 100644 tutorials/quickstart-pin.md diff --git a/jsdoc.json b/jsdoc.json index 92a6417..1339bde 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -12,6 +12,7 @@ "opts": { "template": "node_modules/clean-jsdoc-theme", "recurse": true, + "tutorials": "./tutorials", "destination": "./documentation/", "readme": "./readme.md", "theme_opts": { diff --git a/readme.md b/readme.md index 40544f0..100306e 100644 --- a/readme.md +++ b/readme.md @@ -37,51 +37,30 @@ To use the library in your project, use npm or yarn to install the [`@filebase/s **node.js** ````js // Import Classes -import {BucketManager, ObjectManager, NameManager, GatewayManager} from 'filebase-sdk' +import {BucketManager, ObjectManager, NameManager, GatewayManager, PinManager} from 'filebase-sdk' // Initialize BucketManager const bucketManager = new BucketManager(S3_KEY, S3_SECRET); // Create bucket const bucketName = `create-bucket-[random string]`; await bucketManager.create(bucketName); -// List buckets -const bucketsList = await bucketManager.list(); -// Toggle bucket privacy off -await bucketManager.setPrivacy(bucketName, false); -console.dir(bucketsList); // Initialize ObjectManager -const objectManager = new ObjectManager(S3_KEY, S3_SECRET, bucketName); +const objectManager = new ObjectManager(S3_KEY, S3_SECRET, { + bucket: bucketName +}); // Upload Object const objectName = `new-object`; const uploadedObject = await objectManager.upload(objectName, body); -// Confirm Object Uploaded -const objectsList = await objectManager.list({ - Prefix: key, - MaxKeys: 1, - }); -console.dir(objectsList) +// Download Object +await uploadedObject.download(); // Initialize NameManager const nameManager = new NameManager(S3_KEY, S3_SECRET); // Create New IPNS Name with Broadcast Disabled -const ipnsName = await nameManager.create(`myFirstIpnsKey`, uploadedObject.cid, { - enabled: true -}); -// Update IPNS Value and Optionally Enable the Broadcast const ipnsLabel = `myFirstIpnsKey`; -await nameManager.set(ipnsLabel, uploadedObject.cid, { - enabled: true, -}); -// Enable IPNS Broadcast without updating the IPNS Record -await nameManager.toggle(ipnsLabel, true); -// List IPNS Names -const myIpnsNames = await nameManager.list(); -// List Specific IPNS Name -const myIpnsName = await nameManager.list(ipnsLabel); -// Import IPNS Name -const myImportedIpnsName = await nameManager.import(ipnsLabel, uploadedObject.cid, Base64EncodedPrivateKey, { - enabled: false, +const ipnsName = await nameManager.create(ipnsLabel, uploadedObject.cid, { + enabled: true }); // Initialize GatewayManager @@ -89,28 +68,18 @@ const gatewayManager = new GatewayManager(S3_KEY, S3_SECRET); // Create New Gateway const gatewayName = "myRandomGatewayName"; const myGateway = await gatewayManager.create(gatewayName); -// Get Gateway Setup -const gatewayConfig = await gatewayManager.get(gatewayName); -// List IPFS Gateways -const myGateways = await gatewayManager.list(); -// Update Gateway -const myUpdatedGateway = await gatewayManager.update(gatewayName, { - enabled: false -}); -// Toggle Gateway State -await gatewayManager.toggle(gatewayName, true) -// Delete Object -await objectManager.delete(objectName); - -// Delete Bucket -await bucketManager.delete(bucketName); - -// Delete Name -await nameManager.delete(ipnsLabel); - -// Delete Gateway -await gatewayManager.delete(gatewayName); +// Initialize PinManager +const pinManager = new PinManager(S3_KEY, S3_SECRET, { + bucket: bucketName, + gateway: { + endpoint: "https://myRandomGatewayName.myfilebase.com" + } +}); +// Create New Pin with Metadata +const myNewPin = await pinManager.create("my-pin", "QmTJkc7crTuPG7xRmCQSz1yioBpCW3juFBtJPXhQfdCqGF", { + "application": "my-custom-app-on-filebase" +}); ```` Full API reference doc for the JS client are available at https://filebase.github.io/filebase-sdk diff --git a/src/bucketManager.js b/src/bucketManager.js index fac3736..adddb63 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -18,6 +18,7 @@ class BucketManager { * @summary Creates a new instance of the constructor. * @param {string} clientKey - The access key ID for authentication. * @param {string} clientSecret - The secret access key for authentication. + * @tutorial quickstart-bucket * @example * import { BucketManager } from "@filebase/sdk"; * const bucketManager = new BucketManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD"); diff --git a/src/gatewayManager.js b/src/gatewayManager.js index f816866..b639bc3 100644 --- a/src/gatewayManager.js +++ b/src/gatewayManager.js @@ -10,6 +10,7 @@ class GatewayManager { * @summary Creates a new instance of the constructor. * @param {string} clientKey - The access key ID for authentication. * @param {string} clientSecret - The secret access key for authentication. + * @tutorial quickstart-gateway * @example * import { GatewayManager } from "@filebase/sdk"; * const gatewayManager = new GatewayManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD"); diff --git a/src/nameManager.js b/src/nameManager.js index fbf4662..4628168 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -11,6 +11,7 @@ class NameManager { * @summary Creates a new instance of the constructor. * @param {string} clientKey - The access key ID for authentication. * @param {string} clientSecret - The secret access key for authentication. + * @tutorial quickstart-name * @example * import { NameManager } from "@filebase/sdk"; * const nameManager = new NameManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD"); diff --git a/src/objectManager.js b/src/objectManager.js index 78dc9d3..581dee8 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -52,6 +52,7 @@ class ObjectManager { * @param {string} clientKey - The access key ID for authentication. * @param {string} clientSecret - The secret access key for authentication. * @param {objectManagerOptions} options - Optional settings for the constructor. + * @tutorial quickstart-object * @example * import { ObjectManager } from "@filebase/sdk"; * const objectManager = new ObjectManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD", { diff --git a/src/pinManager.js b/src/pinManager.js index 1f18a3e..cfeabbf 100644 --- a/src/pinManager.js +++ b/src/pinManager.js @@ -29,6 +29,7 @@ class PinManager { * @param {string} clientKey - The access key ID for authentication. * @param {string} clientSecret - The secret access key for authentication. * @param {pinManagerOptions} [options] - Optional settings for the constructor. + * @tutorial quickstart-pin * @example * import { PinManager } from "@filebase/sdk"; * const pinManager = new PinManager("KEY_FROM_DASHBOARD", "SECRET_FROM_DASHBOARD", { @@ -137,7 +138,7 @@ class PinManager { * // Create Pin with Metadata * await pinManager.create("my-pin", "QmTJkc7crTuPG7xRmCQSz1yioBpCW3juFBtJPXhQfdCqGF", { * "application": "my-custom-app-on-filebase" - * } + * }); */ async create(key, cid, metadata, options) { const encodedToken = this.#getEncodedToken(options?.bucket), diff --git a/tutorials/quickstart-bucket.json b/tutorials/quickstart-bucket.json new file mode 100644 index 0000000..28c9622 --- /dev/null +++ b/tutorials/quickstart-bucket.json @@ -0,0 +1,3 @@ +{ + "title": "Buckets" +} \ No newline at end of file diff --git a/tutorials/quickstart-bucket.md b/tutorials/quickstart-bucket.md new file mode 100644 index 0000000..f6de811 --- /dev/null +++ b/tutorials/quickstart-bucket.md @@ -0,0 +1,21 @@ +**node.js** +````js +// Import Classes +import {BucketManager} from 'filebase-sdk' + +// Initialize BucketManager +const bucketManager = new BucketManager(S3_KEY, S3_SECRET); + +// Create bucket +const bucketName = `create-bucket-[random string]`; +await bucketManager.create(bucketName); + +// List buckets +const bucketsList = await bucketManager.list(); + +// Toggle bucket privacy off +await bucketManager.setPrivacy(bucketName, false); +console.dir(bucketsList); + +// Delete Bucket +await bucketManager.delete(bucketName); \ No newline at end of file diff --git a/tutorials/quickstart-gateway.json b/tutorials/quickstart-gateway.json new file mode 100644 index 0000000..bcccf6c --- /dev/null +++ b/tutorials/quickstart-gateway.json @@ -0,0 +1,3 @@ +{ + "title": "Gateways" +} \ No newline at end of file diff --git a/tutorials/quickstart-gateway.md b/tutorials/quickstart-gateway.md new file mode 100644 index 0000000..679c987 --- /dev/null +++ b/tutorials/quickstart-gateway.md @@ -0,0 +1,29 @@ +**node.js** +````js +// Initialize GatewayManager +const gatewayManager = new GatewayManager(S3_KEY, S3_SECRET); + +// Create New Gateway with a custom domain of `cname.mycustomdomain.com`. +// The custom domain must already exist and have a CNAME record pointed at `myRandomGatewayName.myfilebase.com`. +const gatewayName = "myRandomGatewayName"; +const myGateway = await gatewayManager.create(gatewayName); +await gatewayManager.create(gatewayname, { + domain: `cname.mycustomdomain.com` +}); + +// Get Gateway Setup +const gatewayConfig = await gatewayManager.get(gatewayName); + +// List IPFS Gateways +const myGateways = await gatewayManager.list(); + +// Update Gateway +const myUpdatedGateway = await gatewayManager.update(gatewayName, { + enabled: false +}); + +// Toggle Gateway State +await gatewayManager.toggle(gatewayName, true) + +// Delete Gateway +await gatewayManager.delete(gatewayName); \ No newline at end of file diff --git a/tutorials/quickstart-name.json b/tutorials/quickstart-name.json new file mode 100644 index 0000000..13711de --- /dev/null +++ b/tutorials/quickstart-name.json @@ -0,0 +1,3 @@ +{ + "title": "Names" +} \ No newline at end of file diff --git a/tutorials/quickstart-name.md b/tutorials/quickstart-name.md new file mode 100644 index 0000000..441683b --- /dev/null +++ b/tutorials/quickstart-name.md @@ -0,0 +1,33 @@ +**node.js** +````js +// Initialize NameManager +const nameManager = new NameManager(S3_KEY, S3_SECRET); + +// Create New IPNS Name with Broadcast Disabled +const ipnsCid = "QmZqkuqX1qTspb1GgmnzyRFetf1uMyA3CemvvgPZD39sPo"; +const ipnsName = await nameManager.create(`myFirstIpnsKey`, ipnsCid, { + enabled: true +}); + +// Update IPNS Value and Optionally Enable the Broadcast +const ipnsLabel = `myFirstIpnsKey`; +await nameManager.set(ipnsLabel, ipnsCid, { + enabled: true, +}); + +// Enable IPNS Broadcast without updating the IPNS Record +await nameManager.toggle(ipnsLabel, true); + +// List IPNS Names +const myIpnsNames = await nameManager.list(); + +// List Specific IPNS Name +const myIpnsName = await nameManager.list(ipnsLabel); + +// Import IPNS Name +const myImportedIpnsName = await nameManager.import(ipnsLabel, ipnsCid, Base64EncodedPrivateKey, { + enabled: false, +}); + +// Delete Name +await nameManager.delete(ipnsLabel); \ No newline at end of file diff --git a/tutorials/quickstart-object.json b/tutorials/quickstart-object.json new file mode 100644 index 0000000..7088f34 --- /dev/null +++ b/tutorials/quickstart-object.json @@ -0,0 +1,3 @@ +{ + "title": "Objects" +} \ No newline at end of file diff --git a/tutorials/quickstart-object.md b/tutorials/quickstart-object.md new file mode 100644 index 0000000..746468b --- /dev/null +++ b/tutorials/quickstart-object.md @@ -0,0 +1,22 @@ +**node.js** +````js +// Import Classes +import {ObjectManager} from 'filebase-sdk' + +// Initialize ObjectManager +const bucketName = `create-object-[random string]`; +const objectManager = new ObjectManager(S3_KEY, S3_SECRET, bucketName); + +// Upload Object +const objectName = `new-object`; +const uploadedObject = await objectManager.upload(objectName, body); + +// Confirm Object Uploaded +const objectsList = await objectManager.list({ + Prefix: key, + MaxKeys: 1, +}); +console.dir(objectsList) + +// Delete Object +await objectManager.delete(objectName); \ No newline at end of file diff --git a/tutorials/quickstart-pin.json b/tutorials/quickstart-pin.json new file mode 100644 index 0000000..b0363b1 --- /dev/null +++ b/tutorials/quickstart-pin.json @@ -0,0 +1,3 @@ +{ + "title": "Pins" +} \ No newline at end of file diff --git a/tutorials/quickstart-pin.md b/tutorials/quickstart-pin.md new file mode 100644 index 0000000..832a999 --- /dev/null +++ b/tutorials/quickstart-pin.md @@ -0,0 +1,13 @@ +**node.js** +````js +// Initialize PinManager +const pinManager = new PinManager(S3_KEY, S3_SECRET, { + bucket: bucketName, + gateway: { + endpoint: "https://myRandomGatewayName.myfilebase.com" + } +}); +// Create New Pin with Metadata +const myNewPin = await pinManager.create("my-pin", "QmTJkc7crTuPG7xRmCQSz1yioBpCW3juFBtJPXhQfdCqGF", { + "application": "my-custom-app-on-filebase" +}); \ No newline at end of file From 3b9ff3161b2b60ed33c3e0436cb7b2e8fbf1a5b6 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 18 Dec 2023 13:48:18 -0600 Subject: [PATCH 63/79] Update pinManager.spec.js Add gateway to pinManager test --- test/pinManager.spec.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/pinManager.spec.js b/test/pinManager.spec.js index ac07d6a..26121a0 100644 --- a/test/pinManager.spec.js +++ b/test/pinManager.spec.js @@ -40,9 +40,6 @@ test("replace pin", async () => { const replacedPin = await pinManager.replace( createdPin.requestid, TEST_CID_2, - { - updatedByApp: Date.now(), - }, ); assert.strictEqual(replacedPin.requestid, createdPin.requestid); assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); @@ -78,6 +75,9 @@ test("download pin", async () => { process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { bucket: TEST_BUCKET, + gateway: { + endpoint: process.env.TEST_IPFS_GATEWAY, + }, }, ); const createdPin = await pinManager.create(testPinName, TEST_CID_1); @@ -96,6 +96,9 @@ test("download pin by reference", async () => { process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { bucket: TEST_BUCKET, + gateway: { + endpoint: process.env.TEST_IPFS_GATEWAY, + }, }, ); const createdPin = await pinManager.create(testPinName, TEST_CID_1); From cbf2f2e84968068d7af274f4f8fe032157852a2f Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:27:31 -0600 Subject: [PATCH 64/79] Update Tests --- .github/workflows/test.yml | 2 +- src/gatewayManager.js | 2 +- src/nameManager.js | 2 +- src/pinManager.js | 61 ++++++++++++++++++++++++-------------- test/pinManager.spec.js | 20 ++++++------- 5 files changed, 50 insertions(+), 37 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 99655cf..80e8a31 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: with: node-version: '20.x' - run: npm ci - - run: npm test --test-concurrency=1 + - run: npm test --test-concurrency 1 env: TEST_KEY: ${{ secrets.TEST_S3_KEY }} TEST_SECRET: ${{ secrets.TEST_S3_SECRET }} diff --git a/src/gatewayManager.js b/src/gatewayManager.js index b639bc3..6441391 100644 --- a/src/gatewayManager.js +++ b/src/gatewayManager.js @@ -93,7 +93,7 @@ class GatewayManager { method: "DELETE", url: `/${name}`, validateStatus: (status) => { - return status === 202 || status === 404; + return status === 204 || status === 404; }, }); if (deleteResponse.status === 404) { diff --git a/src/nameManager.js b/src/nameManager.js index 4628168..f0823e7 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -191,7 +191,7 @@ class NameManager { method: "DELETE", url: `/${label}`, validateStatus: (status) => { - return status === 202 || status === 404; + return status === 204 || status === 404; }, }); if (deleteResult.status === 404) { diff --git a/src/pinManager.js b/src/pinManager.js index cfeabbf..630a690 100644 --- a/src/pinManager.js +++ b/src/pinManager.js @@ -157,12 +157,18 @@ class PinManager { return pinStatus.data; } + /** + * @typedef {Object} replacePinOptions + * @augments pinOptions + * @property {Object} [metadata] Optional metadata to set on pin during replacement + * @property {string} [name] Optional name for pin to set during replacement + */ + /** * @summary Replace a pinned object in the selected bucket * @param {string} requestid Unique ID for the pinned object * @param {string} cid Content Identifier (CID) to be pinned recursively - * @param {Object} [metadata] Optional metadata for pin object - * @param {pinOptions} [options] Options for pinning the object + * @param {replacePinOptions} [options] Options for pinning the object * @returns {Promise} * @example * // Replace Pin with Metadata @@ -170,28 +176,37 @@ class PinManager { * "revision": Date.now() * } */ - async replace(requestid, cid, metadata, options) { - const encodedToken = this.#getEncodedToken(options?.bucket), - pinStatusResult = await this.#client.request({ - method: "POST", - url: requestid, - data: { - cid, - meta: metadata, - }, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - headers: { Authorization: `Bearer ${encodedToken}` }, - }); - if (pinStatusResult.status === 404) { - throw new Error(`Could not find matching requestid`); + async replace(requestid, cid, options) { + try { + let replaceData = { + cid, + meta: options?.metadata || {}, + }; + if (options?.name) { + replaceData.name = options.name; + } + + const encodedToken = this.#getEncodedToken(options?.bucket), + pinStatusResult = await this.#client.request({ + method: "POST", + url: `/${requestid}`, + data: replaceData, + validateStatus: (status) => { + return status === 200 || status === 404; + }, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + if (pinStatusResult.status === 404) { + throw new Error(`Could not find matching requestid`); + } + const pinStatus = pinStatusResult.data; + pinStatus.download = () => { + return this.download(pinStatus.pin.cid); + }; + return pinStatus; + } catch (err) { + throw err; } - const pinStatus = pinStatusResult; - pinStatus.download = () => { - return this.download(pinStatus.pin.cid); - }; - return pinStatus; } /** diff --git a/test/pinManager.spec.js b/test/pinManager.spec.js index 26121a0..d594ef5 100644 --- a/test/pinManager.spec.js +++ b/test/pinManager.spec.js @@ -5,7 +5,6 @@ import { v4 as uuidv4 } from "uuid"; import Path from "node:path"; import os from "node:os"; import { writeFile } from "node:fs/promises"; -import pinManager from "../src/pinManager.js"; const TEST_BUCKET = "pinning-test", TEST_CID_1 = "QmSEu6zGwKgkQA3ZKaDnvkrwre1kkQa7eRFCbQi7waNwTT", @@ -36,16 +35,15 @@ test("replace pin", async () => { ); const createdPin = await pinManager.create(testPinName, TEST_CID_1); assert.strictEqual(createdPin.pin.cid, TEST_CID_1); - try { - const replacedPin = await pinManager.replace( - createdPin.requestid, - TEST_CID_2, - ); - assert.strictEqual(replacedPin.requestid, createdPin.requestid); - assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); - } finally { - await pinManager.delete(createdPin.requestid); - } + const replacedPin = await pinManager.replace( + createdPin.requestid, + TEST_CID_2, + { + name: `${testPinName}-replaced`, + }, + ); + assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); + await pinManager.delete(replacedPin.requestid); }); test("get pin", async () => { From 42ac8182a121fdf5f34e22dcbac1f2c3c5b5a9a8 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:28:56 -0600 Subject: [PATCH 65/79] Update test.yml --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 80e8a31..2dc38c9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: with: node-version: '20.x' - run: npm ci - - run: npm test --test-concurrency 1 + - run: node --test --test-concurrency 1 env: TEST_KEY: ${{ secrets.TEST_S3_KEY }} TEST_SECRET: ${{ secrets.TEST_S3_SECRET }} From f1c6d13d899265f041c60c632f70f5aeffa133d6 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 19 Dec 2023 10:52:10 -0600 Subject: [PATCH 66/79] Cleanup for Replace Fix --- src/pinManager.js | 52 +++++++++++++++++++--------------------- test/nameManager.spec.js | 2 -- test/pinManager.spec.js | 21 +++++++++++++++- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/pinManager.js b/src/pinManager.js index 630a690..be423de 100644 --- a/src/pinManager.js +++ b/src/pinManager.js @@ -177,36 +177,32 @@ class PinManager { * } */ async replace(requestid, cid, options) { - try { - let replaceData = { - cid, - meta: options?.metadata || {}, - }; - if (options?.name) { - replaceData.name = options.name; - } + let replaceData = { + cid, + meta: options?.metadata || {}, + }; + if (options?.name) { + replaceData.name = options.name; + } - const encodedToken = this.#getEncodedToken(options?.bucket), - pinStatusResult = await this.#client.request({ - method: "POST", - url: `/${requestid}`, - data: replaceData, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - headers: { Authorization: `Bearer ${encodedToken}` }, - }); - if (pinStatusResult.status === 404) { - throw new Error(`Could not find matching requestid`); - } - const pinStatus = pinStatusResult.data; - pinStatus.download = () => { - return this.download(pinStatus.pin.cid); - }; - return pinStatus; - } catch (err) { - throw err; + const encodedToken = this.#getEncodedToken(options?.bucket), + pinStatusResult = await this.#client.request({ + method: "POST", + url: `/${requestid}`, + data: replaceData, + validateStatus: (status) => { + return status === 200 || status === 404; + }, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + if (pinStatusResult.status === 404) { + throw new Error(`Could not find matching requestid`); } + const pinStatus = pinStatusResult.data; + pinStatus.download = () => { + return this.download(pinStatus.pin.cid); + }; + return pinStatus; } /** diff --git a/test/nameManager.spec.js b/test/nameManager.spec.js index 0124791..0b77658 100644 --- a/test/nameManager.spec.js +++ b/test/nameManager.spec.js @@ -113,8 +113,6 @@ test("toggle name on", async () => { assert.strictEqual(updatedName.label, testNameLabel); assert.strictEqual(updatedName.cid, TEST_CID); assert.strictEqual(updatedName.enabled, true); - } catch (err) { - console.error(err); } finally { await nameManager.delete(testNameLabel); } diff --git a/test/pinManager.spec.js b/test/pinManager.spec.js index d594ef5..3e2de41 100644 --- a/test/pinManager.spec.js +++ b/test/pinManager.spec.js @@ -24,7 +24,7 @@ test("create pin", async () => { assert.strictEqual(createdPin.pin.cid, TEST_CID_1); }); -test("replace pin", async () => { +test("replace pin with name", async () => { const testPinName = `${TEST_PREFIX}-replace-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, @@ -46,6 +46,25 @@ test("replace pin", async () => { await pinManager.delete(replacedPin.requestid); }); +test("replace pin without name", async () => { + const testPinName = `${TEST_PREFIX}-replace-pin-test-pass`, + pinManager = new PinManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + { + bucket: TEST_BUCKET, + }, + ); + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + const replacedPin = await pinManager.replace( + createdPin.requestid, + TEST_CID_2, + ); + assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); + await pinManager.delete(replacedPin.requestid); +}); + test("get pin", async () => { const testPinName = `${TEST_PREFIX}-get-pin-test-pass`, pinManager = new PinManager( From aea5bb104040edcdb389fabca16869b7132a84ec Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:07:25 -0600 Subject: [PATCH 67/79] Pinning Test Fix --- src/bucketManager.js | 1 + src/objectManager.js | 1 + test/pinManager.spec.js | 32 +++++++++++++++++++++++++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/bucketManager.js b/src/bucketManager.js index adddb63..e248ca3 100644 --- a/src/bucketManager.js +++ b/src/bucketManager.js @@ -35,6 +35,7 @@ class BucketManager { }, endpoint: clientEndpoint, region: this.#DEFAULT_REGION, + forcePathStyle: true, }; this.#client = new S3Client(clientConfiguration); } diff --git a/src/objectManager.js b/src/objectManager.js index 581dee8..9c441c7 100644 --- a/src/objectManager.js +++ b/src/objectManager.js @@ -76,6 +76,7 @@ class ObjectManager { }, endpoint: clientEndpoint, region: this.#DEFAULT_REGION, + forcePathStyle: true, }; this.#defaultBucket = options?.bucket; this.#maxConcurrentUploads = diff --git a/test/pinManager.spec.js b/test/pinManager.spec.js index 3e2de41..645a193 100644 --- a/test/pinManager.spec.js +++ b/test/pinManager.spec.js @@ -5,11 +5,25 @@ import { v4 as uuidv4 } from "uuid"; import Path from "node:path"; import os from "node:os"; import { writeFile } from "node:fs/promises"; +import BucketManager from "../src/bucketManager.js"; -const TEST_BUCKET = "pinning-test", - TEST_CID_1 = "QmSEu6zGwKgkQA3ZKaDnvkrwre1kkQa7eRFCbQi7waNwTT", +const TEST_CID_1 = "QmSEu6zGwKgkQA3ZKaDnvkrwre1kkQa7eRFCbQi7waNwTT", TEST_CID_2 = "QmNXcMdXadLRTxLpHJMsGnaeKz26d2F6NgUDVWScp54EfC", - TEST_PREFIX = Date.now(); + TEST_PREFIX = Date.now(), + TEST_BUCKET = `${TEST_PREFIX}-pinning-test`; + +async function ensureBucketExists(bucketName) { + try { + // Initialize BucketManager + const bucketManager = new BucketManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + ); + await bucketManager.create(bucketName); + } catch (err) { + console.log(`Bucket Already Exists`); + } +} test("create pin", async () => { const testPinName = `${TEST_PREFIX}-create-pin-test-pass`, @@ -20,6 +34,7 @@ test("create pin", async () => { bucket: TEST_BUCKET, }, ); + await ensureBucketExists(TEST_BUCKET); const createdPin = await pinManager.create(testPinName, TEST_CID_1); assert.strictEqual(createdPin.pin.cid, TEST_CID_1); }); @@ -33,6 +48,7 @@ test("replace pin with name", async () => { bucket: TEST_BUCKET, }, ); + await ensureBucketExists(TEST_BUCKET); const createdPin = await pinManager.create(testPinName, TEST_CID_1); assert.strictEqual(createdPin.pin.cid, TEST_CID_1); const replacedPin = await pinManager.replace( @@ -55,6 +71,7 @@ test("replace pin without name", async () => { bucket: TEST_BUCKET, }, ); + await ensureBucketExists(TEST_BUCKET); const createdPin = await pinManager.create(testPinName, TEST_CID_1); assert.strictEqual(createdPin.pin.cid, TEST_CID_1); const replacedPin = await pinManager.replace( @@ -74,6 +91,7 @@ test("get pin", async () => { bucket: TEST_BUCKET, }, ); + await ensureBucketExists(TEST_BUCKET); const createdPin = await pinManager.create(testPinName, TEST_CID_1); assert.strictEqual(createdPin.pin.cid, TEST_CID_1); try { @@ -97,6 +115,7 @@ test("download pin", async () => { }, }, ); + await ensureBucketExists(TEST_BUCKET); const createdPin = await pinManager.create(testPinName, TEST_CID_1); assert.strictEqual(createdPin.pin.cid, TEST_CID_1); const downloadStream = await pinManager.download(createdPin.pin.cid), @@ -118,6 +137,7 @@ test("download pin by reference", async () => { }, }, ); + await ensureBucketExists(TEST_BUCKET); const createdPin = await pinManager.create(testPinName, TEST_CID_1); assert.strictEqual(createdPin.pin.cid, TEST_CID_1); const pinToDownload = await pinManager.get(createdPin.requestid), @@ -136,8 +156,9 @@ test("list pins", async () => { { bucket: TEST_BUCKET, }, - ), - existingPinList = await pinManager.list(), + ); + await ensureBucketExists(TEST_BUCKET); + const existingPinList = await pinManager.list(), countToCreate = 25; let createdPins = []; for (let i = 0; i < countToCreate; i++) { @@ -164,6 +185,7 @@ test("delete pin", async () => { bucket: TEST_BUCKET, }, ); + await ensureBucketExists(TEST_BUCKET); const createdPin = await pinManager.create(testPinName, TEST_CID_1); assert.strictEqual(createdPin.pin.cid, TEST_CID_1); await pinManager.delete(createdPin.requestid); From 7055bf95b25fb8133b61022e776d7dfed5a7bc20 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:47:20 -0600 Subject: [PATCH 68/79] Update Test --- test/pinManager.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/pinManager.spec.js b/test/pinManager.spec.js index 645a193..4ef7e04 100644 --- a/test/pinManager.spec.js +++ b/test/pinManager.spec.js @@ -59,6 +59,7 @@ test("replace pin with name", async () => { }, ); assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); + assert.strictEqual(replacedPin.pin.name, `${testPinName}-replaced`); await pinManager.delete(replacedPin.requestid); }); @@ -78,6 +79,7 @@ test("replace pin without name", async () => { createdPin.requestid, TEST_CID_2, ); + assert.strictEqual(replacedPin.pin.name, testPinName); assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); await pinManager.delete(replacedPin.requestid); }); From 615efc558a5b4bb00c5c61554f012eee6daeccf4 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:55:34 -0600 Subject: [PATCH 69/79] Update objectManager.spec.js --- test/objectManager.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 59a9b3b..250f019 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -279,7 +279,7 @@ test("list objects", async () => { test("copy object", async () => { // Create bucket `copy-object-test-pass-src` - const bucketSrc = `copy-object-test-pass-src`; + const bucketSrc = `${TEST_PREFIX}-copy-object-test-pass-src`; await createBucket(bucketSrc); // Upload object `copy-object-test` @@ -292,7 +292,7 @@ test("copy object", async () => { assert.equal(uploaded, true); // Create bucket `copy-object-test-pass-dest` - const bucketDest = `copy-object-test-pass-dest`; + const bucketDest = `${TEST_PREFIX}-copy-object-test-pass-dest`; await createBucket(bucketDest); // Initialize ObjectManager From 108c9321fd4acebe893148e893bb13f6e2533d0e Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:07:49 -0600 Subject: [PATCH 70/79] Fix Copy Object Test --- test/objectManager.spec.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 250f019..1ed75dd 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -306,10 +306,6 @@ test("copy object", async () => { await objectManager.copy(objectNameToCreateSrc, bucketDest); // List bucket and assert new object exists - const existingObjects = await objectManager.list({ - Prefix: objectNameToCreateSrc, - MaxKeys: 1, - }), - copiedObject = existingObjects.length > 0 ? existingObjects[0] : undefined; - assert.equal(copiedObject.Name, objectNameToCreateSrc); + const copiedObject = await objectManager.get(objectNameToCreateSrc); + assert.equal(copiedObject.ETag, '"8605273d870f50fde0d8fbcad4a8f702"'); }); From 8de88a58f33abd99fe5303f6bf59313293644f1b Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 21 Dec 2023 10:19:55 -0600 Subject: [PATCH 71/79] Update readme.md --- readme.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 4ecc5f8..a8774c3 100644 --- a/readme.md +++ b/readme.md @@ -37,7 +37,13 @@ To use the library in your project, use npm or yarn to install the [`@filebase/s **node.js** ````js // Import Classes -import {BucketManager, ObjectManager, NameManager, GatewayManager, PinManager} from 'filebase-sdk' +import { + BucketManager, + ObjectManager, + NameManager, + GatewayManager, + PinManager +} from 'filebase-sdk' // Initialize BucketManager const bucketManager = new BucketManager(S3_KEY, S3_SECRET); From 8ab75dbed130d8b34e1d29253f33136dd76a0f1c Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 21 Dec 2023 10:37:42 -0600 Subject: [PATCH 72/79] Add License and Update package.json --- LICENSE | 19 ++ package-lock.json | 690 ++++++++++++++++++++++++---------------------- package.json | 25 +- 3 files changed, 381 insertions(+), 353 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..588ef6c --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) Filebase, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 61ccbe9..2c55b80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,14 +7,15 @@ "": { "name": "@filebase/sdk", "version": "1.0.0", + "license": "MIT", "dependencies": { - "@aws-sdk/client-s3": "3.454.0", - "@aws-sdk/lib-storage": "3.458.0", + "@aws-sdk/client-s3": "3.478.0", + "@aws-sdk/lib-storage": "3.478.0", "@helia/car": "1.0.4", - "@helia/unixfs": "1.4.2", + "@helia/unixfs": "1.4.3", "@ipld/car": "5.2.4", "axios": "1.6.2", - "blockstore-fs": "1.1.6", + "blockstore-fs": "1.1.8", "uuid": "9.0.1" }, "devDependencies": { @@ -158,65 +159,66 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-sdk/client-s3": { - "version": "3.454.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.454.0.tgz", - "integrity": "sha512-vBx4iB1c4mEz+twMnl6angC1/IpnmXaT8L6Kl9uNiurFsb6N4tCyrJ24kECdsOSTM7ePXvE1fKst8zAh6MW5ZA==", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.478.0.tgz", + "integrity": "sha512-OUpbCCnK71lQQ07BohJOx9ZER0rPqRAGOVIIVhNEkeN0uYFLzB7/o5a7+FEPUQXEd5rZRZgbxN5xEmnNW/0Waw==", "dependencies": { "@aws-crypto/sha1-browser": "3.0.0", "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.454.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/credential-provider-node": "3.451.0", - "@aws-sdk/middleware-bucket-endpoint": "3.451.0", - "@aws-sdk/middleware-expect-continue": "3.451.0", - "@aws-sdk/middleware-flexible-checksums": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-location-constraint": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-sdk-s3": "3.451.0", - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/middleware-ssec": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/signature-v4-multi-region": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@aws-sdk/xml-builder": "3.310.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/eventstream-serde-browser": "^2.0.13", - "@smithy/eventstream-serde-config-resolver": "^2.0.13", - "@smithy/eventstream-serde-node": "^2.0.13", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-blob-browser": "^2.0.14", - "@smithy/hash-node": "^2.0.15", - "@smithy/hash-stream-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/md5-js": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", + "@aws-sdk/client-sts": "3.478.0", + "@aws-sdk/core": "3.477.0", + "@aws-sdk/credential-provider-node": "3.478.0", + "@aws-sdk/middleware-bucket-endpoint": "3.470.0", + "@aws-sdk/middleware-expect-continue": "3.468.0", + "@aws-sdk/middleware-flexible-checksums": "3.468.0", + "@aws-sdk/middleware-host-header": "3.468.0", + "@aws-sdk/middleware-location-constraint": "3.468.0", + "@aws-sdk/middleware-logger": "3.468.0", + "@aws-sdk/middleware-recursion-detection": "3.468.0", + "@aws-sdk/middleware-sdk-s3": "3.474.0", + "@aws-sdk/middleware-signing": "3.468.0", + "@aws-sdk/middleware-ssec": "3.468.0", + "@aws-sdk/middleware-user-agent": "3.478.0", + "@aws-sdk/region-config-resolver": "3.470.0", + "@aws-sdk/signature-v4-multi-region": "3.474.0", + "@aws-sdk/types": "3.468.0", + "@aws-sdk/util-endpoints": "3.478.0", + "@aws-sdk/util-user-agent-browser": "3.468.0", + "@aws-sdk/util-user-agent-node": "3.470.0", + "@aws-sdk/xml-builder": "3.472.0", + "@smithy/config-resolver": "^2.0.21", + "@smithy/core": "^1.2.0", + "@smithy/eventstream-serde-browser": "^2.0.15", + "@smithy/eventstream-serde-config-resolver": "^2.0.15", + "@smithy/eventstream-serde-node": "^2.0.15", + "@smithy/fetch-http-handler": "^2.3.1", + "@smithy/hash-blob-browser": "^2.0.16", + "@smithy/hash-node": "^2.0.17", + "@smithy/hash-stream-node": "^2.0.17", + "@smithy/invalid-dependency": "^2.0.15", + "@smithy/md5-js": "^2.0.17", + "@smithy/middleware-content-length": "^2.0.17", + "@smithy/middleware-endpoint": "^2.2.3", + "@smithy/middleware-retry": "^2.0.24", + "@smithy/middleware-serde": "^2.0.15", + "@smithy/middleware-stack": "^2.0.9", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/node-http-handler": "^2.2.1", + "@smithy/protocol-http": "^3.0.11", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", + "@smithy/url-parser": "^2.0.15", "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.1", "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-stream": "^2.0.20", + "@smithy/util-defaults-mode-browser": "^2.0.22", + "@smithy/util-defaults-mode-node": "^2.0.29", + "@smithy/util-endpoints": "^1.0.7", + "@smithy/util-retry": "^2.0.8", + "@smithy/util-stream": "^2.0.23", "@smithy/util-utf8": "^2.0.2", - "@smithy/util-waiter": "^2.0.13", + "@smithy/util-waiter": "^2.0.15", "fast-xml-parser": "4.2.5", "tslib": "^2.5.0" }, @@ -225,44 +227,45 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.451.0.tgz", - "integrity": "sha512-KkYSke3Pdv3MfVH/5fT528+MKjMyPKlcLcd4zQb0x6/7Bl7EHrPh1JZYjzPLHelb+UY5X0qN8+cb8iSu1eiwIQ==", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.478.0.tgz", + "integrity": "sha512-Jxy9cE1JMkPR0PklCpq3cORHnZq/Z4klhSTNGgZNeBWovMa+plor52kyh8iUNHKl3XEJvTbHM7V+dvrr/x0P1g==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", + "@aws-sdk/core": "3.477.0", + "@aws-sdk/middleware-host-header": "3.468.0", + "@aws-sdk/middleware-logger": "3.468.0", + "@aws-sdk/middleware-recursion-detection": "3.468.0", + "@aws-sdk/middleware-user-agent": "3.478.0", + "@aws-sdk/region-config-resolver": "3.470.0", + "@aws-sdk/types": "3.468.0", + "@aws-sdk/util-endpoints": "3.478.0", + "@aws-sdk/util-user-agent-browser": "3.468.0", + "@aws-sdk/util-user-agent-node": "3.470.0", + "@smithy/config-resolver": "^2.0.21", + "@smithy/core": "^1.2.0", + "@smithy/fetch-http-handler": "^2.3.1", + "@smithy/hash-node": "^2.0.17", + "@smithy/invalid-dependency": "^2.0.15", + "@smithy/middleware-content-length": "^2.0.17", + "@smithy/middleware-endpoint": "^2.2.3", + "@smithy/middleware-retry": "^2.0.24", + "@smithy/middleware-serde": "^2.0.15", + "@smithy/middleware-stack": "^2.0.9", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/node-http-handler": "^2.2.1", + "@smithy/protocol-http": "^3.0.11", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", + "@smithy/url-parser": "^2.0.15", "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.1", "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", + "@smithy/util-defaults-mode-browser": "^2.0.22", + "@smithy/util-defaults-mode-node": "^2.0.29", + "@smithy/util-endpoints": "^1.0.7", + "@smithy/util-retry": "^2.0.8", "@smithy/util-utf8": "^2.0.2", "tslib": "^2.5.0" }, @@ -271,47 +274,47 @@ } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.454.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.454.0.tgz", - "integrity": "sha512-0fDvr8WeB6IYO8BUCzcivWmahgGl/zDbaYfakzGnt4mrl5ztYaXE875WI6b7+oFcKMRvN+KLvwu5TtyFuNY+GQ==", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.478.0.tgz", + "integrity": "sha512-D+QID0dYzmn9dcxgKP3/nMndUqiQbDLsqI0Zf2pG4MW5gPhVNKlDGIV3Ztz8SkMjzGJExNOLW2L569o8jshJVw==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/credential-provider-node": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-sdk-sts": "3.451.0", - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", + "@aws-sdk/core": "3.477.0", + "@aws-sdk/credential-provider-node": "3.478.0", + "@aws-sdk/middleware-host-header": "3.468.0", + "@aws-sdk/middleware-logger": "3.468.0", + "@aws-sdk/middleware-recursion-detection": "3.468.0", + "@aws-sdk/middleware-user-agent": "3.478.0", + "@aws-sdk/region-config-resolver": "3.470.0", + "@aws-sdk/types": "3.468.0", + "@aws-sdk/util-endpoints": "3.478.0", + "@aws-sdk/util-user-agent-browser": "3.468.0", + "@aws-sdk/util-user-agent-node": "3.470.0", + "@smithy/config-resolver": "^2.0.21", + "@smithy/core": "^1.2.0", + "@smithy/fetch-http-handler": "^2.3.1", + "@smithy/hash-node": "^2.0.17", + "@smithy/invalid-dependency": "^2.0.15", + "@smithy/middleware-content-length": "^2.0.17", + "@smithy/middleware-endpoint": "^2.2.3", + "@smithy/middleware-retry": "^2.0.24", + "@smithy/middleware-serde": "^2.0.15", + "@smithy/middleware-stack": "^2.0.9", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/node-http-handler": "^2.2.1", + "@smithy/protocol-http": "^3.0.11", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", + "@smithy/url-parser": "^2.0.15", "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.1", "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", + "@smithy/util-defaults-mode-browser": "^2.0.22", + "@smithy/util-defaults-mode-node": "^2.0.29", + "@smithy/util-endpoints": "^1.0.7", + "@smithy/util-middleware": "^2.0.8", + "@smithy/util-retry": "^2.0.8", "@smithy/util-utf8": "^2.0.2", "fast-xml-parser": "4.2.5", "tslib": "^2.5.0" @@ -321,11 +324,15 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.451.0.tgz", - "integrity": "sha512-SamWW2zHEf1ZKe3j1w0Piauryl8BQIlej0TBS18A4ACzhjhWXhCs13bO1S88LvPR5mBFXok3XOT6zPOnKDFktw==", + "version": "3.477.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.477.0.tgz", + "integrity": "sha512-o0434EH+d1BxHZvgG7z8vph2SYefciQ5RnJw2MgvETGnthgqsnI4nnNJLSw0FVeqCeS18n6vRtzqlGYR2YPCNg==", "dependencies": { - "@smithy/smithy-client": "^2.1.15", + "@smithy/core": "^1.2.0", + "@smithy/protocol-http": "^3.0.11", + "@smithy/signature-v4": "^2.0.0", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -333,13 +340,13 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.451.0.tgz", - "integrity": "sha512-9dAav7DcRgaF7xCJEQR5ER9ErXxnu/tdnVJ+UPmb1NPeIZdESv1A3lxFDEq1Fs8c4/lzAj9BpshGyJVIZwZDKg==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.468.0.tgz", + "integrity": "sha512-k/1WHd3KZn0EQYjadooj53FC0z24/e4dUZhbSKTULgmxyO62pwh9v3Brvw4WRa/8o2wTffU/jo54tf4vGuP/ZA==", "dependencies": { - "@aws-sdk/types": "3.451.0", + "@aws-sdk/types": "3.468.0", "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -347,19 +354,19 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.451.0.tgz", - "integrity": "sha512-TySt64Ci5/ZbqFw1F9Z0FIGvYx5JSC9e6gqDnizIYd8eMnn8wFRUscRrD7pIHKfrhvVKN5h0GdYovmMO/FMCBw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.451.0", - "@aws-sdk/credential-provider-process": "3.451.0", - "@aws-sdk/credential-provider-sso": "3.451.0", - "@aws-sdk/credential-provider-web-identity": "3.451.0", - "@aws-sdk/types": "3.451.0", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.478.0.tgz", + "integrity": "sha512-SsrYEYUvTG9ZoPC+zB19AnVoOKID+QIEHJDIi1GCZXW5kTVyr1saTVm4orG2TjYvbHQMddsWtHOvGYXZWAYMbw==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.468.0", + "@aws-sdk/credential-provider-process": "3.468.0", + "@aws-sdk/credential-provider-sso": "3.478.0", + "@aws-sdk/credential-provider-web-identity": "3.468.0", + "@aws-sdk/types": "3.468.0", "@smithy/credential-provider-imds": "^2.0.0", "@smithy/property-provider": "^2.0.0", "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -367,20 +374,20 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.451.0.tgz", - "integrity": "sha512-AEwM1WPyxUdKrKyUsKyFqqRFGU70e4qlDyrtBxJnSU9NRLZI8tfEZ67bN7fHSxBUBODgDXpMSlSvJiBLh5/3pw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.451.0", - "@aws-sdk/credential-provider-ini": "3.451.0", - "@aws-sdk/credential-provider-process": "3.451.0", - "@aws-sdk/credential-provider-sso": "3.451.0", - "@aws-sdk/credential-provider-web-identity": "3.451.0", - "@aws-sdk/types": "3.451.0", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.478.0.tgz", + "integrity": "sha512-nwDutJYeHiIZCQDgKIUrsgwAWTil0mNe+cbd+j8fi+wwxkWUzip+F0+z02molJ8WrUUKNRhqB1V5aVx7IranuA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.468.0", + "@aws-sdk/credential-provider-ini": "3.478.0", + "@aws-sdk/credential-provider-process": "3.468.0", + "@aws-sdk/credential-provider-sso": "3.478.0", + "@aws-sdk/credential-provider-web-identity": "3.468.0", + "@aws-sdk/types": "3.468.0", "@smithy/credential-provider-imds": "^2.0.0", "@smithy/property-provider": "^2.0.0", "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -388,14 +395,14 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.451.0.tgz", - "integrity": "sha512-HQywSdKeD5PErcLLnZfSyCJO+6T+ZyzF+Lm/QgscSC+CbSUSIPi//s15qhBRVely/3KBV6AywxwNH+5eYgt4lQ==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.468.0.tgz", + "integrity": "sha512-OYSn1A/UsyPJ7Z8Q2cNhTf55O36shPmSsvOfND04nSfu1nPaR+VUvvsP7v+brhGpwC/GAKTIdGAo4blH31BS6A==", "dependencies": { - "@aws-sdk/types": "3.451.0", + "@aws-sdk/types": "3.468.0", "@smithy/property-provider": "^2.0.0", "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -403,16 +410,16 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.451.0.tgz", - "integrity": "sha512-Usm/N51+unOt8ID4HnQzxIjUJDrkAQ1vyTOC0gSEEJ7h64NSSPGD5yhN7il5WcErtRd3EEtT1a8/GTC5TdBctg==", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.478.0.tgz", + "integrity": "sha512-LsDShG51X/q+s5ZFN7kHVqrd8ZHdyEyHqdhoocmRvvw2Dif50M0AqQfvCrW1ndj5CNzXO4x/eH8EK5ZOVlS6Sg==", "dependencies": { - "@aws-sdk/client-sso": "3.451.0", - "@aws-sdk/token-providers": "3.451.0", - "@aws-sdk/types": "3.451.0", + "@aws-sdk/client-sso": "3.478.0", + "@aws-sdk/token-providers": "3.478.0", + "@aws-sdk/types": "3.468.0", "@smithy/property-provider": "^2.0.0", "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -420,13 +427,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.451.0.tgz", - "integrity": "sha512-Xtg3Qw65EfDjWNG7o2xD6sEmumPfsy3WDGjk2phEzVg8s7hcZGxf5wYwe6UY7RJvlEKrU0rFA+AMn6Hfj5oOzg==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.468.0.tgz", + "integrity": "sha512-rexymPmXjtkwCPfhnUq3EjO1rSkf39R4Jz9CqiM7OsqK2qlT5Y/V3gnMKn0ZMXsYaQOMfM3cT5xly5R+OKDHlw==", "dependencies": { - "@aws-sdk/types": "3.451.0", + "@aws-sdk/types": "3.468.0", "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -434,13 +441,13 @@ } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.458.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.458.0.tgz", - "integrity": "sha512-wSP/sjG+SH6YHQINLePzu6fgeTo4ibqQSpnvNF52lJWJY/1lRE4qYuLQFLH2WEWG3FuDzEIsJiu3CwHm0cc6mw==", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.478.0.tgz", + "integrity": "sha512-R1D+hX8Lea9mBZqj2A4hWkSNGCTv5pCsX/+fmfnFtmKL4gPn2MZ1GtnI6Rnk0zyTrQL94SpVc6CcEvhWsm5oiQ==", "dependencies": { "@smithy/abort-controller": "^2.0.1", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/smithy-client": "^2.1.15", + "@smithy/middleware-endpoint": "^2.2.3", + "@smithy/smithy-client": "^2.1.18", "buffer": "5.6.0", "events": "3.3.0", "stream-browserify": "3.0.0", @@ -454,15 +461,15 @@ } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.451.0.tgz", - "integrity": "sha512-KWyZ1JGnYz2QbHuJtYTP1BVnMOfVopR8rP8dTinVb/JR5HfAYz4imICJlJUbOYRjN7wpA3PrRI8dNRjrSBjWJg==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-arn-parser": "3.310.0", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", + "version": "3.470.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.470.0.tgz", + "integrity": "sha512-vLXXNWtsRmEIwzJ9HUQfIuTNAsEzvCv0Icsnkvt2BiBZXnmHdp2vIC3e3+kfy1D7dVQloXqMmnfcLu/BUMu2Jw==", + "dependencies": { + "@aws-sdk/types": "3.468.0", + "@aws-sdk/util-arn-parser": "3.465.0", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/protocol-http": "^3.0.11", + "@smithy/types": "^2.7.0", "@smithy/util-config-provider": "^2.0.0", "tslib": "^2.5.0" }, @@ -471,13 +478,13 @@ } }, "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.451.0.tgz", - "integrity": "sha512-vwG8o2Uk6biLDlOZnqXemsO4dS2HvrprUdxyouwu6hlzLFskg8nL122butn19JqXJKgcVLuSSLzT+xwqBWy2Rg==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.468.0.tgz", + "integrity": "sha512-/wmLjmfgeulxhhmnxX3X3N933TvGsYckVIFjAtDSpLjqkbwzEcNiLq7AdmNJ4BfxG0MCMgcht561DCCD19x8Bg==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@smithy/protocol-http": "^3.0.11", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -485,16 +492,16 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.451.0.tgz", - "integrity": "sha512-eOkpcC2zgAvqs1w7Yp5nsk9LBIj6qLU5kaZuZEBOiFbNKIrTnPo6dQuhgvDcKHD6Y5W/cUjSBiFMs/ROb5aoug==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.468.0.tgz", + "integrity": "sha512-LQwL/N5MCj3Y5keLLewHTqeAXUIMsHFZyxDXRm/uxrOon9ufLKDvGvzAmfwn1/CuSUo66ZfT8VPSA4BsC90RtA==", "dependencies": { "@aws-crypto/crc32": "3.0.0", "@aws-crypto/crc32c": "3.0.0", - "@aws-sdk/types": "3.451.0", + "@aws-sdk/types": "3.468.0", "@smithy/is-array-buffer": "^2.0.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", + "@smithy/protocol-http": "^3.0.11", + "@smithy/types": "^2.7.0", "@smithy/util-utf8": "^2.0.2", "tslib": "^2.5.0" }, @@ -503,13 +510,13 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.451.0.tgz", - "integrity": "sha512-j8a5jAfhWmsK99i2k8oR8zzQgXrsJtgrLxc3js6U+525mcZytoiDndkWTmD5fjJ1byU1U2E5TaPq+QJeDip05Q==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.468.0.tgz", + "integrity": "sha512-gwQ+/QhX+lhof304r6zbZ/V5l5cjhGRxLL3CjH1uJPMcOAbw9wUlMdl+ibr8UwBZ5elfKFGiB1cdW/0uMchw0w==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@smithy/protocol-http": "^3.0.11", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -517,12 +524,12 @@ } }, "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.451.0.tgz", - "integrity": "sha512-R4U2G7mybP0BMiQBJWTcB47g49F4PSXTiCsvMDp5WOEhpWvGQuO1ZIhTxCl5s5lgTSne063Os8W6KSdK2yG2TQ==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.468.0.tgz", + "integrity": "sha512-0gBX/lDynQr4YIhM9h1dVnkVWqrg+34iOCVIUq8jHxzUzgZWglGkG9lHGGg0r1xkLTmegeoo1OKH8wrQ6n33Cg==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -530,12 +537,12 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.451.0.tgz", - "integrity": "sha512-0kHrYEyVeB2QBfP6TfbI240aRtatLZtcErJbhpiNUb+CQPgEL3crIjgVE8yYiJumZ7f0jyjo8HLPkwD1/2APaw==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.468.0.tgz", + "integrity": "sha512-X5XHKV7DHRXI3f29SAhJPe/OxWRFgDWDMMCALfzhmJfCi6Jfh0M14cJKoC+nl+dk9lB+36+jKjhjETZaL2bPlA==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -543,13 +550,13 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.451.0.tgz", - "integrity": "sha512-J6jL6gJ7orjHGM70KDRcCP7so/J2SnkN4vZ9YRLTeeZY6zvBuHDjX8GCIgSqPn/nXFXckZO8XSnA7u6+3TAT0w==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.468.0.tgz", + "integrity": "sha512-vch9IQib2Ng9ucSyRW2eKNQXHUPb5jUPCLA5otTW/8nGjcOU37LxQG4WrxO7uaJ9Oe8hjHO+hViE3P0KISUhtA==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@smithy/protocol-http": "^3.0.11", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -557,29 +564,18 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.451.0.tgz", - "integrity": "sha512-XF4Cw8HrYUwGLKOqKtWs6ss1WXoxvQUcgGLACGSqn9a0p51446NiS5671x7qJUsfBuygdKlIKcOc8pPr9a+5Ow==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-arn-parser": "3.310.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.451.0.tgz", - "integrity": "sha512-UJ6UfVUEgp0KIztxpAeelPXI5MLj9wUtUCqYeIMP7C1ZhoEMNm3G39VLkGN43dNhBf1LqjsV9jkKMZbVfYXuwg==", + "version": "3.474.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.474.0.tgz", + "integrity": "sha512-62aAo/8u5daIabeJ+gseYeHeShe9eYH6mH+kfWmLsHybXCCv1EaD/ZkdXWNhL0HZ3bUI1z1SF1p8jjTAWALnwA==", "dependencies": { - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@aws-sdk/util-arn-parser": "3.465.0", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/protocol-http": "^3.0.11", + "@smithy/signature-v4": "^2.0.0", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", + "@smithy/util-config-provider": "^2.0.0", "tslib": "^2.5.0" }, "engines": { @@ -587,16 +583,16 @@ } }, "node_modules/@aws-sdk/middleware-signing": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.451.0.tgz", - "integrity": "sha512-s5ZlcIoLNg1Huj4Qp06iKniE8nJt/Pj1B/fjhWc6cCPCM7XJYUCejCnRh6C5ZJoBEYodjuwZBejPc1Wh3j+znA==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.468.0.tgz", + "integrity": "sha512-s+7fSB1gdnnTj5O0aCCarX3z5Vppop8kazbNSZADdkfHIDWCN80IH4ZNjY3OWqaAz0HmR4LNNrovdR304ojb4Q==", "dependencies": { - "@aws-sdk/types": "3.451.0", + "@aws-sdk/types": "3.468.0", "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.9", + "@smithy/protocol-http": "^3.0.11", "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-middleware": "^2.0.6", + "@smithy/types": "^2.7.0", + "@smithy/util-middleware": "^2.0.8", "tslib": "^2.5.0" }, "engines": { @@ -604,12 +600,12 @@ } }, "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.451.0.tgz", - "integrity": "sha512-hDkeBUiRsvuDbvsPha0/uJHE680WDzjAOoE6ZnLBoWsw7ry+Bw1ULMj0sCmpBVrQ7Gpivi/6zbezhClVmt3ITw==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.468.0.tgz", + "integrity": "sha512-y1qLW24wRkOGBTK5d6eJXf6d8HYo4rzT4a1mNDN1rd18NSffwQ6Yke5qeUiIaxa0y/l+FvvNYErbhYtij2rJoQ==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -617,14 +613,14 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.451.0.tgz", - "integrity": "sha512-8NM/0JiKLNvT9wtAQVl1DFW0cEO7OvZyLSUBLNLTHqyvOZxKaZ8YFk7d8PL6l76LeUKRxq4NMxfZQlUIRe0eSA==", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.478.0.tgz", + "integrity": "sha512-Rec+nAPIzzwxgHPW+xqY6tooJGFOytpYg/xSRv8/IXl3xKGhmpMGs6gDWzmMBv/qy5nKTvLph/csNWJ98GWXCw==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@aws-sdk/util-endpoints": "3.478.0", + "@smithy/protocol-http": "^3.0.11", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -632,14 +628,14 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.451.0.tgz", - "integrity": "sha512-3iMf4OwzrFb4tAAmoROXaiORUk2FvSejnHIw/XHvf/jjR4EqGGF95NZP/n/MeFZMizJWVssrwS412GmoEyoqhg==", + "version": "3.470.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.470.0.tgz", + "integrity": "sha512-C1o1J06iIw8cyAAOvHqT4Bbqf+PgQ/RDlSyjt2gFfP2OovDpc2o2S90dE8f8iZdSGpg70N5MikT1DBhW9NbhtQ==", "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/types": "^2.7.0", "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", + "@smithy/util-middleware": "^2.0.8", "tslib": "^2.5.0" }, "engines": { @@ -647,14 +643,15 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.451.0.tgz", - "integrity": "sha512-qQKY7/txeNUTLyRL3WxUWEwaZ5sf76EIZgu9kLaR96cAYSxwQi/qQB3ijbfD6u7sJIA8aROMxeYK0VmRsQg0CA==", + "version": "3.474.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.474.0.tgz", + "integrity": "sha512-93OWRQgTJZASXLrlUNX7mmXknNkYxFYldRLARmYQccONmnIqgYQW0lQj8BFwqkHJTzSMik3/UsU0SHKwZ9ynYA==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/protocol-http": "^3.0.9", + "@aws-sdk/middleware-sdk-s3": "3.474.0", + "@aws-sdk/types": "3.468.0", + "@smithy/protocol-http": "^3.0.11", "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -662,45 +659,45 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.451.0.tgz", - "integrity": "sha512-ij1L5iUbn6CwxVOT1PG4NFjsrsKN9c4N1YEM0lkl6DwmaNOscjLKGSNyj9M118vSWsOs1ZDbTwtj++h0O/BWrQ==", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.478.0.tgz", + "integrity": "sha512-7b5tj1y/wGHZIZ+ckjOUKgKrMuCJMF/G1UKZKIqqdekeEsjcThbvoxAMeY0FEowu2ODVk/ggOmpBFxcu0iYd6A==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", + "@aws-sdk/middleware-host-header": "3.468.0", + "@aws-sdk/middleware-logger": "3.468.0", + "@aws-sdk/middleware-recursion-detection": "3.468.0", + "@aws-sdk/middleware-user-agent": "3.478.0", + "@aws-sdk/region-config-resolver": "3.470.0", + "@aws-sdk/types": "3.468.0", + "@aws-sdk/util-endpoints": "3.478.0", + "@aws-sdk/util-user-agent-browser": "3.468.0", + "@aws-sdk/util-user-agent-node": "3.470.0", + "@smithy/config-resolver": "^2.0.21", + "@smithy/fetch-http-handler": "^2.3.1", + "@smithy/hash-node": "^2.0.17", + "@smithy/invalid-dependency": "^2.0.15", + "@smithy/middleware-content-length": "^2.0.17", + "@smithy/middleware-endpoint": "^2.2.3", + "@smithy/middleware-retry": "^2.0.24", + "@smithy/middleware-serde": "^2.0.15", + "@smithy/middleware-stack": "^2.0.9", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/node-http-handler": "^2.2.1", "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.9", + "@smithy/protocol-http": "^3.0.11", "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", + "@smithy/url-parser": "^2.0.15", "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.1", "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", + "@smithy/util-defaults-mode-browser": "^2.0.22", + "@smithy/util-defaults-mode-node": "^2.0.29", + "@smithy/util-endpoints": "^1.0.7", + "@smithy/util-retry": "^2.0.8", "@smithy/util-utf8": "^2.0.2", "tslib": "^2.5.0" }, @@ -709,11 +706,11 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.451.0.tgz", - "integrity": "sha512-rhK+qeYwCIs+laJfWCcrYEjay2FR/9VABZJ2NRM89jV/fKqGVQR52E5DQqrI+oEIL5JHMhhnr4N4fyECMS35lw==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.468.0.tgz", + "integrity": "sha512-rx/9uHI4inRbp2tw3Y4Ih4PNZkVj32h7WneSg3MVgVjAoVD5Zti9KhS5hkvsBxfgmQmg0AQbE+b1sy5WGAgntA==", "dependencies": { - "@smithy/types": "^2.5.0", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -721,9 +718,9 @@ } }, "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.310.0.tgz", - "integrity": "sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==", + "version": "3.465.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.465.0.tgz", + "integrity": "sha512-zOJ82vzDJFqBX9yZBlNeHHrul/kpx/DCoxzW5UBbZeb26kfV53QhMSoEmY8/lEbBqlqargJ/sgRC845GFhHNQw==", "dependencies": { "tslib": "^2.5.0" }, @@ -732,12 +729,12 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.451.0.tgz", - "integrity": "sha512-giqLGBTnRIcKkDqwU7+GQhKbtJ5Ku35cjGQIfMyOga6pwTBUbaK0xW1Sdd8sBQ1GhApscnChzI9o/R9x0368vw==", + "version": "3.478.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.478.0.tgz", + "integrity": "sha512-u9Mcg3euGJGs5clPt9mBuhBjHiEKiD0PnfvArhfq9i+dcY5mbCq/i1Dezp3iv1fZH9xxQt7hPXDfSpt1yUSM6g==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/util-endpoints": "^1.0.4", + "@aws-sdk/types": "3.468.0", + "@smithy/util-endpoints": "^1.0.7", "tslib": "^2.5.0" }, "engines": { @@ -756,24 +753,24 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.451.0.tgz", - "integrity": "sha512-Ws5mG3J0TQifH7OTcMrCTexo7HeSAc3cBgjfhS/ofzPUzVCtsyg0G7I6T7wl7vJJETix2Kst2cpOsxygPgPD9w==", + "version": "3.468.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.468.0.tgz", + "integrity": "sha512-OJyhWWsDEizR3L+dCgMXSUmaCywkiZ7HSbnQytbeKGwokIhD69HTiJcibF/sgcM5gk4k3Mq3puUhGnEZ46GIig==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@smithy/types": "^2.7.0", "bowser": "^2.11.0", "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.451.0.tgz", - "integrity": "sha512-TBzm6P+ql4mkGFAjPlO1CI+w3yUT+NulaiALjl/jNX/nnUp6HsJsVxJf4nVFQTG5KRV0iqMypcs7I3KIhH+LmA==", + "version": "3.470.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.470.0.tgz", + "integrity": "sha512-QxsZ9iVHcBB/XRdYvwfM5AMvNp58HfqkIrH88mY0cmxuvtlIGDfWjczdDrZMJk9y0vIq+cuoCHsGXHu7PyiEAQ==", "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", + "@aws-sdk/types": "3.468.0", + "@smithy/node-config-provider": "^2.1.8", + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -797,10 +794,11 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.310.0.tgz", - "integrity": "sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==", + "version": "3.472.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.472.0.tgz", + "integrity": "sha512-PwjVxz1hr9up8QkddabuScPZ/d5aDHgvHYgK4acHYzltXL4wngfvimi5ZqXTzVWF2QANxHmWnHUr45QJX71oJQ==", "dependencies": { + "@smithy/types": "^2.7.0", "tslib": "^2.5.0" }, "engines": { @@ -865,9 +863,9 @@ } }, "node_modules/@helia/unixfs": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@helia/unixfs/-/unixfs-1.4.2.tgz", - "integrity": "sha512-wH/xg++d2fH16aaUJPmB08snPXTgEDwD13uRXQsYqL1A3lgS32RgSQN64Xtb7qfzZ0SzDBtJLeoZDXNJuXDzoQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@helia/unixfs/-/unixfs-1.4.3.tgz", + "integrity": "sha512-jS0En8fGhb01XH+nnxo3kQsmc1lwBEdlttAZFvTo7HCjBGPNFuaYdwTqF9S1wMVWV2fWqj7eS2zBZZa0MDsi1Q==", "dependencies": { "@helia/interface": "^2.0.0", "@ipld/dag-pb": "^4.0.0", @@ -1117,6 +1115,24 @@ "node": ">=14.0.0" } }, + "node_modules/@smithy/core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-1.2.0.tgz", + "integrity": "sha512-l8R89X7+hlt2FEFg+OrNq29LP3h9DfGPmO6ObwT9IXWHD6V7ycpj5u2rVQyIis26ovrgOYakl6nfgmPMm8m1IQ==", + "dependencies": { + "@smithy/middleware-endpoint": "^2.2.3", + "@smithy/middleware-retry": "^2.0.24", + "@smithy/middleware-serde": "^2.0.15", + "@smithy/protocol-http": "^3.0.11", + "@smithy/smithy-client": "^2.1.18", + "@smithy/types": "^2.7.0", + "@smithy/util-middleware": "^2.0.8", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@smithy/credential-provider-imds": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.4.tgz", @@ -1887,9 +1903,9 @@ } }, "node_modules/blockstore-fs": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/blockstore-fs/-/blockstore-fs-1.1.6.tgz", - "integrity": "sha512-7tmntHl7icxusYQ9tDSOYEQKO1QXhZ45AqchfIRvB9ihUpxTTqMx2RRXPN94Fr3pc6PWJ+HwwxeGJobxAnm1cQ==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/blockstore-fs/-/blockstore-fs-1.1.8.tgz", + "integrity": "sha512-1KD1+yEkxszZ3GWQdJbGgXAOs12LJC/Pit7JCPueJT/Pjt9GWtGZ4+8mgoaR3bjXVBgBIdhNlUxxw2NS787noA==", "dependencies": { "blockstore-core": "^4.0.0", "fast-write-atomic": "^0.2.0", diff --git a/package.json b/package.json index 3888d71..822f91e 100644 --- a/package.json +++ b/package.json @@ -1,40 +1,33 @@ { "name": "@filebase/sdk", "version": "1.0.0", - "description": "", - "repository": "https://github.com/filebase/sdk", + "description": "SDK for Interacting with Filebase Services [S3(Buckets, Objects), IPFS(Gateways, Pins) IPNS(Names)]", + "repository": "https://github.com/filebase/filebase-sdk", + "license": "MIT", "type": "module", - "main": "dist/cjs/index.js", - "module": "dist/mjs/index.mjs", + "main": "src/index.js", "engines": { "node": ">=16.0.0", "npm": ">=8.0.0" }, - "exports": { - ".": { - "require": "./dist/mjs/index.cjs", - "import": "./dist/cjs/index.mjs" - } - }, "scripts": { "test": "node --test", "doc": "jsdoc -c jsdoc.json" }, - "keywords": [], - "author": "", + "keywords": ["filebase", "filebase-sdk", "s3", "ipfs", "ipns", "sdk", "web3", "distributed"], "devDependencies": { "clean-jsdoc-theme": "4.2.17", "jsdoc": "4.0.2", "prettier": "3.1.0" }, "dependencies": { - "@aws-sdk/client-s3": "3.454.0", - "@aws-sdk/lib-storage": "3.458.0", + "@aws-sdk/client-s3": "3.478.0", + "@aws-sdk/lib-storage": "3.478.0", "@helia/car": "1.0.4", - "@helia/unixfs": "1.4.2", + "@helia/unixfs": "1.4.3", "@ipld/car": "5.2.4", "axios": "1.6.2", - "blockstore-fs": "1.1.6", + "blockstore-fs": "1.1.8", "uuid": "9.0.1" } } From b855685b05b1da53966c424fb28d3cca27cdcd5e Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:53:49 -0600 Subject: [PATCH 73/79] Pass Errors through API Handler --- src/gatewayManager.js | 164 +++++++++++++++++++++++------------------- src/helpers.js | 18 ++++- src/nameManager.js | 162 +++++++++++++++++++++++------------------ src/pinManager.js | 158 +++++++++++++++++++++------------------- 4 files changed, 284 insertions(+), 218 deletions(-) diff --git a/src/gatewayManager.js b/src/gatewayManager.js index 6441391..b87dd29 100644 --- a/src/gatewayManager.js +++ b/src/gatewayManager.js @@ -1,4 +1,5 @@ import axios from "axios"; +import { apiErrorHandler } from "./helpers.js"; class GatewayManager { #DEFAULT_ENDPOINT = "https://api.filebase.io"; @@ -61,23 +62,27 @@ class GatewayManager { * }); */ async create(name, options = {}) { - let createOptions = { - name, - }; - if (typeof options.domain === "string") { - createOptions.domain = options.domain; + try { + let createOptions = { + name, + }; + if (typeof options.domain === "string") { + createOptions.domain = options.domain; + } + if (typeof options.enabled === "boolean") { + createOptions.enabled = options.enabled; + } + if (typeof options.private === "boolean") { + createOptions.private = options.private; + } + const createResponse = await this.#client.request({ + method: "POST", + data: createOptions, + }); + return createResponse.data; + } catch (err) { + apiErrorHandler(err); } - if (typeof options.enabled === "boolean") { - createOptions.enabled = options.enabled; - } - if (typeof options.private === "boolean") { - createOptions.private = options.private; - } - const createResponse = await this.#client.request({ - method: "POST", - data: createOptions, - }); - return createResponse.data; } /** @@ -89,17 +94,18 @@ class GatewayManager { * await gatewayManager.delete(`delete-name-example`); */ async delete(name) { - const deleteResponse = await this.#client.request({ - method: "DELETE", - url: `/${name}`, - validateStatus: (status) => { - return status === 204 || status === 404; - }, - }); - if (deleteResponse.status === 404) { - throw new Error(`Could not find matching name for gateway`); + try { + await this.#client.request({ + method: "DELETE", + url: `/${name}`, + validateStatus: (status) => { + return status === 204; + }, + }); + return true; + } catch (err) { + apiErrorHandler(err); } - return true; } /** @@ -111,14 +117,18 @@ class GatewayManager { * await gatewayManager.get(`gateway-get-example`); */ async get(name) { - const getResponse = await this.#client.request({ - method: "GET", - url: `/${name}`, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - }); - return getResponse.status === 200 ? getResponse.data : false; + try { + const getResponse = await this.#client.request({ + method: "GET", + url: `/${name}`, + validateStatus: (status) => { + return status === 200 || status === 404; + }, + }); + return getResponse.status === 200 ? getResponse.data : false; + } catch (err) { + apiErrorHandler(err); + } } /** @@ -129,10 +139,14 @@ class GatewayManager { * await gatewayManager.list(); */ async list() { - const getResponse = await this.#client.request({ - method: "GET", - }); - return getResponse.data; + try { + const getResponse = await this.#client.request({ + method: "GET", + }); + return getResponse.data; + } catch (err) { + apiErrorHandler(err); + } } /** @@ -148,30 +162,31 @@ class GatewayManager { * }); */ async update(name, options) { - const updateOptions = { - name, - }; - if (options?.domain) { - updateOptions.domain = String(options.private); - } - if (options?.enabled) { - updateOptions.enabled = Boolean(options.enabled); - } - if (options?.private) { - updateOptions.private = Boolean(options.private); + try { + const updateOptions = { + name, + }; + if (options?.domain) { + updateOptions.domain = String(options.private); + } + if (options?.enabled) { + updateOptions.enabled = Boolean(options.enabled); + } + if (options?.private) { + updateOptions.private = Boolean(options.private); + } + await this.#client.request({ + method: "PUT", + url: `/${name}`, + data: updateOptions, + validateStatus: (status) => { + return status === 200; + }, + }); + return true; + } catch (err) { + apiErrorHandler(err); } - const updateResponse = await this.#client.request({ - method: "PUT", - url: `/${name}`, - data: updateOptions, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - }); - if (updateResponse.status === 404) { - throw new Error(`Could not find matching name for gateway`); - } - return true; } /** @@ -185,20 +200,21 @@ class GatewayManager { * await gatewayManager.toggle(`toggle-gateway-example`, false); // Disabled */ async toggle(name, targetState) { - const toggleResponse = await this.#client.request({ - method: "PUT", - url: `/${name}`, - data: { - enabled: Boolean(targetState), - }, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - }); - if (toggleResponse.status === 404) { - throw new Error(`Could not find matching name for gateway`); + try { + await this.#client.request({ + method: "PUT", + url: `/${name}`, + data: { + enabled: Boolean(targetState), + }, + validateStatus: (status) => { + return status === 200; + }, + }); + return true; + } catch (err) { + apiErrorHandler(err); } - return toggleResponse.status === 200; } } diff --git a/src/helpers.js b/src/helpers.js index 52049e6..9f604b2 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -23,4 +23,20 @@ async function downloadFromGateway(cid, options) { return downloadResponse.data; } -export { downloadFromGateway }; +function apiErrorHandler(err) { + if ( + err?.response && + err?.response?.status && + (err.response.status.toString()[0] === "4" || + err.response.status.toString()[0] === "5") + ) { + throw new Error( + err.response.data.error?.details || + err.response.data.error?.reason || + err, + ); + } + throw err; +} + +export { downloadFromGateway, apiErrorHandler }; diff --git a/src/nameManager.js b/src/nameManager.js index f0823e7..54a02df 100644 --- a/src/nameManager.js +++ b/src/nameManager.js @@ -1,4 +1,5 @@ import axios from "axios"; +import { apiErrorHandler } from "./helpers.js"; /** Provides methods for managing names in an REST endpoint. */ class NameManager { @@ -66,15 +67,19 @@ class NameManager { enabled: true, }, ) { - const createResponse = await this.#client.request({ - method: "POST", - data: { - label, - cid, - enabled: options?.enabled !== false, - }, - }); - return createResponse.data; + try { + const createResponse = await this.#client.request({ + method: "POST", + data: { + label, + cid, + enabled: options?.enabled !== false, + }, + }); + return createResponse.data; + } catch (err) { + apiErrorHandler(err); + } } /** @@ -101,16 +106,20 @@ class NameManager { enabled: true, }, ) { - const importResponse = await this.#client.request({ - method: "POST", - data: { - label, - cid, - network_private_key: privateKey, - enabled: options?.enabled !== false, - }, - }); - return importResponse.data; + try { + const importResponse = await this.#client.request({ + method: "POST", + data: { + label, + cid, + network_private_key: privateKey, + enabled: options?.enabled !== false, + }, + }); + return importResponse.data; + } catch (err) { + apiErrorHandler(err); + } } /** @@ -125,24 +134,25 @@ class NameManager { * await nameManager.update(`update-name-example`, `bafybeidt4nmaci476lyon2mvgfmwyzysdazienhxs2bqnfpdainzjuwjom`); */ async update(label, cid, options = {}) { - const updateOptions = { - cid, - }; - if (options?.enabled) { - updateOptions.enabled = Boolean(options.enabled); - } - const updateResult = await this.#client.request({ - method: "PUT", - url: `/${label}`, - data: updateOptions, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - }); - if (updateResult.status === 404) { - throw new Error(`Could not find matching label for name`); + try { + const updateOptions = { + cid, + }; + if (options?.enabled) { + updateOptions.enabled = Boolean(options.enabled); + } + await this.#client.request({ + method: "PUT", + url: `/${label}`, + data: updateOptions, + validateStatus: (status) => { + return status === 200; + }, + }); + return true; + } catch (err) { + apiErrorHandler(err); } - return true; } /** @@ -154,14 +164,18 @@ class NameManager { * await nameManager.get(`list-name-example`); */ async get(label) { - const getResponse = await this.#client.request({ - method: "GET", - url: `/${label}`, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - }); - return getResponse.status === 200 ? getResponse.data : false; + try { + const getResponse = await this.#client.request({ + method: "GET", + url: `/${label}`, + validateStatus: (status) => { + return status === 200 || status === 404; + }, + }); + return getResponse.status === 200 ? getResponse.data : false; + } catch (err) { + apiErrorHandler(err); + } } /** @@ -172,10 +186,14 @@ class NameManager { * await nameManager.list(); */ async list() { - const listResponse = await this.#client.request({ - method: "GET", - }); - return listResponse.data; + try { + const listResponse = await this.#client.request({ + method: "GET", + }); + return listResponse.data; + } catch (err) { + apiErrorHandler(err); + } } /** @@ -187,17 +205,18 @@ class NameManager { * await nameManager.delete(`delete-name-example`); */ async delete(label) { - const deleteResult = await this.#client.request({ - method: "DELETE", - url: `/${label}`, - validateStatus: (status) => { - return status === 204 || status === 404; - }, - }); - if (deleteResult.status === 404) { - throw new Error(`Could not find matching label for name`); + try { + await this.#client.request({ + method: "DELETE", + url: `/${label}`, + validateStatus: (status) => { + return status === 204; + }, + }); + return true; + } catch (err) { + apiErrorHandler(err); } - return true; } /** @@ -211,20 +230,21 @@ class NameManager { * await nameManager.toggle(`toggle-name-example`, false); // Disabled */ async toggle(label, targetState) { - const toggleResponse = await this.#client.request({ - method: "PUT", - url: `/${label}`, - data: { - enabled: targetState, - }, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - }); - if (toggleResponse.status === 404) { - throw new Error(`Could not find matching label for name`); + try { + await this.#client.request({ + method: "PUT", + url: `/${label}`, + data: { + enabled: targetState, + }, + validateStatus: (status) => { + return status === 200; + }, + }); + return true; + } catch (err) { + apiErrorHandler(err); } - return true; } } diff --git a/src/pinManager.js b/src/pinManager.js index be423de..6255020 100644 --- a/src/pinManager.js +++ b/src/pinManager.js @@ -1,5 +1,5 @@ import axios from "axios"; -import { downloadFromGateway } from "./helpers.js"; +import { apiErrorHandler, downloadFromGateway } from "./helpers.js"; /** Provides methods for managing pins in an REST endpoint. */ class PinManager { @@ -113,18 +113,22 @@ class PinManager { * }); */ async list(listOptions, options) { - const encodedToken = this.#getEncodedToken(options?.bucket), - getResponse = await this.#client.request({ - method: "GET", - params: listOptions, - headers: { Authorization: `Bearer ${encodedToken}` }, - }); - for (let pinStatus of getResponse.data.results) { - pinStatus.download = () => { - return this.download(pinStatus.pin.cid); - }; + try { + const encodedToken = this.#getEncodedToken(options?.bucket), + getResponse = await this.#client.request({ + method: "GET", + params: listOptions, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + for (let pinStatus of getResponse.data.results) { + pinStatus.download = () => { + return this.download(pinStatus.pin.cid); + }; + } + return getResponse.data; + } catch (err) { + apiErrorHandler(err); } - return getResponse.data; } /** @@ -141,20 +145,24 @@ class PinManager { * }); */ async create(key, cid, metadata, options) { - const encodedToken = this.#getEncodedToken(options?.bucket), - pinStatus = await this.#client.request({ - method: "POST", - data: { - cid, - name: key, - meta: metadata, - }, - headers: { Authorization: `Bearer ${encodedToken}` }, - }); - pinStatus.data.download = () => { - return this.download(pinStatus.data.pin.cid); - }; - return pinStatus.data; + try { + const encodedToken = this.#getEncodedToken(options?.bucket), + pinStatus = await this.#client.request({ + method: "POST", + data: { + cid, + name: key, + meta: metadata, + }, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + pinStatus.data.download = () => { + return this.download(pinStatus.data.pin.cid); + }; + return pinStatus.data; + } catch (err) { + apiErrorHandler(err); + } } /** @@ -177,32 +185,33 @@ class PinManager { * } */ async replace(requestid, cid, options) { - let replaceData = { - cid, - meta: options?.metadata || {}, - }; - if (options?.name) { - replaceData.name = options.name; - } + try { + let replaceData = { + cid, + meta: options?.metadata || {}, + }; + if (options?.name) { + replaceData.name = options.name; + } - const encodedToken = this.#getEncodedToken(options?.bucket), - pinStatusResult = await this.#client.request({ - method: "POST", - url: `/${requestid}`, - data: replaceData, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - headers: { Authorization: `Bearer ${encodedToken}` }, - }); - if (pinStatusResult.status === 404) { - throw new Error(`Could not find matching requestid`); + const encodedToken = this.#getEncodedToken(options?.bucket), + pinStatusResult = await this.#client.request({ + method: "POST", + url: `/${requestid}`, + data: replaceData, + validateStatus: (status) => { + return status === 200; + }, + headers: { Authorization: `Bearer ${encodedToken}` }, + }); + const pinStatus = pinStatusResult.data; + pinStatus.download = () => { + return this.download(pinStatus.pin.cid); + }; + return pinStatus; + } catch (err) { + apiErrorHandler(err); } - const pinStatus = pinStatusResult.data; - pinStatus.download = () => { - return this.download(pinStatus.pin.cid); - }; - return pinStatus; } /** @@ -229,23 +238,27 @@ class PinManager { * await pinManager.get("qr4231214"); */ async get(requestid, options) { - const encodedToken = this.#getEncodedToken(options?.bucket), - getResponseResult = await this.#client.request({ - method: "GET", - url: `/${requestid}`, - headers: { Authorization: `Bearer ${encodedToken}` }, - validateStatus: (status) => { - return status === 200 || status === 404; - }, - }); - if (getResponseResult.status === 404) { - return false; + try { + const encodedToken = this.#getEncodedToken(options?.bucket), + getResponseResult = await this.#client.request({ + method: "GET", + url: `/${requestid}`, + headers: { Authorization: `Bearer ${encodedToken}` }, + validateStatus: (status) => { + return status === 200 || status === 404; + }, + }); + if (getResponseResult.status === 404) { + return false; + } + const pinStatus = getResponseResult.data; + pinStatus.download = () => { + return this.download(pinStatus.pin.cid); + }; + return pinStatus; + } catch (err) { + apiErrorHandler(err); } - const pinStatus = getResponseResult.data; - pinStatus.download = () => { - return this.download(pinStatus.pin.cid); - }; - return pinStatus; } /** @@ -258,19 +271,20 @@ class PinManager { * await pinManager.delete("qr4231213"); */ async delete(requestid, options) { - const encodedToken = this.#getEncodedToken(options?.bucket), - deleteResponse = await this.#client.request({ + try { + const encodedToken = this.#getEncodedToken(options?.bucket); + await this.#client.request({ method: "DELETE", url: `/${requestid}`, headers: { Authorization: `Bearer ${encodedToken}` }, validateStatus: (status) => { - return status === 202 || status === 404; + return status === 202; }, }); - if (deleteResponse.status === 404) { - throw new Error(`Could not find matching requestid`); + return true; + } catch (err) { + apiErrorHandler(err); } - return true; } #getEncodedToken(bucket) { From b87fbdbfd82efba327073fd517907acc93f4e76a Mon Sep 17 00:00:00 2001 From: Joshua Noble Date: Thu, 21 Dec 2023 14:54:40 -0500 Subject: [PATCH 74/79] Update LICENSE --- LICENSE | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 588ef6c..d36d5fb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,6 @@ -Copyright (c) Filebase, Inc. All rights reserved. +MIT License + +Copyright (c) 2023 Filebase, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. From f28f0807213232b82877d42e8efb1d016e0b4c22 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:06:21 -0600 Subject: [PATCH 75/79] Update test.yml Fix Names Test --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2dc38c9..06b0b28 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,5 +18,5 @@ jobs: TEST_KEY: ${{ secrets.TEST_S3_KEY }} TEST_SECRET: ${{ secrets.TEST_S3_SECRET }} TEST_IPFS_GATEWAY: ${{ vars.TEST_IPFS_GATEWAY }} - TEST_IPNS_CID: ${{ vars.TEST_IPNS_CID }} TEST_IPNS_PRIVATE_KEY: ${{ secrets.TEST_IPNS_PRIVATE_KEY }} + TEST_NAME_CID: ${{ vars.TEST_NAME_CID }} From eb6bc19544ef4fb83cfd1e751e44343c696ba037 Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:17:04 -0600 Subject: [PATCH 76/79] Update Action to Deploy Documentation on Publish to Master --- .github/workflows/gh-pages.yml | 24 ++++++++++++++++++++++++ jsdoc.json | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/gh-pages.yml diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml new file mode 100644 index 0000000..e6e5ab1 --- /dev/null +++ b/.github/workflows/gh-pages.yml @@ -0,0 +1,24 @@ +name: Build Documentation and Deploy to GitHub Pages +on: + push: + branches: + - master +permissions: + contents: write +jobs: + build-and-deploy: + concurrency: ci-${{ github.ref }} + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v3 + + - name: Install and Build 🔧 + run: | + npm ci + npm run doc + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: documentation \ No newline at end of file diff --git a/jsdoc.json b/jsdoc.json index 1339bde..981e466 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -1,6 +1,6 @@ { "source": { - "include": ["src", "package.json"], + "include": ["src"], "includePattern": ".js$", "excludePattern": "(node_modules/|docs)" }, From 1ad23c9229b6f3c27d8fb6784fef5b6fa933af1d Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:49:29 -0600 Subject: [PATCH 77/79] Cleanup Tests --- test/objectManager.spec.js | 67 ++++++---- test/pinManager.spec.js | 265 +++++++++++++++++++++++-------------- 2 files changed, 207 insertions(+), 125 deletions(-) diff --git a/test/objectManager.spec.js b/test/objectManager.spec.js index 1ed75dd..abb487b 100644 --- a/test/objectManager.spec.js +++ b/test/objectManager.spec.js @@ -282,30 +282,45 @@ test("copy object", async () => { const bucketSrc = `${TEST_PREFIX}-copy-object-test-pass-src`; await createBucket(bucketSrc); - // Upload object `copy-object-test` - const objectNameToCreateSrc = `copy-object-test`; - const uploaded = await uploadObject( - bucketSrc, - objectNameToCreateSrc, - Buffer.from("copy object", "utf-8"), - ); - assert.equal(uploaded, true); - - // Create bucket `copy-object-test-pass-dest` - const bucketDest = `${TEST_PREFIX}-copy-object-test-pass-dest`; - await createBucket(bucketDest); - - // Initialize ObjectManager - const objectManager = new ObjectManager( - process.env.TEST_S3_KEY || process.env.TEST_KEY, - process.env.TEST_S3_SECRET || process.env.TEST_SECRET, - { bucket: bucketSrc }, - ); - - // Copy object `copy-object-test` from `copy-object-test-pass-src` to `copy-object-test-pass-dest` - await objectManager.copy(objectNameToCreateSrc, bucketDest); - - // List bucket and assert new object exists - const copiedObject = await objectManager.get(objectNameToCreateSrc); - assert.equal(copiedObject.ETag, '"8605273d870f50fde0d8fbcad4a8f702"'); + try { + // Upload object `copy-object-test` + const objectNameToCreateSrc = `copy-object-test`; + const uploaded = await uploadObject( + bucketSrc, + objectNameToCreateSrc, + Buffer.from("copy object", "utf-8"), + ); + try { + assert.equal(uploaded, true); + + // Create bucket `copy-object-test-pass-dest` + const bucketDest = `${TEST_PREFIX}-copy-object-test-pass-dest`; + await createBucket(bucketDest); + + try { + // Initialize ObjectManager + const objectManager = new ObjectManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + { bucket: bucketSrc }, + ); + + // Copy object `copy-object-test` from `copy-object-test-pass-src` to `copy-object-test-pass-dest` + await objectManager.copy(objectNameToCreateSrc, bucketDest); + try { + // List bucket and assert new object exists + const copiedObject = await objectManager.get(objectNameToCreateSrc); + assert.equal(copiedObject.ETag, '"8605273d870f50fde0d8fbcad4a8f702"'); + } finally { + await deleteObject(bucketDest, objectNameToCreateSrc); + } + } finally { + await deleteBucket(bucketDest); + } + } finally { + await deleteObject(bucketSrc, objectNameToCreateSrc); + } + } finally { + await deleteBucket(bucketSrc); + } }); diff --git a/test/pinManager.spec.js b/test/pinManager.spec.js index 4ef7e04..e7358c0 100644 --- a/test/pinManager.spec.js +++ b/test/pinManager.spec.js @@ -9,188 +9,255 @@ import BucketManager from "../src/bucketManager.js"; const TEST_CID_1 = "QmSEu6zGwKgkQA3ZKaDnvkrwre1kkQa7eRFCbQi7waNwTT", TEST_CID_2 = "QmNXcMdXadLRTxLpHJMsGnaeKz26d2F6NgUDVWScp54EfC", - TEST_PREFIX = Date.now(), - TEST_BUCKET = `${TEST_PREFIX}-pinning-test`; + TEST_PREFIX = Date.now(); -async function ensureBucketExists(bucketName) { - try { - // Initialize BucketManager - const bucketManager = new BucketManager( - process.env.TEST_NAME_KEY || process.env.TEST_KEY, - process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, - ); - await bucketManager.create(bucketName); - } catch (err) { - console.log(`Bucket Already Exists`); - } +async function createBucket(name) { + // Initialize BucketManager + const bucketManager = new BucketManager( + process.env.TEST_NAME_KEY || process.env.TEST_KEY, + process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, + ); + + // Create bucket with name + const bucketNameToCreate = name; + await bucketManager.create(bucketNameToCreate); + + // List buckets and assert new bucket exists + const currentBuckets = await bucketManager.list(), + createdBucket = currentBuckets.find((currentBucket) => { + return currentBucket.Name === bucketNameToCreate; + }); + + return typeof createdBucket !== "undefined"; +} + +async function deleteBucket(bucket) { + // Initialize BucketManager + const bucketManager = new BucketManager( + process.env.TEST_S3_KEY || process.env.TEST_KEY, + process.env.TEST_S3_SECRET || process.env.TEST_SECRET, + ); + + // Delete Bucket + await bucketManager.delete(bucket); + return true; } test("create pin", async () => { - const testPinName = `${TEST_PREFIX}-create-pin-test-pass`, + const testBucketName = `${TEST_PREFIX}-create-pin-test-pass`, + testPinName = `${TEST_PREFIX}-create-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { - bucket: TEST_BUCKET, + bucket: testBucketName, }, ); - await ensureBucketExists(TEST_BUCKET); - const createdPin = await pinManager.create(testPinName, TEST_CID_1); - assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + await createBucket(testBucketName); + try { + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + await pinManager.delete(createdPin.requestid); + } finally { + await deleteBucket(testBucketName); + } }); test("replace pin with name", async () => { - const testPinName = `${TEST_PREFIX}-replace-pin-test-pass`, + const testBucketName = `${TEST_PREFIX}-replname-pin-test-pass`, + testPinName = `${TEST_PREFIX}-replace-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { - bucket: TEST_BUCKET, + bucket: testBucketName, }, ); - await ensureBucketExists(TEST_BUCKET); - const createdPin = await pinManager.create(testPinName, TEST_CID_1); - assert.strictEqual(createdPin.pin.cid, TEST_CID_1); - const replacedPin = await pinManager.replace( - createdPin.requestid, - TEST_CID_2, - { - name: `${testPinName}-replaced`, - }, - ); - assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); - assert.strictEqual(replacedPin.pin.name, `${testPinName}-replaced`); - await pinManager.delete(replacedPin.requestid); + await createBucket(testBucketName); + try { + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + const replacedPin = await pinManager.replace( + createdPin.requestid, + TEST_CID_2, + { + name: `${testPinName}-replaced`, + }, + ); + assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); + assert.strictEqual(replacedPin.pin.name, `${testPinName}-replaced`); + await pinManager.delete(replacedPin.requestid); + } finally { + await deleteBucket(testBucketName); + } }); test("replace pin without name", async () => { - const testPinName = `${TEST_PREFIX}-replace-pin-test-pass`, + const testBucketName = `${TEST_PREFIX}-replace-pin-test-pass`, + testPinName = `${TEST_PREFIX}-replace-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { - bucket: TEST_BUCKET, + bucket: testBucketName, }, ); - await ensureBucketExists(TEST_BUCKET); - const createdPin = await pinManager.create(testPinName, TEST_CID_1); - assert.strictEqual(createdPin.pin.cid, TEST_CID_1); - const replacedPin = await pinManager.replace( - createdPin.requestid, - TEST_CID_2, - ); - assert.strictEqual(replacedPin.pin.name, testPinName); - assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); - await pinManager.delete(replacedPin.requestid); + await createBucket(testBucketName); + try { + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + const replacedPin = await pinManager.replace( + createdPin.requestid, + TEST_CID_2, + ); + assert.strictEqual(replacedPin.pin.name, testPinName); + assert.strictEqual(replacedPin.pin.cid, TEST_CID_2); + await pinManager.delete(replacedPin.requestid); + } finally { + await deleteBucket(testBucketName); + } }); test("get pin", async () => { - const testPinName = `${TEST_PREFIX}-get-pin-test-pass`, + const testBucketName = `${TEST_PREFIX}-get-pin-test-pass`, + testPinName = `${TEST_PREFIX}-get-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { - bucket: TEST_BUCKET, + bucket: testBucketName, }, ); - await ensureBucketExists(TEST_BUCKET); - const createdPin = await pinManager.create(testPinName, TEST_CID_1); - assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + await createBucket(testBucketName); try { - const queriedPin = await pinManager.get(createdPin.requestid); - assert.strictEqual(queriedPin.requestid, createdPin.requestid); - assert.strictEqual(queriedPin.pin.cid, TEST_CID_1); + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + try { + const queriedPin = await pinManager.get(createdPin.requestid); + assert.strictEqual(queriedPin.requestid, createdPin.requestid); + assert.strictEqual(queriedPin.pin.cid, TEST_CID_1); + } finally { + await pinManager.delete(createdPin.requestid); + } } finally { - await pinManager.delete(createdPin.requestid); + await deleteBucket(testBucketName); } }); test("download pin", async () => { - const testPinName = `${TEST_PREFIX}-download-pin-test-pass`, + const testBucketName = `${TEST_PREFIX}-download-pin-test-pass`, + testPinName = `${TEST_PREFIX}-download-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { - bucket: TEST_BUCKET, + bucket: testBucketName, gateway: { endpoint: process.env.TEST_IPFS_GATEWAY, }, }, ); - await ensureBucketExists(TEST_BUCKET); - const createdPin = await pinManager.create(testPinName, TEST_CID_1); - assert.strictEqual(createdPin.pin.cid, TEST_CID_1); - const downloadStream = await pinManager.download(createdPin.pin.cid), - downloadFilename = uuidv4(), - downloadPath = Path.resolve(os.tmpdir(), downloadFilename), - writeFileResult = await writeFile(downloadPath, downloadStream); - assert.strictEqual(typeof writeFileResult, "undefined"); + await createBucket(testBucketName); + try { + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + try { + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + const downloadStream = await pinManager.download(createdPin.pin.cid), + downloadFilename = uuidv4(), + downloadPath = Path.resolve(os.tmpdir(), downloadFilename), + writeFileResult = await writeFile(downloadPath, downloadStream); + assert.strictEqual(typeof writeFileResult, "undefined"); + } finally { + await pinManager.delete(createdPin.requestid); + } + } finally { + await deleteBucket(testBucketName); + } }); test("download pin by reference", async () => { - const testPinName = `${TEST_PREFIX}-download-pin-test-pass`, + const testBucketName = `${TEST_PREFIX}-download-ref-test-pass`, + testPinName = `${TEST_PREFIX}-download-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { - bucket: TEST_BUCKET, + bucket: testBucketName, gateway: { endpoint: process.env.TEST_IPFS_GATEWAY, }, }, ); - await ensureBucketExists(TEST_BUCKET); - const createdPin = await pinManager.create(testPinName, TEST_CID_1); - assert.strictEqual(createdPin.pin.cid, TEST_CID_1); - const pinToDownload = await pinManager.get(createdPin.requestid), - downloadStream = await pinToDownload.download(), - downloadFilename = uuidv4(), - downloadPath = Path.resolve(os.tmpdir(), downloadFilename), - writeFileResult = await writeFile(downloadPath, downloadStream); - assert.strictEqual(typeof writeFileResult, "undefined"); + await createBucket(testBucketName); + try { + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + try { + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + const pinToDownload = await pinManager.get(createdPin.requestid), + downloadStream = await pinToDownload.download(), + downloadFilename = uuidv4(), + downloadPath = Path.resolve(os.tmpdir(), downloadFilename), + writeFileResult = await writeFile(downloadPath, downloadStream); + assert.strictEqual(typeof writeFileResult, "undefined"); + } finally { + await pinManager.delete(createdPin.requestid); + } + } finally { + await deleteBucket(testBucketName); + } }); test("list pins", async () => { - const testPinName = `${TEST_PREFIX}-list-pin-test-pass`, + const testBucketName = `${TEST_PREFIX}-list-pin-test-pass`, + testPinName = `${TEST_PREFIX}-list-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { - bucket: TEST_BUCKET, + bucket: testBucketName, }, ); - await ensureBucketExists(TEST_BUCKET); - const existingPinList = await pinManager.list(), - countToCreate = 25; - let createdPins = []; - for (let i = 0; i < countToCreate; i++) { - createdPins.push( - await pinManager.create(`${testPinName}_${i}`, TEST_CID_1), - ); - } + await createBucket(testBucketName); try { - const pinList = await pinManager.list(); - assert.strictEqual(pinList.count, existingPinList.count + countToCreate); - } finally { - for (const createdPin of createdPins) { - await pinManager.delete(createdPin.requestid); + const existingPinList = await pinManager.list(), + countToCreate = 25; + let createdPins = []; + for (let i = 0; i < countToCreate; i++) { + createdPins.push( + await pinManager.create(`${testPinName}_${i}`, TEST_CID_1), + ); } + try { + const pinList = await pinManager.list(); + assert.strictEqual(pinList.count, existingPinList.count + countToCreate); + } finally { + for (const createdPin of createdPins) { + await pinManager.delete(createdPin.requestid); + } + } + } finally { + await deleteBucket(testBucketName); } }); test("delete pin", async () => { - const testPinName = `${TEST_PREFIX}-delete-pin-test-pass`, + const testBucketName = `${TEST_PREFIX}-delete-pin-test-pass`, + testPinName = `${TEST_PREFIX}-delete-pin-test-pass`, pinManager = new PinManager( process.env.TEST_NAME_KEY || process.env.TEST_KEY, process.env.TEST_NAME_SECRET || process.env.TEST_SECRET, { - bucket: TEST_BUCKET, + bucket: testBucketName, }, ); - await ensureBucketExists(TEST_BUCKET); - const createdPin = await pinManager.create(testPinName, TEST_CID_1); - assert.strictEqual(createdPin.pin.cid, TEST_CID_1); - await pinManager.delete(createdPin.requestid); - const deletedPin = await pinManager.get(createdPin.requestid); - assert.strictEqual(deletedPin, false); + await createBucket(testBucketName); + try { + const createdPin = await pinManager.create(testPinName, TEST_CID_1); + assert.strictEqual(createdPin.pin.cid, TEST_CID_1); + await pinManager.delete(createdPin.requestid); + const deletedPin = await pinManager.get(createdPin.requestid); + assert.strictEqual(deletedPin, false); + } finally { + await deleteBucket(testBucketName); + } }); From f45d9068832b4ce75789454dafed5f37092da13b Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:49:30 -0600 Subject: [PATCH 78/79] Update test.yml Change Test Name for Better Naming --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 06b0b28..2885f93 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: Node.js CI +name: Build SDK and Test on: [push] From dfb884ce3b2e8df69891595ad8eecc9e9294ee5c Mon Sep 17 00:00:00 2001 From: jtsmedley <38006759+jtsmedley@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:56:49 -0600 Subject: [PATCH 79/79] Fix Tutorials --- tutorials/quickstart-bucket.md | 2 +- tutorials/quickstart-gateway.md | 3 +++ tutorials/quickstart-name.md | 3 +++ tutorials/quickstart-object.md | 2 +- tutorials/quickstart-pin.md | 3 +++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tutorials/quickstart-bucket.md b/tutorials/quickstart-bucket.md index f6de811..b93bd22 100644 --- a/tutorials/quickstart-bucket.md +++ b/tutorials/quickstart-bucket.md @@ -1,7 +1,7 @@ **node.js** ````js // Import Classes -import {BucketManager} from 'filebase-sdk' +import {BucketManager} from 'filebase-sdk'; // Initialize BucketManager const bucketManager = new BucketManager(S3_KEY, S3_SECRET); diff --git a/tutorials/quickstart-gateway.md b/tutorials/quickstart-gateway.md index 679c987..34816d0 100644 --- a/tutorials/quickstart-gateway.md +++ b/tutorials/quickstart-gateway.md @@ -1,5 +1,8 @@ **node.js** ````js +// Import Classes +import {GatewayManager} from 'filebase-sdk'; + // Initialize GatewayManager const gatewayManager = new GatewayManager(S3_KEY, S3_SECRET); diff --git a/tutorials/quickstart-name.md b/tutorials/quickstart-name.md index 441683b..0decf63 100644 --- a/tutorials/quickstart-name.md +++ b/tutorials/quickstart-name.md @@ -1,5 +1,8 @@ **node.js** ````js +// Import Classes +import {NameManager} from 'filebase-sdk'; + // Initialize NameManager const nameManager = new NameManager(S3_KEY, S3_SECRET); diff --git a/tutorials/quickstart-object.md b/tutorials/quickstart-object.md index 746468b..0b4df4a 100644 --- a/tutorials/quickstart-object.md +++ b/tutorials/quickstart-object.md @@ -1,7 +1,7 @@ **node.js** ````js // Import Classes -import {ObjectManager} from 'filebase-sdk' +import {ObjectManager} from 'filebase-sdk'; // Initialize ObjectManager const bucketName = `create-object-[random string]`; diff --git a/tutorials/quickstart-pin.md b/tutorials/quickstart-pin.md index 832a999..fc91a8d 100644 --- a/tutorials/quickstart-pin.md +++ b/tutorials/quickstart-pin.md @@ -1,5 +1,8 @@ **node.js** ````js +// Import Classes +import {PinManager} from 'filebase-sdk'; + // Initialize PinManager const pinManager = new PinManager(S3_KEY, S3_SECRET, { bucket: bucketName,