From c47a6335b77d5284711f13a83349000820f85775 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 10 Mar 2021 12:29:53 +0000 Subject: [PATCH 01/34] "chore: updated example dependencies" --- examples/browser-add-readable-stream/package.json | 2 +- examples/browser-browserify/package.json | 2 +- examples/browser-create-react-app/package.json | 2 +- examples/browser-exchange-files/package.json | 4 ++-- examples/browser-http-client-upload-file/package.json | 4 ++-- examples/browser-ipns-publish/package.json | 4 ++-- examples/browser-mfs/package.json | 2 +- examples/browser-parceljs/package.json | 2 +- examples/browser-readablestream/package.json | 2 +- examples/browser-script-tag/package.json | 2 +- examples/browser-service-worker/package.json | 6 +++--- examples/browser-sharing-node-across-tabs/package.json | 6 +++--- examples/browser-video-streaming/package.json | 2 +- examples/browser-vue/package.json | 2 +- examples/browser-webpack/package.json | 2 +- examples/circuit-relaying/package.json | 4 ++-- examples/custom-ipfs-repo/package.json | 2 +- examples/custom-ipld-formats/package.json | 6 +++--- examples/custom-libp2p/package.json | 2 +- examples/explore-ethereum-blockchain/package.json | 4 ++-- examples/http-client-browser-pubsub/package.json | 4 ++-- examples/http-client-bundle-webpack/package.json | 4 ++-- examples/http-client-name-api/package.json | 2 +- examples/ipfs-101/package.json | 2 +- examples/ipfs-client-add-files/package.json | 4 ++-- examples/run-in-electron/package.json | 2 +- examples/running-multiple-nodes/package.json | 2 +- examples/traverse-ipld-graphs/package.json | 2 +- examples/types-use-ipfs-from-ts/package.json | 2 +- examples/types-use-ipfs-from-typed-js/package.json | 2 +- 30 files changed, 44 insertions(+), 44 deletions(-) diff --git a/examples/browser-add-readable-stream/package.json b/examples/browser-add-readable-stream/package.json index 81c0b612c6..65be515077 100644 --- a/examples/browser-add-readable-stream/package.json +++ b/examples/browser-add-readable-stream/package.json @@ -12,7 +12,7 @@ "keywords": [], "license": "MIT", "devDependencies": { - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "test-ipfs-example": "^3.0.0" } } diff --git a/examples/browser-browserify/package.json b/examples/browser-browserify/package.json index 42f282d940..5d2e005340 100644 --- a/examples/browser-browserify/package.json +++ b/examples/browser-browserify/package.json @@ -18,7 +18,7 @@ "concat-stream": "^2.0.0", "execa": "^5.0.0", "http-server": "^0.12.3", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" } diff --git a/examples/browser-create-react-app/package.json b/examples/browser-create-react-app/package.json index 9adcdebc2b..20e06a5074 100644 --- a/examples/browser-create-react-app/package.json +++ b/examples/browser-create-react-app/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "dot-prop": "^5.0.0", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "ipfs-css": "^0.13.1", "react": "^16.8.6", "react-dom": "^16.8.6", diff --git a/examples/browser-exchange-files/package.json b/examples/browser-exchange-files/package.json index f57c946c87..0e55f015da 100644 --- a/examples/browser-exchange-files/package.json +++ b/examples/browser-exchange-files/package.json @@ -14,11 +14,11 @@ "browserify": "^16.2.3", "execa": "^5.0.0", "http-server": "^0.12.3", - "ipfs-http-client": "^49.0.3", + "ipfs-http-client": "^49.0.4", "uint8arrays": "^2.1.3" }, "dependencies": { - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "it-all": "^1.0.4", "libp2p-websockets": "^0.15.1", "rimraf": "^3.0.2", diff --git a/examples/browser-http-client-upload-file/package.json b/examples/browser-http-client-upload-file/package.json index fc605c9369..00c5bccf83 100644 --- a/examples/browser-http-client-upload-file/package.json +++ b/examples/browser-http-client-upload-file/package.json @@ -15,10 +15,10 @@ ], "license": "MIT", "dependencies": { - "ipfs-http-client": "^49.0.3" + "ipfs-http-client": "^49.0.4" }, "devDependencies": { - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "parcel-bundler": "^1.12.4", "react": "^16.8.6", "react-dom": "^16.8.6", diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index a1d0a963d2..583c291f86 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -13,8 +13,8 @@ "license": "MIT", "dependencies": { "human-crypto-keys": "^0.1.4", - "ipfs": "^0.54.3", - "ipfs-http-client": "^49.0.3", + "ipfs": "^0.54.4", + "ipfs-http-client": "^49.0.4", "ipfs-utils": "^6.0.1", "ipns": "^0.8.0", "it-last": "^1.0.4", diff --git a/examples/browser-mfs/package.json b/examples/browser-mfs/package.json index 5865468e97..285768720d 100644 --- a/examples/browser-mfs/package.json +++ b/examples/browser-mfs/package.json @@ -22,7 +22,7 @@ "webpack-cli": "^3.3.11" }, "dependencies": { - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "mime-sniffer": "~0.0.3" } } diff --git a/examples/browser-parceljs/package.json b/examples/browser-parceljs/package.json index 844203ec12..5766fd7256 100644 --- a/examples/browser-parceljs/package.json +++ b/examples/browser-parceljs/package.json @@ -18,7 +18,7 @@ "author": "", "license": "ISC", "dependencies": { - "ipfs": "^0.54.3" + "ipfs": "^0.54.4" }, "devDependencies": { "@babel/cli": "7.13.0", diff --git a/examples/browser-readablestream/package.json b/examples/browser-readablestream/package.json index ee3c119cac..2220248092 100644 --- a/examples/browser-readablestream/package.json +++ b/examples/browser-readablestream/package.json @@ -21,7 +21,7 @@ "webpack": "^4.43.0" }, "dependencies": { - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "it-to-stream": "^0.1.2", "videostream": "^3.2.0" } diff --git a/examples/browser-script-tag/package.json b/examples/browser-script-tag/package.json index 5b0eb1f28c..bd7184a098 100644 --- a/examples/browser-script-tag/package.json +++ b/examples/browser-script-tag/package.json @@ -16,6 +16,6 @@ "test-ipfs-example": "^3.0.0" }, "dependencies": { - "ipfs": "^0.54.3" + "ipfs": "^0.54.4" } } diff --git a/examples/browser-service-worker/package.json b/examples/browser-service-worker/package.json index 1692364545..8718350059 100644 --- a/examples/browser-service-worker/package.json +++ b/examples/browser-service-worker/package.json @@ -22,10 +22,10 @@ "webpack-dev-server": "3.11.0" }, "dependencies": { - "ipfs": "^0.54.3", - "ipfs-message-port-client": "^0.5.3", + "ipfs": "^0.54.4", + "ipfs-message-port-client": "^0.5.4", "ipfs-message-port-protocol": "^0.6.1", - "ipfs-message-port-server": "^0.6.2", + "ipfs-message-port-server": "^0.6.3", "process": "0.11.10" }, "browserslist": [ diff --git a/examples/browser-sharing-node-across-tabs/package.json b/examples/browser-sharing-node-across-tabs/package.json index 9b5afc03a2..66c281deb4 100644 --- a/examples/browser-sharing-node-across-tabs/package.json +++ b/examples/browser-sharing-node-across-tabs/package.json @@ -24,9 +24,9 @@ "worker-plugin": "4.0.3" }, "dependencies": { - "ipfs": "^0.54.3", - "ipfs-message-port-client": "^0.5.3", - "ipfs-message-port-server": "^0.6.2" + "ipfs": "^0.54.4", + "ipfs-message-port-client": "^0.5.4", + "ipfs-message-port-server": "^0.6.3" }, "browserslist": [ ">1%", diff --git a/examples/browser-video-streaming/package.json b/examples/browser-video-streaming/package.json index eaa626d079..608a17823d 100644 --- a/examples/browser-video-streaming/package.json +++ b/examples/browser-video-streaming/package.json @@ -16,6 +16,6 @@ "test-ipfs-example": "^3.0.0" }, "dependencies": { - "ipfs": "^0.54.3" + "ipfs": "^0.54.4" } } diff --git a/examples/browser-vue/package.json b/examples/browser-vue/package.json index e9b2abada3..476d75c225 100644 --- a/examples/browser-vue/package.json +++ b/examples/browser-vue/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "core-js": "^3.6.4", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "vue": "^2.6.11" }, "devDependencies": { diff --git a/examples/browser-webpack/package.json b/examples/browser-webpack/package.json index c3a8934ae7..ab8da74e8d 100644 --- a/examples/browser-webpack/package.json +++ b/examples/browser-webpack/package.json @@ -29,7 +29,7 @@ "webpack-dev-server": "^3.11.0" }, "dependencies": { - "ipfs": "^0.54.3" + "ipfs": "^0.54.4" }, "browserslist": [ ">1%", diff --git a/examples/circuit-relaying/package.json b/examples/circuit-relaying/package.json index 6a7a3b6b37..1205ef0dad 100644 --- a/examples/circuit-relaying/package.json +++ b/examples/circuit-relaying/package.json @@ -15,7 +15,7 @@ "license": "MIT", "dependencies": { "delay": "^4.4.0", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "ipfs-pubsub-room": "^2.0.1", "libp2p-websockets": "^0.15.1", "uint8arrays": "^2.1.3" @@ -23,7 +23,7 @@ "devDependencies": { "execa": "^5.0.0", "ipfs-css": "^0.13.1", - "ipfs-http-client": "^49.0.3", + "ipfs-http-client": "^49.0.4", "parcel-bundler": "^1.12.4", "rimraf": "^3.0.2", "tachyons": "^4.11.1", diff --git a/examples/custom-ipfs-repo/package.json b/examples/custom-ipfs-repo/package.json index 4ffb713406..27bb5ded62 100644 --- a/examples/custom-ipfs-repo/package.json +++ b/examples/custom-ipfs-repo/package.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "datastore-fs": "^2.0.0", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "ipfs-repo": "^8.0.0", "it-all": "^1.0.4" }, diff --git a/examples/custom-ipld-formats/package.json b/examples/custom-ipld-formats/package.json index 38d2132063..b48f4901f7 100644 --- a/examples/custom-ipld-formats/package.json +++ b/examples/custom-ipld-formats/package.json @@ -12,9 +12,9 @@ }, "dependencies": { "cids": "^1.1.5", - "ipfs-daemon": "^0.5.3", - "ipfs-core": "^0.5.3", - "ipfs-http-client": "^49.0.3", + "ipfs-daemon": "^0.5.4", + "ipfs-core": "^0.5.4", + "ipfs-http-client": "^49.0.4", "multicodec": "^3.0.1", "multihashing-async": "^2.1.2", "uint8arrays": "^2.1.3" diff --git a/examples/custom-libp2p/package.json b/examples/custom-libp2p/package.json index 1c216dd16f..0c0c98daca 100644 --- a/examples/custom-libp2p/package.json +++ b/examples/custom-libp2p/package.json @@ -10,7 +10,7 @@ }, "license": "MIT", "dependencies": { - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "libp2p": "^0.30.7", "libp2p-bootstrap": "^0.12.1", "libp2p-kad-dht": "^0.20.1", diff --git a/examples/explore-ethereum-blockchain/package.json b/examples/explore-ethereum-blockchain/package.json index 689d3a8269..043a608d40 100644 --- a/examples/explore-ethereum-blockchain/package.json +++ b/examples/explore-ethereum-blockchain/package.json @@ -10,8 +10,8 @@ "keywords": [], "license": "MIT", "devDependencies": { - "ipfs": "^0.54.3", - "ipfs-http-client": "^49.0.3", + "ipfs": "^0.54.4", + "ipfs-http-client": "^49.0.4", "ipfsd-ctl": "^7.2.0", "ipld-ethereum": "^5.0.1", "test-ipfs-example": "^3.0.0" diff --git a/examples/http-client-browser-pubsub/package.json b/examples/http-client-browser-pubsub/package.json index c9ece3e21e..cea1d63619 100644 --- a/examples/http-client-browser-pubsub/package.json +++ b/examples/http-client-browser-pubsub/package.json @@ -12,7 +12,7 @@ "author": "Alan Shaw", "license": "MIT", "dependencies": { - "ipfs-http-client": "^49.0.3" + "ipfs-http-client": "^49.0.4" }, "browserslist": [ "last 2 versions and not dead and > 2%" @@ -20,7 +20,7 @@ "devDependencies": { "execa": "^5.0.0", "go-ipfs": "0.8.0", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "ipfsd-ctl": "^7.2.0", "parcel-bundler": "^1.12.4", "test-ipfs-example": "^3.0.0" diff --git a/examples/http-client-bundle-webpack/package.json b/examples/http-client-bundle-webpack/package.json index 70b21a17c4..af73e64b30 100644 --- a/examples/http-client-bundle-webpack/package.json +++ b/examples/http-client-bundle-webpack/package.json @@ -13,7 +13,7 @@ "license": "MIT", "keywords": [], "dependencies": { - "ipfs-http-client": "^49.0.3", + "ipfs-http-client": "^49.0.4", "react": "^16.8.6", "react-dom": "^16.8.6" }, @@ -24,7 +24,7 @@ "babel-loader": "^8.2.2", "copy-webpack-plugin": "^5.0.4", "execa": "^5.0.0", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "ipfsd-ctl": "^7.2.0", "react-hot-loader": "^4.12.21", "rimraf": "^3.0.2", diff --git a/examples/http-client-name-api/package.json b/examples/http-client-name-api/package.json index f5763f701c..ba26c5d75a 100644 --- a/examples/http-client-name-api/package.json +++ b/examples/http-client-name-api/package.json @@ -13,7 +13,7 @@ "author": "Tara Vancil ", "license": "MIT", "dependencies": { - "ipfs-http-client": "^49.0.3" + "ipfs-http-client": "^49.0.4" }, "devDependencies": { "execa": "^5.0.0", diff --git a/examples/ipfs-101/package.json b/examples/ipfs-101/package.json index fb984205fe..1f3a606e8e 100644 --- a/examples/ipfs-101/package.json +++ b/examples/ipfs-101/package.json @@ -10,7 +10,7 @@ "author": "David Dias ", "license": "MIT", "dependencies": { - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "it-all": "^1.0.4", "uint8arrays": "^2.1.3" }, diff --git a/examples/ipfs-client-add-files/package.json b/examples/ipfs-client-add-files/package.json index 043eea6524..04ea4bdf1e 100644 --- a/examples/ipfs-client-add-files/package.json +++ b/examples/ipfs-client-add-files/package.json @@ -11,11 +11,11 @@ "test": "test-ipfs-example" }, "dependencies": { - "ipfs-client": "^0.3.3" + "ipfs-client": "^0.3.4" }, "devDependencies": { "execa": "^5.0.0", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "ipfsd-ctl": "^7.2.0", "parcel-bundler": "^1.12.4", "rimraf": "^3.0.2", diff --git a/examples/run-in-electron/package.json b/examples/run-in-electron/package.json index c69154963f..a0fa3ffc1a 100644 --- a/examples/run-in-electron/package.json +++ b/examples/run-in-electron/package.json @@ -18,7 +18,7 @@ "devDependencies": { "electron": "^11.2.1", "electron-rebuild": "^2.3.4", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "test-ipfs-example": "^3.0.0" }, "greenkeeper": { diff --git a/examples/running-multiple-nodes/package.json b/examples/running-multiple-nodes/package.json index 9506a81dc6..02e17d1c4c 100644 --- a/examples/running-multiple-nodes/package.json +++ b/examples/running-multiple-nodes/package.json @@ -13,6 +13,6 @@ "test-ipfs-example": "^3.0.0" }, "dependencies": { - "ipfs": "^0.54.3" + "ipfs": "^0.54.4" } } diff --git a/examples/traverse-ipld-graphs/package.json b/examples/traverse-ipld-graphs/package.json index f869fd1534..a6998d74a3 100644 --- a/examples/traverse-ipld-graphs/package.json +++ b/examples/traverse-ipld-graphs/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "cids": "^1.1.5", - "ipfs": "^0.54.3", + "ipfs": "^0.54.4", "ipld-block": "^0.11.0", "ipld-dag-pb": "^0.20.0", "ipld-git": "^0.6.1", diff --git a/examples/types-use-ipfs-from-ts/package.json b/examples/types-use-ipfs-from-ts/package.json index 5242d2be5a..91dad859c8 100644 --- a/examples/types-use-ipfs-from-ts/package.json +++ b/examples/types-use-ipfs-from-ts/package.json @@ -2,7 +2,7 @@ "name": "example-types-use-ipfs-from-ts", "private": true, "dependencies": { - "ipfs": "^0.54.3" + "ipfs": "^0.54.4" }, "devDependencies": { "typescript": "4.1.x" diff --git a/examples/types-use-ipfs-from-typed-js/package.json b/examples/types-use-ipfs-from-typed-js/package.json index 8bddb555a7..fba48fc6cf 100644 --- a/examples/types-use-ipfs-from-typed-js/package.json +++ b/examples/types-use-ipfs-from-typed-js/package.json @@ -2,7 +2,7 @@ "name": "example-types-use-ipfs-from-typed-js", "private": true, "dependencies": { - "ipfs": "^0.54.3" + "ipfs": "^0.54.4" }, "devDependencies": { "typescript": "4.1.x" From a192944464a4b36a60e28dca3dc42fda233320dd Mon Sep 17 00:00:00 2001 From: George Shammas Date: Mon, 22 Mar 2021 10:40:24 -0400 Subject: [PATCH 02/34] Fix duplicate and incorrect changelog link. (#3595) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf177f1e53..9cf0fc2b01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Please see the individual package changelogs for what's new: * [`/packages/ipfs/CHANGELOG.md`](./packages/ipfs/CHANGELOG.md) * [`/packages/ipfs-core-utils/CHANGELOG.md`](./packages/ipfs-core-utils/CHANGELOG.md) * [`/packages/ipfs-http-client/CHANGELOG.md`](./packages/ipfs-http-client/CHANGELOG.md) -* [`/packages/ipfs-message-port-client/CHANGELOG.md`](./packages/ipfs-http-client/CHANGELOG.md) +* [`/packages/ipfs-http-server/CHANGELOG.md`](./packages/ipfs-http-server/CHANGELOG.md) * [`/packages/ipfs-message-port-client/CHANGELOG.md`](./packages/ipfs-message-port-client/CHANGELOG.md) * [`/packages/ipfs-message-port-protocol/CHANGELOG.md`](./packages/ipfs-message-port-protocol/CHANGELOG.md) * [`/packages/ipfs-message-port-server/CHANGELOG.md`](./packages/ipfs-message-port-server/CHANGELOG.md) From a418a521574c878d7aabd0ad2fd8d516908a3756 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 31 Mar 2021 14:49:51 +0100 Subject: [PATCH 03/34] chore: upgrade deps with new typedefs (#3550) Upgrades to new version with types - Uses default aegir ts config - Fixes all ts errors - Fully types core-api in ipfs-core-types package - Makes ipfs-core implement types from ipfs-core-types package - Removes duplicate types, ipfs-core-types as single source of type truth - Reduces use of external APIs by internal components in ipfs-core - Switches to named exports BREAKING CHANGE: all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules --- .github/workflows/bundlesize.yml | 15 +- .github/workflows/typecheck.yml | 17 +- .gitignore | 3 + .travis.yml | 54 +- docs/core-api/BITSWAP.md | 14 +- docs/core-api/FILES.md | 10 +- docs/core-api/REPO.md | 8 +- docs/core-api/STATS.md | 18 +- examples/browser-browserify/src/index.js | 2 +- .../browser-create-react-app/package.json | 7 +- .../package.json | 4 +- .../src/App.js | 2 +- examples/browser-ipns-publish/package.json | 10 +- examples/browser-mfs/package.json | 8 +- examples/browser-mfs/webpack.config.js | 62 +-- examples/browser-parceljs/.babelrc | 4 - examples/browser-parceljs/package.json | 16 +- examples/browser-parceljs/public/index.js | 1 - examples/browser-readablestream/package.json | 7 +- .../browser-readablestream/webpack.config.js | 58 +- examples/browser-service-worker/package.json | 17 +- .../browser-service-worker/webpack.config.js | 11 +- .../package.json | 20 +- .../src/main.js | 3 +- .../src/worker.js | 3 +- .../webpack.config.js | 32 +- examples/browser-vue/package.json | 14 +- examples/browser-vue/vue.config.js | 19 +- examples/browser-webpack/package.json | 21 +- examples/browser-webpack/webpack.config.js | 6 +- examples/circuit-relaying/package.json | 11 +- examples/custom-ipfs-repo/package.json | 2 +- examples/custom-libp2p/package.json | 2 +- .../explore-ethereum-blockchain/package.json | 2 +- examples/http-client-browser-pubsub/index.js | 2 +- .../http-client-browser-pubsub/package.json | 8 +- .../http-client-bundle-webpack/package.json | 14 +- .../http-client-bundle-webpack/src/App.js | 2 +- .../webpack.config.js | 13 +- examples/http-client-name-api/index.js | 2 +- examples/http-client-name-api/package.json | 8 +- examples/ipfs-client-add-files/index.js | 2 +- examples/ipfs-client-add-files/package.json | 8 +- examples/traverse-ipld-graphs/package.json | 2 +- package.json | 5 +- packages/interface-ipfs-core/package.json | 25 +- .../src/bitswap/.tern-port | 1 - packages/interface-ipfs-core/src/cat.js | 2 +- packages/interface-ipfs-core/src/dag/get.js | 6 +- packages/interface-ipfs-core/src/files/cp.js | 5 +- packages/interface-ipfs-core/src/files/rm.js | 2 +- .../interface-ipfs-core/src/files/touch.js | 2 +- packages/interface-ipfs-core/src/get.js | 2 +- .../interface-ipfs-core/src/object/get.js | 4 +- .../interface-ipfs-core/src/refs-local.js | 2 +- packages/interface-ipfs-core/src/refs.js | 2 +- .../interface-ipfs-core/src/stats/utils.js | 3 +- .../src/utils/is-shard-at-path.js | 2 +- packages/ipfs-cli/package.json | 27 +- packages/ipfs-cli/src/command-alias.js | 18 +- packages/ipfs-cli/src/commands/add.js | 81 ++- packages/ipfs-cli/src/commands/bitswap.js | 3 + .../ipfs-cli/src/commands/bitswap/stat.js | 44 +- .../ipfs-cli/src/commands/bitswap/unwant.js | 12 +- .../ipfs-cli/src/commands/bitswap/wantlist.js | 7 + packages/ipfs-cli/src/commands/block.js | 3 + packages/ipfs-cli/src/commands/block/get.js | 11 + packages/ipfs-cli/src/commands/block/put.js | 14 +- packages/ipfs-cli/src/commands/block/rm.js | 13 + packages/ipfs-cli/src/commands/block/stat.js | 12 + packages/ipfs-cli/src/commands/bootstrap.js | 3 + .../ipfs-cli/src/commands/bootstrap/add.js | 14 +- .../ipfs-cli/src/commands/bootstrap/list.js | 7 +- .../ipfs-cli/src/commands/bootstrap/rm.js | 14 +- packages/ipfs-cli/src/commands/cat.js | 8 + packages/ipfs-cli/src/commands/cid.js | 3 + packages/ipfs-cli/src/commands/commands.js | 4 + packages/ipfs-cli/src/commands/config.js | 12 + packages/ipfs-cli/src/commands/config/edit.js | 4 + .../ipfs-cli/src/commands/config/profile.js | 3 + .../src/commands/config/profile/apply.js | 7 + .../src/commands/config/profile/ls.js | 5 + .../ipfs-cli/src/commands/config/replace.js | 6 + packages/ipfs-cli/src/commands/config/show.js | 5 + packages/ipfs-cli/src/commands/daemon.js | 21 +- packages/ipfs-cli/src/commands/dag.js | 3 + packages/ipfs-cli/src/commands/dag/get.js | 18 +- packages/ipfs-cli/src/commands/dag/put.js | 40 +- packages/ipfs-cli/src/commands/dag/resolve.js | 7 + packages/ipfs-cli/src/commands/dht.js | 3 + .../ipfs-cli/src/commands/dht/find-peer.js | 9 + .../src/commands/dht/find-providers.js | 12 + packages/ipfs-cli/src/commands/dht/get.js | 16 +- packages/ipfs-cli/src/commands/dht/provide.js | 12 + packages/ipfs-cli/src/commands/dht/put.js | 10 +- packages/ipfs-cli/src/commands/dht/query.js | 9 + packages/ipfs-cli/src/commands/dns.js | 14 +- packages/ipfs-cli/src/commands/files.js | 9 +- packages/ipfs-cli/src/commands/files/chmod.js | 11 + packages/ipfs-cli/src/commands/files/cp.js | 11 + packages/ipfs-cli/src/commands/files/flush.js | 7 + packages/ipfs-cli/src/commands/files/ls.js | 13 +- packages/ipfs-cli/src/commands/files/mkdir.js | 14 + packages/ipfs-cli/src/commands/files/mv.js | 21 +- packages/ipfs-cli/src/commands/files/read.js | 8 + packages/ipfs-cli/src/commands/files/rm.js | 7 + packages/ipfs-cli/src/commands/files/stat.js | 23 +- packages/ipfs-cli/src/commands/files/touch.js | 12 + packages/ipfs-cli/src/commands/files/write.js | 23 +- packages/ipfs-cli/src/commands/get.js | 11 +- packages/ipfs-cli/src/commands/id.js | 6 + packages/ipfs-cli/src/commands/init.js | 23 +- packages/ipfs-cli/src/commands/key.js | 3 + packages/ipfs-cli/src/commands/key/export.js | 8 + packages/ipfs-cli/src/commands/key/gen.js | 8 + packages/ipfs-cli/src/commands/key/import.js | 11 + packages/ipfs-cli/src/commands/key/list.js | 5 + packages/ipfs-cli/src/commands/key/rename.js | 7 + packages/ipfs-cli/src/commands/key/rm.js | 6 + packages/ipfs-cli/src/commands/ls.js | 25 +- packages/ipfs-cli/src/commands/name.js | 3 + .../ipfs-cli/src/commands/name/publish.js | 13 + packages/ipfs-cli/src/commands/name/pubsub.js | 4 +- .../src/commands/name/pubsub/cancel.js | 6 + .../src/commands/name/pubsub/state.js | 5 + .../ipfs-cli/src/commands/name/pubsub/subs.js | 5 + .../ipfs-cli/src/commands/name/resolve.js | 11 +- packages/ipfs-cli/src/commands/object.js | 4 +- packages/ipfs-cli/src/commands/object/data.js | 13 +- packages/ipfs-cli/src/commands/object/get.js | 35 +- .../ipfs-cli/src/commands/object/links.js | 16 +- packages/ipfs-cli/src/commands/object/new.js | 7 + .../ipfs-cli/src/commands/object/patch.js | 3 + .../src/commands/object/patch/add-link.js | 23 +- .../src/commands/object/patch/append-data.js | 22 +- .../src/commands/object/patch/rm-link.js | 18 +- .../src/commands/object/patch/set-data.js | 22 +- packages/ipfs-cli/src/commands/object/put.js | 16 +- packages/ipfs-cli/src/commands/object/stat.js | 23 +- packages/ipfs-cli/src/commands/pin.js | 3 + packages/ipfs-cli/src/commands/pin/add.js | 17 +- packages/ipfs-cli/src/commands/pin/ls.js | 31 +- packages/ipfs-cli/src/commands/pin/rm.js | 8 + packages/ipfs-cli/src/commands/ping.js | 7 + packages/ipfs-cli/src/commands/pubsub.js | 3 + packages/ipfs-cli/src/commands/pubsub/ls.js | 5 + .../ipfs-cli/src/commands/pubsub/peers.js | 6 + packages/ipfs-cli/src/commands/pubsub/pub.js | 14 +- packages/ipfs-cli/src/commands/pubsub/sub.js | 9 + packages/ipfs-cli/src/commands/refs-local.js | 8 +- packages/ipfs-cli/src/commands/refs.js | 14 +- packages/ipfs-cli/src/commands/repo.js | 3 + packages/ipfs-cli/src/commands/repo/gc.js | 12 +- packages/ipfs-cli/src/commands/repo/stat.js | 32 +- .../ipfs-cli/src/commands/repo/version.js | 7 +- packages/ipfs-cli/src/commands/resolve.js | 8 + packages/ipfs-cli/src/commands/shutdown.js | 6 + packages/ipfs-cli/src/commands/stats.js | 3 + packages/ipfs-cli/src/commands/stats/bw.js | 12 +- packages/ipfs-cli/src/commands/swarm.js | 3 + packages/ipfs-cli/src/commands/swarm/addrs.js | 8 + .../src/commands/swarm/addrs/local.js | 5 + .../ipfs-cli/src/commands/swarm/connect.js | 21 +- .../ipfs-cli/src/commands/swarm/disconnect.js | 21 +- packages/ipfs-cli/src/commands/swarm/peers.js | 5 + packages/ipfs-cli/src/commands/version.js | 10 + packages/ipfs-cli/src/index.js | 4 + packages/ipfs-cli/src/types.d.ts | 25 + packages/ipfs-cli/src/utils.js | 129 ++++- packages/ipfs-cli/test/add.js | 15 +- packages/ipfs-cli/test/bitswap.js | 61 ++- packages/ipfs-cli/test/block.js | 20 +- packages/ipfs-cli/test/bootstrap.js | 3 +- packages/ipfs-cli/test/dag.js | 10 +- packages/ipfs-cli/test/dht.js | 42 +- packages/ipfs-cli/test/dns.js | 16 - packages/ipfs-cli/test/files/mkdir.js | 3 +- packages/ipfs-cli/test/files/mv.js | 27 - packages/ipfs-cli/test/files/touch.js | 3 +- packages/ipfs-cli/test/files/write.js | 4 +- packages/ipfs-cli/test/get.js | 10 + packages/ipfs-cli/test/object.js | 76 ++- packages/ipfs-cli/test/pin.js | 1 - packages/ipfs-cli/test/ping.js | 16 +- packages/ipfs-cli/test/repo.js | 25 +- packages/ipfs-cli/test/swarm.js | 38 +- packages/ipfs-cli/tsconfig.json | 5 +- packages/ipfs-client/.aegir.js | 2 +- packages/ipfs-client/README.md | 6 +- packages/ipfs-client/package.json | 17 +- packages/ipfs-client/src/index.js | 14 +- packages/ipfs-client/tsconfig.json | 9 +- packages/ipfs-core-types/README.md | 16 +- packages/ipfs-core-types/package.json | 6 +- packages/ipfs-core-types/src/basic.ts | 39 -- packages/ipfs-core-types/src/bitswap.ts | 99 ---- .../ipfs-core-types/src/bitswap/index.d.ts | 70 +++ .../src/bitswap/moving-avarage.ts | 9 - packages/ipfs-core-types/src/block-service.ts | 25 - packages/ipfs-core-types/src/block-store.ts | 10 - packages/ipfs-core-types/src/block/index.d.ts | 156 ++++++ .../ipfs-core-types/src/bootstrap/index.ts | 71 +++ .../ipfs-core-types/src/config/index.d.ts | 125 +++++ .../src/config/profiles/index.d.ts | 28 + packages/ipfs-core-types/src/dag/index.d.ts | 227 ++++++++ packages/ipfs-core-types/src/datastore.ts | 184 ------- packages/ipfs-core-types/src/dht/index.d.ts | 94 ++++ packages/ipfs-core-types/src/diag/index.d.ts | 16 + packages/ipfs-core-types/src/files.ts | 172 ------ packages/ipfs-core-types/src/files/index.d.ts | 498 ++++++++++++++++++ packages/ipfs-core-types/src/index.d.ts | 53 ++ packages/ipfs-core-types/src/index.ts | 10 - packages/ipfs-core-types/src/ipld.ts | 42 -- packages/ipfs-core-types/src/ipld/format.ts | 42 -- packages/ipfs-core-types/src/key/index.d.ts | 126 +++++ packages/ipfs-core-types/src/log/index.d.ts | 7 + packages/ipfs-core-types/src/name/index.d.ts | 94 ++++ .../src/name/pubsub/index.d.ts | 49 ++ .../ipfs-core-types/src/object/index.d.ts | 34 ++ .../src/object/patch/index.d.ts | 10 + packages/ipfs-core-types/src/pin/index.d.ts | 175 ++++++ .../src/pin/{remote.ts => remote/index.d.ts} | 16 +- .../remote/{service.ts => service/index.d.ts} | 14 +- packages/ipfs-core-types/src/preload.ts | 3 - .../ipfs-core-types/src/pubsub/index.d.ts | 84 +++ packages/ipfs-core-types/src/refs/index.d.ts | 31 ++ packages/ipfs-core-types/src/repo.ts | 102 ---- packages/ipfs-core-types/src/repo/index.d.ts | 44 ++ packages/ipfs-core-types/src/root.d.ts | 345 ++++++++++++ packages/ipfs-core-types/src/root.ts | 111 ---- packages/ipfs-core-types/src/stats/index.d.ts | 28 + packages/ipfs-core-types/src/store.ts | 124 ----- packages/ipfs-core-types/src/swarm/index.d.ts | 53 ++ packages/ipfs-core-types/src/utils.d.ts | 134 +++++ packages/ipfs-core-types/tsconfig.json | 4 +- packages/ipfs-core-utils/package.json | 24 +- .../ipfs-core-utils/src/files/format-mode.js | 9 +- .../ipfs-core-utils/src/files/format-mtime.js | 4 +- .../files/normalise-input/index.browser.js | 10 +- .../src/files/normalise-input/index.js | 11 +- .../normalise-content.browser.js | 4 +- .../normalise-input/normalise-content.js | 5 +- .../files/normalise-input/normalise-input.js | 43 +- .../src/files/normalise-input/utils.js | 89 +--- .../src/pins/normalise-input.js | 56 +- packages/ipfs-core-utils/src/to-url-string.js | 1 + .../src/with-timeout-option.js | 3 + packages/ipfs-core-utils/tsconfig.json | 5 +- packages/ipfs-core/.aegir.js | 2 +- packages/ipfs-core/package.json | 65 +-- .../ipfs-core/src/components/add-all/index.js | 63 ++- packages/ipfs-core/src/components/add.js | 19 +- .../ipfs-core/src/components/bitswap/index.js | 14 +- .../ipfs-core/src/components/bitswap/stat.js | 58 +- .../src/components/bitswap/unwant.js | 29 +- .../components/bitswap/wantlist-for-peer.js | 29 +- .../src/components/bitswap/wantlist.js | 21 +- .../ipfs-core/src/components/block/get.js | 25 +- .../ipfs-core/src/components/block/index.js | 19 +- .../ipfs-core/src/components/block/put.js | 65 +-- packages/ipfs-core/src/components/block/rm.js | 48 +- .../ipfs-core/src/components/block/stat.js | 33 +- .../ipfs-core/src/components/bootstrap/add.js | 37 +- .../src/components/bootstrap/clear.js | 21 +- .../src/components/bootstrap/index.js | 9 +- .../src/components/bootstrap/list.js | 22 +- .../src/components/bootstrap/reset.js | 21 +- .../ipfs-core/src/components/bootstrap/rm.js | 23 +- .../src/components/bootstrap/utils.js | 9 - packages/ipfs-core/src/components/cat.js | 14 +- packages/ipfs-core/src/components/config.js | 363 +------------ packages/ipfs-core/src/components/dag/get.js | 68 +-- .../ipfs-core/src/components/dag/index.js | 65 +-- packages/ipfs-core/src/components/dag/put.js | 86 +-- .../ipfs-core/src/components/dag/resolve.js | 47 +- packages/ipfs-core/src/components/dag/tree.js | 55 +- packages/ipfs-core/src/components/dht.js | 123 +---- packages/ipfs-core/src/components/dns.js | 19 +- .../ipfs-core/src/components/files/chmod.js | 129 +++-- packages/ipfs-core/src/components/files/cp.js | 109 ++-- .../ipfs-core/src/components/files/flush.js | 30 +- .../ipfs-core/src/components/files/index.js | 95 ++-- packages/ipfs-core/src/components/files/ls.js | 96 +--- .../ipfs-core/src/components/files/mkdir.js | 78 +-- packages/ipfs-core/src/components/files/mv.js | 70 ++- .../ipfs-core/src/components/files/read.js | 48 +- packages/ipfs-core/src/components/files/rm.js | 64 ++- .../ipfs-core/src/components/files/stat.js | 159 +++--- .../ipfs-core/src/components/files/touch.js | 60 +-- .../src/components/files/utils/add-link.js | 150 +++++- .../src/components/files/utils/create-lock.js | 13 +- .../src/components/files/utils/create-node.js | 19 +- .../src/components/files/utils/hamt-utils.js | 108 +++- .../src/components/files/utils/remove-link.js | 132 +++-- .../files/utils/to-async-iterator.js | 8 + .../src/components/files/utils/to-mfs-path.js | 216 +++++--- .../files/utils/to-path-components.js | 3 + .../files/utils/to-sources-and-destination.js | 20 - .../src/components/files/utils/to-sources.js | 27 - .../src/components/files/utils/to-trail.js | 33 +- .../src/components/files/utils/types.ts | 12 - .../components/files/utils/update-mfs-root.js | 9 + .../src/components/files/utils/update-tree.js | 21 +- .../components/files/utils/with-mfs-root.js | 12 +- .../ipfs-core/src/components/files/write.js | 166 ++++-- packages/ipfs-core/src/components/gc-lock.js | 1 + packages/ipfs-core/src/components/get.js | 11 +- packages/ipfs-core/src/components/id.js | 18 +- packages/ipfs-core/src/components/index.js | 183 ++----- packages/ipfs-core/src/components/ipld.js | 20 +- packages/ipfs-core/src/components/ipns.js | 61 ++- .../ipfs-core/src/components/is-online.js | 2 +- .../ipfs-core/src/components/key/export.js | 19 +- packages/ipfs-core/src/components/key/gen.js | 36 +- .../ipfs-core/src/components/key/import.js | 17 +- .../ipfs-core/src/components/key/index.js | 13 +- packages/ipfs-core/src/components/key/info.js | 10 +- packages/ipfs-core/src/components/key/list.js | 19 +- .../ipfs-core/src/components/key/rename.js | 28 +- packages/ipfs-core/src/components/key/rm.js | 22 +- packages/ipfs-core/src/components/libp2p.js | 29 +- packages/ipfs-core/src/components/ls.js | 35 +- .../ipfs-core/src/components/name/index.js | 40 +- .../ipfs-core/src/components/name/publish.js | 72 +-- .../src/components/name/pubsub/cancel.js | 25 +- .../src/components/name/pubsub/index.js | 10 +- .../src/components/name/pubsub/state.js | 22 +- .../src/components/name/pubsub/subs.js | 23 +- .../src/components/name/pubsub/utils.js | 18 +- .../ipfs-core/src/components/name/resolve.js | 44 +- .../ipfs-core/src/components/name/utils.js | 20 +- packages/ipfs-core/src/components/network.js | 47 +- .../ipfs-core/src/components/object/data.js | 16 +- .../ipfs-core/src/components/object/get.js | 53 +- .../ipfs-core/src/components/object/index.js | 22 +- .../ipfs-core/src/components/object/links.js | 17 +- .../ipfs-core/src/components/object/new.js | 32 +- .../src/components/object/patch/add-link.js | 9 +- .../components/object/patch/append-data.js | 10 +- .../src/components/object/patch/index.js | 16 +- .../src/components/object/patch/rm-link.js | 12 +- .../src/components/object/patch/set-data.js | 9 +- .../ipfs-core/src/components/object/put.js | 50 +- .../ipfs-core/src/components/object/stat.js | 23 +- .../ipfs-core/src/components/pin/add-all.js | 59 +-- packages/ipfs-core/src/components/pin/add.js | 33 +- .../ipfs-core/src/components/pin/index.js | 39 +- packages/ipfs-core/src/components/pin/ls.js | 70 +-- .../src/components/pin/pin-manager.js | 114 ++-- .../ipfs-core/src/components/pin/rm-all.js | 31 +- packages/ipfs-core/src/components/pin/rm.js | 33 +- packages/ipfs-core/src/components/ping.js | 28 +- packages/ipfs-core/src/components/pubsub.js | 108 +--- .../ipfs-core/src/components/refs/index.js | 135 +++-- .../ipfs-core/src/components/refs/local.js | 5 +- packages/ipfs-core/src/components/repo/gc.js | 67 ++- .../ipfs-core/src/components/repo/index.js | 16 +- .../ipfs-core/src/components/repo/stat.js | 16 +- .../ipfs-core/src/components/repo/version.js | 12 +- packages/ipfs-core/src/components/resolve.js | 55 +- packages/ipfs-core/src/components/root.js | 2 - packages/ipfs-core/src/components/start.js | 23 +- packages/ipfs-core/src/components/stats/bw.js | 64 ++- .../ipfs-core/src/components/stats/index.js | 13 +- packages/ipfs-core/src/components/stop.js | 15 +- packages/ipfs-core/src/components/storage.js | 170 +++--- .../ipfs-core/src/components/swarm/addrs.js | 18 +- .../ipfs-core/src/components/swarm/connect.js | 10 +- .../src/components/swarm/disconnect.js | 10 +- .../ipfs-core/src/components/swarm/index.js | 8 +- .../src/components/swarm/local-addrs.js | 13 +- .../ipfs-core/src/components/swarm/peers.js | 43 +- packages/ipfs-core/src/components/version.js | 32 +- packages/ipfs-core/src/index.js | 1 + packages/ipfs-core/src/ipns/index.js | 50 +- packages/ipfs-core/src/ipns/publisher.js | 68 ++- packages/ipfs-core/src/ipns/republisher.js | 26 +- packages/ipfs-core/src/ipns/resolver.js | 31 +- packages/ipfs-core/src/ipns/routing/config.js | 7 + .../src/ipns/routing/offline-datastore.js | 13 +- .../src/ipns/routing/pubsub-datastore.js | 34 +- packages/ipfs-core/src/ipns/routing/utils.js | 13 +- packages/ipfs-core/src/mfs-preload.js | 23 +- packages/ipfs-core/src/preload.js | 20 +- packages/ipfs-core/src/runtime/dns-browser.js | 13 + packages/ipfs-core/src/runtime/dns-nodejs.js | 22 +- .../src/runtime/init-assets-nodejs.js | 13 +- packages/ipfs-core/src/runtime/ipld.js | 23 +- .../ipfs-core/src/runtime/libp2p-browser.js | 3 + .../ipfs-core/src/runtime/libp2p-nodejs.js | 4 + .../runtime/libp2p-pubsub-routers-nodejs.js | 1 + .../ipfs-core/src/runtime/preload-browser.js | 4 + .../ipfs-core/src/runtime/preload-nodejs.js | 4 + .../ipfs-core/src/runtime/repo-browser.js | 8 +- packages/ipfs-core/src/runtime/repo-nodejs.js | 30 +- packages/ipfs-core/src/types.d.ts | 230 ++++++++ packages/ipfs-core/src/utils.js | 59 +-- packages/ipfs-core/src/utils/service.js | 57 +- packages/ipfs-core/test/name.spec.js | 3 +- packages/ipfs-core/test/utils.js | 10 +- .../test/utils/mock-preload-node-utils.js | 1 + packages/ipfs-core/tsconfig.json | 5 +- packages/ipfs-daemon/package.json | 14 +- packages/ipfs-daemon/src/index.js | 33 +- packages/ipfs-daemon/test/index.spec.js | 5 +- packages/ipfs-daemon/tsconfig.json | 8 +- packages/ipfs-grpc-client/.aegir.js | 2 +- packages/ipfs-grpc-client/README.md | 6 +- packages/ipfs-grpc-client/package.json | 23 +- .../ipfs-grpc-client/src/core-api/add-all.js | 47 +- .../ipfs-grpc-client/src/core-api/files/ls.js | 10 +- .../src/core-api/files/write.js | 56 +- packages/ipfs-grpc-client/src/core-api/id.js | 10 +- .../src/grpc/transport.node.js | 37 +- packages/ipfs-grpc-client/src/index.js | 40 +- packages/ipfs-grpc-client/src/types.d.ts | 15 + .../src/utils/bidi-to-duplex.js | 28 +- .../src/utils/client-stream-to-promise.js | 16 +- .../src/utils/load-services.js | 16 +- .../src/utils/server-stream-to-iterator.js | 12 +- .../ipfs-grpc-client/src/utils/to-headers.js | 10 +- .../src/utils/unary-to-promise.js | 14 +- packages/ipfs-grpc-client/test/agent.js | 4 +- packages/ipfs-grpc-client/test/utils.spec.js | 8 +- packages/ipfs-grpc-client/tsconfig.json | 7 +- packages/ipfs-grpc-protocol/package.json | 3 +- packages/ipfs-grpc-server/package.json | 20 +- .../ipfs-grpc-server/src/endpoints/add.js | 11 +- packages/ipfs-grpc-server/src/endpoints/id.js | 9 + .../ipfs-grpc-server/src/endpoints/mfs/ls.js | 9 + .../src/endpoints/mfs/write.js | 11 +- packages/ipfs-grpc-server/src/index.js | 17 +- packages/ipfs-grpc-server/src/types.d.ts | 24 + .../src/utils/encode-mtime.js | 3 + .../src/utils/load-services.js | 15 + .../src/utils/web-socket-message-channel.js | 38 +- .../src/utils/web-socket-server.js | 53 +- packages/ipfs-grpc-server/tsconfig.json | 5 +- packages/ipfs-http-client/.aegir.js | 2 +- packages/ipfs-http-client/README.md | 38 +- packages/ipfs-http-client/package.json | 34 +- packages/ipfs-http-client/src/add-all.js | 9 +- packages/ipfs-http-client/src/add.js | 11 +- .../ipfs-http-client/src/bitswap/index.js | 3 + packages/ipfs-http-client/src/bitswap/stat.js | 25 +- .../ipfs-http-client/src/bitswap/unwant.js | 7 +- .../src/bitswap/wantlist-for-peer.js | 9 +- .../ipfs-http-client/src/bitswap/wantlist.js | 9 +- packages/ipfs-http-client/src/block/get.js | 7 +- packages/ipfs-http-client/src/block/index.js | 3 + packages/ipfs-http-client/src/block/put.js | 9 +- packages/ipfs-http-client/src/block/rm.js | 12 +- packages/ipfs-http-client/src/block/stat.js | 7 +- .../ipfs-http-client/src/bootstrap/add.js | 9 +- .../ipfs-http-client/src/bootstrap/clear.js | 9 +- .../ipfs-http-client/src/bootstrap/index.js | 3 + .../ipfs-http-client/src/bootstrap/list.js | 9 +- .../ipfs-http-client/src/bootstrap/reset.js | 9 +- packages/ipfs-http-client/src/bootstrap/rm.js | 9 +- packages/ipfs-http-client/src/cat.js | 7 +- packages/ipfs-http-client/src/commands.js | 11 +- packages/ipfs-http-client/src/config/get.js | 7 +- .../ipfs-http-client/src/config/getAll.js | 7 +- packages/ipfs-http-client/src/config/index.js | 3 + .../src/config/profiles/apply.js | 8 + .../src/config/profiles/index.js | 3 + .../src/config/profiles/list.js | 13 +- .../ipfs-http-client/src/config/replace.js | 7 +- packages/ipfs-http-client/src/config/set.js | 14 +- packages/ipfs-http-client/src/dag/get.js | 9 +- packages/ipfs-http-client/src/dag/index.js | 6 +- packages/ipfs-http-client/src/dag/put.js | 8 +- packages/ipfs-http-client/src/dag/resolve.js | 7 +- packages/ipfs-http-client/src/dag/tree.js | 19 + .../ipfs-http-client/src/dht/find-peer.js | 9 +- .../ipfs-http-client/src/dht/find-provs.js | 9 +- packages/ipfs-http-client/src/dht/get.js | 7 +- packages/ipfs-http-client/src/dht/index.js | 3 + packages/ipfs-http-client/src/dht/provide.js | 13 +- packages/ipfs-http-client/src/dht/put.js | 10 +- packages/ipfs-http-client/src/dht/query.js | 11 +- packages/ipfs-http-client/src/diag/cmds.js | 11 +- packages/ipfs-http-client/src/diag/index.js | 3 + packages/ipfs-http-client/src/diag/net.js | 11 +- packages/ipfs-http-client/src/diag/sys.js | 11 +- packages/ipfs-http-client/src/dns.js | 7 +- packages/ipfs-http-client/src/files/chmod.js | 8 +- packages/ipfs-http-client/src/files/cp.js | 17 +- packages/ipfs-http-client/src/files/flush.js | 8 +- packages/ipfs-http-client/src/files/index.js | 3 + packages/ipfs-http-client/src/files/ls.js | 10 +- packages/ipfs-http-client/src/files/mkdir.js | 8 +- packages/ipfs-http-client/src/files/mv.js | 17 +- packages/ipfs-http-client/src/files/read.js | 9 +- packages/ipfs-http-client/src/files/rm.js | 15 +- packages/ipfs-http-client/src/files/stat.js | 13 +- packages/ipfs-http-client/src/files/touch.js | 8 +- packages/ipfs-http-client/src/files/utils.js | 24 - packages/ipfs-http-client/src/files/write.js | 12 +- packages/ipfs-http-client/src/get.js | 8 +- packages/ipfs-http-client/src/id.js | 14 +- packages/ipfs-http-client/src/index.js | 67 +-- packages/ipfs-http-client/src/interface.ts | 57 -- packages/ipfs-http-client/src/is-online.js | 25 + packages/ipfs-http-client/src/key/export.js | 19 + packages/ipfs-http-client/src/key/gen.js | 12 +- packages/ipfs-http-client/src/key/import.js | 17 +- packages/ipfs-http-client/src/key/index.js | 7 +- packages/ipfs-http-client/src/key/info.js | 19 + packages/ipfs-http-client/src/key/list.js | 14 +- packages/ipfs-http-client/src/key/rename.js | 12 +- packages/ipfs-http-client/src/key/rm.js | 12 +- .../ipfs-http-client/src/lib/abort-signal.js | 5 +- .../src/lib/buffer-to-form-data.browser.js | 3 + .../src/lib/buffer-to-form-data.js | 4 +- .../ipfs-http-client/src/lib/configure.js | 6 +- packages/ipfs-http-client/src/lib/core.js | 60 ++- .../ipfs-http-client/src/lib/ipld-formats.js | 17 +- .../src/lib/mode-to-string.js | 7 +- .../src/lib/multipart-request.browser.js | 19 +- .../src/lib/multipart-request.node.js | 22 +- .../src/lib/object-to-camel-with-metadata.js | 3 + .../src/lib/object-to-camel.js | 25 +- .../src/lib/to-url-search-params.js | 6 +- packages/ipfs-http-client/src/log/index.js | 3 + packages/ipfs-http-client/src/log/level.js | 11 +- packages/ipfs-http-client/src/log/ls.js | 11 +- packages/ipfs-http-client/src/log/tail.js | 11 +- packages/ipfs-http-client/src/ls.js | 20 +- packages/ipfs-http-client/src/mount.js | 11 +- packages/ipfs-http-client/src/name/index.js | 3 + packages/ipfs-http-client/src/name/publish.js | 12 +- .../src/name/pubsub/cancel.js | 12 +- .../ipfs-http-client/src/name/pubsub/index.js | 3 + .../ipfs-http-client/src/name/pubsub/state.js | 12 +- .../ipfs-http-client/src/name/pubsub/subs.js | 11 +- packages/ipfs-http-client/src/name/resolve.js | 11 +- packages/ipfs-http-client/src/object/data.js | 11 +- packages/ipfs-http-client/src/object/get.js | 13 +- packages/ipfs-http-client/src/object/index.js | 3 + packages/ipfs-http-client/src/object/links.js | 13 +- packages/ipfs-http-client/src/object/new.js | 11 +- .../src/object/patch/add-link.js | 13 +- .../src/object/patch/append-data.js | 11 +- .../src/object/patch/index.js | 3 + .../src/object/patch/rm-link.js | 12 +- .../src/object/patch/set-data.js | 11 +- packages/ipfs-http-client/src/object/put.js | 35 +- packages/ipfs-http-client/src/object/stat.js | 11 +- packages/ipfs-http-client/src/pin/add-all.js | 11 +- packages/ipfs-http-client/src/pin/add.js | 25 +- packages/ipfs-http-client/src/pin/index.js | 3 + packages/ipfs-http-client/src/pin/ls.js | 24 +- .../ipfs-http-client/src/pin/remote/index.js | 174 +++--- .../src/pin/remote/service.js | 145 ++--- packages/ipfs-http-client/src/pin/rm-all.js | 13 +- packages/ipfs-http-client/src/pin/rm.js | 25 +- packages/ipfs-http-client/src/ping.js | 11 +- packages/ipfs-http-client/src/pubsub/index.js | 3 + packages/ipfs-http-client/src/pubsub/ls.js | 11 +- packages/ipfs-http-client/src/pubsub/peers.js | 16 +- .../ipfs-http-client/src/pubsub/publish.js | 11 +- .../ipfs-http-client/src/pubsub/subscribe.js | 22 +- .../src/pubsub/subscription-tracker.js | 21 + .../src/pubsub/unsubscribe.js | 20 +- packages/ipfs-http-client/src/refs/index.js | 13 +- packages/ipfs-http-client/src/refs/local.js | 11 +- packages/ipfs-http-client/src/repo/gc.js | 11 +- packages/ipfs-http-client/src/repo/index.js | 3 + packages/ipfs-http-client/src/repo/stat.js | 18 +- packages/ipfs-http-client/src/repo/version.js | 11 +- packages/ipfs-http-client/src/resolve.js | 7 +- packages/ipfs-http-client/src/start.js | 19 + packages/ipfs-http-client/src/stats/bw.js | 20 +- packages/ipfs-http-client/src/stats/index.js | 3 + packages/ipfs-http-client/src/stop.js | 11 +- packages/ipfs-http-client/src/swarm/addrs.js | 13 +- .../ipfs-http-client/src/swarm/connect.js | 15 +- .../ipfs-http-client/src/swarm/disconnect.js | 15 +- packages/ipfs-http-client/src/swarm/index.js | 3 + .../ipfs-http-client/src/swarm/localAddrs.js | 13 +- packages/ipfs-http-client/src/swarm/peers.js | 47 +- packages/ipfs-http-client/src/types.d.ts | 34 ++ packages/ipfs-http-client/src/update.js | 17 - packages/ipfs-http-client/src/version.js | 8 +- .../ipfs-http-client/test/constructor.spec.js | 2 +- packages/ipfs-http-client/test/dag.spec.js | 4 +- .../test/endpoint-config.spec.js | 2 +- packages/ipfs-http-client/test/node/agent.js | 2 +- .../test/node/custom-headers.js | 2 +- .../ipfs-http-client/test/node/request-api.js | 2 +- packages/ipfs-http-client/test/node/swarm.js | 19 +- .../ipfs-http-client/test/sub-modules.spec.js | 4 +- packages/ipfs-http-client/tsconfig.json | 9 +- packages/ipfs-http-gateway/package.json | 25 +- packages/ipfs-http-gateway/src/index.js | 41 +- .../src/resources/gateway.js | 30 +- packages/ipfs-http-gateway/src/types.d.ts | 14 + packages/ipfs-http-gateway/src/utils/path.js | 15 + .../ipfs-http-gateway/test/routes.spec.js | 28 +- packages/ipfs-http-gateway/tsconfig.json | 9 +- packages/ipfs-http-server/package.json | 23 +- .../src/api/resources/bitswap.js | 38 +- .../src/api/resources/block.js | 28 +- .../src/api/resources/bootstrap.js | 25 + .../src/api/resources/config.js | 43 +- .../ipfs-http-server/src/api/resources/dag.js | 27 +- .../ipfs-http-server/src/api/resources/dht.js | 41 +- .../ipfs-http-server/src/api/resources/dns.js | 7 +- .../src/api/resources/files-regular.js | 115 ++-- .../src/api/resources/files/chmod.js | 5 + .../src/api/resources/files/cp.js | 11 +- .../src/api/resources/files/flush.js | 5 + .../src/api/resources/files/ls.js | 30 +- .../src/api/resources/files/mkdir.js | 5 + .../src/api/resources/files/mv.js | 5 + .../src/api/resources/files/read.js | 5 + .../src/api/resources/files/rm.js | 36 +- .../src/api/resources/files/stat.js | 22 +- .../src/api/resources/files/touch.js | 5 + .../api/resources/files/utils/parse-mtime.js | 6 +- .../src/api/resources/files/write.js | 10 +- .../ipfs-http-server/src/api/resources/id.js | 4 + .../ipfs-http-server/src/api/resources/key.js | 23 + .../src/api/resources/name.js | 21 + .../src/api/resources/object.js | 79 +-- .../ipfs-http-server/src/api/resources/pin.js | 31 +- .../src/api/resources/ping.js | 7 +- .../src/api/resources/pubsub.js | 32 +- .../src/api/resources/repo.js | 19 +- .../src/api/resources/resolve.js | 4 + .../src/api/resources/shutdown.js | 4 + .../src/api/resources/stats.js | 15 +- .../src/api/resources/swarm.js | 40 +- .../src/api/resources/version.js | 4 + .../ipfs-http-server/src/api/routes/debug.js | 4 + .../ipfs-http-server/src/api/routes/webui.js | 4 + .../ipfs-http-server/src/error-handler.js | 15 +- packages/ipfs-http-server/src/index.js | 54 +- packages/ipfs-http-server/src/types.d.ts | 42 ++ packages/ipfs-http-server/src/utils/joi.js | 41 +- .../src/utils/multipart-request-parser.js | 59 ++- .../src/utils/stream-response.js | 8 + .../ipfs-http-server/test/inject/bitswap.js | 4 +- packages/ipfs-http-server/test/inject/dht.js | 10 +- packages/ipfs-http-server/test/inject/dns.js | 16 - .../ipfs-http-server/test/inject/files.js | 13 +- .../ipfs-http-server/test/inject/mfs/cp.js | 12 +- .../ipfs-http-server/test/inject/mfs/rm.js | 8 +- .../ipfs-http-server/test/inject/mfs/write.js | 1 - .../ipfs-http-server/test/inject/object.js | 21 +- packages/ipfs-http-server/test/inject/ping.js | 11 +- .../ipfs-http-server/test/inject/stats.js | 3 +- .../ipfs-http-server/test/inject/swarm.js | 14 +- packages/ipfs-http-server/tsconfig.json | 2 +- packages/ipfs-message-port-client/.aegir.js | 2 +- .../ipfs-message-port-client/package.json | 20 +- .../ipfs-message-port-client/src/block.js | 169 ++---- packages/ipfs-message-port-client/src/core.js | 265 +++++----- packages/ipfs-message-port-client/src/dag.js | 129 ++--- .../ipfs-message-port-client/src/files.js | 61 +-- .../ipfs-message-port-client/src/index.js | 42 -- .../src/interface.d.ts | 6 + .../ipfs-message-port-client/src/interface.ts | 57 -- .../test/util/worker.js | 2 +- .../ipfs-message-port-client/tsconfig.json | 10 +- .../ipfs-message-port-protocol/package.json | 20 +- .../ipfs-message-port-protocol/src/block.js | 8 + .../ipfs-message-port-protocol/src/cid.js | 2 - .../ipfs-message-port-protocol/src/dag.js | 8 +- .../src/{data.ts => data.d.ts} | 18 - .../ipfs-message-port-protocol/src/files.d.ts | 15 + .../ipfs-message-port-protocol/src/root.d.ts | 40 ++ .../src/{rpc.ts => rpc.d.ts} | 0 .../ipfs-message-port-protocol/tsconfig.json | 10 +- packages/ipfs-message-port-server/.aegir.js | 8 + .../ipfs-message-port-server/package.json | 18 +- .../ipfs-message-port-server/src/block.js | 28 +- packages/ipfs-message-port-server/src/core.js | 182 ++----- packages/ipfs-message-port-server/src/dag.js | 39 +- .../ipfs-message-port-server/src/files.js | 32 +- packages/ipfs-message-port-server/src/ipfs.ts | 241 --------- .../ipfs-message-port-server/src/service.js | 3 +- .../ipfs-message-port-server/tsconfig.json | 8 +- packages/ipfs/.aegir.js | 2 +- packages/ipfs/package.json | 27 +- packages/ipfs/src/cli.js | 36 +- packages/ipfs/tsconfig.json | 9 +- tsconfig.json | 84 --- 689 files changed, 10773 insertions(+), 7815 deletions(-) delete mode 100644 examples/browser-parceljs/.babelrc delete mode 100644 packages/interface-ipfs-core/src/bitswap/.tern-port create mode 100644 packages/ipfs-cli/src/types.d.ts delete mode 100644 packages/ipfs-core-types/src/basic.ts delete mode 100644 packages/ipfs-core-types/src/bitswap.ts create mode 100644 packages/ipfs-core-types/src/bitswap/index.d.ts delete mode 100644 packages/ipfs-core-types/src/bitswap/moving-avarage.ts delete mode 100644 packages/ipfs-core-types/src/block-service.ts delete mode 100644 packages/ipfs-core-types/src/block-store.ts create mode 100644 packages/ipfs-core-types/src/block/index.d.ts create mode 100644 packages/ipfs-core-types/src/bootstrap/index.ts create mode 100644 packages/ipfs-core-types/src/config/index.d.ts create mode 100644 packages/ipfs-core-types/src/config/profiles/index.d.ts create mode 100644 packages/ipfs-core-types/src/dag/index.d.ts delete mode 100644 packages/ipfs-core-types/src/datastore.ts create mode 100644 packages/ipfs-core-types/src/dht/index.d.ts create mode 100644 packages/ipfs-core-types/src/diag/index.d.ts delete mode 100644 packages/ipfs-core-types/src/files.ts create mode 100644 packages/ipfs-core-types/src/files/index.d.ts create mode 100644 packages/ipfs-core-types/src/index.d.ts delete mode 100644 packages/ipfs-core-types/src/index.ts delete mode 100644 packages/ipfs-core-types/src/ipld.ts delete mode 100644 packages/ipfs-core-types/src/ipld/format.ts create mode 100644 packages/ipfs-core-types/src/key/index.d.ts create mode 100644 packages/ipfs-core-types/src/log/index.d.ts create mode 100644 packages/ipfs-core-types/src/name/index.d.ts create mode 100644 packages/ipfs-core-types/src/name/pubsub/index.d.ts create mode 100644 packages/ipfs-core-types/src/object/index.d.ts create mode 100644 packages/ipfs-core-types/src/object/patch/index.d.ts create mode 100644 packages/ipfs-core-types/src/pin/index.d.ts rename packages/ipfs-core-types/src/pin/{remote.ts => remote/index.d.ts} (78%) rename packages/ipfs-core-types/src/pin/remote/{service.ts => service/index.d.ts} (65%) delete mode 100644 packages/ipfs-core-types/src/preload.ts create mode 100644 packages/ipfs-core-types/src/pubsub/index.d.ts create mode 100644 packages/ipfs-core-types/src/refs/index.d.ts delete mode 100644 packages/ipfs-core-types/src/repo.ts create mode 100644 packages/ipfs-core-types/src/repo/index.d.ts create mode 100644 packages/ipfs-core-types/src/root.d.ts delete mode 100644 packages/ipfs-core-types/src/root.ts create mode 100644 packages/ipfs-core-types/src/stats/index.d.ts delete mode 100644 packages/ipfs-core-types/src/store.ts create mode 100644 packages/ipfs-core-types/src/swarm/index.d.ts create mode 100644 packages/ipfs-core-types/src/utils.d.ts delete mode 100644 packages/ipfs-core/src/components/files/utils/to-sources-and-destination.js delete mode 100644 packages/ipfs-core/src/components/files/utils/to-sources.js delete mode 100644 packages/ipfs-core/src/components/files/utils/types.ts create mode 100644 packages/ipfs-core/src/types.d.ts create mode 100644 packages/ipfs-grpc-client/src/types.d.ts create mode 100644 packages/ipfs-grpc-server/src/types.d.ts create mode 100644 packages/ipfs-http-client/src/dag/tree.js delete mode 100644 packages/ipfs-http-client/src/files/utils.js delete mode 100644 packages/ipfs-http-client/src/interface.ts create mode 100644 packages/ipfs-http-client/src/is-online.js create mode 100644 packages/ipfs-http-client/src/key/export.js create mode 100644 packages/ipfs-http-client/src/key/info.js create mode 100644 packages/ipfs-http-client/src/start.js create mode 100644 packages/ipfs-http-client/src/types.d.ts delete mode 100644 packages/ipfs-http-client/src/update.js create mode 100644 packages/ipfs-http-gateway/src/types.d.ts create mode 100644 packages/ipfs-http-server/src/types.d.ts create mode 100644 packages/ipfs-message-port-client/src/interface.d.ts delete mode 100644 packages/ipfs-message-port-client/src/interface.ts rename packages/ipfs-message-port-protocol/src/{data.ts => data.d.ts} (58%) create mode 100644 packages/ipfs-message-port-protocol/src/files.d.ts create mode 100644 packages/ipfs-message-port-protocol/src/root.d.ts rename packages/ipfs-message-port-protocol/src/{rpc.ts => rpc.d.ts} (100%) create mode 100644 packages/ipfs-message-port-server/.aegir.js delete mode 100644 packages/ipfs-message-port-server/src/ipfs.ts delete mode 100644 tsconfig.json diff --git a/.github/workflows/bundlesize.yml b/.github/workflows/bundlesize.yml index e3ca35188e..f59aa78c38 100644 --- a/.github/workflows/bundlesize.yml +++ b/.github/workflows/bundlesize.yml @@ -10,17 +10,24 @@ jobs: runs-on: ubuntu-latest # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md strategy: matrix: + node-version: [15.x] project: - - packages/ipfs-core-utils + - packages/ipfs - packages/ipfs-core + - packages/ipfs-client + - packages/ipfs-grpc-client - packages/ipfs-http-client - - packages/ipfs - packages/ipfs-message-port-client steps: - uses: actions/checkout@v2 - - run: npm install + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - uses: actions/checkout@v2 + - run: npm install -g @mapbox/node-pre-gyp && npm install - name: Bundlesize ${{ matrix.project }} - uses: ipfs/aegir/actions/bundle-size@v31.0.4 + uses: ipfs/aegir/actions/bundle-size@v32.1.0 with: project: ${{ matrix.project }} github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 9bcb2ad555..b64158cba4 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -11,16 +11,21 @@ jobs: matrix: node-version: [14.x] project: - - packages/ipfs-core-utils - - packages/ipfs-core - - packages/ipfs-http-client - packages/ipfs - packages/ipfs-cli - - packages/ipfs-http-server + - packages/ipfs-client + - packages/ipfs-core + - packages/ipfs-core-types + - packages/ipfs-core-utils + - packages/ipfs-daemon + - packages/ipfs-grpc-client + - packages/ipfs-grpc-server + - packages/ipfs-http-client - packages/ipfs-http-gateway + - packages/ipfs-http-server + - packages/ipfs-message-port-client - packages/ipfs-message-port-protocol - packages/ipfs-message-port-server - - packages/ipfs-message-port-client steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} @@ -29,6 +34,8 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install dependencies run: npm install + - name: Build types + run: npm run build - name: Typecheck ${{ matrix.project }} uses: gozala/typescript-error-reporter-action@v1.0.8 with: diff --git a/.gitignore b/.gitignore index 0f7d8b73b7..4da7986f91 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ coverage tests_output cache .cache +.parcel-cache # Dependency directory node_modules @@ -19,6 +20,8 @@ node_modules dist build bundle.js +tsconfig-types.aegir.json +.tsbuildinfo # Deployment files .npmrc diff --git a/.travis.yml b/.travis.yml index 8c5d2841f5..6a63caff09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,10 @@ language: node_js dist: bionic +cache: + # https://travis-ci.community/t/npm-cache-on-windows-supplies-incorrect-dependency-versions/11335 + npm: false + services: - xvfb @@ -32,27 +36,27 @@ env: addons: apt: packages: - # These are required to run webkit - - libwoff1 - - libopus0 - - libwebp6 - - libwebpdemux2 - - libenchant1c2a - - libgudev-1.0-0 - - libsecret-1-0 - - libhyphen0 - - libgdk-pixbuf2.0-0 - - libegl1 - - libgles2 - - libevent-2.1-6 - - libnotify4 - - libxslt1.1 - - libvpx5 - # gstreamer and plugins to support video playback in WebKit. - - gstreamer1.0-gl - - gstreamer1.0-plugins-base - - gstreamer1.0-plugins-good - - gstreamer1.0-plugins-bad + # # These are required to run webkit + # - libwoff1 + # - libopus0 + # - libwebp6 + # - libwebpdemux2 + # - libenchant1c2a + # - libgudev-1.0-0 + # - libsecret-1-0 + # - libhyphen0 + # - libgdk-pixbuf2.0-0 + # - libegl1 + # - libgles2 + # - libevent-2.1-6 + # - libnotify4 + # - libxslt1.1 + # - libvpx5 + # # gstreamer and plugins to support video playback in WebKit. + # - gstreamer1.0-gl + # - gstreamer1.0-plugins-base + # - gstreamer1.0-plugins-good + # - gstreamer1.0-plugins-bad # This is required to run chromium - libgbm1 chrome: stable @@ -165,10 +169,10 @@ jobs: script: - npm run test:interface:core -- $RUN_SINCE -- -- --bail -t browser -- --browser firefox - - stage: test - name: js-ipfs interface tests - firefox webworker - script: - - npm run test:interface:core -- $RUN_SINCE -- -- --bail -t webworker --timeout 60000 -- --browser firefox + #- stage: test + # name: js-ipfs interface tests - firefox webworker + # script: + # - npm run test:interface:core -- $RUN_SINCE -- -- --bail -t webworker --timeout 60000 -- --browser firefox - stage: test name: js-ipfs interface tests - electron main diff --git a/docs/core-api/BITSWAP.md b/docs/core-api/BITSWAP.md index f8f6d3c02a..b882f55367 100644 --- a/docs/core-api/BITSWAP.md +++ b/docs/core-api/BITSWAP.md @@ -160,12 +160,12 @@ The returned object contains the following keys: - `provideBufLen` is an integer. - `wantlist` (array of [CID][cid]s) - `peers` (array of peer IDs represented by CIDs) -- `blocksReceived` is a [BigNumber Int][1] -- `dataReceived` is a [BigNumber Int][1] -- `blocksSent` is a [BigNumber Int][1] -- `dataSent` is a [BigNumber Int][1] -- `dupBlksReceived` is a [BigNumber Int][1] -- `dupDataReceived` is a [BigNumber Int][1] +- `blocksReceived` is a [BigInt][1] +- `dataReceived` is a [BigInt][1] +- `blocksSent` is a [BigInt][1] +- `dataSent` is a [BigInt][1] +- `dupBlksReceived` is a [BigInt][1] +- `dupDataReceived` is a [BigInt][1] ### Example @@ -190,7 +190,7 @@ console.log(stats) A great source of [examples][] can be found in the tests for this API. -[1]: https://github.com/MikeMcl/bignumber.js/ +[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/bitswap [cid]: https://www.npmjs.com/package/cids [peerid]: https://www.npmjs.com/package/peer-id diff --git a/docs/core-api/FILES.md b/docs/core-api/FILES.md index e1b21a1390..1c587b704d 100644 --- a/docs/core-api/FILES.md +++ b/docs/core-api/FILES.md @@ -65,7 +65,7 @@ _Explore the Mutable File System through interactive coding challenges in our [P - [Options](#options-9) - [Returns](#returns-9) - [Example](#example-9) - - [`ipfs.files.rm(...paths, [options])`](#ipfsfilesrmpaths-options) + - [`ipfs.files.rm(path, [options])`](#ipfsfilesrmpath-options) - [Parameters](#parameters-10) - [Options](#options-10) - [Returns](#returns-10) @@ -637,7 +637,7 @@ await ipfs.files.cp('/src-file', '/dst-file') await ipfs.files.cp('/src-dir', '/dst-dir') // To copy multiple files to a directory -await ipfs.files.cp('/src-file1', '/src-file2', '/dst-dir') +await ipfs.files.cp(['/src-file1', '/src-file2'], '/dst-dir') ``` #### Notes @@ -784,7 +784,7 @@ await ipfs.files.touch('/path/to/file.txt', { }) ``` -### `ipfs.files.rm(...paths, [options])` +### `ipfs.files.rm(path, [options])` > Remove a file or directory. @@ -820,7 +820,7 @@ An optional object which may have the following keys: await ipfs.files.rm('/my/beautiful/file.txt') // To remove multiple files -await ipfs.files.rm('/my/beautiful/file.txt', '/my/other/file.txt') +await ipfs.files.rm(['/my/beautiful/file.txt', '/my/other/file.txt']) // To remove a directory await ipfs.files.rm('/my/beautiful/directory', { recursive: true }) @@ -946,7 +946,7 @@ await ipfs.files.mv('/src-file', '/dst-file') await ipfs.files.mv('/src-dir', '/dst-dir') -await ipfs.files.mv('/src-file1', '/src-file2', '/dst-dir') +await ipfs.files.mv(['/src-file1', '/src-file2'], '/dst-dir') ``` #### Notes diff --git a/docs/core-api/REPO.md b/docs/core-api/REPO.md index a545c9a14e..834599a289 100644 --- a/docs/core-api/REPO.md +++ b/docs/core-api/REPO.md @@ -80,11 +80,11 @@ An optional object which may have the following keys: the returned object has the following keys: -- `numObjects` is a [BigNumber Int][1]. -- `repoSize` is a [BigNumber Int][1], in bytes. +- `numObjects` is a [BigInt][1]. +- `repoSize` is a [BigInt][1], in bytes. - `repoPath` is a string. - `version` is a string. -- `storageMax` is a [BigNumber Int][1]. +- `storageMax` is a [BigInt][1]. ### Example @@ -135,6 +135,6 @@ console.log(version) // "6" ``` -[1]: https://github.com/MikeMcl/bignumber.js/ +[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt [cid]: https://www.npmjs.com/package/cids [AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/STATS.md b/docs/core-api/STATS.md index d979042822..bc661c069b 100644 --- a/docs/core-api/STATS.md +++ b/docs/core-api/STATS.md @@ -49,10 +49,10 @@ An optional object which may have the following keys: Each yielded object contains the following keys: -- `totalIn` - is a [BigNumber Int][bigNumber], in bytes. -- `totalOut` - is a [BigNumber Int][bigNumber], in bytes. -- `rateIn` - is a [BigNumber Int][bigNumber], in bytes. -- `rateOut` - is a [BigNumber Int][bigNumber], in bytes. +- `totalIn` - is a [BigInt][bigNumber], in bytes. +- `totalOut` - is a [BigInt][bigNumber], in bytes. +- `rateIn` - is a [BigInt][bigNumber], in bytes. +- `rateOut` - is a [BigInt][bigNumber], in bytes. ### Example @@ -60,15 +60,15 @@ Each yielded object contains the following keys: for await (const stats of ipfs.stats.bw()) { console.log(stats) } -// { totalIn: BigNumber {...}, -// totalOut: BigNumber {...}, -// rateIn: BigNumber {...}, -// rateOut: BigNumber {...} } +// { totalIn: BigInt {...}, +// totalOut: BigInt {...}, +// rateIn: BigInt {...}, +// rateOut: BigInt {...} } ``` A great source of [examples][] can be found in the tests for this API. -[bigNumber]: https://github.com/MikeMcl/bignumber.js/ +[bigNumber]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/stats [AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal [cid]: https://www.npmjs.com/package/cids diff --git a/examples/browser-browserify/src/index.js b/examples/browser-browserify/src/index.js index 96836f860c..c99eb77391 100644 --- a/examples/browser-browserify/src/index.js +++ b/examples/browser-browserify/src/index.js @@ -25,7 +25,7 @@ document.addEventListener('DOMContentLoaded', async () => { async function display (cid) { for await (const data of node.cat(cid)) { document.getElementById('cid').innerText = cid - document.getElementById('content').innerText = data + document.getElementById('content').innerText = new TextDecoder().decode(data) document.getElementById('output').setAttribute('style', 'display: block') } } diff --git a/examples/browser-create-react-app/package.json b/examples/browser-create-react-app/package.json index 20e06a5074..9d84c3f53c 100644 --- a/examples/browser-create-react-app/package.json +++ b/examples/browser-create-react-app/package.json @@ -8,7 +8,7 @@ "ipfs-css": "^0.13.1", "react": "^16.8.6", "react-dom": "^16.8.6", - "react-scripts": "^3.2.0", + "react-scripts": "^4.0.3", "tachyons": "^4.11.1" }, "devDependencies": { @@ -26,9 +26,6 @@ "extends": "react-app" }, "browserslist": [ - ">0.2%", - "not dead", - "not ie <= 11", - "not op_mini all" + "last 2 versions and not dead and > 2%" ] } diff --git a/examples/browser-http-client-upload-file/package.json b/examples/browser-http-client-upload-file/package.json index 00c5bccf83..72cbe42151 100644 --- a/examples/browser-http-client-upload-file/package.json +++ b/examples/browser-http-client-upload-file/package.json @@ -5,7 +5,7 @@ "private": true, "scripts": { "clean": "rimraf ./dist", - "build": "parcel build index.html --public-url '.'", + "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html", "test": "test-ipfs-example" }, @@ -19,7 +19,7 @@ }, "devDependencies": { "ipfs": "^0.54.4", - "parcel-bundler": "^1.12.4", + "parcel": "next", "react": "^16.8.6", "react-dom": "^16.8.6", "rimraf": "^3.0.2", diff --git a/examples/browser-http-client-upload-file/src/App.js b/examples/browser-http-client-upload-file/src/App.js index 0fc3ed63c0..19eba88d1b 100644 --- a/examples/browser-http-client-upload-file/src/App.js +++ b/examples/browser-http-client-upload-file/src/App.js @@ -2,7 +2,7 @@ 'use strict' const React = require('react') -const ipfsClient = require('ipfs-http-client') +const { create: ipfsClient } = require('ipfs-http-client') class App extends React.Component { constructor () { diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index 583c291f86..5e0e57bddd 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -5,7 +5,7 @@ "private": true, "main": "index.js", "scripts": { - "build": "parcel build index.html --public-url ./", + "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html", "test": "test-ipfs-example" }, @@ -15,8 +15,8 @@ "human-crypto-keys": "^0.1.4", "ipfs": "^0.54.4", "ipfs-http-client": "^49.0.4", - "ipfs-utils": "^6.0.1", - "ipns": "^0.8.0", + "ipfs-utils": "^6.0.4", + "ipns": "^0.10.0", "it-last": "^1.0.4", "p-retry": "^4.2.0", "uint8arrays": "^2.1.3" @@ -27,9 +27,9 @@ "devDependencies": { "delay": "^4.4.0", "execa": "^5.0.0", - "ipfsd-ctl": "^7.2.0", + "ipfsd-ctl": "^8.0.0", "go-ipfs": "0.8.0", - "parcel-bundler": "^1.12.4", + "parcel": "next", "path": "^0.12.7", "test-ipfs-example": "^3.0.0" }, diff --git a/examples/browser-mfs/package.json b/examples/browser-mfs/package.json index 285768720d..f2cec78dce 100644 --- a/examples/browser-mfs/package.json +++ b/examples/browser-mfs/package.json @@ -13,13 +13,13 @@ "author": "", "license": "ISC", "devDependencies": { - "html-webpack-plugin": "^3.2.0", + "html-webpack-plugin": "^5.3.1", "http-server": "^0.12.3", + "node-polyfill-webpack-plugin": "^1.0.3", "rimraf": "^3.0.2", - "terser-webpack-plugin": "^1.2.1", "test-ipfs-example": "^3.0.0", - "webpack": "^4.43.0", - "webpack-cli": "^3.3.11" + "webpack": "^5.28.0", + "webpack-cli": "^4.5.0" }, "dependencies": { "ipfs": "^0.54.4", diff --git a/examples/browser-mfs/webpack.config.js b/examples/browser-mfs/webpack.config.js index fd29cf252b..95c414f71a 100644 --- a/examples/browser-mfs/webpack.config.js +++ b/examples/browser-mfs/webpack.config.js @@ -1,59 +1,33 @@ 'use strict' const path = require('path') -const TerserPlugin = require('terser-webpack-plugin') +const webpack = require('webpack') +const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { - mode: 'development', - devtool: 'source-map', + devtool: 'eval', entry: [ './index.js' ], + output: { + path: path.join(__dirname, 'dist'), + filename: 'bundle.js' + }, plugins: [ new HtmlWebpackPlugin({ title: 'IPFS MFS example', template: 'index.html' + }), + // fixes Module not found: Error: Can't resolve 'stream' in '.../node_modules/nofilter/lib' + new NodePolyfillPlugin(), + // Note: stream-browserify has assumption about `Buffer` global in its + // dependencies causing runtime errors. This is a workaround to provide + // global `Buffer` until https://github.com/isaacs/core-util-is/issues/29 + // is fixed. + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + process: 'process/browser' }) - ], - optimization: { - minimizer: [ - new TerserPlugin({ - terserOptions: { - parse: { - // we want terser to parse ecma 8 code. However, we don't want it - // to apply any minfication steps that turns valid ecma 5 code - // into invalid ecma 5 code. This is why the 'compress' and 'output' - // sections only apply transformations that are ecma 5 safe - // https://github.com/facebook/create-react-app/pull/4234 - ecma: 8 - }, - compress: { - ecma: 5, - warnings: false - }, - mangle: { - safari10: true - }, - output: { - ecma: 5, - comments: false - } - }, - // Use multi-process parallel running to improve the build speed - // Default number of concurrent runs: os.cpus().length - 1 - parallel: true, - // Enable file caching - cache: true, - sourceMap: true - }) - ] - }, - output: { - path: path.join(__dirname, 'dist'), - filename: 'bundle.js' - }, - node: { - fs: 'empty' - } + ] } diff --git a/examples/browser-parceljs/.babelrc b/examples/browser-parceljs/.babelrc deleted file mode 100644 index 7fa2b0fc34..0000000000 --- a/examples/browser-parceljs/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["@babel/preset-env"], - "plugins": ["syntax-async-functions","transform-regenerator"] -} diff --git a/examples/browser-parceljs/package.json b/examples/browser-parceljs/package.json index 5766fd7256..985c4a78e6 100644 --- a/examples/browser-parceljs/package.json +++ b/examples/browser-parceljs/package.json @@ -2,16 +2,16 @@ "name": "example-browser-parceljs", "description": "", "version": "1.0.2", - "main": "index.js", + "main": "dist/index.html", "private": true, "browserslist": [ - "last 2 Chrome versions" + "last 2 versions and not dead and > 2%" ], "scripts": { "clean": "rimraf ./dist", "lint": "standard public/**/*.js", "start": "parcel public/index.html", - "build": "parcel build public/index.html --public-url ./", + "build": "parcel build public/index.html --no-scope-hoist", "test": "test-ipfs-example" }, "keywords": [], @@ -21,15 +21,9 @@ "ipfs": "^0.54.4" }, "devDependencies": { - "@babel/cli": "7.13.0", - "@babel/core": "7.13.0", - "@babel/preset-env": "7.13.0", - "babel-plugin-syntax-async-functions": "^6.13.0", - "babel-plugin-transform-regenerator": "^6.26.0", - "babel-polyfill": "^6.26.0", - "parcel-bundler": "^1.12.4", + "parcel": "next", "rimraf": "^3.0.2", - "standard": "^13.1.0", + "standard": "^16.0.3", "test-ipfs-example": "^3.0.0" } } diff --git a/examples/browser-parceljs/public/index.js b/examples/browser-parceljs/public/index.js index 787d012737..b75b54e601 100644 --- a/examples/browser-parceljs/public/index.js +++ b/examples/browser-parceljs/public/index.js @@ -1,4 +1,3 @@ -import 'babel-polyfill' import IPFS from 'ipfs' import uint8ArrayConcat from 'uint8arrays/concat' import uint8ArrayToString from 'uint8arrays/to-string' diff --git a/examples/browser-readablestream/package.json b/examples/browser-readablestream/package.json index 2220248092..6a8b79a26a 100644 --- a/examples/browser-readablestream/package.json +++ b/examples/browser-readablestream/package.json @@ -13,12 +13,13 @@ "author": "", "license": "ISC", "devDependencies": { - "html-webpack-plugin": "^3.2.0", + "html-webpack-plugin": "^5.3.1", "http-server": "^0.12.3", + "node-polyfill-webpack-plugin": "^1.0.3", "rimraf": "^3.0.2", - "terser-webpack-plugin": "^1.2.1", "test-ipfs-example": "^3.0.0", - "webpack": "^4.43.0" + "webpack": "^5.28.0", + "webpack-cli": "^4.5.0" }, "dependencies": { "ipfs": "^0.54.4", diff --git a/examples/browser-readablestream/webpack.config.js b/examples/browser-readablestream/webpack.config.js index a20cb0a67c..f4865c244e 100644 --- a/examples/browser-readablestream/webpack.config.js +++ b/examples/browser-readablestream/webpack.config.js @@ -1,55 +1,33 @@ 'use strict' const path = require('path') -const TerserPlugin = require('terser-webpack-plugin') +const webpack = require('webpack') +const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { - devtool: 'source-map', + devtool: 'eval', entry: [ './index.js' ], + output: { + path: path.join(__dirname, 'dist'), + filename: 'bundle.js' + }, plugins: [ new HtmlWebpackPlugin({ title: 'IPFS Videostream example', template: 'index.html' + }), + // fixes Module not found: Error: Can't resolve 'stream' in '.../node_modules/nofilter/lib' + new NodePolyfillPlugin(), + // Note: stream-browserify has assumption about `Buffer` global in its + // dependencies causing runtime errors. This is a workaround to provide + // global `Buffer` until https://github.com/isaacs/core-util-is/issues/29 + // is fixed. + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + process: 'process/browser' }) - ], - optimization: { - minimizer: [ - new TerserPlugin({ - terserOptions: { - parse: { - // we want terser to parse ecma 8 code. However, we don't want it - // to apply any minfication steps that turns valid ecma 5 code - // into invalid ecma 5 code. This is why the 'compress' and 'output' - // sections only apply transformations that are ecma 5 safe - // https://github.com/facebook/create-react-app/pull/4234 - ecma: 8 - }, - compress: { - ecma: 5, - warnings: false - }, - mangle: { - safari10: true - }, - output: { - ecma: 5, - comments: false - } - }, - // Use multi-process parallel running to improve the build speed - // Default number of concurrent runs: os.cpus().length - 1 - parallel: true, - // Enable file caching - cache: true, - sourceMap: true - }) - ] - }, - output: { - path: path.join(__dirname, 'dist'), - filename: 'bundle.js' - } + ] } diff --git a/examples/browser-service-worker/package.json b/examples/browser-service-worker/package.json index 8718350059..f05c54449a 100644 --- a/examples/browser-service-worker/package.json +++ b/examples/browser-service-worker/package.json @@ -12,14 +12,14 @@ "license": "MIT", "keywords": [], "devDependencies": { - "@babel/core": "7.13.0", - "@babel/preset-env": "7.13.0", + "@babel/core": "^7.13.10", + "@babel/preset-env": "^7.13.12", "babel-loader": "^8.2.2", - "copy-webpack-plugin": "^5.0.4", + "copy-webpack-plugin": "^8.1.0", "test-ipfs-example": "^3.0.0", - "webpack": "5.4.0", - "webpack-cli": "4.1.0", - "webpack-dev-server": "3.11.0" + "webpack": "^5.28.0", + "webpack-cli": "^4.5.0", + "webpack-dev-server": "^3.11.2" }, "dependencies": { "ipfs": "^0.54.4", @@ -29,9 +29,6 @@ "process": "0.11.10" }, "browserslist": [ - ">1%", - "not dead", - "not ie <= 11", - "not op_mini all" + "last 2 versions and not dead and > 2%" ] } diff --git a/examples/browser-service-worker/webpack.config.js b/examples/browser-service-worker/webpack.config.js index e63c6f4d7d..0dc0fbb1ef 100644 --- a/examples/browser-service-worker/webpack.config.js +++ b/examples/browser-service-worker/webpack.config.js @@ -5,8 +5,7 @@ const webpack = require('webpack') const CopyWebpackPlugin = require('copy-webpack-plugin') module.exports = { - mode: 'development', - devtool: 'source-map', + devtool: 'eval', entry: './src/main.js', output: { path: path.join(__dirname, 'dist'), @@ -49,9 +48,11 @@ module.exports = { } }, plugins: [ - new CopyWebpackPlugin([{ - from: 'index.html' - }]), + new CopyWebpackPlugin({ + patterns: [{ + from: 'index.html' + }] + }), // Note: stream-browserify has assumption about `Buffer` global in its // dependencies causing runtime errors. This is a workaround to provide // global `Buffer` until https://github.com/isaacs/core-util-is/issues/29 diff --git a/examples/browser-sharing-node-across-tabs/package.json b/examples/browser-sharing-node-across-tabs/package.json index 66c281deb4..03cefcb364 100644 --- a/examples/browser-sharing-node-across-tabs/package.json +++ b/examples/browser-sharing-node-across-tabs/package.json @@ -12,16 +12,17 @@ "license": "MIT", "keywords": [], "devDependencies": { - "@babel/core": "7.13.0", - "@babel/preset-env": "7.13.0", + "@babel/core": "^7.13.10", + "@babel/preset-env": "^7.13.12", "babel-loader": "^8.2.2", - "copy-webpack-plugin": "^5.0.4", + "copy-webpack-plugin": "^8.1.0", + "node-polyfill-webpack-plugin": "^1.0.3", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0", - "webpack": "^4.43.0", - "webpack-cli": "^3.3.11", - "webpack-dev-server": "^3.11.0", - "worker-plugin": "4.0.3" + "webpack": "^5.28.0", + "webpack-cli": "^4.5.0", + "webpack-dev-server": "^3.11.2", + "worker-loader": "^3.0.8" }, "dependencies": { "ipfs": "^0.54.4", @@ -29,9 +30,6 @@ "ipfs-message-port-server": "^0.6.3" }, "browserslist": [ - ">1%", - "not dead", - "not ie <= 11", - "not op_mini all" + "last 2 versions and not dead and > 2%" ] } diff --git a/examples/browser-sharing-node-across-tabs/src/main.js b/examples/browser-sharing-node-across-tabs/src/main.js index af1759ff83..37da2107fa 100644 --- a/examples/browser-sharing-node-across-tabs/src/main.js +++ b/examples/browser-sharing-node-across-tabs/src/main.js @@ -2,10 +2,9 @@ import IPFSClient from "ipfs-message-port-client" - const main = async () => { // connect / spawn shared ipfs worker & create a client. - const worker = new SharedWorker('./worker.js', { type: 'module' }) + const worker = new SharedWorker(new URL('./worker.js', import.meta.url), { type: 'module' }) const ipfs = IPFSClient.from(worker.port) const path = location.hash.slice(1) diff --git a/examples/browser-sharing-node-across-tabs/src/worker.js b/examples/browser-sharing-node-across-tabs/src/worker.js index e39c5d9b89..335a5980f2 100644 --- a/examples/browser-sharing-node-across-tabs/src/worker.js +++ b/examples/browser-sharing-node-across-tabs/src/worker.js @@ -4,6 +4,7 @@ import IPFS from 'ipfs' import { Server, IPFSService } from 'ipfs-message-port-server' const main = async () => { + console.info('heelo') // start listening to all the incoming connections (browsing contexts that // which run new SharedWorker...) // Note: It is important to start listening before we do any await to ensure @@ -30,7 +31,7 @@ const main = async () => { * the given event `type`. It is like `target.addEventListener(type, listener, options)` * but instead of passing listener you get `AsyncIterable` instead. * @param {EventTarget} target - * @param {string} type + * @param {string} type * @param {AddEventListenerOptions} options */ const listen = function (target, type, options) { diff --git a/examples/browser-sharing-node-across-tabs/webpack.config.js b/examples/browser-sharing-node-across-tabs/webpack.config.js index 0523345954..49c190b123 100644 --- a/examples/browser-sharing-node-across-tabs/webpack.config.js +++ b/examples/browser-sharing-node-across-tabs/webpack.config.js @@ -2,11 +2,12 @@ const path = require('path') const webpack = require('webpack') -const WorkerPlugin = require('worker-plugin') const CopyWebpackPlugin = require('copy-webpack-plugin') +const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') module.exports = { - devtool: 'source-map', + devtool: 'eval', + mode: 'development', entry: [ 'webpack-dev-server/client?http://localhost:3000', 'webpack/hot/only-dev-server', @@ -18,14 +19,22 @@ module.exports = { publicPath: '/' }, plugins: [ - new WorkerPlugin({ - sharedWorker: true, - globalObject: 'self' - }), new webpack.HotModuleReplacementPlugin(), - new CopyWebpackPlugin([{ - from: 'index.html' - }]) + new CopyWebpackPlugin({ + patterns: [{ + from: 'index.html' + }] + }), + // fixes Module not found: Error: Can't resolve 'stream' in '.../node_modules/nofilter/lib' + new NodePolyfillPlugin(), + // Note: stream-browserify has assumption about `Buffer` global in its + // dependencies causing runtime errors. This is a workaround to provide + // global `Buffer` until https://github.com/isaacs/core-util-is/issues/29 + // is fixed. + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + process: 'process/browser' + }) ], module: { rules: [ @@ -49,10 +58,5 @@ module.exports = { } } ] - }, - node: { - fs: 'empty', - net: 'empty', - tls: 'empty' } } diff --git a/examples/browser-vue/package.json b/examples/browser-vue/package.json index 476d75c225..5686b60428 100644 --- a/examples/browser-vue/package.json +++ b/examples/browser-vue/package.json @@ -15,12 +15,13 @@ "vue": "^2.6.11" }, "devDependencies": { - "@vue/cli-plugin-babel": "^4.2.3", - "@vue/cli-plugin-eslint": "^4.2.3", - "@vue/cli-service": "^4.2.3", + "@vue/cli-plugin-babel": "5.0.0-alpha.8", + "@vue/cli-plugin-eslint": "5.0.0-alpha.8", + "@vue/cli-service": "5.0.0-alpha.8", "babel-eslint": "^10.1.0", - "eslint": "^6.8.0", - "eslint-plugin-vue": "^6.2.1", + "eslint": "^7.22.0", + "eslint-plugin-vue": "^7.8.0", + "node-polyfill-webpack-plugin": "^1.0.3", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0", "vue-template-compiler": "^2.6.11" @@ -45,7 +46,6 @@ } }, "browserslist": [ - "> 1%", - "last 2 versions" + "last 2 versions and not dead and > 2%" ] } diff --git a/examples/browser-vue/vue.config.js b/examples/browser-vue/vue.config.js index 8fbad01d65..b8114fc460 100644 --- a/examples/browser-vue/vue.config.js +++ b/examples/browser-vue/vue.config.js @@ -1,3 +1,20 @@ +const webpack = require('webpack') +const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') + module.exports = { - chainWebpack: config => config.resolve.symlinks(false), + configureWebpack: { + plugins: [ + // fixes Module not found: Error: Can't resolve 'stream' in '.../node_modules/nofilter/lib' + new NodePolyfillPlugin(), + // Note: stream-browserify has assumption about `Buffer` global in its + // dependencies causing runtime errors. This is a workaround to provide + // global `Buffer` until https://github.com/isaacs/core-util-is/issues/29 + // is fixed. + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + process: 'process/browser' + }) + ] + }, + chainWebpack: config => config.resolve.symlinks(false) } diff --git a/examples/browser-webpack/package.json b/examples/browser-webpack/package.json index ab8da74e8d..53f6ab8315 100644 --- a/examples/browser-webpack/package.json +++ b/examples/browser-webpack/package.json @@ -12,29 +12,26 @@ "license": "MIT", "keywords": [], "devDependencies": { - "@babel/core": "7.13.0", - "@babel/preset-env": "7.13.0", - "@babel/preset-react": "7.12.1", + "@babel/core": "^7.13.10", + "@babel/preset-env": "^7.13.12", + "@babel/preset-react": "^7.12.13", "babel-loader": "^8.2.2", - "copy-webpack-plugin": "^7.0.0", - "node-polyfill-webpack-plugin": "^1.0.2", + "copy-webpack-plugin": "^8.1.0", + "node-polyfill-webpack-plugin": "^1.0.3", "react": "^17.0.1", "react-dom": "^17.0.1", "react-hot-loader": "^4.12.21", "rimraf": "^3.0.2", "stream-browserify": "^3.0.0", "test-ipfs-example": "^3.0.0", - "webpack": "^5.18.0", - "webpack-cli": "^4.4.0", - "webpack-dev-server": "^3.11.0" + "webpack": "^5.28.0", + "webpack-cli": "^4.5.0", + "webpack-dev-server": "^3.11.2" }, "dependencies": { "ipfs": "^0.54.4" }, "browserslist": [ - ">1%", - "not dead", - "not ie <= 11", - "not op_mini all" + "last 2 versions and not dead and > 2%" ] } diff --git a/examples/browser-webpack/webpack.config.js b/examples/browser-webpack/webpack.config.js index bf615d1304..8d36c445a5 100644 --- a/examples/browser-webpack/webpack.config.js +++ b/examples/browser-webpack/webpack.config.js @@ -46,12 +46,14 @@ module.exports = { loader: 'babel-loader', options: { presets: [ - ['@babel/preset-env', + [ + '@babel/preset-env', { targets: { esmodules: true } - }], + } + ], '@babel/preset-react' ] } diff --git a/examples/circuit-relaying/package.json b/examples/circuit-relaying/package.json index 1205ef0dad..c9b10a0858 100644 --- a/examples/circuit-relaying/package.json +++ b/examples/circuit-relaying/package.json @@ -2,11 +2,11 @@ "name": "example-circuit-relaying", "description": "IPFS quick msg", "version": "0.1.1", - "main": "index.js", + "main": "./dist/index.html", "private": true, "scripts": { "clean": "rimraf ./dist", - "build": "parcel build index.html --public-url '.'", + "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html", "deploy": "ipfs add -r --quieter dist", "test": "test-ipfs-example" @@ -24,15 +24,12 @@ "execa": "^5.0.0", "ipfs-css": "^0.13.1", "ipfs-http-client": "^49.0.4", - "parcel-bundler": "^1.12.4", + "parcel": "next", "rimraf": "^3.0.2", "tachyons": "^4.11.1", "test-ipfs-example": "^3.0.0" }, "browserslist": [ - ">1%", - "not dead", - "not ie <= 11", - "not op_mini all" + "last 2 versions and not dead and > 2%" ] } diff --git a/examples/custom-ipfs-repo/package.json b/examples/custom-ipfs-repo/package.json index 27bb5ded62..ad4dbb7251 100644 --- a/examples/custom-ipfs-repo/package.json +++ b/examples/custom-ipfs-repo/package.json @@ -12,7 +12,7 @@ "dependencies": { "datastore-fs": "^2.0.0", "ipfs": "^0.54.4", - "ipfs-repo": "^8.0.0", + "ipfs-repo": "^9.0.0", "it-all": "^1.0.4" }, "devDependencies": { diff --git a/examples/custom-libp2p/package.json b/examples/custom-libp2p/package.json index 0c0c98daca..ffbe35e0ce 100644 --- a/examples/custom-libp2p/package.json +++ b/examples/custom-libp2p/package.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "ipfs": "^0.54.4", - "libp2p": "^0.30.7", + "libp2p": "^0.30.12", "libp2p-bootstrap": "^0.12.1", "libp2p-kad-dht": "^0.20.1", "libp2p-mdns": "^0.15.0", diff --git a/examples/explore-ethereum-blockchain/package.json b/examples/explore-ethereum-blockchain/package.json index 043a608d40..ece0624d83 100644 --- a/examples/explore-ethereum-blockchain/package.json +++ b/examples/explore-ethereum-blockchain/package.json @@ -12,7 +12,7 @@ "devDependencies": { "ipfs": "^0.54.4", "ipfs-http-client": "^49.0.4", - "ipfsd-ctl": "^7.2.0", + "ipfsd-ctl": "^8.0.0", "ipld-ethereum": "^5.0.1", "test-ipfs-example": "^3.0.0" } diff --git a/examples/http-client-browser-pubsub/index.js b/examples/http-client-browser-pubsub/index.js index 3a21137a7a..64867e7289 100644 --- a/examples/http-client-browser-pubsub/index.js +++ b/examples/http-client-browser-pubsub/index.js @@ -1,6 +1,6 @@ 'use strict' -const IpfsHttpClient = require('ipfs-http-client') +const { create: IpfsHttpClient } = require('ipfs-http-client') const { sleep, Logger, onEnterPress, catchAndLog } = require('./util') const uint8ArrayToString = require('uint8arrays/to-string') diff --git a/examples/http-client-browser-pubsub/package.json b/examples/http-client-browser-pubsub/package.json index cea1d63619..9694895a34 100644 --- a/examples/http-client-browser-pubsub/package.json +++ b/examples/http-client-browser-pubsub/package.json @@ -3,9 +3,9 @@ "version": "0.0.0", "description": "An example demonstrating pubsub in the browser", "private": true, - "main": "index.js", + "main": "dist/index.html", "scripts": { - "build": "parcel build index.html --public-url ./", + "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html -p 8888", "test": "test-ipfs-example" }, @@ -21,8 +21,8 @@ "execa": "^5.0.0", "go-ipfs": "0.8.0", "ipfs": "^0.54.4", - "ipfsd-ctl": "^7.2.0", - "parcel-bundler": "^1.12.4", + "ipfsd-ctl": "^8.0.0", + "parcel": "next", "test-ipfs-example": "^3.0.0" } } diff --git a/examples/http-client-bundle-webpack/package.json b/examples/http-client-bundle-webpack/package.json index af73e64b30..e4d6451561 100644 --- a/examples/http-client-bundle-webpack/package.json +++ b/examples/http-client-bundle-webpack/package.json @@ -18,19 +18,19 @@ "react-dom": "^16.8.6" }, "devDependencies": { - "@babel/core": "7.13.0", - "@babel/preset-env": "7.13.0", - "@babel/preset-react": "7.12.1", + "@babel/core": "^7.13.10", + "@babel/preset-env": "^7.13.12", + "@babel/preset-react": "^7.12.13", "babel-loader": "^8.2.2", - "copy-webpack-plugin": "^5.0.4", + "copy-webpack-plugin": "^8.1.0", "execa": "^5.0.0", "ipfs": "^0.54.4", - "ipfsd-ctl": "^7.2.0", + "ipfsd-ctl": "^8.0.0", "react-hot-loader": "^4.12.21", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0", - "webpack": "^4.43.0", - "webpack-dev-server": "^3.11.0" + "webpack": "^5.28.0", + "webpack-cli": "^4.5.0" }, "browserslist": [ "last 2 versions and not dead and > 2%" diff --git a/examples/http-client-bundle-webpack/src/App.js b/examples/http-client-bundle-webpack/src/App.js index d68aaa855f..e1bdffe99c 100644 --- a/examples/http-client-bundle-webpack/src/App.js +++ b/examples/http-client-bundle-webpack/src/App.js @@ -1,6 +1,6 @@ 'use strict' const React = require('react') -const ipfsClient = require('ipfs-http-client') +const { create: ipfsClient } = require('ipfs-http-client') const stringToUse = 'hello world from webpacked IPFS' class App extends React.Component { diff --git a/examples/http-client-bundle-webpack/webpack.config.js b/examples/http-client-bundle-webpack/webpack.config.js index 48a5caf408..28d5394954 100644 --- a/examples/http-client-bundle-webpack/webpack.config.js +++ b/examples/http-client-bundle-webpack/webpack.config.js @@ -18,9 +18,11 @@ module.exports = { }, plugins: [ new webpack.HotModuleReplacementPlugin(), - new CopyWebpackPlugin([{ - from: 'index.html' - }]) + new CopyWebpackPlugin({ + patterns: [{ + from: 'index.html' + }] + }) ], module: { rules: [ @@ -43,10 +45,5 @@ module.exports = { } } ] - }, - node: { - fs: 'empty', - net: 'empty', - tls: 'empty' } } diff --git a/examples/http-client-name-api/index.js b/examples/http-client-name-api/index.js index 1a725c76da..abe828b492 100644 --- a/examples/http-client-name-api/index.js +++ b/examples/http-client-name-api/index.js @@ -1,7 +1,7 @@ /* eslint-disable no-console */ 'use strict' -const ipfsHttp = require('ipfs-http-client') +const { create: ipfsHttp } = require('ipfs-http-client') let ipfs const DOM = { diff --git a/examples/http-client-name-api/package.json b/examples/http-client-name-api/package.json index ba26c5d75a..a26751ec20 100644 --- a/examples/http-client-name-api/package.json +++ b/examples/http-client-name-api/package.json @@ -2,11 +2,11 @@ "name": "example-http-client-name-api", "version": "1.0.0", "description": "", - "main": "index.js", + "main": "dist/index.html", "private": true, "scripts": { "clean": "rimraf ./dist", - "build": "parcel build index.html --public-url '.'", + "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html -p 8888", "test": "test-ipfs-example" }, @@ -18,8 +18,8 @@ "devDependencies": { "execa": "^5.0.0", "go-ipfs": "0.8.0", - "ipfsd-ctl": "^7.2.0", - "parcel-bundler": "^1.12.4", + "ipfsd-ctl": "^8.0.0", + "parcel": "next", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" }, diff --git a/examples/ipfs-client-add-files/index.js b/examples/ipfs-client-add-files/index.js index d66a40ad4a..ef924a9905 100644 --- a/examples/ipfs-client-add-files/index.js +++ b/examples/ipfs-client-add-files/index.js @@ -1,7 +1,7 @@ /* eslint-disable no-console */ 'use strict' -const ipfsClient = require('ipfs-client') +const { create: ipfsClient } = require('ipfs-client') let ipfs const COLORS = { diff --git a/examples/ipfs-client-add-files/package.json b/examples/ipfs-client-add-files/package.json index 04ea4bdf1e..9fd2b9a0a7 100644 --- a/examples/ipfs-client-add-files/package.json +++ b/examples/ipfs-client-add-files/package.json @@ -2,11 +2,11 @@ "name": "example-ipfs-client-add-files", "version": "1.0.0", "description": "", - "main": "index.js", + "main": "dist/index.html", "private": true, "scripts": { "clean": "rimraf ./dist", - "build": "parcel build index.html --public-url '.'", + "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html -p 8888", "test": "test-ipfs-example" }, @@ -16,8 +16,8 @@ "devDependencies": { "execa": "^5.0.0", "ipfs": "^0.54.4", - "ipfsd-ctl": "^7.2.0", - "parcel-bundler": "^1.12.4", + "ipfsd-ctl": "^8.0.0", + "parcel": "next", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" }, diff --git a/examples/traverse-ipld-graphs/package.json b/examples/traverse-ipld-graphs/package.json index a6998d74a3..0eeaac3e1f 100644 --- a/examples/traverse-ipld-graphs/package.json +++ b/examples/traverse-ipld-graphs/package.json @@ -16,7 +16,7 @@ "cids": "^1.1.5", "ipfs": "^0.54.4", "ipld-block": "^0.11.0", - "ipld-dag-pb": "^0.20.0", + "ipld-dag-pb": "^0.22.0", "ipld-git": "^0.6.1", "ipld-ethereum": "^5.0.1", "multihashing-async": "^2.1.2" diff --git a/package.json b/package.json index d3e36c11fd..07ee2011e1 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "postinstall": "lerna bootstrap", "link": "lerna link", - "reset": "lerna run clean && rimraf packages/*/node_modules node_modules", + "reset": "lerna run clean && rimraf packages/*/node_modules examples/*/node_modules node_modules", "test": "lerna run test", "test:node": "lerna run test:node", "test:browser": "lerna run test:browser", @@ -21,7 +21,6 @@ "test:interface:http-go": "lerna run test:interface:http-go", "test:interface:http-js": "lerna run test:interface:http-js", "test:interface:message-port-client": "lerna run test:interface:message-port-client", - "prepare": "lerna run prepare", "coverage": "lerna run coverage", "build": "lerna run build", "clean": "lerna run clean", @@ -34,7 +33,7 @@ "release:pre:non-dirty-repo": "git diff --quiet", "release:pre:update-contributors": "aegir release --lint=false --test=false --bump=false --build=false --changelog=false --commit=false --tag=false --push=false --ghrelease=false --docs=false --publish=false --types=false", "release:pre:reinstall": "npm run reset && npm i && rimraf package-lock.json packages/*/package-lock.json", - "release:pre:bundle": "NODE_ENV=production npm run build -- --scope={ipfs,ipfs-core,ipfs-*client,ipfs-message-port-*}", + "release:pre:bundle": "NODE_ENV=production npm run build -- --scope={ipfs,ipfs-core,ipfs-*client,ipfs-grpc-protocol,ipfs-message-port-*}", "release:publish": "lerna publish", "docker:release": "run-s docker:release:*", "docker:release:build": "docker build . --no-cache --tag js-ipfs:latest --file ./Dockerfile.latest", diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index c822d27599..b6234d657a 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -37,27 +37,26 @@ }, "dependencies": { "abort-controller": "^3.0.0", - "aegir": "^31.0.0", - "bignumber.js": "^9.0.1", + "aegir": "^32.1.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", "cids": "^1.1.5", - "delay": "^4.4.0", + "delay": "^5.0.0", "dirty-chai": "^2.0.1", - "err-code": "^2.0.3", - "ipfs-unixfs": "^2.0.3", - "ipfs-unixfs-importer": "^5.0.0", - "ipfs-utils": "^6.0.1", + "err-code": "^3.0.1", + "ipfs-unixfs": "^4.0.1", + "ipfs-unixfs-importer": "^7.0.1", + "ipfs-utils": "^6.0.4", "ipld-block": "^0.11.0", - "ipld-dag-cbor": "^0.17.0", - "ipld-dag-pb": "^0.20.0", - "ipns": "^0.8.0", - "is-ipfs": "^2.0.0", + "ipld-dag-cbor": "^0.18.0", + "ipld-dag-pb": "^0.22.0", + "ipns": "^0.10.0", + "is-ipfs": "^4.0.0", "iso-random-stream": "^1.1.1", "it-all": "^1.0.4", - "it-buffer-stream": "^1.0.5", - "it-concat": "^1.0.1", + "it-buffer-stream": "^2.0.0", + "it-concat": "^1.0.3", "it-drain": "^1.0.3", "it-first": "^1.0.4", "it-last": "^1.0.4", diff --git a/packages/interface-ipfs-core/src/bitswap/.tern-port b/packages/interface-ipfs-core/src/bitswap/.tern-port deleted file mode 100644 index afd86f3dc7..0000000000 --- a/packages/interface-ipfs-core/src/bitswap/.tern-port +++ /dev/null @@ -1 +0,0 @@ -36541 \ No newline at end of file diff --git a/packages/interface-ipfs-core/src/cat.js b/packages/interface-ipfs-core/src/cat.js index 779f22c309..b44759e776 100644 --- a/packages/interface-ipfs-core/src/cat.js +++ b/packages/interface-ipfs-core/src/cat.js @@ -10,7 +10,7 @@ const all = require('it-all') const drain = require('it-drain') const { getDescribe, getIt, expect } = require('./utils/mocha') const testTimeout = require('./utils/test-timeout') -const importer = require('ipfs-unixfs-importer') +const { importer } = require('ipfs-unixfs-importer') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** diff --git a/packages/interface-ipfs-core/src/dag/get.js b/packages/interface-ipfs-core/src/dag/get.js index fee4bf2458..4bff6a9528 100644 --- a/packages/interface-ipfs-core/src/dag/get.js +++ b/packages/interface-ipfs-core/src/dag/get.js @@ -5,8 +5,8 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode const dagCBOR = require('ipld-dag-cbor') -const importer = require('ipfs-unixfs-importer') -const Unixfs = require('ipfs-unixfs') +const { importer } = require('ipfs-unixfs-importer') +const { UnixFS } = require('ipfs-unixfs') const all = require('it-all') const CID = require('cids') const { getDescribe, getIt, expect } = require('../utils/mocha') @@ -193,7 +193,7 @@ module.exports = (common, options) => { const cidv0 = cidv1.toV0() const output = await ipfs.dag.get(cidv0) - expect(Unixfs.unmarshal(output.value.Data).data).to.eql(input) + expect(UnixFS.unmarshal(output.value.Data).data).to.eql(input) }) it('should be able to get part of a dag-cbor node', async () => { diff --git a/packages/interface-ipfs-core/src/files/cp.js b/packages/interface-ipfs-core/src/files/cp.js index 7e9880ee37..a60b22d0f3 100644 --- a/packages/interface-ipfs-core/src/files/cp.js +++ b/packages/interface-ipfs-core/src/files/cp.js @@ -65,7 +65,7 @@ module.exports = (common, options) => { create: true }) await ipfs.files.mkdir(parent) - await expect(ipfs.files.cp(src1, src2, `${parent}/child`)).to.eventually.be.rejectedWith(Error) + await expect(ipfs.files.cp([src1, src2], `${parent}/child`)).to.eventually.be.rejectedWith(Error) .that.has.property('message').that.matches(/destination did not exist/) }) @@ -80,6 +80,7 @@ module.exports = (common, options) => { await ipfs.files.write(src1, [], { create: true }) + await expect(ipfs.files.cp(src1, `${parent}/child`)).to.eventually.be.rejectedWith(Error) .that.has.property('message').that.matches(/"identity"/) }) @@ -194,7 +195,7 @@ module.exports = (common, options) => { }) } - await ipfs.files.cp(sources[0].path, sources[1].path, destination, { + await ipfs.files.cp([sources[0].path, sources[1].path], destination, { parents: true }) diff --git a/packages/interface-ipfs-core/src/files/rm.js b/packages/interface-ipfs-core/src/files/rm.js index 90658cfb83..41c640828a 100644 --- a/packages/interface-ipfs-core/src/files/rm.js +++ b/packages/interface-ipfs-core/src/files/rm.js @@ -78,7 +78,7 @@ module.exports = (common, options) => { create: true, parents: true }) - await ipfs.files.rm(file1, file2) + await ipfs.files.rm([file1, file2]) await expect(ipfs.files.stat(file1)).to.eventually.be.rejectedWith(/does not exist/) await expect(ipfs.files.stat(file2)).to.eventually.be.rejectedWith(/does not exist/) diff --git a/packages/interface-ipfs-core/src/files/touch.js b/packages/interface-ipfs-core/src/files/touch.js index 1149be459c..4dcd99e106 100644 --- a/packages/interface-ipfs-core/src/files/touch.js +++ b/packages/interface-ipfs-core/src/files/touch.js @@ -33,7 +33,7 @@ module.exports = (common, options) => { }) const stat2 = await ipfs.files.stat(testPath) - expect(stat2).to.have.nested.deep.property('mtime', expectedMtime) + expect(stat2).to.have.deep.nested.property('mtime', expectedMtime) } before(async () => { ipfs = (await common.spawn()).api }) diff --git a/packages/interface-ipfs-core/src/get.js b/packages/interface-ipfs-core/src/get.js index 2d05173796..4f345954d1 100644 --- a/packages/interface-ipfs-core/src/get.js +++ b/packages/interface-ipfs-core/src/get.js @@ -12,7 +12,7 @@ const last = require('it-last') const map = require('it-map') const { getDescribe, getIt, expect } = require('./utils/mocha') const testTimeout = require('./utils/test-timeout') -const importer = require('ipfs-unixfs-importer') +const { importer } = require('ipfs-unixfs-importer') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** diff --git a/packages/interface-ipfs-core/src/object/get.js b/packages/interface-ipfs-core/src/object/get.js index 97b4472c3c..b81ddb6a82 100644 --- a/packages/interface-ipfs-core/src/object/get.js +++ b/packages/interface-ipfs-core/src/object/get.js @@ -5,7 +5,7 @@ const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') -const UnixFs = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') const randomBytes = require('iso-random-stream/src/random') const { asDAGLink } = require('./utils') const testTimeout = require('../utils/test-timeout') @@ -147,7 +147,7 @@ module.exports = (common, options) => { }) const node = await ipfs.object.get(result.cid) - const meta = UnixFs.unmarshal(node.Data) + const meta = UnixFS.unmarshal(node.Data) expect(meta.fileSize()).to.equal(data.length) }) diff --git a/packages/interface-ipfs-core/src/refs-local.js b/packages/interface-ipfs-core/src/refs-local.js index 9a46f0266d..6824fbbdf6 100644 --- a/packages/interface-ipfs-core/src/refs-local.js +++ b/packages/interface-ipfs-core/src/refs-local.js @@ -4,7 +4,7 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('./utils/mocha') const all = require('it-all') -const importer = require('ipfs-unixfs-importer') +const { importer } = require('ipfs-unixfs-importer') const drain = require('it-drain') const testTimeout = require('./utils/test-timeout') const CID = require('cids') diff --git a/packages/interface-ipfs-core/src/refs.js b/packages/interface-ipfs-core/src/refs.js index 757c395b0b..422cda18a5 100644 --- a/packages/interface-ipfs-core/src/refs.js +++ b/packages/interface-ipfs-core/src/refs.js @@ -12,7 +12,7 @@ const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode const DAGLink = dagPB.DAGLink -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** diff --git a/packages/interface-ipfs-core/src/stats/utils.js b/packages/interface-ipfs-core/src/stats/utils.js index 15904c0c51..32157eb251 100644 --- a/packages/interface-ipfs-core/src/stats/utils.js +++ b/packages/interface-ipfs-core/src/stats/utils.js @@ -1,10 +1,9 @@ 'use strict' const { expect } = require('../utils/mocha') -const { BigNumber } = require('bignumber.js') const isBigInt = (n) => { - return BigNumber.isBigNumber(n) + return typeof n === 'bigint' } exports.expectIsBitswap = (err, stats) => { diff --git a/packages/interface-ipfs-core/src/utils/is-shard-at-path.js b/packages/interface-ipfs-core/src/utils/is-shard-at-path.js index f2be8ee480..a0a48c63c7 100644 --- a/packages/interface-ipfs-core/src/utils/is-shard-at-path.js +++ b/packages/interface-ipfs-core/src/utils/is-shard-at-path.js @@ -1,6 +1,6 @@ 'use strict' -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') module.exports = async (path, ipfs) => { const stats = await ipfs.files.stat(path) diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index f4586ca0a9..50b2011f69 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -11,9 +11,11 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "dist/src/index.d.ts", "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" @@ -24,27 +26,28 @@ "test:node": "aegir test -t node", "coverage": "nyc --reporter=text --reporter=lcov npm run test:node", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i cid-tool" + "dep-check": "aegir dep-check -i cid-tool -i ipfs-core-types", + "build": "aegir build --no-bundle" }, "dependencies": { - "bignumber.js": "^9.0.1", "byteman": "^1.3.5", "cid-tool": "^1.0.0", "cids": "^1.1.5", "debug": "^4.1.1", - "err-code": "^2.0.3", + "err-code": "^3.0.1", "execa": "^5.0.0", "get-folder-size": "^2.0.1", "ipfs-core": "^0.5.4", + "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-daemon": "^0.5.4", "ipfs-http-client": "^49.0.4", - "ipfs-repo": "^8.0.0", - "ipfs-utils": "^6.0.1", - "ipld-dag-cbor": "^0.17.0", - "ipld-dag-pb": "^0.20.0", + "ipfs-repo": "^9.0.0", + "ipfs-utils": "^6.0.4", + "ipld-dag-cbor": "^0.18.0", + "ipld-dag-pb": "^0.22.0", "it-all": "^1.0.4", - "it-concat": "^1.0.1", + "it-concat": "^1.0.3", "it-first": "^1.0.4", "it-glob": "0.0.11", "it-pipe": "^1.1.0", @@ -56,7 +59,6 @@ "multibase": "^4.0.2", "multihashing-async": "^2.1.2", "parse-duration": "^0.4.4", - "peer-id": "^0.14.1", "pretty-bytes": "^5.4.1", "progress": "^2.0.3", "stream-to-it": "^0.2.2", @@ -65,10 +67,13 @@ "yargs": "^16.0.3" }, "devDependencies": { + "@types/get-folder-size": "^2.0.0", + "@types/progress": "^2.0.3", "@types/yargs": "^16.0.0", - "aegir": "^31.0.0", + "aegir": "^32.1.0", "nanoid": "^3.1.12", "ncp": "^2.0.0", + "peer-id": "^0.14.1", "rimraf": "^3.0.2", "sinon": "^9.0.3", "string-argv": "^0.3.1", diff --git a/packages/ipfs-cli/src/command-alias.js b/packages/ipfs-cli/src/command-alias.js index 394da5cb94..d804909f37 100644 --- a/packages/ipfs-cli/src/command-alias.js +++ b/packages/ipfs-cli/src/command-alias.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @type {Record} + */ const aliases = { // We need to be able to show help text for both the `refs` command and the // `refs local` command, but with yargs `refs` cannot be both a command and @@ -7,8 +10,12 @@ const aliases = { 'refs-local': ['refs', 'local'] } -// Replace multi-word command with alias -// eg replace `refs local` with `refs-local` +/** + * Replace multi-word command with alias + * eg replace `refs local` with `refs-local` + * + * @param {string[]} args + */ module.exports = function (args) { for (const [alias, original] of Object.entries(aliases)) { if (arrayMatch(args, original)) { @@ -19,7 +26,12 @@ module.exports = function (args) { return args } -// eg arrayMatch([1, 2, 3], [1, 2]) => true +/** + * eg arrayMatch([1, 2, 3], [1, 2]) => true + * + * @param {string[]} arr + * @param {string[]} sub + */ function arrayMatch (arr, sub) { if (sub.length > arr.length) { return false diff --git a/packages/ipfs-cli/src/commands/add.js b/packages/ipfs-cli/src/commands/add.js index 49de636cbf..f3672910a3 100644 --- a/packages/ipfs-cli/src/commands/add.js +++ b/packages/ipfs-cli/src/commands/add.js @@ -3,6 +3,7 @@ const { promisify } = require('util') const getFolderSize = promisify(require('get-folder-size')) +// @ts-ignore no types const byteman = require('byteman') const mh = require('multihashing-async').multihash const multibase = require('multibase') @@ -16,6 +17,9 @@ const { cidToString } = require('ipfs-core-utils/src/cid') const globSource = require('ipfs-utils/src/files/glob-source') const { default: parseDuration } = require('parse-duration') +/** + * @param {string[]} paths + */ async function getTotalBytes (paths) { const sizes = await Promise.all(paths.map(p => getFolderSize(p))) return sizes.reduce((total, size) => total + size, 0) @@ -161,6 +165,37 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {boolean} argv.trickle + * @param {number} argv.shardSplitThreshold + * @param {import('cids').CIDVersion} argv.cidVersion + * @param {boolean} argv.rawLeaves + * @param {boolean} argv.onlyHash + * @param {import('multihashes').HashName} argv.hash + * @param {boolean} argv.wrapWithDirectory + * @param {boolean} argv.pin + * @param {string} argv.chunker + * @param {boolean} argv.preload + * @param {number} argv.fileImportConcurrency + * @param {number} argv.blockWriteConcurrency + * @param {number} argv.timeout + * @param {boolean} argv.quieter + * @param {boolean} argv.quiet + * @param {boolean} argv.silent + * @param {boolean} argv.progress + * @param {string[]} argv.file + * @param {number} argv.mtime + * @param {number} argv.mtimeNsecs + * @param {boolean} argv.recursive + * @param {boolean} argv.hidden + * @param {boolean} argv.preserveMode + * @param {boolean} argv.preserveMtime + * @param {number} argv.mode + * @param {import('multibase').BaseName} argv.cidBase + * @param {boolean} argv.enableShardingExperiment + */ async handler ({ ctx: { ipfs, print, isDaemon, getStdin }, trickle, @@ -188,7 +223,8 @@ module.exports = { preserveMode, preserveMtime, mode, - cidBase + cidBase, + enableShardingExperiment }) { const options = { trickle, @@ -203,14 +239,18 @@ module.exports = { preload, fileImportConcurrency, blockWriteConcurrency, - progress: () => {}, + /** + * @type {import('ipfs-core-types/src/root').AddProgressFn} + */ + progress: (bytes, name) => {}, timeout } - if (options.enableShardingExperiment && isDaemon) { + if (enableShardingExperiment && isDaemon) { throw new Error('Error: Enabling the sharding experiment should be done on the daemon') } + /** @type {{update: Function, interrupt: Function, terminate: Function} | undefined} */ let bar let log = print @@ -226,18 +266,14 @@ module.exports = { // bar.interrupt uses clearLine and cursorTo methods that are only on TTYs log = bar.interrupt.bind(bar) } - options.progress = byteLength => { - bar.update(byteLength / totalBytes, { progress: byteman(byteLength, 2, 'MB') }) - } - } - - if (mtime != null) { - mtime = { - secs: mtime - } - if (mtimeNsecs != null) { - mtime.nsecs = mtimeNsecs + /** + * @param {number} byteLength + */ + options.progress = byteLength => { + if (bar) { + bar.update(byteLength / totalBytes, { progress: byteman(byteLength, 2, 'MB') }) + } } } @@ -245,6 +281,13 @@ module.exports = { options.rawLeaves = cidVersion > 0 } + /** @type {{ secs: number, nsecs?: number } | undefined} */ + let date + + if (mtime) { + date = { secs: mtime, nsecs: mtimeNsecs } + } + const source = file ? globSource(file, { recursive, @@ -252,13 +295,13 @@ module.exports = { preserveMode, preserveMtime, mode, - mtime + mtime: date }) - : { + : [{ content: getStdin(), mode, - mtime - } // Pipe to ipfs.add tagging with mode and mtime + mtime: date + }] // Pipe to ipfs.add tagging with mode and mtime let finalCid @@ -297,7 +340,7 @@ module.exports = { } } - if (quieter) { + if (quieter && finalCid) { log(cidToString(finalCid, { base: cidBase })) } } diff --git a/packages/ipfs-cli/src/commands/bitswap.js b/packages/ipfs-cli/src/commands/bitswap.js index fa4d9b1c76..0b5f5791b1 100644 --- a/packages/ipfs-cli/src/commands/bitswap.js +++ b/packages/ipfs-cli/src/commands/bitswap.js @@ -5,6 +5,9 @@ module.exports = { description: 'Interact with the bitswap agent.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs.commandDir('bitswap') } diff --git a/packages/ipfs-cli/src/commands/bitswap/stat.js b/packages/ipfs-cli/src/commands/bitswap/stat.js index 20e6b741ec..5c74614597 100644 --- a/packages/ipfs-cli/src/commands/bitswap/stat.js +++ b/packages/ipfs-cli/src/commands/bitswap/stat.js @@ -26,6 +26,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {boolean} argv.human + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx, cidBase, human, timeout }) { const { ipfs, print } = ctx @@ -33,29 +40,34 @@ module.exports = { timeout }) + /** @type {Record} */ + const output = { + ...stats + } + if (human) { - stats.blocksReceived = stats.blocksReceived.toNumber() - stats.blocksSent = stats.blocksSent.toNumber() - stats.dataReceived = prettyBytes(stats.dataReceived.toNumber()).toUpperCase() - stats.dataSent = prettyBytes(stats.dataSent.toNumber()).toUpperCase() - stats.dupBlksReceived = stats.dupBlksReceived.toNumber() - stats.dupDataReceived = prettyBytes(stats.dupDataReceived.toNumber()).toUpperCase() - stats.wantlist = `[${stats.wantlist.length} keys]` + output.blocksReceived = Number(stats.blocksReceived) + output.blocksSent = Number(stats.blocksSent) + output.dataReceived = prettyBytes(Number(stats.dataReceived)).toUpperCase() + output.dataSent = prettyBytes(Number(stats.dataSent)).toUpperCase() + output.dupBlksReceived = Number(stats.dupBlksReceived) + output.dupDataReceived = prettyBytes(Number(stats.dupDataReceived)).toUpperCase() + output.wantlist = `[${stats.wantlist.length} keys]` } else { const wantlist = stats.wantlist.map(cid => cidToString(cid, { base: cidBase, upgrade: false })) - stats.wantlist = `[${wantlist.length} keys] + output.wantlist = `[${wantlist.length} keys] ${wantlist.join('\n ')}` } print(`bitswap status - provides buffer: ${stats.provideBufLen} - blocks received: ${stats.blocksReceived} - blocks sent: ${stats.blocksSent} - data received: ${stats.dataReceived} - data sent: ${stats.dataSent} - dup blocks received: ${stats.dupBlksReceived} - dup data received: ${stats.dupDataReceived} - wantlist ${stats.wantlist} + provides buffer: ${output.provideBufLen} + blocks received: ${output.blocksReceived} + blocks sent: ${output.blocksSent} + data received: ${output.dataReceived} + data sent: ${output.dataSent} + dup blocks received: ${output.dupBlksReceived} + dup data received: ${output.dupDataReceived} + wantlist ${output.wantlist} partners [${stats.peers.length}]`) } } diff --git a/packages/ipfs-cli/src/commands/bitswap/unwant.js b/packages/ipfs-cli/src/commands/bitswap/unwant.js index 129cedc91c..c48d53d01c 100644 --- a/packages/ipfs-cli/src/commands/bitswap/unwant.js +++ b/packages/ipfs-cli/src/commands/bitswap/unwant.js @@ -3,6 +3,7 @@ const multibase = require('multibase') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../utils') module.exports = { command: 'unwant ', @@ -13,7 +14,8 @@ module.exports = { key: { alias: 'k', describe: 'Key to remove from your wantlist', - type: 'string' + type: 'string', + coerce: coerceCID }, 'cid-base': { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', @@ -25,6 +27,14 @@ module.exports = { coerce: parseDuration } }, + + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx, key, cidBase, timeout }) { const { ipfs, print } = ctx await ipfs.bitswap.unwant(key, { diff --git a/packages/ipfs-cli/src/commands/bitswap/wantlist.js b/packages/ipfs-cli/src/commands/bitswap/wantlist.js index 0bd73d73ca..397804c732 100644 --- a/packages/ipfs-cli/src/commands/bitswap/wantlist.js +++ b/packages/ipfs-cli/src/commands/bitswap/wantlist.js @@ -26,6 +26,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.peer + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx, peer, cidBase, timeout }) { const { ipfs, print } = ctx let list diff --git a/packages/ipfs-cli/src/commands/block.js b/packages/ipfs-cli/src/commands/block.js index 6c1de1bc0b..8e22dc0364 100644 --- a/packages/ipfs-cli/src/commands/block.js +++ b/packages/ipfs-cli/src/commands/block.js @@ -5,6 +5,9 @@ module.exports = { description: 'Manipulate raw IPFS blocks.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('block') diff --git a/packages/ipfs-cli/src/commands/block/get.js b/packages/ipfs-cli/src/commands/block/get.js index a521ba83c8..78af009a9d 100644 --- a/packages/ipfs-cli/src/commands/block/get.js +++ b/packages/ipfs-cli/src/commands/block/get.js @@ -2,6 +2,7 @@ const { default: parseDuration } = require('parse-duration') const uint8ArrayToString = require('uint8arrays/to-string') +const { coerceCID } = require('../../utils') module.exports = { command: 'get ', @@ -9,12 +10,22 @@ module.exports = { describe: 'Get a raw IPFS block', builder: { + key: { + type: 'string', + coerce: coerceCID + }, timeout: { type: 'string', coerce: parseDuration } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.key + * @param {number} argv.timeout + */ async handler ({ ctx, key, timeout }) { const { ipfs, print } = ctx const block = await ipfs.block.get(key, { diff --git a/packages/ipfs-cli/src/commands/block/put.js b/packages/ipfs-cli/src/commands/block/put.js index 1fc6f9875f..1b23dbd1f6 100644 --- a/packages/ipfs-cli/src/commands/block/put.js +++ b/packages/ipfs-cli/src/commands/block/put.js @@ -46,13 +46,25 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.block + * @param {import('multicodec').CodecName} argv.format + * @param {import('multihashes').HashName} argv.mhtype + * @param {number} argv.mhlen + * @param {import('cids').CIDVersion} argv.version + * @param {boolean} argv.pin + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print, getStdin }, block, timeout, format, mhtype, mhlen, version, cidBase, pin }) { let data if (block) { data = fs.readFileSync(block) } else { - data = (await concat(getStdin())).slice() + data = (await concat(getStdin(), { type: 'buffer' })).slice() } const { cid } = await ipfs.block.put(data, { diff --git a/packages/ipfs-cli/src/commands/block/rm.js b/packages/ipfs-cli/src/commands/block/rm.js index 4fcd0867a1..1fefce3e5e 100644 --- a/packages/ipfs-cli/src/commands/block/rm.js +++ b/packages/ipfs-cli/src/commands/block/rm.js @@ -1,6 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { coerceCIDs } = require('../../utils') module.exports = { command: 'rm ', @@ -8,6 +9,10 @@ module.exports = { describe: 'Remove IPFS block(s)', builder: { + hash: { + type: 'array', + coerce: coerceCIDs + }, force: { alias: 'f', describe: 'Ignore nonexistent blocks', @@ -26,6 +31,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')[]} argv.hash + * @param {boolean} argv.force + * @param {boolean} argv.quiet + * @param {number} argv.timeout + */ async handler ({ ctx, hash, force, quiet, timeout }) { const { ipfs, print } = ctx diff --git a/packages/ipfs-cli/src/commands/block/stat.js b/packages/ipfs-cli/src/commands/block/stat.js index 75badcdc03..5b6ac98497 100644 --- a/packages/ipfs-cli/src/commands/block/stat.js +++ b/packages/ipfs-cli/src/commands/block/stat.js @@ -3,6 +3,7 @@ const multibase = require('multibase') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../utils') module.exports = { command: 'stat ', @@ -10,6 +11,10 @@ module.exports = { describe: 'Print information of a raw IPFS block', builder: { + key: { + type: 'string', + coerce: coerceCID + }, 'cid-base': { describe: 'Number base to display CIDs in.', type: 'string', @@ -21,6 +26,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx, key, cidBase, timeout }) { const { ipfs, print } = ctx const stats = await ipfs.block.stat(key, { diff --git a/packages/ipfs-cli/src/commands/bootstrap.js b/packages/ipfs-cli/src/commands/bootstrap.js index 9991e966ef..528d9b6987 100644 --- a/packages/ipfs-cli/src/commands/bootstrap.js +++ b/packages/ipfs-cli/src/commands/bootstrap.js @@ -5,6 +5,9 @@ module.exports = { description: 'Show or edit the list of bootstrap peers.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('bootstrap') diff --git a/packages/ipfs-cli/src/commands/bootstrap/add.js b/packages/ipfs-cli/src/commands/bootstrap/add.js index eda65fca1f..bfc97b9fb5 100644 --- a/packages/ipfs-cli/src/commands/bootstrap/add.js +++ b/packages/ipfs-cli/src/commands/bootstrap/add.js @@ -1,6 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { coerceMultiaddr } = require('../../utils') module.exports = { command: 'add []', @@ -8,6 +9,10 @@ module.exports = { describe: 'Add peers to the bootstrap list', builder: { + peer: { + type: 'string', + coerce: coerceMultiaddr + }, default: { describe: 'Add default bootstrap nodes.', type: 'boolean', @@ -19,6 +24,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('multiaddr')} argv.peer + * @param {boolean} argv.default + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, peer, default: defaultPeers, timeout }) { let list @@ -34,6 +46,6 @@ module.exports = { throw new Error('Please specify a peer or the --default flag') } - list.Peers.forEach((peer) => print(peer)) + list.Peers.forEach((peer) => print(peer.toString())) } } diff --git a/packages/ipfs-cli/src/commands/bootstrap/list.js b/packages/ipfs-cli/src/commands/bootstrap/list.js index f4660867f3..d930cb0d17 100644 --- a/packages/ipfs-cli/src/commands/bootstrap/list.js +++ b/packages/ipfs-cli/src/commands/bootstrap/list.js @@ -14,10 +14,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { const list = await ipfs.bootstrap.list({ timeout }) - list.Peers.forEach((node) => print(node)) + list.Peers.forEach((node) => print(node.toString())) } } diff --git a/packages/ipfs-cli/src/commands/bootstrap/rm.js b/packages/ipfs-cli/src/commands/bootstrap/rm.js index 72a691cc5b..27bb6b73d2 100644 --- a/packages/ipfs-cli/src/commands/bootstrap/rm.js +++ b/packages/ipfs-cli/src/commands/bootstrap/rm.js @@ -1,6 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { coerceMultiaddr } = require('../../utils') module.exports = { command: 'rm []', @@ -8,6 +9,10 @@ module.exports = { describe: 'Removes peers from the bootstrap list', builder: { + peer: { + type: 'string', + coerce: coerceMultiaddr + }, all: { type: 'boolean', describe: 'Remove all bootstrap peers.', @@ -19,6 +24,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('multiaddr')} argv.peer + * @param {boolean} argv.all + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, all, peer, timeout }) { let list @@ -34,6 +46,6 @@ module.exports = { throw new Error('Please specify a peer or the --all flag') } - list.Peers.forEach((peer) => print(peer)) + list.Peers.forEach((peer) => print(peer.toString())) } } diff --git a/packages/ipfs-cli/src/commands/cat.js b/packages/ipfs-cli/src/commands/cat.js index 03eb51d745..864814191e 100644 --- a/packages/ipfs-cli/src/commands/cat.js +++ b/packages/ipfs-cli/src/commands/cat.js @@ -24,6 +24,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} argv.ipfsPath + * @param {number} argv.offset + * @param {number} argv.length + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, ipfsPath, offset, length, timeout }) { for await (const buf of ipfs.cat(ipfsPath, { offset, length, timeout })) { print.write(buf) diff --git a/packages/ipfs-cli/src/commands/cid.js b/packages/ipfs-cli/src/commands/cid.js index 278ad5872c..e2a7ab88cf 100644 --- a/packages/ipfs-cli/src/commands/cid.js +++ b/packages/ipfs-cli/src/commands/cid.js @@ -11,6 +11,9 @@ module.exports = { description: 'Convert, format and discover properties of CIDs.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir(cidCommandsPath) diff --git a/packages/ipfs-cli/src/commands/commands.js b/packages/ipfs-cli/src/commands/commands.js index b06d65a78c..4fb33c3f3f 100644 --- a/packages/ipfs-cli/src/commands/commands.js +++ b/packages/ipfs-cli/src/commands/commands.js @@ -9,6 +9,10 @@ module.exports = { describe: 'List all available commands', + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + */ async handler ({ ctx }) { const { print } = ctx diff --git a/packages/ipfs-cli/src/commands/config.js b/packages/ipfs-cli/src/commands/config.js index 7d557dc450..bb1e5b5846 100644 --- a/packages/ipfs-cli/src/commands/config.js +++ b/packages/ipfs-cli/src/commands/config.js @@ -7,6 +7,9 @@ module.exports = { description: 'Get and set IPFS config values.', + /** + * @param {import('yargs').Argv} yargs + */ builder: (yargs) => { return yargs .commandDir('config') @@ -26,6 +29,15 @@ module.exports = { }) }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {any} argv.value + * @param {boolean} argv.bool + * @param {boolean} argv.json + * @param {string} argv.key + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, value, bool, json, key, timeout }) { if (!value) { // Get the value of a given key diff --git a/packages/ipfs-cli/src/commands/config/edit.js b/packages/ipfs-cli/src/commands/config/edit.js index 6ebbb7a718..2662ed2600 100644 --- a/packages/ipfs-cli/src/commands/config/edit.js +++ b/packages/ipfs-cli/src/commands/config/edit.js @@ -8,6 +8,10 @@ module.exports = { describe: 'Opens the config file for editing in $EDITOR', + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + */ async handler (argv) { const editor = process.env.EDITOR diff --git a/packages/ipfs-cli/src/commands/config/profile.js b/packages/ipfs-cli/src/commands/config/profile.js index b05402a502..a167f2a8ff 100644 --- a/packages/ipfs-cli/src/commands/config/profile.js +++ b/packages/ipfs-cli/src/commands/config/profile.js @@ -5,6 +5,9 @@ module.exports = { description: 'Interact with config profiles.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('profile') diff --git a/packages/ipfs-cli/src/commands/config/profile/apply.js b/packages/ipfs-cli/src/commands/config/profile/apply.js index c90458af1b..8d9081bd9f 100644 --- a/packages/ipfs-cli/src/commands/config/profile/apply.js +++ b/packages/ipfs-cli/src/commands/config/profile/apply.js @@ -20,6 +20,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {string} argv.profile + * @param {boolean} argv.dryRun + * @param {number} argv.timeout + */ async handler ({ ctx, profile, dryRun, timeout }) { const { print, ipfs, isDaemon } = ctx const diff = await ipfs.config.profiles.apply(profile, { diff --git a/packages/ipfs-cli/src/commands/config/profile/ls.js b/packages/ipfs-cli/src/commands/config/profile/ls.js index b5490f34fc..6582627878 100644 --- a/packages/ipfs-cli/src/commands/config/profile/ls.js +++ b/packages/ipfs-cli/src/commands/config/profile/ls.js @@ -14,6 +14,11 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { for (const profile of await ipfs.config.profiles.list({ timeout diff --git a/packages/ipfs-cli/src/commands/config/replace.js b/packages/ipfs-cli/src/commands/config/replace.js index 5e39099e92..ed38eb085f 100644 --- a/packages/ipfs-cli/src/commands/config/replace.js +++ b/packages/ipfs-cli/src/commands/config/replace.js @@ -16,6 +16,12 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.file + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs, isDaemon }, file, timeout }) { const filePath = path.resolve(process.cwd(), file) diff --git a/packages/ipfs-cli/src/commands/config/show.js b/packages/ipfs-cli/src/commands/config/show.js index 4c9614ca4b..0b311461f9 100644 --- a/packages/ipfs-cli/src/commands/config/show.js +++ b/packages/ipfs-cli/src/commands/config/show.js @@ -14,6 +14,11 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { const config = await ipfs.config.getAll({ timeout diff --git a/packages/ipfs-cli/src/commands/daemon.js b/packages/ipfs-cli/src/commands/daemon.js index 81340208b9..ad8085d64f 100644 --- a/packages/ipfs-cli/src/commands/daemon.js +++ b/packages/ipfs-cli/src/commands/daemon.js @@ -2,6 +2,7 @@ const os = require('os') const fs = require('fs') +// @ts-ignore no types const toUri = require('multiaddr-to-uri') const { ipfsPathHelp } = require('../utils') const { isTest } = require('ipfs-utils/src/env') @@ -12,6 +13,9 @@ module.exports = { describe: 'Start a long-running daemon process', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .epilog(ipfsPathHelp) @@ -45,6 +49,19 @@ module.exports = { }) }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} [argv.initConfig] + * @param {string[]} [argv.initProfile] + * @param {boolean} argv.enableShardingExperiment + * @param {boolean} argv.offline + * @param {boolean} argv.enableNamesysPubsub + * @param {boolean} argv.enablePreload + * @param {boolean} argv.silent + * @param {boolean} argv.migrate + * @param {string} argv.pass + */ async handler (argv) { const { print, repoPath } = argv.ctx print('Initializing IPFS daemon...') @@ -78,7 +95,7 @@ module.exports = { ipnsPubsub: argv.enableNamesysPubsub, sharding: argv.enableShardingExperiment }, - init: argv.initProfile ? { profiles: argv.initProfile } : true + init: argv.initProfile ? { profiles: argv.initProfile } : undefined }) try { @@ -88,7 +105,7 @@ module.exports = { print(`HTTP API listening on ${apiServer.info.ma}`) }) // @ts-ignore - _grpcServer is possibly undefined - print(`gRPC listening on ${daemon._grpcServer.multiaddr}`) + print(`gRPC listening on ${daemon._grpcServer.info.ma}`) // @ts-ignore - _httpGateway is possibly undefined daemon._httpGateway._gatewayServers.forEach(gatewayServer => { print(`Gateway (read only) listening on ${gatewayServer.info.ma}`) diff --git a/packages/ipfs-cli/src/commands/dag.js b/packages/ipfs-cli/src/commands/dag.js index 68669b2628..a4c45fe166 100644 --- a/packages/ipfs-cli/src/commands/dag.js +++ b/packages/ipfs-cli/src/commands/dag.js @@ -5,6 +5,9 @@ module.exports = { description: 'Interact with ipld dag objects.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('dag') diff --git a/packages/ipfs-cli/src/commands/dag/get.js b/packages/ipfs-cli/src/commands/dag/get.js index 92f1cdf10b..c8c1031010 100644 --- a/packages/ipfs-cli/src/commands/dag/get.js +++ b/packages/ipfs-cli/src/commands/dag/get.js @@ -38,6 +38,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.cidpath + * @param {import('multibase').BaseName} argv.cidBase + * @param {'base16' | 'base64' | 'base58btc'} argv.dataEnc + * @param {boolean} argv.localResolve + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, cidpath, cidBase, dataEnc, localResolve, timeout }) { const options = { localResolve, @@ -67,11 +76,14 @@ module.exports = { const node = result.value if (cid.codec === 'dag-pb') { + /** @type {import('ipld-dag-pb').DAGNode} */ + const dagNode = node + print(JSON.stringify({ - data: node.Data ? uint8ArrayToString(node.Data, dataEnc) : undefined, - links: (node.Links || []).map(link => ({ + data: dagNode.Data ? uint8ArrayToString(node.Data, dataEnc) : undefined, + links: (dagNode.Links || []).map(link => ({ Name: stripControlCharacters(link.Name), - Size: link.Size, + Size: link.Tsize, Cid: { '/': cidToString(link.Hash, { base: cidBase }) } })) })) diff --git a/packages/ipfs-cli/src/commands/dag/put.js b/packages/ipfs-cli/src/commands/dag/put.js index 40aa9629e6..fd4c1cb81a 100644 --- a/packages/ipfs-cli/src/commands/dag/put.js +++ b/packages/ipfs-cli/src/commands/dag/put.js @@ -8,15 +8,24 @@ const concat = require('it-concat') const CID = require('cids') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') -const uint8ArrayToString = require('uint8arrays/to-string') +/** + * @typedef {'dag-cbor' | 'dag-pb' | 'raw'} SupportedFormat + */ + +/** + * @type {Record any>} + */ const inputDecoders = { - json: (buf) => JSON.parse(uint8ArrayToString(buf)), + json: (buf) => JSON.parse(buf.toString()), cbor: (buf) => dagCBOR.util.deserialize(buf), protobuf: (buf) => dagPB.util.deserialize(buf), raw: (buf) => buf } +/** + * @type {Record} + */ const formats = { cbor: 'dag-cbor', raw: 'raw', @@ -86,6 +95,20 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.data + * @param {'dag-cbor' | 'dag-pb' | 'raw' | 'cbor' | 'protobuf'} argv.format + * @param {'json' | 'cbor' | 'raw' | 'protobuf'} argv.inputEncoding + * @param {import('cids').CIDVersion} argv.cidVersion + * @param {boolean} argv.pin + * @param {import('multihashes').HashName} argv.hashAlg + * @param {import('multibase').BaseName} argv.cidBase + * @param {boolean} argv.preload + * @param {boolean} argv.onlyHash + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print, getStdin }, data, format, inputEncoding, pin, hashAlg, cidVersion, cidBase, preload, onlyHash, timeout }) { if (inputEncoding === 'cbor') { format = 'dag-cbor' @@ -99,13 +122,14 @@ module.exports = { cidVersion = 1 } - let source = data + /** @type {Buffer} */ + let source - if (!source) { + if (!data) { // pipe from stdin - source = (await concat(getStdin())).slice() + source = (await concat(getStdin(), { type: 'buffer' })).slice() } else { - source = Buffer.from(source) + source = Buffer.from(data) } source = inputDecoders[inputEncoding](source) @@ -130,6 +154,10 @@ module.exports = { } } +/** + * @param {any} obj + * @returns {any} + */ function objectSlashToCID (obj) { if (Array.isArray(obj)) { return obj.map(objectSlashToCID) diff --git a/packages/ipfs-cli/src/commands/dag/resolve.js b/packages/ipfs-cli/src/commands/dag/resolve.js index 2bec53ab52..b5bff741ff 100644 --- a/packages/ipfs-cli/src/commands/dag/resolve.js +++ b/packages/ipfs-cli/src/commands/dag/resolve.js @@ -17,6 +17,12 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.ref + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, ref, timeout }) { const options = { timeout @@ -32,6 +38,7 @@ module.exports = { ref = ref.substring(6) } + // @ts-ignore we will toString this so it doesn't matter lastCid = ref.split('/').shift() } diff --git a/packages/ipfs-cli/src/commands/dht.js b/packages/ipfs-cli/src/commands/dht.js index 549f37a77c..c02bae3ff9 100644 --- a/packages/ipfs-cli/src/commands/dht.js +++ b/packages/ipfs-cli/src/commands/dht.js @@ -5,6 +5,9 @@ module.exports = { description: 'Issue commands directly through the DHT.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs.commandDir('dht') } diff --git a/packages/ipfs-cli/src/commands/dht/find-peer.js b/packages/ipfs-cli/src/commands/dht/find-peer.js index 1aa6e8afd9..f999af636b 100644 --- a/packages/ipfs-cli/src/commands/dht/find-peer.js +++ b/packages/ipfs-cli/src/commands/dht/find-peer.js @@ -8,12 +8,21 @@ module.exports = { describe: 'Find the multiaddresses associated with a Peer ID.', builder: { + peerId: { + type: 'string' + }, timeout: { type: 'string', coerce: parseDuration } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.peerId + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, peerId, timeout }) { const peer = await ipfs.dht.findPeer(peerId, { timeout diff --git a/packages/ipfs-cli/src/commands/dht/find-providers.js b/packages/ipfs-cli/src/commands/dht/find-providers.js index a51d8fa3f8..0150b430f0 100644 --- a/packages/ipfs-cli/src/commands/dht/find-providers.js +++ b/packages/ipfs-cli/src/commands/dht/find-providers.js @@ -1,6 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../utils') module.exports = { command: 'findprovs ', @@ -8,6 +9,10 @@ module.exports = { describe: 'Find peers that can provide a specific value, given a key.', builder: { + key: { + type: 'string', + coerce: coerceCID + }, 'num-providers': { alias: 'n', describe: 'The number of providers to find. Default: 20.', @@ -20,6 +25,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {number} argv.numProviders + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, key, numProviders, timeout }) { for await (const prov of ipfs.dht.findProvs(key, { numProviders, diff --git a/packages/ipfs-cli/src/commands/dht/get.js b/packages/ipfs-cli/src/commands/dht/get.js index 2e146f938b..4734c7d769 100644 --- a/packages/ipfs-cli/src/commands/dht/get.js +++ b/packages/ipfs-cli/src/commands/dht/get.js @@ -1,6 +1,8 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../utils') +const uint8ArrayToString = require('uint8arrays/to-string') module.exports = { command: 'get ', @@ -8,16 +10,26 @@ module.exports = { describe: 'Given a key, query the routing system for its best value.', builder: { + key: { + type: 'string', + coerce: coerceCID + }, timeout: { type: 'string', coerce: parseDuration } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, key, timeout }) { - const value = await ipfs.dht.get(key, { + const value = await ipfs.dht.get(key.bytes, { timeout }) - print(value) + print(uint8ArrayToString(value, 'base58btc')) } } diff --git a/packages/ipfs-cli/src/commands/dht/provide.js b/packages/ipfs-cli/src/commands/dht/provide.js index 2a9314dfd7..63e747053e 100644 --- a/packages/ipfs-cli/src/commands/dht/provide.js +++ b/packages/ipfs-cli/src/commands/dht/provide.js @@ -1,6 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../utils') module.exports = { command: 'provide ', @@ -8,6 +9,10 @@ module.exports = { describe: 'Announce to the network that you are providing given values.', builder: { + key: { + type: 'string', + coerce: coerceCID + }, recursive: { alias: 'r', recursive: 'Recursively provide entire graph.', @@ -20,6 +25,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {boolean} argv.recursive + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs }, key, recursive, timeout }) { await ipfs.dht.provide(key, { recursive, diff --git a/packages/ipfs-cli/src/commands/dht/put.js b/packages/ipfs-cli/src/commands/dht/put.js index fb62c783c2..f877536362 100644 --- a/packages/ipfs-cli/src/commands/dht/put.js +++ b/packages/ipfs-cli/src/commands/dht/put.js @@ -1,6 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const uint8ArrayFromString = require('uint8arrays/from-string') module.exports = { command: 'put ', @@ -14,8 +15,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.key + * @param {string} argv.value + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs }, key, value, timeout }) { - await ipfs.dht.put(key, value, { + await ipfs.dht.put(uint8ArrayFromString(key), uint8ArrayFromString(value), { timeout }) } diff --git a/packages/ipfs-cli/src/commands/dht/query.js b/packages/ipfs-cli/src/commands/dht/query.js index 6bc9c6ab26..fb3240dfce 100644 --- a/packages/ipfs-cli/src/commands/dht/query.js +++ b/packages/ipfs-cli/src/commands/dht/query.js @@ -8,12 +8,21 @@ module.exports = { describe: 'Find the closest Peer IDs to a given Peer ID by querying the DHT.', builder: { + peerId: { + type: 'string' + }, timeout: { type: 'string', coerce: parseDuration } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.peerId + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, peerId, timeout }) { for await (const result of ipfs.dht.query(peerId, { timeout diff --git a/packages/ipfs-cli/src/commands/dns.js b/packages/ipfs-cli/src/commands/dns.js index ac70670b0c..69c5031913 100644 --- a/packages/ipfs-cli/src/commands/dns.js +++ b/packages/ipfs-cli/src/commands/dns.js @@ -17,17 +17,21 @@ module.exports = { alias: 'r', desc: 'Resolve until the result is not a DNS link' }, - format: { - type: 'string' - }, timeout: { type: 'string', coerce: parseDuration } }, - async handler ({ ctx: { ipfs, print }, domain, recursive, format, timeout }) { - const path = await ipfs.dns(domain, { recursive, format, timeout }) + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} argv.domain + * @param {boolean} argv.recursive + * @param {number} argv.timeout + */ + async handler ({ ctx: { ipfs, print }, domain, recursive, timeout }) { + const path = await ipfs.dns(domain, { recursive, timeout }) print(stripControlCharacters(path)) } } diff --git a/packages/ipfs-cli/src/commands/files.js b/packages/ipfs-cli/src/commands/files.js index 1b1a8c4c8e..1b662a49ab 100644 --- a/packages/ipfs-cli/src/commands/files.js +++ b/packages/ipfs-cli/src/commands/files.js @@ -5,11 +5,18 @@ module.exports = { description: 'Operations over mfs files (ls, mkdir, rm, etc)', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs.commandDir('files') }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + */ handler (argv) { - argv.print('Type `jsipfs files --help` for more instructions') + argv.ctx.print('Type `jsipfs files --help` for more instructions') } } diff --git a/packages/ipfs-cli/src/commands/files/chmod.js b/packages/ipfs-cli/src/commands/files/chmod.js index 7cc3959c08..f45d03454a 100644 --- a/packages/ipfs-cli/src/commands/files/chmod.js +++ b/packages/ipfs-cli/src/commands/files/chmod.js @@ -50,6 +50,17 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {number} argv.mode + * @param {boolean} argv.recursive + * @param {import('multihashes').HashName} argv.hashAlg + * @param {boolean} argv.flush + * @param {number} argv.shardSplitThreshold + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs }, path, diff --git a/packages/ipfs-cli/src/commands/files/cp.js b/packages/ipfs-cli/src/commands/files/cp.js index 080ec0faef..8d5ba3dc56 100644 --- a/packages/ipfs-cli/src/commands/files/cp.js +++ b/packages/ipfs-cli/src/commands/files/cp.js @@ -42,6 +42,17 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.source + * @param {string} argv.dest + * @param {boolean} argv.parents + * @param {import('multihashes').HashName} argv.hashAlg + * @param {boolean} argv.flush + * @param {number} argv.shardSplitThreshold + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs }, source, diff --git a/packages/ipfs-cli/src/commands/files/flush.js b/packages/ipfs-cli/src/commands/files/flush.js index 856bd9eabe..826fde50f3 100644 --- a/packages/ipfs-cli/src/commands/files/flush.js +++ b/packages/ipfs-cli/src/commands/files/flush.js @@ -17,6 +17,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, path, diff --git a/packages/ipfs-cli/src/commands/files/ls.js b/packages/ipfs-cli/src/commands/files/ls.js index 1c399c0a0a..f3307bc643 100644 --- a/packages/ipfs-cli/src/commands/files/ls.js +++ b/packages/ipfs-cli/src/commands/files/ls.js @@ -30,6 +30,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {boolean} argv.long + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, path, @@ -37,11 +45,14 @@ module.exports = { cidBase, timeout }) { + /** + * @param {import('ipfs-core-types/src/files').MFSEntry} file + */ const printListing = file => { const name = stripControlCharacters(file.name) if (long) { - print(`${formatMode(file.mode, file.type === 1)}\t${formatMtime(file.mtime)}\t${name}\t${file.cid.toString(cidBase)}\t${file.size}`) + print(`${file.mode ? formatMode(file.mode, file.type === 'directory') : ''}\t${file.mtime ? formatMtime(file.mtime) : ''}\t${name}\t${file.cid.toString(cidBase)}\t${file.size}`) } else { print(name) } diff --git a/packages/ipfs-cli/src/commands/files/mkdir.js b/packages/ipfs-cli/src/commands/files/mkdir.js index 3dcfa25c2f..278ff855a0 100644 --- a/packages/ipfs-cli/src/commands/files/mkdir.js +++ b/packages/ipfs-cli/src/commands/files/mkdir.js @@ -67,6 +67,20 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {boolean} argv.parents + * @param {import('cids').CIDVersion} argv.cidVersion + * @param {import('multihashes').HashName} argv.hashAlg + * @param {boolean} argv.flush + * @param {number} argv.shardSplitThreshold + * @param {number} argv.mode + * @param {number} argv.mtime + * @param {number} argv.mtimeNsecs + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs }, path, diff --git a/packages/ipfs-cli/src/commands/files/mv.js b/packages/ipfs-cli/src/commands/files/mv.js index c9134ad852..510d89c031 100644 --- a/packages/ipfs-cli/src/commands/files/mv.js +++ b/packages/ipfs-cli/src/commands/files/mv.js @@ -18,13 +18,6 @@ module.exports = { coerce: asBoolean, describe: 'Create any non-existent intermediate directories' }, - recursive: { - alias: 'r', - type: 'boolean', - default: false, - coerce: asBoolean, - describe: 'Remove directories recursively' - }, 'cid-version': { alias: ['cid-ver'], type: 'number', @@ -55,12 +48,23 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.source + * @param {string} argv.dest + * @param {boolean} argv.parents + * @param {import('cids').CIDVersion} argv.cidVersion + * @param {import('multihashes').HashName} argv.hashAlg + * @param {boolean} argv.flush + * @param {number} argv.shardSplitThreshold + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs }, source, dest, parents, - recursive, cidVersion, hashAlg, flush, @@ -69,7 +73,6 @@ module.exports = { }) { return ipfs.files.mv(source, dest, { parents, - recursive, cidVersion, hashAlg, flush, diff --git a/packages/ipfs-cli/src/commands/files/read.js b/packages/ipfs-cli/src/commands/files/read.js index eff2776ab0..4bc443cb7c 100644 --- a/packages/ipfs-cli/src/commands/files/read.js +++ b/packages/ipfs-cli/src/commands/files/read.js @@ -24,6 +24,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {number} argv.offset + * @param {number} argv.length + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, path, diff --git a/packages/ipfs-cli/src/commands/files/rm.js b/packages/ipfs-cli/src/commands/files/rm.js index fee89655ec..24e55dfd91 100644 --- a/packages/ipfs-cli/src/commands/files/rm.js +++ b/packages/ipfs-cli/src/commands/files/rm.js @@ -24,6 +24,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {boolean} argv.recursive + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs }, path, diff --git a/packages/ipfs-cli/src/commands/files/stat.js b/packages/ipfs-cli/src/commands/files/stat.js index e1833882c3..975da6240c 100644 --- a/packages/ipfs-cli/src/commands/files/stat.js +++ b/packages/ipfs-cli/src/commands/files/stat.js @@ -55,6 +55,17 @@ Mtime: `, } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {string} argv.format + * @param {boolean} argv.hash + * @param {boolean} argv.size + * @param {boolean} argv.withLocal + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs, print }, path, @@ -75,17 +86,17 @@ Mtime: `, } if (size) { - return print(stats.size) + return print(`${stats.size}`) } print(format .replace('', stats.cid.toString(cidBase)) - .replace('', stats.size) - .replace('', stats.cumulativeSize) - .replace('', stats.blocks) + .replace('', `${stats.size}`) + .replace('', `${stats.cumulativeSize}`) + .replace('', `${stats.blocks}`) .replace('', stats.type) - .replace('', formatMode(stats.mode, stats.type === 'directory')) - .replace('', formatMtime(stats.mtime)) + .replace('', stats.mode ? formatMode(stats.mode, stats.type === 'directory') : '') + .replace('', stats.mtime ? formatMtime(stats.mtime) : '') ) }) } diff --git a/packages/ipfs-cli/src/commands/files/touch.js b/packages/ipfs-cli/src/commands/files/touch.js index d311a7f4f4..0478b9dd3c 100644 --- a/packages/ipfs-cli/src/commands/files/touch.js +++ b/packages/ipfs-cli/src/commands/files/touch.js @@ -55,6 +55,18 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {boolean} argv.flush + * @param {import('cids').CIDVersion} argv.cidVersion + * @param {import('multihashes').HashName} argv.hashAlg + * @param {number} argv.shardSplitThreshold + * @param {number} argv.mtime + * @param {number} argv.mtimeNsecs + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs }, path, diff --git a/packages/ipfs-cli/src/commands/files/write.js b/packages/ipfs-cli/src/commands/files/write.js index 7cca614770..bbadaba144 100644 --- a/packages/ipfs-cli/src/commands/files/write.js +++ b/packages/ipfs-cli/src/commands/files/write.js @@ -107,6 +107,27 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.path + * @param {number} argv.offset + * @param {number} argv.length + * @param {boolean} argv.create + * @param {boolean} argv.truncate + * @param {boolean} argv.rawLeaves + * @param {boolean} argv.reduceSingleLeafToSelf + * @param {import('cids').CIDVersion} argv.cidVersion + * @param {import('multihashes').HashName} argv.hashAlg + * @param {boolean} argv.parents + * @param {'trickle' | 'balanced'} argv.strategy + * @param {boolean} argv.flush + * @param {number} argv.shardSplitThreshold + * @param {number} argv.mode + * @param {number} argv.mtime + * @param {number} argv.mtimeNsecs + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, getStdin }, path, @@ -119,7 +140,6 @@ module.exports = { cidVersion, hashAlg, parents, - progress, strategy, flush, shardSplitThreshold, @@ -138,7 +158,6 @@ module.exports = { cidVersion, hashAlg, parents, - progress, strategy, flush, shardSplitThreshold, diff --git a/packages/ipfs-cli/src/commands/get.js b/packages/ipfs-cli/src/commands/get.js index db703b19b6..2d09c5c05f 100644 --- a/packages/ipfs-cli/src/commands/get.js +++ b/packages/ipfs-cli/src/commands/get.js @@ -2,6 +2,7 @@ const fs = require('fs') const path = require('path') +// @ts-ignore no types const toIterable = require('stream-to-it') const { pipe } = require('it-pipe') const { map } = require('streaming-iterables') @@ -32,6 +33,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} argv.ipfsPath + * @param {string} argv.output + * @param {boolean} argv.force + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, ipfsPath, output, force, timeout }) { print(`Saving file(s) ${stripControlCharacters(ipfsPath)}`) @@ -44,7 +53,7 @@ module.exports = { throw new Error(`File prefix invalid, would write to files outside of ${output}, pass --force to override`) } - if (file.content) { + if (file.type === 'file') { await fs.promises.mkdir(path.join(output, path.dirname(file.path)), { recursive: true }) await pipe( file.content, diff --git a/packages/ipfs-cli/src/commands/id.js b/packages/ipfs-cli/src/commands/id.js index 56cb71a638..d937204b8d 100644 --- a/packages/ipfs-cli/src/commands/id.js +++ b/packages/ipfs-cli/src/commands/id.js @@ -19,6 +19,12 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} argv.format + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, format, timeout }) { const id = await ipfs.id({ timeout diff --git a/packages/ipfs-cli/src/commands/init.js b/packages/ipfs-cli/src/commands/init.js index ff29400fde..f28340504b 100644 --- a/packages/ipfs-cli/src/commands/init.js +++ b/packages/ipfs-cli/src/commands/init.js @@ -10,6 +10,10 @@ module.exports = { 'If you are going to run IPFS in a server environment, you may want to ' + 'initialize it using the \'server\' profile.\n\n' + 'For the list of available profiles run `jsipfs config profile ls`', + + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .epilog(ipfsPathHelp) @@ -20,8 +24,8 @@ module.exports = { .option('algorithm', { type: 'string', alias: 'a', - default: 'rsa', - describe: 'Cryptographic algorithm to use for key generation. Supports [rsa, ed25519, secp256k1]' + default: 'RSA', + describe: 'Cryptographic algorithm to use for key generation. Supports [RSA, Ed25519, secp256k1]' }) .option('bits', { type: 'number', @@ -50,6 +54,17 @@ module.exports = { }) }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} argv.defaultConfig + * @param {'RSA' | 'Ed25519' | 'secp256k1'} argv.algorithm + * @param {number} argv.bits + * @param {boolean} argv.emptyRepo + * @param {string} argv.privateKey + * @param {string[]} argv.profile + * @param {string} argv.pass + */ async handler (argv) { const { print, repoPath } = argv.ctx let config = {} @@ -78,9 +93,9 @@ module.exports = { bits: argv.bits, privateKey: argv.privateKey, emptyRepo: argv.emptyRepo, - profiles: argv.profile, - pass: argv.pass + profiles: argv.profile }, + pass: argv.pass, start: false, // @ts-ignore - Expects more than {} config diff --git a/packages/ipfs-cli/src/commands/key.js b/packages/ipfs-cli/src/commands/key.js index 09a9b825b2..24bafea997 100644 --- a/packages/ipfs-cli/src/commands/key.js +++ b/packages/ipfs-cli/src/commands/key.js @@ -5,6 +5,9 @@ module.exports = { description: 'Manage your keys', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('key') diff --git a/packages/ipfs-cli/src/commands/key/export.js b/packages/ipfs-cli/src/commands/key/export.js index 203fba92cd..aef2ea5d08 100644 --- a/packages/ipfs-cli/src/commands/key/export.js +++ b/packages/ipfs-cli/src/commands/key/export.js @@ -27,6 +27,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.name + * @param {string} argv.passout + * @param {string} argv.output + * @param {number} argv.timeout + */ async handler ({ ctx, name, passout, output, timeout }) { const { ipfs } = ctx const pem = await ipfs.key.export(name, passout, { diff --git a/packages/ipfs-cli/src/commands/key/gen.js b/packages/ipfs-cli/src/commands/key/gen.js index f57ec66a88..50f53ba9c9 100644 --- a/packages/ipfs-cli/src/commands/key/gen.js +++ b/packages/ipfs-cli/src/commands/key/gen.js @@ -28,6 +28,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.name + * @param {string} argv.type + * @param {number} argv.size + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, name, type, size, timeout }) { const key = await ipfs.key.gen(name, { type, diff --git a/packages/ipfs-cli/src/commands/key/import.js b/packages/ipfs-cli/src/commands/key/import.js index f71a9a8903..30b79550d8 100644 --- a/packages/ipfs-cli/src/commands/key/import.js +++ b/packages/ipfs-cli/src/commands/key/import.js @@ -19,6 +19,9 @@ module.exports = { describe: 'Input PEM file', type: 'string', demandOption: true, + /** + * @param {string} input + */ coerce: input => fs.readFileSync(input, 'utf8') }, timeout: { @@ -27,6 +30,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.name + * @param {string} argv.input + * @param {string} argv.passin + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, name, input, passin, timeout }) { const key = await ipfs.key.import(name, input, passin, { timeout diff --git a/packages/ipfs-cli/src/commands/key/list.js b/packages/ipfs-cli/src/commands/key/list.js index e07e0ac615..5990a3a7ab 100644 --- a/packages/ipfs-cli/src/commands/key/list.js +++ b/packages/ipfs-cli/src/commands/key/list.js @@ -17,6 +17,11 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { const keys = await ipfs.key.list({ timeout diff --git a/packages/ipfs-cli/src/commands/key/rename.js b/packages/ipfs-cli/src/commands/key/rename.js index 4b3bc8bc0e..8cfbd87cd9 100644 --- a/packages/ipfs-cli/src/commands/key/rename.js +++ b/packages/ipfs-cli/src/commands/key/rename.js @@ -17,6 +17,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.name + * @param {string} argv.newName + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, name, newName, timeout }) { const res = await ipfs.key.rename(name, newName, { timeout diff --git a/packages/ipfs-cli/src/commands/key/rm.js b/packages/ipfs-cli/src/commands/key/rm.js index b9de77ae45..d628fa770d 100644 --- a/packages/ipfs-cli/src/commands/key/rm.js +++ b/packages/ipfs-cli/src/commands/key/rm.js @@ -17,6 +17,12 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.name + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, name, timeout }) { const key = await ipfs.key.rm(name, { timeout diff --git a/packages/ipfs-cli/src/commands/ls.js b/packages/ipfs-cli/src/commands/ls.js index 032bdbce41..1305ade633 100644 --- a/packages/ipfs-cli/src/commands/ls.js +++ b/packages/ipfs-cli/src/commands/ls.js @@ -41,6 +41,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} argv.key + * @param {boolean} argv.recursive + * @param {boolean} argv.headers + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, key, recursive, headers, cidBase, timeout }) { // replace multiple slashes key = key.replace(/\/(\/+)/g, '/') @@ -58,12 +67,24 @@ module.exports = { let first = true + /** @type {number[]} */ let maxWidths = [] + /** + * @param {...string} args + */ const getMaxWidths = (...args) => { maxWidths = args.map((v, i) => Math.max(maxWidths[i] || 0, v.length)) return maxWidths } + /** + * @param {*} mode + * @param {*} mtime + * @param {*} cid + * @param {*} size + * @param {*} name + * @param {*} depth + */ const printLink = (mode, mtime, cid, size, name, depth = 0) => { name = stripControlCharacters(name) const widths = getMaxWidths(mode, mtime, cid, size, name) @@ -79,8 +100,8 @@ module.exports = { } for await (const link of ipfs.ls(key, { recursive, timeout })) { - const mode = formatMode(link.mode, link.type === 'dir') - const mtime = formatMtime(link.mtime) + const mode = link.mode != null ? formatMode(link.mode, link.type === 'dir') : '' + const mtime = link.mtime != null ? formatMtime(link.mtime) : '-' const cid = cidToString(link.cid, { base: cidBase }) const size = link.size ? String(link.size) : '-' const name = stripControlCharacters(link.type === 'dir' ? `${link.name || ''}/` : link.name) diff --git a/packages/ipfs-cli/src/commands/name.js b/packages/ipfs-cli/src/commands/name.js index cb9dd7dfaa..5753d4b4fe 100644 --- a/packages/ipfs-cli/src/commands/name.js +++ b/packages/ipfs-cli/src/commands/name.js @@ -11,6 +11,9 @@ module.exports = { description: 'Publish and resolve IPNS names.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs.commandDir('name') } diff --git a/packages/ipfs-cli/src/commands/name/publish.js b/packages/ipfs-cli/src/commands/name/publish.js index 4a1f377823..645bd963b2 100644 --- a/packages/ipfs-cli/src/commands/name/publish.js +++ b/packages/ipfs-cli/src/commands/name/publish.js @@ -11,6 +11,9 @@ module.exports = { describe: 'Publish IPNS names.', builder: { + ipfsPath: { + type: 'string' + }, resolve: { alias: 'r', describe: 'Resolve given path before publishing. Default: true.', @@ -40,6 +43,16 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.ipfsPath + * @param {boolean} argv.resolve + * @param {string} argv.lifetime + * @param {string} argv.key + * @param {string} argv.ttl + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, ipfsPath, resolve, lifetime, key, ttl, timeout }) { const result = await ipfs.name.publish(ipfsPath, { resolve, diff --git a/packages/ipfs-cli/src/commands/name/pubsub.js b/packages/ipfs-cli/src/commands/name/pubsub.js index 85851b9024..2beff40a68 100644 --- a/packages/ipfs-cli/src/commands/name/pubsub.js +++ b/packages/ipfs-cli/src/commands/name/pubsub.js @@ -9,8 +9,10 @@ module.exports = { description: 'IPNS pubsub management.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs.commandDir('pubsub') } - } diff --git a/packages/ipfs-cli/src/commands/name/pubsub/cancel.js b/packages/ipfs-cli/src/commands/name/pubsub/cancel.js index 335e8beb51..b463a01e8f 100644 --- a/packages/ipfs-cli/src/commands/name/pubsub/cancel.js +++ b/packages/ipfs-cli/src/commands/name/pubsub/cancel.js @@ -14,6 +14,12 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {string} argv.name + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, name, timeout }) { const result = await ipfs.name.pubsub.cancel(name, { timeout diff --git a/packages/ipfs-cli/src/commands/name/pubsub/state.js b/packages/ipfs-cli/src/commands/name/pubsub/state.js index f864b42dc7..adc779c185 100644 --- a/packages/ipfs-cli/src/commands/name/pubsub/state.js +++ b/packages/ipfs-cli/src/commands/name/pubsub/state.js @@ -14,6 +14,11 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { const result = await ipfs.name.pubsub.state({ timeout diff --git a/packages/ipfs-cli/src/commands/name/pubsub/subs.js b/packages/ipfs-cli/src/commands/name/pubsub/subs.js index 60d05bf6e1..ed8f79e650 100644 --- a/packages/ipfs-cli/src/commands/name/pubsub/subs.js +++ b/packages/ipfs-cli/src/commands/name/pubsub/subs.js @@ -17,6 +17,11 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { const result = await ipfs.name.pubsub.subs({ timeout diff --git a/packages/ipfs-cli/src/commands/name/resolve.js b/packages/ipfs-cli/src/commands/name/resolve.js index 797874a3b5..4d73d64678 100644 --- a/packages/ipfs-cli/src/commands/name/resolve.js +++ b/packages/ipfs-cli/src/commands/name/resolve.js @@ -32,6 +32,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.name + * @param {boolean} argv.nocache + * @param {boolean} argv.recursive + * @param {boolean} argv.stream + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, nocache, recursive, name, stream, timeout }) { let bestValue @@ -40,6 +49,6 @@ module.exports = { if (stream) print(value) } - if (!stream) print(bestValue) + if (!stream) print(bestValue || '') } } diff --git a/packages/ipfs-cli/src/commands/object.js b/packages/ipfs-cli/src/commands/object.js index 9781528696..3dab4dd879 100644 --- a/packages/ipfs-cli/src/commands/object.js +++ b/packages/ipfs-cli/src/commands/object.js @@ -5,9 +5,11 @@ module.exports = { description: 'Interact with ipfs objects.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('object') } - } diff --git a/packages/ipfs-cli/src/commands/object/data.js b/packages/ipfs-cli/src/commands/object/data.js index 36a5da2715..f0e3334a1b 100644 --- a/packages/ipfs-cli/src/commands/object/data.js +++ b/packages/ipfs-cli/src/commands/object/data.js @@ -1,6 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../utils') module.exports = { command: 'data ', @@ -8,14 +9,24 @@ module.exports = { describe: 'Outputs the raw bytes in an IPFS object', builder: { + key: { + type: 'string', + coerce: coerceCID + }, timeout: { type: 'string', coerce: parseDuration } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, key, timeout }) { - const data = await ipfs.object.data(key, { enc: 'base58', timeout }) + const data = await ipfs.object.data(key, { timeout }) print(data, false) } } diff --git a/packages/ipfs-cli/src/commands/object/get.js b/packages/ipfs-cli/src/commands/object/get.js index 7ded234cdd..c54a0edf04 100644 --- a/packages/ipfs-cli/src/commands/object/get.js +++ b/packages/ipfs-cli/src/commands/object/get.js @@ -5,7 +5,8 @@ const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') const uint8ArrayToString = require('uint8arrays/to-string') const { - stripControlCharacters + stripControlCharacters, + coerceCID } = require('../../utils') module.exports = { @@ -14,6 +15,10 @@ module.exports = { describe: 'Get and serialize the DAG node named by ', builder: { + key: { + type: 'string', + coerce: coerceCID + }, 'data-encoding': { type: 'string', default: 'base64' @@ -29,30 +34,36 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {'base64' | 'text' | 'hex'} argv.dataEncoding + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, key, dataEncoding, cidBase, timeout }) { - const node = await ipfs.object.get(key, { enc: 'base58', timeout }) - let data = node.Data || '' + const node = await ipfs.object.get(key, { timeout }) + + /** @type {import('multibase').BaseName | 'utf8' | 'utf-8' | 'ascii' | undefined} */ + let encoding if (dataEncoding === 'base64') { - dataEncoding = 'base64pad' + encoding = 'base64pad' } if (dataEncoding === 'text') { - dataEncoding = 'ascii' + encoding = 'ascii' } if (dataEncoding === 'hex') { - dataEncoding = 'base16' - } - - if (data instanceof Uint8Array) { - data = uint8ArrayToString(node.Data, dataEncoding || undefined) + encoding = 'base16' } const answer = { - Data: data, + Data: uint8ArrayToString(node.Data, encoding), Hash: cidToString(key, { base: cidBase, upgrade: false }), - Size: node.Size, + Size: node.size, Links: node.Links.map((l) => { return { Name: stripControlCharacters(l.Name), diff --git a/packages/ipfs-cli/src/commands/object/links.js b/packages/ipfs-cli/src/commands/object/links.js index c24e18d93e..cd1adbdc15 100644 --- a/packages/ipfs-cli/src/commands/object/links.js +++ b/packages/ipfs-cli/src/commands/object/links.js @@ -4,7 +4,8 @@ const multibase = require('multibase') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') const { - stripControlCharacters + stripControlCharacters, + coerceCID } = require('../../utils') module.exports = { @@ -13,6 +14,10 @@ module.exports = { describe: 'Outputs the links pointed to by the specified object', builder: { + key: { + type: 'string', + coerce: coerceCID + }, 'cid-base': { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', @@ -24,8 +29,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, key, cidBase, timeout }) { - const links = await ipfs.object.links(key, { enc: 'base58', timeout }) + const links = await ipfs.object.links(key, { timeout }) links.forEach((link) => { const cidStr = cidToString(link.Hash, { base: cidBase, upgrade: false }) diff --git a/packages/ipfs-cli/src/commands/object/new.js b/packages/ipfs-cli/src/commands/object/new.js index 2a10f093c9..3758cd5ff1 100644 --- a/packages/ipfs-cli/src/commands/object/new.js +++ b/packages/ipfs-cli/src/commands/object/new.js @@ -21,6 +21,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {'unixfs-dir'} argv.template + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, template, cidBase, timeout }) { const cid = await ipfs.object.new({ template, diff --git a/packages/ipfs-cli/src/commands/object/patch.js b/packages/ipfs-cli/src/commands/object/patch.js index 9ed767f3bd..8c7a028123 100644 --- a/packages/ipfs-cli/src/commands/object/patch.js +++ b/packages/ipfs-cli/src/commands/object/patch.js @@ -5,6 +5,9 @@ module.exports = { description: 'Create a new merkledag object based on an existing one.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('patch') diff --git a/packages/ipfs-cli/src/commands/object/patch/add-link.js b/packages/ipfs-cli/src/commands/object/patch/add-link.js index 671fba8981..2c27d62d85 100644 --- a/packages/ipfs-cli/src/commands/object/patch/add-link.js +++ b/packages/ipfs-cli/src/commands/object/patch/add-link.js @@ -5,6 +5,7 @@ const DAGLink = dagPB.DAGLink const multibase = require('multibase') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../../utils') module.exports = { command: 'add-link ', @@ -12,6 +13,14 @@ module.exports = { describe: 'Add a link to a given object', builder: { + root: { + type: 'string', + coerce: coerceCID + }, + ref: { + type: 'string', + coerce: coerceCID + }, 'cid-base': { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', @@ -28,13 +37,23 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {import('cids')} argv.root + * @param {string} argv.name + * @param {import('cids')} argv.ref + * @param {import('multibase').BaseName} argv.cidBase + * @param {import('cids').CIDVersion} argv.cidVersion + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, root, name, ref, cidBase, cidVersion, timeout }) { - const nodeA = await ipfs.object.get(ref, { enc: 'base58', timeout }) + const nodeA = await ipfs.object.get(ref, { timeout }) const result = await dagPB.util.cid(dagPB.util.serialize(nodeA), { cidVersion }) const link = new DAGLink(name, nodeA.size, result) - const cid = await ipfs.object.patch.addLink(root, link, { enc: 'base58', timeout }) + const cid = await ipfs.object.patch.addLink(root, link, { timeout }) print(cidToString(cid, { base: cidBase, upgrade: false })) } } diff --git a/packages/ipfs-cli/src/commands/object/patch/append-data.js b/packages/ipfs-cli/src/commands/object/patch/append-data.js index befb708c87..b5063c5891 100644 --- a/packages/ipfs-cli/src/commands/object/patch/append-data.js +++ b/packages/ipfs-cli/src/commands/object/patch/append-data.js @@ -5,6 +5,7 @@ const fs = require('fs') const multibase = require('multibase') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../../utils') module.exports = { command: 'append-data [data]', @@ -12,6 +13,10 @@ module.exports = { describe: 'Append data to the data segment of a dag node', builder: { + root: { + type: 'string', + coerce: coerceCID + }, 'cid-base': { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', @@ -23,15 +28,24 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {import('cids')} argv.root + * @param {string} argv.data + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print, getStdin }, root, data, cidBase, timeout }) { + let buf + if (data) { - data = fs.readFileSync(data) + buf = fs.readFileSync(data) } else { - data = (await concat(getStdin())).slice() + buf = (await concat(getStdin(), { type: 'buffer' })).slice() } - const cid = await ipfs.object.patch.appendData(root, data, { - enc: 'base58', + const cid = await ipfs.object.patch.appendData(root, buf, { timeout }) diff --git a/packages/ipfs-cli/src/commands/object/patch/rm-link.js b/packages/ipfs-cli/src/commands/object/patch/rm-link.js index 7c2d960532..7ec1137cc0 100644 --- a/packages/ipfs-cli/src/commands/object/patch/rm-link.js +++ b/packages/ipfs-cli/src/commands/object/patch/rm-link.js @@ -3,6 +3,7 @@ const multibase = require('multibase') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../../utils') module.exports = { command: 'rm-link ', @@ -10,6 +11,10 @@ module.exports = { describe: 'Remove a link from an object', builder: { + root: { + type: 'string', + coerce: coerceCID + }, 'cid-base': { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', @@ -21,11 +26,16 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {import('cids')} argv.root + * @param {string} argv.link + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, root, link, cidBase, timeout }) { - const cid = await ipfs.object.patch.rmLink(root, { - name: link - }, { - enc: 'base58', + const cid = await ipfs.object.patch.rmLink(root, link, { timeout }) diff --git a/packages/ipfs-cli/src/commands/object/patch/set-data.js b/packages/ipfs-cli/src/commands/object/patch/set-data.js index 41a7bf288f..453bc5547f 100644 --- a/packages/ipfs-cli/src/commands/object/patch/set-data.js +++ b/packages/ipfs-cli/src/commands/object/patch/set-data.js @@ -5,6 +5,7 @@ const concat = require('it-concat') const multibase = require('multibase') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../../utils') module.exports = { command: 'set-data [data]', @@ -12,6 +13,10 @@ module.exports = { describe: 'Set data field of an ipfs object', builder: { + root: { + type: 'string', + coerce: coerceCID + }, 'cid-base': { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', @@ -23,15 +28,24 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {import('cids')} argv.root + * @param {string} argv.data + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print, getStdin }, root, data, cidBase, timeout }) { + let buf + if (data) { - data = fs.readFileSync(data) + buf = fs.readFileSync(data) } else { - data = (await concat(getStdin())).slice() + buf = (await concat(getStdin(), { type: 'buffer' })).slice() } - const cid = await ipfs.object.patch.setData(root, data, { - enc: 'base58', + const cid = await ipfs.object.patch.setData(root, buf, { timeout }) diff --git a/packages/ipfs-cli/src/commands/object/put.js b/packages/ipfs-cli/src/commands/object/put.js index d64a79fc89..b9d6e2a46b 100644 --- a/packages/ipfs-cli/src/commands/object/put.js +++ b/packages/ipfs-cli/src/commands/object/put.js @@ -27,14 +27,24 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.data + * @param {import('ipfs-core-types/src/object').PutEncoding} argv.inputEnc + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print, getStdin }, data, inputEnc, cidBase, timeout }) { + let buf + if (data) { - data = fs.readFileSync(data) + buf = fs.readFileSync(data) } else { - data = (await concat(getStdin())).slice() + buf = (await concat(getStdin(), { type: 'buffer' })).slice() } - const cid = await ipfs.object.put(data, { enc: inputEnc, timeout }) + const cid = await ipfs.object.put(buf, { enc: inputEnc, timeout }) print(`added ${cidToString(cid, { base: cidBase, upgrade: false })}`) } } diff --git a/packages/ipfs-cli/src/commands/object/stat.js b/packages/ipfs-cli/src/commands/object/stat.js index 6d95612917..8c061d521e 100644 --- a/packages/ipfs-cli/src/commands/object/stat.js +++ b/packages/ipfs-cli/src/commands/object/stat.js @@ -1,6 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { coerceCID } = require('../../utils') module.exports = { command: 'stat ', @@ -8,15 +9,31 @@ module.exports = { describe: 'Get stats for the DAG node named by ', builder: { + key: { + type: 'string', + coerce: coerceCID + }, timeout: { type: 'string', coerce: parseDuration } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('cids')} argv.key + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, key, timeout }) { - const stats = await ipfs.object.stat(key, { enc: 'base58', timeout }) - delete stats.Hash // only for js-ipfs-http-client output - Object.keys(stats).forEach((key) => print(`${key}: ${stats[key]}`)) + const stats = await ipfs.object.stat(key, { timeout }) + + Object.entries(stats).forEach(([key, value]) => { + if (key === 'Hash') { + return // only for js-ipfs-http-client output + } + + print(`${key}: ${value}`) + }) } } diff --git a/packages/ipfs-cli/src/commands/pin.js b/packages/ipfs-cli/src/commands/pin.js index 1d939817de..4514251cf7 100644 --- a/packages/ipfs-cli/src/commands/pin.js +++ b/packages/ipfs-cli/src/commands/pin.js @@ -5,6 +5,9 @@ module.exports = { description: 'Pin and unpin objects to local storage.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('pin') diff --git a/packages/ipfs-cli/src/commands/pin/add.js b/packages/ipfs-cli/src/commands/pin/add.js index 6a9a56ee68..68f1bac588 100644 --- a/packages/ipfs-cli/src/commands/pin/add.js +++ b/packages/ipfs-cli/src/commands/pin/add.js @@ -29,14 +29,19 @@ module.exports = { describe: 'Metadata to add to the pin', type: 'string', alias: 'm', + /** + * @param {*} val + * @returns {Record | undefined} + */ coerce: (val) => { if (!val) { return } + /** @type {Record} */ const output = {} - val.split(',').forEach(line => { + val.split(',').forEach((/** @type {string} */ line) => { const parts = line.split('=') output[parts[0]] = parts[1] }) @@ -51,6 +56,16 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string[]} argv.ipfsPath + * @param {boolean} argv.recursive + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + * @param {Record} argv.metadata + * @param {Record} argv.metadataJson + */ async handler ({ ctx, ipfsPath, recursive, cidBase, timeout, metadata, metadataJson }) { const { ipfs, print } = ctx const type = recursive ? 'recursive' : 'direct' diff --git a/packages/ipfs-cli/src/commands/pin/ls.js b/packages/ipfs-cli/src/commands/pin/ls.js index 897ab86d68..e98fef0e84 100644 --- a/packages/ipfs-cli/src/commands/pin/ls.js +++ b/packages/ipfs-cli/src/commands/pin/ls.js @@ -1,7 +1,6 @@ 'use strict' const multibase = require('multibase') -const all = require('it-all') const { cidToString } = require('ipfs-core-utils/src/cid') const { default: parseDuration } = require('parse-duration') const { @@ -33,19 +32,25 @@ module.exports = { type: 'string', choices: Object.keys(multibase.names) }, - stream: { - type: 'boolean', - alias: 's', - default: false, - describe: 'Enable streaming of pins as they are discovered.' - }, timeout: { type: 'string', coerce: parseDuration } }, - async handler ({ ctx: { ipfs, print }, ipfsPath, type, quiet, cidBase, stream, timeout }) { + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string[]} argv.ipfsPath + * @param {'direct' | 'indirect' | 'recursive' | 'all'} argv.type + * @param {boolean} argv.quiet + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ + async handler ({ ctx: { ipfs, print }, ipfsPath, type, quiet, cidBase, timeout }) { + /** + * @param {import('ipfs-core-types/src/pin').LsResult} res + */ const printPin = res => { let line = cidToString(res.cid, { base: cidBase }) if (!quiet) { @@ -58,16 +63,6 @@ module.exports = { print(line) } - if (!stream) { - const pins = await all(ipfs.pin.ls({ - paths: ipfsPath, - type, - stream: false, - timeout - })) - return pins.forEach(printPin) - } - for await (const res of ipfs.pin.ls({ paths: ipfsPath, type, diff --git a/packages/ipfs-cli/src/commands/pin/rm.js b/packages/ipfs-cli/src/commands/pin/rm.js index 9873ec6640..729ed8d0f7 100644 --- a/packages/ipfs-cli/src/commands/pin/rm.js +++ b/packages/ipfs-cli/src/commands/pin/rm.js @@ -27,6 +27,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string[]} argv.ipfsPath + * @param {boolean} argv.recursive + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx, ipfsPath, timeout, recursive, cidBase }) { const { ipfs, print } = ctx diff --git a/packages/ipfs-cli/src/commands/ping.js b/packages/ipfs-cli/src/commands/ping.js index 540423939b..4a089d0f2f 100644 --- a/packages/ipfs-cli/src/commands/ping.js +++ b/packages/ipfs-cli/src/commands/ping.js @@ -19,6 +19,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {number} argv.count + * @param {string} argv.peerId + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, count, peerId, timeout }) { for await (const pong of ipfs.ping(peerId, { count, timeout })) { const { success, time, text } = pong diff --git a/packages/ipfs-cli/src/commands/pubsub.js b/packages/ipfs-cli/src/commands/pubsub.js index 8d7878ebc7..f791ac83bc 100644 --- a/packages/ipfs-cli/src/commands/pubsub.js +++ b/packages/ipfs-cli/src/commands/pubsub.js @@ -5,6 +5,9 @@ module.exports = { description: 'pubsub commands', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('pubsub') diff --git a/packages/ipfs-cli/src/commands/pubsub/ls.js b/packages/ipfs-cli/src/commands/pubsub/ls.js index 3e595fcd3b..e65d4db1b5 100644 --- a/packages/ipfs-cli/src/commands/pubsub/ls.js +++ b/packages/ipfs-cli/src/commands/pubsub/ls.js @@ -17,6 +17,11 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { const subscriptions = await ipfs.pubsub.ls({ timeout diff --git a/packages/ipfs-cli/src/commands/pubsub/peers.js b/packages/ipfs-cli/src/commands/pubsub/peers.js index 807d9f93c6..fb56267499 100644 --- a/packages/ipfs-cli/src/commands/pubsub/peers.js +++ b/packages/ipfs-cli/src/commands/pubsub/peers.js @@ -14,6 +14,12 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.topic + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, topic, timeout }) { const peers = await ipfs.pubsub.peers(topic, { timeout diff --git a/packages/ipfs-cli/src/commands/pubsub/pub.js b/packages/ipfs-cli/src/commands/pubsub/pub.js index c2663e954e..e16e21a3c7 100644 --- a/packages/ipfs-cli/src/commands/pubsub/pub.js +++ b/packages/ipfs-cli/src/commands/pubsub/pub.js @@ -1,7 +1,7 @@ 'use strict' const { default: parseDuration } = require('parse-duration') -const uint8ArrayFromString = require('uint8arrays/from-string') +const { coerceUint8Array } = require('../../utils') module.exports = { command: 'pub ', @@ -9,14 +9,24 @@ module.exports = { describe: 'Publish data to a topic', builder: { + data: { + type: 'string', + coerce: coerceUint8Array + }, timeout: { type: 'string', coerce: parseDuration } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.topic + * @param {Uint8Array} argv.data + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs }, topic, data, timeout }) { - data = uint8ArrayFromString(String(data)) await ipfs.pubsub.publish(topic, data, { timeout }) diff --git a/packages/ipfs-cli/src/commands/pubsub/sub.js b/packages/ipfs-cli/src/commands/pubsub/sub.js index 77074f9793..b4927c45a8 100644 --- a/packages/ipfs-cli/src/commands/pubsub/sub.js +++ b/packages/ipfs-cli/src/commands/pubsub/sub.js @@ -14,7 +14,16 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.topic + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, topic, timeout }) { + /** + * @type {import('ipfs-core-types/src/pubsub').MessageHandlerFn} + */ const handler = msg => print(msg.data.toString()) await ipfs.pubsub.subscribe(topic, handler, { timeout diff --git a/packages/ipfs-cli/src/commands/refs-local.js b/packages/ipfs-cli/src/commands/refs-local.js index e20c0a3319..5a7ff88397 100644 --- a/packages/ipfs-cli/src/commands/refs-local.js +++ b/packages/ipfs-cli/src/commands/refs-local.js @@ -23,12 +23,18 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {boolean} argv.multihash + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout, multihash }) { for await (const { ref, err } of ipfs.refs.local({ timeout })) { if (err) { - print(err, true, true) + print(err.toString(), true, true) } else { if (multihash) { print(multibase.encoding('base32upper').encode(uint8ArrayFromString(ref))) diff --git a/packages/ipfs-cli/src/commands/refs.js b/packages/ipfs-cli/src/commands/refs.js index e7a78dac54..13aec35f38 100644 --- a/packages/ipfs-cli/src/commands/refs.js +++ b/packages/ipfs-cli/src/commands/refs.js @@ -41,6 +41,18 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} argv.key + * @param {string} argv.keys + * @param {boolean} argv.recursive + * @param {string} argv.format + * @param {boolean} argv.edges + * @param {boolean} argv.unique + * @param {number} argv.maxDepth + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, key, keys, recursive, format, edges, unique, maxDepth, timeout }) { if (maxDepth === 0) { return @@ -50,7 +62,7 @@ module.exports = { for await (const { err, ref } of ipfs.refs(k, { recursive, format, edges, unique, maxDepth, timeout })) { if (err) { - print(err, true, true) + print(err.toString(), true, true) } else { print(ref) } diff --git a/packages/ipfs-cli/src/commands/repo.js b/packages/ipfs-cli/src/commands/repo.js index baf81145be..5ed88bba15 100644 --- a/packages/ipfs-cli/src/commands/repo.js +++ b/packages/ipfs-cli/src/commands/repo.js @@ -5,6 +5,9 @@ module.exports = { description: 'Manipulate the IPFS repo.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('repo') diff --git a/packages/ipfs-cli/src/commands/repo/gc.js b/packages/ipfs-cli/src/commands/repo/gc.js index 362a4a8279..dcd254532c 100644 --- a/packages/ipfs-cli/src/commands/repo/gc.js +++ b/packages/ipfs-cli/src/commands/repo/gc.js @@ -25,13 +25,23 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {boolean} argv.quiet + * @param {boolean} argv.streamErrors + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, quiet, streamErrors, timeout }) { for await (const r of ipfs.repo.gc({ timeout })) { - if (r.err) { + // @ts-ignore cannot derive type + if (r.err != null) { + // @ts-ignore cannot derive type streamErrors && print(r.err.message, true, true) } else { + // @ts-ignore cannot derive type print((quiet ? '' : 'removed ') + r.cid) } } diff --git a/packages/ipfs-cli/src/commands/repo/stat.js b/packages/ipfs-cli/src/commands/repo/stat.js index 32a0e81f34..2ec985759f 100644 --- a/packages/ipfs-cli/src/commands/repo/stat.js +++ b/packages/ipfs-cli/src/commands/repo/stat.js @@ -25,27 +25,39 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {boolean} argv.human + * @param {boolean} argv.sizeOnly + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, human, sizeOnly, timeout }) { const stats = await ipfs.repo.stat({ timeout }) + /** @type {Record} */ + const output = { + ...stats + } + if (human) { - stats.numObjects = stats.numObjects.toNumber() - stats.repoSize = prettyBytes(stats.repoSize.toNumber()).toUpperCase() - stats.storageMax = prettyBytes(stats.storageMax.toNumber()).toUpperCase() + output.numObjects = Number(stats.numObjects) + output.repoSize = prettyBytes(Number(stats.repoSize)).toUpperCase() + output.storageMax = prettyBytes(Number(stats.storageMax)).toUpperCase() } if (sizeOnly) { print( - `RepoSize: ${stats.repoSize} -StorageMax: ${stats.storageMax}`) + `RepoSize: ${output.repoSize} +StorageMax: ${output.storageMax}`) } else { - print(`NumObjects: ${stats.numObjects} -RepoSize: ${stats.repoSize} -StorageMax: ${stats.storageMax} -RepoPath: ${stats.repoPath} -Version: ${stats.version}`) + print(`NumObjects: ${output.numObjects} +RepoSize: ${output.repoSize} +StorageMax: ${output.storageMax} +RepoPath: ${output.repoPath} +Version: ${output.version}`) } } } diff --git a/packages/ipfs-cli/src/commands/repo/version.js b/packages/ipfs-cli/src/commands/repo/version.js index 8b0aa5bc1f..104c420cc8 100644 --- a/packages/ipfs-cli/src/commands/repo/version.js +++ b/packages/ipfs-cli/src/commands/repo/version.js @@ -14,10 +14,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { const version = await ipfs.repo.version({ timeout }) - print(version) + print(`${version}`) } } diff --git a/packages/ipfs-cli/src/commands/resolve.js b/packages/ipfs-cli/src/commands/resolve.js index 89eac0f260..193e9f45fa 100644 --- a/packages/ipfs-cli/src/commands/resolve.js +++ b/packages/ipfs-cli/src/commands/resolve.js @@ -28,6 +28,14 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {string} argv.name + * @param {boolean} argv.recursive + * @param {import('multibase').BaseName} argv.cidBase + * @param {number} argv.timeout + */ async handler ({ ctx: { print, ipfs }, name, recursive, cidBase, timeout }) { const res = await ipfs.resolve(name, { recursive, cidBase, timeout }) print(stripControlCharacters(res)) diff --git a/packages/ipfs-cli/src/commands/shutdown.js b/packages/ipfs-cli/src/commands/shutdown.js index 2799bfe5e0..00a709f85c 100644 --- a/packages/ipfs-cli/src/commands/shutdown.js +++ b/packages/ipfs-cli/src/commands/shutdown.js @@ -14,7 +14,13 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {number} argv.timeout + */ handler ({ ctx: { ipfs }, timeout }) { + // @ts-ignore not part of the core api return ipfs.shutdown({ timeout }) diff --git a/packages/ipfs-cli/src/commands/stats.js b/packages/ipfs-cli/src/commands/stats.js index 7bf8e5c1a1..3982d3dd83 100644 --- a/packages/ipfs-cli/src/commands/stats.js +++ b/packages/ipfs-cli/src/commands/stats.js @@ -5,6 +5,9 @@ module.exports = { description: 'Query IPFS statistics.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs.commandDir('stats') } diff --git a/packages/ipfs-cli/src/commands/stats/bw.js b/packages/ipfs-cli/src/commands/stats/bw.js index 208b65c312..699382216e 100644 --- a/packages/ipfs-cli/src/commands/stats/bw.js +++ b/packages/ipfs-cli/src/commands/stats/bw.js @@ -22,7 +22,8 @@ module.exports = { }, interval: { type: 'string', - default: '1s' + default: '1s', + coerce: parseDuration }, timeout: { type: 'string', @@ -30,6 +31,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {string} argv.peer + * @param {string} argv.proto + * @param {boolean} argv.poll + * @param {number} argv.interval + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, peer, proto, poll, interval, timeout }) { for await (const chunk of ipfs.stats.bw({ peer, proto, poll, interval, timeout })) { print(`bandwidth status diff --git a/packages/ipfs-cli/src/commands/swarm.js b/packages/ipfs-cli/src/commands/swarm.js index a89e1f6dad..fa88e5e116 100644 --- a/packages/ipfs-cli/src/commands/swarm.js +++ b/packages/ipfs-cli/src/commands/swarm.js @@ -5,6 +5,9 @@ module.exports = { description: 'Swarm inspection tool.', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('swarm') diff --git a/packages/ipfs-cli/src/commands/swarm/addrs.js b/packages/ipfs-cli/src/commands/swarm/addrs.js index d1e125656e..6aff6fb623 100644 --- a/packages/ipfs-cli/src/commands/swarm/addrs.js +++ b/packages/ipfs-cli/src/commands/swarm/addrs.js @@ -7,6 +7,9 @@ module.exports = { describe: '', + /** + * @param {import('yargs').Argv} yargs + */ builder (yargs) { return yargs .commandDir('addrs') @@ -16,6 +19,11 @@ module.exports = { }) }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { ipfs, print }, timeout }) { const res = await ipfs.swarm.addrs({ timeout diff --git a/packages/ipfs-cli/src/commands/swarm/addrs/local.js b/packages/ipfs-cli/src/commands/swarm/addrs/local.js index 863c84b806..fde4c68de1 100644 --- a/packages/ipfs-cli/src/commands/swarm/addrs/local.js +++ b/packages/ipfs-cli/src/commands/swarm/addrs/local.js @@ -14,6 +14,11 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { print, ipfs, isDaemon }, timeout }) { if (!isDaemon) { throw new Error('This command must be run in online mode. Try running \'ipfs daemon\' first.') diff --git a/packages/ipfs-cli/src/commands/swarm/connect.js b/packages/ipfs-cli/src/commands/swarm/connect.js index d13fa1ac73..23a22ccb75 100644 --- a/packages/ipfs-cli/src/commands/swarm/connect.js +++ b/packages/ipfs-cli/src/commands/swarm/connect.js @@ -1,6 +1,9 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { + coerceMultiaddr +} = require('../../utils') module.exports = { command: 'connect
', @@ -8,19 +11,31 @@ module.exports = { describe: 'Open connection to a given address', builder: { + address: { + type: 'string', + coerce: coerceMultiaddr + }, timeout: { type: 'string', coerce: parseDuration } }, - async handler ({ ctx: { print, ipfs, isDaemon }, address, timeout }) { + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('multiaddr')} argv.address + * @param {number} argv.timeout + */ + async handler ({ ctx: { ipfs, isDaemon, print }, address, timeout }) { if (!isDaemon) { throw new Error('This command must be run in online mode. Try running \'ipfs daemon\' first.') } - const res = await ipfs.swarm.connect(address, { + + await ipfs.swarm.connect(address, { timeout }) - res.forEach(msg => print(msg)) + + print(`${address}`) } } diff --git a/packages/ipfs-cli/src/commands/swarm/disconnect.js b/packages/ipfs-cli/src/commands/swarm/disconnect.js index 6fdeb65e26..d08b5164b6 100644 --- a/packages/ipfs-cli/src/commands/swarm/disconnect.js +++ b/packages/ipfs-cli/src/commands/swarm/disconnect.js @@ -1,6 +1,9 @@ 'use strict' const { default: parseDuration } = require('parse-duration') +const { + coerceMultiaddr +} = require('../../utils') module.exports = { command: 'disconnect
', @@ -8,19 +11,31 @@ module.exports = { describe: 'Close connection to a given address', builder: { + address: { + type: 'string', + coerce: coerceMultiaddr + }, timeout: { type: 'string', coerce: parseDuration } }, - async handler ({ ctx: { print, ipfs, isDaemon }, address, timeout }) { + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {import('multiaddr')} argv.address + * @param {number} argv.timeout + */ + async handler ({ ctx: { ipfs, isDaemon, print }, address, timeout }) { if (!isDaemon) { throw new Error('This command must be run in online mode. Try running \'ipfs daemon\' first.') } - const res = await ipfs.swarm.disconnect(address, { + + await ipfs.swarm.disconnect(address, { timeout }) - res.forEach(msg => print(msg)) + + print(`${address}`) } } diff --git a/packages/ipfs-cli/src/commands/swarm/peers.js b/packages/ipfs-cli/src/commands/swarm/peers.js index de1b868a10..bf438a3fb1 100644 --- a/packages/ipfs-cli/src/commands/swarm/peers.js +++ b/packages/ipfs-cli/src/commands/swarm/peers.js @@ -16,6 +16,11 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../../types').Context} argv.ctx + * @param {number} argv.timeout + */ async handler ({ ctx: { print, ipfs, isDaemon }, timeout }) { if (!isDaemon) { throw new Error('This command must be run in online mode. Try running \'ipfs daemon\' first.') diff --git a/packages/ipfs-cli/src/commands/version.js b/packages/ipfs-cli/src/commands/version.js index 65af2c8744..c4f985fec9 100644 --- a/packages/ipfs-cli/src/commands/version.js +++ b/packages/ipfs-cli/src/commands/version.js @@ -36,6 +36,15 @@ module.exports = { } }, + /** + * @param {object} argv + * @param {import('../types').Context} argv.ctx + * @param {boolean} argv.all + * @param {boolean} argv.commit + * @param {boolean} argv.repo + * @param {boolean} argv.number + * @param {number} argv.timeout + */ async handler ({ ctx: { print, ipfs }, all, commit, repo, number, timeout }) { const data = await ipfs.version({ timeout @@ -46,6 +55,7 @@ module.exports = { if (repo) { // go-ipfs prints only the number, even without the --number flag. + // @ts-ignore version return type is implementation-specific print(data.repo) } else if (number) { print(parsedVersion) diff --git a/packages/ipfs-cli/src/index.js b/packages/ipfs-cli/src/index.js index e795f52460..f070662dd2 100644 --- a/packages/ipfs-cli/src/index.js +++ b/packages/ipfs-cli/src/index.js @@ -4,6 +4,10 @@ const parser = require('./parser') const commandAlias = require('./command-alias') const errCode = require('err-code') +/** + * @param {string[]} command + * @param {import('yargs').MiddlewareFunction} ctxMiddleware + */ module.exports = (command, ctxMiddleware) => { // Apply command aliasing (eg `refs local` -> `refs-local`) command = commandAlias(command) diff --git a/packages/ipfs-cli/src/types.d.ts b/packages/ipfs-cli/src/types.d.ts new file mode 100644 index 0000000000..6f4130de13 --- /dev/null +++ b/packages/ipfs-cli/src/types.d.ts @@ -0,0 +1,25 @@ +import { IPFS } from 'ipfs-core-types' + +declare module '@hapi/hapi' { + interface ServerInfo { + ma: Multiaddr + } +} + +export interface Context { + ipfs: IPFS + print: Print + isDaemon: boolean + getStdin: () => AsyncIterable + repoPath: string +} + +export interface Print { + (msg: string | Uint8Array, includeNewline?: boolean, isError?: boolean): void + clearLine: () => void + cursorTo: (pos: number) => void + write: (data: any) => void + error: (msg: string, includeNewline?: boolean) => void + isTTY: boolean + columns: any +} \ No newline at end of file diff --git a/packages/ipfs-cli/src/utils.js b/packages/ipfs-cli/src/utils.js index 0bb6320956..066a14c256 100644 --- a/packages/ipfs-cli/src/utils.js +++ b/packages/ipfs-cli/src/utils.js @@ -5,10 +5,13 @@ const os = require('os') const path = require('path') const log = require('debug')('ipfs:cli:utils') const Progress = require('progress') +// @ts-ignore no types const byteman = require('byteman') const IPFS = require('ipfs-core') const CID = require('cids') +const Multiaddr = require('multiaddr') const { cidToString } = require('ipfs-core-utils/src/cid') +const uint8ArrayFromString = require('uint8arrays/from-string') const getRepoPath = () => { return process.env.IPFS_PATH || path.join(os.homedir(), '/.jsipfs') @@ -29,10 +32,7 @@ let visible = true const disablePrinting = () => { visible = false } /** - * - * @param {string} msg - * @param {boolean} [includeNewline=true] - * @param {boolean} [isError=false] + * @type {import('./types').Print} */ const print = (msg, includeNewline = true, isError = false) => { if (visible) { @@ -51,6 +51,9 @@ print.clearLine = () => { return process.stdout.clearLine(0) } +/** + * @param {number} pos + */ print.cursorTo = (pos) => { process.stdout.cursorTo(pos) } @@ -78,6 +81,10 @@ print.error = (msg, newline = true) => { print.isTTY = process.stdout.isTTY print.columns = process.stdout.columns +/** + * @param {number} totalBytes + * @param {*} output + */ const createProgressBar = (totalBytes, output) => { const total = byteman(totalBytes, 2, 'MB') const barFormat = `:progress / ${total} [:bar] :percent :etas` @@ -91,6 +98,10 @@ const createProgressBar = (totalBytes, output) => { }) } +/** + * @param {*} val + * @param {number} n + */ const rightpad = (val, n) => { let result = String(val) for (let i = result.length; i < n; ++i) { @@ -103,6 +114,9 @@ const ipfsPathHelp = 'ipfs uses a repository in the local file system. By defaul 'located at ~/.jsipfs. To change the repo location, set the $IPFS_PATH environment variable:\n\n' + 'export IPFS_PATH=/path/to/ipfsrepo\n' +/** + * @param {{ api?: string, silent?: boolean, migrate?: boolean, pass?: string }} argv + */ async function getIpfs (argv) { if (!argv.api && !isDaemonOn()) { const ipfs = await IPFS.create({ @@ -131,14 +145,17 @@ async function getIpfs (argv) { endpoint = argv.api } // Required inline to reduce startup time - const APIctl = require('ipfs-http-client') + const { create } = require('ipfs-http-client') return { isDaemon: true, - ipfs: APIctl(endpoint), + ipfs: create({ url: endpoint }), cleanup: async () => { } } } +/** + * @param {boolean} [value] + */ const asBoolean = (value) => { if (value === false || value === true) { return value @@ -151,26 +168,31 @@ const asBoolean = (value) => { return false } +/** + * @param {any} value + */ const asOctal = (value) => { return parseInt(value, 8) } +/** + * @param {number} [secs] + * @param {number} [nsecs] + */ const asMtimeFromSeconds = (secs, nsecs) => { - if (secs === null || secs === undefined) { + if (secs == null) { return undefined } - const output = { - secs - } - - if (nsecs !== null && nsecs !== undefined) { - output.nsecs = nsecs + return { + secs, + nsecs } - - return output } +/** + * @param {*} value + */ const coerceMtime = (value) => { value = parseInt(value) @@ -181,6 +203,9 @@ const coerceMtime = (value) => { return value } +/** + * @param {*} value + */ const coerceMtimeNsecs = (value) => { value = parseInt(value) @@ -195,13 +220,71 @@ const coerceMtimeNsecs = (value) => { return value } +/** + * @param {*} value + */ +const coerceCID = (value) => { + if (!value) { + return undefined + } + + if (value.startsWith('/ipfs/')) { + return new CID(value.split('/')[2]) + } + + return new CID(value) +} + +/** + * @param {string[]} values + */ +const coerceCIDs = (values) => { + if (values == null) { + return [] + } + + return values.map(coerceCID).filter(Boolean) +} + +/** + * @param {string} value + */ +const coerceMultiaddr = (value) => { + if (value == null) { + return undefined + } + + return new Multiaddr(value) +} + +/** + * @param {string[]} values + */ +const coerceMultiaddrs = (values) => { + if (values == null) { + return undefined + } + + return values.map(coerceMultiaddr).filter(Boolean) +} + +/** + * @param {string} value + */ +const coerceUint8Array = (value) => { + if (value == null) { + return undefined + } + + return uint8ArrayFromString(value) +} + const DEL = 127 /** * Strip control characters from a string * - * @param {string} str - a string to strip control characters from - * @returns {string} + * @param {string} [str] - a string to strip control characters from */ const stripControlCharacters = (str) => { return (str || '') @@ -218,9 +301,9 @@ const stripControlCharacters = (str) => { * Escape control characters in a string * * @param {string} str - a string to escape control characters in - * @returns {string} */ const escapeControlCharacters = (str) => { + /** @type {Record} */ const escapes = { '00': '\\0', '08': '\\b', @@ -251,9 +334,9 @@ const escapeControlCharacters = (str) => { * Removes control characters from all key/values and stringifies * CID properties * - * @param {object} obj - all keys/values in this object will be have control characters stripped + * @param {any} obj - all keys/values in this object will be have control characters stripped * @param {import('cids').BaseNameOrCode} cidBase - any encountered CIDs will be stringified using this base - * @returns {object} + * @returns {any} */ const makeEntriesPrintable = (obj, cidBase = 'base58btc') => { if (CID.isCID(obj)) { @@ -278,6 +361,7 @@ const makeEntriesPrintable = (obj, cidBase = 'base58btc') => { return output } + /** @type {Record} */ const output = {} Object.entries(obj) @@ -304,6 +388,11 @@ module.exports = { asMtimeFromSeconds, coerceMtime, coerceMtimeNsecs, + coerceCID, + coerceCIDs, + coerceMultiaddr, + coerceMultiaddrs, + coerceUint8Array, stripControlCharacters, escapeControlCharacters, makeEntriesPrintable diff --git a/packages/ipfs-cli/test/add.js b/packages/ipfs-cli/test/add.js index 93da2ecbc5..9e9828bc52 100644 --- a/packages/ipfs-cli/test/add.js +++ b/packages/ipfs-cli/test/add.js @@ -158,9 +158,11 @@ describe('add', () => { it('add from pipe', async () => { const cid = new CID('QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB') - ipfs.addAll.withArgs(sinon.match({ - content: matchIterable() - }), defaultOptions).returns([{ + ipfs.addAll.withArgs(sinon.match([{ + content: matchIterable(), + mtime: undefined, + mode: undefined + }]), defaultOptions).returns([{ cid, path: 'README.md' }]) @@ -179,10 +181,11 @@ describe('add', () => { it('add from pipe with mtime=100', async () => { const cid = new CID('QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB') - ipfs.addAll.withArgs(sinon.match({ + ipfs.addAll.withArgs(sinon.match([{ content: matchIterable(), - mtime: { secs: 100 } - }), defaultOptions).returns([{ + mtime: { secs: 100, nsecs: undefined }, + mode: undefined + }]), defaultOptions).returns([{ cid, path: 'README.md' }]) diff --git a/packages/ipfs-cli/test/bitswap.js b/packages/ipfs-cli/test/bitswap.js index 1b86f70531..9d17519f3a 100644 --- a/packages/ipfs-cli/test/bitswap.js +++ b/packages/ipfs-cli/test/bitswap.js @@ -5,10 +5,9 @@ const { expect } = require('aegir/utils/chai') const CID = require('cids') const cli = require('./utils/cli') const sinon = require('sinon') -const Big = require('bignumber.js') describe('bitswap', () => { - const peerId = 'peer' + const peerId = 'QmUBdnXXPyoDFXj3Hj39dNJ5VkN3QFRskXxcGaYFBB8CNA' const key0 = 'QmUBdnXXPyoDFXj3Hj39dNJ5VkN3QFRskXxcGaYFBB8CNR' const key1 = 'zb2rhafnd6kEUujnoMkozHnWXY7XpWttyVDWKXfChqA42VTDU' @@ -88,13 +87,13 @@ describe('bitswap', () => { it('should return bitswap stats', async () => { ipfs.bitswap.stat.withArgs(defaultOptions).resolves({ - provideBufLen: Big(10), - blocksReceived: Big(10), - blocksSent: Big(10), - dataReceived: Big(10), - dupBlksReceived: Big(10), - dupDataReceived: Big(10), - dataSent: Big(10), + provideBufLen: BigInt(10), + blocksReceived: BigInt(10), + blocksSent: BigInt(10), + dataReceived: BigInt(10), + dupBlksReceived: BigInt(10), + dupDataReceived: BigInt(10), + dataSent: BigInt(10), wantlist: [ new CID(key0), new CID(key1) @@ -120,13 +119,13 @@ describe('bitswap', () => { it('stat --human', async () => { ipfs.bitswap.stat.withArgs(defaultOptions).resolves({ - provideBufLen: Big(10), - blocksReceived: Big(10), - blocksSent: Big(10), - dataReceived: Big(10), - dupBlksReceived: Big(10), - dupDataReceived: Big(10), - dataSent: Big(10), + provideBufLen: BigInt(10), + blocksReceived: BigInt(10), + blocksSent: BigInt(10), + dataReceived: BigInt(10), + dupBlksReceived: BigInt(10), + dupDataReceived: BigInt(10), + dataSent: BigInt(10), wantlist: [ new CID(key0), new CID(key1) @@ -152,13 +151,13 @@ describe('bitswap', () => { it('should get stats with wantlist CIDs encoded in specified base', async () => { ipfs.bitswap.stat.withArgs(defaultOptions).resolves({ - provideBufLen: Big(10), - blocksReceived: Big(10), - blocksSent: Big(10), - dataReceived: Big(10), - dupBlksReceived: Big(10), - dupDataReceived: Big(10), - dataSent: Big(10), + provideBufLen: BigInt(10), + blocksReceived: BigInt(10), + blocksSent: BigInt(10), + dataReceived: BigInt(10), + dupBlksReceived: BigInt(10), + dupDataReceived: BigInt(10), + dataSent: BigInt(10), wantlist: [ new CID(key0), new CID(key1) @@ -175,13 +174,13 @@ describe('bitswap', () => { ...defaultOptions, timeout: 1000 }).resolves({ - provideBufLen: Big(10), - blocksReceived: Big(10), - blocksSent: Big(10), - dataReceived: Big(10), - dupBlksReceived: Big(10), - dupDataReceived: Big(10), - dataSent: Big(10), + provideBufLen: BigInt(10), + blocksReceived: BigInt(10), + blocksSent: BigInt(10), + dataReceived: BigInt(10), + dupBlksReceived: BigInt(10), + dupDataReceived: BigInt(10), + dataSent: BigInt(10), wantlist: [ new CID(key0), new CID(key1) @@ -221,7 +220,7 @@ describe('bitswap', () => { const out = await cli(`bitswap unwant ${key0} --timeout=1s`, { ipfs }) expect(out).to.eql(`Key ${key0} removed from wantlist\n`) expect(ipfs.bitswap.unwant.called).to.be.true() - expect(ipfs.bitswap.unwant.getCall(0).args).to.deep.equal([key0, { + expect(ipfs.bitswap.unwant.getCall(0).args).to.deep.equal([new CID(key0), { ...defaultOptions, timeout: 1000 }]) diff --git a/packages/ipfs-cli/test/block.js b/packages/ipfs-cli/test/block.js index 7ece109678..b03433eeb5 100644 --- a/packages/ipfs-cli/test/block.js +++ b/packages/ipfs-cli/test/block.js @@ -94,7 +94,7 @@ describe('block', () => { } it('should get a block', async () => { - ipfs.block.get.withArgs(cid.toString(), defaultOptions).resolves({ + ipfs.block.get.withArgs(cid, defaultOptions).resolves({ cid, data: uint8ArrayFromString('hello world\n') }) @@ -109,7 +109,7 @@ describe('block', () => { }) it('should get a block with a timeout', async () => { - ipfs.block.get.withArgs(cid.toString(), { + ipfs.block.get.withArgs(cid, { ...defaultOptions, timeout: 1000 }).resolves({ @@ -128,7 +128,7 @@ describe('block', () => { } it('should stat a block', async () => { - ipfs.block.stat.withArgs(cid.toString(), defaultOptions).resolves({ + ipfs.block.stat.withArgs(cid, defaultOptions).resolves({ cid, size: 12 }) @@ -142,7 +142,7 @@ describe('block', () => { it('should stat and print CID encoded in specified base', async () => { const cid = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') - ipfs.block.stat.withArgs(cid.toString(), defaultOptions).resolves({ + ipfs.block.stat.withArgs(cid, defaultOptions).resolves({ cid, size: 12 }) @@ -155,7 +155,7 @@ describe('block', () => { }) it('should stat a block with a timeout', async () => { - ipfs.block.stat.withArgs(cid.toString(), { + ipfs.block.stat.withArgs(cid, { ...defaultOptions, timeout: 1000 }).resolves({ @@ -180,7 +180,7 @@ describe('block', () => { it('should remove a block', async () => { const cid = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') - ipfs.block.rm.withArgs([cid.toString()], defaultOptions).returns([{ + ipfs.block.rm.withArgs([cid], defaultOptions).returns([{ cid, error: false }]) @@ -192,7 +192,7 @@ describe('block', () => { it('rm prints error when removing fails', async () => { const err = new Error('Yikes!') const cid = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') - ipfs.block.rm.withArgs([cid.toString()], defaultOptions).returns([{ + ipfs.block.rm.withArgs([cid], defaultOptions).returns([{ cid, error: err }]) @@ -203,7 +203,7 @@ describe('block', () => { it('rm quietly', async () => { const cid = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') - ipfs.block.rm.withArgs([cid.toString()], { + ipfs.block.rm.withArgs([cid], { ...defaultOptions, quiet: true }).returns([{ @@ -217,7 +217,7 @@ describe('block', () => { it('rm force', async () => { const cid = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kh') - ipfs.block.rm.withArgs([cid.toString()], { + ipfs.block.rm.withArgs([cid], { ...defaultOptions, force: true }).returns([{ @@ -231,7 +231,7 @@ describe('block', () => { it('fails to remove non-existent block', async () => { const cid = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kh') - ipfs.block.rm.withArgs([cid.toString()]).returns([{ + ipfs.block.rm.withArgs([cid]).returns([{ cid, error: new Error('block not found') }]) diff --git a/packages/ipfs-cli/test/bootstrap.js b/packages/ipfs-cli/test/bootstrap.js index fab310bc69..e0bba5cf00 100644 --- a/packages/ipfs-cli/test/bootstrap.js +++ b/packages/ipfs-cli/test/bootstrap.js @@ -4,9 +4,10 @@ const { expect } = require('aegir/utils/chai') const cli = require('./utils/cli') const sinon = require('sinon') +const multiaddr = require('multiaddr') describe('bootstrap', () => { - const peer = '/ip4/111.111.111.111/tcp/1001/p2p/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD' + const peer = multiaddr('/ip4/111.111.111.111/tcp/1001/p2p/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD') let ipfs before(() => { diff --git a/packages/ipfs-cli/test/dag.js b/packages/ipfs-cli/test/dag.js index 802a441b9e..041927c9e0 100644 --- a/packages/ipfs-cli/test/dag.js +++ b/packages/ipfs-cli/test/dag.js @@ -52,7 +52,7 @@ describe('dag', () => { Links: [{ Hash: dagCborCid, Name: 'foo', - Size: 10 + Tsize: 10 }] } } @@ -71,7 +71,7 @@ describe('dag', () => { Links: [{ Hash: dagCborCid, Name: 'foo', - Size: 10 + Tsize: 10 }] } } @@ -90,7 +90,7 @@ describe('dag', () => { Links: [{ Hash: dagCborCid, Name: 'foo', - Size: 10 + Tsize: 10 }] } } @@ -216,7 +216,7 @@ describe('dag', () => { Links: [{ Hash: dagPbCid, Name: 'foo\b\n\t.txt', - Size: 9000 + Tsize: 9000 }] } } @@ -340,7 +340,7 @@ describe('dag', () => { const out = await cli('dag put', { getStdin: function * () { - yield uint8ArrayFromString('{}') + yield Buffer.from('{}') }, ipfs }) diff --git a/packages/ipfs-cli/test/dht.js b/packages/ipfs-cli/test/dht.js index a9ef0e17cb..46f4027c29 100644 --- a/packages/ipfs-cli/test/dht.js +++ b/packages/ipfs-cli/test/dht.js @@ -5,6 +5,9 @@ const { expect } = require('aegir/utils/chai') const cli = require('./utils/cli') const sinon = require('sinon') +const uint8ArrayFromString = require('uint8arrays/from-string') +const uint8ArrayToString = require('uint8arrays/to-string') +const CID = require('cids') describe('dht', () => { let ipfs @@ -34,7 +37,7 @@ describe('dht', () => { await cli(`dht put ${key} ${value}`, { ipfs }) - expect(ipfs.dht.put.calledWith(key, value, defaultOptions)).to.be.true() + expect(ipfs.dht.put.calledWith(uint8ArrayFromString(key), uint8ArrayFromString(value), defaultOptions)).to.be.true() }) it('should be able to put a value to the dht with a timeout', async () => { @@ -44,7 +47,7 @@ describe('dht', () => { await cli(`dht put ${key} ${value} --timeout=1s`, { ipfs }) - expect(ipfs.dht.put.calledWith(key, value, { + expect(ipfs.dht.put.calledWith(uint8ArrayFromString(key), uint8ArrayFromString(value), { ...defaultOptions, timeout: 1000 })).to.be.true() @@ -57,22 +60,22 @@ describe('dht', () => { } it('should be able to get a value from the dht', async () => { - const key = 'testkey' - const value = 'testvalue' + const key = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') + const value = uint8ArrayFromString('testvalue') - ipfs.dht.get.withArgs(key, defaultOptions).resolves(value) + ipfs.dht.get.withArgs(key.bytes, defaultOptions).resolves(value) const out = await cli(`dht get ${key}`, { ipfs }) - expect(out).to.equal(`${value}\n`) + expect(out).to.equal(`${uint8ArrayToString(value, 'base58btc')}\n`) }) it('should be able to get a value from the dht with a timeout', async () => { - const key = 'testkey' - const value = 'testvalue' + const key = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') + const value = uint8ArrayFromString('testvalue') - ipfs.dht.get.withArgs(key, { + ipfs.dht.get.withArgs(key.bytes, { ...defaultOptions, timeout: 1000 }).resolves(value) @@ -80,7 +83,7 @@ describe('dht', () => { const out = await cli(`dht get ${key} --timeout=1s`, { ipfs }) - expect(out).to.equal(`${value}\n`) + expect(out).to.equal(`${uint8ArrayToString(value, 'base58btc')}\n`) }) }) @@ -91,7 +94,7 @@ describe('dht', () => { } it('should be able to provide data', async () => { - const key = 'testkey' + const key = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') await cli(`dht provide ${key}`, { ipfs @@ -100,7 +103,7 @@ describe('dht', () => { }) it('should be able to provide data recursively', async () => { - const key = 'testkey' + const key = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') await cli(`dht provide ${key} --recursive`, { ipfs @@ -112,7 +115,7 @@ describe('dht', () => { }) it('should be able to provide data recursively (short option)', async () => { - const key = 'testkey' + const key = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') await cli(`dht provide ${key} -r`, { ipfs @@ -124,7 +127,7 @@ describe('dht', () => { }) it('should be able to provide data with a timeout', async () => { - const key = 'testkey' + const key = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') await cli(`dht provide ${key} --timeout=1s`, { ipfs @@ -141,7 +144,7 @@ describe('dht', () => { numProviders: 20, timeout: undefined } - const key = 'testkey' + const key = new CID('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') const prov = { id: 'prov-id' } @@ -184,7 +187,7 @@ describe('dht', () => { const defaultOptions = { timeout: undefined } - const peerId = 'peerId' + const peerId = 'QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp' const peer = { addrs: [ 'addr' @@ -195,11 +198,12 @@ describe('dht', () => { ipfs.dht.findPeer.withArgs(peerId, defaultOptions).returns(peer) const out = await cli(`dht findpeer ${peerId}`, { ipfs }) + expect(out).to.equal(`${peer.addrs[0]}\n`) }) it('should find a peer with a timeout', async () => { - ipfs.dht.findPeer.withArgs(peerId, { + ipfs.dht.findPeer.withArgs(peerId.toString(), { ...defaultOptions, timeout: 1000 }).returns(peer) @@ -213,12 +217,13 @@ describe('dht', () => { const defaultOptions = { timeout: undefined } - const peerId = 'peerId' + const peerId = 'QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp' const peer = { id: peerId } it('should query the DHT', async () => { + // https://github.com/libp2p/js-peer-id/issues/141 ipfs.dht.query.withArgs(peerId, defaultOptions).returns([ peer ]) @@ -228,6 +233,7 @@ describe('dht', () => { }) it('should query the DHT with a timeout', async () => { + // https://github.com/libp2p/js-peer-id/issues/141 ipfs.dht.query.withArgs(peerId, { ...defaultOptions, timeout: 1000 diff --git a/packages/ipfs-cli/test/dns.js b/packages/ipfs-cli/test/dns.js index 2eb9c641de..796a21bca7 100644 --- a/packages/ipfs-cli/test/dns.js +++ b/packages/ipfs-cli/test/dns.js @@ -7,7 +7,6 @@ const sinon = require('sinon') const defaultOptions = { recursive: true, - format: undefined, timeout: undefined } @@ -62,21 +61,6 @@ describe('dns', () => { expect(out).to.equal(`${path}\n`) }) - it('resolves ipfs.io dns with a format', async () => { - const domain = 'ipfs.io' - const path = 'path' - - ipfs.dns.withArgs(domain, { - ...defaultOptions, - format: 'derp' - }).returns(path) - - const out = await cli('dns ipfs.io --format derp', { - ipfs - }) - expect(out).to.equal(`${path}\n`) - }) - it('resolves ipfs.io dns with a timeout', async () => { const domain = 'ipfs.io' const path = 'path' diff --git a/packages/ipfs-cli/test/files/mkdir.js b/packages/ipfs-cli/test/files/mkdir.js index d9c365a874..8bee855911 100644 --- a/packages/ipfs-cli/test/files/mkdir.js +++ b/packages/ipfs-cli/test/files/mkdir.js @@ -171,7 +171,8 @@ describe('mkdir', () => { path, { ...defaultOptions, mtime: { - secs: 5 + secs: 5, + nsecs: undefined } } ]) diff --git a/packages/ipfs-cli/test/files/mv.js b/packages/ipfs-cli/test/files/mv.js index 7607de9186..7b462752f4 100644 --- a/packages/ipfs-cli/test/files/mv.js +++ b/packages/ipfs-cli/test/files/mv.js @@ -8,7 +8,6 @@ const { isNode } = require('ipfs-utils/src/env') const defaultOptions = { parents: false, - recursive: false, cidVersion: 0, hashAlg: 'sha2-256', flush: true, @@ -70,32 +69,6 @@ describe('mv', () => { ]) }) - it('should move an entry recursively', async () => { - await cli(`files mv --recursive ${source} ${dest}`, { ipfs }) - - expect(ipfs.files.mv.callCount).to.equal(1) - expect(ipfs.files.mv.getCall(0).args).to.deep.equal([ - source, - dest, { - ...defaultOptions, - recursive: true - } - ]) - }) - - it('should move an entry recursively (short option)', async () => { - await cli(`files mv -r ${source} ${dest}`, { ipfs }) - - expect(ipfs.files.mv.callCount).to.equal(1) - expect(ipfs.files.mv.getCall(0).args).to.deep.equal([ - source, - dest, { - ...defaultOptions, - recursive: true - } - ]) - }) - it('should make a directory with a different cid version', async () => { await cli(`files mv --cid-version 5 ${source} ${dest}`, { ipfs }) diff --git a/packages/ipfs-cli/test/files/touch.js b/packages/ipfs-cli/test/files/touch.js index ced5441279..1279e9e78f 100644 --- a/packages/ipfs-cli/test/files/touch.js +++ b/packages/ipfs-cli/test/files/touch.js @@ -22,7 +22,8 @@ describe('touch', () => { const path = '/foo' const mtime = { - secs: 1000 + secs: 1000, + nsecs: undefined } let ipfs diff --git a/packages/ipfs-cli/test/files/write.js b/packages/ipfs-cli/test/files/write.js index 96827d471a..3742eb1ea3 100644 --- a/packages/ipfs-cli/test/files/write.js +++ b/packages/ipfs-cli/test/files/write.js @@ -16,7 +16,6 @@ const defaultOptions = { cidVersion: 0, hashAlg: 'sha2-256', parents: false, - progress: undefined, strategy: 'balanced', flush: true, shardSplitThreshold: 1000, @@ -411,7 +410,8 @@ describe('write', () => { stdin, { ...defaultOptions, mtime: { - secs: 11 + secs: 11, + nsecs: undefined } } ]) diff --git a/packages/ipfs-cli/test/get.js b/packages/ipfs-cli/test/get.js index 9e3848a53d..0677d4cfb4 100644 --- a/packages/ipfs-cli/test/get.js +++ b/packages/ipfs-cli/test/get.js @@ -27,6 +27,7 @@ describe('get', () => { it('should get file', async () => { ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{ + type: 'file', path: 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB', content: function * () { yield buf @@ -47,6 +48,7 @@ describe('get', () => { it('get file with output option', async () => { ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{ + type: 'file', path: 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB', content: function * () { yield buf @@ -67,6 +69,7 @@ describe('get', () => { it('get file with short output option', async () => { ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{ + type: 'file', path: 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB', content: function * () { yield buf @@ -87,6 +90,7 @@ describe('get', () => { it('get directory', async () => { ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{ + type: 'dir', path: cid.toString() }]) @@ -104,8 +108,10 @@ describe('get', () => { it('get recursively', async () => { ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{ + type: 'dir', path: cid.toString() }, { + type: 'file', path: `${cid}/foo.txt`, content: function * () { yield buf @@ -132,6 +138,7 @@ describe('get', () => { ...defaultOptions, timeout: 1000 }).returns([{ + type: 'file', path: cid.toString(), content: function * () { yield buf @@ -152,6 +159,7 @@ describe('get', () => { it('should not get file with path traversal characters that result in leaving the output directory', async () => { ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{ + type: 'file', path: '../foo.txt', content: function * () { yield buf @@ -165,6 +173,7 @@ describe('get', () => { it('should get file with path traversal characters that result in leaving the output directory when forced', async () => { ipfs.get.withArgs(cid.toString(), defaultOptions).returns([{ + type: 'file', path: '../foo.txt', content: function * () { yield buf @@ -194,6 +203,7 @@ describe('get', () => { const junkPath = `${cid}/foo\b/bar` ipfs.get.withArgs(junkPath, defaultOptions).returns([{ + type: 'file', path: junkPath, content: function * () { yield buf diff --git a/packages/ipfs-cli/test/object.js b/packages/ipfs-cli/test/object.js index ad5b252456..4f31a6aa82 100644 --- a/packages/ipfs-cli/test/object.js +++ b/packages/ipfs-cli/test/object.js @@ -81,14 +81,13 @@ describe('object', () => { describe('get', () => { const defaultOptions = { - enc: 'base58', timeout: undefined } it('should get an object', async () => { const node = new DAGNode() - ipfs.object.get.withArgs(cid.toString(), defaultOptions).resolves(node) + ipfs.object.get.withArgs(cid, defaultOptions).resolves(node) const out = await cli(`object get ${cid}`, { ipfs }) const result = JSON.parse(out) @@ -104,7 +103,7 @@ describe('object', () => { Hash: cid }) - ipfs.object.get.withArgs(cid.toString(), defaultOptions).resolves(node) + ipfs.object.get.withArgs(cid, defaultOptions).resolves(node) const out = await cli(`object get ${cid}`, { ipfs }) const result = JSON.parse(out) @@ -119,7 +118,7 @@ describe('object', () => { it('get with data', async () => { const node = new DAGNode(uint8ArrayFromString('aGVsbG8gd29ybGQK', 'base64')) - ipfs.object.get.withArgs(cid.toString(), defaultOptions).resolves(node) + ipfs.object.get.withArgs(cid, defaultOptions).resolves(node) const out = await cli(`object get ${cid}`, { ipfs }) const result = JSON.parse(out) @@ -130,7 +129,7 @@ describe('object', () => { it('get while overriding data-encoding', async () => { const node = new DAGNode(uint8ArrayFromString('hello world')) - ipfs.object.get.withArgs(cid.toString(), defaultOptions).resolves(node) + ipfs.object.get.withArgs(cid, defaultOptions).resolves(node) const out = await cli(`object get --data-encoding=utf8 ${cid}`, { ipfs }) const result = JSON.parse(out) @@ -143,7 +142,7 @@ describe('object', () => { new DAGLink('', 0, cid.toV1()) ]) - ipfs.object.get.withArgs(cid.toV1().toString(), defaultOptions).resolves(node) + ipfs.object.get.withArgs(cid.toV1(), defaultOptions).resolves(node) const out = await cli(`object get --cid-base=base64 ${cid.toV1()}`, { ipfs }) const result = JSON.parse(out) @@ -157,7 +156,7 @@ describe('object', () => { it('should get an object with a timeout', async () => { const node = new DAGNode() - ipfs.object.get.withArgs(cid.toString(), { + ipfs.object.get.withArgs(cid, { ...defaultOptions, timeout: 1000 }).resolves(node) @@ -186,7 +185,7 @@ describe('object', () => { }) it('put from pipe', async () => { - const buf = uint8ArrayFromString('hello world') + const buf = Buffer.from('hello world') ipfs.object.put.withArgs(buf, defaultOptions).resolves(cid) @@ -231,12 +230,11 @@ describe('object', () => { describe('stat', () => { const defaultOptions = { - enc: 'base58', timeout: undefined } it('should stat an object', async () => { - ipfs.object.stat.withArgs(cid.toString(), defaultOptions).resolves({ + ipfs.object.stat.withArgs(cid, defaultOptions).resolves({ Hash: cid, NumLinks: 1, BlockSize: 60, @@ -256,7 +254,7 @@ describe('object', () => { }) it('should stat an object with a timeout', async () => { - ipfs.object.stat.withArgs(cid.toString(), { + ipfs.object.stat.withArgs(cid, { ...defaultOptions, timeout: 1000 }).resolves({ @@ -282,19 +280,18 @@ describe('object', () => { describe('data', () => { const data = 'another' const defaultOptions = { - enc: 'base58', timeout: undefined } it('should return data from an object', async () => { - ipfs.object.data.withArgs(cid.toString(), defaultOptions).resolves(data) + ipfs.object.data.withArgs(cid, defaultOptions).resolves(data) const out = await cli(`object data ${cid}`, { ipfs }) expect(out).to.equal(data) }) it('should return data from an object with a timeout', async () => { - ipfs.object.data.withArgs(cid.toString(), { + ipfs.object.data.withArgs(cid, { ...defaultOptions, timeout: 1000 }).resolves(data) @@ -306,12 +303,11 @@ describe('object', () => { describe('links', () => { const defaultOptions = { - enc: 'base58', timeout: undefined } it('should return links from an object', async () => { - ipfs.object.links.withArgs(cid.toString(), defaultOptions).resolves([ + ipfs.object.links.withArgs(cid, defaultOptions).resolves([ new DAGLink('some link', 8, new CID('QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V')) ]) @@ -324,7 +320,7 @@ describe('object', () => { it('should get links and print CIDs encoded in specified base', async () => { const cid = new CID('QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm').toV1() - ipfs.object.links.withArgs(cid.toString(), defaultOptions).resolves([ + ipfs.object.links.withArgs(cid, defaultOptions).resolves([ new DAGLink('some link', 8, new CID('QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V').toV1()) ]) @@ -337,7 +333,7 @@ describe('object', () => { }) it('should return links from an object with a timeout', async () => { - ipfs.object.links.withArgs(cid.toString(), { + ipfs.object.links.withArgs(cid, { ...defaultOptions, timeout: 1000 }).resolves([ @@ -351,7 +347,7 @@ describe('object', () => { }) it('should get an object and strip control characters from link names', async () => { - ipfs.object.links.withArgs(cid.toString(), defaultOptions).resolves([ + ipfs.object.links.withArgs(cid, defaultOptions).resolves([ new DAGLink('derp\t\n\b', 8, new CID('QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V')) ]) @@ -365,7 +361,6 @@ describe('object', () => { describe('patch', () => { describe('append-data', () => { const defaultOptions = { - enc: 'base58', timeout: undefined } @@ -373,7 +368,7 @@ describe('object', () => { const filePath = 'README.md' const buf = fs.readFileSync(filePath) - ipfs.object.patch.appendData.withArgs(cid.toString(), buf, defaultOptions).resolves( + ipfs.object.patch.appendData.withArgs(cid, buf, defaultOptions).resolves( cid ) @@ -381,10 +376,10 @@ describe('object', () => { expect(out).to.equal(`${cid}\n`) }) - it('append-data from pipe', async () => { + it('append data from pipe', async () => { const buf = Buffer.from('hello world') - ipfs.object.patch.appendData.withArgs(cid.toString(), buf, defaultOptions).resolves( + ipfs.object.patch.appendData.withArgs(cid, buf, defaultOptions).resolves( cid ) @@ -397,11 +392,11 @@ describe('object', () => { expect(out).to.equal(`${cid}\n`) }) - it('should append-data and print CID encoded in specified base', async () => { + it('should append data and print CID encoded in specified base', async () => { const filePath = 'README.md' const buf = fs.readFileSync(filePath) - ipfs.object.patch.appendData.withArgs(cid.toString(), buf, defaultOptions).resolves( + ipfs.object.patch.appendData.withArgs(cid, buf, defaultOptions).resolves( cid.toV1() ) @@ -413,7 +408,7 @@ describe('object', () => { const filePath = 'README.md' const buf = fs.readFileSync(filePath) - ipfs.object.patch.appendData.withArgs(cid.toString(), buf, { + ipfs.object.patch.appendData.withArgs(cid, buf, { ...defaultOptions, timeout: 1000 }).resolves( @@ -427,7 +422,6 @@ describe('object', () => { describe('set-data', () => { const defaultOptions = { - enc: 'base58', timeout: undefined } @@ -435,7 +429,7 @@ describe('object', () => { const filePath = 'README.md' const buf = fs.readFileSync(filePath) - ipfs.object.patch.setData.withArgs(cid.toString(), buf, defaultOptions).resolves( + ipfs.object.patch.setData.withArgs(cid, buf, defaultOptions).resolves( cid ) @@ -446,7 +440,7 @@ describe('object', () => { it('set-data from pipe', async () => { const buf = Buffer.from('hello world') - ipfs.object.patch.setData.withArgs(cid.toString(), buf, defaultOptions).resolves( + ipfs.object.patch.setData.withArgs(cid, buf, defaultOptions).resolves( cid ) @@ -463,7 +457,7 @@ describe('object', () => { const filePath = 'README.md' const buf = fs.readFileSync(filePath) - ipfs.object.patch.setData.withArgs(cid.toV1().toString(), buf, defaultOptions).resolves( + ipfs.object.patch.setData.withArgs(cid.toV1(), buf, defaultOptions).resolves( cid.toV1() ) @@ -475,7 +469,7 @@ describe('object', () => { const filePath = 'README.md' const buf = fs.readFileSync(filePath) - ipfs.object.patch.setData.withArgs(cid.toString(), buf, { + ipfs.object.patch.setData.withArgs(cid, buf, { ...defaultOptions, timeout: 1000 }).resolves( @@ -489,7 +483,6 @@ describe('object', () => { describe('add-link', () => { const defaultOptions = { - enc: 'base58', timeout: undefined } @@ -497,10 +490,10 @@ describe('object', () => { const linkCid = new CID('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n') const updatedCid = new CID('QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm') - ipfs.object.get.withArgs(linkCid.toString(), defaultOptions).resolves( + ipfs.object.get.withArgs(linkCid, defaultOptions).resolves( new DAGNode() ) - ipfs.object.patch.addLink.withArgs(cid.toString(), sinon.match.instanceOf(DAGLink), defaultOptions).resolves( + ipfs.object.patch.addLink.withArgs(cid, sinon.match.instanceOf(DAGLink), defaultOptions).resolves( updatedCid ) @@ -514,10 +507,10 @@ describe('object', () => { const linkCid = new CID('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n').toV1() const updatedCid = new CID('QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm').toV1() - ipfs.object.get.withArgs(linkCid.toString(), defaultOptions).resolves( + ipfs.object.get.withArgs(linkCid, defaultOptions).resolves( new DAGNode() ) - ipfs.object.patch.addLink.withArgs(cid.toV1().toString(), sinon.match.instanceOf(DAGLink), defaultOptions).resolves( + ipfs.object.patch.addLink.withArgs(cid.toV1(), sinon.match.instanceOf(DAGLink), defaultOptions).resolves( updatedCid ) @@ -531,13 +524,13 @@ describe('object', () => { const linkCid = new CID('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n') const updatedCid = new CID('QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm') - ipfs.object.get.withArgs(linkCid.toString(), { + ipfs.object.get.withArgs(linkCid, { ...defaultOptions, timeout: 1000 }).resolves( new DAGNode() ) - ipfs.object.patch.addLink.withArgs(cid.toString(), sinon.match.instanceOf(DAGLink), { + ipfs.object.patch.addLink.withArgs(cid, sinon.match.instanceOf(DAGLink), { ...defaultOptions, timeout: 1000 }).resolves( @@ -553,7 +546,6 @@ describe('object', () => { describe('rm-link', () => { const defaultOptions = { - enc: 'base58', timeout: undefined } @@ -562,7 +554,7 @@ describe('object', () => { const updatedCid = new CID('QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm') const linkName = 'foo' - ipfs.object.patch.rmLink.withArgs(cid.toString(), { name: linkName }, defaultOptions).resolves( + ipfs.object.patch.rmLink.withArgs(cid, linkName, defaultOptions).resolves( updatedCid ) @@ -577,7 +569,7 @@ describe('object', () => { const updatedCid = new CID('QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm').toV1() const linkName = 'foo' - ipfs.object.patch.rmLink.withArgs(cid.toString(), { name: linkName }, defaultOptions).resolves( + ipfs.object.patch.rmLink.withArgs(cid, linkName, defaultOptions).resolves( updatedCid ) @@ -592,7 +584,7 @@ describe('object', () => { const updatedCid = new CID('QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm') const linkName = 'foo' - ipfs.object.patch.rmLink.withArgs(cid.toString(), { name: linkName }, { + ipfs.object.patch.rmLink.withArgs(cid, linkName, { ...defaultOptions, timeout: 1000 }).resolves( diff --git a/packages/ipfs-cli/test/pin.js b/packages/ipfs-cli/test/pin.js index 88fe2bceba..deeb3c524d 100644 --- a/packages/ipfs-cli/test/pin.js +++ b/packages/ipfs-cli/test/pin.js @@ -235,7 +235,6 @@ describe('pin', () => { describe('ls', function () { const defaultOptions = { type: 'all', - stream: false, timeout: undefined, paths: undefined } diff --git a/packages/ipfs-cli/test/ping.js b/packages/ipfs-cli/test/ping.js index 0b5bec2f02..0c729bb867 100644 --- a/packages/ipfs-cli/test/ping.js +++ b/packages/ipfs-cli/test/ping.js @@ -20,9 +20,10 @@ describe('ping', function () { }) it('ping host', async () => { - const peerId = 'peer-id' + const peerId = 'QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp' const time = 10 + // https://github.com/libp2p/js-peer-id/issues/141 ipfs.ping.withArgs(peerId, defaultOptions).returns([{ success: true, time @@ -33,9 +34,10 @@ describe('ping', function () { }) it('ping host with --n option', async () => { - const peerId = 'peer-id' + const peerId = 'QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp' const time = 10 + // https://github.com/libp2p/js-peer-id/issues/141 ipfs.ping.withArgs(peerId, { ...defaultOptions, count: 1 @@ -49,10 +51,11 @@ describe('ping', function () { }) it('ping host with --count option', async () => { - const peerId = 'peer-id' + const peerId = 'QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp' const time = 10 - ipfs.ping.withArgs(peerId, { + // https://github.com/libp2p/js-peer-id/issues/141 + ipfs.ping.withArgs(peerId.toString(), { ...defaultOptions, count: 1 }).returns([{ @@ -65,10 +68,11 @@ describe('ping', function () { }) it('ping host with timeout', async () => { - const peerId = 'peer-id' + const peerId = 'QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp' const time = 10 - ipfs.ping.withArgs(peerId, { + // https://github.com/libp2p/js-peer-id/issues/141 + ipfs.ping.withArgs(peerId.toString(), { ...defaultOptions, timeout: 1000 }).returns([{ diff --git a/packages/ipfs-cli/test/repo.js b/packages/ipfs-cli/test/repo.js index 2ee960d392..66051740a7 100644 --- a/packages/ipfs-cli/test/repo.js +++ b/packages/ipfs-cli/test/repo.js @@ -4,7 +4,6 @@ const { expect } = require('aegir/utils/chai') const cli = require('./utils/cli') const sinon = require('sinon') -const BigNumber = require('bignumber.js') const CID = require('cids') describe('repo', () => { @@ -27,9 +26,9 @@ describe('repo', () => { it('get repo stats', async () => { ipfs.repo.stat.withArgs(defaultOptions).resolves({ - numObjects: BigNumber(10), - repoSize: BigNumber(10), - storageMax: BigNumber(10), + numObjects: BigInt(10), + repoSize: BigInt(10), + storageMax: BigInt(10), repoPath: '/foo', version: 5 }) @@ -44,9 +43,9 @@ describe('repo', () => { it('get repo stats with just size', async () => { ipfs.repo.stat.withArgs(defaultOptions).resolves({ - numObjects: BigNumber(10), - repoSize: BigNumber(10), - storageMax: BigNumber(10), + numObjects: BigInt(10), + repoSize: BigInt(10), + storageMax: BigInt(10), repoPath: '/foo', version: 5 }) @@ -61,9 +60,9 @@ describe('repo', () => { it('get human readable repo stats', async () => { ipfs.repo.stat.withArgs(defaultOptions).resolves({ - numObjects: BigNumber(10), - repoSize: BigNumber(10), - storageMax: BigNumber(10), + numObjects: BigInt(10), + repoSize: BigInt(10), + storageMax: BigInt(10), repoPath: '/foo', version: 5 }) @@ -81,9 +80,9 @@ describe('repo', () => { ...defaultOptions, timeout: 1000 }).resolves({ - numObjects: BigNumber(10), - repoSize: BigNumber(10), - storageMax: BigNumber(10), + numObjects: BigInt(10), + repoSize: BigInt(10), + storageMax: BigInt(10), repoPath: '/foo', version: 5 }) diff --git a/packages/ipfs-cli/test/swarm.js b/packages/ipfs-cli/test/swarm.js index ceb332d937..e173d3a555 100644 --- a/packages/ipfs-cli/test/swarm.js +++ b/packages/ipfs-cli/test/swarm.js @@ -28,17 +28,16 @@ describe('swarm', () => { } it('connect online', async () => { - const multiaddr = 'multiaddr' - const result = 'result' + const multiaddr = ma('/ip4/123.123.123.123/tcp/482') - ipfs.swarm.connect.withArgs(multiaddr, defaultOptions).resolves([result]) + ipfs.swarm.connect.withArgs(multiaddr, defaultOptions).resolves() const out = await cli(`swarm connect ${multiaddr}`, { ipfs, isDaemon: true }) - expect(out).to.equal(`${result}\n`) + expect(out).to.equal(`${multiaddr}\n`) }) it('connect offline', async () => { - const multiaddr = 'multiaddr' + const multiaddr = ma('/ip4/123.123.123.123/tcp/482') const out = await cli.fail(`swarm connect ${multiaddr}`, { ipfs, isDaemon: false }) expect(out).to.include('This command must be run in online mode') @@ -47,16 +46,15 @@ describe('swarm', () => { }) it('connect with timeout', async () => { - const multiaddr = 'multiaddr' - const result = 'result' + const multiaddr = ma('/ip4/123.123.123.123/tcp/482') ipfs.swarm.connect.withArgs(multiaddr, { ...defaultOptions, timeout: 1000 - }).resolves([result]) + }).resolves() const out = await cli(`swarm connect ${multiaddr} --timeout=1s`, { ipfs, isDaemon: true }) - expect(out).to.equal(`${result}\n`) + expect(out).to.equal(`${multiaddr}\n`) }) }) @@ -177,26 +175,26 @@ describe('swarm', () => { } it('disconnect online', async () => { - const addr = 'addr' - ipfs.swarm.disconnect.withArgs(addr, defaultOptions).resolves([addr]) - const out = await cli(`swarm disconnect ${addr}`, { ipfs, isDaemon: true }) - expect(out).to.equal(`${addr}\n`) + const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + ipfs.swarm.disconnect.withArgs(multiaddr, defaultOptions).resolves() + const out = await cli(`swarm disconnect ${multiaddr}`, { ipfs, isDaemon: true }) + expect(out).to.equal(`${multiaddr}\n`) }) it('disconnect offline', async () => { - const addr = 'addr' - const out = await cli.fail(`swarm disconnect ${addr}`, { ipfs, isDaemon: false }) + const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + const out = await cli.fail(`swarm disconnect ${multiaddr}`, { ipfs, isDaemon: false }) expect(out).to.include('This command must be run in online mode') }) it('disconnect with timeout', async () => { - const addr = 'addr' - ipfs.swarm.disconnect.withArgs(addr, { + const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + ipfs.swarm.disconnect.withArgs(multiaddr, { ...defaultOptions, timeout: 1000 - }).resolves([addr]) - const out = await cli(`swarm disconnect ${addr} --timeout=1s`, { ipfs, isDaemon: true }) - expect(out).to.equal(`${addr}\n`) + }).resolves() + const out = await cli(`swarm disconnect ${multiaddr} --timeout=1s`, { ipfs, isDaemon: true }) + expect(out).to.equal(`${multiaddr}\n`) }) }) }) diff --git a/packages/ipfs-cli/tsconfig.json b/packages/ipfs-cli/tsconfig.json index f9f47fbb7d..2a5580b45c 100644 --- a/packages/ipfs-cli/tsconfig.json +++ b/packages/ipfs-cli/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, @@ -11,6 +11,9 @@ { "path": "../ipfs-core" }, + { + "path": "../ipfs-core-types" + }, { "path": "../ipfs-core-utils" }, diff --git a/packages/ipfs-client/.aegir.js b/packages/ipfs-client/.aegir.js index 4b403feb55..358a154f0b 100644 --- a/packages/ipfs-client/.aegir.js +++ b/packages/ipfs-client/.aegir.js @@ -3,6 +3,6 @@ /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '135kB' + bundlesizeMax: '137kB' } } diff --git a/packages/ipfs-client/README.md b/packages/ipfs-client/README.md index 3750448ddb..06cc41df46 100644 --- a/packages/ipfs-client/README.md +++ b/packages/ipfs-client/README.md @@ -14,7 +14,7 @@ $ npm install ipfs-client The client object created by the `createClient` function supports the [IPFS Core API](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api), see the docs for more. -### `createClient([options])` +### `create([options])` ### Parameters @@ -39,9 +39,9 @@ An optional object which may have the following keys: ### Example ```js -const createClient = require('ipfs-client') +const { create } = require('ipfs-client') -const client = createClient({ +const client = create({ grpc: '/ipv4/127.0.0.1/tcp/5003/ws', http: '/ipv4/127.0.0.1/tcp/5002/http' }) diff --git a/packages/ipfs-client/package.json b/packages/ipfs-client/package.json index 7fc9947d03..8cbce7067e 100644 --- a/packages/ipfs-client/package.json +++ b/packages/ipfs-client/package.json @@ -11,17 +11,11 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", - "typesVersions": { - "*": { - "*": [ - "dist/*", - "dist/*/index" - ] - } - }, + "types": "dist/src/index.d.ts", "eslintConfig": { "extends": "ipfs" }, @@ -30,9 +24,8 @@ "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { - "prepare": "npm run build", "build": "aegir build", - "test": "aegir test", + "test": "echo please run test:interface:client in the ipfs package instead", "lint": "aegir lint", "coverage": "npx nyc -r html npm run test:node -- --bail", "clean": "rimraf ./dist", @@ -44,7 +37,7 @@ "merge-options": "^3.0.4" }, "devDependencies": { - "aegir": "^31.0.0", + "aegir": "^32.1.0", "rimraf": "^3.0.2" } } diff --git a/packages/ipfs-client/src/index.js b/packages/ipfs-client/src/index.js index db02299da2..e4e14466cd 100644 --- a/packages/ipfs-client/src/index.js +++ b/packages/ipfs-client/src/index.js @@ -1,18 +1,18 @@ 'use strict' -const httpClient = require('ipfs-http-client') -const grpcClient = require('ipfs-grpc-client') +const { create: httpClient } = require('ipfs-http-client') +const { create: grpcClient } = require('ipfs-grpc-client') const mergeOptions = require('merge-options') /** - * @typedef {import('ipfs-http-client/src/lib/core').ClientOptions} HTTPOptions - * @typedef {import('ipfs-grpc-client/src/index').Options} GRPCOptions + * @typedef {import('ipfs-http-client').Options} HTTPOptions + * @typedef {import('ipfs-grpc-client').Options} GRPCOptions * @typedef {string|URL|import('multiaddr')} Address * @typedef {{http?: Address, grpc?: Address} & Partial} Options * * @param {Options} [opts] */ -module.exports = function createClient (opts = {}) { +function create (opts = {}) { const clients = [] if (opts.http) { @@ -32,3 +32,7 @@ module.exports = function createClient (opts = {}) { // override http methods with grpc if address is supplied return mergeOptions.apply({ ignoreUndefined: true }, clients) } + +module.exports = { + create +} diff --git a/packages/ipfs-client/tsconfig.json b/packages/ipfs-client/tsconfig.json index b45232f56a..5ddfb7d12d 100644 --- a/packages/ipfs-client/tsconfig.json +++ b/packages/ipfs-client/tsconfig.json @@ -1,8 +1,11 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, + "include": [ + "src" + ], "references": [ { "path": "../ipfs-http-client" @@ -10,9 +13,5 @@ { "path": "../ipfs-grpc-client" } - ], - "include": [ - "src", - "package.json" ] } diff --git a/packages/ipfs-core-types/README.md b/packages/ipfs-core-types/README.md index 831e49bf1f..5573ad5265 100644 --- a/packages/ipfs-core-types/README.md +++ b/packages/ipfs-core-types/README.md @@ -6,7 +6,7 @@ [![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) [![Dependency Status](https://david-dm.org/ipfs/js-ipfs/status.svg?style=flat-square&path=packages/interface-ipfs-core)](https://david-dm.org/ipfs/js-ipfs?path=packages/interface-ipfs-core) -> IPFS interface definitions used by implementations for API compatibility. +> IPFS interface definitions used by implementations for API compatibility ## Lead Maintainer @@ -17,6 +17,8 @@ - [Background](#background) - [Install](#install) - [Usage](#usage) + - [In JSDoc syntax](#in-jsdoc-syntax) + - [In Typescript](#in-typescript) - [Validation](#validation) - [Contribute](#contribute) - [Want to hack on IPFS?](#want-to-hack-on-ipfs) @@ -24,9 +26,9 @@ ## Background -The primary goal of this module is to define and ensure that IPFS core implementations and their respective HTTP client libraries implement the same interface, so that developers can quickly change between a local and a remote node without having to change their applications. +The primary goal of this module is to define and ensure that IPFS core implementations and their respective client libraries implement the same interface, so that developers can quickly change between a local and a remote node without having to change their applications. -It offers set of typescript interface definitions that implementations can claim compatibility with and use typescript to validate those claims. +It offers a set of typescript interface definitions that define the IPFS core API. Once your implementation implements those APIs you can use the tests found in the [interface-ipfs-core](https://www.npmjs.com/package/interface-ipfs-core) module to validate your implementation. ## Install @@ -44,9 +46,9 @@ Install `ipfs-core-types` as one of the dependencies of your project and use it ```js /** - * @implements {import('ipfs-core-types').RootAPI} + * @implements {import('ipfs-core-types').IPFS} */ -class Root { +class MyImpl { // your implementation goes here } ``` @@ -54,8 +56,8 @@ class Root { ### In Typescript ```ts -import { RootAPI } from 'ipfs-core-types' -class Root implements RootAPI { +import type { IPFS } from 'ipfs-core-types' +class MyImpl implements IPFS { // your implementation goes here } ``` diff --git a/packages/ipfs-core-types/package.json b/packages/ipfs-core-types/package.json index 65d4518953..c3e1fe718d 100644 --- a/packages/ipfs-core-types/package.json +++ b/packages/ipfs-core-types/package.json @@ -3,7 +3,7 @@ "version": "0.3.1", "description": "IPFS interface definitions used by implementations for API compatibility.", "leadMaintainer": "Alex Potsides ", - "types": "src/index.ts", + "types": "src/index.d.ts", "homepage": "https://github.com/ipfs/js-ipfs/tree/master/packages/interface-ipfs-core#readme", "bugs": "https://github.com/ipfs/js-ipfs/issues", "scripts": { @@ -30,10 +30,10 @@ "dependencies": { "cids": "^1.1.5", "multiaddr": "^8.0.0", - "peer-id": "^0.14.1" + "multibase": "^4.0.2" }, "devDependencies": { - "aegir": "^31.0.0" + "aegir": "^32.1.0" }, "contributors": [ "Irakli Gozalishvili " diff --git a/packages/ipfs-core-types/src/basic.ts b/packages/ipfs-core-types/src/basic.ts deleted file mode 100644 index f492bb853a..0000000000 --- a/packages/ipfs-core-types/src/basic.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Represents a value that you can await on, which is either value or a promise - * of one. - */ -export type Await = - | T - | Promise - -/** - * Represents an iterable that can be used in `for await` loops, that is either - * iterable or an async iterable. - */ -export type AwaitIterable = - | Iterable - | AsyncIterable - -/** - * Common options across all cancellable requests. - */ -export interface AbortOptions { - /** - * Can be provided to a function that starts a long running task, which will - * be aborted when signal is triggered. - */ - signal?: AbortSignal - /** - * Can be provided to a function that starts a long running task, which will - * be aborted after provided timeout (in ms). - */ - timeout?: number -} - -export type ToJSON = - | null - | string - | number - | boolean - | ToJSON[] - | { toJSON?: () => ToJSON } & { [key: string]: ToJSON } diff --git a/packages/ipfs-core-types/src/bitswap.ts b/packages/ipfs-core-types/src/bitswap.ts deleted file mode 100644 index a00c8de9b5..0000000000 --- a/packages/ipfs-core-types/src/bitswap.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type BigInteger from 'bignumber.js' -import type PeerId from 'peer-id' -import type CID from 'cids' -import type { Block } from './block-service' -import type { AbortOptions, Await } from './basic' -import type { MovingAverage } from './bitswap/moving-avarage' -import type { StoreReader, StoreExporter, StoreImporter } from './store' - -export interface Bitswap extends - StoreReader, - StoreExporter, - StoreImporter { - - readonly peerId: PeerId - - enableStats: () => void - disableStats: () => void - - wantlistForPeer: (peerId: PeerId, options?: AbortOptions) => Map - ledgerForPeer: (peerId: PeerId) => null|LedgerForPeer - - put: (block: Block, options?: AbortOptions) => Await - - unwant: (cids: CID|CID[], options?: AbortOptions) => void - cancelWants: (cids: CID|CID[]) => void - getWantlist: (options?: AbortOptions) => Iterable<[string, WantListEntry]> - peers: () => PeerId[] - stat: () => Stats - start: () => void - stop: () => void -} - -export interface LedgerForPeer { - peer: string - value: number - sent: number - recv: number - exchanged: number -} - -export interface Ledger { - sentBytes: (n: number) => void - receivedBytes: (n: number) => void - - wants: (cid: CID, priority: number, wantType: WantType) => void - cancelWant: (cid: CID) => void - wantlistContains: (cid: CID) => WantListEntry|undefined - - debtRatio: () => number -} - -export interface WantListEntry { - readonly cid: CID - priority: number - inc: () => void - dec: () => void - hasRefs: () => boolean - equals: (other: WantListEntry) => boolean -} - -export interface WantList { - entries: Entry[] - full?: boolean -} - -export interface Entry { - block: Uint8Array - priority: number - cancel: boolean - wantType?: WantType - sendDontHave?: boolean -} - -export interface BlockPresence { - cid: Uint8Array - type: BlockPresenceType -} - -export type Have = 0 -export type DontHave = 1 -export type BlockPresenceType = Have | DontHave - -export type WantBlock = 0 -export type HaveBlock = 1 -export type WantType = WantBlock | HaveBlock - -export interface BlockData { - prefix: Uint8Array - data: Uint8Array -} - -export interface Stats { - enable: () => void - disable: () => void - stop: () => void - readonly snapshot: Record - readonly movingAverages: Record> - push: (peer: string|null, counter: string, inc: number) => void -} diff --git a/packages/ipfs-core-types/src/bitswap/index.d.ts b/packages/ipfs-core-types/src/bitswap/index.d.ts new file mode 100644 index 0000000000..7737cb222b --- /dev/null +++ b/packages/ipfs-core-types/src/bitswap/index.d.ts @@ -0,0 +1,70 @@ +import type CID from 'cids' +import type { AbortOptions } from '../utils' + +export interface API { + /** + * Returns the wantlist for your node + * + * @example + * ```js + * const list = await ipfs.bitswap.wantlist() + * console.log(list) + * // [ CID('QmHash') ] + * ``` + */ + wantlist: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Returns the wantlist for a connected peer + * + * @example + * ```js + * const list = await ipfs.bitswap.wantlistForPeer(peerId) + * console.log(list) + * // [ CID('QmHash') ] + * ``` + */ + wantlistForPeer: (peerId: CID | string, options?: AbortOptions & OptionExtension) => Promise + + /** + * Removes one or more CIDs from the wantlist + * + * @example + * ```JavaScript + * let list = await ipfs.bitswap.wantlist() + * console.log(list) + * // [ CID('QmHash') ] + * + * await ipfs.bitswap.unwant(cid) + * + * list = await ipfs.bitswap.wantlist() + * console.log(list) + * // [] + * ``` + */ + unwant: (cids: CID | CID[], options?: AbortOptions & OptionExtension) => Promise + + /** + * Show diagnostic information on the bitswap agent. + * Note: `bitswap.stat` and `stats.bitswap` can be used interchangeably. + * + * @example + * ```js + * const stats = await ipfs.bitswap.stat() + * console.log(stats) + * ``` + */ + stat: (options?: AbortOptions & OptionExtension) => Promise +} + +export interface Stats { + provideBufLen: number + wantlist: CID[] + peers: CID[] + blocksReceived: BigInt + dataReceived: BigInt + blocksSent: BigInt + dataSent: BigInt + dupBlksReceived: BigInt + dupDataReceived: BigInt +} diff --git a/packages/ipfs-core-types/src/bitswap/moving-avarage.ts b/packages/ipfs-core-types/src/bitswap/moving-avarage.ts deleted file mode 100644 index 8fe2db8431..0000000000 --- a/packages/ipfs-core-types/src/bitswap/moving-avarage.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface MovingAverage { - variance: () => number - movingAverage: () => number - - deviation: () => number - forecast: () => number - - push: (time: number, value: number) => void -} diff --git a/packages/ipfs-core-types/src/block-service.ts b/packages/ipfs-core-types/src/block-service.ts deleted file mode 100644 index c9e1271cc5..0000000000 --- a/packages/ipfs-core-types/src/block-service.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type CID from 'cids' -import type { Await, AbortOptions } from './basic' -import type { StoreReader, StoreImporter, StoreExporter, StoreEraser } from './store' -import type { Bitswap } from './bitswap' - -export interface BlockService extends - StoreReader, - StoreExporter, - StoreImporter, - StoreEraser { - setExchange: (bitswap: Bitswap) => void - - unsetExchange: () => void - hasExchange: () => boolean - - /** - * Put a block to the underlying datastore. - */ - put: (block: Block, options?: AbortOptions) => Await -} - -export interface Block { - cid: CID - data: Uint8Array -} diff --git a/packages/ipfs-core-types/src/block-store.ts b/packages/ipfs-core-types/src/block-store.ts deleted file mode 100644 index b34f78fd74..0000000000 --- a/packages/ipfs-core-types/src/block-store.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { AbortOptions, Await, AwaitIterable } from './basic' -import type { Block } from './block-service' -import type CID from 'cids' - -export interface BlockStore { - has: (cid: CID, options?: AbortOptions) => Await - get: (cid: CID, options?: AbortOptions) => Await - put: (block: Block, options?: AbortOptions) => Await - putMany: (blocks: AsyncIterable|Iterable, options?: AbortOptions) => AwaitIterable -} diff --git a/packages/ipfs-core-types/src/block/index.d.ts b/packages/ipfs-core-types/src/block/index.d.ts new file mode 100644 index 0000000000..3035ac8910 --- /dev/null +++ b/packages/ipfs-core-types/src/block/index.d.ts @@ -0,0 +1,156 @@ +import { AbortOptions, PreloadOptions } from '../utils' +import CID, { CIDVersion } from 'cids' +import Block from 'ipld-block' +import { CodecName } from 'multicodec' +import { HashName } from 'multihashes' + +export interface API { + /** + * Get a raw IPFS block + * + * @example + * ```js + * const block = await ipfs.block.get(cid) + * console.log(block.data) + * ``` + */ + get: (cid: CID | string | Uint8Array, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise + + /** + * Stores input as an IPFS block. + * + * **Note:** If you pass a `Block` instance as the block parameter, you + * don't need to pass options, as the block instance will carry the CID + * value as a property. + * + * @example + * ```js + * // Defaults + * const encoder = new TextEncoder() + * const decoder = new TextDecoder() + * + * const bytes = encoder.encode('a serialized object') + * const block = await ipfs.block.put(bytes) + * + * console.log(decoder.decode(block.data)) + * // Logs: + * // a serialized object + * console.log(block.cid.toString()) + * // Logs: + * // the CID of the object + * + * // With custom format and hashtype through CID + * const CID = require('cids') + * const another = encoder.encode('another serialized object') + * const cid = new CID(1, 'dag-pb', multihash) + * const block = await ipfs.block.put(another, cid) + * console.log(decoder.decode(block.data)) + * + * // Logs: + * // a serialized object + * console.log(block.cid.toString()) + * // Logs: + * // the CID of the object + * ``` + */ + put: (block: Block | Uint8Array, options?: PutOptions & OptionExtension) => Promise + + /** + * Remove one or more IPFS block(s) from the underlying block store + * + * @example + * ```js + * for await (const result of ipfs.block.rm(cid)) { + * if (result.error) { + * console.error(`Failed to remove block ${result.cid} due to ${result.error.message}`) + * } else { + * console.log(`Removed block ${result.cid}`) + * } + * } + * ``` + */ + rm: (cid: CID | CID[], options?: RmOptions & OptionExtension) => AsyncIterable + + /** + * Print information of a raw IPFS block + * + * @example + * ```js + * const cid = CID.from('QmQULBtTjNcMwMr4VMNknnVv3RpytrLSdgpvMcTnfNhrBJ') + * const stats = await ipfs.block.stat(cid) + * console.log(stats.cid.toString()) + * // Logs: QmQULBtTjNcMwMr4VMNknnVv3RpytrLSdgpvMcTnfNhrBJ + * console.log(stat.size) + * // Logs: 3739 + * ``` + */ + stat: (ipfsPath: IPFSPath, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise +} + +export interface PutOptions extends AbortOptions, PreloadOptions { + /** + * CID to store the block under - ignored if a Block is passed + */ + cid?: CID + + /** + * The codec to use to create the CID + */ + format?: CodecName + + /** + * Multihash hashing algorithm to use. (Defaults to 'sha2-256') + */ + mhtype?: HashName + + /** + * @deprecated + */ + mhlen?: any + + /** + * The version to use to create the CID + */ + version?: CIDVersion + + /** + * Pin this block when adding. (Defaults to `false`) + */ + pin?: boolean +} + +export interface RmOptions extends AbortOptions { + /** + * Ignores non-existent blocks + */ + force?: boolean, + + /** + * Do not return output if true + */ + quiet?: boolean +} + +export interface RmResult { + /** + * The CID of the removed block + */ + cid: CID + + /** + * Any error that occurred while trying to remove the block + */ + error?: Error +} + +export interface StatResult { + /** + * The CID of the block + */ + cid: CID + + /** + * The size of the block + */ + size: number +} diff --git a/packages/ipfs-core-types/src/bootstrap/index.ts b/packages/ipfs-core-types/src/bootstrap/index.ts new file mode 100644 index 0000000000..b9be74e76e --- /dev/null +++ b/packages/ipfs-core-types/src/bootstrap/index.ts @@ -0,0 +1,71 @@ +import type { AbortOptions } from '../utils' +import type Multiaddr from 'multiaddr' + +export interface API { + /** + * Add a peer address to the bootstrap list + * + * @example + * ```js + * const validIp4 = '/ip4/104....9z' + * + * const res = await ipfs.bootstrap.add(validIp4) + * console.log(res.Peers) + * // Logs: + * // ['/ip4/104....9z'] + * ``` + */ + add: (addr: Multiaddr, options?: AbortOptions & OptionExtension) => Promise<{ Peers: Multiaddr[] }> + + /** + * Reset the bootstrap list to contain only the default bootstrap nodes + * + * @example + * ```js + * const res = await ipfs.bootstrap.list() + * console.log(res.Peers) + * // Logs: + * // [address1, address2, ...] + * ``` + */ + reset: (options?: AbortOptions & OptionExtension) => Promise<{ Peers: Multiaddr[] }> + + /** + * List all peer addresses in the bootstrap list + * + * @example + * ```js + * const res = await ipfs.bootstrap.list() + * console.log(res.Peers) + * // Logs: + * // [address1, address2, ...] + * ``` + */ + list: (options?: AbortOptions & OptionExtension) => Promise<{ Peers: Multiaddr[] }> + + /** + * Remove a peer address from the bootstrap list + * + * @example + * ```js + * const res = await ipfs.bootstrap.list() + * console.log(res.Peers) + * // Logs: + * // [address1, address2, ...] + * ``` + */ + rm: (addr: Multiaddr, options?: AbortOptions & OptionExtension) => Promise<{ Peers: Multiaddr[] }> + + /** + * Remove all peer addresses from the bootstrap list + * + * @example + * ```js + * const res = await ipfs.bootstrap.clear() + * console.log(res.Peers) + * // Logs: + * // [address1, address2, ...] + * ``` + */ + clear: (options?: AbortOptions & OptionExtension) => Promise<{ Peers: Multiaddr[] }> +} diff --git a/packages/ipfs-core-types/src/config/index.d.ts b/packages/ipfs-core-types/src/config/index.d.ts new file mode 100644 index 0000000000..d5a543a9bf --- /dev/null +++ b/packages/ipfs-core-types/src/config/index.d.ts @@ -0,0 +1,125 @@ +import type { AbortOptions } from '../utils' +import { API as ProfilesAPI} from './profiles' + +export interface API { + /** + * Returns a value from the currently being used config. If the daemon + * is off, it returns the value from the stored config. + */ + get: (key: string, options?: AbortOptions & OptionExtension) => Promise + + /** + * Returns the full config been used. If the daemon is off, it returns the + * stored config + */ + getAll: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Adds or replaces a config value. Note that restarting the node will be + * necessary for any change to take effect. + */ + set: (key: string, value: any, options?: AbortOptions & OptionExtension) => Promise + + /** + * Replaces the full config. Note that restarting the node will be + * necessary for any change to take effect. + */ + replace: (config: Config, options?: AbortOptions & OptionExtension) => Promise + + profiles: ProfilesAPI +} + +export interface Config { + Addresses: AddressConfig + API?: APIConfig, + Profiles?: string + Bootstrap: string[] + Discovery: DiscoveryConfig + Datastore?: DatastoreConfig + Identity?: IdentityConfig + Keychain?: KeychainConfig + Pubsub?: PubsubConfig + Swarm?: SwarmConfig + Routing?: RoutingConfig +} + +/** + * Contains information about various listener addresses to be used by this node + */ +export interface AddressConfig { + API?: string + RPC?: string + Delegates?: string[] + Gateway?: string + Swarm: string[] +} + +export interface APIConfig { + HTTPHeaders?: Record +} + +export interface DiscoveryConfig { + MDNS: MDNSDiscovery + webRTCStar: WebRTCStarDiscovery +} + +export interface MDNSDiscovery { + Enabled?: boolean + Interval?: number +} + +export interface WebRTCStarDiscovery { + Enabled?: boolean +} + +export interface DatastoreConfig { + Spec?: DatastoreSpec +} + +export interface DatastoreSpec { + +} + +export interface IdentityConfig { + /** + * The unique PKI identity label for this configs peer. Set on init and never + * read, its merely here for convenience. IPFS will always generate the peerID + * from its keypair at runtime. + */ + PeerID: string + + /** + * The base64 encoded protobuf describing (and containing) the nodes private key. + */ + PrivateKey: string +} + +export interface KeychainConfig { + DEK?: DEK +} + +export interface DEK { + keyLength?: number + iterationCount?: number + salt?: string + hash?: string +} + +export interface PubsubConfig { + PubSubRouter?: 'gossipsub' | 'floodsub' + Enabled?: booleam +} + +export interface SwarmConfig { + ConnMgr?: ConnMgrConfig + DisableNatPortMap?: boolean +} + +export interface ConnMgrConfig { + LowWater?: number + HighWater?: number +} + +export interface RoutingConfig { + Type?: string +} diff --git a/packages/ipfs-core-types/src/config/profiles/index.d.ts b/packages/ipfs-core-types/src/config/profiles/index.d.ts new file mode 100644 index 0000000000..146a90aa1a --- /dev/null +++ b/packages/ipfs-core-types/src/config/profiles/index.d.ts @@ -0,0 +1,28 @@ +import type { AbortOptions } from '../../utils' + +export interface API { + /** + * List available config profiles + */ + list: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Apply a profile to the current config. Note that restarting the node + * will be necessary for any change to take effect. + */ + apply: (name: string, options?: ProfilesApplyOptions & OptionExtension) => Promise +} + +export interface Profile { + name: string + description: string +} + +export interface ProfilesApplyOptions extends AbortOptions { + dryRun?: boolean +} + +export interface ProfilesApplyResult { + original: object + updated: object +} diff --git a/packages/ipfs-core-types/src/dag/index.d.ts b/packages/ipfs-core-types/src/dag/index.d.ts new file mode 100644 index 0000000000..4214f55b6c --- /dev/null +++ b/packages/ipfs-core-types/src/dag/index.d.ts @@ -0,0 +1,227 @@ +import { AbortOptions, PreloadOptions, IPFSPath } from '../utils' +import CID from 'cids' +import { CodecName } from 'multicodec' +import { HashName } from 'multihashes' + +export interface API { + /** + * Retrieve an IPLD format node + * + * @example + * ```js + * // example obj + * const obj = { + * a: 1, + * b: [1, 2, 3], + * c: { + * ca: [5, 6, 7], + * cb: 'foo' + * } + * } + * + * const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha2-256' }) + * console.log(cid.toString()) + * // zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5 + * + * async function getAndLog(cid, path) { + * const result = await ipfs.dag.get(cid, { path }) + * console.log(result.value) + * } + * + * await getAndLog(cid, '/a') + * // Logs: + * // 1 + * + * await getAndLog(cid, '/b') + * // Logs: + * // [1, 2, 3] + * + * await getAndLog(cid, '/c') + * // Logs: + * // { + * // ca: [5, 6, 7], + * // cb: 'foo' + * // } + * + * await getAndLog(cid, '/c/ca/1') + * // Logs: + * // 6 + * ``` + */ + get: (cid: CID, options?: GetOptions & OptionExtension) => Promise + + /** + * Store an IPLD format node + * + * @example + * ```js + * const obj = { simple: 'object' } + * const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha3-512' }) + * + * console.log(cid.toString()) + * // zBwWX9ecx5F4X54WAjmFLErnBT6ByfNxStr5ovowTL7AhaUR98RWvXPS1V3HqV1qs3r5Ec5ocv7eCdbqYQREXNUfYNuKG + * ``` + */ + put: (node: any, options?: PutOptions & OptionExtension) => Promise + + /** + * Enumerate all the entries in a graph + * + * @example + * ```js + * // example obj + * const obj = { + * a: 1, + * b: [1, 2, 3], + * c: { + * ca: [5, 6, 7], + * cb: 'foo' + * } + * } + * + * const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha2-256' }) + * console.log(cid.toString()) + * // zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5 + * + * const result = await ipfs.dag.tree('zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5') + * console.log(result) + * // Logs: + * // a + * // b + * // b/0 + * // b/1 + * // b/2 + * // c + * // c/ca + * // c/ca/0 + * // c/ca/1 + * // c/ca/2 + * // c/cb + * ``` + */ + tree: (cid: CID, options?: TreeOptions & OptionExtension) => Promise + + /** + * Returns the CID and remaining path of the node at the end of the passed IPFS path + * + * @example + * ```JavaScript + * // example obj + * const obj = { + * a: 1, + * b: [1, 2, 3], + * c: { + * ca: [5, 6, 7], + * cb: 'foo' + * } + * } + * + * const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha2-256' }) + * console.log(cid.toString()) + * // bafyreicyer3d34cutdzlsbe2nqu5ye62mesuhwkcnl2ypdwpccrsecfmjq + * + * const result = await ipfs.dag.resolve(`${cid}/c/cb`) + * console.log(result) + * // Logs: + * // { + * // cid: CID(bafyreicyer3d34cutdzlsbe2nqu5ye62mesuhwkcnl2ypdwpccrsecfmjq), + * // remainderPath: 'c/cb' + * // } + * ``` + */ + resolve: (ipfsPath: IPFSPath, options?: ResolveOptions & OptionExtension) => Promise +} + +export interface GetOptions extends AbortOptions, PreloadOptions { + /** + * An optional path within the DAG to resolve + */ + path?: string + + /** + * If set to true, it will avoid resolving through different objects + */ + localResolve?: boolean +} + +export interface GetResult { + /** + * The value or node that was fetched during the get operation + */ + value: any + + /** + * The remainder of the Path that the node was unable to resolve or what was left in a localResolve scenario + */ + remainderPath?: string +} + +export interface PutOptions extends AbortOptions, PreloadOptions { + /** + * CID to store the value with + */ + cid?: CID + + /** + * The codec to use to create the CID (ignored if `cid` is passed) + */ + format?: CodecName + + /** + * Multihash hashing algorithm to use (ignored if `cid` is passed) + */ + hashAlg?: HashName + + /** + * The version to use to create the CID (ignored if `cid` is passed) + */ + version?: CIDVersion + + /** + * Pin this block when adding. (Defaults to `false`) + */ + pin?: boolean + + /** + * If true no blocks will be written to the underlying blockstore + */ + onlyHash?: boolean +} + +export interface RmOptions extends AbortOptions { + /** + * Ignores non-existent blocks + */ + force?: boolean +} + +export interface TreeOptions extends AbortOptions, PreloadOptions { + /** + * An optional path within the DAG to resolve + */ + path?: string + + /** + * If set to true, it will follow the links and continuously run tree on them, returning all the paths in the graph + */ + recursive?: boolean +} + +export interface ResolveOptions extends AbortOptions, PreloadOptions { + /** + * If ipfsPath is a CID, you may pass a path here + */ + path?: string +} + +export interface ResolveResult { + /** + * The last CID encountered during the traversal and the path to the end of the IPFS path inside the node referenced by the CID + */ + cid: CID + + /** + * The remainder of the Path that the node was unable to resolve + */ + remainderPath?: string +} \ No newline at end of file diff --git a/packages/ipfs-core-types/src/datastore.ts b/packages/ipfs-core-types/src/datastore.ts deleted file mode 100644 index 51e69384bc..0000000000 --- a/packages/ipfs-core-types/src/datastore.ts +++ /dev/null @@ -1,184 +0,0 @@ -import type { KeyValueStore, StoreBatch, StoreSelector, Resource } from './store' -export interface DataStore extends - KeyValueStore, - StoreSelector, - StoreBatch, - Resource { -} - -export interface Key { - /** - * Returns the "name" of this key (field of last namespace). - * - * @example - * ```js - * key.toString() - * // '/Comedy/MontyPython/Actor:JohnCleese' - * key.name() - * // 'JohnCleese' - * ``` - */ - name: () => string - - /** - * Returns the "type" of this key (value of last namespace). - * - * @example - * ```js - * key.toString() - * '/Comedy/MontyPython/Actor:JohnCleese' - * key.type() - * // 'Actor' - * ``` - */ - type: () => string - - /** - * Returns the `namespaces` making up this `Key`. - */ - namespaces: () => string[] - - /** - * Returns the "base" namespace of this key. - * - * @example - * ```js - * key.toString() - * // '/Comedy/MontyPython/Actor:JohnCleese' - * key.baseNamespace() - * // 'Actor:JohnCleese' - */ - baseNamespace: () => string - - /** - * Returns an "instance" of this type key (appends value to namespace). - * - * @example - * ```js - * key.toString() - * // '/Comedy/MontyPython/Actor' - * key.instance('JohnClesse').toString() - * // '/Comedy/MontyPython/Actor:JohnCleese' - * ``` - */ - instance: () => Key - - /** - * Returns the "path" of this key (parent + type). - * - * @example - * ```js - * key.toString() - * '/Comedy/MontyPython/Actor:JohnCleese' - * key.path().toString() - * // '/Comedy/MontyPython/Actor' - * ``` - */ - path: () => Key - - /** - * Returns the `parent` Key of this Key. - * - * @example - * ```js - * key.toString() - * "/Comedy/MontyPython/Actor:JohnCleese" - * key.parent().toString() - * // "/Comedy/MontyPython" - * ``` - */ - parent: () => Key - - /** - * Returns the `child` Key of this Key. - * - * @example - * ```js - * key.toString() - * '/Comedy/MontyPython' - * child.toString() - * // 'Actor:JohnCleese' - * key.child(child).toString() - * '/Comedy/MontyPython/Actor:JohnCleese' - * ``` - */ - child: (key: Key) => Key - - /** - * Check if the given key is sorted lower than this. - */ - less: (key: Key) => boolean - - /** - * Returns whether this key is a prefix of `other` - * - * @example - * ```js - * comedy.toString() - * '/Comedy' - * monty.toString() - * '/Comedy/MontyPython' - * comedy.isAncestorOf(monty) - * // true - * ``` - */ - isAncestorOf: (other: Key) => boolean - - /** - * Returns whether this key is a contains `other` as prefix. - * ```js - * comedy.toString() - * '/Comedy' - * monty.toString() - * '/Comedy/MontyPython' - * monty.isDecendantOf(comedy) - * // true - * ``` - */ - isDecendantOf: (other: Key) => boolean - - /** - * Returns wether this key has only one namespace. - */ - isTopLevel: () => boolean - - /** - * Returns the key with all parts in reversed order. - * - * @example - * ```js - * key.toString() - * // '/Comedy/MontyPython/Actor:JohnCleese' - * key.reverse().toString() - * // /Actor:JohnCleese/MontyPython/Comedy - * new Key('/Comedy/MontyPython/Actor:JohnCleese').reverse() - * ``` - */ - reverse: () => Key - - /** - * Concats one or more Keys into one new Key. - */ - concat: (...keys: Key[]) => Key - - /** - * Returns the array representation of this key. - * - * @example - * ```js - * key.toString() - * // '/Comedy/MontyPython/Actor:JohnCleese' - * key.list() - * // ['Comedy', 'MontyPythong', 'Actor:JohnCleese'] - * ``` - */ - list: () => string[] - toString: () => string -} - -export type Value = Uint8Array - -export interface Entry { - key: Key - value: Value -} diff --git a/packages/ipfs-core-types/src/dht/index.d.ts b/packages/ipfs-core-types/src/dht/index.d.ts new file mode 100644 index 0000000000..1e1db25d50 --- /dev/null +++ b/packages/ipfs-core-types/src/dht/index.d.ts @@ -0,0 +1,94 @@ +import type { AbortOptions } from '../utils' +import type Multiaddr from 'multiaddr' +import type CID from 'cids' + +export interface API { + /** + * Query the DHT for all multiaddresses associated with a `PeerId`. + * + * @example + * ```js + * const info = await ipfs.dht.findPeer('QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt') + * + * console.log(info.id) + * // QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt + * + * info.addrs.forEach(addr => console.log(addr.toString())) + * // '/ip4/147.75.94.115/udp/4001/quic' + * // '/ip6/2604:1380:3000:1f00::1/udp/4001/quic' + * // '/dnsaddr/bootstrap.libp2p.io' + * // '/ip6/2604:1380:3000:1f00::1/tcp/4001' + * // '/ip4/147.75.94.115/tcp/4001' + * ``` + */ + findPeer: (peerId: CID | string, options?: AbortOptions & OptionExtension) => Promise + + /** + * Find peers in the DHT that can provide a specific value, given a CID. + * + * @example + * ```js + * const providers = ipfs.dht.findProvs('QmdPAhQRxrDKqkGPvQzBvjYe3kU8kiEEAd2J6ETEamKAD9') + * for await (const provider of providers) { + * console.log(provider.id.toString()) + * } + * ``` + */ + findProvs: (cid: CID, options?: DHTFindProvsOptions & OptionExtension) => AsyncIterable + + /** + * Given a key, query the DHT for its best value. + */ + get: (key: Uint8Array, options?: AbortOptions & OptionExtension) => Promise + + /** + * Announce to the network that we are providing given values. + */ + provide: (cid: CID | CID[], options?: DHTProvideOptions & OptionExtension) => AsyncIterable + + /** + * Write a key/value pair to the DHT. + * + * Given a key of the form /foo/bar and a value of any + * form, this will write that value to the DHT with + * that key. + * + */ + put: (key: Uint8Array, value: Uint8Array, options?: AbortOptions & OptionExtension) => AsyncIterable + + /** + * Find the closest peers to a given `PeerId`, by querying the DHT. + */ + query: (peerId: CID | string, options?: AbortOptions & OptionExtension) => AsyncIterable +} + +export interface PeerResult { + id: string + addrs: Multiaddr[] +} + +export interface DHTFindProvsOptions extends AbortOptions { + numProviders?: number +} + +export interface DHTProvideOptions extends AbortOptions { + recursive?: boolean +} + +export enum QueryEventType { + SendingQuery = 1, + PeerResponse, + FinalPeer, + QueryError, + Provider, + Value, + AddingPeer, + DialingPeer +} + +export interface DHTQueryMessage { + extra: string + id: string + responses: PeerResult[] + type: QueryEventType +} diff --git a/packages/ipfs-core-types/src/diag/index.d.ts b/packages/ipfs-core-types/src/diag/index.d.ts new file mode 100644 index 0000000000..9af9fdc0e5 --- /dev/null +++ b/packages/ipfs-core-types/src/diag/index.d.ts @@ -0,0 +1,16 @@ +import type { AbortOptions } from '../utils' + +export interface API { + cmds: (options?: AbortOptions & OptionExtension) => Promise + net: (options?: AbortOptions & OptionExtension) => Promise + sys: (options?: AbortOptions & OptionExtension) => Promise +} + +export interface CmdsResult { + active: boolean + args: string[] + endTime: Date + id: string + options: Record + startTime: Date +} diff --git a/packages/ipfs-core-types/src/files.ts b/packages/ipfs-core-types/src/files.ts deleted file mode 100644 index e9f45c7d5b..0000000000 --- a/packages/ipfs-core-types/src/files.ts +++ /dev/null @@ -1,172 +0,0 @@ -import CID from 'cids' -import { AwaitIterable } from './basic' - -export type Entry|Blob> = - | FileEntry - | DirectoryEntry - -export interface BaseEntry { - path: string - mode?: Mode - mtime?: MTime -} -export interface FileEntry |Blob> extends BaseEntry { - content?: Content -} - -export interface DirectoryEntry extends BaseEntry { - content?: undefined -} - -export type ImportSource = -| AwaitIterable -| ReadableStream - -export type ToEntry = - | ToFile - | ToDirectory - | ToContent - -export interface ToFile extends ToFileMetadata { - path?: string - content: ToContent -} - -export interface ToDirectory extends ToFileMetadata { - path: string - content?: undefined -} - -export interface ToFileMetadata { - mode?: ToMode - mtime?: ToMTime -} - -/** - * File content in arbitrary (supported) represenation. It is used in input - * positions and is usually normalized to `Blob` in browser contexts and - * `AsyncIterable` in node. - */ -export type ToContent = - | string - | InstanceType - | ArrayBufferView - | ArrayBuffer - | Blob - | AwaitIterable - | ReadableStream - -/** - * Timestamp representation in arbitrary (supported) in representations. It is - * used in input positions and usurally get's normalised to `MTime` before use. - */ -export type ToMTime = - | Date - | HRTime - | MTimeLike - -export type ToMode = - | string - | number - -export interface File { - readonly type: 'file' - readonly cid: CID - readonly name: string - - /** - * File path - */ - readonly path: string - /** - * File content - */ - readonly content?: AsyncIterable - mode?: Mode - mtime?: MTime - size?: number - depth?: number -} - -export interface Directory { - type: 'dir' - cid: CID - name: string - /** - * Directory path - */ - path: string - mode?: Mode - mtime?: MTime - size?: number - depth?: number -} - -export type IPFSEntry = File | Directory - -export interface BaseFile { - cid: CID - path: string - name: string -} - -export interface InputFile extends BaseFile { - unixfs: undefined -} - -export interface UnixFSFile extends BaseFile { - content: () => AsyncIterable - unixfs: UnixFS -} - -export interface UnixFSEntry { - path: string - cid: CID - mode: Mode - mtime: MTime - size: number -} - -export interface MTime { - /** - * The number of seconds since(positive) or before (negative) the Unix Epoch - * began. - */ - readonly secs: number - - /** - * The number of nanoseconds since the last full second - */ - readonly nsecs: number -} - -export interface MTimeLike { - /** - * The number of seconds since(positive) or before (negative) the Unix Epoch - * began. - */ - secs: number - - /** - * The number of nanoseconds since the last full second - */ - nsecs?: number -} - -interface UnixFS { - readonly type: 'directory' | 'file' | 'dir' - readonly mode: Mode - readonly mtime: MTime - - fileSize: () => number - content: () => AsyncIterable -} - -/** - * Time representation as tuple of two integers, as per the output of - * [`process.hrtime()`](https://nodejs.org/dist/latest/docs/api/process.html#process_process_hrtime_time). - */ -type HRTime = [number, number] - -// It's just a named type alias, but it better captures intent. -export type Mode = number diff --git a/packages/ipfs-core-types/src/files/index.d.ts b/packages/ipfs-core-types/src/files/index.d.ts new file mode 100644 index 0000000000..ac735b0d83 --- /dev/null +++ b/packages/ipfs-core-types/src/files/index.d.ts @@ -0,0 +1,498 @@ +import { AbortOptions, IPFSPath } from '../utils' +import { ToMTime } from './files' +import CID, { CIDVersion } from 'cids' +import { CodecName } from 'multicodec' +import { HashName } from 'multihashes' +import { Mtime } from 'ipfs-unixfs' +import type { AddProgressFn } from '../root' + +export interface API { + /** + * Change mode for files and directories + * + * @example + * ```js + * // To give a file -rwxrwxrwx permissions + * await ipfs.files.chmod('/path/to/file.txt', parseInt('0777', 8)) + * + * // Alternatively + * await ipfs.files.chmod('/path/to/file.txt', '+rwx') + * + * // You can omit the leading `0` too + * await ipfs.files.chmod('/path/to/file.txt', '777') + * ``` + */ + chmod: (path: string, mode: number | string, options?: ChmodOptions & OptionExtension) => Promise + + /** + * Copy files from one location to another + * + * - If from has multiple values then to must be a directory. + * - If from has a single value and to exists and is a directory, from will be copied into to. + * - If from has a single value and to exists and is a file, from must be a file and the contents of to will be replaced with the contents of from otherwise an error will be returned. + * - If from is an IPFS path, and an MFS path exists with the same name, the IPFS path will be chosen. + * - If from is an IPFS path and the content does not exist in your node's repo, only the root node of the source file with be retrieved from the network and linked to from the destination. The remainder of the file will be retrieved on demand. + * + * @example + * ```js + * // To copy a file +* await ipfs.files.cp('/src-file', '/dst-file') +* +* // To copy a directory +* await ipfs.files.cp('/src-dir', '/dst-dir') +* +* // To copy multiple files to a directory +* await ipfs.files.cp('/src-file1', '/src-file2', '/dst-dir') + * ``` + */ + cp: (from: IPFSPath | IPFSPath[], to: string, options?: CpOptions & OptionExtension) => Promise + + /** + * Make a directory in your MFS + */ + mkdir: (path: string, options?: MkdirOptions & OptionExtension) => Promise + + /** + * Get file or directory statistics + */ + stat: (ipfsPath: IPFSPath, options?: StatOptions & OptionExtension) => Promise + + /** + * Update the mtime of a file or directory + * + * @example + * ```js + * // set the mtime to the current time + * await ipfs.files.touch('/path/to/file.txt') + * + * // set the mtime to a specific time + * await ipfs.files.touch('/path/to/file.txt', { + * mtime: new Date('May 23, 2014 14:45:14 -0700') + * }) + * ``` + */ + touch: (ipfsPath: string, options?: TouchOptions & OptionExtension) => Promise + + /** + * Remove a file or directory + * + * @example + * ```js + * // To remove a file + * await ipfs.files.rm('/my/beautiful/file.txt') + * + * // To remove multiple files + * await ipfs.files.rm('/my/beautiful/file.txt', '/my/other/file.txt') + * + * // To remove a directory + * await ipfs.files.rm('/my/beautiful/directory', { recursive: true }) + * ``` + */ + rm: (ipfsPaths: string | string[], options?: RmOptions & OptionExtension) => Promise + + /** + * Read a file + * + * @example + * ```js + * const chunks = [] + * + * for await (const chunk of ipfs.files.read('/hello-world')) { + * chunks.push(chunk) + * } + * + * console.log(uint8ArrayConcat(chunks).toString()) + * // Hello, World! + * ``` + */ + read: (ipfsPath: IPFSPath, options?: ResolveOptions & OptionExtension) => AsyncIterable + + /** + * Write to an MFS path + * + * @example + * ```js + * await ipfs.files.write('/hello-world', new TextEncoder().encode('Hello, world!')) + * ``` + */ + write: (ipfsPath: string, content: string | Uint8Array | Blob | AsyncIterable | Iterable, options?: WriteOptions & OptionExtension) => Promise + + /** + * Move files from one location to another + * + * - If from has multiple values then to must be a directory. + * - If from has a single value and to exists and is a directory, from will be moved into to. + * - If from has a single value and to exists and is a file, from must be a file and the contents of to will be replaced with the contents of from otherwise an error will be returned. + * - If from is an IPFS path, and an MFS path exists with the same name, the IPFS path will be chosen. + * - If from is an IPFS path and the content does not exist in your node's repo, only the root node of the source file with be retrieved from the network and linked to from the destination. The remainder of the file will be retrieved on demand. + * - All values of from will be removed after the operation is complete unless they are an IPFS path. + * + * @example + * ```js + * await ipfs.files.mv('/src-file', '/dst-file') + * + * await ipfs.files.mv('/src-dir', '/dst-dir') + * + * await ipfs.files.mv('/src-file1', '/src-file2', '/dst-dir') + * ``` + */ + mv: (from: string | string[], to: string, options?: MvOptions & OptionExtension) => Promise + + /** + * Flush a given path's data to the disk + * + * @example + * ```js + * const cid = await ipfs.files.flush('/') + * ``` + */ + flush: (ipfsPath: string, options?: AbortOptions & OptionExtension) => Promise + + /** + * List directories in the local mutable namespace + * + * @example + * ```js + * for await (const file of ipfs.files.ls('/screenshots')) { + * console.log(file.name) + * } + * // 2018-01-22T18:08:46.775Z.png + * // 2018-01-22T18:08:49.184Z.png + * ``` + */ + ls: (ipfsPath: IPFSPath, options?: AbortOptions & OptionExtension) => AsyncIterable +} + +export interface MFSEntry { + /** + * The object's name + */ + name: string + + /** + * The object's type (directory or file) + */ + type: 'directory' | 'file' + + /** + * The size of the file in bytes + */ + size: number + + /** + * The CID of the object + */ + cid: CID + + /** + * The UnixFS mode as a Number + */ + mode?: number + + /** + * An object with numeric secs and nsecs properties + */ + mtime?: Mtime +} + +export interface MFSOptions { + /** + * If true the changes will be immediately flushed to disk + */ + flush?: boolean +} + +export interface ChmodOptions extends MFSOptions, AbortOptions { + /** + * If true mode will be applied to the entire tree under path + */ + recursive?: boolean + + /** + * The hash algorithm to use for any updated entries + */ + hashAlg?: HashName + + /** + * The CID version to use for any updated entries + */ + cidVersion?: CIDVersion + + /** + * The threshold for splitting any modified folders into HAMT shards + */ + shardSplitThreshold?: number +} + +export interface CpOptions extends MFSOptions, AbortOptions { + /** + * The value or node that was fetched during the get operation + */ + parents?: boolean + + /** + * The hash algorithm to use for any updated entries + */ + hashAlg?: HashName + + /** + * The CID version to use for any updated entries + */ + cidVersion?: CIDVersion + + /** + * The threshold for splitting any modified folders into HAMT shards + */ + shardSplitThreshold?: number +} + +export interface MkdirOptions extends MFSOptions, AbortOptions { + /** + * If true, create intermediate directories + */ + parents?: boolean + + /** + * An integer that represents the file mode + */ + mode?: number + + /** + * A Date object, an object with { secs, nsecs } properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of process.hrtime() + */ + mtime?: ToMTime + + /** + * The hash algorithm to use for any updated entries + */ + hashAlg?: HashName + + /** + * The CID version to use for any updated entries + */ + cidVersion?: CIDVersion + + /** + * The threshold for splitting any modified folders into HAMT shards + */ + shardSplitThreshold?: number +} + +export interface StatOptions extends AbortOptions { + /** + * If true, return only the CID + */ + hash?: boolean + + /** + * If true, return only the size + */ + size?: boolean + + /** + * If true, compute the amount of the DAG that is local and if possible the total size + */ + withLocal?: boolean +} + +export interface StatResult { + /** + * A CID instance + */ + cid: CID + + /** + * The file size in Bytes + */ + size: number + + /** + * The size of the DAGNodes making up the file in Bytes + */ + cumulativeSize: number + + /** + * Either directory or file + */ + type: 'directory' | 'file' + + /** + * If type is directory, this is the number of files in the directory. If it is file it is the number of blocks that make up the file + */ + blocks: number + + /** + * Indicates if locality information is present + */ + withLocality: boolean + + /** + * Indicates if the queried dag is fully present locally + */ + local?: boolean + + /** + * Indicates the cumulative size of the data present locally + */ + sizeLocal?: number + + /** + * UnixFS mode if applicable + */ + mode?: number + + /** + * UnixFS mtime if applicable + */ + mtime?: Mtime +} + +export interface TouchOptions extends MFSOptions, AbortOptions { + /** + * A Date object, an object with { secs, nsecs } properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of process.hrtime() + */ + mtime?: ToMTime + + /** + * The hash algorithm to use for any updated entries + */ + hashAlg?: HashName + + /** + * The CID version to use for any updated entries + */ + cidVersion?: CIDVersion + + /** + * The threshold for splitting any modified folders into HAMT shards + */ + shardSplitThreshold?: number +} + +export interface RmOptions extends MFSOptions, AbortOptions { + /** + * If true all paths under the specifed path(s) will be removed + */ + recursive?: boolean + + /** + * The hash algorithm to use for any updated entries + */ + hashAlg?: HashName + + /** + * The CID version to use for any updated entries + */ + cidVersion?: CIDVersion + + /** + * The threshold for splitting any modified folders into HAMT shards + */ + shardSplitThreshold?: number +} + +export interface ReadOptions extends AbortOptions { + /** + * An offset to start reading the file from + */ + offset?: number + + /** + * An optional max length to read from the file + */ + length?: number +} + +export interface WriteOptions extends MFSOptions, AbortOptions { + /** + * An offset within the file to start writing at + */ + offset?: number + + /** + * Optionally limit how many bytes are written + */ + length?: number + + /** + * Create the MFS path if it does not exist + */ + create?: boolean + + /** + * Create intermediate MFS paths if they do not exist + */ + parents?: boolean + + /** + * Truncate the file at the MFS path if it would have been larger than the passed content + */ + truncate?: boolean + + /** + * If true, DAG leaves will contain raw file data and not be wrapped in a protobuf + */ + rawLeaves?: boolean + + /** + * An integer that represents the file mode + */ + mode?: number + + /** + * A Date object, an object with { secs, nsecs } properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of process.hrtime() + */ + mtime?: ToMTime + + /** + * The hash algorithm to use for any updated entries + */ + hashAlg?: HashName + + /** + * The CID version to use for any updated entries + */ + cidVersion?: CIDVersion + + /** + * The threshold for splitting any modified folders into HAMT shards + */ + shardSplitThreshold?: number + + /** + * If writing a file and only a single leaf would be present, store the file data in the root node + */ + reduceSingleLeafToSelf?: boolean + + /** + * What sort of DAG structure to create + */ + strategy?: 'balanced' | 'trickle' + + /** + * Callback to be notified of write progress + */ + progress?: AddProgressFn +} + +export interface MvOptions extends MFSOptions, AbortOptions { + /** + * Create intermediate MFS paths if they do not exist + */ + parents?: boolean + + /** + * The hash algorithm to use for any updated entries + */ + hashAlg?: HashName + + /** + * The CID version to use for any updated entries + */ + cidVersion?: CIDVersion + + /** + * The threshold for splitting any modified folders into HAMT shards + */ + shardSplitThreshold?: number +} diff --git a/packages/ipfs-core-types/src/index.d.ts b/packages/ipfs-core-types/src/index.d.ts new file mode 100644 index 0000000000..edfa19e338 --- /dev/null +++ b/packages/ipfs-core-types/src/index.d.ts @@ -0,0 +1,53 @@ +import { API as RootAPI } from './root' +import { API as BitswapAPI } from './bitswap' +import { API as BlockAPI } from './block' +import { API as BootstrapAPI } from './bootstrap' +import { API as ConfigAPI } from './config' +import { API as DAGAPI } from './dag' +import { API as DHTAPI } from './dht' +import { API as DiagAPI } from './diag' +import { API as FilesAPI } from './files' +import { API as KeyAPI } from './key' +import { API as LogAPI } from './log' +import { API as NameAPI } from './name' +import { API as ObjectAPI } from './object' +import { API as PinAPI } from './pin' +import { API as PubsubAPI } from './pubsub' +import { Refs, Local } from './refs' +import { API as RepoAPI } from './repo' +import { API as StatsAPI } from './stats' +import { API as SwarmAPI } from './swarm' +import { AbortOptions, Await, AwaitIterable } from './utils' + +interface RefsAPI extends Refs { + local: Local +} + +export interface IPFS extends RootAPI { + bitswap: BitswapAPI + block: BlockAPI + bootstrap: BootstrapAPI + config: ConfigAPI + dag: DAGAPI + dht: DHTAPI + diag: DiagAPI + files: FilesAPI + key: KeyAPI + log: LogAPI + name: NameAPI + object: ObjectAPI + pin: PinAPI + pubsub: PubsubAPI + refs: RefsAPI + repo: RepoAPI + stats: StatsAPI + swarm: SwarmAPI +} + +export type { + IPFS, + + AbortOptions, + Await, + AwaitIterable +} diff --git a/packages/ipfs-core-types/src/index.ts b/packages/ipfs-core-types/src/index.ts deleted file mode 100644 index b1898affd0..0000000000 --- a/packages/ipfs-core-types/src/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { RootAPI } from './root' -import { AbortOptions, Await, AwaitIterable } from './basic' - -export type { - RootAPI, - - AbortOptions, - Await, - AwaitIterable -} diff --git a/packages/ipfs-core-types/src/ipld.ts b/packages/ipfs-core-types/src/ipld.ts deleted file mode 100644 index c15adceb82..0000000000 --- a/packages/ipfs-core-types/src/ipld.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { BlockService } from './block-service' -import CID from 'cids' -import { Await, AwaitIterable, AbortOptions } from './basic' -import { StoreReader, StoreExporter, StoreEraser } from './store' -import { ResolveResult, Format } from './ipld/format' - -export interface IPLD extends - StoreReader, - StoreExporter, - StoreEraser { - put: (value: T, format: FormatCode, options?: PutOptions & AbortOptions) => Await - putMany: (values: AwaitIterable, format: FormatCode, options?: PutOptions) => AwaitIterable - - resolve: (cid: CID, path: string, options?: AbortOptions) => AwaitIterable> - tree: (cid: CID, path?: string, options?: TreeOptions & AbortOptions) => AwaitIterable - - addFormat: (format: Format) => IPLD - removeFormat: (format: Format) => IPLD - - defaultOptions: Options -} - -export type FormatCode = number -export type HashAlg = number - -export interface Options { - blockService?: BlockService - formats?: Record - - loadFormat?: (code: number|string) => Promise> -} - -export interface PutOptions { - hashAlg?: HashAlg - cidVersion?: 0|1 - onlyHash?: boolean - -} - -export interface TreeOptions { - recursive?: boolean -} diff --git a/packages/ipfs-core-types/src/ipld/format.ts b/packages/ipfs-core-types/src/ipld/format.ts deleted file mode 100644 index 6a459b8634..0000000000 --- a/packages/ipfs-core-types/src/ipld/format.ts +++ /dev/null @@ -1,42 +0,0 @@ - -import CID from 'cids' -import { Await } from '../basic' - -export interface Format { - util: Util - resolver: Resolver - - defaultHashArg: string | number - codec: string | number -} - -export interface Util { - /** - * Serialize an IPLD Node into a binary blob. - */ - serialize: (node: T) => Uint8Array - /** - * Deserialize a binary blob into an IPLD Node. - */ - deserialize: (bytes: Uint8Array) => T - - /** - * Calculate the CID of the binary blob. - */ - cid: (bytes: Uint8Array, options?: CIDOptions) => Await -} - -export interface CIDOptions { - cidVersion?: number - hashAlg?: number | string -} - -export interface Resolver { - resolve: (bytes: Uint8Array, path: string) => ResolveResult - tree: (byte: Uint8Array) => string[] -} - -export interface ResolveResult { - value: T - remainderPath: string -} diff --git a/packages/ipfs-core-types/src/key/index.d.ts b/packages/ipfs-core-types/src/key/index.d.ts new file mode 100644 index 0000000000..fa1f5f213e --- /dev/null +++ b/packages/ipfs-core-types/src/key/index.d.ts @@ -0,0 +1,126 @@ +import type { AbortOptions } from '../utils' + +export interface API { + /** + * Generate a new key + * + * @example + * ```js + * const key = await ipfs.key.gen('my-key', { + * type: 'rsa', + * size: 2048 + * }) + * + * console.log(key) + * // { id: 'QmYWqAFvLWb2G5A69JGXui2JJXzaHXiUEmQkQgor6kNNcJ', + * // name: 'my-key' } + * ``` + */ + gen: (name: string, options?: GenOptions & OptionExtension) => Promise + + /** + * List all the keys + * + * @example + * ```js + * const keys = await ipfs.key.list() + * + * console.log(keys) + * // [ + * // { id: 'QmTe4tuceM2sAmuZiFsJ9tmAopA8au71NabBDdpPYDjxAb', + * // name: 'self' }, + * // { id: 'QmWETF5QvzGnP7jKq5sPDiRjSM2fzwzNsna4wSBEzRzK6W', + * // name: 'my-key' } + * // ] + * ``` + */ + list: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Remove a key + * + * @example + * ```js + * const key = await ipfs.key.rm('my-key') + * + * console.log(key) + * // { id: 'QmWETF5QvzGnP7jKq5sPDiRjSM2fzwzNsna4wSBEzRzK6W', + * // name: 'my-key' } + * ``` + */ + rm: (name: string, options?: AbortOptions & OptionExtension) => Promise + + /** + * Rename a key + * + * @example + * ```js + * const key = await ipfs.key.rename('my-key', 'my-new-key') + * + * console.log(key) + * // { id: 'Qmd4xC46Um6s24MradViGLFtMitvrR4SVexKUgPgFjMNzg', + * // was: 'my-key', + * // now: 'my-new-key', + * // overwrite: false } + * ``` + */ + rename: (oldName: string, newName: string, options?: AbortOptions & OptionExtension) => Promise + + /** + * Remove a key + * + * @example + * ```js + * const pem = await ipfs.key.export('self', 'password') + * + * console.log(pem) + * // -----BEGIN ENCRYPTED PRIVATE KEY----- + * // MIIFDTA/BgkqhkiG9w0BBQ0wMjAaBgkqhkiG9w0BBQwwDQQIpdO40RVyBwACAWQw + * // ... + * // YA== + * // -----END ENCRYPTED PRIVATE KEY----- + * ``` + */ + export: (name: string, password: string, options?: AbortOptions & OptionExtension) => Promise + + /** + * Remove a key + * + * @example + * ```js + * const key = await ipfs.key.import('clone', pem, 'password') + * + * console.log(key) + * // { id: 'QmQRiays958UM7norGRQUG3tmrLq8pJdmJarwYSk2eLthQ', + * // name: 'clone' } + * ``` + */ + import: (name: string, pem: string, password: string, options?: AbortOptions & OptionExtension) => Promise + + /** + * Return the id and name of a key + * + * * @example + * ```js + * const { id, name } = await ipfs.key.info('key-name') + * ``` + */ + info: (name: string, options?: AbortOptions & OptionExtension) => Promise +} + +export interface GenOptions extends AbortOptions { + type: string + size: number +} + +export interface Key { + id: string + name: string +} + +export interface RenameKeyResult { + id: string + was: string + now: string + overwrite: boolean +} diff --git a/packages/ipfs-core-types/src/log/index.d.ts b/packages/ipfs-core-types/src/log/index.d.ts new file mode 100644 index 0000000000..a1adef8550 --- /dev/null +++ b/packages/ipfs-core-types/src/log/index.d.ts @@ -0,0 +1,7 @@ +import type { AbortOptions } from '../utils' + +export interface API { + level: (subsystem: string, level: string, options?: AbortOptions & OptionExtension) => Promise + ls: (options?: AbortOptions & OptionExtension) => Promise + tail: (options?: AbortOptions & OptionExtension) => AsyncIterable +} diff --git a/packages/ipfs-core-types/src/name/index.d.ts b/packages/ipfs-core-types/src/name/index.d.ts new file mode 100644 index 0000000000..ab71f8d3d9 --- /dev/null +++ b/packages/ipfs-core-types/src/name/index.d.ts @@ -0,0 +1,94 @@ +import CID from 'cids'; +import type { AbortOptions } from '../utils' +import type { API as PubsubAPI } from './pubsub' + +export interface API { + /** + * IPNS is a PKI namespace, where names are the hashes of public keys, and + * the private key enables publishing new (signed) values. In both publish + * and resolve, the default name used is the node's own PeerID, + * which is the hash of its public key. + * + * @example + * ```js + * // The address of your files. + * const addr = '/ipfs/QmbezGequPwcsWo8UL4wDF6a8hYwM1hmbzYv2mnKkEWaUp' + * const res = await ipfs.name.publish(addr) + * // You now have a res which contains two fields: + * // - name: the name under which the content was published. + * // - value: the "real" address to which Name points. + * console.log(`https://gateway.ipfs.io/ipns/${res.name}`) + * ``` + */ + publish: (value: CID | string, options?: PublishOptions & OptionExtension) => Promise + + /** + * Given a key, query the DHT for its best value. + * + * @example + * ```js + * // The IPNS address you want to resolve. + * const addr = '/ipns/ipfs.io' + * + * for await (const name of ipfs.name.resolve(addr)) { + * console.log(name) + * } + * // Logs: /ipfs/QmQrX8hka2BtNHa8N8arAq16TCVx5qHcb46c5yPewRycLm + * ``` + */ + resolve: (value: string, options?: ResolveOptions & OptionExtension) => AsyncIterable + + pubsub: PubsubAPI +} + +export interface PublishOptions extends AbortOptions { + /** + * Resolve given path before publishing + */ + resolve?: boolean + /** + * Time duration of the record + */ + lifetime?: string + /** + * Time duration this record should be cached + */ + ttl?: string + /** + * Name of the key to be used + */ + key?: string + /** + * When offline, save the IPNS record + * to the the local datastore without broadcasting to the network instead of + * simply failing. + * + * This option is not yet implemented in js-ipfs. See tracking issue [ipfs/js-ipfs#1997] + * (https://github.com/ipfs/js-ipfs/issues/1997). + */ + allowOffline?: boolean +} + +export interface PublishResult { + /** + * The published IPNS name + */ + name: string + + /** + * The IPNS record + */ + value: string +} + +export interface ResolveOptions extends AbortOptions { + /** + * resolve until the result is not an IPNS name + */ + recursive?: boolean + + /** + * do not use cached entries + */ + nocache?: boolean +} diff --git a/packages/ipfs-core-types/src/name/pubsub/index.d.ts b/packages/ipfs-core-types/src/name/pubsub/index.d.ts new file mode 100644 index 0000000000..2d262891f7 --- /dev/null +++ b/packages/ipfs-core-types/src/name/pubsub/index.d.ts @@ -0,0 +1,49 @@ +import CID from 'cids'; +import type { AbortOptions } from '../../utils' + +export interface API { + /** + * Cancel a name subscription. + * + * @example + * ```js + * const name = 'QmQrX8hka2BtNHa8N8arAq16TCVx5qHcb46c5yPewRycLm' + * const result = await ipfs.name.pubsub.cancel(name) + * console.log(result.canceled) + * // Logs: true + * ``` + */ + cancel: (name: string, options?: AbortOptions & OptionExtension) => Promise + + /** + * Query the state of IPNS pubsub. + * + * @returns {Promise<{ enabled: boolean }>} + * ```js + * const result = await ipfs.name.pubsub.state() + * console.log(result.enabled) + * // Logs: true + * ``` + */ + state: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Show current name subscriptions. + * + * @example + * ```js + * const result = await ipfs.name.pubsub.subs() + * console.log(result) + * // Logs: ['/ipns/QmQrX8hka2BtNHa8N8arAq16TCVx5qHcb46c5yPewRycLm'] + * ``` + */ + subs: (options?: AbortOptions & OptionExtension) => Promise +} + +export interface PubsubCancelResult { + canceled: boolean +} + +export interface PubsubStateResult { + enabled: boolean +} diff --git a/packages/ipfs-core-types/src/object/index.d.ts b/packages/ipfs-core-types/src/object/index.d.ts new file mode 100644 index 0000000000..2a1206e095 --- /dev/null +++ b/packages/ipfs-core-types/src/object/index.d.ts @@ -0,0 +1,34 @@ +import CID from 'cids'; +import type { AbortOptions, PreloadOptions } from '../utils' +import type { DAGNode, DAGNodeLike, DAGLink } from 'ipld-dag-pb' +import type { API as PatchAPI } from './patch' + +export interface API { + new: (options?: NewObjectOptions & OptionExtension) => Promise + put: (obj: DAGNode | DAGNodeLike | Uint8Array, options?: PutOptions & OptionExtension) => Promise + get: (cid: CID, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise + data: (cid: CID, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise + links: (cid, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise + stat: (cid, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise + + patch: PatchAPI +} + +export interface NewObjectOptions extends AbortOptions, PreloadOptions { + template?: 'unixfs-dir' +} + +export interface PutOptions extends AbortOptions, PreloadOptions { + enc?: PutEncoding +} + +export interface StatResult { + Hash: string + NumLinks: number + BlockSize: number + LinksSize: number + DataSize: number + CumulativeSize: number +} + +export type PutEncoding = 'json' | 'protobuf' \ No newline at end of file diff --git a/packages/ipfs-core-types/src/object/patch/index.d.ts b/packages/ipfs-core-types/src/object/patch/index.d.ts new file mode 100644 index 0000000000..4d38c0a05a --- /dev/null +++ b/packages/ipfs-core-types/src/object/patch/index.d.ts @@ -0,0 +1,10 @@ +import type CID from 'cids'; +import type { AbortOptions } from '../../utils' +import type { DAGLink } from 'ipld-dag-pb' + +export interface API { + addLink: (cid: CID, link: DAGLink, options?: AbortOptions & OptionExtension) => Promise + rmLink: (cid: CID, link: DAGLink | string, options?: AbortOptions & OptionExtension) => Promise + appendData: (cid: CID, data: Uint8Array, options?: AbortOptions & OptionExtension) => Promise + setData: (cid: CID, data: Uint8Array, options?: AbortOptions & OptionExtension) => Promise +} diff --git a/packages/ipfs-core-types/src/pin/index.d.ts b/packages/ipfs-core-types/src/pin/index.d.ts new file mode 100644 index 0000000000..378996b305 --- /dev/null +++ b/packages/ipfs-core-types/src/pin/index.d.ts @@ -0,0 +1,175 @@ +import type { AbortOptions, AwaitIterable } from '../utils' +import type CID from 'cids' +import type { API as remote } from './remote' + +export interface API { + /** + * Adds an IPFS block to the pinset and also stores it to the IPFS + * repo. pinset is the set of hashes currently pinned (not gc'able) + * + * @example + * ```js + * const cid = CID.from('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') + * const pinned of ipfs.pin.add(cid)) + * console.log(pinned) + * // Logs: + * // CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') + * ``` + */ + add: (cid: string | CID, options?: AddOptions & OptionExtension) => Promise + + /** + * Adds multiple IPFS blocks to the pinset and also stores it to the IPFS + * repo. pinset is the set of hashes currently pinned (not gc'able) + * + * @example + * ```js + * const cid = CID.from('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') + * for await (const cid of ipfs.pin.addAll([cid])) { + * console.log(cid) + * } + * // Logs: + * // CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') + * ``` + */ + addAll: (source: AwaitIterable, options?: AddAllOptions & OptionExtension) => AsyncIterable + + /** + * List all the objects pinned to local storage + * + * @example + * ```js + * for await (const { cid, type } of ipfs.pin.ls()) { + * console.log({ cid, type }) + * } + * // { cid: CID(Qmc5XkteJdb337s7VwFBAGtiaoj2QCEzyxtNRy3iMudc3E), type: 'recursive' } + * // { cid: CID(QmZbj5ruYneZb8FuR9wnLqJCpCXMQudhSdWhdhp5U1oPWJ), type: 'indirect' } + * // { cid: CID(QmSo73bmN47gBxMNqbdV6rZ4KJiqaArqJ1nu5TvFhqqj1R), type: 'indirect' } + * + * const paths = [ + * CID.from('Qmc5..'), + * CID.from('QmZb..'), + * CID.from('QmSo..') + * ] + * for await (const { cid, type } of ipfs.pin.ls({ paths })) { + * console.log({ cid, type }) + * } + * // { cid: CID(Qmc5XkteJdb337s7VwFBAGtiaoj2QCEzyxtNRy3iMudc3E), type: 'recursive' } + * // { cid: CID(QmZbj5ruYneZb8FuR9wnLqJCpCXMQudhSdWhdhp5U1oPWJ), type: 'indirect' } + * // { cid: CID(QmSo73bmN47gBxMNqbdV6rZ4KJiqaArqJ1nu5TvFhqqj1R), type: 'indirect' } + * ``` + */ + ls: (options?: LsOptions & OptionExtension) => AsyncIterable + + /** + * Unpin this block from your repo + * + * @example + * ```js + * const cid = CID.from('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') + * const result = await ipfs.pin.rm(cid) + * console.log(result) + * // prints the CID that was unpinned + * // CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') + * ``` + */ + rm: (ipfsPath: string | CID, options?: RmOptions & OptionExtension) => Promise + + /** + * Unpin one or more blocks from your repo + * + * @example + * ```js + * const source = [ + * CID.from('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') + * ] + * for await (const cid of ipfs.pin.rmAll(source)) { + * console.log(cid) + * } + * // prints the CIDs that were unpinned + * // CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') + * ``` + */ + rmAll: (source: AwaitIterable, options?: AbortOptions & OptionExtension) => AsyncIterable + + remote +} + +export interface AddOptions extends AbortOptions { + /** + * If true, pin all blocked linked to from the pinned CID + */ + recursive?: boolean + + /** + * Whether to preload all blocks pinned during this operation + */ + preload?: boolean + + /** + * Internal option used to control whether to create a repo write lock during a pinning operation + */ + lock?: boolean +} + +export interface AddAllOptions extends AbortOptions { + lock?: boolean + + /** + * Whether to preload all blocks pinned during this operation + */ + preload?: boolean + + /** + * Internal option used to control whether to create a repo write lock during a pinning operation + */ + lock?: boolean +} + +export interface AddInput { + /** + * A CID to pin - nb. you must pass either `cid` or `path`, not both + */ + cid?: CID + + /** + * An IPFS path to pin - nb. you must pass either `cid` or `path`, not both + */ + path?: string + + /** + * If true, pin all blocked linked to from the pinned CID + */ + recursive?: boolean + + /** + * A human readable string to store with this pin + */ + comments?: string +} + +export type PinType = 'recursive' | 'direct' | 'indirect' | 'all' + +export type PinQueryType = 'recursive' | 'direct' | 'indirect' | 'all' + +export interface LsOptions extends AbortOptions { + paths?: CID | CID[] | string | string[] + type?: PinQueryType +} + +export interface LsResult { + cid: CID + type: PinType | string + metadata?: Record +} + +export interface RmOptions extends AbortOptions { + recursive?: boolean +} + +export interface RmAllInput { + cid?: CID + path?: string + recursive?: boolean +} + diff --git a/packages/ipfs-core-types/src/pin/remote.ts b/packages/ipfs-core-types/src/pin/remote/index.d.ts similarity index 78% rename from packages/ipfs-core-types/src/pin/remote.ts rename to packages/ipfs-core-types/src/pin/remote/index.d.ts index 7dde960720..5fe9265b04 100644 --- a/packages/ipfs-core-types/src/pin/remote.ts +++ b/packages/ipfs-core-types/src/pin/remote/index.d.ts @@ -1,9 +1,9 @@ import CID from 'cids' import Multiaddr from 'multiaddr' -import { API as Service } from './remote/service' -import { AbortOptions } from '../basic' +import { API as Service } from './service' +import { AbortOptions } from '../../utils' -export interface API { +export interface API { /** * API for configuring remote pinning services. */ @@ -12,25 +12,25 @@ export interface API { /** * Pin a content with a given CID to a remote pinning service. */ - add: (cid: CID, options: AddOptions & AbortOptions) => Promise + add: (cid: CID, options: AddOptions & AbortOptions & OptionExtension) => Promise /** * Returns a list of matching pins on the remote pinning service. */ - ls: (query: Query & AbortOptions) => AsyncIterable + ls: (query: Query & AbortOptions & OptionExtension) => AsyncIterable /** * Removes a single pin object matching query allowing it to be garbage - * collected (if needed). Will error if multiple pins mtach provided + * collected (if needed). Will error if multiple pins match provided * query. To remove all matches use `rmAll` instead. */ - rm: (query: Query & AbortOptions) => Promise + rm: (query: Query & AbortOptions & OptionExtension) => Promise /** * Removes all pin object that match given query allowing them to be garbage * collected if needed. */ - rmAll: (query: Query & AbortOptions) => Promise + rmAll: (query: Query & AbortOptions & OptionExtension) => Promise } export interface AddOptions extends RemoteServiceOptions { diff --git a/packages/ipfs-core-types/src/pin/remote/service.ts b/packages/ipfs-core-types/src/pin/remote/service/index.d.ts similarity index 65% rename from packages/ipfs-core-types/src/pin/remote/service.ts rename to packages/ipfs-core-types/src/pin/remote/service/index.d.ts index 7368f14403..14f6c2a996 100644 --- a/packages/ipfs-core-types/src/pin/remote/service.ts +++ b/packages/ipfs-core-types/src/pin/remote/service/index.d.ts @@ -1,22 +1,22 @@ -import { AbortOptions } from '../../basic' +import { AbortOptions } from '../../../utils' -export interface API { +export interface API { /** * Registers remote pinning service with a given name. Errors if service * with the given name is already registered. */ - add: (name: string, credentials: Credentials & AbortOptions) => Promise + add: (name: string, credentials: Credentials & AbortOptions & OptionExtension) => Promise /** - * Unregisteres remote pinning service with a given name. If service with such - * name isn't registerede this is a noop. + * Unregisters remote pinning service with a given name. If service with such + * name isn't registered this is a noop. */ - rm: (name: string, options?: AbortOptions) => Promise + rm: (name: string, options?: AbortOptions & OptionExtension) => Promise /** * List registered remote pinning services. */ - ls: ((options: { stat: true } & AbortOptions) => Promise) & ((options?: AbortOptions) => Promise) + ls: ((options: { stat: true } & AbortOptions & OptionExtension) => Promise) & ((options?: AbortOptions & OptionExtension) => Promise) } export interface Credentials { diff --git a/packages/ipfs-core-types/src/preload.ts b/packages/ipfs-core-types/src/preload.ts deleted file mode 100644 index ea62ac506d..0000000000 --- a/packages/ipfs-core-types/src/preload.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface Options { - preload?: boolean -} diff --git a/packages/ipfs-core-types/src/pubsub/index.d.ts b/packages/ipfs-core-types/src/pubsub/index.d.ts new file mode 100644 index 0000000000..2fb26a06fc --- /dev/null +++ b/packages/ipfs-core-types/src/pubsub/index.d.ts @@ -0,0 +1,84 @@ +import type { AbortOptions } from '../utils' + +export interface API { + /** + * Subscribe to a pubsub topic + * + * @example + * ```js + * const topic = 'fruit-of-the-day' + * const receiveMsg = (msg) => console.log(msg.data.toString()) + * + * await ipfs.pubsub.subscribe(topic, receiveMsg) + * console.log(`subscribed to ${topic}`) + * ``` + */ + subscribe: (topic: string, handler: MessageHandlerFn, options?: AbortOptions & OptionExtension) => Promise + + /** + * Unsubscribes from a pubsub topic + * + * @example + * ```js + * const topic = 'fruit-of-the-day' + * const receiveMsg = (msg) => console.log(msg.toString()) + * + * await ipfs.pubsub.subscribe(topic, receiveMsg) + * console.log(`subscribed to ${topic}`) + * + * await ipfs.pubsub.unsubscribe(topic, receiveMsg) + * console.log(`unsubscribed from ${topic}`) + * + * // Or removing all listeners: + * + * const topic = 'fruit-of-the-day' + * const receiveMsg = (msg) => console.log(msg.toString()) + * await ipfs.pubsub.subscribe(topic, receiveMsg); + * // Will unsubscribe ALL handlers for the given topic + * await ipfs.pubsub.unsubscribe(topic); + * ``` + */ + unsubscribe: (topic: string, handler: MessageHandlerFn, options?: AbortOptions & OptionExtension) => Promise + + /** + * Publish a data message to a pubsub topic + * + * @example + * ```js + * const topic = 'fruit-of-the-day' + * const msg = new TextEncoder().encode('banana') + * + * await ipfs.pubsub.publish(topic, msg) + * // msg was broadcasted + * console.log(`published to ${topic}`) + * ``` + */ + publish: (topic: string, data: Uint8Array, options?: AbortOptions & OptionExtension) => Promise + + /** + * Returns the list of subscriptions the peer is subscribed to + */ + ls: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Returns the peers that are subscribed to one topic. + * + * @example + * ```js + * const topic = 'fruit-of-the-day' + * + * const peerIds = await ipfs.pubsub.peers(topic) + * console.log(peerIds) + * ``` + */ + peers: (topic: string, options?: AbortOptions & OptionExtension) => Promise +} + +export interface Message { + from: string + seqno: Uint8Array + data: Uint8Array + topicIDs: string[] +} + +export type MessageHandlerFn = (message: Message) => void diff --git a/packages/ipfs-core-types/src/refs/index.d.ts b/packages/ipfs-core-types/src/refs/index.d.ts new file mode 100644 index 0000000000..3d1ff80143 --- /dev/null +++ b/packages/ipfs-core-types/src/refs/index.d.ts @@ -0,0 +1,31 @@ +import type { AbortOptions, PreloadOptions, IPFSPath } from '../utils' +import type CID from 'cids' + +export type API = { + /** + * Get links (references) from an object + */ + refs: Refs + + /** + * List blocks stored in the local block store + */ + local: Local +} + +export type Refs = (ipfsPath: IPFSPath | IPFSPath[], options?: RefsOptions & OptionExtension) => AsyncIterable + +export interface RefsOptions extends AbortOptions, PreloadOptions { + recursive?: boolean + unique?: boolean + format?: string + edges?: boolean + maxDepth?: number +} + +export type Local = (options?: AbortOptions & OptionExtension) => AsyncIterable + +export interface RefsResult { + ref: string + err?: Error +} diff --git a/packages/ipfs-core-types/src/repo.ts b/packages/ipfs-core-types/src/repo.ts deleted file mode 100644 index ca208d5be1..0000000000 --- a/packages/ipfs-core-types/src/repo.ts +++ /dev/null @@ -1,102 +0,0 @@ -import CID from 'cids' -import { Block } from './block-service' -import { ToJSON, Await, AbortOptions } from './basic' -import { DataStore, Key } from './datastore' -import { - ValueStore, StoreReader, Resource, StoreLookup, - StoreImporter, StoreExporter, StoreEraser, StoreSelector, - KeyValueStore -} from './store' - -export interface Repo extends Resource { - readonly path: string - closed: boolean - - /** - * Initializes necessary structures inside the repo - */ - init: (config: Partial) => Await - - /** - * Tells whether this repo exists or not. - */ - exists: () => Await - - /** - * Tells whether the repo has been initialized. - */ - isInitialized: () => Await - - /** - * Gets the repo status. - */ - stat: (options?: AbortOptions) => Await - - root: KeyValueStore - - blocks: BlockStore - datastore: DataStore - - pins: PinStore - config: ConfigStore - keys: KeyStore - - version: ValueStore - apiAddr: ValueStore -} - -export interface RepoStatus { - numObjects: number - repoPath: string - repoSize: number - version: number - storageMax: number -} - -interface BlockStore extends - StoreImporter, - StoreReader, - StoreLookup, - StoreExporter, - StoreEraser, - StoreSelector { - put: (block: Block) => Await -} - -export interface ConfigStore extends - StoreReader { - /** - * Set a config `value`, where `value` can be anything that is serializable - * to JSON. - */ - set: (key: string, value: ToJSON, options?: AbortOptions) => Await - - /** - * Set the whole `config` which can be a any value that is serializable to - * JSON. - * - * @param config - */ - replace: (config: Config, options?: AbortOptions) => Await - - /** - * Get the entire config value. - */ - getAll: (options?: AbortOptions) => Await - - /** - * Whether the config sub-repo exists. - */ - exists: () => Await -} - -export interface PinStore extends - KeyValueStore, - Object { -} - -export interface KeyStore extends - KeyValueStore, - Object { - -} diff --git a/packages/ipfs-core-types/src/repo/index.d.ts b/packages/ipfs-core-types/src/repo/index.d.ts new file mode 100644 index 0000000000..2401185bae --- /dev/null +++ b/packages/ipfs-core-types/src/repo/index.d.ts @@ -0,0 +1,44 @@ +import type { AbortOptions } from '../utils' +import CID from 'cids' + +export interface API { + /** + * Perform garbage collection on the repo + * + * Any unpinned blocks will be deleted + */ + gc: (options?: GCOptions & OptionExtension) => AsyncIterable + + /** + * Return stats about the repo + */ + stat: (options?: AbortOptions & OptionExtension) => Promise + + /** + * If the repo has been initialized, report the current version, + * otherwise report the version that would be initialized + */ + version: (options?: AbortOptions & OptionExtension) => Promise +} + +export interface GCOptions extends AbortOptions { + quiet?: boolean +} + +export interface GCError { + err: Error +} + +export interface GCSuccess { + cid: CID +} + +export type GCResult = GCSuccess | GCError + +export interface StatResult { + numObjects: BigInt + repoPath: string + repoSize: BigInt + version: string + storageMax: BigInt +} diff --git a/packages/ipfs-core-types/src/root.d.ts b/packages/ipfs-core-types/src/root.d.ts new file mode 100644 index 0000000000..6499817235 --- /dev/null +++ b/packages/ipfs-core-types/src/root.d.ts @@ -0,0 +1,345 @@ +import type { AbortOptions, PreloadOptions, IPFSPath, ImportSource, ToEntry } from './utils' +import type CID, { CIDVersion } from 'cids' +import type { Mtime } from 'ipfs-unixfs' +import type Multiaddr from 'multiaddr' +import type { BaseName } from 'multibase' + +export interface API { + /** + * Import a file or data into IPFS + */ + add: (entry: ToEntry, options?: AddOptions & OptionExtension) => Promise + + /** + * Import multiple files and data into IPFS + */ + addAll: (source: ImportSource, options?: AddAllOptions & AbortOptions & OptionExtension) => AsyncIterable + + /** + * Returns content of the file addressed by a valid IPFS Path or CID + */ + cat: (ipfsPath: IPFSPath, options?: CatOptions & OptionExtension) => AsyncIterable + + /** + * Fetch a file or an entire directory tree from IPFS that is addressed by a + * valid IPFS Path + */ + get: (ipfsPath: IPFSPath, options?: GetOptions & OptionExtension) => AsyncIterable + + /** + * Lists a directory from IPFS that is addressed by a valid IPFS Path + */ + ls: (ipfsPath: IPFSPath, options?: ListOptions & OptionExtension) => AsyncIterable + + /** + * Returns the identity of the Peer + * + * @example + * ```js + * const identity = await ipfs.id() + * console.log(identity) + * ``` + */ + id: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Returns the implementation version + * + * @example + * ```js + * const version = await ipfs.version() + * console.log(version) + * ``` + */ + version: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Resolve DNS links + */ + dns: (domain: string, options?: DNSOptions & OptionExtension) => Promise + + /** + * Start the node + */ + start: () => Promise + + /** + * Stop the node + */ + stop: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Send echo request packets to IPFS hosts. + * + * @example + * ```js + * for await (const res of ipfs.ping('Qmhash')) { + * if (res.time) { + * console.log(`Pong received: time=${res.time} ms`) + * } else { + * console.log(res.text) + * } + * } + * ``` + */ + ping: (peerId: CID | string, options?: PingOptions & OptionExtension) => AsyncIterable + + /** + * Resolve the value of names to IPFS + * + * There are a number of mutable name protocols that can link among themselves + * and into IPNS. For example IPNS references can (currently) point at an IPFS + * object, and DNS links can point at other DNS links, IPNS entries, or IPFS + * objects. This command accepts any of these identifiers and resolves them + * to the referenced item. + * + * @example + * ```js + * // Resolve the value of your identity: + * const name = '/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy' + * + * const res = await ipfs.resolve(name) + * console.log(res) + * // Logs: /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj + * + * // Resolve the value of another name recursively: + * const name = '/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n' + * + * // Where: + * // /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n + * // ...resolves to: + * // /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy + * // ...which in turn resolves to: + * // /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj + * + * const res = await ipfs.resolve(name, { recursive: true }) + * console.log(res) + * // Logs: /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj + * + * // Resolve the value of an IPFS path: + * const name = '/ipfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop' + * const res = await ipfs.resolve(name) + * console.log(res) + * // Logs: /ipfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1 + * ``` + */ + resolve: (name: string, options?: ResolveOptions & OptionExtension) => Promise + + /** + * Returns a list of available commands + */ + commands: (options?: AbortOptions & OptionExtension) => Promise + + mount: (options?: MountOptions & OptionExtension) => Promise + + /** + * Returns true if this IPFS node is online - that is, it's listening on network addresses + * for incoming connections + */ + isOnline: () => boolean +} + +export interface File { + readonly type: 'file' + readonly cid: CID + readonly name: string + + /** + * File path + */ + readonly path: string + /** + * File content + */ + readonly content?: AsyncIterable + mode?: number + mtime?: Mtime + size: number + depth: number +} + +export interface Directory { + type: 'dir' + cid: CID + name: string + /** + * Directory path + */ + path: string + mode?: number + mtime?: Mtime + size: number + depth: number +} + +export type IPFSEntry = File | Directory + +export type AddProgressFn = (bytes: number, path?: string) => void + +export interface AddOptions extends AbortOptions { + /** + * Chunking algorithm used to build ipfs DAGs. (defaults to 'size-262144') + */ + chunker?: string + /** + * The CID version to use when storing the data + */ + cidVersion?: CIDVersion + + /** + * Multihash hashing algorithm to use. (Defaults to 'sha2-256') + */ + hashAlg?: string + + /** + * If true, will not add blocks to the blockstore. (Defaults to `false`) + */ + onlyHash?: boolean + + /** + * Pin this object when adding. (Defaults to `true`) + */ + pin?: boolean + + /** + * A function that will be called with the number of bytes added as a file is + * added to ipfs and the path of the file being added. + * + * **Note** It will not be called for directory entries. + */ + progress?: AddProgressFn + + /** + * If true, DAG leaves will contain raw file data and not be wrapped in a + * protobuf. (Defaults to `false`) + */ + rawLeaves?: boolean + + /** + * If true will use the + * [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) + * format for DAG generation. (Defaults to `false`). + */ + trickle?: boolean + + /** + * Adds a wrapping node around the content. (Defaults to `false`) + */ + wrapWithDirectory?: boolean + + /** + * Whether to preload all blocks created during this operation + */ + preload?: boolean + + /** + * How many blocks from a file to write concurrently + */ + blockWriteConcurrency?: number +} + +export interface AddAllOptions extends AddOptions { + + /** + * Allows to create directories with an unlimited number of entries currently + * size of unixfs directories is limited by the maximum block size. + * ** Note ** that this is an experimental feature. (Defaults to `false`) + */ + enableShardingExperiment?: boolean + + /** + * Directories with more than this number of files will be created as HAMT - + * sharded directories. (Defaults to 1000) + */ + shardSplitThreshold?: number + + /** + * How many files to write concurrently + */ + fileImportConcurrency?: number +} + +export interface AddResult { + cid: CID + size: number + path: string + mode?: number + mtime?: Mtime +} + +export interface ShardingOptions { + sharding?: boolean +} + +export interface CatOptions extends AbortOptions, PreloadOptions { + /** + * An offset to start reading the file from + */ + offset?: number + /** + * An optional max length to read from the file + */ + length?: number +} + +export interface GetOptions extends AbortOptions, PreloadOptions {} + +export interface ListOptions extends AbortOptions, PreloadOptions { + recursive?: boolean + includeContent?: boolean +} + +export interface IDResult { + id: string + publicKey: string + addresses: Multiaddr[] + agentVersion: string + protocolVersion: string + protocols: string[] +} + +/** + * An object with the version information for the implementation, + * the commit and the Repo. `js-ipfs` instances will also return + * the version of `interface-ipfs-core` and `ipfs-http-client` + * supported by this node + */ +export interface VersionResult { + version: string + commit?: string + repo?: string + system?: string + golang?: string + 'interface-ipfs-core'?: string + 'ipfs-http-client'?: string +} + +export interface DNSOptions extends AbortOptions { + recursive?: boolean +} + +export interface PingOptions extends AbortOptions { + count?: number +} + +export interface PingResult { + success: boolean + time: number + text: string +} + +export interface ResolveOptions extends AbortOptions { + recursive?: boolean + cidBase?: BaseName +} + +export interface MountOptions extends AbortOptions { + ipfsPath?: string + ipnsPath?: string +} + +export interface MountResult { + fuseAllowOther?: boolean + ipfs?: string + ipns?: string +} diff --git a/packages/ipfs-core-types/src/root.ts b/packages/ipfs-core-types/src/root.ts deleted file mode 100644 index 5472b2bf89..0000000000 --- a/packages/ipfs-core-types/src/root.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { AbortOptions } from './basic' -import { Options as PreloadOptions } from './preload' -import { ImportSource, IPFSEntry, ToEntry, UnixFSEntry } from './files' -import CID, { CIDVersion } from 'cids' - -export interface RootAPI { - add: (entry: ToEntry, options?: AddOptions) => Promise - addAll: (source: ImportSource, options?: AddAllOptions & AbortOptions) => AsyncIterable - cat: (ipfsPath: IPFSPath, options?: CatOptions) => AsyncIterable - get: (ipfsPath: IPFSPath, options?: GetOptions) => AsyncIterable - - ls: (ipfsPath: IPFSPath, options?: ListOptions) => AsyncIterable -} - -export interface AddProgressFn { (bytes: number, path: string): void } - -export interface AddOptions extends AbortOptions { - /** - * Chunking algorithm used to build ipfs DAGs. (defaults to 'size-262144') - */ - chunker?: string - /** - * The CID version to use when storing the data - */ - cidVersion?: CIDVersion - - /** - * Multihash hashing algorithm to use. (Defaults to 'sha2-256') - */ - hashAlg?: string - - /** - * If true, will not add blocks to the blockstore. (Defaults to `false`) - */ - onlyHash?: boolean - - /** - * Pin this object when adding. (Defaults to `true`) - */ - pin?: boolean - - /** - * A function that will be called with the number of bytes added as a file is - * added to ipfs and the path of the file being added. - * - * **Note** It will not be called for directory entries. - */ - progress?: AddProgressFn - - /** - * If true, DAG leaves will contain raw file data and not be wrapped in a - * protobuf. (Defaults to `false`) - */ - rawLeaves?: boolean - - /** - * If true will use the - * [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) - * format for DAG generation. (Defaults to `false`). - */ - trickle?: boolean - - /** - * Adds a wrapping node around the content. (Defaults to `false`) - */ - wrapWithDirectory?: boolean - -} - -export interface AddAllOptions extends AddOptions { - - /** - * Allows to create directories with an unlimited number of entries currently - * size of unixfs directories is limited by the maximum block size. - * ** Note ** that this is an experimental feature. (Defaults to `false`) - */ - enableShardingExperiment?: boolean - - /** - * Directories with more than this number of files will be created as HAMT - - * sharded directories. (Defaults to 1000) - */ - shardSplitThreshold?: number -} - -export interface ShardingOptions { - sharding?: boolean -} - -export interface CatOptions extends AbortOptions, PreloadOptions { - /** - * An offset to start reading the file from - */ - offset?: number - /** - * An optional max length to read from the file - */ - length?: number -} - -export interface GetOptions extends AbortOptions, PreloadOptions {} - -export interface ListOptions extends AbortOptions, PreloadOptions { - recursive?: boolean - includeContent?: boolean -} - -/** - * An IPFS path or CID - */ -export type IPFSPath = CID | string diff --git a/packages/ipfs-core-types/src/stats/index.d.ts b/packages/ipfs-core-types/src/stats/index.d.ts new file mode 100644 index 0000000000..49ce7154a4 --- /dev/null +++ b/packages/ipfs-core-types/src/stats/index.d.ts @@ -0,0 +1,28 @@ +import type { AbortOptions } from '../utils' +import { API as BitswapAPI } from '../bitswap' +import { API as RepoAPI } from '../repo' +import type CID from 'cid' + +export interface API { + bitswap: BitswapAPI["stat"] + repo: RepoAPI["stat"] + + /** + * Return bandwith usage stats + */ + bw: (options?: BWOptions & OptionExtension) => AsyncIterable +} + +export interface BWOptions extends AbortOptions { + peer?: CID | string + proto?: string + poll?: boolean + interval?: number +} + +export interface BWResult { + totalIn: BigInt + totalOut: BigInt + rateIn: BigInt + rateOut: BigInt +} diff --git a/packages/ipfs-core-types/src/store.ts b/packages/ipfs-core-types/src/store.ts deleted file mode 100644 index 4a8c5048b4..0000000000 --- a/packages/ipfs-core-types/src/store.ts +++ /dev/null @@ -1,124 +0,0 @@ - -import type { Await, AwaitIterable, AbortOptions } from './basic' - -export interface ValueStore { - get: (options?: AbortOptions) => Await - set: (value: T) => Await -} - -export interface KeyValueStore extends - StoreReader, - StoreExporter, - StoreSelector, - StoreLookup, - StoreWriter, - StoreImporter, - StoreEraser { -} - -// Interface Datastore - -export interface StoreReader { - /** - * The key retrieve the value for. - */ - get: (key: Key, options?: AbortOptions) => Await -} - -export interface StoreLookup { - /** - * Check for the existence of a given key - */ - has: (key: Key, options?: AbortOptions) => Await -} - -export interface StoreExporter { - /** - * Retrieve a stream of values stored under the given keys. - */ - getMany: (keys: AwaitIterable, options?: AbortOptions) => AwaitIterable -} - -export interface StoreSelector { - /** - * Search the store for some values. - */ - query: (query: Query, options?: AbortOptions) => AwaitIterable -} - -export interface StoreWriter { - /** - * Store a value with the given key. - */ - put: (key: Key, value: Value, options?: AbortOptions) => Await -} - -export interface StoreImporter { - /** - * Store many key-value pairs. - */ - putMany: (entries: AwaitIterable, options?: AbortOptions) => AwaitIterable -} - -export interface StoreEraser { - /** - * Delete the content stored under the given key. - */ - delete: (key: Key, options?: AbortOptions) => Await - /** - * Delete the content stored under the given keys. - */ - deleteMany: (keys: AwaitIterable, options?: AbortOptions) => AwaitIterable - -} -export interface StoreBatch { - batch: () => Batch -} - -export interface Batch { - put: (key: Key, value: Value) => void - delete: (key: Key) => void - - commit: (options?: AbortOptions) => Await -} - -export interface Resource { - /** - * Opens the datastore, this is only needed if the store was closed before, - * otherwise this is taken care of by the constructor. - */ - open: () => Await - /** - * Close the datastore, this should always be called to ensure resources - * are cleaned up. - */ - close: () => Await -} - -export interface Query { - /** - * Only return values where the key starts with this prefix - */ - prefix?: string - /** - * Filter the results according to the these functions - */ - filters?: Array<(resut: Entry) => boolean> - /** - * Order the results according to these functions - */ - orders?: Array<(results: Entry[]) => Entry[]> - /** - * Only return this many records - */ - limit?: number - /** - * An options object, all properties are optional - */ - options?: Options - /** - * A way to signal that the caller is no longer interested in the outcome of - * this operation - */ - signal?: AbortSignal -} diff --git a/packages/ipfs-core-types/src/swarm/index.d.ts b/packages/ipfs-core-types/src/swarm/index.d.ts new file mode 100644 index 0000000000..be0befcd0a --- /dev/null +++ b/packages/ipfs-core-types/src/swarm/index.d.ts @@ -0,0 +1,53 @@ +import type { AbortOptions } from '../utils' +import { API as BitswapAPI } from '../bitswap' +import { API as RepoAPI } from '../repo' +import type CID from 'cid' +import type Multiaddr from 'multiaddr' + +export interface API { + /** + * List of known addresses of each peer connected + */ + addrs: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Open a connection to a given address + */ + connect: (addr: Multiaddr, options?: AbortOptions & OptionExtension) => Promise + + /** + * Close a connection to a given address + */ + disconnect: (addr: Multiaddr, options?: AbortOptions & OptionExtension) => Promise + + /** + * Local addresses this node is listening on + */ + localAddrs: (options?: AbortOptions & OptionExtension) => Promise + + /** + * Return a list of connected peers + */ + peers: (options?: PeersOptions & OptionExtension) => Promise +} + +export interface AddrsResult { + id: string + addrs: Multiaddr[] +} + +export interface PeersOptions extends AbortOptions { + direction?: boolean + streams?: boolean + verbose?: boolean + latency?: boolean +} + +export interface PeersResult { + addr: Multiaddr + peer: string + latency?: string + muxer?: string + streams?: string[] + direction?: 'inbound' | 'outbound' +} diff --git a/packages/ipfs-core-types/src/utils.d.ts b/packages/ipfs-core-types/src/utils.d.ts new file mode 100644 index 0000000000..6b667bd8b6 --- /dev/null +++ b/packages/ipfs-core-types/src/utils.d.ts @@ -0,0 +1,134 @@ +import CID from 'cids' +import { AwaitIterable } from './utils' +import { Mtime, MtimeLike } from 'ipfs-unixfs' + +export type Entry|Blob> = + | FileEntry + | DirectoryEntry + +export interface BaseEntry { + path: string + mode?: number + mtime?: Mtime +} +export interface FileEntry |Blob> extends BaseEntry { + content?: Content +} + +export interface DirectoryEntry extends BaseEntry { + content?: undefined +} + +export type ImportSource = +| AwaitIterable +| ReadableStream + +export type ToEntry = + | ToFile + | ToDirectory + | ToContent + +export interface ToFile extends ToFileMetadata { + path?: string + content: ToContent +} + +export interface ToDirectory extends ToFileMetadata { + path: string + content?: undefined +} + +export interface ToFileMetadata { + mode?: ToMode + mtime?: MtimeLike +} + +/** + * File content in arbitrary (supported) representation. It is used in input + * positions and is usually normalized to `Blob` in browser contexts and + * `AsyncIterable` in node. + */ +export type ToContent = + | string + | InstanceType + | ArrayBufferView + | ArrayBuffer + | Blob + | AwaitIterable + | ReadableStream + +export type ToMode = + | string + | number + +export interface BaseFile { + cid: CID + path: string + name: string +} + +export interface InputFile extends BaseFile { + unixfs: undefined +} + +export interface BrowserImportCandidate { + path?: string, + content?: Blob, + mtime?: Mtime, + mode?: number +} + +/** + * Represents a value that you can await on, which is either value or a promise + * of one. + */ +export type Await = + | T + | Promise + +/** + * Represents an iterable that can be used in `for await` loops, that is either + * iterable or an async iterable. + */ +export type AwaitIterable = + | Iterable + | AsyncIterable + +/** + * Common options across all cancellable requests. + */ +export interface AbortOptions { + /** + * Can be provided to a function that starts a long running task, which will + * be aborted when signal is triggered. + */ + signal?: AbortSignal + /** + * Can be provided to a function that starts a long running task, which will + * be aborted after provided timeout (in ms). + */ + timeout?: number +} + +export interface PreloadOptions { + preload?: boolean +} + +export type ToJSON = + | null + | string + | number + | boolean + | ToJSON[] + | { toJSON?: () => ToJSON } & { [key: string]: ToJSON } + +/** + * An IPFS path or CID + */ +export type IPFSPath = CID | string + +export interface BufferStore { + put: (key: Uint8Array, value: Uint8Array) => Promise + get: (key: Uint8Array) => Promise + stores: any[] +} diff --git a/packages/ipfs-core-types/tsconfig.json b/packages/ipfs-core-types/tsconfig.json index f090f172de..5fe8ea40d7 100644 --- a/packages/ipfs-core-types/tsconfig.json +++ b/packages/ipfs-core-types/tsconfig.json @@ -1,7 +1,7 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { - "noImplicitAny": true + "outDir": "dist" }, "include": [ "src" diff --git a/packages/ipfs-core-utils/package.json b/packages/ipfs-core-utils/package.json index 720dc04294..d0e9ce4147 100644 --- a/packages/ipfs-core-utils/package.json +++ b/packages/ipfs-core-utils/package.json @@ -7,15 +7,20 @@ "bugs": "https://github.com/ipfs/js-ipfs/issues", "leadMaintainer": "Alex Potsides ", "main": "src/index.js", + "types": "dist/src/index.d.ts", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "typesVersions": { "*": { - "*": [ - "dist/*", - "dist/*/index" + "src/*": [ + "dist/src/*", + "dist/src/*/index" + ], + "src/": [ + "dist/src/index" ] } }, @@ -24,7 +29,6 @@ "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { - "prepare": "aegir build --no-bundle", "test": "aegir test", "test:browser": "aegir test -t browser", "test:electron": "aegir test -t electron-main", @@ -32,7 +36,8 @@ "test:node": "aegir test -t node", "lint": "aegir lint", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i rimraf -i ipfs-core-types" + "dep-check": "aegir dep-check -i rimraf -i ipfs-core-types", + "build": "aegir build --no-bundle" }, "license": "MIT", "dependencies": { @@ -40,9 +45,10 @@ "blob-to-it": "^1.0.1", "browser-readablestream-to-it": "^1.0.1", "cids": "^1.1.5", - "err-code": "^2.0.3", + "err-code": "^3.0.1", "ipfs-core-types": "^0.3.1", - "ipfs-utils": "^6.0.1", + "ipfs-unixfs": "^4.0.1", + "ipfs-utils": "^6.0.4", "it-all": "^1.0.4", "it-map": "^1.0.4", "it-peekable": "^1.0.1", @@ -53,7 +59,7 @@ "uint8arrays": "^2.1.3" }, "devDependencies": { - "aegir": "^31.0.0", + "aegir": "^32.1.0", "rimraf": "^3.0.2" } } diff --git a/packages/ipfs-core-utils/src/files/format-mode.js b/packages/ipfs-core-utils/src/files/format-mode.js index 304ccc3464..53158d975f 100644 --- a/packages/ipfs-core-utils/src/files/format-mode.js +++ b/packages/ipfs-core-utils/src/files/format-mode.js @@ -16,6 +16,12 @@ const S_IROTH = parseInt('4', 8) // others have read permission const S_IWOTH = parseInt('2', 8) // others have write permission const S_IXOTH = parseInt('1', 8) // others have execute permission +/** + * @param {number} mode + * @param {number} perm + * @param {string} type + * @param {string[]} output + */ function checkPermission (mode, perm, type, output) { if ((mode & perm) === perm) { output.push(type) @@ -25,8 +31,7 @@ function checkPermission (mode, perm, type, output) { } /** - * - * @param {import('ipfs-core-types/src/files').Mode} mode + * @param {number} mode * @param {boolean} isDirectory * @returns {string} */ diff --git a/packages/ipfs-core-utils/src/files/format-mtime.js b/packages/ipfs-core-utils/src/files/format-mtime.js index 8195600efa..0e1d0b31ae 100644 --- a/packages/ipfs-core-utils/src/files/format-mtime.js +++ b/packages/ipfs-core-utils/src/files/format-mtime.js @@ -1,7 +1,7 @@ 'use strict' /** - * @param {import('ipfs-core-types/src/files').MTime} mtime + * @param {import('ipfs-unixfs').Mtime} mtime * @returns {string} */ function formatMtime (mtime) { @@ -9,7 +9,7 @@ function formatMtime (mtime) { return '-' } - const date = new Date((mtime.secs * 1000) + Math.round(mtime.nsecs / 1000)) + const date = new Date((mtime.secs * 1000) + Math.round((mtime.nsecs || 0) / 1000)) return date.toLocaleDateString(Intl.DateTimeFormat().resolvedOptions().locale, { year: 'numeric', diff --git a/packages/ipfs-core-utils/src/files/normalise-input/index.browser.js b/packages/ipfs-core-utils/src/files/normalise-input/index.browser.js index e937dd1fbd..97eb2dcd19 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/index.browser.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/index.browser.js @@ -3,6 +3,11 @@ const normaliseContent = require('./normalise-content.browser') const normaliseInput = require('./normalise-input') +/** + * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource + * @typedef {import('ipfs-core-types/src/utils').BrowserImportCandidate} BrowserImportCandidate + */ + /** * Transforms any of the `ipfs.add` input types into * @@ -12,7 +17,8 @@ const normaliseInput = require('./normalise-input') * * See https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/FILES.md#ipfsadddata-options * - * @param {import('ipfs-core-types/src/files').ImportSource} input - * @returns {AsyncIterable>} + * @param {ImportSource} input + * @returns {AsyncGenerator} */ +// @ts-ignore module.exports = (input) => normaliseInput(input, normaliseContent) diff --git a/packages/ipfs-core-utils/src/files/normalise-input/index.js b/packages/ipfs-core-utils/src/files/normalise-input/index.js index 3e30de6ce4..8a69940471 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/index.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/index.js @@ -3,16 +3,21 @@ const normaliseContent = require('./normalise-content') const normaliseInput = require('./normalise-input') +/** + * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource + * @typedef {import('ipfs-unixfs-importer').ImportCandidate} ImportCandidate + */ + /** * Transforms any of the `ipfs.add` input types into * * ``` - * AsyncIterable<{ path, mode, mtime, content: AsyncIterable }> + * AsyncIterable<{ path, mode, mtime, content: AsyncIterable }> * ``` * * See https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/FILES.md#ipfsadddata-options * - * @param {import('ipfs-core-types/src/files').ImportSource} input - * @returns {AsyncIterable>>} + * @param {ImportSource} input + * @returns {AsyncGenerator} */ module.exports = (input) => normaliseInput(input, normaliseContent) diff --git a/packages/ipfs-core-utils/src/files/normalise-input/normalise-content.browser.js b/packages/ipfs-core-utils/src/files/normalise-input/normalise-content.browser.js index a2bdc54fea..10efa46351 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/normalise-content.browser.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/normalise-content.browser.js @@ -13,7 +13,6 @@ const { /** * @param {import('./normalise-input').ToContent} input - * @returns {Promise} */ async function toBlob (input) { // Bytes @@ -37,7 +36,7 @@ async function toBlob (input) { } // (Async)Iterator - if (input[Symbol.iterator] || input[Symbol.asyncIterator]) { + if (Symbol.iterator in input || Symbol.asyncIterator in input) { /** @type {any} peekable */ const peekable = itPeekable(input) @@ -67,7 +66,6 @@ async function toBlob (input) { /** * @param {AsyncIterable|Iterable} stream - * @returns {Promise} */ async function itToBlob (stream) { const parts = [] diff --git a/packages/ipfs-core-utils/src/files/normalise-input/normalise-content.js b/packages/ipfs-core-utils/src/files/normalise-input/normalise-content.js index db205d62c5..a959547474 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/normalise-content.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/normalise-content.js @@ -15,7 +15,6 @@ const { /** * @param {import('./normalise-input').ToContent} input - * @returns {AsyncIterable} */ async function * toAsyncIterable (input) { // Bytes | String @@ -41,7 +40,7 @@ async function * toAsyncIterable (input) { } // (Async)Iterator - if (input[Symbol.iterator] || input[Symbol.asyncIterator]) { + if (Symbol.iterator in input || Symbol.asyncIterator in input) { /** @type {any} peekable */ const peekable = itPeekable(input) @@ -73,9 +72,7 @@ async function * toAsyncIterable (input) { } /** - * * @param {ArrayBuffer | ArrayBufferView | string | InstanceType | number[]} chunk - * @returns {Uint8Array} */ function toBytes (chunk) { if (chunk instanceof Uint8Array) { diff --git a/packages/ipfs-core-utils/src/files/normalise-input/normalise-input.js b/packages/ipfs-core-utils/src/files/normalise-input/normalise-input.js index 79365847d8..7f1d933a1a 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/normalise-input.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/normalise-input.js @@ -8,27 +8,27 @@ const { isBytes, isBlob, isReadableStream, - isFileObject, - mtimeToObject, - modeToNumber + isFileObject } = require('./utils') - -// eslint-disable-next-line complexity +const { + parseMtime, + parseMode +} = require('ipfs-unixfs') /** - * @typedef {import('ipfs-core-types/src/files').ToContent} ToContent + * @typedef {import('ipfs-core-types/src/utils').ToContent} ToContent + * @typedef {import('ipfs-unixfs-importer').ImportCandidate} ImportCandidate + * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry */ + /** - * @template {Blob|AsyncIterable} Content - * @param {import('ipfs-core-types/src/files').ImportSource} input - * @param {(content:ToContent) => Content|Promise} normaliseContent - * @returns {AsyncIterable>} + * @param {import('ipfs-core-types/src/utils').ImportSource} input + * @param {(content:ToContent) => AsyncIterable} normaliseContent */ // eslint-disable-next-line complexity module.exports = async function * normaliseInput (input, normaliseContent) { - // must give us something if (input === null || input === undefined) { - throw errCode(new Error(`Unexpected input: ${input}`), 'ERR_UNEXPECTED_INPUT') + return } // String @@ -50,7 +50,7 @@ module.exports = async function * normaliseInput (input, normaliseContent) { } // Iterable - if (input[Symbol.iterator] || input[Symbol.asyncIterator]) { + if (Symbol.iterator in input || Symbol.asyncIterator in input) { /** @type {any} peekable */ const peekable = itPeekable(input) @@ -76,7 +76,7 @@ module.exports = async function * normaliseInput (input, normaliseContent) { // (Async)Iterable // (Async)Iterable<{ path, content }> if (isFileObject(value) || isBlob(value) || typeof value === 'string' || value instanceof String) { - yield * map(peekable, (value) => toFileObject(value, normaliseContent)) + yield * map(peekable, (/** @type {ToEntry} */ value) => toFileObject(value, normaliseContent)) return } @@ -85,7 +85,7 @@ module.exports = async function * normaliseInput (input, normaliseContent) { // ReadableStream<(Async)Iterable> // ReadableStream> if (value[Symbol.iterator] || value[Symbol.asyncIterator] || isReadableStream(value)) { - yield * map(peekable, (value) => toFileObject(value, normaliseContent)) + yield * map(peekable, (/** @type {ToEntry} */ value) => toFileObject(value, normaliseContent)) return } } @@ -102,16 +102,19 @@ module.exports = async function * normaliseInput (input, normaliseContent) { } /** - * @template {Blob|AsyncIterable} Content - * @param {import('ipfs-core-types/src/files').ToEntry} input - * @param {(content:ToContent) => Content|Promise} normaliseContent - * @returns {Promise>} + * @param {ToEntry} input + * @param {(content:ToContent) => AsyncIterable} normaliseContent */ async function toFileObject (input, normaliseContent) { // @ts-ignore - Those properties don't exist on most input types const { path, mode, mtime, content } = input - const file = { path: path || '', mode: modeToNumber(mode), mtime: mtimeToObject(mtime) } + /** @type {ImportCandidate} */ + const file = { + path: path || '', + mode: parseMode(mode), + mtime: parseMtime(mtime) + } if (content) { file.content = await normaliseContent(content) diff --git a/packages/ipfs-core-utils/src/files/normalise-input/utils.js b/packages/ipfs-core-utils/src/files/normalise-input/utils.js index defceec5e8..b118265a01 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/utils.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/utils.js @@ -22,7 +22,7 @@ function isBlob (obj) { * An object with a path or content property * * @param {any} obj - * @returns {obj is import('ipfs-core-types/src/files').ToEntry} + * @returns {obj is import('ipfs-core-types/src/utils').ToEntry} */ function isFileObject (obj) { return typeof obj === 'object' && (obj.path || obj.content) @@ -35,94 +35,9 @@ function isFileObject (obj) { const isReadableStream = (value) => value && typeof value.getReader === 'function' -/** - * @param {any} mtime - * @returns {{secs:number, nsecs:number}|undefined} - */ -function mtimeToObject (mtime) { - if (mtime == null) { - return undefined - } - - // Javascript Date - if (mtime instanceof Date) { - const ms = mtime.getTime() - const secs = Math.floor(ms / 1000) - - return { - secs: secs, - nsecs: (ms - (secs * 1000)) * 1000 - } - } - - // { secs, nsecs } - if (Object.prototype.hasOwnProperty.call(mtime, 'secs')) { - return { - secs: mtime.secs, - nsecs: mtime.nsecs - } - } - - // UnixFS TimeSpec - if (Object.prototype.hasOwnProperty.call(mtime, 'Seconds')) { - return { - secs: mtime.Seconds, - nsecs: mtime.FractionalNanoseconds - } - } - - // process.hrtime() - if (Array.isArray(mtime)) { - return { - secs: mtime[0], - nsecs: mtime[1] - } - } - /* - TODO: https://github.com/ipfs/aegir/issues/487 - - // process.hrtime.bigint() - if (typeof mtime === 'bigint') { - const secs = mtime / BigInt(1e9) - const nsecs = mtime - (secs * BigInt(1e9)) - - return { - secs: parseInt(secs), - nsecs: parseInt(nsecs) - } - } - */ -} - -/** - * @param {any} mode - * @returns {number|undefined} - */ -function modeToNumber (mode) { - if (mode == null) { - return undefined - } - - if (typeof mode === 'number') { - return mode - } - - mode = mode.toString() - - if (mode.substring(0, 1) === '0') { - // octal string - return parseInt(mode, 8) - } - - // decimal string - return parseInt(mode, 10) -} - module.exports = { isBytes, isBlob, isFileObject, - isReadableStream, - mtimeToObject, - modeToNumber + isReadableStream } diff --git a/packages/ipfs-core-utils/src/pins/normalise-input.js b/packages/ipfs-core-utils/src/pins/normalise-input.js index fc4299b7ce..e7dc21dd24 100644 --- a/packages/ipfs-core-utils/src/pins/normalise-input.js +++ b/packages/ipfs-core-utils/src/pins/normalise-input.js @@ -3,6 +3,22 @@ const errCode = require('err-code') const CID = require('cids') +/** + * @typedef {Object} Pinnable + * @property {string | InstanceType | CID} [path] + * @property {CID} [cid] + * @property {boolean} [recursive] + * @property {any} [metadata] + * + * @typedef {CID|string|InstanceType|Pinnable} ToPin + * @typedef {ToPin|Iterable|AsyncIterable} Source + * + * @typedef {Object} Pin + * @property {string|CID} path + * @property {boolean} recursive + * @property {any} [metadata] + */ + /** * Transform one of: * @@ -55,7 +71,8 @@ module.exports = async function * normaliseInput (input) { } // Iterable - if (input[Symbol.iterator]) { + if (Symbol.iterator in input) { + // @ts-ignore const iterator = input[Symbol.iterator]() const first = iterator.next() if (first.done) return iterator @@ -82,7 +99,8 @@ module.exports = async function * normaliseInput (input) { } // AsyncIterable - if (input[Symbol.asyncIterator]) { + if (Symbol.asyncIterator in input) { + // @ts-ignore const iterator = input[Symbol.asyncIterator]() const first = await iterator.next() if (first.done) return iterator @@ -112,12 +130,18 @@ module.exports = async function * normaliseInput (input) { } /** - * @param {ToPinWithPath|ToPinWithCID} input - * @returns {Pin} + * @param {Pinnable} input */ function toPin (input) { + const path = input.cid || `${input.path}` + + if (!path) { + throw errCode(new Error('Unexpected input: Please path either a CID or an IPFS path'), 'ERR_UNEXPECTED_INPUT') + } + + /** @type {Pin} */ const pin = { - path: input.path == null ? input.cid : `${input.path}`, + path, recursive: input.recursive !== false } @@ -127,25 +151,3 @@ function toPin (input) { return pin } - -/** - * @typedef {Object} ToPinWithPath - * @property {string | InstanceType | CID} path - * @property {undefined} [cid] - * @property {boolean} [recursive] - * @property {any} [metadata] - * - * @typedef {Object} ToPinWithCID - * @property {undefined} [path] - * @property {CID} cid - * @property {boolean} [recursive] - * @property {any} [metadata] - * - * @typedef {CID|string|InstanceType|ToPinWithPath|ToPinWithPath} ToPin - * @typedef {ToPin|Iterable|AsyncIterable} Source - * - * @typedef {Object} Pin - * @property {string|CID} path - * @property {boolean} recursive - * @property {any} [metadata] - */ diff --git a/packages/ipfs-core-utils/src/to-url-string.js b/packages/ipfs-core-utils/src/to-url-string.js index c74f0e601a..877b1f5a0c 100644 --- a/packages/ipfs-core-utils/src/to-url-string.js +++ b/packages/ipfs-core-utils/src/to-url-string.js @@ -1,6 +1,7 @@ 'use strict' const multiaddr = require('multiaddr') +// @ts-ignore no types const multiAddrToUri = require('multiaddr-to-uri') /** diff --git a/packages/ipfs-core-utils/src/with-timeout-option.js b/packages/ipfs-core-utils/src/with-timeout-option.js index 70e159263f..ccbca756cb 100644 --- a/packages/ipfs-core-utils/src/with-timeout-option.js +++ b/packages/ipfs-core-utils/src/with-timeout-option.js @@ -1,6 +1,7 @@ /* eslint-disable no-unreachable */ 'use strict' +// @ts-ignore const TimeoutController = require('timeout-abort-controller') const { anySignal } = require('any-signal') const { default: parseDuration } = require('parse-duration') @@ -53,9 +54,11 @@ function withTimeoutOption (fn, optionsArgIndex) { } } + // @ts-ignore if (fnRes[Symbol.asyncIterator]) { // @ts-ignore return (async function * () { + // @ts-ignore const it = fnRes[Symbol.asyncIterator]() try { diff --git a/packages/ipfs-core-utils/tsconfig.json b/packages/ipfs-core-utils/tsconfig.json index 979a39adab..5fe8ea40d7 100644 --- a/packages/ipfs-core-utils/tsconfig.json +++ b/packages/ipfs-core-utils/tsconfig.json @@ -1,10 +1,9 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" ] } diff --git a/packages/ipfs-core/.aegir.js b/packages/ipfs-core/.aegir.js index d5af852bc9..73bad951ae 100644 --- a/packages/ipfs-core/.aegir.js +++ b/packages/ipfs-core/.aegir.js @@ -70,7 +70,7 @@ module.exports = { } }, build: { - bundlesizeMax: '660kB', + bundlesizeMax: '614kB', config: esbuild } } diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index 0f80960762..a3e1acba42 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -10,9 +10,11 @@ "license": "(Apache-2.0 OR MIT)", "leadMaintainer": "Alex Potsides ", "main": "src/index.js", + "types": "dist/src/index.d.ts", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "browser": { "./src/runtime/init-assets-nodejs.js": "./src/runtime/init-assets-browser.js", @@ -27,9 +29,12 @@ }, "typesVersions": { "*": { - "*": [ - "dist/*", - "dist/*/index" + "src/*": [ + "dist/src/*", + "dist/src/*/index" + ], + "src/": [ + "dist/src/index" ] } }, @@ -38,7 +43,6 @@ "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { - "prepare": "npm run build", "build": "aegir build", "lint": "aegir lint", "test": "aegir test", @@ -55,50 +59,50 @@ "dependencies": { "abort-controller": "^3.0.0", "array-shuffle": "^2.0.0", - "bignumber.js": "^9.0.1", - "cbor": "^6.0.1", + "cborg": "^1.2.1", "cids": "^1.1.5", - "class-is": "^1.1.0", "dag-cbor-links": "^2.0.0", "datastore-core": "^3.0.0", - "datastore-pubsub": "^0.4.1", + "datastore-pubsub": "^0.5.0", "debug": "^4.1.1", "dlv": "^1.1.3", - "err-code": "^2.0.3", - "hamt-sharding": "^1.0.0", + "err-code": "^3.0.1", + "hamt-sharding": "^2.0.0", "hashlru": "^2.3.0", "interface-datastore": "^3.0.3", - "ipfs-bitswap": "^4.0.2", - "ipfs-block-service": "^0.18.0", + "ipfs-bitswap": "^5.0.1", + "ipfs-block-service": "^0.19.0", "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", - "ipfs-repo": "^8.0.0", - "ipfs-unixfs": "^2.0.3", - "ipfs-unixfs-exporter": "^3.0.4", - "ipfs-unixfs-importer": "^5.0.0", - "ipfs-utils": "^6.0.1", - "ipld": "^0.28.0", + "ipfs-repo": "^9.0.0", + "ipfs-unixfs": "^4.0.1", + "ipfs-unixfs-exporter": "^5.0.1", + "ipfs-unixfs-importer": "^7.0.1", + "ipfs-utils": "^6.0.4", + "ipld": "^0.29.0", "ipld-block": "^0.11.0", - "ipld-dag-cbor": "^0.17.0", - "ipld-dag-pb": "^0.20.0", - "ipld-raw": "^6.0.0", - "ipns": "^0.8.0", + "ipld-dag-cbor": "^0.18.0", + "ipld-dag-pb": "^0.22.0", + "ipld-raw": "^7.0.0", + "ipns": "^0.10.0", "is-domain-name": "^1.0.1", - "is-ipfs": "^2.0.0", + "is-ipfs": "^4.0.0", "it-all": "^1.0.4", + "it-drain": "^1.0.3", "it-first": "^1.0.4", "it-last": "^1.0.4", + "it-map": "^1.0.4", "it-pipe": "^1.1.0", - "libp2p": "^0.30.7", + "libp2p": "^0.30.12", "libp2p-bootstrap": "^0.12.1", "libp2p-crypto": "^0.19.0", "libp2p-floodsub": "^0.24.1", "libp2p-gossipsub": "^0.8.0", - "libp2p-kad-dht": "^0.20.1", + "libp2p-kad-dht": "^0.21.0", "libp2p-mdns": "^0.15.0", "libp2p-mplex": "^0.10.0", "libp2p-noise": "^2.0.1", - "libp2p-record": "^0.9.0", + "libp2p-record": "^0.10.0", "libp2p-tcp": "^0.15.1", "libp2p-webrtc-star": "^0.21.0", "libp2p-websockets": "^0.15.1", @@ -118,11 +122,12 @@ "uint8arrays": "^2.1.3" }, "devDependencies": { - "aegir": "^31.0.0", - "delay": "^4.4.0", + "@types/dlv": "^1.1.2", + "aegir": "^32.1.0", + "delay": "^5.0.0", "go-ipfs": "0.8.0", "interface-ipfs-core": "^0.144.2", - "ipfsd-ctl": "^7.2.0", + "ipfsd-ctl": "^8.0.0", "ipld-git": "^0.6.1", "iso-url": "^1.0.0", "nanoid": "^3.1.12", diff --git a/packages/ipfs-core/src/components/add-all/index.js b/packages/ipfs-core/src/components/add-all/index.js index 9de540a7d6..5d14f5685d 100644 --- a/packages/ipfs-core/src/components/add-all/index.js +++ b/packages/ipfs-core/src/components/add-all/index.js @@ -1,18 +1,23 @@ 'use strict' -const importer = require('ipfs-unixfs-importer') +const { importer } = require('ipfs-unixfs-importer') const normaliseAddInput = require('ipfs-core-utils/src/files/normalise-input/index') const { parseChunkerString } = require('./utils') const { pipe } = require('it-pipe') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) +/** + * @typedef {import('cids')} CID + * @typedef {import('ipfs-unixfs-importer').ImportResult} ImportResult + */ + /** * @typedef {Object} Context - * @property {import('..').Block} block - * @property {import('..').GCLock} gcLock - * @property {import('..').Preload} preload - * @property {import('..').Pin} pin + * @property {import('ipfs-core-types/src/block').API} block + * @property {import('../gc-lock').GCLock} gcLock + * @property {import('../../types').Preload} preload + * @property {import('ipfs-core-types/src/pin').API} pin * @property {import('ipfs-core-types/src/root').ShardingOptions} [options] * * @param {Context} context @@ -21,11 +26,7 @@ module.exports = ({ block, gcLock, preload, pin, options }) => { const isShardingEnabled = options && options.sharding /** - * Import multiple files and data into IPFS. - * - * @param {import('ipfs-core-types/src/files').ImportSource} source - * @param {import('ipfs-core-types/src/root').AddAllOptions} [options] - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/root').API["addAll"]} */ async function * addAll (source, options = {}) { const opts = mergeOptions({ @@ -63,11 +64,16 @@ module.exports = ({ block, gcLock, preload, pin, options }) => { delete opts.trickle + /** @type {Record} */ const totals = {} if (opts.progress) { const prog = opts.progress + /** + * @param {number} bytes + * @param {string} path + */ opts.progress = (bytes, path) => { if (!totals[path]) { totals[path] = 0 @@ -81,6 +87,9 @@ module.exports = ({ block, gcLock, preload, pin, options }) => { const iterator = pipe( normaliseAddInput(source), + /** + * @param {AsyncIterable} source + */ source => importer(source, block, { ...opts, pin: false @@ -107,8 +116,14 @@ module.exports = ({ block, gcLock, preload, pin, options }) => { return withTimeoutOption(addAll) } +/** + * @param {import('ipfs-core-types/src/root').AddAllOptions} opts + */ function transformFile (opts) { - return async function * (source) { + /** + * @param {AsyncGenerator} source + */ + async function * transformFile (source) { for await (const file of source) { let cid = file.cid @@ -131,10 +146,19 @@ function transformFile (opts) { } } } + + return transformFile } +/** + * @param {(cid: CID) => void} preload + * @param {import('ipfs-core-types/src/root').AddAllOptions} opts + */ function preloadFile (preload, opts) { - return async function * (source) { + /** + * @param {AsyncGenerator} source + */ + async function * maybePreloadFile (source) { for await (const file of source) { const isRootFile = !file.path || opts.wrapWithDirectory ? file.path === '' @@ -149,14 +173,23 @@ function preloadFile (preload, opts) { yield file } } + + return maybePreloadFile } +/** + * @param {import('ipfs-core-types/src/pin').API} pin + * @param {import('ipfs-core-types/src/root').AddAllOptions} opts + */ function pinFile (pin, opts) { - return async function * (source) { + /** + * @param {AsyncGenerator} source + */ + async function * maybePinFile (source) { for await (const file of source) { // Pin a file if it is the root dir of a recursive add or the single file // of a direct add. - const isRootDir = !file.path.includes('/') + const isRootDir = !file.path?.includes('/') const shouldPin = (opts.pin == null ? true : opts.pin) && isRootDir && !opts.onlyHash if (shouldPin) { @@ -171,4 +204,6 @@ function pinFile (pin, opts) { yield file } } + + return maybePinFile } diff --git a/packages/ipfs-core/src/components/add.js b/packages/ipfs-core/src/components/add.js index 15fe4ca229..1789d14844 100644 --- a/packages/ipfs-core/src/components/add.js +++ b/packages/ipfs-core/src/components/add.js @@ -3,23 +3,16 @@ const last = require('it-last') /** - * @typedef {Object} Context - * @property {ReturnType} addAll - * - * @param {Context} context + * @param {Object} context + * @param {import('ipfs-core-types/src/root').API["addAll"]} context.addAll */ module.exports = ({ addAll }) => { /** - * Import a file or data into IPFS. - * - * @param {import('ipfs-core-types/src/files').ToEntry} entry - * @param {import('ipfs-core-types/src/root').AddAllOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/root').API["add"]} */ - async function add (entry, options) { - /** @type {import('ipfs-core-types/src/files').ImportSource} */ - const source = (entry) - const result = await last(addAll(source, options)) + async function add (entry, options = {}) { + // @ts-ignore TODO: https://github.com/ipfs/js-ipfs/issues/3290 + const result = await last(addAll(entry, options)) // Note this should never happen as `addAll` should yield at least one item // but to satisfy type checker we perfom this check and for good measure // throw an error in case it does happen. diff --git a/packages/ipfs-core/src/components/bitswap/index.js b/packages/ipfs-core/src/components/bitswap/index.js index 8209007a75..178b75171e 100644 --- a/packages/ipfs-core/src/components/bitswap/index.js +++ b/packages/ipfs-core/src/components/bitswap/index.js @@ -5,6 +5,13 @@ const createWantlistForPeer = require('./wantlist-for-peer') const createUnwant = require('./unwant') const createStat = require('./stat') +/** + * @typedef {import('../../types').NetworkService} NetworkService + * @typedef {import('peer-id')} PeerId + * @typedef {import('cids')} CID + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ + class BitswapAPI { /** * @param {Object} config @@ -18,10 +25,3 @@ class BitswapAPI { } } module.exports = BitswapAPI - -/** - * @typedef {import('..').NetworkService} NetworkService - * @typedef {import('..').PeerId} PeerId - * @typedef {import('..').CID} CID - * @typedef {import('..').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/bitswap/stat.js b/packages/ipfs-core/src/components/bitswap/stat.js index 279c77a67a..fae73a9cff 100644 --- a/packages/ipfs-core/src/components/bitswap/stat.js +++ b/packages/ipfs-core/src/components/bitswap/stat.js @@ -1,69 +1,33 @@ 'use strict' -const { default: Big } = require('bignumber.js') const CID = require('cids') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Show diagnostic information on the bitswap agent. - * Note: `bitswap.stat` and `stats.bitswap` can be used interchangeably. - * - * @example - * ```js - * const stats = await ipfs.bitswap.stat() - * console.log(stats) - * // { - * // provideBufLen: 0, - * // wantlist: [ CID('QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM') ], - * // peers: - * // [ 'QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', - * // 'QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', - * // 'QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd' ], - * // blocksReceived: 0, - * // dataReceived: 0, - * // blocksSent: 0, - * // dataSent: 0, - * // dupBlksReceived: 0, - * // dupDataReceived: 0 - * // } - * ``` - * @param {import('.').AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/bitswap').API["stat"]} */ - async function stat (options) { - const { bitswap } = await network.use(options) + async function stat (options = {}) { + /** @type {import('ipfs-bitswap')} */ + const bitswap = (await network.use(options)).bitswap const snapshot = bitswap.stat().snapshot return { provideBufLen: parseInt(snapshot.providesBufferLength.toString()), - blocksReceived: new Big(snapshot.blocksReceived), + blocksReceived: BigInt(snapshot.blocksReceived.toString()), wantlist: Array.from(bitswap.getWantlist()).map(e => e[1].cid), peers: bitswap.peers().map(id => new CID(id.toB58String())), - dupBlksReceived: new Big(snapshot.dupBlksReceived), - dupDataReceived: new Big(snapshot.dupDataReceived), - dataReceived: new Big(snapshot.dataReceived), - blocksSent: new Big(snapshot.blocksSent), - dataSent: new Big(snapshot.dataSent) + dupBlksReceived: BigInt(snapshot.dupBlksReceived.toString()), + dupDataReceived: BigInt(snapshot.dupDataReceived.toString()), + dataReceived: BigInt(snapshot.dataReceived.toString()), + blocksSent: BigInt(snapshot.blocksSent.toString()), + dataSent: BigInt(snapshot.dataSent.toString()) } } return withTimeoutOption(stat) } - -/** - * @typedef {object} BitswapStats - An object that contains information about the bitswap agent - * @property {number} provideBufLen - an integer - * @property {CID[]} wantlist - * @property {CID[]} peers - array of peer IDs - * @property {Big} blocksReceived - * @property {Big} dataReceived - * @property {Big} blocksSent - * @property {Big} dataSent - * @property {Big} dupBlksReceived - * @property {Big} dupDataReceived - */ diff --git a/packages/ipfs-core/src/components/bitswap/unwant.js b/packages/ipfs-core/src/components/bitswap/unwant.js index bcfc308c36..e86306c940 100644 --- a/packages/ipfs-core/src/components/bitswap/unwant.js +++ b/packages/ipfs-core/src/components/bitswap/unwant.js @@ -6,30 +6,13 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Removes one or more CIDs from the wantlist - * - * @example - * ```JavaScript - * let list = await ipfs.bitswap.wantlist() - * console.log(list) - * // [ CID('QmHash') ] - * - * await ipfs.bitswap.unwant(cid) - * - * list = await ipfs.bitswap.wantlist() - * console.log(list) - * // [] - * ``` - * - * @param {CID | CID[]} cids - The CIDs to remove from the wantlist - * @param {AbortOptions} [options] - * @returns {Promise} - A promise that resolves once the request is complete + * @type {import('ipfs-core-types/src/bitswap').API["unwant"]} */ - async function unwant (cids, options) { + async function unwant (cids, options = {}) { const { bitswap } = await network.use(options) if (!Array.isArray(cids)) { @@ -42,12 +25,8 @@ module.exports = ({ network }) => { throw errCode(err, 'ERR_INVALID_CID') } - return bitswap.unwant(cids, options) + return bitswap.unwant(cids) } return withTimeoutOption(unwant) } - -/** - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/bitswap/wantlist-for-peer.js b/packages/ipfs-core/src/components/bitswap/wantlist-for-peer.js index 12d9958da0..d22db8031f 100644 --- a/packages/ipfs-core/src/components/bitswap/wantlist-for-peer.js +++ b/packages/ipfs-core/src/components/bitswap/wantlist-for-peer.js @@ -5,23 +5,11 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Returns the wantlist for a connected peer - * - * @example - * ```js - * const list = await ipfs.bitswap.wantlistForPeer(peerId) - * console.log(list) - * // [ CID('QmHash') ] - * ``` - * - * @param {PeerId | CID | string | Uint8Array} peerId - A peer ID to return the wantlist for\ - * @param {AbortOptions} [options] - * @returns {Promise} - An array of CIDs currently in the wantlist - * + * @type {import('ipfs-core-types/src/bitswap').API["wantlistForPeer"]} */ async function wantlistForPeer (peerId, options = {}) { const { bitswap } = await network.use(options) @@ -32,16 +20,3 @@ module.exports = ({ network }) => { return withTimeoutOption(wantlistForPeer) } - -/** - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').CID} CID - */ - -/** - * @template ExtraOptions - * @callback WantlistForPeer - * @param {PeerId | CID | string | Uint8Array} peerId - * @param {AbortOptions & ExtraOptions} [options] - * @returns {Promise} - */ diff --git a/packages/ipfs-core/src/components/bitswap/wantlist.js b/packages/ipfs-core/src/components/bitswap/wantlist.js index 9f2e0d0298..5acaafdedd 100644 --- a/packages/ipfs-core/src/components/bitswap/wantlist.js +++ b/packages/ipfs-core/src/components/bitswap/wantlist.js @@ -4,33 +4,18 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Returns the wantlist for your node - * - * @example - * ```js - * const list = await ipfs.bitswap.wantlist() - * console.log(list) - * // [ CID('QmHash') ] - * ``` - * - * @param {AbortOptions} [options] - * @returns {Promise} - An array of CIDs currently in the wantlist. + * @type {import('ipfs-core-types/src/bitswap').API["wantlist"]} */ async function wantlist (options = {}) { const { bitswap } = await network.use(options) - const list = bitswap.getWantlist(options) + const list = bitswap.getWantlist() return Array.from(list).map(e => e[1].cid) } return withTimeoutOption(wantlist) } - -/** - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').CID} CID - */ diff --git a/packages/ipfs-core/src/components/block/get.js b/packages/ipfs-core/src/components/block/get.js index 42ea8b22ff..772e15f76f 100644 --- a/packages/ipfs-core/src/components/block/get.js +++ b/packages/ipfs-core/src/components/block/get.js @@ -5,22 +5,12 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').BlockService} config.blockService - * @param {import('.').Preload} config.preload + * @param {import('ipfs-block-service')} config.blockService + * @param {import('../../types').Preload} config.preload */ module.exports = ({ blockService, preload }) => { /** - * Get a raw IPFS block. - * - * @param {CID | string | Uint8Array} cid - A CID that corresponds to the desired block - * @param {GetOptions & AbortOptions} [options] - * @returns {Promise} - A Block type object, containing both the data and the hash of the block - * - * @example - * ```js - * const block = await ipfs.block.get(cid) - * console.log(block.data) - * ``` + * @type {import('ipfs-core-types/src/block').API["get"]} */ async function get (cid, options = {}) { // eslint-disable-line require-await cid = cleanCid(cid) @@ -34,12 +24,3 @@ module.exports = ({ blockService, preload }) => { return withTimeoutOption(get) } - -/** - * @typedef {Object} GetOptions - * @property {boolean} [preload=true] - * - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').CID} CID - * @typedef {import('.').IPLDBlock} IPLDBlock - */ diff --git a/packages/ipfs-core/src/components/block/index.js b/packages/ipfs-core/src/components/block/index.js index 252a49d115..fd11eaf27c 100644 --- a/packages/ipfs-core/src/components/block/index.js +++ b/packages/ipfs-core/src/components/block/index.js @@ -5,6 +5,14 @@ const createPut = require('./put') const createRm = require('./rm') const createStat = require('./stat') +/** + * @typedef {import('../../types').Preload} Preload + * @typedef {import('ipfs-block-service')} BlockService + * @typedef {import('../gc-lock').GCLock} GCLock + * @typedef {import('ipfs-core-types/src/pin').API} Pin + * @typedef {import('../pin/pin-manager')} PinManager + */ + class BlockAPI { /** * @param {Object} config @@ -23,14 +31,3 @@ class BlockAPI { } module.exports = BlockAPI - -/** - * @typedef {import('..').Preload} Preload - * @typedef {import('..').BlockService} BlockService - * @typedef {import('..').GCLock} GCLock - * @typedef {import('..').Pin} Pin - * @typedef {import('..').PinManager} PinManager - * @typedef {import('..').AbortOptions} AbortOptions - * @typedef {import('..').CID} CID - * @typedef {import('..').IPLDBlock} IPLDBlock - */ diff --git a/packages/ipfs-core/src/components/block/put.js b/packages/ipfs-core/src/components/block/put.js index 4c65a0da55..77002b2cb0 100644 --- a/packages/ipfs-core/src/components/block/put.js +++ b/packages/ipfs-core/src/components/block/put.js @@ -6,54 +6,20 @@ const CID = require('cids') const isIPFS = require('is-ipfs') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('cids').CIDVersion} CIDVersion + */ + /** * @param {Object} config - * @param {import('.').BlockService} config.blockService - * @param {import('.').Pin} config.pin + * @param {import('ipfs-block-service')} config.blockService + * @param {import('ipfs-core-types/src/pin').API} config.pin * @param {import('.').GCLock} config.gcLock - * @param {import('.').Preload} config.preload + * @param {import('../../types').Preload} config.preload */ module.exports = ({ blockService, pin, gcLock, preload }) => { /** - * Stores input as an IPFS block. - * - * **Note:** If you pass a `Block` instance as the block parameter, you - * don't need to pass options, as the block instance will carry the CID - * value as a property. - * - * @example - * ```js - * // Defaults - * const encoder = new TextEncoder() - * const decoder = new TextDecoder() - * - * const bytes = encoder.encode('a serialized object') - * const block = await ipfs.block.put(bytes) - * - * console.log(decoder.decode(block.data)) - * // Logs: - * // a serialized object - * console.log(block.cid.toString()) - * // Logs: - * // the CID of the object - * - * // With custom format and hashtype through CID - * const CID = require('cids') - * const another = encoder.encode('another serialized object') - * const cid = new CID(1, 'dag-pb', multihash) - * const block = await ipfs.block.put(another, cid) - * console.log(decoder.decode(block.data)) - * - * // Logs: - * // a serialized object - * console.log(block.cid.toString()) - * // Logs: - * // the CID of the object - * ``` - * - * @param {IPLDBlock|Uint8Array} block - The block or data to store - * @param {PutOptions & AbortOptions} [options] - **Note:** If you pass a `Block` instance as the block parameter, you don't need to pass options, as the block instance will carry the CID value as a property. - * @returns {Promise} - A Block type object, containing both the data and the hash of the block + * @type {import('ipfs-core-types/src/block').API["put"]} */ async function put (block, options = {}) { if (Array.isArray(block)) { @@ -115,18 +81,3 @@ module.exports = ({ blockService, pin, gcLock, preload }) => { return withTimeoutOption(put) } - -/** - * @typedef {Object} PutOptions - * @property {CID} [cid] - A CID to store the block under (default: `undefined`) - * @property {string} [format='dag-pb'] - The codec to use to create the CID (default: `'dag-pb'`) - * @property {import('multihashes').HashName} [mhtype='sha2-256'] - The hashing algorithm to use to create the CID (default: `'sha2-256'`) - * @property {number} [mhlen] - * @property {CIDVersion} [version=0] - The version to use to create the CID (default: `0`) - * @property {boolean} [pin=false] - If true, pin added blocks recursively (default: `false`) - * @property {boolean} [preload] - * - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').IPLDBlock} IPLDBlock - * @typedef {0|1} CIDVersion - */ diff --git a/packages/ipfs-core/src/components/block/rm.js b/packages/ipfs-core/src/components/block/rm.js index 4f05a387f5..3ac995c375 100644 --- a/packages/ipfs-core/src/components/block/rm.js +++ b/packages/ipfs-core/src/components/block/rm.js @@ -12,29 +12,13 @@ const BLOCK_RM_CONCURRENCY = 8 /** * @param {Object} config - * @param {import('.').BlockService} config.blockService - * @param {import('.').PinManager} config.pinManager + * @param {import('ipfs-block-service')} config.blockService + * @param {import('../pin/pin-manager')} config.pinManager * @param {import('.').GCLock} config.gcLock */ module.exports = ({ blockService, gcLock, pinManager }) => { /** - /** - * Remove one or more IPFS block(s). - * - * @param {CID[]|CID} cids - CID(s) corresponding to the block(s) to be removed. - * @param {RmOptions & AbortOptions} [options] - * @returns {AsyncIterable} - * - * @example - * ```js - * for await (const result of ipfs.block.rm(cid)) { - * if (result.error) { - * console.error(`Failed to remove block ${result.cid} due to ${result.error.message}`) - * } else { - * console.log(`Removed block ${result.cid}`) - * } - * } - * ``` + * @type {import('ipfs-core-types/src/block').API["rm"]} */ async function * rm (cids, options = {}) { if (!Array.isArray(cids)) { @@ -51,6 +35,7 @@ module.exports = ({ blockService, gcLock, pinManager }) => { parallelMap(BLOCK_RM_CONCURRENCY, async cid => { cid = cleanCid(cid) + /** @type {import('ipfs-core-types/src/block').RmResult} */ const result = { cid } try { @@ -58,10 +43,10 @@ module.exports = ({ blockService, gcLock, pinManager }) => { if (pinResult.pinned) { if (CID.isCID(pinResult.reason)) { // eslint-disable-line max-depth - throw errCode(new Error(`pinned via ${pinResult.reason}`)) + throw errCode(new Error(`pinned via ${pinResult.reason}`), 'ERR_BLOCK_PINNED') } - throw errCode(new Error(`pinned: ${pinResult.reason}`)) + throw errCode(new Error(`pinned: ${pinResult.reason}`), 'ERR_BLOCK_PINNED') } // remove has check when https://github.com/ipfs/js-ipfs-block-service/pull/88 is merged @@ -91,24 +76,3 @@ module.exports = ({ blockService, gcLock, pinManager }) => { return withTimeoutOption(rm) } - -/** - * @typedef {Object} RmOptions - * @property {boolean} [force=false] - Ignores nonexistent blocks - * @property {boolean} [quiet=false] - Write minimal output - * - * @typedef {import('.').AbortOptions} AbortOptions - * - * @typedef {RmSucceess|RmFailure} RmResult - * Note: If an error is present for a given object, the block with - * that cid was not removed and the error will contain the reason why, - * for example if the block was pinned. - * - * @typedef {Object} RmSucceess - * @property {CID} cid - * @property {void} [error] - * - * @typedef {Object} RmFailure - * @property {CID} cid - * @property {Error} error - */ diff --git a/packages/ipfs-core/src/components/block/stat.js b/packages/ipfs-core/src/components/block/stat.js index 080530fd7b..191479ccb7 100644 --- a/packages/ipfs-core/src/components/block/stat.js +++ b/packages/ipfs-core/src/components/block/stat.js @@ -5,27 +5,13 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').BlockService} config.blockService - * @param {import('.').Preload} config.preload + * @param {import('ipfs-block-service')} config.blockService + * @param {import('../../types').Preload} config.preload */ module.exports = ({ blockService, preload }) => { /** - /** - * Print information of a raw IPFS block. - * - * @param {CID} cid - CID of the block to get a stats for. - * @param {StatOptions & AbortOptions} options - * @returns {Promise} - * @example - * ```js - * const cid = CID.from('QmQULBtTjNcMwMr4VMNknnVv3RpytrLSdgpvMcTnfNhrBJ') - * const stats = await ipfs.block.stat(cid) - * console.log(stats.cid.toString()) - * // Logs: QmQULBtTjNcMwMr4VMNknnVv3RpytrLSdgpvMcTnfNhrBJ - * console.log(stat.size) - * // Logs: 3739 - * ``` + * @type {import('ipfs-core-types/src/block').API["stat"]} */ async function stat (cid, options = {}) { cid = cleanCid(cid) @@ -41,16 +27,3 @@ module.exports = ({ blockService, preload }) => { return withTimeoutOption(stat) } - -/** - * @typedef {Object} Stat - * An object containing the block's info - * @property {CID} cid - * @property {number} size - * - * @typedef {Object} StatOptions - * @property {boolean} [preload] - * - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').CID} CID - */ diff --git a/packages/ipfs-core/src/components/bootstrap/add.js b/packages/ipfs-core/src/components/bootstrap/add.js index d7b44421a9..47275d179c 100644 --- a/packages/ipfs-core/src/components/bootstrap/add.js +++ b/packages/ipfs-core/src/components/bootstrap/add.js @@ -5,37 +5,27 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { /** - * Add a peer address to the bootstrap list - * - * @param {Multiaddr} multiaddr - The address of a network peer - * @param {AbortOptions} [options] - * @returns {Promise} - * @example - * ```js - * const validIp4 = '/ip4/104....9z' - * - * const res = await ipfs.bootstrap.add(validIp4) - * console.log(res.Peers) - * // Logs: - * // ['/ip4/104....9z'] - * ``` + * @type {import('ipfs-core-types/src/bootstrap').API["add"]} */ async function add (multiaddr, options = {}) { if (!isValidMultiaddr(multiaddr)) { throw new Error(`${multiaddr} is not a valid Multiaddr`) } + /** @type {import('ipfs-core-types/src/config').Config} */ + // @ts-ignore repo returns type unknown const config = await repo.config.getAll(options) - // @ts-ignore - May not have `Bootstrap` - if (config.Bootstrap.indexOf(multiaddr.toString()) === -1) { - // @ts-ignore - May not have `Bootstrap` - config.Bootstrap.push(multiaddr.toString()) - } + const boostrappers = config.Bootstrap || [] + boostrappers.push(multiaddr.toString()) + + config.Bootstrap = Array.from( + new Set(boostrappers) + ).sort((a, b) => a.localeCompare(b)) await repo.config.replace(config) @@ -46,10 +36,3 @@ module.exports = ({ repo }) => { return withTimeoutOption(add) } - -/** - * @typedef {import('./utils').Peers} Peers - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').CID} CID - * @typedef {import('.').Multiaddr} Multiaddr - */ diff --git a/packages/ipfs-core/src/components/bootstrap/clear.js b/packages/ipfs-core/src/components/bootstrap/clear.js index a755451a81..f4a8e672a9 100644 --- a/packages/ipfs-core/src/components/bootstrap/clear.js +++ b/packages/ipfs-core/src/components/bootstrap/clear.js @@ -5,23 +5,15 @@ const Multiaddr = require('multiaddr') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { /** - * Remove all peer addresses from the bootstrap list - * - * @param {AbortOptions} options - * @returns {Promise} - * @example - * ```js - * const res = await ipfs.bootstrap.clear() - * console.log(res.Peers) - * // Logs: - * // [address1, address2, ...] - * ``` + * @type {import('ipfs-core-types/src/bootstrap').API["clear"]} */ async function clear (options = {}) { + /** @type {import('ipfs-core-types/src/config').Config} */ + // @ts-ignore repo returns type unknown const config = await repo.config.getAll(options) const removed = config.Bootstrap || [] config.Bootstrap = [] @@ -33,8 +25,3 @@ module.exports = ({ repo }) => { return withTimeoutOption(clear) } - -/** - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('./utils').Peers} Peers - */ diff --git a/packages/ipfs-core/src/components/bootstrap/index.js b/packages/ipfs-core/src/components/bootstrap/index.js index 3cb7c9dafa..72a568d9c6 100644 --- a/packages/ipfs-core/src/components/bootstrap/index.js +++ b/packages/ipfs-core/src/components/bootstrap/index.js @@ -8,7 +8,7 @@ const createRm = require('./rm') class BootstrapAPI { /** * @param {Object} config - * @param {Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ constructor ({ repo }) { this.add = createAdd({ repo }) @@ -19,10 +19,3 @@ class BootstrapAPI { } } module.exports = BootstrapAPI - -/** - * @typedef {import('..').Repo} Repo - * @typedef {import('..').AbortOptions} AbortOptions - * @typedef {import('..').CID} CID - * @typedef {import('..').Multiaddr} Multiaddr - */ diff --git a/packages/ipfs-core/src/components/bootstrap/list.js b/packages/ipfs-core/src/components/bootstrap/list.js index 87785d3df6..3bd9d3c06f 100644 --- a/packages/ipfs-core/src/components/bootstrap/list.js +++ b/packages/ipfs-core/src/components/bootstrap/list.js @@ -5,23 +5,13 @@ const Multiaddr = require('multiaddr') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { /** - * List all peer addresses in the bootstrap list - * - * @param {AbortOptions} [options] - * @returns {Promise} - * @example - * ```js - * const res = await ipfs.bootstrap.list() - * console.log(res.Peers) - * // Logs: - * // [address1, address2, ...] - * ``` + * @type {import('ipfs-core-types/src/bootstrap').API["list"]} */ - async function list (options) { + async function list (options = {}) { /** @type {string[]|null} */ const peers = (await repo.config.get('Bootstrap', options)) return { Peers: (peers || []).map(ma => new Multiaddr(ma)) } @@ -29,9 +19,3 @@ module.exports = ({ repo }) => { return withTimeoutOption(list) } - -/** - * @typedef {import('./utils').Peers} Peers - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').CID} CID - */ diff --git a/packages/ipfs-core/src/components/bootstrap/reset.js b/packages/ipfs-core/src/components/bootstrap/reset.js index 9fdf3bc743..c1bcf951b5 100644 --- a/packages/ipfs-core/src/components/bootstrap/reset.js +++ b/packages/ipfs-core/src/components/bootstrap/reset.js @@ -6,23 +6,15 @@ const Multiaddr = require('multiaddr') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { /** - * List all peer addresses in the bootstrap list - * - * @param {AbortOptions} options - * @returns {Promise} - * @example - * ```js - * const res = await ipfs.bootstrap.list() - * console.log(res.Peers) - * // Logs: - * // [address1, address2, ...] - * ``` + * @type {import('ipfs-core-types/src/bootstrap').API["reset"]} */ async function reset (options = {}) { + /** @type {import('ipfs-core-types/src/config').Config} */ + // @ts-ignore repo returns type unknown const config = await repo.config.getAll(options) config.Bootstrap = defaultConfig().Bootstrap @@ -35,8 +27,3 @@ module.exports = ({ repo }) => { return withTimeoutOption(reset) } - -/** - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('./utils').Peers} Peers - */ diff --git a/packages/ipfs-core/src/components/bootstrap/rm.js b/packages/ipfs-core/src/components/bootstrap/rm.js index 1e10b1b87b..a326748a04 100644 --- a/packages/ipfs-core/src/components/bootstrap/rm.js +++ b/packages/ipfs-core/src/components/bootstrap/rm.js @@ -5,28 +5,19 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { /** - * Remove a peer address from the bootstrap list - * - * @param {Multiaddr} multiaddr - The address of a network peer - * @param {AbortOptions} options - * @returns {Promise} - * @example - * ```js - * const res = await ipfs.bootstrap.list() - * console.log(res.Peers) - * // Logs: - * // [address1, address2, ...] - * ``` + * @type {import('ipfs-core-types/src/bootstrap').API["rm"]} */ async function rm (multiaddr, options = {}) { if (!isValidMultiaddr(multiaddr)) { throw new Error(`${multiaddr} is not a valid Multiaddr`) } + /** @type {import('ipfs-core-types/src/config').Config} */ + // @ts-ignore repo returns type unknown const config = await repo.config.getAll(options) config.Bootstrap = (config.Bootstrap || []).filter(ma => ma.toString() !== multiaddr.toString()) @@ -37,9 +28,3 @@ module.exports = ({ repo }) => { return withTimeoutOption(rm) } - -/** - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').Multiaddr} Multiaddr - * @typedef {import('./utils').Peers} Peers - */ diff --git a/packages/ipfs-core/src/components/bootstrap/utils.js b/packages/ipfs-core/src/components/bootstrap/utils.js index 48dd2c61d7..41762b870f 100644 --- a/packages/ipfs-core/src/components/bootstrap/utils.js +++ b/packages/ipfs-core/src/components/bootstrap/utils.js @@ -4,7 +4,6 @@ const isMultiaddr = require('mafmt').IPFS.matches /** * @param {any} ma - * @returns {boolean} */ exports.isValidMultiaddr = ma => { try { @@ -13,11 +12,3 @@ exports.isValidMultiaddr = ma => { return false } } - -/** - * @typedef {Object} Peers - * An object that contains an array with all the added addresses - * @property {Array} Peers - * - * @typedef {import('..').Multiaddr} Multiaddr - */ diff --git a/packages/ipfs-core/src/components/cat.js b/packages/ipfs-core/src/components/cat.js index 8146ec4119..e161a608d3 100644 --- a/packages/ipfs-core/src/components/cat.js +++ b/packages/ipfs-core/src/components/cat.js @@ -1,23 +1,19 @@ 'use strict' -const exporter = require('ipfs-unixfs-exporter') +const { exporter } = require('ipfs-unixfs-exporter') const { normalizeCidPath } = require('../utils') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @typedef {Object} Context - * @property {import('.').IPLD} ipld - * @property {import('.').Preload} preload + * @property {import('ipld')} ipld + * @property {import('../types').Preload} preload * * @param {Context} context */ module.exports = function ({ ipld, preload }) { /** - * Returns content of the file addressed by a valid IPFS Path or CID. - * - * @param {import('ipfs-core-types/src/root').IPFSPath} ipfsPath - * @param {import('ipfs-core-types/src/root').CatOptions} [options] - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/root').API["cat"]} */ async function * cat (ipfsPath, options = {}) { ipfsPath = normalizeCidPath(ipfsPath) @@ -30,7 +26,7 @@ module.exports = function ({ ipld, preload }) { const file = await exporter(ipfsPath, ipld, options) // File may not have unixfs prop if small & imported with rawLeaves true - if (file.unixfs && file.unixfs.type.includes('dir')) { + if (file.type === 'directory') { throw new Error('this dag node is a directory') } diff --git a/packages/ipfs-core/src/components/config.js b/packages/ipfs-core/src/components/config.js index bc598485ae..c20169573e 100644 --- a/packages/ipfs-core/src/components/config.js +++ b/packages/ipfs-core/src/components/config.js @@ -4,9 +4,17 @@ const getDefaultConfig = require('../runtime/config-nodejs.js') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') const log = require('debug')('ipfs:core:config') +/** + * @typedef {import('ipfs-core-types/src/config').Config} Config + * + * @typedef {object} Transformer + * @property {string} description + * @property {(config: Config) => Config} transform + */ + /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { return { @@ -21,49 +29,43 @@ module.exports = ({ repo }) => { } /** - * @param {AbortOptions} [options] + * @type {import('ipfs-core-types/src/config').API["getAll"]} */ async function getAll (options = {}) { // eslint-disable-line require-await + // @ts-ignore TODO: move config typedefs into ipfs-repo return repo.config.getAll(options) } /** - * - * @param {string} key - * @param {AbortOptions} [options] + * @type {import('ipfs-core-types/src/config').API["get"]} */ async function get (key, options) { // eslint-disable-line require-await if (!key) { return Promise.reject(new Error('key argument is required')) } + // @ts-ignore TODO: move config typedefs into ipfs-repo return repo.config.get(key, options) } /** - * - * @param {string} key - * @param {ToJSON} value - * @param {AbortOptions} [options] + * @type {import('ipfs-core-types/src/config').API["set"]} */ async function set (key, value, options) { // eslint-disable-line require-await return repo.config.set(key, value, options) } /** - * @param {IPFSConfig} value - * @param {AbortOptions} [options] + * @type {import('ipfs-core-types/src/config').API["replace"]} */ async function replace (value, options) { // eslint-disable-line require-await return repo.config.replace(value, options) } /** - * @param {string} profileName - * @param {*} options - * @returns {Promise<{original: IPFSConfig, updated: IPFSConfig}>} + * @type {import('ipfs-core-types/src/config/profiles').API["apply"]} */ - async function applyProfile (profileName, options = {}) { + async function applyProfile (profileName, options = { dryRun: false }) { const { dryRun } = options const profile = profiles[profileName] @@ -86,6 +88,7 @@ module.exports = ({ repo }) => { delete oldCfg.Identity.PrivKey delete newCfg.Identity.PrivKey + // @ts-ignore TODO: move config typedefs into ipfs-repo return { original: oldCfg, updated: newCfg } } catch (err) { log(err) @@ -96,8 +99,7 @@ module.exports = ({ repo }) => { } /** - * @param {any} _options - * @returns {Promise<{name:string, description:string}[]>} + * @type {import('ipfs-core-types/src/config/profiles').API["list"]} */ async function listProfiles (_options) { // eslint-disable-line require-await return Object.keys(profiles).map(name => ({ @@ -106,13 +108,12 @@ async function listProfiles (_options) { // eslint-disable-line require-await })) } +/** + * @type {Record} + */ const profiles = { server: { description: 'Recommended for nodes with public IPv4 address (servers, VPSes, etc.), disables host and content discovery and UPnP in local networks.', - /** - * @param {IPFSConfig} config - * @returns {IPFSConfig} - */ transform: (config) => { config.Discovery.MDNS.Enabled = false config.Discovery.webRTCStar.Enabled = false @@ -126,10 +127,6 @@ const profiles = { }, 'local-discovery': { description: 'Sets default values to fields affected by `server` profile, enables discovery and UPnP in local networks.', - /** - * @param {IPFSConfig} config - * @returns {IPFSConfig} - */ transform: (config) => { config.Discovery.MDNS.Enabled = true config.Discovery.webRTCStar.Enabled = true @@ -143,10 +140,6 @@ const profiles = { }, test: { description: 'Reduces external interference, useful for running ipfs in test environments. Note that with these settings node won\'t be able to talk to the rest of the network without manual bootstrap.', - /** - * @param {IPFSConfig} config - * @returns {IPFSConfig} - */ transform: (config) => { const defaultConfig = getDefaultConfig() @@ -167,10 +160,6 @@ const profiles = { }, 'default-networking': { description: 'Restores default network settings. Inverse profile of the `test` profile.', - /** - * @param {IPFSConfig} config - * @returns {IPFSConfig} - */ transform: (config) => { const defaultConfig = getDefaultConfig() @@ -191,10 +180,6 @@ const profiles = { }, lowpower: { description: 'Reduces daemon overhead on the system. May affect node functionality,performance of content discovery and data fetching may be degraded. Recommended for low power systems.', - /** - * @param {IPFSConfig} config - * @returns {IPFSConfig} - */ transform: (config) => { const Swarm = config.Swarm || {} const ConnMgr = Swarm.ConnMgr || {} @@ -209,10 +194,6 @@ const profiles = { }, 'default-power': { description: 'Inverse of "lowpower" profile.', - /** - * @param {IPFSConfig} config - * @returns {IPFSConfig} - */ transform: (config) => { const defaultConfig = getDefaultConfig() @@ -225,303 +206,3 @@ const profiles = { } module.exports.profiles = profiles - -/** - * @typedef {Object} Config - * @property {Get} get - * @property {GetAll} getAll - * @property {Set} set - * @property {Replace} replace - * @property {Profiles} profiles - * - * @callback Get - * Returns the currently being used config. If the daemon is off, it returns - * the stored config. - * - * @param {string} key - The key of the value that should be fetched from the - * config file. If no key is passed, then the whole config will be returned. - * @param {AbortOptions} [options] - * @returns {Promise} - An object containing the configuration of the IPFS node - * @example - * const config = await ipfs.config.get('Addresses.Swarm') - * console.log(config) - * - * - * @callback GetAll - * Returns the full config been used. If the daemon is off, it returns the - * stored config. - * - * @param {AbortOptions} [options] - * @returns {Promise} - * @example - * const config = await ipfs.config.getAll() - * console.log(config) - * - * @callback Set - * Adds or replaces a config value. Note that this operation will not spark the - * restart of any service, i.e: if a config.replace changes the multiaddrs of - * the Swarm, Swarm will have to be restarted manually for the changes to take - * an effect. - * - * @param {string} key - The key of the value that should be added or replaced. - * @param {ToJSON} value - The value to be set. - * @param {AbortOptions} [options] - * @returns {Promise} - Promise succeeds if config change succeeded, - * otherwise fails with error. - * @example - * // Disable MDNS Discovery - * await ipfs.config.set('Discovery.MDNS.Enabled', false) - * - * @callback Replace - * Adds or replaces a config file. - * - * Note that this operation will not spark the restart of any service, - * i.e: if a config.replace changes the multiaddrs of the Swarm, Swarm will - * have to be restarted manually for the changes to take an effect. - * - * @param {IPFSConfig} value - A new configuration. - * @param {AbortOptions} [options] - * @returns {Promise} - * @example - * const newConfig = { - * Bootstrap: [] - * } - * await ipfs.config.replace(newConfig) - * - * @typedef {Object} Profiles - * @property {ListProfiles} list - * @property {ApplyProfile} apply - * - * @callback ListProfiles - * List available config profiles - * @param {AbortOptions} [options] - * @returns {Promise} - An array with all the available config profiles - * @example - * const profiles = await ipfs.config.profiles.list() - * profiles.forEach(profile => { - * console.info(profile.name, profile.description) - * }) - * - * @typedef {Object} Profile - * @property {string} description - * @property {string} name - * - * - * @callback ApplyProfile - * List available config profiles - * @param {string} name - * @param {ApplyOptions & AbortOptions} [options] - * @returns {Promise<{original: IPFSConfig, updated: IPFSConfig}>} - * - * @typedef {Object} ApplyOptions - * @property {boolean} [dryRun=false] - If true does not apply the profile - * - * - * @typedef {Object} IPFSConfig - * @property {AddressConfig} Addresses - * @property {string} [Profiles] - * @property {string[]} [Bootstrap] - * @property {DiscoveryConfig} Discovery - * @property {DatastoreConfig} [Datastore] - * @property {IdentityConfig} [Identity] - * @property {KeychainConfig} [Keychain] - * @property {PubsubConfig} [Pubsub] - * @property {SwarmConfig} [Swarm] - * @property {RoutingConfig} [Routing] - * - * @typedef {Object} AddressConfig - * Contains information about various listener addresses to be used by this node. - * @property {APIAddress} [API='/ip4/127.0.0.1/tcp/5002'] - * @property {DelegateAddress} [Delegates=[]] - * @property {GatewayAddress} [Gateway='/ip4/127.0.0.1/tcp/9090'] - * @property {SwarmAddress} [Swarm=['/ip4/0.0.0.0/tcp/4002', '/ip4/127.0.0.1/tcp/4003/ws']] - * * - * @typedef {string} Multiaddr - * Composable and future-proof network address following [Multiaddr][] - * specification. - * - * [Multiaddr]:https://github.com/multiformats/multiaddr/ - * - * @typedef {Multiaddr|Multiaddr[]} APIAddress - * The IPFS daemon exposes an [HTTP API][] that allows to control the node and - * run the same commands as you can do from the command line. It is defined on - * the [HTTP API][] Spec. - * - * [Multiaddr][] or array of [Multiaddr][] describing the address(es) to serve the - * [HTTP API][] on. - * - * [Multiaddr]:https://github.com/multiformats/multiaddr/ - * [HTTP API]:https://docs.ipfs.io/reference/api/http - * - * @typedef {Multiaddr[]} DelegateAddress - * Delegate peers are used to find peers and retrieve content from the network - * on your behalf. - * - * Array of [Multiaddr][] describing which addresses to use as delegate nodes. - * - * [Multiaddr]:https://github.com/multiformats/multiaddr/ - * - * @typedef {Multiaddr|Multiaddr[]} GatewayAddress - * A gateway is exposed by the IPFS daemon, which allows an easy way to access - * content from IPFS, using an IPFS path. - * - * [Multiaddr][] or array of [Multiaddr][] describing the address(es) to serve - * the gateway on. - * - * [Multiaddr]:https://github.com/multiformats/multiaddr/ - * - * @typedef {Multiaddr[]} SwarmAddress - * Array of [Multiaddr][] describing which addresses to listen on for p2p swarm - * connections. - * - * [Multiaddr]:https://github.com/multiformats/multiaddr/ - * - * - * @typedef {Multiaddr[]} BootstrapConfig - * Bootstrap is an array of [Multiaddr][] of trusted nodes to connect to in order - * to initiate a connection to the network. - * - * [Multiaddr]:https://github.com/multiformats/multiaddr/ - * - * @typedef {Object} DatastoreConfig - * Contains information related to the construction and operation of the on-disk - * storage system. - * @property {DatastoreSpec} [Spec] - * - * @typedef {Object} DatastoreSpec - * Spec defines the structure of the IPFS datastore. It is a composable - * structure, where each datastore is represented by a JSON object. Datastores - * can wrap other datastores to provide extra functionality (e.g. metrics, - * logging, or caching). - * - * This can be changed manually, however, if you make any changes that require - * a different on-disk structure, you will need to run the [ipfs-ds-convert][] - * tool to migrate data into the new structures. - * - * [ipfs-ds-convert]:https://github.com/ipfs/ipfs-ds-convert - * - * Default: - * ```json - * { - * "mounts": [ - * { - * "child": { - * "path": "blocks", - * "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2", - * "sync": true, - * "type": "flatfs" - * }, - * "mountpoint": "/blocks", - * "prefix": "flatfs.datastore", - * "type": "measure" - * }, - * { - * "child": { - * "compression": "none", - * "path": "datastore", - * "type": "levelds" - * }, - * "mountpoint": "/", - * "prefix": "leveldb.datastore", - * "type": "measure" - * } - * ], - * "type": "mount" - * } - * ``` - * - * @typedef {Object} DiscoveryConfig - * Contains options for configuring IPFS node discovery mechanisms. - * @property {MDNSDiscovery} MDNS - * @property {WebRTCStarDiscovery} webRTCStar - * - * @typedef {Object} MDNSDiscovery - * Multicast DNS is a discovery protocol that is able to find other peers on the local network. - * @property {boolean} [Enabled=true] - A boolean value for whether or not MDNS - * should be active. - * @property {number} [Interval=10] - A number of seconds to wait between - * discovery checks. - * - * @typedef {Object} WebRTCStarDiscovery - * WebRTCStar is a discovery mechanism prvided by a signalling-star that allows - * peer-to-peer communications in the browser. - * @property {boolean} [Enabled=true] - A boolean value for whether or not - * webRTCStar should be active. - * - * @typedef {Object} IdentityConfig - * @property {PeerID} [PeerID] - * @property {PrivateKey} [PrivKey] - * - * @typedef {string} PeerID - * The unique PKI identity label for this configs peer. Set on init and never - * read, its merely here for convenience. IPFS will always generate the peerID - * from its keypair at runtime. - * - * @typedef {string} PrivateKey - * The base64 encoded protobuf describing (and containing) the nodes private key. - * - * @typedef {Object} KeychainConfig - * We can customize the key management and criptographically protected messages - * by changing the Keychain options. Those options are used for generating the - * derived encryption key (DEK). - * - * The DEK object, along with the passPhrase, is the input to a PBKDF2 function. - * - * You can check the [parameter choice for pbkdf2](https://cryptosense.com/parameter-choice-for-pbkdf2/) - * for more information. - * @property {DEK} DEK - * - * @typedef {Object} DEK - * @property {number} keyLength - * @property {number} iterationCount - * @property {string} salt - * @property {string} hash - * - * @typedef {Object} PubsubConfig - * Options for configuring the pubsub subsystem. It is important pointing out - * that this is not supported in the browser. If you want to configure a - * different pubsub router in the browser you must configure - * `libp2p.modules.pubsub` options instead. - * - * @property {PubSubRouter} [Router='gossipsub'] - * @property {boolean} [Enabled=true] - * - * @typedef {'gossipsub'|'floodsub'} PubSubRouter - * A string value for specifying which pubsub routing protocol to use. You can - * either use `'gossipsub'` in order to use the [ChainSafe/gossipsub-js] - * (https://github.com/ChainSafe/gossipsub-js) implementation, or `'floodsub'` - * to use the [libp2p/js-libp2p-floodsub](https://github.com/libp2p/js-libp2p-floodsub) - * implementation. - * - * You can read more about these implementations on the [libp2p/specs/pubsub] - * (https://github.com/libp2p/specs/tree/master/pubsub) document. - * - * @typedef {Object} SwarmConfig - * Options for configuring the swarm. - * @property {ConnMgrConfig} [ConnMgr] - * @property {boolean} [DisableNatPortMap] - * - * @typedef {Object} ConnMgrConfig - * The connection manager determines which and how many connections to keep and - * can be configured to keep. - * - * The "basic" connection manager tries to keep between `LowWater` and - * `HighWater` connections. It works by: - * - * 1. Keeping all connections until `HighWater` connections is reached. - * 2. Once `HighWater` is reached, it closes connections until `LowWater` is - * reached. - * - * @property {number} [LowWater=200] - The minimum number of connections to - * maintain. - * @property {number} [HighWater=500] - The number of connections that, when - * exceeded, will trigger a connection GC operation. - * - * {{LowWater?:number, HighWater?:number}} ConnMgr - * - * @typedef {Object} RoutingConfig - * @property {string} [Type] - * - * @typedef {import('ipfs-core-types/src/basic').ToJSON} ToJSON - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/dag/get.js b/packages/ipfs-core/src/components/dag/get.js index 7fb86bfca8..15b5d01c5f 100644 --- a/packages/ipfs-core/src/components/dag/get.js +++ b/packages/ipfs-core/src/components/dag/get.js @@ -7,57 +7,12 @@ const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') /** * @param {Object} config - * @param {import('..').IPLD} config.ipld - * @param {import('..').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../types').Preload} config.preload */ module.exports = ({ ipld, preload }) => { /** - * Retrieve an IPLD format node - * - * @example - * ```js - * // example obj - * const obj = { - * a: 1, - * b: [1, 2, 3], - * c: { - * ca: [5, 6, 7], - * cb: 'foo' - * } - * } - * - * const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha2-256' }) - * console.log(cid.toString()) - * // zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5 - * - * async function getAndLog(cid, path) { - * const result = await ipfs.dag.get(cid, { path }) - * console.log(result.value) - * } - * - * await getAndLog(cid, '/a') - * // Logs: - * // 1 - * - * await getAndLog(cid, '/b') - * // Logs: - * // [1, 2, 3] - * - * await getAndLog(cid, '/c') - * // Logs: - * // { - * // ca: [5, 6, 7], - * // cb: 'foo' - * // } - * - * await getAndLog(cid, '/c/ca/1') - * // Logs: - * // 6 - * ``` - * - * @param {CID|string} ipfsPath - A DAG node that follows one of the supported IPLD formats - * @param {GetOptions & AbortOptions} [options] - An optional configration - * @returns {Promise} + * @type {import('ipfs-core-types/src/dag').API["get"]} */ const get = async function get (ipfsPath, options = {}) { const { @@ -77,7 +32,7 @@ module.exports = ({ ipld, preload }) => { const entry = options.localResolve ? await first(ipld.resolve(cid, options.path)) : await last(ipld.resolve(cid, options.path)) - /** @type {DagEntry} - first and last will return undefined when empty */ + /** @type {import('ipfs-core-types/src/dag').GetResult} - first and last will return undefined when empty */ const result = (entry) return result } @@ -90,18 +45,3 @@ module.exports = ({ ipld, preload }) => { return withTimeoutOption(get) } - -/** - * @typedef {Object} GetOptions - * @property {boolean} [localResolve=false] - * @property {number} [timeout] - * @property {boolean} [preload=false] - * @property {string} [path] - An optional path within the DAG to resolve - * - * @typedef {Object} DagEntry - * @property {Object} value - * @property {string} remainderPath - * - * @typedef {import('.').CID} CID - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/dag/index.js b/packages/ipfs-core/src/components/dag/index.js index ccb49b2986..932811bd73 100644 --- a/packages/ipfs-core/src/components/dag/index.js +++ b/packages/ipfs-core/src/components/dag/index.js @@ -5,16 +5,17 @@ const createResolve = require('./resolve') const createTree = require('./tree') const createPut = require('./put') -class Reader { - /** - * @param {ReaderConfig} config - */ - constructor (config) { - this.get = createGet(config) - this.resolve = createResolve(config) - this.tree = createTree(config) - } -} +/** + * @typedef {Object} ReaderConfig + * @property {IPLD} ipld + * @property {Preload} preload + * + * @typedef {import('ipld')} IPLD + * @typedef {import('../../types').Preload} Preload + * @typedef {import('ipfs-core-types/src/pin').API} Pin + * @typedef {import('../gc-lock').GCLock} GCLock + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ class DagAPI { /** @@ -23,47 +24,13 @@ class DagAPI { * @param {Preload} config.preload * @param {Pin} config.pin * @param {GCLock} config.gcLock - * @param {DagReader} config.dagReader */ - constructor ({ ipld, pin, preload, gcLock, dagReader }) { - const { get, resolve, tree } = dagReader - const put = createPut({ ipld, preload, pin, gcLock }) - - this.get = get - this.resolve = resolve - this.tree = tree - this.put = put - } - - /** - * Creates a reader part of the DAG API. This allows other APIs that require - * reader parts of the DAG API to be instantiated before components required - * by writer end are. - * - * @param {ReaderConfig} config - * @returns {DagReader} - */ - static reader (config) { - return new Reader(config) + constructor ({ ipld, pin, preload, gcLock }) { + this.get = createGet({ ipld, preload }) + this.resolve = createResolve({ ipld, preload }) + this.tree = createTree({ ipld, preload }) + this.put = createPut({ ipld, preload, pin, gcLock }) } } module.exports = DagAPI - -/** - * @typedef {Object} DagReader - * @property {ReturnType} get - * @property {ReturnType} resolve - * @property {ReturnType} tree - * - * @typedef {Object} ReaderConfig - * @property {IPLD} ipld - * @property {Preload} preload - * - * @typedef {import('..').IPLD} IPLD - * @typedef {import('..').Preload} Preload - * @typedef {import('..').Pin} Pin - * @typedef {import('..').GCLock} GCLock - * @typedef {import('..').CID} CID - * @typedef {import('..').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/dag/put.js b/packages/ipfs-core/src/components/dag/put.js index 687d11ccc8..edb33cb1ac 100644 --- a/packages/ipfs-core/src/components/dag/put.js +++ b/packages/ipfs-core/src/components/dag/put.js @@ -1,36 +1,37 @@ 'use strict' const multicodec = require('multicodec') +const multihashes = require('multihashing-async').multihash /** - * @param {string} name - * @returns {number} + * @typedef {import('cids')} CID + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('multicodec').CodecCode} CodecCode + * @typedef {import('multicodec').CodecName} CodecName + * @typedef {import('multihashes').HashCode} HashCode + * @typedef {import('multihashes').HashName} HashName */ -const nameToCodec = name => multicodec[name.toUpperCase().replace(/-/g, '_')] +/** + * + * @param {CodecName} name + */ +const nameToCodec = name => multicodec.getCodeFromName(name) +/** + * @param {HashName} name + */ +const nameToHashCode = name => multihashes.names[name] const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Pin} config.pin - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('ipfs-core-types/src/pin').API} config.pin + * @param {import('../../types').Preload} config.preload * @param {import('.').GCLock} config.gcLock */ module.exports = ({ ipld, pin, gcLock, preload }) => { /** - * Store an IPLD format node - * - * @param {Object} dagNode - * @param {PutOptions & AbortOptions} [options] - * @returns {Promise} - * @example - * ```js - * const obj = { simple: 'object' } - * const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha3-512' }) - * - * console.log(cid.toString()) - * // zBwWX9ecx5F4X54WAjmFLErnBT6ByfNxStr5ovowTL7AhaUR98RWvXPS1V3HqV1qs3r5Ec5ocv7eCdbqYQREXNUfYNuKG - * ``` + * @type {import('ipfs-core-types/src/dag').API["put"]} */ async function put (dagNode, options = {}) { const { cidVersion, format, hashAlg } = readEncodingOptions(options) @@ -66,8 +67,7 @@ module.exports = ({ ipld, pin, gcLock, preload }) => { } /** - * - * @param {PutOptions} options + * @param {import('ipfs-core-types/src/dag').PutOptions} options */ const readEncodingOptions = (options) => { if (options.cid && (options.format || options.hashAlg)) { @@ -91,22 +91,22 @@ const readEncodingOptions = (options) => { /** * * @param {Object} options - * @param {number|string} options.format - * @param {number|string} [options.hashAlg] + * @param {CodecCode|CodecName} options.format + * @param {HashCode|HashName} [options.hashAlg] */ const encodingCodes = ({ format, hashAlg }) => ({ format: typeof format === 'string' ? nameToCodec(format) : format, - hashAlg: typeof hashAlg === 'string' ? nameToCodec(hashAlg) : hashAlg + hashAlg: typeof hashAlg === 'string' ? nameToHashCode(hashAlg) : hashAlg }) /** * Figures out what version of CID should be used given the options. * * @param {Object} options - * @param {0|1} [options.version] + * @param {CIDVersion} [options.version] * @param {CID} [options.cid] - * @param {number} [options.format] - * @param {number} [options.hashAlg] + * @param {CodecCode} [options.format] + * @param {HashCode} [options.hashAlg] */ const readVersion = ({ version, cid, format, hashAlg }) => { // If version is passed just use that. @@ -124,35 +124,7 @@ const readVersion = ({ version, cid, format, hashAlg }) => { } } -/** @type {WithCIDOptions} */ const defaultCIDOptions = { - format: multicodec.DAG_CBOR, - hashAlg: multicodec.SHA2_256 + format: multicodec.getCodeFromName('dag-cbor'), + hashAlg: multihashes.names['sha2-256'] } - -/** - * @typedef {PutWith & OtherPutOptions} PutOptions - * @typedef {WithCID | WithCIDOptions} PutWith - * - * - * @typedef {Object} WithCID - * @property {CID} [cid] - * // Note: We still stil need to reserve these fields otherwise it implies - * // that those fields can still be there and have very different types. - * @property {undefined} [format] - * @property {undefined} [hashAlg] - * @property {undefined} [version] - * - * @typedef {Object} WithCIDOptions - * @property {undefined} [cid] - * @property {string|number} format - * @property {string|number} hashAlg - * @property {0|1} [version] - * - * @typedef {Object} OtherPutOptions - * @property {boolean} [pin=false] - * @property {boolean} [preload=false] - * - * @typedef {import('.').CID} CID - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/dag/resolve.js b/packages/ipfs-core/src/components/dag/resolve.js index 574b62665d..f8e0c7855b 100644 --- a/packages/ipfs-core/src/components/dag/resolve.js +++ b/packages/ipfs-core/src/components/dag/resolve.js @@ -6,40 +6,12 @@ const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../types').Preload} config.preload */ module.exports = ({ ipld, preload }) => { /** - * Returns the CID and remaining path of the node at the end of the passed IPFS path - * - * @param {CID|string} ipfsPath - * @param {ResolveOptions & AbortOptions} options - * @returns {Promise} - * @example - * ```JavaScript - * // example obj - * const obj = { - * a: 1, - * b: [1, 2, 3], - * c: { - * ca: [5, 6, 7], - * cb: 'foo' - * } - * } - * - * const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha2-256' }) - * console.log(cid.toString()) - * // bafyreicyer3d34cutdzlsbe2nqu5ye62mesuhwkcnl2ypdwpccrsecfmjq - * - * const result = await ipfs.dag.resolve(`${cid}/c/cb`) - * console.log(result) - * // Logs: - * // { - * // cid: CID(bafyreicyer3d34cutdzlsbe2nqu5ye62mesuhwkcnl2ypdwpccrsecfmjq), - * // remainderPath: 'c/cb' - * // } - * ``` + * @type {import('ipfs-core-types/src/dag').API["resolve"]} */ async function resolve (ipfsPath, options = {}) { const { @@ -92,16 +64,3 @@ module.exports = ({ ipld, preload }) => { return withTimeoutOption(resolve) } - -/** - * @typedef {Object} ResolveOptions - * @property {string} [path] - If `ipfsPath` is a `CID`, you may pass a path here - * @property {boolean} [preload] - * - * @typedef {Object} ResolveResult - * @property {CID} cid - The last CID encountered during the traversal - * @property {string} remainderPath - The path to the end of the IPFS path - * inside the node referenced by the CID - * - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/dag/tree.js b/packages/ipfs-core/src/components/dag/tree.js index f18c980afa..d65b627532 100644 --- a/packages/ipfs-core/src/components/dag/tree.js +++ b/packages/ipfs-core/src/components/dag/tree.js @@ -5,47 +5,12 @@ const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../types').Preload} config.preload */ module.exports = ({ ipld, preload }) => { /** - * Enumerate all the entries in a graph - * - * @param {CID} ipfsPath - A DAG node that follows one of the supported IPLD formats - * @param {TreeOptions & AbortOptions} [options] - * @returns {AsyncIterable} - * @example - * ```js - * // example obj - * const obj = { - * a: 1, - * b: [1, 2, 3], - * c: { - * ca: [5, 6, 7], - * cb: 'foo' - * } - * } - * - * const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha2-256' }) - * console.log(cid.toString()) - * // zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5 - * - * const result = await ipfs.dag.tree('zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5') - * console.log(result) - * // Logs: - * // a - * // b - * // b/0 - * // b/1 - * // b/2 - * // c - * // c/ca - * // c/ca/0 - * // c/ca/1 - * // c/ca/2 - * // c/cb - * ``` + * @type {import('ipfs-core-types/src/dag').API["tree"]} */ async function * tree (ipfsPath, options = {}) { // eslint-disable-line require-await const { @@ -66,17 +31,3 @@ module.exports = ({ ipld, preload }) => { return withTimeoutOption(tree) } - -/** - * @typedef {Object} TreeOptions - * @property {string} [path] - If `ipfsPath` is a `CID`, you may pass a path here - * @property {boolean} [preload] - * - * @typedef {Object} TreeResult - * @property {CID} cid - The last CID encountered during the traversal - * @property {string} remainderPath - The path to the end of the IPFS path - * inside the node referenced by the CID - * - * @typedef {import('.').CID} CID - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/dht.js b/packages/ipfs-core/src/components/dht.js index 73f3b91b4c..426fed203d 100644 --- a/packages/ipfs-core/src/components/dht.js +++ b/packages/ipfs-core/src/components/dht.js @@ -9,17 +9,13 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network - * @param {import('.').Repo} config.repo + * @param {import('../types').NetworkService} config.network + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ network, repo }) => { const { get, put, findProvs, findPeer, provide, query } = { /** - * Given a key, query the DHT for its best value. - * - * @param {Uint8Array|string} key - * @param {AbortOptions} [options] - The key associated with the value to find - * @returns {Promise} + * @type {import('ipfs-core-types/src/dht').API["get"]} */ async get (key, options = {}) { const { libp2p } = await use(network, options) @@ -27,16 +23,7 @@ module.exports = ({ network, repo }) => { }, /** - * Write a key/value pair to the DHT. - * - * Given a key of the form /foo/bar and a value of any - * form, this will write that value to the DHT with - * that key. - * - * @param {Uint8Array} key - * @param {Uint8Array} value - * @param {AbortOptions} [options] - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/dht').API["put"]} */ async * put (key, value, options) { const { libp2p } = await use(network, options) @@ -44,27 +31,15 @@ module.exports = ({ network, repo }) => { }, /** - * Find peers in the DHT that can provide a specific value, given a CID. - * - * @param {CID} cid - They key to find providers for. - * @param {FindProvsOptions & AbortOptions} [options] - findProviders options - * @returns {AsyncIterable} - * - * @example - * ```js - * const providers = ipfs.dht.findProvs('QmdPAhQRxrDKqkGPvQzBvjYe3kU8kiEEAd2J6ETEamKAD9') - * for await (const provider of providers) { - * console.log(provider.id.toString()) - * } - * ``` + * @type {import('ipfs-core-types/src/dht').API["findProvs"]} */ - async * findProvs (cid, options = {}) { + async * findProvs (cid, options = { numProviders: 20 }) { const { libp2p } = await use(network, options) - if (options.numProviders) { - options.maxNumProviders = options.numProviders - } - for await (const peer of libp2p._dht.findProviders(normalizeCID(cid), options)) { + for await (const peer of libp2p._dht.findProviders(normalizeCID(cid), { + maxNumProviders: options.numProviders, + signal: options.signal + })) { yield { id: peer.id.toB58String(), addrs: peer.addrs @@ -73,33 +48,11 @@ module.exports = ({ network, repo }) => { }, /** - * Query the DHT for all multiaddresses associated with a `PeerId`. - * - * @param {PeerId|CID} peerId - The id of the peer to search for. - * @param {AbortOptions} [options] - * @returns {Promise<{id: string, addrs: Multiaddr[]}>} - * @example - * ```js - * const info = await ipfs.dht.findPeer('QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt') - * - * console.log(info.id) - * // QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt - * - * info.addrs.forEach(addr => console.log(addr.toString())) - * // '/ip4/147.75.94.115/udp/4001/quic' - * // '/ip6/2604:1380:3000:1f00::1/udp/4001/quic' - * // '/dnsaddr/bootstrap.libp2p.io' - * // '/ip6/2604:1380:3000:1f00::1/tcp/4001' - * // '/ip4/147.75.94.115/tcp/4001' - * ``` + * @type {import('ipfs-core-types/src/dht').API["findPeer"]} */ async findPeer (peerId, options) { const { libp2p } = await use(network, options) - if (typeof peerId === 'string') { - peerId = PeerId.createFromCID(peerId) - } - - const peer = await libp2p._dht.findPeer(peerId) + const peer = await libp2p._dht.findPeer(PeerId.createFromCID(peerId)) return { id: peer.id.toB58String(), @@ -108,13 +61,9 @@ module.exports = ({ network, repo }) => { }, /** - * Announce to the network that we are providing given values. - * - * @param {CID|CID[]} cids - The keys that should be announced. - * @param {ProvideOptions & AbortOptions} [options] - provide options - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/dht').API["provide"]} */ - async * provide (cids, options = {}) { + async * provide (cids, options = { recursive: false }) { const { libp2p } = await use(network, options) cids = Array.isArray(cids) ? cids : [cids] @@ -147,19 +96,12 @@ module.exports = ({ network, repo }) => { }, /** - * Find the closest peers to a given `PeerId`, by querying the DHT. - * - * @param {string|PeerId} peerId - The `PeerId` to run the query against. - * @param {AbortOptions} [options] - * @returns {AsyncIterable<{ id: CID, addrs: Multiaddr[] }>} + * @type {import('ipfs-core-types/src/dht').API["query"]} */ async * query (peerId, options) { const { libp2p } = await use(network, options) - if (typeof peerId === 'string') { - peerId = PeerId.createFromCID(peerId) - } - for await (const closerPeerId of libp2p._dht.getClosestPeers(peerId.toBytes())) { + for await (const closerPeerId of libp2p._dht.getClosestPeers(PeerId.createFromCID(peerId).toBytes())) { yield { id: closerPeerId.toB58String(), addrs: [] // TODO: get addrs? @@ -179,8 +121,8 @@ module.exports = ({ network, repo }) => { } /** - * Turns given cid in some stringifyeable represenation, to Uint8Array - * representation. Throws an error if given value isn't a vaild CID. + * Turns given cid in some stringifyable representation, to Uint8Array + * representation. Throws an error if given value isn't a valid CID. * * @param {any} cid * @returns {Uint8Array} @@ -188,7 +130,7 @@ module.exports = ({ network, repo }) => { const parseCID = cid => { try { const cidStr = cid.toString().split('/') - .filter(part => part && part !== 'ipfs' && part !== 'ipns')[0] + .filter((/** @type {string} */ part) => part && part !== 'ipfs' && part !== 'ipns')[0] return (new CID(cidStr)).bytes } catch (error) { @@ -197,7 +139,7 @@ const parseCID = cid => { } /** - * Turns given cid in some represenation to Uint8Array reperesentation. + * Turns given cid in some representation to Uint8Array representation * * @param {any} cid */ @@ -205,8 +147,8 @@ const normalizeCID = cid => cid instanceof Uint8Array ? cid : parseCID(cid) /** - * @param {import('.').NetworkService} network - * @param {AbortOptions} [options] + * @param {import('../types').NetworkService} network + * @param {import('ipfs-core-types/src/utils').AbortOptions} [options] */ const use = async (network, options) => { const net = await network.use(options) @@ -216,24 +158,3 @@ const use = async (network, options) => { throw new NotEnabledError('dht not enabled') } } -/** - * @typedef {Object} QueryEvent - * @property {PeerId} id - * @property {number} type - * @property {string} extra - * @property {PeerInfo[]} responses - * - * @typedef {Object} ProvideOptions - * @property {boolean} [recursive=false] - Provide not only the given object but also all objects linked from it. - * - * @typedef {Object} FindProvsOptions - * @property {number} [numProviders] - maximum number of providers to find - * @property {number} [maxNumProviders] - * - * @typedef {Object} PeerInfo - * @property {PeerId} id - * @property {Multiaddr[]} addrs - * - * @typedef {import('multiaddr')} Multiaddr - * @typedef {import('../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/dns.js b/packages/ipfs-core/src/components/dns.js index 0d206989d5..81a29db802 100644 --- a/packages/ipfs-core/src/components/dns.js +++ b/packages/ipfs-core/src/components/dns.js @@ -1,6 +1,6 @@ 'use strict' -// dns-nodejs gets replaced by dns-browser when webpacked/browserified +// dns-nodejs gets replaced by dns-browser when bundled const dns = require('../runtime/dns-nodejs') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') @@ -19,13 +19,9 @@ function fqdnFixups (domain) { module.exports = () => { /** - * Resolve DNS links - * - * @param {string} domain - * @param {DNSOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/root').API["dns"]} */ - const resolveDNS = async (domain, options = {}) => { // eslint-disable-line require-await + const resolveDNS = async (domain, options = { recursive: true }) => { // eslint-disable-line require-await if (typeof domain !== 'string') { throw new Error('Invalid arguments, domain must be a string') } @@ -37,12 +33,3 @@ module.exports = () => { return withTimeoutOption(resolveDNS) } - -/** - * @typedef {DNSSettings & AbortOptions} DNSOptions - * - * @typedef {Object} DNSSettings - * @property {boolean} [recursive=true] - Resolve until result is not a domain name - * - * @typedef {import('../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/files/chmod.js b/packages/ipfs-core/src/components/files/chmod.js index 01735d674a..3bc09e4820 100644 --- a/packages/ipfs-core/src/components/files/chmod.js +++ b/packages/ipfs-core/src/components/files/chmod.js @@ -4,7 +4,7 @@ const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) const toMfsPath = require('./utils/to-mfs-path') const log = require('debug')('ipfs:mfs:touch') const errCode = require('err-code') -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') const toTrail = require('./utils/to-trail') const addLink = require('./utils/add-link') const updateTree = require('./utils/update-tree') @@ -13,23 +13,45 @@ const { DAGNode } = require('ipld-dag-pb') const mc = require('multicodec') const mh = require('multihashing-async').multihash const { pipe } = require('it-pipe') -const importer = require('ipfs-unixfs-importer') -const exporter = require('ipfs-unixfs-exporter') +const { importer } = require('ipfs-unixfs-importer') +const { recursive } = require('ipfs-unixfs-exporter') const last = require('it-last') const cp = require('./cp') const rm = require('./rm') +// @ts-ignore - TODO: refactor this so it does not require a deep require const persist = require('ipfs-unixfs-importer/src/utils/persist') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {boolean} flush + * @property {HashName} hashAlg + * @property {CIDVersion} cidVersion + * @property {number} shardSplitThreshold + * @property {boolean} recursive + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { flush: true, shardSplitThreshold: 1000, hashAlg: 'sha2-256', cidVersion: 0, - recursive: false, - signal: undefined + recursive: false } +/** + * @param {string} mode + * @param {number} originalMode + * @param {boolean} isDirectory + */ function calculateModification (mode, originalMode, isDirectory) { let modification = 0 @@ -48,6 +70,10 @@ function calculateModification (mode, originalMode, isDirectory) { return modification } +/** + * @param {string} references + * @param {number} modification + */ function calculateUGO (references, modification) { let ugo = 0 @@ -66,6 +92,11 @@ function calculateUGO (references, modification) { return ugo } +/** + * @param {string} references + * @param {string} mode + * @param {number} modification + */ function calculateSpecial (references, mode, modification) { if (mode.includes('t')) { modification += parseInt('1000', 8) @@ -84,7 +115,13 @@ function calculateSpecial (references, mode, modification) { return modification } -// https://en.wikipedia.org/wiki/Chmod#Symbolic_modes +/** + * https://en.wikipedia.org/wiki/Chmod#Symbolic_modes + * + * @param {string} input + * @param {number} originalMode + * @param {boolean} isDirectory + */ function parseSymbolicMode (input, originalMode, isDirectory) { if (!originalMode) { originalMode = 0 @@ -146,34 +183,41 @@ function parseSymbolicMode (input, originalMode, isDirectory) { if (operator === '-') { return modification ^ originalMode } + + return originalMode } +/** + * @param {string | InstanceType | number} mode + * @param {UnixFS} metadata + * @returns {number} + */ function calculateMode (mode, metadata) { - if (mode instanceof String) { - mode = mode.toString() - } + if (mode instanceof String || typeof mode === 'string') { + const strMode = `${mode}` - if (typeof mode === 'string') { - if (mode.match(/^\d+$/g)) { - mode = parseInt(mode, 8) + if (strMode.match(/^\d+$/g)) { + mode = parseInt(strMode, 8) } else { - mode = mode.split(',').reduce((curr, acc) => { + // @ts-ignore freaks out over the curr: number, acc: string thing + mode = 0 + strMode.split(',').reduce((curr, acc) => { return parseSymbolicMode(acc, curr, metadata.isDirectory()) - }, metadata.mode) + }, metadata.mode || 0) } } return mode } +/** + * @param {MfsContext} context + */ module.exports = (context) => { /** - * @param {string} path - * @param {string | number} mode - * @param {ChmodOptions & AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/files').API["chmod"]} */ async function mfsChmod (path, mode, options = {}) { + /** @type {DefaultOptions} */ const opts = mergeOptions(defaultOptions, options) log(`Fetching stats for ${path}`) @@ -193,10 +237,14 @@ module.exports = (context) => { // but do not reimport files, only manipulate dag-pb nodes const root = await pipe( async function * () { - for await (const entry of exporter.recursive(cid, context.ipld)) { - let node = await context.ipld.get(entry.cid) + for await (const entry of recursive(cid, context.ipld)) { + if (entry.type !== 'file' && entry.type !== 'directory') { + throw errCode(new Error(`${path} was not a UnixFS node`), 'ERR_NOT_UNIXFS') + } + entry.unixfs.mode = calculateMode(mode, entry.unixfs) - node = new DAGNode(entry.unixfs.marshal(), node.Links) + + const node = new DAGNode(entry.unixfs.marshal(), entry.node.Links) yield { path: entry.path, @@ -204,19 +252,26 @@ module.exports = (context) => { } } }, + // @ts-ignore source is not compatible because we are not importing files (source) => importer(source, context.block, { ...opts, pin: false, dagBuilder: async function * (source, block, opts) { for await (const entry of source) { yield async function () { - const cid = await persist(entry.content.serialize(), block, opts) + /** @type {DAGNode} */ + // @ts-ignore - cannot derive type + const node = entry.content + + const buf = node.serialize() + const cid = await persist(buf, block, opts) + const unixfs = UnixFS.unmarshal(node.Data) return { cid, + size: buf.length, path: entry.path, - unixfs: UnixFS.unmarshal(entry.content.Data), - node: entry.content + unixfs } } } @@ -225,6 +280,10 @@ module.exports = (context) => { (nodes) => last(nodes) ) + if (!root) { + throw errCode(new Error(`Could not chmod ${path}`), 'ERR_COULD_NOT_CHMOD') + } + // remove old path from mfs await rm(context)(path, opts) @@ -239,9 +298,12 @@ module.exports = (context) => { metadata.mode = calculateMode(mode, metadata) node = new DAGNode(metadata.marshal(), node.Links) + /** @type {HashName} */ + const hashAlg = opts.hashAlg || defaultOptions.hashAlg + const updatedCid = await context.ipld.put(node, mc.DAG_PB, { cidVersion: cid.version, - hashAlg: mh.names[opts.hashAlg || defaultOptions.hashAlg], + hashAlg: mh.names[hashAlg], onlyHash: !opts.flush }) @@ -255,8 +317,9 @@ module.exports = (context) => { cid: updatedCid, size: node.serialize().length, flush: opts.flush, - hashAlg: opts.hashAlg, - cidVersion: cid.version + hashAlg: hashAlg, + cidVersion: cid.version, + shardSplitThreshold: Infinity }) parent.cid = result.cid @@ -270,15 +333,3 @@ module.exports = (context) => { return withTimeoutOption(mfsChmod) } - -/** - * @typedef {Object} ChmodOptions - * @property {boolean} [flush=false] - * @property {number} [shardSplitThreshold=1000] - * @property {string} [hashAlg=sha2-256] - * @property {0|1} [cidVersion=0] - * @property {boolean} [recursive=false] - * - * @typedef {import('cids')} CID - * @typedef {import('../../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/files/cp.js b/packages/ipfs-core/src/components/files/cp.js index 8936421a75..64a4e6561a 100644 --- a/packages/ipfs-core/src/components/files/cp.js +++ b/packages/ipfs-core/src/components/files/cp.js @@ -8,39 +8,63 @@ const updateTree = require('./utils/update-tree') const updateMfsRoot = require('./utils/update-mfs-root') const addLink = require('./utils/add-link') const toMfsPath = require('./utils/to-mfs-path') -const toSourcesAndDestination = require('./utils/to-sources-and-destination') +const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) const toTrail = require('./utils/to-trail') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('ipld-dag-pb').DAGNode} DAGNode + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids')} CID + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('ipfs-unixfs').Mtime} Mtime + * @typedef {import('./utils/to-mfs-path').MfsPath} MfsPath + * @typedef {import('./utils/to-trail').MfsTrail} MfsTrail + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {boolean} parents + * @property {boolean} flush + * @property {HashName} hashAlg + * @property {CIDVersion} cidVersion + * @property {number} shardSplitThreshold + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { parents: false, flush: true, hashAlg: 'sha2-256', cidVersion: 0, - shardSplitThreshold: 1000, - signal: undefined + shardSplitThreshold: 1000 } /** - * @param {any} context + * @param {MfsContext} context */ -module.exports = function derp (context) { +module.exports = (context) => { /** - * @param {[...from:From, options?:CpOptions]} args - * @returns {Promise} + * @type {import('ipfs-core-types/src/files').API["cp"]} */ - async function mfsCp (...args) { - let { - sources, - destination, - options - } = await toSourcesAndDestination(context, args, defaultOptions) - - if (!sources.length) { - throw errCode(new Error('Please supply at least one source'), 'ERR_INVALID_PARAMS') + async function mfsCp (from, to, opts = {}) { + /** @type {DefaultOptions} */ + const options = mergeOptions(defaultOptions, opts) + + if (!Array.isArray(from)) { + from = [from] } - options.parents = options.p || options.parents + const sources = await Promise.all( + from.map(path => toMfsPath(context, path, options)) + ) + let destination = await toMfsPath(context, to, options) + + if (!sources.length || !destination) { + throw errCode(new Error('Please supply at least one source'), 'ERR_INVALID_PARAMS') + } // make sure all sources exist const missing = sources.find(source => !source.exists) @@ -94,6 +118,11 @@ module.exports = function derp (context) { if (sources.length === 1) { const source = sources.pop() + + if (!source) { + throw errCode(new Error('could not find source'), 'ERR_INVALID_PARAMS') + } + const destinationName = destinationIsDirectory ? source.name : destination.name log(`Only one source, copying to destination ${destinationIsDirectory ? 'directory' : 'file'} ${destinationName}`) @@ -108,15 +137,29 @@ module.exports = function derp (context) { return withTimeoutOption(mfsCp) } +/** + * @param {*} destination + */ const isDirectory = (destination) => { return destination.unixfs && destination.unixfs.type && destination.unixfs.type.includes('directory') } +/** + * @param {MfsContext} context + * @param {MfsPath} source + * @param {string} destination + * @param {MfsTrail[]} destinationTrail + * @param {DefaultOptions} options + */ const copyToFile = async (context, source, destination, destinationTrail, options) => { let parent = destinationTrail.pop() + if (!parent) { + throw errCode(new Error('destination had no parent'), 'ERR_INVALID_PARAMS') + } + parent = await addSourceToParent(context, source, destination, parent, options) // update the tree with the new containing directory @@ -128,6 +171,13 @@ const copyToFile = async (context, source, destination, destinationTrail, option await updateMfsRoot(context, newRootCid, options) } +/** + * @param {MfsContext} context + * @param {MfsPath[]} sources + * @param {*} destination + * @param {MfsTrail[]} destinationTrail + * @param {DefaultOptions} options + */ const copyToDirectory = async (context, sources, destination, destinationTrail, options) => { // copy all the sources to the destination for (let i = 0; i < sources.length; i++) { @@ -145,6 +195,14 @@ const copyToDirectory = async (context, sources, destination, destinationTrail, await updateMfsRoot(context, newRootCid, options) } +/** + * @param {MfsContext} context + * @param {MfsPath} source + * @param {string} childName + * @param {*} parent + * @param {DefaultOptions} options + * @returns {Promise} + */ const addSourceToParent = async (context, source, childName, parent, options) => { const sourceBlock = await context.repo.blocks.get(source.cid) @@ -158,7 +216,8 @@ const addSourceToParent = async (context, source, childName, parent, options) => name: childName, hashAlg: options.hashAlg, cidVersion: options.cidVersion, - flush: options.flush + flush: options.flush, + shardSplitThreshold: options.shardSplitThreshold }) parent.node = node @@ -167,17 +226,3 @@ const addSourceToParent = async (context, source, childName, parent, options) => return parent } - -/** - * @typedef {Object} CpOptions - * @property {boolean} [flush=false] - * @property {number} [shardSplitThreshold=1000] - * @property {string} [hashAlg=sha2-256] - * @property {0|1} [cidVersion=0] - * @property {boolean} [parents=false] - * - * @typedef {import('./utils/types').Tuple} From - * - * @typedef {import('..').CID} CID - * @typedef {import('../../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/files/flush.js b/packages/ipfs-core/src/components/files/flush.js index 5df96ff0e1..0b469ea122 100644 --- a/packages/ipfs-core/src/components/files/flush.js +++ b/packages/ipfs-core/src/components/files/flush.js @@ -4,20 +4,27 @@ const stat = require('./stat') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) -const defaultOptions = { - timeout: undefined, - signal: undefined -} +/** + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ +const defaultOptions = {} +/** + * @param {MfsContext} context + */ module.exports = (context) => { /** - * Flush a given path's data to disk - * - * @param {string} path - * @param {AbortOptions} [options] - * @returns {Promise} The CID of the path that has been flushed + * @type {import('ipfs-core-types/src/files').API["flush"]} */ async function mfsFlush (path, options = {}) { + /** @type {DefaultOptions} */ options = mergeOptions(defaultOptions, options) const { cid } = await stat(context)(path, options) @@ -27,8 +34,3 @@ module.exports = (context) => { return withTimeoutOption(mfsFlush) } - -/** - * @typedef {import('cids')} CID - * @typedef {import('../../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/files/index.js b/packages/ipfs-core/src/components/files/index.js index bb1478e7b9..46898d4b83 100644 --- a/packages/ipfs-core/src/components/files/index.js +++ b/packages/ipfs-core/src/components/files/index.js @@ -4,26 +4,26 @@ const createLock = require('./utils/create-lock') const isIpfs = require('is-ipfs') /** - * @typedef {Object} MFS - * @property {ReturnType} stat - * @property {ReturnType} chmod - * @property {ReturnType} cp - * @property {ReturnType} flush - * @property {ReturnType} mkdir - * @property {ReturnType} mv - * @property {ReturnType} rm - * @property {ReturnType} touch - * @property {ReturnType} write - * @property {ReturnType} read - * @property {ReturnType} ls + * @typedef {object} MfsContext + * @property {import('ipld')} ipld + * @property {import('ipfs-repo')} repo + * @property {import('ipfs-core-types/src/block').API} block */ -// These operations are read-locked at the function level and will execute simultaneously +/** + * These operations are read-locked at the function level and will execute simultaneously + * + * @type {Record} + */ const readOperations = { stat: require('./stat') } -// These operations are locked at the function level and will execute in series +/** + * These operations are locked at the function level and will execute in series + * + * @type {Record} + */ const writeOperations = { chmod: require('./chmod'), cp: require('./cp'), @@ -34,13 +34,24 @@ const writeOperations = { touch: require('./touch') } -// These operations are asynchronous and manage their own locking +/** + * These operations are asynchronous and manage their own locking + * + * @type {Record} + */ const unwrappedOperations = { write: require('./write'), read: require('./read'), ls: require('./ls') } +/** + * @param {object} arg + * @param {*} arg.options + * @param {*} arg.mfs + * @param {*} arg.operations + * @param {*} arg.lock + */ const wrap = ({ options, mfs, operations, lock }) => { @@ -55,6 +66,9 @@ const defaultOptions = { repo: null } +/** + * @param {*} options + */ function createMfs (options) { const { repoOwner @@ -67,14 +81,21 @@ function createMfs (options) { const lock = createLock(repoOwner) + /** + * @param {(fn: (...args: any) => any) => (...args: any) => any} operation + */ const readLock = (operation) => { return lock.readLock(operation) } + /** + * @param {(fn: (...args: any) => any) => (...args: any) => any} operation + */ const writeLock = (operation) => { return lock.writeLock(operation) } + /** @type {Record} */ const mfs = {} wrap({ @@ -92,14 +113,14 @@ function createMfs (options) { } /** - * @param {Object} context - * @param {import('..').IPLD} context.ipld - * @param {import('..').Block} context.block - * @param {import('..').BlockService} context.blockService - * @param {import('..').Repo} context.repo - * @param {import('..').Preload} context.preload + * @param {object} context + * @param {import('ipld')} context.ipld + * @param {import('ipfs-core-types/src/block').API} context.block + * @param {import('ipfs-block-service')} context.blockService + * @param {import('ipfs-repo')} context.repo + * @param {import('../../types').Preload} context.preload * @param {import('..').Options} context.options - * @returns {MFS} + * @returns {import('ipfs-core-types/src/files').API} */ module.exports = ({ ipld, block, blockService, repo, preload, options: constructorOptions }) => { const methods = createMfs({ @@ -110,17 +131,29 @@ module.exports = ({ ipld, block, blockService, repo, preload, options: construct repoOwner: constructorOptions.repoOwner }) - const withPreload = fn => (...args) => { - const paths = args.filter(arg => isIpfs.ipfsPath(arg) || isIpfs.cid(arg)) - - if (paths.length) { - const options = args[args.length - 1] - if (options && options.preload !== false) { - paths.forEach(path => preload(path)) + /** + * @param {any} fn + */ + const withPreload = fn => { + /** + * @param {...any} args + */ + const wrapped = (...args) => { + // @ts-ignore cannot derive type of arg + const paths = args.filter(arg => isIpfs.ipfsPath(arg) || isIpfs.cid(arg)) + + if (paths.length) { + const options = args[args.length - 1] + // @ts-ignore it's a PreloadOptions, honest + if (options && options.preload !== false) { + paths.forEach(path => preload(path)) + } } + + return fn(...args) } - return fn(...args) + return wrapped } return { @@ -135,7 +168,7 @@ module.exports = ({ ipld, block, blockService, repo, preload, options: construct write: methods.write, mv: withPreload(methods.mv), flush: methods.flush, - ls: withPreload(async function * (...args) { + ls: withPreload(async function * (/** @type {...any} */ ...args) { for await (const file of methods.ls(...args)) { yield { ...file, size: file.size || 0 } } diff --git a/packages/ipfs-core/src/components/files/ls.js b/packages/ipfs-core/src/components/files/ls.js index 951074e86b..c0f6db2515 100644 --- a/packages/ipfs-core/src/components/files/ls.js +++ b/packages/ipfs-core/src/components/files/ls.js @@ -1,104 +1,56 @@ 'use strict' -const exporter = require('ipfs-unixfs-exporter') +const { exporter } = require('ipfs-unixfs-exporter') const toMfsPath = require('./utils/to-mfs-path') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +const map = require('it-map') /** - * @param {*} fsEntry - * @returns {UnixFSEntry} + * @typedef {import('./').MfsContext} MfsContext + * @typedef {import('ipfs-core-types/src/files').MFSEntry} MFSEntry */ -const toOutput = (fsEntry) => { - /** @type FileType */ - let type = 'file' - let size = fsEntry.node.size || fsEntry.node.length - let mode - let mtime - - if (fsEntry.unixfs) { - size = fsEntry.unixfs.fileSize() - type = fsEntry.unixfs.type - - if (fsEntry.unixfs.type === 'hamt-sharded-directory') { - type = 'directory' - } - - mode = fsEntry.unixfs.mode - mtime = fsEntry.unixfs.mtime - } +/** + * @param {import('ipfs-unixfs-exporter').UnixFSEntry} fsEntry + */ +const toOutput = (fsEntry) => { + /** @type {MFSEntry} */ const output = { cid: fsEntry.cid, name: fsEntry.name, - type, - size - } - - if (mtime !== undefined) { - output.mtime = mtime + type: fsEntry.type === 'directory' ? 'directory' : 'file', + size: fsEntry.size } - if (mode !== undefined) { - output.mode = mode + if (fsEntry.type === 'file' || fsEntry.type === 'directory') { + output.mode = fsEntry.unixfs.mode + output.mtime = fsEntry.unixfs.mtime } return output } +/** + * @param {MfsContext} context + */ module.exports = (context) => { /** - * List directories in the local mutable namespace - * - * @param {string} path - * @param {AbortOptions} [options] - * @returns {AsyncIterable} - * @example - * - * ```js - * for await (const file of ipfs.files.ls('/screenshots')) { - * console.log(file.name) - * } - * // 2018-01-22T18:08:46.775Z.png - * // 2018-01-22T18:08:49.184Z.png - * ``` + * @type {import('ipfs-core-types/src/files').API["ls"]} */ async function * mfsLs (path, options = {}) { const mfsPath = await toMfsPath(context, path, options) - const fsDir = await exporter(mfsPath.mfsPath, context.ipld) + const fsEntry = await exporter(mfsPath.mfsPath, context.ipld) - // single file/node - if (!fsDir.unixfs || !fsDir.unixfs.type.includes('directory')) { - yield toOutput(fsDir) + // directory, perhaps sharded + if (fsEntry.type === 'directory') { + yield * map(fsEntry.content(options), toOutput) return } - // directory, perhaps sharded - for await (const fsEntry of fsDir.content(options)) { - yield toOutput(fsEntry) - } + // single file/node + yield toOutput(fsEntry) } return withTimeoutOption(mfsLs) } - -/** - * @typedef {import('cids')} CID - * @typedef {import('../../utils').AbortOptions} AbortOptions - * - * @typedef {object} UnixTimeObj - * @property {number} secs - the number of seconds since (positive) or before - * (negative) the Unix Epoch began - * @property {number} [nsecs] - the number of nanoseconds since the last full - * second. - * - * @typedef {'file'|'directory'} FileType - * - * @typedef {object} UnixFSEntry - * @property {CID} cid - * @property {string} name - * @property {number} [mode] - * @property {UnixTimeObj} [mtime] - * @property {number} size - * @property {FileType} type - */ diff --git a/packages/ipfs-core/src/components/files/mkdir.js b/packages/ipfs-core/src/components/files/mkdir.js index 0763dcb8f7..dbc8c6b48a 100644 --- a/packages/ipfs-core/src/components/files/mkdir.js +++ b/packages/ipfs-core/src/components/files/mkdir.js @@ -2,7 +2,7 @@ const errCode = require('err-code') const log = require('debug')('ipfs:mfs:mkdir') -const exporter = require('ipfs-unixfs-exporter') +const { exporter } = require('ipfs-unixfs-exporter') const createNode = require('./utils/create-node') const toPathComponents = require('./utils/to-path-components') const updateMfsRoot = require('./utils/update-mfs-root') @@ -12,30 +12,46 @@ const withMfsRoot = require('./utils/with-mfs-root') const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('ipld-dag-pb').DAGNode} DAGNode + * @typedef {import('ipld-dag-pb').DAGLink} DAGLink + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids')} CID + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('ipfs-unixfs').MtimeLike} MtimeLike + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {boolean} parents + * @property {HashName} hashAlg + * @property {CIDVersion} cidVersion + * @property {number} shardSplitThreshold + * @property {boolean} flush + * @property {number} [mode] + * @property {MtimeLike} [mtime] + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { parents: false, hashAlg: 'sha2-256', cidVersion: 0, shardSplitThreshold: 1000, - flush: true, - mode: null, - mtime: null, - signal: undefined + flush: true } +/** + * @param {MfsContext} context + */ module.exports = (context) => { /** - * Make a directory in your MFS - * - * @param {string} path - * @param {MkdirOptions & AbortOptions} [options] - * @returns {Promise} - * @example - * ```js - * await ipfs.files.mkdir('/my/beautiful/directory') - * ``` + * @type {import('ipfs-core-types/src/files').API["mkdir"]} */ async function mfsMkdir (path, options = {}) { + /** @type {DefaultOptions} */ const opts = mergeOptions(defaultOptions, options) if (!path) { @@ -76,8 +92,10 @@ module.exports = (context) => { try { parent = await exporter(subPath, context.ipld) - log(`${subPath} existed`) - log(`${subPath} had children ${parent.node.Links.map(link => link.Name)}`) + + if (parent.type !== 'file' && parent.type !== 'directory') { + throw errCode(new Error(`${path} was not a UnixFS node`), 'ERR_NOT_UNIXFS') + } if (i === pathComponents.length) { if (opts.parents) { @@ -118,6 +136,14 @@ module.exports = (context) => { return withTimeoutOption(mfsMkdir) } +/** + * @param {MfsContext} context + * @param {string} childName + * @param {{ cid: CID, node: { size: number }}} emptyDir + * @param {{ cid?: CID, node?: DAGNode }} parent + * @param {{ name: string, cid: CID }[]} trail + * @param {DefaultOptions} options + */ const addEmptyDir = async (context, childName, emptyDir, parent, trail, options) => { log(`Adding empty dir called ${childName} to ${parent.cid}`) @@ -129,7 +155,8 @@ const addEmptyDir = async (context, childName, emptyDir, parent, trail, options) name: childName, hashAlg: options.hashAlg, cidVersion: options.cidVersion, - flush: options.flush + flush: options.flush, + shardSplitThreshold: options.shardSplitThreshold }) trail[trail.length - 1].cid = result.cid @@ -139,20 +166,3 @@ const addEmptyDir = async (context, childName, emptyDir, parent, trail, options) cid: emptyDir.cid }) } - -/** - * @typedef {Object} MkdirOptions - * @property {boolean} [parents=false] - If true, create intermediate directories - * @property {ToMode} [mode] - An integer that represents the file mode - * @property {ToMTime} [mtime] - A Date object, an object with `{ secs, nsecs }` properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of `process.hrtime() - * @property {boolean} [flush] - If true the changes will be immediately flushed to disk - * @property {string} [hashAlg='sha2-256'] - The hash algorithm to use for any updated entries - * @property {CIDVersion} [cidVersion=0] - The CID version to use for any updated entries - * - * @typedef {import('cids')} CID - * @typedef {import('cids').CIDVersion} CIDVersion - * @typedef {import('ipfs-core-types/src/basic').AbortOptions} AbortOptions - * @typedef {import('ipfs-core-types/src/files').MTime} Mtime - * @typedef {import('ipfs-core-types/src/files').ToMTime} ToMTime - * @typedef {import('ipfs-core-types/src/files').ToMode} ToMode - */ diff --git a/packages/ipfs-core/src/components/files/mv.js b/packages/ipfs-core/src/components/files/mv.js index e58ad02963..92844286ab 100644 --- a/packages/ipfs-core/src/components/files/mv.js +++ b/packages/ipfs-core/src/components/files/mv.js @@ -1,62 +1,52 @@ 'use strict' -const toSources = require('./utils/to-sources') const cp = require('./cp') const rm = require('./rm') +const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {boolean} parents + * @property {boolean} flush + * @property {CIDVersion} cidVersion + * @property {HashName} hashAlg + * @property {number} shardSplitThreshold + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { parents: false, - recursive: false, flush: true, cidVersion: 0, hashAlg: 'sha2-256', - shardSplitThreshold: 1000, - signal: undefined + shardSplitThreshold: 1000 } /** - * - * @param {any} context + * @param {MfsContext} context */ module.exports = (context) => { /** - * - * @param {[...from:From, to:string, options?:MvOptions]} args - * @returns {Promise} + * @type {import('ipfs-core-types/src/files').API["mv"]} */ - async function mfsMv (...args) { - const { - sources, - options - } = await toSources(context, args, defaultOptions) - - const cpArgs = sources - .map(source => source.path).concat(options) - - // remove the last source as it'll be the destination - const rmArgs = sources - .slice(0, -1) - .map(source => source.path) - .concat(Object.assign(options, { - recursive: true - })) - - await cp(context).apply(null, cpArgs) - await rm(context).apply(null, rmArgs) + async function mfsMv (from, to, options = {}) { + /** @type {DefaultOptions} */ + const opts = mergeOptions(defaultOptions, options) + + await cp(context)(from, to, opts) + await rm(context)(from, { + ...opts, + recursive: true + }) } return withTimeoutOption(mfsMv) } - -/** - * @typedef {Object} MvOptions - * @property {boolean} [parents=false] - * @property {boolean} [flush=false] - * @property {string} [hashAlg='sha2-256'] - * @property {0|1} [cidVersion] - * - * @typedef {import('./utils/types').Tuple} From - * @typedef {import('cids')} CID - * @typedef {import('../../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/files/read.js b/packages/ipfs-core/src/components/files/read.js index ea697c85b7..eb71aecb09 100644 --- a/packages/ipfs-core/src/components/files/read.js +++ b/packages/ipfs-core/src/components/files/read.js @@ -1,40 +1,37 @@ 'use strict' -const exporter = require('ipfs-unixfs-exporter') +const { exporter } = require('ipfs-unixfs-exporter') const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) const toMfsPath = require('./utils/to-mfs-path') const errCode = require('err-code') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {number} offset + * @property {number} length + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { offset: 0, - length: Infinity, - signal: undefined + length: Infinity } /** - * @param {any} context + * @param {MfsContext} context */ module.exports = (context) => { /** - * Read a file - * - * @param {string | CID} path - An MFS path, IPFS Path or CID to read - * @param {ReadOptions & AbortOptions} [options] - * @returns {AsyncIterable} - * @example - * ```js - * const chunks = [] - * - * for await (const chunk of ipfs.files.read('/hello-world')) { - * chunks.push(chunk) - * } - * - * console.log(uint8ArrayConcat(chunks).toString()) - * // Hello, World! - * ``` + * @type {import('ipfs-core-types/src/files').API["read"]} */ function mfsRead (path, options = {}) { + /** @type {DefaultOptions} */ options = mergeOptions(defaultOptions, options) return { @@ -42,7 +39,7 @@ module.exports = (context) => { const mfsPath = await toMfsPath(context, path, options) const result = await exporter(mfsPath.mfsPath, context.ipld) - if (result.unixfs.type !== 'file') { + if (result.type !== 'file') { throw errCode(new Error(`${path} was not a file`), 'ERR_NOT_FILE') } @@ -62,12 +59,3 @@ module.exports = (context) => { return withTimeoutOption(mfsRead) } - -/** - * @typedef {Object} ReadOptions - * @property {number} [offset] - An offset to start reading the file from - * @property {number} [length] - An optional max length to read from the file - * - * @typedef {import('cids')} CID - * @typedef {import('../../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/files/rm.js b/packages/ipfs-core/src/components/files/rm.js index d9677f99e8..f235feafee 100644 --- a/packages/ipfs-core/src/components/files/rm.js +++ b/packages/ipfs-core/src/components/files/rm.js @@ -3,35 +3,55 @@ const errCode = require('err-code') const updateTree = require('./utils/update-tree') const updateMfsRoot = require('./utils/update-mfs-root') -const toSources = require('./utils/to-sources') const removeLink = require('./utils/remove-link') const toMfsPath = require('./utils/to-mfs-path') const toTrail = require('./utils/to-trail') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) +/** + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {boolean} recursive + * @property {CIDVersion} cidVersion + * @property {HashName} hashAlg + * @property {boolean} flush + * @property {number} shardSplitThreshold + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { recursive: false, cidVersion: 0, hashAlg: 'sha2-256', flush: true, - signal: undefined + shardSplitThreshold: 1000 } /** - * @param {any} context + * @param {MfsContext} context */ module.exports = (context) => { /** - * Remove a file or directory - * - * @param {[...paths: Paths, options?:RmOptions]} args - * @returns {Promise} + * @type {import('ipfs-core-types/src/files').API["rm"]} */ - async function mfsRm (...args) { - const { - sources, - options - } = await toSources(context, args, defaultOptions) + async function mfsRm (paths, opts = {}) { + /** @type {DefaultOptions} */ + const options = mergeOptions(defaultOptions, opts) + + if (!Array.isArray(paths)) { + paths = [paths] + } + + const sources = await Promise.all( + paths.map(path => toMfsPath(context, path, options)) + ) if (!sources.length) { throw errCode(new Error('Please supply at least one path to remove'), 'ERR_INVALID_PARAMS') @@ -51,6 +71,11 @@ module.exports = (context) => { return withTimeoutOption(mfsRm) } +/** + * @param {MfsContext} context + * @param {string} path + * @param {DefaultOptions} options + */ const removePath = async (context, path, options) => { const mfsPath = await toMfsPath(context, path, options) const trail = await toTrail(context, mfsPath.mfsPath) @@ -73,7 +98,8 @@ const removePath = async (context, path, options) => { name: child.name, hashAlg: options.hashAlg, cidVersion: options.cidVersion, - flush: options.flush + flush: options.flush, + shardSplitThreshold: options.shardSplitThreshold }) parent.cid = cid @@ -84,15 +110,3 @@ const removePath = async (context, path, options) => { // Update the MFS record with the new CID for the root of the tree await updateMfsRoot(context, newRootCid, options) } - -/** - * @typedef {Object} RmOptions - * @property {boolean} [recursive=false] - If true all paths under the specifed path(s) will be removed - * @property {boolean} [flush=false] - If true the changes will be immediately flushed to disk - * @property {string} [hashAlg='sha2-256'] - The hash algorithm to use for any updated entries - * @property {0|1} [cidVersion] - The CID version to use for any updated entries - * - * @typedef {import('..').CID} CID - * @typedef {import('./utils/types').Tuple} Paths - * @typedef {import('../../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/files/stat.js b/packages/ipfs-core/src/components/files/stat.js index e1a3690f8f..cd38b9d907 100644 --- a/packages/ipfs-core/src/components/files/stat.js +++ b/packages/ipfs-core/src/components/files/stat.js @@ -2,29 +2,39 @@ const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) const toMfsPath = require('./utils/to-mfs-path') -const exporter = require('ipfs-unixfs-exporter') +const { exporter } = require('ipfs-unixfs-exporter') const log = require('debug')('ipfs:mfs:stat') const errCode = require('err-code') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {boolean} withLocal + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { - withLocal: false, - signal: undefined + withLocal: false } /** - * @param {Object} context - * @param {import('..').IPLD} context.ipld + * @typedef {import('ipfs-core-types/src/files').StatResult} StatResult + */ + +/** + * @param {MfsContext} context */ module.exports = (context) => { /** - * Get file or directory statistics - * - * @param {string} path - The MFS path return statistics from - * @param {StatOptions & AbortOptions} [options] - * @returns {Promise} - An object containing the file/directory status + * @type {import('ipfs-core-types/src/files').API["stat"]} */ - async function mfsStat (path, options) { + async function mfsStat (path, options = {}) { + /** @type {DefaultOptions} */ options = mergeOptions(defaultOptions, options) log(`Fetching stats for ${path}`) @@ -48,21 +58,20 @@ module.exports = (context) => { throw err } - if (!statters[file.cid.codec]) { + if (!statters[file.type]) { throw new Error(`Cannot stat codec ${file.cid.codec}`) } - return statters[file.cid.codec](file) + return statters[file.type](file) } return withTimeoutOption(mfsStat) } -/** @type {Record Stat>} */ +/** @type {Record StatResult>} */ const statters = { /** - * @param {any} file - * @returns {Stat} + * @param {import('ipfs-unixfs-exporter').RawNode} file */ raw: (file) => { return { @@ -77,77 +86,76 @@ const statters = { } }, /** - * @param {any} file - * @returns {Stat} + * @param {import('ipfs-unixfs-exporter').UnixFSFile} file */ - 'dag-pb': (file) => { - const blocks = file.node.Links.length - const size = file.node.size - const cumulativeSize = file.node.size - - /** @type {Stat} */ - const output = { + file: (file) => { + /** @type {StatResult} */ + const stat = { cid: file.cid, type: 'file', - size: size, - cumulativeSize: cumulativeSize, - blocks: blocks, + size: file.unixfs.fileSize(), + cumulativeSize: file.node.size, + blocks: file.unixfs.blockSizes.length, local: undefined, sizeLocal: undefined, - withLocality: false + withLocality: false, + mode: file.unixfs.mode } - if (file.unixfs) { - output.size = file.unixfs.fileSize() - - // for go-ipfs compatibility - if (file.unixfs.type === 'hamt-sharded-directory') { - output.type = 'directory' - } else { - output.type = file.unixfs.type - } - - output.mode = file.unixfs.mode - - if (file.unixfs.isDirectory()) { - output.size = 0 - output.cumulativeSize = file.node.size - } + if (file.unixfs.mtime) { + stat.mtime = file.unixfs.mtime + } - if (output.type === 'file') { - output.blocks = file.unixfs.blockSizes.length - } + return stat + }, + /** + * @param {import('ipfs-unixfs-exporter').UnixFSDirectory} file + */ + directory: (file) => { + /** @type {StatResult} */ + const stat = { + cid: file.cid, + type: 'directory', + size: 0, + cumulativeSize: file.node.size, + blocks: file.node.Links.length, + local: undefined, + sizeLocal: undefined, + withLocality: false, + mode: file.unixfs.mode + } - if (file.unixfs.mtime) { - output.mtime = file.unixfs.mtime - } + if (file.unixfs.mtime) { + stat.mtime = file.unixfs.mtime } - return output + return stat }, /** - * @param {any} file - * @returns {Stat} + * @param {import('ipfs-unixfs-exporter').ObjectNode} file */ - 'dag-cbor': (file) => { - // @ts-ignore - This is incompatible with Stat object - // @TODO - https://github.com/ipfs/js-ipfs/issues/3325 + object: (file) => { + /** @type {StatResult} */ return { cid: file.cid, + size: file.node.length, + cumulativeSize: file.node.length, + type: 'file', // for go compatibility + blocks: 0, local: undefined, sizeLocal: undefined, withLocality: false } }, /** - * @param {any} file - * @returns {Stat} + * @param {import('ipfs-unixfs-exporter').IdentityNode} file */ identity: (file) => { + /** @type {StatResult} */ return { cid: file.cid, - size: file.node.digest.length, - cumulativeSize: file.node.digest.length, + size: file.node.length, + cumulativeSize: file.node.length, blocks: 0, type: 'file', // for go compatibility local: undefined, @@ -156,32 +164,3 @@ const statters = { } } } - -/** - * @typedef {Object} StatOptions - * @property {boolean} [hash=false] - If true, return only the CID - * @property {boolean} [size=false] - If true, return only the size - * @property {boolean} [withLocal=false] - If true, compute the amount of the DAG that is local and if possible the total size - * - * @typedef {Object} Stat - * @property {CID} cid - Content idenntifier - * @property {number} size - An integer with the file size in bytes. - * @property {number} cumulativeSize - An integer with the size of the - * DAGNodes making up the file in bytes. - * @property {'directory'|'file'} type - Type of the file which is either directory - * or file. - * @property {number} blocks - If type is directory, this is the number of files - * in the directory. If it is file it is the number of blocks that make up the - * file. - * @property {boolean} [withLocality] - A boolean to indicate if locality - * information is present. - * @property {boolean} [local] - Is a boolean to indicate if the queried dag is - * fully present locally. - * @property {number} [sizeLocal] - An integer indicating the cumulative size of - * the data present locally. - * @property {number} [mode] - File mode - * @property {import('ipfs-core-types/src/files').MTime} [mtime] - Modification time - * - * @typedef {import('cids')} CID - * @typedef {import('ipfs-core-types/src/basic').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/files/touch.js b/packages/ipfs-core/src/components/files/touch.js index 6c6dbc3d7d..c194821ba0 100644 --- a/packages/ipfs-core/src/components/files/touch.js +++ b/packages/ipfs-core/src/components/files/touch.js @@ -4,7 +4,7 @@ const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) const toMfsPath = require('./utils/to-mfs-path') const log = require('debug')('ipfs:mfs:touch') const errCode = require('err-code') -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') const toTrail = require('./utils/to-trail') const addLink = require('./utils/add-link') const updateTree = require('./utils/update-tree') @@ -14,35 +14,40 @@ const mc = require('multicodec') const mh = require('multihashing-async').multihash const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('ipfs-unixfs').MtimeLike} MtimeLike + * @typedef {import('./').MfsContext} MfsContext + * @typedef {object} DefaultOptions + * @property {boolean} flush + * @property {number} shardSplitThreshold + * @property {CIDVersion} cidVersion + * @property {HashName} hashAlg + * @property {MtimeLike} [mtime] + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { - /** @type {ToMTime|undefined} */ - mtime: undefined, flush: true, shardSplitThreshold: 1000, cidVersion: 0, - hashAlg: 'sha2-256', - signal: undefined + hashAlg: 'sha2-256' } +/** + * @param {MfsContext} context + */ module.exports = (context) => { /** - * Update the mtime of a file or directory - * - * @param {string} path - The MFS path to update the mtime for - * @param {TouchOptions & AbortOptions} [options] - * @returns {Promise} - * - * @example - * ```js - * // set the mtime to the current time - * await ipfs.files.touch('/path/to/file.txt') - * // set the mtime to a specific time - * await ipfs.files.touch('/path/to/file.txt', { - * mtime: new Date('May 23, 2014 14:45:14 -0700') - * }) - * ``` + * @type {import('ipfs-core-types/src/files').API["touch"]} */ async function mfsTouch (path, options = {}) { + /** @type {DefaultOptions} */ const settings = mergeOptions(defaultOptions, options) settings.mtime = settings.mtime || new Date() @@ -63,6 +68,7 @@ module.exports = (context) => { if (!exists) { const metadata = new UnixFS({ type: 'file', + // @ts-ignore TODO: restore hrtime support to ipfs-unixfs constructor - it's in the code, just not the signature mtime: settings.mtime }) node = new DAGNode(metadata.marshal()) @@ -81,6 +87,8 @@ module.exports = (context) => { node = await context.ipld.get(cid) const metadata = UnixFS.unmarshal(node.Data) + + // @ts-ignore TODO: restore setting all date types as mtime - it's in the code, just not the signature metadata.mtime = settings.mtime node = new DAGNode(metadata.marshal(), node.Links) @@ -118,15 +126,3 @@ module.exports = (context) => { return withTimeoutOption(mfsTouch) } - -/** - * @typedef {Object} TouchOptions - * @property {ToMTime} [mtime] - A Date object, an object with `{ secs, nsecs }` properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of `process.hrtime()` - * @property {boolean} [flush=false] - If true the changes will be immediately flushed to disk - * @property {string} [hashAlg='sha2-256'] - The hash algorithm to use for any updated entries - * @property {import('cids').CIDVersion} [cidVersion] - The CID version to use for any updated entries - * - * @typedef {import('cids')} CID - * @typedef {import('ipfs-core-types/src/basic').AbortOptions} AbortOptions - * @typedef {import('ipfs-core-types/src/files').ToMTime} ToMTime - */ diff --git a/packages/ipfs-core/src/components/files/utils/add-link.js b/packages/ipfs-core/src/components/files/utils/add-link.js index b622f64d33..a316c354e3 100644 --- a/packages/ipfs-core/src/components/files/utils/add-link.js +++ b/packages/ipfs-core/src/components/files/utils/add-link.js @@ -6,11 +6,15 @@ const { } = require('ipld-dag-pb') const CID = require('cids') const log = require('debug')('ipfs:mfs:core:utils:add-link') -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') +// @ts-ignore - refactor this to not need deep require const DirSharded = require('ipfs-unixfs-importer/src/dir-sharded') +// @ts-ignore - refactor this to not need deep require +const defaultImporterOptions = require('ipfs-unixfs-importer/src/options') const { updateHamtDirectory, recreateHamtLevel, + recreateInitialHamtLevel, createShard, toPrefix, addLinksToHamtBucket @@ -20,19 +24,41 @@ const mc = require('multicodec') const mh = require('multihashing-async').multihash const last = require('it-last') +/** + * @typedef {import('ipfs-unixfs').Mtime} Mtime + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('hamt-sharding').Bucket} Bucket + * @typedef {import('../').MfsContext} MfsContext + */ + +/** + * @param {MfsContext} context + * @param {object} options + * @param {CID} options.cid + * @param {string} options.name + * @param {number} options.size + * @param {number} options.shardSplitThreshold + * @param {HashName} options.hashAlg + * @param {CIDVersion} options.cidVersion + * @param {boolean} options.flush + * @param {CID} [options.parentCid] + * @param {DAGNode} [options.parent] + */ const addLink = async (context, options) => { - if (!options.parentCid && !options.parent) { - throw errCode(new Error('No parent node or CID passed to addLink'), 'EINVALIDPARENT') - } + let parent = options.parent - if (options.parentCid && !CID.isCID(options.parentCid)) { - throw errCode(new Error('Invalid CID passed to addLink'), 'EINVALIDPARENTCID') - } + if (options.parentCid) { + if (!CID.isCID(options.parentCid)) { + throw errCode(new Error('Invalid CID passed to addLink'), 'EINVALIDPARENTCID') + } - if (!options.parent) { log(`Loading parent node ${options.parentCid}`) + parent = await context.ipld.get(options.parentCid) + } - options.parent = await context.ipld.get(options.parentCid) + if (!parent) { + throw errCode(new Error('No parent node or CID passed to addLink'), 'EINVALIDPARENT') } if (!options.cid) { @@ -51,19 +77,23 @@ const addLink = async (context, options) => { throw errCode(new Error('No child size passed to addLink'), 'EINVALIDCHILDSIZE') } - const meta = UnixFS.unmarshal(options.parent.Data) + const meta = UnixFS.unmarshal(parent.Data) if (meta.type === 'hamt-sharded-directory') { log('Adding link to sharded directory') - return addToShardedDirectory(context, options) + return addToShardedDirectory(context, { + ...options, + parent + }) } - if (options.parent.Links.length >= options.shardSplitThreshold) { + if (parent.Links.length >= options.shardSplitThreshold) { log('Converting directory to sharded directory') return convertToShardedDirectory(context, { ...options, + parent, mtime: meta.mtime, mode: meta.mode }) @@ -71,9 +101,25 @@ const addLink = async (context, options) => { log(`Adding ${options.name} (${options.cid}) to regular directory`) - return addToDirectory(context, options) + return addToDirectory(context, { + ...options, + parent + }) } +/** + * @param {MfsContext} context + * @param {object} options + * @param {CID} options.cid + * @param {string} options.name + * @param {number} options.size + * @param {DAGNode} options.parent + * @param {HashName} options.hashAlg + * @param {CIDVersion} options.cidVersion + * @param {boolean} options.flush + * @param {Mtime} [options.mtime] + * @param {number} [options.mode] + */ const convertToShardedDirectory = async (context, options) => { const result = await createShard(context, options.parent.Links.map(link => ({ name: link.Name, @@ -90,6 +136,19 @@ const convertToShardedDirectory = async (context, options) => { return result } +/** + * @param {MfsContext} context + * @param {object} options + * @param {CID} options.cid + * @param {string} options.name + * @param {number} options.size + * @param {DAGNode} options.parent + * @param {HashName} options.hashAlg + * @param {CIDVersion} options.cidVersion + * @param {boolean} options.flush + * @param {Mtime} [options.mtime] + * @param {number} [options.mode] + */ const addToDirectory = async (context, options) => { options.parent.rmLink(options.name) options.parent.addLink(new DAGLink(options.name, options.size, options.cid)) @@ -98,7 +157,13 @@ const addToDirectory = async (context, options) => { if (node.mtime) { // Update mtime if previously set - node.mtime = new Date() + const ms = Date.now() + const secs = Math.floor(ms / 1000) + + node.mtime = { + secs: secs, + nsecs: (ms - (secs * 1000)) * 1000 + } options.parent = new DAGNode(node.marshal(), options.parent.Links) } @@ -119,21 +184,38 @@ const addToDirectory = async (context, options) => { } } +/** + * @param {MfsContext} context + * @param {object} options + * @param {CID} options.cid + * @param {string} options.name + * @param {number} options.size + * @param {DAGNode} options.parent + * @param {HashName} options.hashAlg + * @param {CIDVersion} options.cidVersion + * @param {boolean} options.flush + */ const addToShardedDirectory = async (context, options) => { const { shard, path } = await addFileToShardedDirectory(context, options) - const result = await last(shard.flush('', context.block)) + const result = await last(shard.flush(context.block)) + /** @type {DAGNode} */ const node = await context.ipld.get(result.cid) // we have written out the shard, but only one sub-shard will have been written so replace it in the original shard const oldLink = options.parent.Links .find(link => link.Name.substring(0, 2) === path[0].prefix) + /** @type {DAGLink | undefined} */ const newLink = node.Links .find(link => link.Name.substring(0, 2) === path[0].prefix) + if (!newLink) { + throw new Error(`No link found with prefix ${path[0].prefix}`) + } + if (oldLink) { options.parent.rmLink(oldLink.Name) } @@ -143,6 +225,16 @@ const addToShardedDirectory = async (context, options) => { return updateHamtDirectory(context, options.parent.Links, path[0].bucket, options) } +/** + * @param {MfsContext} context + * @param {object} options + * @param {CID} options.cid + * @param {string} options.name + * @param {number} options.size + * @param {DAGNode} options.parent + * @param {HashName} options.hashAlg + * @param {CIDVersion} options.cidVersion + */ const addFileToShardedDirectory = async (context, options) => { const file = { name: options.name, @@ -151,8 +243,9 @@ const addFileToShardedDirectory = async (context, options) => { } // start at the root bucket and descend, loading nodes as we go - const rootBucket = await recreateHamtLevel(options.parent.Links) + const rootBucket = await recreateInitialHamtLevel(options.parent.Links) const node = UnixFS.unmarshal(options.parent.Data) + const importerOptions = defaultImporterOptions() const shard = new DirSharded({ root: true, @@ -163,7 +256,12 @@ const addFileToShardedDirectory = async (context, options) => { dirty: true, flat: false, mode: node.mode - }, options) + }, { + hamtHashFn: importerOptions.hamtHashFn, + hamtHashCode: importerOptions.hamtHashCode, + hamtBucketBits: importerOptions.hamtBucketBits, + ...options + }) shard._bucket = rootBucket if (node.mtime) { @@ -182,6 +280,10 @@ const addFileToShardedDirectory = async (context, options) => { index++ const node = segment.node + if (!node) { + throw new Error('Segment had no node') + } + const link = node.Links .find(link => link.Name.substring(0, 2) === segment.prefix) @@ -248,16 +350,18 @@ const addFileToShardedDirectory = async (context, options) => { } } +/** + * @param {{ pos: number, bucket: Bucket }} position + * @returns {{ bucket: Bucket, prefix: string, node?: DAGNode }[]} + */ const toBucketPath = (position) => { - let bucket = position.bucket - let positionInBucket = position.pos const path = [{ - bucket, - prefix: toPrefix(positionInBucket) + bucket: position.bucket, + prefix: toPrefix(position.pos) }] - bucket = position.bucket._parent - positionInBucket = position.bucket._posAtParent + let bucket = position.bucket._parent + let positionInBucket = position.bucket._posAtParent while (bucket) { path.push({ diff --git a/packages/ipfs-core/src/components/files/utils/create-lock.js b/packages/ipfs-core/src/components/files/utils/create-lock.js index fa3c6192dd..b6302981b8 100644 --- a/packages/ipfs-core/src/components/files/utils/create-lock.js +++ b/packages/ipfs-core/src/components/files/utils/create-lock.js @@ -1,10 +1,21 @@ 'use strict' +// @ts-ignore - no types const mortice = require('mortice') +/** + * @typedef {object} Lock + * @property {(fn: (...args: any) => any) => (...args: any) => any} readLock + * @property {(fn: (...args: any) => any) => (...args: any) => any} writeLock + */ + +/** @type {Lock} */ let lock -module.exports = (repoOwner) => { +/** + * @param {boolean} [repoOwner] + */ +module.exports = (repoOwner = false) => { if (lock) { return lock } diff --git a/packages/ipfs-core/src/components/files/utils/create-node.js b/packages/ipfs-core/src/components/files/utils/create-node.js index dede8f7fc6..e2e05fc13f 100644 --- a/packages/ipfs-core/src/components/files/utils/create-node.js +++ b/packages/ipfs-core/src/components/files/utils/create-node.js @@ -1,17 +1,34 @@ 'use strict' -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') const { DAGNode } = require('ipld-dag-pb') const mc = require('multicodec') const mh = require('multihashing-async').multihash +/** + * @typedef {import('ipfs-unixfs').MtimeLike} MtimeLike + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('../').MfsContext} MfsContext + */ + +/** + * @param {MfsContext} context + * @param {'file' | 'directory'} type + * @param {object} options + * @param {import('multihashes').HashName} options.hashAlg + * @param {CIDVersion} options.cidVersion + * @param {boolean} options.flush + * @param {MtimeLike} [options.mtime] + * @param {number} [options.mode] + */ const createNode = async (context, type, options) => { const hashAlg = mh.names[options.hashAlg] const metadata = new UnixFS({ type, mode: options.mode, + // @ts-ignore TODO: restore hrtime support to ipfs-unixfs constructor - it's in the code, just not the signature mtime: options.mtime }) diff --git a/packages/ipfs-core/src/components/files/utils/hamt-utils.js b/packages/ipfs-core/src/components/files/utils/hamt-utils.js index 17466eff73..f155b557f0 100644 --- a/packages/ipfs-core/src/components/files/utils/hamt-utils.js +++ b/packages/ipfs-core/src/components/files/utils/hamt-utils.js @@ -3,15 +3,42 @@ const { DAGNode } = require('ipld-dag-pb') -const Bucket = require('hamt-sharding/src/bucket') +const { + Bucket, + createHAMT +} = require('hamt-sharding') +// @ts-ignore - refactor this to not need deep require const DirSharded = require('ipfs-unixfs-importer/src/dir-sharded') +// @ts-ignore - refactor this to not need deep require +const defaultImporterOptions = require('ipfs-unixfs-importer/src/options') const log = require('debug')('ipfs:mfs:core:utils:hamt-utils') -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') const mc = require('multicodec') const mh = require('multihashing-async').multihash const last = require('it-last') +/** + * @typedef {import('ipld-dag-pb').DAGLink} DAGLink + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('ipfs-unixfs').Mtime} Mtime + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids')} CID + * @typedef {import('../').MfsContext} MfsContext + */ + +/** + * @param {MfsContext} context + * @param {DAGLink[]} links + * @param {Bucket} bucket + * @param {object} options + * @param {DAGNode} options.parent + * @param {CIDVersion} options.cidVersion + * @param {boolean} options.flush + * @param {HashName} options.hashAlg + */ const updateHamtDirectory = async (context, links, bucket, options) => { + const importerOptions = defaultImporterOptions() + // update parent with new bit field const data = Uint8Array.from(bucket._children.bitField().reverse()) const node = UnixFS.unmarshal(options.parent.Data) @@ -19,7 +46,7 @@ const updateHamtDirectory = async (context, links, bucket, options) => { type: 'hamt-sharded-directory', data, fanout: bucket.tableSize(), - hashType: DirSharded.hashFn.code, + hashType: importerOptions.hamtHashCode, mode: node.mode, mtime: node.mtime }) @@ -39,22 +66,45 @@ const updateHamtDirectory = async (context, links, bucket, options) => { } } +/** + * @param {DAGLink[]} links + * @param {Bucket} rootBucket + * @param {Bucket} parentBucket + * @param {number} positionAtParent + */ const recreateHamtLevel = async (links, rootBucket, parentBucket, positionAtParent) => { // recreate this level of the HAMT const bucket = new Bucket({ - hashFn: DirSharded.hashFn, - hash: parentBucket ? parentBucket._options.hash : undefined + hash: rootBucket._options.hash, + bits: rootBucket._options.bits }, parentBucket, positionAtParent) - - if (parentBucket) { - parentBucket._putObjectAt(positionAtParent, bucket) - } + parentBucket._putObjectAt(positionAtParent, bucket) await addLinksToHamtBucket(links, bucket, rootBucket) return bucket } +/** + * @param {DAGLink[]} links + */ +const recreateInitialHamtLevel = async (links) => { + const importerOptions = defaultImporterOptions() + const bucket = createHAMT({ + hashFn: importerOptions.hamtHashFn, + bits: importerOptions.hamtBucketBits + }) + + await addLinksToHamtBucket(links, bucket, bucket) + + return bucket +} + +/** + * @param {DAGLink[]} links + * @param {Bucket} bucket + * @param {Bucket} rootBucket + */ const addLinksToHamtBucket = async (links, bucket, rootBucket) => { await Promise.all( links.map(link => { @@ -62,13 +112,14 @@ const addLinksToHamtBucket = async (links, bucket, rootBucket) => { const pos = parseInt(link.Name, 16) bucket._putObjectAt(pos, new Bucket({ - hashFn: DirSharded.hashFn + hash: rootBucket._options.hash, + bits: rootBucket._options.bits }, bucket, pos)) return Promise.resolve() } - return (rootBucket || bucket).put(link.Name.substring(2), { + return rootBucket.put(link.Name.substring(2), { size: link.Tsize, cid: link.Hash }) @@ -76,20 +127,29 @@ const addLinksToHamtBucket = async (links, bucket, rootBucket) => { ) } +/** + * @param {number} position + */ const toPrefix = (position) => { return position - .toString('16') + .toString(16) .toUpperCase() .padStart(2, '0') .substring(0, 2) } +/** + * @param {MfsContext} context + * @param {string} fileName + * @param {DAGNode} rootNode + */ const generatePath = async (context, fileName, rootNode) => { // start at the root bucket and descend, loading nodes as we go - const rootBucket = await recreateHamtLevel(rootNode.Links, null, null, null) + const rootBucket = await recreateInitialHamtLevel(rootNode.Links) const position = await rootBucket._findNewBucketAndPos(fileName) // the path to the root bucket + /** @type {{ bucket: Bucket, prefix: string, node?: DAGNode }[]} */ const path = [{ bucket: position.bucket, prefix: toPrefix(position.pos) @@ -102,6 +162,7 @@ const generatePath = async (context, fileName, rootNode) => { prefix: toPrefix(currentBucket._posAtParent) }) + // @ts-ignore - only the root bucket's parent will be undefined currentBucket = currentBucket._parent } @@ -112,6 +173,10 @@ const generatePath = async (context, fileName, rootNode) => { for (let i = 0; i < path.length; i++) { const segment = path[i] + if (!segment.node) { + throw new Error('Could not generate HAMT path') + } + // find prefix in links const link = segment.node.Links .filter(link => link.Name.substring(0, 2) === segment.prefix) @@ -172,7 +237,16 @@ const generatePath = async (context, fileName, rootNode) => { } } -const createShard = async (context, contents, options) => { +/** + * @param {MfsContext} context + * @param {{ name: string, size: number, cid: CID }[]} contents + * @param {object} [options] + * @param {Mtime} [options.mtime] + * @param {number} [options.mode] + */ +const createShard = async (context, contents, options = {}) => { + const importerOptions = defaultImporterOptions() + const shard = new DirSharded({ root: true, dir: true, @@ -184,6 +258,9 @@ const createShard = async (context, contents, options) => { mtime: options.mtime, mode: options.mode }, { + hamtHashFn: importerOptions.hamtHashFn, + hamtHashCode: importerOptions.hamtHashCode, + hamtBucketBits: importerOptions.hamtBucketBits, ...options, codec: 'dag-pb' }) @@ -195,13 +272,14 @@ const createShard = async (context, contents, options) => { }) } - return last(shard.flush('', context.block, null)) + return last(shard.flush(context.block)) } module.exports = { generatePath, updateHamtDirectory, recreateHamtLevel, + recreateInitialHamtLevel, addLinksToHamtBucket, toPrefix, createShard diff --git a/packages/ipfs-core/src/components/files/utils/remove-link.js b/packages/ipfs-core/src/components/files/utils/remove-link.js index 572521bc93..cd76807707 100644 --- a/packages/ipfs-core/src/components/files/utils/remove-link.js +++ b/packages/ipfs-core/src/components/files/utils/remove-link.js @@ -1,12 +1,11 @@ 'use strict' const { - DAGNode, DAGLink } = require('ipld-dag-pb') const CID = require('cids') const log = require('debug')('ipfs:mfs:core:utils:remove-link') -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') const { generatePath, updateHamtDirectory @@ -15,38 +14,78 @@ const errCode = require('err-code') const mc = require('multicodec') const mh = require('multihashing-async').multihash +/** + * @typedef {import('../').MfsContext} MfsContext + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('hamt-sharding').Bucket} Bucket + * @typedef {import('ipld-dag-pb').DAGNode} DAGNode + * + * @typedef {object} RemoveLinkOptions + * @property {string} name + * @property {number} shardSplitThreshold + * @property {HashName} hashAlg + * @property {CIDVersion} cidVersion + * @property {boolean} flush + * @property {CID} [parentCid] + * @property {DAGNode} [parent] + * + * @typedef {object} RemoveLinkOptionsInternal + * @property {string} name + * @property {number} shardSplitThreshold + * @property {HashName} hashAlg + * @property {CIDVersion} cidVersion + * @property {boolean} flush + * @property {DAGNode} parent + */ + +/** + * @param {MfsContext} context + * @param {RemoveLinkOptions} options + */ const removeLink = async (context, options) => { - if (!options.parentCid && !options.parent) { - throw errCode(new Error('No parent node or CID passed to removeLink'), 'EINVALIDPARENT') - } + let parent = options.parent - if (options.parentCid && !CID.isCID(options.parentCid)) { - throw errCode(new Error('Invalid CID passed to removeLink'), 'EINVALIDPARENTCID') - } + if (options.parentCid) { + if (!CID.isCID(options.parentCid)) { + throw errCode(new Error('Invalid CID passed to removeLink'), 'EINVALIDPARENTCID') + } - if (!options.parent) { log(`Loading parent node ${options.parentCid}`) + parent = await context.ipld.get(options.parentCid) + } - options.parent = await context.ipld.get(options.parentCid) + if (!parent) { + throw errCode(new Error('No parent node or CID passed to removeLink'), 'EINVALIDPARENT') } if (!options.name) { throw errCode(new Error('No child name passed to removeLink'), 'EINVALIDCHILDNAME') } - const meta = UnixFS.unmarshal(options.parent.Data) + const meta = UnixFS.unmarshal(parent.Data) if (meta.type === 'hamt-sharded-directory') { log(`Removing ${options.name} from sharded directory`) - return removeFromShardedDirectory(context, options) + return removeFromShardedDirectory(context, { + ...options, + parent + }) } log(`Removing link ${options.name} regular directory`) - return removeFromDirectory(context, options) + return removeFromDirectory(context, { + ...options, + parent + }) } +/** + * @param {MfsContext} context + * @param {RemoveLinkOptionsInternal} options + */ const removeFromDirectory = async (context, options) => { const hashAlg = mh.names[options.hashAlg] @@ -64,6 +103,10 @@ const removeFromDirectory = async (context, options) => { } } +/** + * @param {MfsContext} context + * @param {RemoveLinkOptionsInternal} options + */ const removeFromShardedDirectory = async (context, options) => { const { rootBucket, path @@ -73,65 +116,86 @@ const removeFromShardedDirectory = async (context, options) => { const { node - } = await updateShard(context, path, { - name: options.name, - cid: options.cid, - size: options.size, - hashAlg: options.hashAlg, - cidVersion: options.cidVersion, - flush: options.flush - }, options) + } = await updateShard(context, path, options.name, options) return updateHamtDirectory(context, node.Links, rootBucket, options) } -const updateShard = async (context, positions, child, options) => { +/** + * @param {MfsContext} context + * @param {{ bucket: Bucket, prefix: string, node?: DAGNode }[]} positions + * @param {string} name + * @param {RemoveLinkOptionsInternal} options + * @returns {Promise<{ node: DAGNode, cid: CID, size: number }>} + */ +const updateShard = async (context, positions, name, options) => { + const last = positions.pop() + + if (!last) { + throw errCode(new Error('Could not find parent'), 'EINVALIDPARENT') + } + const { bucket, prefix, node - } = positions.pop() + } = last + + if (!node) { + throw errCode(new Error('Could not find parent'), 'EINVALIDPARENT') + } const link = node.Links .find(link => link.Name.substring(0, 2) === prefix) if (!link) { - throw errCode(new Error(`No link found with prefix ${prefix} for file ${child.name}`), 'ERR_NOT_FOUND') + throw errCode(new Error(`No link found with prefix ${prefix} for file ${name}`), 'ERR_NOT_FOUND') } - if (link.Name === `${prefix}${child.name}`) { + if (link.Name === `${prefix}${name}`) { log(`Removing existing link ${link.Name}`) node.rmLink(link.Name) - await bucket.del(child.name) + await bucket.del(name) return updateHamtDirectory(context, node.Links, bucket, options) } - log(`Descending into sub-shard ${link.Name} for ${prefix}${child.name}`) + log(`Descending into sub-shard ${link.Name} for ${prefix}${name}`) - const result = await updateShard(context, positions, child, options) + const result = await updateShard(context, positions, name, options) + let cid = result.cid + let size = result.size let newName = prefix if (result.node.Links.length === 1) { log(`Removing subshard for ${prefix}`) // convert shard back to normal dir - result.cid = result.node.Links[0].Hash - result.node = result.node.Links[0] + const link = result.node.Links[0] - newName = `${prefix}${result.node.Name.substring(2)}` + newName = `${prefix}${link.Name.substring(2)}` + cid = link.Hash + size = link.Tsize } log(`Updating shard ${prefix} with name ${newName}`) - const size = DAGNode.isDAGNode(result.node) ? result.node.size : result.node.Tsize - - return updateShardParent(context, bucket, node, prefix, newName, size, result.cid, options) + return updateShardParent(context, bucket, node, prefix, newName, size, cid, options) } +/** + * @param {MfsContext} context + * @param {Bucket} bucket + * @param {DAGNode} parent + * @param {string} oldName + * @param {string} newName + * @param {number} size + * @param {CID} cid + * @param {RemoveLinkOptionsInternal} options + */ const updateShardParent = (context, bucket, parent, oldName, newName, size, cid, options) => { parent.rmLink(oldName) parent.addLink(new DAGLink(newName, size, cid)) diff --git a/packages/ipfs-core/src/components/files/utils/to-async-iterator.js b/packages/ipfs-core/src/components/files/utils/to-async-iterator.js index e591bcd2c0..93acfbcf26 100644 --- a/packages/ipfs-core/src/components/files/utils/to-async-iterator.js +++ b/packages/ipfs-core/src/components/files/utils/to-async-iterator.js @@ -7,6 +7,9 @@ const { } = require('../../../utils') const uint8ArrayFromString = require('uint8arrays/from-string') +/** + * @param {*} content + */ const toAsyncIterator = (content) => { if (!content) { throw errCode(new Error('paths must start with a leading slash'), 'ERR_INVALID_PATH') @@ -58,7 +61,11 @@ const toAsyncIterator = (content) => { const reader = new global.FileReader() + /** + * @param {{ error?: Error }} ev + */ const handleLoad = (ev) => { + // @ts-ignore No overload matches this call. reader.removeEventListener('loadend', handleLoad, false) if (ev.error) { @@ -71,6 +78,7 @@ const toAsyncIterator = (content) => { }) } + // @ts-ignore No overload matches this call. reader.addEventListener('loadend', handleLoad) reader.readAsArrayBuffer(chunk) }) diff --git a/packages/ipfs-core/src/components/files/utils/to-mfs-path.js b/packages/ipfs-core/src/components/files/utils/to-mfs-path.js index c5a23828af..7c82641894 100644 --- a/packages/ipfs-core/src/components/files/utils/to-mfs-path.js +++ b/packages/ipfs-core/src/components/files/utils/to-mfs-path.js @@ -2,71 +2,157 @@ const loadMfsRoot = require('./with-mfs-root') const toPathComponents = require('./to-path-components') -const exporter = require('ipfs-unixfs-exporter') +const { exporter } = require('ipfs-unixfs-exporter') const errCode = require('err-code') const CID = require('cids') const IPFS_PREFIX = 'ipfs' +/** + * @typedef {import('ipfs-unixfs-exporter').UnixFSEntry} UnixFSEntry + * @typedef {import('ipfs-unixfs-exporter').ExporterOptions} ExporterOptions + * @typedef {import('../').MfsContext} MfsContext + * + * @typedef {object} FilePath + * @property {'mfs' | 'ipfs'} type + * @property {'file'} entryType + * @property {number} depth + * @property {string} mfsPath + * @property {string} mfsDirectory + * @property {string[]} parts + * @property {string} path + * @property {string} name + * @property {CID} cid + * @property {boolean} exists + * @property {import('ipfs-unixfs').UnixFS} unixfs + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {object} DirectoryPath + * @property {'mfs' | 'ipfs'} type + * @property {'directory'} entryType + * @property {number} depth + * @property {string} mfsPath + * @property {string} mfsDirectory + * @property {string[]} parts + * @property {string} path + * @property {string} name + * @property {CID} cid + * @property {boolean} exists + * @property {import('ipfs-unixfs').UnixFS} unixfs + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {object} ObjectPath + * @property {'mfs' | 'ipfs'} type + * @property {'object'} entryType + * @property {number} depth + * @property {string} mfsPath + * @property {string} mfsDirectory + * @property {string[]} parts + * @property {string} path + * @property {string} name + * @property {CID} cid + * @property {boolean} exists + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {object} RawPath + * @property {'mfs' | 'ipfs'} type + * @property {'raw'} entryType + * @property {number} depth + * @property {string} mfsPath + * @property {string} mfsDirectory + * @property {string[]} parts + * @property {string} path + * @property {string} name + * @property {CID} cid + * @property {boolean} exists + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {object} IdentityPath + * @property {'mfs' | 'ipfs'} type + * @property {'identity'} entryType + * @property {number} depth + * @property {string} mfsPath + * @property {string} mfsDirectory + * @property {string[]} parts + * @property {string} path + * @property {string} name + * @property {CID} cid + * @property {boolean} exists + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {FilePath | DirectoryPath | ObjectPath | RawPath | IdentityPath} MfsPath + */ + +/** + * @param {MfsContext} context + * @param {string | CID} path + * @param {import('ipfs-core-types/src/utils').AbortOptions} [options] + */ const toMfsPath = async (context, path, options) => { - const outputArray = Array.isArray(path) - let paths = Array.isArray(path) ? path : [path] const root = await loadMfsRoot(context, options) - paths = paths.map(path => { - if (CID.isCID(path)) { - path = `/ipfs/${path}` - } - - path = (path || '').trim() - path = path.replace(/(\/\/+)/g, '/') + /** @type {MfsPath} */ + // @ts-ignore fields get set later + let output = { + entryType: 'file' + } - if (path.endsWith('/') && path.length > 1) { - path = path.substring(0, path.length - 1) - } + if (CID.isCID(path)) { + path = `/ipfs/${path}` + } - if (!path) { - throw errCode(new Error('paths must not be empty'), 'ERR_NO_PATH') - } + path = (path || '').trim() + path = path.replace(/(\/\/+)/g, '/') - if (path.substring(0, 1) !== '/') { - throw errCode(new Error('paths must start with a leading slash'), 'ERR_INVALID_PATH') - } + if (path.endsWith('/') && path.length > 1) { + path = path.substring(0, path.length - 1) + } - if (path.substring(path.length - 1) === '/') { - path = path.substring(0, path.length - 1) - } + if (!path) { + throw errCode(new Error('paths must not be empty'), 'ERR_NO_PATH') + } - const pathComponents = toPathComponents(path) + if (path.substring(0, 1) !== '/') { + throw errCode(new Error('paths must start with a leading slash'), 'ERR_INVALID_PATH') + } - if (pathComponents[0] === IPFS_PREFIX) { - // e.g. /ipfs/QMfoo or /ipfs/Qmfoo/sub/path - let mfsDirectory + if (path.substring(path.length - 1) === '/') { + path = path.substring(0, path.length - 1) + } - if (pathComponents.length === 2) { - mfsDirectory = `/${pathComponents.join('/')}` - } else { - mfsDirectory = `/${pathComponents.slice(0, pathComponents.length - 1).join('/')}` - } + const pathComponents = toPathComponents(path) - return { - type: 'ipfs', - depth: pathComponents.length - 2, + if (pathComponents[0] === IPFS_PREFIX) { + // e.g. /ipfs/QMfoo or /ipfs/Qmfoo/sub/path + let mfsDirectory - mfsPath: `/${pathComponents.join('/')}`, - mfsDirectory, - parts: pathComponents, - path: `/${pathComponents.join('/')}`, - name: pathComponents[pathComponents.length - 1] - } + if (pathComponents.length === 2) { + mfsDirectory = `/${pathComponents.join('/')}` + } else { + mfsDirectory = `/${pathComponents.slice(0, pathComponents.length - 1).join('/')}` } + // @ts-ignore fields being set + output = { + type: 'ipfs', + depth: pathComponents.length - 2, + entryType: 'file', + + mfsPath: `/${pathComponents.join('/')}`, + mfsDirectory, + parts: pathComponents, + path: `/${pathComponents.join('/')}`, + name: pathComponents[pathComponents.length - 1] + } + } else { const mfsPath = `/${IPFS_PREFIX}/${root}${pathComponents.length ? '/' + pathComponents.join('/') : ''}` const mfsDirectory = `/${IPFS_PREFIX}/${root}/${pathComponents.slice(0, pathComponents.length - 1).join('/')}` - return { + // @ts-ignore fields being set + output = { type: 'mfs', depth: pathComponents.length, + entryType: 'file', mfsDirectory, mfsPath, @@ -74,34 +160,30 @@ const toMfsPath = async (context, path, options) => { path: `/${pathComponents.join('/')}`, name: pathComponents[pathComponents.length - 1] } - }) - - await Promise.all( - paths.map(async (path) => { - const cidPath = path.type === 'mfs' ? path.mfsPath : path.path - - try { - const res = await exporter(cidPath, context.ipld) - - path.cid = res.cid - path.mfsPath = `/ipfs/${res.path}` - path.unixfs = res.unixfs - path.content = res.content - } catch (err) { - if (err.code !== 'ERR_NOT_FOUND') { - throw err - } - } - - path.exists = Boolean(path.cid) - }) - ) - - if (outputArray) { - return paths } - return paths[0] + const cidPath = output.type === 'mfs' ? output.mfsPath : output.path + + try { + const res = await exporter(cidPath, context.ipld) + + output.cid = res.cid + output.mfsPath = `/ipfs/${res.path}` + output.entryType = res.type + output.content = res.content + + if ((output.entryType === 'file' || output.entryType === 'directory') && (res.type === 'file' || res.type === 'directory')) { + output.unixfs = res.unixfs + } + } catch (err) { + if (err.code !== 'ERR_NOT_FOUND') { + throw err + } + } + + output.exists = Boolean(output.cid) + + return output } module.exports = toMfsPath diff --git a/packages/ipfs-core/src/components/files/utils/to-path-components.js b/packages/ipfs-core/src/components/files/utils/to-path-components.js index 5e8262727a..bc80b125d9 100644 --- a/packages/ipfs-core/src/components/files/utils/to-path-components.js +++ b/packages/ipfs-core/src/components/files/utils/to-path-components.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {string} [path] + */ const toPathComponents = (path = '') => { // split on / unless escaped with \ return (path diff --git a/packages/ipfs-core/src/components/files/utils/to-sources-and-destination.js b/packages/ipfs-core/src/components/files/utils/to-sources-and-destination.js deleted file mode 100644 index 26e8d6a536..0000000000 --- a/packages/ipfs-core/src/components/files/utils/to-sources-and-destination.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -const toSources = require('./to-sources') - -async function toSourcesAndDestination (context, args, defaultOptions) { - const { - sources, - options - } = await toSources(context, args, defaultOptions) - - const destination = sources.pop() - - return { - destination, - sources, - options - } -} - -module.exports = toSourcesAndDestination diff --git a/packages/ipfs-core/src/components/files/utils/to-sources.js b/packages/ipfs-core/src/components/files/utils/to-sources.js deleted file mode 100644 index 256e0440f8..0000000000 --- a/packages/ipfs-core/src/components/files/utils/to-sources.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict' - -const toMfsPath = require('./to-mfs-path') -const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) - -async function toSources (context, args, defaultOptions) { - const sources = [] - let options - - // takes string arguments and a final optional non-string argument - for (let i = 0; i < args.length; i++) { - if (typeof args[i] === 'string' || args[i] instanceof String) { - sources.push(args[i].trim()) - } else if (i === args.length - 1) { - options = args[i] - } - } - - options = mergeOptions(defaultOptions, options) - - return { - sources: await toMfsPath(context, sources, options), - options - } -} - -module.exports = toSources diff --git a/packages/ipfs-core/src/components/files/utils/to-trail.js b/packages/ipfs-core/src/components/files/utils/to-trail.js index 7a42d8acca..387c50a920 100644 --- a/packages/ipfs-core/src/components/files/utils/to-trail.js +++ b/packages/ipfs-core/src/components/files/utils/to-trail.js @@ -1,19 +1,44 @@ 'use strict' -const exporter = require('ipfs-unixfs-exporter') +const { walkPath } = require('ipfs-unixfs-exporter') const log = require('debug')('ipfs:mfs:utils:to-trail') +/** + * @typedef {import('../').MfsContext} MfsContext + * @typedef {object} MfsTrail + * @property {string} name + * @property {import('cids')} cid + * @property {number} [size] + * @property {string} [type] + * + * TODO: export supported types from unixfs-exporter and use for `type` above + */ + +/** + * @param {MfsContext} context + * @param {string} path + * @returns {Promise} + */ const toTrail = async (context, path) => { log(`Creating trail for path ${path}`) const output = [] - for await (const fsEntry of exporter.path(path, context.ipld)) { + for await (const fsEntry of walkPath(path, context.ipld)) { + let size + + // TODO: include `.size` property in unixfs-exporter output + if (fsEntry.node instanceof Uint8Array) { + size = fsEntry.node.length + } else { + size = fsEntry.node.size + } + output.push({ name: fsEntry.name, cid: fsEntry.cid, - size: fsEntry.node.size, - type: fsEntry.unixfs ? fsEntry.unixfs.type : undefined + size, + type: fsEntry.type }) } diff --git a/packages/ipfs-core/src/components/files/utils/types.ts b/packages/ipfs-core/src/components/files/utils/types.ts deleted file mode 100644 index 9d22f87a08..0000000000 --- a/packages/ipfs-core/src/components/files/utils/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Helper type to represet monomorphic tuples with up to 8 items. - */ -export type Tuple = - | [T] - | [T, T] - | [T, T, T] - | [T, T, T, T] - | [T, T, T, T, T] - | [T, T, T, T, T, T] - | [T, T, T, T, T, T, T] - | [T, T, T, T, T, T, T, T] diff --git a/packages/ipfs-core/src/components/files/utils/update-mfs-root.js b/packages/ipfs-core/src/components/files/utils/update-mfs-root.js index d172c34c76..b96ba32983 100644 --- a/packages/ipfs-core/src/components/files/utils/update-mfs-root.js +++ b/packages/ipfs-core/src/components/files/utils/update-mfs-root.js @@ -6,6 +6,15 @@ const { } = require('../../../utils') const errCode = require('err-code') +/** + * @typedef {import('../').MfsContext} MfsContext + */ + +/** + * @param {MfsContext} context + * @param {import('cids')} cid + * @param {import('ipfs-core-types/src/utils').AbortOptions} options + */ const updateMfsRoot = async (context, cid, options) => { if (options && options.signal && options.signal.aborted) { throw errCode(new Error('Request aborted'), 'ERR_ABORTED', { name: 'Aborted' }) diff --git a/packages/ipfs-core/src/components/files/utils/update-tree.js b/packages/ipfs-core/src/components/files/utils/update-tree.js index dc78800482..226f9c79a8 100644 --- a/packages/ipfs-core/src/components/files/utils/update-tree.js +++ b/packages/ipfs-core/src/components/files/utils/update-tree.js @@ -7,7 +7,25 @@ const defaultOptions = { shardSplitThreshold: 1000 } -// loop backwards through the trail, replacing links of all components to update CIDs +/** + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids')} CID + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('../').MfsContext} MfsContext + * @typedef {import('./to-trail').MfsTrail} MfsTrail + */ + +/** + * Loop backwards through the trail, replacing links of all components to update CIDs + * + * @param {MfsContext} context + * @param {MfsTrail[]} trail + * @param {object} options + * @param {number} options.shardSplitThreshold + * @param {HashName} options.hashAlg + * @param {CIDVersion} options.cidVersion + * @param {boolean} options.flush + */ const updateTree = async (context, trail, options) => { options = Object.assign({}, defaultOptions, options) @@ -32,6 +50,7 @@ const updateTree = async (context, trail, options) => { continue } + /** @type {{ cid: CID, size: number }} */ const result = await addLink(context, { parent: node, name: child.name, diff --git a/packages/ipfs-core/src/components/files/utils/with-mfs-root.js b/packages/ipfs-core/src/components/files/utils/with-mfs-root.js index a25b0ceb73..234016f18c 100644 --- a/packages/ipfs-core/src/components/files/utils/with-mfs-root.js +++ b/packages/ipfs-core/src/components/files/utils/with-mfs-root.js @@ -1,7 +1,7 @@ 'use strict' const CID = require('cids') -const UnixFs = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') const { DAGNode } = require('ipld-dag-pb') @@ -14,6 +14,14 @@ const { MFS_ROOT_KEY } = require('../../../utils') +/** + * @typedef {import('../').MfsContext} MfsContext + */ + +/** + * @param {MfsContext} context + * @param {import('ipfs-core-types/src/utils').AbortOptions} [options] + */ const loadMfsRoot = async (context, options) => { if (options && options.signal && options.signal.aborted) { throw errCode(new Error('Request aborted'), 'ERR_ABORTED', { name: 'Aborted' }) @@ -35,7 +43,7 @@ const loadMfsRoot = async (context, options) => { } log('Creating new MFS root') - const node = new DAGNode(new UnixFs({ type: 'directory' }).marshal()) + const node = new DAGNode(new UnixFS({ type: 'directory' }).marshal()) cid = await context.ipld.put(node, mc.DAG_PB, { cidVersion: 0, hashAlg: mh.names['sha2-256'] // why can't ipld look this up? diff --git a/packages/ipfs-core/src/components/files/write.js b/packages/ipfs-core/src/components/files/write.js index 330043ca8a..c24ffd86a2 100644 --- a/packages/ipfs-core/src/components/files/write.js +++ b/packages/ipfs-core/src/components/files/write.js @@ -1,7 +1,7 @@ 'use strict' const log = require('debug')('ipfs:mfs:write') -const importer = require('ipfs-unixfs-importer') +const { importer } = require('ipfs-unixfs-importer') const stat = require('./stat') const mkdir = require('./mkdir') const addLink = require('./utils/add-link') @@ -19,10 +19,45 @@ const { } = require('../../utils') const last = require('it-last') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +const { + parseMode, + parseMtime +} = require('ipfs-unixfs') +/** + * @typedef {import('multihashes').HashName} HashName + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('ipfs-unixfs').MtimeLike} MtimeLike + * @typedef {import('./').MfsContext} MfsContext + * @typedef {import('./utils/to-mfs-path').FilePath} FilePath + * @typedef {import('./utils/to-mfs-path').MfsPath} MfsPath + * @typedef {object} DefaultOptions + * @property {number} offset + * @property {number} length + * @property {boolean} create + * @property {boolean} truncate + * @property {boolean} rawLeaves + * @property {boolean} reduceSingleLeafToSelf + * @property {CIDVersion} cidVersion + * @property {HashName} hashAlg + * @property {boolean} parents + * @property {import('ipfs-core-types/src/root').AddProgressFn} progress + * @property {'trickle' | 'balanced'} strategy + * @property {boolean} flush + * @property {'raw' | 'file'} leafType + * @property {number} shardSplitThreshold + * @property {MtimeLike} [mtime] + * @property {number} [mode] + * @property {AbortSignal} [signal] + * @property {number} [timeout] + */ + +/** + * @type {DefaultOptions} + */ const defaultOptions = { offset: 0, // the offset in the file to begin writing - length: undefined, // how many bytes from the incoming buffer to write + length: Infinity, // how many bytes from the incoming buffer to write create: false, // whether to create the file if it does not exist truncate: false, // whether to truncate the file first rawLeaves: false, @@ -30,29 +65,30 @@ const defaultOptions = { cidVersion: 0, hashAlg: 'sha2-256', parents: false, // whether to create intermediate directories if they do not exist - progress: () => {}, + progress: (bytes, path) => {}, strategy: 'trickle', flush: true, leafType: 'raw', - shardSplitThreshold: 1000, - mode: undefined, - mtime: undefined, - signal: undefined + shardSplitThreshold: 1000 } +/** + * @param {MfsContext} context + */ module.exports = (context) => { /** - * Write to an MFS path - * - * @param {string} path - The MFS path where you will write to - * @param {string|Uint8Array|AsyncIterable|Blob} content - The content to write to the path - * @param {WriteOptions & AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/files').API["write"]} */ - async function mfsWrite (path, content, options = {}) { - options = mergeOptions(defaultOptions, options) - - let source, destination, parent + async function mfsWrite (path, content, opts = {}) { + /** @type {DefaultOptions} */ + const options = mergeOptions(defaultOptions, opts) + + /** @type {AsyncIterable} */ + let source + /** @type {MfsPath} */ + let destination + /** @type {MfsPath} */ + let parent log('Reading source, destination and parent') await createLock().readLock(async () => { source = await toAsyncIterator(content) @@ -60,22 +96,42 @@ module.exports = (context) => { parent = await toMfsPath(context, destination.mfsDirectory, options) })() log('Read source, destination and parent') - // @ts-ignore - parent maybe undefined + // @ts-ignore - parent may be undefined if (!options.parents && !parent.exists) { throw errCode(new Error('directory does not exist'), 'ERR_NO_EXIST') } - // @ts-ignore - parent maybe undefined + // @ts-ignore + if (source == null) { + throw errCode(new Error('could not create source'), 'ERR_NO_SOURCE') + } + + // @ts-ignore + if (destination == null) { + throw errCode(new Error('could not create destination'), 'ERR_NO_DESTINATION') + } + if (!options.create && !destination.exists) { throw errCode(new Error('file does not exist'), 'ERR_NO_EXIST') } + if (destination.entryType !== 'file') { + throw errCode(new Error('not a file'), 'ERR_NOT_A_FILE') + } + return updateOrImport(context, path, source, destination, options) } return withTimeoutOption(mfsWrite) } +/** + * @param {MfsContext} context + * @param {string} path + * @param {AsyncIterable} source + * @param {FilePath} destination + * @param {DefaultOptions} options + */ const updateOrImport = async (context, path, source, destination, options) => { const child = await write(context, source, destination, options) @@ -84,6 +140,11 @@ const updateOrImport = async (context, path, source, destination, options) => { await createLock().writeLock(async () => { const pathComponents = toPathComponents(path) const fileName = pathComponents.pop() + + if (fileName == null) { + throw errCode(new Error('source does not exist'), 'ERR_NO_EXIST') + } + let parentExists = false try { @@ -104,7 +165,11 @@ const updateOrImport = async (context, path, source, destination, options) => { const trail = await toTrail(context, updatedPath.mfsDirectory) const parent = trail[trail.length - 1] - if (!parent.type.includes('directory')) { + if (!parent) { + throw errCode(new Error('directory does not exist'), 'ERR_NO_EXIST') + } + + if (!parent.type || !parent.type.includes('directory')) { throw errCode(new Error(`cannot write to ${parent.name}: Not a directory`), 'ERR_NOT_A_DIRECTORY') } @@ -131,6 +196,12 @@ const updateOrImport = async (context, path, source, destination, options) => { })() } +/** + * @param {MfsContext} context + * @param {AsyncIterable} source + * @param {FilePath} destination + * @param {DefaultOptions} options + */ const write = async (context, source, destination, options) => { if (destination.exists) { log(`Overwriting file ${destination.cid} offset ${options.offset} length ${options.length}`) @@ -138,6 +209,7 @@ const write = async (context, source, destination, options) => { log(`Writing file offset ${options.offset} length ${options.length}`) } + /** @type {Array<() => AsyncIterable>} */ const sources = [] // pad start of file if necessary @@ -196,18 +268,20 @@ const write = async (context, source, destination, options) => { } }) + /** @type {number | undefined} */ let mode if (options.mode !== undefined && options.mode !== null) { - mode = options.mode + mode = parseMode(options.mode) } else if (destination && destination.unixfs) { mode = destination.unixfs.mode } + /** @type {import('ipfs-unixfs').Mtime | undefined} */ let mtime - if (options.mtime !== undefined && options.mtine !== null) { - mtime = options.mtime + if (options.mtime != null) { + mtime = parseMtime(options.mtime) } else if (destination && destination.unixfs) { mtime = destination.unixfs.mtime } @@ -229,6 +303,10 @@ const write = async (context, source, destination, options) => { pin: false })) + if (!result) { + throw errCode(new Error(`cannot write to ${parent.name}`), 'ERR_COULD_NOT_WRITE') + } + log(`Wrote ${result.cid}`) return { @@ -237,6 +315,10 @@ const write = async (context, source, destination, options) => { } } +/** + * @param {AsyncIterable} stream + * @param {number} limit + */ const limitAsyncStreamBytes = (stream, limit) => { return async function * _limitAsyncStreamBytes () { let emitted = 0 @@ -255,26 +337,35 @@ const limitAsyncStreamBytes = (stream, limit) => { } } +/** + * @param {number} count + * @param {number} chunkSize + */ const asyncZeroes = (count, chunkSize = MFS_MAX_CHUNK_SIZE) => { const buf = new Uint8Array(chunkSize) - const stream = { - [Symbol.asyncIterator]: function * _asyncZeroes () { - while (true) { - yield buf.slice() - } + async function * _asyncZeroes () { + while (true) { + yield buf.slice() } } - return limitAsyncStreamBytes(stream, count) + return limitAsyncStreamBytes(_asyncZeroes(), count) } +/** + * @param {Array<() => AsyncIterable>} sources + */ const catAsyncIterators = async function * (sources) { // eslint-disable-line require-await for (let i = 0; i < sources.length; i++) { yield * sources[i]() } } +/** + * @param {AsyncIterable} source + * @param {(count: number) => AsyncIterable} notify + */ const countBytesStreamed = async function * (source, notify) { let wrote = 0 @@ -290,20 +381,3 @@ const countBytesStreamed = async function * (source, notify) { yield buf } } - -/** - * @typedef {Object} WriteOptions - * @property {number} [offset] - An offset to start writing to file at - * @property {number} [length] - Optionally limit how many bytes are read from the stream - * @property {boolean} [create=false] - Create the MFS path if it does not exist - * @property {boolean} [parents=false] - Create intermediate MFS paths if they do not exist - * @property {boolean} [truncate=false] - Truncate the file at the MFS path if it would have been larger than the passed content - * @property {boolean} [rawLeaves=false] - If true, DAG leaves will contain raw file data and not be wrapped in a protobuf - * @property {import('ipfs-core-types/src/files').ToMode} [mode] - An integer that represents the file mode - * @property {import('ipfs-core-types/src/files').ToMTime} [mtime] - A Date object, an object with `{ secs, nsecs }` properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of `process.hrtime() - * @property {boolean} [flush] - If true the changes will be immediately flushed to disk - * @property {string} [hashAlg='sha2-256'] - The hash algorithm to use for any updated entries - * @property {0|1} [cidVersion=0] - The CID version to use for any updated entries - * - * @typedef {import('../../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/gc-lock.js b/packages/ipfs-core/src/components/gc-lock.js index 9eed02de1c..16a7053c2c 100644 --- a/packages/ipfs-core/src/components/gc-lock.js +++ b/packages/ipfs-core/src/components/gc-lock.js @@ -1,5 +1,6 @@ 'use strict' +// @ts-ignore - no types const mortice = require('mortice') /** diff --git a/packages/ipfs-core/src/components/get.js b/packages/ipfs-core/src/components/get.js index f183dc37a2..f7a30afe60 100644 --- a/packages/ipfs-core/src/components/get.js +++ b/packages/ipfs-core/src/components/get.js @@ -7,19 +7,14 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @typedef {Object} Context - * @property {import('.').IPLD} ipld - * @property {import('.').Preload} preload + * @property {import('ipld')} ipld + * @property {import('../types').Preload} preload * * @param {Context} context */ module.exports = function ({ ipld, preload }) { /** - * Fetch a file or an entire directory tree from IPFS that is addressed by a - * valid IPFS Path. - * - * @param {import('ipfs-core-types/src/root').IPFSPath} ipfsPath - * @param {import('ipfs-core-types/src/root').GetOptions} [options] - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/root').API["get"]} */ async function * get (ipfsPath, options = {}) { if (options.preload !== false) { diff --git a/packages/ipfs-core/src/components/id.js b/packages/ipfs-core/src/components/id.js index cbd06eb187..88a94ff3ec 100644 --- a/packages/ipfs-core/src/components/id.js +++ b/packages/ipfs-core/src/components/id.js @@ -7,24 +7,18 @@ const uint8ArrayToString = require('uint8arrays/to-string') /** * @param {Object} config - * @param {import('.').PeerId} config.peerId - * @param {import('.').NetworkService} config.network + * @param {import('peer-id')} config.peerId + * @param {import('../types').NetworkService} config.network */ module.exports = ({ peerId, network }) => { /** - * Returns the identity of the Peer - * - * @param {import('../utils').AbortOptions} [_options] - * @returns {Promise} - * @example - * ```js - * const identity = await ipfs.id() - * console.log(identity) - * ``` + * @type {import('ipfs-core-types/src/root').API["id"]} */ - async function id (_options) { // eslint-disable-line require-await + async function id (_options = {}) { // eslint-disable-line require-await const id = peerId.toB58String() + /** @type {import('multiaddr')[]} */ let addresses = [] + /** @type {string[]} */ let protocols = [] const net = network.try() diff --git a/packages/ipfs-core/src/components/index.js b/packages/ipfs-core/src/components/index.js index 20652c29a5..051f2b6819 100644 --- a/packages/ipfs-core/src/components/index.js +++ b/packages/ipfs-core/src/components/index.js @@ -3,12 +3,12 @@ const { mergeOptions } = require('../utils') const { isTest } = require('ipfs-utils/src/env') const log = require('debug')('ipfs') - +const errCode = require('err-code') const { DAGNode } = require('ipld-dag-pb') -const UnixFs = require('ipfs-unixfs') -const multicodec = require('multicodec') +const { UnixFS } = require('ipfs-unixfs') const initAssets = require('../runtime/init-assets-nodejs') const { AlreadyInitializedError } = require('../errors') +const uint8ArrayFromString = require('uint8arrays/from-string') const createStartAPI = require('./start') const createStopAPI = require('./stop') @@ -36,7 +36,7 @@ const KeyAPI = require('./key') const ObjectAPI = require('./object') const RepoAPI = require('./repo') const StatsAPI = require('./stats') -const IPFSBlockService = require('ipfs-block-service') +const BlockService = require('ipfs-block-service') const createIPLD = require('./ipld') const Storage = require('./storage') const Network = require('./network') @@ -47,6 +47,12 @@ const createPingAPI = require('./ping') const createDHTAPI = require('./dht') const createPubSubAPI = require('./pubsub') +/** + * @typedef {import('../types').Options} Options + * @typedef {import('../types').Print} Print + * @typedef {import('./storage')} StorageAPI + */ + class IPFS { /** * @param {Object} config @@ -60,9 +66,8 @@ class IPFS { const preload = createPreloadAPI(options.preload) - /** @type {BlockService} */ - const blockService = new IPFSBlockService(storage.repo) - const ipld = createIPLD({ blockService, print, options: options.ipld }) + const blockService = new BlockService(storage.repo) + const ipld = createIPLD({ blockService, options: options.ipld }) const gcLock = createGCLockAPI({ path: repo.path, @@ -73,22 +78,21 @@ class IPFS { // @ts-ignore This type check fails as options. // libp2p can be a function, while IPNS router config expects libp2p config const ipns = new IPNSAPI(options) - const dagReader = DagAPI.reader({ ipld, preload }) const name = new NameAPI({ dns, ipns, - dagReader, + ipld, peerId, isOnline, keychain, options }) const resolve = createResolveAPI({ ipld, name }) - const pinManager = new PinManagerAPI({ repo, dagReader }) - const pin = new PinAPI({ gcLock, pinManager, dagReader }) + const pinManager = new PinManagerAPI({ repo, ipld }) + const pin = new PinAPI({ gcLock, pinManager, ipld }) const block = new BlockAPI({ blockService, preload, gcLock, pinManager, pin }) - const dag = new DagAPI({ ipld, preload, gcLock, pin, dagReader }) + const dag = new DagAPI({ ipld, preload, gcLock, pin }) const refs = Object.assign(createRefsAPI({ ipld, resolve, preload }), { local: createRefsLocalAPI({ repo: storage.repo }) }) @@ -167,7 +171,7 @@ class IPFS { this.dag = dag this.files = files this.key = new KeyAPI({ keychain }) - this.object = new ObjectAPI({ ipld, preload, gcLock, dag }) + this.object = new ObjectAPI({ ipld, preload, gcLock }) this.repo = new RepoAPI({ gcLock, pin, repo, refs }) this.stats = new StatsAPI({ repo, network }) this.swarm = new SwarmAPI({ network }) @@ -179,6 +183,22 @@ class IPFS { return net ? net.libp2p : undefined } }) + + // unimplemented methods + const notImplemented = () => Promise.reject(errCode(new Error('Not implemented'), 'ERR_NOT_IMPLEMENTED')) + const notImplementedIter = async function * () { throw errCode(new Error('Not implemented'), 'ERR_NOT_IMPLEMENTED') } // eslint-disable-line require-yield + this.commands = notImplemented + this.diag = { + cmds: notImplemented, + net: notImplemented, + sys: notImplemented + } + this.log = { + level: notImplemented, + ls: notImplemented, + tail: notImplementedIter + } + this.mount = notImplemented } /** @@ -196,16 +216,11 @@ class IPFS { */ static async create (options = {}) { options = mergeOptions(getDefaultOptions(), options) + const initOptions = options.init || {} // eslint-disable-next-line no-console const print = options.silent ? log : console.log - - const init = { - ...mergeOptions(initOptions(options), options), - print - } - - const storage = await Storage.start(init) + const storage = await Storage.start(print, options) const config = await storage.repo.config.getAll() const ipfs = new IPFS({ @@ -217,7 +232,8 @@ class IPFS { await ipfs.preload.start() ipfs.ipns.startOffline(storage) - if (storage.isNew && !init.emptyRepo) { + + if (storage.isNew && !initOptions.emptyRepo) { // add empty unixfs dir object (go-ipfs assumes this exists) const cid = await addEmptyDir(ipfs) @@ -225,7 +241,7 @@ class IPFS { await initAssets({ addAll: ipfs.addAll, print }) log('initializing IPNS keyspace') - await ipfs.ipns.initializeKeyspace(storage.peerId.privKey, cid.toString()) + await ipfs.ipns.initializeKeyspace(storage.peerId.privKey, uint8ArrayFromString(`/ipfs/${cid}`)) } if (options.start !== false) { @@ -235,24 +251,18 @@ class IPFS { return ipfs } } -module.exports = IPFS -/** - * @param {Options} options - * @returns {InitOptions} - */ -const initOptions = ({ init }) => - typeof init === 'object' ? init : {} +module.exports = IPFS /** * @param {IPFS} ipfs */ const addEmptyDir = async (ipfs) => { - const node = new DAGNode(new UnixFs('directory').marshal()) + const node = new DAGNode(new UnixFS({ type: 'directory' }).marshal()) const cid = await ipfs.dag.put(node, { version: 0, - format: multicodec.DAG_PB, - hashAlg: multicodec.SHA2_256, + format: 'dag-pb', + hashAlg: 'sha2-256', preload: false }) @@ -277,112 +287,3 @@ const getDefaultOptions = () => ({ ] } }) - -/** - * @typedef {StorageOptions & IPFSOptions} Options - * - * @typedef {Object} IPFSOptions - * Options argument can be used to specify advanced configuration. - * @property {InitOptions} [init] - Initialization options - * the IPFS node. - * Note that *initializing* a repo is different from creating an instance of - * [`ipfs.Repo`](https://github.com/ipfs/js-ipfs-repo). The IPFS constructor - * sets many special properties when initializing a repo, so you should usually - * not try and call `repoInstance.init()` yourself. - * @property {boolean} [start=true] - If `false`, do not automatically - * start the IPFS node. Instead, you’ll need to manually call - * [`node.start()`](https://github.com/ipfs/js-ipfs/blob/master/packages/ipfs/docs/MODULE.md#nodestart) - * yourself. - * @property {string} [pass=null] - A passphrase to encrypt/decrypt your keys. - * @property {boolean} [silent=false] - Prevents all logging output from the - * IPFS node. (Default: `false`) - * @property {RelayOptions} [relay={ enabled: true, hop: { enabled: false, active: false } }] - * - Configure circuit relay (see the [circuit relay tutorial] - * (https://github.com/ipfs/js-ipfs/tree/master/examples/circuit-relaying) - * to learn more). - * @property {boolean} [offline=false] - Run ipfs node offline. The node does - * not connect to the rest of the network but provides a local API. - * @property {PreloadOptions} [preload] - Configure remote preload nodes. - * The remote will preload content added on this node, and also attempt to - * preload objects requested by this node. - * @property {ExperimentalOptions} [EXPERIMENTAL] - Enable and configure - * experimental features. - * @property {IPFSConfig} [config] - Modify the default IPFS node config. This - * object will be *merged* with the default config; it will not replace it. - * (Default: [`config-nodejs.js`](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/config-nodejs.js) - * in Node.js, [`config-browser.js`](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/config-browser.js) - * in browsers) - * @property {IPLDOptions} [ipld] - Modify the default IPLD config. This object - * will be *merged* with the default config; it will not replace it. Check IPLD - * [docs](https://github.com/ipld/js-ipld#ipld-constructor) for more information - * on the available options. (Default: [`ipld.js`] - * (https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/ipld-nodejs.js) in Node.js, [`ipld-browser.js`](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/ipld-browser.js) - * (https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/ipld.js) - * in browsers) - * @property {LibP2POptions|Function} [libp2p] - The libp2p option allows you to build - * your libp2p node by configuration, or via a bundle function. If you are - * looking to just modify the below options, using the object format is the - * quickest way to get the default features of libp2p. If you need to create a - * more customized libp2p node, such as with custom transports or peer/content - * routers that need some of the ipfs data on startup, a custom bundle is a - * great way to achieve this. - * - You can see the bundle in action in the [custom libp2p example](https://github.com/ipfs/js-ipfs/tree/master/examples/custom-libp2p). - * - Please see [libp2p/docs/CONFIGURATION.md](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md) - * for the list of options libp2p supports. - * - Default: [`libp2p-nodejs.js`](../src/core/runtime/libp2p-nodejs.js) - * in Node.js, [`libp2p-browser.js`](../src/core/runtime/libp2p-browser.js) in - * browsers. - * @property {boolean} [repoOwner] - * - * @typedef {object} ExperimentalOptions - * @property {boolean} [ipnsPubsub] - Enable pub-sub on IPNS. (Default: `false`) - * @property {boolean} [sharding] - Enable directory sharding. Directories that have many child objects will be represented by multiple DAG nodes instead of just one. It can improve lookup performance when a directory has several thousand files or more. (Default: `false`) - * - * - * @typedef {import('./storage').StorageOptions} StorageOptions - * @typedef {import('../preload').Options} PreloadOptions - * @typedef {import('./ipld').Options} IPLDOptions - * @typedef {import('./libp2p').Options} LibP2POptions - * - * @typedef {object} RelayOptions - * @property {boolean} [enabled] - Enable circuit relay dialer and listener. (Default: `true`) - * @property {object} [hop] - * @property {boolean} [hop.enabled] - Make this node a relay (other nodes can connect *through* it). (Default: `false`) - * @property {boolean} [hop.active] - Make this an *active* relay node. Active relay nodes will attempt to dial a destin - * - * @typedef {import('./storage').InitOptions} InitOptions - * - * @typedef {import('./storage')} StorageAPI - * - * @typedef {import('./network').Options} NetworkOptions - * @typedef {Service} NetworkService - * @typedef {import('./storage').Repo} Repo - * @typedef {(...args:any[]) => void} Print - * @typedef {import('./storage').Keychain} Keychain - * @typedef {import('./config').IPFSConfig} IPFSConfig - * - * @typedef {import('peer-id')} PeerId - * @typedef {import('./libp2p').LibP2P} LibP2P - * @typedef {import('./pin/pin-manager')} PinManager - * @typedef {import('ipfs-core-types/src/block-service').BlockService} BlockService - * @typedef {import('ipfs-core-types/src/bitswap').Bitswap} BitSwap - * @typedef {import('./ipld').IPLD} IPLD - * @typedef {import('./gc-lock').GCLock} GCLock - * @typedef {import('../preload').Preload} Preload - * @typedef {import('../mfs-preload').MFSPreload} MFSPreload - * @typedef {import('./ipns')} IPNS - * @typedef {import('./pin')} Pin - * @typedef {import('./block')} Block - * @typedef {import('./dag').DagReader} DagReader - * @typedef {import('./dag')} Dag - * @typedef {ReturnType} Files - * @typedef {ReturnType} IsOnline - * @typedef {ReturnType} Resolve - * @typedef {ReturnType} Refs - * @typedef {ReturnType} DNS - * @typedef {import('./name')} Name - * @typedef {import('../utils').AbortOptions} AbortOptions - * @typedef {import('cids')} CID - * @typedef {import('multiaddr')} Multiaddr - * @typedef {import('./ipld').Block} IPLDBlock - */ diff --git a/packages/ipfs-core/src/components/ipld.js b/packages/ipfs-core/src/components/ipld.js index a4505424d5..998166a50d 100644 --- a/packages/ipfs-core/src/components/ipld.js +++ b/packages/ipfs-core/src/components/ipld.js @@ -5,19 +5,11 @@ const Ipld = require('ipld') /** * @param {Object} config - * @param {BlockService} config.blockService - * @param {Print} config.print - * @param {Options} [config.options] - * @returns {IPLD} + * @param {import('ipfs-block-service')} config.blockService + * @param {import('ipld').Options} [config.options] */ -const createIPLD = ({ blockService, print, options }) => - new Ipld(getDefaultIpldOptions(blockService, options, print)) -module.exports = createIPLD +const createIPLD = ({ blockService, options }) => { + return new Ipld(getDefaultIpldOptions(blockService, options)) +} -/** - * @typedef {import('ipfs-core-types/src/ipld').IPLD} IPLD - * @typedef {import('ipfs-core-types/src/ipld').Options} Options - * @typedef {import('ipfs-core-types/src/block-service').BlockService} BlockService - * @typedef {import('ipfs-core-types/src/block-service').Block} Block - * @typedef {import('.').Print} Print - */ +module.exports = createIPLD diff --git a/packages/ipfs-core/src/components/ipns.js b/packages/ipfs-core/src/components/ipns.js index 4c732f6df4..2f85ed61f8 100644 --- a/packages/ipfs-core/src/components/ipns.js +++ b/packages/ipfs-core/src/components/ipns.js @@ -6,17 +6,34 @@ const OfflineDatastore = require('../ipns/routing/offline-datastore') const { NotInitializedError, AlreadyInitializedError } = require('../errors') const log = require('debug')('ipfs:components:ipns') +/** + * @typedef {import('libp2p-crypto').PrivateKey} PrivateKey + * + * @typedef {Object} ExperimentalOptions + * @property {boolean} [ipnsPubsub] + * + * @typedef {Object} LibP2POptions + * @property {DHTConfig} [config] + * + * @typedef {Object} DHTConfig + * @property {boolean} [enabled] + */ + class IPNSAPI { /** * @param {Object} options - * @param {string} [options.pass] + * @param {string} options.pass * @param {boolean} [options.offline] * @param {LibP2POptions} [options.libp2p] * @param {ExperimentalOptions} [options.EXPERIMENTAL] */ - constructor (options = {}) { + constructor (options = { pass: '' }) { this.options = options + + /** @type {IPNS | null} */ this.offline = null + + /** @type {IPNS | null} */ this.online = null } @@ -41,9 +58,9 @@ class IPNSAPI { * initializeKeyspace feature. * * @param {Object} config - * @param {import('.').Repo} config.repo - * @param {import('.').PeerId} config.peerId - * @param {import('.').Keychain} config.keychain + * @param {import('ipfs-repo')} config.repo + * @param {import('peer-id')} config.peerId + * @param {import('libp2p/src/keychain')} config.keychain */ startOffline ({ repo, peerId, keychain }) { if (this.offline != null) { @@ -60,10 +77,10 @@ class IPNSAPI { /** * @param {Object} config - * @param {import('.').LibP2P} config.libp2p - * @param {import('.').Repo} config.repo - * @param {import('.').PeerId} config.peerId - * @param {import('.').Keychain} config.keychain + * @param {import('libp2p')} config.libp2p + * @param {import('ipfs-repo')} config.repo + * @param {import('peer-id')} config.peerId + * @param {import('libp2p/src/keychain')} config.keychain */ async startOnline ({ libp2p, repo, peerId, keychain }) { if (this.online != null) { @@ -71,6 +88,7 @@ class IPNSAPI { } const routing = routingConfig({ libp2p, repo, peerId, options: this.options }) + // @ts-ignore routing is a TieredDatastore which wants keys to be Keys, IPNS needs keys to be Uint8Arrays const ipns = new IPNS(routing, repo.datastore, peerId, keychain, this.options) await ipns.republisher.start() this.online = ipns @@ -84,27 +102,30 @@ class IPNSAPI { } } + /** + * @param {PrivateKey} privKey + * @param {Uint8Array} value + * @param {number} lifetime + */ publish (privKey, value, lifetime) { return this.getIPNS().publish(privKey, value, lifetime) } + /** + * + * @param {string} name + * @param {*} [options] + */ resolve (name, options) { return this.getIPNS().resolve(name, options) } + /** + * @param {PrivateKey} privKey + * @param {Uint8Array} value + */ initializeKeyspace (privKey, value) { return this.getIPNS().initializeKeyspace(privKey, value) } } module.exports = IPNSAPI - -/** - * @typedef {Object} ExperimentalOptions - * @property {boolean} [ipnsPubsub] - * - * @typedef {Object} LibP2POptions - * @property {DHTConfig} [config] - * - * @typedef {Object} DHTConfig - * @property {boolean} [enabled] - */ diff --git a/packages/ipfs-core/src/components/is-online.js b/packages/ipfs-core/src/components/is-online.js index 9bb6467ef1..54a3defefd 100644 --- a/packages/ipfs-core/src/components/is-online.js +++ b/packages/ipfs-core/src/components/is-online.js @@ -2,7 +2,7 @@ /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../types').NetworkService} config.network */ module.exports = ({ network }) => /** diff --git a/packages/ipfs-core/src/components/key/export.js b/packages/ipfs-core/src/components/key/export.js index b4ccc2f661..85a387f59b 100644 --- a/packages/ipfs-core/src/components/key/export.js +++ b/packages/ipfs-core/src/components/key/export.js @@ -4,26 +4,11 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Keychain} config.keychain + * @param {import('libp2p/src/keychain')} config.keychain */ module.exports = ({ keychain }) => { /** - * Remove a key - * - * @example - * ```js - * const pem = await ipfs.key.export('self', 'password') - * - * console.log(pem) - * // -----BEGIN ENCRYPTED PRIVATE KEY----- - * // MIIFDTA/BgkqhkiG9w0BBQ0wMjAaBgkqhkiG9w0BBQwwDQQIpdO40RVyBwACAWQw - * // ... - * // YA== - * // -----END ENCRYPTED PRIVATE KEY----- - * ``` - * @param {string} name - The name of the key to export - * @param {string} password - Password to set on the PEM output - * @returns {Promise} - The string representation of the key + * @type {import('ipfs-core-types/src/key').API["export"]} */ const exportKey = (name, password) => keychain.exportKey(name, password) diff --git a/packages/ipfs-core/src/components/key/gen.js b/packages/ipfs-core/src/components/key/gen.js index 491a938657..f1ec77ee17 100644 --- a/packages/ipfs-core/src/components/key/gen.js +++ b/packages/ipfs-core/src/components/key/gen.js @@ -2,42 +2,20 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +const DEFAULT_KEY_TYPE = 'rsa' +const DEFAULT_KEY_SIZE = 2048 + /** * @param {Object} config - * @param {import('.').Keychain} config.keychain + * @param {import('libp2p/src/keychain')} config.keychain */ module.exports = ({ keychain }) => { /** - * Generate a new key - * - * @example - * ```js - * const key = await ipfs.key.gen('my-key', { - * type: 'rsa', - * size: 2048 - * }) - * - * console.log(key) - * // { id: 'QmYWqAFvLWb2G5A69JGXui2JJXzaHXiUEmQkQgor6kNNcJ', - * // name: 'my-key' } - * ``` - * - * @param {string} name - The name to give the key - * @param {GenOptions & AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/key').API["gen"]} */ - const gen = (name, options = {}) => { - return keychain.createKey(name, options.type || 'rsa', options.size || 2048) + const gen = (name, options = { type: DEFAULT_KEY_TYPE, size: DEFAULT_KEY_SIZE }) => { + return keychain.createKey(name, options.type || DEFAULT_KEY_TYPE, options.size || DEFAULT_KEY_SIZE) } return withTimeoutOption(gen) } - -/** - * @typedef {Object} GenOptions - * @property {import('libp2p-crypto').KeyType} [type='RSA'] - The key type - * @property {number} [size=2048] - The key size in bits - * - * @typedef {import('.').Key} Key - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/key/import.js b/packages/ipfs-core/src/components/key/import.js index 35eebe224d..14b4c966f6 100644 --- a/packages/ipfs-core/src/components/key/import.js +++ b/packages/ipfs-core/src/components/key/import.js @@ -4,24 +4,11 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Keychain} config.keychain + * @param {import('libp2p/src/keychain')} config.keychain */ module.exports = ({ keychain }) => { /** - * Remove a key - * - * @example - * ```js - * const key = await ipfs.key.import('clone', pem, 'password') - * - * console.log(key) - * // { id: 'QmQRiays958UM7norGRQUG3tmrLq8pJdmJarwYSk2eLthQ', - * // name: 'clone' } - * ``` - * @param {string} name - The name of the key to import - * @param {string} pem - The PEM encoded key - * @param {string} password - The password that protects the PEM key - * @returns {Promise} - An object that describes the new key + * @type {import('ipfs-core-types/src/key').API["import"]} */ const importKey = (name, pem, password) => { return keychain.importKey(name, pem, password) diff --git a/packages/ipfs-core/src/components/key/index.js b/packages/ipfs-core/src/components/key/index.js index 4869addc74..aa176cf776 100644 --- a/packages/ipfs-core/src/components/key/index.js +++ b/packages/ipfs-core/src/components/key/index.js @@ -8,6 +8,10 @@ const createList = require('./list') const createRename = require('./rename') const createRm = require('./rm') +/** + * @typedef {import('libp2p/src/keychain')} Keychain + */ + class KeyAPI { /** * @param {Object} config @@ -24,12 +28,3 @@ class KeyAPI { } } module.exports = KeyAPI - -/** - * @typedef {import('..').Keychain} Keychain - * @typedef {import('..').AbortOptions} AbortOptions - * - * @typedef {Object} Key - * @property {string} name - * @property {string} id - */ diff --git a/packages/ipfs-core/src/components/key/info.js b/packages/ipfs-core/src/components/key/info.js index d585027a8c..7a2456e3d2 100644 --- a/packages/ipfs-core/src/components/key/info.js +++ b/packages/ipfs-core/src/components/key/info.js @@ -4,19 +4,13 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Keychain} config.keychain + * @param {import('libp2p/src/keychain')} config.keychain */ module.exports = ({ keychain }) => { /** - * @param {string} name - * @returns {Promise} + * @type {import('ipfs-core-types/src/key').API["info"]} */ const info = (name) => keychain.findKeyByName(name) return withTimeoutOption(info) } - -/** - * @typedef {import('.').Key} Key - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/key/list.js b/packages/ipfs-core/src/components/key/list.js index 66e05baca5..0f5c83fda1 100644 --- a/packages/ipfs-core/src/components/key/list.js +++ b/packages/ipfs-core/src/components/key/list.js @@ -4,26 +4,11 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Keychain} config.keychain + * @param {import('libp2p/src/keychain')} config.keychain */ module.exports = ({ keychain }) => { /** - * List all the keys - * - * @example - * ```js - * const keys = await ipfs.key.list() - * - * console.log(keys) - * // [ - * // { id: 'QmTe4tuceM2sAmuZiFsJ9tmAopA8au71NabBDdpPYDjxAb', - * // name: 'self' }, - * // { id: 'QmWETF5QvzGnP7jKq5sPDiRjSM2fzwzNsna4wSBEzRzK6W', - * // name: 'my-key' } - * // ] - * ``` - * - * @returns {Promise} + * @type {import('ipfs-core-types/src/key').API["list"]} */ const list = () => keychain.listKeys() diff --git a/packages/ipfs-core/src/components/key/rename.js b/packages/ipfs-core/src/components/key/rename.js index 2012a81f87..a02ed0d13c 100644 --- a/packages/ipfs-core/src/components/key/rename.js +++ b/packages/ipfs-core/src/components/key/rename.js @@ -4,25 +4,11 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Keychain} config.keychain + * @param {import('libp2p/src/keychain')} config.keychain */ module.exports = ({ keychain }) => { /** - * Rename a key - * - * @example - * ```js - * const key = await ipfs.key.rename('my-key', 'my-new-key') - * - * console.log(key) - * // { id: 'Qmd4xC46Um6s24MradViGLFtMitvrR4SVexKUgPgFjMNzg', - * // was: 'my-key', - * // now: 'my-new-key', - * // overwrite: false } - * ``` - * @param {string} oldName - The current key name - * @param {string} newName - The desired key name - * @returns {Promise} + * @type {import('ipfs-core-types/src/key').API["rename"]} */ const rename = async (oldName, newName) => { const key = await keychain.renameKey(oldName, newName) @@ -37,13 +23,3 @@ module.exports = ({ keychain }) => { return withTimeoutOption(rename) } - -/** - * @typedef {Object} RenamedKey - * @property {string} was - The name of the key - * @property {string} now - The hash of the key - * @property {string} id - * @property {boolean} overwrite - * - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/key/rm.js b/packages/ipfs-core/src/components/key/rm.js index a27dd8e091..134354b9c0 100644 --- a/packages/ipfs-core/src/components/key/rm.js +++ b/packages/ipfs-core/src/components/key/rm.js @@ -4,31 +4,13 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Keychain} config.keychain + * @param {import('libp2p/src/keychain')} config.keychain */ module.exports = ({ keychain }) => { /** - * Remove a key - * - * @example - * ```js - * const key = await ipfs.key.rm('my-key') - * - * console.log(key) - * // { id: 'QmWETF5QvzGnP7jKq5sPDiRjSM2fzwzNsna4wSBEzRzK6W', - * // name: 'my-key' } - * ``` - * - * @param {string} name - The name of the key to remove - * @returns {Promise} - An object that describes the removed key + * @type {import('ipfs-core-types/src/key').API["rm"]} */ const rm = (name) => keychain.removeKey(name) return withTimeoutOption(rm) } - -/** - * @typedef {Object} RemovedKey - * @property {string} name - The name of the key - * @property {string} id - The hash of the key - */ diff --git a/packages/ipfs-core/src/components/libp2p.js b/packages/ipfs-core/src/components/libp2p.js index 5073f8e649..236ddaa726 100644 --- a/packages/ipfs-core/src/components/libp2p.js +++ b/packages/ipfs-core/src/components/libp2p.js @@ -5,6 +5,19 @@ const mergeOptions = require('merge-options') const errCode = require('err-code') const PubsubRouters = require('../runtime/libp2p-pubsub-routers-nodejs') +/** + * @typedef {Object} KeychainConfig + * @property {string} [pass] + * + * @typedef {import('ipfs-repo')} Repo + * @typedef {import('multiaddr')} Multiaddr + * @typedef {import('peer-id')} PeerId + * @typedef {import('../types').Options} IPFSOptions + * @typedef {import('libp2p')} LibP2P + * @typedef {import('libp2p').Libp2pOptions & import('libp2p').constructorOptions} Options + * @typedef {import('ipfs-core-types/src/config').Config} IPFSConfig + */ + /** * @param {Object} config * @param {Repo} config.repo @@ -13,7 +26,6 @@ const PubsubRouters = require('../runtime/libp2p-pubsub-routers-nodejs') * @param {Multiaddr[]|undefined} config.multiaddrs * @param {KeychainConfig|undefined} config.keychainConfig * @param {Partial|undefined} config.config - * @returns {LibP2P} */ module.exports = ({ options = {}, @@ -59,10 +71,12 @@ function getLibp2pOptions ({ options, config, datastore, keys, keychainConfig, p const getPubsubRouter = () => { const router = get(config, 'Pubsub.Router') || 'gossipsub' + // @ts-ignore - `router` value is not constrained if (!PubsubRouters[router]) { throw errCode(new Error(`Router unavailable. Configure libp2p.modules.pubsub to use the ${router} router.`), 'ERR_NOT_SUPPORTED') } + // @ts-ignore - `router` value is not constrained return PubsubRouters[router] } @@ -163,16 +177,3 @@ function getLibp2pOptions ({ options, config, datastore, keys, keychainConfig, p return libp2pConfig } - -/** - * @typedef {Object} KeychainConfig - * @property {string} [pass] - * - * @typedef {import('.').Repo} Repo - * @typedef {import('.').Multiaddr} Multiaddr - * @typedef {import('.').PeerId} PeerId - * @typedef {import('.').Options} IPFSOptions - * @typedef {import('libp2p')} LibP2P - * @typedef {import('libp2p').Libp2pOptions & import('libp2p').constructorOptions} Options - * @typedef {import('.').IPFSConfig} IPFSConfig - */ diff --git a/packages/ipfs-core/src/components/ls.js b/packages/ipfs-core/src/components/ls.js index c97985d9e0..d19bb5ee21 100644 --- a/packages/ipfs-core/src/components/ls.js +++ b/packages/ipfs-core/src/components/ls.js @@ -1,28 +1,23 @@ 'use strict' -const exporter = require('ipfs-unixfs-exporter') +const { exporter, recursive } = require('ipfs-unixfs-exporter') const errCode = require('err-code') const { normalizeCidPath, mapFile } = require('../utils') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @typedef {Object} Context - * @property {import('.').IPLD} ipld - * @property {import('.').Preload} preload + * @property {import('ipld')} ipld + * @property {import('../types').Preload} preload * * @param {Context} context */ module.exports = function ({ ipld, preload }) { /** - * Lists a directory from IPFS that is addressed by a valid IPFS Path. - * - * @param {import('ipfs-core-types/src/root').IPFSPath} ipfsPath - * @param {import('ipfs-core-types/src/root').ListOptions} [options] - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/root').API["ls"]} */ async function * ls (ipfsPath, options = {}) { const path = normalizeCidPath(ipfsPath) - const recursive = options.recursive const pathComponents = path.split('/') if (options.preload !== false) { @@ -31,18 +26,14 @@ module.exports = function ({ ipld, preload }) { const file = await exporter(ipfsPath, ipld, options) - if (!file.unixfs) { - throw errCode(new Error('dag node was not a UnixFS node'), 'ERR_NOT_UNIXFS') - } - - if (file.unixfs.type === 'file') { + if (file.type === 'file') { yield mapFile(file, options) return } - if (file.unixfs.type.includes('dir')) { - if (recursive) { - for await (const child of exporter.recursive(file.cid, ipld, options)) { + if (file.type === 'directory') { + if (options.recursive) { + for await (const child of recursive(file.cid, ipld, options)) { if (file.cid.toBaseEncodedString() === child.cid.toBaseEncodedString()) { continue } @@ -53,17 +44,17 @@ module.exports = function ({ ipld, preload }) { return } - for await (let child of file.content()) { - child = mapFile(child, options) - child.depth-- + for await (const child of file.content()) { + const entry = mapFile(child, options) + entry.depth-- - yield child + yield entry } return } - throw errCode(new Error(`Unknown UnixFS type ${file.unixfs.type}`), 'ERR_UNKNOWN_UNIXFS_TYPE') + throw errCode(new Error(`Unknown UnixFS type ${file.type}`), 'ERR_UNKNOWN_UNIXFS_TYPE') } return withTimeoutOption(ls) diff --git a/packages/ipfs-core/src/components/name/index.js b/packages/ipfs-core/src/components/name/index.js index a8bb3b7faf..58fa79e72f 100644 --- a/packages/ipfs-core/src/components/name/index.js +++ b/packages/ipfs-core/src/components/name/index.js @@ -3,39 +3,23 @@ const createPublishAPI = require('./publish') const createResolveAPI = require('./resolve') const PubSubAPI = require('./pubsub') + class NameAPI { /** * @param {Object} config - * @param {IPNS} config.ipns - * @param {PeerId} config.peerId - * @param {Options} config.options - * @param {DagReader} config.dagReader - * @param {IsOnline} config.isOnline - * @param {Keychain} config.keychain - * @param {DNS} config.dns + * @param {import('../ipns')} config.ipns + * @param {import('peer-id')} config.peerId + * @param {import('../../types').Options} config.options + * @param {import('ipld')} config.ipld + * @param {import('ipfs-core-types/src/root').API["isOnline"]} config.isOnline + * @param {import('libp2p/src/keychain')} config.keychain + * @param {import('ipfs-core-types/src/root').API["dns"]} config.dns */ - constructor ({ dns, ipns, dagReader, peerId, isOnline, keychain, options }) { - this.publish = createPublishAPI({ ipns, dagReader, peerId, isOnline, keychain }) + constructor ({ dns, ipns, ipld, peerId, isOnline, keychain, options }) { + this.publish = createPublishAPI({ ipns, ipld, peerId, isOnline, keychain }) this.resolve = createResolveAPI({ dns, ipns, peerId, isOnline, options }) - this.pubsub = new PubSubAPI({ ipns, options: options.EXPERIMENTAL }) + this.pubsub = new PubSubAPI({ ipns, options }) } } -module.exports = NameAPI -/** - * @typedef {ResolveOptions & ExperimentalOptions} Options - * - * @typedef {Object} ExperimentalOptions - * @property {PubSubOptions} [EXPERIMENTAL] - * - * @typedef {import('./pubsub').Options} PubSubOptions - * @typedef {import('./resolve').ResolveOptions} ResolveOptions - * - * @typedef {import('..').IPNS} IPNS - * @typedef {import('..').PeerId} PeerId - * @typedef {import('..').DagReader} DagReader - * @typedef {import('..').Keychain} Keychain - * @typedef {import('..').IsOnline} IsOnline - * @typedef {import('..').DNS} DNS - * @typedef {import('..').AbortOptions} AbortOptions - */ +module.exports = NameAPI diff --git a/packages/ipfs-core/src/components/name/publish.js b/packages/ipfs-core/src/components/name/publish.js index 9328debdea..3f19d3798c 100644 --- a/packages/ipfs-core/src/components/name/publish.js +++ b/packages/ipfs-core/src/components/name/publish.js @@ -4,6 +4,8 @@ const debug = require('debug') const { default: parseDuration } = require('parse-duration') const crypto = require('libp2p-crypto') const errcode = require('err-code') +const uint8ArrayFromString = require('uint8arrays/from-string') +const uint8ArrayToString = require('uint8arrays/to-string') const log = Object.assign(debug('ipfs:name:publish'), { error: debug('ipfs:name:publish:error') @@ -17,13 +19,16 @@ const { resolvePath } = require('./utils') * IPNS - Inter-Planetary Naming System * * @param {Object} config - * @param {import('.').IPNS} config.ipns - * @param {import('.').DagReader} config.dagReader - * @param {import('.').PeerId} config.peerId - * @param {import('.').IsOnline} config.isOnline - * @param {import('.').Keychain} config.keychain + * @param {import('../ipns')} config.ipns + * @param {import('ipld')} config.ipld + * @param {import('peer-id')} config.peerId + * @param {import('ipfs-core-types/src/root').API["isOnline"]} config.isOnline + * @param {import('libp2p/src/keychain')} config.keychain */ -module.exports = ({ ipns, dagReader, peerId, isOnline, keychain }) => { +module.exports = ({ ipns, ipld, peerId, isOnline, keychain }) => { + /** + * @param {string} keyName + */ const lookupKey = async keyName => { if (keyName === 'self') { return peerId.privKey @@ -41,24 +46,7 @@ module.exports = ({ ipns, dagReader, peerId, isOnline, keychain }) => { } /** - * IPNS is a PKI namespace, where names are the hashes of public keys, and - * the private key enables publishing new (signed) values. In both publish - * and resolve, the default name used is the node's own PeerID, - * which is the hash of its public key. - * - * @param {string} value - ipfs path of the object to be published. - * @param {PublishOptions} [options] - * @returns {Promise} - * @example - * ```js - * // The address of your files. - * const addr = '/ipfs/QmbezGequPwcsWo8UL4wDF6a8hYwM1hmbzYv2mnKkEWaUp' - * const res = await ipfs.name.publish(addr) - * // You now have a res which contains two fields: - * // - name: the name under which the content was published. - * // - value: the "real" address to which Name points. - * console.log(`https://gateway.ipfs.io/ipns/${res.name}`) - * ``` + * @type {import('ipfs-core-types/src/name').API["publish"]} */ async function publish (value, options = {}) { const resolve = !(options.resolve === false) @@ -70,7 +58,6 @@ module.exports = ({ ipns, dagReader, peerId, isOnline, keychain }) => { } // TODO: params related logic should be in the core implementation - // Normalize path value try { value = normalizePath(value) @@ -94,35 +81,20 @@ module.exports = ({ ipns, dagReader, peerId, isOnline, keychain }) => { const results = await Promise.all([ // verify if the path exists, if not, an error will stop the execution lookupKey(key), - resolve ? resolvePath({ ipns, dagReader }, value) : Promise.resolve() + // if resolving, do a get so we make sure we have the blocks + resolve ? resolvePath({ ipns, ipld }, value) : Promise.resolve() ]) + const bytes = uint8ArrayFromString(value) + // Start publishing process - return ipns.publish(results[0], value, pubLifetime) + const result = await ipns.publish(results[0], bytes, pubLifetime) + + return { + name: result.name, + value: uint8ArrayToString(result.value) + } } return withTimeoutOption(publish) } - -/** - * @typedef {PublishSettings & AbortOptions} PublishOptions - * ipfs publish options. - * - * @typedef {Object} PublishSettings - * @property {boolean} [resolve=true] - Resolve given path before publishing. - * @property {string} [lifetime='24h'] - Time duration of the record. - * @property {string} [ttl] - Time duration this record should be cached. - * @property {string} [key=self] - Name of the key to be used. - * @property {boolean} [allowOffline=true] - When offline, save the IPNS record - * to the the local datastore without broadcasting to the network instead of - * simply failing. - * - * This option is not yet implemented in js-ipfs. See tracking issue [ipfs/js-ipfs#1997] - * (https://github.com/ipfs/js-ipfs/issues/1997). - * - * @typedef {Object} PublishResult - * @property {string} name - * @property {string} value - * - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/name/pubsub/cancel.js b/packages/ipfs-core/src/components/name/pubsub/cancel.js index 5d9508c52d..78934a5128 100644 --- a/packages/ipfs-core/src/components/name/pubsub/cancel.js +++ b/packages/ipfs-core/src/components/name/pubsub/cancel.js @@ -5,26 +5,17 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPNS} config.ipns - * @param {import('.').Options} [config.options] + * @param {import('../../ipns')} config.ipns + * @param {import('../../../types').Options} config.options */ -module.exports = ({ ipns, options: routingOptions }) => { +module.exports = ({ ipns, options }) => { + const experimental = options.EXPERIMENTAL + /** - * Cancel a name subscription. - * - * @param {string} name - The name of the subscription to cancel. - * @param {import('.').AbortOptions} [options] - * @returns {Promise<{ canceled: boolean }>} - * @example - * ```js - * const name = 'QmQrX8hka2BtNHa8N8arAq16TCVx5qHcb46c5yPewRycLm' - * const result = await ipfs.name.pubsub.cancel(name) - * console.log(result.canceled) - * // Logs: true - * ``` + * @type {import('ipfs-core-types/src/name/pubsub').API["cancel"]} */ - async function cancel (name, options) { // eslint-disable-line require-await - const pubsub = getPubsubRouting(ipns, routingOptions) + async function cancel (name, options = {}) { // eslint-disable-line require-await + const pubsub = getPubsubRouting(ipns, experimental) return pubsub.cancel(name, options) } diff --git a/packages/ipfs-core/src/components/name/pubsub/index.js b/packages/ipfs-core/src/components/name/pubsub/index.js index 1ea174e082..417ea94d30 100644 --- a/packages/ipfs-core/src/components/name/pubsub/index.js +++ b/packages/ipfs-core/src/components/name/pubsub/index.js @@ -7,8 +7,8 @@ const createSubsAPI = require('./subs') class PubSubAPI { /** * @param {Object} config - * @param {IPNS} config.ipns - * @param {Options} [config.options] + * @param {import('../../ipns')} config.ipns + * @param {import('../../../types').Options} config.options */ constructor ({ ipns, options }) { this.cancel = createCancelAPI({ ipns, options }) @@ -17,9 +17,3 @@ class PubSubAPI { } } module.exports = PubSubAPI - -/** - * @typedef {import('..').IPNS} IPNS - * @typedef {import('./utils').PubSubRoutingOptions} Options - * @typedef {import('..').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/name/pubsub/state.js b/packages/ipfs-core/src/components/name/pubsub/state.js index 4794d4abc4..747b5b8199 100644 --- a/packages/ipfs-core/src/components/name/pubsub/state.js +++ b/packages/ipfs-core/src/components/name/pubsub/state.js @@ -5,24 +5,18 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPNS} config.ipns - * @param {import('.').Options} [config.options] + * @param {import('../../ipns')} config.ipns + * @param {import('../../../types').Options} config.options */ -module.exports = ({ ipns, options: routingOptions }) => { +module.exports = ({ ipns, options }) => { + const experimental = options.EXPERIMENTAL + /** - * Query the state of IPNS pubsub. - * - * @param {import('.').AbortOptions} [_options] - * @returns {Promise<{ enabled: boolean }>} - * ```js - * const result = await ipfs.name.pubsub.state() - * console.log(result.enabled) - * // Logs: true - * ``` + * @type {import('ipfs-core-types/src/name/pubsub').API["state"]} */ - async function state (_options) { // eslint-disable-line require-await + async function state (_options = {}) { // eslint-disable-line require-await try { - return { enabled: Boolean(getPubsubRouting(ipns, routingOptions)) } + return { enabled: Boolean(getPubsubRouting(ipns, experimental)) } } catch (err) { return { enabled: false } } diff --git a/packages/ipfs-core/src/components/name/pubsub/subs.js b/packages/ipfs-core/src/components/name/pubsub/subs.js index 3c16d72c2e..41158a9fc0 100644 --- a/packages/ipfs-core/src/components/name/pubsub/subs.js +++ b/packages/ipfs-core/src/components/name/pubsub/subs.js @@ -5,24 +5,17 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPNS} config.ipns - * @param {import('.').Options} [config.options] + * @param {import('../../ipns')} config.ipns + * @param {import('../../../types').Options} config.options */ -module.exports = ({ ipns, options: routingOptions }) => { +module.exports = ({ ipns, options }) => { + const experimental = options.EXPERIMENTAL + /** - * Show current name subscriptions. - * - * @param {import('.').AbortOptions} [options] - * @returns {Promise} - * @example - * ```js - * const result = await ipfs.name.pubsub.subs() - * console.log(result) - * // Logs: ['/ipns/QmQrX8hka2BtNHa8N8arAq16TCVx5qHcb46c5yPewRycLm'] - * ``` + * @type {import('ipfs-core-types/src/name/pubsub').API["subs"]} */ - async function subs (options) { // eslint-disable-line require-await - const pubsub = getPubsubRouting(ipns, routingOptions) + async function subs (options = {}) { // eslint-disable-line require-await + const pubsub = getPubsubRouting(ipns, experimental) return pubsub.getSubscriptions(options) } diff --git a/packages/ipfs-core/src/components/name/pubsub/utils.js b/packages/ipfs-core/src/components/name/pubsub/utils.js index 43e7e69ae9..e9daacbf52 100644 --- a/packages/ipfs-core/src/components/name/pubsub/utils.js +++ b/packages/ipfs-core/src/components/name/pubsub/utils.js @@ -3,11 +3,16 @@ const IpnsPubsubDatastore = require('../../../ipns/routing/pubsub-datastore') const errcode = require('err-code') +/** + * @typedef {import('../../../types').ExperimentalOptions} ExperimentalOptions + * @property {boolean} [ipnsPubsub] - Enable pub-sub on IPNS. (Default: `false`) + */ + /** * Get pubsub from IPNS routing * - * @param {import('.').IPNS} ipns - * @param {PubSubRoutingOptions} [options] + * @param {import('../../ipns')} ipns + * @param {ExperimentalOptions} [options] */ exports.getPubsubRouting = (ipns, options) => { if (!ipns || !(options && options.ipnsPubsub)) { @@ -15,12 +20,12 @@ exports.getPubsubRouting = (ipns, options) => { } // Only one store and it is pubsub - if (IpnsPubsubDatastore.isIpnsPubsubDatastore(ipns.routing)) { + if (ipns.routing instanceof IpnsPubsubDatastore) { return ipns.routing } // Find in tiered - const pubsub = (ipns.routing.stores || []).find(s => IpnsPubsubDatastore.isIpnsPubsubDatastore(s)) + const pubsub = (ipns.routing.stores || []).find(s => s instanceof IpnsPubsubDatastore) if (!pubsub) { throw errcode(new Error('IPNS pubsub datastore not found'), 'ERR_PUBSUB_DATASTORE_NOT_FOUND') @@ -28,8 +33,3 @@ exports.getPubsubRouting = (ipns, options) => { return pubsub } - -/** - * @typedef {Object} PubSubRoutingOptions - * @property {boolean} [ipnsPubsub] - Enable pub-sub on IPNS. (Default: `false`) - */ diff --git a/packages/ipfs-core/src/components/name/resolve.js b/packages/ipfs-core/src/components/name/resolve.js index 0f747a4a7c..a6e7a81f43 100644 --- a/packages/ipfs-core/src/components/name/resolve.js +++ b/packages/ipfs-core/src/components/name/resolve.js @@ -4,7 +4,9 @@ const debug = require('debug') const errcode = require('err-code') const { mergeOptions } = require('../../utils') const CID = require('cids') +// @ts-ignore no types const isDomain = require('is-domain-name') +const uint8ArrayToString = require('uint8arrays/to-string') const log = Object.assign(debug('ipfs:name:resolve'), { error: debug('ipfs:name:resolve:error') @@ -28,29 +30,15 @@ const appendRemainder = (result, remainder) => * IPNS - Inter-Planetary Naming System * * @param {Object} config - * @param {import('.').DNS} config.dns - * @param {import('.').IPNS} config.ipns - * @param {import('.').PeerId} config.peerId - * @param {import('.').IsOnline} config.isOnline - * @param {ResolveOptions} config.options + * @param {import('ipfs-core-types/src/root').API["dns"]} config.dns + * @param {import('../ipns')} config.ipns + * @param {import('peer-id')} config.peerId + * @param {import('ipfs-core-types/src/root').API["isOnline"]} config.isOnline + * @param {import('../../types').Options} config.options */ module.exports = ({ dns, ipns, peerId, isOnline, options: { offline } }) => { /** - * Given a key, query the DHT for its best value. - * - * @param {string} name - ipns name to resolve. Defaults to your node's peerID. - * @param {Options & AbortOptions} [options] - * @returns {AsyncIterable} - * @example - * ```js - * // The IPNS address you want to resolve. - * const addr = '/ipns/ipfs.io' - * - * for await (const name of ipfs.name.resolve(addr)) { - * console.log(name) - * } - * // Logs: /ipfs/QmQrX8hka2BtNHa8N8arAq16TCVx5qHcb46c5yPewRycLm - * ``` + * @type {import('ipfs-core-types/src/name').API["resolve"]} */ async function * resolve (name, options = {}) { // eslint-disable-line require-await options = mergeOptions({ @@ -93,21 +81,9 @@ module.exports = ({ dns, ipns, peerId, isOnline, options: { offline } }) => { } // TODO: convert ipns.resolve to return an iterator - yield appendRemainder(await ipns.resolve(`/${namespace}/${hash}`, options), remainder) + const value = await ipns.resolve(`/${namespace}/${hash}`, options) + yield appendRemainder(value instanceof Uint8Array ? uint8ArrayToString(value) : value, remainder) } return withTimeoutOption(resolve) } - -/** - * IPFS resolve options. - * - * @typedef {Object} Options - * @property {boolean} [options.nocache=false] - do not use cached entries. - * @property {boolean} [options.recursive=true] - resolve until the result is not an IPNS name. - * - * @typedef {Object} ResolveOptions - * @property {boolean} [offline] - * - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/name/utils.js b/packages/ipfs-core/src/components/name/utils.js index b2b5970f78..18f8b48910 100644 --- a/packages/ipfs-core/src/components/name/utils.js +++ b/packages/ipfs-core/src/components/name/utils.js @@ -1,27 +1,29 @@ 'use strict' const isIPFS = require('is-ipfs') +const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') +const drain = require('it-drain') /** * resolves the given path by parsing out protocol-specific entries * (e.g. /ipns/) and then going through the /ipfs/ entries and returning the final node * * @param {Object} context - * @param {IPNS} context.ipns - * @param {DagReader} context.dagReader + * @param {import('../ipns')} context.ipns + * @param {import('ipld')} context.ipld * @param {string} name */ -exports.resolvePath = ({ ipns, dagReader }, name) => { +exports.resolvePath = async ({ ipns, ipld }, name) => { // ipns path if (isIPFS.ipnsPath(name)) { return ipns.resolve(name) } + const { + cid, + path + } = toCidAndPath(name) + // ipfs path - return dagReader.get(name.substring('/ipfs/'.length)) + await drain(ipld.resolve(cid, path || '')) } - -/** - * @typedef {import('.').DagReader} DagReader - * @typedef {import('.').IPNS} IPNS - */ diff --git a/packages/ipfs-core/src/components/network.js b/packages/ipfs-core/src/components/network.js index be8111af99..a1a940bf70 100644 --- a/packages/ipfs-core/src/components/network.js +++ b/packages/ipfs-core/src/components/network.js @@ -5,11 +5,32 @@ const createLibP2P = require('./libp2p') const Multiaddr = require('multiaddr') const errCode = require('err-code') +/** + * @typedef {Object} Online + * @property {libp2p} libp2p + * @property {Bitswap} bitswap + * + * @typedef {Object} Options + * @property {PeerId} options.peerId + * @property {Repo} options.repo + * @property {Print} options.print + * @property {IPFSOptions} options.options + * + * @typedef {import('ipfs-core-types/src/config').Config} IPFSConfig + * @typedef {import('../types').Options} IPFSOptions + * @typedef {import('ipfs-repo')} Repo + * @typedef {import('../types').Print} Print + * @typedef {import('libp2p')} libp2p + * @typedef {import('ipfs-bitswap')} Bitswap + * @typedef {import('peer-id')} PeerId + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ + class Network { /** * @param {PeerId} peerId - * @param {LibP2P} libp2p - * @param {BitSwap} bitswap + * @param {libp2p} libp2p + * @param {Bitswap} bitswap */ constructor (peerId, libp2p, bitswap) { this.peerId = peerId @@ -33,7 +54,9 @@ class Network { options, repo, peerId, + // @ts-ignore - TODO move config types into ipfs-repo multiaddrs: readAddrs(peerId, config), + // @ts-ignore - TODO move config types into ipfs-repo config, keychainConfig: undefined }) @@ -101,23 +124,3 @@ const readAddrs = (peerId, config) => { } const WEBSOCKET_STAR_PROTO_CODE = 479 -/** - * @typedef {Object} Online - * @property {LibP2P} libp2p - * @property {BitSwap} bitswap - * - * @typedef {Object} Options - * @property {PeerId} options.peerId - * @property {Repo} options.repo - * @property {Print} options.print - * @property {IPFSOptions} options.options - * - * @typedef {import('.').IPFSConfig} IPFSConfig - * @typedef {import('.').Options} IPFSOptions - * @typedef {import('.').Repo} Repo - * @typedef {import('.').Print} Print - * @typedef {import('.').LibP2P} LibP2P - * @typedef {import('ipfs-core-types/src/bitswap').Bitswap} BitSwap - * @typedef {import('.').PeerId} PeerId - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/object/data.js b/packages/ipfs-core/src/components/object/data.js index 3245cc6f14..4894a99ee4 100644 --- a/packages/ipfs-core/src/components/object/data.js +++ b/packages/ipfs-core/src/components/object/data.js @@ -4,27 +4,19 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../types').Preload} config.preload */ module.exports = ({ ipld, preload }) => { const get = require('./get')({ ipld, preload }) /** - * @param {import('.').CID} multihash - * @param {GetOptions & AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/object').API["data"]} */ - async function data (multihash, options) { + async function data (multihash, options = {}) { const node = await get(multihash, options) return node.Data } return withTimeoutOption(data) } - -/** - * @typedef {import('cids')} CID - * @typedef {import('./get').GetOptions} GetOptions - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/object/get.js b/packages/ipfs-core/src/components/object/get.js index b294b3cec9..7633b71b60 100644 --- a/packages/ipfs-core/src/components/object/get.js +++ b/packages/ipfs-core/src/components/object/get.js @@ -3,61 +3,29 @@ const CID = require('cids') const errCode = require('err-code') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') -const uint8ArrayFromString = require('uint8arrays/from-string') /** - * @typedef {import('multibase/src/types').BaseName} BaseName + * @typedef {import('multibase').BaseName} BaseName */ -/** - * @param {string|Uint8Array|CID} multihash - * @param {BaseName | 'utf8' | 'utf-8' | 'ascii' | 'base58'} [enc] - * @returns {string|Uint8Array} - */ -function normalizeMultihash (multihash, enc) { - if (typeof multihash === 'string') { - if (enc === 'base58' || !enc) { - return multihash - } - return uint8ArrayFromString(multihash, enc) - } else if (multihash instanceof Uint8Array) { - return multihash - } else if (CID.isCID(multihash)) { - return multihash.bytes - } - throw new Error('unsupported multihash') -} - /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../types').Preload} config.preload */ module.exports = ({ ipld, preload }) => { /** - * - * @param {CID} multihash - * @param {GetOptions & AbortOptions} [options] + * @type {import('ipfs-core-types/src/object').API["get"]} */ async function get (multihash, options = {}) { // eslint-disable-line require-await - let mh, cid + let cid try { - mh = normalizeMultihash(multihash, options.enc) - } catch (err) { - throw errCode(err, 'ERR_INVALID_MULTIHASH') - } - - try { - cid = new CID(mh) + cid = new CID(multihash) } catch (err) { throw errCode(err, 'ERR_INVALID_CID') } - if (options.cidVersion === 1) { - cid = cid.toV1() - } - if (options.preload !== false) { preload(cid) } @@ -67,12 +35,3 @@ module.exports = ({ ipld, preload }) => { return withTimeoutOption(get) } - -/** - * @typedef {Object} GetOptions - * @property {boolean} [preload] - * @property {number} [cidVersion] - * @property {BaseName | 'utf8' | 'utf-8' | 'ascii' | 'base58'} [enc] - * - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/object/index.js b/packages/ipfs-core/src/components/object/index.js index 210ab36f3d..7587da1b82 100644 --- a/packages/ipfs-core/src/components/object/index.js +++ b/packages/ipfs-core/src/components/object/index.js @@ -8,18 +8,25 @@ const createPut = require('./put') const createStat = require('./stat') const ObjectPatchAPI = require('./patch') +/** + * @typedef {import('ipld')} IPLD + * @typedef {import('../../types').Preload} Preload + * @typedef {import('../gc-lock').GCLock} GCLock + * @typedef {import('cids')} CID + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ + class ObjectAPI { /** * @param {Object} config * @param {IPLD} config.ipld * @param {Preload} config.preload * @param {GCLock} config.gcLock - * @param {Dag} config.dag */ - constructor ({ ipld, preload, dag, gcLock }) { + constructor ({ ipld, preload, gcLock }) { this.data = createData({ ipld, preload }) this.get = createGet({ ipld, preload }) - this.links = createLinks({ dag }) + this.links = createLinks({ ipld }) this.new = createNew({ ipld, preload }) this.put = createPut({ ipld, preload, gcLock }) this.stat = createStat({ ipld, preload }) @@ -28,12 +35,3 @@ class ObjectAPI { } module.exports = ObjectAPI - -/** - * @typedef {import('..').IPLD} IPLD - * @typedef {import('..').Preload} Preload - * @typedef {import('..').GCLock} GCLock - * @typedef {import('..').Dag} Dag - * @typedef {import('..').CID} CID - * @typedef {import('..').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/object/links.js b/packages/ipfs-core/src/components/object/links.js index d0b3739945..7713cb7243 100644 --- a/packages/ipfs-core/src/components/object/links.js +++ b/packages/ipfs-core/src/components/object/links.js @@ -1,7 +1,8 @@ 'use strict' -const dagPB = require('ipld-dag-pb') -const DAGLink = dagPB.DAGLink +const { + DAGLink +} = require('ipld-dag-pb') const CID = require('cids') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') @@ -42,24 +43,22 @@ function findLinks (node, links = []) { /** * @param {Object} config - * @param {import('.').Dag} config.dag + * @param {import('ipld')} config.ipld */ -module.exports = ({ dag }) => { +module.exports = ({ ipld }) => { /** - * @param {CID} multihash - * @param {import('.').AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/object').API["links"]} */ async function links (multihash, options = {}) { const cid = new CID(multihash) - const result = await dag.get(cid, options) + const result = await ipld.get(cid, options) if (cid.codec === 'raw') { return [] } if (cid.codec === 'dag-pb') { - return result.value.Links + return result.Links } if (cid.codec === 'dag-cbor') { diff --git a/packages/ipfs-core/src/components/object/new.js b/packages/ipfs-core/src/components/object/new.js index 00d9199278..2289c100c8 100644 --- a/packages/ipfs-core/src/components/object/new.js +++ b/packages/ipfs-core/src/components/object/new.js @@ -1,28 +1,28 @@ 'use strict' -const dagPB = require('ipld-dag-pb') -const DAGNode = dagPB.DAGNode +const { + DAGNode +} = require('ipld-dag-pb') const multicodec = require('multicodec') -const Unixfs = require('ipfs-unixfs') +const mh = require('multihashing-async').multihash +const { UnixFS } = require('ipfs-unixfs') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../types').Preload} config.preload */ module.exports = ({ ipld, preload }) => { /** - * - * @param {NewOptions & AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/object').API["new"]} */ async function _new (options = {}) { let data if (options.template) { if (options.template === 'unixfs-dir') { - data = (new Unixfs('directory')).marshal() + data = (new UnixFS({ type: 'directory' })).marshal() } else { throw new Error('unknown template') } @@ -34,7 +34,7 @@ module.exports = ({ ipld, preload }) => { const cid = await ipld.put(node, multicodec.DAG_PB, { cidVersion: 0, - hashAlg: multicodec.SHA2_256, + hashAlg: mh.names['sha2-256'], signal: options.signal }) @@ -47,15 +47,3 @@ module.exports = ({ ipld, preload }) => { return withTimeoutOption(_new) } - -/** - * @typedef {Object} NewOptions - * @property {string} [template] - * @property {boolean} [recursive] - * @property {boolean} [nocache] - * @property {boolean} [preload] - * @property {string} [enc] - * - * @typedef {import('.').CID} CID - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/object/patch/add-link.js b/packages/ipfs-core/src/components/object/patch/add-link.js index f46b5e53f4..ec9aca29a0 100644 --- a/packages/ipfs-core/src/components/object/patch/add-link.js +++ b/packages/ipfs-core/src/components/object/patch/add-link.js @@ -4,15 +4,18 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../../types').Preload} config.preload * @param {import('.').GCLock} config.gcLock */ module.exports = ({ ipld, gcLock, preload }) => { const get = require('../get')({ ipld, preload }) const put = require('../put')({ ipld, gcLock, preload }) - async function addLink (multihash, link, options) { + /** + * @type {import('ipfs-core-types/src/object/patch').API["addLink"]} + */ + async function addLink (multihash, link, options = {}) { const node = await get(multihash, options) node.addLink(link) return put(node, options) diff --git a/packages/ipfs-core/src/components/object/patch/append-data.js b/packages/ipfs-core/src/components/object/patch/append-data.js index b2d6b07c0d..7f7286c851 100644 --- a/packages/ipfs-core/src/components/object/patch/append-data.js +++ b/packages/ipfs-core/src/components/object/patch/append-data.js @@ -6,14 +6,18 @@ const uint8ArrayConcat = require('uint8arrays/concat') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../../types').Preload} config.preload * @param {import('.').GCLock} config.gcLock */ module.exports = ({ ipld, gcLock, preload }) => { const get = require('../get')({ ipld, preload }) const put = require('../put')({ ipld, gcLock, preload }) - async function appendData (multihash, data, options) { + + /** + * @type {import('ipfs-core-types/src/object/patch').API["appendData"]} + */ + async function appendData (multihash, data, options = {}) { const node = await get(multihash, options) const newData = uint8ArrayConcat([node.Data, data]) return put(new DAGNode(newData, node.Links), options) diff --git a/packages/ipfs-core/src/components/object/patch/index.js b/packages/ipfs-core/src/components/object/patch/index.js index 5166c6b33e..b8d4929459 100644 --- a/packages/ipfs-core/src/components/object/patch/index.js +++ b/packages/ipfs-core/src/components/object/patch/index.js @@ -5,6 +5,14 @@ const createAppendData = require('./append-data') const createRmLink = require('./rm-link') const createSetData = require('./set-data') +/** + * @typedef {import('ipld')} IPLD + * @typedef {import('../../../types').Preload} Preload + * @typedef {import('..').GCLock} GCLock + * @typedef {import('cids')} CID + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ + class ObjectPatchAPI { /** * @param {Object} config @@ -20,11 +28,3 @@ class ObjectPatchAPI { } } module.exports = ObjectPatchAPI - -/** - * @typedef {import('..').IPLD} IPLD - * @typedef {import('..').Preload} Preload - * @typedef {import('..').GCLock} GCLock - * @typedef {import('..').CID} CID - * @typedef {import('..').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/object/patch/rm-link.js b/packages/ipfs-core/src/components/object/patch/rm-link.js index 3edf78ac4b..28a2e1e79b 100644 --- a/packages/ipfs-core/src/components/object/patch/rm-link.js +++ b/packages/ipfs-core/src/components/object/patch/rm-link.js @@ -4,17 +4,21 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../../types').Preload} config.preload * @param {import('.').GCLock} config.gcLock */ module.exports = ({ ipld, gcLock, preload }) => { const get = require('../get')({ ipld, preload }) const put = require('../put')({ ipld, gcLock, preload }) - async function rmLink (multihash, linkRef, options) { + /** + * @type {import('ipfs-core-types/src/object/patch').API["rmLink"]} + */ + async function rmLink (multihash, linkRef, options = {}) { const node = await get(multihash, options) - node.rmLink(linkRef.Name || linkRef.name) + // @ts-ignore - loose input types + node.rmLink(linkRef.Name || linkRef.name || linkRef) return put(node, options) } diff --git a/packages/ipfs-core/src/components/object/patch/set-data.js b/packages/ipfs-core/src/components/object/patch/set-data.js index 1777ed2a59..56ac8eb984 100644 --- a/packages/ipfs-core/src/components/object/patch/set-data.js +++ b/packages/ipfs-core/src/components/object/patch/set-data.js @@ -5,15 +5,18 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../../types').Preload} config.preload * @param {import('.').GCLock} config.gcLock */ module.exports = ({ ipld, gcLock, preload }) => { const get = require('../get')({ ipld, preload }) const put = require('../put')({ ipld, gcLock, preload }) - async function setData (multihash, data, options) { + /** + * @type {import('ipfs-core-types/src/object/patch').API["setData"]} + */ + async function setData (multihash, data, options = {}) { const node = await get(multihash, options) return put(new DAGNode(data, node.Links), options) } diff --git a/packages/ipfs-core/src/components/object/put.js b/packages/ipfs-core/src/components/object/put.js index 6afbfbde2c..9d92baf8b9 100644 --- a/packages/ipfs-core/src/components/object/put.js +++ b/packages/ipfs-core/src/components/object/put.js @@ -1,14 +1,20 @@ 'use strict' -const dagPB = require('ipld-dag-pb') -const DAGNode = dagPB.DAGNode -const DAGLink = dagPB.DAGLink +const { + DAGNode, + DAGLink, + util: DAGLinkUtil +} = require('ipld-dag-pb') const mh = require('multihashing-async').multihash const multicodec = require('multicodec') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayFromString = require('uint8arrays/from-string') +/** + * @param {Uint8Array} buf + * @param {import('ipfs-core-types/src/object').PutEncoding} encoding + */ function parseBuffer (buf, encoding) { switch (encoding) { case 'json': @@ -16,10 +22,13 @@ function parseBuffer (buf, encoding) { case 'protobuf': return parseProtoBuffer(buf) default: - throw new Error(`unkown encoding: ${encoding}`) + throw new Error(`unknown encoding: ${encoding}`) } } +/** + * @param {Uint8Array} buf + */ function parseJSONBuffer (buf) { let data let links @@ -27,13 +36,19 @@ function parseJSONBuffer (buf) { try { const parsed = JSON.parse(uint8ArrayToString(buf)) + // @ts-ignore - loose input types links = (parsed.Links || []).map((link) => { return new DAGLink( + // @ts-ignore - loose input types link.Name || link.name, + // @ts-ignore - loose input types link.Size || link.size, + // @ts-ignore - loose input types mh.fromB58String(link.Hash || link.hash || link.multihash) ) }) + + // @ts-ignore - loose input types data = uint8ArrayFromString(parsed.Data) } catch (err) { throw new Error('failed to parse JSON: ' + err) @@ -42,22 +57,22 @@ function parseJSONBuffer (buf) { return new DAGNode(data, links) } +/** + * @param {Uint8Array} buf + */ function parseProtoBuffer (buf) { - return dagPB.util.deserialize(buf) + return DAGLinkUtil.deserialize(buf) } /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../types').Preload} config.preload * @param {import('.').GCLock} config.gcLock */ module.exports = ({ ipld, gcLock, preload }) => { /** - * - * @param {Uint8Array|DAGNode|{ Data: any, links: DAGLink[]}} obj - * @param {PutOptions & AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/object').API["put"]} */ async function put (obj, options = {}) { const encoding = options.enc @@ -69,7 +84,7 @@ module.exports = ({ ipld, gcLock, preload }) => { } else { node = new DAGNode(obj) } - } else if (DAGNode.isDAGNode(obj)) { + } else if (obj instanceof DAGNode) { // already a dag node node = obj } else if (typeof obj === 'object') { @@ -83,7 +98,7 @@ module.exports = ({ ipld, gcLock, preload }) => { try { const cid = await ipld.put(node, multicodec.DAG_PB, { cidVersion: 0, - hashAlg: multicodec.SHA2_256 + hashAlg: mh.names['sha2-256'] }) if (options.preload !== false) { @@ -98,12 +113,3 @@ module.exports = ({ ipld, gcLock, preload }) => { return withTimeoutOption(put) } - -/** - * @typedef {Object} PutOptions - * @property {boolean} [preload] - * @property {string} [enc] - * - * @typedef {import('.').CID} CID - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/object/stat.js b/packages/ipfs-core/src/components/object/stat.js index 666967c0be..43c8170e41 100644 --- a/packages/ipfs-core/src/components/object/stat.js +++ b/packages/ipfs-core/src/components/object/stat.js @@ -5,18 +5,14 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('../../types').Preload} config.preload */ module.exports = ({ ipld, preload }) => { const get = require('./get')({ ipld, preload }) /** - * Returns stats about an Object - * - * @param {CID} multihash - * @param {StatOptions & AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/object').API["stat"]} */ async function stat (multihash, options = {}) { const node = await get(multihash, options) @@ -40,16 +36,3 @@ module.exports = ({ ipld, preload }) => { return withTimeoutOption(stat) } -/** - * @typedef {Object} Stat - * @property {string} Hash - * @property {number} NumLinks - * @property {number} BlockSize - * @property {number} LinksSize - * @property {number} DataSize - * @property {number} CumulativeSize - * - * @typedef {import('./get').GetOptions} StatOptions - * @typedef {import('.').CID} CID - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/pin/add-all.js b/packages/ipfs-core/src/components/pin/add-all.js index cf6bdf6e69..6b5aa0ac58 100644 --- a/packages/ipfs-core/src/components/pin/add-all.js +++ b/packages/ipfs-core/src/components/pin/add-all.js @@ -5,33 +5,29 @@ const { resolvePath } = require('../../utils') const PinManager = require('./pin-manager') const { PinTypes } = PinManager const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') - -/** @type {(source:Source) => AsyncIterable} */ const normaliseInput = require('ipfs-core-utils/src/pins/normalise-input') +/** + * @typedef {import('ipfs-core-utils/src/pins/normalise-input').Source} Source + * @typedef {import('ipfs-core-utils/src/pins/normalise-input').Pin} PinTarget + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + * @typedef {import('cids')} CID + */ + +/** + * @template T + * @typedef {Iterable|AsyncIterable} AwaitIterable + */ + /** * @param {Object} config - * @param {import('.').GCLock} config.gcLock - * @param {import('.').DagReader} config.dagReader - * @param {import('.').PinManager} config.pinManager + * @param {import('../gc-lock').GCLock} config.gcLock + * @param {import('ipld')} config.ipld + * @param {import('./pin-manager')} config.pinManager */ -module.exports = ({ pinManager, gcLock, dagReader }) => { +module.exports = ({ pinManager, gcLock, ipld }) => { /** - * Adds multiple IPFS objects to the pinset and also stores it to the IPFS - * repo. pinset is the set of hashes currently pinned (not gc'able) - * - * @param {Source} source - One or more CIDs or IPFS Paths to pin in your repo - * @param {AddOptions} [options] - * @returns {AsyncIterable} - CIDs that were pinned. - * @example - * ```js - * const cid = CID.from('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') - * for await (const cid of ipfs.pin.addAll([cid])) { - * console.log(cid) - * } - * // Logs: - * // CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') - * ``` + * @type {import('ipfs-core-types/src/pin').API["addAll"]} */ async function * addAll (source, options = {}) { /** @@ -39,7 +35,7 @@ module.exports = ({ pinManager, gcLock, dagReader }) => { */ const pinAdd = async function * () { for await (const { path, recursive, metadata } of normaliseInput(source)) { - const cid = await resolvePath(dagReader, path) + const cid = await resolvePath(ipld, path) // verify that each hash can be pinned const { reason } = await pinManager.isPinnedWithType(cid, [PinTypes.recursive, PinTypes.direct]) @@ -79,22 +75,3 @@ module.exports = ({ pinManager, gcLock, dagReader }) => { return withTimeoutOption(addAll) } - -/** - * @typedef {import('ipfs-core-utils/src/pins/normalise-input').Source} Source - * @typedef {import('ipfs-core-utils/src/pins/normalise-input').Pin} PinTarget - * - * @typedef {AddSettings & AbortOptions} AddOptions - * - * @typedef {Object} AddSettings - * @property {boolean} [lock] - * - * @typedef {import('.').AbortOptions} AbortOptions - * - * @typedef {import('.').CID} CID - */ - -/** - * @template T - * @typedef {Iterable|AsyncIterable} AwaitIterable - */ diff --git a/packages/ipfs-core/src/components/pin/add.js b/packages/ipfs-core/src/components/pin/add.js index 8d10ea31f4..842d34d166 100644 --- a/packages/ipfs-core/src/components/pin/add.js +++ b/packages/ipfs-core/src/components/pin/add.js @@ -1,6 +1,7 @@ 'use strict' const last = require('it-last') +const CID = require('cids') /** * @param {Object} config @@ -8,19 +9,23 @@ const last = require('it-last') */ module.exports = ({ addAll }) => /** - * @param {CID|string} path - * @param {AddOptions & AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/pin').API["add"]} */ - async (path, options = {}) => - /** @type {CID} - Need to loosen check here because it could be void */ - (await last(addAll({ path, ...options }, options))) + (path, options = {}) => { + let iter -/** - * @typedef {Object} AddOptions - * @property {boolean} [lock] - * @property {boolean} [recursive] - Recursively pin all links contained by the object - * - * @typedef {import('../../utils').AbortOptions} AbortOptions - * @typedef {import('..').CID} CID - */ + if (CID.isCID(path)) { + iter = addAll([{ + cid: path, + ...options + }], options) + } else { + iter = addAll([{ + path: path.toString(), + ...options + }], options) + } + + // @ts-ignore return value of last can be undefined + return last(iter) + } diff --git a/packages/ipfs-core/src/components/pin/index.js b/packages/ipfs-core/src/components/pin/index.js index 2e3ee7c66b..468cab5d48 100644 --- a/packages/ipfs-core/src/components/pin/index.js +++ b/packages/ipfs-core/src/components/pin/index.js @@ -6,30 +6,41 @@ const createLs = require('./ls') const createRm = require('./rm') const createRmAll = require('./rm-all') +/** + * @typedef {import('../gc-lock').GCLock} GCLock + * @typedef {import('./pin-manager')} PinManager + */ + class PinAPI { /** * @param {Object} config * @param {GCLock} config.gcLock - * @param {DagReader} config.dagReader + * @param {import('ipld')} config.ipld * @param {PinManager} config.pinManager */ - constructor ({ gcLock, dagReader, pinManager }) { - const addAll = createAddAll({ gcLock, dagReader, pinManager }) + constructor ({ gcLock, ipld, pinManager }) { + const addAll = createAddAll({ gcLock, ipld, pinManager }) this.addAll = addAll this.add = createAdd({ addAll }) - const rmAll = createRmAll({ gcLock, dagReader, pinManager }) + const rmAll = createRmAll({ gcLock, ipld, pinManager }) this.rmAll = rmAll this.rm = createRm({ rmAll }) - this.ls = createLs({ dagReader, pinManager }) + this.ls = createLs({ ipld, pinManager }) + + const notImplemented = () => Promise.reject(new Error('Not implemented')) + + this.remote = { + add: notImplemented, + ls: notImplemented, + rm: notImplemented, + rmAll: notImplemented, + service: { + add: notImplemented, + rm: notImplemented, + ls: notImplemented + } + } } } -module.exports = PinAPI -/** - * @typedef {import('..').Repo} Repo - * @typedef {import('..').GCLock} GCLock - * @typedef {import('..').DagReader} DagReader - * @typedef {import('..').PinManager} PinManager - * @typedef {import('..').AbortOptions} AbortOptions - * @typedef {import('..').CID} CID - */ +module.exports = PinAPI diff --git a/packages/ipfs-core/src/components/pin/ls.js b/packages/ipfs-core/src/components/pin/ls.js index 3fb486288a..b06b255fcc 100644 --- a/packages/ipfs-core/src/components/pin/ls.js +++ b/packages/ipfs-core/src/components/pin/ls.js @@ -7,7 +7,17 @@ const normaliseInput = require('ipfs-core-utils/src/pins/normalise-input') const { resolvePath } = require('../../utils') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @typedef {import('cids')} CID + */ + +/** + * @param {string} type + * @param {CID} cid + * @param {Record} [metadata] + */ function toPin (type, cid, metadata) { + /** @type {import('ipfs-core-types/src/pin').LsResult} */ const output = { type, cid @@ -22,51 +32,21 @@ function toPin (type, cid, metadata) { /** * @param {Object} config - * @param {import('.').PinManager} config.pinManager - * @param {import('.').DagReader} config.dagReader + * @param {import('./pin-manager')} config.pinManager + * @param {import('ipld')} config.ipld */ -module.exports = ({ pinManager, dagReader }) => { +module.exports = ({ pinManager, ipld }) => { /** - * List all the objects pinned to local storage - * - * @param {LsOptions} [options] - * @returns {AsyncIterable} - * @example - * ```js - * for await (const { cid, type } of ipfs.pin.ls()) { - * console.log({ cid, type }) - * } - * // { cid: CID(Qmc5XkteJdb337s7VwFBAGtiaoj2QCEzyxtNRy3iMudc3E), type: 'recursive' } - * // { cid: CID(QmZbj5ruYneZb8FuR9wnLqJCpCXMQudhSdWhdhp5U1oPWJ), type: 'indirect' } - * // { cid: CID(QmSo73bmN47gBxMNqbdV6rZ4KJiqaArqJ1nu5TvFhqqj1R), type: 'indirect' } - * - * const paths = [ - * CID.from('Qmc5..'), - * CID.from('QmZb..'), - * CID.from('QmSo..') - * ] - * for await (const { cid, type } of ipfs.pin.ls({ paths })) { - * console.log({ cid, type }) - * } - * // { cid: CID(Qmc5XkteJdb337s7VwFBAGtiaoj2QCEzyxtNRy3iMudc3E), type: 'recursive' } - * // { cid: CID(QmZbj5ruYneZb8FuR9wnLqJCpCXMQudhSdWhdhp5U1oPWJ), type: 'indirect' } - * // { cid: CID(QmSo73bmN47gBxMNqbdV6rZ4KJiqaArqJ1nu5TvFhqqj1R), type: 'indirect' } - * ``` + * @type {import('ipfs-core-types/src/pin').API["ls"]} */ async function * ls (options = {}) { - /** @type {PinQueryType} */ + /** @type {import('ipfs-core-types/src/pin').PinQueryType} */ let type = PinTypes.all if (options.type) { type = options.type - if (typeof options.type === 'string') { - // @ts-ignore - Can't infer that string returned by toLowerCase() is PinQueryType - type = options.type.toLowerCase() - } PinManager.checkPinType(type) - } else { - options.type = PinTypes.all } if (options.paths) { @@ -74,7 +54,7 @@ module.exports = ({ pinManager, dagReader }) => { let matched = false for await (const { path } of normaliseInput(options.paths)) { - const cid = await resolvePath(dagReader, path) + const cid = await resolvePath(ipld, path) const { reason, pinned, parent, metadata } = await pinManager.isPinnedWithType(cid, type) if (!pinned) { @@ -123,21 +103,3 @@ module.exports = ({ pinManager, dagReader }) => { return withTimeoutOption(ls) } - -/** - * @typedef {LsSettings & AbortOptions} LsOptions - * - * @typedef {Object} LsSettings - * @property {string[]|CID[]} [paths] - CIDs or IPFS paths to search for in the pinset. - * @property {PinQueryType} [type] - Filter by this type of pin ("recursive", "direct" or "indirect") - * - * @typedef {Object} LsEntry - * @property {CID} cid - CID of the pinned node - * @property {PinType} type - Pin type ("recursive", "direct" or "indirect") - * - * @typedef {import('./pin-manager').PinType} PinType - * @typedef {import('./pin-manager').PinQueryType} PinQueryType - * - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('.').CID} CID - */ diff --git a/packages/ipfs-core/src/components/pin/pin-manager.js b/packages/ipfs-core/src/components/pin/pin-manager.js index e284831ec2..0378cd8795 100644 --- a/packages/ipfs-core/src/components/pin/pin-manager.js +++ b/packages/ipfs-core/src/components/pin/pin-manager.js @@ -3,20 +3,44 @@ const CID = require('cids') const errCode = require('err-code') +// @ts-ignore - no types const dagCborLinks = require('dag-cbor-links') const debug = require('debug') -// const parallelBatch = require('it-parallel-batch') const first = require('it-first') const all = require('it-all') -const cbor = require('cbor') +const cborg = require('cborg') const multibase = require('multibase') const multicodec = require('multicodec') +const { Key } = require('interface-datastore') + +/** + * @typedef {object} Pin + * @property {number} depth + * @property {CID.CIDVersion} [version] + * @property {multicodec.CodecCode} [codec] + * @property {Record} [metadata] + */ + +/** + * @typedef {import('ipfs-core-types/src/pin').PinType} PinType + * @typedef {import('ipfs-core-types/src/pin').PinQueryType} PinQueryType + */ + +/** + * @typedef {Object} PinOptions + * @property {any} [metadata] + * + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ // arbitrary limit to the number of concurrent dag operations // const WALK_DAG_CONCURRENCY_LIMIT = 300 // const IS_PINNED_WITH_TYPE_CONCURRENCY_LIMIT = 300 // const PIN_DS_KEY = new Key('/local/pins') +/** + * @param {string} type + */ function invalidPinTypeErr (type) { const errMsg = `Invalid type '${type}', must be one of {direct, indirect, recursive, all}` return errCode(new Error(errMsg), 'ERR_INVALID_PIN_TYPE') @@ -24,19 +48,20 @@ function invalidPinTypeErr (type) { const encoder = multibase.encoding('base32upper') +/** + * @param {CID} cid + */ function cidToKey (cid) { - return `/${encoder.encode(cid.multihash)}` + return new Key(`/${encoder.encode(cid.multihash)}`) } +/** + * @param {Key | string} key + */ function keyToMultihash (key) { return encoder.decode(key.toString().slice(1)) } -/** - * @typedef {'direct'|'recursive'|'indirect'} PinType - * @typedef {PinType|'all'} PinQueryType - */ - const PinTypes = { /** @type {'direct'} */ direct: ('direct'), @@ -51,12 +76,12 @@ const PinTypes = { class PinManager { /** * @param {Object} config - * @param {import('.').Repo} config.repo - * @param {import('.').DagReader} config.dagReader + * @param {import('ipfs-repo')} config.repo + * @param {import('ipld')} config.ipld */ - constructor ({ repo, dagReader }) { + constructor ({ repo, ipld }) { this.repo = repo - this.dag = dagReader + this.ipld = ipld this.log = debug('ipfs:pin') this.directPins = new Set() this.recursivePins = new Set() @@ -65,21 +90,21 @@ class PinManager { /** * @private * @param {CID} cid - * @param {Object} options - * @param {boolean} [options.preload] + * @param {AbortOptions} [options] + * @returns {AsyncGenerator} */ - async * _walkDag (cid, { preload = false }) { - const { value: node } = await this.dag.get(cid, { preload }) + async * _walkDag (cid, options) { + const node = await this.ipld.get(cid, options) if (cid.codec === 'dag-pb') { for (const link of node.Links) { yield link.Hash - yield * this._walkDag(link.Hash, { preload }) + yield * this._walkDag(link.Hash, options) } } else if (cid.codec === 'dag-cbor') { for (const [, childCid] of dagCborLinks(node)) { yield childCid - yield * this._walkDag(childCid, { preload }) + yield * this._walkDag(childCid, options) } } } @@ -90,8 +115,9 @@ class PinManager { * @returns {Promise} */ async pinDirectly (cid, options = {}) { - await this.dag.get(cid, options) + await this.ipld.get(cid, options) + /** @type {Pin} */ const pin = { depth: 0 } @@ -108,7 +134,7 @@ class PinManager { pin.metadata = options.metadata } - return this.repo.pins.put(cidToKey(cid), cbor.encode(pin)) + return this.repo.pins.put(cidToKey(cid), cborg.encode(pin)) } /** @@ -123,12 +149,13 @@ class PinManager { /** * @param {CID} cid - * @param {PreloadOptions & PinOptions & AbortOptions} [options] + * @param {PinOptions & AbortOptions} [options] * @returns {Promise} */ async pinRecursively (cid, options = {}) { await this.fetchCompleteDag(cid, options) + /** @type {Pin} */ const pin = { depth: Infinity } @@ -145,22 +172,21 @@ class PinManager { pin.metadata = options.metadata } - await this.repo.pins.put(cidToKey(cid), cbor.encode(pin)) + await this.repo.pins.put(cidToKey(cid), cborg.encode(pin)) } /** * @param {AbortOptions} [options] - * @returns {AsyncIterable<{ cid: CID, metadata: any }>} */ async * directKeys (options) { for await (const entry of this.repo.pins.query({ filters: [(entry) => { - const pin = cbor.decode(entry.value) + const pin = cborg.decode(entry.value) return pin.depth === 0 }] })) { - const pin = cbor.decode(entry.value) + const pin = cborg.decode(entry.value) const version = pin.version || 0 const codec = pin.codec ? multicodec.getName(pin.codec) : 'dag-pb' const multihash = keyToMultihash(entry.key) @@ -174,17 +200,16 @@ class PinManager { /** * @param {AbortOptions} [options] - * @returns {AsyncIterable<{ cid: CID, metadata: any }>} */ async * recursiveKeys (options) { for await (const entry of this.repo.pins.query({ filters: [(entry) => { - const pin = cbor.decode(entry.value) + const pin = cborg.decode(entry.value) return pin.depth === Infinity }] })) { - const pin = cbor.decode(entry.value) + const pin = cborg.decode(entry.value) const version = pin.version || 0 const codec = pin.codec ? multicodec.getName(pin.codec) : 'dag-pb' const multihash = keyToMultihash(entry.key) @@ -197,12 +222,11 @@ class PinManager { } /** - * @param {Object} options - * @param {boolean} [options.preload] + * @param {AbortOptions} [options] */ - async * indirectKeys ({ preload }) { + async * indirectKeys (options) { for await (const { cid } of this.recursiveKeys()) { - for await (const childCid of this._walkDag(cid, { preload })) { + for await (const childCid of this._walkDag(cid, options)) { // recursive pins override indirect pins const types = [ PinTypes.recursive @@ -236,13 +260,13 @@ class PinManager { if (recursive || direct || all) { const result = await first(this.repo.pins.query({ - prefix: cidToKey(cid), + prefix: cidToKey(cid).toString(), filters: [entry => { if (all) { return true } - const pin = cbor.decode(entry.value) + const pin = cborg.decode(entry.value) return types.includes(pin.depth === 0 ? PinTypes.direct : PinTypes.recursive) }], @@ -250,7 +274,7 @@ class PinManager { })) if (result) { - const pin = cbor.decode(result.value) + const pin = cborg.decode(result.value) return { cid, @@ -263,9 +287,13 @@ class PinManager { const self = this + /** + * @param {CID} key + * @param {AsyncIterable<{ cid: CID, metadata: any }>} source + */ async function * findChild (key, source) { for await (const { cid: parentCid } of source) { - for await (const childCid of self._walkDag(parentCid, { preload: false })) { + for await (const childCid of self._walkDag(parentCid)) { if (childCid.equals(key)) { yield parentCid return @@ -298,10 +326,10 @@ class PinManager { /** * @param {CID} cid - * @param {PreloadOptions & AbortOptions} options + * @param {AbortOptions} options */ async fetchCompleteDag (cid, options) { - await all(this._walkDag(cid, { preload: options.preload })) + await all(this._walkDag(cid, options)) } /** @@ -321,13 +349,3 @@ class PinManager { PinManager.PinTypes = PinTypes module.exports = PinManager - -/** - * @typedef {Object} PinOptions - * @property {any} [metadata] - * - * @typedef {Object} PreloadOptions - * @property {boolean} [preload] - * - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/pin/rm-all.js b/packages/ipfs-core/src/components/pin/rm-all.js index 2157acd407..9e84fb4274 100644 --- a/packages/ipfs-core/src/components/pin/rm-all.js +++ b/packages/ipfs-core/src/components/pin/rm-all.js @@ -7,28 +7,13 @@ const { PinTypes } = require('./pin-manager') /** * @param {Object} config - * @param {import('.').PinManager} config.pinManager + * @param {import('./pin-manager')} config.pinManager * @param {import('.').GCLock} config.gcLock - * @param {import('.').DagReader} config.dagReader + * @param {import('ipld')} config.ipld */ -module.exports = ({ pinManager, gcLock, dagReader }) => { +module.exports = ({ pinManager, gcLock, ipld }) => { /** - * Unpin one or more blocks from your repo - * - * @param {Source} source - Unpin all pins from the source - * @param {AbortOptions} [_options] - * @returns {AsyncIterable} - * @example - * ```js - * const source = [ - * CID.from('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') - * ] - * for await (const cid of ipfs.pin.rmAll(source)) { - * console.log(cid) - * } - * // prints the CIDs that were unpinned - * // CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') - * ``` + * @type {import('ipfs-core-types/src/pin').API["rmAll"]} */ async function * rmAll (source, _options = {}) { const release = await gcLock.readLock() @@ -36,7 +21,7 @@ module.exports = ({ pinManager, gcLock, dagReader }) => { try { // verify that each hash can be unpinned for await (const { path, recursive } of normaliseInput(source)) { - const cid = await resolvePath(dagReader, path) + const cid = await resolvePath(ipld, path) const { pinned, reason } = await pinManager.isPinnedWithType(cid, PinTypes.all) if (!pinned) { @@ -71,9 +56,3 @@ module.exports = ({ pinManager, gcLock, dagReader }) => { return withTimeoutOption(rmAll) } - -/** - * @typedef {import('.').CID} CID - * @typedef {import('.').AbortOptions} AbortOptions - * @typedef {import('./add-all').Source} Source - */ diff --git a/packages/ipfs-core/src/components/pin/rm.js b/packages/ipfs-core/src/components/pin/rm.js index dbb9c47317..516cda8824 100644 --- a/packages/ipfs-core/src/components/pin/rm.js +++ b/packages/ipfs-core/src/components/pin/rm.js @@ -4,34 +4,13 @@ const last = require('it-last') /** * @param {Object} config - * @param {ReturnType} config.rmAll + * @param {import('ipfs-core-types/src/pin').API["rmAll"]} config.rmAll */ module.exports = ({ rmAll }) => /** - * Unpin this block from your repo - * - * @param {string|CID} path - CID or IPFS Path to unpin. - * @param {RmOptions} [options] - * @returns {Promise} - The CIDs that was unpinned - * @example - * ```js - * const cid = CID.from('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') - * const result = await ipfs.pin.rm(cid) - * console.log(result) - * // prints the CID that was unpinned - * // CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') - * ``` + * @type {import('ipfs-core-types/src/pin').API["rm"]} */ - async (path, options) => - /** @type {CID} - Need to loosen check here because it could be void */ - (await last(rmAll({ path, ...options }, options))) - -/** - * @typedef {RmSettings & AbortOptions} RmOptions - * - * @typedef {Object} RmSettings - * @property {boolean} [recursive=true] - Recursively unpin the object linked - * - * @typedef {import('..').CID} CID - * @typedef {import('../../utils').AbortOptions} AbortOptions - */ + (path, options = {}) => { + // @ts-ignore return value of last can be undefined + return last(rmAll([{ path, ...options }], options)) + } diff --git a/packages/ipfs-core/src/components/ping.js b/packages/ipfs-core/src/components/ping.js index 295263085d..d7fca94fd5 100644 --- a/packages/ipfs-core/src/components/ping.js +++ b/packages/ipfs-core/src/components/ping.js @@ -7,40 +7,24 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Send echo request packets to IPFS hosts. - * - * @param {PeerId} peerId - The remote peer to send packets to - * @param {PingOptions} [options] - * @returns {AsyncIterable} - * @example - * ```js - * for await (const res of ipfs.ping('Qmhash')) { - * if (res.time) { - * console.log(`Pong received: time=${res.time} ms`) - * } else { - * console.log(res.text) - * } - * } - * ``` + * @type {import('ipfs-core-types/src/root').API["ping"]} */ async function * ping (peerId, options = {}) { const { libp2p } = await network.use() options.count = options.count || 10 - if (!PeerId.isPeerId(peerId)) { - peerId = PeerId.createFromCID(peerId) - } + const peer = PeerId.createFromCID(peerId) - const storedPeer = libp2p.peerStore.get(peerId) + const storedPeer = libp2p.peerStore.get(peer) let id = storedPeer && storedPeer.id if (!id) { yield { ...basePacket, text: `Looking up peer ${peerId}` } - const remotePeer = await libp2p.peerRouting.findPeer(peerId) + const remotePeer = await libp2p.peerRouting.findPeer(peer) id = remotePeer && remotePeer.id } @@ -100,5 +84,5 @@ module.exports = ({ network }) => { * @typedef {Object} PingSettings * @property {number} [count=10] - The number of ping messages to send * - * @typedef {import('.').AbortOptions} AbortOptions + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions */ diff --git a/packages/ipfs-core/src/components/pubsub.js b/packages/ipfs-core/src/components/pubsub.js index 56b659477a..951ad2d1c3 100644 --- a/packages/ipfs-core/src/components/pubsub.js +++ b/packages/ipfs-core/src/components/pubsub.js @@ -7,11 +7,11 @@ const get = require('dlv') /** * @param {Object} config - * @param {import('.').NetworkService} config.network - * @param {import('.').IPFSConfig} [config.config] + * @param {import('../types').NetworkService} config.network + * @param {import('ipfs-core-types/src/config').Config} [config.config] */ module.exports = ({ network, config }) => { - const isEnabled = get(config, 'Pubsub.Enabled', true) + const isEnabled = get(config || {}, 'Pubsub.Enabled', true) return { subscribe: isEnabled ? withTimeoutOption(subscribe) : notEnabled, @@ -22,116 +22,46 @@ module.exports = ({ network, config }) => { } /** - * Subscribe to a pubsub topic. - * - * @example - * ```js - * const topic = 'fruit-of-the-day' - * const receiveMsg = (msg) => console.log(msg.data.toString()) - * - * await ipfs.pubsub.subscribe(topic, receiveMsg) - * console.log(`subscribed to ${topic}`) - * ``` - * - * @param {string} topic - The topic name - * @param {(message:Message) => void} handler - Event handler which will be - * called with a message object everytime one is received. - * @param {AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/pubsub').API["subscribe"]} */ - async function subscribe (topic, handler, options) { + async function subscribe (topic, handler, options = {}) { const { libp2p } = await network.use(options) // @ts-ignore Libp2p Pubsub is deprecating the handler, using the EventEmitter return libp2p.pubsub.subscribe(topic, handler, options) } /** - * Unsubscribes from a pubsub topic. - * - * @example - * ```js - * const topic = 'fruit-of-the-day' - * const receiveMsg = (msg) => console.log(msg.toString()) - * - * await ipfs.pubsub.subscribe(topic, receiveMsg) - * console.log(`subscribed to ${topic}`) - * - * await ipfs.pubsub.unsubscribe(topic, receiveMsg) - * console.log(`unsubscribed from ${topic}`) - * - * // Or removing all listeners: - * - * const topic = 'fruit-of-the-day' - * const receiveMsg = (msg) => console.log(msg.toString()) - * await ipfs.pubsub.subscribe(topic, receiveMsg); - * // Will unsubscribe ALL handlers for the given topic - * await ipfs.pubsub.unsubscribe(topic); - * ``` - * - * @param {string} topic - The topic to unsubscribe from - * @param {(message:Message) => void} [handler] - The handler to remove. If - * not provided unsubscribes al handlers for the topic. - * @param {AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/pubsub').API["unsubscribe"]} */ - async function unsubscribe (topic, handler, options) { + async function unsubscribe (topic, handler, options = {}) { const { libp2p } = await network.use(options) // @ts-ignore Libp2p Pubsub is deprecating the handler, using the EventEmitter libp2p.pubsub.unsubscribe(topic, handler, options) } /** - * Publish a data message to a pubsub topic. - * - * @example - * ```js - * const topic = 'fruit-of-the-day' - * const msg = new TextEncoder().encode('banana') - * - * await ipfs.pubsub.publish(topic, msg) - * // msg was broadcasted - * console.log(`published to ${topic}`) - * ``` - * - * @param {string} topic - * @param {Uint8Array} data - * @param {AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/pubsub').API["publish"]} */ - async function publish (topic, data, options) { + async function publish (topic, data, options = {}) { const { libp2p } = await network.use(options) if (!data) { throw errCode(new Error('argument "data" is required'), 'ERR_ARG_REQUIRED') } await libp2p.pubsub.publish(topic, data) } + /** - * Returns the list of subscriptions the peer is subscribed to. - * - * @param {AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/pubsub').API["ls"]} */ - async function ls (options) { + async function ls (options = {}) { const { libp2p } = await network.use(options) return libp2p.pubsub.getTopics() } /** - * Returns the peers that are subscribed to one topic. - * - * @example - * ```js - * const topic = 'fruit-of-the-day' - * - * const peerIds = await ipfs.pubsub.peers(topic) - * console.log(peerIds) - * ``` - * - * @param {string} topic - * @param {AbortOptions} [options] - * @returns {Promise} - An array of peer IDs subscribed to the topic + * @type {import('ipfs-core-types/src/pubsub').API["peers"]} */ - async function peers (topic, options) { + async function peers (topic, options = {}) { const { libp2p } = await network.use(options) return libp2p.pubsub.getSubscribers(topic) } @@ -140,13 +70,3 @@ module.exports = ({ network, config }) => { const notEnabled = async () => { // eslint-disable-line require-await throw new NotEnabledError('pubsub not enabled') } - -/** - * @typedef {Object} Message - * @property {string} from - * @property {Uint8Array} seqno - * @property {Uint8Array} data - * @property {string[]} topicIDs - * - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/refs/index.js b/packages/ipfs-core/src/components/refs/index.js index 438532a74d..db4018883e 100644 --- a/packages/ipfs-core/src/components/refs/index.js +++ b/packages/ipfs-core/src/components/refs/index.js @@ -1,31 +1,37 @@ 'use strict' -const isIpfs = require('is-ipfs') const CID = require('cids') const { DAGNode } = require('ipld-dag-pb') -const { normalizeCidPath } = require('../../utils') const { Errors } = require('interface-datastore') const ERR_NOT_FOUND = Errors.notFoundError().code const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +const toCIDAndPath = require('ipfs-core-utils/src/to-cid-and-path') const Format = { default: '', edges: ' -> ' } +/** + * @typedef {object} Node + * @property {string} [name] + * @property {CID} cid + * + * @typedef {object} TraversalResult + * @property {Node} parent + * @property {Node} node + * @property {boolean} isDuplicate + */ + /** * @param {Object} config - * @param {import('..').IPLD} config.ipld - * @param {import('..').Resolve} config.resolve - * @param {import('..').Preload} config.preload + * @param {import('ipld')} config.ipld + * @param {import('ipfs-core-types/src/root').API["resolve"]} config.resolve + * @param {import('../../types').Preload} config.preload */ module.exports = function ({ ipld, resolve, preload }) { /** - * Get links (references) from an object - * - * @param {CID|string} ipfsPath - The object to search for references - * @param {RefsOptions & AbortOptions} [options] - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/refs').API["refs"]} */ async function * refs (ipfsPath, options = {}) { if (options.maxDepth === 0) { @@ -36,7 +42,7 @@ module.exports = function ({ ipld, resolve, preload }) { throw new Error('Cannot set edges to true and also specify format') } - options.format = options.edges ? Format.edges : options.format || Format.default + options.format = options.edges ? Format.edges : options.format if (typeof options.maxDepth !== 'number') { options.maxDepth = options.recursive ? Infinity : 1 @@ -57,34 +63,44 @@ module.exports = function ({ ipld, resolve, preload }) { module.exports.Format = Format +/** + * @param {import('../../types').Preload} preload + * @param {string | CID} ipfsPath + * @param {import('ipfs-core-types/src/refs').RefsOptions} options + */ function getFullPath (preload, ipfsPath, options) { - // normalizeCidPath() strips /ipfs/ off the front of the path so the CID will - // be at the front of the path - const path = normalizeCidPath(ipfsPath) - const pathComponents = path.split('/') - const cid = pathComponents[0] - - if (!isIpfs.cid(cid)) { - throw new Error(`Error resolving path '${path}': '${cid}' is not a valid CID`) - } + const { + cid, + path + } = toCIDAndPath(ipfsPath) if (options.preload !== false) { preload(cid) } - return '/ipfs/' + path + return `/ipfs/${cid}${path || ''}` } -// Get a stream of refs at the given path +/** + * Get a stream of refs at the given path + * + * @param {import('ipfs-core-types/src/root').API["resolve"]} resolve + * @param {import('ipld')} ipld + * @param {string} path + * @param {import('ipfs-core-types/src/refs').RefsOptions} options + */ async function * refsStream (resolve, ipld, path, options) { // Resolve to the target CID of the path const resPath = await resolve(path) - // path is /ipfs/ - const parts = resPath.split('/') - const cid = parts[2] + const { + cid + } = toCIDAndPath(resPath) + + const maxDepth = options.maxDepth != null ? options.maxDepth : Infinity + const unique = options.unique || false // Traverse the DAG, converting it into a stream - for await (const obj of objectStream(ipld, cid, options.maxDepth, options.unique)) { + for await (const obj of objectStream(ipld, cid, maxDepth, unique)) { // Root object will not have a parent if (!obj.parent) { continue @@ -103,18 +119,37 @@ async function * refsStream (resolve, ipld, path, options) { } } -// Get formatted link -function formatLink (srcCid, dstCid, linkName, format) { +/** + * Get formatted link + * + * @param {CID} srcCid + * @param {CID} dstCid + * @param {string} [linkName] + * @param {string} [format] + */ +function formatLink (srcCid, dstCid, linkName = '', format = Format.default) { let out = format.replace(//g, srcCid.toString()) out = out.replace(//g, dstCid.toString()) out = out.replace(//g, linkName) return out } -// Do a depth first search of the DAG, starting from the given root cid +/** + * Do a depth first search of the DAG, starting from the given root cid + * + * @param {import('ipld')} ipld + * @param {CID} rootCid + * @param {number} maxDepth + * @param {boolean} uniqueOnly + */ async function * objectStream (ipld, rootCid, maxDepth, uniqueOnly) { // eslint-disable-line require-await const seen = new Set() + /** + * @param {Node} parent + * @param {number} depth + * @returns {AsyncGenerator} + */ async function * traverseLevel (parent, depth) { const nextLevelDepth = depth + 1 @@ -151,19 +186,35 @@ async function * objectStream (ipld, rootCid, maxDepth, uniqueOnly) { // eslint- yield * traverseLevel({ cid: rootCid }, 0) } -// Fetch a node from IPLD then get all its links +/** + * Fetch a node from IPLD then get all its links + * + * @param {import('ipld')} ipld + * @param {CID} cid + */ async function getLinks (ipld, cid) { - const node = await ipld.get(new CID(cid)) - - if (DAGNode.isDAGNode(node)) { - return node.Links.map(({ Name, Hash }) => ({ name: Name, cid: new CID(Hash) })) + const node = await ipld.get(cid) + + if (node instanceof DAGNode) { + /** + * @param {import('ipld-dag-pb').DAGLink} arg + */ + const mapper = ({ Name, Hash }) => ({ name: Name, cid: Hash }) + return node.Links.map(mapper) } return getNodeLinks(node) } -// Recursively search the node for CIDs +/** + * Recursively search the node for CIDs + * + * @param {object} node + * @param {string} [path] + * @returns {Node[]} + */ function getNodeLinks (node, path = '') { + /** @type {Node[]} */ let links = [] for (const [name, value] of Object.entries(node)) { if (CID.isCID(value)) { @@ -177,17 +228,3 @@ function getNodeLinks (node, path = '') { } return links } - -/** - * @typedef {Object} RefsOptions - * @property {boolean} [recursive=false] - Recursively list references of child nodes - * @property {boolean} [unique=false] - Omit duplicate references from output - * @property {string} [format=''] - Output edges with given format. Available tokens: ``, ``, `` - * @property {boolean} [edges=false] - output references in edge format: `" -> "` - * @property {number} [maxDepth=1] - only for recursive refs, limits fetch and listing to the given depth - * - * @typedef {{ref:string, err?:null}|{ref?:undefined, err:Error}} RefResult - * - * @typedef {import('..').AbortOptions} AbortOptions - * @typedef {import('..').Repo} Repo - */ diff --git a/packages/ipfs-core/src/components/refs/local.js b/packages/ipfs-core/src/components/refs/local.js index 0615b05a2d..e8a87bdd63 100644 --- a/packages/ipfs-core/src/components/refs/local.js +++ b/packages/ipfs-core/src/components/refs/local.js @@ -4,12 +4,11 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = function ({ repo }) { /** - * @param {import('.').AbortOptions} [options] - * @returns {AsyncIterable<{ref: string}>} + * @type {import('ipfs-core-types/src/refs').API["local"]} */ async function * refsLocal (options = {}) { // @ts-ignore - TS is not aware of keysOnly diff --git a/packages/ipfs-core/src/components/repo/gc.js b/packages/ipfs-core/src/components/repo/gc.js index 327f156bea..206091da7e 100644 --- a/packages/ipfs-core/src/components/repo/gc.js +++ b/packages/ipfs-core/src/components/repo/gc.js @@ -12,19 +12,25 @@ const multibase = require('multibase') // Limit on the number of parallel block remove operations const BLOCK_RM_CONCURRENCY = 256 +/** + * @typedef {import('ipfs-core-types/src/pin').API} PinAPI + * @typedef {import('ipfs-core-types/src/refs').API} RefsAPI + * @typedef {import('ipfs-repo')} IPFSRepo + * @typedef {import('interface-datastore').Key} Key + */ + /** * Perform mark and sweep garbage collection * * @param {Object} config - * @param {import('.').GCLock} config.gcLock - * @param {import('.').Pin} config.pin - * @param {import('.').Refs} config.refs - * @param {import('.').Repo} config.repo + * @param {import('../gc-lock').GCLock} config.gcLock + * @param {PinAPI} config.pin + * @param {RefsAPI["refs"]} config.refs + * @param {IPFSRepo} config.repo */ module.exports = ({ gcLock, pin, refs, repo }) => { /** - * @param {AbortOptions} [_options] - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/repo').API["gc"]} */ async function * gc (_options = {}) { const start = Date.now() @@ -51,7 +57,14 @@ module.exports = ({ gcLock, pin, refs, repo }) => { return withTimeoutOption(gc) } -// Get Set of CIDs of blocks to keep +/** + * Get Set of CIDs of blocks to keep + * + * @param {object} arg + * @param {PinAPI} arg.pin + * @param {RefsAPI["refs"]} arg.refs + * @param {IPFSRepo} arg.repo + */ async function createMarkedSet ({ pin, refs, repo }) { const pinsSource = map(({ cid }) => cid, pin.ls()) @@ -82,29 +95,43 @@ async function createMarkedSet ({ pin, refs, repo }) { return output } -// Delete all blocks that are not marked as in use +/** + * Delete all blocks that are not marked as in use + * + * @param {object} arg + * @param {IPFSRepo} arg.repo + * @param {Set} markedSet + * @param {AsyncIterable} blockKeys + */ async function * deleteUnmarkedBlocks ({ repo }, markedSet, blockKeys) { // Iterate through all blocks and find those that are not in the marked set // blockKeys yields { key: Key() } let blocksCount = 0 let removedBlocksCount = 0 + /** + * @param {CID} cid + */ const removeBlock = async (cid) => { blocksCount++ try { const b32 = multibase.encode('base32', cid.multihash).toString() - if (markedSet.has(b32)) return null - const res = { cid } + + if (markedSet.has(b32)) { + return null + } try { await repo.blocks.delete(cid) removedBlocksCount++ } catch (err) { - res.err = new Error(`Could not delete block with CID ${cid}: ${err.message}`) + return { + err: new Error(`Could not delete block with CID ${cid}: ${err.message}`) + } } - return res + return { cid } } catch (err) { const msg = `Could delete block with CID ${cid}` log(msg, err) @@ -120,19 +147,3 @@ async function * deleteUnmarkedBlocks ({ repo }, markedSet, blockKeys) { log(`Marked set has ${markedSet.size} unique blocks. Blockstore has ${blocksCount} blocks. ` + `Deleted ${removedBlocksCount} blocks.`) } - -/** - * @typedef {import('../../utils').AbortOptions} AbortOptions - * - * @typedef {Err|BlockID} Notification - * - * @typedef {Object} Err - * @property {void} [cid] - * @property {Error} err - * - * @typedef {Object} BlockID - * @property {CID} cid - * @property {void} [err] - * - * @typedef {import('interface-datastore').Key} Key - */ diff --git a/packages/ipfs-core/src/components/repo/index.js b/packages/ipfs-core/src/components/repo/index.js index 82e4e401d5..7854c39df7 100644 --- a/packages/ipfs-core/src/components/repo/index.js +++ b/packages/ipfs-core/src/components/repo/index.js @@ -7,10 +7,10 @@ const createVersion = require('./version') class RepoAPI { /** * @param {Object} config - * @param {GCLock} config.gcLock - * @param {Pin} config.pin - * @param {Repo} config.repo - * @param {Refs} config.refs + * @param {import('../gc-lock').GCLock} config.gcLock + * @param {import('ipfs-core-types/src/pin').API} config.pin + * @param {import('ipfs-repo')} config.repo + * @param {import('ipfs-core-types/src/refs').API["refs"]} config.refs */ constructor ({ gcLock, pin, repo, refs }) { this.gc = createGC({ gcLock, pin, refs, repo }) @@ -19,11 +19,3 @@ class RepoAPI { } } module.exports = RepoAPI - -/** - * @typedef {import('..').GCLock} GCLock - * @typedef {import('..').Pin} Pin - * @typedef {import('..').Repo} Repo - * @typedef {import('..').Refs} Refs - * @typedef {import('..').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/repo/stat.js b/packages/ipfs-core/src/components/repo/stat.js index 612ec451fc..1813644304 100644 --- a/packages/ipfs-core/src/components/repo/stat.js +++ b/packages/ipfs-core/src/components/repo/stat.js @@ -4,21 +4,21 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { /** - * @param {import('.').AbortOptions} [options] + * @type {import('ipfs-core-types/src/repo').API["stat"]} */ - async function stat (options) { - const stats = await repo.stat(options) + async function stat (options = {}) { + const stats = await repo.stat() return { - numObjects: stats.numObjects, - repoSize: stats.repoSize, + numObjects: BigInt(stats.numObjects.toString()), + repoSize: BigInt(stats.repoSize.toString()), repoPath: stats.repoPath, - version: stats.version.toString(), - storageMax: stats.storageMax + version: `${stats.version}`, + storageMax: BigInt(stats.storageMax.toString()) } } diff --git a/packages/ipfs-core/src/components/repo/version.js b/packages/ipfs-core/src/components/repo/version.js index 25c6202595..b47a2970dd 100644 --- a/packages/ipfs-core/src/components/repo/version.js +++ b/packages/ipfs-core/src/components/repo/version.js @@ -5,17 +5,13 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { /** - * If the repo has been initialized, report the current version. - * Otherwise report the version that would be initialized. - * - * @param {import('.').AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/repo').API["version"]} */ - async function version (options) { + async function version (options = {}) { try { // @ts-ignore - not a public API await repo._checkInitialized(options) @@ -35,7 +31,7 @@ module.exports = ({ repo }) => { throw err } - return repo.version.get(options) + return repo.version.get() } return withTimeoutOption(version) diff --git a/packages/ipfs-core/src/components/resolve.js b/packages/ipfs-core/src/components/resolve.js index 9c6b0b3ef7..c220a60404 100644 --- a/packages/ipfs-core/src/components/resolve.js +++ b/packages/ipfs-core/src/components/resolve.js @@ -7,51 +7,12 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').IPLD} config.ipld - * @param {import('.').Name} config.name - An IPFS core interface name API + * @param {import('ipld')} config.ipld + * @param {import('ipfs-core-types/src/name').API} config.name - An IPFS core interface name API */ module.exports = ({ ipld, name }) => { /** - * Resolve the value of names to IPFS - * - * There are a number of mutable name protocols that can link among themselves - * and into IPNS. For example IPNS references can (currently) point at an IPFS - * object, and DNS links can point at other DNS links, IPNS entries, or IPFS - * objects. This command accepts any of these identifiers and resolves them - * to the referenced item. - * - * @param {string} path - The name to resolve - * @param {ResolveOptions} [opts] - * @returns {Promise} - A string representing the resolved name - * @example - * ```js - * // Resolve the value of your identity: - * const name = '/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy' - * - * const res = await ipfs.resolve(name) - * console.log(res) - * // Logs: /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj - * - * // Resolve the value of another name recursively: - * const name = '/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n' - * - * // Where: - * // /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n - * // ...resolves to: - * // /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy - * // ...which in turn resolves to: - * // /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj - * - * const res = await ipfs.resolve(name, { recursive: true }) - * console.log(res) - * // Logs: /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj - * - * // Resolve the value of an IPFS path: - * const name = '/ipfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop' - * const res = await ipfs.resolve(name) - * console.log(res) - * // Logs: /ipfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1 - * ``` + * @type {import('ipfs-core-types/src/root').API["resolve"]} */ async function resolve (path, opts = {}) { if (!isIpfs.path(path)) { @@ -94,13 +55,3 @@ module.exports = ({ ipld, name }) => { return withTimeoutOption(resolve) } - -/** - * @typedef {ResolveSettings & AbortOptions} ResolveOptions - * - * @typedef {Object} ResolveSettings - * @property {boolean} [recursive=true] - Resolve until result is an IPFS name. - * @property {import('cids').BaseNameOrCode} [cidBase='base58btc'] - Multibase codec name the CID in the resolved path will be encoded with. - * - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/root.js b/packages/ipfs-core/src/components/root.js index 9be83d8169..054a61e341 100644 --- a/packages/ipfs-core/src/components/root.js +++ b/packages/ipfs-core/src/components/root.js @@ -12,8 +12,6 @@ const createLsAPI = require('./ls') * @typedef {import('./cat').Context} CatContext * @typedef {import('./get').Context} GetContext * @typedef {import('./ls').Context} ListContext - * @typedef {import('ipfs-core-types/src').RootAPI} RootAPI - * @implements {RootAPI} */ class Root { /** diff --git a/packages/ipfs-core/src/components/start.js b/packages/ipfs-core/src/components/start.js index a9d512f377..b56b1c7d84 100644 --- a/packages/ipfs-core/src/components/start.js +++ b/packages/ipfs-core/src/components/start.js @@ -4,18 +4,21 @@ const Service = require('../utils/service') /** * @param {Object} config - * @param {import('.').NetworkService} config.network - * @param {import('.').PeerId} config.peerId - * @param {import('.').Repo} config.repo - * @param {import('.').BlockService} config.blockService - * @param {import('.').Print} config.print - * @param {import('.').Preload} config.preload - * @param {import('.').MFSPreload} config.mfsPreload - * @param {import('.').IPNS} config.ipns - * @param {import('.').Keychain} config.keychain - * @param {import('.').Options} config.options + * @param {import('../types').NetworkService} config.network + * @param {import('peer-id')} config.peerId + * @param {import('ipfs-repo')} config.repo + * @param {import('ipfs-block-service')} config.blockService + * @param {import('../types').Print} config.print + * @param {import('../types').Preload} config.preload + * @param {import('../types').MfsPreload} config.mfsPreload + * @param {import('./ipns')} config.ipns + * @param {import('libp2p/src/keychain')} config.keychain + * @param {import('../types').Options} config.options */ module.exports = ({ network, preload, peerId, keychain, repo, ipns, blockService, mfsPreload, print, options }) => { + /** + * @type {import('ipfs-core-types/src/root').API["start"]} + */ const start = async () => { const { bitswap, libp2p } = await Service.start(network, { peerId, diff --git a/packages/ipfs-core/src/components/stats/bw.js b/packages/ipfs-core/src/components/stats/bw.js index 1b6ecac384..52c5a72a14 100644 --- a/packages/ipfs-core/src/components/stats/bw.js +++ b/packages/ipfs-core/src/components/stats/bw.js @@ -1,12 +1,30 @@ 'use strict' -const { default: Big } = require('bignumber.js') const { default: parseDuration } = require('parse-duration') const errCode = require('err-code') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** - * @param {LibP2P} libp2p + * @typedef {Object} BWOptions + * @property {PeerId} [peer] - Specifies a peer to print bandwidth for + * @property {string} [proto] - Specifies a protocol to print bandwidth for + * @property {boolean} [poll] - Is used to yield bandwidth info at an interval + * @property {number|string} [interval=1000] - The time interval to wait between updating output, if `poll` is `true`. + * + * @typedef {Object} BandwidthInfo + * @property {bigint} totalIn + * @property {bigint} totalOut + * @property {bigint} rateIn + * @property {bigint} rateOut + * + * @typedef {import('libp2p')} libp2p + * @typedef {import('peer-id')} PeerId + * @typedef {import('cids')} CID + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ + +/** + * @param {libp2p} libp2p * @param {BWOptions} opts * @returns {BandwidthInfo} */ @@ -25,33 +43,30 @@ function getBandwidthStats (libp2p, opts) { if (!stats) { return { - totalIn: new Big(0), - totalOut: new Big(0), - rateIn: new Big(0), - rateOut: new Big(0) + totalIn: BigInt(0), + totalOut: BigInt(0), + rateIn: BigInt(0), + rateOut: BigInt(0) } } const { movingAverages, snapshot } = stats return { - totalIn: snapshot.dataReceived, - totalOut: snapshot.dataSent, - rateIn: new Big(movingAverages.dataReceived[60000].movingAverage() / 60), - rateOut: new Big(movingAverages.dataSent[60000].movingAverage() / 60) + totalIn: BigInt(snapshot.dataReceived.toString()), + totalOut: BigInt(snapshot.dataSent.toString()), + rateIn: BigInt(movingAverages.dataReceived[60000].movingAverage() / 60), + rateOut: BigInt(movingAverages.dataSent[60000].movingAverage() / 60) } } /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Get IPFS bandwidth information - * - * @param {BWOptions & AbortOptions} options - * @returns {AsyncIterable} + * @type {import('ipfs-core-types/src/stats').API["bw"]} */ const bw = async function * (options = {}) { const { libp2p } = await network.use(options) @@ -84,22 +99,3 @@ module.exports = ({ network }) => { return withTimeoutOption(bw) } - -/** - * @typedef {Object} BWOptions - * @property {PeerId} [peer] - Specifies a peer to print bandwidth for - * @property {string} [proto] - Specifies a protocol to print bandwidth for - * @property {boolean} [poll] - Is used to yield bandwidth info at an interval - * @property {number|string} [interval=1000] - The time interval to wait between updating output, if `poll` is `true`. - * - * @typedef {Object} BandwidthInfo - * @property {Big} totalIn - * @property {Big} totalOut - * @property {Big} rateIn - * @property {Big} rateOut - * - * @typedef {import('.').LibP2P} LibP2P - * @typedef {import('.').PeerId} PeerId - * @typedef {import('.').CID} CID - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/stats/index.js b/packages/ipfs-core/src/components/stats/index.js index 6760c21853..700653cbcb 100644 --- a/packages/ipfs-core/src/components/stats/index.js +++ b/packages/ipfs-core/src/components/stats/index.js @@ -7,8 +7,8 @@ const createBitswap = require('../bitswap/stat') class StatsAPI { /** * @param {Object} config - * @param {Repo} config.repo - * @param {NetworkService} config.network + * @param {import('ipfs-repo')} config.repo + * @param {import('../../types').NetworkService} config.network */ constructor ({ repo, network }) { this.repo = createRepo({ repo }) @@ -18,12 +18,3 @@ class StatsAPI { } module.exports = StatsAPI - -/** - * @typedef {import('..').Repo} Repo - * @typedef {import('..').PeerId} PeerId - * @typedef {import('..').LibP2P} LibP2P - * @typedef {import('..').CID} CID - * @typedef {import('..').NetworkService} NetworkService - * @typedef {import('..').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/stop.js b/packages/ipfs-core/src/components/stop.js index 5ff0412014..5cde54ef1d 100644 --- a/packages/ipfs-core/src/components/stop.js +++ b/packages/ipfs-core/src/components/stop.js @@ -4,14 +4,17 @@ const Service = require('../utils/service') /** * @param {Object} config - * @param {import('.').NetworkService} config.network - * @param {import('.').Preload} config.preload - * @param {import('.').BlockService} config.blockService - * @param {import('.').IPNS} config.ipns - * @param {import('.').Repo} config.repo - * @param {import('.').MFSPreload} config.mfsPreload + * @param {import('../types').NetworkService} config.network + * @param {import('../types').Preload} config.preload + * @param {import('ipfs-block-service')} config.blockService + * @param {import('./ipns')} config.ipns + * @param {import('ipfs-repo')} config.repo + * @param {import('../types').MfsPreload} config.mfsPreload */ module.exports = ({ network, preload, blockService, ipns, repo, mfsPreload }) => { + /** + * @type {import('ipfs-core-types/src/root').API["stop"]} + */ const stop = async () => { blockService.unsetExchange() await Promise.all([ diff --git a/packages/ipfs-core/src/components/storage.js b/packages/ipfs-core/src/components/storage.js index d44a66bf8d..c8b50b5af1 100644 --- a/packages/ipfs-core/src/components/storage.js +++ b/packages/ipfs-core/src/components/storage.js @@ -12,12 +12,22 @@ const configService = require('./config') const { NotEnabledError } = require('../errors') const createLibP2P = require('./libp2p') +/** + * @typedef {import('ipfs-repo')} IPFSRepo + * @typedef {import('../types').Options} IPFSOptions + * @typedef {import('../types').InitOptions} InitOptions + * @typedef {import('../types').Print} Print + * @typedef {import('ipfs-core-types/src/config').Config} IPFSConfig + * @typedef {import('libp2p-crypto').KeyType} KeyType + * @typedef {import('libp2p/src/keychain')} Keychain + */ + class Storage { /** * @private * @param {PeerId} peerId * @param {Keychain} keychain - * @param {Repo} repo + * @param {IPFSRepo} repo * @param {Print} print * @param {boolean} isNew */ @@ -31,17 +41,17 @@ class Storage { } /** - * - * @param {Options} options + * @param {Print} print + * @param {IPFSOptions} options */ - static async start (options) { - const { repoAutoMigrate: autoMigrate, repo: inputRepo, print, silent } = options + static async start (print, options) { + const { repoAutoMigrate, repo: inputRepo } = options const repo = (typeof inputRepo === 'string' || inputRepo == null) - ? createRepo({ path: inputRepo, autoMigrate, silent }) + ? createRepo(print, { path: inputRepo, autoMigrate: Boolean(repoAutoMigrate) }) : inputRepo - const { peerId, keychain, isNew } = await loadRepo(repo, options) + const { peerId, keychain, isNew } = await loadRepo(print, repo, options) // TODO: throw error? // @ts-ignore On start, keychain will always be available @@ -51,58 +61,42 @@ class Storage { module.exports = Storage /** - * - * @param {Repo} repo - * @param {RepoOptions & InitOptions} options - * @returns {Promise<{peerId: PeerId, keychain?: Keychain, isNew:boolean }>} + * @param {Print} print + * @param {IPFSRepo} repo + * @param {IPFSOptions} options */ -const loadRepo = async (repo, options) => { - const openError = await openRepo(repo) - if (openError == null) { - // If opened successfully configure repo +const loadRepo = async (print, repo, options) => { + if (!repo.closed) { return { ...await configureRepo(repo, options), isNew: false } - } else if (openError.code === ERR_REPO_NOT_INITIALIZED) { - if (options.allowNew === false) { - throw new NotEnabledError('Initialization of new repos disabled by config, pass `config.init.isNew: true` to enable it') - } else { - // If failed to open, because repo isn't initilaized and initalizing a - // new repo allowed, init repo: - return { ...await initRepo(repo, options), isNew: true } - } - } else { - throw openError } -} -/** - * Attempts to open given repo unless it is already open and returns result - * containing repo or an error if failed. - * - * @param {Repo} repo - * @returns {Promise<(Error & { code: number }) | null>} - */ -const openRepo = async (repo) => { - // If repo is closed attempt to open it. - if (repo.closed) { - try { - await repo.open() - return null - } catch (error) { - return error + try { + await repo.open() + + return { ...await configureRepo(repo, options), isNew: false } + } catch (err) { + if (err.code !== ERR_REPO_NOT_INITIALIZED) { + throw err } - } else { - return null + + if (options.init && options.init.allowNew === false) { + throw new NotEnabledError('Initialization of new repos disabled by config, pass `config.init.isNew: true` to enable it') + } + + return { ...await initRepo(print, repo, options), isNew: true } } } /** - * @param {Repo} repo - * @param {RepoOptions & InitOptions} options + * @param {Print} print + * @param {IPFSRepo} repo + * @param {IPFSOptions} options * @returns {Promise<{peerId: PeerId, keychain?: Keychain}>} */ -const initRepo = async (repo, options) => { - // 1. Verify that repo does not exist yet (if it does and we could not - // open it we give up) +const initRepo = async (print, repo, options) => { + const initOptions = options.init || {} + + // 1. Verify that repo does not exist yet (if it does and we could not open it we give up) const exists = await repo.exists() log('repo exists?', exists) @@ -110,20 +104,18 @@ const initRepo = async (repo, options) => { throw new Error('repo already exists') } - // 2. Restore `peerId` from a given `.privateKey` or init new using - // provide options. - const peerId = options.privateKey - ? await decodePeerId(options.privateKey) - : await initPeerId(options) + // 2. Restore `peerId` from a given `.privateKey` or init new using provided options. + const peerId = initOptions.privateKey + ? await decodePeerId(initOptions.privateKey) + : await initPeerId(print, initOptions) const identity = peerIdToIdentity(peerId) log('peer identity: %s', identity.PeerID) - // 3. Init new repo with provided `.config` and restored / initalized - // peerd identity. + // 3. Init new repo with provided `.config` and restored / initialized `peerId` const config = { - ...mergeOptions(applyProfiles(getDefaultConfig(), options.profiles), options.config), + ...mergeOptions(applyProfiles(getDefaultConfig(), initOptions.profiles), options.config), Identity: identity } await repo.init(config) @@ -171,15 +163,15 @@ const decodePeerId = (peerId) => { } /** - * Initializes new PeerId by generting an underlying keypair. + * Initializes new PeerId by generating an underlying keypair. * + * @param {Print} print * @param {Object} options * @param {KeyType} [options.algorithm='RSA'] * @param {number} [options.bits=2048] - * @param {Print} options.print * @returns {Promise} */ -const initPeerId = ({ print, algorithm = 'RSA', bits = 2048 }) => { +const initPeerId = (print, { algorithm = 'RSA', bits = 2048 }) => { // Generate peer identity keypair + transform to desired format + add to config. print('generating %s-bit (rsa only) %s keypair...', bits, algorithm) return PeerId.create({ keyType: algorithm, bits }) @@ -195,14 +187,18 @@ const peerIdToIdentity = (peerId) => ({ }) /** - * Applies passed `profiles` and a `config` to an open repo. + * Applies passed `profiles` and a `config` to an open repo. * - * @param {Repo} repo - * @param {ConfigureOptions} options + * @param {IPFSRepo} repo + * @param {IPFSOptions} options * @returns {Promise<{peerId: PeerId, keychain?: Keychain}>} */ -const configureRepo = async (repo, { config, profiles, pass }) => { +const configureRepo = async (repo, options) => { + const config = options.config + const profiles = (options.init && options.init.profiles) || [] + const pass = options.pass const original = await repo.config.getAll() + // @ts-ignore TODO: move config types to repo const changed = mergeConfigs(applyProfiles(original, profiles), config) if (original !== changed) { @@ -253,51 +249,3 @@ const applyProfiles = (config, profiles) => { return profile.transform(config) }, config) } - -/** - * @typedef {StorageOptions & RepoOptions & InitOptions} Options - * - * @typedef {Object} StorageOptions - * @property {Repo|string} [repo='~/.jsipfs'] - The file path at which to store the - * IPFS node’s data. Alternatively, you can set up a customized storage system - * by providing an Repo implementation. (In browser default is 'ipfs'). - * @property {boolean} [repoAutoMigrate=true] - js-ipfs comes bundled with a tool - * that automatically migrates your IPFS repository when a new version is - * available. - * @property {boolean} [repoOwner] - * @property {IPLDOptions} [ipld] - * - * - * @typedef {Object} RepoOptions - * @property {Print} print - * @property {IPFSConfig} [config] - * @property {boolean} [silent] - * - * @typedef {Object} ConfigureOptions - * @property {IPFSConfig} [options.config] - * @property {string[]} [options.profiles] - * @property {string} [options.pass] - * - * @typedef {Object} InitOptions - On Frist run js-ipfs will initalize a repo - * which can be customized through this settings. - * @property {boolean} [emptyRepo=false] - Whether to remove built-in assets, - * like the instructional tour and empty mutable file system, from the repo. - * @property {KeyType} [algorithm='RSA'] - The type of key to use. - * @property {number} [bits=2048] - Number of bits to use in the generated key - * pair (rsa only). - * @property {PeerId|string} [privateKey] - A pre-generated private key to use. - * **NOTE: This overrides `bits`.** - * @property {string} [pass] - A passphrase to encrypt keys. You should - * generally use the top-level `pass` option instead of the `init.pass` - * option (this one will take its value from the top-level option if not set). - * @property {string[]} [profiles] - Apply profile settings to config. - * @property {boolean} [allowNew=true] - Set to `false` to disallow - * initialization if the repo does not already exist. - * - * @typedef {import('.').IPLDOptions} IPLDOptions - * @typedef {import('.').Print} Print - * @typedef {import('.').IPFSConfig} IPFSConfig - * @typedef {import('ipfs-core-types/src/repo').Repo} Repo - * @typedef {import('libp2p-crypto').KeyType} KeyType - * @typedef {import('libp2p/src/keychain')} Keychain - */ diff --git a/packages/ipfs-core/src/components/swarm/addrs.js b/packages/ipfs-core/src/components/swarm/addrs.js index 28ae132fd3..aa96cafe7f 100644 --- a/packages/ipfs-core/src/components/swarm/addrs.js +++ b/packages/ipfs-core/src/components/swarm/addrs.js @@ -4,21 +4,19 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * List of known addresses of each peer connected. - * - * @param {import('../../utils').AbortOptions} options - * @returns {Promise} + * @type {import('ipfs-core-types/src/swarm').API["addrs"]} */ - async function addrs (options) { // eslint-disable-line require-await + async function addrs (options = {}) { // eslint-disable-line require-await const peers = [] const { libp2p } = await network.use(options) for (const [peerId, peer] of libp2p.peerStore.peers.entries()) { peers.push({ id: peerId, + // @ts-ignore - libp2p types are missing addrs: peer.addresses.map((mi) => mi.multiaddr) }) } @@ -27,11 +25,3 @@ module.exports = ({ network }) => { return withTimeoutOption(addrs) } - -/** - * @typedef {Object} PeerInfo - * @property {string} id - * @property {Multiaddr[]} addrs - * - * @typedef {import('.').Multiaddr} Multiaddr - */ diff --git a/packages/ipfs-core/src/components/swarm/connect.js b/packages/ipfs-core/src/components/swarm/connect.js index 49c078a3b8..137ec6892e 100644 --- a/packages/ipfs-core/src/components/swarm/connect.js +++ b/packages/ipfs-core/src/components/swarm/connect.js @@ -4,17 +4,13 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Open a connection to a given address. - * - * @param {import('.').Multiaddr} addr - * @param {import('.').AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/swarm').API["connect"]} */ - async function connect (addr, options) { + async function connect (addr, options = {}) { const { libp2p } = await network.use(options) await libp2p.dial(addr, options) } diff --git a/packages/ipfs-core/src/components/swarm/disconnect.js b/packages/ipfs-core/src/components/swarm/disconnect.js index 6e3c8ad0f7..0eb9bcc184 100644 --- a/packages/ipfs-core/src/components/swarm/disconnect.js +++ b/packages/ipfs-core/src/components/swarm/disconnect.js @@ -4,17 +4,13 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Close a connection on a given address. - * - * @param {import('.').Multiaddr} addr - * @param {import('.').AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/swarm').API["disconnect"]} */ - async function disconnect (addr, options) { + async function disconnect (addr, options = {}) { const { libp2p } = await network.use(options) await libp2p.hangUp(addr) } diff --git a/packages/ipfs-core/src/components/swarm/index.js b/packages/ipfs-core/src/components/swarm/index.js index 29af23f83b..c7986d9185 100644 --- a/packages/ipfs-core/src/components/swarm/index.js +++ b/packages/ipfs-core/src/components/swarm/index.js @@ -9,7 +9,7 @@ const createPeersAPI = require('./peers') class SwarmAPI { /** * @param {Object} config - * @param {NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ constructor ({ network }) { this.addrs = createAddrsAPI({ network }) @@ -21,9 +21,3 @@ class SwarmAPI { } module.exports = SwarmAPI - -/** - * @typedef {import('..').NetworkService} NetworkService - * @typedef {import('..').Multiaddr} Multiaddr - * @typedef {import('..').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/swarm/local-addrs.js b/packages/ipfs-core/src/components/swarm/local-addrs.js index e7321aa175..a99b6435c5 100644 --- a/packages/ipfs-core/src/components/swarm/local-addrs.js +++ b/packages/ipfs-core/src/components/swarm/local-addrs.js @@ -4,23 +4,16 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Local addresses this node is listening on. - * - * @param {import('.').AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/swarm').API["localAddrs"]} */ - async function localAddrs (options) { + async function localAddrs (options = {}) { const { libp2p } = await network.use(options) return libp2p.multiaddrs } return withTimeoutOption(localAddrs) } - -/** - * @typedef {import('.').Multiaddr} Multiaddr - */ diff --git a/packages/ipfs-core/src/components/swarm/peers.js b/packages/ipfs-core/src/components/swarm/peers.js index 0c91011217..dfae29201e 100644 --- a/packages/ipfs-core/src/components/swarm/peers.js +++ b/packages/ipfs-core/src/components/swarm/peers.js @@ -4,37 +4,35 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').NetworkService} config.network + * @param {import('../../types').NetworkService} config.network */ module.exports = ({ network }) => { /** - * Local addresses this node is listening on. - * - * @param {PeersOptions & AbortOptions} [options] - * @returns {Promise} + * @type {import('ipfs-core-types/src/swarm').API["peers"]} */ async function peers (options = {}) { const { libp2p } = await network.use(options) - const verbose = options.v || options.verbose const peers = [] for (const [peerId, connections] of libp2p.connections) { for (const connection of connections) { - const tupple = { + /** @type {import('ipfs-core-types/src/swarm').PeersResult} */ + const peer = { addr: connection.remoteAddr, peer: peerId } - if (verbose || options.direction) { - tupple.direction = connection.stat.direction + if (options.verbose || options.direction) { + peer.direction = connection.stat.direction } - if (verbose) { - tupple.muxer = connection.stat.multiplexer - tupple.latency = 'n/a' + if (options.verbose) { + peer.muxer = connection.stat.multiplexer + peer.latency = 'n/a' + peer.streams = [] // TODO: get this from libp2p } - peers.push(tupple) + peers.push(peer) } } @@ -43,22 +41,3 @@ module.exports = ({ network }) => { return withTimeoutOption(peers) } - -/** - * @typedef {Object} PeerConnection - * @property {Multiaddr} addr - * @property {string} peer - * @property {string} [latency] - * @property {string} [muxer] - * @property {number} [direction] - * - * @typedef {Object} PeersOptions - * @property {boolean} [direction=false] - * @property {boolean} [streams=false] - * @property {boolean} [verbose=false] - * @property {boolean} [v=false] - * @property {boolean} [latency=false] - * - * @typedef {import('.').Multiaddr} Multiaddr - * @typedef {import('.').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/components/version.js b/packages/ipfs-core/src/components/version.js index e4c0e3c010..4471ff8b29 100644 --- a/packages/ipfs-core/src/components/version.js +++ b/packages/ipfs-core/src/components/version.js @@ -5,26 +5,18 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** * @param {Object} config - * @param {import('.').Repo} config.repo + * @param {import('ipfs-repo')} config.repo */ module.exports = ({ repo }) => { /** - * Returns the implementation version - * - * @param {import('.').AbortOptions} [options] - * @returns {Promise} - * @example - * ```js - * const version = await ipfs.version() - * console.log(version) - * ``` + * @type {import('ipfs-core-types/src/root').API["version"]} */ - async function version (options) { - const repoVersion = await repo.version.get(options) + async function version (_options = {}) { + const repoVersion = await repo.version.get() return { version: pkg.version, - repo: repoVersion, + repo: `${repoVersion}`, // @ts-ignore gitHead is defined in published versions commit: pkg.gitHead || '', @@ -34,17 +26,3 @@ module.exports = ({ repo }) => { return withTimeoutOption(version) } - -/** - * @typedef {object} Version - * An object with the version information for the implementation, - * the commit and the Repo. `js-ipfs` instances will also return - * the version of `interface-ipfs-core` and `ipfs-http-client` - * supported by this node - * - * @property {string} version - * @property {number} repo - * @property {string} [commit] - * @property {string} [interface-ipfs-core] - * @property {string} [ipfs-http-client] - */ diff --git a/packages/ipfs-core/src/index.js b/packages/ipfs-core/src/index.js index f52ec102c6..d437622a81 100644 --- a/packages/ipfs-core/src/index.js +++ b/packages/ipfs-core/src/index.js @@ -15,6 +15,7 @@ const { create } = require('./components') /** * @typedef {import('./components')} IPFS + * @typedef {import('./types').Options} Options */ module.exports = { diff --git a/packages/ipfs-core/src/ipns/index.js b/packages/ipfs-core/src/ipns/index.js index 87fd6b4970..e95a666afb 100644 --- a/packages/ipfs-core/src/ipns/index.js +++ b/packages/ipfs-core/src/ipns/index.js @@ -10,11 +10,26 @@ const log = Object.assign(debug('ipfs:ipns'), { const IpnsPublisher = require('./publisher') const IpnsRepublisher = require('./republisher') const IpnsResolver = require('./resolver') -const { normalizePath } = require('../utils') const TLRU = require('../utils/tlru') const defaultRecordTtl = 60 * 1000 +const uint8ArrayToString = require('uint8arrays/to-string') + +/** + * @typedef {import('libp2p-crypto').PrivateKey} PrivateKey + * @typedef {import('peer-id')} PeerId + */ class IPNS { + /** + * @param {import('ipfs-core-types/src/utils').BufferStore} routing + * @param {import('interface-datastore').Datastore} datastore + * @param {PeerId} peerId + * @param {import('libp2p/src/keychain')} keychain + * @param {object} options + * @param {string} options.pass + * @param {number} [options.initialBroadcastInterval] + * @param {number} [options.broadcastInterval] + */ constructor (routing, datastore, peerId, keychain, options) { this.publisher = new IpnsPublisher(routing, datastore) this.republisher = new IpnsRepublisher(this.publisher, datastore, peerId, keychain, options) @@ -23,15 +38,19 @@ class IPNS { this.routing = routing } - // Publish + /** + * Publish + * + * @param {PrivateKey} privKey + * @param {Uint8Array} value + * @param {number} lifetime + */ async publish (privKey, value, lifetime = IpnsPublisher.defaultRecordLifetime) { try { - value = normalizePath(value) - const peerId = await createFromPrivKey(privKey.bytes) await this.publisher.publishWithEOL(privKey, value, lifetime) - log(`IPNS value ${value} was published correctly`) + log(`IPNS value ${uint8ArrayToString(value, 'base32')} was published correctly`) // // Add to cache const id = peerId.toB58String() @@ -41,7 +60,7 @@ class IPNS { this.cache.set(id, value, ttl) - log(`IPNS value ${value} was cached correctly`) + log(`IPNS value ${uint8ArrayToString(value, 'base32')} was cached correctly`) return { name: id, @@ -54,7 +73,14 @@ class IPNS { } } - // Resolve + /** + * Resolve + * + * @param {string} name + * @param {object} options + * @param {boolean} [options.nocache] + * @param {boolean} [options.recursive] + */ async resolve (name, options = {}) { if (typeof name !== 'string') { throw errcode(new Error('name received is not valid'), 'ERR_INVALID_NAME') @@ -84,8 +110,14 @@ class IPNS { } } - // Initialize keyspace - // sets the ipns record for the given key to point to an empty directory + /** + * Initialize keyspace + * + * Sets the ipns record for the given key to point to an empty directory + * + * @param {PrivateKey} privKey + * @param {Uint8Array} value + */ async initializeKeyspace (privKey, value) { // eslint-disable-line require-await return this.publish(privKey, value, IpnsPublisher.defaultRecordLifetime) } diff --git a/packages/ipfs-core/src/ipns/publisher.js b/packages/ipfs-core/src/ipns/publisher.js index 3b66854dc0..acf0dbd265 100644 --- a/packages/ipfs-core/src/ipns/publisher.js +++ b/packages/ipfs-core/src/ipns/publisher.js @@ -8,20 +8,37 @@ const log = Object.assign(debug('ipfs:ipns:publisher'), { error: debug('ipfs:ipns:publisher:error') }) const uint8ArrayToString = require('uint8arrays/to-string') +const uint8ArrayEquals = require('uint8arrays/equals') const ipns = require('ipns') +/** + * @typedef {import('libp2p-crypto').PrivateKey} PrivateKey + * @typedef {import('libp2p-crypto').PublicKey} PublicKey + * @typedef {import('ipns').IPNSEntry} IPNSEntry + */ + const ERR_NOT_FOUND = Errors.notFoundError().code const defaultRecordLifetime = 60 * 60 * 1000 // IpnsPublisher is capable of publishing and resolving names to the IPFS routing system. class IpnsPublisher { + /** + * @param {import('ipfs-core-types/src/utils').BufferStore} routing + * @param {import('interface-datastore').Datastore} datastore + */ constructor (routing, datastore) { this._routing = routing this._datastore = datastore } - // publish record with a eol + /** + * Publish record with a eol + * + * @param {PrivateKey} privKey + * @param {Uint8Array} value + * @param {number} lifetime + */ async publishWithEOL (privKey, value, lifetime) { if (!privKey || !privKey.bytes) { throw errcode(new Error('invalid private key'), 'ERR_INVALID_PRIVATE_KEY') @@ -33,11 +50,20 @@ class IpnsPublisher { return this._putRecordToRouting(record, peerId) } - // Accepts a keypair, as well as a value (ipfsPath), and publishes it out to the routing system + /** + * Accepts a keypair, as well as a value (ipfsPath), and publishes it out to the routing system + * + * @param {PrivateKey} privKey + * @param {Uint8Array} value + */ publish (privKey, value) { return this.publishWithEOL(privKey, value, defaultRecordLifetime) } + /** + * @param {IPNSEntry} record + * @param {PeerId} peerId + */ async _putRecordToRouting (record, peerId) { if (!(PeerId.isPeerId(peerId))) { const errMsg = 'peerId received is not valid' @@ -61,6 +87,10 @@ class IpnsPublisher { return embedPublicKeyRecord || record } + /** + * @param {Key} key + * @param {IPNSEntry} entry + */ async _publishEntry (key, entry) { if (!(Key.isKey(key))) { const errMsg = 'datastore key does not have a valid format' @@ -95,6 +125,10 @@ class IpnsPublisher { } } + /** + * @param {Key} key + * @param {PublicKey} publicKey + */ async _publishPublicKey (key, publicKey) { if ((!Key.isKey(key))) { const errMsg = 'datastore key does not have a valid format' @@ -125,8 +159,15 @@ class IpnsPublisher { } } - // Returns the record this node has published corresponding to the given peer ID. - // If `checkRouting` is true and we have no existing record, this method will check the routing system for any existing records. + /** + * Returns the record this node has published corresponding to the given peer ID. + * + * If `checkRouting` is true and we have no existing record, this method will check the routing system for any existing records. + * + * @param {PeerId} peerId + * @param {object} options + * @param {boolean} [options.checkRouting] + */ async _getPublished (peerId, options = {}) { if (!(PeerId.isPeerId(peerId))) { const errMsg = 'peerId received is not valid' @@ -152,7 +193,7 @@ class IpnsPublisher { } if (!checkRouting) { - throw errcode(err) + throw errcode(err, 'ERR_NOT_FOUND_AND_CHECK_ROUTING_NOT_ENABLED') } // Try to get from routing @@ -170,6 +211,9 @@ class IpnsPublisher { } } + /** + * @param {Uint8Array} data + */ _unmarshalData (data) { try { return ipns.unmarshal(data) @@ -178,7 +222,13 @@ class IpnsPublisher { } } - async _updateOrCreateRecord (privKey, value, validity, peerId) { + /** + * @param {PrivateKey} privKey + * @param {Uint8Array} value + * @param {number} lifetime + * @param {PeerId} peerId + */ + async _updateOrCreateRecord (privKey, value, lifetime, peerId) { if (!(PeerId.isPeerId(peerId))) { const errMsg = 'peerId received is not valid' log.error(errMsg) @@ -207,14 +257,14 @@ class IpnsPublisher { let seqNumber = 0 if (record && record.sequence !== undefined) { - seqNumber = record.value.toString() !== value ? record.sequence + 1 : record.sequence + seqNumber = !uint8ArrayEquals(record.value, value) ? record.sequence + 1 : record.sequence } let entryData try { // Create record - entryData = await ipns.create(privKey, value, seqNumber, validity) + entryData = await ipns.create(privKey, value, seqNumber, lifetime) } catch (err) { const errMsg = `ipns record for ${value} could not be created` @@ -231,7 +281,7 @@ class IpnsPublisher { // Store the new record await this._datastore.put(ipns.getLocalKey(peerId.id), data) - log(`ipns record for ${value} was stored in the datastore`) + log(`ipns record for ${uint8ArrayToString(value, 'base32')} was stored in the datastore`) return entryData } catch (err) { diff --git a/packages/ipfs-core/src/ipns/republisher.js b/packages/ipfs-core/src/ipns/republisher.js index 0efccdc954..e419ab8884 100644 --- a/packages/ipfs-core/src/ipns/republisher.js +++ b/packages/ipfs-core/src/ipns/republisher.js @@ -10,6 +10,10 @@ const log = Object.assign(debug('ipfs:ipns:republisher'), { error: debug('ipfs:ipns:republisher:error') }) +/** + * @typedef {import('libp2p-crypto').PrivateKey} PrivateKey + */ + const minute = 60 * 1000 const hour = 60 * minute @@ -17,7 +21,17 @@ const defaultBroadcastInterval = 4 * hour const defaultRecordLifetime = 24 * hour class IpnsRepublisher { - constructor (publisher, datastore, peerId, keychain, options = {}) { + /** + * @param {import('./publisher')} publisher + * @param {import('interface-datastore').Datastore} datastore + * @param {PeerId} peerId + * @param {import('libp2p/src/keychain')} keychain + * @param {object} options + * @param {string} options.pass + * @param {number} [options.initialBroadcastInterval] + * @param {number} [options.broadcastInterval] + */ + constructor (publisher, datastore, peerId, keychain, options = { pass: '' }) { this._publisher = publisher this._datastore = datastore this._peerId = peerId @@ -102,6 +116,10 @@ class IpnsRepublisher { await republishHandle.cancel() } + /** + * @param {PrivateKey} privateKey + * @param {string} pass + */ async _republishEntries (privateKey, pass) { // TODO: Should use list of published entries. // We can't currently *do* that because go uses this method for now. @@ -131,6 +149,9 @@ class IpnsRepublisher { } } + /** + * @param {PrivateKey} privateKey + */ async _republishEntry (privateKey) { if (!privateKey || !privateKey.bytes) { throw errcode(new Error('invalid private key'), 'ERR_INVALID_PRIVATE_KEY') @@ -149,6 +170,9 @@ class IpnsRepublisher { } } + /** + * @param {PeerId} peerId + */ async _getPreviousValue (peerId) { if (!(PeerId.isPeerId(peerId))) { throw errcode(new Error('invalid peer ID'), 'ERR_INVALID_PEER_ID') diff --git a/packages/ipfs-core/src/ipns/resolver.js b/packages/ipfs-core/src/ipns/resolver.js index f57936064d..a7faf11e35 100644 --- a/packages/ipfs-core/src/ipns/resolver.js +++ b/packages/ipfs-core/src/ipns/resolver.js @@ -15,10 +15,18 @@ const ERR_NOT_FOUND = Errors.notFoundError().code const defaultMaximumRecursiveDepth = 32 class IpnsResolver { + /** + * @param {import('ipfs-core-types/src/utils').BufferStore} routing + */ constructor (routing) { this._routing = routing } + /** + * @param {string} name + * @param {object} options + * @param {boolean} [options.recursive] + */ async resolve (name, options = {}) { if (typeof name !== 'string') { throw errcode(new Error('invalid name'), 'ERR_INVALID_NAME') @@ -35,7 +43,7 @@ class IpnsResolver { const key = nameSegments[2] // Define a maximum depth if recursive option enabled - let depth + let depth = Infinity if (recursive) { depth = defaultMaximumRecursiveDepth @@ -47,7 +55,13 @@ class IpnsResolver { return res } - // Recursive resolver according to the specified depth + /** + * Recursive resolver according to the specified depth + * + * @param {string} name + * @param {number} depth + * @returns {Promise} + */ async resolver (name, depth) { // Exceeded recursive maximum depth if (depth === 0) { @@ -69,7 +83,11 @@ class IpnsResolver { return this.resolver(nameSegments[2], depth - 1) } - // resolve ipns entries from the provided routing + /** + * Resolve ipns entries from the provided routing + * + * @param {string} name + */ async _resolveName (name) { const peerId = PeerId.createFromCID(name) const { routingKey } = ipns.getIdKeys(peerId.toBytes()) @@ -101,7 +119,12 @@ class IpnsResolver { return this._validateRecord(peerId, ipnsEntry) } - // validate a resolved record + /** + * Validate a resolved record + * + * @param {PeerId} peerId + * @param {import('ipns').IPNSEntry} ipnsEntry + */ async _validateRecord (peerId, ipnsEntry) { const pubKey = await ipns.extractPublicKey(peerId, ipnsEntry) diff --git a/packages/ipfs-core/src/ipns/routing/config.js b/packages/ipfs-core/src/ipns/routing/config.js index 941097e100..033b928d8a 100644 --- a/packages/ipfs-core/src/ipns/routing/config.js +++ b/packages/ipfs-core/src/ipns/routing/config.js @@ -6,6 +6,13 @@ const get = require('dlv') const PubsubDatastore = require('./pubsub-datastore') const OfflineDatastore = require('./offline-datastore') +/** + * @param {object} arg + * @param {import('libp2p')} arg.libp2p + * @param {import('ipfs-repo')} arg.repo + * @param {import('peer-id')} arg.peerId + * @param {object} arg.options + */ module.exports = ({ libp2p, repo, peerId, options }) => { // Setup online routing for IPNS with a tiered routing composed by a DHT and a Pubsub router (if properly enabled) const ipnsStores = [] diff --git a/packages/ipfs-core/src/ipns/routing/offline-datastore.js b/packages/ipfs-core/src/ipns/routing/offline-datastore.js index aef4bbe0b0..7a2c9e3f48 100644 --- a/packages/ipfs-core/src/ipns/routing/offline-datastore.js +++ b/packages/ipfs-core/src/ipns/routing/offline-datastore.js @@ -13,8 +13,13 @@ const log = Object.assign(debug('ipfs:ipns:offline-datastore'), { // Offline datastore aims to mimic the same encoding as routing when storing records // to the local datastore class OfflineDatastore { + /** + * @param {import('ipfs-repo')} repo + */ constructor (repo) { this._repo = repo + /** @type {any[]} */ + this.stores = [] } /** @@ -22,7 +27,6 @@ class OfflineDatastore { * * @param {Uint8Array} key - identifier of the value. * @param {Uint8Array} value - value to be stored. - * @returns {Promise} */ async put (key, value) { // eslint-disable-line require-await if (!(key instanceof Uint8Array)) { @@ -52,7 +56,6 @@ class OfflineDatastore { * Get a value from the local datastore indexed by the received key properly encoded. * * @param {Uint8Array} key - identifier of the value to be obtained. - * @returns {Promise} */ async get (key) { if (!(key instanceof Uint8Array)) { @@ -82,7 +85,11 @@ class OfflineDatastore { return record.value } - // encode key properly - base32(/ipns/{cid}) + /** + * encode key properly - base32(/ipns/{cid}) + * + * @param {Uint8Array} key + */ _routingKey (key) { return new Key('/' + encodeBase32(key), false) } diff --git a/packages/ipfs-core/src/ipns/routing/pubsub-datastore.js b/packages/ipfs-core/src/ipns/routing/pubsub-datastore.js index ae0f02bbe4..925725ee59 100644 --- a/packages/ipfs-core/src/ipns/routing/pubsub-datastore.js +++ b/packages/ipfs-core/src/ipns/routing/pubsub-datastore.js @@ -6,8 +6,6 @@ const PubsubDatastore = require('datastore-pubsub') const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayFromString = require('uint8arrays/from-string') -const withIs = require('class-is') - const errcode = require('err-code') const debug = require('debug') const log = Object.assign(debug('ipfs:ipns:pubsub'), { @@ -16,8 +14,13 @@ const log = Object.assign(debug('ipfs:ipns:pubsub'), { // Pubsub datastore aims to manage the pubsub subscriptions for IPNS class IpnsPubsubDatastore { + /** + * @param {import('libp2p-interfaces/src/pubsub')} pubsub + * @param {import('interface-datastore').Datastore} localDatastore + * @param {import('peer-id')} peerId + */ constructor (pubsub, localDatastore, peerId) { - this._pubsub = pubsub + /** @type {Record} */ this._subscriptions = {} // Bind _handleSubscriptionKey function, which is called by PubsubDatastore. @@ -28,11 +31,11 @@ class IpnsPubsubDatastore { /** * Put a value to the pubsub datastore indexed by the received key properly encoded. * - * @param {Buffer} key - identifier of the value. - * @param {Buffer} value - value to be stored. - * @returns {Promise} + * @param {Uint8Array} key - identifier of the value. + * @param {Uint8Array} value - value to be stored. */ - async put (key, value) { // eslint-disable-line require-await + put (key, value) { + // @ts-ignore datastores take Key keys, this one takes Uint8Array keys return this._pubsubDs.put(key, value) } @@ -41,14 +44,14 @@ class IpnsPubsubDatastore { * Also, the identifier topic is subscribed to and the pubsub datastore records will be * updated once new publishes occur. * - * @param {Buffer} key - identifier of the value to be obtained. - * @returns {Promise} + * @param {Uint8Array} key - identifier of the value to be obtained. */ async get (key) { let res let err try { + // @ts-ignore datastores take Key keys, this one takes Uint8Array keys res = await this._pubsubDs.get(key) } catch (e) { err = e @@ -74,7 +77,11 @@ class IpnsPubsubDatastore { return res } - // Modify subscription key to have a proper encoding + /** + * Modify subscription key to have a proper encoding + * + * @param {Uint8Array | string} key + */ _handleSubscriptionKey (key) { if (key instanceof Uint8Array) { key = uint8ArrayToString(key, 'base58btc') @@ -99,8 +106,6 @@ class IpnsPubsubDatastore { /** * Get pubsub subscriptions related to ipns. - * - * @returns {string[]} */ getSubscriptions () { const subscriptions = Object.values(this._subscriptions).filter(Boolean) @@ -112,7 +117,6 @@ class IpnsPubsubDatastore { * Cancel pubsub subscriptions related to ipns. * * @param {string} name - ipns path to cancel the pubsub subscription. - * @returns {Promise<{canceled: boolean}>} */ async cancel (name) { // eslint-disable-line require-await if (typeof name !== 'string') { @@ -138,7 +142,7 @@ class IpnsPubsubDatastore { this._pubsubDs.unsubscribe(bufTopic) - this._subscriptions[stringifiedTopic] = undefined + delete this._subscriptions[stringifiedTopic] log(`unsubscribed pubsub ${stringifiedTopic}: ${name}`) return { @@ -147,4 +151,4 @@ class IpnsPubsubDatastore { } } -exports = module.exports = withIs(IpnsPubsubDatastore, { className: 'IpnsPubsubDatastore', symbolName: '@js-ipfs/ipns/IpnsPubsubDatastore' }) +module.exports = IpnsPubsubDatastore diff --git a/packages/ipfs-core/src/ipns/routing/utils.js b/packages/ipfs-core/src/ipns/routing/utils.js index 20f2b65423..e3af891327 100644 --- a/packages/ipfs-core/src/ipns/routing/utils.js +++ b/packages/ipfs-core/src/ipns/routing/utils.js @@ -4,9 +4,20 @@ const ipns = require('ipns') const uint8ArrayToString = require('uint8arrays/to-string') module.exports = { + /** + * @param {Uint8Array} buf + */ encodeBase32: (buf) => uint8ArrayToString(buf, 'base32upper'), validator: { - func: (key, record, cb) => ipns.validator.validate(record, key, cb) + /** + * @param {Uint8Array} key + * @param {Uint8Array} record + */ + func: (key, record) => ipns.validator.validate(record, key) }, + /** + * @param {*} _k + * @param {Uint8Array[]} records + */ selector: (_k, records) => ipns.validator.select(records[0], records[1]) } diff --git a/packages/ipfs-core/src/mfs-preload.js b/packages/ipfs-core/src/mfs-preload.js index e800eff9f4..96fc18f206 100644 --- a/packages/ipfs-core/src/mfs-preload.js +++ b/packages/ipfs-core/src/mfs-preload.js @@ -6,10 +6,17 @@ const log = Object.assign(debug('ipfs:mfs-preload'), { error: debug('ipfs:mfs-preload:error') }) +/** + * @typedef {PreloadOptions & MFSPreloadOptions} Options + * @typedef {Object} MFSPreloadOptions + * @property {number} [interval] + * @typedef {import('./types').PreloadOptions} PreloadOptions + */ + /** * @param {Object} config - * @param {import('./components').Preload} config.preload - * @param {import('./components').Files} config.files + * @param {import('./types').Preload} config.preload + * @param {import('ipfs-core-types/src/files').API} config.files * @param {Options} [config.options] */ module.exports = ({ preload, files, options = {} }) => { @@ -21,7 +28,9 @@ module.exports = ({ preload, files, options = {} }) => { return { start: noop, stop: noop } } - let rootCid, timeoutId + let rootCid = '' + /** @type {any} */ + let timeoutId const preloadMfs = async () => { try { @@ -58,11 +67,3 @@ module.exports = ({ preload, files, options = {} }) => { } } } - -/** - * @typedef {ReturnType} MFSPreload - * @typedef {PreloadOptions & MFSPreloadOptions} Options - * @typedef {Object} MFSPreloadOptions - * @property {number} [interval] - * @typedef {import('./components').PreloadOptions} PreloadOptions - */ diff --git a/packages/ipfs-core/src/preload.js b/packages/ipfs-core/src/preload.js index d6857ca8ed..d0eca680a4 100644 --- a/packages/ipfs-core/src/preload.js +++ b/packages/ipfs-core/src/preload.js @@ -1,5 +1,6 @@ 'use strict' +// @ts-ignore no types const toUri = require('multiaddr-to-uri') const debug = require('debug') const CID = require('cids') @@ -16,7 +17,7 @@ const log = Object.assign( ) /** - * @param {Options & AbortOptions} [options] + * @param {import('./types').PreloadOptions} [options] */ const createPreloader = (options = {}) => { options.enabled = Boolean(options.enabled) @@ -33,6 +34,7 @@ const createPreloader = (options = {}) => { } let stopped = true + /** @type {AbortController[]} */ let requests = [] const apiUris = options.addresses.map(toUri) @@ -40,8 +42,7 @@ const createPreloader = (options = {}) => { const cache = hashlru(options.cache) /** - * @param {string|CID} path - * @returns {Promise} + * @type {import('./types').Preload} */ const api = async path => { try { @@ -65,6 +66,7 @@ const createPreloader = (options = {}) => { for (const uri of fallbackApiUris) { if (stopped) throw new Error(`preload aborted for ${path}`) + /** @type {AbortController} */ let controller try { @@ -108,15 +110,3 @@ const createPreloader = (options = {}) => { } module.exports = createPreloader - -/** - * @typedef {ReturnType} Preload - * - * @typedef {object} Options - * @property {boolean} [enabled = false] - Whether to preload anything - * @property {number} [cache = 1000] - How many CIDs to cache - * @property {string[]} [addresses = []] - Which preload servers to use. - * **NOTE:** nodes specified here should also be added to your node's bootstrap address list at `config.Boostrap`. - * - * @typedef {import('./components').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/src/runtime/dns-browser.js b/packages/ipfs-core/src/runtime/dns-browser.js index 3d2fab2bd4..c66e3934dc 100644 --- a/packages/ipfs-core/src/runtime/dns-browser.js +++ b/packages/ipfs-core/src/runtime/dns-browser.js @@ -16,13 +16,26 @@ const ttl = 60 * 1000 // we don't want preload calls to exhaust the limit (~6) const httpQueue = new PQueue({ concurrency: 4 }) +/** + * @param {{ Path: string, Message: string }} response + */ const ipfsPath = (response) => { if (response.Path) return response.Path throw new Error(response.Message) } +/** + * @param {string} fqdn + * @param {object} opts + */ module.exports = async (fqdn, opts) => { // eslint-disable-line require-await + /** + * @param {string} fqdn + * @param {object} opts + * @param {boolean} [opts.nocache] + */ const resolveDnslink = async (fqdn, opts = {}) => { + // @ts-ignore - URLSearchParams does not take boolean options, only strings const searchParams = new URLSearchParams(opts) searchParams.set('arg', fqdn) diff --git a/packages/ipfs-core/src/runtime/dns-nodejs.js b/packages/ipfs-core/src/runtime/dns-nodejs.js index 3b75c3b2de..f4e70d42a2 100644 --- a/packages/ipfs-core/src/runtime/dns-nodejs.js +++ b/packages/ipfs-core/src/runtime/dns-nodejs.js @@ -7,18 +7,29 @@ const { promisify } = require('util') const MAX_RECURSIVE_DEPTH = 32 +/** + * @param {string} domain + * @param {object} opts + * @param {boolean} [opts.recursive] + */ module.exports = (domain, opts) => { // recursive is true by default, it's set to false only if explicitly passed as argument in opts - const recursive = opts.recursive == null ? true : Boolean(opts.recursive) + const nonRecursive = !opts.recursive - let depth - if (recursive) { - depth = MAX_RECURSIVE_DEPTH + /** @type {number | undefined} */ + let depth = MAX_RECURSIVE_DEPTH + if (nonRecursive) { + depth = undefined } return recursiveResolveDnslink(domain, depth) } +/** + * @param {string} domain + * @param {number} [depth] + * @returns {Promise} + */ async function recursiveResolveDnslink (domain, depth) { if (depth === 0) { throw errcode(new Error('recursion limit exceeded'), 'ERR_DNSLINK_RECURSION_LIMIT') @@ -57,6 +68,9 @@ async function recursiveResolveDnslink (domain, depth) { return recursiveResolveDnslink(domainOrCID, depth - 1) } +/** + * @param {string} domain + */ async function resolveDnslink (domain) { const DNSLINK_REGEX = /^dnslink=.+$/ const records = await promisify(dns.resolveTxt)(domain) diff --git a/packages/ipfs-core/src/runtime/init-assets-nodejs.js b/packages/ipfs-core/src/runtime/init-assets-nodejs.js index 356ef6f5e6..cf6b1c8b48 100644 --- a/packages/ipfs-core/src/runtime/init-assets-nodejs.js +++ b/packages/ipfs-core/src/runtime/init-assets-nodejs.js @@ -4,12 +4,23 @@ const path = require('path') const globSource = require('ipfs-utils/src/files/glob-source') const all = require('it-all') -// Add the default assets to the repo. +/** + * Add the default assets to the repo. + * + * @param {object} arg + * @param {import('ipfs-core-types/src/root').API["addAll"]} arg.addAll + * @param {(msg: string) => void} arg.print + */ module.exports = async function initAssets ({ addAll, print }) { const initDocsPath = path.join(__dirname, '..', 'init-files', 'init-docs') const results = await all(addAll(globSource(initDocsPath, { recursive: true }), { preload: false })) + const dir = results.filter(file => file.path === 'init-docs').pop() + if (!dir) { + return + } + print('to get started, enter:\n') print(`\tjsipfs cat /ipfs/${dir.cid}/readme\n`) } diff --git a/packages/ipfs-core/src/runtime/ipld.js b/packages/ipfs-core/src/runtime/ipld.js index fd942f888c..61e51d6977 100644 --- a/packages/ipfs-core/src/runtime/ipld.js +++ b/packages/ipfs-core/src/runtime/ipld.js @@ -3,7 +3,15 @@ const mergeOptions = require('merge-options') const multicodec = require('multicodec') -// All known (non-default) IPLD formats +/** + * @typedef {import('interface-ipld-format').Format} IPLDFormat + */ + +/** + * All known (non-default) IPLD formats + * + * @type {Record} + */ const IpldFormats = { get [multicodec.DAG_PB] () { return require('ipld-dag-pb') @@ -16,16 +24,23 @@ const IpldFormats = { } } -module.exports = (blockService, options = {}, log) => { +/** + * @param {import('ipfs-block-service')} blockService + * @param {import('ipld').Options} [options] + */ +module.exports = (blockService, options) => { return mergeOptions.call( // ensure we have the defaults formats even if the user overrides `formats: []` { concatArrays: true }, { blockService: blockService, + formats: [], + /** + * @type {import('ipld').LoadFormatFn} + */ loadFormat: (codec) => { - log('Loading IPLD format', codec) if (IpldFormats[codec]) { - return IpldFormats[codec] + return Promise.resolve(IpldFormats[codec]) } else { throw new Error(`Missing IPLD format "${multicodec.getName(codec)}"`) } diff --git a/packages/ipfs-core/src/runtime/libp2p-browser.js b/packages/ipfs-core/src/runtime/libp2p-browser.js index b7c9680c4f..48d4cab843 100644 --- a/packages/ipfs-core/src/runtime/libp2p-browser.js +++ b/packages/ipfs-core/src/runtime/libp2p-browser.js @@ -1,7 +1,10 @@ 'use strict' +// @ts-ignore - no types const WS = require('libp2p-websockets') +// @ts-ignore - no types const WebRTCStar = require('libp2p-webrtc-star') +// @ts-ignore - no types const Multiplex = require('libp2p-mplex') const { NOISE } = require('libp2p-noise') const KadDHT = require('libp2p-kad-dht') diff --git a/packages/ipfs-core/src/runtime/libp2p-nodejs.js b/packages/ipfs-core/src/runtime/libp2p-nodejs.js index cb72c3cfe8..6336d2455b 100644 --- a/packages/ipfs-core/src/runtime/libp2p-nodejs.js +++ b/packages/ipfs-core/src/runtime/libp2p-nodejs.js @@ -1,10 +1,14 @@ 'use strict' +// @ts-ignore - no types const TCP = require('libp2p-tcp') +// @ts-ignore - no types const MulticastDNS = require('libp2p-mdns') +// @ts-ignore - no types const WS = require('libp2p-websockets') const KadDHT = require('libp2p-kad-dht') const GossipSub = require('libp2p-gossipsub') +// @ts-ignore - no types const Multiplex = require('libp2p-mplex') const { NOISE } = require('libp2p-noise') const ipnsUtils = require('../ipns/routing/utils') diff --git a/packages/ipfs-core/src/runtime/libp2p-pubsub-routers-nodejs.js b/packages/ipfs-core/src/runtime/libp2p-pubsub-routers-nodejs.js index 0af111e881..cf329268b7 100644 --- a/packages/ipfs-core/src/runtime/libp2p-pubsub-routers-nodejs.js +++ b/packages/ipfs-core/src/runtime/libp2p-pubsub-routers-nodejs.js @@ -2,5 +2,6 @@ module.exports = { gossipsub: require('libp2p-gossipsub'), + // @ts-ignore - no types floodsub: require('libp2p-floodsub') } diff --git a/packages/ipfs-core/src/runtime/preload-browser.js b/packages/ipfs-core/src/runtime/preload-browser.js index 5005982b62..c162f641f7 100644 --- a/packages/ipfs-core/src/runtime/preload-browser.js +++ b/packages/ipfs-core/src/runtime/preload-browser.js @@ -13,6 +13,10 @@ const log = Object.assign(debug('ipfs:preload'), { // we don't want preload calls to exhaust the limit (~6) const httpQueue = new PQueue({ concurrency: 4 }) +/** + * @param {string} url + * @param {import('ipfs-core-types/src/utils').AbortOptions} options + */ module.exports = function preload (url, options = {}) { log(url) diff --git a/packages/ipfs-core/src/runtime/preload-nodejs.js b/packages/ipfs-core/src/runtime/preload-nodejs.js index 0cf65212c8..b63afcb6ca 100644 --- a/packages/ipfs-core/src/runtime/preload-nodejs.js +++ b/packages/ipfs-core/src/runtime/preload-nodejs.js @@ -7,6 +7,10 @@ const log = Object.assign(debug('ipfs:preload'), { error: debug('ipfs:preload:error') }) +/** + * @param {string} url + * @param {import('ipfs-core-types/src/utils').AbortOptions} options + */ module.exports = async function preload (url, options = {}) { log(url) diff --git a/packages/ipfs-core/src/runtime/repo-browser.js b/packages/ipfs-core/src/runtime/repo-browser.js index ad13c85d93..576257a65f 100644 --- a/packages/ipfs-core/src/runtime/repo-browser.js +++ b/packages/ipfs-core/src/runtime/repo-browser.js @@ -2,7 +2,13 @@ const IPFSRepo = require('ipfs-repo') -module.exports = (options = {}) => { +/** + * @param {import('../types').Print} print + * @param {object} options + * @param {string} [options.path] + * @param {boolean} options.autoMigrate + */ +module.exports = (print, options) => { const repoPath = options.path || 'ipfs' return new IPFSRepo(repoPath, { autoMigrate: options.autoMigrate }) } diff --git a/packages/ipfs-core/src/runtime/repo-nodejs.js b/packages/ipfs-core/src/runtime/repo-nodejs.js index 78bae2d565..992d0a3504 100644 --- a/packages/ipfs-core/src/runtime/repo-nodejs.js +++ b/packages/ipfs-core/src/runtime/repo-nodejs.js @@ -5,33 +5,35 @@ const IPFSRepo = require('ipfs-repo') const path = require('path') /** - * @param {Object} [options] + * @param {import('../types').Print} print + * @param {object} options * @param {string} [options.path] - * @param {boolean} [options.silent] - * @param {boolean} [options.autoMigrate] - * @returns {Repo} + * @param {boolean} options.autoMigrate */ -module.exports = (options = {}) => { +module.exports = (print, options = { autoMigrate: true }) => { const repoPath = options.path || path.join(os.homedir(), '.jsipfs') - let lastMigration = null + /** + * @type {number} + */ + let lastMigration + /** + * @param {number} version + * @param {string} percentComplete + * @param {string} message + */ const onMigrationProgress = (version, percentComplete, message) => { if (version !== lastMigration) { lastMigration = version - console.info(`Migrating repo from v${version - 1} to v${version}`) // eslint-disable-line no-console + print(`Migrating repo from v${version - 1} to v${version}`) } - console.info(`${percentComplete.toString().padStart(6, ' ')}% ${message}`) // eslint-disable-line no-console + print(`${percentComplete.toString().padStart(6, ' ')}% ${message}`) } return new IPFSRepo(repoPath, { autoMigrate: options.autoMigrate, - onMigrationProgress: options.silent ? null : onMigrationProgress + onMigrationProgress: onMigrationProgress }) } - -/** - * @typedef {import('ipfs-core-types/src/repo').Repo} Repo - * @typedef {import('../components/config').IPFSConfig} IPFSConfig - */ diff --git a/packages/ipfs-core/src/types.d.ts b/packages/ipfs-core/src/types.d.ts new file mode 100644 index 0000000000..557013ebf9 --- /dev/null +++ b/packages/ipfs-core/src/types.d.ts @@ -0,0 +1,230 @@ +import type { KeyType } from 'libp2p-crypto' +import type PeerId from 'peer-id' +import type { IPFSConfig } from 'ipfs-core-types/src/config' +import type { ProfileNames } from 'ipfs-core-types/src/config/profiles' +import type IPLD from 'ipld' +import type { Options as IPLDOptions } from 'ipld' +import type Libp2p from 'libp2p' +import type { Libp2pConfig as Libp2pOptions } from 'libp2p' +import type IPFSRepo from 'ipfs-repo' +import type { ProgressCallback as MigrationProgressCallback } from 'ipfs-repo-migrations' +import type { Datastore } from 'interface-datastore' +import type Network, { Options as NetworkOptions } from './components/network' +import type Service from './utils/service' + +export interface Options { + /** + * Initialization options of the IPFS node. + * Note that *initializing* a repo is different from creating an instance of + * [`ipfs-repo`](https://github.com/ipfs/js-ipfs-repo). The IPFS constructor + * sets many special properties when initializing a repo, so you should usually + * not try and call `repoInstance.init()` yourself. + */ + init?: InitOptions + + /** + * If `false`, do not automatically start the IPFS node. Instead, you’ll need to manually call + * [`node.start()`](https://github.com/ipfs/js-ipfs/blob/master/packages/ipfs/docs/MODULE.md#nodestart) + * yourself. + */ + start?: boolean + + /** + * A passphrase to encrypt/decrypt keys stored in your keychain + */ + pass?: string + + /** + * Configure circuit relay (see the [circuit relay tutorial](https://github.com/ipfs/js-ipfs/tree/master/examples/circuit-relaying) + * to learn more) + */ + relay?: RelayOptions + + /** + * Run ipfs node offline. The node does not connect to the rest of the network + * but APIs that do not require network access will still work. + */ + offline?: boolean + + /** + * Configure remote preload nodes. The remote will preload content added on this node, + * and also attempt to preload objects requested by this node. + */ + preload?: PreloadOptions + + /** + * Enable and configure experimental features + */ + EXPERIMENTAL?: ExperimentalOptions + + /** + * Modify the default IPFS node config. This object will be *merged* with the default config; it will not replace it. + * (Default: [`config-nodejs.js`](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/config-nodejs.js) + * in Node.js, [`config-browser.js`](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/config-browser.js) + * in browsers) + */ + config?: IPFSConfig + + /** + * If multiple instances of IPFS are accessing the same repo - e.g. via node cluster or browser UI and webworkers + * one instance must be designated the repo owner to hold the lock on shared resources like the datastore. + * + * Set this property to true on one instance only if this is how your application is set up. + */ + repoOwner?: boolean + + /** + * The file path at which to store the IPFS node’s data. Alternatively, you can set up a customized + * storage system by providing an Repo implementation. (In browser default is 'ipfs'). + */ + repo?: IPFSRepo | string + + /** + * Occasionally a repo migration is necessary - pass true here to to this automatically at startup + * when a new version of IPFS is being run for the first time and a migration is necssary, otherwise + * the node will refuse to start + */ + repoAutoMigrate?: boolean + + /** + * Pass a function here to be notified of progress when a repo migration is taking place + */ + onMigrationProgress?: MigrationProgressCallback + + /** + * Modify the default IPLD config. This object + * will be *merged* with the default config; it will not replace it. Check IPLD + * [docs](https://github.com/ipld/js-ipld#ipld-constructor) for more information + * on the available options. (Default: [`ipld.js`] + * (https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/ipld-nodejs.js) in Node.js, [`ipld-browser.js`](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/ipld-browser.js) + * (https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/ipld.js) + * in browsers) + */ + ipld?: IPLDOptions + + /** + * The libp2p option allows you to build + * your libp2p node by configuration, or via a bundle function. If you are + * looking to just modify the below options, using the object format is the + * quickest way to get the default features of libp2p. If you need to create a + * more customized libp2p node, such as with custom transports or peer/content + * routers that need some of the ipfs data on startup, a custom bundle is a + * great way to achieve this. + * - You can see the bundle in action in the [custom libp2p example](https://github.com/ipfs/js-ipfs/tree/master/examples/custom-libp2p). + * - Please see [libp2p/docs/CONFIGURATION.md](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md) + * for the list of options libp2p supports. + * - Default: [`libp2p-nodejs.js`](../src/core/runtime/libp2p-nodejs.js) + * in Node.js, [`libp2p-browser.js`](../src/core/runtime/libp2p-browser.js) in + * browsers. + */ + libp2p?: Libp2pOptions | Libp2pFactoryFn + + silent?: boolean +} + +export type Libp2pFactoryFn = ({ libp2pOptions: Libp2pOptions, options: Options, config: IPFSConfig, datastore: Datastore, peerId: PeerId }) => Libp2p + +/** + * On first run js-IPFS will initialize a repo which can be customized through this settings + */ +export interface InitOptions { + /** + * Whether to remove built-in assets, like the instructional tour and empty mutable file system, from the repo + */ + emptyRepo?: boolean + + /** + * The type of key to use + */ + algorithm?: KeyType + + /** + * Number of bits to use in the generated key pair (rsa only) + */ + bits?: number + + /** + * A pre-generated private key to use + * **NOTE: This overrides `bits`.** + */ + privateKey?: PeerId|string + + /** + * Apply profile settings to config + */ + profiles?: ProfileNames[] + + /** + * Set to `false` to disallow initialization if the repo does not already exist + */ + allowNew?: boolean +} + +export interface RelayOptions { + /** + * Enable circuit relay dialer and listener. (Default: `true`) + */ + enabled?: boolean + + hop?: { + /** + * Make this node a relay (other nodes can connect *through* it). (Default: `false`) + */ + enabled?: boolean + + /** + * Make this an active relay node. Active relay nodes will attempt to dial a destination peer even if that peer is not yet connected to the relay. (Default: false) + */ + active?: boolean + } +} + +export interface PreloadOptions { + /** + * Whether to preload anything + */ + enabled?: boolean + + /** + * How many CIDs to cache + */ + cache?: number + + /** + * Which preload servers to use. **NOTE:** nodes specified here should also be added to your node's + * bootstrap address list at `config.Boostrap` + */ + addresses?: string[] +} + +export interface ExperimentalOptions { + /** + * Enable pub-sub on IPNS. (Default: `false`) + */ + ipnsPubsub?: boolean + + /** + * Enable directory sharding. Directories that have many child objects will be represented by multiple + * DAG nodes instead of just one. It can improve lookup performance when a directory has several + * thousand files or more. (Default: `false`) + */ + sharding?: boolean +} + +/** + * Prints output to the console + */ +export type Print = (...args:any[]) => void + +export interface Preload { + (cid: CID): void + start: () => void + stop: () => void +} + +export interface MfsPreload { + start: () => void + stop: () => void +} + +export type NetworkService = Service diff --git a/packages/ipfs-core/src/utils.js b/packages/ipfs-core/src/utils.js index c32e3abaf0..39494dc222 100644 --- a/packages/ipfs-core/src/utils.js +++ b/packages/ipfs-core/src/utils.js @@ -5,10 +5,14 @@ const isIpfs = require('is-ipfs') const CID = require('cids') const Key = require('interface-datastore').Key const errCode = require('err-code') -const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** @type {typeof Object.assign} */ const mergeOptions = require('merge-options') +const resolve = require('./components/dag/resolve') + +/** + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ exports.mergeOptions = mergeOptions @@ -23,12 +27,12 @@ exports.MFS_MAX_LINKS = 174 * Returns a well-formed ipfs Path. * The returned path will always be prefixed with /ipfs/ or /ipns/. * - * @param {string} pathStr - An ipfs-path, or ipns-path or a cid + * @param {string | CID} pathStr - An ipfs-path, or ipns-path or a cid * @returns {string} - ipfs-path or ipns-path * @throws on an invalid @param pathStr */ const normalizePath = (pathStr) => { - if (isIpfs.cid(pathStr)) { + if (isIpfs.cid(pathStr) || CID.isCID(pathStr)) { return `/ipfs/${new CID(pathStr)}` } else if (isIpfs.path(pathStr)) { return pathStr @@ -38,6 +42,7 @@ const normalizePath = (pathStr) => { } // TODO: do we need both normalizePath and normalizeCidPath? +// TODO: don't forget ipfs-core-utils/src/to-cid-and-path /** * @param {Uint8Array|CID|string} path * @returns {string} @@ -68,47 +73,30 @@ const normalizeCidPath = (path) => { * - /ipfs//link/to/pluto * - multihash Buffer * - * @param {import('./components').DagReader} dag + * @param {import('ipld')} ipld * @param {CID | string} ipfsPath - A CID or IPFS path * @param {Object} [options] - Optional options passed directly to dag.resolve * @returns {Promise} */ -const resolvePath = async function (dag, ipfsPath, options = {}) { - if (isIpfs.cid(ipfsPath)) { - // @ts-ignore - CID|string seems to confuse typedef - return new CID(ipfsPath) - } +const resolvePath = async function (ipld, ipfsPath, options = {}) { + const preload = () => {} + preload.stop = () => {} + preload.start = () => {} - const { - cid, - path - } = toCidAndPath(ipfsPath) + const { cid } = await resolve({ ipld, preload })(ipfsPath, { preload: false }) - if (!path) { - return cid - } - - const result = await dag.resolve(cid, { - ...options, - path - }) - - return result.cid + return cid } /** - * @typedef {import('ipfs-core-types/src/files').InputFile} InputFile - * @typedef {import('ipfs-core-types/src/files').UnixFSFile} UnixFSFile - * @typedef {import('ipfs-core-types/src/files').IPFSEntry} IPFSEntry - * @typedef {import('ipfs-core-types/src').AbortOptions} AbortOptions + * @typedef {import('ipfs-unixfs-exporter').UnixFSEntry} UnixFSEntry * - * @param {InputFile|UnixFSFile} file + * @param {UnixFSEntry} file * @param {Object} [options] * @param {boolean} [options.includeContent] - * @returns {IPFSEntry} */ const mapFile = (file, options = {}) => { - /** @type {IPFSEntry} */ + /** @type {import('ipfs-core-types/src/root').IPFSEntry} */ const output = { cid: file.cid, path: file.path, @@ -118,11 +106,11 @@ const mapFile = (file, options = {}) => { type: 'file' } - if (file.unixfs) { + if (file.type === 'file' || file.type === 'directory') { // @ts-ignore - TS type can't be changed from File to Directory - output.type = file.unixfs.type === 'directory' ? 'dir' : 'file' + output.type = file.type === 'directory' ? 'dir' : 'file' - if (file.unixfs.type === 'file') { + if (file.type === 'file') { output.size = file.unixfs.fileSize() if (options.includeContent) { @@ -132,7 +120,10 @@ const mapFile = (file, options = {}) => { } output.mode = file.unixfs.mode - output.mtime = file.unixfs.mtime + + if (file.unixfs.mtime !== undefined) { + output.mtime = file.unixfs.mtime + } } return output diff --git a/packages/ipfs-core/src/utils/service.js b/packages/ipfs-core/src/utils/service.js index 33473d9e2e..c9b8b50709 100644 --- a/packages/ipfs-core/src/utils/service.js +++ b/packages/ipfs-core/src/utils/service.js @@ -3,6 +3,35 @@ const { NotStartedError, AlreadyStartingError, AlreadyStartedError } = require('../errors') const { withTimeout } = require('../utils') +/** + * @template T + * @typedef {import('ipfs-core-types/src/utils').Await} Await + */ +/** + * @template {(options:any) => any} T + * @typedef {Parameters[0]} Options + */ +/** + * @template {(options:any) => any} T + * @typedef {ReturnType extends ? Promise ? U : ReturnType} State + */ +/** + * Represents service state which can be not started in which case + * it is instance of `Error`. Pending in which case it's promise or + * ready in which case it is the value itself. + * + * @template T + * @typedef {{ status: 'stopped' } + * | { status: 'starting', ready: Await } + * | { status: 'started', value: T } + * | { status: 'stopping', ready: Await } + * } ServiceState + */ + +/** + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ + /** * @template Options, T * @@ -209,31 +238,3 @@ class Service { } } module.exports = Service - -/** - * @template T - * @typedef {import('ipfs-core-types/src/basic').Await} Await - */ -/** - * @template {(options:any) => any} T - * @typedef {Parameters[0]} Options - */ -/** - * @template {(options:any) => any} T - * @typedef {ReturnType extends ? Promise ? U : ReturnType} State - */ -/** - * Represents service state which can be not started in which case - * it is instanceof `Error`. Pending in which case it's promise or - * ready in which case it is the value itself. - * - * @template T - * @typedef {{ status: 'stopped' } - * | { status: 'starting', ready: Await } - * | { status: 'started', value: T } - * | { status: 'stopping', ready: Await } - * } ServiceState - */ -/** - * @typedef {import('../utils').AbortOptions} AbortOptions - */ diff --git a/packages/ipfs-core/test/name.spec.js b/packages/ipfs-core/test/name.spec.js index 0349e94c82..b972915225 100644 --- a/packages/ipfs-core/test/name.spec.js +++ b/packages/ipfs-core/test/name.spec.js @@ -14,6 +14,7 @@ const IpnsRepublisher = require('../src/ipns/republisher') const IpnsResolver = require('../src/ipns/resolver') const OfflineDatastore = require('../src/ipns/routing/offline-datastore') const PubsubDatastore = require('../src/ipns/routing/pubsub-datastore') +const uint8ArrayFromString = require('uint8arrays/from-string') const ipfsRef = '/ipfs/QmPFVLPmp9zv5Z5KUqLhe2EivAGccQW2r7M7jhVJGLZoZU' @@ -151,7 +152,7 @@ describe('name', function () { it('should resolve an inlined public key', async () => { const peerId = await PeerId.create({ keyType: 'ed25519' }) const value = `/ipfs/${peerId.toB58String()}` - const record = await ipns.create(peerId.privKey, value, 1, 10e3) + const record = await ipns.create(peerId.privKey, uint8ArrayFromString(value), 1, 10e3) const routing = { get: sinon.stub().returns(ipns.marshal(record)) diff --git a/packages/ipfs-core/test/utils.js b/packages/ipfs-core/test/utils.js index 2088679545..30b4029530 100644 --- a/packages/ipfs-core/test/utils.js +++ b/packages/ipfs-core/test/utils.js @@ -46,31 +46,31 @@ describe('utils', () => { after(() => cleanup()) it('handles base58 hash format', async () => { - const hash = await utils.resolvePath(ipfs.dag, rootHash) + const hash = await utils.resolvePath(ipfs.ipld, rootHash) expect(hash).to.have.property('bytes').that.deep.equals(rootMultihash) }) it('handles multihash format', async () => { - const hash = await utils.resolvePath(ipfs.dag, aboutMultihash) + const hash = await utils.resolvePath(ipfs.ipld, aboutMultihash) expect(hash).to.have.property('bytes').that.deep.equals(aboutMultihash) }) it('handles ipfs paths format', async function () { this.timeout(200 * 1000) - const hash = await utils.resolvePath(ipfs.dag, aboutPath) + const hash = await utils.resolvePath(ipfs.ipld, aboutPath) expect(hash).to.have.property('bytes').that.deep.equals(aboutMultihash) }) it('should error on invalid hashes', () => { - return expect(utils.resolvePath(ipfs.dag, '/ipfs/asdlkjahsdfkjahsdfd')) + return expect(utils.resolvePath(ipfs.ipld, '/ipfs/asdlkjahsdfkjahsdfd')) .to.eventually.be.rejected() }) it('should error when a link doesn\'t exist', () => { - return expect(utils.resolvePath(ipfs.dag, `${aboutPath}/fusion`)) + return expect(utils.resolvePath(ipfs.ipld, `${aboutPath}/fusion`)) .to.eventually.be.rejected() .and.have.property('message') .that.includes('no link named "fusion" under QmbJCNKXJqVK8CzbjpNFz2YekHwh3CSHpBA86uqYg3sJ8q') diff --git a/packages/ipfs-core/test/utils/mock-preload-node-utils.js b/packages/ipfs-core/test/utils/mock-preload-node-utils.js index 831beff3df..300adf5585 100644 --- a/packages/ipfs-core/test/utils/mock-preload-node-utils.js +++ b/packages/ipfs-core/test/utils/mock-preload-node-utils.js @@ -1,6 +1,7 @@ /* eslint-env browser */ 'use strict' +// @ts-ignore no types const toUri = require('multiaddr-to-uri') const errCode = require('err-code') const HTTP = require('ipfs-utils/src/http') diff --git a/packages/ipfs-core/tsconfig.json b/packages/ipfs-core/tsconfig.json index 6264673867..bf6e95d877 100644 --- a/packages/ipfs-core/tsconfig.json +++ b/packages/ipfs-core/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, @@ -8,6 +8,9 @@ "package.json" ], "references": [ + { + "path": "../ipfs-core-types" + }, { "path": "../ipfs-core-utils" } diff --git a/packages/ipfs-daemon/package.json b/packages/ipfs-daemon/package.json index f4b6a3a1db..178f81c0cf 100644 --- a/packages/ipfs-daemon/package.json +++ b/packages/ipfs-daemon/package.json @@ -11,9 +11,11 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "dist/src/index.d.ts", "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" @@ -24,26 +26,28 @@ "test:node": "aegir test -t node", "coverage": "nyc --reporter=text --reporter=lcov npm run test:node", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check" + "dep-check": "aegir dep-check -i ipfs-core-types", + "build": "aegir build --no-bundle" }, "dependencies": { "debug": "^4.1.1", "dlv": "^1.1.3", "ipfs-core": "^0.5.4", + "ipfs-core-types": "^0.3.1", "ipfs-grpc-server": "^0.2.4", "ipfs-http-client": "^49.0.4", "ipfs-http-gateway": "^0.3.2", "ipfs-http-server": "^0.3.4", - "ipfs-utils": "^6.0.1", + "ipfs-utils": "^6.0.4", "just-safe-set": "^2.1.0", - "libp2p": "^0.30.7", + "libp2p": "^0.30.12", "libp2p-delegated-content-routing": "^0.9.0", "libp2p-delegated-peer-routing": "^0.8.0", "libp2p-webrtc-star": "^0.21.0", "multiaddr": "^8.0.0" }, "devDependencies": { - "aegir": "^31.0.0", + "aegir": "^32.1.0", "node-fetch": "^2.6.1", "ws": "^7.3.1" }, diff --git a/packages/ipfs-daemon/src/index.js b/packages/ipfs-daemon/src/index.js index fba55015bf..f0afad9dfd 100644 --- a/packages/ipfs-daemon/src/index.js +++ b/packages/ipfs-daemon/src/index.js @@ -4,10 +4,13 @@ const log = require('debug')('ipfs:daemon') const get = require('dlv') const set = require('just-safe-set') const Multiaddr = require('multiaddr') +// @ts-ignore - no types const WebRTCStar = require('libp2p-webrtc-star') +// @ts-ignore - no types const DelegatedPeerRouter = require('libp2p-delegated-peer-routing') +// @ts-ignore - no types const DelegatedContentRouter = require('libp2p-delegated-content-routing') -const ipfsHttpClient = require('ipfs-http-client') +const { create: ipfsHttpClient } = require('ipfs-http-client') const IPFS = require('ipfs-core') const HttpApi = require('ipfs-http-server') const HttpGateway = require('ipfs-http-gateway') @@ -16,12 +19,16 @@ const createRepo = require('ipfs-core/src/runtime/repo-nodejs') const { isElectron } = require('ipfs-utils/src/env') class Daemon { + /** + * @param {import('ipfs-core').Options} options + */ constructor (options = {}) { this._options = options if (process.env.IPFS_MONITORING) { // Setup debug metrics collection const prometheusClient = require('prom-client') + // @ts-ignore - no types const prometheusGcStats = require('prometheus-gc-stats') const collectDefaultMetrics = prometheusClient.collectDefaultMetrics // @ts-ignore - timeout isn't in typedefs @@ -32,25 +39,27 @@ class Daemon { /** * Starts the IPFS HTTP server - * - * @returns {Promise} - A promise that resolves to a Daemon instance */ async start () { log('starting') const repo = typeof this._options.repo === 'string' || this._options.repo == null - ? createRepo({ path: this._options.repo, autoMigrate: this._options.repoAutoMigrate, silent: this._options.silent }) + ? createRepo(console.info, { // eslint-disable-line no-console + path: this._options.repo, + autoMigrate: Boolean(this._options.repoAutoMigrate) + }) : this._options.repo // start the daemon const ipfsOpts = Object.assign({}, { start: true, libp2p: getLibp2p }, this._options, { repo }) - const ipfs = this._ipfs = await IPFS.create(ipfsOpts) + this._ipfs = await IPFS.create(ipfsOpts) // start HTTP servers (if API or Gateway is enabled in options) - const httpApi = new HttpApi(ipfs, ipfsOpts) + // @ts-ignore http api expects .libp2p and .ipld properties + const httpApi = new HttpApi(this._ipfs) this._httpApi = await httpApi.start() - const httpGateway = new HttpGateway(ipfs, ipfsOpts) + const httpGateway = new HttpGateway(this._ipfs) this._httpGateway = await httpGateway.start() // for the CLI to know the whereabouts of the API @@ -60,26 +69,28 @@ class Daemon { await repo.apiAddr.set(this._httpApi._apiServers[0].info.ma) } - this._grpcServer = await gRPCServer(ipfs, ipfsOpts) + this._grpcServer = await gRPCServer(this._ipfs) log('started') - return this } async stop () { log('stopping') + await Promise.all([ this._httpApi && this._httpApi.stop(), this._httpGateway && this._httpGateway.stop(), this._grpcServer && this._grpcServer.stop(), - // @ts-ignore - may not have stop if init was false this._ipfs && this._ipfs.stop() ]) + log('stopped') - return this } } +/** + * @type {import('ipfs-core/src/types').Libp2pFactoryFn} + */ function getLibp2p ({ libp2pOptions, options, config, peerId }) { // Attempt to use any of the WebRTC versions available globally let electronWebRTC diff --git a/packages/ipfs-daemon/test/index.spec.js b/packages/ipfs-daemon/test/index.spec.js index f0a283135b..f93eaad43f 100644 --- a/packages/ipfs-daemon/test/index.spec.js +++ b/packages/ipfs-daemon/test/index.spec.js @@ -15,10 +15,7 @@ function createDaemon () { repo: `${os.tmpdir()}/ipfs-test-${Math.random()}`, config: { Addresses: { - Swarm: [ - '/ip4/0.0.0.0/tcp/0', - '/ip4/127.0.0.1/tcp/0/ws' - ], + Swarm: [], API: '/ip4/127.0.0.1/tcp/0', Gateway: '/ip4/127.0.0.1/tcp/0', RPC: '/ip4/127.0.0.1/tcp/0' diff --git a/packages/ipfs-daemon/tsconfig.json b/packages/ipfs-daemon/tsconfig.json index 2111e28905..eb2e789b86 100644 --- a/packages/ipfs-daemon/tsconfig.json +++ b/packages/ipfs-daemon/tsconfig.json @@ -1,16 +1,18 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" ], "references": [ { "path": "../ipfs-core" }, + { + "path": "../ipfs-core-types" + }, { "path": "../ipfs-core-utils" }, diff --git a/packages/ipfs-grpc-client/.aegir.js b/packages/ipfs-grpc-client/.aegir.js index 13212abe94..9549fd1c7a 100644 --- a/packages/ipfs-grpc-client/.aegir.js +++ b/packages/ipfs-grpc-client/.aegir.js @@ -3,6 +3,6 @@ /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '48kB' + bundlesizeMax: '65KB' } } diff --git a/packages/ipfs-grpc-client/README.md b/packages/ipfs-grpc-client/README.md index 2de71d5b73..f379dd7030 100644 --- a/packages/ipfs-grpc-client/README.md +++ b/packages/ipfs-grpc-client/README.md @@ -22,7 +22,7 @@ $ npm install ipfs-grpc-client ## API -### `createClient([options])` +### `create([options])` ### Parameters @@ -46,9 +46,9 @@ An optional object which may have the following keys: ### Example ```js -const createClient = require('ipfs-gprc-client') +const { create } = require('ipfs-gprc-client') -const client = createClient({ +const client = create({ url: '/ipv4/127.0.0.1/tcp/1234/ws' }) diff --git a/packages/ipfs-grpc-client/package.json b/packages/ipfs-grpc-client/package.json index 20ccec3225..c227bbcda6 100644 --- a/packages/ipfs-grpc-client/package.json +++ b/packages/ipfs-grpc-client/package.json @@ -11,50 +11,45 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "dist/src/index.d.ts", "browser": { "./src/grpc/transport.js": "./src/grpc/transport.browser.js" }, - "typesVersions": { - "*": { - "*": [ - "dist/*", - "dist/*/index" - ] - } - }, "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { - "prepare": "npm run build", "build": "aegir build", "test": "aegir test", "lint": "aegir lint", "coverage": "npx nyc -r html npm run test:node -- --bail", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i aegir -i rimraf -i ipfs-grpc-protocol" + "dep-check": "aegir dep-check -i aegir -i rimraf -i ipfs-grpc-protocol -i ipfs-core-types" }, "dependencies": { "@improbable-eng/grpc-web": "^0.13.0", "change-case": "^4.1.1", "cids": "^1.1.5", "debug": "^4.1.1", - "err-code": "^2.0.3", + "err-code": "^3.0.1", + "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-grpc-protocol": "^0.2.0", + "ipfs-unixfs": "^4.0.1", "it-first": "^1.0.4", "it-pushable": "^1.4.0", "multiaddr": "^8.0.0", "protobufjs": "^6.10.2", - "wherearewe": "0.0.1", + "wherearewe": "1.0.0", "ws": "^7.3.1" }, "devDependencies": { - "aegir": "^31.0.0", + "aegir": "^32.1.0", "it-all": "^1.0.4", "rimraf": "^3.0.2", "sinon": "^9.0.3" diff --git a/packages/ipfs-grpc-client/src/core-api/add-all.js b/packages/ipfs-grpc-client/src/core-api/add-all.js index a27d14a3fc..981770069d 100644 --- a/packages/ipfs-grpc-client/src/core-api/add-all.js +++ b/packages/ipfs-grpc-client/src/core-api/add-all.js @@ -5,7 +5,19 @@ const CID = require('cids') const bidiToDuplex = require('../utils/bidi-to-duplex') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +/** + * @param {number} index + * @param {import('it-pushable').Pushable} sink + * @param {string} path + * @param {number} [mode] + * @param {import('ipfs-unixfs').Mtime} [mtime] + */ function sendDirectory (index, sink, path, mode, mtime) { + /** + * TODO: type properly after https://github.com/ipfs/js-ipfs/issues/3594 + * + * @type {Record} + */ const message = { index, type: 'DIRECTORY', @@ -24,8 +36,25 @@ function sendDirectory (index, sink, path, mode, mtime) { sink.push(message) } +/** + * @param {number} index + * @param {import('it-pushable').Pushable} sink + * @param {AsyncIterable | Iterable | Uint8Array} content + * @param {string} [path] + * @param {number} [mode] + * @param {import('ipfs-unixfs').Mtime} [mtime] + */ async function sendFile (index, sink, content, path, mode, mtime) { + if (content instanceof Uint8Array) { + content = [content] + } + for await (const buf of content) { + /** + * TODO: type properly after https://github.com/ipfs/js-ipfs/issues/3594 + * + * @type {Record} + */ const message = { index, type: 'FILE', @@ -56,6 +85,10 @@ async function sendFile (index, sink, content, path, mode, mtime) { sink.push(message) } +/** + * @param {import('ipfs-core-types/src/utils').ImportSource} stream + * @param {import('it-pushable').Pushable} sink + */ async function sendFiles (stream, sink) { let i = 1 @@ -65,13 +98,23 @@ async function sendFiles (stream, sink) { if (content) { await sendFile(index, sink, content, path, mode, mtime) - } else { + } else if (path) { sendDirectory(index, sink, path, mode, mtime) + } else { + throw new Error('Must pass path or content or both') } } } -module.exports = function grpcAddAll (grpc, service, opts = {}) { +/** + * @param {import('@improbable-eng/grpc-web').grpc} grpc + * @param {*} service + * @param {import('../types').Options} opts + */ +module.exports = function grpcAddAll (grpc, service, opts) { + /** + * @type {import('ipfs-core-types/src/root').API["addAll"]} + */ async function * addAll (stream, options = {}) { const { source, diff --git a/packages/ipfs-grpc-client/src/core-api/files/ls.js b/packages/ipfs-grpc-client/src/core-api/files/ls.js index 7a7a9945c2..cd97fc7553 100644 --- a/packages/ipfs-grpc-client/src/core-api/files/ls.js +++ b/packages/ipfs-grpc-client/src/core-api/files/ls.js @@ -4,7 +4,15 @@ const CID = require('cids') const serverStreamToIterator = require('../../utils/server-stream-to-iterator') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') -module.exports = function grpcMfsLs (grpc, service, opts = {}) { +/** + * @param {import('@improbable-eng/grpc-web').grpc} grpc + * @param {*} service + * @param {import('../../types').Options} opts + */ +module.exports = function grpcMfsLs (grpc, service, opts) { + /** + * @type {import('ipfs-core-types/src/files').API["ls"]} + */ async function * mfsLs (path, options = {}) { const request = { path diff --git a/packages/ipfs-grpc-client/src/core-api/files/write.js b/packages/ipfs-grpc-client/src/core-api/files/write.js index f9c686c947..9a8edbedf5 100644 --- a/packages/ipfs-grpc-client/src/core-api/files/write.js +++ b/packages/ipfs-grpc-client/src/core-api/files/write.js @@ -2,43 +2,57 @@ const clientStreamToPromise = require('../../utils/client-stream-to-promise') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') -const normaliseInput = require('ipfs-core-utils/src/files/normalise-input') -const { mtimeToObject, modeToNumber } = require('ipfs-core-utils/src/files/normalise-input/utils') - +const normaliseContent = require('ipfs-core-utils/src/files/normalise-input/normalise-content') +const { + parseMtime, + parseMode +} = require('ipfs-unixfs') + +/** + * @param {string} path + * @param {*} content + */ async function * stream (path, content) { - for await (const { content: bufs } of normaliseInput(content)) { - if (!bufs) { - return - } - - for await (const content of bufs) { - yield { path, content } - } + for await (const buf of normaliseContent(content)) { + yield { path, content: buf } } } -module.exports = function grpcMfsWrite (grpc, service, opts = {}) { +/** + * @param {import('@improbable-eng/grpc-web').grpc} grpc + * @param {*} service + * @param {import('../../types').Options} opts + */ +module.exports = function grpcMfsWrite (grpc, service, opts) { + /** + * @type {import('ipfs-core-types/src/files').API["write"]} + */ async function mfsWrite (path, content, options = {}) { - const mtime = mtimeToObject(options.mtime) + /** + * TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 + * + * @type {Record} + */ + const metadata = { + ...options + } + const mtime = parseMtime(options.mtime) if (mtime != null) { - options = { - ...options, - mtime: mtime.secs, - mtimeNsecs: mtime.nsecs - } + metadata.mtime = mtime.secs + metadata.mtimeNsecs = mtime.nsecs } - const mode = modeToNumber(options.mode) + const mode = parseMode(options.mode) if (mode != null) { - options.mode = mode + metadata.mode = mode } await clientStreamToPromise(grpc, service, stream(path, content), { host: opts.url, debug: Boolean(process.env.DEBUG), - metadata: options, + metadata, agent: opts.agent }) } diff --git a/packages/ipfs-grpc-client/src/core-api/id.js b/packages/ipfs-grpc-client/src/core-api/id.js index b3af2a623d..185bbd9d31 100644 --- a/packages/ipfs-grpc-client/src/core-api/id.js +++ b/packages/ipfs-grpc-client/src/core-api/id.js @@ -5,7 +5,15 @@ const toHeaders = require('../utils/to-headers') const unaryToPromise = require('../utils/unary-to-promise') const multiaddr = require('multiaddr') -module.exports = function grpcId (grpc, service, opts = {}) { +/** + * @param {import('@improbable-eng/grpc-web').grpc} grpc + * @param {*} service + * @param {import('../types').Options} opts + */ +module.exports = function grpcId (grpc, service, opts) { + /** + * @type {import('ipfs-core-types/src/root').API["id"]} + */ async function id (options = {}) { const request = {} diff --git a/packages/ipfs-grpc-client/src/grpc/transport.node.js b/packages/ipfs-grpc-client/src/grpc/transport.node.js index 4349866f94..2023db6028 100644 --- a/packages/ipfs-grpc-client/src/grpc/transport.node.js +++ b/packages/ipfs-grpc-client/src/grpc/transport.node.js @@ -47,13 +47,18 @@ function WebsocketTransport (options) { function websocketRequest (options) { const webSocketAddress = constructWebSocketAddress(options.url) + /** @type {Array} */ let sendQueue = [] + /** @type {WebSocket} */ let ws + /** + * @param {number | Uint8Array} toSend + */ function sendToWebsocket (toSend) { if (toSend === WebsocketSignal.FINISH_SEND) { ws.send(finishSendFrame) - } else { + } else if (toSend instanceof Uint8Array) { const byteArray = toSend const c = new Int8Array(byteArray.byteLength + 1) c.set(new Uint8Array([0])) @@ -64,6 +69,9 @@ function websocketRequest (options) { } return { + /** + * @param {Uint8Array} msgBytes + */ sendMessage: (msgBytes) => { if (!ws || ws.readyState === ws.CONNECTING) { sendQueue.push(msgBytes) @@ -78,6 +86,9 @@ function websocketRequest (options) { sendToWebsocket(WebsocketSignal.FINISH_SEND) } }, + /** + * @param {import('@improbable-eng/grpc-web').grpc.Metadata} metadata + */ start: (metadata) => { ws = new WebSocket(webSocketAddress, ['grpc-websockets'], options) ws.binaryType = 'arraybuffer' @@ -101,7 +112,12 @@ function websocketRequest (options) { } ws.onmessage = function (e) { - options.onChunk(new Uint8Array(e.data, 0, e.data.byteLength)) + if (e.data instanceof ArrayBuffer) { + options.onChunk(new Uint8Array(e.data, 0, e.data.byteLength)) + } else { + options.onEnd(new Error(`Incorrect message type received - expected ArrayBuffer, got ${typeof e.data}`)) + ws.close() + } } }, cancel: () => { @@ -110,6 +126,9 @@ function websocketRequest (options) { } } +/** + * @param {string} url + */ function constructWebSocketAddress (url) { if (url.startsWith('wss://') || url.startsWith('ws://')) { return url @@ -122,6 +141,11 @@ function constructWebSocketAddress (url) { throw new Error('Websocket transport url must start with ws:// or wss:// or http:// or https://') } +/** + * TODO: type properly after https://github.com/ipfs/js-ipfs/issues/3594 + * + * @param {import('@improbable-eng/grpc-web').grpc.Metadata} headers + */ function headersToBytes (headers) { let asString = '' headers.forEach((key, values) => { @@ -130,6 +154,9 @@ function headersToBytes (headers) { return encodeASCII(asString) } +/** + * @param {string} input + */ function encodeASCII (input) { const encoded = new Uint8Array(input.length) for (let i = 0; i !== input.length; ++i) { @@ -142,8 +169,14 @@ function encodeASCII (input) { return encoded } +/** + * @param {number} char + */ const isAllowedControlChars = (char) => char === 0x9 || char === 0xa || char === 0xd +/** + * @param {number} val + */ function isValidHeaderAscii (val) { return isAllowedControlChars(val) || (val >= 0x20 && val <= 0x7e) } diff --git a/packages/ipfs-grpc-client/src/index.js b/packages/ipfs-grpc-client/src/index.js index ecfdffec57..f35b76989d 100644 --- a/packages/ipfs-grpc-client/src/index.js +++ b/packages/ipfs-grpc-client/src/index.js @@ -4,13 +4,21 @@ const toUrlString = require('ipfs-core-utils/src/to-url-string') const loadServices = require('./utils/load-services') const { grpc } = require('@improbable-eng/grpc-web') +/** + * @typedef {import('./types').Options} Options + */ + const service = loadServices() +/** @type {Record} */ const protocols = { 'ws://': 'http://', 'wss://': 'https://' } +/** + * @param {{ url: string }} opts + */ function normaliseUrls (opts) { Object.keys(protocols).forEach(protocol => { if (opts.url.startsWith(protocol)) { @@ -20,29 +28,33 @@ function normaliseUrls (opts) { } /** - * @typedef {import('http').Agent} HttpAgent - * @typedef {import('https').Agent} HttpsAgent - * - * @typedef {Object} Options - * @property {string|URL|import('multiaddr')} url - The URL to connect to as a URL or Multiaddr - * @property {HttpAgent|HttpsAgent} [agent] - http.Agent used to control HTTP client behaviour (node.js only) - * * @param {Options} [opts] */ -module.exports = function createClient (opts = { url: '' }) { - opts.url = toUrlString(opts.url) +function create (opts = { url: '' }) { + const options = { + ...opts, + url: toUrlString(opts.url) + } // @improbable-eng/grpc-web requires http:// protocol URLs, not ws:// - normaliseUrls(opts) + normaliseUrls(options) const client = { - addAll: require('./core-api/add-all')(grpc, service.Root.add, opts), - id: require('./core-api/id')(grpc, service.Root.id, opts), + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 + addAll: require('./core-api/add-all')(grpc, service.Root.add, options), + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 + id: require('./core-api/id')(grpc, service.Root.id, options), files: { - ls: require('./core-api/files/ls')(grpc, service.MFS.ls, opts), - write: require('./core-api/files/write')(grpc, service.MFS.write, opts) + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 + ls: require('./core-api/files/ls')(grpc, service.MFS.ls, options), + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 + write: require('./core-api/files/write')(grpc, service.MFS.write, options) } } return client } + +module.exports = { + create +} diff --git a/packages/ipfs-grpc-client/src/types.d.ts b/packages/ipfs-grpc-client/src/types.d.ts new file mode 100644 index 0000000000..866850b41d --- /dev/null +++ b/packages/ipfs-grpc-client/src/types.d.ts @@ -0,0 +1,15 @@ +import { agent as HttpAgent } from 'http' +import { agent as HttpsAgent } from 'https' +import Multiaddr from 'multiaddr' + +export interface Options { + url: string | URL | Multiaddr + agent?: HttpAgent | HttpsAgent +} + +export interface RPCOptions { + host: string | URL | Multiaddr + debug?: boolean + metadata: Metadata + agent?: HttpAgent | HttpsAgent +} diff --git a/packages/ipfs-grpc-client/src/utils/bidi-to-duplex.js b/packages/ipfs-grpc-client/src/utils/bidi-to-duplex.js index e4146a83df..c36a64f5de 100644 --- a/packages/ipfs-grpc-client/src/utils/bidi-to-duplex.js +++ b/packages/ipfs-grpc-client/src/utils/bidi-to-duplex.js @@ -2,14 +2,15 @@ const pushable = require('it-pushable') const errCode = require('err-code') +const toUrlString = require('ipfs-core-utils/src/to-url-string') const toHeaders = require('./to-headers') const transport = require('../grpc/transport') /** - * @typedef {import('http').Agent} HttpAgent - * @typedef {import('https').Agent} HttpsAgent + * @param {*} service + * @param {import('@improbable-eng/grpc-web').grpc.Client} client + * @param {AsyncIterable} source */ - async function sendMessages (service, client, source) { for await (const obj of source) { client.send({ @@ -23,24 +24,18 @@ async function sendMessages (service, client, source) { * for the caller to write client messages into and a source to read * server messages from. * - * @param {object} grpc - an @improbable-eng/grpc-web instance - * @param {object} service - an @improbable-eng/grpc-web service - * @param {object} options - RPC options - * @param {string} options.host - The remote host - * @param {boolean} [options.debug] - Whether to print debug messages - * @param {object} [options.metadata] - Metadata sent as headers - * @param {HttpAgent|HttpsAgent} [options.agent] - http.Agent used to control HTTP client behaviour (node.js only) - * @returns {{ source: AsyncIterable, sink: { push: Function, end: Function } }} + * @param {import('@improbable-eng/grpc-web').grpc} grpc - an @improbable-eng/grpc-web instance + * @param {*} service - an @improbable-eng/grpc-web service + * @param {import('../types').RPCOptions} options + * @returns {{ source: AsyncIterable, sink: import('it-pushable').Pushable }} **/ module.exports = function bidiToDuplex (grpc, service, options) { - // @ts-ignore const source = pushable() - - // @ts-ignore const sink = pushable() const client = grpc.client(service, { ...options, + host: toUrlString(options.host), transport: transport({ agent: options.agent }) @@ -58,7 +53,10 @@ module.exports = function bidiToDuplex (grpc, service, options) { status }) - err.stack = trailers.get('grpc-stack')[0] || error.stack + let stack = trailers.get('grpc-stack')[0] + stack = stack && stack.replace(/\\n/g, '\n') + + err.stack = stack || error.stack } sink.end(err) diff --git a/packages/ipfs-grpc-client/src/utils/client-stream-to-promise.js b/packages/ipfs-grpc-client/src/utils/client-stream-to-promise.js index 5b3d2725c2..119a31d405 100644 --- a/packages/ipfs-grpc-client/src/utils/client-stream-to-promise.js +++ b/packages/ipfs-grpc-client/src/utils/client-stream-to-promise.js @@ -13,16 +13,12 @@ const bidiToDuplex = require('./bidi-to-duplex') * function takes a source that can emit multiple messages and * returns a promise that resolves to the server response. * - * @param {object} grpc - an @improbable-eng/grpc-web instance - * @param {object} service - an @improbable-eng/grpc-web service - * @param {AsyncIterable} source - a source of objects to send - * @param {object} options - RPC options - * @param {string} options.host - The remote host - * @param {boolean} [options.debug] - Whether to print debug messages - * @param {object} [options.metadata] - Metadata sent as headers - * @param {HttpAgent|HttpsAgent} [options.agent] - http.Agent used to control HTTP client behaviour (node.js only) - * @returns {Promise} - A promise that resolves to a response object - **/ + * @param {import('@improbable-eng/grpc-web').grpc} grpc - an @improbable-eng/grpc-web instance + * @param {*} service - an @improbable-eng/grpc-web service + * @param {AsyncIterable} source - a source of objects to send + * @param {import('../types').RPCOptions} options + * @returns {Promise} - A promise that resolves to a response object + */ module.exports = async function clientStreamToPromise (grpc, service, source, options) { const { source: serverSource, sink diff --git a/packages/ipfs-grpc-client/src/utils/load-services.js b/packages/ipfs-grpc-client/src/utils/load-services.js index d929136ad6..5da8b1213c 100644 --- a/packages/ipfs-grpc-client/src/utils/load-services.js +++ b/packages/ipfs-grpc-client/src/utils/load-services.js @@ -17,11 +17,10 @@ const CONVERSION_OPTS = { * Converts protobufjs service definitions into the format expected * by @improbable-eng/grpc-web. This is to let us use the same * service definition on both the server and the client. - * - * @returns {object} */ module.exports = function loadServices () { const root = protobuf.Root.fromJSON(protocol) + /** @type {Record} */ const output = {} Object @@ -32,6 +31,7 @@ module.exports = function loadServices () { // @ts-ignore .map(key => root.nested.ipfs[key]) .forEach(service => { + /** @type {Record} */ const serviceDef = {} output[service.name] = serviceDef @@ -48,10 +48,16 @@ module.exports = function loadServices () { requestStream: method.requestStream, responseStream: method.responseStream, requestType: { + /** + * @param {any} obj + */ serializeBinary: (obj) => { const message = method.resolvedRequestType.fromObject(obj) return method.resolvedRequestType.encode(message).finish() }, + /** + * @param {Uint8Array} buf + */ deserializeBinary: (buf) => { const message = method.resolvedRequestType.decode(buf) const obj = method.resolvedRequestType.toObject(message, CONVERSION_OPTS) @@ -66,10 +72,16 @@ module.exports = function loadServices () { } }, responseType: { + /** + * @param {any} obj + */ serializeBinary: (obj) => { const message = method.resolvedResponseType.fromObject(obj) return method.resolvedResponseType.encode(message).finish() }, + /** + * @param {Uint8Array} buf + */ deserializeBinary: (buf) => { const message = method.resolvedResponseType.decode(buf) const obj = method.resolvedResponseType.toObject(message, CONVERSION_OPTS) diff --git a/packages/ipfs-grpc-client/src/utils/server-stream-to-iterator.js b/packages/ipfs-grpc-client/src/utils/server-stream-to-iterator.js index 228b6032af..d180dd7120 100644 --- a/packages/ipfs-grpc-client/src/utils/server-stream-to-iterator.js +++ b/packages/ipfs-grpc-client/src/utils/server-stream-to-iterator.js @@ -12,15 +12,11 @@ const bidiToDuplex = require('./bidi-to-duplex') * function accepts a client message and returns a source * from which multiple server messages can be read. * - * @param {object} grpc - an @improbable-eng/grpc-web instance - * @param {object} service - an @improbable-eng/grpc-web service + * @param {import('@improbable-eng/grpc-web').grpc} grpc - an @improbable-eng/grpc-web instance + * @param {*} service - an @improbable-eng/grpc-web service * @param {object} request - a request object - * @param {object} options - RPC options - * @param {string} options.host - The remote host - * @param {boolean} [options.debug] - Whether to print debug messages - * @param {object} [options.metadata] - Metadata sent as headers - * @param {HttpAgent|HttpsAgent} [options.agent] - http.Agent used to control HTTP client behaviour (node.js only) - * @returns {AsyncIterable} + * @param {import('../types').RPCOptions} options - RPC options + * @returns {AsyncIterable} **/ module.exports = function serverStreamToIterator (grpc, service, request, options) { const { diff --git a/packages/ipfs-grpc-client/src/utils/to-headers.js b/packages/ipfs-grpc-client/src/utils/to-headers.js index 9cffb3c766..db58903681 100644 --- a/packages/ipfs-grpc-client/src/utils/to-headers.js +++ b/packages/ipfs-grpc-client/src/utils/to-headers.js @@ -3,10 +3,10 @@ const { paramCase } = require('change-case') /** - * @param {object} [object] - key/value pairs to turn into HTTP headers - * @returns {object} - HTTP headers - **/ -module.exports = (object) => { + * @param {Record} [object] - key/value pairs to turn into HTTP headers + */ +module.exports = (object = {}) => { + /** @type {Record} */ const output = {} Object.keys(object || {}).forEach(key => { @@ -14,7 +14,7 @@ module.exports = (object) => { return } - output[paramCase(key)] = object[key] + output[paramCase(key)] = object[key].toString() }) return output diff --git a/packages/ipfs-grpc-client/src/utils/unary-to-promise.js b/packages/ipfs-grpc-client/src/utils/unary-to-promise.js index e57537aa77..cf0c6643a5 100644 --- a/packages/ipfs-grpc-client/src/utils/unary-to-promise.js +++ b/packages/ipfs-grpc-client/src/utils/unary-to-promise.js @@ -13,15 +13,11 @@ const bidiToDuplex = require('./bidi-to-duplex') * takes a client message and returns a promise that resolves * to the server response. * - * @param {object} grpc - an @improbable-eng/grpc-web instance - * @param {object} service - an @improbable-eng/grpc-web service - * @param {object} request - a request object - * @param {object} options - RPC options - * @param {string} options.host - The remote host - * @param {boolean} [options.debug] - Whether to print debug messages - * @param {object} [options.metadata] - Metadata sent as headers - * @param {HttpAgent|HttpsAgent} [options.agent] - http.Agent used to control HTTP client behaviour (node.js only) - * @returns {Promise} - A promise that resolves to a response object + * @param {import('@improbable-eng/grpc-web').grpc} grpc - an @improbable-eng/grpc-web instance + * @param {*} service - an @improbable-eng/grpc-web service + * @param {any} request - a request object + * @param {import('../types').RPCOptions} options - RPC options + * @returns {Promise} - A promise that resolves to a response object **/ module.exports = function unaryToPromise (grpc, service, request, options) { const { diff --git a/packages/ipfs-grpc-client/test/agent.js b/packages/ipfs-grpc-client/test/agent.js index 4553ef5c89..01a256b0fb 100644 --- a/packages/ipfs-grpc-client/test/agent.js +++ b/packages/ipfs-grpc-client/test/agent.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict' -const grpcClient = require('../src') +const { create } = require('../src') const WebSocket = require('ws') function startServer () { @@ -30,7 +30,7 @@ describe('agent', function () { try { await new Promise((resolve) => { - const ipfs = grpcClient({ + const ipfs = create({ url: `http://localhost:${server.port}`, agent: { addRequest () { diff --git a/packages/ipfs-grpc-client/test/utils.spec.js b/packages/ipfs-grpc-client/test/utils.spec.js index 6bdf5ddfba..debf9b962a 100644 --- a/packages/ipfs-grpc-client/test/utils.spec.js +++ b/packages/ipfs-grpc-client/test/utils.spec.js @@ -31,7 +31,7 @@ describe('utils', () => { source } = bidiToDuplex(grpc, service, options) - expect(client.start.calledWith(options.metadata)).to.be.true() + expect(client.start.calledWith(toHeaders(options.metadata))).to.be.true() client.onMessage.getCall(0).args[0]('hello') client.onMessage.getCall(0).args[0]('world') @@ -62,7 +62,7 @@ describe('utils', () => { source } = bidiToDuplex(grpc, service, options) - expect(client.start.calledWith(options.metadata)).to.be.true() + expect(client.start.calledWith(toHeaders(options.metadata))).to.be.true() client.onEnd.getCall(0).args[0](1, 'Erp!', { get: () => [] }) @@ -79,7 +79,7 @@ describe('utils', () => { const output = toHeaders(input) expect(output.propSimple).to.be.undefined() - expect(output['prop-simple']).to.equal(input.propSimple) + expect(output['prop-simple']).to.deep.equal(input.propSimple) }) it('should remove function fields', () => { @@ -90,7 +90,7 @@ describe('utils', () => { const output = toHeaders(input) expect(output.funcProp).to.be.undefined() - expect(output['func-prop']).to.be.undefined() + expect(output.funcProp).to.be.undefined() }) }) }) diff --git a/packages/ipfs-grpc-client/tsconfig.json b/packages/ipfs-grpc-client/tsconfig.json index a42a1aac5d..3a4cc05655 100644 --- a/packages/ipfs-grpc-client/tsconfig.json +++ b/packages/ipfs-grpc-client/tsconfig.json @@ -1,15 +1,14 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" ], "references": [ { - "path": "../ipfs-core" + "path": "../ipfs-core-types" }, { "path": "../ipfs-core-utils" diff --git a/packages/ipfs-grpc-protocol/package.json b/packages/ipfs-grpc-protocol/package.json index 20ad908854..961a11a199 100644 --- a/packages/ipfs-grpc-protocol/package.json +++ b/packages/ipfs-grpc-protocol/package.json @@ -21,7 +21,8 @@ "scripts": { "test": "echo 'No tests here'", "clean": "rimraf ./dist", - "prepare": "npm run clean && mkdirp ./dist && pbjs ./src/*.proto -t json -o ./dist/ipfs.json" + "prepare": "npm run build", + "build": "npm run clean && mkdirp ./dist && pbjs ./src/*.proto -t json -o ./dist/ipfs.json" }, "devDependencies": { "mkdirp": "^1.0.4", diff --git a/packages/ipfs-grpc-server/package.json b/packages/ipfs-grpc-server/package.json index 22373b8bd1..506ffd055e 100644 --- a/packages/ipfs-grpc-server/package.json +++ b/packages/ipfs-grpc-server/package.json @@ -11,18 +11,12 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "dist/src/index.d.ts", "browser": {}, - "typesVersions": { - "*": { - "*": [ - "dist/*", - "dist/*/index" - ] - } - }, "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" @@ -32,24 +26,28 @@ "test": "aegir test -t node", "coverage": "nyc --reporter=text --reporter=lcov npm run test:node", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf" + "dep-check": "aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types", + "build": "aegir build --no-bundle" }, "dependencies": { "@grpc/grpc-js": "^1.1.8", "change-case": "^4.1.1", "coercer": "^1.1.2", "debug": "^4.1.1", + "ipfs-core-types": "^0.3.1", "ipfs-grpc-protocol": "^0.2.0", "it-first": "^1.0.4", "it-map": "^1.0.4", "it-peekable": "^1.0.1", "it-pipe": "^1.1.0", "it-pushable": "^1.4.0", + "multiaddr": "^8.0.0", "protobufjs": "^6.10.2", "ws": "^7.3.1" }, "devDependencies": { - "aegir": "^31.0.0", + "@types/ws": "^7.4.0", + "aegir": "^32.1.0", "ipfs-core": "^0.5.4", "it-all": "^1.0.4", "it-drain": "^1.0.3", diff --git a/packages/ipfs-grpc-server/src/endpoints/add.js b/packages/ipfs-grpc-server/src/endpoints/add.js index c31a8d3b1a..e3fe5b2f54 100644 --- a/packages/ipfs-grpc-server/src/endpoints/add.js +++ b/packages/ipfs-grpc-server/src/endpoints/add.js @@ -1,11 +1,19 @@ 'use strict' -// @ts-ignore const pushable = require('it-pushable') const { pipe } = require('it-pipe') const encodeMtime = require('../utils/encode-mtime') +/** + * @param {import('ipfs-core-types').IPFS} ipfs + * @param {import('../types').Options} options + */ module.exports = function grpcAdd (ipfs, options = {}) { + /** + * TODO: Fill out input/output types after https://github.com/ipfs/js-ipfs/issues/3594 + * + * @type {import('../types').BidirectionalStreamingEndpoint} + */ async function add (source, sink, metadata) { const opts = { ...metadata, @@ -20,7 +28,6 @@ module.exports = function grpcAdd (ipfs, options = {}) { await pipe( async function * toInput () { - // @ts-ignore const fileInputStream = pushable() setTimeout(async () => { diff --git a/packages/ipfs-grpc-server/src/endpoints/id.js b/packages/ipfs-grpc-server/src/endpoints/id.js index 8bdd210fce..c12a9214b5 100644 --- a/packages/ipfs-grpc-server/src/endpoints/id.js +++ b/packages/ipfs-grpc-server/src/endpoints/id.js @@ -2,7 +2,16 @@ const { callbackify } = require('util') +/** + * @param {import('ipfs-core-types').IPFS} ipfs + * @param {import('../types').Options} options + */ module.exports = function grpcId (ipfs, options = {}) { + /** + * TODO: Fill out input/output types after https://github.com/ipfs/js-ipfs/issues/3594 + * + * @type {import('../types').UnaryEndpoint} + */ function id (request, metadata) { const opts = { ...request, diff --git a/packages/ipfs-grpc-server/src/endpoints/mfs/ls.js b/packages/ipfs-grpc-server/src/endpoints/mfs/ls.js index 1432553d93..70d52b50a6 100644 --- a/packages/ipfs-grpc-server/src/endpoints/mfs/ls.js +++ b/packages/ipfs-grpc-server/src/endpoints/mfs/ls.js @@ -2,7 +2,16 @@ const encodeMtime = require('../../utils/encode-mtime') +/** + * @param {import('ipfs-core-types').IPFS} ipfs + * @param {import('../../types').Options} options + */ module.exports = function grpcMfsLs (ipfs, options = {}) { + /** + * TODO: Fill out input/output types after https://github.com/ipfs/js-ipfs/issues/3594 + * + * @type {import('../../types').ServerStreamingEndpoint} + */ async function mfsLs (request, sink, metadata) { const opts = { ...metadata diff --git a/packages/ipfs-grpc-server/src/endpoints/mfs/write.js b/packages/ipfs-grpc-server/src/endpoints/mfs/write.js index 92eb61b600..185c8e838c 100644 --- a/packages/ipfs-grpc-server/src/endpoints/mfs/write.js +++ b/packages/ipfs-grpc-server/src/endpoints/mfs/write.js @@ -4,7 +4,16 @@ const peekable = require('it-peekable') const map = require('it-map') const { callbackify } = require('util') +/** + * @param {import('ipfs-core-types').IPFS} ipfs + * @param {import('../../types').Options} options + */ module.exports = function grpcMfsWrite (ipfs, options = {}) { + /** + * TODO: Fill out input/output types after https://github.com/ipfs/js-ipfs/issues/3594 + * + * @type {import('../../types').ClientStreamingEndpoint} + */ async function mfsWrite (source, metadata) { const opts = { ...metadata @@ -22,13 +31,11 @@ module.exports = function grpcMfsWrite (ipfs, options = {}) { const result = await content.peek() const { value: { - // @ts-ignore path } } = result content.push(result.value) - // @ts-ignore await ipfs.files.write(path, map(content, ({ content }) => content), opts) return {} diff --git a/packages/ipfs-grpc-server/src/index.js b/packages/ipfs-grpc-server/src/index.js index 1a98a79950..05b64821e7 100644 --- a/packages/ipfs-grpc-server/src/index.js +++ b/packages/ipfs-grpc-server/src/index.js @@ -11,18 +11,24 @@ const { MFS } = loadServices() +/** + * @param {import('ipfs-core-types').IPFS} ipfs + * @param {import('./types').Options} options + */ module.exports = async function createServer (ipfs, options = {}) { options = options || {} const server = new grpc.Server() server.addService(Root, { + // @ts-ignore - types differ because we only invoke via websockets - https://github.com/ipfs/js-ipfs/issues/3594 add: require('./endpoints/add')(ipfs, options), - // @ts-ignore + // @ts-ignore - types differ because we only invoke via websockets - https://github.com/ipfs/js-ipfs/issues/3594 id: require('./endpoints/id')(ipfs, options) }) server.addService(MFS, { + // @ts-ignore - types differ because we only invoke via websockets - https://github.com/ipfs/js-ipfs/issues/3594 ls: require('./endpoints/mfs/ls')(ipfs, options), - // @ts-ignore + // @ts-ignore - types differ because we only invoke via websockets - https://github.com/ipfs/js-ipfs/issues/3594 write: require('./endpoints/mfs/write')(ipfs, options) }) @@ -31,7 +37,7 @@ module.exports = async function createServer (ipfs, options = {}) { socket.on('error', (error) => debug(error)) socket.on('data', async ({ path, metadata, channel }) => { - // @ts-ignore + // @ts-ignore - types differ because we only invoke via websockets - https://github.com/ipfs/js-ipfs/issues/3594 const handler = server.handlers.get(path) if (!handler) { @@ -44,6 +50,7 @@ module.exports = async function createServer (ipfs, options = {}) { switch (handler.type) { case 'bidi': handler.func(channel.source, channel.sink, metadata) + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 .catch(err => { channel.end(err) }) @@ -58,6 +65,7 @@ module.exports = async function createServer (ipfs, options = {}) { break case 'unary': + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 handler.func(await first(channel.source), metadata, (err, value, metadata, flags) => { if (err) { return channel.end(err) @@ -73,6 +81,7 @@ module.exports = async function createServer (ipfs, options = {}) { }) break case 'clientStream': + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 handler.func(channel.source, metadata, (err, value, metadata, flags) => { if (err) { return channel.end(err) @@ -88,7 +97,9 @@ module.exports = async function createServer (ipfs, options = {}) { }) break case 'serverStream': + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 handler.func(await first(channel.source), channel.sink, metadata) + // @ts-ignore - TODO: fix after https://github.com/ipfs/js-ipfs/issues/3594 .catch(err => { channel.end(err) }) diff --git a/packages/ipfs-grpc-server/src/types.d.ts b/packages/ipfs-grpc-server/src/types.d.ts new file mode 100644 index 0000000000..413f60da84 --- /dev/null +++ b/packages/ipfs-grpc-server/src/types.d.ts @@ -0,0 +1,24 @@ +import { Pushable } from 'it-pushable' +import { EventEmitter } from 'events' + +export interface Options { + socket?: WebsocketServer +} + +export type UnaryEndpoint = (input: InputMessage, metadata: Metadata) => Promise +export type BidirectionalStreamingEndpoint = (source: AsyncIterable, sink: Pushable, metadata: Metadata) => Promise +export type ClientStreamingEndpoint = (source: AsyncIterable, metadata: Metadata) => Promise +export type ServerStreamingEndpoint = (input: InputMessage, sink: Pushable, metadata: Metadata) => Promise + +export interface WebsocketMessage { + path: string + metadata: any + channel: any +} + +export interface WebsocketServer extends EventEmitter { + // events + on(event: 'error', listener: (err: Error) => void): this + on(event: 'data', listener: (message: WebsocketMessage) => void): this + stop: () => Promise +} diff --git a/packages/ipfs-grpc-server/src/utils/encode-mtime.js b/packages/ipfs-grpc-server/src/utils/encode-mtime.js index 12d9bb0eb9..c88d30605b 100644 --- a/packages/ipfs-grpc-server/src/utils/encode-mtime.js +++ b/packages/ipfs-grpc-server/src/utils/encode-mtime.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('ipfs-unixfs').Mtime} [mtime] + */ function encodeMtime (mtime) { const output = {} diff --git a/packages/ipfs-grpc-server/src/utils/load-services.js b/packages/ipfs-grpc-server/src/utils/load-services.js index c901d4e1d0..55664f0494 100644 --- a/packages/ipfs-grpc-server/src/utils/load-services.js +++ b/packages/ipfs-grpc-server/src/utils/load-services.js @@ -15,6 +15,8 @@ const CONVERSION_OPTS = { module.exports = function loadServices () { const root = protobuf.Root.fromJSON(protocol) + + /** @type {Record} */ const output = {} Object @@ -25,6 +27,7 @@ module.exports = function loadServices () { // @ts-ignore .map(key => root.nested.ipfs[key]) .forEach(service => { + /** @type {Record} */ const serviceDef = {} output[service.name] = serviceDef @@ -37,10 +40,16 @@ module.exports = function loadServices () { path: `/ipfs.${service.name}/${methodName}`, requestStream: method.requestStream, responseStream: method.responseStream, + /** + * @param {*} obj + */ requestSerialize: (obj) => { const message = method.resolvedRequestType.fromObject(obj) return method.resolvedRequestType.encode(message).finish() }, + /** + * @param {Uint8Array} buf + */ requestDeserialize: (buf) => { const message = method.resolvedRequestType.decode(buf) const obj = method.resolvedRequestType.toObject(message, CONVERSION_OPTS) @@ -53,10 +62,16 @@ module.exports = function loadServices () { return obj }, + /** + * @param {any} obj + */ responseSerialize: (obj) => { const message = method.resolvedResponseType.fromObject(obj) return method.resolvedResponseType.encode(message).finish() }, + /** + * @param {Uint8Array} buf + */ responseDeserialize: (buf) => { const message = method.resolvedResponseType.decode(buf) const obj = method.resolvedResponseType.toObject(message, CONVERSION_OPTS) diff --git a/packages/ipfs-grpc-server/src/utils/web-socket-message-channel.js b/packages/ipfs-grpc-server/src/utils/web-socket-message-channel.js index 1322f94b7a..98038ada81 100644 --- a/packages/ipfs-grpc-server/src/utils/web-socket-message-channel.js +++ b/packages/ipfs-grpc-server/src/utils/web-socket-message-channel.js @@ -1,6 +1,5 @@ 'use strict' -// @ts-ignore const pushable = require('it-pushable') const { paramCase } = require('change-case') @@ -13,10 +12,11 @@ const HEADER_SIZE = 5 const TRAILER_BYTES = 0x80 /** - * @param {object} object - key/value pairs to turn into HTTP headers + * @param {Record} object - key/value pairs to turn into HTTP headers * @returns {Uint8Array} - HTTP headers **/ const objectToHeaders = (object) => { + /** @type {Record} */ const output = {} Object.keys(object).forEach(key => { @@ -28,7 +28,7 @@ const objectToHeaders = (object) => { }) return Buffer.from( - Object.entries(object) + Object.entries(output) .filter(([, value]) => value != null) .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) .join('\r\n') @@ -36,21 +36,35 @@ const objectToHeaders = (object) => { } class WebsocketMessageChannel { + /** + * @param {import('ws')} ws + */ constructor (ws) { this._ws = ws this.handler = { + /** + * @param {Uint8Array} buf + */ deserialize: (buf) => ({}), + /** + * @param {any} message + */ serialize: (message) => Buffer.from([]) } - // @ts-ignore this.source = pushable() - - // @ts-ignore this.sink = pushable() ws.on('message', (buf) => { + if (!(buf instanceof Uint8Array)) { + this.source.end(new Error(`Incorrect message type received - expected Uint8Array, got ${typeof buf}`)) + this.sink.end() + ws.terminate() + + return + } + const flag = buf[0] if (flag === WebsocketSignal.FINISH_SEND) { @@ -66,7 +80,7 @@ class WebsocketMessageChannel { } const header = buf.slice(offset, HEADER_SIZE + offset) - const length = header.readUInt32BE(1, 4) + const length = header.readUInt32BE(1) offset += HEADER_SIZE if (buf.length < (length + offset)) { @@ -84,13 +98,15 @@ class WebsocketMessageChannel { }) } + /** + * @param {Record} metadata + */ sendMetadata (metadata) { this._ws.send(objectToHeaders(metadata)) } /** * @param {object} message - A message object to send to the client - * @returns {void} */ sendMessage (message) { const response = this.handler.serialize(message) @@ -108,6 +124,9 @@ class WebsocketMessageChannel { this.sendTrailer() } + /** + * @param {Error & { code?: string }} [err] + */ sendTrailer (err) { const trailerBuffer = objectToHeaders({ 'grpc-status': err ? 1 : 0, @@ -128,6 +147,9 @@ class WebsocketMessageChannel { ) } + /** + * @param {Error} [err] + */ end (err) { this.sendTrailer(err) this.source.end() diff --git a/packages/ipfs-grpc-server/src/utils/web-socket-server.js b/packages/ipfs-grpc-server/src/utils/web-socket-server.js index bc4d8fa471..d08f4d2dfc 100644 --- a/packages/ipfs-grpc-server/src/utils/web-socket-server.js +++ b/packages/ipfs-grpc-server/src/utils/web-socket-server.js @@ -4,19 +4,21 @@ const { Server: WebSocketServer } = require('ws') const { EventEmitter } = require('events') const WebSocketMessageChannel = require('./web-socket-message-channel') const debug = require('debug')('ipfs:grpc-server:utils:web-socket-server') +// @ts-ignore - no types const coerce = require('coercer') const { camelCase } = require('change-case') +const ma = require('multiaddr') /** * @param {Buffer} buf - e.g. `Buffer.from('foo-bar: baz\r\n')` - * @returns {object} - e.g. `{ foorBar: 'baz' }` + * @returns {Record} - e.g. `{ foorBar: 'baz' }` **/ const fromHeaders = (buf) => { const headers = buf.toString('utf8') .trim() .split('\r\n') .map(s => s.split(':').map(s => s.trim())) - .reduce((acc, curr) => { + .reduce((/** @type {Record } */ acc, curr) => { if (curr[0] !== 'content-type' && curr[0] !== 'x-grpc-web') { acc[camelCase(curr[0])] = curr[1] } @@ -28,6 +30,9 @@ const fromHeaders = (buf) => { } class Messages extends EventEmitter { + /** + * @param {WebSocketServer} wss + */ constructor (wss) { super() @@ -57,20 +62,36 @@ class Messages extends EventEmitter { * @returns {Promise} */ stop () { - return new Promise((resolve) => { - this._wss.close(() => resolve()) + return new Promise((resolve, reject) => { + this._wss.close((err) => { + if (err) { + return reject(err) + } + resolve() + }) }) } - /** - * @returns {Promise} - */ ready () { return new Promise((resolve) => { this._wss.on('listening', () => { - this.info = this._wss.address() - this.info.uri = `http://${this.info.address}:${this.info.port}` - this.multiaddr = `/ip4/${this._wss.address().address}/tcp/${this._wss.address().port}/ws` + const info = this._wss.address() + + if (typeof info === 'string') { + // this is only the case when a net.Server is listening on a pipe or a unix domain socket + // which is not how this server runs: https://nodejs.org/dist/latest-v15.x/docs/api/net.html#net_server_address + this.info = { + uri: info, + ma: ma(info) + } + } else { + this.info = { + address: info.address, + port: info.port, + uri: `http://${info.address}:${info.port}`, + ma: ma(`/ip4/${info.address}/tcp/${info.port}/ws`) + } + } resolve(this) }) @@ -78,16 +99,26 @@ class Messages extends EventEmitter { } } +/** + * @param {import('ipfs-core-types').IPFS} ipfs + * @param {any} options + * @returns {Promise} + */ module.exports = async (ipfs, options = {}) => { const config = await ipfs.config.getAll() const grpcAddr = config.Addresses.RPC + + if (!grpcAddr) { + throw new Error('No gRPC address configured, please set an Adresses.RPC key in your IPFS config') + } + const [,, host, , port] = grpcAddr.split('/') debug(`starting ws server on ${host}:${port}`) const wss = new WebSocketServer({ host, - port + port: parseInt(port, 10) }) const messages = new Messages(wss) diff --git a/packages/ipfs-grpc-server/tsconfig.json b/packages/ipfs-grpc-server/tsconfig.json index 979a39adab..5fe8ea40d7 100644 --- a/packages/ipfs-grpc-server/tsconfig.json +++ b/packages/ipfs-grpc-server/tsconfig.json @@ -1,10 +1,9 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" ] } diff --git a/packages/ipfs-http-client/.aegir.js b/packages/ipfs-http-client/.aegir.js index bd9b72bd07..63eb11ed9d 100644 --- a/packages/ipfs-http-client/.aegir.js +++ b/packages/ipfs-http-client/.aegir.js @@ -6,7 +6,7 @@ const getPort = require('aegir/utils/get-port') /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '110kB' + bundlesizeMax: '106kB' }, test: { async before (options) { diff --git a/packages/ipfs-http-client/README.md b/packages/ipfs-http-client/README.md index f8a7ce65cc..0ca627fd38 100644 --- a/packages/ipfs-http-client/README.md +++ b/packages/ipfs-http-client/README.md @@ -39,7 +39,7 @@ - [Install](#install) - [Next Steps](#next-steps) - [Usage](#usage) - - [`ipfsHttpClient([options])`](#ipfshttpclientoptions) + - [`create([options])`](#createoptions) - [Parameters](#parameters) - [Options](#options) - [Returns](#returns) @@ -92,7 +92,7 @@ Both the Current and Active LTS versions of Node.js are supported. Please see [n ## Usage -#### `ipfsHttpClient([options])` +#### `create([options])` > create an instance of the HTTP API client @@ -124,16 +124,16 @@ Alternatively it can be an object which may have the following keys: #### Example ```JavaScript -const createClient = require('ipfs-http-client') +const { create } = require('ipfs-http-client') // connect to the default API address http://localhost:5001 -const client = createClient() +const client = create() // connect to a different API -const client = createClient('http://127.0.0.1:5002') +const client = create('http://127.0.0.1:5002') // connect using a URL -const client = createClient(new URL('http://127.0.0.1:5002')) +const client = create(new URL('http://127.0.0.1:5002')) // call Core API methods const { cid } = await client.add('Hello world!') @@ -195,9 +195,8 @@ Returns an async iterable that yields `{ path, content }` objects suitable for p ##### Example ```js -const IpfsHttpClient = require('ipfs-http-client') -const { globSource } = IpfsHttpClient -const ipfs = IpfsHttpClient() +const { create, globSource } = require('ipfs-http-client') +const ipfs = create() const file = await ipfs.add(globSource('./docs', { recursive: true })) console.log(file) @@ -230,9 +229,8 @@ Returns an async iterable that yields `{ path, content }` objects suitable for p ##### Example ```js -const IpfsHttpClient = require('ipfs-http-client') -const { urlSource } = IpfsHttpClient -const ipfs = IpfsHttpClient() +const { create, urlSource } = require('ipfs-http-client') +const ipfs = create() const file = await ipfs.add(urlSource('https://ipfs.io/images/ipfs-logo.svg')) console.log(file) @@ -265,19 +263,19 @@ To interact with the API, you need to have a local daemon running. It needs to b ### Importing the module and usage ```javascript -const ipfsClient = require('ipfs-http-client') +const { create } = require('ipfs-http-client') // connect to ipfs daemon API server -const ipfs = ipfsClient('http://localhost:5001') // (the default in Node.js) +const ipfs = create('http://localhost:5001') // (the default in Node.js) // or connect with multiaddr -const ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001') +const ipfs = create('/ip4/127.0.0.1/tcp/5001') // or using options -const ipfs = ipfsClient({ host: 'localhost', port: '5001', protocol: 'http' }) +const ipfs = create({ host: 'localhost', port: '5001', protocol: 'http' }) // or specifying a specific API path -const ipfs = ipfsClient({ host: '1.1.1.1', port: '80', apiPath: '/ipfs/api/v0' }) +const ipfs = create({ host: '1.1.1.1', port: '80', apiPath: '/ipfs/api/v0' }) ``` ### In a web browser @@ -334,7 +332,7 @@ const ipfs = window.IpfsHttpClient() If you wish to send custom headers with each request made by this library, for example, the Authorization header. You can use the config to do so: ```js -const ipfs = ipfsClient({ +const ipfs = create({ host: 'localhost', port: 5001, protocol: 'http', @@ -350,9 +348,9 @@ To set a global timeout for _all_ requests pass a value for the `timeout` option ```js // Timeout after 10 seconds -const ipfs = ipfsClient({ timeout: 10000 }) +const ipfs = create({ timeout: 10000 }) // Timeout after 2 minutes -const ipfs = ipfsClient({ timeout: '2m' }) +const ipfs = create({ timeout: '2m' }) // see https://www.npmjs.com/package/parse-duration for valid string values ``` diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index dd2ad3bac4..8ac4a8517c 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -11,9 +11,11 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "./dist/src/index.d.ts", "browser": { "./src/lib/multipart-request.js": "./src/lib/multipart-request.browser.js", "ipfs-utils/src/files/glob-source": false, @@ -22,20 +24,11 @@ "http": false, "https": false }, - "typesVersions": { - "*": { - "*": [ - "dist/*", - "dist/*/index" - ] - } - }, "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { - "prepare": "npm run build", "build": "aegir build", "test": "aegir test", "test:node": "aegir test -t node", @@ -53,17 +46,17 @@ "dependencies": { "abort-controller": "^3.0.0", "any-signal": "^2.1.2", - "bignumber.js": "^9.0.1", "cids": "^1.1.5", "debug": "^4.1.1", - "form-data": "^3.0.0", + "form-data": "^4.0.0", "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", - "ipfs-utils": "^6.0.1", + "ipfs-unixfs": "^4.0.1", + "ipfs-utils": "^6.0.4", "ipld-block": "^0.11.0", - "ipld-dag-cbor": "^0.17.0", - "ipld-dag-pb": "^0.20.0", - "ipld-raw": "^6.0.0", + "ipld-dag-cbor": "^0.18.0", + "ipld-dag-pb": "^0.22.0", + "ipld-raw": "^7.0.0", "it-last": "^1.0.4", "it-map": "^1.0.4", "it-tar": "^1.2.2", @@ -80,13 +73,12 @@ "uint8arrays": "^2.1.3" }, "devDependencies": { - "aegir": "^31.0.0", - "delay": "^4.4.0", + "aegir": "^32.1.0", + "delay": "^5.0.0", "go-ipfs": "0.8.0", - "ipfs-core": "^0.5.4", - "ipfsd-ctl": "^7.2.0", + "ipfsd-ctl": "^8.0.0", "it-all": "^1.0.4", - "it-concat": "^1.0.1", + "it-concat": "^1.0.3", "it-first": "^1.0.4", "nock": "^13.0.2", "rimraf": "^3.0.2" diff --git a/packages/ipfs-http-client/src/add-all.js b/packages/ipfs-http-client/src/add-all.js index 57a54e8bb2..4c8ca20ba8 100644 --- a/packages/ipfs-http-client/src/add-all.js +++ b/packages/ipfs-http-client/src/add-all.js @@ -11,11 +11,14 @@ const { AbortController } = require('native-abort-controller') /** * @typedef {import('ipfs-utils/src/types').ProgressFn} IPFSUtilsHttpUploadProgressFn * @typedef {import('ipfs-core-types/src/root').AddProgressFn} IPFSCoreAddProgressFn + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + * @typedef {import('ipfs-core-types/src/root').AddResult} AddResult */ module.exports = configure((api) => { /** - * @type {import('.').Implements} + * @type {RootAPI["addAll"]} */ async function * addAll (source, options = {}) { // allow aborting requests on body errors @@ -30,6 +33,7 @@ module.exports = configure((api) => { // `{ total, loaded}` passed to `onUploadProgress` and `multipart.total` // in which case we disable progress updates to be written out. const [progressFn, onUploadProgress] = typeof options.progress === 'function' + // @ts-ignore tsc picks up the node codepath ? createProgressHandler(total, parts, options.progress) : [undefined, undefined] @@ -104,9 +108,9 @@ const createOnUploadProgress = (size, parts, progress) => { /** * @param {any} input - * @returns {import('ipfs-core-types/src/files').UnixFSEntry} */ function toCoreInterface ({ name, hash, size, mode, mtime, mtimeNsecs }) { + /** @type {AddResult} */ const output = { path: name, cid: new CID(hash), @@ -124,6 +128,5 @@ function toCoreInterface ({ name, hash, size, mode, mtime, mtimeNsecs }) { } } - // @ts-ignore return output } diff --git a/packages/ipfs-http-client/src/add.js b/packages/ipfs-http-client/src/add.js index 83383db4fa..c339a0fee3 100644 --- a/packages/ipfs-http-client/src/add.js +++ b/packages/ipfs-http-client/src/add.js @@ -5,16 +5,21 @@ const last = require('it-last') const configure = require('./lib/configure') /** - * @param {import("./lib/core").ClientOptions} options + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + +/** + * @param {import('./types').Options} options */ module.exports = (options) => { const all = addAll(options) return configure(() => { /** - * @type {import('.').Implements} + * @type {RootAPI["add"]} */ async function add (input, options = {}) { - // @ts-ignore - last may return undefind if source is empty + // @ts-ignore - last may return undefined if source is empty return await last(all(input, options)) } return add diff --git a/packages/ipfs-http-client/src/bitswap/index.js b/packages/ipfs-http-client/src/bitswap/index.js index 36d70b7db8..db125c13e2 100644 --- a/packages/ipfs-http-client/src/bitswap/index.js +++ b/packages/ipfs-http-client/src/bitswap/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ wantlist: require('./wantlist')(config), wantlistForPeer: require('./wantlist-for-peer')(config), diff --git a/packages/ipfs-http-client/src/bitswap/stat.js b/packages/ipfs-http-client/src/bitswap/stat.js index 5d3d33a894..0c06048eca 100644 --- a/packages/ipfs-http-client/src/bitswap/stat.js +++ b/packages/ipfs-http-client/src/bitswap/stat.js @@ -1,13 +1,17 @@ 'use strict' -const { BigNumber } = require('bignumber.js') const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bitswap').API} BitswapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BitswapAPI["stat"]} */ async function stat (options = {}) { const res = await api.post('bitswap/stat', { @@ -22,16 +26,19 @@ module.exports = configure(api => { return stat }) +/** + * @param {any} res + */ function toCoreInterface (res) { return { provideBufLen: res.ProvideBufLen, - wantlist: (res.Wantlist || []).map(k => new CID(k['/'])), + wantlist: (res.Wantlist || []).map((/** @type {{ '/': string }} */ k) => new CID(k['/'])), peers: (res.Peers || []), - blocksReceived: new BigNumber(res.BlocksReceived), - dataReceived: new BigNumber(res.DataReceived), - blocksSent: new BigNumber(res.BlocksSent), - dataSent: new BigNumber(res.DataSent), - dupBlksReceived: new BigNumber(res.DupBlksReceived), - dupDataReceived: new BigNumber(res.DupDataReceived) + blocksReceived: BigInt(res.BlocksReceived), + dataReceived: BigInt(res.DataReceived), + blocksSent: BigInt(res.BlocksSent), + dataSent: BigInt(res.DataSent), + dupBlksReceived: BigInt(res.DupBlksReceived), + dupDataReceived: BigInt(res.DupDataReceived) } } diff --git a/packages/ipfs-http-client/src/bitswap/unwant.js b/packages/ipfs-http-client/src/bitswap/unwant.js index 60c9e144d4..5774dd819e 100644 --- a/packages/ipfs-http-client/src/bitswap/unwant.js +++ b/packages/ipfs-http-client/src/bitswap/unwant.js @@ -4,9 +4,14 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bitswap').API} BitswapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BitswapAPI["unwant"]} */ async function unwant (cid, options = {}) { const res = await api.post('bitswap/unwant', { diff --git a/packages/ipfs-http-client/src/bitswap/wantlist-for-peer.js b/packages/ipfs-http-client/src/bitswap/wantlist-for-peer.js index 973ce7c8eb..85fe17760b 100644 --- a/packages/ipfs-http-client/src/bitswap/wantlist-for-peer.js +++ b/packages/ipfs-http-client/src/bitswap/wantlist-for-peer.js @@ -4,9 +4,14 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bitswap').API} BitswapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BitswapAPI["wantlistForPeer"]} */ async function wantlistForPeer (peerId, options = {}) { // @ts-ignore - CID|string seems to confuse typedef @@ -22,7 +27,7 @@ module.exports = configure(api => { headers: options.headers })).json() - return (res.Keys || []).map(k => new CID(k['/'])) + return (res.Keys || []).map((/** @type {{ '/': string }} */ k) => new CID(k['/'])) } return wantlistForPeer }) diff --git a/packages/ipfs-http-client/src/bitswap/wantlist.js b/packages/ipfs-http-client/src/bitswap/wantlist.js index fab480887e..536d43812f 100644 --- a/packages/ipfs-http-client/src/bitswap/wantlist.js +++ b/packages/ipfs-http-client/src/bitswap/wantlist.js @@ -4,9 +4,14 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bitswap').API} BitswapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BitswapAPI["wantlist"]} */ async function wantlist (options = {}) { const res = await (await api.post('bitswap/wantlist', { @@ -16,7 +21,7 @@ module.exports = configure(api => { headers: options.headers })).json() - return (res.Keys || []).map(k => new CID(k['/'])) + return (res.Keys || []).map((/** @type {{ '/': string }} */ k) => new CID(k['/'])) } return wantlist }) diff --git a/packages/ipfs-http-client/src/block/get.js b/packages/ipfs-http-client/src/block/get.js index 84377477d6..ca9d09b138 100644 --- a/packages/ipfs-http-client/src/block/get.js +++ b/packages/ipfs-http-client/src/block/get.js @@ -5,9 +5,14 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/block').API} BlockAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BlockAPI["get"]} */ async function get (cid, options = {}) { // @ts-ignore - CID|string seems to confuse typedef diff --git a/packages/ipfs-http-client/src/block/index.js b/packages/ipfs-http-client/src/block/index.js index f25c73366c..36af9bc8cb 100644 --- a/packages/ipfs-http-client/src/block/index.js +++ b/packages/ipfs-http-client/src/block/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ get: require('./get')(config), stat: require('./stat')(config), diff --git a/packages/ipfs-http-client/src/block/put.js b/packages/ipfs-http-client/src/block/put.js index 2e3d5c8a34..cd96ae7232 100644 --- a/packages/ipfs-http-client/src/block/put.js +++ b/packages/ipfs-http-client/src/block/put.js @@ -9,9 +9,14 @@ const toUrlSearchParams = require('../lib/to-url-search-params') const abortSignal = require('../lib/abort-signal') const { AbortController } = require('native-abort-controller') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/block').API} BlockAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BlockAPI["put"]} */ async function put (data, options = {}) { if (Block.isBlock(data)) { @@ -67,7 +72,7 @@ module.exports = configure(api => { throw err } - return new Block(/** @type {Uint8Array} */(data), new CID(res.Key)) + return new Block((/** @type {Uint8Array} */ data), new CID(res.Key)) } return put diff --git a/packages/ipfs-http-client/src/block/rm.js b/packages/ipfs-http-client/src/block/rm.js index 6137194d9a..7f9d6b0d7e 100644 --- a/packages/ipfs-http-client/src/block/rm.js +++ b/packages/ipfs-http-client/src/block/rm.js @@ -4,9 +4,15 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/block').API} BlockAPI + * @typedef {import('ipfs-core-types/src/block').RmResult} RmResult + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BlockAPI["rm"]} */ async function * rm (cid, options = {}) { if (!Array.isArray(cid)) { @@ -32,7 +38,11 @@ module.exports = configure(api => { return rm }) +/** + * @param {*} removed + */ function toCoreInterface (removed) { + /** @type {RmResult} */ const out = { cid: new CID(removed.Hash) } diff --git a/packages/ipfs-http-client/src/block/stat.js b/packages/ipfs-http-client/src/block/stat.js index 94f37be7c8..e0c6c4bf64 100644 --- a/packages/ipfs-http-client/src/block/stat.js +++ b/packages/ipfs-http-client/src/block/stat.js @@ -4,9 +4,14 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/block').API} BlockAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BlockAPI["stat"]} */ async function stat (cid, options = {}) { const res = await api.post('block/stat', { diff --git a/packages/ipfs-http-client/src/bootstrap/add.js b/packages/ipfs-http-client/src/bootstrap/add.js index 781354b9ea..35afcc4bfe 100644 --- a/packages/ipfs-http-client/src/bootstrap/add.js +++ b/packages/ipfs-http-client/src/bootstrap/add.js @@ -4,9 +4,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const Multiaddr = require('multiaddr') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bootstrap').API} BootstrapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BootstrapAPI["add"]} */ async function add (addr, options = {}) { const res = await api.post('bootstrap/add', { @@ -21,7 +26,7 @@ module.exports = configure(api => { const { Peers } = await res.json() - return { Peers: Peers.map(ma => new Multiaddr(ma)) } + return { Peers: Peers.map((/** @type {string} */ ma) => new Multiaddr(ma)) } } return add diff --git a/packages/ipfs-http-client/src/bootstrap/clear.js b/packages/ipfs-http-client/src/bootstrap/clear.js index 5b437bd53f..930b258bcb 100644 --- a/packages/ipfs-http-client/src/bootstrap/clear.js +++ b/packages/ipfs-http-client/src/bootstrap/clear.js @@ -4,9 +4,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const Multiaddr = require('multiaddr') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bootstrap').API} BootstrapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BootstrapAPI["clear"]} */ async function clear (options = {}) { const res = await api.post('bootstrap/rm', { @@ -21,7 +26,7 @@ module.exports = configure(api => { const { Peers } = await res.json() - return { Peers: Peers.map(ma => new Multiaddr(ma)) } + return { Peers: Peers.map((/** @type {string} */ ma) => new Multiaddr(ma)) } } return clear diff --git a/packages/ipfs-http-client/src/bootstrap/index.js b/packages/ipfs-http-client/src/bootstrap/index.js index 3a1021d342..989bb61188 100644 --- a/packages/ipfs-http-client/src/bootstrap/index.js +++ b/packages/ipfs-http-client/src/bootstrap/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ add: require('./add')(config), clear: require('./clear')(config), diff --git a/packages/ipfs-http-client/src/bootstrap/list.js b/packages/ipfs-http-client/src/bootstrap/list.js index f15ac71160..9c0ac38d78 100644 --- a/packages/ipfs-http-client/src/bootstrap/list.js +++ b/packages/ipfs-http-client/src/bootstrap/list.js @@ -4,9 +4,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const Multiaddr = require('multiaddr') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bootstrap').API} BootstrapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BootstrapAPI["list"]} */ async function list (options = {}) { const res = await api.post('bootstrap/list', { @@ -18,7 +23,7 @@ module.exports = configure(api => { const { Peers } = await res.json() - return { Peers: Peers.map(ma => new Multiaddr(ma)) } + return { Peers: Peers.map((/** @type {string} */ ma) => new Multiaddr(ma)) } } return list diff --git a/packages/ipfs-http-client/src/bootstrap/reset.js b/packages/ipfs-http-client/src/bootstrap/reset.js index 5eb9e5c3fd..2959a53855 100644 --- a/packages/ipfs-http-client/src/bootstrap/reset.js +++ b/packages/ipfs-http-client/src/bootstrap/reset.js @@ -4,9 +4,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const Multiaddr = require('multiaddr') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bootstrap').API} BootstrapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BootstrapAPI["reset"]} */ async function reset (options = {}) { const res = await api.post('bootstrap/add', { @@ -21,7 +26,7 @@ module.exports = configure(api => { const { Peers } = await res.json() - return { Peers: Peers.map(ma => new Multiaddr(ma)) } + return { Peers: Peers.map((/** @type {string} */ ma) => new Multiaddr(ma)) } } return reset diff --git a/packages/ipfs-http-client/src/bootstrap/rm.js b/packages/ipfs-http-client/src/bootstrap/rm.js index 9eab1100ce..f09c15cb89 100644 --- a/packages/ipfs-http-client/src/bootstrap/rm.js +++ b/packages/ipfs-http-client/src/bootstrap/rm.js @@ -4,9 +4,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const Multiaddr = require('multiaddr') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/bootstrap').API} BootstrapAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {BootstrapAPI["rm"]} */ async function rm (addr, options = {}) { const res = await api.post('bootstrap/rm', { @@ -21,7 +26,7 @@ module.exports = configure(api => { const { Peers } = await res.json() - return { Peers: Peers.map(ma => new Multiaddr(ma)) } + return { Peers: Peers.map((/** @type {string} */ ma) => new Multiaddr(ma)) } } return rm diff --git a/packages/ipfs-http-client/src/cat.js b/packages/ipfs-http-client/src/cat.js index 7719a06ee9..3ff6240f46 100644 --- a/packages/ipfs-http-client/src/cat.js +++ b/packages/ipfs-http-client/src/cat.js @@ -4,9 +4,14 @@ const CID = require('cids') const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { /** - * @type {import('.').Implements} + * @type {RootAPI["cat"]} */ async function * cat (path, options = {}) { const res = await api.post('cat', { diff --git a/packages/ipfs-http-client/src/commands.js b/packages/ipfs-http-client/src/commands.js index 81fbd3efc8..69f134cb0d 100644 --- a/packages/ipfs-http-client/src/commands.js +++ b/packages/ipfs-http-client/src/commands.js @@ -3,8 +3,16 @@ const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {RootAPI["commands"]} + */ + const commands = async (options = {}) => { const res = await api.post('commands', { timeout: options.timeout, signal: options.signal, @@ -14,4 +22,5 @@ module.exports = configure(api => { return res.json() } + return commands }) diff --git a/packages/ipfs-http-client/src/config/get.js b/packages/ipfs-http-client/src/config/get.js index 3b69da2679..1d480b54d2 100644 --- a/packages/ipfs-http-client/src/config/get.js +++ b/packages/ipfs-http-client/src/config/get.js @@ -3,9 +3,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/config').API} ConfigAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'get', import('ipfs-core/src/components/config')>} + * @type {ConfigAPI["get"]} */ const get = async (key, options = {}) => { if (!key) { diff --git a/packages/ipfs-http-client/src/config/getAll.js b/packages/ipfs-http-client/src/config/getAll.js index 8e74b6b89e..35d83e5236 100644 --- a/packages/ipfs-http-client/src/config/getAll.js +++ b/packages/ipfs-http-client/src/config/getAll.js @@ -3,9 +3,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/config').API} ConfigAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'getAll', import('ipfs-core/src/components/config')>} + * @type {ConfigAPI["getAll"]} */ const getAll = async (options = {}) => { const res = await api.post('config/show', { diff --git a/packages/ipfs-http-client/src/config/index.js b/packages/ipfs-http-client/src/config/index.js index d177cda308..83176f57f5 100644 --- a/packages/ipfs-http-client/src/config/index.js +++ b/packages/ipfs-http-client/src/config/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ getAll: require('./getAll')(config), get: require('./get')(config), diff --git a/packages/ipfs-http-client/src/config/profiles/apply.js b/packages/ipfs-http-client/src/config/profiles/apply.js index cf44f0f397..12d0a21211 100644 --- a/packages/ipfs-http-client/src/config/profiles/apply.js +++ b/packages/ipfs-http-client/src/config/profiles/apply.js @@ -3,7 +3,15 @@ const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/config/profiles').API} ConfigProfilesAPI + */ + module.exports = configure(api => { + /** + * @type {ConfigProfilesAPI["apply"]} + */ async function apply (profile, options = {}) { const res = await api.post('config/profile/apply', { timeout: options.timeout, diff --git a/packages/ipfs-http-client/src/config/profiles/index.js b/packages/ipfs-http-client/src/config/profiles/index.js index 77b68de411..809dca8ee4 100644 --- a/packages/ipfs-http-client/src/config/profiles/index.js +++ b/packages/ipfs-http-client/src/config/profiles/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../../types').Options} config + */ module.exports = config => ({ apply: require('./apply')(config), list: require('./list')(config) diff --git a/packages/ipfs-http-client/src/config/profiles/list.js b/packages/ipfs-http-client/src/config/profiles/list.js index a5cde9dc56..4cb96d0247 100644 --- a/packages/ipfs-http-client/src/config/profiles/list.js +++ b/packages/ipfs-http-client/src/config/profiles/list.js @@ -4,8 +4,16 @@ const toCamel = require('../../lib/object-to-camel') const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/config/profiles').API} ConfigProfilesAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {ConfigProfilesAPI["list"]} + */ + async function list (options = {}) { const res = await api.post('config/profile/list', { timeout: options.timeout, signal: options.signal, @@ -15,6 +23,7 @@ module.exports = configure(api => { const data = await res.json() - return data.map(profile => toCamel(profile)) + return data.map((/** @type {Record} */ profile) => toCamel(profile)) } + return list }) diff --git a/packages/ipfs-http-client/src/config/replace.js b/packages/ipfs-http-client/src/config/replace.js index fe9386aa77..172a9ffeed 100644 --- a/packages/ipfs-http-client/src/config/replace.js +++ b/packages/ipfs-http-client/src/config/replace.js @@ -7,9 +7,14 @@ const toUrlSearchParams = require('../lib/to-url-search-params') const abortSignal = require('../lib/abort-signal') const { AbortController } = require('native-abort-controller') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/config').API} ConfigAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'replace', import('ipfs-core/src/components/config')>} + * @type {ConfigAPI["replace"]} */ const replace = async (config, options = {}) => { // allow aborting requests on body errors diff --git a/packages/ipfs-http-client/src/config/set.js b/packages/ipfs-http-client/src/config/set.js index 9a4f68aa41..3cfbe770c0 100644 --- a/packages/ipfs-http-client/src/config/set.js +++ b/packages/ipfs-http-client/src/config/set.js @@ -1,12 +1,16 @@ 'use strict' -const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/config').API} ConfigAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'set', import('ipfs-core/src/components/config')>} + * @type {ConfigAPI["set"]} */ const set = async (key, value, options = {}) => { if (typeof key !== 'string') { @@ -25,12 +29,16 @@ module.exports = configure(api => { headers: options.headers }) - return toCamel(await res.json()) + await res.text() } return set }) +/** + * @param {*} key + * @param {*} value + */ const encodeParam = (key, value) => { switch (typeof value) { case 'boolean': diff --git a/packages/ipfs-http-client/src/dag/get.js b/packages/ipfs-http-client/src/dag/get.js index 0d03d31308..21f30e27aa 100644 --- a/packages/ipfs-http-client/src/dag/get.js +++ b/packages/ipfs-http-client/src/dag/get.js @@ -4,13 +4,18 @@ const configure = require('../lib/configure') const multicodec = require('multicodec') const loadFormat = require('../lib/ipld-formats') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dag').API} DAGAPI + */ + module.exports = configure((api, opts) => { const getBlock = require('../block/get')(opts) const dagResolve = require('./resolve')(opts) const load = loadFormat(opts.ipld) /** - * @type {import('..').Implements} + * @type {DAGAPI["get"]} */ const get = async (cid, options = {}) => { const resolved = await dagResolve(cid, options) @@ -23,7 +28,7 @@ module.exports = configure((api, opts) => { resolved.remainderPath = '/' } - return format.resolver.resolve(block.data, resolved.remainderPath) + return format.resolver.resolve(block.data, resolved.remainderPath || '') } return get diff --git a/packages/ipfs-http-client/src/dag/index.js b/packages/ipfs-http-client/src/dag/index.js index 3cc4d410ec..2754bb6dd7 100644 --- a/packages/ipfs-http-client/src/dag/index.js +++ b/packages/ipfs-http-client/src/dag/index.js @@ -1,7 +1,11 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ get: require('./get')(config), put: require('./put')(config), - resolve: require('./resolve')(config) + resolve: require('./resolve')(config), + tree: require('./tree')(config) }) diff --git a/packages/ipfs-http-client/src/dag/put.js b/packages/ipfs-http-client/src/dag/put.js index 5c2899ecb7..9290b4844b 100644 --- a/packages/ipfs-http-client/src/dag/put.js +++ b/packages/ipfs-http-client/src/dag/put.js @@ -10,11 +10,16 @@ const { AbortController } = require('native-abort-controller') const multicodec = require('multicodec') const loadFormat = require('../lib/ipld-formats') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dag').API} DAGAPI + */ + module.exports = configure((api, opts) => { const load = loadFormat(opts.ipld) /** - * @type {import('..').Implements} + * @type {DAGAPI["put"]} */ const put = async (dagNode, options = {}) => { if (options.cid && (options.format || options.hashAlg)) { @@ -43,6 +48,7 @@ module.exports = configure((api, opts) => { ...encodingOptions } + // @ts-ignore settings.format might be an invalid CodecName const format = await load(settings.format) const serialized = format.util.serialize(dagNode) diff --git a/packages/ipfs-http-client/src/dag/resolve.js b/packages/ipfs-http-client/src/dag/resolve.js index 18a294d323..c0e69354b6 100644 --- a/packages/ipfs-http-client/src/dag/resolve.js +++ b/packages/ipfs-http-client/src/dag/resolve.js @@ -4,9 +4,14 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dag').API} DAGAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {DAGAPI["resolve"]} */ const resolve = async (ipfsPath, options = {}) => { const res = await api.post('dag/resolve', { diff --git a/packages/ipfs-http-client/src/dag/tree.js b/packages/ipfs-http-client/src/dag/tree.js new file mode 100644 index 0000000000..43809ed84d --- /dev/null +++ b/packages/ipfs-http-client/src/dag/tree.js @@ -0,0 +1,19 @@ +'use strict' + +const configure = require('../lib/configure') + +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dag').API} DAGAPI + */ + +module.exports = configure(api => { + /** + * @type {DAGAPI["tree"]} + */ + const tree = async (ipfsPath, options = {}) => { + throw new Error('Not implemented') + } + + return tree +}) diff --git a/packages/ipfs-http-client/src/dht/find-peer.js b/packages/ipfs-http-client/src/dht/find-peer.js index c35c1da8b8..6a70e9cc44 100644 --- a/packages/ipfs-http-client/src/dht/find-peer.js +++ b/packages/ipfs-http-client/src/dht/find-peer.js @@ -6,9 +6,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const { FinalPeer } = require('./response-types') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dht').API} DHTAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'findPeer', import('ipfs-core/src/components/dht')>} + * @type {DHTAPI["findPeer"]} */ async function findPeer (peerId, options = {}) { const res = await api.post('dht/findpeer', { @@ -26,7 +31,7 @@ module.exports = configure(api => { const { ID, Addrs } = data.Responses[0] return { id: ID, - addrs: (Addrs || []).map(a => multiaddr(a)) + addrs: (Addrs || []).map((/** @type {string} **/ a) => multiaddr(a)) } } } diff --git a/packages/ipfs-http-client/src/dht/find-provs.js b/packages/ipfs-http-client/src/dht/find-provs.js index 64e6a60b9e..c5175a6cd9 100644 --- a/packages/ipfs-http-client/src/dht/find-provs.js +++ b/packages/ipfs-http-client/src/dht/find-provs.js @@ -6,9 +6,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const { Provider } = require('./response-types') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dht').API} DHTAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'findProvs', import('ipfs-core/src/components/dht')>} + * @type {DHTAPI["findProvs"]} */ async function * findProvs (cid, options = {}) { const res = await api.post('dht/findprovs', { @@ -26,7 +31,7 @@ module.exports = configure(api => { for (const { ID, Addrs } of message.Responses) { yield { id: ID, - addrs: (Addrs || []).map(a => multiaddr(a)) + addrs: (Addrs || []).map((/** @type {string} **/ a) => multiaddr(a)) } } } diff --git a/packages/ipfs-http-client/src/dht/get.js b/packages/ipfs-http-client/src/dht/get.js index 990edb1790..581dd70bd4 100644 --- a/packages/ipfs-http-client/src/dht/get.js +++ b/packages/ipfs-http-client/src/dht/get.js @@ -6,9 +6,14 @@ const { Value } = require('./response-types') const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayFromString = require('uint8arrays/from-string') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dht').API} DHTAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'get', import('ipfs-core/src/components/dht')>} + * @type {DHTAPI["get"]} */ async function get (key, options = {}) { const res = await api.post('dht/get', { diff --git a/packages/ipfs-http-client/src/dht/index.js b/packages/ipfs-http-client/src/dht/index.js index 754e57b838..0e45080af9 100644 --- a/packages/ipfs-http-client/src/dht/index.js +++ b/packages/ipfs-http-client/src/dht/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ get: require('./get')(config), put: require('./put')(config), diff --git a/packages/ipfs-http-client/src/dht/provide.js b/packages/ipfs-http-client/src/dht/provide.js index 70cd14b558..9ef17a394c 100644 --- a/packages/ipfs-http-client/src/dht/provide.js +++ b/packages/ipfs-http-client/src/dht/provide.js @@ -6,11 +6,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dht').API} DHTAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'provide', import('ipfs-core/src/components/dht')>} + * @type {DHTAPI["provide"]} */ - async function * provide (cids, options = {}) { + async function * provide (cids, options = { recursive: false }) { cids = Array.isArray(cids) ? cids : [cids] const res = await api.post('dht/provide', { @@ -27,9 +32,9 @@ module.exports = configure(api => { message = toCamel(message) message.id = new CID(message.id) if (message.responses) { - message.responses = message.responses.map(({ ID, Addrs }) => ({ + message.responses = message.responses.map((/** @type {{ ID: string, Addrs: string[] }} */ { ID, Addrs }) => ({ id: ID, - addrs: (Addrs || []).map(a => multiaddr(a)) + addrs: (Addrs || []).map((/** @type {string} **/ a) => multiaddr(a)) })) } else { message.responses = [] diff --git a/packages/ipfs-http-client/src/dht/put.js b/packages/ipfs-http-client/src/dht/put.js index 66a9de5349..949bc3f446 100644 --- a/packages/ipfs-http-client/src/dht/put.js +++ b/packages/ipfs-http-client/src/dht/put.js @@ -8,9 +8,15 @@ const toUrlSearchParams = require('../lib/to-url-search-params') const multipartRequest = require('../lib/multipart-request') const abortSignal = require('../lib/abort-signal') const { AbortController } = require('native-abort-controller') + +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dht').API} DHTAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'put', import('ipfs-core/src/components/dht')>} + * @type {DHTAPI["put"]} */ async function * put (key, value, options = {}) { // allow aborting requests on body errors @@ -34,7 +40,7 @@ module.exports = configure(api => { message = toCamel(message) message.id = new CID(message.id) if (message.responses) { - message.responses = message.responses.map(({ ID, Addrs }) => ({ + message.responses = message.responses.map((/** @type {{ ID: string, Addrs: string[] }} */ { ID, Addrs }) => ({ id: ID, addrs: (Addrs || []).map(a => multiaddr(a)) })) diff --git a/packages/ipfs-http-client/src/dht/query.js b/packages/ipfs-http-client/src/dht/query.js index 7183f74d16..4193970f9e 100644 --- a/packages/ipfs-http-client/src/dht/query.js +++ b/packages/ipfs-http-client/src/dht/query.js @@ -6,9 +6,14 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/dht').API} DHTAPI + */ + module.exports = configure(api => { /** - * @type {import('..').ImplementsMethod<'query', import('ipfs-core/src/components/dht')>} + * @type {DHTAPI["query"]} */ async function * query (peerId, options = {}) { const res = await api.post('dht/query', { @@ -24,9 +29,9 @@ module.exports = configure(api => { for await (let message of res.ndjson()) { message = toCamel(message) message.id = new CID(message.id) - message.responses = (message.responses || []).map(({ ID, Addrs }) => ({ + message.responses = (message.responses || []).map((/** @type {{ ID: string, Addrs: string[] }} */ { ID, Addrs }) => ({ id: ID, - addrs: (Addrs || []).map(a => multiaddr(a)) + addrs: (Addrs || []).map((/** @type {string} **/ a) => multiaddr(a)) })) yield message } diff --git a/packages/ipfs-http-client/src/diag/cmds.js b/packages/ipfs-http-client/src/diag/cmds.js index dd0854e77e..1bd2c06e37 100644 --- a/packages/ipfs-http-client/src/diag/cmds.js +++ b/packages/ipfs-http-client/src/diag/cmds.js @@ -3,8 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/diag').API} DiagAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {DiagAPI["cmds"]} + */ + async function cmds (options = {}) { const res = await api.post('diag/cmds', { timeout: options.timeout, signal: options.signal, @@ -14,4 +22,5 @@ module.exports = configure(api => { return res.json() } + return cmds }) diff --git a/packages/ipfs-http-client/src/diag/index.js b/packages/ipfs-http-client/src/diag/index.js index d3ac85d551..dc4cc3ea48 100644 --- a/packages/ipfs-http-client/src/diag/index.js +++ b/packages/ipfs-http-client/src/diag/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ net: require('./net')(config), sys: require('./sys')(config), diff --git a/packages/ipfs-http-client/src/diag/net.js b/packages/ipfs-http-client/src/diag/net.js index 3fc0fe9a9a..d485af7c4a 100644 --- a/packages/ipfs-http-client/src/diag/net.js +++ b/packages/ipfs-http-client/src/diag/net.js @@ -3,8 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/diag').API} DiagAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {DiagAPI["net"]} + */ + async function net (options = {}) { const res = await api.post('diag/net', { timeout: options.timeout, signal: options.signal, @@ -13,4 +21,5 @@ module.exports = configure(api => { }) return res.json() } + return net }) diff --git a/packages/ipfs-http-client/src/diag/sys.js b/packages/ipfs-http-client/src/diag/sys.js index 761edeb8b1..31f1a5bd03 100644 --- a/packages/ipfs-http-client/src/diag/sys.js +++ b/packages/ipfs-http-client/src/diag/sys.js @@ -3,8 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/diag').API} DiagAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {DiagAPI["sys"]} + */ + async function sys (options = {}) { const res = await api.post('diag/sys', { timeout: options.timeout, signal: options.signal, @@ -14,4 +22,5 @@ module.exports = configure(api => { return res.json() } + return sys }) diff --git a/packages/ipfs-http-client/src/dns.js b/packages/ipfs-http-client/src/dns.js index 42d90f44d0..6059d30de3 100644 --- a/packages/ipfs-http-client/src/dns.js +++ b/packages/ipfs-http-client/src/dns.js @@ -3,9 +3,14 @@ const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { /** - * @type {import('.').Implements} + * @type {RootAPI["dns"]} */ const dns = async (domain, options = {}) => { const res = await api.post('dns', { diff --git a/packages/ipfs-http-client/src/files/chmod.js b/packages/ipfs-http-client/src/files/chmod.js index 0a40a46f79..6cd344d480 100644 --- a/packages/ipfs-http-client/src/files/chmod.js +++ b/packages/ipfs-http-client/src/files/chmod.js @@ -3,9 +3,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["chmod"]} */ async function chmod (path, mode, options = {}) { const res = await api.post('files/chmod', { @@ -21,6 +26,5 @@ module.exports = configure(api => { await res.text() } - return chmod }) diff --git a/packages/ipfs-http-client/src/files/cp.js b/packages/ipfs-http-client/src/files/cp.js index 0513071644..f87bcef5e5 100644 --- a/packages/ipfs-http-client/src/files/cp.js +++ b/packages/ipfs-http-client/src/files/cp.js @@ -1,22 +1,28 @@ 'use strict' const CID = require('cids') -const { findSources } = require('./utils') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["cp"]} */ - async function cp (...args) { - const { sources, options } = findSources(args) + async function cp (sources, destination, options = {}) { + if (!Array.isArray(sources)) { + sources = [sources] + } const res = await api.post('files/cp', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: sources.map(src => CID.isCID(src) ? `/ipfs/${src}` : src), + arg: sources.concat(destination).map(src => CID.isCID(src) ? `/ipfs/${src}` : src), ...options }), headers: options.headers @@ -24,6 +30,5 @@ module.exports = configure(api => { await res.text() } - return cp }) diff --git a/packages/ipfs-http-client/src/files/flush.js b/packages/ipfs-http-client/src/files/flush.js index 344e87874f..33bbdae1aa 100644 --- a/packages/ipfs-http-client/src/files/flush.js +++ b/packages/ipfs-http-client/src/files/flush.js @@ -4,9 +4,14 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["flush"]} */ async function flush (path, options = {}) { if (!path || typeof path !== 'string') { @@ -26,6 +31,5 @@ module.exports = configure(api => { return new CID(data.Cid) } - return flush }) diff --git a/packages/ipfs-http-client/src/files/index.js b/packages/ipfs-http-client/src/files/index.js index 563cff691e..0a1921ca73 100644 --- a/packages/ipfs-http-client/src/files/index.js +++ b/packages/ipfs-http-client/src/files/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ chmod: require('./chmod')(config), cp: require('./cp')(config), diff --git a/packages/ipfs-http-client/src/files/ls.js b/packages/ipfs-http-client/src/files/ls.js index eca14ad317..71d05b8491 100644 --- a/packages/ipfs-http-client/src/files/ls.js +++ b/packages/ipfs-http-client/src/files/ls.js @@ -5,9 +5,13 @@ const toCamelWithMetadata = require('../lib/object-to-camel-with-metadata') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["ls"]} */ async function * ls (path, options = {}) { if (!path || typeof path !== 'string') { @@ -38,10 +42,12 @@ module.exports = configure(api => { } } } - return ls }) +/** + * @param {*} entry + */ function toCoreInterface (entry) { if (entry.hash) { entry.cid = new CID(entry.hash) diff --git a/packages/ipfs-http-client/src/files/mkdir.js b/packages/ipfs-http-client/src/files/mkdir.js index 0fe84790e4..86952f9dac 100644 --- a/packages/ipfs-http-client/src/files/mkdir.js +++ b/packages/ipfs-http-client/src/files/mkdir.js @@ -3,9 +3,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["mkdir"]} */ async function mkdir (path, options = {}) { const res = await api.post('files/mkdir', { @@ -20,6 +25,5 @@ module.exports = configure(api => { await res.text() } - return mkdir }) diff --git a/packages/ipfs-http-client/src/files/mv.js b/packages/ipfs-http-client/src/files/mv.js index ad717590b3..c8c4cf7ced 100644 --- a/packages/ipfs-http-client/src/files/mv.js +++ b/packages/ipfs-http-client/src/files/mv.js @@ -1,27 +1,32 @@ 'use strict' const CID = require('cids') -const { findSources } = require('./utils') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["mv"]} */ - async function mv (...args) { - const { sources, options } = findSources(args) + async function mv (sources, destination, options = {}) { + if (!Array.isArray(sources)) { + sources = [sources] + } const res = await api.post('files/mv', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: sources.map(src => CID.isCID(src) ? `/ipfs/${src}` : src), + arg: sources.concat(destination).map(src => CID.isCID(src) ? `/ipfs/${src}` : src), ...options }), headers: options.headers }) - await res.text() } diff --git a/packages/ipfs-http-client/src/files/read.js b/packages/ipfs-http-client/src/files/read.js index 10e9399e71..26b6b80495 100644 --- a/packages/ipfs-http-client/src/files/read.js +++ b/packages/ipfs-http-client/src/files/read.js @@ -1,12 +1,18 @@ 'use strict' +// @ts-ignore no types const toIterable = require('stream-to-it/source') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["read"]} */ async function * read (path, options = {}) { const res = await api.post('files/read', { @@ -22,6 +28,5 @@ module.exports = configure(api => { yield * toIterable(res.body) } - return read }) diff --git a/packages/ipfs-http-client/src/files/rm.js b/packages/ipfs-http-client/src/files/rm.js index d8eba8db39..bc9a5a47ae 100644 --- a/packages/ipfs-http-client/src/files/rm.js +++ b/packages/ipfs-http-client/src/files/rm.js @@ -1,21 +1,23 @@ 'use strict' const configure = require('../lib/configure') -const { findSources } = require('./utils') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["rm"]} */ - async function rm (...args) { - const { sources, options } = findSources(args) - + async function rm (path, options = {}) { const res = await api.post('files/rm', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: sources, + arg: path, ...options }), headers: options.headers @@ -23,6 +25,5 @@ module.exports = configure(api => { await res.text() } - return rm }) diff --git a/packages/ipfs-http-client/src/files/stat.js b/packages/ipfs-http-client/src/files/stat.js index 6df5e31c62..da07682204 100644 --- a/packages/ipfs-http-client/src/files/stat.js +++ b/packages/ipfs-http-client/src/files/stat.js @@ -5,12 +5,17 @@ const toCamelWithMetadata = require('../lib/object-to-camel-with-metadata') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["stat"]} */ async function stat (path, options = {}) { - if (typeof path !== 'string') { + if (path && !CID.isCID(path) && typeof path !== 'string') { options = path || {} path = '/' } @@ -29,10 +34,12 @@ module.exports = configure(api => { data.WithLocality = data.WithLocality || false return toCoreInterface(toCamelWithMetadata(data)) } - return stat }) +/** + * @param {*} entry + */ function toCoreInterface (entry) { entry.cid = new CID(entry.hash) delete entry.hash diff --git a/packages/ipfs-http-client/src/files/touch.js b/packages/ipfs-http-client/src/files/touch.js index 743c3230c1..ad0fb6982c 100644 --- a/packages/ipfs-http-client/src/files/touch.js +++ b/packages/ipfs-http-client/src/files/touch.js @@ -3,9 +3,14 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["touch"]} */ async function touch (path, options = {}) { const res = await api.post('files/touch', { @@ -20,6 +25,5 @@ module.exports = configure(api => { await res.text() } - return touch }) diff --git a/packages/ipfs-http-client/src/files/utils.js b/packages/ipfs-http-client/src/files/utils.js deleted file mode 100644 index 4856b30f50..0000000000 --- a/packages/ipfs-http-client/src/files/utils.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' - -exports.findSources = (args) => { - /** @type {Record} */ - let options = {} - let sources = [] - - if (!Array.isArray(args[args.length - 1]) && typeof args[args.length - 1] === 'object') { - options = args.pop() - } - - if (args.length === 1 && Array.isArray(args[0])) { - // support ipfs.files.cp([src, dest], opts) - sources = args[0] - } else { - // support ipfs.files.cp(src, dest, opts) and ipfs.files.cp(src1, src2, dest, opts) - sources = args - } - - return { - sources, - options - } -} diff --git a/packages/ipfs-http-client/src/files/write.js b/packages/ipfs-http-client/src/files/write.js index 917078613f..f553478280 100644 --- a/packages/ipfs-http-client/src/files/write.js +++ b/packages/ipfs-http-client/src/files/write.js @@ -1,16 +1,21 @@ 'use strict' const modeToString = require('../lib/mode-to-string') -const { mtimeToObject } = require('ipfs-core-utils/src/files/normalise-input/utils') +const { parseMtime } = require('ipfs-unixfs') const configure = require('../lib/configure') const multipartRequest = require('../lib/multipart-request') const toUrlSearchParams = require('../lib/to-url-search-params') const abortSignal = require('../lib/abort-signal') const { AbortController } = require('native-abort-controller') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI + */ + module.exports = configure(api => { /** - * @type {import('..').Implements} + * @type {FilesAPI["write"]} */ async function write (path, input, options = {}) { // allow aborting requests on body errors @@ -32,13 +37,12 @@ module.exports = configure(api => { content: input, path: 'arg', mode: modeToString(options.mode), - mtime: mtimeToObject(options.mtime) + mtime: parseMtime(options.mtime) }, controller, options.headers) ) }) await res.text() } - return write }) diff --git a/packages/ipfs-http-client/src/get.js b/packages/ipfs-http-client/src/get.js index b0ed304d4a..5573c85c26 100644 --- a/packages/ipfs-http-client/src/get.js +++ b/packages/ipfs-http-client/src/get.js @@ -1,14 +1,20 @@ 'use strict' +// @ts-ignore no types const Tar = require('it-tar') const CID = require('cids') const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') const map = require('it-map') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { /** - * @type {import('.').Implements} + * @type {RootAPI["get"]} */ async function * get (path, options = {}) { const res = await api.post('get', { diff --git a/packages/ipfs-http-client/src/id.js b/packages/ipfs-http-client/src/id.js index 28b2e3ff98..c7d19610ed 100644 --- a/packages/ipfs-http-client/src/id.js +++ b/packages/ipfs-http-client/src/id.js @@ -5,9 +5,14 @@ const multiaddr = require('multiaddr') const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { /** - * @type {import('.').Implements} + * @type {RootAPI["id"]} */ async function id (options = {}) { const res = await api.post('id', { @@ -18,12 +23,15 @@ module.exports = configure(api => { }) const data = await res.json() - const output = toCamel(data) + const output = { + ...toCamel(data) + } if (output.addresses) { - output.addresses = output.addresses.map(ma => multiaddr(ma)) + output.addresses = output.addresses.map((/** @type {string} */ ma) => multiaddr(ma)) } + // @ts-ignore server output is not typed return output } return id diff --git a/packages/ipfs-http-client/src/index.js b/packages/ipfs-http-client/src/index.js index 11c2ad9d9f..5172ceec27 100644 --- a/packages/ipfs-http-client/src/index.js +++ b/packages/ipfs-http-client/src/index.js @@ -10,10 +10,16 @@ const globSource = require('ipfs-utils/src/files/glob-source') const urlSource = require('ipfs-utils/src/files/url-source') /** - * @param {import("./lib/core").ClientOptions} options + * @typedef {import('./types').EndpointConfig} EndpointConfig + * @typedef {import('./types').Options} Options */ -function ipfsClient (options = {}) { - return { + +/** + * @param {Options} options + */ +function create (options = {}) { + /** @type {import('ipfs-core-types').IPFS & { getEndpointConfig: () => EndpointConfig }} */ + const client = { add: require('./add')(options), addAll: require('./add-all')(options), bitswap: require('./bitswap')(options), @@ -30,6 +36,7 @@ function ipfsClient (options = {}) { get: require('./get')(options), getEndpointConfig: require('./get-endpoint-config')(options), id: require('./id')(options), + isOnline: require('./is-online')(options), key: require('./key')(options), log: require('./log')(options), ls: require('./ls')(options), @@ -42,51 +49,23 @@ function ipfsClient (options = {}) { refs: require('./refs')(options), repo: require('./repo')(options), resolve: require('./resolve')(options), + start: require('./start')(options), stats: require('./stats')(options), stop: require('./stop')(options), - shutdown: require('./stop')(options), swarm: require('./swarm')(options), version: require('./version')(options) } -} - -Object.assign(ipfsClient, { CID, multiaddr, multibase, multicodec, multihash, globSource, urlSource }) - -module.exports = ipfsClient - -/** - * @typedef {Object} HttpOptions - * @property {Headers | Record} [headers] - An object or [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) instance that can be used to set custom HTTP headers. Note that this option can also be [configured globally](#custom-headers) via the constructor options. - * @property {URLSearchParams | Record} [searchParams] - An object or [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) instance that can be used to add additional query parameters to the query string sent with each request. - * - * @typedef {import('ipfs-core/src/utils').AbortOptions} AbortOptions} - */ -/** - * This is an utility type that can be used to derive type of the HTTP Client - * API from the Core API. It takes type of the API factory (from ipfs-core), - * derives API from it's return type and extends it last `options` parameter - * with `HttpOptions`. - * - * This can be used to avoid (re)typing API interface when implementing it in - * http client e.g you can annotate `ipfs.addAll` implementation with - * - * `@type {Implements}` - * - * **Caution**: This supports APIs with up to four parameters and last optional - * `options` parameter, anything else will result to `never` type. - * - * @template {(config:any) => any} APIFactory - * @typedef {APIWithExtraOptions, HttpOptions>} Implements - */ - -/** - * @template Key - * @template {(config:any) => any} APIFactory - * @typedef {import('./interface').APIMethodWithExtraOptions, Key, HttpOptions>} ImplementsMethod - */ + return client +} -/** - * @template API, Extra - * @typedef {import('./interface').APIWithExtraOptions} APIWithExtraOptions - */ +module.exports = { + create, + CID, + multiaddr, + multibase, + multicodec, + multihash, + globSource, + urlSource +} diff --git a/packages/ipfs-http-client/src/interface.ts b/packages/ipfs-http-client/src/interface.ts deleted file mode 100644 index d70df28957..0000000000 --- a/packages/ipfs-http-client/src/interface.ts +++ /dev/null @@ -1,57 +0,0 @@ -// This file contains some utility types that either can't be expressed in -// JSDoc syntax or that result in a different behaviour when typed in JSDoc. - -/** - * Utility type that takes IPFS Core API function type (with 0 to 4 arguments - * & last **optional** `options` parameter) and derives a function type with - * `options` parameter extended with given `Extra` options. - * - * **Caution**: API Functions with more than for arguments ahead of `options` - * will result to `never` type. API function that does not take `options` will - * result in function whose last argument is extended with `Extra` which would - * be an error. - */ -// This is typed in TS file because otherwise TS unifies on the first parameter -// regardless of number of parameters function has. -export interface APIWithExtraOptions any, Extra> { (...args: WithExtendedOptions, Extra>): ReturnType } - -type End = never[] -type WithExtendedOptions = Params extends [...End] - ? [] - // (options?: Options) -> (options?: Options & Ext) - : Params extends [options?: infer Options, ...end: End] - ? [options?: Options & Ext] - // (a: A1, options?: Options) -> (a1: A1, options?: Options & Ext) - : Params extends [a1: infer A1, options?: infer Options, ...end: End] - ? [a1: A1, options?: Options & Ext] - // (a1?: A1, options?: Options) -> (a1?: A1, options?: Options & Ext) - : Params extends [a1?: infer A1, options?: infer Options, ...end: End] - ? [a1?: A1, options?: Options & Ext] - // (a1: A1, a2: A2, options?: Options) -> (a1: A1, a2: A2 options?: Options & Ext) - : Params extends [a1: infer A1, a2: infer A2, options?: infer Options, ...end: End] - ? [a1: A1, a2: A2, options?: Options & Ext] - // (a1: A1, a2?: A2, options?: Options) -> (a1: A1, a2?: A2 options?: Options & Ext) - : Params extends [a1: infer A1, a2?: infer A2, options?: infer Options, ...end: End] - ? [a1: A1, a2?: A2, options?: Options & Ext] - // (a1: A1, a2?: A2, options?: Options) -> (a1: A1, a2?: A2 options?: Options & Ext) - : Params extends [a1?: infer A1, a2?: infer A2, options?: infer Options, ...end: End] - ? [a1?: A1, a2?: A2, options?: Options & Ext] - // (a1: A1, a2: A2, a3:A3 options?: Options) -> (a1: A1, a2: A2, a3:A3, options?: Options & Ext) - : Params extends [a1: infer A1, a2: infer A2, a3:infer A3, options?: infer Options, ...end: End] - ? [a1: A1, a2: A2, a3: A3, options?: Options & Ext] - // (a1: A1, a2: A2, a3?:A3 options?: Options) -> (a1: A1, a2: A2, a3?:A3, options?: Options & Ext) - : Params extends [a1: infer A1, a2:infer A2, a3?: infer A3, options?: infer Options, ...end: End] - ? [a1: A1, a2: A2, a3?: A3, options?: Options & Ext] - // (a1: A1, a2?: A2, a3?:A3 options?: Options) -> (a1: A1, a2?: A2, a3?:A3, options?: Options & Ext) - : Params extends [a1: infer A1, a2?: infer A2, a3?: infer A3, options?: infer Options, ...end: End] - ? [a1: A1, a2?: A2, a3?: A3, options?: Options & Ext] - // (a1?: A1, a2?: A2, a3?:A3 options?: Options) -> (a1?: A1, a2?: A2, a3?:A3, options?: Options & Ext) - : Params extends [a1?: infer A1, a2?: infer A2, a3?: infer A3, options?: infer Options, ...end: End] - ? [a1?: A1, a2?: A2, a3?: A3, options?: Options & Ext] - : never - -export type APIMethodWithExtraOptions < - API, - Key extends keyof API, - Extra -> = API[Key] extends (...args: any[]) => any ? APIWithExtraOptions : never diff --git a/packages/ipfs-http-client/src/is-online.js b/packages/ipfs-http-client/src/is-online.js new file mode 100644 index 0000000000..45ef706ff6 --- /dev/null +++ b/packages/ipfs-http-client/src/is-online.js @@ -0,0 +1,25 @@ +'use strict' + +const callId = require('./id') + +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + +/** + * @param {import('./types').Options} options + */ +module.exports = options => { + const id = callId(options) + + /** + * @type {RootAPI["isOnline"]} + */ + async function isOnline (options = {}) { + const res = await id(options) + + return Boolean(res && res.addresses && res.addresses.length) + } + return isOnline +} diff --git a/packages/ipfs-http-client/src/key/export.js b/packages/ipfs-http-client/src/key/export.js new file mode 100644 index 0000000000..285d3ab988 --- /dev/null +++ b/packages/ipfs-http-client/src/key/export.js @@ -0,0 +1,19 @@ +'use strict' + +const configure = require('../lib/configure') + +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/key').API} KeyAPI + */ + +module.exports = configure(api => { + /** + * @type {KeyAPI["export"]} + */ + const exportKey = async (name, password, options = {}) => { + throw new Error('Not implemented') + } + + return exportKey +}) diff --git a/packages/ipfs-http-client/src/key/gen.js b/packages/ipfs-http-client/src/key/gen.js index fdb21a00d7..f838e2b7b8 100644 --- a/packages/ipfs-http-client/src/key/gen.js +++ b/packages/ipfs-http-client/src/key/gen.js @@ -4,8 +4,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/key').API} KeyAPI + */ + module.exports = configure(api => { - return async (name, options = {}) => { + /** + * @type {KeyAPI["gen"]} + */ + async function gen (name, options = { type: 'rsa', size: 2048 }) { const res = await api.post('key/gen', { timeout: options.timeout, signal: options.signal, @@ -17,6 +25,8 @@ module.exports = configure(api => { }) const data = await res.json() + // @ts-ignore server output is not typed return toCamel(data) } + return gen }) diff --git a/packages/ipfs-http-client/src/key/import.js b/packages/ipfs-http-client/src/key/import.js index 9c68120739..006a296ab4 100644 --- a/packages/ipfs-http-client/src/key/import.js +++ b/packages/ipfs-http-client/src/key/import.js @@ -4,13 +4,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -module.exports = configure(api => { - return async (name, pem, password, options = {}) => { - if (typeof password !== 'string') { - options = password || {} - password = null - } +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/key').API} KeyAPI + */ +module.exports = configure(api => { + /** + * @type {KeyAPI["import"]} + */ + async function importKey (name, pem, password, options = {}) { const res = await api.post('key/import', { timeout: options.timeout, signal: options.signal, @@ -24,6 +27,8 @@ module.exports = configure(api => { }) const data = await res.json() + // @ts-ignore server output is not typed return toCamel(data) } + return importKey }) diff --git a/packages/ipfs-http-client/src/key/index.js b/packages/ipfs-http-client/src/key/index.js index c9d9c59f08..7249739814 100644 --- a/packages/ipfs-http-client/src/key/index.js +++ b/packages/ipfs-http-client/src/key/index.js @@ -1,9 +1,14 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ gen: require('./gen')(config), list: require('./list')(config), rename: require('./rename')(config), rm: require('./rm')(config), - import: require('./import')(config) + import: require('./import')(config), + export: require('./export')(config), + info: require('./info')(config) }) diff --git a/packages/ipfs-http-client/src/key/info.js b/packages/ipfs-http-client/src/key/info.js new file mode 100644 index 0000000000..4b5948082f --- /dev/null +++ b/packages/ipfs-http-client/src/key/info.js @@ -0,0 +1,19 @@ +'use strict' + +const configure = require('../lib/configure') + +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/key').API} KeyAPI + */ + +module.exports = configure(api => { + /** + * @type {KeyAPI["info"]} + */ + const info = async (name, options = {}) => { + throw new Error('Not implemented') + } + + return info +}) diff --git a/packages/ipfs-http-client/src/key/list.js b/packages/ipfs-http-client/src/key/list.js index 868c7b81f6..7dbc55147a 100644 --- a/packages/ipfs-http-client/src/key/list.js +++ b/packages/ipfs-http-client/src/key/list.js @@ -4,8 +4,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/key').API} KeyAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {KeyAPI["list"]} + */ + async function list (options = {}) { const res = await api.post('key/list', { timeout: options.timeout, signal: options.signal, @@ -14,6 +22,8 @@ module.exports = configure(api => { }) const data = await res.json() - return (data.Keys || []).map(k => toCamel(k)) + // @ts-ignore server output is not typed + return (data.Keys || []).map((/** @type {any} **/ k) => toCamel(k)) } + return list }) diff --git a/packages/ipfs-http-client/src/key/rename.js b/packages/ipfs-http-client/src/key/rename.js index d435b167c9..b891574c97 100644 --- a/packages/ipfs-http-client/src/key/rename.js +++ b/packages/ipfs-http-client/src/key/rename.js @@ -4,8 +4,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/key').API} KeyAPI + */ + module.exports = configure(api => { - return async (oldName, newName, options = {}) => { + /** + * @type {KeyAPI["rename"]} + */ + async function rename (oldName, newName, options = {}) { const res = await api.post('key/rename', { timeout: options.timeout, signal: options.signal, @@ -19,6 +27,8 @@ module.exports = configure(api => { headers: options.headers }) + // @ts-ignore server output is not typed return toCamel(await res.json()) } + return rename }) diff --git a/packages/ipfs-http-client/src/key/rm.js b/packages/ipfs-http-client/src/key/rm.js index 47b8124e3a..f1c87f8b07 100644 --- a/packages/ipfs-http-client/src/key/rm.js +++ b/packages/ipfs-http-client/src/key/rm.js @@ -4,8 +4,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/key').API} KeyAPI + */ + module.exports = configure(api => { - return async (name, options = {}) => { + /** + * @type {KeyAPI["rm"]} + */ + async function rm (name, options = {}) { const res = await api.post('key/rm', { timeout: options.timeout, signal: options.signal, @@ -17,6 +25,8 @@ module.exports = configure(api => { }) const data = await res.json() + // @ts-ignore server output is not typed return toCamel(data.Keys[0]) } + return rm }) diff --git a/packages/ipfs-http-client/src/lib/abort-signal.js b/packages/ipfs-http-client/src/lib/abort-signal.js index c12e44c921..7cff01ef46 100644 --- a/packages/ipfs-http-client/src/lib/abort-signal.js +++ b/packages/ipfs-http-client/src/lib/abort-signal.js @@ -3,13 +3,10 @@ const { anySignal } = require('any-signal') /** - * @typedef {AbortSignal | undefined} MaybeSignal - * - * @param {MaybeSignal[]} signals + * @param {any[]} signals * @returns {AbortSignal[]} */ function filter (signals) { - // @ts-ignore return signals.filter(Boolean) } diff --git a/packages/ipfs-http-client/src/lib/buffer-to-form-data.browser.js b/packages/ipfs-http-client/src/lib/buffer-to-form-data.browser.js index dab8da9ce2..e93b010949 100644 --- a/packages/ipfs-http-client/src/lib/buffer-to-form-data.browser.js +++ b/packages/ipfs-http-client/src/lib/buffer-to-form-data.browser.js @@ -1,6 +1,9 @@ 'use strict' /* eslint-env browser */ +/** + * @param {Uint8Array} buf + */ module.exports = buf => { const formData = new FormData() formData.append('file', new Blob([buf], { type: 'application/octet-stream' })) diff --git a/packages/ipfs-http-client/src/lib/buffer-to-form-data.js b/packages/ipfs-http-client/src/lib/buffer-to-form-data.js index 695c052c2b..43be9ce180 100644 --- a/packages/ipfs-http-client/src/lib/buffer-to-form-data.js +++ b/packages/ipfs-http-client/src/lib/buffer-to-form-data.js @@ -2,9 +2,7 @@ const FormData = require('form-data') -// TODO form data append doesnt have header option - -// @ts-ignore +// @ts-ignore TODO form data append doesn't have header option module.exports = (buf, { mode, mtime, mtimeNsecs } = {}) => { const headers = {} diff --git a/packages/ipfs-http-client/src/lib/configure.js b/packages/ipfs-http-client/src/lib/configure.js index 6396c05d1d..79e5a1f546 100644 --- a/packages/ipfs-http-client/src/lib/configure.js +++ b/packages/ipfs-http-client/src/lib/configure.js @@ -5,17 +5,17 @@ const Client = require('./core') // Set default configuration and call create function with them /** - * @typedef { import("./core").ClientOptions } ClientOptions + * @typedef { import("../types").Options } Options */ /** * @template T - * @typedef {(client: Client, clientOptions: ClientOptions) => T} Fn + * @typedef {(client: Client, clientOptions: Options) => T} Fn */ /** * @template T - * @typedef {(clientOptions: ClientOptions) => T} Factory + * @typedef {(clientOptions: Options) => T} Factory */ /** diff --git a/packages/ipfs-http-client/src/lib/core.js b/packages/ipfs-http-client/src/lib/core.js index 3b8d2e315d..744b143c72 100644 --- a/packages/ipfs-http-client/src/lib/core.js +++ b/packages/ipfs-http-client/src/lib/core.js @@ -15,11 +15,19 @@ const DEFAULT_HOST = isBrowser || isWebWorker ? location.hostname : 'localhost' const DEFAULT_PORT = isBrowser || isWebWorker ? location.port : '5001' /** - * @param {ClientOptions|URL|Multiaddr|string} [options] - * @returns {ClientOptions} + * @typedef {import('electron-fetch').Response} Response + * @typedef {import('ipfs-utils/dist/types/electron-fetch').Request} Request + * @typedef {import('ipfs-utils/src/types').HTTPOptions} HTTPOptions + * @typedef {import('../types').Options} Options + */ + +/** + * @param {Options|URL|Multiaddr|string} [options] + * @returns {Options} */ const normalizeOptions = (options = {}) => { let url + /** @type {Options} */ let opts = {} let agent @@ -70,6 +78,9 @@ const normalizeOptions = (options = {}) => { } } +/** + * @param {Response} response + */ const errorHandler = async (response) => { let msg @@ -92,12 +103,12 @@ const errorHandler = async (response) => { // This is what go-ipfs returns where there's a timeout if (msg && msg.includes('context deadline exceeded')) { - error = new HTTP.TimeoutError(response) + error = new HTTP.TimeoutError('Request timed out') } // This also gets returned if (msg && msg.includes('request timed out')) { - error = new HTTP.TimeoutError(response) + error = new HTTP.TimeoutError('Request timed out') } // If we managed to extract a message from the response, use it @@ -109,42 +120,32 @@ const errorHandler = async (response) => { } const KEBAB_REGEX = /[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g + +/** + * @param {string} str + */ const kebabCase = (str) => { return str.replace(KEBAB_REGEX, function (match) { return '-' + match.toLowerCase() }) } +/** + * @param {string | number} value + */ const parseTimeout = (value) => { return typeof value === 'string' ? parseDuration(value) : value } -/** - * @typedef {import('http').Agent} HttpAgent - * @typedef {import('https').Agent} HttpsAgent - * - * @typedef {Object} ClientOptions - * @property {string} [host] - * @property {number} [port] - * @property {string} [protocol] - * @property {Headers|Record} [headers] - Request headers. - * @property {number|string} [timeout] - Amount of time until request should timeout in ms or humand readable. https://www.npmjs.com/package/parse-duration for valid string values. - * @property {string} [apiPath] - Path to the API. - * @property {URL|string|Multiaddr} [url] - Full API URL. - * @property {object} [ipld] - * @property {any[]} [ipld.formats] - An array of additional [IPLD formats](https://github.com/ipld/interface-ipld-format) to support - * @property {(format: string) => Promise} [ipld.loadFormat] - an async function that takes the name of an [IPLD format](https://github.com/ipld/interface-ipld-format) as a string and should return the implementation of that codec - * @property {HttpAgent|HttpsAgent} [agent] - A [http.Agent](https://nodejs.org/api/http.html#http_class_http_agent) used to control connection persistence and reuse for HTTP clients (only supported in node.js) - */ class Client extends HTTP { /** - * @param {ClientOptions|URL|Multiaddr|string} [options] + * @param {Options|URL|Multiaddr|string} [options] */ constructor (options = {}) { const opts = normalizeOptions(options) super({ - timeout: parseTimeout(opts.timeout) || 60000 * 20, + timeout: parseTimeout(opts.timeout || 0) || 60000 * 20, headers: opts.headers, base: `${opts.url}`, handleError: errorHandler, @@ -173,17 +174,22 @@ class Client extends HTTP { agent: opts.agent }) - // @ts-ignore + // @ts-ignore - cannot delete no-optional fields delete this.get - // @ts-ignore + // @ts-ignore - cannot delete no-optional fields delete this.put - // @ts-ignore + // @ts-ignore - cannot delete no-optional fields delete this.delete - // @ts-ignore + // @ts-ignore - cannot delete no-optional fields delete this.options const fetch = this.fetch + /** + * @param {string | Request} resource + * @param {HTTPOptions} options + * @returns {Promise} + */ this.fetch = (resource, options = {}) => { if (typeof resource === 'string' && !resource.startsWith('/')) { resource = `${opts.url}/${resource}` diff --git a/packages/ipfs-http-client/src/lib/ipld-formats.js b/packages/ipfs-http-client/src/lib/ipld-formats.js index 7348b8505a..235fc9b7e1 100644 --- a/packages/ipfs-http-client/src/lib/ipld-formats.js +++ b/packages/ipfs-http-client/src/lib/ipld-formats.js @@ -5,19 +5,25 @@ const dagCBOR = require('ipld-dag-cbor') const raw = require('ipld-raw') const multicodec = require('multicodec') -const noop = () => {} - /** * @typedef {import('cids')} CID + * @typedef {import('interface-ipld-format').Format} IPLDFormat + * @typedef {import('ipld').LoadFormatFn} LoadFormatFn */ +/** + * @type {LoadFormatFn} + */ +const noop = (codec) => { + return Promise.reject(new Error(`Missing IPLD format "${codec}"`)) +} + /** * Return an object containing supported IPLD Formats * * @param {object} [options] - IPLD options passed to the http client constructor - * @param {Array} [options.formats] - A list of IPLD Formats to use - * @param {Function} [options.loadFormat] - An async function that can load a format when passed a codec number - * @returns {Function} + * @param {IPLDFormat[]} [options.formats] - A list of IPLD Formats to use + * @param {import('ipld').LoadFormatFn} [options.loadFormat] - An async function that can load a format when passed a codec number */ module.exports = ({ formats = [], loadFormat = noop } = {}) => { formats = formats || [] @@ -37,7 +43,6 @@ module.exports = ({ formats = [], loadFormat = noop } = {}) => { * Attempts to load an IPLD format for the passed CID * * @param {import('multicodec').CodecName} codec - The code to load the format for - * @returns {Promise} - An IPLD format */ const loadResolver = async (codec) => { // @ts-ignore - codec is a string and not a CodecName diff --git a/packages/ipfs-http-client/src/lib/mode-to-string.js b/packages/ipfs-http-client/src/lib/mode-to-string.js index ee2742b9a3..a6a378cfe4 100644 --- a/packages/ipfs-http-client/src/lib/mode-to-string.js +++ b/packages/ipfs-http-client/src/lib/mode-to-string.js @@ -1,11 +1,14 @@ 'use strict' +/** + * @param {number | string | undefined} mode + */ module.exports = (mode) => { - if (mode === undefined || mode === null) { + if (mode == null) { return undefined } - if (typeof mode === 'string' || mode instanceof String) { + if (typeof mode === 'string') { return mode } diff --git a/packages/ipfs-http-client/src/lib/multipart-request.browser.js b/packages/ipfs-http-client/src/lib/multipart-request.browser.js index 6e48cd80b7..290ad0db3c 100644 --- a/packages/ipfs-http-client/src/lib/multipart-request.browser.js +++ b/packages/ipfs-http-client/src/lib/multipart-request.browser.js @@ -5,12 +5,23 @@ const normaliseInput = require('ipfs-core-utils/src/files/normalise-input/index.browser') const modeToString = require('./mode-to-string') -async function multipartRequest (source = '', abortController, headers = {}) { +/** + * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource + * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + */ + +/** + * @param {ImportSource|ToEntry} source + * @param {AbortController} abortController + * @param {Headers|Record} [headers] + */ +async function multipartRequest (source, abortController, headers = {}) { const parts = [] const formData = new FormData() let index = 0 let total = 0 + // @ts-ignore wrong input type for normaliseInput for await (const { content, path, mode, mtime } of normaliseInput(source)) { let fileSuffix = '' const type = content ? 'file' : 'dir' @@ -41,12 +52,14 @@ async function multipartRequest (source = '', abortController, headers = {}) { } if (content) { - formData.set(fieldName, content, encodeURIComponent(path)) + formData.set(fieldName, content, path != null ? encodeURIComponent(path) : undefined) const end = total + content.size parts.push({ name: path, start: total, end }) total = end - } else { + } else if (path != null) { formData.set(fieldName, new File([''], encodeURIComponent(path), { type: 'application/x-directory' })) + } else { + throw new Error('path or content or both must be set') } index++ diff --git a/packages/ipfs-http-client/src/lib/multipart-request.node.js b/packages/ipfs-http-client/src/lib/multipart-request.node.js index 61d82c12e4..d2e69ded30 100644 --- a/packages/ipfs-http-client/src/lib/multipart-request.node.js +++ b/packages/ipfs-http-client/src/lib/multipart-request.node.js @@ -4,20 +4,29 @@ const normaliseInput = require('ipfs-core-utils/src/files/normalise-input') const { nanoid } = require('nanoid') const modeToString = require('./mode-to-string') const merge = require('merge-options').bind({ ignoreUndefined: true }) +// @ts-ignore no types const toStream = require('it-to-stream') /** - * - * @param {Object} source + * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource + * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + */ + +/** + * @param {ImportSource|ToEntry} source * @param {AbortController} abortController * @param {Headers|Record} [headers] * @param {string} [boundary] */ -async function multipartRequest (source = '', abortController, headers = {}, boundary = `-----------------------------${nanoid()}`) { +async function multipartRequest (source, abortController, headers = {}, boundary = `-----------------------------${nanoid()}`) { + /** + * @param {ImportSource|ToEntry} source + */ async function * streamFiles (source) { try { let index = 0 + // @ts-ignore wrong input type for normaliseInput for await (const { content, path, mode, mtime } of normaliseInput(source)) { let fileSuffix = '' const type = content ? 'file' : 'dir' @@ -50,7 +59,7 @@ async function multipartRequest (source = '', abortController, headers = {}, bou } yield `--${boundary}\r\n` - yield `Content-Disposition: form-data; name="${fieldName}"; filename="${encodeURIComponent(path)}"\r\n` + yield `Content-Disposition: form-data; name="${fieldName}"; filename="${encodeURIComponent(path || '')}"\r\n` yield `Content-Type: ${content ? 'application/octet-stream' : 'application/x-directory'}\r\n` yield '\r\n' @@ -60,10 +69,9 @@ async function multipartRequest (source = '', abortController, headers = {}, bou index++ } - } catch (err) { + } catch { // workaround for https://github.com/node-fetch/node-fetch/issues/753 - // @ts-ignore - abort does not expect an arguments - abortController.abort(err) + abortController.abort() } finally { yield `\r\n--${boundary}--\r\n` } diff --git a/packages/ipfs-http-client/src/lib/object-to-camel-with-metadata.js b/packages/ipfs-http-client/src/lib/object-to-camel-with-metadata.js index 55f16d0bb3..0612d73011 100644 --- a/packages/ipfs-http-client/src/lib/object-to-camel-with-metadata.js +++ b/packages/ipfs-http-client/src/lib/object-to-camel-with-metadata.js @@ -2,6 +2,9 @@ const toCamel = require('./object-to-camel') +/** + * @param {Record} entry + */ function toCamelWithMetadata (entry) { const file = toCamel(entry) diff --git a/packages/ipfs-http-client/src/lib/object-to-camel.js b/packages/ipfs-http-client/src/lib/object-to-camel.js index f13b2b6a17..fa74cd184e 100644 --- a/packages/ipfs-http-client/src/lib/object-to-camel.js +++ b/packages/ipfs-http-client/src/lib/object-to-camel.js @@ -1,13 +1,24 @@ 'use strict' -// Convert object properties to camel case. -// NOT recursive! -// e.g. -// AgentVersion => agentVersion -// ID => id +/** + * Convert object properties to camel case. + * NOT recursive! + * e.g. + * AgentVersion => agentVersion + * ID => id + * + * @param {Record} obj + */ module.exports = obj => { - if (obj == null) return obj + if (obj == null) { + return obj + } + const caps = /^[A-Z]+$/ + + /** @type {Record} */ + const output = {} + return Object.keys(obj).reduce((camelObj, k) => { if (caps.test(k)) { // all caps camelObj[k.toLowerCase()] = obj[k] @@ -17,5 +28,5 @@ module.exports = obj => { camelObj[k] = obj[k] } return camelObj - }, {}) + }, output) } diff --git a/packages/ipfs-http-client/src/lib/to-url-search-params.js b/packages/ipfs-http-client/src/lib/to-url-search-params.js index 2067b0be02..1125959b8a 100644 --- a/packages/ipfs-http-client/src/lib/to-url-search-params.js +++ b/packages/ipfs-http-client/src/lib/to-url-search-params.js @@ -1,7 +1,7 @@ 'use strict' const modeToString = require('./mode-to-string') -const { mtimeToObject } = require('ipfs-core-utils/src/files/normalise-input/utils') +const { parseMtime } = require('ipfs-unixfs') /** * @param {*} params @@ -20,7 +20,7 @@ module.exports = ({ arg, searchParams, hashAlg, mtime, mode, ...options } = {}) } if (mtime != null) { - mtime = mtimeToObject(mtime) + mtime = parseMtime(mtime) options.mtime = mtime.secs options.mtimeNsecs = mtime.nsecs @@ -43,7 +43,7 @@ module.exports = ({ arg, searchParams, hashAlg, mtime, mode, ...options } = {}) const urlSearchParams = new URLSearchParams(options) - arg.forEach(arg => urlSearchParams.append('arg', arg)) + arg.forEach((/** @type {any} */ arg) => urlSearchParams.append('arg', arg)) return urlSearchParams } diff --git a/packages/ipfs-http-client/src/log/index.js b/packages/ipfs-http-client/src/log/index.js index 3eea39fd5c..e9980e4b0e 100644 --- a/packages/ipfs-http-client/src/log/index.js +++ b/packages/ipfs-http-client/src/log/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ tail: require('./tail')(config), ls: require('./ls')(config), diff --git a/packages/ipfs-http-client/src/log/level.js b/packages/ipfs-http-client/src/log/level.js index 39f6396dda..4227bb684b 100644 --- a/packages/ipfs-http-client/src/log/level.js +++ b/packages/ipfs-http-client/src/log/level.js @@ -4,8 +4,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/log').API} LogAPI + */ + module.exports = configure(api => { - return async (subsystem, level, options = {}) => { + /** + * @type {LogAPI["level"]} + */ + async function level (subsystem, level, options = {}) { const res = await api.post('log/level', { timeout: options.timeout, signal: options.signal, @@ -21,4 +29,5 @@ module.exports = configure(api => { return toCamel(await res.json()) } + return level }) diff --git a/packages/ipfs-http-client/src/log/ls.js b/packages/ipfs-http-client/src/log/ls.js index d43c5f0c65..362018386c 100644 --- a/packages/ipfs-http-client/src/log/ls.js +++ b/packages/ipfs-http-client/src/log/ls.js @@ -3,8 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/log').API} LogAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {LogAPI["ls"]} + */ + async function ls (options = {}) { const res = await api.post('log/ls', { timeout: options.timeout, signal: options.signal, @@ -15,4 +23,5 @@ module.exports = configure(api => { const data = await res.json() return data.Strings } + return ls }) diff --git a/packages/ipfs-http-client/src/log/tail.js b/packages/ipfs-http-client/src/log/tail.js index e3238b19f8..443c3717c4 100644 --- a/packages/ipfs-http-client/src/log/tail.js +++ b/packages/ipfs-http-client/src/log/tail.js @@ -3,8 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/log').API} LogAPI + */ + module.exports = configure(api => { - return async function * tail (options = {}) { + /** + * @type {LogAPI["tail"]} + */ + async function * tail (options = {}) { const res = await api.post('log/tail', { timeout: options.timeout, signal: options.signal, @@ -14,4 +22,5 @@ module.exports = configure(api => { yield * res.ndjson() } + return tail }) diff --git a/packages/ipfs-http-client/src/ls.js b/packages/ipfs-http-client/src/ls.js index f51a9f640e..cec925d12b 100644 --- a/packages/ipfs-http-client/src/ls.js +++ b/packages/ipfs-http-client/src/ls.js @@ -5,10 +5,21 @@ const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') const stat = require('./files/stat') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure((api, opts) => { - return async function * ls (path, options = {}) { + /** + * @type {RootAPI["ls"]} + */ + async function * ls (path, options = {}) { const pathStr = `${path instanceof Uint8Array ? new CID(path) : path}` + /** + * @param {*} link + */ async function mapLink (link) { let hash = link.Hash @@ -20,6 +31,7 @@ module.exports = configure((api, opts) => { hash = stats.cid } + /** @type {import('ipfs-core-types/src/root').IPFSEntry} */ const entry = { name: link.Name, path: pathStr + (link.Name ? `/${link.Name}` : ''), @@ -83,8 +95,12 @@ module.exports = configure((api, opts) => { yield * links.map(mapLink) } } + return ls }) +/** + * @param {any} link + */ function typeOf (link) { switch (link.Type) { case 1: @@ -93,6 +109,6 @@ function typeOf (link) { case 2: return 'file' default: - return 'unknown' + return 'file' } } diff --git a/packages/ipfs-http-client/src/mount.js b/packages/ipfs-http-client/src/mount.js index 56b35e58e4..edb7734c5c 100644 --- a/packages/ipfs-http-client/src/mount.js +++ b/packages/ipfs-http-client/src/mount.js @@ -4,8 +4,16 @@ const toCamel = require('./lib/object-to-camel') const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {RootAPI["mount"]} + */ + async function mount (options = {}) { const res = await api.post('dns', { timeout: options.timeout, signal: options.signal, @@ -15,4 +23,5 @@ module.exports = configure(api => { return toCamel(await res.json()) } + return mount }) diff --git a/packages/ipfs-http-client/src/name/index.js b/packages/ipfs-http-client/src/name/index.js index 65d1acca28..5bca0fe588 100644 --- a/packages/ipfs-http-client/src/name/index.js +++ b/packages/ipfs-http-client/src/name/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ publish: require('./publish')(config), resolve: require('./resolve')(config), diff --git a/packages/ipfs-http-client/src/name/publish.js b/packages/ipfs-http-client/src/name/publish.js index 4d98221cc2..947dcbbcd2 100644 --- a/packages/ipfs-http-client/src/name/publish.js +++ b/packages/ipfs-http-client/src/name/publish.js @@ -4,8 +4,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/name').API} NameAPI + */ + module.exports = configure(api => { - return async (path, options = {}) => { + /** + * @type {NameAPI["publish"]} + */ + async function publish (path, options = {}) { const res = await api.post('name/publish', { timeout: options.timeout, signal: options.signal, @@ -16,6 +24,8 @@ module.exports = configure(api => { headers: options.headers }) + // @ts-ignore server output is not typed return toCamel(await res.json()) } + return publish }) diff --git a/packages/ipfs-http-client/src/name/pubsub/cancel.js b/packages/ipfs-http-client/src/name/pubsub/cancel.js index 28c483d466..3c6aa9fdd0 100644 --- a/packages/ipfs-http-client/src/name/pubsub/cancel.js +++ b/packages/ipfs-http-client/src/name/pubsub/cancel.js @@ -4,8 +4,16 @@ const toCamel = require('../../lib/object-to-camel') const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/name/pubsub').API} NamePubsubAPI + */ + module.exports = configure(api => { - return async (name, options = {}) => { + /** + * @type {NamePubsubAPI["cancel"]} + */ + async function cancel (name, options = {}) { const res = await api.post('name/pubsub/cancel', { timeout: options.timeout, signal: options.signal, @@ -16,6 +24,8 @@ module.exports = configure(api => { headers: options.headers }) + // @ts-ignore server output is not typed return toCamel(await res.json()) } + return cancel }) diff --git a/packages/ipfs-http-client/src/name/pubsub/index.js b/packages/ipfs-http-client/src/name/pubsub/index.js index 14ffd88527..b7fae5c5b5 100644 --- a/packages/ipfs-http-client/src/name/pubsub/index.js +++ b/packages/ipfs-http-client/src/name/pubsub/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../../types').Options} config + */ module.exports = config => ({ cancel: require('./cancel')(config), state: require('./state')(config), diff --git a/packages/ipfs-http-client/src/name/pubsub/state.js b/packages/ipfs-http-client/src/name/pubsub/state.js index 5d6a95d28c..97849b25a1 100644 --- a/packages/ipfs-http-client/src/name/pubsub/state.js +++ b/packages/ipfs-http-client/src/name/pubsub/state.js @@ -4,8 +4,16 @@ const toCamel = require('../../lib/object-to-camel') const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/name/pubsub').API} NamePubsubAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {NamePubsubAPI["state"]} + */ + async function state (options = {}) { const res = await api.post('name/pubsub/state', { timeout: options.timeout, signal: options.signal, @@ -13,6 +21,8 @@ module.exports = configure(api => { headers: options.headers }) + // @ts-ignore server output is not typed return toCamel(await res.json()) } + return state }) diff --git a/packages/ipfs-http-client/src/name/pubsub/subs.js b/packages/ipfs-http-client/src/name/pubsub/subs.js index bc4697868b..2827c6e42f 100644 --- a/packages/ipfs-http-client/src/name/pubsub/subs.js +++ b/packages/ipfs-http-client/src/name/pubsub/subs.js @@ -3,8 +3,16 @@ const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/name/pubsub').API} NamePubsubAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {NamePubsubAPI["subs"]} + */ + async function subs (options = {}) { const res = await api.post('name/pubsub/subs', { timeout: options.timeout, signal: options.signal, @@ -15,4 +23,5 @@ module.exports = configure(api => { return data.Strings || [] } + return subs }) diff --git a/packages/ipfs-http-client/src/name/resolve.js b/packages/ipfs-http-client/src/name/resolve.js index 27ea78ad5b..087f6f5519 100644 --- a/packages/ipfs-http-client/src/name/resolve.js +++ b/packages/ipfs-http-client/src/name/resolve.js @@ -3,8 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/name').API} NameAPI + */ + module.exports = configure(api => { - return async function * (path, options = {}) { + /** + * @type {NameAPI["resolve"]} + */ + async function * resolve (path, options = {}) { const res = await api.post('name/resolve', { timeout: options.timeout, signal: options.signal, @@ -20,4 +28,5 @@ module.exports = configure(api => { yield result.Path } } + return resolve }) diff --git a/packages/ipfs-http-client/src/object/data.js b/packages/ipfs-http-client/src/object/data.js index dfc87e5bcc..805472c3e9 100644 --- a/packages/ipfs-http-client/src/object/data.js +++ b/packages/ipfs-http-client/src/object/data.js @@ -4,8 +4,16 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object').API} ObjectAPI + */ + module.exports = configure(api => { - return async function data (cid, options = {}) { + /** + * @type {ObjectAPI["data"]} + */ + async function data (cid, options = {}) { const res = await api.post('object/data', { timeout: options.timeout, signal: options.signal, @@ -19,4 +27,5 @@ module.exports = configure(api => { return new Uint8Array(data, 0, data.byteLength) } + return data }) diff --git a/packages/ipfs-http-client/src/object/get.js b/packages/ipfs-http-client/src/object/get.js index 4857fe724a..0d6a8953d1 100644 --- a/packages/ipfs-http-client/src/object/get.js +++ b/packages/ipfs-http-client/src/object/get.js @@ -6,8 +6,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const uint8ArrayFromString = require('uint8arrays/from-string') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object').API} ObjectAPI + */ + module.exports = configure(api => { - return async (cid, options = {}) => { + /** + * @type {ObjectAPI["get"]} + */ + async function get (cid, options = {}) { const res = await api.post('object/get', { timeout: options.timeout, signal: options.signal, @@ -22,7 +30,8 @@ module.exports = configure(api => { return new DAGNode( uint8ArrayFromString(data.Data, 'base64pad'), - (data.Links || []).map(l => new DAGLink(l.Name, l.Size, l.Hash)) + (data.Links || []).map((/** @type {any} */ l) => new DAGLink(l.Name, l.Size, l.Hash)) ) } + return get }) diff --git a/packages/ipfs-http-client/src/object/index.js b/packages/ipfs-http-client/src/object/index.js index ee7c85dd68..e0c83027e5 100644 --- a/packages/ipfs-http-client/src/object/index.js +++ b/packages/ipfs-http-client/src/object/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ data: require('./data')(config), get: require('./get')(config), diff --git a/packages/ipfs-http-client/src/object/links.js b/packages/ipfs-http-client/src/object/links.js index 97f2f5b331..2582c51c6e 100644 --- a/packages/ipfs-http-client/src/object/links.js +++ b/packages/ipfs-http-client/src/object/links.js @@ -5,8 +5,16 @@ const { DAGLink } = require('ipld-dag-pb') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object').API} ObjectAPI + */ + module.exports = configure(api => { - return async (cid, options = {}) => { + /** + * @type {ObjectAPI["links"]} + */ + async function links (cid, options = {}) { const res = await api.post('object/links', { timeout: options.timeout, signal: options.signal, @@ -18,6 +26,7 @@ module.exports = configure(api => { }) const data = await res.json() - return (data.Links || []).map(l => new DAGLink(l.Name, l.Size, l.Hash)) + return (data.Links || []).map((/** @type {any} */ l) => new DAGLink(l.Name, l.Size, l.Hash)) } + return links }) diff --git a/packages/ipfs-http-client/src/object/new.js b/packages/ipfs-http-client/src/object/new.js index f0ae4e5574..eee675f39b 100644 --- a/packages/ipfs-http-client/src/object/new.js +++ b/packages/ipfs-http-client/src/object/new.js @@ -4,8 +4,16 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object').API} ObjectAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {ObjectAPI["new"]} + */ + async function newObject (options = {}) { const res = await api.post('object/new', { timeout: options.timeout, signal: options.signal, @@ -20,4 +28,5 @@ module.exports = configure(api => { return new CID(Hash) } + return newObject }) diff --git a/packages/ipfs-http-client/src/object/patch/add-link.js b/packages/ipfs-http-client/src/object/patch/add-link.js index ab8535406d..ef45de5c20 100644 --- a/packages/ipfs-http-client/src/object/patch/add-link.js +++ b/packages/ipfs-http-client/src/object/patch/add-link.js @@ -4,15 +4,25 @@ const CID = require('cids') const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object/patch').API} ObjectPatchAPI + */ + module.exports = configure(api => { - return async (cid, dLink, options = {}) => { + /** + * @type {ObjectPatchAPI["addLink"]} + */ + async function addLink (cid, dLink, options = {}) { const res = await api.post('object/patch/add-link', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ arg: [ `${cid instanceof Uint8Array ? new CID(cid) : cid}`, + // @ts-ignore loose types dLink.Name || dLink.name || '', + // @ts-ignore loose types (dLink.Hash || dLink.cid || '').toString() || null ], ...options @@ -24,4 +34,5 @@ module.exports = configure(api => { return new CID(Hash) } + return addLink }) diff --git a/packages/ipfs-http-client/src/object/patch/append-data.js b/packages/ipfs-http-client/src/object/patch/append-data.js index c7d8f67715..ee6deb8953 100644 --- a/packages/ipfs-http-client/src/object/patch/append-data.js +++ b/packages/ipfs-http-client/src/object/patch/append-data.js @@ -7,8 +7,16 @@ const toUrlSearchParams = require('../../lib/to-url-search-params') const abortSignal = require('../../lib/abort-signal') const { AbortController } = require('native-abort-controller') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object/patch').API} ObjectPatchAPI + */ + module.exports = configure(api => { - return async (cid, data, options = {}) => { + /** + * @type {ObjectPatchAPI["appendData"]} + */ + async function appendData (cid, data, options = {}) { // allow aborting requests on body errors const controller = new AbortController() const signal = abortSignal(controller.signal, options.signal) @@ -30,4 +38,5 @@ module.exports = configure(api => { return new CID(Hash) } + return appendData }) diff --git a/packages/ipfs-http-client/src/object/patch/index.js b/packages/ipfs-http-client/src/object/patch/index.js index f886e288fe..34b47b2f4c 100644 --- a/packages/ipfs-http-client/src/object/patch/index.js +++ b/packages/ipfs-http-client/src/object/patch/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../../types').Options} config + */ module.exports = config => ({ addLink: require('./add-link')(config), appendData: require('./append-data')(config), diff --git a/packages/ipfs-http-client/src/object/patch/rm-link.js b/packages/ipfs-http-client/src/object/patch/rm-link.js index 3a58238c08..8881e577ee 100644 --- a/packages/ipfs-http-client/src/object/patch/rm-link.js +++ b/packages/ipfs-http-client/src/object/patch/rm-link.js @@ -4,14 +4,23 @@ const CID = require('cids') const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object/patch').API} ObjectPatchAPI + */ + module.exports = configure(api => { - return async (cid, dLink, options = {}) => { + /** + * @type {ObjectPatchAPI["rmLink"]} + */ + async function rmLink (cid, dLink, options = {}) { const res = await api.post('object/patch/rm-link', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ arg: [ `${cid instanceof Uint8Array ? new CID(cid) : cid}`, + // @ts-ignore loose types dLink.Name || dLink.name || null ], ...options @@ -23,4 +32,5 @@ module.exports = configure(api => { return new CID(Hash) } + return rmLink }) diff --git a/packages/ipfs-http-client/src/object/patch/set-data.js b/packages/ipfs-http-client/src/object/patch/set-data.js index 84eedc6b64..06b4f21193 100644 --- a/packages/ipfs-http-client/src/object/patch/set-data.js +++ b/packages/ipfs-http-client/src/object/patch/set-data.js @@ -7,8 +7,16 @@ const toUrlSearchParams = require('../../lib/to-url-search-params') const abortSignal = require('../../lib/abort-signal') const { AbortController } = require('native-abort-controller') +/** + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object/patch').API} ObjectPatchAPI + */ + module.exports = configure(api => { - return async (cid, data, options = {}) => { + /** + * @type {ObjectPatchAPI["setData"]} + */ + async function setData (cid, data, options = {}) { // allow aborting requests on body errors const controller = new AbortController() const signal = abortSignal(controller.signal, options.signal) @@ -30,4 +38,5 @@ module.exports = configure(api => { return new CID(Hash) } + return setData }) diff --git a/packages/ipfs-http-client/src/object/put.js b/packages/ipfs-http-client/src/object/put.js index abf6b203ff..81974122bf 100644 --- a/packages/ipfs-http-client/src/object/put.js +++ b/packages/ipfs-http-client/src/object/put.js @@ -7,25 +7,38 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const abortSignal = require('../lib/abort-signal') const { AbortController } = require('native-abort-controller') -const unit8ArrayToString = require('uint8arrays/to-string') +const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayFromString = require('uint8arrays/from-string') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object').API} ObjectAPI + */ + module.exports = configure(api => { - return async (obj, options = {}) => { + /** + * @type {ObjectAPI["put"]} + */ + async function put (obj, options = {}) { let tmpObj = { + /** @type {string | undefined} */ + Data: undefined, + /** @type {{ Name: string, Hash: string, Size: number }[]} */ Links: [] } if (obj instanceof Uint8Array) { if (!options.enc) { tmpObj = { - Data: unit8ArrayToString(obj), + // FIXME: this will corrupt data for byte values over 127 + Data: uint8ArrayToString(obj), Links: [] } } - } else if (DAGNode.isDAGNode(obj)) { + } else if (obj instanceof DAGNode) { tmpObj = { - Data: unit8ArrayToString(obj.Data), + // FIXME: this will corrupt data for byte values over 127 + Data: uint8ArrayToString(obj.Data), Links: obj.Links.map(l => ({ Name: l.Name, Hash: l.Hash.toString(), @@ -33,8 +46,15 @@ module.exports = configure(api => { })) } } else if (typeof obj === 'object') { - tmpObj.Data = unit8ArrayToString(obj.Data) - tmpObj.Links = obj.Links + // FIXME: this will corrupt data for for byte values over 127 + if (obj.Data) { + tmpObj.Data = uint8ArrayToString(obj.Data) + } + + if (obj.Links) { + // @ts-ignore Size is Tsize + tmpObj.Links = obj.Links + } } else { throw new Error('obj not recognized') } @@ -65,4 +85,5 @@ module.exports = configure(api => { return new CID(Hash) } + return put }) diff --git a/packages/ipfs-http-client/src/object/stat.js b/packages/ipfs-http-client/src/object/stat.js index 294a1c222b..70307ba597 100644 --- a/packages/ipfs-http-client/src/object/stat.js +++ b/packages/ipfs-http-client/src/object/stat.js @@ -4,8 +4,16 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/object').API} ObjectAPI + */ + module.exports = configure(api => { - return async (cid, options = {}) => { + /** + * @type {ObjectAPI["stat"]} + */ + async function stat (cid, options = {}) { const res = await api.post('object/stat', { timeout: options.timeout, signal: options.signal, @@ -18,4 +26,5 @@ module.exports = configure(api => { return res.json() } + return stat }) diff --git a/packages/ipfs-http-client/src/pin/add-all.js b/packages/ipfs-http-client/src/pin/add-all.js index e49f386d4d..fbfa2317b5 100644 --- a/packages/ipfs-http-client/src/pin/add-all.js +++ b/packages/ipfs-http-client/src/pin/add-all.js @@ -5,8 +5,16 @@ const configure = require('../lib/configure') const normaliseInput = require('ipfs-core-utils/src/pins/normalise-input') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pin').API} PinAPI + */ + module.exports = configure(api => { - return async function * addAll (source, options = {}) { + /** + * @type {PinAPI["addAll"]} + */ + async function * addAll (source, options = {}) { for await (const { path, recursive, metadata } of normaliseInput(source)) { const res = await api.post('pin/add', { timeout: options.timeout, @@ -33,4 +41,5 @@ module.exports = configure(api => { } } } + return addAll }) diff --git a/packages/ipfs-http-client/src/pin/add.js b/packages/ipfs-http-client/src/pin/add.js index 7303010169..e316f331da 100644 --- a/packages/ipfs-http-client/src/pin/add.js +++ b/packages/ipfs-http-client/src/pin/add.js @@ -4,15 +4,28 @@ const addAll = require('./add-all') const last = require('it-last') const configure = require('../lib/configure') -module.exports = (options) => { - const all = addAll(options) +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pin').API} PinAPI + */ + +/** + * @param {import('../types').Options} config + */ +module.exports = (config) => { + const all = addAll(config) return configure(() => { - return async function add (path, options = {}) { // eslint-disable-line require-await - return last(all({ + /** + * @type {PinAPI["add"]} + */ + async function add (path, options = {}) { + // @ts-ignore last can return undefined + return last(all([{ path, ...options - }, options)) + }], options)) } - })(options) + return add + })(config) } diff --git a/packages/ipfs-http-client/src/pin/index.js b/packages/ipfs-http-client/src/pin/index.js index e27a8af501..986b26d28b 100644 --- a/packages/ipfs-http-client/src/pin/index.js +++ b/packages/ipfs-http-client/src/pin/index.js @@ -2,6 +2,9 @@ const Remote = require('./remote') +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ add: require('./add')(config), addAll: require('./add-all')(config), diff --git a/packages/ipfs-http-client/src/pin/ls.js b/packages/ipfs-http-client/src/pin/ls.js index c8ed0d1366..07850063ce 100644 --- a/packages/ipfs-http-client/src/pin/ls.js +++ b/packages/ipfs-http-client/src/pin/ls.js @@ -4,7 +4,18 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pin').API} PinAPI + */ + +/** + * @param {string} type + * @param {string} cid + * @param {Record} metadata + */ function toPin (type, cid, metadata) { + /** @type {import('ipfs-core-types/src/pin').LsResult} */ const pin = { type, cid: new CID(cid) @@ -18,9 +29,15 @@ function toPin (type, cid, metadata) { } module.exports = configure(api => { - return async function * ls (options = {}) { + /** + * @type {PinAPI["ls"]} + */ + async function * ls (options = {}) { + /** @type {any[]} */ + let paths = [] + if (options.paths) { - options.paths = Array.isArray(options.paths) ? options.paths : [options.paths] + paths = Array.isArray(options.paths) ? options.paths : [options.paths] } const res = await api.post('pin/ls', { @@ -28,7 +45,7 @@ module.exports = configure(api => { signal: options.signal, searchParams: toUrlSearchParams({ ...options, - arg: (options.paths || []).map(path => `${path}`), + arg: paths.map(path => `${path}`), stream: true }), headers: options.headers @@ -45,4 +62,5 @@ module.exports = configure(api => { yield toPin(pin.Type, pin.Cid, pin.Metadata) } } + return ls }) diff --git a/packages/ipfs-http-client/src/pin/remote/index.js b/packages/ipfs-http-client/src/pin/remote/index.js index 0019020f6b..aa8ffd66d4 100644 --- a/packages/ipfs-http-client/src/pin/remote/index.js +++ b/packages/ipfs-http-client/src/pin/remote/index.js @@ -6,131 +6,99 @@ const Service = require('./service') const toUrlSearchParams = require('../../lib/to-url-search-params') /** - * @typedef {import('../..').HttpOptions} HttpOptions - * @typedef {import('../../lib/core').ClientOptions} ClientOptions - * @typedef {import('ipfs-core-types/src/basic').AbortOptions} AbortOptions - * @typedef {import('ipfs-core-types/src/pin/remote').API} API + * @typedef {import('../../types').Options} Options + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions * @typedef {import('ipfs-core-types/src/pin/remote').Pin} Pin * @typedef {import('ipfs-core-types/src/pin/remote').AddOptions} AddOptions * @typedef {import('ipfs-core-types/src/pin/remote').Query} Query * @typedef {import('ipfs-core-types/src/pin/remote').Status} Status - * - * @implements {API} + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pin/remote').API} RemotePiningAPI */ + class Remote { /** - * @param {ClientOptions} options + * @param {Options} options */ constructor (options) { - /** @private */ this.client = new Client(options) /** @readonly */ this.service = new Service(options) } +} - /** - * Stores an IPFS object(s) from a given path to a remote pinning service. - * - * @param {CID} cid - * @param {AddOptions & AbortOptions & HttpOptions} options - * @returns {Promise} - */ - add (cid, options) { - return Remote.add(this.client, cid, options) - } - - /** - * @param {Client} client - * @param {CID} cid - * @param {AddOptions & AbortOptions & HttpOptions} options - */ - static async add (client, cid, { timeout, signal, headers, ...options }) { - const response = await client.post('pin/remote/add', { - timeout, - signal, - headers, - searchParams: encodeAddParams({ cid, ...options }) - }) +/** + * @type {RemotePiningAPI["add"]} + */ +Remote.prototype.add = async function add (cid, { timeout, signal, headers, ...query }) { + const response = await this.client.post('pin/remote/add', { + timeout, + signal, + headers, + searchParams: encodeAddParams({ cid, ...query }) + }) - return Remote.decodePin(await response.json()) - } + return decodePin(await response.json()) +} - /** - * @param {Object} json - * @param {string} json.Name - * @param {string} json.Cid - * @param {Status} json.Status - * @returns {Pin} - */ - static decodePin ({ Name: name, Status: status, Cid: cid }) { - return { - cid: new CID(cid), - name, - status - } - } +/** + * @type {RemotePiningAPI["ls"]} + */ +Remote.prototype.ls = async function * ls ({ timeout, signal, headers, ...query }) { + const response = await this.client.post('pin/remote/ls', { + timeout, + signal, + headers, + searchParams: encodeQuery(query) + }) - /** - * Returns a list of matching pins on the remote pinning service. - * - * @param {Query & AbortOptions & HttpOptions} query - */ - ls (query) { - return Remote.ls(this.client, query) + for await (const pin of response.ndjson()) { + yield decodePin(pin) } +} - /** - * - * @param {Client} client - * @param {Query & AbortOptions & HttpOptions} options - * @returns {AsyncIterable} - */ - static async * ls (client, { timeout, signal, headers, ...query }) { - const response = await client.post('pin/remote/ls', { - signal, - timeout, - headers, - searchParams: encodeQuery(query) +/** + * @type {RemotePiningAPI["rm"]} + */ +Remote.prototype.rm = async function rm ({ timeout, signal, headers, ...query }) { + await this.client.post('pin/remote/rm', { + timeout, + signal, + headers, + searchParams: encodeQuery({ + ...query, + all: false }) + }) +} - for await (const pin of response.ndjson()) { - yield Remote.decodePin(pin) - } - } - - /** - * Removes a single pin object matching query allowing it to be garbage - * collected (if needed). Will error if multiple pins mtach provided - * query. To remove all matches use `rmAll` instead. - * - * @param {Query & AbortOptions & HttpOptions} query - */ - rm (query) { - return Remote.rm(this.client, { ...query, all: false }) - } - - /** - * Removes all pin object that match given query allowing them to be garbage - * collected if needed. - * - * @param {Query & AbortOptions & HttpOptions} query - */ - rmAll (query) { - return Remote.rm(this.client, { ...query, all: true }) - } - - /** - * - * @param {Client} client - * @param {{all: boolean} & Query & AbortOptions & HttpOptions} options - */ - static async rm (client, { timeout, signal, headers, ...query }) { - await client.post('pin/remote/rm', { - timeout, - signal, - headers, - searchParams: encodeQuery(query) +/** + * @type {RemotePiningAPI["rmAll"]} + */ +Remote.prototype.rmAll = async function ({ timeout, signal, headers, ...query }) { + await this.client.post('pin/remote/rm', { + timeout, + signal, + headers, + searchParams: encodeQuery({ + ...query, + all: true }) + }) +} + +/** + * @param {Object} json + * @param {string} json.Name + * @param {string} json.Cid + * @param {Status} json.Status + * @returns {Pin} + */ +const decodePin = ({ Name: name, Status: status, Cid: cid }) => { + return { + cid: new CID(cid), + name, + status } } diff --git a/packages/ipfs-http-client/src/pin/remote/service.js b/packages/ipfs-http-client/src/pin/remote/service.js index 9a718e8475..f5cc658613 100644 --- a/packages/ipfs-http-client/src/pin/remote/service.js +++ b/packages/ipfs-http-client/src/pin/remote/service.js @@ -4,41 +4,22 @@ const Client = require('../../lib/core') const toUrlSearchParams = require('../../lib/to-url-search-params') /** - * @typedef {import('../../lib/core').ClientOptions} ClientOptions - * @typedef {import('../..').HttpOptions} HttpOptions - * @typedef {import('ipfs-core-types/src/basic').AbortOptions} AbortOptions - * @typedef {import('ipfs-core-types/src/pin/remote/service').API} API + * @typedef {import('../../types').Options} Options + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions * @typedef {import('ipfs-core-types/src/pin/remote/service').Credentials} Credentials * @typedef {import('ipfs-core-types/src/pin/remote/service').RemotePinService} RemotePinService * @typedef {import('ipfs-core-types/src/pin/remote/service').RemotePinServiceWithStat} RemotePinServiceWithStat - * @implements {API} + * @typedef {import('../../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pin/remote/service').API} RemotePiningServiceAPI */ class Service { /** - * @param {ClientOptions} options + * @param {Options} options */ constructor (options) { - /** @private */ this.client = new Client(options) } - /** - * @param {Client} client - * @param {string} name - * @param {Credentials & AbortOptions & HttpOptions} options - */ - static async add (client, name, options) { - const { endpoint, key, headers, timeout, signal } = options - await client.post('pin/remote/service/add', { - timeout, - signal, - searchParams: toUrlSearchParams({ - arg: [name, Service.encodeEndpoint(endpoint), key] - }), - headers - }) - } - /** * @param {URL} url */ @@ -53,43 +34,7 @@ class Service { } /** - * @param {Client} client - * @param {string} name - * @param {AbortOptions & HttpOptions} [options] - */ - static async rm (client, name, { timeout, signal, headers } = {}) { - await client.post('pin/remote/service/rm', { - timeout, - signal, - headers, - searchParams: toUrlSearchParams({ - arg: name - }) - }) - } - - /** - * @template {true} Stat - * @param {Client} client - * @param {{ stat?: Stat } & AbortOptions & HttpOptions} [options] - */ - static async ls (client, { stat, timeout, signal, headers } = {}) { - const response = await client.post('pin/remote/service/ls', { - searchParams: stat === true ? toUrlSearchParams({ stat }) : undefined, - timeout, - signal, - headers - }) - - /** @type {{RemoteServices: Object[]}} */ - const { RemoteServices } = await response.json() - - /** @type {Stat extends true ? RemotePinServiceWithStat[] : RemotePinService []} */ - return (RemoteServices.map(Service.decodeRemoteService)) - } - - /** - * @param {Object} json + * @param {any} json * @returns {RemotePinServiceWithStat} */ static decodeRemoteService (json) { @@ -101,7 +46,7 @@ class Service { } /** - * @param {Object} json + * @param {any} json * @returns {import('ipfs-core-types/src/pin/remote/service').Stat} */ static decodeStat (json) { @@ -126,37 +71,57 @@ class Service { } } } +} - /** - * Registers remote pinning service with a given name. Errors if service - * with the given name is already registered. - * - * @param {string} name - * @param {Credentials & AbortOptions & HttpOptions} options - */ - add (name, options) { - return Service.add(this.client, name, options) - } +/** + * @type {RemotePiningServiceAPI["add"]} + */ +Service.prototype.add = async function add (name, options) { + const { endpoint, key, headers, timeout, signal } = options - /** - * Unregisteres remote pinning service with a given name. If service with such - * name isn't registerede this is a noop. - * - * @param {string} name - * @param {AbortOptions & HttpOptions} [options] - */ - rm (name, options) { - return Service.rm(this.client, name, options) - } + await this.client.post('pin/remote/service/add', { + timeout, + signal, + searchParams: toUrlSearchParams({ + arg: [name, Service.encodeEndpoint(endpoint), key] + }), + headers + }) +} - /** - * List registered remote pinning services. - * - * @param {{ stat?: true } & AbortOptions & HttpOptions} [options] - */ - ls (options) { - return Service.ls(this.client, options) - } +/** + * @type {RemotePiningServiceAPI["rm"]} + */ +Service.prototype.rm = async function rm (name, options = {}) { + await this.client.post('pin/remote/service/rm', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: toUrlSearchParams({ + arg: name + }) + }) +} + +/** + * @type {RemotePiningServiceAPI["ls"]} + */ +Service.prototype.ls = async function ls (options = {}) { + // @ts-ignore cannot derive option type from typedef + const { stat, headers, timeout, signal } = options + + const response = await this.client.post('pin/remote/service/ls', { + timeout, + signal, + headers, + searchParams: stat === true ? toUrlSearchParams({ stat }) : undefined + }) + + /** @type {{RemoteServices: Object[]}} */ + const { RemoteServices } = await response.json() + + /** @type {Stat extends true ? RemotePinServiceWithStat[] : RemotePinService []} */ + return (RemoteServices.map(Service.decodeRemoteService)) } module.exports = Service diff --git a/packages/ipfs-http-client/src/pin/rm-all.js b/packages/ipfs-http-client/src/pin/rm-all.js index e19edd68e0..d4d0ca65b7 100644 --- a/packages/ipfs-http-client/src/pin/rm-all.js +++ b/packages/ipfs-http-client/src/pin/rm-all.js @@ -5,8 +5,16 @@ const configure = require('../lib/configure') const normaliseInput = require('ipfs-core-utils/src/pins/normalise-input') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pin').API} PinAPI + */ + module.exports = configure(api => { - return async function * rmAll (source, options = {}) { + /** + * @type {PinAPI["rmAll"]} + */ + async function * rmAll (source, options = {}) { for await (const { path, recursive } of normaliseInput(source)) { const searchParams = new URLSearchParams(options.searchParams) searchParams.append('arg', `${path}`) @@ -26,11 +34,12 @@ module.exports = configure(api => { for await (const pin of res.ndjson()) { if (pin.Pins) { // non-streaming response - yield * pin.Pins.map(cid => new CID(cid)) + yield * pin.Pins.map((/** @type {string} */ cid) => new CID(cid)) continue } yield new CID(pin) } } } + return rmAll }) diff --git a/packages/ipfs-http-client/src/pin/rm.js b/packages/ipfs-http-client/src/pin/rm.js index 34f3daf067..1b1b23abcd 100644 --- a/packages/ipfs-http-client/src/pin/rm.js +++ b/packages/ipfs-http-client/src/pin/rm.js @@ -4,15 +4,28 @@ const rmAll = require('./rm-all') const last = require('it-last') const configure = require('../lib/configure') -module.exports = (options) => { - const all = rmAll(options) +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pin').API} PinAPI + */ + +/** + * @param {import('../types').Options} config + */ +module.exports = (config) => { + const all = rmAll(config) return configure(() => { - return async function rm (path, options = {}) { // eslint-disable-line require-await - return last(all({ + /** + * @type {PinAPI["rm"]} + */ + async function rm (path, options = {}) { + // @ts-ignore last can return undefined + return last(all([{ path, ...options - }, options)) + }], options)) } - })(options) + return rm + })(config) } diff --git a/packages/ipfs-http-client/src/ping.js b/packages/ipfs-http-client/src/ping.js index f4710b7f6b..95d36969c2 100644 --- a/packages/ipfs-http-client/src/ping.js +++ b/packages/ipfs-http-client/src/ping.js @@ -4,8 +4,16 @@ const toCamel = require('./lib/object-to-camel') const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { - return async function * ping (peerId, options = {}) { + /** + * @type {RootAPI["ping"]} + */ + async function * ping (peerId, options = {}) { const res = await api.post('ping', { timeout: options.timeout, signal: options.signal, @@ -19,4 +27,5 @@ module.exports = configure(api => { yield * res.ndjson() } + return ping }) diff --git a/packages/ipfs-http-client/src/pubsub/index.js b/packages/ipfs-http-client/src/pubsub/index.js index e369bb6f3c..4898e6687c 100644 --- a/packages/ipfs-http-client/src/pubsub/index.js +++ b/packages/ipfs-http-client/src/pubsub/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ ls: require('./ls')(config), peers: require('./peers')(config), diff --git a/packages/ipfs-http-client/src/pubsub/ls.js b/packages/ipfs-http-client/src/pubsub/ls.js index 985f069afd..282ac0ef15 100644 --- a/packages/ipfs-http-client/src/pubsub/ls.js +++ b/packages/ipfs-http-client/src/pubsub/ls.js @@ -3,8 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pubsub').API} PubsubAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {PubsubAPI["ls"]} + */ + async function ls (options = {}) { const { Strings } = await (await api.post('pubsub/ls', { timeout: options.timeout, signal: options.signal, @@ -14,4 +22,5 @@ module.exports = configure(api => { return Strings || [] } + return ls }) diff --git a/packages/ipfs-http-client/src/pubsub/peers.js b/packages/ipfs-http-client/src/pubsub/peers.js index b8847d0c67..06ac54e541 100644 --- a/packages/ipfs-http-client/src/pubsub/peers.js +++ b/packages/ipfs-http-client/src/pubsub/peers.js @@ -3,13 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -module.exports = configure(api => { - return async (topic, options = {}) => { - if (!options && typeof topic === 'object') { - options = topic || {} - topic = null - } +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pubsub').API} PubsubAPI + */ +module.exports = configure(api => { + /** + * @type {PubsubAPI["peers"]} + */ + async function peers (topic, options = {}) { const res = await api.post('pubsub/peers', { timeout: options.timeout, signal: options.signal, @@ -24,4 +27,5 @@ module.exports = configure(api => { return Strings || [] } + return peers }) diff --git a/packages/ipfs-http-client/src/pubsub/publish.js b/packages/ipfs-http-client/src/pubsub/publish.js index e9ef335303..29b9750d95 100644 --- a/packages/ipfs-http-client/src/pubsub/publish.js +++ b/packages/ipfs-http-client/src/pubsub/publish.js @@ -6,8 +6,16 @@ const multipartRequest = require('../lib/multipart-request') const abortSignal = require('../lib/abort-signal') const { AbortController } = require('native-abort-controller') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pubsub').API} PubsubAPI + */ + module.exports = configure(api => { - return async (topic, data, options = {}) => { + /** + * @type {PubsubAPI["publish"]} + */ + async function publish (topic, data, options = {}) { const searchParams = toUrlSearchParams({ arg: topic, ...options @@ -29,4 +37,5 @@ module.exports = configure(api => { await res.text() } + return publish }) diff --git a/packages/ipfs-http-client/src/pubsub/subscribe.js b/packages/ipfs-http-client/src/pubsub/subscribe.js index ab5ee3c2db..83db478e4e 100644 --- a/packages/ipfs-http-client/src/pubsub/subscribe.js +++ b/packages/ipfs-http-client/src/pubsub/subscribe.js @@ -7,13 +7,25 @@ const SubscriptionTracker = require('./subscription-tracker') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pubsub').Message} Message + * @typedef {(err: Error, fatal: boolean, msg?: Message) => void} ErrorHandlerFn + * @typedef {import('ipfs-core-types/src/pubsub').API} PubsubAPI + */ + module.exports = configure((api, options) => { const subsTracker = SubscriptionTracker.singleton() - return async (topic, handler, options = {}) => { // eslint-disable-line require-await + /** + * @type {PubsubAPI["subscribe"]} + */ + async function subscribe (topic, handler, options = {}) { // eslint-disable-line require-await options.signal = subsTracker.subscribe(topic, handler, options.signal) + /** @type {(value?: any) => void} */ let done + /** @type {(error: Error) => void} */ let fail const result = new Promise((resolve, reject) => { @@ -62,8 +74,16 @@ module.exports = configure((api, options) => { return result } + return subscribe }) +/** + * @param {*} msgStream + * @param {object} options + * @param {(message: Message) => void} options.onMessage + * @param {() => void} options.onEnd + * @param {ErrorHandlerFn} [options.onError] + */ async function readMessages (msgStream, { onMessage, onEnd, onError }) { onError = onError || log diff --git a/packages/ipfs-http-client/src/pubsub/subscription-tracker.js b/packages/ipfs-http-client/src/pubsub/subscription-tracker.js index 5aaf93f5be..a257b57a89 100644 --- a/packages/ipfs-http-client/src/pubsub/subscription-tracker.js +++ b/packages/ipfs-http-client/src/pubsub/subscription-tracker.js @@ -2,8 +2,17 @@ const { AbortController } = require('native-abort-controller') +/** + * @typedef {import('ipfs-core-types/src/pubsub').MessageHandlerFn} MessageHandlerFn + * + * @typedef {Object} Subscription + * @property {MessageHandlerFn} handler + * @property {AbortController} controller + */ + class SubscriptionTracker { constructor () { + /** @type {Map} */ this._subs = new Map() } @@ -13,6 +22,11 @@ class SubscriptionTracker { return SubscriptionTracker.instance } + /** + * @param {string} topic + * @param {MessageHandlerFn} handler + * @param {AbortSignal} [signal] + */ subscribe (topic, handler, signal) { const topicSubs = this._subs.get(topic) || [] @@ -33,6 +47,10 @@ class SubscriptionTracker { return controller.signal } + /** + * @param {string} topic + * @param {MessageHandlerFn} [handler] + */ unsubscribe (topic, handler) { const subs = this._subs.get(topic) || [] let unsubs @@ -49,6 +67,9 @@ class SubscriptionTracker { } } +/** + * @type {SubscriptionTracker | null} + */ SubscriptionTracker.instance = null module.exports = SubscriptionTracker diff --git a/packages/ipfs-http-client/src/pubsub/unsubscribe.js b/packages/ipfs-http-client/src/pubsub/unsubscribe.js index 7d90a02c07..4989883727 100644 --- a/packages/ipfs-http-client/src/pubsub/unsubscribe.js +++ b/packages/ipfs-http-client/src/pubsub/unsubscribe.js @@ -2,8 +2,22 @@ const SubscriptionTracker = require('./subscription-tracker') -module.exports = api => { +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/pubsub').API} PubsubAPI + */ + +/** + * @param {import('../types').Options} config + */ +module.exports = config => { const subsTracker = SubscriptionTracker.singleton() - // eslint-disable-next-line require-await - return async (topic, handler) => subsTracker.unsubscribe(topic, handler) + + /** + * @type {PubsubAPI["unsubscribe"]} + */ + async function unsubscribe (topic, handler) { + subsTracker.unsubscribe(topic, handler) + } + return unsubscribe } diff --git a/packages/ipfs-http-client/src/refs/index.js b/packages/ipfs-http-client/src/refs/index.js index b21560ee5d..2ecbc1c2fe 100644 --- a/packages/ipfs-http-client/src/refs/index.js +++ b/packages/ipfs-http-client/src/refs/index.js @@ -5,7 +5,15 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/refs').API} RefsAPI + */ + module.exports = configure((api, options) => { + /** + * @type {RefsAPI["refs"]} + */ const refs = async function * (args, options = {}) { if (!Array.isArray(args)) { args = [args] @@ -24,7 +32,8 @@ module.exports = configure((api, options) => { yield * res.ndjson() } - refs.local = require('./local')(options) - return refs + return Object.assign(refs, { + local: require('./local')(options) + }) }) diff --git a/packages/ipfs-http-client/src/refs/local.js b/packages/ipfs-http-client/src/refs/local.js index 845d320c37..9ca8facc81 100644 --- a/packages/ipfs-http-client/src/refs/local.js +++ b/packages/ipfs-http-client/src/refs/local.js @@ -4,8 +4,16 @@ const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/refs').API} RefsAPI + */ + module.exports = configure(api => { - return async function * refsLocal (options = {}) { + /** + * @type {RefsAPI["local"]} + */ + async function * refsLocal (options = {}) { const res = await api.post('refs/local', { timeout: options.timeout, signal: options.signal, @@ -16,4 +24,5 @@ module.exports = configure(api => { yield * res.ndjson() } + return refsLocal }) diff --git a/packages/ipfs-http-client/src/repo/gc.js b/packages/ipfs-http-client/src/repo/gc.js index 7d69e05957..a1199f21f6 100644 --- a/packages/ipfs-http-client/src/repo/gc.js +++ b/packages/ipfs-http-client/src/repo/gc.js @@ -4,8 +4,16 @@ const CID = require('cids') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/repo').API} RepoAPI + */ + module.exports = configure(api => { - return async function * gc (options = {}) { + /** + * @type {RepoAPI["gc"]} + */ + async function * gc (options = {}) { const res = await api.post('repo/gc', { timeout: options.timeout, signal: options.signal, @@ -21,4 +29,5 @@ module.exports = configure(api => { yield * res.ndjson() } + return gc }) diff --git a/packages/ipfs-http-client/src/repo/index.js b/packages/ipfs-http-client/src/repo/index.js index 4785f55db5..9f2f28fc53 100644 --- a/packages/ipfs-http-client/src/repo/index.js +++ b/packages/ipfs-http-client/src/repo/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ gc: require('./gc')(config), stat: require('./stat')(config), diff --git a/packages/ipfs-http-client/src/repo/stat.js b/packages/ipfs-http-client/src/repo/stat.js index 200ab9b433..a8bfa91d00 100644 --- a/packages/ipfs-http-client/src/repo/stat.js +++ b/packages/ipfs-http-client/src/repo/stat.js @@ -1,11 +1,18 @@ 'use strict' -const { BigNumber } = require('bignumber.js') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/repo').API} RepoAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {RepoAPI["stat"]} + */ + async function stat (options = {}) { const res = await api.post('repo/stat', { timeout: options.timeout, signal: options.signal, @@ -15,11 +22,12 @@ module.exports = configure(api => { const data = await res.json() return { - numObjects: new BigNumber(data.NumObjects), - repoSize: new BigNumber(data.RepoSize), + numObjects: BigInt(data.NumObjects), + repoSize: BigInt(data.RepoSize), repoPath: data.RepoPath, version: data.Version, - storageMax: new BigNumber(data.StorageMax) + storageMax: BigInt(data.StorageMax) } } + return stat }) diff --git a/packages/ipfs-http-client/src/repo/version.js b/packages/ipfs-http-client/src/repo/version.js index 450b3b52a7..0d64ea19d7 100644 --- a/packages/ipfs-http-client/src/repo/version.js +++ b/packages/ipfs-http-client/src/repo/version.js @@ -3,8 +3,16 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/repo').API} RepoAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {RepoAPI["version"]} + */ + async function version (options = {}) { const res = await (await api.post('repo/version', { timeout: options.timeout, signal: options.signal, @@ -14,4 +22,5 @@ module.exports = configure(api => { return res.Version } + return version }) diff --git a/packages/ipfs-http-client/src/resolve.js b/packages/ipfs-http-client/src/resolve.js index 0438013ea8..77fbfb5f6a 100644 --- a/packages/ipfs-http-client/src/resolve.js +++ b/packages/ipfs-http-client/src/resolve.js @@ -3,9 +3,14 @@ const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { /** - * @type {import('.').Implements} + * @type {RootAPI["resolve"]} */ async function resolve (path, options = {}) { const res = await api.post('resolve', { diff --git a/packages/ipfs-http-client/src/start.js b/packages/ipfs-http-client/src/start.js new file mode 100644 index 0000000000..62d748ccce --- /dev/null +++ b/packages/ipfs-http-client/src/start.js @@ -0,0 +1,19 @@ +'use strict' + +const configure = require('./lib/configure') + +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + +module.exports = configure(api => { + /** + * @type {RootAPI["start"]} + */ + const start = async (options = {}) => { + throw new Error('Not implemented') + } + + return start +}) diff --git a/packages/ipfs-http-client/src/stats/bw.js b/packages/ipfs-http-client/src/stats/bw.js index f4997ca0da..bcea618085 100644 --- a/packages/ipfs-http-client/src/stats/bw.js +++ b/packages/ipfs-http-client/src/stats/bw.js @@ -1,24 +1,32 @@ 'use strict' -const { BigNumber } = require('bignumber.js') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/stats').API} StatsAPI + */ + module.exports = configure(api => { - return async function * bw (options = {}) { + /** + * @type {StatsAPI["bw"]} + */ + async function * bw (options = {}) { const res = await api.post('stats/bw', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams(options), headers: options.headers, transform: (stats) => ({ - totalIn: new BigNumber(stats.TotalIn), - totalOut: new BigNumber(stats.TotalOut), - rateIn: new BigNumber(stats.RateIn), - rateOut: new BigNumber(stats.RateOut) + totalIn: BigInt(stats.TotalIn), + totalOut: BigInt(stats.TotalOut), + rateIn: BigInt(stats.RateIn), + rateOut: BigInt(stats.RateOut) }) }) yield * res.ndjson() } + return bw }) diff --git a/packages/ipfs-http-client/src/stats/index.js b/packages/ipfs-http-client/src/stats/index.js index d13a534a71..f7737e8c9c 100644 --- a/packages/ipfs-http-client/src/stats/index.js +++ b/packages/ipfs-http-client/src/stats/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ bitswap: require('../bitswap/stat')(config), bw: require('./bw')(config), diff --git a/packages/ipfs-http-client/src/stop.js b/packages/ipfs-http-client/src/stop.js index d5157cdef9..621a3b6b54 100644 --- a/packages/ipfs-http-client/src/stop.js +++ b/packages/ipfs-http-client/src/stop.js @@ -3,8 +3,16 @@ const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {RootAPI["stop"]} + */ + async function stop (options = {}) { const res = await api.post('shutdown', { timeout: options.timeout, signal: options.signal, @@ -14,4 +22,5 @@ module.exports = configure(api => { await res.text() } + return stop }) diff --git a/packages/ipfs-http-client/src/swarm/addrs.js b/packages/ipfs-http-client/src/swarm/addrs.js index 199585b78a..acd0242556 100644 --- a/packages/ipfs-http-client/src/swarm/addrs.js +++ b/packages/ipfs-http-client/src/swarm/addrs.js @@ -4,14 +4,24 @@ const multiaddr = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/swarm').API} SwarmAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {SwarmAPI["addrs"]} + */ + async function addrs (options = {}) { const res = await api.post('swarm/addrs', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams(options), headers: options.headers }) + + /** @type {{ Addrs: Record }} */ const { Addrs } = await res.json() return Object.keys(Addrs).map(id => ({ @@ -19,4 +29,5 @@ module.exports = configure(api => { addrs: (Addrs[id] || []).map(a => multiaddr(a)) })) } + return addrs }) diff --git a/packages/ipfs-http-client/src/swarm/connect.js b/packages/ipfs-http-client/src/swarm/connect.js index 7b939577b4..1a6e649a30 100644 --- a/packages/ipfs-http-client/src/swarm/connect.js +++ b/packages/ipfs-http-client/src/swarm/connect.js @@ -3,15 +3,21 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -module.exports = configure(api => { - return async (addrs, options = {}) => { - addrs = Array.isArray(addrs) ? addrs : [addrs] +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/swarm').API} SwarmAPI + */ +module.exports = configure(api => { + /** + * @type {SwarmAPI["connect"]} + */ + async function connect (addr, options = {}) { const res = await api.post('swarm/connect', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: addrs.map(addr => `${addr}`), + arg: addr, ...options }), headers: options.headers @@ -20,4 +26,5 @@ module.exports = configure(api => { return Strings || [] } + return connect }) diff --git a/packages/ipfs-http-client/src/swarm/disconnect.js b/packages/ipfs-http-client/src/swarm/disconnect.js index 956c384431..8e20d3e6ff 100644 --- a/packages/ipfs-http-client/src/swarm/disconnect.js +++ b/packages/ipfs-http-client/src/swarm/disconnect.js @@ -3,15 +3,21 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -module.exports = configure(api => { - return async (addrs, options = {}) => { - addrs = Array.isArray(addrs) ? addrs : [addrs] +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/swarm').API} SwarmAPI + */ +module.exports = configure(api => { + /** + * @type {SwarmAPI["disconnect"]} + */ + async function disconnect (addr, options = {}) { const res = await api.post('swarm/disconnect', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: addrs.map(addr => `${addr}`), + arg: addr, ...options }), headers: options.headers @@ -20,4 +26,5 @@ module.exports = configure(api => { return Strings || [] } + return disconnect }) diff --git a/packages/ipfs-http-client/src/swarm/index.js b/packages/ipfs-http-client/src/swarm/index.js index 84648439d9..ede0d7832b 100644 --- a/packages/ipfs-http-client/src/swarm/index.js +++ b/packages/ipfs-http-client/src/swarm/index.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {import('../types').Options} config + */ module.exports = config => ({ addrs: require('./addrs')(config), connect: require('./connect')(config), diff --git a/packages/ipfs-http-client/src/swarm/localAddrs.js b/packages/ipfs-http-client/src/swarm/localAddrs.js index 23d2874f2f..55f3927b1e 100644 --- a/packages/ipfs-http-client/src/swarm/localAddrs.js +++ b/packages/ipfs-http-client/src/swarm/localAddrs.js @@ -4,16 +4,27 @@ const multiaddr = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/swarm').API} SwarmAPI + */ + module.exports = configure(api => { - return async (options = {}) => { + /** + * @type {SwarmAPI["localAddrs"]} + */ + async function localAddrs (options = {}) { const res = await api.post('swarm/addrs/local', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams(options), headers: options.headers }) + + /** @type {{ Strings: string[] }} */ const { Strings } = await res.json() return (Strings || []).map(a => multiaddr(a)) } + return localAddrs }) diff --git a/packages/ipfs-http-client/src/swarm/peers.js b/packages/ipfs-http-client/src/swarm/peers.js index ed1b0f7d85..e85bbb3b08 100644 --- a/packages/ipfs-http-client/src/swarm/peers.js +++ b/packages/ipfs-http-client/src/swarm/peers.js @@ -4,37 +4,36 @@ const multiaddr = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +/** + * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/swarm').API} SwarmAPI + */ + module.exports = configure(api => { - return async (options = {}) => { - const res = await (await api.post('swarm/peers', { + /** + * @type {SwarmAPI["peers"]} + */ + async function peers (options = {}) { + const res = await api.post('swarm/peers', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams(options), headers: options.headers - })).json() + }) - return (res.Peers || []).map(peer => { - const info = {} - try { - info.addr = multiaddr(peer.Addr) - info.peer = peer.Peer - } catch (error) { - info.error = error - info.rawPeerInfo = peer - } - if (peer.Muxer) { - info.muxer = peer.Muxer - } - if (peer.Latency) { - info.latency = peer.Latency - } - if (peer.Streams) { - info.streams = peer.Streams - } - if (peer.Direction != null) { - info.direction = peer.Direction + /** @type {{ Peers: { Peer: string, Addr: string, Muxer?: string, Latency?: string, Streams?: string[], Direction?: 0 | 1 }[] }} */ + const { Peers } = await res.json() + + return (Peers || []).map(peer => { + return { + addr: multiaddr(peer.Addr), + peer: peer.Peer, + muxer: peer.Muxer, + latency: peer.Latency, + streams: peer.Streams, + direction: peer.Direction == null ? undefined : peer.Direction === 0 ? 'inbound' : 'outbound' } - return info }) } + return peers }) diff --git a/packages/ipfs-http-client/src/types.d.ts b/packages/ipfs-http-client/src/types.d.ts new file mode 100644 index 0000000000..557d2637d7 --- /dev/null +++ b/packages/ipfs-http-client/src/types.d.ts @@ -0,0 +1,34 @@ +import { Format as IPLDFormat } from 'interface-ipld-format' +import { LoadFormatFn } from 'ipld' +import { Agent as HttpAgent } from 'http' +import { Agent as HttpsAgent } from 'https' + +export interface Options { + host?: string + port?: number + protocol?: string + headers?: Headers | Record + timeout?: number | sttring + apiPath?: string + url?: URL|string|Multiaddr + ipld?: IPLDOptions + agent?: HttpAgent | HttpsAgent +} + +export interface IPLDOptions { + formats?: IPLDFormat[] + loadFormat?: LoadFormatFn +} + +export interface HTTPClientExtraOptions { + headers?: Record + searchParams?: URLSearchParams +} + +export interface EndpointConfig { + host: string, + port: string, + protocol: string, + pathname: string + 'api-path': string +} diff --git a/packages/ipfs-http-client/src/update.js b/packages/ipfs-http-client/src/update.js deleted file mode 100644 index 026eff5b84..0000000000 --- a/packages/ipfs-http-client/src/update.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict' - -const configure = require('./lib/configure') -const toUrlSearchParams = require('./lib/to-url-search-params') - -module.exports = configure(api => { - return async (options = {}) => { - const res = await api.post('update', { - timeout: options.timeout, - signal: options.signal, - searchParams: toUrlSearchParams(options), - headers: options.headers - }) - - await res.text() - } -}) diff --git a/packages/ipfs-http-client/src/version.js b/packages/ipfs-http-client/src/version.js index ca6c428f94..0b15ae98a4 100644 --- a/packages/ipfs-http-client/src/version.js +++ b/packages/ipfs-http-client/src/version.js @@ -4,9 +4,14 @@ const toCamel = require('./lib/object-to-camel') const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') +/** + * @typedef {import('./types').HTTPClientExtraOptions} HTTPClientExtraOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + */ + module.exports = configure(api => { /** - * @type {import('.').Implements} + * @type {RootAPI["version"]} */ async function version (options = {}) { const res = await api.post('version', { @@ -16,6 +21,7 @@ module.exports = configure(api => { headers: options.headers }) + // @ts-ignore server output is not typed return toCamel(await res.json()) } diff --git a/packages/ipfs-http-client/test/constructor.spec.js b/packages/ipfs-http-client/test/constructor.spec.js index dc06022c4e..1c74af9c61 100644 --- a/packages/ipfs-http-client/test/constructor.spec.js +++ b/packages/ipfs-http-client/test/constructor.spec.js @@ -4,7 +4,7 @@ const multiaddr = require('multiaddr') const { expect } = require('aegir/utils/chai') const f = require('./utils/factory')() -const ipfsClient = require('../src/index.js') +const { create: ipfsClient } = require('../src/index.js') const { isBrowser } = require('ipfs-utils/src/env') describe('ipfs-http-client constructor tests', () => { diff --git a/packages/ipfs-http-client/test/dag.spec.js b/packages/ipfs-http-client/test/dag.spec.js index fb3bdc438b..34cbaf4970 100644 --- a/packages/ipfs-http-client/test/dag.spec.js +++ b/packages/ipfs-http-client/test/dag.spec.js @@ -78,7 +78,7 @@ describe('.dag', function () { it('should attempt to load an unsupported format', async () => { let askedToLoadFormat - const ipfs2 = ipfsHttpClient({ + const ipfs2 = ipfsHttpClient.create({ url: `http://${ipfs.apiHost}:${ipfs.apiPort}`, ipld: { loadFormat: (format) => { @@ -101,7 +101,7 @@ describe('.dag', function () { }) it('should allow formats to be specified without overwriting others', async () => { - const ipfs2 = ipfsHttpClient({ + const ipfs2 = ipfsHttpClient.create({ url: `http://${ipfs.apiHost}:${ipfs.apiPort}`, ipld: { formats: [ diff --git a/packages/ipfs-http-client/test/endpoint-config.spec.js b/packages/ipfs-http-client/test/endpoint-config.spec.js index 1c019fb0f9..e12bd9125c 100644 --- a/packages/ipfs-http-client/test/endpoint-config.spec.js +++ b/packages/ipfs-http-client/test/endpoint-config.spec.js @@ -3,7 +3,7 @@ 'use strict' const { expect } = require('aegir/utils/chai') -const ipfsClient = require('../src') +const ipfsClient = require('../src').create describe('.getEndpointConfig', () => { it('should return the endpoint configuration', function () { diff --git a/packages/ipfs-http-client/test/node/agent.js b/packages/ipfs-http-client/test/node/agent.js index 6cc98cbe5b..b0940ae68a 100644 --- a/packages/ipfs-http-client/test/node/agent.js +++ b/packages/ipfs-http-client/test/node/agent.js @@ -2,7 +2,7 @@ 'use strict' const { expect } = require('aegir/utils/chai') -const ipfsClient = require('../../src') +const ipfsClient = require('../../src').create const delay = require('delay') function startServer (handler) { diff --git a/packages/ipfs-http-client/test/node/custom-headers.js b/packages/ipfs-http-client/test/node/custom-headers.js index 2d0df7a847..61676899f1 100644 --- a/packages/ipfs-http-client/test/node/custom-headers.js +++ b/packages/ipfs-http-client/test/node/custom-headers.js @@ -3,7 +3,7 @@ const { isNode } = require('ipfs-utils/src/env') const { expect } = require('aegir/utils/chai') -const ipfsClient = require('../../src') +const ipfsClient = require('../../src').create const uint8ArrayFromString = require('uint8arrays/from-string') function startServer (fn) { diff --git a/packages/ipfs-http-client/test/node/request-api.js b/packages/ipfs-http-client/test/node/request-api.js index ed91c61574..81cad266b3 100644 --- a/packages/ipfs-http-client/test/node/request-api.js +++ b/packages/ipfs-http-client/test/node/request-api.js @@ -3,7 +3,7 @@ const { expect } = require('aegir/utils/chai') const uint8ArrayFromString = require('uint8arrays/from-string') -const ipfsClient = require('../../src/index.js') +const ipfsClient = require('../../src').create describe('\'deal with HTTP weirdness\' tests', () => { it('does not crash if no content-type header is provided', async function () { diff --git a/packages/ipfs-http-client/test/node/swarm.js b/packages/ipfs-http-client/test/node/swarm.js index c437caabfe..30b9c71b70 100644 --- a/packages/ipfs-http-client/test/node/swarm.js +++ b/packages/ipfs-http-client/test/node/swarm.js @@ -3,7 +3,7 @@ const { expect } = require('aegir/utils/chai') const nock = require('nock') -const ipfsClient = require('../../src') +const ipfsClient = require('../../src').create describe('.swarm.peers', function () { this.timeout(50 * 1000) // slow CI @@ -47,23 +47,6 @@ describe('.swarm.peers', function () { expect(scope.isDone()).to.equal(true) }) - it('handles unvalidatable peer addr', async () => { - const response = { Peers: [{ Addr: '/ip4/104.131.131.82/future-tech', Peer: 'QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC', Latency: '', Muxer: '', Streams: null }] } - - const scope = nock(apiUrl) - .post('/api/v0/swarm/peers') - .query(true) - .reply(200, response) - - const res = await ipfs.swarm.peers() - - expect(res).to.be.a('array') - expect(res.length).to.equal(1) - expect(res[0].error).to.exist() - expect(res[0].rawPeerInfo).to.deep.equal(response.Peers[0]) - expect(scope.isDone()).to.equal(true) - }) - it('handles an error response', async () => { const scope = nock(apiUrl) .post('/api/v0/swarm/peers') diff --git a/packages/ipfs-http-client/test/sub-modules.spec.js b/packages/ipfs-http-client/test/sub-modules.spec.js index 9b939d1e56..7cd9e07ecb 100644 --- a/packages/ipfs-http-client/test/sub-modules.spec.js +++ b/packages/ipfs-http-client/test/sub-modules.spec.js @@ -63,7 +63,7 @@ describe('submodules', () => { }) it('ping', () => { - const ping = require('../src')().ping + const ping = require('../src').create().ping expect(ping).to.be.a('function') }) @@ -157,7 +157,7 @@ describe('submodules', () => { }) it('files regular API', () => { - const filesRegular = require('../src')() + const filesRegular = require('../src').create() expect(filesRegular.add).to.be.a('function') expect(filesRegular.get).to.be.a('function') diff --git a/packages/ipfs-http-client/tsconfig.json b/packages/ipfs-http-client/tsconfig.json index bbdcd5851e..3a4cc05655 100644 --- a/packages/ipfs-http-client/tsconfig.json +++ b/packages/ipfs-http-client/tsconfig.json @@ -1,18 +1,17 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" ], "references": [ { - "path": "../ipfs-core-utils" + "path": "../ipfs-core-types" }, { - "path": "../ipfs-core" + "path": "../ipfs-core-utils" } ] } diff --git a/packages/ipfs-http-gateway/package.json b/packages/ipfs-http-gateway/package.json index d85a8bb5bc..35ca193438 100644 --- a/packages/ipfs-http-gateway/package.json +++ b/packages/ipfs-http-gateway/package.json @@ -11,9 +11,22 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "dist/src/index.d.ts", + "typesVersions": { + "*": { + "src/*": [ + "dist/src/*", + "dist/src/*/index" + ], + "src/": [ + "dist/src/index" + ] + } + }, "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" @@ -24,7 +37,8 @@ "test:node": "aegir test -t node", "coverage": "nyc --reporter=text --reporter=lcov npm run test:node", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i rimraf" + "dep-check": "aegir dep-check -i rimraf -i ipfs-core-types", + "build": "aegir build --no-bundle" }, "dependencies": { "@hapi/ammo": "^5.0.1", @@ -33,9 +47,10 @@ "cids": "^1.1.5", "debug": "^4.1.1", "hapi-pino": "^8.3.0", + "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-http-response": "^0.6.0", - "is-ipfs": "^2.0.0", + "is-ipfs": "^4.0.0", "it-last": "^1.0.4", "it-to-stream": "^0.1.2", "joi": "^17.2.1", @@ -44,7 +59,9 @@ "uri-to-multiaddr": "^4.0.0" }, "devDependencies": { - "aegir": "^31.0.0", + "@types/hapi__hapi": "^20.0.5", + "@types/hapi-pino": "^8.0.1", + "aegir": "^32.1.0", "file-type": "^16.0.0", "rimraf": "^3.0.2", "sinon": "^9.0.3" diff --git a/packages/ipfs-http-gateway/src/index.js b/packages/ipfs-http-gateway/src/index.js index f1e5766336..74df014088 100644 --- a/packages/ipfs-http-gateway/src/index.js +++ b/packages/ipfs-http-gateway/src/index.js @@ -3,10 +3,19 @@ const Hapi = require('@hapi/hapi') const Pino = require('hapi-pino') const debug = require('debug') +// @ts-ignore no types const toMultiaddr = require('uri-to-multiaddr') const LOG = 'ipfs:http-gateway' const LOG_ERROR = 'ipfs:http-gateway:error' +/** + * @typedef {import('ipfs-core-types').IPFS} IPFS + * @typedef {import('./types').Server} Server + */ + +/** + * @param {import('@hapi/hapi').ServerInfo} info + */ function hapiInfoToMultiaddr (info) { let hostname = info.host let uri = info.uri @@ -20,15 +29,21 @@ function hapiInfoToMultiaddr (info) { return toMultiaddr(uri) } -async function serverCreator (serverAddrs, createServer, ipfs, cors) { +/** + * @param {string | string[]} serverAddrs + * @param {(host: string, port: string, ipfs: IPFS) => Promise} createServer + * @param {IPFS} ipfs + */ +async function serverCreator (serverAddrs, createServer, ipfs) { serverAddrs = serverAddrs || [] // just in case the address is just string serverAddrs = Array.isArray(serverAddrs) ? serverAddrs : [serverAddrs] + /** @type {Server[]} */ const servers = [] for (const address of serverAddrs) { const addrParts = address.split('/') - const server = await createServer(addrParts[2], addrParts[4], ipfs, cors) + const server = await createServer(addrParts[2], addrParts[4], ipfs) await server.start() server.info.ma = hapiInfoToMultiaddr(server.info) servers.push(server) @@ -37,12 +52,16 @@ async function serverCreator (serverAddrs, createServer, ipfs, cors) { } class HttpGateway { - constructor (ipfs, options = {}) { + /** + * @param {IPFS} ipfs + */ + constructor (ipfs) { this._ipfs = ipfs - this._options = {} this._log = Object.assign(debug(LOG), { error: debug(LOG_ERROR) }) + /** @type {Server[]} */ + this._gatewayServers = [] } async start () { @@ -50,9 +69,10 @@ class HttpGateway { const ipfs = this._ipfs + // @ts-ignore TODO: move config typedefs to repo const config = await ipfs.config.getAll() - config.Addresses = config.Addresses || {} - const gatewayAddrs = config.Addresses.Gateway + config.Addresses = config.Addresses || { Swarm: [], Gateway: [] } + const gatewayAddrs = config.Addresses.Gateway || [] this._gatewayServers = await serverCreator(gatewayAddrs, this._createGatewayServer, ipfs) @@ -60,6 +80,11 @@ class HttpGateway { return this } + /** + * @param {string} host + * @param {string} port + * @param {IPFS} ipfs + */ async _createGatewayServer (host, port, ipfs) { const server = Hapi.server({ host, @@ -89,12 +114,14 @@ class HttpGateway { async stop () { this._log('stopping') + /** + * @param {Server[]} servers + */ const stopServers = servers => Promise.all((servers || []).map(s => s.stop())) await Promise.all([ stopServers(this._gatewayServers) ]) this._log('stopped') - return this } } diff --git a/packages/ipfs-http-gateway/src/resources/gateway.js b/packages/ipfs-http-gateway/src/resources/gateway.js index a76f4a4ac7..e33a41bb4a 100644 --- a/packages/ipfs-http-gateway/src/resources/gateway.js +++ b/packages/ipfs-http-gateway/src/resources/gateway.js @@ -7,9 +7,12 @@ const Boom = require('@hapi/boom') const Ammo = require('@hapi/ammo') // HTTP Range processing utilities const last = require('it-last') const multibase = require('multibase') +// @ts-ignore no types const { resolver } = require('ipfs-http-response') +// @ts-ignore no types const detectContentType = require('ipfs-http-response/src/utils/content-type') const isIPFS = require('is-ipfs') +// @ts-ignore no types const toStream = require('it-to-stream') const PathUtils = require('../utils/path') const { cidToString } = require('ipfs-core-utils/src/cid') @@ -20,17 +23,25 @@ const log = Object.assign(debug('ipfs:http-gateway'), { module.exports = { + /** + * @param {import('../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { ipfs } = request.server.app const path = request.path + let ipfsPath = path + + if (path.startsWith('/ipns/')) { + ipfsPath = await last(ipfs.name.resolve(path, { recursive: true })) || path + } + // The resolver from ipfs-http-response supports only immutable /ipfs/ for now, // so we convert /ipns/ to /ipfs/ before passing it to the resolver ¯\_(ツ)_/¯ // This could be removed if a solution proposed in // https://github.com/ipfs/js-ipfs-http-response/issues/22 lands upstream - let ipfsPath = decodeURI(path.startsWith('/ipns/') - ? await last(ipfs.name.resolve(path, { recursive: true })) - : path) + ipfsPath = decodeURI(ipfsPath) let directory = false let data @@ -157,11 +168,11 @@ module.exports = { const from = catOptions.offset const to = catOptions.offset + catOptions.length - 1 res.header('Content-Range', `bytes ${from}-${to}/${size}`) - res.header('Content-Length', catOptions.length) + res.header('Content-Length', `${catOptions.length}`) } else { // Announce support for Range requests res.header('Accept-Ranges', 'bytes') - res.header('Content-Length', size) + res.header('Content-Length', `${size}`) } // Support Content-Disposition via ?filename=foo parameter @@ -174,8 +185,17 @@ module.exports = { return res }, + /** + * @param {import('../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ afterHandler (request, h) { const { response } = request + + if (Boom.isBoom(response)) { + return h.continue + } + // Add headers to successful responses (regular or range) if (response.statusCode === 200 || response.statusCode === 206) { const path = request.path diff --git a/packages/ipfs-http-gateway/src/types.d.ts b/packages/ipfs-http-gateway/src/types.d.ts new file mode 100644 index 0000000000..8a24cf6a29 --- /dev/null +++ b/packages/ipfs-http-gateway/src/types.d.ts @@ -0,0 +1,14 @@ +import { IPFS } from 'ipfs-core-types' +import { Request, Server } from '@hapi/hapi' +import Multiaddr from 'multiaddrs' + +declare module '@hapi/hapi' { + interface ServerApplicationState { + ipfs: IPFS + } + interface ServerInfo { + ma: Multiaddr + } +} + +export { Request, Server } diff --git a/packages/ipfs-http-gateway/src/utils/path.js b/packages/ipfs-http-gateway/src/utils/path.js index a7f6a58072..9f0564ff19 100644 --- a/packages/ipfs-http-gateway/src/utils/path.js +++ b/packages/ipfs-http-gateway/src/utils/path.js @@ -1,5 +1,8 @@ 'use strict' +/** + * @param {string} path + */ function splitPath (path) { if (path[path.length - 1] === '/') { path = path.substring(0, path.length - 1) @@ -8,6 +11,9 @@ function splitPath (path) { return path.substring(6).split('/') } +/** + * @param {string} url + */ function removeLeadingSlash (url) { if (url[0] === '/') { url = url.substring(1) @@ -16,6 +22,9 @@ function removeLeadingSlash (url) { return url } +/** + * @param {string} url + */ function removeTrailingSlash (url) { if (url.endsWith('/')) { url = url.substring(0, url.length - 1) @@ -24,6 +33,9 @@ function removeTrailingSlash (url) { return url } +/** + * @param {string} url + */ function removeSlashFromBothEnds (url) { url = removeLeadingSlash(url) url = removeTrailingSlash(url) @@ -31,6 +43,9 @@ function removeSlashFromBothEnds (url) { return url } +/** + * @param {...string} urls + */ function joinURLParts (...urls) { urls = urls.filter((url) => url.length > 0) urls = [''].concat(urls.map((url) => removeSlashFromBothEnds(url))) diff --git a/packages/ipfs-http-gateway/test/routes.spec.js b/packages/ipfs-http-gateway/test/routes.spec.js index 5c4ef41be8..5eae5547e3 100644 --- a/packages/ipfs-http-gateway/test/routes.spec.js +++ b/packages/ipfs-http-gateway/test/routes.spec.js @@ -97,7 +97,7 @@ describe('HTTP Gateway', function () { expect(res.rawPayload).to.eql(uint8ArrayFromString('hello world' + '\n')) expect(res.payload).to.equal('hello world' + '\n') expect(res.headers['cache-control']).to.equal('public, max-age=29030400, immutable') - expect(res.headers['content-length']).to.equal(res.rawPayload.length).to.equal(12) + expect(res.headers['content-length']).to.equal(res.rawPayload.length.toString()).to.equal('12') expect(res.headers['last-modified']).to.equal('Thu, 01 Jan 1970 00:00:01 GMT') expect(res.headers.etag).to.equal('"QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o"') expect(res.headers['x-ipfs-path']).to.equal('/ipfs/QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o') @@ -256,7 +256,7 @@ describe('HTTP Gateway', function () { expect(res).to.have.property('statusCode', 200) expect(res.rawPayload).to.eql(content) - expect(res.headers['content-length']).to.equal(res.rawPayload.length).to.equal(15000000) + expect(res.headers['content-length']).to.equal(res.rawPayload.length.toString()).to.equal('15000000') expect(res.headers['x-ipfs-path']).to.equal(`/ipfs/${cid}`) expect(res.headers['etag']).to.equal(`"${cid}"`) expect(res.headers['last-modified']).to.equal('Thu, 01 Jan 1970 00:00:01 GMT') @@ -294,7 +294,7 @@ describe('HTTP Gateway', function () { expect(resFull.headers['accept-ranges']).to.equal('bytes') expect(resFull.headers['etag']).to.equal(`"${cid}"`) expect(resFull.headers['cache-control']).to.equal('public, max-age=29030400, immutable') - expect(resFull.headers['content-length']).to.equal(resFull.rawPayload.length).to.equal(fileLength) + expect(resFull.headers['content-length']).to.equal(resFull.rawPayload.length.toString()).to.equal(fileLength.toString()) // extract expected chunk of interest const rangeValue = `bytes=${range.from}-` @@ -313,7 +313,7 @@ describe('HTTP Gateway', function () { // range headers expect(resRange.statusCode).to.equal(206) expect(resRange.headers['content-range']).to.equal(`bytes ${range.from}-${range.length}/${fileLength}`) - expect(resRange.headers['content-length']).to.equal(resRange.rawPayload.length).to.equal(range.length) + expect(resRange.headers['content-length']).to.equal(resRange.rawPayload.length.toString()).to.equal(range.length.toString()) expect(resRange.headers['accept-ranges']).to.equal(undefined) expect(resRange.rawPayload).to.deep.equal(expectedChunk) // regular headers that should also be present @@ -354,7 +354,7 @@ describe('HTTP Gateway', function () { expect(resFull.headers['accept-ranges']).to.equal('bytes') expect(resFull.headers['etag']).to.equal(`"${cid}"`) expect(resFull.headers['cache-control']).to.equal('public, max-age=29030400, immutable') - expect(resFull.headers['content-length']).to.equal(resFull.rawPayload.length).to.equal(fileLength) + expect(resFull.headers['content-length']).to.equal(resFull.rawPayload.length.toString()).to.equal(fileLength.toString()) // extract expected chunk of interest const rangeValue = `bytes=${range.from}-${range.to}` @@ -373,7 +373,7 @@ describe('HTTP Gateway', function () { // range headers expect(resRange.statusCode).to.equal(206) expect(resRange.headers['content-range']).to.equal(`bytes ${range.from}-${range.to}/${fileLength}`) - expect(resRange.headers['content-length']).to.equal(resRange.rawPayload.length).to.equal(range.length) + expect(resRange.headers['content-length']).to.equal(resRange.rawPayload.length.toString()).to.equal(range.length.toString()) expect(resRange.headers['accept-ranges']).to.equal(undefined) expect(resRange.rawPayload).to.deep.equal(expectedChunk) // regular headers that should also be present @@ -417,7 +417,7 @@ describe('HTTP Gateway', function () { expect(resFull.headers['accept-ranges']).to.equal('bytes') expect(resFull.headers['etag']).to.equal(`"${cid}"`) expect(resFull.headers['cache-control']).to.equal('public, max-age=29030400, immutable') - expect(resFull.headers['content-length']).to.equal(resFull.rawPayload.length).to.equal(fileLength) + expect(resFull.headers['content-length']).to.equal(resFull.rawPayload.length.toString()).to.equal(fileLength.toString()) // extract expected chunk of interest const rangeValue = `bytes=-${range.tail}` @@ -436,7 +436,7 @@ describe('HTTP Gateway', function () { // range headers expect(resRange.statusCode).to.equal(206) expect(resRange.headers['content-range']).to.equal(`bytes ${range.from}-${range.to}/${fileLength}`) - expect(resRange.headers['content-length']).to.equal(resRange.rawPayload.length).to.equal(range.length) + expect(resRange.headers['content-length']).to.equal(resRange.rawPayload.length.toString()).to.equal(range.length.toString()) expect(resRange.headers['accept-ranges']).to.equal(undefined) expect(resRange.rawPayload).to.deep.equal(expectedChunk) // regular headers that should also be present @@ -500,7 +500,7 @@ describe('HTTP Gateway', function () { expect(res).to.have.property('statusCode', 200) expect(res.headers['content-type']).to.equal('image/jpeg') - expect(res.headers['content-length']).to.equal(res.rawPayload.length).to.equal(content.length) + expect(res.headers['content-length']).to.equal(res.rawPayload.length.toString()).to.equal(content.length.toString()) expect(res.headers['x-ipfs-path']).to.equal(`/ipfs/${dirCid}/cat.jpg`) expect(res.headers['etag']).to.equal(`"${fileCid}"`) expect(res.headers['cache-control']).to.equal('public, max-age=29030400, immutable') @@ -633,7 +633,7 @@ describe('HTTP Gateway', function () { expect(res.headers['x-ipfs-path']).to.equal(`/ipfs/${dirCid}/index.html`) expect(res.headers['cache-control']).to.equal('public, max-age=29030400, immutable') expect(res.headers['last-modified']).to.equal('Thu, 01 Jan 1970 00:00:01 GMT') - expect(res.headers['content-length']).to.equal(res.rawPayload.length) + expect(res.headers['content-length']).to.equal(res.rawPayload.length.toString()) expect(res.headers.etag).to.equal(`"${fileCid}"`) expect(res.headers.suborigin).to.equal(`ipfs000${dirCid.toV1().toString('base32')}`) expect(res.rawPayload).to.deep.equal(content) @@ -667,7 +667,7 @@ describe('HTTP Gateway', function () { expect(res.headers['x-ipfs-path']).to.equal(`/ipfs/${dirCid}/nested-folder/nested.html`) expect(res.headers['cache-control']).to.equal('public, max-age=29030400, immutable') expect(res.headers['last-modified']).to.equal('Thu, 01 Jan 1970 00:00:01 GMT') - expect(res.headers['content-length']).to.equal(res.rawPayload.length) + expect(res.headers['content-length']).to.equal(res.rawPayload.length.toString()) expect(res.headers.etag).to.equal(`"${fileCid}"`) expect(res.headers.suborigin).to.equal(`ipfs000${dirCid.toV1().toString('base32')}`) expect(res.rawPayload).to.deep.equal(content) @@ -759,7 +759,7 @@ describe('HTTP Gateway', function () { expect(res.headers['x-ipfs-path']).to.equal(`/ipfs/${dirCid}/`) expect(res.headers['cache-control']).to.equal('public, max-age=29030400, immutable') expect(res.headers['last-modified']).to.equal('Thu, 01 Jan 1970 00:00:01 GMT') - expect(res.headers['content-length']).to.equal(res.rawPayload.length) + expect(res.headers['content-length']).to.equal(res.rawPayload.length.toString()) expect(res.headers.etag).to.equal(`"${fileCid}"`) expect(res.headers.suborigin).to.equal(`ipfs000${dirCid.toV1().toString('base32')}`) expect(res.rawPayload).to.deep.equal(content) @@ -796,7 +796,7 @@ describe('HTTP Gateway', function () { expect(res.headers['x-ipfs-path']).to.equal(escapedPath) expect(res.headers['cache-control']).to.equal('public, max-age=29030400, immutable') expect(res.headers['last-modified']).to.equal('Thu, 01 Jan 1970 00:00:01 GMT') - expect(res.headers['content-length']).to.equal(res.rawPayload.length) + expect(res.headers['content-length']).to.equal(res.rawPayload.length.toString()) expect(res.headers.etag).to.equal(`"${fileCid}"`) expect(res.headers.suborigin).to.equal(`ipfs000${dirCid.toV1().toString('base32')}`) }) @@ -829,7 +829,7 @@ describe('HTTP Gateway', function () { expect(res).to.have.property('statusCode', 200) expect(res.headers['content-type']).to.equal('image/jpeg') - expect(res.headers['content-length']).to.equal(res.rawPayload.length).to.equal(443230) + expect(res.headers['content-length']).to.equal(res.rawPayload.length.toString()).to.equal('443230') expect(res.headers['x-ipfs-path']).to.equal(ipnsPath) expect(res.headers['etag']).to.equal(`"${fileCid}"`) expect(res.headers['cache-control']).to.equal('no-cache') // TODO: should be record TTL diff --git a/packages/ipfs-http-gateway/tsconfig.json b/packages/ipfs-http-gateway/tsconfig.json index bbdcd5851e..35715d452d 100644 --- a/packages/ipfs-http-gateway/tsconfig.json +++ b/packages/ipfs-http-gateway/tsconfig.json @@ -1,18 +1,17 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" ], "references": [ { - "path": "../ipfs-core-utils" + "path": "../ipfs-core" }, { - "path": "../ipfs-core" + "path": "../ipfs-core-utils" } ] } diff --git a/packages/ipfs-http-server/package.json b/packages/ipfs-http-server/package.json index b5a11e8171..c17e930fd4 100644 --- a/packages/ipfs-http-server/package.json +++ b/packages/ipfs-http-server/package.json @@ -11,9 +11,11 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "dist/src/index.d.ts", "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" @@ -24,7 +26,8 @@ "test:node": "aegir test -t node", "coverage": "nyc --reporter=text --reporter=lcov npm run test:node", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i ipfs-http-client -i rimraf -i abort-controller" + "dep-check": "aegir dep-check -i ipfs-http-client -i rimraf -i abort-controller -i ipfs-core-types", + "build": "aegir build --no-bundle" }, "dependencies": { "@hapi/boom": "^9.1.0", @@ -34,18 +37,19 @@ "cids": "^1.1.5", "debug": "^4.1.1", "dlv": "^1.1.3", - "err-code": "^2.0.3", + "err-code": "^3.0.1", "hapi-pino": "^8.3.0", + "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-http-gateway": "^0.3.2", - "ipfs-unixfs": "^2.0.3", - "ipld-dag-pb": "^0.20.0", + "ipfs-unixfs": "^4.0.1", + "ipld-dag-pb": "^0.22.1", "it-all": "^1.0.4", "it-drain": "^1.0.3", "it-first": "^1.0.4", "it-last": "^1.0.4", "it-map": "^1.0.4", - "it-multipart": "^1.0.5", + "it-multipart": "^1.0.8", "it-pipe": "^1.1.0", "it-tar": "^1.2.2", "it-to-stream": "^0.1.2", @@ -64,8 +68,11 @@ "uri-to-multiaddr": "^4.0.0" }, "devDependencies": { - "aegir": "^31.0.0", - "form-data": "^3.0.0", + "@types/hapi__hapi": "^20.0.5", + "@types/hapi-pino": "^8.0.1", + "@types/just-safe-set": "^2.1.0", + "aegir": "^32.1.0", + "form-data": "^4.0.0", "ipfs-http-client": "^49.0.4", "iso-random-stream": "^1.1.1", "it-to-buffer": "^1.0.2", diff --git a/packages/ipfs-http-server/src/api/resources/bitswap.js b/packages/ipfs-http-server/src/api/resources/bitswap.js index 2154963e40..74c078c569 100644 --- a/packages/ipfs-http-server/src/api/resources/bitswap.js +++ b/packages/ipfs-http-server/src/api/resources/bitswap.js @@ -11,7 +11,7 @@ exports.wantlist = { stripUnknown: true }, query: Joi.object().keys({ - peer: Joi.peerId(), + peer: Joi.cid(), cidBase: Joi.cidBase(), timeout: Joi.timeout() }) @@ -21,6 +21,11 @@ exports.wantlist = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -77,6 +82,11 @@ exports.stat = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -98,20 +108,18 @@ exports.stat = { timeout }) - stats.wantlist = stats.wantlist.map(cid => ({ - '/': cidToString(cid, { base: cidBase, upgrade: false }) - })) - return h.response({ ProvideBufLen: stats.provideBufLen, - BlocksReceived: stats.blocksReceived, - Wantlist: stats.wantlist, + BlocksReceived: stats.blocksReceived.toString(), + Wantlist: stats.wantlist.map(cid => ({ + '/': cidToString(cid, { base: cidBase, upgrade: false }) + })), Peers: stats.peers, - DupBlksReceived: stats.dupBlksReceived, - DupDataReceived: stats.dupDataReceived, - DataReceived: stats.dataReceived, - BlocksSent: stats.blocksSent, - DataSent: stats.dataSent + DupBlksReceived: stats.dupBlksReceived.toString(), + DupDataReceived: stats.dupDataReceived.toString(), + DataReceived: stats.dataReceived.toString(), + BlocksSent: stats.blocksSent.toString(), + DataSent: stats.dataSent.toString() }) } } @@ -138,7 +146,11 @@ exports.unwant = { }) } }, - // main route handler which is called after the above `parseArgs`, but only if the args were valid + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/block.js b/packages/ipfs-http-server/src/api/resources/block.js index bee96e199c..be4e47ecae 100644 --- a/packages/ipfs-http-server/src/api/resources/block.js +++ b/packages/ipfs-http-server/src/api/resources/block.js @@ -9,6 +9,7 @@ const { cidToString } = require('ipfs-core-utils/src/cid') const all = require('it-all') const { pipe } = require('it-pipe') const { map } = require('streaming-iterables') +// @ts-ignore no types const ndjson = require('iterable-ndjson') const streamResponse = require('../../utils/stream-response') @@ -34,7 +35,10 @@ exports.get = { } }, - // main route handler which is called after the above `parseArgs`, but only if the args were valid + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -76,6 +80,10 @@ exports.put = { }, pre: [{ assign: 'args', + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} _h + */ method: async (request, _h) => { if (!request.payload) { throw Boom.badRequest("File argument 'data' is required") @@ -83,7 +91,7 @@ exports.put = { let data - for await (const part of multipart(request)) { + for await (const part of multipart(request.raw.req)) { if (part.type !== 'file') { continue } @@ -118,6 +126,11 @@ exports.put = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -190,6 +203,11 @@ exports.rm = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { @@ -244,7 +262,11 @@ exports.stat = { }) } }, - // main route handler which is called after the above `parseArgs`, but only if the args were valid + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/bootstrap.js b/packages/ipfs-http-server/src/api/resources/bootstrap.js index 541f6d9a2b..af4c7ed091 100644 --- a/packages/ipfs-http-server/src/api/resources/bootstrap.js +++ b/packages/ipfs-http-server/src/api/resources/bootstrap.js @@ -15,6 +15,11 @@ exports.list = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -56,6 +61,11 @@ exports.add = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -105,6 +115,11 @@ exports.addDefault = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -146,6 +161,11 @@ exports.rm = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -195,6 +215,11 @@ exports.rmAll = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/config.js b/packages/ipfs-http-server/src/api/resources/config.js index 67504f1fd9..379f6c82d3 100644 --- a/packages/ipfs-http-server/src/api/resources/config.js +++ b/packages/ipfs-http-server/src/api/resources/config.js @@ -19,7 +19,14 @@ exports.getOrSet = { }, pre: [{ assign: 'args', + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} _h + */ method: (request, _h) => { + /** + * @param {{ key: string, value: any }} args + */ const parseValue = (args) => { if (request.query.bool) { args.value = args.value === 'true' @@ -70,6 +77,11 @@ exports.getOrSet = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -154,6 +166,11 @@ exports.get = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -197,6 +214,11 @@ exports.show = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -234,6 +256,10 @@ exports.replace = { }, pre: [{ assign: 'args', + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} _h + */ method: async (request, _h) => { if (!request.payload) { throw Boom.badRequest("Argument 'file' is required") @@ -241,7 +267,7 @@ exports.replace = { let file - for await (const part of multipart(request)) { + for await (const part of multipart(request.raw.req)) { if (part.type !== 'file') { continue } @@ -270,6 +296,11 @@ exports.replace = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -326,6 +357,11 @@ exports.profiles = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async function (request, h) { const { app: { @@ -368,6 +404,11 @@ exports.profiles = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async function (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/dag.js b/packages/ipfs-http-server/src/api/resources/dag.js index b76e19a33c..2e313c3c47 100644 --- a/packages/ipfs-http-server/src/api/resources/dag.js +++ b/packages/ipfs-http-server/src/api/resources/dag.js @@ -10,6 +10,10 @@ const { const all = require('it-all') const uint8ArrayToString = require('uint8arrays/to-string') +/** + * @param {undefined | Uint8Array | Record} obj + * @param {import('multibase').BaseName | 'utf8' | 'utf-8' | 'ascii'} encoding + */ const encodeBufferKeys = (obj, encoding) => { if (!obj) { return obj @@ -20,7 +24,7 @@ const encodeBufferKeys = (obj, encoding) => { } Object.keys(obj).forEach(key => { - if (obj instanceof Uint8Array) { + if (obj[key] instanceof Uint8Array) { obj[key] = uint8ArrayToString(obj[key], encoding) return @@ -57,6 +61,11 @@ exports.get = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -113,6 +122,10 @@ exports.put = { }, pre: [{ assign: 'args', + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} _h + */ method: async (request, _h) => { if (!request.payload) { throw Boom.badRequest("File argument 'object data' is required") @@ -126,7 +139,7 @@ exports.put = { let data - for await (const part of multipart(request)) { + for await (const part of multipart(request.raw.req)) { if (part.type !== 'file') { continue } @@ -196,6 +209,11 @@ exports.put = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -263,6 +281,11 @@ exports.resolve = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/dht.js b/packages/ipfs-http-server/src/api/resources/dht.js index 1cfa2f42d2..85dc418115 100644 --- a/packages/ipfs-http-server/src/api/resources/dht.js +++ b/packages/ipfs-http-server/src/api/resources/dht.js @@ -3,10 +3,13 @@ const Joi = require('../../utils/joi') const Boom = require('@hapi/boom') const { pipe } = require('it-pipe') +// @ts-ignore no types const ndjson = require('iterable-ndjson') +// @ts-ignore no types const toStream = require('it-to-stream') const { map } = require('streaming-iterables') const { PassThrough } = require('stream') +// @ts-ignore no types const toIterable = require('stream-to-it') const debug = require('debug') const log = Object.assign(debug('ipfs:http-api:dht'), { @@ -21,7 +24,7 @@ exports.findPeer = { stripUnknown: true }, query: Joi.object().keys({ - peerId: Joi.peerId().required(), + peerId: Joi.cid().required(), timeout: Joi.timeout() }) .rename('arg', 'peerId', { @@ -30,6 +33,11 @@ exports.findPeer = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -93,6 +101,11 @@ exports.findProvs = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { @@ -125,7 +138,7 @@ exports.findProvs = { return { Responses: [{ ID: id.toString(), - Addrs: (addrs || []).map(a => a.toString()) + Addrs: (addrs || []).map((/** @type {import('multiaddr')} */ a) => a.toString()) }], Type: 4 } @@ -133,7 +146,7 @@ exports.findProvs = { ndjson.stringify, toIterable.sink(output) ) - .catch(err => { + .catch((/** @type {Error} */ err) => { log.error(err) if (!providersFound && output.writable) { @@ -175,6 +188,11 @@ exports.get = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -220,6 +238,11 @@ exports.provide = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -258,6 +281,11 @@ exports.put = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -294,7 +322,7 @@ exports.query = { stripUnknown: true }, query: Joi.object().keys({ - peerId: Joi.peerId().required(), + peerId: Joi.cid().required(), timeout: Joi.timeout() }) .rename('arg', 'peerId', { @@ -303,6 +331,11 @@ exports.query = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/dns.js b/packages/ipfs-http-server/src/api/resources/dns.js index b1af27c9c2..90162bed52 100644 --- a/packages/ipfs-http-server/src/api/resources/dns.js +++ b/packages/ipfs-http-server/src/api/resources/dns.js @@ -25,6 +25,11 @@ module.exports = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -38,14 +43,12 @@ module.exports = { query: { domain, recursive, - format, timeout } } = request const path = await ipfs.dns(domain, { recursive, - format, signal, timeout }) diff --git a/packages/ipfs-http-server/src/api/resources/files-regular.js b/packages/ipfs-http-server/src/api/resources/files-regular.js index c3d9725bd1..934a8c0bcb 100644 --- a/packages/ipfs-http-server/src/api/resources/files-regular.js +++ b/packages/ipfs-http-server/src/api/resources/files-regular.js @@ -2,10 +2,12 @@ const multipart = require('../../utils/multipart-request-parser') const debug = require('debug') +// @ts-ignore no types const tar = require('it-tar') const log = Object.assign(debug('ipfs:http-api:files'), { error: debug('ipfs:http-api:files:error') }) +// @ts-ignore no types const toIterable = require('stream-to-it') const Joi = require('../../utils/joi') const Boom = require('@hapi/boom') @@ -13,10 +15,14 @@ const { PassThrough } = require('stream') const { cidToString } = require('ipfs-core-utils/src/cid') const { pipe } = require('it-pipe') const all = require('it-all') +// @ts-ignore no types const ndjson = require('iterable-ndjson') const { map } = require('streaming-iterables') const streamResponse = require('../../utils/stream-response') +/** + * @param {AsyncIterable} source + */ const toBuffer = async function * (source) { for await (const chunk of source) { yield chunk.slice() @@ -44,7 +50,10 @@ exports.cat = { } }, - // main route handler which is called after the above `parseArgs`, but only if the args were valid + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { @@ -100,7 +109,10 @@ exports.get = { } }, - // main route handler which is called after the above `parseArgs`, but only if the args were valid + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { @@ -113,28 +125,25 @@ exports.get = { }, query: { path, - archive, - compress, - compressionLevel, timeout } } = request return streamResponse(request, h, () => pipe( ipfs.get(path, { - archive, - compress, - compressionLevel, timeout, signal }), + /** + * @param {AsyncIterable} source + */ async function * (source) { for await (const file of source) { const header = { name: file.path } - if (file.content) { + if (file.type === 'file' && file.content != null) { yield { header: { ...header, size: file.size }, body: toBuffer(file.content) } } else { yield { header: { ...header, type: 'directory' } } @@ -214,6 +223,11 @@ exports.add = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { if (!request.payload) { throw Boom.badRequest('Array, Buffer, or String is required.') @@ -247,21 +261,25 @@ exports.add = { } = request let filesParsed = false - let currentFileName const output = new PassThrough() - const progressHandler = bytes => { + /** + * @type {import('ipfs-core-types/src/root').AddProgressFn} + */ + const progressHandler = (bytes, path) => { + // TODO: path should be passed as a second option output.write(JSON.stringify({ - Name: currentFileName, + Name: path, Bytes: bytes }) + '\n') } pipe( - multipart(request), + multipart(request.raw.req), + /** + * @param {AsyncIterable} source + */ async function * (source) { for await (const entry of source) { - currentFileName = entry.name || '' - if (entry.type === 'file') { filesParsed = true @@ -284,6 +302,9 @@ exports.add = { } } }, + /** + * @param {import('ipfs-core-types/src/utils').ImportSource} source + */ function (source) { return ipfs.addAll(source, { cidVersion, @@ -308,19 +329,14 @@ exports.add = { }) }, map(file => { - const entry = { + return { Name: file.path, Hash: cidToString(file.cid, { base: cidBase }), Size: file.size, - Mode: file.mode === undefined ? undefined : file.mode.toString(8).padStart(4, '0') + Mode: file.mode === undefined ? undefined : file.mode.toString(8).padStart(4, '0'), + Mtime: file.mtime ? file.mtime.secs : undefined, + MtimeNsecs: file.mtime ? file.mtime.nsecs : undefined } - - if (file.mtime) { - entry.Mtime = file.mtime.secs - entry.MtimeNsecs = file.mtime.nsecs - } - - return entry }), ndjson.stringify, toIterable.sink(output) @@ -330,7 +346,7 @@ exports.add = { throw new Error("File argument 'data' is required.") } }) - .catch(err => { + .catch((/** @type {Error} */ err) => { log.error(err) if (!filesParsed && output.writable) { @@ -380,6 +396,11 @@ exports.ls = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -399,31 +420,22 @@ exports.ls = { } } = request + /** + * TODO: can be ipfs.files.stat result or ipfs.ls result + * + * @param {any} link + */ const mapLink = link => { - const output = { + return { Hash: cidToString(link.cid, { base: cidBase }), Size: link.size, Type: toTypeCode(link.type), - Depth: link.depth - } - - if (link.name) { - output.Name = link.name + Depth: link.depth, + Name: link.name ? link.name : undefined, + Mode: link.mode != null ? link.mode.toString(8).padStart(4, '0') : undefined, + Mtime: link.mtime ? link.mtime.secs : undefined, + MtimeNsecs: link.mtime ? link.mtime.nsecs : undefined } - - if (link.mode != null) { - output.Mode = link.mode.toString(8).padStart(4, '0') - } - - if (link.mtime) { - output.Mtime = link.mtime.secs - - if (link.mtime.nsecs !== null && link.mtime.nsecs !== undefined) { - output.MtimeNsecs = link.mtime.nsecs - } - } - - return output } const stat = await ipfs.files.stat(path.startsWith('/ipfs/') ? path : `/ipfs/${path}`) @@ -466,6 +478,9 @@ exports.ls = { } } +/** + * @param {string} type + */ function toTypeCode (type) { switch (type) { case 'dir': @@ -503,6 +518,11 @@ exports.refs = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { @@ -552,6 +572,11 @@ exports.refsLocal = { }) } }, + + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/files/chmod.js b/packages/ipfs-http-server/src/api/resources/files/chmod.js index 30ce359f3c..a97d4be390 100644 --- a/packages/ipfs-http-server/src/api/resources/files/chmod.js +++ b/packages/ipfs-http-server/src/api/resources/files/chmod.js @@ -36,6 +36,11 @@ const mfsChmod = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/files/cp.js b/packages/ipfs-http-server/src/api/resources/files/cp.js index 99e564f512..b82d2d2efa 100644 --- a/packages/ipfs-http-server/src/api/resources/files/cp.js +++ b/packages/ipfs-http-server/src/api/resources/files/cp.js @@ -40,6 +40,11 @@ const mfsCp = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -61,7 +66,9 @@ const mfsCp = { } } = request - const args = paths.concat({ + const dest = paths.pop() + + await ipfs.files.cp(paths, dest, { parents, flush, hashAlg, @@ -71,8 +78,6 @@ const mfsCp = { timeout }) - await ipfs.files.cp.apply(null, args) - return h.response() } } diff --git a/packages/ipfs-http-server/src/api/resources/files/flush.js b/packages/ipfs-http-server/src/api/resources/files/flush.js index 60166173f7..7fc3398671 100644 --- a/packages/ipfs-http-server/src/api/resources/files/flush.js +++ b/packages/ipfs-http-server/src/api/resources/files/flush.js @@ -25,6 +25,11 @@ const mfsFlush = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/files/ls.js b/packages/ipfs-http-server/src/api/resources/files/ls.js index 3170c65679..22a6bd6642 100644 --- a/packages/ipfs-http-server/src/api/resources/files/ls.js +++ b/packages/ipfs-http-server/src/api/resources/files/ls.js @@ -6,29 +6,22 @@ const map = require('it-map') const { pipe } = require('it-pipe') const streamResponse = require('../../../utils/stream-response') +/** + * @param {*} entry + * @param {{ cidBase?: string, long?: boolean }} options + */ const mapEntry = (entry, options = {}) => { const type = entry.type === 'file' ? 0 : 1 - const output = { + return { Name: entry.name, Type: options.long ? type : 0, Size: options.long ? entry.size || 0 : 0, - Hash: entry.cid.toString(options.cidBase) + Hash: entry.cid.toString(options.cidBase), + Mtime: entry.mtime ? entry.mtime.secs : undefined, + MtimeNsecs: entry.mtime ? entry.mtime.nsecs : undefined, + Mode: entry.mode != null ? entry.mode.toString(8).padStart(4, '0') : undefined } - - if (entry.mtime) { - output.Mtime = entry.mtime.secs - - if (entry.mtime.nsecs != null) { - output.MtimeNsecs = entry.mtime.nsecs - } - } - - if (entry.mode != null) { - output.Mode = entry.mode.toString(8).padStart(4, '0') - } - - return output } const mfsLs = { @@ -51,6 +44,11 @@ const mfsLs = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/files/mkdir.js b/packages/ipfs-http-server/src/api/resources/files/mkdir.js index a0ae41c6ec..6723334350 100644 --- a/packages/ipfs-http-server/src/api/resources/files/mkdir.js +++ b/packages/ipfs-http-server/src/api/resources/files/mkdir.js @@ -48,6 +48,11 @@ const mfsMkdir = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { ipfs diff --git a/packages/ipfs-http-server/src/api/resources/files/mv.js b/packages/ipfs-http-server/src/api/resources/files/mv.js index 028ed27067..9a852994fc 100644 --- a/packages/ipfs-http-server/src/api/resources/files/mv.js +++ b/packages/ipfs-http-server/src/api/resources/files/mv.js @@ -37,6 +37,11 @@ const mfsMv = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { ipfs diff --git a/packages/ipfs-http-server/src/api/resources/files/read.js b/packages/ipfs-http-server/src/api/resources/files/read.js index f5c344eab8..f5bcacc6ae 100644 --- a/packages/ipfs-http-server/src/api/resources/files/read.js +++ b/packages/ipfs-http-server/src/api/resources/files/read.js @@ -30,6 +30,11 @@ const mfsRead = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { ipfs diff --git a/packages/ipfs-http-server/src/api/resources/files/rm.js b/packages/ipfs-http-server/src/api/resources/files/rm.js index bb85efb698..2530706c46 100644 --- a/packages/ipfs-http-server/src/api/resources/files/rm.js +++ b/packages/ipfs-http-server/src/api/resources/files/rm.js @@ -25,25 +25,35 @@ const mfsRm = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { - ipfs - } = request.server.app - const { - arg, - recursive, - shardSplitThreshold, - timeout - } = request.query + server: { + app: { + ipfs + } + }, + query: { + arg, + recursive, + shardSplitThreshold, + timeout + }, + app: { + signal + } + } = request - const args = [...arg, { + await ipfs.files.rm(arg, { recursive, shardSplitThreshold, - signal: request.app.signal, + signal, timeout - }] - - await ipfs.files.rm.apply(null, args) + }) return h.response() } diff --git a/packages/ipfs-http-server/src/api/resources/files/stat.js b/packages/ipfs-http-server/src/api/resources/files/stat.js index 35fe68bfc9..222a204ac6 100644 --- a/packages/ipfs-http-server/src/api/resources/files/stat.js +++ b/packages/ipfs-http-server/src/api/resources/files/stat.js @@ -19,6 +19,11 @@ const mfsStat = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { ipfs @@ -48,19 +53,10 @@ const mfsStat = { CumulativeSize: stats.cumulativeSize, WithLocality: stats.withLocality, Local: stats.local, - SizeLocal: stats.sizeLocal - } - - if (stats.mtime) { - output.Mtime = stats.mtime.secs - - if (stats.mtime.nsecs) { - output.MtimeNsecs = stats.mtime.nsecs - } - } - - if (stats.mode != null) { - output.Mode = stats.mode.toString(8).padStart(4, '0') + SizeLocal: stats.sizeLocal, + Mtime: stats.mtime ? stats.mtime.secs : undefined, + MtimeNsecs: stats.mtime ? stats.mtime.nsecs : undefined, + Mode: stats.mode != null ? stats.mode.toString(8).padStart(4, '0') : undefined } return h.response(output) diff --git a/packages/ipfs-http-server/src/api/resources/files/touch.js b/packages/ipfs-http-server/src/api/resources/files/touch.js index 444576581a..3ffc8793fb 100644 --- a/packages/ipfs-http-server/src/api/resources/files/touch.js +++ b/packages/ipfs-http-server/src/api/resources/files/touch.js @@ -42,6 +42,11 @@ const mfsTouch = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { ipfs diff --git a/packages/ipfs-http-server/src/api/resources/files/utils/parse-mtime.js b/packages/ipfs-http-server/src/api/resources/files/utils/parse-mtime.js index 863c53b7ac..516d08b4ca 100644 --- a/packages/ipfs-http-server/src/api/resources/files/utils/parse-mtime.js +++ b/packages/ipfs-http-server/src/api/resources/files/utils/parse-mtime.js @@ -1,7 +1,11 @@ 'use strict' +/** + * @param {number | undefined} secs + * @param {number | undefined} nsecs + */ module.exports = (secs, nsecs) => { - if ((secs === undefined || secs === null) && (nsecs === undefined || nsecs === null)) { + if (secs == null && nsecs == null) { return } diff --git a/packages/ipfs-http-server/src/api/resources/files/write.js b/packages/ipfs-http-server/src/api/resources/files/write.js index 60661b9e82..870672bcd0 100644 --- a/packages/ipfs-http-server/src/api/resources/files/write.js +++ b/packages/ipfs-http-server/src/api/resources/files/write.js @@ -27,7 +27,6 @@ const mfsWrite = { cidVersion: Joi.number().integer().valid(0, 1).default(0), hashAlg: Joi.string().default('sha2-256'), parents: Joi.boolean().default(false), - progress: Joi.func(), strategy: Joi.string().valid('flat', 'balanced', 'trickle').default('trickle'), flush: Joi.boolean().default(true), reduceSingleLeafToSelf: Joi.boolean().default(false), @@ -72,6 +71,11 @@ const mfsWrite = { }) } }, + + /** + * @param {import('../../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { ipfs @@ -87,7 +91,6 @@ const mfsWrite = { cidVersion, hashAlg, parents, - progress, strategy, flush, shardSplitThreshold, @@ -96,7 +99,7 @@ const mfsWrite = { let files = 0 - for await (const entry of multipart(request)) { + for await (const entry of multipart(request.raw.req)) { if (entry.type === 'file') { files++ @@ -114,7 +117,6 @@ const mfsWrite = { cidVersion, hashAlg, parents, - progress, strategy, flush, shardSplitThreshold, diff --git a/packages/ipfs-http-server/src/api/resources/id.js b/packages/ipfs-http-server/src/api/resources/id.js index bdece8a0f6..fa69f797a3 100644 --- a/packages/ipfs-http-server/src/api/resources/id.js +++ b/packages/ipfs-http-server/src/api/resources/id.js @@ -14,6 +14,10 @@ module.exports = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/key.js b/packages/ipfs-http-server/src/api/resources/key.js index c935f9a6a0..9e24a75729 100644 --- a/packages/ipfs-http-server/src/api/resources/key.js +++ b/packages/ipfs-http-server/src/api/resources/key.js @@ -2,6 +2,9 @@ const Joi = require('../../utils/joi') +/** + * @param {any} key + */ function toKeyInfo (key) { return { Name: key.name, @@ -21,6 +24,10 @@ exports.list = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -62,6 +69,10 @@ exports.rm = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -100,6 +111,10 @@ exports.rename = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -152,6 +167,10 @@ exports.gen = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -200,6 +219,10 @@ exports.import = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/name.js b/packages/ipfs-http-server/src/api/resources/name.js index 539b84db49..54fafee3cc 100644 --- a/packages/ipfs-http-server/src/api/resources/name.js +++ b/packages/ipfs-http-server/src/api/resources/name.js @@ -4,6 +4,7 @@ const Joi = require('../../utils/joi') const { pipe } = require('it-pipe') const { map } = require('streaming-iterables') const last = require('it-last') +// @ts-ignore no types const ndjson = require('iterable-ndjson') const streamResponse = require('../../utils/stream-response') @@ -27,6 +28,10 @@ exports.resolve = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -95,6 +100,10 @@ exports.publish = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -146,6 +155,10 @@ exports.pubsub = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -183,6 +196,10 @@ exports.pubsub = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -225,6 +242,10 @@ exports.pubsub = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/object.js b/packages/ipfs-http-server/src/api/resources/object.js index 69290fb939..53da8a6ff5 100644 --- a/packages/ipfs-http-server/src/api/resources/object.js +++ b/packages/ipfs-http-server/src/api/resources/object.js @@ -14,6 +14,10 @@ const log = Object.assign(debug('ipfs:http-api:object'), { error: debug('ipfs:http-api:object:error') }) +/** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} _h + */ const readFilePart = async (request, _h) => { if (!request.payload) { throw Boom.badRequest("File argument 'data' is required") @@ -21,7 +25,7 @@ const readFilePart = async (request, _h) => { let data - for await (const part of multipart(request)) { + for await (const part of multipart(request.raw.req)) { if (part.type !== 'file') { continue } @@ -69,6 +73,10 @@ exports.new = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -130,7 +138,6 @@ exports.get = { query: Joi.object().keys({ cid: Joi.cid().required(), cidBase: Joi.cidBase(), - enc: Joi.string(), dataEncoding: Joi.string() .valid('ascii', 'base64pad', 'base16', 'utf8') .replace(/text/, 'ascii') @@ -153,6 +160,10 @@ exports.get = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -166,7 +177,6 @@ exports.get = { query: { cid, cidBase, - enc, dataEncoding, timeout } @@ -175,7 +185,6 @@ exports.get = { let node try { node = await ipfs.object.get(cid, { - enc, signal, timeout }) @@ -224,6 +233,10 @@ exports.put = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -302,6 +315,10 @@ exports.stat = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -345,7 +362,6 @@ exports.data = { query: Joi.object().keys({ cid: Joi.cid().required(), cidBase: Joi.cidBase(), - enc: Joi.string(), timeout: Joi.timeout() }) .rename('cid-base', 'cidBase', { @@ -358,6 +374,10 @@ exports.data = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -370,7 +390,6 @@ exports.data = { }, query: { cid, - enc, timeout } } = request @@ -378,7 +397,6 @@ exports.data = { let data try { data = await ipfs.object.data(cid, { - enc, signal, timeout }) @@ -400,7 +418,6 @@ exports.links = { query: Joi.object().keys({ cid: Joi.cid().required(), cidBase: Joi.cidBase(), - enc: Joi.string(), timeout: Joi.timeout() }) .rename('cid-base', 'cidBase', { @@ -413,6 +430,10 @@ exports.links = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -426,22 +447,18 @@ exports.links = { query: { cid, cidBase, - enc, timeout } } = request - const response = { - Hash: cidToString(cid, { base: cidBase, upgrade: false }) - } const links = await ipfs.object.links(cid, { - enc, signal, timeout }) - if (links) { - response.Links = links.map((l) => { + const response = { + Hash: cidToString(cid, { base: cidBase, upgrade: false }), + Links: (links || []).map((l) => { return { Name: l.Name, Size: l.Tsize, @@ -472,7 +489,6 @@ exports.patchAppendData = { query: Joi.object().keys({ cid: Joi.cid().required(), cidBase: Joi.cidBase(), - enc: Joi.string(), timeout: Joi.timeout() }) .rename('cid-base', 'cidBase', { @@ -489,6 +505,10 @@ exports.patchAppendData = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -507,7 +527,6 @@ exports.patchAppendData = { query: { cid, cidBase, - enc, timeout } } = request @@ -515,7 +534,6 @@ exports.patchAppendData = { let newCid, node try { newCid = await ipfs.object.patch.appendData(cid, data, { - enc, signal, timeout }) @@ -564,7 +582,6 @@ exports.patchSetData = { query: Joi.object().keys({ cid: Joi.cid().required(), cidBase: Joi.cidBase(), - enc: Joi.string(), timeout: Joi.timeout() }) .rename('cid-base', 'cidBase', { @@ -577,6 +594,10 @@ exports.patchSetData = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -595,7 +616,6 @@ exports.patchSetData = { query: { cid, cidBase, - enc, timeout } } = request @@ -603,7 +623,6 @@ exports.patchSetData = { let newCid, node try { newCid = await ipfs.object.patch.setData(cid, data, { - enc, signal, timeout }) @@ -643,7 +662,6 @@ exports.patchAddLink = { Joi.cid().required() ).required(), cidBase: Joi.cidBase(), - enc: Joi.string(), timeout: Joi.timeout() }) .rename('cid-base', 'cidBase', { @@ -656,6 +674,10 @@ exports.patchAddLink = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -673,7 +695,6 @@ exports.patchAddLink = { ref ], cidBase, - enc, timeout } } = request @@ -681,12 +702,10 @@ exports.patchAddLink = { let node, cid try { node = await ipfs.object.get(ref, { - enc, signal, timeout }) cid = await ipfs.object.patch.addLink(root, new DAGLink(name, node.size, ref), { - enc, signal, timeout }) @@ -730,7 +749,6 @@ exports.patchRmLink = { Joi.string().required() ).required(), cidBase: Joi.cidBase(), - enc: Joi.string(), timeout: Joi.timeout() }) .rename('cid-base', 'cidBase', { @@ -743,6 +761,10 @@ exports.patchRmLink = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -759,16 +781,13 @@ exports.patchRmLink = { link ], cidBase, - enc, timeout } } = request let cid, node try { - cid = await ipfs.object.patch.rmLink(root, { - name: link, - enc, + cid = await ipfs.object.patch.rmLink(root, link, { signal, timeout }) diff --git a/packages/ipfs-http-server/src/api/resources/pin.js b/packages/ipfs-http-server/src/api/resources/pin.js index 207023c217..8b020d024a 100644 --- a/packages/ipfs-http-server/src/api/resources/pin.js +++ b/packages/ipfs-http-server/src/api/resources/pin.js @@ -4,12 +4,23 @@ const Joi = require('../../utils/joi') const Boom = require('@hapi/boom') const { map, reduce } = require('streaming-iterables') const { pipe } = require('it-pipe') +// @ts-ignore no types const ndjson = require('iterable-ndjson') const { cidToString } = require('ipfs-core-utils/src/cid') const streamResponse = require('../../utils/stream-response') const all = require('it-all') +/** + * @typedef {import('cids')} CID + */ + +/** + * @param {string} type + * @param {string} [cid] + * @param {Record} [metadata] + */ function toPin (type, cid, metadata) { + /** @type {{ Type: string, Cid?: string, Metadata?: Record }} */ const output = { Type: type } @@ -50,6 +61,10 @@ exports.ls = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -79,8 +94,8 @@ exports.ls = { if (!stream) { const res = await pipe( source, - reduce((res, { type, cid, metadata }) => { - res.Keys[cidToString(cid, { base: cidBase })] = toPin(type, metadata) + reduce((/** @type {{ Keys: Record }} */ res, { type, cid, metadata }) => { + res.Keys[cidToString(cid, { base: cidBase })] = toPin(type, undefined, metadata) return res }, { Keys: {} }) ) @@ -120,6 +135,10 @@ exports.add = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -141,7 +160,7 @@ exports.add = { let result try { - result = await all(ipfs.pin.addAll(cids.map(cid => ({ cid, recursive, metadata })), { + result = await all(ipfs.pin.addAll(cids.map((/** @type {CID} */ cid) => ({ cid, recursive, metadata })), { signal, timeout })) @@ -186,6 +205,10 @@ exports.rm = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -206,7 +229,7 @@ exports.rm = { let result try { - result = await all(ipfs.pin.rmAll(cids.map(cid => ({ cid, recursive })), { + result = await all(ipfs.pin.rmAll(cids.map((/** @type {CID} */ cid) => ({ cid, recursive })), { signal, timeout })) diff --git a/packages/ipfs-http-server/src/api/resources/ping.js b/packages/ipfs-http-server/src/api/resources/ping.js index 0d8af0452a..63ed42eb25 100644 --- a/packages/ipfs-http-server/src/api/resources/ping.js +++ b/packages/ipfs-http-server/src/api/resources/ping.js @@ -3,6 +3,7 @@ const Joi = require('../../utils/joi') const { pipe } = require('it-pipe') const { map } = require('streaming-iterables') +// @ts-ignore no types const ndjson = require('iterable-ndjson') const streamResponse = require('../../utils/stream-response') @@ -15,7 +16,7 @@ module.exports = { }, query: Joi.object().keys({ count: Joi.number().integer().greater(0).default(10), - peerId: Joi.peerId().required(), + peerId: Joi.cid().required(), timeout: Joi.timeout() }) .rename('arg', 'peerId', { @@ -28,6 +29,10 @@ module.exports = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/pubsub.js b/packages/ipfs-http-server/src/api/resources/pubsub.js index b974535b09..5d62a3a45d 100644 --- a/packages/ipfs-http-server/src/api/resources/pubsub.js +++ b/packages/ipfs-http-server/src/api/resources/pubsub.js @@ -19,8 +19,7 @@ exports.subscribe = { stripUnknown: true }, query: Joi.object().keys({ - topic: Joi.string().required(), - discover: Joi.boolean() + topic: Joi.string().required() }) .rename('arg', 'topic', { override: true, @@ -28,6 +27,10 @@ exports.subscribe = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -39,12 +42,14 @@ exports.subscribe = { } }, query: { - topic, - discover + topic } } = request const res = new PassThrough({ highWaterMark: 1 }) + /** + * @type {import('ipfs-core-types/src/pubsub').MessageHandlerFn} + */ const handler = (msg) => { res.write(JSON.stringify({ from: uint8ArrayToString(uint8ArrayFromString(msg.from, 'base58btc'), 'base64pad'), @@ -66,7 +71,6 @@ exports.subscribe = { request.events.once('finish', unsubscribe) await ipfs.pubsub.subscribe(topic, handler, { - discover: discover, signal }) @@ -85,6 +89,10 @@ exports.publish = { }, pre: [{ assign: 'data', + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} _h + */ method: async (request, _h) => { if (!request.payload) { throw Boom.badRequest('argument "data" is required') @@ -92,7 +100,7 @@ exports.publish = { let data - for await (const part of multipart(request)) { + for await (const part of multipart(request.raw.req)) { if (part.type === 'file') { data = Buffer.concat(await all(part.content)) } @@ -121,6 +129,10 @@ exports.publish = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -165,6 +177,10 @@ exports.ls = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -211,6 +227,10 @@ exports.peers = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/repo.js b/packages/ipfs-http-server/src/api/resources/repo.js index 32b210ae78..abb3f42e28 100644 --- a/packages/ipfs-http-server/src/api/resources/repo.js +++ b/packages/ipfs-http-server/src/api/resources/repo.js @@ -3,6 +3,7 @@ const Joi = require('../../utils/joi') const { map, filter } = require('streaming-iterables') const { pipe } = require('it-pipe') +// @ts-ignore no types const ndjson = require('iterable-ndjson') const streamResponse = require('../../utils/stream-response') @@ -23,6 +24,10 @@ exports.gc = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { @@ -66,6 +71,10 @@ exports.version = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -103,6 +112,10 @@ exports.stat = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: async (request, h) => { const { app: { @@ -124,11 +137,11 @@ exports.stat = { }) return h.response({ - NumObjects: stat.numObjects, - RepoSize: stat.repoSize, + NumObjects: stat.numObjects.toString(), + RepoSize: stat.repoSize.toString(), RepoPath: stat.repoPath, Version: stat.version, - StorageMax: stat.storageMax + StorageMax: stat.storageMax.toString() }) } diff --git a/packages/ipfs-http-server/src/api/resources/resolve.js b/packages/ipfs-http-server/src/api/resources/resolve.js index 5b97ecd328..68fed902fc 100644 --- a/packages/ipfs-http-server/src/api/resources/resolve.js +++ b/packages/ipfs-http-server/src/api/resources/resolve.js @@ -25,6 +25,10 @@ module.exports = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/shutdown.js b/packages/ipfs-http-server/src/api/resources/shutdown.js index 428c902226..9a5115c6d8 100644 --- a/packages/ipfs-http-server/src/api/resources/shutdown.js +++ b/packages/ipfs-http-server/src/api/resources/shutdown.js @@ -7,6 +7,10 @@ * on the next 'tick' emits SIGTERM. */ module.exports = { + /** + * @param {import('../../types').Request} _request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler: (_request, h) => { // @ts-ignore - TS expects second argument setImmediate(() => process.emit('SIGTERM')) diff --git a/packages/ipfs-http-server/src/api/resources/stats.js b/packages/ipfs-http-server/src/api/resources/stats.js index 6cb999ba20..80628038c1 100644 --- a/packages/ipfs-http-server/src/api/resources/stats.js +++ b/packages/ipfs-http-server/src/api/resources/stats.js @@ -2,6 +2,7 @@ const { map } = require('streaming-iterables') const { pipe } = require('it-pipe') +// @ts-ignore no types const ndjson = require('iterable-ndjson') const streamResponse = require('../../utils/stream-response') const Joi = require('../../utils/joi') @@ -18,7 +19,7 @@ exports.bw = { stripUnknown: true }, query: Joi.object().keys({ - peer: Joi.peerId(), + peer: Joi.cid(), proto: Joi.string(), poll: Joi.boolean().default(false), interval: Joi.string().default('1s'), @@ -26,6 +27,10 @@ exports.bw = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (request, h) { const { app: { @@ -55,10 +60,10 @@ exports.bw = { timeout }), map(stat => ({ - TotalIn: stat.totalIn, - TotalOut: stat.totalOut, - RateIn: stat.rateIn, - RateOut: stat.rateOut + TotalIn: stat.totalIn.toString(), + TotalOut: stat.totalOut.toString(), + RateIn: stat.rateIn.toString(), + RateOut: stat.rateOut.toString() })), ndjson.stringify )) diff --git a/packages/ipfs-http-server/src/api/resources/swarm.js b/packages/ipfs-http-server/src/api/resources/swarm.js index 067d96cd59..cbfa564cea 100644 --- a/packages/ipfs-http-server/src/api/resources/swarm.js +++ b/packages/ipfs-http-server/src/api/resources/swarm.js @@ -20,6 +20,10 @@ exports.peers = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -45,21 +49,13 @@ exports.peers = { return h.response({ Peers: peers.map((p) => { - const res = { + return { Peer: p.peer.toString(), - Addr: p.addr.toString() + Addr: p.addr.toString(), + Direction: verbose || direction ? p.direction : undefined, + Muxer: verbose ? p.muxer : undefined, + Latency: verbose ? p.latency : undefined } - - if (verbose || direction) { - res.Direction = p.direction - } - - if (verbose) { - res.Muxer = p.muxer - res.Latency = p.latency - } - - return res }) }) } @@ -77,6 +73,10 @@ exports.addrs = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -98,7 +98,7 @@ exports.addrs = { }) return h.response({ - Addrs: peers.reduce((addrs, peer) => { + Addrs: peers.reduce((/** @type {Record} */ addrs, peer) => { addrs[peer.id.toString()] = peer.addrs.map(a => a.toString()) return addrs }, {}) @@ -118,6 +118,10 @@ exports.localAddrs = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -161,6 +165,10 @@ exports.connect = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { @@ -205,6 +213,10 @@ exports.disconnect = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/resources/version.js b/packages/ipfs-http-server/src/api/resources/version.js index 9d504ed006..0b89bf1381 100644 --- a/packages/ipfs-http-server/src/api/resources/version.js +++ b/packages/ipfs-http-server/src/api/resources/version.js @@ -15,6 +15,10 @@ module.exports = { }) } }, + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { const { app: { diff --git a/packages/ipfs-http-server/src/api/routes/debug.js b/packages/ipfs-http-server/src/api/routes/debug.js index fe65eb2c8a..c0d66756c0 100644 --- a/packages/ipfs-http-server/src/api/routes/debug.js +++ b/packages/ipfs-http-server/src/api/routes/debug.js @@ -11,6 +11,10 @@ const gauge = new client.Gauge({ name: 'number_of_peers', help: 'the_number_of_c module.exports = { method: 'POST', path: '/debug/metrics/prometheus', + /** + * @param {import('../../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ async handler (request, h) { if (!process.env.IPFS_MONITORING) { throw Boom.notImplemented('Monitoring is disabled. Enable it by setting environment variable IPFS_MONITORING') diff --git a/packages/ipfs-http-server/src/api/routes/webui.js b/packages/ipfs-http-server/src/api/routes/webui.js index 53767f2d1a..95780fa3c3 100644 --- a/packages/ipfs-http-server/src/api/routes/webui.js +++ b/packages/ipfs-http-server/src/api/routes/webui.js @@ -21,6 +21,10 @@ module.exports = [ { method: 'GET', path: '/webui/{slug?}', // optional slug makes it work with and without slash + /** + * @param {import('../../types').Request} _request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ handler (_request, h) { return h.redirect(`/ipfs/${webuiCid}/`) } diff --git a/packages/ipfs-http-server/src/error-handler.js b/packages/ipfs-http-server/src/error-handler.js index f735dff5dd..5f1de35d4c 100644 --- a/packages/ipfs-http-server/src/error-handler.js +++ b/packages/ipfs-http-server/src/error-handler.js @@ -1,10 +1,19 @@ 'use strict' +const Boom = require('@hapi/boom') + +/** + * @param {import('./types').Server} server + */ module.exports = server => { + /** + * @param {import('./types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + */ server.ext('onPreResponse', (request, h) => { const res = request.response - if (!res.isBoom) { + if (!Boom.isBoom(res)) { return h.continue } @@ -28,7 +37,7 @@ module.exports = server => { const { req } = request.raw const debug = { method: req.method, - url: request.url.path, + url: request.url, headers: req.headers, info: request.info, payload: request.payload, @@ -48,7 +57,7 @@ module.exports = server => { const headers = res.output.headers || {} Object.keys(headers).forEach(header => { - response.header(header, headers[header]) + response.header(header, `${headers[header]}`) }) return response diff --git a/packages/ipfs-http-server/src/index.js b/packages/ipfs-http-server/src/index.js index 409452b0c5..30f1805ff1 100644 --- a/packages/ipfs-http-server/src/index.js +++ b/packages/ipfs-http-server/src/index.js @@ -4,6 +4,7 @@ const Hapi = require('@hapi/hapi') const Pino = require('hapi-pino') const debug = require('debug') const multiaddr = require('multiaddr') +// @ts-ignore no types const toMultiaddr = require('uri-to-multiaddr') const Boom = require('@hapi/boom') const { AbortController } = require('native-abort-controller') @@ -11,6 +12,17 @@ const errorHandler = require('./error-handler') const LOG = 'ipfs:http-api' const LOG_ERROR = 'ipfs:http-api:error' +/** + * @typedef {import('ipfs-core-types').IPFS} IPFS + * @typedef {import('./types').Server} Server + * @typedef {import('ipld')} IPLD + * @typedef {import('libp2p')} libp2p + * @typedef {IPFS & { ipld: IPLD, libp2p: libp2p }} JSIPFS + */ + +/** + * @param {import('@hapi/hapi').ServerInfo} info + */ function hapiInfoToMultiaddr (info) { let hostname = info.host let uri = info.uri @@ -24,11 +36,18 @@ function hapiInfoToMultiaddr (info) { return toMultiaddr(uri) } +/** + * @param {string | string[]} serverAddrs + * @param {(host: string, port: string, ipfs: JSIPFS, cors: Record) => Promise} createServer + * @param {JSIPFS} ipfs + * @param {Record} cors + */ async function serverCreator (serverAddrs, createServer, ipfs, cors) { serverAddrs = serverAddrs || [] // just in case the address is just string serverAddrs = Array.isArray(serverAddrs) ? serverAddrs : [serverAddrs] + /** @type {Server[]} */ const servers = [] for (const address of serverAddrs) { const addrParts = address.split('/') @@ -41,11 +60,16 @@ async function serverCreator (serverAddrs, createServer, ipfs, cors) { } class HttpApi { - constructor (ipfs, options = {}) { + /** + * @param {JSIPFS} ipfs + */ + constructor (ipfs) { this._ipfs = ipfs this._log = Object.assign(debug(LOG), { error: debug(LOG_ERROR) }) + /** @type {Server[]} */ + this._apiServers = [] } /** @@ -59,20 +83,24 @@ class HttpApi { const ipfs = this._ipfs const config = await ipfs.config.getAll() - config.Addresses = config.Addresses || {} - config.API = config.API || {} - config.API.HTTPHeaders = config.API.HTTPHeaders || {} + const headers = (config.API && config.API.HTTPHeaders) || {} + const apiAddrs = (config.Addresses && config.Addresses.API) || [] - const apiAddrs = config.Addresses.API this._apiServers = await serverCreator(apiAddrs, this._createApiServer, ipfs, { - origin: config.API.HTTPHeaders['Access-Control-Allow-Origin'] || [], - credentials: Boolean(config.API.HTTPHeaders['Access-Control-Allow-Credentials']) + origin: headers['Access-Control-Allow-Origin'] || [], + credentials: Boolean(headers['Access-Control-Allow-Credentials']) }) this._log('started') return this } + /** + * @param {string} host + * @param {string} port + * @param {JSIPFS} ipfs + * @param {Record} cors + */ async _createApiServer (host, port, ipfs, cors) { cors = { ...cors, @@ -80,15 +108,13 @@ class HttpApi { additionalExposedHeaders: ['X-Stream-Output', 'X-Chunked-Output', 'X-Content-Length'] } - if (!cors.origin || !cors.origin.length) { - cors = false - } + const enableCors = Boolean(cors.origin?.length) const server = Hapi.server({ host, port, routes: { - cors, + cors: enableCors ? cors : false, response: { emptyStatusCode: 200 } @@ -130,7 +156,7 @@ class HttpApi { server.ext('onPreResponse', (request, h) => { const { response } = request - if (response.isBoom && response.output && response.output.statusCode === 405) { + if (Boom.isBoom(response) && response.output && response.output.statusCode === 405) { response.output.headers.Allow = 'OPTIONS, POST' } @@ -207,12 +233,14 @@ class HttpApi { async stop () { this._log('stopping') + /** + * @param {Server[]} servers + */ const stopServers = servers => Promise.all((servers || []).map(s => s.stop())) await Promise.all([ stopServers(this._apiServers) ]) this._log('stopped') - return this } } diff --git a/packages/ipfs-http-server/src/types.d.ts b/packages/ipfs-http-server/src/types.d.ts new file mode 100644 index 0000000000..8f09c2394f --- /dev/null +++ b/packages/ipfs-http-server/src/types.d.ts @@ -0,0 +1,42 @@ +import { IPFS } from 'ipfs-core-types' +import { Request, Server } from '@hapi/hapi' +import Multiaddr from 'multiaddrs' +import { Mtime } from 'ipfs-unixfs' +import IPLD from 'ipld' +import libp2p from 'libp2p' + +declare module '@hapi/hapi' { + interface ServerApplicationState { + ipfs: IPFS & { ipld: IPLD, libp2p: libp2p } + } + interface RequestApplicationState { + signal: AbortSignal + } + interface ServerInfo { + ma: Multiaddr + } +} + +export { Request, Server } + +interface MultipartUpload { + name: string + mtime?: Mtime + mode?: number +} + +export interface MultipartFile extends MultipartUpload { + type: 'file' + content: AsyncIterable +} + +export interface MultipartDirectory extends MultipartUpload { + type: 'directory' +} + +export interface MultipartSymlink extends MultipartUpload { + type: 'symlink' + target: string +} + +export type MultipartEntry = MultipartFile | MultipartDirectory | MultipartSymlink diff --git a/packages/ipfs-http-server/src/utils/joi.js b/packages/ipfs-http-server/src/utils/joi.js index 346f1615a7..2db2dcf281 100644 --- a/packages/ipfs-http-server/src/utils/joi.js +++ b/packages/ipfs-http-server/src/utils/joi.js @@ -7,6 +7,9 @@ const multiaddr = require('multiaddr') const multibase = require('multibase') const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') +/** + * @param {*} value + */ const toIpfsPath = (value) => { if (!value) { throw new Error('Must have value') @@ -33,11 +36,18 @@ const toIpfsPath = (value) => { return `${startedWithIpfs ? '/ipfs/' : ''}${parts.join('/')}` } +/** + * @param {*} value + */ const toCID = (value) => { return new CID(value.toString().replace('/ipfs/', '')) } -const reqiureIfRequired = (value, helpers) => { +/** + * @param {*} value + * @param {import('joi').CustomHelpers} helpers + */ +const requireIfRequired = (value, helpers) => { if (helpers.schema.$_getFlag('presence') === 'required' && !value) { return { value, errors: helpers.error('required') } } @@ -51,7 +61,7 @@ module.exports = Joi return { type: 'cid', base: joi.any(), - validate: reqiureIfRequired, + validate: requireIfRequired, coerce (value, _helpers) { if (!value) { return @@ -65,7 +75,7 @@ module.exports = Joi return { type: 'ipfsPath', base: joi.string(), - validate: reqiureIfRequired, + validate: requireIfRequired, coerce (value, _helpers) { if (!value) { return @@ -75,25 +85,11 @@ module.exports = Joi } } }, - (joi) => { - return { - type: 'peerId', - base: joi.string(), - validate: reqiureIfRequired, - coerce (value, _helpers) { - if (!value) { - return - } - - return { value: new CID(value).toString() } - } - } - }, (joi) => { return { type: 'multiaddr', base: joi.string(), - validate: reqiureIfRequired, + validate: requireIfRequired, coerce (value, _helpers) { if (!value) { return @@ -107,7 +103,7 @@ module.exports = Joi return { type: 'timeout', base: joi.number(), - validate: reqiureIfRequired, + validate: requireIfRequired, coerce (value, _helpers) { if (!value) { return @@ -121,7 +117,7 @@ module.exports = Joi return { type: 'cidAndPath', base: joi.any(), - validate: reqiureIfRequired, + validate: requireIfRequired, coerce (value, _helpers) { if (!value) { return @@ -135,12 +131,13 @@ module.exports = Joi return { type: 'cidBase', base: joi.string(), - validate: reqiureIfRequired, + validate: requireIfRequired, coerce (value, _helpers) { if (!value) { return } + // @ts-ignore value is not a BaseName if (!multibase.names[value]) { throw new Error('Invalid base name') } @@ -153,7 +150,7 @@ module.exports = Joi return { type: 'json', base: joi.any(), - validate: reqiureIfRequired, + validate: requireIfRequired, coerce (value, _helpers) { if (!value) { return diff --git a/packages/ipfs-http-server/src/utils/multipart-request-parser.js b/packages/ipfs-http-server/src/utils/multipart-request-parser.js index baa412a683..49f4b41578 100644 --- a/packages/ipfs-http-server/src/utils/multipart-request-parser.js +++ b/packages/ipfs-http-server/src/utils/multipart-request-parser.js @@ -1,5 +1,6 @@ 'use strict' +// @ts-ignore no types const Content = require('@hapi/content') const multipart = require('it-multipart') const uint8ArrayConcat = require('uint8arrays/concat') @@ -11,8 +12,20 @@ const multipartFormdataType = 'multipart/form-data' const applicationDirectory = 'application/x-directory' const applicationSymlink = 'application/symlink' +/** + * @typedef {import('http').IncomingMessage} IncomingMessage + * @typedef {import('it-multipart').Part} Part + * @typedef {import('../types').MultipartEntry} MultipartEntry + */ + +/** + * @param {string} mediatype + */ const isDirectory = (mediatype) => mediatype === multipartFormdataType || mediatype === applicationDirectory +/** + * @param {string} disposition + */ const parseDisposition = (disposition) => { const details = {} details.type = disposition.split(';')[0] @@ -30,6 +43,9 @@ const parseDisposition = (disposition) => { return details } +/** + * @param {AsyncIterable} stream + */ const collect = async (stream) => { const buffers = [] let size = 0 @@ -42,7 +58,18 @@ const collect = async (stream) => { return uint8ArrayConcat(buffers, size) } -async function * parseEntry (stream, options) { +/** + * @typedef {Object} MultipartUpload + * @property {'file' | 'directory' | 'symlink'} type + * @property {string} name + * @property {AsyncIterable} body + * @property {number} [mode] + * @property {import('ipfs-unixfs').Mtime} [mtime] + * + * @param {AsyncIterable} stream + * @returns {AsyncGenerator} + */ +async function * parseEntry (stream) { for await (const part of stream) { if (!part.headers['content-type']) { throw new Error('No content-type in multipart part') @@ -52,10 +79,7 @@ async function * parseEntry (stream, options) { if (type.boundary) { // recursively parse nested multiparts - yield * parser(part.body, { - ...options, - boundary: type.boundary - }) + yield * parseEntry(multipart(part.body, type.boundary)) continue } @@ -64,6 +88,7 @@ async function * parseEntry (stream, options) { throw new Error('No content disposition in multipart part') } + /** @type {MultipartUpload} */ const entry = {} if (isDirectory(type.mime)) { @@ -75,7 +100,7 @@ async function * parseEntry (stream, options) { } const disposition = parseDisposition(part.headers['content-disposition']) - const query = qs.parse(disposition.name.split('?').pop()) + const query = qs.parse(`${disposition.name}`.split('?').pop() || '') if (query.mode) { entry.mode = parseInt(readQueryParam(query.mode), 8) @@ -104,9 +129,15 @@ async function * parseEntry (stream, options) { */ const readQueryParam = value => Array.isArray(value) ? value[0] : value -async function * parser (stream, options) { - for await (const entry of parseEntry(multipart(stream, options.boundary), options)) { +/** + * @param {AsyncIterable} stream + * @param {string} boundary + * @returns {AsyncGenerator} + */ +async function * parser (stream, boundary) { + for await (const entry of parseEntry(multipart(stream, boundary))) { if (entry.type === 'directory') { + /** @type {import('../types').MultipartDirectory} */ yield { type: 'directory', name: entry.name, @@ -118,6 +149,7 @@ async function * parser (stream, options) { } if (entry.type === 'symlink') { + /** @type {import('../types').MultipartSymlink} */ yield { type: 'symlink', name: entry.name, @@ -128,6 +160,7 @@ async function * parser (stream, options) { } if (entry.type === 'file') { + /** @type {import('../types').MultipartFile} */ yield { type: 'file', name: entry.name, @@ -142,12 +175,10 @@ async function * parser (stream, options) { /** * Request Parser * - * @param {Object} req - Request - * @param {Object} options - Options passed to stream constructors - * @returns {Object} an async iterable + * @param {IncomingMessage} req */ -module.exports = (req, options = {}) => { - options.boundary = Content.type(req.headers['content-type']).boundary +module.exports = (req) => { + const boundary = Content.type(req.headers['content-type']).boundary - return parser(req.payload || req, options) + return parser(req, boundary) } diff --git a/packages/ipfs-http-server/src/utils/stream-response.js b/packages/ipfs-http-server/src/utils/stream-response.js index 9a76168958..18b392c885 100644 --- a/packages/ipfs-http-server/src/utils/stream-response.js +++ b/packages/ipfs-http-server/src/utils/stream-response.js @@ -3,10 +3,18 @@ const { PassThrough } = require('stream') const { pipe } = require('it-pipe') const log = require('debug')('ipfs:http-api:utils:stream-response') +// @ts-ignore no types const toIterable = require('stream-to-it') const errorTrailer = 'X-Stream-Error' +/** + * + * @param {import('../types').Request} request + * @param {import('@hapi/hapi').ResponseToolkit} h + * @param {() => AsyncIterable} getSource + * @param {{ objectMode?: boolean, onError?: (error: Error) => void }} [options] + */ async function streamResponse (request, h, getSource, options = {}) { options.objectMode = options.objectMode !== false diff --git a/packages/ipfs-http-server/test/inject/bitswap.js b/packages/ipfs-http-server/test/inject/bitswap.js index 98caf1787f..2fe534658d 100644 --- a/packages/ipfs-http-server/test/inject/bitswap.js +++ b/packages/ipfs-http-server/test/inject/bitswap.js @@ -96,7 +96,7 @@ describe('/bitswap', () => { it('/wantlist?peer=QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D', async () => { const peerId = 'QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D' - ipfs.bitswap.wantlistForPeer.withArgs(peerId, defaultOptions).returns([ + ipfs.bitswap.wantlistForPeer.withArgs(new CID(peerId), defaultOptions).returns([ cid ]) @@ -112,7 +112,7 @@ describe('/bitswap', () => { it('/wantlist?peer=QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D&timeout=1s', async () => { const peerId = 'QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D' - ipfs.bitswap.wantlistForPeer.withArgs(peerId, { + ipfs.bitswap.wantlistForPeer.withArgs(new CID(peerId), { ...defaultOptions, timeout: 1000 }).returns([ diff --git a/packages/ipfs-http-server/test/inject/dht.js b/packages/ipfs-http-server/test/inject/dht.js index bac0671ceb..93f7c22d06 100644 --- a/packages/ipfs-http-server/test/inject/dht.js +++ b/packages/ipfs-http-server/test/inject/dht.js @@ -50,7 +50,7 @@ describe('/dht', () => { }) it('returns 404 if peerId is provided as there is no peers in the routing table', async () => { - ipfs.dht.findPeer.withArgs(peerId, defaultOptions).throws(errCode(new Error('Nope'), 'ERR_LOOKUP_FAILED')) + ipfs.dht.findPeer.withArgs(new CID(peerId), defaultOptions).throws(errCode(new Error('Nope'), 'ERR_LOOKUP_FAILED')) const res = await http({ method: 'POST', @@ -59,11 +59,11 @@ describe('/dht', () => { expect(res).to.have.property('statusCode', 404) expect(ipfs.dht.findPeer.called).to.be.true() - expect(ipfs.dht.findPeer.getCall(0).args[0]).to.equal(peerId) + expect(ipfs.dht.findPeer.getCall(0).args[0]).to.deep.equal(new CID(peerId)) }) it('accepts a timeout', async () => { - ipfs.dht.findPeer.withArgs(peerId, { + ipfs.dht.findPeer.withArgs(new CID(peerId), { ...defaultOptions, timeout: 1000 }).returns({ @@ -392,7 +392,7 @@ describe('/dht', () => { }) it('returns 200 if key is provided', async function () { - ipfs.dht.query.withArgs(peerId, defaultOptions).returns([{ + ipfs.dht.query.withArgs(new CID(peerId), defaultOptions).returns([{ id: 'id' }]) @@ -406,7 +406,7 @@ describe('/dht', () => { }) it('accepts a timeout', async function () { - ipfs.dht.query.withArgs(peerId, { + ipfs.dht.query.withArgs(new CID(peerId), { ...defaultOptions, timeout: 1000 }).returns([{ diff --git a/packages/ipfs-http-server/test/inject/dns.js b/packages/ipfs-http-server/test/inject/dns.js index 9965e363ba..8a48130b5f 100644 --- a/packages/ipfs-http-server/test/inject/dns.js +++ b/packages/ipfs-http-server/test/inject/dns.js @@ -9,7 +9,6 @@ const { AbortSignal } = require('native-abort-controller') const defaultOptions = { recursive: false, - format: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -69,21 +68,6 @@ describe('/dns', () => { expect(res).to.have.nested.property('result.Path', 'path') }) - it('resolves a domain with a format', async () => { - const domain = 'ipfs.io' - ipfs.dns.withArgs(domain, { - ...defaultOptions, - format: 'derp' - }).returns('path') - - const res = await http({ - method: 'POST', - url: `/api/v0/dns?arg=${domain}&format=derp` - }, { ipfs }) - - expect(res).to.have.nested.property('result.Path', 'path') - }) - it('accepts a timeout', async () => { const domain = 'ipfs.io' ipfs.dns.withArgs(domain, { diff --git a/packages/ipfs-http-server/test/inject/files.js b/packages/ipfs-http-server/test/inject/files.js index 9b73c2ed7f..f2ba06c9f3 100644 --- a/packages/ipfs-http-server/test/inject/files.js +++ b/packages/ipfs-http-server/test/inject/files.js @@ -315,9 +315,6 @@ describe('/files', () => { describe('/get', () => { const defaultOptions = { - archive: false, - compress: false, - compressionLevel: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -379,6 +376,8 @@ describe('/files', () => { Depth: 1, Hash: cid.toString(), Mode: '0420', + Mtime: undefined, + MtimeNsecs: undefined, Name: 'link', Size: 10, Type: 2 @@ -405,6 +404,9 @@ describe('/files', () => { Hash: `${cid}/derp`, Depth: 1, Mode: '0420', + Mtime: undefined, + MtimeNsecs: undefined, + Name: undefined, Size: 10, Type: 2, Links: [] @@ -435,6 +437,9 @@ describe('/files', () => { Links: [{ Depth: 1, Hash: cid.toString(), + Mode: undefined, + Mtime: undefined, + MtimeNsecs: undefined, Name: 'link', Size: 10, Type: 2 @@ -470,6 +475,8 @@ describe('/files', () => { Depth: 1, Hash: cid.toString(), Mode: '0420', + Mtime: undefined, + MtimeNsecs: undefined, Name: 'link', Size: 10, Type: 2 diff --git a/packages/ipfs-http-server/test/inject/mfs/cp.js b/packages/ipfs-http-server/test/inject/mfs/cp.js index f704a1434d..5f37ae57e7 100644 --- a/packages/ipfs-http-server/test/inject/mfs/cp.js +++ b/packages/ipfs-http-server/test/inject/mfs/cp.js @@ -41,7 +41,7 @@ describe('/files/cp', () => { }, { ipfs }) expect(ipfs.files.cp.callCount).to.equal(1) - expect(ipfs.files.cp.calledWith(source, dest, defaultOptions)).to.be.true() + expect(ipfs.files.cp.calledWith([source], dest, defaultOptions)).to.be.true() }) it('should copy files and create intermediate directories', async () => { @@ -51,7 +51,7 @@ describe('/files/cp', () => { }, { ipfs }) expect(ipfs.files.cp.callCount).to.equal(1) - expect(ipfs.files.cp.calledWith(source, dest, { + expect(ipfs.files.cp.calledWith([source], dest, { ...defaultOptions, parents: true })).to.be.true() @@ -64,7 +64,7 @@ describe('/files/cp', () => { }, { ipfs }) expect(ipfs.files.cp.callCount).to.equal(1) - expect(ipfs.files.cp.calledWith(source, dest, { + expect(ipfs.files.cp.calledWith([source], dest, { ...defaultOptions, cidVersion: 1 })).to.be.true() @@ -77,7 +77,7 @@ describe('/files/cp', () => { }, { ipfs }) expect(ipfs.files.cp.callCount).to.equal(1) - expect(ipfs.files.cp.calledWith(source, dest, { + expect(ipfs.files.cp.calledWith([source], dest, { ...defaultOptions, hashAlg: 'sha3-256' })).to.be.true() @@ -90,7 +90,7 @@ describe('/files/cp', () => { }, { ipfs }) expect(ipfs.files.cp.callCount).to.equal(1) - expect(ipfs.files.cp.calledWith(source, dest, { + expect(ipfs.files.cp.calledWith([source], dest, { ...defaultOptions, shardSplitThreshold: 10 })).to.be.true() @@ -103,7 +103,7 @@ describe('/files/cp', () => { }, { ipfs }) expect(ipfs.files.cp.callCount).to.equal(1) - expect(ipfs.files.cp.calledWith(source, dest, { + expect(ipfs.files.cp.calledWith([source], dest, { ...defaultOptions, timeout: 1000 })).to.be.true() diff --git a/packages/ipfs-http-server/test/inject/mfs/rm.js b/packages/ipfs-http-server/test/inject/mfs/rm.js index 9819a1287f..6617004ccf 100644 --- a/packages/ipfs-http-server/test/inject/mfs/rm.js +++ b/packages/ipfs-http-server/test/inject/mfs/rm.js @@ -37,7 +37,7 @@ describe('/files/rm', () => { }, { ipfs }) expect(ipfs.files.rm.callCount).to.equal(1) - expect(ipfs.files.rm.calledWith(path, defaultOptions)).to.be.true() + expect(ipfs.files.rm.calledWith([path], defaultOptions)).to.be.true() }) it('should remove a path recursively', async () => { @@ -47,7 +47,7 @@ describe('/files/rm', () => { }, { ipfs }) expect(ipfs.files.rm.callCount).to.equal(1) - expect(ipfs.files.rm.calledWith(path, { + expect(ipfs.files.rm.calledWith([path], { ...defaultOptions, recursive: true })).to.be.true() @@ -60,7 +60,7 @@ describe('/files/rm', () => { }, { ipfs }) expect(ipfs.files.rm.callCount).to.equal(1) - expect(ipfs.files.rm.calledWith(path, { + expect(ipfs.files.rm.calledWith([path], { ...defaultOptions, shardSplitThreshold: 10 })).to.be.true() @@ -73,7 +73,7 @@ describe('/files/rm', () => { }, { ipfs }) expect(ipfs.files.rm.callCount).to.equal(1) - expect(ipfs.files.rm.calledWith(path, { + expect(ipfs.files.rm.calledWith([path], { ...defaultOptions, timeout: 1000 })).to.be.true() diff --git a/packages/ipfs-http-server/test/inject/mfs/write.js b/packages/ipfs-http-server/test/inject/mfs/write.js index 2033713ab5..bc654ad468 100644 --- a/packages/ipfs-http-server/test/inject/mfs/write.js +++ b/packages/ipfs-http-server/test/inject/mfs/write.js @@ -18,7 +18,6 @@ const defaultOptions = { cidVersion: 0, hashAlg: 'sha2-256', parents: false, - progress: undefined, strategy: 'trickle', flush: true, shardSplitThreshold: 1000, diff --git a/packages/ipfs-http-server/test/inject/object.js b/packages/ipfs-http-server/test/inject/object.js index b5911322ee..be5fb4b913 100644 --- a/packages/ipfs-http-server/test/inject/object.js +++ b/packages/ipfs-http-server/test/inject/object.js @@ -11,7 +11,7 @@ const testHttpMethod = require('../utils/test-http-method') const http = require('../utils/http') const sinon = require('sinon') const CID = require('cids') -const UnixFS = require('ipfs-unixfs') +const { UnixFS } = require('ipfs-unixfs') const { AbortSignal } = require('native-abort-controller') const { DAGNode, @@ -166,7 +166,6 @@ describe('/object', () => { describe('/get', () => { const defaultOptions = { - enc: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -516,7 +515,6 @@ describe('/object', () => { describe('/data', () => { const defaultOptions = { - enc: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -555,7 +553,7 @@ describe('/object', () => { }, { ipfs }) expect(res).to.have.property('statusCode', 200) - expect(res).to.have.property('result', emptyDirectoryNode.Data) + expect(res).to.have.deep.property('rawPayload', emptyDirectoryNode.Data) }) it('accepts a timeout', async () => { @@ -570,13 +568,12 @@ describe('/object', () => { }, { ipfs }) expect(res).to.have.property('statusCode', 200) - expect(res).to.have.property('result', emptyDirectoryNode.Data) + expect(res).to.have.deep.property('rawPayload', emptyDirectoryNode.Data) }) }) describe('/links', () => { const defaultOptions = { - enc: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -677,7 +674,6 @@ describe('/object', () => { describe('/patch/append-data', () => { const defaultOptions = { - enc: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -825,7 +821,6 @@ describe('/object', () => { describe('/patch/set-data', () => { const defaultOptions = { - enc: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -969,7 +964,6 @@ describe('/object', () => { describe('/patch/add-link', () => { const defaultOptions = { - enc: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -1095,7 +1089,6 @@ describe('/object', () => { describe('/patch/rm-link', () => { const defaultOptions = { - enc: undefined, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -1149,9 +1142,8 @@ describe('/object', () => { it('returns value', async () => { const name = 'name' - ipfs.object.patch.rmLink.withArgs(cid, { - ...defaultOptions, - name + ipfs.object.patch.rmLink.withArgs(cid, name, { + ...defaultOptions }).returns(cid2) ipfs.object.get.withArgs(cid2).returns(emptyDirectoryNode) @@ -1190,9 +1182,8 @@ describe('/object', () => { it('accepts a timeout', async () => { const name = 'name' - ipfs.object.patch.rmLink.withArgs(cid, { + ipfs.object.patch.rmLink.withArgs(cid, name, { ...defaultOptions, - name, timeout: 1000 }).returns(cid2) ipfs.object.get.withArgs(cid2).returns(emptyDirectoryNode) diff --git a/packages/ipfs-http-server/test/inject/ping.js b/packages/ipfs-http-server/test/inject/ping.js index ef1f0c07a7..e77a7c679d 100644 --- a/packages/ipfs-http-server/test/inject/ping.js +++ b/packages/ipfs-http-server/test/inject/ping.js @@ -8,6 +8,7 @@ const http = require('../utils/http') const sinon = require('sinon') const allNdjson = require('../utils/all-ndjson') const { AbortSignal } = require('native-abort-controller') +const CID = require('cids') const defaultOptions = { count: 10, @@ -48,7 +49,7 @@ describe('/ping', function () { }) it('returns 500 for incorrect Peer Id', async () => { - ipfs.ping.withArgs(peerId).throws(new Error('derp')) + ipfs.ping.withArgs(new CID(peerId)).throws(new Error('derp')) const res = await http({ method: 'POST', @@ -59,7 +60,7 @@ describe('/ping', function () { }) it('pings with a count', async () => { - ipfs.ping.withArgs(peerId, { + ipfs.ping.withArgs(new CID(peerId), { ...defaultOptions, count: 5 }).returns([]) @@ -73,7 +74,7 @@ describe('/ping', function () { }) it('pings with a count as n', async () => { - ipfs.ping.withArgs(peerId, { + ipfs.ping.withArgs(new CID(peerId), { ...defaultOptions, count: 5 }).returns([]) @@ -87,7 +88,7 @@ describe('/ping', function () { }) it('pings a remote peer', async () => { - ipfs.ping.withArgs(peerId, defaultOptions).returns([{ + ipfs.ping.withArgs(new CID(peerId), defaultOptions).returns([{ success: true, time: 1, text: 'hello' @@ -115,7 +116,7 @@ describe('/ping', function () { }) it('accepts a timeout', async () => { - ipfs.ping.withArgs(peerId, { + ipfs.ping.withArgs(new CID(peerId), { ...defaultOptions, timeout: 1000 }).returns([]) diff --git a/packages/ipfs-http-server/test/inject/stats.js b/packages/ipfs-http-server/test/inject/stats.js index 0f1e5b5623..f744f8bc54 100644 --- a/packages/ipfs-http-server/test/inject/stats.js +++ b/packages/ipfs-http-server/test/inject/stats.js @@ -7,6 +7,7 @@ const http = require('../utils/http') const sinon = require('sinon') const allNdjson = require('../utils/all-ndjson') const { AbortSignal } = require('native-abort-controller') +const CID = require('cids') describe('/stats', () => { let ipfs @@ -70,7 +71,7 @@ describe('/stats', () => { ipfs.stats.bw.withArgs({ ...defaultOptions, - peer + peer: new CID(peer) }).returns([{ totalIn: 'totalIn1', totalOut: 'totalOut1', diff --git a/packages/ipfs-http-server/test/inject/swarm.js b/packages/ipfs-http-server/test/inject/swarm.js index c5bf8a6575..e3ff31978e 100644 --- a/packages/ipfs-http-server/test/inject/swarm.js +++ b/packages/ipfs-http-server/test/inject/swarm.js @@ -51,7 +51,10 @@ describe('/swarm', () => { expect(res).to.have.property('statusCode', 200) expect(res).to.have.nested.property('result.Peers').with.lengthOf(1).that.deep.includes({ Peer: 'peerId', - Addr: 'addr' + Addr: 'addr', + Direction: undefined, + Muxer: undefined, + Latency: undefined }) }) @@ -127,7 +130,9 @@ describe('/swarm', () => { expect(res).to.have.nested.property('result.Peers').with.lengthOf(1).that.deep.includes({ Peer: 'peerId', Addr: 'addr', - Direction: 'direction' + Direction: 'direction', + Muxer: undefined, + Latency: undefined }) }) @@ -151,7 +156,10 @@ describe('/swarm', () => { expect(res).to.have.property('statusCode', 200) expect(res).to.have.nested.property('result.Peers').with.lengthOf(1).that.deep.includes({ Peer: 'peerId', - Addr: 'addr' + Addr: 'addr', + Direction: undefined, + Muxer: undefined, + Latency: undefined }) }) }) diff --git a/packages/ipfs-http-server/tsconfig.json b/packages/ipfs-http-server/tsconfig.json index 2e66dcb8a7..089355b43e 100644 --- a/packages/ipfs-http-server/tsconfig.json +++ b/packages/ipfs-http-server/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, diff --git a/packages/ipfs-message-port-client/.aegir.js b/packages/ipfs-message-port-client/.aegir.js index e5fa08175e..ab363f4a28 100644 --- a/packages/ipfs-message-port-client/.aegir.js +++ b/packages/ipfs-message-port-client/.aegir.js @@ -21,7 +21,7 @@ const buildConfig = { /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '23kB', + bundlesizeMax: '47kB', config: buildConfig }, test: { diff --git a/packages/ipfs-message-port-client/package.json b/packages/ipfs-message-port-client/package.json index 906a189b74..f272f56634 100644 --- a/packages/ipfs-message-port-client/package.json +++ b/packages/ipfs-message-port-client/package.json @@ -13,24 +13,17 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", - "typesVersions": { - "*": { - "*": [ - "dist/*", - "dist/*/index" - ] - } - }, + "types": "dist/src/index.d.ts", "browser": {}, "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { - "prepare": "npm run build", "build": "aegir build", "test": "echo 'Only interface tests live here'", "test:interface:message-port-client": "aegir test -t browser --bail -f ./test/interface-message-port-client.js", @@ -41,13 +34,14 @@ }, "dependencies": { "browser-readablestream-to-it": "^1.0.1", + "cids": "^1.1.6", "ipfs-core-types": "^0.3.1", - "ipfs-message-port-protocol": "^0.6.1" + "ipfs-message-port-protocol": "^0.6.1", + "ipfs-unixfs": "^4.0.1" }, "devDependencies": { - "aegir": "^31.0.0", + "aegir": "^32.1.0", "interface-ipfs-core": "^0.144.2", - "ipfs": "^0.54.4", "ipfs-core": "^0.5.4", "ipfs-message-port-server": "^0.6.3", "rimraf": "^3.0.2" diff --git a/packages/ipfs-message-port-client/src/block.js b/packages/ipfs-message-port-client/src/block.js index fae2c7f4a5..4f982860da 100644 --- a/packages/ipfs-message-port-client/src/block.js +++ b/packages/ipfs-message-port-client/src/block.js @@ -7,14 +7,13 @@ const { encodeBlock, decodeBlock } = require('ipfs-message-port-protocol/src/block') +const CID = require('cids') /** - * @typedef {import('cids')} CID - * @typedef {import('ipfs-message-port-server/src/block').Block} Block - * @typedef {import('ipfs-message-port-server/src/block').EncodedBlock} EncodedBlock - * @typedef {import('ipfs-message-port-server/src/block').Rm} EncodedRmEntry - * @typedef {import('ipfs-message-port-server/src/block').BlockService} BlockService * @typedef {import('./client').MessageTransport} MessageTransport + * @typedef {import('ipfs-message-port-server').BlockService} BlockService + * @typedef {import('./interface').MessagePortClientOptions} MessagePortClientOptions + * @typedef {import('ipfs-core-types/src/block').API} BlockAPI */ /** @@ -28,123 +27,67 @@ class BlockClient extends Client { constructor (transport) { super('block', ['put', 'get', 'rm', 'stat'], transport) } +} - /** - * Get a raw IPFS block. - * - * @param {CID} cid - A CID that corresponds to the desired block - * @param {Object} [options] - * @param {number} [options.timeout] - A timeout in ms - * @param {AbortSignal} [options.signal] - Can be used to cancel any long - * running requests started as a result of this call - * @param {Transferable[]} [options.transfer] - References to transfer to the - * worker if passed. - * @returns {Promise} - */ - async get (cid, options = {}) { - const { transfer } = options - const { block } = await this.remote.get({ - ...options, - cid: encodeCID(cid, transfer) - }) - return decodeBlock(block) - } +/** + * @type {BlockAPI["get"]} + */ +BlockClient.prototype.get = async function get (cid, options = {}) { + const { transfer } = options + const { block } = await this.remote.get({ + ...options, + cid: encodeCID(new CID(cid), transfer) + }) + return decodeBlock(block) +} - /** - * Stores input as an IPFS block. - * - * @param {Block|Uint8Array} block - A Block or Uint8Array of block data - * @param {Object} [options] - * @param {CID} [options.cid] - A CID to store the block under (if block is - * `Uint8Array`) - * @param {string} [options.format='dag-pb'] - The codec to use to create the - * CID (if block is `Uint8Array`) - * @param {string} [options.mhtype='sha2-256'] - The hashing algorithm to use - * to create the CID (if block is `Uint8Array`) - * @param {0|1} [options.version=0] - The version to use to create the CID - * (if block is `Uint8Array`) - * @param {number} [options.mhlen] - * @param {boolean} [options.pin=false] - If true, pin added blocks recursively - * @param {number} [options.timeout] - A timeout in ms - * @param {AbortSignal} [options.signal] - Can be used to cancel any long - * running requests started as a result of this call - * @param {Transferable[]} [options.transfer] - References to transfer to the - * worker if passed. - * @returns {Promise} - */ - async put (block, options = {}) { - const { transfer } = options - // @ts-ignore - ipfs-unixfs-importer passes `progress` which causing errors - // because functions can't be transferred. - delete options.progress - const result = await this.remote.put({ - ...options, - cid: options.cid == null ? undefined : encodeCID(options.cid, transfer), - block: block instanceof Uint8Array ? block : encodeBlock(block, transfer) - }) - return decodeBlock(result.block) - } +/** + * @type {BlockAPI["put"]} + */ +BlockClient.prototype.put = async function put (block, options = {}) { + const { transfer } = options + // @ts-ignore - ipfs-unixfs-importer passes `progress` which causing errors + // because functions can't be transferred. + delete options.progress + const result = await this.remote.put({ + ...options, + // @ts-ignore PutOptions requires CID, we send EncodedCID + cid: options.cid == null ? undefined : encodeCID(new CID(options.cid), transfer), + block: block instanceof Uint8Array ? block : encodeBlock(block, transfer) + }) + return decodeBlock(result.block) +} - /** - * Remove one or more IPFS block(s). - * - * @param {CID|CID[]} cids - Block(s) to be removed - * @param {Object} [options] - * @param {boolean} [options.force=false] - Ignores nonexistent blocks - * @param {boolean} [options.quiet=false] - Write minimal output - * @param {number} [options.timeout] - A timeout in ms - * @param {AbortSignal} [options.signal] - Can be used to cancel any long - * running requests started as a result of this call - * @param {Transferable[]} [options.transfer] - References to transfer to the - * worker if passed. - * @returns {AsyncIterable} - * - * @typedef {Object} RmEntry - * @property {CID} cid - * @property {Error|void} [error] - */ - async * rm (cids, options = {}) { - const { transfer } = options - const entries = await this.remote.rm({ - ...options, - cids: Array.isArray(cids) - ? cids.map(cid => encodeCID(cid, transfer)) - : [encodeCID(cids, transfer)] - }) +/** + * @type {BlockAPI["rm"]} + */ +BlockClient.prototype.rm = async function * rm (cids, options = {}) { + const { transfer } = options + const entries = await this.remote.rm({ + ...options, + cids: Array.isArray(cids) + ? cids.map(cid => encodeCID(new CID(cid), transfer)) + : [encodeCID(new CID(cids), transfer)] + }) - yield * entries.map(decodeRmEntry) - } + yield * entries.map(decodeRmEntry) +} - /** - * Returns information about a raw IPFS block. - * - * @param {CID} cid - Block to get information about. - * @param {Object} [options] - * @param {number} [options.timeout] - A timeout in ms - * @param {AbortSignal} [options.signal] - Can be used to cancel any long - * running requests started as a result of this call - * @param {Transferable[]} [options.transfer] - References to transfer to the - * worker if passed. - * @returns {Promise} - * - * @typedef {Object} Stat - * @property {CID} cid - * @property {number} size - */ - async stat (cid, options = {}) { - const { transfer } = options - const result = await this.remote.stat({ - ...options, - cid: encodeCID(cid, transfer) - }) +/** + * @type {BlockAPI["stat"]} + */ +BlockClient.prototype.stat = async function stat (cid, options = {}) { + const { transfer } = options + const result = await this.remote.stat({ + ...options, + cid: encodeCID(new CID(cid), transfer) + }) - return { ...result, cid: decodeCID(result.cid) } - } + return { ...result, cid: decodeCID(result.cid) } } /** - * @param {EncodedRmEntry} entry - * @returns {RmEntry} + * @param {import('ipfs-message-port-protocol/src/block').EncodedRmResult} entry */ const decodeRmEntry = entry => { const cid = decodeCID(entry.cid) diff --git a/packages/ipfs-message-port-client/src/core.js b/packages/ipfs-message-port-client/src/core.js index 352c24d412..78793d918f 100644 --- a/packages/ipfs-message-port-client/src/core.js +++ b/packages/ipfs-message-port-client/src/core.js @@ -3,55 +3,47 @@ /* eslint-env browser */ const Client = require('./client') -const { encodeCID, decodeCID, CID } = require('ipfs-message-port-protocol/src/cid') +const CID = require('cids') +const { encodeCID, decodeCID } = require('ipfs-message-port-protocol/src/cid') const { decodeIterable, encodeIterable, encodeCallback } = require('ipfs-message-port-protocol/src/core') /** @type {(stream:ReadableStream) => AsyncIterable} */ -// @ts-ignore - browser-stream-to-it has not types +// @ts-ignore - browser-stream-to-it has no types const iterateReadableStream = require('browser-readablestream-to-it') +const { + parseMode, + parseMtime +} = require('ipfs-unixfs') /** * @template T * @typedef {import('ipfs-message-port-protocol/src/core').RemoteIterable} RemoteIterable */ + /** - * @typedef {import('ipfs-message-port-protocol/src/data').Time} Time - * @typedef {import('ipfs-message-port-protocol/src/data').UnixFSTime} UnixFSTime - * @typedef {import('ipfs-message-port-protocol/src/dag').EncodedCID} EncodedCID - * @typedef {import('ipfs-message-port-server/src/core').SingleFileInput} EncodedAddInput - * @typedef {import('ipfs-message-port-server/src/core').MultiFileInput} EncodedAddAllInput - * @typedef {import('ipfs-message-port-server/src/core').FileInput} FileInput - * @typedef {import('ipfs-message-port-server/src/core').FileContent} EncodedFileContent - * - * @typedef {Object} NoramilzedFileInput - * @property {string} path - * @property {AsyncIterable} content - * - * @typedef {ArrayBuffer|ArrayBufferView} Bytes - * - * @typedef {Blob|Bytes|string|Iterable|Iterable|AsyncIterable} FileContent - * - * @typedef {Object} FileObject - * @property {string} [path] - * @property {FileContent} [content] - * @property {string|number} [mode] - * @property {UnixFSTime} [mtime] - * + * @typedef {import('ipfs-message-port-protocol/src/cid').EncodedCID} EncodedCID + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedAddInput} EncodedAddInput + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedAddAllInput} EncodedAddAllInput + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedAddResult} EncodedAddResult + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedIPFSEntry} EncodedIPFSEntry + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedFileInput} EncodedFileInput + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedFileContent} EncodedFileContent + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedDirectoryInput} EncodedDirectoryInput * - * @typedef {Blob|Bytes|string|FileObject|Iterable|Iterable|AsyncIterable|ReadableStream} AddInput + * @typedef {import('ipfs-message-port-server').CoreService} CoreService * - * @typedef {Iterable|AsyncIterable} AddAllInput - */ - -/** - * @typedef {import('ipfs-message-port-server/src/core').CoreService} CoreService - * @typedef {import('ipfs-message-port-server/src/core').AddedEntry} AddedEntry - * @typedef {import('ipfs-message-port-server/src/core').EncodedLsEntry} EncodedLsEntry - * @typedef {import('ipfs-message-port-server/src/core').LsEntry} LsEntry * @typedef {import('./client').MessageTransport} MessageTransport + * @typedef {import('./interface').MessagePortClientOptions} MessagePortClientOptions + * @typedef {import('ipfs-core-types/src/root').API} RootAPI + * + * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + * @typedef {import('ipfs-core-types/src/utils').ToFile} ToFile + * @typedef {import('ipfs-core-types/src/utils').ToDirectory} ToDirectory + * @typedef {import('ipfs-core-types/src/utils').ToContent} ToContent + * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource */ /** @@ -65,103 +57,93 @@ class CoreClient extends Client { constructor (transport) { super('core', ['add', 'addAll', 'cat', 'ls'], transport) } +} - /** - * Import files and data into IPFS. - * - * If you pass binary data like `Uint8Array` it is recommended to provide - * `transfer: [input.buffer]` which would allow transferring it instead of - * copying. - * - * @type {import('.').Implements} - */ - async * addAll (input, options = {}) { - const { timeout, signal } = options - const transfer = [...(options.transfer || [])] - const progress = options.progress - ? encodeCallback(options.progress, transfer) - : undefined - - const result = await this.remote.addAll({ - ...options, - input: encodeAddAllInput(input, transfer), - progress, - transfer, - timeout, - signal - }) - yield * decodeIterable(result.data, decodeAddedData) - } +/** + * Import files and data into IPFS. + * + * If you pass binary data like `Uint8Array` it is recommended to provide + * `transfer: [input.buffer]` which would allow transferring it instead of + * copying. + * + * @type {RootAPI["addAll"]} + */ +CoreClient.prototype.addAll = async function * addAll (input, options = {}) { + const { timeout, signal } = options + const transfer = [...(options.transfer || [])] + const progressCallback = options.progress + ? encodeCallback(options.progress, transfer) + : undefined + + const result = await this.remote.addAll({ + ...options, + input: encodeAddAllInput(input, transfer), + progress: undefined, + progressCallback, + transfer, + timeout, + signal + }) + yield * decodeIterable(result.data, decodeAddedData) +} - /** - * Add file to IPFS. - * - * If you pass binary data like `Uint8Array` it is recommended to provide - * `transfer: [input.buffer]` which would allow transferring it instead of - * copying. - * - * @type {import('.').Implements} - */ - async add (input, options = {}) { - const { timeout, signal } = options - const transfer = [...(options.transfer || [])] - const progress = options.progress - ? encodeCallback(options.progress, transfer) - : undefined - - const result = await this.remote.add({ - ...options, - input: encodeAddInput(input, transfer), - progress, - transfer, - timeout, - signal - }) - - return decodeAddedData(result.data) - } +/** + * Add file to IPFS. + * + * If you pass binary data like `Uint8Array` it is recommended to provide + * `transfer: [input.buffer]` which would allow transferring it instead of + * copying. + * + * @type {RootAPI["add"]} + */ +CoreClient.prototype.add = async function add (input, options = {}) { + const { timeout, signal } = options + const transfer = [...(options.transfer || [])] + const progressCallback = options.progress + ? encodeCallback(options.progress, transfer) + : undefined + + const result = await this.remote.add({ + ...options, + input: encodeAddInput(input, transfer), + progress: undefined, + progressCallback, + transfer, + timeout, + signal + }) + + return decodeAddedData(result.data) +} - /** - * Returns content addressed by a valid IPFS Path. - * - * @param {string|CID} inputPath - * @param {Object} [options] - * @param {number} [options.offset] - * @param {number} [options.length] - * @param {number} [options.timeout] - * @param {AbortSignal} [options.signal] - * @returns {AsyncIterable} - */ - async * cat (inputPath, options = {}) { - const input = CID.isCID(inputPath) ? encodeCID(inputPath) : inputPath - const result = await this.remote.cat({ ...options, path: input }) - yield * decodeIterable(result.data, identity) - } +/** + * Returns content addressed by a valid IPFS Path. + * + * @type {RootAPI["cat"]} + */ +CoreClient.prototype.cat = async function * cat (inputPath, options = {}) { + const input = CID.isCID(inputPath) ? encodeCID(inputPath) : inputPath + const result = await this.remote.cat({ ...options, path: input }) + yield * decodeIterable(result.data, identity) +} - /** - * Returns content addressed by a valid IPFS Path. - * - * @param {string|CID} inputPath - * @param {Object} [options] - * @param {boolean} [options.recursive] - * @param {boolean} [options.preload] - * @param {number} [options.timeout] - * @param {AbortSignal} [options.signal] - * @returns {AsyncIterable} - */ - async * ls (inputPath, options = {}) { - const input = CID.isCID(inputPath) ? encodeCID(inputPath) : inputPath - const result = await this.remote.ls({ ...options, path: input }) +/** + * Returns content addressed by a valid IPFS Path. + * + * @type {RootAPI["ls"]} + */ +CoreClient.prototype.ls = async function * ls (inputPath, options = {}) { + const input = CID.isCID(inputPath) ? encodeCID(inputPath) : inputPath + const result = await this.remote.ls({ ...options, path: input }) - yield * decodeIterable(result.data, decodeLsEntry) - } + yield * decodeIterable(result.data, decodeLsEntry) } /** * Decodes values yield by `ipfs.add`. * - * @param {AddedEntry} data - * @returns {import('ipfs-core-types/src/files').UnixFSEntry} + * @param {EncodedAddResult} data + * @returns {import('ipfs-core-types/src/root').AddResult} */ const decodeAddedData = ({ path, cid, mode, mtime, size }) => { return { @@ -174,8 +156,8 @@ const decodeAddedData = ({ path, cid, mode, mtime, size }) => { } /** - * @param {EncodedLsEntry} encodedEntry - * @returns {LsEntry} + * @param {EncodedIPFSEntry} encodedEntry + * @returns {import('ipfs-core-types/src/root').IPFSEntry} */ const decodeLsEntry = ({ depth, name, path, size, cid, type, mode, mtime }) => ({ cid: decodeCID(cid), @@ -199,7 +181,7 @@ const identity = (v) => v * Encodes input passed to the `ipfs.add` via the best possible strategy for the * given input. * - * @param {AddInput} input + * @param {ToEntry} input * @param {Transferable[]} transfer * @returns {EncodedAddInput} */ @@ -253,7 +235,7 @@ const encodeAddInput = (input, transfer) => { * Encodes input passed to the `ipfs.add` via the best possible strategy for the * given input. * - * @param {AddAllInput} input + * @param {ImportSource} input * @param {Transferable[]} transfer * @returns {EncodedAddAllInput} */ @@ -290,9 +272,9 @@ const encodeAddAllInput = (input, transfer) => { * Function encodes individual item of some `AsyncIterable` by choosing most * effective strategy. * - * @param {ArrayBuffer|ArrayBufferView|Blob|string|FileObject} content + * @param {ToEntry} content * @param {Transferable[]} transfer - * @returns {FileInput|ArrayBuffer|ArrayBufferView} + * @returns {EncodedAddInput} */ const encodeAsyncIterableContent = (content, transfer) => { if (content instanceof ArrayBuffer) { @@ -314,9 +296,9 @@ const encodeAsyncIterableContent = (content, transfer) => { } /** - * @param {number|Bytes|Blob|string|FileObject|void} content + * @param {ToEntry} content * @param {Transferable[]} transfer - * @returns {FileInput|ArrayBuffer|ArrayBufferView} + * @returns {EncodedAddInput} */ const encodeIterableContent = (content, transfer) => { if (typeof content === 'number') { @@ -340,22 +322,27 @@ const encodeIterableContent = (content, transfer) => { } /** - * @param {FileObject} file + * @param {ToFile | ToDirectory} file * @param {Transferable[]} transfer - * @returns {FileInput} + * @returns {EncodedFileInput | EncodedDirectoryInput} */ const encodeFileObject = ({ path, mode, mtime, content }, transfer) => { - return { + /** @type {any} */ + const output = { path, - mode, - mtime, - content: content ? encodeFileContent(content, transfer) : undefined + mode: parseMode(mode), + mtime: parseMtime(mtime) + } + + if (content) { + output.content = encodeFileContent(content, transfer) } + + return output } /** - * - * @param {FileContent|undefined} content + * @param {ToContent|undefined} content * @param {Transferable[]} transfer * @returns {EncodedFileContent} */ @@ -401,7 +388,7 @@ const encodeFileContent = (content, transfer) => { * iterable or `null`. * * @template I - * @param {Iterable|AddInput|AddAllInput} input + * @param {Iterable|ToEntry|ImportSource} input * @returns {Iterable|null} */ const asIterable = (input) => { @@ -419,7 +406,7 @@ const asIterable = (input) => { * matched `AsyncIterable` or `null`. * * @template I - * @param {AsyncIterable|AddInput|AddAllInput} input + * @param {AsyncIterable|ToEntry|ImportSource} input * @returns {AsyncIterable|null} */ const asAsyncIterable = (input) => { @@ -452,7 +439,7 @@ const asReadableStream = (input) => { * input or `null`. * * @param {*} input - * @returns {FileObject|null} + * @returns {ToFile|null} */ const asFileObject = (input) => { if (typeof input === 'object' && (input.path || input.content)) { diff --git a/packages/ipfs-message-port-client/src/dag.js b/packages/ipfs-message-port-client/src/dag.js index 7a7434de89..542db13f62 100644 --- a/packages/ipfs-message-port-client/src/dag.js +++ b/packages/ipfs-message-port-client/src/dag.js @@ -6,12 +6,11 @@ const { encodeNode, decodeNode } = require('ipfs-message-port-protocol/src/dag') /** * @typedef {import('cids')} CID - * @typedef {import('ipfs-message-port-server/src/dag').EncodedCID} EncodedCID - * @typedef {import('ipfs-message-port-server/src/dag').DAGNode} DAGNode - * @typedef {import('ipfs-message-port-server/src/dag').EncodedDAGNode} EncodedDAGNode - * @typedef {import('ipfs-message-port-server/src/dag').DAGEntry} DAGEntry - * @typedef {import('ipfs-message-port-server/src/dag').DAGService} DagService + * @typedef {import('ipfs-message-port-protocol/src/cid').EncodedCID} EncodedCID + * @typedef {import('ipfs-message-port-server').DAGService} DagService * @typedef {import('./client').MessageTransport} MessageTransport + * @typedef {import('./interface').MessagePortClientOptions} MessagePortClientOptions + * @typedef {import('ipfs-core-types/src/dag').API} DAGAPI */ /** @@ -25,93 +24,57 @@ class DAGClient extends Client { constructor (transport) { super('dag', ['put', 'get', 'resolve', 'tree'], transport) } +} - /** - * @param {DAGNode} dagNode - * @param {Object} [options] - * @param {string} [options.format="dag-cbor"] - The IPLD format multicodec - * @param {string} [options.hashAlg="sha2-256"] - The hash algorithm to be used over the serialized DAG node - * @param {CID} [options.cid] - * @param {boolean} [options.pin=false] - Pin this node when adding to the blockstore - * @param {boolean} [options.preload=true] - * @param {Transferable[]} [options.transfer] - References to transfer to the - * @param {number} [options.timeout] - A timeout in ms - * @param {AbortSignal} [options.signal] - Can be used to cancel any long running requests started as a result of this call. - * @returns {Promise} - */ - async put (dagNode, options = {}) { - const { cid } = options +/** + * @type {DAGAPI["put"]} + */ +DAGClient.prototype.put = async function put (dagNode, options = {}) { + const { cid } = options - const encodedCID = await this.remote.put({ - ...options, - cid: cid != null ? encodeCID(cid) : undefined, - dagNode: encodeNode(dagNode, options.transfer) - }) + const encodedCID = await this.remote.put({ + ...options, + encodedCid: cid != null ? encodeCID(cid) : undefined, + dagNode: encodeNode(dagNode, options.transfer) + }) - return decodeCID(encodedCID) - } + return decodeCID(encodedCID) +} - /** - * @param {CID} cid - * @param {Object} [options] - * @param {string} [options.path] - * @param {boolean} [options.localResolve] - * @param {number} [options.timeout] - * @param {Transferable[]} [options.transfer] - References to transfer to the - * @param {AbortSignal} [options.signal] - * @returns {Promise} - */ - async get (cid, options = {}) { - const { value, remainderPath } = await this.remote.get({ - ...options, - cid: encodeCID(cid, options.transfer) - }) +/** + * @type {DAGAPI["get"]} + */ +DAGClient.prototype.get = async function get (cid, options = {}) { + const { value, remainderPath } = await this.remote.get({ + ...options, + cid: encodeCID(cid, options.transfer) + }) - return { value: decodeNode(value), remainderPath } - } + return { value: decodeNode(value), remainderPath } +} - /** - * @typedef {Object} ResolveResult - * @property {CID} cid - * @property {string|void} remainderPath - * - * @param {CID} cid - * @param {Object} [options] - * @param {string} [options.path] - * @param {number} [options.timeout] - * @param {Transferable[]} [options.transfer] - References to transfer to the - * @param {AbortSignal} [options.signal] - * @returns {Promise} - */ - async resolve (cid, options = {}) { - const { cid: encodedCID, remainderPath } = await this.remote.resolve({ - ...options, - cid: encodeCIDOrPath(cid, options.transfer) - }) +/** + * @type {DAGAPI["resolve"]} + */ +DAGClient.prototype.resolve = async function resolve (cid, options = {}) { + const { cid: encodedCID, remainderPath } = await this.remote.resolve({ + ...options, + cid: encodeCIDOrPath(cid, options.transfer) + }) - return { cid: decodeCID(encodedCID), remainderPath } - } + return { cid: decodeCID(encodedCID), remainderPath } +} - /** - * Enumerate all the entries in a graph - * - * @param {CID} cid - CID of the DAG node to enumerate - * @param {Object} [options] - * @param {string} [options.path] - * @param {boolean} [options.recursive] - * @param {Transferable[]} [options.transfer] - References to transfer to the - * @param {number} [options.timeout] - * @param {AbortSignal} [options.signal] - * @returns {AsyncIterable} - */ - async * tree (cid, options = {}) { - const paths = await this.remote.tree({ - ...options, - cid: encodeCID(cid, options.transfer) - }) +/** + * @type {DAGAPI["tree"]} + */ +DAGClient.prototype.tree = async function * tree (cid, options = {}) { + const paths = await this.remote.tree({ + ...options, + cid: encodeCID(cid, options.transfer) + }) - yield * paths - } + yield * paths } /** diff --git a/packages/ipfs-message-port-client/src/files.js b/packages/ipfs-message-port-client/src/files.js index 1aab19f11f..f12a305758 100644 --- a/packages/ipfs-message-port-client/src/files.js +++ b/packages/ipfs-message-port-client/src/files.js @@ -2,12 +2,15 @@ /* eslint-env browser */ const Client = require('./client') -const { decodeCID, CID } = require('ipfs-message-port-protocol/src/cid') +const { decodeCID } = require('ipfs-message-port-protocol/src/cid') +const CID = require('cids') /** - * @typedef {import('ipfs-message-port-server/src/files').FilesService} FilesService - * @typedef {import('ipfs-message-port-server/src/files').EncodedStat} EncodedStat + * @typedef {import('ipfs-message-port-server').FilesService} FilesService + * @typedef {import('ipfs-message-port-protocol/src/files').EncodedStat} EncodedStat * @typedef {import('./client').MessageTransport} MessageTransport + * @typedef {import('./interface').MessagePortClientOptions} MessagePortClientOptions + * @typedef {import('ipfs-core-types/src/files').API} FilesAPI */ /** @@ -21,56 +24,36 @@ class FilesClient extends Client { constructor (transport) { super('files', ['stat'], transport) } +} - /** - * @typedef {Object} Stat - * @property {CID} cid Content identifier. - * @property {number} size File size in bytes. - * @property {number} cumulativeSize Size of the DAGNodes making up the file in bytes. - * @property {"directory"|"file"} type - * @property {number} blocks Number of files making up directory (when a direcotry) - * or number of blocks that make up the file (when a file) - * @property {boolean} withLocality True when locality information is present - * @property {boolean} local True if the queried dag is fully present locally - * @property {number} sizeLocal Cumulative size of the data present locally - * - * @param {string|CID} pathOrCID - * @param {Object} [options] - * @param {boolean} [options.hash=false] - If true will only return hash - * @param {boolean} [options.size=false] - If true will only return size - * @param {boolean} [options.withLocal=false] - If true computes size of the dag that is local, and total size when possible - * @param {number} [options.timeout] - * @param {AbortSignal} [options.signal] - * @returns {Promise} - */ - async stat (pathOrCID, options = {}) { - const { size, hash, withLocal, timeout, signal } = options - const { stat } = await this.remote.stat({ - path: encodeLocation(pathOrCID), - size, - hash, - withLocal, - timeout, - signal - }) - return decodeStat(stat) - } +/** + * @type {FilesAPI["stat"]} + */ +FilesClient.prototype.stat = async function stat (pathOrCID, options = {}) { + const { size, hash, withLocal, timeout, signal } = options + const { stat } = await this.remote.stat({ + path: encodeLocation(pathOrCID), + size, + hash, + withLocal, + timeout, + signal + }) + return decodeStat(stat) } + module.exports = FilesClient /** * Turns content address (path or CID) into path. * * @param {string|CID} pathOrCID - * @returns {string} */ const encodeLocation = pathOrCID => CID.isCID(pathOrCID) ? `/ipfs/${pathOrCID.toString()}` : pathOrCID /** - * * @param {EncodedStat} data - * @returns {Stat} */ const decodeStat = data => { return { ...data, cid: decodeCID(data.cid) } diff --git a/packages/ipfs-message-port-client/src/index.js b/packages/ipfs-message-port-client/src/index.js index 205298b822..fd01e814b8 100644 --- a/packages/ipfs-message-port-client/src/index.js +++ b/packages/ipfs-message-port-client/src/index.js @@ -6,12 +6,6 @@ const BlockClient = require('./block') const DAGClient = require('./dag') const CoreClient = require('./core') const FilesClient = require('./files') - -/** - * @typedef {Object} ClientOptions - * @property {MessagePort} port - */ - class IPFSClient extends CoreClient { /** * @param {MessageTransport} transport @@ -60,39 +54,3 @@ class IPFSClient extends CoreClient { } module.exports = IPFSClient - -/** - * @typedef {Object} MessagePortOptions - * @property {Array} [transfer] - A list of ArrayBuffers whose ownership will be transferred to the shared worker - * - * @typedef {import('ipfs-core/src/utils').AbortOptions} AbortOptions} - */ - -/** - * This is an utility type that can be used to derive type of the HTTP Client - * API from the Core API. It takes type of the API factory (from ipfs-core), - * derives API from it's return type and extends it last `options` parameter - * with `HttpOptions`. - * - * This can be used to avoid (re)typing API interface when implementing it in - * http client e.g you can annotate `ipfs.addAll` implementation with - * - * `@type {Implements}` - * - * **Caution**: This supports APIs with up to four parameters and last optional - * `options` parameter, anything else will result to `never` type. - * - * @template {(config:any) => any} APIFactory - * @typedef {APIWithExtraOptions, MessagePortOptions>} Implements - */ - -/** - * @template Key - * @template {(config:any) => any} APIFactory - * @typedef {import('./interface').APIMethodWithExtraOptions, Key, MessagePortOptions>} ImplementsMethod - */ - -/** - * @template API, Extra - * @typedef {import('./interface').APIWithExtraOptions} APIWithExtraOptions - */ diff --git a/packages/ipfs-message-port-client/src/interface.d.ts b/packages/ipfs-message-port-client/src/interface.d.ts new file mode 100644 index 0000000000..693f9172e6 --- /dev/null +++ b/packages/ipfs-message-port-client/src/interface.d.ts @@ -0,0 +1,6 @@ +// This file contains some utility types that either can't be expressed in +// JSDoc syntax or that result in a different behaviour when typed in JSDoc. + +export interface MessagePortClientOptions { + transfer?: Transferable[] +} diff --git a/packages/ipfs-message-port-client/src/interface.ts b/packages/ipfs-message-port-client/src/interface.ts deleted file mode 100644 index d70df28957..0000000000 --- a/packages/ipfs-message-port-client/src/interface.ts +++ /dev/null @@ -1,57 +0,0 @@ -// This file contains some utility types that either can't be expressed in -// JSDoc syntax or that result in a different behaviour when typed in JSDoc. - -/** - * Utility type that takes IPFS Core API function type (with 0 to 4 arguments - * & last **optional** `options` parameter) and derives a function type with - * `options` parameter extended with given `Extra` options. - * - * **Caution**: API Functions with more than for arguments ahead of `options` - * will result to `never` type. API function that does not take `options` will - * result in function whose last argument is extended with `Extra` which would - * be an error. - */ -// This is typed in TS file because otherwise TS unifies on the first parameter -// regardless of number of parameters function has. -export interface APIWithExtraOptions any, Extra> { (...args: WithExtendedOptions, Extra>): ReturnType } - -type End = never[] -type WithExtendedOptions = Params extends [...End] - ? [] - // (options?: Options) -> (options?: Options & Ext) - : Params extends [options?: infer Options, ...end: End] - ? [options?: Options & Ext] - // (a: A1, options?: Options) -> (a1: A1, options?: Options & Ext) - : Params extends [a1: infer A1, options?: infer Options, ...end: End] - ? [a1: A1, options?: Options & Ext] - // (a1?: A1, options?: Options) -> (a1?: A1, options?: Options & Ext) - : Params extends [a1?: infer A1, options?: infer Options, ...end: End] - ? [a1?: A1, options?: Options & Ext] - // (a1: A1, a2: A2, options?: Options) -> (a1: A1, a2: A2 options?: Options & Ext) - : Params extends [a1: infer A1, a2: infer A2, options?: infer Options, ...end: End] - ? [a1: A1, a2: A2, options?: Options & Ext] - // (a1: A1, a2?: A2, options?: Options) -> (a1: A1, a2?: A2 options?: Options & Ext) - : Params extends [a1: infer A1, a2?: infer A2, options?: infer Options, ...end: End] - ? [a1: A1, a2?: A2, options?: Options & Ext] - // (a1: A1, a2?: A2, options?: Options) -> (a1: A1, a2?: A2 options?: Options & Ext) - : Params extends [a1?: infer A1, a2?: infer A2, options?: infer Options, ...end: End] - ? [a1?: A1, a2?: A2, options?: Options & Ext] - // (a1: A1, a2: A2, a3:A3 options?: Options) -> (a1: A1, a2: A2, a3:A3, options?: Options & Ext) - : Params extends [a1: infer A1, a2: infer A2, a3:infer A3, options?: infer Options, ...end: End] - ? [a1: A1, a2: A2, a3: A3, options?: Options & Ext] - // (a1: A1, a2: A2, a3?:A3 options?: Options) -> (a1: A1, a2: A2, a3?:A3, options?: Options & Ext) - : Params extends [a1: infer A1, a2:infer A2, a3?: infer A3, options?: infer Options, ...end: End] - ? [a1: A1, a2: A2, a3?: A3, options?: Options & Ext] - // (a1: A1, a2?: A2, a3?:A3 options?: Options) -> (a1: A1, a2?: A2, a3?:A3, options?: Options & Ext) - : Params extends [a1: infer A1, a2?: infer A2, a3?: infer A3, options?: infer Options, ...end: End] - ? [a1: A1, a2?: A2, a3?: A3, options?: Options & Ext] - // (a1?: A1, a2?: A2, a3?:A3 options?: Options) -> (a1?: A1, a2?: A2, a3?:A3, options?: Options & Ext) - : Params extends [a1?: infer A1, a2?: infer A2, a3?: infer A3, options?: infer Options, ...end: End] - ? [a1?: A1, a2?: A2, a3?: A3, options?: Options & Ext] - : never - -export type APIMethodWithExtraOptions < - API, - Key extends keyof API, - Extra -> = API[Key] extends (...args: any[]) => any ? APIWithExtraOptions : never diff --git a/packages/ipfs-message-port-client/test/util/worker.js b/packages/ipfs-message-port-client/test/util/worker.js index 93b81cc3a3..4ed16a139b 100644 --- a/packages/ipfs-message-port-client/test/util/worker.js +++ b/packages/ipfs-message-port-client/test/util/worker.js @@ -1,6 +1,6 @@ 'use strict' -const IPFS = require('ipfs') +const IPFS = require('ipfs-core') const { IPFSService, Server } = require('ipfs-message-port-server') const main = async connections => { diff --git a/packages/ipfs-message-port-client/tsconfig.json b/packages/ipfs-message-port-client/tsconfig.json index ad2457a225..8b0642becf 100644 --- a/packages/ipfs-message-port-client/tsconfig.json +++ b/packages/ipfs-message-port-client/tsconfig.json @@ -1,11 +1,10 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" ], "references": [ { @@ -15,10 +14,7 @@ "path": "../ipfs-message-port-server" }, { - "path": "../ipfs-core" - }, - { - "path": "../ipfs-core-utils" + "path": "../ipfs-core-types" } ] } diff --git a/packages/ipfs-message-port-protocol/package.json b/packages/ipfs-message-port-protocol/package.json index f456322d21..0bdd48a860 100644 --- a/packages/ipfs-message-port-protocol/package.json +++ b/packages/ipfs-message-port-protocol/package.json @@ -11,13 +11,18 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], + "types": "dist/src/index.d.ts", "typesVersions": { "*": { - "*": [ - "dist/*", - "dist/*/index" + "src/*": [ + "dist/src/*", + "dist/src/*/index" + ], + "src/": [ + "dist/src/index" ] } }, @@ -27,6 +32,8 @@ "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { + "prepare": "npm run build", + "build": "aegir build --no-bundle", "test": "aegir test", "test:node": "aegir test -t node", "test:browser": "aegir test -t browser", @@ -36,14 +43,15 @@ "lint": "aegir lint", "coverage": "npx nyc -r html npm run test:node -- --bail", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i rimraf" + "dep-check": "aegir dep-check -i rimraf -i ipfs-core-types" }, "dependencies": { "cids": "^1.1.5", + "ipfs-core-types": "^0.3.1", "ipld-block": "^0.11.0" }, "devDependencies": { - "aegir": "^31.0.0", + "aegir": "^32.1.0", "rimraf": "^3.0.2", "uint8arrays": "^2.1.3" }, diff --git a/packages/ipfs-message-port-protocol/src/block.js b/packages/ipfs-message-port-protocol/src/block.js index 8d8a59111e..01608f1017 100644 --- a/packages/ipfs-message-port-protocol/src/block.js +++ b/packages/ipfs-message-port-protocol/src/block.js @@ -4,7 +4,15 @@ const { encodeCID, decodeCID } = require('./cid') const Block = require('ipld-block') /** + * @typedef {import('./error').EncodedError} EncodedError * @typedef {import('./cid').EncodedCID} EncodedCID + * + * @typedef {Object} EncodedRmResult + * @property {EncodedCID} cid + * @property {EncodedError|undefined} [error] + */ + +/** * @typedef {Object} EncodedBlock * @property {Uint8Array} data * @property {EncodedCID} cid diff --git a/packages/ipfs-message-port-protocol/src/cid.js b/packages/ipfs-message-port-protocol/src/cid.js index a33e4b3843..8b2fd2cf79 100644 --- a/packages/ipfs-message-port-protocol/src/cid.js +++ b/packages/ipfs-message-port-protocol/src/cid.js @@ -46,5 +46,3 @@ const decodeCID = encodedCID => { return cid } exports.decodeCID = decodeCID - -exports.CID = CID diff --git a/packages/ipfs-message-port-protocol/src/dag.js b/packages/ipfs-message-port-protocol/src/dag.js index ec37aa50fb..01bfdb2ad3 100644 --- a/packages/ipfs-message-port-protocol/src/dag.js +++ b/packages/ipfs-message-port-protocol/src/dag.js @@ -1,6 +1,7 @@ 'use strict' -const { encodeCID, decodeCID, CID } = require('./cid') +const CID = require('cids') +const { encodeCID, decodeCID } = require('./cid') /** * @typedef {import('./data').JSONValue} JSONValue @@ -12,12 +13,7 @@ const { encodeCID, decodeCID, CID } = require('./cid') */ /** - * @typedef {Object} EncodedCID - * @property {string} codec - * @property {Uint8Array} multihash - * @property {number} version * @typedef {JSONValue} DAGNode - * * @typedef {Object} EncodedDAGNode * @property {DAGNode} dagNode * @property {CID[]} cids diff --git a/packages/ipfs-message-port-protocol/src/data.ts b/packages/ipfs-message-port-protocol/src/data.d.ts similarity index 58% rename from packages/ipfs-message-port-protocol/src/data.ts rename to packages/ipfs-message-port-protocol/src/data.d.ts index fd0beb8de6..975fff41b8 100644 --- a/packages/ipfs-message-port-protocol/src/data.ts +++ b/packages/ipfs-message-port-protocol/src/data.d.ts @@ -11,24 +11,6 @@ export type JSONValue = export type Encoded<_Data, Representation> = Representation // eslint-disable-line @typescript-eslint/no-unused-vars export type StringEncoded = Encoded -export interface UnixFSTime { - secs: number - nsecs: number -} - -export interface LooseUnixFSTime { - secs: number - nsecs?: number -} - -export type HRTime = [number, number] - -export type Time = Date | LooseUnixFSTime | HRTime -export type Mode = string | number -export type HashAlg = string -export type FileType = 'directory' | 'file' -export type CIDVersion = 0 | 1 - export type Result = { ok: true, value: T } | { ok: false, error: X } export interface EncodedError { diff --git a/packages/ipfs-message-port-protocol/src/files.d.ts b/packages/ipfs-message-port-protocol/src/files.d.ts new file mode 100644 index 0000000000..1a3d7423a3 --- /dev/null +++ b/packages/ipfs-message-port-protocol/src/files.d.ts @@ -0,0 +1,15 @@ +import { Mtime } from 'ipfs-unixfs' +import { EncodedCID } from './cid' + +export interface EncodedStat { + cid: EncodedCID + size: number + cumulativeSize: number + type: 'directory' | 'file' + blocks: number + withLocality: boolean + local?: boolean + sizeLocal?: number + mode?: number + mtime?: Mtime +} diff --git a/packages/ipfs-message-port-protocol/src/root.d.ts b/packages/ipfs-message-port-protocol/src/root.d.ts new file mode 100644 index 0000000000..5fcfaf8458 --- /dev/null +++ b/packages/ipfs-message-port-protocol/src/root.d.ts @@ -0,0 +1,40 @@ +import type { Mtime } from 'ipfs-unixfs' +import type { RemoteIterable } from './core' +import type { FileType } from './data' + +export type EncodedFileContent = ArrayBufferView | ArrayBuffer | Blob | string | RemoteIterable | RemoteIterable + +export interface EncodedFileInput { + path?: string + content: EncodedFileContent + mode?: number + mtime?: Mtime +} + +export interface EncodedDirectoryInput { + path: string + mode?: number + mtime?: Mtime +} + +export type EncodedAddInput = EncodedFileContent | EncodedFileInput | EncodedDirectoryInput +export type EncodedAddAllInput = RemoteIterable + +export interface EncodedAddResult { + path: string + cid: EncodedCID + size: number + mode?: number + mtime?: Mtime +} + +export interface EncodedIPFSEntry { + cid: EncodedCID + type: FileType + name: string + path: string + depth: number + size: number + mode?: number + mtime?: Mtime +} diff --git a/packages/ipfs-message-port-protocol/src/rpc.ts b/packages/ipfs-message-port-protocol/src/rpc.d.ts similarity index 100% rename from packages/ipfs-message-port-protocol/src/rpc.ts rename to packages/ipfs-message-port-protocol/src/rpc.d.ts diff --git a/packages/ipfs-message-port-protocol/tsconfig.json b/packages/ipfs-message-port-protocol/tsconfig.json index 979a39adab..03031d1601 100644 --- a/packages/ipfs-message-port-protocol/tsconfig.json +++ b/packages/ipfs-message-port-protocol/tsconfig.json @@ -1,10 +1,14 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" + ], + "references": [ + { + "path": "../ipfs-core-types" + } ] } diff --git a/packages/ipfs-message-port-server/.aegir.js b/packages/ipfs-message-port-server/.aegir.js new file mode 100644 index 0000000000..bafbe7e4db --- /dev/null +++ b/packages/ipfs-message-port-server/.aegir.js @@ -0,0 +1,8 @@ +'use strict' + +/** @type {import('aegir').PartialOptions} */ +module.exports = { + build: { + bundlesizeMax: '22kB' + } +} diff --git a/packages/ipfs-message-port-server/package.json b/packages/ipfs-message-port-server/package.json index 6e97e9c54d..896fe6ad3b 100644 --- a/packages/ipfs-message-port-server/package.json +++ b/packages/ipfs-message-port-server/package.json @@ -13,26 +13,19 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "dist/src/index.d.ts", "browser": { "worker_threads": false }, - "typesVersions": { - "*": { - "*": [ - "dist/*", - "dist/*/index" - ] - } - }, "repository": { "type": "git", "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { - "prepare": "npm run build", "build": "aegir build", "test": "aegir test", "test:browser": "aegir test -t browser", @@ -42,14 +35,15 @@ "lint": "aegir lint", "coverage": "npx nyc -r html npm run test:node -- --bail", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i rimraf" + "dep-check": "aegir dep-check -i rimraf -i ipfs-core-types" }, "dependencies": { + "ipfs-core-types": "^0.3.1", "ipfs-message-port-protocol": "^0.6.1", "it-all": "^1.0.4" }, "devDependencies": { - "aegir": "^31.0.0", + "aegir": "^32.1.0", "cids": "^1.1.5", "rimraf": "^3.0.2" }, diff --git a/packages/ipfs-message-port-server/src/block.js b/packages/ipfs-message-port-server/src/block.js index 0e19ec581a..1a19efb596 100644 --- a/packages/ipfs-message-port-server/src/block.js +++ b/packages/ipfs-message-port-server/src/block.js @@ -9,14 +9,14 @@ const { } = require('ipfs-message-port-protocol/src/block') /** - * @typedef {import('./ipfs').IPFS} IPFS + * @typedef {import('ipfs-core-types').IPFS} IPFS * @typedef {import('cids')} CID * @typedef {import('ipfs-message-port-protocol/src/error').EncodedError} EncodedError * @typedef {import('ipfs-message-port-protocol/src/block').Block} Block * @typedef {import('ipfs-message-port-protocol/src/cid').EncodedCID} EncodedCID * @typedef {import('ipfs-message-port-protocol/src/block').EncodedBlock} EncodedBlock - * @typedef {RmEntry} Rm - * @typedef {StatResult} Stat + * @typedef {import('ipfs-message-port-protocol/src/block').EncodedRmResult} EncodedRmResult + * @typedef {import('ipfs-core-types/src/block').PutOptions} PutOptions */ exports.BlockService = class BlockService { @@ -56,17 +56,10 @@ exports.BlockService = class BlockService { * @typedef {Object} PutQuery * @property {EncodedBlock|Uint8Array} block * @property {EncodedCID|undefined} [cid] - * @property {string} [format] - * @property {string} [mhtype] - * @property {number} [mhlen] - * @property {number} [version] - * @property {boolean} [pin] - * @property {number} [timeout] - * @property {AbortSignal} [signal] * * Stores input as an IPFS block. * - * @param {PutQuery} query + * @param {PutOptions & PutQuery} query * @returns {Promise} */ async put (query) { @@ -99,15 +92,9 @@ exports.BlockService = class BlockService { * @property {number} [timeout] * @property {AbortSignal} [signal] * - * @typedef {RmEntry[]} RmResult - * - * @typedef {Object} RmEntry - * @property {EncodedCID} cid - * @property {EncodedError|undefined} [error] - * * Remove one or more IPFS block(s). * @param {RmQuery} query - * @returns {Promise} + * @returns {Promise} */ async rm (query) { /** @type {Transferable[]} */ @@ -125,14 +112,14 @@ exports.BlockService = class BlockService { * @property {number} [timeout] * @property {AbortSignal} [signal] * - * @typedef {Object} StatResult + * @typedef {Object} EncodedStatResult * @property {EncodedCID} cid * @property {number} size * * Gets information of a raw IPFS block. * * @param {StatQuery} query - * @returns {Promise} + * @returns {Promise} */ async stat (query) { const cid = decodeCID(query.cid) @@ -146,7 +133,6 @@ exports.BlockService = class BlockService { * @param {CID} entry.cid * @param {Error|void} [entry.error] * @param {Transferable[]} transfer - * @returns {RmEntry} */ const encodeRmEntry = (entry, transfer) => { const cid = encodeCID(entry.cid, transfer) diff --git a/packages/ipfs-message-port-server/src/core.js b/packages/ipfs-message-port-server/src/core.js index dea2eb81a1..fa58711039 100644 --- a/packages/ipfs-message-port-server/src/core.js +++ b/packages/ipfs-message-port-server/src/core.js @@ -10,18 +10,19 @@ const { const { decodeCID, encodeCID } = require('ipfs-message-port-protocol/src/cid') /** - * @typedef {import("./ipfs").IPFS} IPFS - * @typedef {import("ipfs-message-port-protocol/src/data").Time} Time - * @typedef {import("ipfs-message-port-protocol/src/data").UnixFSTime} UnixFSTime - * @typedef {import("ipfs-message-port-protocol/src/data").Mode} Mode - * @typedef {import("ipfs-message-port-protocol/src/data").HashAlg} HashAlg - * @typedef {import('ipfs-message-port-protocol/src/data').FileType} FileType + * @typedef {import('cids').CIDVersion} CIDVersion + * @typedef {import('ipfs-core-types').IPFS} IPFS + * @typedef {import('ipfs-core-types/src/root').AddOptions} AddOptions + * @typedef {import('ipfs-core-types/src/root').AddAllOptions} AddAllOptions + * @typedef {import('ipfs-core-types/src/root').IPFSEntry} IPFSEntry * @typedef {import('ipfs-message-port-protocol/src/cid').EncodedCID} EncodedCID - * @typedef {import("./ipfs").FileOutput} FileOutput - * @typedef {import('./ipfs').FileObject} FileObject - * @typedef {import('./ipfs').FileContent} DecodedFileContent - * @typedef {import('./ipfs').FileInput} DecodedFileInput - * @typedef {import('./ipfs').LsEntry} LsEntry + * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource + * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + * @typedef {import('ipfs-core-types/src/root').AddResult} AddResult + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedAddInput} EncodedAddInput + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedAddAllInput} EncodedAddAllInput + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedFileContent} EncodedFileContent + * @typedef {import('ipfs-message-port-protocol/src/root').EncodedIPFSEntry} EncodedIPFSEntry */ /** @@ -34,69 +35,20 @@ const { decodeCID, encodeCID } = require('ipfs-message-port-protocol/src/cid') */ /** - * @typedef {Object} AddOptions - * @property {string} [chunker] - * @property {number} [cidVersion] - * @property {boolean} [enableShardingExperiment] - * @property {HashAlg} [hashAlg] - * @property {boolean} [onlyHash] - * @property {boolean} [pin] - * @property {RemoteCallback|void} [progress] - * @property {boolean} [rawLeaves] - * @property {number} [shardSplitThreshold] - * @property {boolean} [trickle] - * @property {boolean} [wrapWithDirectory] - * @property {number} [timeout] - * @property {AbortSignal} [signal] - * * @typedef {Object} AddAllInput - * @property {MultiFileInput} input + * @property {EncodedAddAllInput} input + * @property {RemoteCallback} [progressCallback] * * @typedef {Object} AddInput - * @property {SingleFileInput} input + * @property {EncodedAddInput} input + * @property {RemoteCallback} [progressCallback] * * @typedef {AddInput & AddOptions} AddQuery - * @typedef {AddAllInput & AddOptions} AddAllQuery - * - * @typedef {ArrayBuffer|ArrayBufferView|Blob|string|FileInput|RemoteIterable} SingleFileInput - * @typedef {RemoteIterable} MultiFileInput - * - * @typedef {Object} FileInput - * @property {string} [path] - * @property {FileContent} [content] - * @property {Mode} [mode] - * @property {Time} [mtime] - * - * @typedef {ArrayBufferView|ArrayBuffer|Blob|string|RemoteIterable|RemoteIterable} FileContent - * - * @typedef {Object} AddedEntry - * @property {string} path - * @property {EncodedCID} cid - * @property {number} mode - * @property {UnixFSTime} mtime - * @property {number} size - * - * @typedef {Object} FileEntry - * @property {string} path - * @property {RemoteIterable} content - * @property {Mode} [mode] - * @property {UnixFSTime} [mtime] - * - * - * @typedef {Object} EncodedLsEntry - * @property {EncodedCID} cid - * @property {FileType} type - * @property {string} name - * @property {string} path - * @property {number} depth - * @property {number} size - * @property {Mode} mode - * @property {UnixFSTime} [mtime] + * @typedef {AddAllInput & AddAllOptions} AddAllQuery */ exports.CoreService = class CoreService { /** - * * @param {IPFS} ipfs */ constructor (ipfs) { @@ -104,12 +56,7 @@ exports.CoreService = class CoreService { } /** - * @typedef {Object} AddAllResult - * @property {RemoteIterable} data - * @property {Transferable[]} transfer - * * @param {AddAllQuery} query - * @returns {AddAllResult} */ addAll (query) { const { input } = query @@ -120,7 +67,7 @@ exports.CoreService = class CoreService { hashAlg, onlyHash, pin, - progress, + progressCallback, rawLeaves, shardSplitThreshold, trickle, @@ -129,13 +76,15 @@ exports.CoreService = class CoreService { signal } = query - let progressCallback + let progress - if (progress) { - const fn = decodeCallback(progress) - progressCallback = (bytes, fileName) => fn([bytes, fileName]) + if (progressCallback) { + const fn = decodeCallback(progressCallback) + /** @type {import('ipfs-core-types/src/root').AddProgressFn} */ + progress = (bytes, fileName) => { fn([bytes, fileName]) } } + /** @type {AddAllOptions} */ const options = { chunker, cidVersion, @@ -148,7 +97,7 @@ exports.CoreService = class CoreService { trickle, wrapWithDirectory, timeout, - progress: progressCallback, + progress, signal } @@ -157,51 +106,44 @@ exports.CoreService = class CoreService { } /** - * @typedef {Object} AddResult - * @property {AddedEntry} data - * @property {Transferable[]} transfer - * * @param {AddQuery} query - * @returns {Promise} */ async add (query) { const { input } = query const { chunker, cidVersion, - enableShardingExperiment, hashAlg, onlyHash, pin, - progress, + progressCallback, rawLeaves, - shardSplitThreshold, trickle, wrapWithDirectory, timeout, signal } = query - let progressCallback + let progress - if (progress) { - const fn = decodeCallback(progress) - progressCallback = (bytes, fileName) => fn([bytes, fileName]) + if (progressCallback) { + const fn = decodeCallback(progressCallback) + /** @type {import('ipfs-core-types/src/root').AddProgressFn} */ + progress = (bytes, fileName) => { fn([bytes, fileName]) } } + /** @type {AddOptions} */ const options = { chunker, cidVersion, - enableShardingExperiment, hashAlg, onlyHash, pin, rawLeaves, - shardSplitThreshold, trickle, wrapWithDirectory, timeout, - progress: progressCallback, + progress, signal } @@ -217,12 +159,7 @@ exports.CoreService = class CoreService { * @property {number} [timeout] * @property {AbortSignal} [signal] * - * @typedef {Object} CatResult - * @property {RemoteIterable} data - * @property {Transferable[]} transfer - * * @param {CatQuery} query - * @returns {CatResult} */ cat (query) { const { path, offset, length, timeout, signal } = query @@ -239,12 +176,7 @@ exports.CoreService = class CoreService { * @property {number} [timeout] * @property {AbortSignal} [signal] * - * @typedef {Object} LsResult - * @property {RemoteIterable} data - * @property {Transferable[]} transfer - * * @param {LsQuery} query - * @returns {LsResult} */ ls (query) { const { path, recursive, preload, timeout, signal } = query @@ -253,26 +185,20 @@ exports.CoreService = class CoreService { return encodeLsResult(entries) } } -// @returns {string|ArrayBufferView|ArrayBuffer|Blob|AsyncIterable|AsyncIterable|AsyncIterable|AsyncIterable|AsyncIterable} /** - * @param {MultiFileInput} input - * @returns {AsyncIterable} + * @param {EncodedAddAllInput} input + * @returns {ImportSource} */ const decodeAddAllInput = input => decodeIterable(input, decodeFileInput) /** - * @param {SingleFileInput} input - * @returns {string|ArrayBufferView|ArrayBuffer|Blob|FileObject} + * @param {*} input */ const decodeAddInput = input => matchInput( input, - /** - * @param {*} data - * @returns {*} - */ data => { if (data.type === 'RemoteIterable') { return { content: decodeIterable(data, decodeFileInput) } @@ -283,8 +209,9 @@ const decodeAddInput = input => ) /** - * @param {ArrayBufferView|ArrayBuffer|string|Blob|FileInput} input - * @returns {string|ArrayBuffer|ArrayBufferView|Blob|FileObject} + * + * @param {*} input + * @returns */ const decodeFileInput = input => matchInput(input, file => ({ @@ -293,17 +220,16 @@ const decodeFileInput = input => })) /** - * @param {FileContent} content - * @returns {DecodedFileContent} + * @param {EncodedFileContent} content */ const decodeFileContent = content => matchInput(content, input => decodeIterable(input, identity)) /** - * @template I,O - * @param {string|ArrayBuffer|ArrayBufferView|Blob|I} input - * @param {function(I):O} decode - * @returns {string|ArrayBuffer|ArrayBufferView|Blob|O} + * @template I, O + * @param {I} input + * @param {(input: any) => O} decode + * @returns {I | O} */ const matchInput = (input, decode) => { if ( @@ -319,8 +245,7 @@ const matchInput = (input, decode) => { } /** - * @param {AsyncIterable} out - * @returns {AddAllResult} + * @param {AsyncIterable} out */ const encodeAddAllResult = out => { /** @type {Transferable[]} */ @@ -332,8 +257,7 @@ const encodeAddAllResult = out => { } /** - * @param {FileOutput} out - * @returns {AddResult} + * @param {AddResult} out */ const encodeAddResult = out => { /** @type {Transferable[]} */ @@ -345,9 +269,7 @@ const encodeAddResult = out => { } /** - * * @param {AsyncIterable} content - * @returns {CatResult} */ const encodeCatResult = content => { /** @type {Transferable[]} */ @@ -356,9 +278,7 @@ const encodeCatResult = content => { } /** - * - * @param {AsyncIterable} entries - * @returns {LsResult} + * @param {AsyncIterable} entries */ const encodeLsResult = entries => { /** @type {Transferable[]} */ @@ -367,9 +287,7 @@ const encodeLsResult = entries => { } /** - * - * @param {LsEntry} entry - * @returns {EncodedLsEntry} + * @param {IPFSEntry} entry */ const encodeLsEntry = ({ depth, name, path, size, cid, type, mode, mtime }) => ({ cid: encodeCID(cid), @@ -395,11 +313,9 @@ const moveBuffer = (buffer, transfer) => { } /** - * - * @param {FileOutput} file + * @param {AddResult} file * @param {Transferable[]} _transfer */ - const encodeFileOutput = (file, _transfer) => ({ ...file, cid: encodeCID(file.cid) diff --git a/packages/ipfs-message-port-server/src/dag.js b/packages/ipfs-message-port-server/src/dag.js index 386af65b26..98aadb1f25 100644 --- a/packages/ipfs-message-port-server/src/dag.js +++ b/packages/ipfs-message-port-server/src/dag.js @@ -5,16 +5,11 @@ const { decodeNode, encodeNode } = require('ipfs-message-port-protocol/src/dag') const collect = require('it-all') /** - * @typedef {import('./ipfs').IPFS} IPFS - * @typedef {import('ipfs-message-port-protocol/src/cid').CID} CID + * @typedef {import('ipfs-core-types').IPFS} IPFS + * @typedef {import('cids')} CID * @typedef {import('ipfs-message-port-protocol/src/cid').EncodedCID} EncodedCID - * @typedef {import('ipfs-message-port-protocol/src/dag').DAGNode} DAGNode * @typedef {import('ipfs-message-port-protocol/src/dag').EncodedDAGNode} EncodedDAGNode - * - * - * @typedef {Object} DAGEntry - * @property {DAGNode} value - * @property {string} remainderPath + * @typedef {import('ipfs-core-types/src/dag').PutOptions} PutOptions */ exports.DAGService = class DAGService { @@ -28,14 +23,9 @@ exports.DAGService = class DAGService { /** * @typedef {Object} PutDag * @property {EncodedDAGNode} dagNode - * @property {string} [hashAlg] - * @property {EncodedCID|void} [cid] - * @property {boolean} [pin] - * @property {boolean} [preload] - * @property {number} [timeout] - * @property {AbortSignal} [signal] + * @property {EncodedCID} [encodedCid] * - * @param {PutDag} query + * @param {PutOptions & PutDag} query * @returns {Promise} */ async put (query) { @@ -43,15 +33,15 @@ exports.DAGService = class DAGService { const cid = await this.ipfs.dag.put(dagNode, { ...query, - cid: query.cid ? decodeCID(query.cid) : undefined + cid: query.encodedCid ? decodeCID(query.encodedCid) : undefined }) return encodeCID(cid) } /** - * @typedef {Object} GetResult + * @typedef {Object} EncodedGetResult * @property {Transferable[]} transfer - * @property {string} remainderPath + * @property {string} [remainderPath] * @property {EncodedDAGNode} value * * @typedef {Object} GetDAG @@ -62,7 +52,7 @@ exports.DAGService = class DAGService { * @property {AbortSignal} [signal] * * @param {GetDAG} query - * @returns {Promise} + * @returns {Promise} */ async get (query) { const { cid, path, localResolve, timeout, signal } = query @@ -88,12 +78,12 @@ exports.DAGService = class DAGService { * @property {number} [timeout] * @property {AbortSignal} [signal] * - * @typedef {Object} ResolveResult + * @typedef {Object} EncodedResolveResult * @property {EncodedCID} cid - * @property {string|void} remainderPath + * @property {string} [remainderPath] * * @param {ResolveQuery} query - * @returns {Promise} + * @returns {Promise} */ async resolve (query) { const { cid, remainderPath } = @@ -141,8 +131,3 @@ const decodePathOrCID = (input) => { return decodeCID(input) } } - -/** - * @param {EncodedDAGNode} value - * @returns {DAGNode} - */ diff --git a/packages/ipfs-message-port-server/src/files.js b/packages/ipfs-message-port-server/src/files.js index f1084dcd5b..cbc715dd81 100644 --- a/packages/ipfs-message-port-server/src/files.js +++ b/packages/ipfs-message-port-server/src/files.js @@ -5,13 +5,9 @@ const { encodeCID } = require('ipfs-message-port-protocol/src/cid') /** - * @typedef {import('ipfs-message-port-protocol/src/dag').EncodedCID} EncodedCID - */ -/** - * @typedef {import('ipfs-message-port-protocol/src/data').HashAlg} HashAlg - * @typedef {import('ipfs-message-port-protocol/src/data').Mode} Mode - * @typedef {import('./ipfs').IPFS} IPFS - * @typedef {Stat} EncodedStat + * @typedef {import('ipfs-core-types').IPFS} IPFS + * @typedef {import('ipfs-core-types/src/files').StatOptions} StatOptions + * @typedef {import('ipfs-message-port-protocol/src/files').EncodedStat} EncodedStat */ exports.FilesService = class FilesService { @@ -26,28 +22,8 @@ exports.FilesService = class FilesService { /** * @typedef {Object} StatQuery * @property {string} path - * @property {boolean} [hash=false] - * @property {boolean} [size=false] - * @property {boolean} [withLocal=false] - * @property {number} [timeout] - * @property {AbortSignal} [signal] - * - * @typedef {Object} Stat - * @property {EncodedCID} cid - * @property {number} size - * @property {number} cumulativeSize - * @property {'file'|'directory'} type - * @property {number} blocks - * @property {boolean} withLocality - * @property {boolean} local - * @property {number} sizeLocal - * - * @typedef {Object} StatResult - * @property {Stat} stat - * @property {Transferable[]} transfer * - * @param {StatQuery} input - * @returns {Promise} + * @param {StatOptions & StatQuery} input */ async stat (input) { const stat = await this.ipfs.files.stat(input.path, input) diff --git a/packages/ipfs-message-port-server/src/ipfs.ts b/packages/ipfs-message-port-server/src/ipfs.ts deleted file mode 100644 index 197e47b4ea..0000000000 --- a/packages/ipfs-message-port-server/src/ipfs.ts +++ /dev/null @@ -1,241 +0,0 @@ -import { DAGNode } from 'ipfs-message-port-protocol/src/dag' -import CID from 'cids' -import { - FileType, - UnixFSTime, - HashAlg, - Time, - CIDVersion -} from 'ipfs-message-port-protocol/src/data' -import { ReadStream } from 'fs' -import Block from 'ipld-block' - -type Mode = string | number -export interface IPFS extends Core { - dag: DAG - files: Files - block: BlockService -} - -export interface IPFSFactory { - create: () => Promise -} - -export interface AbortOptions { - timeout?: number - signal?: AbortSignal -} - -export interface PutOptions extends AbortOptions { - format?: string | undefined - hashAlg?: string | undefined - cid?: CID | undefined - preload?: boolean - pin?: boolean -} - -export interface GetOptions extends AbortOptions { - path?: string - localResolve?: boolean -} - -export interface ResolveOptions extends AbortOptions { - path?: string -} - -export interface TreeOptions extends AbortOptions { - path?: string - recursive?: boolean -} - -export interface DAG { - put: (dagNode: DAGNode, options: PutOptions) => Promise - get: (cid: CID, options: GetOptions) => Promise<{ value: DAGNode, remainderPath: string }> - resolve: (pathOrCID: string | CID, options: ResolveOptions) => Promise<{ cid: CID, remainderPath: string }> - tree: (cid: CID, options: TreeOptions) => AsyncIterable -} - -export interface Core { - addAll: (inputs: AddAllInput, options: AddOptions) => AsyncIterable - add: (input: AddInput, options: AddOptions) => Promise - cat: (ipfsPath: CID | string, options: CatOptions) => AsyncIterable - - ls: (ipfsPath: CID | string, options: CoreLsOptions) => AsyncIterable -} - -export interface AddOptions extends AbortOptions { - chunker?: string - cidVersion?: number - enableShardingExperiment?: boolean - hashAlg?: HashAlg - onlyHash?: boolean - pin?: boolean - progress?: (progress: number) => void - rawLeaves?: boolean - shardSplitThreshold?: number - trickle?: boolean - wrapWithDirectory?: boolean -} - -export interface FileInput { - path?: string - content?: FileContent - mode?: string | number | undefined - mtime?: Time -} - -export interface FileOutput { - path: string - cid: CID - mode: number - mtime: { secs: number, nsecs: number } - size: number -} - -export interface CatOptions extends AbortOptions { - offset?: number - length?: number -} - -interface CoreLsOptions extends AbortOptions { - preload?: boolean - recursive?: boolean -} - -export interface Files { - chmod: (path: string | CID, mode: Mode, options?: ChmodOptions) => Promise - - write: ( - path: string, - content: WriteContent, - options?: WriteOptions - ) => Promise - - ls: (path?: string, opitons?: LsOptions) => AsyncIterable - - stat: (path: string, options?: StatOptions) => Promise -} - -export interface ChmodOptions extends AbortOptions { - recursive?: boolean - flush?: boolean - hashAlg?: string - cidVersion?: number -} - -interface LsOptions extends AbortOptions { - sort?: boolean -} - -export interface LsEntry { - name: string - path: string - type: FileType - size: number - depth: number - cid: CID - mode: Mode - mtime?: UnixFSTime -} - -export interface StatOptions extends AbortOptions { - hash?: boolean - size?: boolean - withLocal?: boolean -} - -export interface Stat { - cid: CID - size: number - cumulativeSize: number - type: 'file' | 'directory' - blocks: number - withLocality: boolean - local: boolean - sizeLocal: number -} - -export type WriteContent = - | string - | ArrayBufferView - | ArrayBuffer - | Blob - | AsyncIterable - -export type AddInput = - | Blob - | string - | ArrayBufferView - | ArrayBuffer - | FileInput - | ReadStream - -export type AddAllInput = - | Iterable - | AsyncIterable - -export interface FileObject { - path?: string - content?: FileContent - mode?: Mode - mtime?: Time -} - -export type FileContent = - | string - | ArrayBufferView - | ArrayBuffer - | Blob - | Iterable - | AsyncIterable - -export interface WriteOptions extends AbortOptions { - offset?: number - length?: number - create?: boolean - parents?: boolean - truncate?: boolean - rawLeaves?: boolean - mode?: Mode - mtime?: Time - flush?: boolean - hashAlg?: HashAlg - cidVersion?: CIDVersion -} - -export interface WriteResult { - cid: CID - size: number -} - -export interface BlockService { - get: (cid: CID, options?: GetBlockOptions) => Promise - put: ((block: Uint8Array | Block, options?: PutBufferOptions) => Promise) & ((buffer: Uint8Array, options?: PutBufferOptions) => Promise) - rm: ( - cid: CID | CID[], - options?: RmBlockOptions - ) => AsyncIterable<{ cid: CID, error?: Error }> - stat: ( - cid: CID, - options?: StatBlockOptions - ) => Promise<{ cid: CID, size: number }> -} - -export interface GetBlockOptions extends AbortOptions { } // eslint-disable-line @typescript-eslint/no-empty-interface -export interface PutBlockOptions extends AbortOptions { - format?: string - mhtype?: string - mhlen?: number - version?: number - pin?: boolean -} -export interface PutBufferOptions extends PutBlockOptions { - cid?: CID | undefined -} - -export interface RmBlockOptions extends AbortOptions { - force?: boolean - quiet?: boolean -} - -export interface StatBlockOptions extends AbortOptions { } // eslint-disable-line @typescript-eslint/no-empty-interface diff --git a/packages/ipfs-message-port-server/src/service.js b/packages/ipfs-message-port-server/src/service.js index 5c48f3836b..e56fb4038b 100644 --- a/packages/ipfs-message-port-server/src/service.js +++ b/packages/ipfs-message-port-server/src/service.js @@ -8,12 +8,11 @@ const { FilesService } = require('./files') const { BlockService } = require('./block') /** - * @typedef {import('./ipfs').IPFS} IPFS + * @typedef {import('ipfs-core-types').IPFS} IPFS */ exports.IPFSService = class IPFSService { /** - * * @param {IPFS} ipfs */ constructor (ipfs) { diff --git a/packages/ipfs-message-port-server/tsconfig.json b/packages/ipfs-message-port-server/tsconfig.json index a7d52a397b..58366df84c 100644 --- a/packages/ipfs-message-port-server/tsconfig.json +++ b/packages/ipfs-message-port-server/tsconfig.json @@ -1,15 +1,17 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "src", - "package.json" + "src" ], "references": [ { "path": "../ipfs-message-port-protocol" + }, + { + "path": "../ipfs-core-types" } ] } diff --git a/packages/ipfs/.aegir.js b/packages/ipfs/.aegir.js index b6f95eaa21..03566736d0 100644 --- a/packages/ipfs/.aegir.js +++ b/packages/ipfs/.aegir.js @@ -118,7 +118,7 @@ module.exports = { } }, build: { - bundlesizeMax: '660kB', + bundlesizeMax: '614kB', config: esbuild }, dependencyCheck: { diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index d45df36021..41fd4f1932 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -11,9 +11,11 @@ "leadMaintainer": "Alex Potsides ", "files": [ "src", - "dist" + "dist", + "!dist/*.tsbuildinfo" ], "main": "src/index.js", + "types": "dist/src/index.d.ts", "bin": { "jsipfs": "src/cli.js" }, @@ -22,7 +24,6 @@ "url": "git+https://github.com/ipfs/js-ipfs.git" }, "scripts": { - "prepare": "npm run build", "build": "aegir build", "lint": "aegir lint", "test": "echo 'Only interface tests live here'", @@ -34,28 +35,30 @@ "test:external": "aegir test-dependant", "coverage": "nyc --reporter=text --reporter=lcov npm run test:interface:core -- -t node", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check" + "dep-check": "aegir dep-check -i ipfs-core-types -i @types/*" }, "dependencies": { "debug": "^4.1.1", "ipfs-cli": "^0.4.4", "ipfs-core": "^0.5.4", - "ipfs-repo": "^8.0.0", "semver": "^7.3.2", "update-notifier": "^5.0.0" }, "devDependencies": { - "aegir": "^31.0.0", + "@types/semver": "^7.3.4", + "@types/update-notifier": "^5.0.0", + "aegir": "^32.1.0", "assert": "^2.0.0", "cross-env": "^7.0.0", "electron-webrtc": "^0.3.0", "go-ipfs": "0.8.0", "interface-ipfs-core": "^0.144.2", "ipfs-client": "^0.3.4", + "ipfs-core-types": "^0.3.1", "ipfs-http-client": "^49.0.4", - "ipfs-interop": "^4.0.3", - "ipfs-utils": "^6.0.1", - "ipfsd-ctl": "^7.2.0", + "ipfs-interop": "^5.0.0", + "ipfs-utils": "^6.0.4", + "ipfsd-ctl": "^8.0.0", "iso-url": "^1.0.0", "libp2p-webrtc-star": "^0.21.0", "merge-options": "^3.0.4", @@ -64,14 +67,6 @@ "url": "^0.11.0", "wrtc": "^0.4.6" }, - "typesVersions": { - "*": { - "*": [ - "dist/*", - "dist/*/index" - ] - } - }, "browser": { "./src/cli.js": false, "go-ipfs": false diff --git a/packages/ipfs/src/cli.js b/packages/ipfs/src/cli.js index abc94587c9..5aa5bfe30e 100755 --- a/packages/ipfs/src/cli.js +++ b/packages/ipfs/src/cli.js @@ -3,17 +3,31 @@ /* eslint-disable no-console */ 'use strict' -// Handle any uncaught errors -process.once('uncaughtException', (err, origin) => { +/** + * Handle any uncaught errors + * + * @param {any} err + * @param {string} [origin] + */ +const onUncaughtException = (err, origin) => { if (!origin || origin === 'uncaughtException') { console.error(err) process.exit(1) } -}) -process.once('unhandledRejection', (err) => { +} + +/** + * Handle any uncaught errors + * + * @param {any} err + */ +const onUnhandledRejection = (err) => { console.error(err) process.exit(1) -}) +} + +process.once('uncaughtException', onUncaughtException) +process.once('unhandledRejection', onUnhandledRejection) const semver = require('semver') const pkg = require('../package.json') @@ -34,19 +48,24 @@ if (!pkg.version.includes('-rc')) { updateNotifier({ pkg, updateCheckInterval: oneWeek }).notify() } -const { InvalidRepoVersionError } = require('ipfs-repo/src/errors/index') const { NotEnabledError } = require('ipfs-core/src/errors') +// @ts-ignore - TODO: refactor this so it does not require deep requires const { print, getIpfs, getRepoPath } = require('ipfs-cli/src/utils') const debug = require('debug')('ipfs:cli') const cli = require('ipfs-cli') +/** + * @param {string[]} argv + */ async function main (argv) { let exitCode = 0 let ctx = { print, getStdin: () => process.stdin, repoPath: getRepoPath(), - cleanup: () => {} + cleanup: () => {}, + isDaemon: false, + ipfs: undefined } const command = argv.slice(2) @@ -73,7 +92,8 @@ async function main (argv) { print(data) } } catch (err) { - if (err.code === InvalidRepoVersionError.code) { + // TODO: export errors from ipfs-repo to use .code constants + if (err.code === 'ERR_INVALID_REPO_VERSION') { err.message = 'Incompatible repo version. Migration needed. Pass --migrate for automatic migration' } diff --git a/packages/ipfs/tsconfig.json b/packages/ipfs/tsconfig.json index 76a587cd96..6554caa886 100644 --- a/packages/ipfs/tsconfig.json +++ b/packages/ipfs/tsconfig.json @@ -1,11 +1,11 @@ { - "extends": "../../tsconfig.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ - "package.json", - "./src" + "src", + "package.json" ], "references": [ { @@ -13,6 +13,9 @@ }, { "path": "../ipfs-core" + }, + { + "path": "../ipfs-core-types" } ] } diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 2c7ec5306b..0000000000 --- a/tsconfig.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "forceConsistentCasingInFileNames": true, - "noImplicitReturns": false, - "noImplicitAny": false, - "noImplicitThis": true, - "noFallthroughCasesInSwitch": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "strictFunctionTypes": true, - "strictNullChecks": true, - "strictPropertyInitialization": true, - "strictBindCallApply": true, - "strict": true, - "alwaysStrict": true, - "esModuleInterop": true, - "target": "ES2018", - "moduleResolution": "node", - "declaration": true, - "declarationMap": true, - "skipLibCheck": true, - "stripInternal": true, - "resolveJsonModule": true, - "incremental": true, - "isolatedModules": true, - "baseUrl": ".", - "paths": { - "interface-ipfs-core/*": [ - "interface-ipfs-core/*" - ], - "ipfs/*": [ - "ipfs/*" - ], - "ipfs-cli/*": [ - "ipfs-cli/*" - ], - "ipfs-client/*": [ - "ipfs-client/*" - ], - "ipfs-core/*": [ - "ipfs-core/*" - ], - "ipfs-core-utils/*": [ - "ipfs-core-utils/*" - ], - "ipfs-daemon/*": [ - "ipfs-daemon/*" - ], - "ipfs-grpc-client/*": [ - "ipfs-grpc-client/*" - ], - "ipfs-grpc-server/*": [ - "ipfs-grpc-server/*" - ], - "ipfs-http-client/*": [ - "ipfs-http-client/*" - ], - "ipfs-http-gateway/*": [ - "ipfs-http-gateway/*" - ], - "ipfs-http-server/*": [ - "ipfs-http-server/*" - ], - "ipfs-message-port-protocol/*": [ - "ipfs-message-port-protocol/*" - ], - "ipfs-message-port-server/*": [ - "ipfs-message-port-server/*" - ] - }, - "composite": true, - "emitDeclarationOnly": true - }, - "exclude": [ - "dist", - "packages/*/dist", - "packages/*/test", - "packages/*/node_modules", - "node_modules" - ], - "compileOnSave": false -} From 087fd1eb402d1b933730e09c1d0cfb21067e9992 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 1 Apr 2021 10:43:57 +0100 Subject: [PATCH 04/34] chore: update node version in docker build (#3603) The optional chaining operator requires a supported node. Also updates the engines field where defined to reflect this. BREAKING CHANGE: Minimum supported node version is 14 --- Dockerfile.latest | 2 +- Dockerfile.next | 2 +- packages/ipfs-http-client/package.json | 2 +- packages/ipfs-message-port-client/package.json | 2 +- packages/ipfs-message-port-protocol/package.json | 2 +- packages/ipfs-message-port-server/package.json | 2 +- packages/ipfs/package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Dockerfile.latest b/Dockerfile.latest index 267e8c09a8..aceceb7983 100644 --- a/Dockerfile.latest +++ b/Dockerfile.latest @@ -1,4 +1,4 @@ -FROM mhart/alpine-node:12 +FROM mhart/alpine-node:15 ENV IPFS_VERSION=latest ENV IPFS_MONITORING=1 diff --git a/Dockerfile.next b/Dockerfile.next index f0cabc9b64..3e2ad99d48 100644 --- a/Dockerfile.next +++ b/Dockerfile.next @@ -1,4 +1,4 @@ -FROM mhart/alpine-node:12 +FROM mhart/alpine-node:15 ENV IPFS_VERSION=next ENV IPFS_MONITORING=1 diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 8ac4a8517c..0f89d79cbb 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -84,7 +84,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=10.3.0", + "node": ">=14.0.0", "npm": ">=3.0.0" }, "contributors": [ diff --git a/packages/ipfs-message-port-client/package.json b/packages/ipfs-message-port-client/package.json index f272f56634..fca157b1c3 100644 --- a/packages/ipfs-message-port-client/package.json +++ b/packages/ipfs-message-port-client/package.json @@ -47,7 +47,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=10.3.0", + "node": ">=14.0.0", "npm": ">=3.0.0" } } diff --git a/packages/ipfs-message-port-protocol/package.json b/packages/ipfs-message-port-protocol/package.json index 0bdd48a860..97bfb9425e 100644 --- a/packages/ipfs-message-port-protocol/package.json +++ b/packages/ipfs-message-port-protocol/package.json @@ -56,7 +56,7 @@ "uint8arrays": "^2.1.3" }, "engines": { - "node": ">=10.3.0", + "node": ">=14.0.0", "npm": ">=3.0.0" } } diff --git a/packages/ipfs-message-port-server/package.json b/packages/ipfs-message-port-server/package.json index 896fe6ad3b..c25693a3aa 100644 --- a/packages/ipfs-message-port-server/package.json +++ b/packages/ipfs-message-port-server/package.json @@ -48,7 +48,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=10.3.0", + "node": ">=14.0.0", "npm": ">=3.0.0" } } diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index 41fd4f1932..b34c94a801 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -72,7 +72,7 @@ "go-ipfs": false }, "engines": { - "node": ">=10.0.0", + "node": ">=14.0.0", "npm": ">=6.0.0" }, "contributors": [ From 6870873f0696bb5d8d91fce4a4ef1f7420443993 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 1 Apr 2021 13:34:01 +0100 Subject: [PATCH 05/34] chore: update it-to-buffer dep (#3606) Updates dep to get version without Buffer dependency --- packages/ipfs-http-server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ipfs-http-server/package.json b/packages/ipfs-http-server/package.json index c17e930fd4..77e99bb607 100644 --- a/packages/ipfs-http-server/package.json +++ b/packages/ipfs-http-server/package.json @@ -75,7 +75,7 @@ "form-data": "^4.0.0", "ipfs-http-client": "^49.0.4", "iso-random-stream": "^1.1.1", - "it-to-buffer": "^1.0.2", + "it-to-buffer": "^2.0.0", "qs": "^6.9.4", "rimraf": "^3.0.2", "sinon": "^9.0.3", From 74bfce3c12f743b8c1cda4b2160b25802f9f27d6 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 7 Apr 2021 11:00:43 +0100 Subject: [PATCH 06/34] chore: fix types (#3608) Updates deps, fixes typos. Not sure why the compiler doesn't pick up things like this. --- examples/browser-create-react-app/package.json | 8 ++++---- examples/browser-http-client-upload-file/package.json | 6 +++--- examples/browser-http-client-upload-file/src/App.js | 4 ++-- examples/browser-ipns-publish/package.json | 4 ++-- examples/browser-parceljs/package.json | 2 +- examples/browser-video-streaming/index.html | 4 ++-- examples/browser-webpack/package.json | 4 ++-- examples/circuit-relaying/package.json | 6 +++--- examples/custom-ipld-formats/package.json | 2 +- examples/custom-libp2p/package.json | 2 +- examples/http-client-browser-pubsub/package.json | 2 +- examples/http-client-bundle-webpack/package.json | 8 ++++---- examples/http-client-name-api/package.json | 4 ++-- examples/ipfs-client-add-files/package.json | 4 ++-- examples/traverse-ipld-graphs/package.json | 4 ++-- packages/interface-ipfs-core/package.json | 4 ++-- packages/ipfs-cli/package.json | 4 ++-- packages/ipfs-core-types/package.json | 3 ++- packages/ipfs-core-types/src/block/index.d.ts | 2 +- packages/ipfs-core-types/src/config/index.d.ts | 2 +- packages/ipfs-core-types/src/dag/index.d.ts | 2 +- packages/ipfs-core-types/src/files/index.d.ts | 11 +++++------ packages/ipfs-core-types/src/index.d.ts | 2 -- packages/ipfs-core-types/src/pin/index.d.ts | 2 -- packages/ipfs-core-types/src/root.d.ts | 10 +++++----- packages/ipfs-core-types/src/stats/index.d.ts | 2 +- packages/ipfs-core-types/src/swarm/index.d.ts | 2 +- packages/ipfs-core-types/src/utils.d.ts | 1 - packages/ipfs-core-utils/package.json | 2 +- packages/ipfs-core/package.json | 4 ++-- packages/ipfs-grpc-client/package.json | 2 +- packages/ipfs-http-client/package.json | 7 ++++--- packages/ipfs-http-client/src/lib/core.js | 5 ++--- packages/ipfs-http-client/src/lib/ipld-formats.js | 4 ++-- packages/ipfs-http-client/src/types.d.ts | 5 +++-- packages/ipfs-http-gateway/package.json | 2 +- packages/ipfs-http-server/package.json | 2 +- packages/ipfs-message-port-protocol/package.json | 2 +- packages/ipfs-message-port-server/package.json | 2 +- 39 files changed, 72 insertions(+), 76 deletions(-) diff --git a/examples/browser-create-react-app/package.json b/examples/browser-create-react-app/package.json index 9d84c3f53c..39892d8be8 100644 --- a/examples/browser-create-react-app/package.json +++ b/examples/browser-create-react-app/package.json @@ -3,11 +3,11 @@ "version": "1.0.0", "private": true, "dependencies": { - "dot-prop": "^5.0.0", + "dot-prop": "^6.0.1", "ipfs": "^0.54.4", - "ipfs-css": "^0.13.1", - "react": "^16.8.6", - "react-dom": "^16.8.6", + "ipfs-css": "^1.3.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "react-scripts": "^4.0.3", "tachyons": "^4.11.1" }, diff --git a/examples/browser-http-client-upload-file/package.json b/examples/browser-http-client-upload-file/package.json index 72cbe42151..cab2f0dbc9 100644 --- a/examples/browser-http-client-upload-file/package.json +++ b/examples/browser-http-client-upload-file/package.json @@ -19,9 +19,9 @@ }, "devDependencies": { "ipfs": "^0.54.4", - "parcel": "next", - "react": "^16.8.6", - "react-dom": "^16.8.6", + "parcel": "2.0.0-beta.2", + "react": "^17.0.2", + "react-dom": "^17.0.2", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" }, diff --git a/examples/browser-http-client-upload-file/src/App.js b/examples/browser-http-client-upload-file/src/App.js index 19eba88d1b..852d963830 100644 --- a/examples/browser-http-client-upload-file/src/App.js +++ b/examples/browser-http-client-upload-file/src/App.js @@ -2,7 +2,7 @@ 'use strict' const React = require('react') -const { create: ipfsClient } = require('ipfs-http-client') +const { create: ipfsHttpClient } = require('ipfs-http-client') class App extends React.Component { constructor () { @@ -73,7 +73,7 @@ class App extends React.Component { async connect () { this.setState({ - ipfs: ipfsClient(this.multiaddr.current.value) + ipfs: ipfsHttpClient(this.multiaddr.current.value) }) } diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index 5e0e57bddd..2b60a4cbcd 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -25,11 +25,11 @@ "last 2 versions and not dead and > 2%" ], "devDependencies": { - "delay": "^4.4.0", + "delay": "^5.0.0", "execa": "^5.0.0", "ipfsd-ctl": "^8.0.0", "go-ipfs": "0.8.0", - "parcel": "next", + "parcel": "2.0.0-beta.2", "path": "^0.12.7", "test-ipfs-example": "^3.0.0" }, diff --git a/examples/browser-parceljs/package.json b/examples/browser-parceljs/package.json index 985c4a78e6..4eea6d5870 100644 --- a/examples/browser-parceljs/package.json +++ b/examples/browser-parceljs/package.json @@ -21,7 +21,7 @@ "ipfs": "^0.54.4" }, "devDependencies": { - "parcel": "next", + "parcel": "2.0.0-beta.2", "rimraf": "^3.0.2", "standard": "^16.0.3", "test-ipfs-example": "^3.0.0" diff --git a/examples/browser-video-streaming/index.html b/examples/browser-video-streaming/index.html index d79b5f5474..a86482a382 100644 --- a/examples/browser-video-streaming/index.html +++ b/examples/browser-video-streaming/index.html @@ -2,8 +2,8 @@ - - + + diff --git a/examples/browser-webpack/package.json b/examples/browser-webpack/package.json index 53f6ab8315..614bce7a05 100644 --- a/examples/browser-webpack/package.json +++ b/examples/browser-webpack/package.json @@ -18,8 +18,8 @@ "babel-loader": "^8.2.2", "copy-webpack-plugin": "^8.1.0", "node-polyfill-webpack-plugin": "^1.0.3", - "react": "^17.0.1", - "react-dom": "^17.0.1", + "react": "^17.0.2", + "react-dom": "^17.0.2", "react-hot-loader": "^4.12.21", "rimraf": "^3.0.2", "stream-browserify": "^3.0.0", diff --git a/examples/circuit-relaying/package.json b/examples/circuit-relaying/package.json index c9b10a0858..fcc17438f6 100644 --- a/examples/circuit-relaying/package.json +++ b/examples/circuit-relaying/package.json @@ -14,7 +14,7 @@ "author": "Dmitriy Ryajov ", "license": "MIT", "dependencies": { - "delay": "^4.4.0", + "delay": "^5.0.0", "ipfs": "^0.54.4", "ipfs-pubsub-room": "^2.0.1", "libp2p-websockets": "^0.15.1", @@ -22,9 +22,9 @@ }, "devDependencies": { "execa": "^5.0.0", - "ipfs-css": "^0.13.1", + "ipfs-css": "^1.3.0", "ipfs-http-client": "^49.0.4", - "parcel": "next", + "parcel": "2.0.0-beta.2", "rimraf": "^3.0.2", "tachyons": "^4.11.1", "test-ipfs-example": "^3.0.0" diff --git a/examples/custom-ipld-formats/package.json b/examples/custom-ipld-formats/package.json index b48f4901f7..7377db532f 100644 --- a/examples/custom-ipld-formats/package.json +++ b/examples/custom-ipld-formats/package.json @@ -11,7 +11,7 @@ "test-ipfs-example": "^3.0.0" }, "dependencies": { - "cids": "^1.1.5", + "cids": "^1.1.6", "ipfs-daemon": "^0.5.4", "ipfs-core": "^0.5.4", "ipfs-http-client": "^49.0.4", diff --git a/examples/custom-libp2p/package.json b/examples/custom-libp2p/package.json index ffbe35e0ce..1c0095b8e2 100644 --- a/examples/custom-libp2p/package.json +++ b/examples/custom-libp2p/package.json @@ -13,7 +13,7 @@ "ipfs": "^0.54.4", "libp2p": "^0.30.12", "libp2p-bootstrap": "^0.12.1", - "libp2p-kad-dht": "^0.20.1", + "libp2p-kad-dht": "^0.21.0", "libp2p-mdns": "^0.15.0", "libp2p-mplex": "^0.10.0", "libp2p-noise": "^2.0.1", diff --git a/examples/http-client-browser-pubsub/package.json b/examples/http-client-browser-pubsub/package.json index 9694895a34..fac560f9f6 100644 --- a/examples/http-client-browser-pubsub/package.json +++ b/examples/http-client-browser-pubsub/package.json @@ -22,7 +22,7 @@ "go-ipfs": "0.8.0", "ipfs": "^0.54.4", "ipfsd-ctl": "^8.0.0", - "parcel": "next", + "parcel": "2.0.0-beta.2", "test-ipfs-example": "^3.0.0" } } diff --git a/examples/http-client-bundle-webpack/package.json b/examples/http-client-bundle-webpack/package.json index e4d6451561..f27f147c7c 100644 --- a/examples/http-client-bundle-webpack/package.json +++ b/examples/http-client-bundle-webpack/package.json @@ -14,13 +14,13 @@ "keywords": [], "dependencies": { "ipfs-http-client": "^49.0.4", - "react": "^16.8.6", - "react-dom": "^16.8.6" + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "devDependencies": { - "@babel/core": "^7.13.10", + "@babel/core": "^7.13.14", "@babel/preset-env": "^7.13.12", - "@babel/preset-react": "^7.12.13", + "@babel/preset-react": "^7.13.13", "babel-loader": "^8.2.2", "copy-webpack-plugin": "^8.1.0", "execa": "^5.0.0", diff --git a/examples/http-client-name-api/package.json b/examples/http-client-name-api/package.json index a26751ec20..3d291d9e39 100644 --- a/examples/http-client-name-api/package.json +++ b/examples/http-client-name-api/package.json @@ -6,7 +6,7 @@ "private": true, "scripts": { "clean": "rimraf ./dist", - "build": "parcel build index.html --no-scope-hoist", + "build": "parcel build index.html", "start": "parcel index.html -p 8888", "test": "test-ipfs-example" }, @@ -19,7 +19,7 @@ "execa": "^5.0.0", "go-ipfs": "0.8.0", "ipfsd-ctl": "^8.0.0", - "parcel": "next", + "parcel": "2.0.0-beta.2", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" }, diff --git a/examples/ipfs-client-add-files/package.json b/examples/ipfs-client-add-files/package.json index 9fd2b9a0a7..1b5dbb2fe1 100644 --- a/examples/ipfs-client-add-files/package.json +++ b/examples/ipfs-client-add-files/package.json @@ -6,7 +6,7 @@ "private": true, "scripts": { "clean": "rimraf ./dist", - "build": "parcel build index.html --no-scope-hoist", + "build": "parcel build index.html", "start": "parcel index.html -p 8888", "test": "test-ipfs-example" }, @@ -17,7 +17,7 @@ "execa": "^5.0.0", "ipfs": "^0.54.4", "ipfsd-ctl": "^8.0.0", - "parcel": "next", + "parcel": "2.0.0-beta.2", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" }, diff --git a/examples/traverse-ipld-graphs/package.json b/examples/traverse-ipld-graphs/package.json index 0eeaac3e1f..95e068a8bd 100644 --- a/examples/traverse-ipld-graphs/package.json +++ b/examples/traverse-ipld-graphs/package.json @@ -13,10 +13,10 @@ "test-ipfs-example": "^3.0.0" }, "dependencies": { - "cids": "^1.1.5", + "cids": "^1.1.6", "ipfs": "^0.54.4", "ipld-block": "^0.11.0", - "ipld-dag-pb": "^0.22.0", + "ipld-dag-pb": "^0.22.1", "ipld-git": "^0.6.1", "ipld-ethereum": "^5.0.1", "multihashing-async": "^2.1.2" diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index b6234d657a..1493d99773 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -41,7 +41,7 @@ "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", - "cids": "^1.1.5", + "cids": "^1.1.6", "delay": "^5.0.0", "dirty-chai": "^2.0.1", "err-code": "^3.0.1", @@ -50,7 +50,7 @@ "ipfs-utils": "^6.0.4", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^0.18.0", - "ipld-dag-pb": "^0.22.0", + "ipld-dag-pb": "^0.22.1", "ipns": "^0.10.0", "is-ipfs": "^4.0.0", "iso-random-stream": "^1.1.1", diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index 50b2011f69..4359a3ecf0 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -32,7 +32,7 @@ "dependencies": { "byteman": "^1.3.5", "cid-tool": "^1.0.0", - "cids": "^1.1.5", + "cids": "^1.1.6", "debug": "^4.1.1", "err-code": "^3.0.1", "execa": "^5.0.0", @@ -45,7 +45,7 @@ "ipfs-repo": "^9.0.0", "ipfs-utils": "^6.0.4", "ipld-dag-cbor": "^0.18.0", - "ipld-dag-pb": "^0.22.0", + "ipld-dag-pb": "^0.22.1", "it-all": "^1.0.4", "it-concat": "^1.0.3", "it-first": "^1.0.4", diff --git a/packages/ipfs-core-types/package.json b/packages/ipfs-core-types/package.json index c3e1fe718d..a57b69dfac 100644 --- a/packages/ipfs-core-types/package.json +++ b/packages/ipfs-core-types/package.json @@ -28,7 +28,8 @@ ], "license": "(Apache-2.0 OR MIT)", "dependencies": { - "cids": "^1.1.5", + "cids": "^1.1.6", + "ipld": "^0.29.0", "multiaddr": "^8.0.0", "multibase": "^4.0.2" }, diff --git a/packages/ipfs-core-types/src/block/index.d.ts b/packages/ipfs-core-types/src/block/index.d.ts index 3035ac8910..65bc5e3401 100644 --- a/packages/ipfs-core-types/src/block/index.d.ts +++ b/packages/ipfs-core-types/src/block/index.d.ts @@ -1,4 +1,4 @@ -import { AbortOptions, PreloadOptions } from '../utils' +import { AbortOptions, PreloadOptions, IPFSPath } from '../utils' import CID, { CIDVersion } from 'cids' import Block from 'ipld-block' import { CodecName } from 'multicodec' diff --git a/packages/ipfs-core-types/src/config/index.d.ts b/packages/ipfs-core-types/src/config/index.d.ts index d5a543a9bf..a1de611046 100644 --- a/packages/ipfs-core-types/src/config/index.d.ts +++ b/packages/ipfs-core-types/src/config/index.d.ts @@ -107,7 +107,7 @@ export interface DEK { export interface PubsubConfig { PubSubRouter?: 'gossipsub' | 'floodsub' - Enabled?: booleam + Enabled?: boolean } export interface SwarmConfig { diff --git a/packages/ipfs-core-types/src/dag/index.d.ts b/packages/ipfs-core-types/src/dag/index.d.ts index 4214f55b6c..fa8bbdd961 100644 --- a/packages/ipfs-core-types/src/dag/index.d.ts +++ b/packages/ipfs-core-types/src/dag/index.d.ts @@ -1,5 +1,5 @@ import { AbortOptions, PreloadOptions, IPFSPath } from '../utils' -import CID from 'cids' +import CID, { CIDVersion } from 'cids' import { CodecName } from 'multicodec' import { HashName } from 'multihashes' diff --git a/packages/ipfs-core-types/src/files/index.d.ts b/packages/ipfs-core-types/src/files/index.d.ts index ac735b0d83..08ee4fa1d3 100644 --- a/packages/ipfs-core-types/src/files/index.d.ts +++ b/packages/ipfs-core-types/src/files/index.d.ts @@ -1,9 +1,8 @@ import { AbortOptions, IPFSPath } from '../utils' -import { ToMTime } from './files' import CID, { CIDVersion } from 'cids' import { CodecName } from 'multicodec' import { HashName } from 'multihashes' -import { Mtime } from 'ipfs-unixfs' +import { Mtime, MtimeLike } from 'ipfs-unixfs' import type { AddProgressFn } from '../root' export interface API { @@ -105,7 +104,7 @@ export interface API { * // Hello, World! * ``` */ - read: (ipfsPath: IPFSPath, options?: ResolveOptions & OptionExtension) => AsyncIterable + read: (ipfsPath: IPFSPath, options?: ReadOptions & OptionExtension) => AsyncIterable /** * Write to an MFS path @@ -260,7 +259,7 @@ export interface MkdirOptions extends MFSOptions, AbortOptions { /** * A Date object, an object with { secs, nsecs } properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of process.hrtime() */ - mtime?: ToMTime + mtime?: MtimeLike /** * The hash algorithm to use for any updated entries @@ -351,7 +350,7 @@ export interface TouchOptions extends MFSOptions, AbortOptions { /** * A Date object, an object with { secs, nsecs } properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of process.hrtime() */ - mtime?: ToMTime + mtime?: MtimeLike /** * The hash algorithm to use for any updated entries @@ -442,7 +441,7 @@ export interface WriteOptions extends MFSOptions, AbortOptions { /** * A Date object, an object with { secs, nsecs } properties where secs is the number of seconds since (positive) or before (negative) the Unix Epoch began and nsecs is the number of nanoseconds since the last full second, or the output of process.hrtime() */ - mtime?: ToMTime + mtime?: MtimeLike /** * The hash algorithm to use for any updated entries diff --git a/packages/ipfs-core-types/src/index.d.ts b/packages/ipfs-core-types/src/index.d.ts index edfa19e338..ea1e19a98a 100644 --- a/packages/ipfs-core-types/src/index.d.ts +++ b/packages/ipfs-core-types/src/index.d.ts @@ -45,8 +45,6 @@ export interface IPFS extends RootAPI { } export type { - IPFS, - AbortOptions, Await, AwaitIterable diff --git a/packages/ipfs-core-types/src/pin/index.d.ts b/packages/ipfs-core-types/src/pin/index.d.ts index 378996b305..8072d32371 100644 --- a/packages/ipfs-core-types/src/pin/index.d.ts +++ b/packages/ipfs-core-types/src/pin/index.d.ts @@ -113,8 +113,6 @@ export interface AddOptions extends AbortOptions { } export interface AddAllOptions extends AbortOptions { - lock?: boolean - /** * Whether to preload all blocks pinned during this operation */ diff --git a/packages/ipfs-core-types/src/root.d.ts b/packages/ipfs-core-types/src/root.d.ts index 6499817235..f6293a6374 100644 --- a/packages/ipfs-core-types/src/root.d.ts +++ b/packages/ipfs-core-types/src/root.d.ts @@ -1,8 +1,8 @@ -import type { AbortOptions, PreloadOptions, IPFSPath, ImportSource, ToEntry } from './utils' -import type CID, { CIDVersion } from 'cids' -import type { Mtime } from 'ipfs-unixfs' -import type Multiaddr from 'multiaddr' -import type { BaseName } from 'multibase' +import { AbortOptions, PreloadOptions, IPFSPath, ImportSource, ToEntry } from './utils' +import CID, { CIDVersion } from 'cids' +import { Mtime } from 'ipfs-unixfs' +import Multiaddr from 'multiaddr' +import { BaseName } from 'multibase' export interface API { /** diff --git a/packages/ipfs-core-types/src/stats/index.d.ts b/packages/ipfs-core-types/src/stats/index.d.ts index 49ce7154a4..828617c950 100644 --- a/packages/ipfs-core-types/src/stats/index.d.ts +++ b/packages/ipfs-core-types/src/stats/index.d.ts @@ -1,7 +1,7 @@ import type { AbortOptions } from '../utils' import { API as BitswapAPI } from '../bitswap' import { API as RepoAPI } from '../repo' -import type CID from 'cid' +import type CID from 'cids' export interface API { bitswap: BitswapAPI["stat"] diff --git a/packages/ipfs-core-types/src/swarm/index.d.ts b/packages/ipfs-core-types/src/swarm/index.d.ts index be0befcd0a..ea2508f2bd 100644 --- a/packages/ipfs-core-types/src/swarm/index.d.ts +++ b/packages/ipfs-core-types/src/swarm/index.d.ts @@ -1,7 +1,7 @@ import type { AbortOptions } from '../utils' import { API as BitswapAPI } from '../bitswap' import { API as RepoAPI } from '../repo' -import type CID from 'cid' +import type CID from 'cids' import type Multiaddr from 'multiaddr' export interface API { diff --git a/packages/ipfs-core-types/src/utils.d.ts b/packages/ipfs-core-types/src/utils.d.ts index 6b667bd8b6..67540e17bc 100644 --- a/packages/ipfs-core-types/src/utils.d.ts +++ b/packages/ipfs-core-types/src/utils.d.ts @@ -1,5 +1,4 @@ import CID from 'cids' -import { AwaitIterable } from './utils' import { Mtime, MtimeLike } from 'ipfs-unixfs' export type Entry|Blob> = diff --git a/packages/ipfs-core-utils/package.json b/packages/ipfs-core-utils/package.json index d0e9ce4147..7b7e89a6fe 100644 --- a/packages/ipfs-core-utils/package.json +++ b/packages/ipfs-core-utils/package.json @@ -44,7 +44,7 @@ "any-signal": "^2.1.2", "blob-to-it": "^1.0.1", "browser-readablestream-to-it": "^1.0.1", - "cids": "^1.1.5", + "cids": "^1.1.6", "err-code": "^3.0.1", "ipfs-core-types": "^0.3.1", "ipfs-unixfs": "^4.0.1", diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index a3e1acba42..8f26e64c8e 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -60,7 +60,7 @@ "abort-controller": "^3.0.0", "array-shuffle": "^2.0.0", "cborg": "^1.2.1", - "cids": "^1.1.5", + "cids": "^1.1.6", "dag-cbor-links": "^2.0.0", "datastore-core": "^3.0.0", "datastore-pubsub": "^0.5.0", @@ -82,7 +82,7 @@ "ipld": "^0.29.0", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^0.18.0", - "ipld-dag-pb": "^0.22.0", + "ipld-dag-pb": "^0.22.1", "ipld-raw": "^7.0.0", "ipns": "^0.10.0", "is-domain-name": "^1.0.1", diff --git a/packages/ipfs-grpc-client/package.json b/packages/ipfs-grpc-client/package.json index c227bbcda6..5017992e13 100644 --- a/packages/ipfs-grpc-client/package.json +++ b/packages/ipfs-grpc-client/package.json @@ -34,7 +34,7 @@ "dependencies": { "@improbable-eng/grpc-web": "^0.13.0", "change-case": "^4.1.1", - "cids": "^1.1.5", + "cids": "^1.1.6", "debug": "^4.1.1", "err-code": "^3.0.1", "ipfs-core-types": "^0.3.1", diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 0f89d79cbb..f00443eb66 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -41,21 +41,22 @@ "lint": "aegir lint", "coverage": "npx nyc -r html npm run test:node -- --bail", "clean": "rimraf ./dist", - "dep-check": "aegir dep-check -i ipfs-core -i rimraf -i ipfs-core-types -i abort-controller" + "dep-check": "aegir dep-check -i ipfs-core -i rimraf -i ipfs-core-types -i abort-controller -i ipld" }, "dependencies": { "abort-controller": "^3.0.0", "any-signal": "^2.1.2", - "cids": "^1.1.5", + "cids": "^1.1.6", "debug": "^4.1.1", "form-data": "^4.0.0", "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-unixfs": "^4.0.1", "ipfs-utils": "^6.0.4", + "ipld": "^0.29.0", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^0.18.0", - "ipld-dag-pb": "^0.22.0", + "ipld-dag-pb": "^0.22.1", "ipld-raw": "^7.0.0", "it-last": "^1.0.4", "it-map": "^1.0.4", diff --git a/packages/ipfs-http-client/src/lib/core.js b/packages/ipfs-http-client/src/lib/core.js index 744b143c72..2aafe8149c 100644 --- a/packages/ipfs-http-client/src/lib/core.js +++ b/packages/ipfs-http-client/src/lib/core.js @@ -15,8 +15,8 @@ const DEFAULT_HOST = isBrowser || isWebWorker ? location.hostname : 'localhost' const DEFAULT_PORT = isBrowser || isWebWorker ? location.port : '5001' /** - * @typedef {import('electron-fetch').Response} Response - * @typedef {import('ipfs-utils/dist/types/electron-fetch').Request} Request + * @typedef {import('ipfs-utils/dist/types/native-fetch').Response} Response + * @typedef {import('ipfs-utils/dist/types/native-fetch').Request} Request * @typedef {import('ipfs-utils/src/types').HTTPOptions} HTTPOptions * @typedef {import('../types').Options} Options */ @@ -188,7 +188,6 @@ class Client extends HTTP { /** * @param {string | Request} resource * @param {HTTPOptions} options - * @returns {Promise} */ this.fetch = (resource, options = {}) => { if (typeof resource === 'string' && !resource.startsWith('/')) { diff --git a/packages/ipfs-http-client/src/lib/ipld-formats.js b/packages/ipfs-http-client/src/lib/ipld-formats.js index 235fc9b7e1..ffcb753c18 100644 --- a/packages/ipfs-http-client/src/lib/ipld-formats.js +++ b/packages/ipfs-http-client/src/lib/ipld-formats.js @@ -45,8 +45,8 @@ module.exports = ({ formats = [], loadFormat = noop } = {}) => { * @param {import('multicodec').CodecName} codec - The code to load the format for */ const loadResolver = async (codec) => { - // @ts-ignore - codec is a string and not a CodecName - const number = multicodec.getNumber(codec) + const number = multicodec.getCodeFromName(codec) + // @ts-ignore wat const format = configuredFormats[number] || await loadFormat(codec) if (!format) { diff --git a/packages/ipfs-http-client/src/types.d.ts b/packages/ipfs-http-client/src/types.d.ts index 557d2637d7..037fa68b01 100644 --- a/packages/ipfs-http-client/src/types.d.ts +++ b/packages/ipfs-http-client/src/types.d.ts @@ -2,13 +2,14 @@ import { Format as IPLDFormat } from 'interface-ipld-format' import { LoadFormatFn } from 'ipld' import { Agent as HttpAgent } from 'http' import { Agent as HttpsAgent } from 'https' +import Multiaddr from 'multiaddr' export interface Options { host?: string port?: number protocol?: string headers?: Headers | Record - timeout?: number | sttring + timeout?: number | string apiPath?: string url?: URL|string|Multiaddr ipld?: IPLDOptions @@ -16,7 +17,7 @@ export interface Options { } export interface IPLDOptions { - formats?: IPLDFormat[] + formats?: IPLDFormat[] loadFormat?: LoadFormatFn } diff --git a/packages/ipfs-http-gateway/package.json b/packages/ipfs-http-gateway/package.json index 35ca193438..3f529e89ce 100644 --- a/packages/ipfs-http-gateway/package.json +++ b/packages/ipfs-http-gateway/package.json @@ -44,7 +44,7 @@ "@hapi/ammo": "^5.0.1", "@hapi/boom": "^9.1.0", "@hapi/hapi": "^20.0.0", - "cids": "^1.1.5", + "cids": "^1.1.6", "debug": "^4.1.1", "hapi-pino": "^8.3.0", "ipfs-core-types": "^0.3.1", diff --git a/packages/ipfs-http-server/package.json b/packages/ipfs-http-server/package.json index 77e99bb607..577bc560d0 100644 --- a/packages/ipfs-http-server/package.json +++ b/packages/ipfs-http-server/package.json @@ -34,7 +34,7 @@ "@hapi/content": "^5.0.2", "@hapi/hapi": "^20.0.0", "abort-controller": "^3.0.0", - "cids": "^1.1.5", + "cids": "^1.1.6", "debug": "^4.1.1", "dlv": "^1.1.3", "err-code": "^3.0.1", diff --git a/packages/ipfs-message-port-protocol/package.json b/packages/ipfs-message-port-protocol/package.json index 97bfb9425e..65bae65635 100644 --- a/packages/ipfs-message-port-protocol/package.json +++ b/packages/ipfs-message-port-protocol/package.json @@ -46,7 +46,7 @@ "dep-check": "aegir dep-check -i rimraf -i ipfs-core-types" }, "dependencies": { - "cids": "^1.1.5", + "cids": "^1.1.6", "ipfs-core-types": "^0.3.1", "ipld-block": "^0.11.0" }, diff --git a/packages/ipfs-message-port-server/package.json b/packages/ipfs-message-port-server/package.json index c25693a3aa..cf37bded06 100644 --- a/packages/ipfs-message-port-server/package.json +++ b/packages/ipfs-message-port-server/package.json @@ -44,7 +44,7 @@ }, "devDependencies": { "aegir": "^32.1.0", - "cids": "^1.1.5", + "cids": "^1.1.6", "rimraf": "^3.0.2" }, "engines": { From 63b11e5ac9d0b36d89ec23966e4523721878a7c0 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Mon, 19 Apr 2021 16:17:57 +0200 Subject: [PATCH 07/34] docs: ipfs.object.get typo fix (#3600) AFAIK it is `Data` and `Links`, not `data` --- docs/core-api/OBJECT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core-api/OBJECT.md b/docs/core-api/OBJECT.md index d99b4a9a6d..9382abcb33 100644 --- a/docs/core-api/OBJECT.md +++ b/docs/core-api/OBJECT.md @@ -165,7 +165,7 @@ An optional object which may have the following keys: const multihash = 'QmPb5f92FxKPYdT3QNBd1GKiL4tZUXUrzF4Hkpdr3Gf1gK' const node = await ipfs.object.get(multihash) -console.log(node.data) +console.log(node.Data) // Logs: // some data ``` From c79d3d626e56808bfd2aad9943b3f26e546a695c Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 27 Apr 2021 08:46:29 +0100 Subject: [PATCH 08/34] chore: update buffer deps (#3607) Updates deps to pull in Buffer@6.x.x Refs #3604 Fixes #3389 Co-authored-by: Vasco Santos --- docs/core-api/BITSWAP.md | 2 +- examples/browser-browserify/package.json | 2 +- examples/browser-exchange-files/package.json | 4 +- examples/browser-exchange-files/public/app.js | 1 + .../package.json | 2 +- examples/browser-ipns-publish/package.json | 5 +- examples/browser-parceljs/package.json | 2 +- examples/browser-readablestream/package.json | 2 +- examples/circuit-relaying/package.json | 2 +- examples/custom-ipfs-repo/package.json | 4 +- examples/custom-libp2p/index.js | 2 +- examples/custom-libp2p/package.json | 14 ++--- examples/custom-libp2p/test.js | 2 +- .../explore-ethereum-blockchain/package.json | 4 +- .../http-client-browser-pubsub/package.json | 3 +- .../http-client-bundle-webpack/package.json | 2 +- examples/http-client-name-api/package.json | 6 +- examples/ipfs-101/1.js | 3 +- examples/ipfs-101/test.js | 2 +- examples/ipfs-client-add-files/package.json | 6 +- examples/run-in-electron/package.json | 2 +- examples/traverse-ipld-graphs/package.json | 2 +- examples/types-use-ipfs-from-ts/package.json | 2 +- .../types-use-ipfs-from-typed-js/package.json | 2 +- packages/interface-ipfs-core/package.json | 20 +++--- packages/interface-ipfs-core/src/add-all.js | 7 --- packages/interface-ipfs-core/src/add.js | 7 --- .../interface-ipfs-core/src/bitswap/stat.js | 7 --- .../src/bitswap/transfer.js | 4 +- .../src/bitswap/wantlist-for-peer.js | 7 --- packages/interface-ipfs-core/src/block/put.js | 7 --- .../interface-ipfs-core/src/bootstrap/add.js | 9 +-- .../src/bootstrap/clear.js | 9 +-- .../interface-ipfs-core/src/bootstrap/list.js | 9 +-- .../src/bootstrap/reset.js | 9 +-- .../interface-ipfs-core/src/bootstrap/rm.js | 9 +-- .../interface-ipfs-core/src/config/get.js | 13 ---- .../src/config/profiles/apply.js | 7 --- .../src/config/profiles/list.js | 7 --- .../interface-ipfs-core/src/config/replace.js | 7 --- .../interface-ipfs-core/src/config/set.js | 7 --- packages/interface-ipfs-core/src/dag/put.js | 9 --- .../interface-ipfs-core/src/dht/provide.js | 9 --- packages/interface-ipfs-core/src/dht/put.js | 11 ---- .../interface-ipfs-core/src/files/chmod.js | 13 ---- packages/interface-ipfs-core/src/files/cp.js | 9 +-- .../interface-ipfs-core/src/files/flush.js | 7 --- packages/interface-ipfs-core/src/files/ls.js | 10 +-- .../interface-ipfs-core/src/files/mkdir.js | 7 --- packages/interface-ipfs-core/src/files/mv.js | 17 +----- .../interface-ipfs-core/src/files/read.js | 16 +---- packages/interface-ipfs-core/src/files/rm.js | 16 +---- .../interface-ipfs-core/src/files/stat.js | 12 +--- .../interface-ipfs-core/src/files/touch.js | 7 --- .../interface-ipfs-core/src/files/write.js | 12 +--- packages/interface-ipfs-core/src/key/gen.js | 9 --- .../interface-ipfs-core/src/key/import.js | 12 ---- packages/interface-ipfs-core/src/key/list.js | 7 --- .../interface-ipfs-core/src/key/rename.js | 11 ---- packages/interface-ipfs-core/src/key/rm.js | 10 --- packages/interface-ipfs-core/src/ls.js | 5 +- .../src/miscellaneous/dns.js | 7 --- .../src/miscellaneous/id.js | 9 +-- .../src/miscellaneous/resolve.js | 7 --- .../src/miscellaneous/stop.js | 7 --- .../src/miscellaneous/version.js | 7 --- .../src/name-pubsub/cancel.js | 7 --- .../src/name-pubsub/state.js | 7 --- .../src/name-pubsub/subs.js | 7 --- .../interface-ipfs-core/src/name/publish.js | 8 --- .../interface-ipfs-core/src/object/data.js | 8 --- .../interface-ipfs-core/src/object/get.js | 10 +-- .../interface-ipfs-core/src/object/links.js | 8 --- .../interface-ipfs-core/src/object/new.js | 7 --- .../src/object/patch/add-link.js | 8 --- .../src/object/patch/append-data.js | 8 --- .../src/object/patch/rm-link.js | 8 --- .../src/object/patch/set-data.js | 8 --- .../interface-ipfs-core/src/object/put.js | 7 --- .../interface-ipfs-core/src/object/stat.js | 8 --- .../interface-ipfs-core/src/pin/add-all.js | 8 --- packages/interface-ipfs-core/src/pin/add.js | 8 --- packages/interface-ipfs-core/src/pin/ls.js | 7 --- .../interface-ipfs-core/src/pin/remote/add.js | 9 --- .../interface-ipfs-core/src/pin/remote/ls.js | 8 --- .../src/pin/remote/rm-all.js | 8 --- .../interface-ipfs-core/src/pin/remote/rm.js | 8 --- .../interface-ipfs-core/src/pin/rm-all.js | 10 --- packages/interface-ipfs-core/src/pin/rm.js | 10 --- packages/interface-ipfs-core/src/ping/ping.js | 8 --- packages/interface-ipfs-core/src/pubsub/ls.js | 7 --- .../interface-ipfs-core/src/pubsub/peers.js | 7 --- .../interface-ipfs-core/src/pubsub/publish.js | 7 --- .../interface-ipfs-core/src/refs-local.js | 7 --- packages/interface-ipfs-core/src/repo/gc.js | 7 --- packages/interface-ipfs-core/src/repo/stat.js | 7 --- .../interface-ipfs-core/src/repo/version.js | 7 --- .../interface-ipfs-core/src/stats/bitswap.js | 7 --- packages/interface-ipfs-core/src/stats/bw.js | 7 --- .../interface-ipfs-core/src/stats/repo.js | 7 --- .../interface-ipfs-core/src/swarm/addrs.js | 9 +-- .../interface-ipfs-core/src/swarm/connect.js | 7 --- .../src/swarm/disconnect.js | 7 --- .../src/swarm/local-addrs.js | 7 --- .../interface-ipfs-core/src/swarm/peers.js | 26 ++++---- packages/ipfs-cli/package.json | 21 +++---- packages/ipfs-cli/src/commands/add.js | 1 + .../ipfs-cli/src/commands/bootstrap/add.js | 2 +- .../ipfs-cli/src/commands/bootstrap/rm.js | 2 +- .../ipfs-cli/src/commands/swarm/connect.js | 2 +- .../ipfs-cli/src/commands/swarm/disconnect.js | 2 +- packages/ipfs-cli/src/commands/swarm/peers.js | 4 +- packages/ipfs-cli/src/utils.js | 2 +- packages/ipfs-cli/test/bootstrap.js | 4 +- packages/ipfs-cli/test/swarm.js | 18 +++--- packages/ipfs-client/.aegir.js | 2 +- packages/ipfs-client/package.json | 2 +- packages/ipfs-client/src/index.js | 2 +- packages/ipfs-core-types/package.json | 4 +- .../ipfs-core-types/src/bitswap/index.d.ts | 2 +- .../ipfs-core-types/src/bootstrap/index.ts | 2 +- .../ipfs-core-types/src/config/index.d.ts | 34 ++++++++--- packages/ipfs-core-types/src/dht/index.d.ts | 2 +- .../ipfs-core-types/src/pin/remote/index.d.ts | 2 +- packages/ipfs-core-types/src/root.d.ts | 2 +- packages/ipfs-core-types/src/swarm/index.d.ts | 2 +- packages/ipfs-core-types/src/utils.d.ts | 54 ++++++++++++++++ packages/ipfs-core-utils/package.json | 10 +-- packages/ipfs-core-utils/src/to-url-string.js | 8 +-- packages/ipfs-core/.aegir.js | 2 +- packages/ipfs-core/package.json | 61 ++++++++++--------- .../ipfs-core/src/components/bitswap/stat.js | 3 +- .../src/components/bootstrap/clear.js | 2 +- .../src/components/bootstrap/list.js | 2 +- .../src/components/bootstrap/reset.js | 2 +- packages/ipfs-core/src/components/config.js | 49 +++++++-------- packages/ipfs-core/src/components/id.js | 8 +-- packages/ipfs-core/src/components/libp2p.js | 18 +++--- packages/ipfs-core/src/components/network.js | 6 +- .../ipfs-core/src/components/refs/local.js | 3 +- packages/ipfs-core/src/components/repo/gc.js | 3 +- packages/ipfs-core/src/components/storage.js | 6 +- packages/ipfs-core/src/index.js | 2 +- .../src/ipns/routing/pubsub-datastore.js | 2 + .../ipfs-core/src/runtime/libp2p-browser.js | 5 +- .../ipfs-core/src/runtime/libp2p-nodejs.js | 5 +- packages/ipfs-core/test/config.spec.js | 4 +- packages/ipfs-core/test/exports.spec.js | 2 +- packages/ipfs-core/test/libp2p.spec.js | 16 ++--- packages/ipfs-daemon/package.json | 14 ++--- packages/ipfs-daemon/src/index.js | 4 +- packages/ipfs-grpc-client/.aegir.js | 2 +- packages/ipfs-grpc-client/package.json | 10 +-- packages/ipfs-grpc-client/src/core-api/id.js | 4 +- packages/ipfs-grpc-client/src/types.d.ts | 2 +- packages/ipfs-grpc-server/package.json | 6 +- .../src/utils/web-socket-server.js | 10 +-- packages/ipfs-http-client/.aegir.js | 2 +- packages/ipfs-http-client/package.json | 16 ++--- .../ipfs-http-client/src/bootstrap/add.js | 2 +- .../ipfs-http-client/src/bootstrap/clear.js | 2 +- .../ipfs-http-client/src/bootstrap/list.js | 2 +- .../ipfs-http-client/src/bootstrap/reset.js | 2 +- packages/ipfs-http-client/src/bootstrap/rm.js | 2 +- .../ipfs-http-client/src/dht/find-peer.js | 4 +- .../ipfs-http-client/src/dht/find-provs.js | 4 +- packages/ipfs-http-client/src/dht/provide.js | 4 +- packages/ipfs-http-client/src/dht/put.js | 4 +- packages/ipfs-http-client/src/dht/query.js | 4 +- packages/ipfs-http-client/src/id.js | 4 +- packages/ipfs-http-client/src/index.js | 2 +- packages/ipfs-http-client/src/lib/core.js | 2 +- packages/ipfs-http-client/src/swarm/addrs.js | 4 +- .../ipfs-http-client/src/swarm/localAddrs.js | 4 +- packages/ipfs-http-client/src/swarm/peers.js | 4 +- packages/ipfs-http-client/src/types.d.ts | 2 +- .../ipfs-http-client/test/constructor.spec.js | 8 +-- .../ipfs-http-client/test/exports.spec.js | 2 +- packages/ipfs-http-gateway/package.json | 10 +-- packages/ipfs-http-gateway/src/index.js | 4 +- packages/ipfs-http-server/package.json | 23 ++++--- .../ipfs-http-server/src/api/resources/dht.js | 2 +- .../src/api/resources/files-regular.js | 5 +- packages/ipfs-http-server/src/index.js | 4 +- packages/ipfs-http-server/src/utils/joi.js | 4 +- .../src/utils/multipart-request-parser.js | 25 ++------ .../ipfs-http-server/test/inject/files.js | 2 +- .../ipfs-http-server/test/inject/pubsub.js | 2 +- packages/ipfs-message-port-client/.aegir.js | 2 +- .../ipfs-message-port-client/package.json | 4 +- .../ipfs-message-port-protocol/package.json | 2 +- packages/ipfs-message-port-server/.aegir.js | 2 +- .../ipfs-message-port-server/package.json | 2 +- packages/ipfs/.aegir.js | 2 +- packages/ipfs/package.json | 8 +-- packages/ipfs/test/interface-http-go.js | 58 +++++++++++++----- packages/ipfs/test/interface-http-js.js | 50 ++++++++++++++- 197 files changed, 513 insertions(+), 1005 deletions(-) diff --git a/docs/core-api/BITSWAP.md b/docs/core-api/BITSWAP.md index b882f55367..8c4eb0c62f 100644 --- a/docs/core-api/BITSWAP.md +++ b/docs/core-api/BITSWAP.md @@ -159,7 +159,7 @@ The returned object contains the following keys: - `provideBufLen` is an integer. - `wantlist` (array of [CID][cid]s) -- `peers` (array of peer IDs represented by CIDs) +- `peers` (array of peer IDs represented by strings) - `blocksReceived` is a [BigInt][1] - `dataReceived` is a [BigInt][1] - `blocksSent` is a [BigInt][1] diff --git a/examples/browser-browserify/package.json b/examples/browser-browserify/package.json index 5d2e005340..3260f36dd9 100644 --- a/examples/browser-browserify/package.json +++ b/examples/browser-browserify/package.json @@ -14,7 +14,7 @@ "keywords": [], "license": "MIT", "devDependencies": { - "browserify": "^16.2.3", + "browserify": "^17.0.0", "concat-stream": "^2.0.0", "execa": "^5.0.0", "http-server": "^0.12.3", diff --git a/examples/browser-exchange-files/package.json b/examples/browser-exchange-files/package.json index 0e55f015da..b880239522 100644 --- a/examples/browser-exchange-files/package.json +++ b/examples/browser-exchange-files/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "devDependencies": { - "browserify": "^16.2.3", + "browserify": "^17.0.0", "execa": "^5.0.0", "http-server": "^0.12.3", "ipfs-http-client": "^49.0.4", @@ -20,7 +20,7 @@ "dependencies": { "ipfs": "^0.54.4", "it-all": "^1.0.4", - "libp2p-websockets": "^0.15.1", + "libp2p-websockets": "^0.15.6", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" } diff --git a/examples/browser-exchange-files/public/app.js b/examples/browser-exchange-files/public/app.js index 5f42c7b309..5b20d82f84 100644 --- a/examples/browser-exchange-files/public/app.js +++ b/examples/browser-exchange-files/public/app.js @@ -41,6 +41,7 @@ let workspace = (location.hash || 'default-workspace').replace(/^#/, '') let fileSize = 0 +/** @type {import('ipfs').IPFS} */ let node let info diff --git a/examples/browser-http-client-upload-file/package.json b/examples/browser-http-client-upload-file/package.json index cab2f0dbc9..b0557692b5 100644 --- a/examples/browser-http-client-upload-file/package.json +++ b/examples/browser-http-client-upload-file/package.json @@ -4,7 +4,7 @@ "description": "Upload file to IPFS via browser using js-ipfs-http-client with Webpack", "private": true, "scripts": { - "clean": "rimraf ./dist", + "clean": "rimraf ./dist ./.cache ./.parcel-cache", "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html", "test": "test-ipfs-example" diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index 2b60a4cbcd..c111149010 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -5,6 +5,7 @@ "private": true, "main": "index.js", "scripts": { + "clean": "rimraf ./dist ./.cache ./.parcel-cache", "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html", "test": "test-ipfs-example" @@ -16,7 +17,7 @@ "ipfs": "^0.54.4", "ipfs-http-client": "^49.0.4", "ipfs-utils": "^6.0.4", - "ipns": "^0.10.0", + "ipns": "^0.11.0", "it-last": "^1.0.4", "p-retry": "^4.2.0", "uint8arrays": "^2.1.3" @@ -27,7 +28,7 @@ "devDependencies": { "delay": "^5.0.0", "execa": "^5.0.0", - "ipfsd-ctl": "^8.0.0", + "ipfsd-ctl": "^8.0.1", "go-ipfs": "0.8.0", "parcel": "2.0.0-beta.2", "path": "^0.12.7", diff --git a/examples/browser-parceljs/package.json b/examples/browser-parceljs/package.json index 4eea6d5870..6bfa873b6d 100644 --- a/examples/browser-parceljs/package.json +++ b/examples/browser-parceljs/package.json @@ -8,7 +8,7 @@ "last 2 versions and not dead and > 2%" ], "scripts": { - "clean": "rimraf ./dist", + "clean": "rimraf ./dist ./.cache ./.parcel-cache", "lint": "standard public/**/*.js", "start": "parcel public/index.html", "build": "parcel build public/index.html --no-scope-hoist", diff --git a/examples/browser-readablestream/package.json b/examples/browser-readablestream/package.json index 6a8b79a26a..e73d557fd2 100644 --- a/examples/browser-readablestream/package.json +++ b/examples/browser-readablestream/package.json @@ -23,7 +23,7 @@ }, "dependencies": { "ipfs": "^0.54.4", - "it-to-stream": "^0.1.2", + "it-to-stream": "^1.0.0", "videostream": "^3.2.0" } } diff --git a/examples/circuit-relaying/package.json b/examples/circuit-relaying/package.json index fcc17438f6..7305a63911 100644 --- a/examples/circuit-relaying/package.json +++ b/examples/circuit-relaying/package.json @@ -17,7 +17,7 @@ "delay": "^5.0.0", "ipfs": "^0.54.4", "ipfs-pubsub-room": "^2.0.1", - "libp2p-websockets": "^0.15.1", + "libp2p-websockets": "^0.15.6", "uint8arrays": "^2.1.3" }, "devDependencies": { diff --git a/examples/custom-ipfs-repo/package.json b/examples/custom-ipfs-repo/package.json index ad4dbb7251..6ddb416f46 100644 --- a/examples/custom-ipfs-repo/package.json +++ b/examples/custom-ipfs-repo/package.json @@ -10,9 +10,9 @@ }, "license": "MIT", "dependencies": { - "datastore-fs": "^2.0.0", + "datastore-fs": "4.0.0", "ipfs": "^0.54.4", - "ipfs-repo": "^9.0.0", + "ipfs-repo": "^9.1.1", "it-all": "^1.0.4" }, "devDependencies": { diff --git a/examples/custom-libp2p/index.js b/examples/custom-libp2p/index.js index 5ca0a0d1bf..aebc92bcbb 100644 --- a/examples/custom-libp2p/index.js +++ b/examples/custom-libp2p/index.js @@ -30,7 +30,7 @@ const libp2pBundle = (opts) => { // Build and return our libp2p node // n.b. for full configuration options, see https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md - return new Libp2p({ + return Libp2p.create({ peerId, addresses: { listen: ['/ip4/127.0.0.1/tcp/0'] diff --git a/examples/custom-libp2p/package.json b/examples/custom-libp2p/package.json index 1c0095b8e2..5b73f6c230 100644 --- a/examples/custom-libp2p/package.json +++ b/examples/custom-libp2p/package.json @@ -11,13 +11,13 @@ "license": "MIT", "dependencies": { "ipfs": "^0.54.4", - "libp2p": "^0.30.12", - "libp2p-bootstrap": "^0.12.1", - "libp2p-kad-dht": "^0.21.0", - "libp2p-mdns": "^0.15.0", - "libp2p-mplex": "^0.10.0", - "libp2p-noise": "^2.0.1", - "libp2p-tcp": "^0.15.1" + "libp2p": "^0.31.0-rc.6", + "libp2p-bootstrap": "^0.12.3", + "libp2p-kad-dht": "libp2p/js-libp2p-kad-dht#chore/update-deps-12-04-2021", + "libp2p-mdns": "^0.16.0", + "libp2p-mplex": "^0.10.2", + "libp2p-noise": "^3.0.0", + "libp2p-tcp": "^0.15.4" }, "devDependencies": { "execa": "^5.0.0", diff --git a/examples/custom-libp2p/test.js b/examples/custom-libp2p/test.js index fbed8f8cb5..3c8b099859 100644 --- a/examples/custom-libp2p/test.js +++ b/examples/custom-libp2p/test.js @@ -28,7 +28,7 @@ async function test () { console.info('Dialling', address) const peerId = await PeerId.create() - const libp2p = new Libp2p({ + const libp2p = await Libp2p.create({ peerId, addresses: { listen: ['/ip4/127.0.0.1/tcp/0'] diff --git a/examples/explore-ethereum-blockchain/package.json b/examples/explore-ethereum-blockchain/package.json index ece0624d83..38d5ec94d6 100644 --- a/examples/explore-ethereum-blockchain/package.json +++ b/examples/explore-ethereum-blockchain/package.json @@ -12,8 +12,8 @@ "devDependencies": { "ipfs": "^0.54.4", "ipfs-http-client": "^49.0.4", - "ipfsd-ctl": "^8.0.0", - "ipld-ethereum": "^5.0.1", + "ipfsd-ctl": "^8.0.1", + "ipld-ethereum": "^6.0.0", "test-ipfs-example": "^3.0.0" } } diff --git a/examples/http-client-browser-pubsub/package.json b/examples/http-client-browser-pubsub/package.json index fac560f9f6..b2f655a2d3 100644 --- a/examples/http-client-browser-pubsub/package.json +++ b/examples/http-client-browser-pubsub/package.json @@ -5,6 +5,7 @@ "private": true, "main": "dist/index.html", "scripts": { + "clean": "rimraf ./dist ./.cache ./.parcel-cache", "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html -p 8888", "test": "test-ipfs-example" @@ -21,7 +22,7 @@ "execa": "^5.0.0", "go-ipfs": "0.8.0", "ipfs": "^0.54.4", - "ipfsd-ctl": "^8.0.0", + "ipfsd-ctl": "^8.0.1", "parcel": "2.0.0-beta.2", "test-ipfs-example": "^3.0.0" } diff --git a/examples/http-client-bundle-webpack/package.json b/examples/http-client-bundle-webpack/package.json index f27f147c7c..3716a03482 100644 --- a/examples/http-client-bundle-webpack/package.json +++ b/examples/http-client-bundle-webpack/package.json @@ -25,7 +25,7 @@ "copy-webpack-plugin": "^8.1.0", "execa": "^5.0.0", "ipfs": "^0.54.4", - "ipfsd-ctl": "^8.0.0", + "ipfsd-ctl": "^8.0.1", "react-hot-loader": "^4.12.21", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0", diff --git a/examples/http-client-name-api/package.json b/examples/http-client-name-api/package.json index 3d291d9e39..ebe8d1ea3e 100644 --- a/examples/http-client-name-api/package.json +++ b/examples/http-client-name-api/package.json @@ -5,8 +5,8 @@ "main": "dist/index.html", "private": true, "scripts": { - "clean": "rimraf ./dist", - "build": "parcel build index.html", + "clean": "rimraf ./dist ./.cache ./.parcel-cache", + "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html -p 8888", "test": "test-ipfs-example" }, @@ -18,7 +18,7 @@ "devDependencies": { "execa": "^5.0.0", "go-ipfs": "0.8.0", - "ipfsd-ctl": "^8.0.0", + "ipfsd-ctl": "^8.0.1", "parcel": "2.0.0-beta.2", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" diff --git a/examples/ipfs-101/1.js b/examples/ipfs-101/1.js index 9f78faf8ae..1850df48ab 100644 --- a/examples/ipfs-101/1.js +++ b/examples/ipfs-101/1.js @@ -4,6 +4,7 @@ const IPFS = require('ipfs') const all = require('it-all') const uint8ArrayConcat = require('uint8arrays/concat') const uint8ArrayFromString = require('uint8arrays/from-string') +const uint8ArrayToString = require('uint8arrays/to-string') async function main () { const node = await IPFS.create() @@ -20,7 +21,7 @@ async function main () { const data = uint8ArrayConcat(await all(node.cat(file.cid))) - console.log('Added file contents:', data.toString()) + console.log('Added file contents:', uint8ArrayToString(data)) } main() diff --git a/examples/ipfs-101/test.js b/examples/ipfs-101/test.js index 5599e0fbed..6c0c70f1bc 100644 --- a/examples/ipfs-101/test.js +++ b/examples/ipfs-101/test.js @@ -6,7 +6,7 @@ const { } = require('test-ipfs-example/utils') async function runTest () { - await waitForOutput('Added file contents:', path.resolve(__dirname, '1.js')) + await waitForOutput('Added file contents: Hello World 101', path.resolve(__dirname, '1.js')) } module.exports = runTest diff --git a/examples/ipfs-client-add-files/package.json b/examples/ipfs-client-add-files/package.json index 1b5dbb2fe1..70afb111f3 100644 --- a/examples/ipfs-client-add-files/package.json +++ b/examples/ipfs-client-add-files/package.json @@ -5,8 +5,8 @@ "main": "dist/index.html", "private": true, "scripts": { - "clean": "rimraf ./dist", - "build": "parcel build index.html", + "clean": "rimraf ./dist ./.cache ./.parcel-cache", + "build": "parcel build index.html --no-scope-hoist", "start": "parcel index.html -p 8888", "test": "test-ipfs-example" }, @@ -16,7 +16,7 @@ "devDependencies": { "execa": "^5.0.0", "ipfs": "^0.54.4", - "ipfsd-ctl": "^8.0.0", + "ipfsd-ctl": "^8.0.1", "parcel": "2.0.0-beta.2", "rimraf": "^3.0.2", "test-ipfs-example": "^3.0.0" diff --git a/examples/run-in-electron/package.json b/examples/run-in-electron/package.json index a0fa3ffc1a..6e69f215b0 100644 --- a/examples/run-in-electron/package.json +++ b/examples/run-in-electron/package.json @@ -16,7 +16,7 @@ "author": "David Dias ", "license": "MIT", "devDependencies": { - "electron": "^11.2.1", + "electron": "^12.0.2", "electron-rebuild": "^2.3.4", "ipfs": "^0.54.4", "test-ipfs-example": "^3.0.0" diff --git a/examples/traverse-ipld-graphs/package.json b/examples/traverse-ipld-graphs/package.json index 95e068a8bd..ad002d1bf4 100644 --- a/examples/traverse-ipld-graphs/package.json +++ b/examples/traverse-ipld-graphs/package.json @@ -18,7 +18,7 @@ "ipld-block": "^0.11.0", "ipld-dag-pb": "^0.22.1", "ipld-git": "^0.6.1", - "ipld-ethereum": "^5.0.1", + "ipld-ethereum": "^6.0.0", "multihashing-async": "^2.1.2" } } diff --git a/examples/types-use-ipfs-from-ts/package.json b/examples/types-use-ipfs-from-ts/package.json index 91dad859c8..7caab49abb 100644 --- a/examples/types-use-ipfs-from-ts/package.json +++ b/examples/types-use-ipfs-from-ts/package.json @@ -5,7 +5,7 @@ "ipfs": "^0.54.4" }, "devDependencies": { - "typescript": "4.1.x" + "typescript": "4.2.x" }, "scripts": { "test": "tsc --noEmit" diff --git a/examples/types-use-ipfs-from-typed-js/package.json b/examples/types-use-ipfs-from-typed-js/package.json index fba48fc6cf..54f9ded620 100644 --- a/examples/types-use-ipfs-from-typed-js/package.json +++ b/examples/types-use-ipfs-from-typed-js/package.json @@ -5,7 +5,7 @@ "ipfs": "^0.54.4" }, "devDependencies": { - "typescript": "4.1.x" + "typescript": "4.2.x" }, "scripts": { "test": "tsc --noEmit" diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 1493d99773..03fdfd946f 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -37,7 +37,7 @@ }, "dependencies": { "abort-controller": "^3.0.0", - "aegir": "^32.1.0", + "aegir": "^33.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", @@ -45,26 +45,26 @@ "delay": "^5.0.0", "dirty-chai": "^2.0.1", "err-code": "^3.0.1", - "ipfs-unixfs": "^4.0.1", - "ipfs-unixfs-importer": "^7.0.1", + "ipfs-unixfs": "^4.0.3", + "ipfs-unixfs-importer": "^7.0.3", "ipfs-utils": "^6.0.4", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^0.18.0", "ipld-dag-pb": "^0.22.1", - "ipns": "^0.10.0", - "is-ipfs": "^4.0.0", - "iso-random-stream": "^1.1.1", + "ipns": "^0.11.0", + "is-ipfs": "^5.0.0", + "iso-random-stream": "^2.0.0", "it-all": "^1.0.4", "it-buffer-stream": "^2.0.0", - "it-concat": "^1.0.3", + "it-concat": "^2.0.0", "it-drain": "^1.0.3", "it-first": "^1.0.4", "it-last": "^1.0.4", "it-map": "^1.0.4", "it-pushable": "^1.4.0", - "libp2p-crypto": "^0.19.0", - "libp2p-websockets": "^0.15.1", - "multiaddr": "^8.0.0", + "libp2p-crypto": "^0.19.3", + "libp2p-websockets": "^0.15.6", + "multiaddr": "^9.0.1", "multibase": "^4.0.2", "multihashing-async": "^2.1.2", "nanoid": "^3.1.12", diff --git a/packages/interface-ipfs-core/src/add-all.js b/packages/interface-ipfs-core/src/add-all.js index b83abc55b7..84667f2c8c 100644 --- a/packages/interface-ipfs-core/src/add-all.js +++ b/packages/interface-ipfs-core/src/add-all.js @@ -13,7 +13,6 @@ const { supportsFileReader } = require('ipfs-utils/src/supports') const globSource = require('ipfs-utils/src/files/glob-source') const { isNode } = require('ipfs-utils/src/env') const { getDescribe, getIt, expect } = require('./utils/mocha') -const testTimeout = require('./utils/test-timeout') const uint8ArrayFromString = require('uint8arrays/from-string') const bufferStream = require('it-buffer-stream') @@ -61,12 +60,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when adding files', () => { - return testTimeout(() => drain(ipfs.addAll(uint8ArrayFromString('Hello'), { - timeout: 1 - }))) - }) - it('should add a File as array of tuples', async function () { if (!supportsFileReader) return this.skip('skip in node') diff --git a/packages/interface-ipfs-core/src/add.js b/packages/interface-ipfs-core/src/add.js index 4be482f5ac..d62af444dc 100644 --- a/packages/interface-ipfs-core/src/add.js +++ b/packages/interface-ipfs-core/src/add.js @@ -7,7 +7,6 @@ const { supportsFileReader } = require('ipfs-utils/src/supports') const urlSource = require('ipfs-utils/src/files/url-source') const { isNode } = require('ipfs-utils/src/env') const { getDescribe, getIt, expect } = require('./utils/mocha') -const testTimeout = require('./utils/test-timeout') const echoUrl = (text) => `${process.env.ECHO_SERVER}/download?data=${encodeURIComponent(text)}` const redirectUrl = (url) => `${process.env.ECHO_SERVER}/redirect?to=${encodeURI(url)}` const uint8ArrayFromString = require('uint8arrays/from-string') @@ -55,12 +54,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when adding a file', () => { - return testTimeout(() => ipfs.add('Hello', { - timeout: 1 - })) - }) - it('should add a File', async function () { if (!supportsFileReader) return this.skip('skip in node') diff --git a/packages/interface-ipfs-core/src/bitswap/stat.js b/packages/interface-ipfs-core/src/bitswap/stat.js index bb1386fe13..7dd1264238 100644 --- a/packages/interface-ipfs-core/src/bitswap/stat.js +++ b/packages/interface-ipfs-core/src/bitswap/stat.js @@ -3,7 +3,6 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { expectIsBitswap } = require('../stats/utils') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,12 +23,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting bitswap stats', () => { - return testTimeout(() => ipfs.bitswap.stat({ - timeout: 1 - })) - }) - it('should get bitswap stats', async () => { const res = await ipfs.bitswap.stat() expectIsBitswap(null, res) diff --git a/packages/interface-ipfs-core/src/bitswap/transfer.js b/packages/interface-ipfs-core/src/bitswap/transfer.js index c1cb73b3c9..1af720055c 100644 --- a/packages/interface-ipfs-core/src/bitswap/transfer.js +++ b/packages/interface-ipfs-core/src/bitswap/transfer.js @@ -4,7 +4,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') const CID = require('cids') -const randomBytes = require('iso-random-stream/src/random') +const { randomBytes } = require('iso-random-stream') const Block = require('ipld-block') const concat = require('it-concat') const { nanoid } = require('nanoid') @@ -75,7 +75,7 @@ module.exports = (factory, options) => { describe('transfer a file between', () => { it('2 peers', async () => { - const content = randomBytes(1024 * 1024 * 10) + const content = randomBytes(1024) const remote = (await factory.spawn({ type: isWebWorker ? 'go' : undefined })).api const local = (await factory.spawn({ type: 'proc', ipfsOptions })).api local.swarm.connect(remote.peerId.addresses[0]) diff --git a/packages/interface-ipfs-core/src/bitswap/wantlist-for-peer.js b/packages/interface-ipfs-core/src/bitswap/wantlist-for-peer.js index 47e5ceb0ab..1ca5dce2b9 100644 --- a/packages/interface-ipfs-core/src/bitswap/wantlist-for-peer.js +++ b/packages/interface-ipfs-core/src/bitswap/wantlist-for-peer.js @@ -4,7 +4,6 @@ const { getDescribe, getIt } = require('../utils/mocha') const { waitForWantlistKey } = require('./utils') const { isWebWorker } = require('ipfs-utils/src/env') -const testTimeout = require('../utils/test-timeout') const getIpfsOptions = require('../utils/ipfs-options-websockets-filter-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -36,12 +35,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting bitswap wantlist by peer', () => { - return testTimeout(() => ipfsA.bitswap.wantlistForPeer(ipfsB.peerId.id, { - timeout: 1 - })) - }) - it('should get the wantlist by peer ID for a different node', function () { return waitForWantlistKey(ipfsA, key, { peerId: ipfsB.peerId.id, diff --git a/packages/interface-ipfs-core/src/block/put.js b/packages/interface-ipfs-core/src/block/put.js index 43a14216b1..3be1ca96a8 100644 --- a/packages/interface-ipfs-core/src/block/put.js +++ b/packages/interface-ipfs-core/src/block/put.js @@ -6,7 +6,6 @@ const Block = require('ipld-block') const multihash = require('multihashing-async').multihash const CID = require('cids') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') const all = require('it-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -27,12 +26,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when putting a block', () => { - return testTimeout(() => ipfs.block.put(uint8ArrayFromString('derp'), { - timeout: 1 - })) - }) - it('should put a buffer, using defaults', async () => { const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' const blob = uint8ArrayFromString('blorb') diff --git a/packages/interface-ipfs-core/src/bootstrap/add.js b/packages/interface-ipfs-core/src/bootstrap/add.js index 162483bced..2b931bd98e 100644 --- a/packages/interface-ipfs-core/src/bootstrap/add.js +++ b/packages/interface-ipfs-core/src/bootstrap/add.js @@ -2,8 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const invalidArg = 'this/Is/So/Invalid/' const validIp4 = new Multiaddr('/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z') @@ -28,12 +27,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when adding bootstrap nodes', () => { - return testTimeout(() => ipfs.bootstrap.add(validIp4, { - timeout: 1 - })) - }) - it('should return an error when called with an invalid arg', () => { return expect(ipfs.bootstrap.add(invalidArg)).to.eventually.be.rejected .and.be.an.instanceOf(Error) diff --git a/packages/interface-ipfs-core/src/bootstrap/clear.js b/packages/interface-ipfs-core/src/bootstrap/clear.js index 374eed4194..6fd49162d6 100644 --- a/packages/interface-ipfs-core/src/bootstrap/clear.js +++ b/packages/interface-ipfs-core/src/bootstrap/clear.js @@ -2,8 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -25,12 +24,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when removing bootstrap nodes', () => { - return testTimeout(() => ipfs.bootstrap.clear({ - timeout: 1 - })) - }) - it('should return a list containing the peer removed when called with a valid arg (ip4)', async () => { await ipfs.bootstrap.clear() diff --git a/packages/interface-ipfs-core/src/bootstrap/list.js b/packages/interface-ipfs-core/src/bootstrap/list.js index 868b1191b2..53d30b88d1 100644 --- a/packages/interface-ipfs-core/src/bootstrap/list.js +++ b/packages/interface-ipfs-core/src/bootstrap/list.js @@ -2,8 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,12 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option listing bootstrap nodes', () => { - return testTimeout(() => ipfs.bootstrap.list({ - timeout: 1 - })) - }) - it('should return a list of peers', async () => { const res = await ipfs.bootstrap.list() diff --git a/packages/interface-ipfs-core/src/bootstrap/reset.js b/packages/interface-ipfs-core/src/bootstrap/reset.js index fe0c78bd7e..334c6922c4 100644 --- a/packages/interface-ipfs-core/src/bootstrap/reset.js +++ b/packages/interface-ipfs-core/src/bootstrap/reset.js @@ -2,8 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -25,12 +24,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when resetting the bootstrap nodes', () => { - return testTimeout(() => ipfs.bootstrap.reset({ - timeout: 1 - })) - }) - it('should return a list of bootstrap peers when resetting the bootstrap nodes', async () => { const res = await ipfs.bootstrap.reset() diff --git a/packages/interface-ipfs-core/src/bootstrap/rm.js b/packages/interface-ipfs-core/src/bootstrap/rm.js index ec0b5e59a8..cb8e22af0f 100644 --- a/packages/interface-ipfs-core/src/bootstrap/rm.js +++ b/packages/interface-ipfs-core/src/bootstrap/rm.js @@ -2,8 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,12 +25,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when removing bootstrap nodes', () => { - return testTimeout(() => ipfs.bootstrap.rm(validIp4, { - timeout: 1 - })) - }) - it('should return an error when called with an invalid arg', () => { return expect(ipfs.bootstrap.rm(invalidArg)).to.eventually.be.rejected .and.be.an.instanceOf(Error) diff --git a/packages/interface-ipfs-core/src/config/get.js b/packages/interface-ipfs-core/src/config/get.js index 5071e6f93c..f65521af91 100644 --- a/packages/interface-ipfs-core/src/config/get.js +++ b/packages/interface-ipfs-core/src/config/get.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -21,12 +20,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting config values', () => { - return testTimeout(() => ipfs.config.get('Identity.PeerID', { - timeout: 1 - })) - }) - it('should fail with error', async () => { await expect(ipfs.config.get()).to.eventually.rejectedWith('key argument is required') }) @@ -58,12 +51,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting config values', () => { - return testTimeout(() => ipfs.config.getAll({ - timeout: 1 - })) - }) - it('should retrieve the whole config', async () => { const config = await ipfs.config.getAll() diff --git a/packages/interface-ipfs-core/src/config/profiles/apply.js b/packages/interface-ipfs-core/src/config/profiles/apply.js index d0980cd4d9..2e05dfa4b9 100644 --- a/packages/interface-ipfs-core/src/config/profiles/apply.js +++ b/packages/interface-ipfs-core/src/config/profiles/apply.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../../utils/mocha') -const testTimeout = require('../../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,12 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when applying a config profile', () => { - return testTimeout(() => ipfs.config.profiles.apply('server', { - timeout: 1 - })) - }) - it('should apply a config profile', async () => { const diff = await ipfs.config.profiles.apply('lowpower') expect(diff.original.Swarm.ConnMgr.LowWater).to.not.equal(diff.updated.Swarm.ConnMgr.LowWater) diff --git a/packages/interface-ipfs-core/src/config/profiles/list.js b/packages/interface-ipfs-core/src/config/profiles/list.js index b46c1d5c70..9cbe56219e 100644 --- a/packages/interface-ipfs-core/src/config/profiles/list.js +++ b/packages/interface-ipfs-core/src/config/profiles/list.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../../utils/mocha') -const testTimeout = require('../../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,12 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing config profiles', () => { - return testTimeout(() => ipfs.config.profiles.list({ - timeout: 1 - })) - }) - it('should list config profiles', async () => { const profiles = await ipfs.config.profiles.list() diff --git a/packages/interface-ipfs-core/src/config/replace.js b/packages/interface-ipfs-core/src/config/replace.js index d532e64019..847e9f0a83 100644 --- a/packages/interface-ipfs-core/src/config/replace.js +++ b/packages/interface-ipfs-core/src/config/replace.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -27,12 +26,6 @@ module.exports = (common, options) => { Fruit: 'Bananas' } - it('should respect timeout option when replacing config', () => { - return testTimeout(() => ipfs.config.replace(config, { - timeout: 1 - })) - }) - it('should replace the whole config', async () => { await ipfs.config.replace(config) diff --git a/packages/interface-ipfs-core/src/config/set.js b/packages/interface-ipfs-core/src/config/set.js index 82151bea6f..38ad9ae339 100644 --- a/packages/interface-ipfs-core/src/config/set.js +++ b/packages/interface-ipfs-core/src/config/set.js @@ -3,7 +3,6 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,12 +23,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when setting config values', () => { - return testTimeout(() => ipfs.config.set('Fruit', 'banana', { - timeout: 1 - })) - }) - it('should set a new key', async () => { await ipfs.config.set('Fruit', 'banana') diff --git a/packages/interface-ipfs-core/src/dag/put.js b/packages/interface-ipfs-core/src/dag/put.js index 0e22946275..ea8fe7ea21 100644 --- a/packages/interface-ipfs-core/src/dag/put.js +++ b/packages/interface-ipfs-core/src/dag/put.js @@ -8,7 +8,6 @@ const dagCBOR = require('ipld-dag-cbor') const CID = require('cids') const multihash = require('multihashing-async').multihash const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -45,14 +44,6 @@ module.exports = (common, options) => { done() }) - it('should respect timeout option when putting a DAG node', () => { - return testTimeout(() => ipfs.dag.put(pbNode, { - format: 'dag-pb', - hashAlg: 'sha2-256', - timeout: 1 - })) - }) - it('should put dag-pb with default hash func (sha2-256)', () => { return ipfs.dag.put(pbNode, { format: 'dag-pb', diff --git a/packages/interface-ipfs-core/src/dht/provide.js b/packages/interface-ipfs-core/src/dht/provide.js index 2b729f45d4..bcf18ae8ad 100644 --- a/packages/interface-ipfs-core/src/dht/provide.js +++ b/packages/interface-ipfs-core/src/dht/provide.js @@ -5,7 +5,6 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const CID = require('cids') const all = require('it-all') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,14 +28,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when providing a value on the DHT', async () => { - const res = await ipfs.add(uint8ArrayFromString('test')) - - await testTimeout(() => ipfs.dht.provide(res.cid, { - timeout: 1 - })) - }) - it('should provide local CID', async () => { const res = await ipfs.add(uint8ArrayFromString('test')) diff --git a/packages/interface-ipfs-core/src/dht/put.js b/packages/interface-ipfs-core/src/dht/put.js index 4721fd3a28..d059e8950c 100644 --- a/packages/interface-ipfs-core/src/dht/put.js +++ b/packages/interface-ipfs-core/src/dht/put.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') const all = require('it-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -26,16 +25,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when putting a value into the DHT', async () => { - const { cid } = await nodeA.add('should respect timeout option when putting a value into the DH') - const publish = await nodeA.name.publish(cid) - const record = await nodeA.dht.get(`/ipns/${publish.name}`) - - await testTimeout(() => nodeA.dht.put(`/ipns/${publish.name}`, record, { - timeout: 1 - })) - }) - it('should put a value to the DHT', async function () { const { cid } = await nodeA.add('should put a value to the DHT') const publish = await nodeA.name.publish(cid) diff --git a/packages/interface-ipfs-core/src/files/chmod.js b/packages/interface-ipfs-core/src/files/chmod.js index a3a1e9d811..84ae5837ec 100644 --- a/packages/interface-ipfs-core/src/files/chmod.js +++ b/packages/interface-ipfs-core/src/files/chmod.js @@ -5,7 +5,6 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const isShardAtPath = require('../utils/is-shard-at-path') -const testTimeout = require('../utils/test-timeout') module.exports = (common, options) => { const describe = getDescribe(options) @@ -331,17 +330,5 @@ module.exports = (common, options) => { // files with prior execute bit should now be user and group executable await expect(ipfs.files.stat(bin)).to.eventually.have.property('mode', 0o754) }) - - it('should respect timeout option when changing the mode of a file', async () => { - const path = `/foo-${Math.random()}` - - await ipfs.files.write(path, uint8ArrayFromString('Hello world'), { - create: true - }) - - await testTimeout(() => ipfs.files.chmod(path, '0777', { - timeout: 1 - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/files/cp.js b/packages/interface-ipfs-core/src/files/cp.js index a60b22d0f3..0ad20e99fc 100644 --- a/packages/interface-ipfs-core/src/files/cp.js +++ b/packages/interface-ipfs-core/src/files/cp.js @@ -10,10 +10,9 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const mh = require('multihashing-async').multihash const Block = require('ipld-block') const CID = require('cids') -const randomBytes = require('iso-random-stream/src/random') +const { randomBytes } = require('iso-random-stream') const createShardedDirectory = require('../utils/create-sharded-directory') const isShardAtPath = require('../utils/is-shard-at-path') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -337,12 +336,6 @@ module.exports = (common, options) => { expect(stats).to.have.property('mode', mode) }) - it('should respect timeout option when copying a file', async () => { - await testTimeout(() => ipfs.files.cp('/ipfs/QmaWLMK8yg36wMZX4Ybz7PAbKi1z5FzEtg5iEVeXHtNBqa', '/derp', { - timeout: 1 - })) - }) - describe('with sharding', () => { let ipfs diff --git a/packages/interface-ipfs-core/src/files/flush.js b/packages/interface-ipfs-core/src/files/flush.js index b8dd57cb77..c1471a8ffe 100644 --- a/packages/interface-ipfs-core/src/files/flush.js +++ b/packages/interface-ipfs-core/src/files/flush.js @@ -3,7 +3,6 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -54,11 +53,5 @@ module.exports = (common, options) => { expect(dirStats.cid.toString()).to.equal(flushed.toString()) }) - - it('should respect timeout option when flushing changes', async () => { - await testTimeout(() => ipfs.files.flush('/', { - timeout: 1 - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/files/ls.js b/packages/interface-ipfs-core/src/files/ls.js index e0e02e95ae..7c272a9363 100644 --- a/packages/interface-ipfs-core/src/files/ls.js +++ b/packages/interface-ipfs-core/src/files/ls.js @@ -6,9 +6,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const CID = require('cids') const createShardedDirectory = require('../utils/create-sharded-directory') const all = require('it-all') -const drain = require('it-drain') -const randomBytes = require('iso-random-stream/src/random') -const testTimeout = require('../utils/test-timeout') +const { randomBytes } = require('iso-random-stream') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -158,12 +156,6 @@ module.exports = (common, options) => { }]) }) - it('should respect timeout option when listing files', async () => { - await testTimeout(() => drain(ipfs.files.ls('/', { - timeout: 1 - }))) - }) - describe('with sharding', () => { let ipfs diff --git a/packages/interface-ipfs-core/src/files/mkdir.js b/packages/interface-ipfs-core/src/files/mkdir.js index bd6b133653..b55f200c20 100644 --- a/packages/interface-ipfs-core/src/files/mkdir.js +++ b/packages/interface-ipfs-core/src/files/mkdir.js @@ -7,7 +7,6 @@ const multihash = require('multihashing-async').multihash const createShardedDirectory = require('../utils/create-sharded-directory') const all = require('it-all') const isShardAtPath = require('../utils/is-shard-at-path') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -213,12 +212,6 @@ module.exports = (common, options) => { }) }) - it('should respect timeout option when making a directory', async () => { - await testTimeout(() => ipfs.files.mkdir('/dir-to-make', { - timeout: 1 - })) - }) - describe('with sharding', () => { let ipfs diff --git a/packages/interface-ipfs-core/src/files/mv.js b/packages/interface-ipfs-core/src/files/mv.js index aada231394..027b2319a3 100644 --- a/packages/interface-ipfs-core/src/files/mv.js +++ b/packages/interface-ipfs-core/src/files/mv.js @@ -5,9 +5,8 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayConcat = require('uint8arrays/concat') const { getDescribe, getIt, expect } = require('../utils/mocha') const createShardedDirectory = require('../utils/create-sharded-directory') -const randomBytes = require('iso-random-stream/src/random') +const { randomBytes } = require('iso-random-stream') const isShardAtPath = require('../utils/is-shard-at-path') -const testTimeout = require('../utils/test-timeout') const all = require('it-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -103,20 +102,6 @@ module.exports = (common, options) => { } }) - it('should respect timeout option when moving files', async () => { - const source = `/source-file-${Math.random()}.txt` - const destination = `/dest-file-${Math.random()}.txt` - const data = randomBytes(500) - - await ipfs.files.write(source, data, { - create: true - }) - - await testTimeout(() => ipfs.files.mv(source, destination, { - timeout: 1 - })) - }) - describe('with sharding', () => { let ipfs diff --git a/packages/interface-ipfs-core/src/files/read.js b/packages/interface-ipfs-core/src/files/read.js index 124cd6aad0..9de211bfe4 100644 --- a/packages/interface-ipfs-core/src/files/read.js +++ b/packages/interface-ipfs-core/src/files/read.js @@ -7,8 +7,7 @@ const all = require('it-all') const { fixtures } = require('../utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const createShardedDirectory = require('../utils/create-sharded-directory') -const randomBytes = require('iso-random-stream/src/random') -const testTimeout = require('../utils/test-timeout') +const { randomBytes } = require('iso-random-stream') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -109,19 +108,6 @@ module.exports = (common, options) => { expect(testFileData).to.eql(fixtures.smallFile.data) }) - it('should respect timeout option when reading files', async () => { - const path = `/some-file-${Math.random()}.txt` - const data = randomBytes(100) - - await ipfs.files.write(path, data, { - create: true - }) - - await testTimeout(() => drain(ipfs.files.read(path, { - timeout: 1 - }))) - }) - describe('with sharding', () => { let ipfs diff --git a/packages/interface-ipfs-core/src/files/rm.js b/packages/interface-ipfs-core/src/files/rm.js index 41c640828a..99465f5d8b 100644 --- a/packages/interface-ipfs-core/src/files/rm.js +++ b/packages/interface-ipfs-core/src/files/rm.js @@ -5,9 +5,8 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const createShardedDirectory = require('../utils/create-sharded-directory') const createTwoShards = require('../utils/create-two-shards') -const randomBytes = require('iso-random-stream/src/random') +const { randomBytes } = require('iso-random-stream') const isShardAtPath = require('../utils/is-shard-at-path') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -271,18 +270,5 @@ module.exports = (common, options) => { expect((await ipfs.files.stat(dirPath)).type).to.equal('directory') expect(updatedDirCid.toString()).to.deep.equal(dirWithSomeFiles.toString()) }) - - it('should respect timeout option when removing files', async () => { - const file = `/some-file-${Math.random()}.txt` - - await ipfs.files.write(file, randomBytes(100), { - create: true, - parents: true - }) - - await testTimeout(() => ipfs.files.rm(file, { - timeout: 1 - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/files/stat.js b/packages/interface-ipfs-core/src/files/stat.js index e8f5a272f9..ee39e44e07 100644 --- a/packages/interface-ipfs-core/src/files/stat.js +++ b/packages/interface-ipfs-core/src/files/stat.js @@ -9,9 +9,8 @@ const createShardedDirectory = require('../utils/create-sharded-directory') const CID = require('cids') const mh = require('multihashing-async').multihash const Block = require('ipld-block') -const randomBytes = require('iso-random-stream/src/random') +const { randomBytes } = require('iso-random-stream') const isShardAtPath = require('../utils/is-shard-at-path') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -359,15 +358,6 @@ module.exports = (common, options) => { expect(stat.sizeLocal).to.be.undefined() }) - it('should respect timeout option when statting files', async () => { - const path = `/directory-${Math.random()}` - await ipfs.files.mkdir(path) - - await testTimeout(() => ipfs.files.stat(path, { - timeout: 1 - })) - }) - describe('with sharding', () => { let ipfs diff --git a/packages/interface-ipfs-core/src/files/touch.js b/packages/interface-ipfs-core/src/files/touch.js index 4dcd99e106..e8a71900f7 100644 --- a/packages/interface-ipfs-core/src/files/touch.js +++ b/packages/interface-ipfs-core/src/files/touch.js @@ -6,7 +6,6 @@ const uint8ArrayConcat = require('uint8arrays/concat') const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const delay = require('delay') -const testTimeout = require('../utils/test-timeout') const all = require('it-all') module.exports = (common, options) => { @@ -158,11 +157,5 @@ module.exports = (common, options) => { nsecs: mtime[1] }) }) - - it('should respect timeout option when updating the modification time of files', async () => { - await testTimeout(() => ipfs.files.touch('/derp', { - timeout: 1 - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/files/write.js b/packages/interface-ipfs-core/src/files/write.js index d35e0ed9d7..f6ef1a8fbb 100644 --- a/packages/interface-ipfs-core/src/files/write.js +++ b/packages/interface-ipfs-core/src/files/write.js @@ -10,11 +10,10 @@ const multihash = require('multihashing-async').multihash const traverseLeafNodes = require('../utils/traverse-leaf-nodes') const createShardedDirectory = require('../utils/create-sharded-directory') const createTwoShards = require('../utils/create-two-shards') -const randomBytes = require('iso-random-stream/src/random') -const randomStream = require('iso-random-stream') +const { randomBytes } = require('iso-random-stream') +const { randomStream } = require('iso-random-stream') const all = require('it-all') const isShardAtPath = require('../utils/is-shard-at-path') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -627,13 +626,6 @@ module.exports = (common, options) => { }) }) - it('should respect timeout option when writing files', async () => { - await testTimeout(() => ipfs.files.write('/derp', [], { - create: true, - timeout: 1 - })) - }) - describe('with sharding', () => { let ipfs diff --git a/packages/interface-ipfs-core/src/key/gen.js b/packages/interface-ipfs-core/src/key/gen.js index 9b3257eb00..d3241b1382 100644 --- a/packages/interface-ipfs-core/src/key/gen.js +++ b/packages/interface-ipfs-core/src/key/gen.js @@ -3,7 +3,6 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -27,14 +26,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when generating a key', () => { - return testTimeout(() => ipfs.key.gen(nanoid(), { - type: 'rsa', - size: 2048, - timeout: 1 - })) - }) - keyTypes.forEach((kt) => { it(`should generate a new ${kt.type} key`, async function () { this.timeout(20 * 1000) diff --git a/packages/interface-ipfs-core/src/key/import.js b/packages/interface-ipfs-core/src/key/import.js index 9c7721ad65..0bb9933fd1 100644 --- a/packages/interface-ipfs-core/src/key/import.js +++ b/packages/interface-ipfs-core/src/key/import.js @@ -4,7 +4,6 @@ const { nanoid } = require('nanoid') const keys = require('libp2p-crypto/src/keys') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,17 +23,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when importing a key', async () => { - const password = nanoid() - - const key = await keys.generateKeyPair('ed25519') - const exported = key.export(password) - - await testTimeout(() => ipfs.key.import('derp', exported, password, { - timeout: 1 - })) - }) - it('should import an exported key', async () => { const password = nanoid() diff --git a/packages/interface-ipfs-core/src/key/list.js b/packages/interface-ipfs-core/src/key/list.js index c90c53f82f..a965b80c5a 100644 --- a/packages/interface-ipfs-core/src/key/list.js +++ b/packages/interface-ipfs-core/src/key/list.js @@ -3,7 +3,6 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,12 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing keys', () => { - return testTimeout(() => ipfs.key.list({ - timeout: 1 - })) - }) - it('should list all the keys', async function () { this.timeout(60 * 1000) diff --git a/packages/interface-ipfs-core/src/key/rename.js b/packages/interface-ipfs-core/src/key/rename.js index 5ccb6a9ec4..9eafa9d622 100644 --- a/packages/interface-ipfs-core/src/key/rename.js +++ b/packages/interface-ipfs-core/src/key/rename.js @@ -3,7 +3,6 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,16 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when renaming keys', async () => { - const oldName = nanoid() - const newName = nanoid() - await ipfs.key.gen(oldName, { type: 'rsa', size: 2048 }) - - await testTimeout(() => ipfs.key.rename(oldName, newName, { - timeout: 1 - })) - }) - it('should rename a key', async function () { this.timeout(30 * 1000) diff --git a/packages/interface-ipfs-core/src/key/rm.js b/packages/interface-ipfs-core/src/key/rm.js index 0f8338aa68..df8f7ed143 100644 --- a/packages/interface-ipfs-core/src/key/rm.js +++ b/packages/interface-ipfs-core/src/key/rm.js @@ -3,7 +3,6 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,15 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when removing keys', async () => { - const name = nanoid() - await ipfs.key.gen(name, { type: 'rsa', size: 2048 }) - - await testTimeout(() => ipfs.key.rm(name, { - timeout: 1 - })) - }) - it('should rm a key', async function () { this.timeout(30 * 1000) diff --git a/packages/interface-ipfs-core/src/ls.js b/packages/interface-ipfs-core/src/ls.js index 7a1bf59015..63b11dd383 100644 --- a/packages/interface-ipfs-core/src/ls.js +++ b/packages/interface-ipfs-core/src/ls.js @@ -4,7 +4,6 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('./utils/mocha') const all = require('it-all') -const drain = require('it-drain') const CID = require('cids') const testTimeout = require('./utils/test-timeout') @@ -31,9 +30,9 @@ module.exports = (common, options) => { after(() => common.clean()) it('should respect timeout option when listing files', () => { - return testTimeout(() => drain(ipfs.ls(new CID('QmNonExistentCiD8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXg'), { + return testTimeout(() => ipfs.ls(new CID('QmNonExistentCiD8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXg'), { timeout: 1 - }))) + })) }) it('should ls with a base58 encoded CID', async function () { diff --git a/packages/interface-ipfs-core/src/miscellaneous/dns.js b/packages/interface-ipfs-core/src/miscellaneous/dns.js index 17653da145..a4e54151d3 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/dns.js +++ b/packages/interface-ipfs-core/src/miscellaneous/dns.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,12 +23,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when resolving a DNS name', () => { - return testTimeout(() => ipfs.dns('derp.io', { - timeout: 1 - })) - }) - it('should non-recursively resolve ipfs.io', async function () { try { const res = await ipfs.dns('ipfs.io', { recursive: false }) diff --git a/packages/interface-ipfs-core/src/miscellaneous/id.js b/packages/interface-ipfs-core/src/miscellaneous/id.js index edbf65f4c9..a0ffc8d769 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/id.js +++ b/packages/interface-ipfs-core/src/miscellaneous/id.js @@ -2,9 +2,8 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const CID = require('cids') -const testTimeout = require('../utils/test-timeout') const { isWebWorker } = require('ipfs-utils/src/env') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -26,12 +25,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting the node id', () => { - return testTimeout(() => ipfs.id({ - timeout: 1 - })) - }) - it('should get the node ID', async () => { const res = await ipfs.id() expect(res).to.have.a.property('id').that.is.a('string') diff --git a/packages/interface-ipfs-core/src/miscellaneous/resolve.js b/packages/interface-ipfs-core/src/miscellaneous/resolve.js index 7a69854e55..4700756a2b 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/resolve.js +++ b/packages/interface-ipfs-core/src/miscellaneous/resolve.js @@ -8,7 +8,6 @@ const multibase = require('multibase') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') const { isWebWorker } = require('ipfs-utils/src/env') -const testTimeout = require('../utils/test-timeout') const getIpfsOptions = require('../utils/ipfs-options-websockets-filter-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -31,12 +30,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when resoving an ipfs path', () => { - return testTimeout(() => ipfs.resolve('/ipfs/Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ/herp/derp', { - timeout: 1 - })) - }) - it('should resolve an IPFS hash', async () => { const content = uint8ArrayFromString('Hello world') diff --git a/packages/interface-ipfs-core/src/miscellaneous/stop.js b/packages/interface-ipfs-core/src/miscellaneous/stop.js index 44f9997dbf..80ab85199b 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/stop.js +++ b/packages/interface-ipfs-core/src/miscellaneous/stop.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,12 +28,6 @@ module.exports = (common, options) => { common.controllers = [] }) - it('should respect timeout option when stopping the node', () => { - return testTimeout(() => ipfs.api.stop({ - timeout: 1 - })) - }) - it('should stop the node', async () => { // Should succeed because node is started await ipfs.api.swarm.peers() diff --git a/packages/interface-ipfs-core/src/miscellaneous/version.js b/packages/interface-ipfs-core/src/miscellaneous/version.js index 2a58bd801d..d7b4bb874e 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/version.js +++ b/packages/interface-ipfs-core/src/miscellaneous/version.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,12 +21,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting the node version', () => { - return testTimeout(() => ipfs.version({ - timeout: 1 - })) - }) - it('should get the node version', async () => { const result = await ipfs.version() expect(result).to.have.a.property('version') diff --git a/packages/interface-ipfs-core/src/name-pubsub/cancel.js b/packages/interface-ipfs-core/src/name-pubsub/cancel.js index 7b00a5cd6a..d0ab76b495 100644 --- a/packages/interface-ipfs-core/src/name-pubsub/cancel.js +++ b/packages/interface-ipfs-core/src/name-pubsub/cancel.js @@ -4,7 +4,6 @@ const PeerId = require('peer-id') const all = require('it-all') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,12 +25,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when cancelling an IPNS pubsub subscription', () => { - return testTimeout(() => ipfs.name.pubsub.cancel(nodeId, { - timeout: 1 - })) - }) - it('should return false when the name that is intended to cancel is not subscribed', async function () { this.timeout(60 * 1000) diff --git a/packages/interface-ipfs-core/src/name-pubsub/state.js b/packages/interface-ipfs-core/src/name-pubsub/state.js index 81f972a70d..01da8dbaac 100644 --- a/packages/interface-ipfs-core/src/name-pubsub/state.js +++ b/packages/interface-ipfs-core/src/name-pubsub/state.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,12 +21,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting the IPNS pubsub state', () => { - return testTimeout(() => ipfs.name.pubsub.state({ - timeout: 1 - })) - }) - it('should get the current state of pubsub', async function () { this.timeout(50 * 1000) diff --git a/packages/interface-ipfs-core/src/name-pubsub/subs.js b/packages/interface-ipfs-core/src/name-pubsub/subs.js index 7b1d0778aa..f6a555d054 100644 --- a/packages/interface-ipfs-core/src/name-pubsub/subs.js +++ b/packages/interface-ipfs-core/src/name-pubsub/subs.js @@ -3,7 +3,6 @@ const all = require('it-all') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,12 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting IPNS pubsub subscriptions', () => { - return testTimeout(() => ipfs.name.pubsub.subs({ - timeout: 1 - })) - }) - it('should get an empty array as a result of subscriptions before any resolve', async function () { this.timeout(60 * 1000) diff --git a/packages/interface-ipfs-core/src/name/publish.js b/packages/interface-ipfs-core/src/name/publish.js index fe0e097687..68fe8b65ba 100644 --- a/packages/interface-ipfs-core/src/name/publish.js +++ b/packages/interface-ipfs-core/src/name/publish.js @@ -6,7 +6,6 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const { fixture } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const last = require('it-last') -const testTimeout = require('../utils/test-timeout') const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -31,13 +30,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when publishing an IPNS name', () => { - return testTimeout(() => ipfs.name.publish(fixture.cid, { - allowOffline: true, - timeout: 1 - })) - }) - it('should publish an IPNS record with the default params', async function () { this.timeout(50 * 1000) diff --git a/packages/interface-ipfs-core/src/object/data.js b/packages/interface-ipfs-core/src/object/data.js index fab08955c1..ab89b44239 100644 --- a/packages/interface-ipfs-core/src/object/data.js +++ b/packages/interface-ipfs-core/src/object/data.js @@ -3,8 +3,6 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') -const CID = require('cids') const uint8ArrayFromString = require('uint8arrays/from-string') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -27,12 +25,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting the data from an object', () => { - return testTimeout(() => ipfs.object.data(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { - timeout: 1 - })) - }) - it('should get data by multihash', async () => { const testObj = { Data: uint8ArrayFromString(nanoid()), diff --git a/packages/interface-ipfs-core/src/object/get.js b/packages/interface-ipfs-core/src/object/get.js index b81ddb6a82..6b5f941a80 100644 --- a/packages/interface-ipfs-core/src/object/get.js +++ b/packages/interface-ipfs-core/src/object/get.js @@ -6,10 +6,8 @@ const DAGNode = dagPB.DAGNode const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const { UnixFS } = require('ipfs-unixfs') -const randomBytes = require('iso-random-stream/src/random') +const { randomBytes } = require('iso-random-stream') const { asDAGLink } = require('./utils') -const testTimeout = require('../utils/test-timeout') -const CID = require('cids') const uint8ArrayFromString = require('uint8arrays/from-string') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -32,12 +30,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting an object', () => { - return testTimeout(() => ipfs.object.get(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { - timeout: 1 - })) - }) - it('should get object by multihash', async () => { const obj = { Data: uint8ArrayFromString(nanoid()), diff --git a/packages/interface-ipfs-core/src/object/links.js b/packages/interface-ipfs-core/src/object/links.js index c394270920..d37a1e786d 100644 --- a/packages/interface-ipfs-core/src/object/links.js +++ b/packages/interface-ipfs-core/src/object/links.js @@ -7,8 +7,6 @@ const DAGNode = dagPB.DAGNode const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const { asDAGLink } = require('./utils') -const testTimeout = require('../utils/test-timeout') -const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -30,12 +28,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting the links from an object', () => { - return testTimeout(() => ipfs.object.links(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { - timeout: 1 - })) - }) - it('should get empty links by multihash', async () => { const testObj = { Data: uint8ArrayFromString(nanoid()), diff --git a/packages/interface-ipfs-core/src/object/new.js b/packages/interface-ipfs-core/src/object/new.js index 9788218d01..0b3116f564 100644 --- a/packages/interface-ipfs-core/src/object/new.js +++ b/packages/interface-ipfs-core/src/object/new.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,12 +23,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when creating a new object', () => { - return testTimeout(() => ipfs.object.new({ - timeout: 1 - })) - }) - it('should create a new object with no template', async () => { const cid = await ipfs.object.new() expect(cid.toBaseEncodedString()).to.equal('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n') diff --git a/packages/interface-ipfs-core/src/object/patch/add-link.js b/packages/interface-ipfs-core/src/object/patch/add-link.js index 5e1d34f6b2..82747319c7 100644 --- a/packages/interface-ipfs-core/src/object/patch/add-link.js +++ b/packages/interface-ipfs-core/src/object/patch/add-link.js @@ -6,8 +6,6 @@ const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode const { getDescribe, getIt, expect } = require('../../utils/mocha') const { asDAGLink } = require('../utils') -const CID = require('cids') -const testTimeout = require('../../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,12 +27,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when adding a link to an object', () => { - return testTimeout(() => ipfs.object.patch.addLink(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { name: '', size: 37, cid: new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxaZ') }, { - timeout: 1 - })) - }) - it('should add a link to an existing node', async () => { const obj = { Data: uint8ArrayFromString('patch test object'), diff --git a/packages/interface-ipfs-core/src/object/patch/append-data.js b/packages/interface-ipfs-core/src/object/patch/append-data.js index 26bf929208..b6672166ff 100644 --- a/packages/interface-ipfs-core/src/object/patch/append-data.js +++ b/packages/interface-ipfs-core/src/object/patch/append-data.js @@ -3,8 +3,6 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const { getDescribe, getIt, expect } = require('../../utils/mocha') -const testTimeout = require('../../utils/test-timeout') -const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,12 +24,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when appending data to an object', () => { - return testTimeout(() => ipfs.object.patch.appendData(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), uint8ArrayFromString('derp'), { - timeout: 1 - })) - }) - it('should append data to an existing node', async () => { const obj = { Data: uint8ArrayFromString('patch test object'), diff --git a/packages/interface-ipfs-core/src/object/patch/rm-link.js b/packages/interface-ipfs-core/src/object/patch/rm-link.js index 653a53c84b..b9184abc02 100644 --- a/packages/interface-ipfs-core/src/object/patch/rm-link.js +++ b/packages/interface-ipfs-core/src/object/patch/rm-link.js @@ -4,8 +4,6 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const { getDescribe, getIt, expect } = require('../../utils/mocha') const { asDAGLink } = require('../utils') -const testTimeout = require('../../utils/test-timeout') -const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -27,12 +25,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when removing a link from an object', () => { - return testTimeout(() => ipfs.object.patch.rmLink(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { name: 'link' }, { - timeout: 1 - })) - }) - it('should remove a link from an existing node', async () => { const obj1 = { Data: uint8ArrayFromString('patch test object 1'), diff --git a/packages/interface-ipfs-core/src/object/patch/set-data.js b/packages/interface-ipfs-core/src/object/patch/set-data.js index 7c80a67fd0..8f610116d7 100644 --- a/packages/interface-ipfs-core/src/object/patch/set-data.js +++ b/packages/interface-ipfs-core/src/object/patch/set-data.js @@ -3,8 +3,6 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const { getDescribe, getIt, expect } = require('../../utils/mocha') -const testTimeout = require('../../utils/test-timeout') -const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,12 +24,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when setting the data of an object', () => { - return testTimeout(() => ipfs.object.patch.setData(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), uint8ArrayFromString('derp'), { - timeout: 1 - })) - }) - it('should set data for an existing node', async () => { const obj = { Data: uint8ArrayFromString('patch test object'), diff --git a/packages/interface-ipfs-core/src/object/put.js b/packages/interface-ipfs-core/src/object/put.js index 5d1483306b..44aa25058f 100644 --- a/packages/interface-ipfs-core/src/object/put.js +++ b/packages/interface-ipfs-core/src/object/put.js @@ -7,7 +7,6 @@ const DAGNode = dagPB.DAGNode const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const { asDAGLink } = require('./utils') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,12 +28,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when putting an object', () => { - return testTimeout(() => ipfs.object.put({ Data: uint8ArrayFromString('derp') }, { - timeout: 1 - })) - }) - it('should put an object', async () => { const obj = { Data: uint8ArrayFromString(nanoid()), diff --git a/packages/interface-ipfs-core/src/object/stat.js b/packages/interface-ipfs-core/src/object/stat.js index cad848accd..f312eeaf33 100644 --- a/packages/interface-ipfs-core/src/object/stat.js +++ b/packages/interface-ipfs-core/src/object/stat.js @@ -6,8 +6,6 @@ const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode const { getDescribe, getIt, expect } = require('../utils/mocha') const { asDAGLink } = require('./utils') -const testTimeout = require('../utils/test-timeout') -const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,12 +27,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when statting an object', () => { - return testTimeout(() => ipfs.object.stat(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { - timeout: 1 - })) - }) - it('should get stats by multihash', async () => { const testObj = { Data: uint8ArrayFromString('get test object'), diff --git a/packages/interface-ipfs-core/src/pin/add-all.js b/packages/interface-ipfs-core/src/pin/add-all.js index 138b9e2f9b..aa318358ac 100644 --- a/packages/interface-ipfs-core/src/pin/add-all.js +++ b/packages/interface-ipfs-core/src/pin/add-all.js @@ -5,8 +5,6 @@ const { fixtures, clearPins } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') const drain = require('it-drain') -const testTimeout = require('../utils/test-timeout') -const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -118,11 +116,5 @@ module.exports = (common, options) => { } }()) }) - - it('should respect timeout option when pinning a block', () => { - return testTimeout(() => ipfs.pin.addAll([new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ')], { - timeout: 1 - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/pin/add.js b/packages/interface-ipfs-core/src/pin/add.js index 32f2d46cdf..7b4ce227fa 100644 --- a/packages/interface-ipfs-core/src/pin/add.js +++ b/packages/interface-ipfs-core/src/pin/add.js @@ -9,8 +9,6 @@ const drain = require('it-drain') const { DAGNode } = require('ipld-dag-pb') -const testTimeout = require('../utils/test-timeout') -const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -181,11 +179,5 @@ module.exports = (common, options) => { type: 'indirect' }) }) - - it('should respect timeout option when pinning a block', () => { - return testTimeout(() => ipfs.pin.add(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { - timeout: 1 - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/pin/ls.js b/packages/interface-ipfs-core/src/pin/ls.js index 111d84459b..4e02b08251 100644 --- a/packages/interface-ipfs-core/src/pin/ls.js +++ b/packages/interface-ipfs-core/src/pin/ls.js @@ -4,7 +4,6 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -36,12 +35,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing pins', () => { - return testTimeout(() => ipfs.pin.ls({ - timeout: 1 - })) - }) - // 1st, because ipfs.add pins automatically it('should list all recursive pins', async () => { const pinset = await all(ipfs.pin.ls({ type: 'recursive' })) diff --git a/packages/interface-ipfs-core/src/pin/remote/add.js b/packages/interface-ipfs-core/src/pin/remote/add.js index 78457490f9..3607777771 100644 --- a/packages/interface-ipfs-core/src/pin/remote/add.js +++ b/packages/interface-ipfs-core/src/pin/remote/add.js @@ -3,8 +3,6 @@ const { fixtures, clearRemotePins, clearServices } = require('../utils') const { getDescribe, getIt, expect } = require('../../utils/mocha') -const testTimeout = require('../../utils/test-timeout') -const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -138,12 +136,5 @@ module.exports = (common, options) => { name: '' }) }) - - it('should respect timeout option when pinning a block', () => { - return testTimeout(() => ipfs.pin.remote.add(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { - timeout: 1, - service: SERVICE - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/pin/remote/ls.js b/packages/interface-ipfs-core/src/pin/remote/ls.js index b3a92f4177..d76654361c 100644 --- a/packages/interface-ipfs-core/src/pin/remote/ls.js +++ b/packages/interface-ipfs-core/src/pin/remote/ls.js @@ -4,7 +4,6 @@ const { clearRemotePins, addRemotePins, clearServices } = require('../utils') const { getDescribe, getIt, expect } = require('../../utils/mocha') const all = require('it-all') -const testTimeout = require('../../utils/test-timeout') const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -421,13 +420,6 @@ module.exports = (common, options) => { ]) }) }) - - it('should respect timeout option', () => { - return testTimeout(() => all(ipfs.pin.remote.ls({ - timeout: 1, - service: SERVICE - }))) - }) }) } diff --git a/packages/interface-ipfs-core/src/pin/remote/rm-all.js b/packages/interface-ipfs-core/src/pin/remote/rm-all.js index 9b80f37921..5036792e87 100644 --- a/packages/interface-ipfs-core/src/pin/remote/rm-all.js +++ b/packages/interface-ipfs-core/src/pin/remote/rm-all.js @@ -3,7 +3,6 @@ const { clearRemotePins, addRemotePins, clearServices } = require('../utils') const { getDescribe, getIt, expect } = require('../../utils/mocha') -const testTimeout = require('../../utils/test-timeout') const CID = require('cids') const all = require('it-all') @@ -151,13 +150,6 @@ module.exports = (common, options) => { } ].sort(byCID)) }) - - it('should respect timeout option', () => { - return testTimeout(() => ipfs.pin.remote.rmAll({ - timeout: 1, - service: SERVICE - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/pin/remote/rm.js b/packages/interface-ipfs-core/src/pin/remote/rm.js index 4dead16588..32b8ba7ea0 100644 --- a/packages/interface-ipfs-core/src/pin/remote/rm.js +++ b/packages/interface-ipfs-core/src/pin/remote/rm.js @@ -3,7 +3,6 @@ const { clearRemotePins, addRemotePins, clearServices } = require('../utils') const { getDescribe, getIt, expect } = require('../../utils/mocha') -const testTimeout = require('../../utils/test-timeout') const CID = require('cids') const all = require('it-all') @@ -169,13 +168,6 @@ module.exports = (common, options) => { } ].sort(byCID)) }) - - it('should respect timeout option', () => { - return testTimeout(() => ipfs.pin.remote.rm({ - timeout: 1, - service: SERVICE - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/pin/rm-all.js b/packages/interface-ipfs-core/src/pin/rm-all.js index b2f319ac7e..f0ad36408f 100644 --- a/packages/interface-ipfs-core/src/pin/rm-all.js +++ b/packages/interface-ipfs-core/src/pin/rm-all.js @@ -5,7 +5,6 @@ const { fixtures, clearPins } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') const drain = require('it-drain') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -36,15 +35,6 @@ module.exports = (common, options) => { return clearPins(ipfs) }) - it('should respect timeout option when unpinning a block', async () => { - await ipfs.pin.add(fixtures.files[0].cid, { recursive: true }) - - await testTimeout(() => ipfs.pin.rmAll([fixtures.files[0].cid], { - recursive: true, - timeout: 1 - })) - }) - it('should pipe the output of ls to rm', async () => { await ipfs.pin.add(fixtures.directory.cid) diff --git a/packages/interface-ipfs-core/src/pin/rm.js b/packages/interface-ipfs-core/src/pin/rm.js index 7ae804518f..59f1ae2642 100644 --- a/packages/interface-ipfs-core/src/pin/rm.js +++ b/packages/interface-ipfs-core/src/pin/rm.js @@ -4,7 +4,6 @@ const { fixtures, expectPinned, clearPins } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -34,15 +33,6 @@ module.exports = (common, options) => { return clearPins(ipfs) }) - it('should respect timeout option when unpinning a block', async () => { - await ipfs.pin.add(fixtures.files[0].cid, { recursive: true }) - - await testTimeout(() => ipfs.pin.rm(fixtures.files[0].cid, { - recursive: true, - timeout: 1 - })) - }) - it('should remove a recursive pin', async () => { await ipfs.pin.add(fixtures.directory.cid) diff --git a/packages/interface-ipfs-core/src/ping/ping.js b/packages/interface-ipfs-core/src/ping/ping.js index 8bdae916d4..71dbbbccd0 100644 --- a/packages/interface-ipfs-core/src/ping/ping.js +++ b/packages/interface-ipfs-core/src/ping/ping.js @@ -4,9 +4,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { expectIsPingResponse, isPong } = require('./utils') const all = require('it-all') -const drain = require('it-drain') const { isWebWorker } = require('ipfs-utils/src/env') -const testTimeout = require('../utils/test-timeout') const getIpfsOptions = require('../utils/ipfs-options-websockets-filter-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -34,12 +32,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when pinging a peer', () => { - return testTimeout(() => drain(ipfsA.ping(ipfsB.peerId.id, { - timeout: 1 - }))) - }) - it('should send the specified number of packets', async () => { const count = 3 const responses = await all(ipfsA.ping(ipfsB.peerId.id, { count })) diff --git a/packages/interface-ipfs-core/src/pubsub/ls.js b/packages/interface-ipfs-core/src/pubsub/ls.js index fbc918b32e..85449bf02c 100644 --- a/packages/interface-ipfs-core/src/pubsub/ls.js +++ b/packages/interface-ipfs-core/src/pubsub/ls.js @@ -4,7 +4,6 @@ const { getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const delay = require('delay') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -34,12 +33,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing pubsub subscriptions', () => { - return testTimeout(() => ipfs.pubsub.ls({ - timeout: 1 - })) - }) - it('should return an empty list when no topics are subscribed', async () => { const topics = await ipfs.pubsub.ls() expect(topics.length).to.equal(0) diff --git a/packages/interface-ipfs-core/src/pubsub/peers.js b/packages/interface-ipfs-core/src/pubsub/peers.js index 5d1bc25f9d..8bdcb1c97f 100644 --- a/packages/interface-ipfs-core/src/pubsub/peers.js +++ b/packages/interface-ipfs-core/src/pubsub/peers.js @@ -5,7 +5,6 @@ const { waitForPeers, getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const delay = require('delay') const { isWebWorker } = require('ipfs-utils/src/env') -const testTimeout = require('../utils/test-timeout') const getIpfsOptions = require('../utils/ipfs-options-websockets-filter-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -54,12 +53,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing pubsub peers', () => { - return testTimeout(() => ipfs1.pubsub.peers(getTopic(), { - timeout: 1 - })) - }) - it('should not error when not subscribed to a topic', async () => { const topic = getTopic() const peers = await ipfs1.pubsub.peers(topic) diff --git a/packages/interface-ipfs-core/src/pubsub/publish.js b/packages/interface-ipfs-core/src/pubsub/publish.js index 27e048eb97..cab0494ae9 100644 --- a/packages/interface-ipfs-core/src/pubsub/publish.js +++ b/packages/interface-ipfs-core/src/pubsub/publish.js @@ -5,7 +5,6 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const { nanoid } = require('nanoid') const { getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -27,12 +26,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when publishing a pubsub message', () => { - return testTimeout(() => ipfs.pubsub.publish(getTopic(), 'derp', { - timeout: 1 - })) - }) - it('should publish message from string', () => { const topic = getTopic() return ipfs.pubsub.publish(topic, 'hello friend') diff --git a/packages/interface-ipfs-core/src/refs-local.js b/packages/interface-ipfs-core/src/refs-local.js index 6824fbbdf6..6942f88afb 100644 --- a/packages/interface-ipfs-core/src/refs-local.js +++ b/packages/interface-ipfs-core/src/refs-local.js @@ -6,7 +6,6 @@ const { getDescribe, getIt, expect } = require('./utils/mocha') const all = require('it-all') const { importer } = require('ipfs-unixfs-importer') const drain = require('it-drain') -const testTimeout = require('./utils/test-timeout') const CID = require('cids') const uint8ArrayEquals = require('uint8arrays/equals') @@ -30,12 +29,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing local refs', () => { - return testTimeout(() => drain(ipfs.refs.local({ - timeout: 1 - }))) - }) - it('should get local refs', async function () { const content = (name) => ({ path: `test-folder/${name}`, diff --git a/packages/interface-ipfs-core/src/repo/gc.js b/packages/interface-ipfs-core/src/repo/gc.js index 6ab8a46c96..50252a0dc1 100644 --- a/packages/interface-ipfs-core/src/repo/gc.js +++ b/packages/interface-ipfs-core/src/repo/gc.js @@ -6,7 +6,6 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { DAGNode } = require('ipld-dag-pb') const all = require('it-all') const drain = require('it-drain') -const testTimeout = require('../utils/test-timeout') const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -27,12 +26,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when garbage collecting', () => { - return testTimeout(() => ipfs.repo.gc({ - timeout: 1 - })) - }) - it('should run garbage collection', async () => { const res = await ipfs.add(uint8ArrayFromString('apples')) diff --git a/packages/interface-ipfs-core/src/repo/stat.js b/packages/interface-ipfs-core/src/repo/stat.js index b766c7b219..ae9a002633 100644 --- a/packages/interface-ipfs-core/src/repo/stat.js +++ b/packages/interface-ipfs-core/src/repo/stat.js @@ -3,7 +3,6 @@ const { expectIsRepo } = require('../stats/utils') const { getDescribe, getIt } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,12 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting repo stats', () => { - return testTimeout(() => ipfs.repo.stat({ - timeout: 1 - })) - }) - it('should get repo stats', async () => { const res = await ipfs.repo.stat() expectIsRepo(null, res) diff --git a/packages/interface-ipfs-core/src/repo/version.js b/packages/interface-ipfs-core/src/repo/version.js index d431e434ee..3010424c82 100644 --- a/packages/interface-ipfs-core/src/repo/version.js +++ b/packages/interface-ipfs-core/src/repo/version.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,12 +21,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting the repo version', () => { - return testTimeout(() => ipfs.repo.version({ - timeout: 1 - })) - }) - it('should get the repo version', async () => { const version = await ipfs.repo.version() expect(version).to.exist() diff --git a/packages/interface-ipfs-core/src/stats/bitswap.js b/packages/interface-ipfs-core/src/stats/bitswap.js index ad1da81f56..3189cf225a 100644 --- a/packages/interface-ipfs-core/src/stats/bitswap.js +++ b/packages/interface-ipfs-core/src/stats/bitswap.js @@ -3,7 +3,6 @@ const { getDescribe, getIt } = require('../utils/mocha') const { expectIsBitswap } = require('./utils') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,12 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting bitswap stats', () => { - return testTimeout(() => ipfs.stats.bitswap({ - timeout: 1 - })) - }) - it('should get bitswap stats', async () => { const res = await ipfs.stats.bitswap() expectIsBitswap(null, res) diff --git a/packages/interface-ipfs-core/src/stats/bw.js b/packages/interface-ipfs-core/src/stats/bw.js index 64c09515cb..2b3a2d5479 100644 --- a/packages/interface-ipfs-core/src/stats/bw.js +++ b/packages/interface-ipfs-core/src/stats/bw.js @@ -4,7 +4,6 @@ const { expectIsBandwidth } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const last = require('it-last') -const testTimeout = require('../utils/test-timeout') const all = require('it-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -25,12 +24,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting bandwith stats', () => { - return testTimeout(() => ipfs.stats.bw({ - timeout: 1 - })) - }) - it('should get bandwidth stats ', async () => { const res = await last(ipfs.stats.bw()) expectIsBandwidth(null, res) diff --git a/packages/interface-ipfs-core/src/stats/repo.js b/packages/interface-ipfs-core/src/stats/repo.js index cc7d40e802..d6972d5399 100644 --- a/packages/interface-ipfs-core/src/stats/repo.js +++ b/packages/interface-ipfs-core/src/stats/repo.js @@ -3,7 +3,6 @@ const { expectIsRepo } = require('./utils') const { getDescribe, getIt } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,12 +22,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when getting repo stats', () => { - return testTimeout(() => ipfs.stats.repo({ - timeout: 1 - })) - }) - it('should get repo stats', async () => { const res = await ipfs.stats.repo() expectIsRepo(null, res) diff --git a/packages/interface-ipfs-core/src/swarm/addrs.js b/packages/interface-ipfs-core/src/swarm/addrs.js index d6d2889004..810f80027e 100644 --- a/packages/interface-ipfs-core/src/swarm/addrs.js +++ b/packages/interface-ipfs-core/src/swarm/addrs.js @@ -2,10 +2,9 @@ 'use strict' const CID = require('cids') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') -const testTimeout = require('../utils/test-timeout') const getIpfsOptions = require('../utils/ipfs-options-websockets-filter-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -33,12 +32,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing swarm addresses', () => { - return testTimeout(() => ipfsA.swarm.addrs({ - timeout: 1 - })) - }) - it('should get a list of node addresses', async () => { const peers = await ipfsA.swarm.addrs() expect(peers).to.not.be.empty() diff --git a/packages/interface-ipfs-core/src/swarm/connect.js b/packages/interface-ipfs-core/src/swarm/connect.js index 76f92c3c5d..2dae4cacb9 100644 --- a/packages/interface-ipfs-core/src/swarm/connect.js +++ b/packages/interface-ipfs-core/src/swarm/connect.js @@ -3,7 +3,6 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') -const testTimeout = require('../utils/test-timeout') const getIpfsOptions = require('../utils/ipfs-options-websockets-filter-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -40,11 +39,5 @@ module.exports = (common, options) => { peers = await ipfsA.swarm.peers() expect(peers).to.have.length.above(0) }) - - it('should respect timeout option when connecting to a remote peer', () => { - return testTimeout(() => ipfsA.swarm.connect(ipfsB.peerId.addresses[0], { - timeout: 1 - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/swarm/disconnect.js b/packages/interface-ipfs-core/src/swarm/disconnect.js index 09230535e9..d70c6edd76 100644 --- a/packages/interface-ipfs-core/src/swarm/disconnect.js +++ b/packages/interface-ipfs-core/src/swarm/disconnect.js @@ -3,7 +3,6 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') -const testTimeout = require('../utils/test-timeout') const getIpfsOptions = require('../utils/ipfs-options-websockets-filter-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -45,11 +44,5 @@ module.exports = (common, options) => { peers = await ipfsA.swarm.peers() expect(peers).to.have.length(0) }) - - it('should respect timeout option when disconnecting from a remote peer', () => { - return testTimeout(() => ipfsA.swarm.disconnect(ipfsB.peerId.addresses[0], { - timeout: 1 - })) - }) }) } diff --git a/packages/interface-ipfs-core/src/swarm/local-addrs.js b/packages/interface-ipfs-core/src/swarm/local-addrs.js index 434bcb213e..45da62461d 100644 --- a/packages/interface-ipfs-core/src/swarm/local-addrs.js +++ b/packages/interface-ipfs-core/src/swarm/local-addrs.js @@ -3,7 +3,6 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') -const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -25,12 +24,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing local addresses', () => { - return testTimeout(() => ipfs.swarm.localAddrs({ - timeout: 1 - })) - }) - it('should list local addresses the node is listening on', async () => { const multiaddrs = await ipfs.swarm.localAddrs() diff --git a/packages/interface-ipfs-core/src/swarm/peers.js b/packages/interface-ipfs-core/src/swarm/peers.js index ad36c7c623..08b08c8f26 100644 --- a/packages/interface-ipfs-core/src/swarm/peers.js +++ b/packages/interface-ipfs-core/src/swarm/peers.js @@ -1,12 +1,11 @@ /* eslint-env mocha */ 'use strict' -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const CID = require('cids') const delay = require('delay') const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') const { getDescribe, getIt, expect } = require('../utils/mocha') -const testTimeout = require('../utils/test-timeout') const getIpfsOptions = require('../utils/ipfs-options-websockets-filter-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ @@ -36,12 +35,6 @@ module.exports = (common, options) => { after(() => common.clean()) - it('should respect timeout option when listing swarm peers', () => { - return testTimeout(() => ipfsA.swarm.peers({ - timeout: 1 - })) - }) - it('should list peers this node is connected to', async () => { const peers = await ipfsA.swarm.peers() expect(peers).to.have.length.above(0) @@ -49,7 +42,7 @@ module.exports = (common, options) => { const peer = peers[0] expect(peer).to.have.a.property('addr') - expect(multiaddr.isMultiaddr(peer.addr)).to.equal(true) + expect(Multiaddr.isMultiaddr(peer.addr)).to.equal(true) expect(peer).to.have.a.property('peer').that.is.a('string') expect(CID.isCID(new CID(peer.peer))).to.equal(true) expect(peer).to.not.have.a.property('latency') @@ -66,7 +59,7 @@ module.exports = (common, options) => { const peer = peers[0] expect(peer).to.have.a.property('addr') - expect(multiaddr.isMultiaddr(peer.addr)).to.equal(true) + expect(Multiaddr.isMultiaddr(peer.addr)).to.equal(true) expect(peer).to.have.a.property('peer') expect(peer).to.have.a.property('latency') expect(peer.latency).to.match(/n\/a|[0-9]+[mµ]?s/) // n/a or 3ms or 3µs or 3s @@ -118,7 +111,13 @@ module.exports = (common, options) => { '/ip4/127.0.0.1/tcp/26546/ws' ]) - const nodeA = (await common.spawn({ type: 'proc', ipfsOptions })).api + const nodeA = (await common.spawn({ + // browser nodes have webrtc-star addresses which can't be dialled by go so make the other + // peer a js-ipfs node to get a tcp address that can be dialled. Also, webworkers are not + // diable so don't use a in-proc node for webworkers + type: ((isBrowser && common.opts.type === 'go') || isWebWorker) ? 'js' : 'proc', + ipfsOptions + })).api const nodeB = (await common.spawn({ type: isWebWorker ? 'go' : undefined, ipfsOptions: { @@ -126,10 +125,7 @@ module.exports = (common, options) => { } })).api - // TODO: the webrtc-star transport only keeps the last listened on address around - // so the browser has to use 1 as the array index - // await nodeA.swarm.connect(nodeB.peerId.addresses[0]) - await nodeA.swarm.connect(nodeB.peerId.addresses[isBrowser ? 1 : 0]) + await nodeB.swarm.connect(nodeA.peerId.addresses[0]) await delay(1000) const peersA = await nodeA.swarm.peers() diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index 4359a3ecf0..edb4951ee9 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "byteman": "^1.3.5", - "cid-tool": "^1.0.0", + "cid-tool": "^3.0.0", "cids": "^1.1.6", "debug": "^4.1.1", "err-code": "^3.0.1", @@ -42,23 +42,23 @@ "ipfs-core-utils": "^0.7.2", "ipfs-daemon": "^0.5.4", "ipfs-http-client": "^49.0.4", - "ipfs-repo": "^9.0.0", + "ipfs-repo": "^9.1.1", "ipfs-utils": "^6.0.4", "ipld-dag-cbor": "^0.18.0", "ipld-dag-pb": "^0.22.1", "it-all": "^1.0.4", - "it-concat": "^1.0.3", + "it-concat": "^2.0.0", "it-first": "^1.0.4", "it-glob": "0.0.11", "it-pipe": "^1.1.0", "jsondiffpatch": "^0.4.1", - "libp2p-crypto": "^0.19.0", - "mafmt": "^8.0.0", - "multiaddr": "^8.0.0", - "multiaddr-to-uri": "^6.0.0", + "libp2p-crypto": "^0.19.3", + "mafmt": "^9.0.0", + "multiaddr": "^9.0.1", + "multiaddr-to-uri": "^7.0.0", "multibase": "^4.0.2", "multihashing-async": "^2.1.2", - "parse-duration": "^0.4.4", + "parse-duration": "^1.0.0", "pretty-bytes": "^5.4.1", "progress": "^2.0.3", "stream-to-it": "^0.2.2", @@ -67,15 +67,14 @@ "yargs": "^16.0.3" }, "devDependencies": { - "@types/get-folder-size": "^2.0.0", "@types/progress": "^2.0.3", "@types/yargs": "^16.0.0", - "aegir": "^32.1.0", + "aegir": "^33.0.0", "nanoid": "^3.1.12", "ncp": "^2.0.0", "peer-id": "^0.14.1", "rimraf": "^3.0.2", - "sinon": "^9.0.3", + "sinon": "^10.0.1", "string-argv": "^0.3.1", "temp-write": "^4.0.0" } diff --git a/packages/ipfs-cli/src/commands/add.js b/packages/ipfs-cli/src/commands/add.js index f3672910a3..fa914cff09 100644 --- a/packages/ipfs-cli/src/commands/add.js +++ b/packages/ipfs-cli/src/commands/add.js @@ -2,6 +2,7 @@ 'use strict' const { promisify } = require('util') +// @ts-ignore no types const getFolderSize = promisify(require('get-folder-size')) // @ts-ignore no types const byteman = require('byteman') diff --git a/packages/ipfs-cli/src/commands/bootstrap/add.js b/packages/ipfs-cli/src/commands/bootstrap/add.js index bfc97b9fb5..dade7eb41a 100644 --- a/packages/ipfs-cli/src/commands/bootstrap/add.js +++ b/packages/ipfs-cli/src/commands/bootstrap/add.js @@ -27,7 +27,7 @@ module.exports = { /** * @param {object} argv * @param {import('../../types').Context} argv.ctx - * @param {import('multiaddr')} argv.peer + * @param {import('multiaddr').Multiaddr} argv.peer * @param {boolean} argv.default * @param {number} argv.timeout */ diff --git a/packages/ipfs-cli/src/commands/bootstrap/rm.js b/packages/ipfs-cli/src/commands/bootstrap/rm.js index 27bb6b73d2..3756fb6aee 100644 --- a/packages/ipfs-cli/src/commands/bootstrap/rm.js +++ b/packages/ipfs-cli/src/commands/bootstrap/rm.js @@ -27,7 +27,7 @@ module.exports = { /** * @param {object} argv * @param {import('../../types').Context} argv.ctx - * @param {import('multiaddr')} argv.peer + * @param {import('multiaddr').Multiaddr} argv.peer * @param {boolean} argv.all * @param {number} argv.timeout */ diff --git a/packages/ipfs-cli/src/commands/swarm/connect.js b/packages/ipfs-cli/src/commands/swarm/connect.js index 23a22ccb75..7460254fa5 100644 --- a/packages/ipfs-cli/src/commands/swarm/connect.js +++ b/packages/ipfs-cli/src/commands/swarm/connect.js @@ -24,7 +24,7 @@ module.exports = { /** * @param {object} argv * @param {import('../../types').Context} argv.ctx - * @param {import('multiaddr')} argv.address + * @param {import('multiaddr').Multiaddr} argv.address * @param {number} argv.timeout */ async handler ({ ctx: { ipfs, isDaemon, print }, address, timeout }) { diff --git a/packages/ipfs-cli/src/commands/swarm/disconnect.js b/packages/ipfs-cli/src/commands/swarm/disconnect.js index d08b5164b6..f25c020191 100644 --- a/packages/ipfs-cli/src/commands/swarm/disconnect.js +++ b/packages/ipfs-cli/src/commands/swarm/disconnect.js @@ -24,7 +24,7 @@ module.exports = { /** * @param {object} argv * @param {import('../../types').Context} argv.ctx - * @param {import('multiaddr')} argv.address + * @param {import('multiaddr').Multiaddr} argv.address * @param {number} argv.timeout */ async handler ({ ctx: { ipfs, isDaemon, print }, address, timeout }) { diff --git a/packages/ipfs-cli/src/commands/swarm/peers.js b/packages/ipfs-cli/src/commands/swarm/peers.js index bf438a3fb1..b192083642 100644 --- a/packages/ipfs-cli/src/commands/swarm/peers.js +++ b/packages/ipfs-cli/src/commands/swarm/peers.js @@ -1,7 +1,7 @@ 'use strict' const mafmt = require('mafmt') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const { default: parseDuration } = require('parse-duration') module.exports = { @@ -31,7 +31,7 @@ module.exports = { }) result.forEach((item) => { - let ma = multiaddr(`${item.addr}`) + let ma = new Multiaddr(`${item.addr}`) if (!mafmt.IPFS.matches(ma)) { ma = ma.encapsulate(`/ipfs/${item.peer}`) diff --git a/packages/ipfs-cli/src/utils.js b/packages/ipfs-cli/src/utils.js index 066a14c256..74702bd2a2 100644 --- a/packages/ipfs-cli/src/utils.js +++ b/packages/ipfs-cli/src/utils.js @@ -9,7 +9,7 @@ const Progress = require('progress') const byteman = require('byteman') const IPFS = require('ipfs-core') const CID = require('cids') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const { cidToString } = require('ipfs-core-utils/src/cid') const uint8ArrayFromString = require('uint8arrays/from-string') diff --git a/packages/ipfs-cli/test/bootstrap.js b/packages/ipfs-cli/test/bootstrap.js index e0bba5cf00..b240b8b055 100644 --- a/packages/ipfs-cli/test/bootstrap.js +++ b/packages/ipfs-cli/test/bootstrap.js @@ -4,10 +4,10 @@ const { expect } = require('aegir/utils/chai') const cli = require('./utils/cli') const sinon = require('sinon') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') describe('bootstrap', () => { - const peer = multiaddr('/ip4/111.111.111.111/tcp/1001/p2p/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD') + const peer = new Multiaddr('/ip4/111.111.111.111/tcp/1001/p2p/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD') let ipfs before(() => { diff --git a/packages/ipfs-cli/test/swarm.js b/packages/ipfs-cli/test/swarm.js index e173d3a555..4509b48831 100644 --- a/packages/ipfs-cli/test/swarm.js +++ b/packages/ipfs-cli/test/swarm.js @@ -5,7 +5,7 @@ const { expect } = require('aegir/utils/chai') const cli = require('./utils/cli') const sinon = require('sinon') -const ma = require('multiaddr') +const { Multiaddr } = require('multiaddr') describe('swarm', () => { let ipfs @@ -28,7 +28,7 @@ describe('swarm', () => { } it('connect online', async () => { - const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + const multiaddr = new Multiaddr('/ip4/123.123.123.123/tcp/482') ipfs.swarm.connect.withArgs(multiaddr, defaultOptions).resolves() @@ -37,7 +37,7 @@ describe('swarm', () => { }) it('connect offline', async () => { - const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + const multiaddr = new Multiaddr('/ip4/123.123.123.123/tcp/482') const out = await cli.fail(`swarm connect ${multiaddr}`, { ipfs, isDaemon: false }) expect(out).to.include('This command must be run in online mode') @@ -46,7 +46,7 @@ describe('swarm', () => { }) it('connect with timeout', async () => { - const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + const multiaddr = new Multiaddr('/ip4/123.123.123.123/tcp/482') ipfs.swarm.connect.withArgs(multiaddr, { ...defaultOptions, @@ -110,7 +110,7 @@ describe('swarm', () => { ipfs.swarm.addrs.withArgs(defaultOptions).resolves([{ id: peer, addrs: [ - ma(addr) + new Multiaddr(addr) ] }]) @@ -128,7 +128,7 @@ describe('swarm', () => { }).resolves([{ id: peer, addrs: [ - ma(addr) + new Multiaddr(addr) ] }]) @@ -175,20 +175,20 @@ describe('swarm', () => { } it('disconnect online', async () => { - const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + const multiaddr = new Multiaddr('/ip4/123.123.123.123/tcp/482') ipfs.swarm.disconnect.withArgs(multiaddr, defaultOptions).resolves() const out = await cli(`swarm disconnect ${multiaddr}`, { ipfs, isDaemon: true }) expect(out).to.equal(`${multiaddr}\n`) }) it('disconnect offline', async () => { - const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + const multiaddr = new Multiaddr('/ip4/123.123.123.123/tcp/482') const out = await cli.fail(`swarm disconnect ${multiaddr}`, { ipfs, isDaemon: false }) expect(out).to.include('This command must be run in online mode') }) it('disconnect with timeout', async () => { - const multiaddr = ma('/ip4/123.123.123.123/tcp/482') + const multiaddr = new Multiaddr('/ip4/123.123.123.123/tcp/482') ipfs.swarm.disconnect.withArgs(multiaddr, { ...defaultOptions, timeout: 1000 diff --git a/packages/ipfs-client/.aegir.js b/packages/ipfs-client/.aegir.js index 358a154f0b..3e94bf32cf 100644 --- a/packages/ipfs-client/.aegir.js +++ b/packages/ipfs-client/.aegir.js @@ -3,6 +3,6 @@ /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '137kB' + bundlesizeMax: '127kB' } } diff --git a/packages/ipfs-client/package.json b/packages/ipfs-client/package.json index 8cbce7067e..8d43aa35d9 100644 --- a/packages/ipfs-client/package.json +++ b/packages/ipfs-client/package.json @@ -37,7 +37,7 @@ "merge-options": "^3.0.4" }, "devDependencies": { - "aegir": "^32.1.0", + "aegir": "^33.0.0", "rimraf": "^3.0.2" } } diff --git a/packages/ipfs-client/src/index.js b/packages/ipfs-client/src/index.js index e4e14466cd..4fe4fd57ba 100644 --- a/packages/ipfs-client/src/index.js +++ b/packages/ipfs-client/src/index.js @@ -7,7 +7,7 @@ const mergeOptions = require('merge-options') /** * @typedef {import('ipfs-http-client').Options} HTTPOptions * @typedef {import('ipfs-grpc-client').Options} GRPCOptions - * @typedef {string|URL|import('multiaddr')} Address + * @typedef {string|URL|import('multiaddr').Multiaddr} Address * @typedef {{http?: Address, grpc?: Address} & Partial} Options * * @param {Options} [opts] diff --git a/packages/ipfs-core-types/package.json b/packages/ipfs-core-types/package.json index a57b69dfac..fe9289074c 100644 --- a/packages/ipfs-core-types/package.json +++ b/packages/ipfs-core-types/package.json @@ -30,11 +30,11 @@ "dependencies": { "cids": "^1.1.6", "ipld": "^0.29.0", - "multiaddr": "^8.0.0", + "multiaddr": "^9.0.1", "multibase": "^4.0.2" }, "devDependencies": { - "aegir": "^32.1.0" + "aegir": "^33.0.0" }, "contributors": [ "Irakli Gozalishvili " diff --git a/packages/ipfs-core-types/src/bitswap/index.d.ts b/packages/ipfs-core-types/src/bitswap/index.d.ts index 7737cb222b..e5cf40e119 100644 --- a/packages/ipfs-core-types/src/bitswap/index.d.ts +++ b/packages/ipfs-core-types/src/bitswap/index.d.ts @@ -60,7 +60,7 @@ export interface API { export interface Stats { provideBufLen: number wantlist: CID[] - peers: CID[] + peers: string[] blocksReceived: BigInt dataReceived: BigInt blocksSent: BigInt diff --git a/packages/ipfs-core-types/src/bootstrap/index.ts b/packages/ipfs-core-types/src/bootstrap/index.ts index b9be74e76e..cc2c0a6257 100644 --- a/packages/ipfs-core-types/src/bootstrap/index.ts +++ b/packages/ipfs-core-types/src/bootstrap/index.ts @@ -1,5 +1,5 @@ import type { AbortOptions } from '../utils' -import type Multiaddr from 'multiaddr' +import type { Multiaddr } from 'multiaddr' export interface API { /** diff --git a/packages/ipfs-core-types/src/config/index.d.ts b/packages/ipfs-core-types/src/config/index.d.ts index a1de611046..0c21ea3936 100644 --- a/packages/ipfs-core-types/src/config/index.d.ts +++ b/packages/ipfs-core-types/src/config/index.d.ts @@ -30,11 +30,11 @@ export interface API { } export interface Config { - Addresses: AddressConfig + Addresses?: AddressConfig API?: APIConfig, Profiles?: string - Bootstrap: string[] - Discovery: DiscoveryConfig + Bootstrap?: string[] + Discovery?: DiscoveryConfig Datastore?: DatastoreConfig Identity?: IdentityConfig Keychain?: KeychainConfig @@ -51,7 +51,7 @@ export interface AddressConfig { RPC?: string Delegates?: string[] Gateway?: string - Swarm: string[] + Swarm?: string[] } export interface APIConfig { @@ -59,8 +59,8 @@ export interface APIConfig { } export interface DiscoveryConfig { - MDNS: MDNSDiscovery - webRTCStar: WebRTCStarDiscovery + MDNS?: MDNSDiscovery + webRTCStar?: WebRTCStarDiscovery } export interface MDNSDiscovery { @@ -76,15 +76,31 @@ export interface DatastoreConfig { Spec?: DatastoreSpec } -export interface DatastoreSpec { +export interface DatastoreType { + type: string, + path: string, + sync?: boolean, + shardFunc?: string, + compression?: string +} +export interface DatastoreMountPoint { + mountpoint: string, + type: string, + prefix: string, + child: DatastoreType +} + +export interface DatastoreSpec { + type?: string, + mounts?: DatastoreMountPoint[] } export interface IdentityConfig { /** * The unique PKI identity label for this configs peer. Set on init and never - * read, its merely here for convenience. IPFS will always generate the peerID - * from its keypair at runtime. + * read, its merely here for convenience. IPFS will always generate the peerID + * from its keypair at runtime. */ PeerID: string diff --git a/packages/ipfs-core-types/src/dht/index.d.ts b/packages/ipfs-core-types/src/dht/index.d.ts index 1e1db25d50..00c4aeaea1 100644 --- a/packages/ipfs-core-types/src/dht/index.d.ts +++ b/packages/ipfs-core-types/src/dht/index.d.ts @@ -1,5 +1,5 @@ import type { AbortOptions } from '../utils' -import type Multiaddr from 'multiaddr' +import type { Multiaddr } from 'multiaddr' import type CID from 'cids' export interface API { diff --git a/packages/ipfs-core-types/src/pin/remote/index.d.ts b/packages/ipfs-core-types/src/pin/remote/index.d.ts index 5fe9265b04..63395c350a 100644 --- a/packages/ipfs-core-types/src/pin/remote/index.d.ts +++ b/packages/ipfs-core-types/src/pin/remote/index.d.ts @@ -1,5 +1,5 @@ import CID from 'cids' -import Multiaddr from 'multiaddr' +import { Multiaddr } from 'multiaddr' import { API as Service } from './service' import { AbortOptions } from '../../utils' diff --git a/packages/ipfs-core-types/src/root.d.ts b/packages/ipfs-core-types/src/root.d.ts index f6293a6374..dba7e3e22f 100644 --- a/packages/ipfs-core-types/src/root.d.ts +++ b/packages/ipfs-core-types/src/root.d.ts @@ -1,7 +1,7 @@ import { AbortOptions, PreloadOptions, IPFSPath, ImportSource, ToEntry } from './utils' import CID, { CIDVersion } from 'cids' import { Mtime } from 'ipfs-unixfs' -import Multiaddr from 'multiaddr' +import { Multiaddr } from 'multiaddr' import { BaseName } from 'multibase' export interface API { diff --git a/packages/ipfs-core-types/src/swarm/index.d.ts b/packages/ipfs-core-types/src/swarm/index.d.ts index ea2508f2bd..69b1ba872b 100644 --- a/packages/ipfs-core-types/src/swarm/index.d.ts +++ b/packages/ipfs-core-types/src/swarm/index.d.ts @@ -2,7 +2,7 @@ import type { AbortOptions } from '../utils' import { API as BitswapAPI } from '../bitswap' import { API as RepoAPI } from '../repo' import type CID from 'cids' -import type Multiaddr from 'multiaddr' +import type { Multiaddr } from 'multiaddr' export interface API { /** diff --git a/packages/ipfs-core-types/src/utils.d.ts b/packages/ipfs-core-types/src/utils.d.ts index 67540e17bc..1ff3a28fdf 100644 --- a/packages/ipfs-core-types/src/utils.d.ts +++ b/packages/ipfs-core-types/src/utils.d.ts @@ -131,3 +131,57 @@ export interface BufferStore { get: (key: Uint8Array) => Promise stores: any[] } + +export interface Blockstore { + open: () => Promise + + /** + * Query the store + */ + query: (Query, options?: DatastoreOptions) => AsyncIterable + + /** + * Query the store, returning only keys + */ + queryKeys: (query: KeyQuery, options?: DatastoreOptions) => AsyncIterable + + /** + * Get a single block by CID + */ + get: (cid: CID, options?: DatastoreOptions) => Promise + + /** + * Like get, but for more + */ + getMany: (cids: AwaitIterable, options?: DatastoreOptions) => AsyncIterable + + /** + * Write a single block to the store + */ + put: (block: Block, options?: DatastoreOptions) => Promise + + /** + * Like put, but for more + */ + putMany: (blocks: AwaitIterable, options?: DatastoreOptions) => AsyncIterable + + /** + * Does the store contain block with this CID? + */ + has: (cid: CID, options?: DatastoreOptions) => Promise + + /** + * Delete a block from the store + */ + delete: (cid: CID, options?: DatastoreOptions) => Promise + + /** + * Delete a block from the store + */ + deleteMany: (cids: AwaitIterable, options?: DatastoreOptions) => AsyncIterable + + /** + * Close the store + */ + close: () => Promise +} diff --git a/packages/ipfs-core-utils/package.json b/packages/ipfs-core-utils/package.json index 7b7e89a6fe..2755a324ef 100644 --- a/packages/ipfs-core-utils/package.json +++ b/packages/ipfs-core-utils/package.json @@ -47,19 +47,19 @@ "cids": "^1.1.6", "err-code": "^3.0.1", "ipfs-core-types": "^0.3.1", - "ipfs-unixfs": "^4.0.1", + "ipfs-unixfs": "^4.0.3", "ipfs-utils": "^6.0.4", "it-all": "^1.0.4", "it-map": "^1.0.4", "it-peekable": "^1.0.1", - "multiaddr": "^8.0.0", - "multiaddr-to-uri": "^6.0.0", - "parse-duration": "^0.4.4", + "multiaddr": "^9.0.1", + "multiaddr-to-uri": "^7.0.0", + "parse-duration": "^1.0.0", "timeout-abort-controller": "^1.1.1", "uint8arrays": "^2.1.3" }, "devDependencies": { - "aegir": "^32.1.0", + "aegir": "^33.0.0", "rimraf": "^3.0.2" } } diff --git a/packages/ipfs-core-utils/src/to-url-string.js b/packages/ipfs-core-utils/src/to-url-string.js index 877b1f5a0c..198175828a 100644 --- a/packages/ipfs-core-utils/src/to-url-string.js +++ b/packages/ipfs-core-utils/src/to-url-string.js @@ -1,6 +1,6 @@ 'use strict' -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') // @ts-ignore no types const multiAddrToUri = require('multiaddr-to-uri') @@ -11,14 +11,10 @@ const multiAddrToUri = require('multiaddr-to-uri') module.exports = (url) => { try { // @ts-expect-error - url = multiAddrToUri(multiaddr(url)) + url = multiAddrToUri(new Multiaddr(url)) } catch (err) { } url = url.toString() return url } - -/** - * @typedef {import('multiaddr')} Multiaddr - */ diff --git a/packages/ipfs-core/.aegir.js b/packages/ipfs-core/.aegir.js index 73bad951ae..35c38a3a8c 100644 --- a/packages/ipfs-core/.aegir.js +++ b/packages/ipfs-core/.aegir.js @@ -70,7 +70,7 @@ module.exports = { } }, build: { - bundlesizeMax: '614kB', + bundlesizeMax: '542KB', config: esbuild } } diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index 8f26e64c8e..c13b62e3d3 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -62,76 +62,77 @@ "cborg": "^1.2.1", "cids": "^1.1.6", "dag-cbor-links": "^2.0.0", - "datastore-core": "^3.0.0", - "datastore-pubsub": "^0.5.0", + "datastore-core": "^4.0.0", + "datastore-pubsub": "^0.6.1", "debug": "^4.1.1", "dlv": "^1.1.3", "err-code": "^3.0.1", "hamt-sharding": "^2.0.0", "hashlru": "^2.3.0", - "interface-datastore": "^3.0.3", - "ipfs-bitswap": "^5.0.1", + "interface-datastore": "^4.0.0", + "ipfs-bitswap": "^5.0.3", "ipfs-block-service": "^0.19.0", "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", - "ipfs-repo": "^9.0.0", - "ipfs-unixfs": "^4.0.1", - "ipfs-unixfs-exporter": "^5.0.1", - "ipfs-unixfs-importer": "^7.0.1", + "ipfs-repo": "^9.1.1", + "ipfs-unixfs": "^4.0.3", + "ipfs-unixfs-exporter": "^5.0.3", + "ipfs-unixfs-importer": "^7.0.3", "ipfs-utils": "^6.0.4", "ipld": "^0.29.0", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^0.18.0", "ipld-dag-pb": "^0.22.1", "ipld-raw": "^7.0.0", - "ipns": "^0.10.0", + "ipns": "^0.11.0", "is-domain-name": "^1.0.1", - "is-ipfs": "^4.0.0", + "is-ipfs": "^5.0.0", "it-all": "^1.0.4", "it-drain": "^1.0.3", "it-first": "^1.0.4", "it-last": "^1.0.4", "it-map": "^1.0.4", "it-pipe": "^1.1.0", - "libp2p": "^0.30.12", - "libp2p-bootstrap": "^0.12.1", - "libp2p-crypto": "^0.19.0", - "libp2p-floodsub": "^0.24.1", - "libp2p-gossipsub": "^0.8.0", - "libp2p-kad-dht": "^0.21.0", - "libp2p-mdns": "^0.15.0", - "libp2p-mplex": "^0.10.0", - "libp2p-noise": "^2.0.1", - "libp2p-record": "^0.10.0", - "libp2p-tcp": "^0.15.1", - "libp2p-webrtc-star": "^0.21.0", - "libp2p-websockets": "^0.15.1", - "mafmt": "^8.0.0", + "just-safe-set": "^2.2.1", + "libp2p": "^0.31.0-rc.6", + "libp2p-bootstrap": "^0.12.3", + "libp2p-crypto": "^0.19.3", + "libp2p-floodsub": "^0.25.1", + "libp2p-gossipsub": "ChainSafe/js-libp2p-gossipsub#chore/update-deps-and-remove-protons", + "libp2p-kad-dht": "libp2p/js-libp2p-kad-dht#chore/update-deps-12-04-2021", + "libp2p-mdns": "^0.16.0", + "libp2p-mplex": "^0.10.2", + "libp2p-noise": "^3.0.0", + "libp2p-record": "^0.10.3", + "libp2p-tcp": "^0.15.4", + "libp2p-webrtc-star": "^0.22.2", + "libp2p-websockets": "^0.15.6", + "mafmt": "^9.0.0", "merge-options": "^3.0.4", "mortice": "^2.0.0", - "multiaddr": "^8.0.0", - "multiaddr-to-uri": "^6.0.0", + "multiaddr": "^9.0.1", + "multiaddr-to-uri": "^7.0.0", "multibase": "^4.0.2", "multicodec": "^3.0.1", "multihashing-async": "^2.1.2", "native-abort-controller": "^1.0.3", "p-queue": "^6.6.1", - "parse-duration": "^0.4.4", + "parse-duration": "^1.0.0", "peer-id": "^0.14.1", "streaming-iterables": "^5.0.2", "uint8arrays": "^2.1.3" }, "devDependencies": { "@types/dlv": "^1.1.2", - "aegir": "^32.1.0", + "aegir": "^33.0.0", "delay": "^5.0.0", "go-ipfs": "0.8.0", "interface-ipfs-core": "^0.144.2", - "ipfsd-ctl": "^8.0.0", + "ipfsd-ctl": "^8.0.1", "ipld-git": "^0.6.1", "iso-url": "^1.0.0", "nanoid": "^3.1.12", "rimraf": "^3.0.2", - "sinon": "^9.0.3" + "sinon": "^10.0.1" } } diff --git a/packages/ipfs-core/src/components/bitswap/stat.js b/packages/ipfs-core/src/components/bitswap/stat.js index fae73a9cff..5301c41005 100644 --- a/packages/ipfs-core/src/components/bitswap/stat.js +++ b/packages/ipfs-core/src/components/bitswap/stat.js @@ -1,6 +1,5 @@ 'use strict' -const CID = require('cids') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') /** @@ -20,7 +19,7 @@ module.exports = ({ network }) => { provideBufLen: parseInt(snapshot.providesBufferLength.toString()), blocksReceived: BigInt(snapshot.blocksReceived.toString()), wantlist: Array.from(bitswap.getWantlist()).map(e => e[1].cid), - peers: bitswap.peers().map(id => new CID(id.toB58String())), + peers: bitswap.peers().map(id => id.toB58String()), dupBlksReceived: BigInt(snapshot.dupBlksReceived.toString()), dupDataReceived: BigInt(snapshot.dupDataReceived.toString()), dataReceived: BigInt(snapshot.dataReceived.toString()), diff --git a/packages/ipfs-core/src/components/bootstrap/clear.js b/packages/ipfs-core/src/components/bootstrap/clear.js index f4a8e672a9..eea3666444 100644 --- a/packages/ipfs-core/src/components/bootstrap/clear.js +++ b/packages/ipfs-core/src/components/bootstrap/clear.js @@ -1,7 +1,7 @@ 'use strict' const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @param {Object} config diff --git a/packages/ipfs-core/src/components/bootstrap/list.js b/packages/ipfs-core/src/components/bootstrap/list.js index 3bd9d3c06f..4501a38aec 100644 --- a/packages/ipfs-core/src/components/bootstrap/list.js +++ b/packages/ipfs-core/src/components/bootstrap/list.js @@ -1,7 +1,7 @@ 'use strict' const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @param {Object} config diff --git a/packages/ipfs-core/src/components/bootstrap/reset.js b/packages/ipfs-core/src/components/bootstrap/reset.js index c1bcf951b5..f8d1a134bd 100644 --- a/packages/ipfs-core/src/components/bootstrap/reset.js +++ b/packages/ipfs-core/src/components/bootstrap/reset.js @@ -2,7 +2,7 @@ const defaultConfig = require('../../runtime/config-nodejs.js') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @param {Object} config diff --git a/packages/ipfs-core/src/components/config.js b/packages/ipfs-core/src/components/config.js index c20169573e..6fc3e3455b 100644 --- a/packages/ipfs-core/src/components/config.js +++ b/packages/ipfs-core/src/components/config.js @@ -1,5 +1,6 @@ 'use strict' +const set = require('just-safe-set') const getDefaultConfig = require('../runtime/config-nodejs.js') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') const log = require('debug')('ipfs:core:config') @@ -115,8 +116,8 @@ const profiles = { server: { description: 'Recommended for nodes with public IPv4 address (servers, VPSes, etc.), disables host and content discovery and UPnP in local networks.', transform: (config) => { - config.Discovery.MDNS.Enabled = false - config.Discovery.webRTCStar.Enabled = false + set(config, 'Discovery.MDNS.Enabled', false) + set(config, 'Discovery.webRTCStar.Enabled', false) config.Swarm = { ...(config.Swarm || {}), DisableNatPortMap: true @@ -128,12 +129,12 @@ const profiles = { 'local-discovery': { description: 'Sets default values to fields affected by `server` profile, enables discovery and UPnP in local networks.', transform: (config) => { - config.Discovery.MDNS.Enabled = true - config.Discovery.webRTCStar.Enabled = true - config.Swarm = { + set(config, 'Discovery.MDNS.Enabled', true) + set(config, 'Discovery.webRTCStar.Enabled', true) + set(config, 'Swarm', { ...(config.Swarm || {}), DisableNatPortMap: false - } + }) return config } @@ -143,17 +144,17 @@ const profiles = { transform: (config) => { const defaultConfig = getDefaultConfig() - config.Addresses.API = defaultConfig.Addresses.API ? '/ip4/127.0.0.1/tcp/0' : '' - config.Addresses.Gateway = defaultConfig.Addresses.Gateway ? '/ip4/127.0.0.1/tcp/0' : '' - config.Addresses.Swarm = defaultConfig.Addresses.Swarm.length ? ['/ip4/127.0.0.1/tcp/0'] : [] - config.Addresses.Delegates = [] - config.Bootstrap = [] - config.Discovery.MDNS.Enabled = false - config.Discovery.webRTCStar.Enabled = false - config.Swarm = { + set(config, 'Addresses.API', defaultConfig.Addresses.API ? '/ip4/127.0.0.1/tcp/0' : '') + set(config, 'Addresses.Gateway', defaultConfig.Addresses.Gateway ? '/ip4/127.0.0.1/tcp/0' : '') + set(config, 'Addresses.Swarm', defaultConfig.Addresses.Swarm.length ? ['/ip4/127.0.0.1/tcp/0'] : []) + set(config, 'Addresses.Delegates', []) + set(config, 'Bootstrap', []) + set(config, 'Discovery.MDNS.Enabled', false) + set(config, 'Discovery.webRTCStar.Enabled', false) + set(config, 'Swarm', { ...(config.Swarm || {}), DisableNatPortMap: true - } + }) return config } @@ -163,17 +164,17 @@ const profiles = { transform: (config) => { const defaultConfig = getDefaultConfig() - config.Addresses.API = defaultConfig.Addresses.API - config.Addresses.Gateway = defaultConfig.Addresses.Gateway - config.Addresses.Swarm = defaultConfig.Addresses.Swarm - config.Addresses.Delegates = defaultConfig.Addresses.Delegates - config.Bootstrap = defaultConfig.Bootstrap - config.Discovery.MDNS.Enabled = defaultConfig.Discovery.MDNS.Enabled - config.Discovery.webRTCStar.Enabled = defaultConfig.Discovery.webRTCStar.Enabled - config.Swarm = { + set(config, 'Addresses.API', defaultConfig.Addresses.API) + set(config, 'Addresses.Gateway', defaultConfig.Addresses.Gateway) + set(config, 'Addresses.Swarm', defaultConfig.Addresses.Swarm) + set(config, 'Addresses.Delegates', defaultConfig.Addresses.Delegates) + set(config, 'Bootstrap', defaultConfig.Bootstrap) + set(config, 'Discovery.MDNS.Enabled', defaultConfig.Discovery.MDNS.Enabled) + set(config, 'Discovery.webRTCStar.Enabled', defaultConfig.Discovery.webRTCStar.Enabled) + set(config, 'Swarm', { ...(config.Swarm || {}), DisableNatPortMap: false - } + }) return config } diff --git a/packages/ipfs-core/src/components/id.js b/packages/ipfs-core/src/components/id.js index 88a94ff3ec..e4ad10338b 100644 --- a/packages/ipfs-core/src/components/id.js +++ b/packages/ipfs-core/src/components/id.js @@ -1,7 +1,7 @@ 'use strict' const pkgversion = require('../../package.json').version -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') const uint8ArrayToString = require('uint8arrays/to-string') @@ -16,7 +16,7 @@ module.exports = ({ peerId, network }) => { */ async function id (_options = {}) { // eslint-disable-line require-await const id = peerId.toB58String() - /** @type {import('multiaddr')[]} */ + /** @type {Multiaddr[]} */ let addresses = [] /** @type {string[]} */ let protocols = [] @@ -46,7 +46,7 @@ module.exports = ({ peerId, network }) => { return `${str}/p2p/${id}` }) .sort() - .map(ma => multiaddr(ma)), + .map(ma => new Multiaddr(ma)), agentVersion: `js-ipfs/${pkgversion}`, protocolVersion: '9000', protocols: protocols.sort() @@ -60,7 +60,7 @@ module.exports = ({ peerId, network }) => { * The Peer identity * @property {string} id - the Peer ID * @property {string} publicKey - the public key of the peer as a base64 encoded string - * @property {import('multiaddr')[]} addresses - A list of multiaddrs this node is listening on + * @property {Multiaddr[]} addresses - A list of multiaddrs this node is listening on * @property {string} agentVersion - The agent version * @property {string} protocolVersion - The supported protocol version * @property {string[]} protocols - The supported protocols diff --git a/packages/ipfs-core/src/components/libp2p.js b/packages/ipfs-core/src/components/libp2p.js index 236ddaa726..2fa457bf8c 100644 --- a/packages/ipfs-core/src/components/libp2p.js +++ b/packages/ipfs-core/src/components/libp2p.js @@ -10,12 +10,12 @@ const PubsubRouters = require('../runtime/libp2p-pubsub-routers-nodejs') * @property {string} [pass] * * @typedef {import('ipfs-repo')} Repo - * @typedef {import('multiaddr')} Multiaddr * @typedef {import('peer-id')} PeerId * @typedef {import('../types').Options} IPFSOptions * @typedef {import('libp2p')} LibP2P * @typedef {import('libp2p').Libp2pOptions & import('libp2p').constructorOptions} Options * @typedef {import('ipfs-core-types/src/config').Config} IPFSConfig + * @typedef {import('multiaddr').Multiaddr} Multiaddr */ /** @@ -54,7 +54,7 @@ module.exports = ({ // Required inline to reduce startup time const Libp2p = require('libp2p') - return new Libp2p(libp2pOptions) + return Libp2p.create(libp2pOptions) } /** @@ -124,18 +124,18 @@ function getLibp2pOptions ({ options, config, datastore, keys, keychainConfig, p get(config, 'Pubsub.Enabled', true)) }, nat: { - enabled: get(options, 'nat.enabled', !get(config, 'Swarm.DisableNatPortMap', false)), - ttl: get(options, 'nat.ttl', 7200), - autoUpdate: get(options, 'nat.autoUpdate', true), - gateway: get(options, 'nat.gateway'), - externalIp: get(options, 'nat.externalIp'), + enabled: get(options, 'libp2p.config.nat.enabled', !get(config, 'Swarm.DisableNatPortMap', false)), + ttl: get(options, 'libp2p.config.nat.ttl', 7200), + keepAlive: get(options, 'libp2p.config.nat.keepAlive', true), + gateway: get(options, 'libp2p.config.nat.gateway'), + externalIp: get(options, 'libp2p.config.nat.externalIp'), pmp: { - enabled: get(options, 'nat.pmp.enabled', false) + enabled: get(options, 'libp2p.config.nat.pmp.enabled', false) } } }, addresses: { - listen: multiaddrs, + listen: multiaddrs.map(ma => ma.toString()), announce: get(options, 'addresses.announce', get(config, 'Addresses.Announce', [])) }, diff --git a/packages/ipfs-core/src/components/network.js b/packages/ipfs-core/src/components/network.js index a1a940bf70..5f8d05dd9d 100644 --- a/packages/ipfs-core/src/components/network.js +++ b/packages/ipfs-core/src/components/network.js @@ -2,7 +2,7 @@ const IPFSBitswap = require('ipfs-bitswap') const createLibP2P = require('./libp2p') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const errCode = require('err-code') /** @@ -50,7 +50,7 @@ class Network { const config = await repo.config.getAll() - const libp2p = createLibP2P({ + const libp2p = await createLibP2P({ options, repo, peerId, @@ -101,7 +101,7 @@ const readAddrs = (peerId, config) => { const addrs = [] const swarm = (config.Addresses && config.Addresses.Swarm) || [] for (const addr of swarm) { - let ma = Multiaddr(addr) + let ma = new Multiaddr(addr) // Temporary error for users migrating using websocket-star multiaddrs for listenning on libp2p // websocket-star support was removed from ipfs and libp2p diff --git a/packages/ipfs-core/src/components/refs/local.js b/packages/ipfs-core/src/components/refs/local.js index e8a87bdd63..8c03835080 100644 --- a/packages/ipfs-core/src/components/refs/local.js +++ b/packages/ipfs-core/src/components/refs/local.js @@ -11,8 +11,7 @@ module.exports = function ({ repo }) { * @type {import('ipfs-core-types/src/refs').API["local"]} */ async function * refsLocal (options = {}) { - // @ts-ignore - TS is not aware of keysOnly - for await (const cid of repo.blocks.query({ keysOnly: true, signal: options.signal })) { + for await (const cid of repo.blocks.queryKeys({}, { signal: options.signal })) { yield { ref: cid.toString() } } } diff --git a/packages/ipfs-core/src/components/repo/gc.js b/packages/ipfs-core/src/components/repo/gc.js index 206091da7e..cc3fdfd138 100644 --- a/packages/ipfs-core/src/components/repo/gc.js +++ b/packages/ipfs-core/src/components/repo/gc.js @@ -42,8 +42,7 @@ module.exports = ({ gcLock, pin, refs, repo }) => { // Mark all blocks that are being used const markedSet = await createMarkedSet({ pin, refs, repo }) // Get all blocks keys from the blockstore - // @ts-ignore - TS is not aware of keysOnly overload - const blockKeys = repo.blocks.query({ keysOnly: true }) + const blockKeys = repo.blocks.queryKeys({}) // Delete blocks that are not being used yield * deleteUnmarkedBlocks({ repo }, markedSet, blockKeys) diff --git a/packages/ipfs-core/src/components/storage.js b/packages/ipfs-core/src/components/storage.js index c8b50b5af1..1c5f7ae027 100644 --- a/packages/ipfs-core/src/components/storage.js +++ b/packages/ipfs-core/src/components/storage.js @@ -120,13 +120,13 @@ const initRepo = async (print, repo, options) => { } await repo.init(config) - // 4. Open initalized repo. + // 4. Open initialized repo. await repo.open() log('repo opened') // Create libp2p for Keychain creation - const libp2p = createLibP2P({ + const libp2p = await createLibP2P({ options: undefined, multiaddrs: undefined, peerId, @@ -207,7 +207,7 @@ const configureRepo = async (repo, options) => { // @ts-ignore - Identity may not be present const peerId = await PeerId.createFromPrivKey(changed.Identity.PrivKey) - const libp2p = createLibP2P({ + const libp2p = await createLibP2P({ options: undefined, multiaddrs: undefined, peerId, diff --git a/packages/ipfs-core/src/index.js b/packages/ipfs-core/src/index.js index d437622a81..02dd242be5 100644 --- a/packages/ipfs-core/src/index.js +++ b/packages/ipfs-core/src/index.js @@ -5,7 +5,7 @@ const urlSource = require('ipfs-utils/src/files/url-source') const PeerId = require('peer-id') const crypto = require('libp2p-crypto') const isIPFS = require('is-ipfs') -const multiaddr = require('multiaddr') +const { multiaddr } = require('multiaddr') const multibase = require('multibase') const multicodec = require('multicodec') const multihashing = require('multihashing-async') diff --git a/packages/ipfs-core/src/ipns/routing/pubsub-datastore.js b/packages/ipfs-core/src/ipns/routing/pubsub-datastore.js index 925725ee59..f6d4da49bc 100644 --- a/packages/ipfs-core/src/ipns/routing/pubsub-datastore.js +++ b/packages/ipfs-core/src/ipns/routing/pubsub-datastore.js @@ -25,6 +25,8 @@ class IpnsPubsubDatastore { // Bind _handleSubscriptionKey function, which is called by PubsubDatastore. this._handleSubscriptionKey = this._handleSubscriptionKey.bind(this) + + // @ts-ignore will be fixed by https://github.com/ipfs/js-datastore-pubsub/pull/74 this._pubsubDs = new PubsubDatastore(pubsub, localDatastore, peerId, ipns.validator, this._handleSubscriptionKey) } diff --git a/packages/ipfs-core/src/runtime/libp2p-browser.js b/packages/ipfs-core/src/runtime/libp2p-browser.js index 48d4cab843..e3801398ab 100644 --- a/packages/ipfs-core/src/runtime/libp2p-browser.js +++ b/packages/ipfs-core/src/runtime/libp2p-browser.js @@ -12,7 +12,8 @@ const GossipSub = require('libp2p-gossipsub') const ipnsUtils = require('../ipns/routing/utils') module.exports = () => { - return { + /** @type {import('libp2p').Libp2pOptions} */ + const options = { dialer: { maxParallelDials: 150, // 150 total parallel multiaddr dials maxDialsPerPeer: 4, // Allow 4 multiaddrs to be dialed per peer in parallel @@ -75,4 +76,6 @@ module.exports = () => { threshold: 1 } } + + return options } diff --git a/packages/ipfs-core/src/runtime/libp2p-nodejs.js b/packages/ipfs-core/src/runtime/libp2p-nodejs.js index 6336d2455b..9cac4a8063 100644 --- a/packages/ipfs-core/src/runtime/libp2p-nodejs.js +++ b/packages/ipfs-core/src/runtime/libp2p-nodejs.js @@ -15,7 +15,8 @@ const ipnsUtils = require('../ipns/routing/utils') const os = require('os') module.exports = () => { - return { + /** @type {import('libp2p').Libp2pOptions} */ + const options = { dialer: { maxParallelDials: 150, // 150 total parallel multiaddr dials maxDialsPerPeer: 4, // Allow 4 multiaddrs to be dialed per peer in parallel @@ -81,4 +82,6 @@ module.exports = () => { persistence: true } } + + return options } diff --git a/packages/ipfs-core/test/config.spec.js b/packages/ipfs-core/test/config.spec.js index df41bf2e43..3bd9196694 100644 --- a/packages/ipfs-core/test/config.spec.js +++ b/packages/ipfs-core/test/config.spec.js @@ -3,7 +3,7 @@ 'use strict' const { expect } = require('aegir/utils/chai') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') const createNode = require('./utils/create-node') const bootstrapList = require('../src/runtime/config-nodejs.js')().Bootstrap @@ -36,7 +36,7 @@ describe('config', function () { return acc } - const ma = multiaddr(curr) + const ma = new Multiaddr(curr) return ma.protos().some(proto => proto.name === 'wss' || proto.resolvable) }, true) diff --git a/packages/ipfs-core/test/exports.spec.js b/packages/ipfs-core/test/exports.spec.js index f0be187418..e4b63d24f7 100644 --- a/packages/ipfs-core/test/exports.spec.js +++ b/packages/ipfs-core/test/exports.spec.js @@ -4,7 +4,7 @@ const crypto = require('libp2p-crypto') const isIPFS = require('is-ipfs') const CID = require('cids') -const multiaddr = require('multiaddr') +const { multiaddr } = require('multiaddr') const multibase = require('multibase') const multihashing = require('multihashing-async') const multihash = multihashing.multihash diff --git a/packages/ipfs-core/test/libp2p.spec.js b/packages/ipfs-core/test/libp2p.spec.js index e347f29b9e..0fc25dc610 100644 --- a/packages/ipfs-core/test/libp2p.spec.js +++ b/packages/ipfs-core/test/libp2p.spec.js @@ -73,10 +73,10 @@ describe('libp2p customization', function () { describe('bundle', () => { it('should allow for using a libp2p bundle', async () => { - libp2p = libp2pComponent({ + libp2p = await libp2pComponent({ options: { libp2p: (opts) => { - return new Libp2p({ + return Libp2p.create({ peerId: opts.peerId, modules: { transport: [DummyTransport], connEncryption: [Crypto] }, config: { relay: { enabled: false } } @@ -97,10 +97,10 @@ describe('libp2p customization', function () { }) it('should pass libp2p options to libp2p bundle function', async () => { - libp2p = libp2pComponent({ + libp2p = await libp2pComponent({ options: { libp2p: (opts) => { - return new Libp2p({ + return Libp2p.create({ peerId: opts.peerId, modules: { transport: [DummyTransport], connEncryption: [Crypto] }, config: { relay: { enabled: false } } @@ -123,7 +123,7 @@ describe('libp2p customization', function () { describe('options', () => { it('should use options by default', async () => { - libp2p = libp2pComponent({ + libp2p = await libp2pComponent({ peerId, repo: { datastore }, print: console.log, // eslint-disable-line no-console @@ -158,7 +158,7 @@ describe('libp2p customization', function () { it('should allow for overriding via options', async () => { const annAddr = '/dns4/test.ipfs.io/tcp/443/wss' - libp2p = libp2pComponent({ + libp2p = await libp2pComponent({ peerId, repo: { datastore }, print: console.log, // eslint-disable-line no-console @@ -195,7 +195,7 @@ describe('libp2p customization', function () { it('should be able to specify Announce addresses', async () => { const annAddr = '/dns4/test.ipfs.io/tcp/443/wss' - libp2p = libp2pComponent({ + libp2p = await libp2pComponent({ peerId, repo: { datastore }, print: console.log, // eslint-disable-line no-console @@ -214,7 +214,7 @@ describe('libp2p customization', function () { }) it('should select gossipsub as pubsub router', async () => { - libp2p = libp2pComponent({ + libp2p = await libp2pComponent({ peerId, repo: { datastore }, print: console.log, // eslint-disable-line no-console diff --git a/packages/ipfs-daemon/package.json b/packages/ipfs-daemon/package.json index 178f81c0cf..351fa31abd 100644 --- a/packages/ipfs-daemon/package.json +++ b/packages/ipfs-daemon/package.json @@ -39,15 +39,15 @@ "ipfs-http-gateway": "^0.3.2", "ipfs-http-server": "^0.3.4", "ipfs-utils": "^6.0.4", - "just-safe-set": "^2.1.0", - "libp2p": "^0.30.12", - "libp2p-delegated-content-routing": "^0.9.0", - "libp2p-delegated-peer-routing": "^0.8.0", - "libp2p-webrtc-star": "^0.21.0", - "multiaddr": "^8.0.0" + "just-safe-set": "^2.2.1", + "libp2p": "^0.31.0-rc.6", + "libp2p-delegated-content-routing": "^0.10.0", + "libp2p-delegated-peer-routing": "^0.9.0", + "libp2p-webrtc-star": "^0.22.2", + "multiaddr": "^9.0.1" }, "devDependencies": { - "aegir": "^32.1.0", + "aegir": "^33.0.0", "node-fetch": "^2.6.1", "ws": "^7.3.1" }, diff --git a/packages/ipfs-daemon/src/index.js b/packages/ipfs-daemon/src/index.js index f0afad9dfd..44c33dee30 100644 --- a/packages/ipfs-daemon/src/index.js +++ b/packages/ipfs-daemon/src/index.js @@ -3,7 +3,7 @@ const log = require('debug')('ipfs:daemon') const get = require('dlv') const set = require('just-safe-set') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') // @ts-ignore - no types const WebRTCStar = require('libp2p-webrtc-star') // @ts-ignore - no types @@ -128,7 +128,7 @@ function getLibp2p ({ libp2pOptions, options, config, peerId }) { if (delegateHosts.length > 0) { // Pick a random delegate host const delegateString = delegateHosts[Math.floor(Math.random() * delegateHosts.length)] - const delegateAddr = Multiaddr(delegateString).toOptions() + const delegateAddr = new Multiaddr(delegateString).toOptions() const delegateApiOptions = { host: delegateAddr.host, // port is a string atm, so we need to convert for the check diff --git a/packages/ipfs-grpc-client/.aegir.js b/packages/ipfs-grpc-client/.aegir.js index 9549fd1c7a..4dc0a9fba2 100644 --- a/packages/ipfs-grpc-client/.aegir.js +++ b/packages/ipfs-grpc-client/.aegir.js @@ -3,6 +3,6 @@ /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '65KB' + bundlesizeMax: '56KB' } } diff --git a/packages/ipfs-grpc-client/package.json b/packages/ipfs-grpc-client/package.json index 5017992e13..c3534e6b47 100644 --- a/packages/ipfs-grpc-client/package.json +++ b/packages/ipfs-grpc-client/package.json @@ -32,7 +32,7 @@ "dep-check": "aegir dep-check -i aegir -i rimraf -i ipfs-grpc-protocol -i ipfs-core-types" }, "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", + "@improbable-eng/grpc-web": "^0.14.0", "change-case": "^4.1.1", "cids": "^1.1.6", "debug": "^4.1.1", @@ -40,19 +40,19 @@ "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-grpc-protocol": "^0.2.0", - "ipfs-unixfs": "^4.0.1", + "ipfs-unixfs": "^4.0.3", "it-first": "^1.0.4", "it-pushable": "^1.4.0", - "multiaddr": "^8.0.0", + "multiaddr": "^9.0.1", "protobufjs": "^6.10.2", "wherearewe": "1.0.0", "ws": "^7.3.1" }, "devDependencies": { - "aegir": "^32.1.0", + "aegir": "^33.0.0", "it-all": "^1.0.4", "rimraf": "^3.0.2", - "sinon": "^9.0.3" + "sinon": "^10.0.1" }, "eslintConfig": { "extends": "ipfs" diff --git a/packages/ipfs-grpc-client/src/core-api/id.js b/packages/ipfs-grpc-client/src/core-api/id.js index 185bbd9d31..6396858131 100644 --- a/packages/ipfs-grpc-client/src/core-api/id.js +++ b/packages/ipfs-grpc-client/src/core-api/id.js @@ -3,7 +3,7 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') const toHeaders = require('../utils/to-headers') const unaryToPromise = require('../utils/unary-to-promise') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @param {import('@improbable-eng/grpc-web').grpc} grpc @@ -25,7 +25,7 @@ module.exports = function grpcId (grpc, service, opts) { return { ...res, - addresses: (res.addresses || []).map(multiaddr) + addresses: (res.addresses || []).map((/** @type {string} */ str) => new Multiaddr(str)) } } diff --git a/packages/ipfs-grpc-client/src/types.d.ts b/packages/ipfs-grpc-client/src/types.d.ts index 866850b41d..082c6da0fc 100644 --- a/packages/ipfs-grpc-client/src/types.d.ts +++ b/packages/ipfs-grpc-client/src/types.d.ts @@ -1,6 +1,6 @@ import { agent as HttpAgent } from 'http' import { agent as HttpsAgent } from 'https' -import Multiaddr from 'multiaddr' +import { Multiaddr } from 'multiaddr' export interface Options { url: string | URL | Multiaddr diff --git a/packages/ipfs-grpc-server/package.json b/packages/ipfs-grpc-server/package.json index 506ffd055e..32d372d657 100644 --- a/packages/ipfs-grpc-server/package.json +++ b/packages/ipfs-grpc-server/package.json @@ -41,18 +41,18 @@ "it-peekable": "^1.0.1", "it-pipe": "^1.1.0", "it-pushable": "^1.4.0", - "multiaddr": "^8.0.0", + "multiaddr": "^9.0.1", "protobufjs": "^6.10.2", "ws": "^7.3.1" }, "devDependencies": { "@types/ws": "^7.4.0", - "aegir": "^32.1.0", + "aegir": "^33.0.0", "ipfs-core": "^0.5.4", "it-all": "^1.0.4", "it-drain": "^1.0.3", "rimraf": "^3.0.2", - "sinon": "^9.0.3", + "sinon": "^10.0.1", "uint8arrays": "^2.1.3" } } diff --git a/packages/ipfs-grpc-server/src/utils/web-socket-server.js b/packages/ipfs-grpc-server/src/utils/web-socket-server.js index d08f4d2dfc..d5f9c4a0bf 100644 --- a/packages/ipfs-grpc-server/src/utils/web-socket-server.js +++ b/packages/ipfs-grpc-server/src/utils/web-socket-server.js @@ -7,7 +7,7 @@ const debug = require('debug')('ipfs:grpc-server:utils:web-socket-server') // @ts-ignore - no types const coerce = require('coercer') const { camelCase } = require('change-case') -const ma = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @param {Buffer} buf - e.g. `Buffer.from('foo-bar: baz\r\n')` @@ -82,14 +82,14 @@ class Messages extends EventEmitter { // which is not how this server runs: https://nodejs.org/dist/latest-v15.x/docs/api/net.html#net_server_address this.info = { uri: info, - ma: ma(info) + ma: new Multiaddr(info) } } else { this.info = { address: info.address, port: info.port, uri: `http://${info.address}:${info.port}`, - ma: ma(`/ip4/${info.address}/tcp/${info.port}/ws`) + ma: new Multiaddr(`/ip4/${info.address}/tcp/${info.port}/ws`) } } @@ -106,10 +106,10 @@ class Messages extends EventEmitter { */ module.exports = async (ipfs, options = {}) => { const config = await ipfs.config.getAll() - const grpcAddr = config.Addresses.RPC + const grpcAddr = config.Addresses?.RPC if (!grpcAddr) { - throw new Error('No gRPC address configured, please set an Adresses.RPC key in your IPFS config') + throw new Error('No gRPC address configured, please set an Addresses.RPC key in your IPFS config') } const [,, host, , port] = grpcAddr.split('/') diff --git a/packages/ipfs-http-client/.aegir.js b/packages/ipfs-http-client/.aegir.js index 63eb11ed9d..149fff9487 100644 --- a/packages/ipfs-http-client/.aegir.js +++ b/packages/ipfs-http-client/.aegir.js @@ -6,7 +6,7 @@ const getPort = require('aegir/utils/get-port') /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '106kB' + bundlesizeMax: '96KB' }, test: { async before (options) { diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index f00443eb66..98bcdeb066 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -51,7 +51,7 @@ "form-data": "^4.0.0", "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", - "ipfs-unixfs": "^4.0.1", + "ipfs-unixfs": "^4.0.3", "ipfs-utils": "^6.0.4", "ipld": "^0.29.0", "ipld-block": "^0.11.0", @@ -60,26 +60,26 @@ "ipld-raw": "^7.0.0", "it-last": "^1.0.4", "it-map": "^1.0.4", - "it-tar": "^1.2.2", - "it-to-stream": "^0.1.2", + "it-tar": "^3.0.0", + "it-to-stream": "^1.0.0", "merge-options": "^3.0.4", - "multiaddr": "^8.0.0", + "multiaddr": "^9.0.1", "multibase": "^4.0.2", "multicodec": "^3.0.1", "multihashes": "^4.0.2", "nanoid": "^3.1.12", "native-abort-controller": "^1.0.3", - "parse-duration": "^0.4.4", + "parse-duration": "^1.0.0", "stream-to-it": "^0.2.2", "uint8arrays": "^2.1.3" }, "devDependencies": { - "aegir": "^32.1.0", + "aegir": "^33.0.0", "delay": "^5.0.0", "go-ipfs": "0.8.0", - "ipfsd-ctl": "^8.0.0", + "ipfsd-ctl": "^8.0.1", "it-all": "^1.0.4", - "it-concat": "^1.0.3", + "it-concat": "^2.0.0", "it-first": "^1.0.4", "nock": "^13.0.2", "rimraf": "^3.0.2" diff --git a/packages/ipfs-http-client/src/bootstrap/add.js b/packages/ipfs-http-client/src/bootstrap/add.js index 35afcc4bfe..6caa170a85 100644 --- a/packages/ipfs-http-client/src/bootstrap/add.js +++ b/packages/ipfs-http-client/src/bootstrap/add.js @@ -2,7 +2,7 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions diff --git a/packages/ipfs-http-client/src/bootstrap/clear.js b/packages/ipfs-http-client/src/bootstrap/clear.js index 930b258bcb..26355bbb55 100644 --- a/packages/ipfs-http-client/src/bootstrap/clear.js +++ b/packages/ipfs-http-client/src/bootstrap/clear.js @@ -2,7 +2,7 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions diff --git a/packages/ipfs-http-client/src/bootstrap/list.js b/packages/ipfs-http-client/src/bootstrap/list.js index 9c0ac38d78..aad38554b1 100644 --- a/packages/ipfs-http-client/src/bootstrap/list.js +++ b/packages/ipfs-http-client/src/bootstrap/list.js @@ -2,7 +2,7 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions diff --git a/packages/ipfs-http-client/src/bootstrap/reset.js b/packages/ipfs-http-client/src/bootstrap/reset.js index 2959a53855..b958d78700 100644 --- a/packages/ipfs-http-client/src/bootstrap/reset.js +++ b/packages/ipfs-http-client/src/bootstrap/reset.js @@ -2,7 +2,7 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions diff --git a/packages/ipfs-http-client/src/bootstrap/rm.js b/packages/ipfs-http-client/src/bootstrap/rm.js index f09c15cb89..13cea8dbe0 100644 --- a/packages/ipfs-http-client/src/bootstrap/rm.js +++ b/packages/ipfs-http-client/src/bootstrap/rm.js @@ -2,7 +2,7 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') /** * @typedef {import('../types').HTTPClientExtraOptions} HTTPClientExtraOptions diff --git a/packages/ipfs-http-client/src/dht/find-peer.js b/packages/ipfs-http-client/src/dht/find-peer.js index 6a70e9cc44..f4eabe5370 100644 --- a/packages/ipfs-http-client/src/dht/find-peer.js +++ b/packages/ipfs-http-client/src/dht/find-peer.js @@ -1,7 +1,7 @@ 'use strict' const CID = require('cids') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const { FinalPeer } = require('./response-types') @@ -31,7 +31,7 @@ module.exports = configure(api => { const { ID, Addrs } = data.Responses[0] return { id: ID, - addrs: (Addrs || []).map((/** @type {string} **/ a) => multiaddr(a)) + addrs: (Addrs || []).map((/** @type {string} **/ a) => new Multiaddr(a)) } } } diff --git a/packages/ipfs-http-client/src/dht/find-provs.js b/packages/ipfs-http-client/src/dht/find-provs.js index c5175a6cd9..c431648ae6 100644 --- a/packages/ipfs-http-client/src/dht/find-provs.js +++ b/packages/ipfs-http-client/src/dht/find-provs.js @@ -1,7 +1,7 @@ 'use strict' const CID = require('cids') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') const { Provider } = require('./response-types') @@ -31,7 +31,7 @@ module.exports = configure(api => { for (const { ID, Addrs } of message.Responses) { yield { id: ID, - addrs: (Addrs || []).map((/** @type {string} **/ a) => multiaddr(a)) + addrs: (Addrs || []).map((/** @type {string} **/ a) => new Multiaddr(a)) } } } diff --git a/packages/ipfs-http-client/src/dht/provide.js b/packages/ipfs-http-client/src/dht/provide.js index 9ef17a394c..878880398f 100644 --- a/packages/ipfs-http-client/src/dht/provide.js +++ b/packages/ipfs-http-client/src/dht/provide.js @@ -1,7 +1,7 @@ 'use strict' const CID = require('cids') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') @@ -34,7 +34,7 @@ module.exports = configure(api => { if (message.responses) { message.responses = message.responses.map((/** @type {{ ID: string, Addrs: string[] }} */ { ID, Addrs }) => ({ id: ID, - addrs: (Addrs || []).map((/** @type {string} **/ a) => multiaddr(a)) + addrs: (Addrs || []).map((/** @type {string} **/ a) => new Multiaddr(a)) })) } else { message.responses = [] diff --git a/packages/ipfs-http-client/src/dht/put.js b/packages/ipfs-http-client/src/dht/put.js index 949bc3f446..d2b88aa89a 100644 --- a/packages/ipfs-http-client/src/dht/put.js +++ b/packages/ipfs-http-client/src/dht/put.js @@ -1,7 +1,7 @@ 'use strict' const CID = require('cids') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') @@ -42,7 +42,7 @@ module.exports = configure(api => { if (message.responses) { message.responses = message.responses.map((/** @type {{ ID: string, Addrs: string[] }} */ { ID, Addrs }) => ({ id: ID, - addrs: (Addrs || []).map(a => multiaddr(a)) + addrs: (Addrs || []).map(a => new Multiaddr(a)) })) } yield message diff --git a/packages/ipfs-http-client/src/dht/query.js b/packages/ipfs-http-client/src/dht/query.js index 4193970f9e..429f487ef2 100644 --- a/packages/ipfs-http-client/src/dht/query.js +++ b/packages/ipfs-http-client/src/dht/query.js @@ -1,7 +1,7 @@ 'use strict' const CID = require('cids') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const toCamel = require('../lib/object-to-camel') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') @@ -31,7 +31,7 @@ module.exports = configure(api => { message.id = new CID(message.id) message.responses = (message.responses || []).map((/** @type {{ ID: string, Addrs: string[] }} */ { ID, Addrs }) => ({ id: ID, - addrs: (Addrs || []).map((/** @type {string} **/ a) => multiaddr(a)) + addrs: (Addrs || []).map((/** @type {string} **/ a) => new Multiaddr(a)) })) yield message } diff --git a/packages/ipfs-http-client/src/id.js b/packages/ipfs-http-client/src/id.js index c7d19610ed..6b9c439d5b 100644 --- a/packages/ipfs-http-client/src/id.js +++ b/packages/ipfs-http-client/src/id.js @@ -1,7 +1,7 @@ 'use strict' const toCamel = require('./lib/object-to-camel') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const configure = require('./lib/configure') const toUrlSearchParams = require('./lib/to-url-search-params') @@ -28,7 +28,7 @@ module.exports = configure(api => { } if (output.addresses) { - output.addresses = output.addresses.map((/** @type {string} */ ma) => multiaddr(ma)) + output.addresses = output.addresses.map((/** @type {string} */ ma) => new Multiaddr(ma)) } // @ts-ignore server output is not typed diff --git a/packages/ipfs-http-client/src/index.js b/packages/ipfs-http-client/src/index.js index 5172ceec27..c9c9551b29 100644 --- a/packages/ipfs-http-client/src/index.js +++ b/packages/ipfs-http-client/src/index.js @@ -2,7 +2,7 @@ /* eslint-env browser */ const CID = require('cids') -const multiaddr = require('multiaddr') +const { multiaddr } = require('multiaddr') const multibase = require('multibase') const multicodec = require('multicodec') const multihash = require('multihashes') diff --git a/packages/ipfs-http-client/src/lib/core.js b/packages/ipfs-http-client/src/lib/core.js index 2aafe8149c..eb1340716a 100644 --- a/packages/ipfs-http-client/src/lib/core.js +++ b/packages/ipfs-http-client/src/lib/core.js @@ -1,6 +1,6 @@ 'use strict' /* eslint-env browser */ -const Multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const { isBrowser, isWebWorker, isNode } = require('ipfs-utils/src/env') const { default: parseDuration } = require('parse-duration') const log = require('debug')('ipfs-http-client:lib:error-handler') diff --git a/packages/ipfs-http-client/src/swarm/addrs.js b/packages/ipfs-http-client/src/swarm/addrs.js index acd0242556..e0880e5549 100644 --- a/packages/ipfs-http-client/src/swarm/addrs.js +++ b/packages/ipfs-http-client/src/swarm/addrs.js @@ -1,6 +1,6 @@ 'use strict' -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') @@ -26,7 +26,7 @@ module.exports = configure(api => { return Object.keys(Addrs).map(id => ({ id, - addrs: (Addrs[id] || []).map(a => multiaddr(a)) + addrs: (Addrs[id] || []).map(a => new Multiaddr(a)) })) } return addrs diff --git a/packages/ipfs-http-client/src/swarm/localAddrs.js b/packages/ipfs-http-client/src/swarm/localAddrs.js index 55f3927b1e..c1b3ae91bd 100644 --- a/packages/ipfs-http-client/src/swarm/localAddrs.js +++ b/packages/ipfs-http-client/src/swarm/localAddrs.js @@ -1,6 +1,6 @@ 'use strict' -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') @@ -24,7 +24,7 @@ module.exports = configure(api => { /** @type {{ Strings: string[] }} */ const { Strings } = await res.json() - return (Strings || []).map(a => multiaddr(a)) + return (Strings || []).map(a => new Multiaddr(a)) } return localAddrs }) diff --git a/packages/ipfs-http-client/src/swarm/peers.js b/packages/ipfs-http-client/src/swarm/peers.js index e85bbb3b08..cb68ac5c5b 100644 --- a/packages/ipfs-http-client/src/swarm/peers.js +++ b/packages/ipfs-http-client/src/swarm/peers.js @@ -1,6 +1,6 @@ 'use strict' -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') @@ -26,7 +26,7 @@ module.exports = configure(api => { return (Peers || []).map(peer => { return { - addr: multiaddr(peer.Addr), + addr: new Multiaddr(peer.Addr), peer: peer.Peer, muxer: peer.Muxer, latency: peer.Latency, diff --git a/packages/ipfs-http-client/src/types.d.ts b/packages/ipfs-http-client/src/types.d.ts index 037fa68b01..b6d9e45527 100644 --- a/packages/ipfs-http-client/src/types.d.ts +++ b/packages/ipfs-http-client/src/types.d.ts @@ -2,7 +2,7 @@ import { Format as IPLDFormat } from 'interface-ipld-format' import { LoadFormatFn } from 'ipld' import { Agent as HttpAgent } from 'http' import { Agent as HttpsAgent } from 'https' -import Multiaddr from 'multiaddr' +import { Multiaddr } from 'multiaddr' export interface Options { host?: string diff --git a/packages/ipfs-http-client/test/constructor.spec.js b/packages/ipfs-http-client/test/constructor.spec.js index 1c74af9c61..c1f4a7f7ca 100644 --- a/packages/ipfs-http-client/test/constructor.spec.js +++ b/packages/ipfs-http-client/test/constructor.spec.js @@ -1,7 +1,7 @@ /* eslint-env mocha, browser */ 'use strict' -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const { expect } = require('aegir/utils/chai') const f = require('./utils/factory')() const { create: ipfsClient } = require('../src/index.js') @@ -75,7 +75,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr instance', () => { const host = 'ace.place' const port = '1001' - const addr = multiaddr(`/dns4/${host}/tcp/${port}`) + const addr = new Multiaddr(`/dns4/${host}/tcp/${port}`) const ipfs = ipfsClient(addr) expectConfig(ipfs, { host, port }) }) @@ -132,7 +132,7 @@ describe('ipfs-http-client constructor tests', () => { const port = '1001' const protocol = 'http' // default to http if not specified in multiaddr const addr = `/dns4/${host}/tcp/${port}` - const ipfs = ipfsClient({ url: multiaddr(addr) }) + const ipfs = ipfsClient({ url: new Multiaddr(addr) }) expectConfig(ipfs, { host, port, protocol }) }) @@ -141,7 +141,7 @@ describe('ipfs-http-client constructor tests', () => { const port = '1001' const protocol = 'https' const addr = `/dns4/${host}/tcp/${port}/https` - const ipfs = ipfsClient({ url: multiaddr(addr) }) + const ipfs = ipfsClient({ url: new Multiaddr(addr) }) expectConfig(ipfs, { host, port, protocol }) }) diff --git a/packages/ipfs-http-client/test/exports.spec.js b/packages/ipfs-http-client/test/exports.spec.js index 1cc99c946f..b13008847e 100644 --- a/packages/ipfs-http-client/test/exports.spec.js +++ b/packages/ipfs-http-client/test/exports.spec.js @@ -2,7 +2,7 @@ 'use strict' const CID = require('cids') -const multiaddr = require('multiaddr') +const { multiaddr } = require('multiaddr') const multibase = require('multibase') const multicodec = require('multicodec') const multihash = require('multihashes') diff --git a/packages/ipfs-http-gateway/package.json b/packages/ipfs-http-gateway/package.json index 3f529e89ce..a6213167e4 100644 --- a/packages/ipfs-http-gateway/package.json +++ b/packages/ipfs-http-gateway/package.json @@ -50,20 +50,20 @@ "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-http-response": "^0.6.0", - "is-ipfs": "^4.0.0", + "is-ipfs": "^5.0.0", "it-last": "^1.0.4", - "it-to-stream": "^0.1.2", + "it-to-stream": "^1.0.0", "joi": "^17.2.1", "multibase": "^4.0.2", "uint8arrays": "^2.1.3", - "uri-to-multiaddr": "^4.0.0" + "uri-to-multiaddr": "^5.0.0" }, "devDependencies": { "@types/hapi__hapi": "^20.0.5", "@types/hapi-pino": "^8.0.1", - "aegir": "^32.1.0", + "aegir": "^33.0.0", "file-type": "^16.0.0", "rimraf": "^3.0.2", - "sinon": "^9.0.3" + "sinon": "^10.0.1" } } diff --git a/packages/ipfs-http-gateway/src/index.js b/packages/ipfs-http-gateway/src/index.js index 74df014088..e3a0229a12 100644 --- a/packages/ipfs-http-gateway/src/index.js +++ b/packages/ipfs-http-gateway/src/index.js @@ -71,8 +71,8 @@ class HttpGateway { // @ts-ignore TODO: move config typedefs to repo const config = await ipfs.config.getAll() - config.Addresses = config.Addresses || { Swarm: [], Gateway: [] } - const gatewayAddrs = config.Addresses.Gateway || [] + const addresses = config.Addresses || { Swarm: [], Gateway: [] } + const gatewayAddrs = addresses?.Gateway || [] this._gatewayServers = await serverCreator(gatewayAddrs, this._createGatewayServer, ipfs) diff --git a/packages/ipfs-http-server/package.json b/packages/ipfs-http-server/package.json index 577bc560d0..4cb4115209 100644 --- a/packages/ipfs-http-server/package.json +++ b/packages/ipfs-http-server/package.json @@ -42,43 +42,42 @@ "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-http-gateway": "^0.3.2", - "ipfs-unixfs": "^4.0.1", + "ipfs-unixfs": "^4.0.3", "ipld-dag-pb": "^0.22.1", "it-all": "^1.0.4", "it-drain": "^1.0.3", "it-first": "^1.0.4", "it-last": "^1.0.4", "it-map": "^1.0.4", - "it-multipart": "^1.0.8", + "it-multipart": "^2.0.0", "it-pipe": "^1.1.0", - "it-tar": "^1.2.2", - "it-to-stream": "^0.1.2", + "it-tar": "^3.0.0", + "it-to-stream": "^1.0.0", "iterable-ndjson": "^1.1.0", "joi": "^17.2.1", - "just-safe-set": "^2.1.0", - "multiaddr": "^8.0.0", + "just-safe-set": "^2.2.1", + "multiaddr": "^9.0.1", "multibase": "^4.0.2", "multicodec": "^3.0.1", "multihashing-async": "^2.1.2", "native-abort-controller": "^1.0.3", - "parse-duration": "^0.4.4", + "parse-duration": "^1.0.0", "stream-to-it": "^0.2.2", "streaming-iterables": "^5.0.2", "uint8arrays": "^2.1.3", - "uri-to-multiaddr": "^4.0.0" + "uri-to-multiaddr": "^5.0.0" }, "devDependencies": { "@types/hapi__hapi": "^20.0.5", "@types/hapi-pino": "^8.0.1", - "@types/just-safe-set": "^2.1.0", - "aegir": "^32.1.0", + "aegir": "^33.0.0", "form-data": "^4.0.0", "ipfs-http-client": "^49.0.4", - "iso-random-stream": "^1.1.1", + "iso-random-stream": "^2.0.0", "it-to-buffer": "^2.0.0", "qs": "^6.9.4", "rimraf": "^3.0.2", - "sinon": "^9.0.3", + "sinon": "^10.0.1", "stream-to-promise": "^3.0.0" }, "optionalDependencies": { diff --git a/packages/ipfs-http-server/src/api/resources/dht.js b/packages/ipfs-http-server/src/api/resources/dht.js index 85dc418115..f498a3d319 100644 --- a/packages/ipfs-http-server/src/api/resources/dht.js +++ b/packages/ipfs-http-server/src/api/resources/dht.js @@ -138,7 +138,7 @@ exports.findProvs = { return { Responses: [{ ID: id.toString(), - Addrs: (addrs || []).map((/** @type {import('multiaddr')} */ a) => a.toString()) + Addrs: (addrs || []).map((/** @type {import('multiaddr').Multiaddr} */ a) => a.toString()) }], Type: 4 } diff --git a/packages/ipfs-http-server/src/api/resources/files-regular.js b/packages/ipfs-http-server/src/api/resources/files-regular.js index 934a8c0bcb..b57da354a2 100644 --- a/packages/ipfs-http-server/src/api/resources/files-regular.js +++ b/packages/ipfs-http-server/src/api/resources/files-regular.js @@ -438,7 +438,10 @@ exports.ls = { } } - const stat = await ipfs.files.stat(path.startsWith('/ipfs/') ? path : `/ipfs/${path}`) + const stat = await ipfs.files.stat(path.startsWith('/ipfs/') ? path : `/ipfs/${path}`, { + signal, + timeout + }) if (stat.type === 'file') { // return single object with metadata diff --git a/packages/ipfs-http-server/src/index.js b/packages/ipfs-http-server/src/index.js index 30f1805ff1..fb0d99f8c7 100644 --- a/packages/ipfs-http-server/src/index.js +++ b/packages/ipfs-http-server/src/index.js @@ -3,7 +3,7 @@ const Hapi = require('@hapi/hapi') const Pino = require('hapi-pino') const debug = require('debug') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') // @ts-ignore no types const toMultiaddr = require('uri-to-multiaddr') const Boom = require('@hapi/boom') @@ -228,7 +228,7 @@ class HttpApi { if (!this._apiServers || !this._apiServers.length) { throw new Error('API address unavailable - server is not started') } - return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServers[0].info.port) + return new Multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServers[0].info.port) } async stop () { diff --git a/packages/ipfs-http-server/src/utils/joi.js b/packages/ipfs-http-server/src/utils/joi.js index 2db2dcf281..9488068fb5 100644 --- a/packages/ipfs-http-server/src/utils/joi.js +++ b/packages/ipfs-http-server/src/utils/joi.js @@ -3,7 +3,7 @@ const Joi = require('joi') const CID = require('cids') const { default: parseDuration } = require('parse-duration') -const multiaddr = require('multiaddr') +const { Multiaddr } = require('multiaddr') const multibase = require('multibase') const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') @@ -95,7 +95,7 @@ module.exports = Joi return } - return { value: multiaddr(value).toString() } + return { value: new Multiaddr(value).toString() } } } }, diff --git a/packages/ipfs-http-server/src/utils/multipart-request-parser.js b/packages/ipfs-http-server/src/utils/multipart-request-parser.js index 49f4b41578..e9e349a654 100644 --- a/packages/ipfs-http-server/src/utils/multipart-request-parser.js +++ b/packages/ipfs-http-server/src/utils/multipart-request-parser.js @@ -77,13 +77,6 @@ async function * parseEntry (stream) { const type = Content.type(part.headers['content-type']) - if (type.boundary) { - // recursively parse nested multiparts - yield * parseEntry(multipart(part.body, type.boundary)) - - continue - } - if (!part.headers['content-disposition']) { throw new Error('No content disposition in multipart part') } @@ -130,12 +123,11 @@ async function * parseEntry (stream) { const readQueryParam = value => Array.isArray(value) ? value[0] : value /** - * @param {AsyncIterable} stream - * @param {string} boundary + * @param {IncomingMessage} stream * @returns {AsyncGenerator} */ -async function * parser (stream, boundary) { - for await (const entry of parseEntry(multipart(stream, boundary))) { +async function * parser (stream) { + for await (const entry of parseEntry(multipart(stream))) { if (entry.type === 'directory') { /** @type {import('../types').MultipartDirectory} */ yield { @@ -172,13 +164,4 @@ async function * parser (stream, boundary) { } } -/** - * Request Parser - * - * @param {IncomingMessage} req - */ -module.exports = (req) => { - const boundary = Content.type(req.headers['content-type']).boundary - - return parser(req, boundary) -} +module.exports = parser diff --git a/packages/ipfs-http-server/test/inject/files.js b/packages/ipfs-http-server/test/inject/files.js index f2ba06c9f3..47b2f4a3e0 100644 --- a/packages/ipfs-http-server/test/inject/files.js +++ b/packages/ipfs-http-server/test/inject/files.js @@ -2,7 +2,7 @@ /* eslint-env mocha */ 'use strict' -const randomBytes = require('iso-random-stream/src/random') +const { randomBytes } = require('iso-random-stream') const { expect } = require('aegir/utils/chai') const FormData = require('form-data') const streamToPromise = require('stream-to-promise') diff --git a/packages/ipfs-http-server/test/inject/pubsub.js b/packages/ipfs-http-server/test/inject/pubsub.js index 7570b35acc..3b0484c6e9 100644 --- a/packages/ipfs-http-server/test/inject/pubsub.js +++ b/packages/ipfs-http-server/test/inject/pubsub.js @@ -8,7 +8,7 @@ const http = require('../utils/http') const FormData = require('form-data') const sinon = require('sinon') const { AbortSignal } = require('native-abort-controller') -const randomBytes = require('iso-random-stream/src/random') +const { randomBytes } = require('iso-random-stream') const streamToPromise = require('stream-to-promise') const sendData = async (data) => { diff --git a/packages/ipfs-message-port-client/.aegir.js b/packages/ipfs-message-port-client/.aegir.js index ab363f4a28..26fecf0923 100644 --- a/packages/ipfs-message-port-client/.aegir.js +++ b/packages/ipfs-message-port-client/.aegir.js @@ -21,7 +21,7 @@ const buildConfig = { /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '47kB', + bundlesizeMax: '32KB', config: buildConfig }, test: { diff --git a/packages/ipfs-message-port-client/package.json b/packages/ipfs-message-port-client/package.json index fca157b1c3..59b68df236 100644 --- a/packages/ipfs-message-port-client/package.json +++ b/packages/ipfs-message-port-client/package.json @@ -37,10 +37,10 @@ "cids": "^1.1.6", "ipfs-core-types": "^0.3.1", "ipfs-message-port-protocol": "^0.6.1", - "ipfs-unixfs": "^4.0.1" + "ipfs-unixfs": "^4.0.3" }, "devDependencies": { - "aegir": "^32.1.0", + "aegir": "^33.0.0", "interface-ipfs-core": "^0.144.2", "ipfs-core": "^0.5.4", "ipfs-message-port-server": "^0.6.3", diff --git a/packages/ipfs-message-port-protocol/package.json b/packages/ipfs-message-port-protocol/package.json index 65bae65635..6d62f77113 100644 --- a/packages/ipfs-message-port-protocol/package.json +++ b/packages/ipfs-message-port-protocol/package.json @@ -51,7 +51,7 @@ "ipld-block": "^0.11.0" }, "devDependencies": { - "aegir": "^32.1.0", + "aegir": "^33.0.0", "rimraf": "^3.0.2", "uint8arrays": "^2.1.3" }, diff --git a/packages/ipfs-message-port-server/.aegir.js b/packages/ipfs-message-port-server/.aegir.js index bafbe7e4db..7309e2a5d4 100644 --- a/packages/ipfs-message-port-server/.aegir.js +++ b/packages/ipfs-message-port-server/.aegir.js @@ -3,6 +3,6 @@ /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '22kB' + bundlesizeMax: '13KB' } } diff --git a/packages/ipfs-message-port-server/package.json b/packages/ipfs-message-port-server/package.json index cf37bded06..ff3956fb98 100644 --- a/packages/ipfs-message-port-server/package.json +++ b/packages/ipfs-message-port-server/package.json @@ -43,7 +43,7 @@ "it-all": "^1.0.4" }, "devDependencies": { - "aegir": "^32.1.0", + "aegir": "^33.0.0", "cids": "^1.1.6", "rimraf": "^3.0.2" }, diff --git a/packages/ipfs/.aegir.js b/packages/ipfs/.aegir.js index 03566736d0..28b69a93f5 100644 --- a/packages/ipfs/.aegir.js +++ b/packages/ipfs/.aegir.js @@ -118,7 +118,7 @@ module.exports = { } }, build: { - bundlesizeMax: '614kB', + bundlesizeMax: '542KB', config: esbuild }, dependencyCheck: { diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index b34c94a801..69ae0b8dd5 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -47,7 +47,7 @@ "devDependencies": { "@types/semver": "^7.3.4", "@types/update-notifier": "^5.0.0", - "aegir": "^32.1.0", + "aegir": "^33.0.0", "assert": "^2.0.0", "cross-env": "^7.0.0", "electron-webrtc": "^0.3.0", @@ -56,11 +56,11 @@ "ipfs-client": "^0.3.4", "ipfs-core-types": "^0.3.1", "ipfs-http-client": "^49.0.4", - "ipfs-interop": "^5.0.0", + "ipfs-interop": "^5.0.2", "ipfs-utils": "^6.0.4", - "ipfsd-ctl": "^8.0.0", + "ipfsd-ctl": "^8.0.1", "iso-url": "^1.0.0", - "libp2p-webrtc-star": "^0.21.0", + "libp2p-webrtc-star": "^0.22.2", "merge-options": "^3.0.4", "mock-ipfs-pinning-service": "^0.1.2", "rimraf": "^3.0.2", diff --git a/packages/ipfs/test/interface-http-go.js b/packages/ipfs/test/interface-http-go.js index add166de8b..f297424b08 100644 --- a/packages/ipfs/test/interface-http-go.js +++ b/packages/ipfs/test/interface-http-go.js @@ -3,7 +3,8 @@ const tests = require('interface-ipfs-core') const factory = require('./utils/factory') -const isWindows = global.process && global.process.platform && global.process.platform === 'win32' +const isWindows = globalThis.process && globalThis.process.platform && globalThis.process.platform === 'win32' +const isFirefox = globalThis.navigator?.userAgent?.toLowerCase().includes('firefox') /** @typedef {import("ipfsd-ctl").ControllerOptions} ControllerOptions */ @@ -70,7 +71,18 @@ describe('interface-ipfs-core over ipfs-http-client tests against go-ipfs', () = name: 'should error during add-all stream', reason: 'Not supported by http' } - ] + ].concat(isFirefox + ? [{ + name: 'should add a BIG Uint8Array', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'should add a BIG Uint8Array with progress enabled', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'should add big files', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }] + : []) }) tests.bitswap(commonFactory, { @@ -98,10 +110,6 @@ describe('interface-ipfs-core over ipfs-http-client tests against go-ipfs', () = name: 'replace', reason: 'FIXME Waiting for fix on go-ipfs https://github.com/ipfs/js-ipfs-http-client/pull/307#discussion_r69281789 and https://github.com/ipfs/go-ipfs/issues/2927' }, - { - name: 'should respect timeout option when listing config profiles', - reason: 'TODO: Not implemented in go-ipfs' - }, { name: 'should list config profiles', reason: 'TODO: Not implemented in go-ipfs' @@ -164,10 +172,6 @@ describe('interface-ipfs-core over ipfs-http-client tests against go-ipfs', () = name: 'should ls from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' }, - { - name: 'should respect timeout option when changing the mode of a file', - reason: 'TODO not implemented in go-ipfs yet' - }, { name: 'should update the mode for a file', reason: 'TODO not implemented in go-ipfs yet' @@ -260,10 +264,6 @@ describe('interface-ipfs-core over ipfs-http-client tests against go-ipfs', () = name: 'should respect metadata when copying from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' }, - { - name: 'should respect timeout option when updating the modification time of files', - reason: 'TODO not implemented in go-ipfs yet' - }, { name: 'should have default mtime', reason: 'TODO not implemented in go-ipfs yet' @@ -461,6 +461,30 @@ describe('interface-ipfs-core over ipfs-http-client tests against go-ipfs', () = reason: 'TODO go-ipfs drops the connection' } ] + .concat(isFirefox + ? [{ + name: 'overwrites start of a file without truncating (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'limits how many bytes to write to a file (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'pads the start of a new file when an offset is specified (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'expands a file when an offset is specified (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'expands a file when an offset is specified and the offset is longer than the file (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'truncates a file after writing (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'writes a file with raw blocks for newly created leaf nodes (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }] + : []) }) tests.key(commonFactory, { @@ -575,6 +599,12 @@ describe('interface-ipfs-core over ipfs-http-client tests against go-ipfs', () = reason: 'FIXME go-ipfs throws invalid encoding: protobuf' } ] + .concat(isFirefox + ? [{ + name: 'should supply unaltered data', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }] + : []) }) tests.pin(commonFactory, { diff --git a/packages/ipfs/test/interface-http-js.js b/packages/ipfs/test/interface-http-js.js index 912d854388..5749d77c86 100644 --- a/packages/ipfs/test/interface-http-js.js +++ b/packages/ipfs/test/interface-http-js.js @@ -4,6 +4,7 @@ const tests = require('interface-ipfs-core') const { isNode, isBrowser, isWebWorker } = require('ipfs-utils/src/env') const factory = require('./utils/factory') +const isFirefox = globalThis.navigator?.userAgent?.toLowerCase().includes('firefox') /** @typedef { import("ipfsd-ctl").ControllerOptions } ControllerOptions */ @@ -36,6 +37,18 @@ describe('interface-ipfs-core over ipfs-http-client tests against js-ipfs', func name: 'should add with mtime as hrtime', reason: 'Not designed to run in the browser' }]) + .concat(isFirefox + ? [{ + name: 'should add a BIG Uint8Array', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'should add a BIG Uint8Array with progress enabled', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'should add big files', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }] + : []) }) tests.bitswap(commonFactory) @@ -63,7 +76,7 @@ describe('interface-ipfs-core over ipfs-http-client tests against js-ipfs', func }) tests.files(commonFactory, { - skip: isBrowser || isWebWorker + skip: (isBrowser || isWebWorker ? [{ name: 'should make directory and specify mtime as hrtime', reason: 'Not designed to run in the browser' @@ -74,7 +87,31 @@ describe('interface-ipfs-core over ipfs-http-client tests against js-ipfs', func name: 'should set mtime as hrtime', reason: 'Not designed to run in the browser' }] - : [] + : []) + .concat(isFirefox + ? [{ + name: 'overwrites start of a file without truncating (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'limits how many bytes to write to a file (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'pads the start of a new file when an offset is specified (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'expands a file when an offset is specified (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'expands a file when an offset is specified and the offset is longer than the file (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'truncates a file after writing (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }, { + name: 'writes a file with raw blocks for newly created leaf nodes (Really large file)', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }] + : []) }) tests.key(commonFactory) @@ -98,7 +135,14 @@ describe('interface-ipfs-core over ipfs-http-client tests against js-ipfs', func } })) - tests.object(commonFactory) + tests.object(commonFactory, { + skip: isFirefox + ? [{ + name: 'should supply unaltered data', + reason: 'https://github.com/microsoft/playwright/issues/4704#issuecomment-826782602' + }] + : [] + }) tests.pin(commonFactory, { skip: [{ From 4a14d20e727b50a8d98c14573d9a5b6fa0e8699d Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 27 Apr 2021 17:17:58 +0100 Subject: [PATCH 09/34] fix: update data type for ws message event handler (#3641) The data type was wrong so use the version from the `ws` module --- packages/ipfs-grpc-server/src/utils/web-socket-server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ipfs-grpc-server/src/utils/web-socket-server.js b/packages/ipfs-grpc-server/src/utils/web-socket-server.js index d5f9c4a0bf..dbe52ff8d6 100644 --- a/packages/ipfs-grpc-server/src/utils/web-socket-server.js +++ b/packages/ipfs-grpc-server/src/utils/web-socket-server.js @@ -10,7 +10,7 @@ const { camelCase } = require('change-case') const { Multiaddr } = require('multiaddr') /** - * @param {Buffer} buf - e.g. `Buffer.from('foo-bar: baz\r\n')` + * @param {import('ws').Data} buf - e.g. `Buffer.from('foo-bar: baz\r\n')` * @returns {Record} - e.g. `{ foorBar: 'baz' }` **/ const fromHeaders = (buf) => { From 8545a763daa38aefa71cca514016ba400363830a Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Wed, 28 Apr 2021 07:32:23 +0200 Subject: [PATCH 10/34] fix: do not republish self key twice (#3634) * fix: do not republish self key twice * chore: decrease brodcast initial delay * chore: decrease other test timers --- packages/ipfs-core/src/ipns/republisher.js | 3 ++ packages/ipfs-core/test/name.spec.js | 32 ++++++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/packages/ipfs-core/src/ipns/republisher.js b/packages/ipfs-core/src/ipns/republisher.js index e419ab8884..93ca682dac 100644 --- a/packages/ipfs-core/src/ipns/republisher.js +++ b/packages/ipfs-core/src/ipns/republisher.js @@ -138,6 +138,9 @@ class IpnsRepublisher { const keys = await this._keychain.listKeys() for (const key of keys) { + if (key.name === 'self') { + continue + } const pem = await this._keychain.exportKey(key.name, pass) const privKey = await crypto.keys.import(pem, pass) diff --git a/packages/ipfs-core/test/name.spec.js b/packages/ipfs-core/test/name.spec.js index b972915225..5612f9ec51 100644 --- a/packages/ipfs-core/test/name.spec.js +++ b/packages/ipfs-core/test/name.spec.js @@ -32,8 +32,8 @@ describe('name', function () { it('should republish entries', async function () { republisher = new IpnsRepublisher(sinon.stub(), sinon.stub(), sinon.stub(), sinon.stub(), { - initialBroadcastInterval: 500, - broadcastInterval: 1000 + initialBroadcastInterval: 200, + broadcastInterval: 500 }) republisher._republishEntries = sinon.stub() @@ -41,15 +41,35 @@ describe('name', function () { expect(republisher._republishEntries.calledOnce).to.equal(false) - // Initial republish should happen after ~500ms - await delay(750) + // Initial republish should happen after ~200ms + await delay(300) expect(republisher._republishEntries.calledOnce).to.equal(true) - // Subsequent republishes should happen after ~1500ms - await delay(1000) + // Subsequent republishes should happen after ~700 + await delay(600) expect(republisher._republishEntries.calledTwice).to.equal(true) }) + it('should not republish self key twice', async function () { + const mockKeychain = { + listKeys: () => Promise.resolve([{ name: 'self' }]) + } + republisher = new IpnsRepublisher(sinon.stub(), sinon.stub(), sinon.stub(), mockKeychain, { + initialBroadcastInterval: 100, + broadcastInterval: 1000, + pass: 'pass' + }) + republisher._republishEntry = sinon.stub() + + await republisher.start() + + expect(republisher._republishEntry.calledOnce).to.equal(false) + + // Initial republish should happen after ~100ms + await delay(200) + expect(republisher._republishEntry.calledOnce).to.equal(true) + }) + it('should error if run republish again', async () => { republisher = new IpnsRepublisher(sinon.stub(), sinon.stub(), sinon.stub(), sinon.stub(), { initialBroadcastInterval: 50, From d46559d14c37cebc9d2bd67865d3c270e8d2ccaf Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 28 Apr 2021 12:26:20 +0100 Subject: [PATCH 11/34] chore: update ipld-dag-cbor (#3642) Pulls in the latest borc for the latest buffer, also ipld and ipld-dag-cbor, all for the latest buffer. --- packages/interface-ipfs-core/package.json | 2 +- packages/ipfs-cli/package.json | 2 +- packages/ipfs-client/.aegir.js | 2 +- packages/ipfs-core-types/package.json | 2 +- packages/ipfs-core/.aegir.js | 2 +- packages/ipfs-core/package.json | 4 ++-- packages/ipfs-http-client/.aegir.js | 2 +- packages/ipfs-http-client/package.json | 4 ++-- packages/ipfs/.aegir.js | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 03fdfd946f..20b1c0978d 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -49,7 +49,7 @@ "ipfs-unixfs-importer": "^7.0.3", "ipfs-utils": "^6.0.4", "ipld-block": "^0.11.0", - "ipld-dag-cbor": "^0.18.0", + "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", "ipns": "^0.11.0", "is-ipfs": "^5.0.0", diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index edb4951ee9..bf51e626ca 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -44,7 +44,7 @@ "ipfs-http-client": "^49.0.4", "ipfs-repo": "^9.1.1", "ipfs-utils": "^6.0.4", - "ipld-dag-cbor": "^0.18.0", + "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", "it-all": "^1.0.4", "it-concat": "^2.0.0", diff --git a/packages/ipfs-client/.aegir.js b/packages/ipfs-client/.aegir.js index 3e94bf32cf..8942c3deb8 100644 --- a/packages/ipfs-client/.aegir.js +++ b/packages/ipfs-client/.aegir.js @@ -3,6 +3,6 @@ /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '127kB' + bundlesizeMax: '120kB' } } diff --git a/packages/ipfs-core-types/package.json b/packages/ipfs-core-types/package.json index fe9289074c..931f71a7c7 100644 --- a/packages/ipfs-core-types/package.json +++ b/packages/ipfs-core-types/package.json @@ -29,7 +29,7 @@ "license": "(Apache-2.0 OR MIT)", "dependencies": { "cids": "^1.1.6", - "ipld": "^0.29.0", + "ipld": "^0.30.0", "multiaddr": "^9.0.1", "multibase": "^4.0.2" }, diff --git a/packages/ipfs-core/.aegir.js b/packages/ipfs-core/.aegir.js index 35c38a3a8c..4be9fc4821 100644 --- a/packages/ipfs-core/.aegir.js +++ b/packages/ipfs-core/.aegir.js @@ -70,7 +70,7 @@ module.exports = { } }, build: { - bundlesizeMax: '542KB', + bundlesizeMax: '549KB', config: esbuild } } diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index c13b62e3d3..1dfa13aa17 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -79,9 +79,9 @@ "ipfs-unixfs-exporter": "^5.0.3", "ipfs-unixfs-importer": "^7.0.3", "ipfs-utils": "^6.0.4", - "ipld": "^0.29.0", + "ipld": "^0.30.0", "ipld-block": "^0.11.0", - "ipld-dag-cbor": "^0.18.0", + "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", "ipld-raw": "^7.0.0", "ipns": "^0.11.0", diff --git a/packages/ipfs-http-client/.aegir.js b/packages/ipfs-http-client/.aegir.js index 149fff9487..fec9ee097f 100644 --- a/packages/ipfs-http-client/.aegir.js +++ b/packages/ipfs-http-client/.aegir.js @@ -6,7 +6,7 @@ const getPort = require('aegir/utils/get-port') /** @type {import('aegir').PartialOptions} */ module.exports = { build: { - bundlesizeMax: '96KB' + bundlesizeMax: '89KB' }, test: { async before (options) { diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 98bcdeb066..f02c02c9c6 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -53,9 +53,9 @@ "ipfs-core-utils": "^0.7.2", "ipfs-unixfs": "^4.0.3", "ipfs-utils": "^6.0.4", - "ipld": "^0.29.0", + "ipld": "^0.30.0", "ipld-block": "^0.11.0", - "ipld-dag-cbor": "^0.18.0", + "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", "ipld-raw": "^7.0.0", "it-last": "^1.0.4", diff --git a/packages/ipfs/.aegir.js b/packages/ipfs/.aegir.js index 28b69a93f5..42b6de0a45 100644 --- a/packages/ipfs/.aegir.js +++ b/packages/ipfs/.aegir.js @@ -118,7 +118,7 @@ module.exports = { } }, build: { - bundlesizeMax: '542KB', + bundlesizeMax: '549KB', config: esbuild }, dependencyCheck: { From 3d68a4493d7dcc550a4c449490f5c950d00c27fc Mon Sep 17 00:00:00 2001 From: Ludwig <35169452+ludwigschubi@users.noreply.github.com> Date: Wed, 28 Apr 2021 16:25:55 +0200 Subject: [PATCH 12/34] docs: fix typo in readme (#3635) --- docs/core-api/FILES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core-api/FILES.md b/docs/core-api/FILES.md index 1c587b704d..2c6ad68622 100644 --- a/docs/core-api/FILES.md +++ b/docs/core-api/FILES.md @@ -121,7 +121,7 @@ The regular, top-level API for add, cat, get and ls Files on IPFS ```js { - // The path you want to the file to be accessible at from the root CID _after_ it has been added + // The path you want the file to be accessible at from the root CID _after_ it has been added path?: string // The contents of the file (see below for definition) content?: FileContent From 93e7dc43f1476a9a583f28cd8d9b30bb25ed9623 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 28 Apr 2021 16:22:27 +0100 Subject: [PATCH 13/34] chore: fix docker images (#3651) The python package has gone, we need to use python3 instead. There's a futher problem with npm not setting the $PATH properly so it fails as it can't find pbjs, but this is only necessary with gh dep versions which should go away with the next libp2p-kad-dht/libp2p-gossipsub releases. --- Dockerfile.latest | 4 ++-- Dockerfile.next | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile.latest b/Dockerfile.latest index aceceb7983..085684d7fd 100644 --- a/Dockerfile.latest +++ b/Dockerfile.latest @@ -5,13 +5,13 @@ ENV IPFS_MONITORING=1 ENV IPFS_PATH=/root/.jsipfs ENV BUILD_DEPS='libnspr4 libnspr4-dev libnss3' -RUN apk add --no-cache git python build-base +RUN apk add --no-cache git python3 build-base RUN npm install --unsafe-perm -g ipfs@"$IPFS_VERSION" # Make the image a bit smaller RUN npm cache clear --force -RUN apk del build-base python git +RUN apk del build-base python3 git # Configure jsipfs RUN jsipfs init diff --git a/Dockerfile.next b/Dockerfile.next index 3e2ad99d48..2c63a9f629 100644 --- a/Dockerfile.next +++ b/Dockerfile.next @@ -5,13 +5,13 @@ ENV IPFS_MONITORING=1 ENV IPFS_PATH=/root/.jsipfs ENV BUILD_DEPS='libnspr4 libnspr4-dev libnss3' -RUN apk add --no-cache git python build-base +RUN apk add --no-cache git python3 build-base RUN npm install --unsafe-perm -g ipfs@"$IPFS_VERSION" # Make the image a bit smaller RUN npm cache clear --force -RUN apk del build-base python git +RUN apk del build-base python3 git # Configure jsipfs RUN jsipfs init From 9e5afd66ab4eff58a0841ba11b8d1ca67eccb8f7 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 28 Apr 2021 17:29:23 +0100 Subject: [PATCH 14/34] chore: update libp2p to final release version (#3652) Also libp2p-kad-dht and libp2p-gossipsub. --- examples/custom-libp2p/package.json | 4 ++-- packages/ipfs-core/package.json | 6 +++--- packages/ipfs-daemon/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/custom-libp2p/package.json b/examples/custom-libp2p/package.json index 5b73f6c230..12ac5c2ad3 100644 --- a/examples/custom-libp2p/package.json +++ b/examples/custom-libp2p/package.json @@ -11,9 +11,9 @@ "license": "MIT", "dependencies": { "ipfs": "^0.54.4", - "libp2p": "^0.31.0-rc.6", + "libp2p": "^0.31.0", "libp2p-bootstrap": "^0.12.3", - "libp2p-kad-dht": "libp2p/js-libp2p-kad-dht#chore/update-deps-12-04-2021", + "libp2p-kad-dht": "^0.22.0", "libp2p-mdns": "^0.16.0", "libp2p-mplex": "^0.10.2", "libp2p-noise": "^3.0.0", diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index 1dfa13aa17..02bc42cda6 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -94,12 +94,12 @@ "it-map": "^1.0.4", "it-pipe": "^1.1.0", "just-safe-set": "^2.2.1", - "libp2p": "^0.31.0-rc.6", + "libp2p": "^0.31.0", "libp2p-bootstrap": "^0.12.3", "libp2p-crypto": "^0.19.3", "libp2p-floodsub": "^0.25.1", - "libp2p-gossipsub": "ChainSafe/js-libp2p-gossipsub#chore/update-deps-and-remove-protons", - "libp2p-kad-dht": "libp2p/js-libp2p-kad-dht#chore/update-deps-12-04-2021", + "libp2p-gossipsub": "^0.9.0", + "libp2p-kad-dht": "^0.22.0", "libp2p-mdns": "^0.16.0", "libp2p-mplex": "^0.10.2", "libp2p-noise": "^3.0.0", diff --git a/packages/ipfs-daemon/package.json b/packages/ipfs-daemon/package.json index 351fa31abd..4374a3244e 100644 --- a/packages/ipfs-daemon/package.json +++ b/packages/ipfs-daemon/package.json @@ -40,7 +40,7 @@ "ipfs-http-server": "^0.3.4", "ipfs-utils": "^6.0.4", "just-safe-set": "^2.2.1", - "libp2p": "^0.31.0-rc.6", + "libp2p": "^0.31.0", "libp2p-delegated-content-routing": "^0.10.0", "libp2p-delegated-peer-routing": "^0.9.0", "libp2p-webrtc-star": "^0.22.2", From 28ad9ad6e50abb89a366ecd6b5301e848f0e9962 Mon Sep 17 00:00:00 2001 From: Hannah Howard Date: Wed, 28 Apr 2021 10:26:14 -0700 Subject: [PATCH 15/34] feat: support identity hash in block.get + dag.get (#3616) - Adds support for identity hashes in ipfs-repo blockstore - Add core interface tests for block.get and dag.get when fetching identity hashes Refs: https://github.com/ipfs/js-ipfs-repo/pull/297 Closes: https://github.com/ipfs/js-ipfs/issues/3289 Co-authored-by: Alex Potsides --- packages/interface-ipfs-core/src/block/get.js | 12 ++++++++++-- packages/interface-ipfs-core/src/dag/get.js | 9 +++++++++ packages/ipfs-core/src/components/repo/gc.js | 1 + packages/ipfs-http-server/src/api/resources/block.js | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/interface-ipfs-core/src/block/get.js b/packages/interface-ipfs-core/src/block/get.js index 7ab52f83ff..c9790daa1f 100644 --- a/packages/interface-ipfs-core/src/block/get.js +++ b/packages/interface-ipfs-core/src/block/get.js @@ -2,7 +2,7 @@ 'use strict' const uint8ArrayFromString = require('uint8arrays/from-string') -const multihash = require('multihashing-async').multihash +const multihashing = require('multihashing-async') const CID = require('cids') const { getDescribe, getIt, expect } = require('../utils/mocha') const testTimeout = require('../utils/test-timeout') @@ -43,7 +43,7 @@ module.exports = (common, options) => { }) it('should get by CID in string', async () => { - const block = await ipfs.block.get(multihash.toB58String(hash)) + const block = await ipfs.block.get(multihashing.multihash.toB58String(hash)) expect(block.data).to.eql(uint8ArrayFromString('blorb')) expect(block.cid.multihash).to.eql(hash) @@ -89,6 +89,14 @@ module.exports = (common, options) => { expect(block.data).to.eql(input) }) + it('should get a block with an identity CID, without putting first', async () => { + const identityData = uint8ArrayFromString('A16461736466190144', 'base16upper') + const identityHash = await multihashing(identityData, 'identity') + const identityCID = new CID(1, 'dag-cbor', identityHash) + const block = await ipfs.block.get(identityCID) + expect(block.data).to.eql(identityData) + }) + it('should return an error for an invalid CID', () => { return expect(ipfs.block.get('Non-base58 character')).to.eventually.be.rejected .and.be.an.instanceOf(Error) diff --git a/packages/interface-ipfs-core/src/dag/get.js b/packages/interface-ipfs-core/src/dag/get.js index 4bff6a9528..cc7f7803e6 100644 --- a/packages/interface-ipfs-core/src/dag/get.js +++ b/packages/interface-ipfs-core/src/dag/get.js @@ -11,6 +11,7 @@ const all = require('it-all') const CID = require('cids') const { getDescribe, getIt, expect } = require('../utils/mocha') const testTimeout = require('../utils/test-timeout') +const multihashing = require('multihashing-async') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -240,6 +241,14 @@ module.exports = (common, options) => { expect(result.value).to.deep.equal(buf) }) + it('should be able to get a dag-cbor node with the identity hash', async () => { + const identityData = uint8ArrayFromString('A16461736466190144', 'base16upper') + const identityHash = await multihashing(identityData, 'identity') + const identityCID = new CID(1, 'dag-cbor', identityHash) + const result = await ipfs.dag.get(identityCID) + expect(result.value).to.deep.equal({ asdf: 324 }) + }) + it('should throw error for invalid string CID input', () => { return expect(ipfs.dag.get('INVALID CID')) .to.eventually.be.rejected() diff --git a/packages/ipfs-core/src/components/repo/gc.js b/packages/ipfs-core/src/components/repo/gc.js index cc3fdfd138..e022c23f89 100644 --- a/packages/ipfs-core/src/components/repo/gc.js +++ b/packages/ipfs-core/src/components/repo/gc.js @@ -17,6 +17,7 @@ const BLOCK_RM_CONCURRENCY = 256 * @typedef {import('ipfs-core-types/src/refs').API} RefsAPI * @typedef {import('ipfs-repo')} IPFSRepo * @typedef {import('interface-datastore').Key} Key + * @typedef {import('ipld-block')} Block */ /** diff --git a/packages/ipfs-http-server/src/api/resources/block.js b/packages/ipfs-http-server/src/api/resources/block.js index be4e47ecae..df8108da05 100644 --- a/packages/ipfs-http-server/src/api/resources/block.js +++ b/packages/ipfs-http-server/src/api/resources/block.js @@ -69,7 +69,7 @@ exports.get = { throw Boom.notFound('Block was unwanted before it could be remotely retrieved') } - return h.response(block.data).header('X-Stream-Output', '1') + return h.response(Buffer.from(block.data.buffer, block.data.byteOffset, block.data.byteLength)).header('X-Stream-Output', '1') } } exports.put = { From 084589c0116d8f27ce1462424fb93b6037b776a9 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 29 Apr 2021 16:04:14 +0100 Subject: [PATCH 16/34] fix: ignore the ts error caused by the recent protobufjs type change (#3656) The json generated by protobufjs is now not compatible with the types on protobufjs's `fromJSON` method. --- packages/ipfs-grpc-client/src/utils/load-services.js | 1 + packages/ipfs-grpc-server/src/utils/load-services.js | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/ipfs-grpc-client/src/utils/load-services.js b/packages/ipfs-grpc-client/src/utils/load-services.js index 5da8b1213c..b4032e6bd5 100644 --- a/packages/ipfs-grpc-client/src/utils/load-services.js +++ b/packages/ipfs-grpc-client/src/utils/load-services.js @@ -19,6 +19,7 @@ const CONVERSION_OPTS = { * service definition on both the server and the client. */ module.exports = function loadServices () { + // @ts-ignore - recent protobufjs release changed the types const root = protobuf.Root.fromJSON(protocol) /** @type {Record} */ const output = {} diff --git a/packages/ipfs-grpc-server/src/utils/load-services.js b/packages/ipfs-grpc-server/src/utils/load-services.js index 55664f0494..079632f53b 100644 --- a/packages/ipfs-grpc-server/src/utils/load-services.js +++ b/packages/ipfs-grpc-server/src/utils/load-services.js @@ -14,6 +14,7 @@ const CONVERSION_OPTS = { } module.exports = function loadServices () { + // @ts-ignore - recent protobufjs release changed the types const root = protobuf.Root.fromJSON(protocol) /** @type {Record} */ From 7e61fbf28dae722f3a9a3dc3ed5d38bbf2b64673 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 29 Apr 2021 16:24:59 +0100 Subject: [PATCH 17/34] chore: fix docker images (#3654) Install node-pre-gyp before IPFS and switch to official node image as the size difference is now quite small. --- Dockerfile.latest | 7 +++++-- Dockerfile.next | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Dockerfile.latest b/Dockerfile.latest index 085684d7fd..561126ae68 100644 --- a/Dockerfile.latest +++ b/Dockerfile.latest @@ -1,4 +1,4 @@ -FROM mhart/alpine-node:15 +FROM node:16-alpine ENV IPFS_VERSION=latest ENV IPFS_MONITORING=1 @@ -7,9 +7,12 @@ ENV BUILD_DEPS='libnspr4 libnspr4-dev libnss3' RUN apk add --no-cache git python3 build-base -RUN npm install --unsafe-perm -g ipfs@"$IPFS_VERSION" +# Hopefully remove when https://github.com/node-webrtc/node-webrtc/pull/694 is merged +RUN npm install -g @mapbox/node-pre-gyp +RUN npm install -g ipfs@"$IPFS_VERSION" # Make the image a bit smaller +RUN npm uninstall -g @mapbox/node-pre-gyp RUN npm cache clear --force RUN apk del build-base python3 git diff --git a/Dockerfile.next b/Dockerfile.next index 2c63a9f629..f517a8e350 100644 --- a/Dockerfile.next +++ b/Dockerfile.next @@ -1,4 +1,4 @@ -FROM mhart/alpine-node:15 +FROM node:16-alpine ENV IPFS_VERSION=next ENV IPFS_MONITORING=1 @@ -7,9 +7,12 @@ ENV BUILD_DEPS='libnspr4 libnspr4-dev libnss3' RUN apk add --no-cache git python3 build-base -RUN npm install --unsafe-perm -g ipfs@"$IPFS_VERSION" +# Hopefully remove when https://github.com/node-webrtc/node-webrtc/pull/694 is merged +RUN npm install -g @mapbox/node-pre-gyp +RUN npm install -g ipfs@"$IPFS_VERSION" # Make the image a bit smaller +RUN npm uninstall -g @mapbox/node-pre-gyp RUN npm cache clear --force RUN apk del build-base python3 git From 0ddbb1b1deb4e40dac3e365d7f98a5f174c2ce8f Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 30 Apr 2021 09:44:53 +0100 Subject: [PATCH 18/34] fix: update types after feedback from ceramic (#3657) Some of the types need a little correcting. Fixes #3640 --- examples/custom-ipfs-repo/package.json | 2 +- packages/ipfs-cli/package.json | 2 +- .../ipfs-core-types/src/config/index.d.ts | 4 +- packages/ipfs-core/package.json | 2 +- packages/ipfs-core/src/components/libp2p.js | 45 +++++++------------ packages/ipfs-core/src/components/network.js | 5 +-- .../ipfs-core/src/runtime/config-browser.js | 1 + .../ipfs-core/src/runtime/config-nodejs.js | 1 + packages/ipfs-core/src/types.d.ts | 4 +- 9 files changed, 27 insertions(+), 39 deletions(-) diff --git a/examples/custom-ipfs-repo/package.json b/examples/custom-ipfs-repo/package.json index 6ddb416f46..b941303b6d 100644 --- a/examples/custom-ipfs-repo/package.json +++ b/examples/custom-ipfs-repo/package.json @@ -12,7 +12,7 @@ "dependencies": { "datastore-fs": "4.0.0", "ipfs": "^0.54.4", - "ipfs-repo": "^9.1.1", + "ipfs-repo": "^9.1.3", "it-all": "^1.0.4" }, "devDependencies": { diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index bf51e626ca..c4eafac171 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -42,7 +42,7 @@ "ipfs-core-utils": "^0.7.2", "ipfs-daemon": "^0.5.4", "ipfs-http-client": "^49.0.4", - "ipfs-repo": "^9.1.1", + "ipfs-repo": "^9.1.3", "ipfs-utils": "^6.0.4", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", diff --git a/packages/ipfs-core-types/src/config/index.d.ts b/packages/ipfs-core-types/src/config/index.d.ts index 0c21ea3936..941b3033a8 100644 --- a/packages/ipfs-core-types/src/config/index.d.ts +++ b/packages/ipfs-core-types/src/config/index.d.ts @@ -51,7 +51,9 @@ export interface AddressConfig { RPC?: string Delegates?: string[] Gateway?: string - Swarm?: string[] + Swarm?: string[], + Announce?: string[], + NoAnnounce?: string[] } export interface APIConfig { diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index 02bc42cda6..60d3d2c5b7 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -74,7 +74,7 @@ "ipfs-block-service": "^0.19.0", "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", - "ipfs-repo": "^9.1.1", + "ipfs-repo": "^9.1.3", "ipfs-unixfs": "^4.0.3", "ipfs-unixfs-exporter": "^5.0.3", "ipfs-unixfs-importer": "^7.0.3", diff --git a/packages/ipfs-core/src/components/libp2p.js b/packages/ipfs-core/src/components/libp2p.js index 2fa457bf8c..e7167009cd 100644 --- a/packages/ipfs-core/src/components/libp2p.js +++ b/packages/ipfs-core/src/components/libp2p.js @@ -13,7 +13,7 @@ const PubsubRouters = require('../runtime/libp2p-pubsub-routers-nodejs') * @typedef {import('peer-id')} PeerId * @typedef {import('../types').Options} IPFSOptions * @typedef {import('libp2p')} LibP2P - * @typedef {import('libp2p').Libp2pOptions & import('libp2p').constructorOptions} Options + * @typedef {import('libp2p').Libp2pOptions & import('libp2p').CreateOptions} Libp2pOptions * @typedef {import('ipfs-core-types/src/config').Config} IPFSConfig * @typedef {import('multiaddr').Multiaddr} Multiaddr */ @@ -66,6 +66,7 @@ module.exports = ({ * @param {KeychainConfig} input.keychainConfig * @param {PeerId} input.peerId * @param {Multiaddr[]} input.multiaddrs + * @returns {Libp2pOptions} */ function getLibp2pOptions ({ options, config, datastore, keys, keychainConfig, peerId, multiaddrs }) { const getPubsubRouter = () => { @@ -93,25 +94,20 @@ function getLibp2pOptions ({ options, config, datastore, keys, keychainConfig, p config: { peerDiscovery: { mdns: { - enabled: get(options, 'config.Discovery.MDNS.Enabled', - get(config, 'Discovery.MDNS.Enabled', true)) + enabled: get(options, 'config.Discovery.MDNS.Enabled', get(config, 'Discovery.MDNS.Enabled', true)) }, webRTCStar: { - enabled: get(options, 'config.Discovery.webRTCStar.Enabled', - get(config, 'Discovery.webRTCStar.Enabled', true)) + enabled: get(options, 'config.Discovery.webRTCStar.Enabled', get(config, 'Discovery.webRTCStar.Enabled', true)) }, bootstrap: { list: get(options, 'config.Bootstrap', get(config, 'Bootstrap', [])) } }, relay: { - enabled: get(options, 'relay.enabled', - get(config, 'relay.enabled', true)), + enabled: get(options, 'relay.enabled', get(config, 'relay.enabled', true)), hop: { - enabled: get(options, 'relay.hop.enabled', - get(config, 'relay.hop.enabled', false)), - active: get(options, 'relay.hop.active', - get(config, 'relay.hop.active', false)) + enabled: get(options, 'relay.hop.enabled', get(config, 'relay.hop.enabled', false)), + active: get(options, 'relay.hop.active', get(config, 'relay.hop.active', false)) } }, dht: { @@ -120,30 +116,20 @@ function getLibp2pOptions ({ options, config, datastore, keys, keychainConfig, p kBucketSize: get(options, 'dht.kBucketSize', 20) }, pubsub: { - enabled: get(options, 'config.Pubsub.Enabled', - get(config, 'Pubsub.Enabled', true)) + enabled: get(options, 'config.Pubsub.Enabled', get(config, 'Pubsub.Enabled', true)) }, nat: { - enabled: get(options, 'libp2p.config.nat.enabled', !get(config, 'Swarm.DisableNatPortMap', false)), - ttl: get(options, 'libp2p.config.nat.ttl', 7200), - keepAlive: get(options, 'libp2p.config.nat.keepAlive', true), - gateway: get(options, 'libp2p.config.nat.gateway'), - externalIp: get(options, 'libp2p.config.nat.externalIp'), - pmp: { - enabled: get(options, 'libp2p.config.nat.pmp.enabled', false) - } + enabled: !get(config, 'Swarm.DisableNatPortMap', false) } }, addresses: { listen: multiaddrs.map(ma => ma.toString()), - announce: get(options, 'addresses.announce', - get(config, 'Addresses.Announce', [])) + announce: get(options, 'addresses.announce', get(config, 'Addresses.Announce', [])), + noAnnounce: get(options, 'addresses.noAnnounce', get(config, 'Addresses.NoAnnounce', [])) }, connectionManager: get(options, 'connectionManager', { - maxConnections: get(options, 'config.Swarm.ConnMgr.HighWater', - get(config, 'Swarm.ConnMgr.HighWater')), - minConnections: get(options, 'config.Swarm.ConnMgr.LowWater', - get(config, 'Swarm.ConnMgr.LowWater')) + maxConnections: get(options, 'config.Swarm.ConnMgr.HighWater', get(config, 'Swarm.ConnMgr.HighWater')), + minConnections: get(options, 'config.Swarm.ConnMgr.LowWater', get(config, 'Swarm.ConnMgr.LowWater')) }), keychain: { datastore: keys, @@ -155,10 +141,11 @@ function getLibp2pOptions ({ options, config, datastore, keys, keychainConfig, p // Note: libp2p-nodejs gets replaced by libp2p-browser when webpacked/browserified const getEnvLibp2pOptions = require('../runtime/libp2p-nodejs') - let constructorOptions = get(options, 'libp2p', {}) + /** @type {import('libp2p').Libp2pOptions | undefined} */ + let constructorOptions = get(options, 'libp2p', undefined) if (typeof constructorOptions === 'function') { - constructorOptions = {} + constructorOptions = undefined } // Merge defaults with Node.js/browser/other environments options and configuration diff --git a/packages/ipfs-core/src/components/network.js b/packages/ipfs-core/src/components/network.js index 5f8d05dd9d..1516fb9fc4 100644 --- a/packages/ipfs-core/src/components/network.js +++ b/packages/ipfs-core/src/components/network.js @@ -48,15 +48,14 @@ class Network { await repo.open() } + /** @type {IPFSConfig} */ const config = await repo.config.getAll() const libp2p = await createLibP2P({ options, repo, peerId, - // @ts-ignore - TODO move config types into ipfs-repo multiaddrs: readAddrs(peerId, config), - // @ts-ignore - TODO move config types into ipfs-repo config, keychainConfig: undefined }) @@ -90,10 +89,8 @@ class Network { module.exports = Network /** - * * @param {PeerId} peerId * @param {IPFSConfig} config - * @returns {Multiaddr[]} */ const readAddrs = (peerId, config) => { const peerIdStr = peerId.toB58String() diff --git a/packages/ipfs-core/src/runtime/config-browser.js b/packages/ipfs-core/src/runtime/config-browser.js index 249871bf51..08d65589be 100644 --- a/packages/ipfs-core/src/runtime/config-browser.js +++ b/packages/ipfs-core/src/runtime/config-browser.js @@ -5,6 +5,7 @@ module.exports = () => ({ Swarm: [ ], Announce: [], + NoAnnounce: [], API: '', Gateway: '', RPC: '', diff --git a/packages/ipfs-core/src/runtime/config-nodejs.js b/packages/ipfs-core/src/runtime/config-nodejs.js index 1ef765647c..3d9aba88f6 100644 --- a/packages/ipfs-core/src/runtime/config-nodejs.js +++ b/packages/ipfs-core/src/runtime/config-nodejs.js @@ -7,6 +7,7 @@ module.exports = () => ({ '/ip4/127.0.0.1/tcp/4003/ws' ], Announce: [], + NoAnnounce: [], API: '/ip4/127.0.0.1/tcp/5002', Gateway: '/ip4/127.0.0.1/tcp/9090', RPC: '/ip4/127.0.0.1/tcp/5003', diff --git a/packages/ipfs-core/src/types.d.ts b/packages/ipfs-core/src/types.d.ts index 557013ebf9..48547c1158 100644 --- a/packages/ipfs-core/src/types.d.ts +++ b/packages/ipfs-core/src/types.d.ts @@ -5,7 +5,7 @@ import type { ProfileNames } from 'ipfs-core-types/src/config/profiles' import type IPLD from 'ipld' import type { Options as IPLDOptions } from 'ipld' import type Libp2p from 'libp2p' -import type { Libp2pConfig as Libp2pOptions } from 'libp2p' +import type { Libp2pOptions } from 'libp2p' import type IPFSRepo from 'ipfs-repo' import type { ProgressCallback as MigrationProgressCallback } from 'ipfs-repo-migrations' import type { Datastore } from 'interface-datastore' @@ -117,7 +117,7 @@ export interface Options { * in Node.js, [`libp2p-browser.js`](../src/core/runtime/libp2p-browser.js) in * browsers. */ - libp2p?: Libp2pOptions | Libp2pFactoryFn + libp2p?: Partial | Libp2pFactoryFn silent?: boolean } From 06bd4f3cf18bd05837a8e38ff4b4cc03480885ae Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 30 Apr 2021 17:10:09 +0200 Subject: [PATCH 19/34] chore: update libp2p 0.31.2 (#3659) --- packages/ipfs-core/package.json | 2 +- packages/ipfs-daemon/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index 60d3d2c5b7..cc9b31ff60 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -94,7 +94,7 @@ "it-map": "^1.0.4", "it-pipe": "^1.1.0", "just-safe-set": "^2.2.1", - "libp2p": "^0.31.0", + "libp2p": "^0.31.2", "libp2p-bootstrap": "^0.12.3", "libp2p-crypto": "^0.19.3", "libp2p-floodsub": "^0.25.1", diff --git a/packages/ipfs-daemon/package.json b/packages/ipfs-daemon/package.json index 4374a3244e..9492b58047 100644 --- a/packages/ipfs-daemon/package.json +++ b/packages/ipfs-daemon/package.json @@ -40,7 +40,7 @@ "ipfs-http-server": "^0.3.4", "ipfs-utils": "^6.0.4", "just-safe-set": "^2.2.1", - "libp2p": "^0.31.0", + "libp2p": "^0.31.2", "libp2p-delegated-content-routing": "^0.10.0", "libp2p-delegated-peer-routing": "^0.9.0", "libp2p-webrtc-star": "^0.22.2", From 61d0981c05371c4846dcea3330ac9fb2e810b8fa Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 30 Apr 2021 18:06:00 +0100 Subject: [PATCH 20/34] fix: only use public api in http api server (#3660) We needed to reach into ipld in order to get at the formats so we can deserialize the data. Instead, put the data as a block and then read it out using ipfs.dag.get. Slightly inefficient but better to use the public API. Fixes #3639 --- packages/ipfs-http-server/package.json | 1 + .../ipfs-http-server/src/api/resources/dag.js | 25 +++++++++++++------ packages/ipfs-http-server/src/index.js | 9 +++---- packages/ipfs-http-server/src/types.d.ts | 2 +- packages/ipfs-http-server/test/inject/dag.js | 18 ++++++------- 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/packages/ipfs-http-server/package.json b/packages/ipfs-http-server/package.json index 4cb4115209..3b5cb073a7 100644 --- a/packages/ipfs-http-server/package.json +++ b/packages/ipfs-http-server/package.json @@ -43,6 +43,7 @@ "ipfs-core-utils": "^0.7.2", "ipfs-http-gateway": "^0.3.2", "ipfs-unixfs": "^4.0.3", + "ipld-block": "^0.11.1", "ipld-dag-pb": "^0.22.1", "it-all": "^1.0.4", "it-drain": "^1.0.3", diff --git a/packages/ipfs-http-server/src/api/resources/dag.js b/packages/ipfs-http-server/src/api/resources/dag.js index 2e313c3c47..0fe44cddf7 100644 --- a/packages/ipfs-http-server/src/api/resources/dag.js +++ b/packages/ipfs-http-server/src/api/resources/dag.js @@ -1,7 +1,8 @@ 'use strict' const multipart = require('../../utils/multipart-request-parser') -const mh = require('multihashing-async').multihash +const mha = require('multihashing-async') +const mh = mha.multihash const Joi = require('../../utils/joi') const Boom = require('@hapi/boom') const { @@ -9,6 +10,8 @@ const { } = require('ipfs-core-utils/src/cid') const all = require('it-all') const uint8ArrayToString = require('uint8arrays/to-string') +const Block = require('ipld-block') +const CID = require('cids') /** * @param {undefined | Uint8Array | Record} obj @@ -169,14 +172,17 @@ exports.put = { } } else { // the node is an uncommon format which the client should have - // serialized so deserialize it before continuing - const ipldFormat = await request.server.app.ipfs.ipld.getFormat(format) + // serialized so add it to the block store and fetch it deserialized + // before continuing + const hash = await mha(data, request.query.hash) + const cid = new CID(request.query.cidVersion, format, hash) - if (!ipldFormat) { - throw new Error(`Missing IPLD format "${format}"`) - } + await request.server.app.ipfs.block.put(new Block(data, cid)) - node = await ipldFormat.util.deserialize(data) + const { + value + } = await request.server.app.ipfs.dag.get(cid) + node = value } return { @@ -197,6 +203,7 @@ exports.put = { pin: Joi.boolean().default(false), hash: Joi.string().valid(...Object.keys(mh.names)).default('sha2-256'), cidBase: Joi.cidBase(), + cidVersion: Joi.number().integer().valid(0, 1).default(1), timeout: Joi.timeout() }) .rename('input-enc', 'inputEncoding', { @@ -207,6 +214,10 @@ exports.put = { override: true, ignoreUndefined: true }) + .rename('cid-version', 'cidVersion', { + override: true, + ignoreUndefined: true + }) } }, diff --git a/packages/ipfs-http-server/src/index.js b/packages/ipfs-http-server/src/index.js index fb0d99f8c7..50c03b90e5 100644 --- a/packages/ipfs-http-server/src/index.js +++ b/packages/ipfs-http-server/src/index.js @@ -17,7 +17,6 @@ const LOG_ERROR = 'ipfs:http-api:error' * @typedef {import('./types').Server} Server * @typedef {import('ipld')} IPLD * @typedef {import('libp2p')} libp2p - * @typedef {IPFS & { ipld: IPLD, libp2p: libp2p }} JSIPFS */ /** @@ -38,8 +37,8 @@ function hapiInfoToMultiaddr (info) { /** * @param {string | string[]} serverAddrs - * @param {(host: string, port: string, ipfs: JSIPFS, cors: Record) => Promise} createServer - * @param {JSIPFS} ipfs + * @param {(host: string, port: string, ipfs: IPFS, cors: Record) => Promise} createServer + * @param {IPFS} ipfs * @param {Record} cors */ async function serverCreator (serverAddrs, createServer, ipfs, cors) { @@ -61,7 +60,7 @@ async function serverCreator (serverAddrs, createServer, ipfs, cors) { class HttpApi { /** - * @param {JSIPFS} ipfs + * @param {IPFS} ipfs */ constructor (ipfs) { this._ipfs = ipfs @@ -98,7 +97,7 @@ class HttpApi { /** * @param {string} host * @param {string} port - * @param {JSIPFS} ipfs + * @param {IPFS} ipfs * @param {Record} cors */ async _createApiServer (host, port, ipfs, cors) { diff --git a/packages/ipfs-http-server/src/types.d.ts b/packages/ipfs-http-server/src/types.d.ts index 8f09c2394f..fbe0d52f75 100644 --- a/packages/ipfs-http-server/src/types.d.ts +++ b/packages/ipfs-http-server/src/types.d.ts @@ -7,7 +7,7 @@ import libp2p from 'libp2p' declare module '@hapi/hapi' { interface ServerApplicationState { - ipfs: IPFS & { ipld: IPLD, libp2p: libp2p } + ipfs: IPFS } interface RequestApplicationState { signal: AbortSignal diff --git a/packages/ipfs-http-server/test/inject/dag.js b/packages/ipfs-http-server/test/inject/dag.js index ab1a273d48..c25b2d94d2 100644 --- a/packages/ipfs-http-server/test/inject/dag.js +++ b/packages/ipfs-http-server/test/inject/dag.js @@ -38,8 +38,8 @@ describe('/dag', () => { put: sinon.stub(), resolve: sinon.stub() }, - ipld: { - getFormat: sinon.stub() + block: { + put: sinon.stub() } } }) @@ -295,16 +295,14 @@ describe('/dag', () => { expect(res).to.have.deep.nested.property('result.Cid', { '/': cid.toString() }) }) - it('should attempt to load an unsupported format', async () => { + it('adds a node with an esoteric format', async () => { + const cid = new CID('baf4beiata6mq425fzikf5m26temcvg7mizjrxrkn35swuybmpah2ajan5y') const data = Buffer.from('some data') const codec = 'git-raw' - const format = { - util: { - deserialize: (buf) => buf - } - } - ipfs.ipld.getFormat.withArgs(codec).returns(format) + ipfs.dag.get.withArgs(cid).returns({ + value: data + }) ipfs.dag.put.withArgs(data, { ...defaultOptions, format: codec @@ -316,7 +314,7 @@ describe('/dag', () => { ...await toHeadersAndPayload(data) }, { ipfs }) - expect(ipfs.ipld.getFormat.calledWith(codec)).to.be.true() + expect(ipfs.block.put.called).to.be.true() expect(res).to.have.property('statusCode', 200) expect(res).to.have.deep.nested.property('result.Cid', { '/': cid.toString() }) }) From 0fe8892361180dab53ed3c3b006479b32a792d44 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Sun, 2 May 2021 09:00:51 +0100 Subject: [PATCH 21/34] fix: fix types (#3662) * fix: fix types Fix type errors exposed by integrating with powergate-client. * chore: remove ipld dependency as the types are too heavy * chore: remove unused dep and import * chore: remove unused type --- packages/ipfs-core-types/package.json | 3 +- .../ipfs-core-types/src/object/index.d.ts | 4 +- packages/ipfs-core-types/src/pin/index.d.ts | 4 +- packages/ipfs-core-types/src/utils.d.ts | 56 +------------------ .../ipfs-core/src/components/pin/index.js | 17 +++--- packages/ipfs-http-client/package.json | 1 - .../ipfs-http-client/src/lib/ipld-formats.js | 8 +-- packages/ipfs-http-client/src/types.d.ts | 3 +- 8 files changed, 22 insertions(+), 74 deletions(-) diff --git a/packages/ipfs-core-types/package.json b/packages/ipfs-core-types/package.json index 931f71a7c7..a131cb475f 100644 --- a/packages/ipfs-core-types/package.json +++ b/packages/ipfs-core-types/package.json @@ -29,7 +29,8 @@ "license": "(Apache-2.0 OR MIT)", "dependencies": { "cids": "^1.1.6", - "ipld": "^0.30.0", + "interface-datastore": "^4.0.0", + "ipld-block": "^0.11.1", "multiaddr": "^9.0.1", "multibase": "^4.0.2" }, diff --git a/packages/ipfs-core-types/src/object/index.d.ts b/packages/ipfs-core-types/src/object/index.d.ts index 2a1206e095..f1864d9b2d 100644 --- a/packages/ipfs-core-types/src/object/index.d.ts +++ b/packages/ipfs-core-types/src/object/index.d.ts @@ -8,8 +8,8 @@ export interface API { put: (obj: DAGNode | DAGNodeLike | Uint8Array, options?: PutOptions & OptionExtension) => Promise get: (cid: CID, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise data: (cid: CID, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise - links: (cid, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise - stat: (cid, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise + links: (cid: CID, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise + stat: (cid: CID, options?: AbortOptions & PreloadOptions & OptionExtension) => Promise patch: PatchAPI } diff --git a/packages/ipfs-core-types/src/pin/index.d.ts b/packages/ipfs-core-types/src/pin/index.d.ts index 8072d32371..9a22c8f6a7 100644 --- a/packages/ipfs-core-types/src/pin/index.d.ts +++ b/packages/ipfs-core-types/src/pin/index.d.ts @@ -1,6 +1,6 @@ import type { AbortOptions, AwaitIterable } from '../utils' import type CID from 'cids' -import type { API as remote } from './remote' +import type { API as Remote } from './remote' export interface API { /** @@ -92,7 +92,7 @@ export interface API { */ rmAll: (source: AwaitIterable, options?: AbortOptions & OptionExtension) => AsyncIterable - remote + remote: Remote } export interface AddOptions extends AbortOptions { diff --git a/packages/ipfs-core-types/src/utils.d.ts b/packages/ipfs-core-types/src/utils.d.ts index 1ff3a28fdf..3424cfb307 100644 --- a/packages/ipfs-core-types/src/utils.d.ts +++ b/packages/ipfs-core-types/src/utils.d.ts @@ -1,5 +1,7 @@ import CID from 'cids' import { Mtime, MtimeLike } from 'ipfs-unixfs' +import { Options as DatastoreOptions, Query, KeyQuery } from 'interface-datastore' +import Block from 'ipld-block' export type Entry|Blob> = | FileEntry @@ -131,57 +133,3 @@ export interface BufferStore { get: (key: Uint8Array) => Promise stores: any[] } - -export interface Blockstore { - open: () => Promise - - /** - * Query the store - */ - query: (Query, options?: DatastoreOptions) => AsyncIterable - - /** - * Query the store, returning only keys - */ - queryKeys: (query: KeyQuery, options?: DatastoreOptions) => AsyncIterable - - /** - * Get a single block by CID - */ - get: (cid: CID, options?: DatastoreOptions) => Promise - - /** - * Like get, but for more - */ - getMany: (cids: AwaitIterable, options?: DatastoreOptions) => AsyncIterable - - /** - * Write a single block to the store - */ - put: (block: Block, options?: DatastoreOptions) => Promise - - /** - * Like put, but for more - */ - putMany: (blocks: AwaitIterable, options?: DatastoreOptions) => AsyncIterable - - /** - * Does the store contain block with this CID? - */ - has: (cid: CID, options?: DatastoreOptions) => Promise - - /** - * Delete a block from the store - */ - delete: (cid: CID, options?: DatastoreOptions) => Promise - - /** - * Delete a block from the store - */ - deleteMany: (cids: AwaitIterable, options?: DatastoreOptions) => AsyncIterable - - /** - * Close the store - */ - close: () => Promise -} diff --git a/packages/ipfs-core/src/components/pin/index.js b/packages/ipfs-core/src/components/pin/index.js index 468cab5d48..b78d33f647 100644 --- a/packages/ipfs-core/src/components/pin/index.js +++ b/packages/ipfs-core/src/components/pin/index.js @@ -27,17 +27,16 @@ class PinAPI { this.rm = createRm({ rmAll }) this.ls = createLs({ ipld, pinManager }) - const notImplemented = () => Promise.reject(new Error('Not implemented')) - + /** @type {import('ipfs-core-types/src/pin/remote').API} */ this.remote = { - add: notImplemented, - ls: notImplemented, - rm: notImplemented, - rmAll: notImplemented, + add: (cid, options = {}) => Promise.reject(new Error('Not implemented')), + ls: async function * (query, options = {}) { return Promise.reject(new Error('Not implemented')) }, // eslint-disable-line require-yield + rm: (query, options = {}) => Promise.reject(new Error('Not implemented')), + rmAll: (query, options = {}) => Promise.reject(new Error('Not implemented')), service: { - add: notImplemented, - rm: notImplemented, - ls: notImplemented + add: (name, credentials) => Promise.reject(new Error('Not implemented')), + rm: (name, options = {}) => Promise.reject(new Error('Not implemented')), + ls: (options = {}) => Promise.reject(new Error('Not implemented')) } } } diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index f02c02c9c6..8c0c90e8e5 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -53,7 +53,6 @@ "ipfs-core-utils": "^0.7.2", "ipfs-unixfs": "^4.0.3", "ipfs-utils": "^6.0.4", - "ipld": "^0.30.0", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", diff --git a/packages/ipfs-http-client/src/lib/ipld-formats.js b/packages/ipfs-http-client/src/lib/ipld-formats.js index ffcb753c18..69d47bae0b 100644 --- a/packages/ipfs-http-client/src/lib/ipld-formats.js +++ b/packages/ipfs-http-client/src/lib/ipld-formats.js @@ -8,7 +8,8 @@ const multicodec = require('multicodec') /** * @typedef {import('cids')} CID * @typedef {import('interface-ipld-format').Format} IPLDFormat - * @typedef {import('ipld').LoadFormatFn} LoadFormatFn + * @typedef {import('multicodec').CodecName} CodecName + * @typedef {import('../types').LoadFormatFn} LoadFormatFn */ /** @@ -23,7 +24,7 @@ const noop = (codec) => { * * @param {object} [options] - IPLD options passed to the http client constructor * @param {IPLDFormat[]} [options.formats] - A list of IPLD Formats to use - * @param {import('ipld').LoadFormatFn} [options.loadFormat] - An async function that can load a format when passed a codec number + * @param {LoadFormatFn} [options.loadFormat] - An async function that can load a format when passed a codec name */ module.exports = ({ formats = [], loadFormat = noop } = {}) => { formats = formats || [] @@ -42,11 +43,10 @@ module.exports = ({ formats = [], loadFormat = noop } = {}) => { /** * Attempts to load an IPLD format for the passed CID * - * @param {import('multicodec').CodecName} codec - The code to load the format for + * @param {CodecName} codec - The code to load the format for */ const loadResolver = async (codec) => { const number = multicodec.getCodeFromName(codec) - // @ts-ignore wat const format = configuredFormats[number] || await loadFormat(codec) if (!format) { diff --git a/packages/ipfs-http-client/src/types.d.ts b/packages/ipfs-http-client/src/types.d.ts index b6d9e45527..582bbfebf3 100644 --- a/packages/ipfs-http-client/src/types.d.ts +++ b/packages/ipfs-http-client/src/types.d.ts @@ -1,9 +1,10 @@ import { Format as IPLDFormat } from 'interface-ipld-format' -import { LoadFormatFn } from 'ipld' import { Agent as HttpAgent } from 'http' import { Agent as HttpsAgent } from 'https' import { Multiaddr } from 'multiaddr' +export type LoadFormatFn = (name: CodecName) => Promise + export interface Options { host?: string port?: number From 64cc1e1ea7da77f1553ac127e9fef1905f7c78da Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Sun, 2 May 2021 11:57:22 +0100 Subject: [PATCH 22/34] fix: add missing type import (#3664) And generic format type too. --- packages/ipfs-http-client/src/types.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ipfs-http-client/src/types.d.ts b/packages/ipfs-http-client/src/types.d.ts index 582bbfebf3..0579c49520 100644 --- a/packages/ipfs-http-client/src/types.d.ts +++ b/packages/ipfs-http-client/src/types.d.ts @@ -2,8 +2,9 @@ import { Format as IPLDFormat } from 'interface-ipld-format' import { Agent as HttpAgent } from 'http' import { Agent as HttpsAgent } from 'https' import { Multiaddr } from 'multiaddr' +import { CodecName } from 'multicodec' -export type LoadFormatFn = (name: CodecName) => Promise +export type LoadFormatFn = (name: CodecName) => Promise> export interface Options { host?: string From 9bc2d7ca4fa4adcefd1cb8d95de4711ed4f7861c Mon Sep 17 00:00:00 2001 From: Ludwig <35169452+ludwigschubi@users.noreply.github.com> Date: Tue, 4 May 2021 10:03:42 +0200 Subject: [PATCH 23/34] docs: fix example for pin remote service add (#3636) Update key name --- docs/core-api/PIN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core-api/PIN.md b/docs/core-api/PIN.md index cd68eb3d52..54a25e3df4 100644 --- a/docs/core-api/PIN.md +++ b/docs/core-api/PIN.md @@ -303,7 +303,7 @@ An object may have the following optional fields: ```JavaScript await ipfs.pin.remote.sevice.add('pinata', { endpoint: new URL('https://api.pinata.cloud'), - name: 'block-party' + key: 'your-pinata-key' }) ``` From f98af8ed24784929898bb5d33a64dc442c77074d Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 4 May 2021 10:49:37 +0100 Subject: [PATCH 24/34] fix: mark ipld options as partial (#3669) Otherwise the user has to specify a blockstore etc. We make the options object whole before instantiating ipld. --- examples/browser-ipns-publish/package.json | 2 +- examples/custom-ipfs-repo/package.json | 2 +- packages/interface-ipfs-core/package.json | 2 +- packages/ipfs-cli/package.json | 4 ++-- packages/ipfs-core-types/src/config/index.d.ts | 2 +- packages/ipfs-core-utils/package.json | 2 +- packages/ipfs-core/package.json | 4 ++-- packages/ipfs-core/src/components/cat.js | 3 ++- packages/ipfs-core/src/components/get.js | 3 ++- packages/ipfs-core/src/components/ipld.js | 2 +- packages/ipfs-core/src/components/ls.js | 3 ++- packages/ipfs-core/src/preload.js | 11 +++++------ packages/ipfs-core/src/runtime/ipld.js | 3 ++- packages/ipfs-core/src/types.d.ts | 13 ++++++------- packages/ipfs-daemon/package.json | 2 +- packages/ipfs-http-client/package.json | 2 +- packages/ipfs-http-client/src/lib/core.js | 2 -- packages/ipfs/package.json | 2 +- 18 files changed, 32 insertions(+), 32 deletions(-) diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index c111149010..f13bbf5a3d 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -16,7 +16,7 @@ "human-crypto-keys": "^0.1.4", "ipfs": "^0.54.4", "ipfs-http-client": "^49.0.4", - "ipfs-utils": "^6.0.4", + "ipfs-utils": "^7.0.0", "ipns": "^0.11.0", "it-last": "^1.0.4", "p-retry": "^4.2.0", diff --git a/examples/custom-ipfs-repo/package.json b/examples/custom-ipfs-repo/package.json index b941303b6d..063c869baf 100644 --- a/examples/custom-ipfs-repo/package.json +++ b/examples/custom-ipfs-repo/package.json @@ -12,7 +12,7 @@ "dependencies": { "datastore-fs": "4.0.0", "ipfs": "^0.54.4", - "ipfs-repo": "^9.1.3", + "ipfs-repo": "^9.1.4", "it-all": "^1.0.4" }, "devDependencies": { diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 20b1c0978d..0f1ea1030f 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -47,7 +47,7 @@ "err-code": "^3.0.1", "ipfs-unixfs": "^4.0.3", "ipfs-unixfs-importer": "^7.0.3", - "ipfs-utils": "^6.0.4", + "ipfs-utils": "^7.0.0", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index c4eafac171..974b2e2a02 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -42,8 +42,8 @@ "ipfs-core-utils": "^0.7.2", "ipfs-daemon": "^0.5.4", "ipfs-http-client": "^49.0.4", - "ipfs-repo": "^9.1.3", - "ipfs-utils": "^6.0.4", + "ipfs-repo": "^9.1.4", + "ipfs-utils": "^7.0.0", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", "it-all": "^1.0.4", diff --git a/packages/ipfs-core-types/src/config/index.d.ts b/packages/ipfs-core-types/src/config/index.d.ts index 941b3033a8..d039f88e64 100644 --- a/packages/ipfs-core-types/src/config/index.d.ts +++ b/packages/ipfs-core-types/src/config/index.d.ts @@ -109,7 +109,7 @@ export interface IdentityConfig { /** * The base64 encoded protobuf describing (and containing) the nodes private key. */ - PrivateKey: string + PrivKey: string } export interface KeychainConfig { diff --git a/packages/ipfs-core-utils/package.json b/packages/ipfs-core-utils/package.json index 2755a324ef..f7597b7517 100644 --- a/packages/ipfs-core-utils/package.json +++ b/packages/ipfs-core-utils/package.json @@ -48,7 +48,7 @@ "err-code": "^3.0.1", "ipfs-core-types": "^0.3.1", "ipfs-unixfs": "^4.0.3", - "ipfs-utils": "^6.0.4", + "ipfs-utils": "^7.0.0", "it-all": "^1.0.4", "it-map": "^1.0.4", "it-peekable": "^1.0.1", diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index cc9b31ff60..cfd5f744db 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -74,11 +74,11 @@ "ipfs-block-service": "^0.19.0", "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", - "ipfs-repo": "^9.1.3", + "ipfs-repo": "^9.1.4", "ipfs-unixfs": "^4.0.3", "ipfs-unixfs-exporter": "^5.0.3", "ipfs-unixfs-importer": "^7.0.3", - "ipfs-utils": "^6.0.4", + "ipfs-utils": "^7.0.0", "ipld": "^0.30.0", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^1.0.0", diff --git a/packages/ipfs-core/src/components/cat.js b/packages/ipfs-core/src/components/cat.js index e161a608d3..1b491f3fd1 100644 --- a/packages/ipfs-core/src/components/cat.js +++ b/packages/ipfs-core/src/components/cat.js @@ -3,6 +3,7 @@ const { exporter } = require('ipfs-unixfs-exporter') const { normalizeCidPath } = require('../utils') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +const CID = require('cids') /** * @typedef {Object} Context @@ -20,7 +21,7 @@ module.exports = function ({ ipld, preload }) { if (options.preload !== false) { const pathComponents = ipfsPath.split('/') - preload(pathComponents[0]) + preload(new CID(pathComponents[0])) } const file = await exporter(ipfsPath, ipld, options) diff --git a/packages/ipfs-core/src/components/get.js b/packages/ipfs-core/src/components/get.js index f7a30afe60..0c972902b1 100644 --- a/packages/ipfs-core/src/components/get.js +++ b/packages/ipfs-core/src/components/get.js @@ -4,6 +4,7 @@ const exporter = require('ipfs-unixfs-exporter') const errCode = require('err-code') const { normalizeCidPath, mapFile } = require('../utils') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +const CID = require('cids') /** * @typedef {Object} Context @@ -26,7 +27,7 @@ module.exports = function ({ ipld, preload }) { throw errCode(err, 'ERR_INVALID_PATH') } - preload(pathComponents[0]) + preload(new CID(pathComponents[0])) } for await (const file of exporter.recursive(ipfsPath, ipld, options)) { diff --git a/packages/ipfs-core/src/components/ipld.js b/packages/ipfs-core/src/components/ipld.js index 998166a50d..4f9f688fca 100644 --- a/packages/ipfs-core/src/components/ipld.js +++ b/packages/ipfs-core/src/components/ipld.js @@ -6,7 +6,7 @@ const Ipld = require('ipld') /** * @param {Object} config * @param {import('ipfs-block-service')} config.blockService - * @param {import('ipld').Options} [config.options] + * @param {Partial} [config.options] */ const createIPLD = ({ blockService, options }) => { return new Ipld(getDefaultIpldOptions(blockService, options)) diff --git a/packages/ipfs-core/src/components/ls.js b/packages/ipfs-core/src/components/ls.js index d19bb5ee21..d7d703d8b2 100644 --- a/packages/ipfs-core/src/components/ls.js +++ b/packages/ipfs-core/src/components/ls.js @@ -4,6 +4,7 @@ const { exporter, recursive } = require('ipfs-unixfs-exporter') const errCode = require('err-code') const { normalizeCidPath, mapFile } = require('../utils') const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') +const CID = require('cids') /** * @typedef {Object} Context @@ -21,7 +22,7 @@ module.exports = function ({ ipld, preload }) { const pathComponents = path.split('/') if (options.preload !== false) { - preload(pathComponents[0]) + preload(new CID(pathComponents[0])) } const file = await exporter(ipfsPath, ipld, options) diff --git a/packages/ipfs-core/src/preload.js b/packages/ipfs-core/src/preload.js index d0eca680a4..38429537b8 100644 --- a/packages/ipfs-core/src/preload.js +++ b/packages/ipfs-core/src/preload.js @@ -3,7 +3,6 @@ // @ts-ignore no types const toUri = require('multiaddr-to-uri') const debug = require('debug') -const CID = require('cids') const shuffle = require('array-shuffle') const { AbortController } = require('native-abort-controller') const preload = require('./runtime/preload-nodejs') @@ -44,14 +43,14 @@ const createPreloader = (options = {}) => { /** * @type {import('./types').Preload} */ - const api = async path => { + const api = async cid => { try { - if (stopped) throw new Error(`preload ${path} but preloader is not started`) - - if (typeof path !== 'string') { - path = new CID(path).toString() + if (stopped) { + throw new Error(`preload ${cid} but preloader is not started`) } + const path = cid.toString() + if (cache.has(path)) { // we've preloaded this recently, don't preload it again return diff --git a/packages/ipfs-core/src/runtime/ipld.js b/packages/ipfs-core/src/runtime/ipld.js index 61e51d6977..b439caa964 100644 --- a/packages/ipfs-core/src/runtime/ipld.js +++ b/packages/ipfs-core/src/runtime/ipld.js @@ -5,6 +5,7 @@ const multicodec = require('multicodec') /** * @typedef {import('interface-ipld-format').Format} IPLDFormat + * @typedef {import('ipld').Options} IPLDOptions */ /** @@ -26,7 +27,7 @@ const IpldFormats = { /** * @param {import('ipfs-block-service')} blockService - * @param {import('ipld').Options} [options] + * @param {Partial} [options] */ module.exports = (blockService, options) => { return mergeOptions.call( diff --git a/packages/ipfs-core/src/types.d.ts b/packages/ipfs-core/src/types.d.ts index 48547c1158..eb22cf8213 100644 --- a/packages/ipfs-core/src/types.d.ts +++ b/packages/ipfs-core/src/types.d.ts @@ -1,16 +1,15 @@ import type { KeyType } from 'libp2p-crypto' import type PeerId from 'peer-id' -import type { IPFSConfig } from 'ipfs-core-types/src/config' -import type { ProfileNames } from 'ipfs-core-types/src/config/profiles' -import type IPLD from 'ipld' +import type { Config as IPFSConfig } from 'ipfs-core-types/src/config' import type { Options as IPLDOptions } from 'ipld' import type Libp2p from 'libp2p' import type { Libp2pOptions } from 'libp2p' import type IPFSRepo from 'ipfs-repo' import type { ProgressCallback as MigrationProgressCallback } from 'ipfs-repo-migrations' -import type { Datastore } from 'interface-datastore' -import type Network, { Options as NetworkOptions } from './components/network' +import type Network from './components/network' +import type { Options as NetworkOptions } from './components/network' import type Service from './utils/service' +import CID from 'cids' export interface Options { /** @@ -100,7 +99,7 @@ export interface Options { * (https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs/src/core/runtime/ipld.js) * in browsers) */ - ipld?: IPLDOptions + ipld?: Partial /** * The libp2p option allows you to build @@ -152,7 +151,7 @@ export interface InitOptions { /** * Apply profile settings to config */ - profiles?: ProfileNames[] + profiles?: string[] /** * Set to `false` to disallow initialization if the repo does not already exist diff --git a/packages/ipfs-daemon/package.json b/packages/ipfs-daemon/package.json index 9492b58047..d671feb58e 100644 --- a/packages/ipfs-daemon/package.json +++ b/packages/ipfs-daemon/package.json @@ -38,7 +38,7 @@ "ipfs-http-client": "^49.0.4", "ipfs-http-gateway": "^0.3.2", "ipfs-http-server": "^0.3.4", - "ipfs-utils": "^6.0.4", + "ipfs-utils": "^7.0.0", "just-safe-set": "^2.2.1", "libp2p": "^0.31.2", "libp2p-delegated-content-routing": "^0.10.0", diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 8c0c90e8e5..80f00e9a2f 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -52,7 +52,7 @@ "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", "ipfs-unixfs": "^4.0.3", - "ipfs-utils": "^6.0.4", + "ipfs-utils": "^7.0.0", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", diff --git a/packages/ipfs-http-client/src/lib/core.js b/packages/ipfs-http-client/src/lib/core.js index eb1340716a..e03592bd9a 100644 --- a/packages/ipfs-http-client/src/lib/core.js +++ b/packages/ipfs-http-client/src/lib/core.js @@ -15,8 +15,6 @@ const DEFAULT_HOST = isBrowser || isWebWorker ? location.hostname : 'localhost' const DEFAULT_PORT = isBrowser || isWebWorker ? location.port : '5001' /** - * @typedef {import('ipfs-utils/dist/types/native-fetch').Response} Response - * @typedef {import('ipfs-utils/dist/types/native-fetch').Request} Request * @typedef {import('ipfs-utils/src/types').HTTPOptions} HTTPOptions * @typedef {import('../types').Options} Options */ diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index 69ae0b8dd5..3bd452604a 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -57,7 +57,7 @@ "ipfs-core-types": "^0.3.1", "ipfs-http-client": "^49.0.4", "ipfs-interop": "^5.0.2", - "ipfs-utils": "^6.0.4", + "ipfs-utils": "^7.0.0", "ipfsd-ctl": "^8.0.1", "iso-url": "^1.0.0", "libp2p-webrtc-star": "^0.22.2", From eccb067fad5948d1cac6440339a8dae72bb5ca72 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 4 May 2021 11:13:23 +0100 Subject: [PATCH 25/34] chore: remove sidetree test (#3670) sidetree removed the direct dependency on js-ipfs in https://github.com/decentralized-identity/sidetree/commit/be481c002c8643d65e7203097338ddc94eca6cd6#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519 License: MIT Signed-off-by: Oli Evans --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6a63caff09..c6ee3beba2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -81,7 +81,6 @@ jobs: - name: external - service-worker-gateway - name: external - orbit-db - name: external - ipfs-log - - name: external - sidetree include: - stage: test @@ -371,12 +370,5 @@ jobs: script: - npm run test:external -- -- -- https://github.com/orbitdb/ipfs-log.git --deps=ipfs@next - - stage: test-external - # only run on changes to master - if: branch = master AND type = push AND fork = false - name: external - sidetree - script: - - npm run test:external -- -- -- https://github.com/decentralized-identity/sidetree.git --deps=ipfs@next - notifications: email: false From 9029ee591fa74ea65c9600f2d249897e933416fa Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 4 May 2021 14:11:09 +0100 Subject: [PATCH 26/34] fix: update ipfs repo (#3671) Align config types --- examples/custom-ipfs-repo/package.json | 2 +- examples/running-multiple-nodes/README.md | 3 ++- examples/running-multiple-nodes/test.js | 4 +++- packages/ipfs-cli/package.json | 2 +- packages/ipfs-core-types/src/config/index.d.ts | 2 +- packages/ipfs-core/package.json | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/custom-ipfs-repo/package.json b/examples/custom-ipfs-repo/package.json index 063c869baf..5a0f834c5e 100644 --- a/examples/custom-ipfs-repo/package.json +++ b/examples/custom-ipfs-repo/package.json @@ -12,7 +12,7 @@ "dependencies": { "datastore-fs": "4.0.0", "ipfs": "^0.54.4", - "ipfs-repo": "^9.1.4", + "ipfs-repo": "^9.1.6", "it-all": "^1.0.4" }, "devDependencies": { diff --git a/examples/running-multiple-nodes/README.md b/examples/running-multiple-nodes/README.md index 2955bf861b..fe8bc45057 100644 --- a/examples/running-multiple-nodes/README.md +++ b/examples/running-multiple-nodes/README.md @@ -72,7 +72,8 @@ await IPFS.create({ '/ip4/127.0.0.1/tcp/4013/ws' ], API: '/ip4/127.0.0.1/tcp/5012', - Gateway: '/ip4/127.0.0.1/tcp/9191' + Gateway: '/ip4/127.0.0.1/tcp/9191', + RPC: '/ip4/127.0.0.1/tcp/4839' } } }) diff --git a/examples/running-multiple-nodes/test.js b/examples/running-multiple-nodes/test.js index 43222823f7..ff661328fa 100644 --- a/examples/running-multiple-nodes/test.js +++ b/examples/running-multiple-nodes/test.js @@ -31,6 +31,7 @@ async function startCliNode () { await execa(ipfs, ['config', 'Addresses.Swarm', '--json', JSON.stringify([`/ip4/0.0.0.0/tcp/0`, `/ip4/127.0.0.1/tcp/0/ws`])], opts) await execa(ipfs, ['config', 'Addresses.API', `/ip4/127.0.0.1/tcp/0`], opts) await execa(ipfs, ['config', 'Addresses.Gateway', `/ip4/127.0.0.1/tcp/0`], opts) + await execa(ipfs, ['config', 'Addresses.RPC', `/ip4/127.0.0.1/tcp/0`], opts) return waitForOutput('Daemon is ready', ipfs, ['daemon'], opts) } @@ -53,7 +54,8 @@ async function startProgramaticNode () { `/ip4/127.0.0.1/tcp/0/ws` ], API: `/ip4/127.0.0.1/tcp/0`, - Gateway: `/ip4/127.0.0.1/tcp/0` + Gateway: `/ip4/127.0.0.1/tcp/0`, + RPC: `/ip4/127.0.0.1/tcp/0` }, Bootstrap: [] } diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index 974b2e2a02..6211dfe94c 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -42,7 +42,7 @@ "ipfs-core-utils": "^0.7.2", "ipfs-daemon": "^0.5.4", "ipfs-http-client": "^49.0.4", - "ipfs-repo": "^9.1.4", + "ipfs-repo": "^9.1.6", "ipfs-utils": "^7.0.0", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", diff --git a/packages/ipfs-core-types/src/config/index.d.ts b/packages/ipfs-core-types/src/config/index.d.ts index d039f88e64..61881834b2 100644 --- a/packages/ipfs-core-types/src/config/index.d.ts +++ b/packages/ipfs-core-types/src/config/index.d.ts @@ -57,7 +57,7 @@ export interface AddressConfig { } export interface APIConfig { - HTTPHeaders?: Record + HTTPHeaders?: Record } export interface DiscoveryConfig { diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index cfd5f744db..c51ab02681 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -74,7 +74,7 @@ "ipfs-block-service": "^0.19.0", "ipfs-core-types": "^0.3.1", "ipfs-core-utils": "^0.7.2", - "ipfs-repo": "^9.1.4", + "ipfs-repo": "^9.1.6", "ipfs-unixfs": "^4.0.3", "ipfs-unixfs-exporter": "^5.0.3", "ipfs-unixfs-importer": "^7.0.3", From 5eb32a75137f8ddfc76567e89b1e35c982cc3f7f Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 6 May 2021 11:48:48 +0100 Subject: [PATCH 27/34] docs: add missing repo API docs link (#3672) --- docs/core-api/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/core-api/README.md b/docs/core-api/README.md index 055560db23..0578a9eef7 100644 --- a/docs/core-api/README.md +++ b/docs/core-api/README.md @@ -18,5 +18,6 @@ It is broken up into the following sections: * [PIN.md](PIN.md) * [PUBSUB.md](PUBSUB.md) * [REFS.md](REFS.md) +* [REPO.md](REPO.md) * [STATS.md](STATS.md) * [SWARM.md](SWARM.md) From 46618c795bf5363ba3186645640fb81349231db7 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 6 May 2021 14:01:05 +0100 Subject: [PATCH 28/34] fix: loosen input type for swarm.connect and swarm.disconnect (#3673) Accept peer ids as strings or multiaddrs as Multiaddrs. Fixes #3638 --- packages/ipfs-core-types/src/bitswap/index.d.ts | 2 +- packages/ipfs-core-types/src/dht/index.d.ts | 4 ++-- packages/ipfs-core-types/src/root.d.ts | 2 +- packages/ipfs-core-types/src/stats/index.d.ts | 2 +- packages/ipfs-core-types/src/swarm/index.d.ts | 10 +++++----- packages/ipfs-http-client/src/dht/find-peer.js | 3 +-- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/ipfs-core-types/src/bitswap/index.d.ts b/packages/ipfs-core-types/src/bitswap/index.d.ts index e5cf40e119..de1b2dabfa 100644 --- a/packages/ipfs-core-types/src/bitswap/index.d.ts +++ b/packages/ipfs-core-types/src/bitswap/index.d.ts @@ -24,7 +24,7 @@ export interface API { * // [ CID('QmHash') ] * ``` */ - wantlistForPeer: (peerId: CID | string, options?: AbortOptions & OptionExtension) => Promise + wantlistForPeer: (peerId: string, options?: AbortOptions & OptionExtension) => Promise /** * Removes one or more CIDs from the wantlist diff --git a/packages/ipfs-core-types/src/dht/index.d.ts b/packages/ipfs-core-types/src/dht/index.d.ts index 00c4aeaea1..91aa08c7ed 100644 --- a/packages/ipfs-core-types/src/dht/index.d.ts +++ b/packages/ipfs-core-types/src/dht/index.d.ts @@ -21,7 +21,7 @@ export interface API { * // '/ip4/147.75.94.115/tcp/4001' * ``` */ - findPeer: (peerId: CID | string, options?: AbortOptions & OptionExtension) => Promise + findPeer: (peerId: string, options?: AbortOptions & OptionExtension) => Promise /** * Find peers in the DHT that can provide a specific value, given a CID. @@ -59,7 +59,7 @@ export interface API { /** * Find the closest peers to a given `PeerId`, by querying the DHT. */ - query: (peerId: CID | string, options?: AbortOptions & OptionExtension) => AsyncIterable + query: (peerId: string, options?: AbortOptions & OptionExtension) => AsyncIterable } export interface PeerResult { diff --git a/packages/ipfs-core-types/src/root.d.ts b/packages/ipfs-core-types/src/root.d.ts index dba7e3e22f..3615811025 100644 --- a/packages/ipfs-core-types/src/root.d.ts +++ b/packages/ipfs-core-types/src/root.d.ts @@ -82,7 +82,7 @@ export interface API { * } * ``` */ - ping: (peerId: CID | string, options?: PingOptions & OptionExtension) => AsyncIterable + ping: (peerId: string, options?: PingOptions & OptionExtension) => AsyncIterable /** * Resolve the value of names to IPFS diff --git a/packages/ipfs-core-types/src/stats/index.d.ts b/packages/ipfs-core-types/src/stats/index.d.ts index 828617c950..8a2e997f21 100644 --- a/packages/ipfs-core-types/src/stats/index.d.ts +++ b/packages/ipfs-core-types/src/stats/index.d.ts @@ -14,7 +14,7 @@ export interface API { } export interface BWOptions extends AbortOptions { - peer?: CID | string + peer?: string proto?: string poll?: boolean interval?: number diff --git a/packages/ipfs-core-types/src/swarm/index.d.ts b/packages/ipfs-core-types/src/swarm/index.d.ts index 69b1ba872b..910e63271e 100644 --- a/packages/ipfs-core-types/src/swarm/index.d.ts +++ b/packages/ipfs-core-types/src/swarm/index.d.ts @@ -5,20 +5,20 @@ import type CID from 'cids' import type { Multiaddr } from 'multiaddr' export interface API { - /** + /** * List of known addresses of each peer connected */ addrs: (options?: AbortOptions & OptionExtension) => Promise /** - * Open a connection to a given address + * Open a connection to a given address or peer id */ - connect: (addr: Multiaddr, options?: AbortOptions & OptionExtension) => Promise + connect: (addr: Multiaddr | string, options?: AbortOptions & OptionExtension) => Promise /** - * Close a connection to a given address + * Close a connection to a given address or peer id */ - disconnect: (addr: Multiaddr, options?: AbortOptions & OptionExtension) => Promise + disconnect: (addr: Multiaddr | string, options?: AbortOptions & OptionExtension) => Promise /** * Local addresses this node is listening on diff --git a/packages/ipfs-http-client/src/dht/find-peer.js b/packages/ipfs-http-client/src/dht/find-peer.js index f4eabe5370..4e9880fb9e 100644 --- a/packages/ipfs-http-client/src/dht/find-peer.js +++ b/packages/ipfs-http-client/src/dht/find-peer.js @@ -1,6 +1,5 @@ 'use strict' -const CID = require('cids') const { Multiaddr } = require('multiaddr') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') @@ -20,7 +19,7 @@ module.exports = configure(api => { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: `${peerId instanceof Uint8Array ? new CID(peerId) : peerId}`, + arg: peerId, ...options }), headers: options.headers From 0b2d98c53ba18491d7b99ae9cc0955281146610d Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 7 May 2021 12:00:32 +0100 Subject: [PATCH 29/34] fix: reject requests when cors origin list is empty (#3674) If CORS origin list is empty, Hapi throws an error as it considers that to be invalid configuration. We want to reject requests that send and origin or a referer when no allowed origins have been configured, so when these headers are sent, reject the request if no allowed origins are present in the config. Co-authored-by: Vasco Santos Co-authored-by: Marcin Rataj --- packages/ipfs-http-server/src/index.js | 42 +++++++++- packages/ipfs-http-server/test/cors.js | 111 +++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 3 deletions(-) diff --git a/packages/ipfs-http-server/src/index.js b/packages/ipfs-http-server/src/index.js index 50c03b90e5..46648400e7 100644 --- a/packages/ipfs-http-server/src/index.js +++ b/packages/ipfs-http-server/src/index.js @@ -58,6 +58,36 @@ async function serverCreator (serverAddrs, createServer, ipfs, cors) { return servers } +/** + * @param {string} [str] + * @param {string[]} [allowedOrigins] + */ +function isAllowedOrigin (str, allowedOrigins = []) { + if (!str) { + return false + } + + let origin + + try { + origin = (new URL(str)).origin + } catch { + return false + } + + for (const allowedOrigin of allowedOrigins) { + if (allowedOrigin === '*') { + return true + } + + if (allowedOrigin === origin) { + return true + } + } + + return false +} + class HttpApi { /** * @param {IPFS} ipfs @@ -175,11 +205,17 @@ class HttpApi { const headers = request.headers || {} const origin = headers.origin || '' - const referrer = headers.referrer || '' + const referer = headers.referer || '' const userAgent = headers['user-agent'] || '' - // If these are set, we leave up to CORS and CSRF checks. - if (origin || referrer) { + // If these are set, check them against the configured list + if (origin || referer) { + if (!isAllowedOrigin(origin || referer, cors.origin)) { + // Hapi will not allow an empty CORS origin list so we have to manually + // reject the request if CORS origins have not been configured + throw Boom.forbidden() + } + return h.continue } diff --git a/packages/ipfs-http-server/test/cors.js b/packages/ipfs-http-server/test/cors.js index e96a8c87b8..3c5962f146 100644 --- a/packages/ipfs-http-server/test/cors.js +++ b/packages/ipfs-http-server/test/cors.js @@ -32,9 +32,23 @@ describe('cors', () => { } }, { ipfs, cors: { origin: [origin] } }) + expect(res).to.have.property('statusCode', 200) expect(res).to.have.nested.property('headers.access-control-allow-origin', origin) }) + it('allows request when referer is supplied in request', async () => { + const origin = 'http://localhost:8080' + const res = await http({ + method: 'POST', + url: '/api/v0/id', + headers: { + referer: origin + '/index.html' + } + }, { ipfs, cors: { origin: [origin] } }) + + expect(res).to.have.property('statusCode', 200) + }) + it('does not allow credentials when omitted in config', async () => { const origin = 'http://localhost:8080' const res = await http({ @@ -149,5 +163,102 @@ describe('cors', () => { expect(res).to.have.property('statusCode', 404) }) + + it('rejects requests when cors origin list is empty and origin is sent', async () => { + const origin = 'http://localhost:8080' + const res = await http({ + method: 'POST', + url: '/api/v0/id', + headers: { + origin + } + }, { + ipfs, + cors: { origin: [] } + }) + + expect(res).to.have.property('statusCode', 403) + }) + + it('rejects requests when cors origin list is empty and referer is sent', async () => { + const referer = 'http://localhost:8080/index.html' + const res = await http({ + method: 'POST', + url: '/api/v0/id', + headers: { + referer + } + }, { + ipfs, + cors: { origin: [] } + }) + + expect(res).to.have.property('statusCode', 403) + }) + + it('rejects requests when cors origin list is empty and referer and origin are sent', async () => { + const referer = 'http://localhost:8080/index.html' + const res = await http({ + method: 'POST', + url: '/api/v0/id', + headers: { + referer, + origin: 'http://localhost:8080' + } + }, { + ipfs, + cors: { origin: [] } + }) + + expect(res).to.have.property('statusCode', 403) + }) + + it('rejects requests when cors origin list is empty and origin is sent as "null" (e.g. data urls and sandboxed iframes)', async () => { + const origin = 'null' + const res = await http({ + method: 'POST', + url: '/api/v0/id', + headers: { + origin + } + }, { + ipfs, + cors: { origin: [] } + }) + + expect(res).to.have.property('statusCode', 403) + }) + + it('rejects requests when cors origin list does not contain the correct origin and origin is sent', async () => { + const origin = 'http://localhost:8080' + const res = await http({ + method: 'POST', + url: '/api/v0/id', + headers: { + origin + } + }, { + ipfs, + cors: { origin: ['http://example.com:8080'] } + }) + + expect(res).to.have.property('statusCode', 403) + }) + + it('rejects requests when cors origin list does not contain the correct origin and referer is sent', async () => { + const referer = 'http://localhost:8080/index.html' + const res = await http({ + method: 'POST', + url: '/api/v0/id', + headers: { + referer + } + }, { + ipfs, + cors: { origin: ['http://example.com:8080'] } + }) + + expect(res).to.have.property('statusCode', 403) + }) }) }) From bb8f8bc501ffc1ee0f064ba61ec0bca4015bf6ad Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 7 May 2021 13:57:59 +0100 Subject: [PATCH 30/34] fix: only accept cid for ipfs.dag.get (#3675) If you have a path within the DAG to resolve, pass it as `path` in the options object. Makes the API conform to the documentation. Fixes #3637 --- examples/traverse-ipld-graphs/eth.js | 8 +++---- examples/traverse-ipld-graphs/get-path.js | 6 +++--- examples/traverse-ipld-graphs/git.js | 12 +++++------ packages/interface-ipfs-core/src/dag/get.js | 22 ++++---------------- packages/ipfs-core/src/components/dag/get.js | 12 +---------- packages/ipfs/test/interface-http-go.js | 2 +- 6 files changed, 19 insertions(+), 43 deletions(-) diff --git a/examples/traverse-ipld-graphs/eth.js b/examples/traverse-ipld-graphs/eth.js index c9bb90e6ca..adcadf854b 100644 --- a/examples/traverse-ipld-graphs/eth.js +++ b/examples/traverse-ipld-graphs/eth.js @@ -34,14 +34,14 @@ async function main () { await ipfs.block.put(new Block(data, cid)) } - const block302516 = 'z43AaGEywSDX5PUJcrn5GfZmb6FjisJyR7uahhWPk456f7k7LDA' - const block302517 = 'z43AaGF42R2DXsU65bNnHRCypLPr9sg6D7CUws5raiqATVaB1jj' + const block302516 = new CID('z43AaGEywSDX5PUJcrn5GfZmb6FjisJyR7uahhWPk456f7k7LDA') + const block302517 = new CID('z43AaGF42R2DXsU65bNnHRCypLPr9sg6D7CUws5raiqATVaB1jj') let res - res = await ipfs.dag.get(block302516 + '/number') + res = await ipfs.dag.get(block302516, { path: 'number' }) console.log(uint8ArrayToString(res.value, 'base16')) - res = await ipfs.dag.get(block302517 + '/parent/number') + res = await ipfs.dag.get(block302517, { path: 'parent/number' }) console.log(uint8ArrayToString(res.value, 'base16')) } diff --git a/examples/traverse-ipld-graphs/get-path.js b/examples/traverse-ipld-graphs/get-path.js index f48b9d733c..0cf13d2cbf 100644 --- a/examples/traverse-ipld-graphs/get-path.js +++ b/examples/traverse-ipld-graphs/get-path.js @@ -15,13 +15,13 @@ async function main () { const cid = await ipfs.dag.put(myData, { format: 'dag-cbor', hashAlg: 'sha2-256' }) let result - result = await ipfs.dag.get(cid, 'name') + result = await ipfs.dag.get(cid, { path: 'name' }) console.log(result.value) - result = await ipfs.dag.get(cid, 'likes') + result = await ipfs.dag.get(cid, { path: 'likes' }) console.log(result.value) - result = await ipfs.dag.get(cid + '/likes/0') + result = await ipfs.dag.get(cid, { path: '/likes/0' }) console.log(result.value) } diff --git a/examples/traverse-ipld-graphs/git.js b/examples/traverse-ipld-graphs/git.js index e955c08fbe..00901e15d5 100644 --- a/examples/traverse-ipld-graphs/git.js +++ b/examples/traverse-ipld-graphs/git.js @@ -42,7 +42,7 @@ async function main () { await ipfs.block.put(new Block(data, cid)) })) - const v1tag = 'z8mWaGfwSWLMPJ6Q2JdsAjGiXTf61Nbue' + const v1tag = new CID('z8mWaGfwSWLMPJ6Q2JdsAjGiXTf61Nbue') async function logResult (fn, comment) { const result = await fn() @@ -56,11 +56,11 @@ async function main () { console.log(result.value) } - await logResult(() => ipfs.dag.get(v1tag + '/'), 'Tag object:') - await logResult(() => ipfs.dag.get(v1tag + '/object/message'), 'Tagged commit message:') - await logResult(() => ipfs.dag.get(v1tag + '/object/parents/0/message'), 'Parent of tagged commit:') - await logResult(() => ipfs.dag.get(v1tag + '/object/tree/src/hash/hello/hash'), '/src/hello file:') - await logResult(() => ipfs.dag.get(v1tag + '/object/parents/0/tree/src/hash/hello/hash'), 'previous version of /src/hello file:') + await logResult(() => ipfs.dag.get(v1tag), 'Tag object:') + await logResult(() => ipfs.dag.get(v1tag, { path: '/object/message' }), 'Tagged commit message:') + await logResult(() => ipfs.dag.get(v1tag, { path: '/object/parents/0/message' }), 'Parent of tagged commit:') + await logResult(() => ipfs.dag.get(v1tag, { path: '/object/tree/src/hash/hello/hash' }), '/src/hello file:') + await logResult(() => ipfs.dag.get(v1tag, { path: '/object/parents/0/tree/src/hash/hello/hash' }), 'previous version of /src/hello file:') } main() diff --git a/packages/interface-ipfs-core/src/dag/get.js b/packages/interface-ipfs-core/src/dag/get.js index cc7f7803e6..f41aaa6991 100644 --- a/packages/interface-ipfs-core/src/dag/get.js +++ b/packages/interface-ipfs-core/src/dag/get.js @@ -135,21 +135,8 @@ module.exports = (common, options) => { expect(result.value).to.eql(uint8ArrayFromString('I am inside a Protobuf')) }) - it('should get by CID string', async () => { - const cidCborStr = cidCbor.toBaseEncodedString() - - const result = await ipfs.dag.get(cidCborStr) - - const node = result.value - - const cid = await dagCBOR.util.cid(dagCBOR.util.serialize(node)) - expect(cid).to.eql(cidCbor) - }) - - it('should get by CID string + path', async function () { - const cidCborStr = cidCbor.toBaseEncodedString() - - const result = await ipfs.dag.get(cidCborStr + '/pb/Data') + it('should get by CID with path option', async function () { + const result = await ipfs.dag.get(cidCbor, { path: '/pb/Data' }) expect(result.value).to.eql(uint8ArrayFromString('I am inside a Protobuf')) }) @@ -202,10 +189,9 @@ module.exports = (common, options) => { foo: 'dag-cbor-bar' } - let cid = await ipfs.dag.put(cbor, { format: 'dag-cbor', hashAlg: 'sha2-256' }) + const cid = await ipfs.dag.put(cbor, { format: 'dag-cbor', hashAlg: 'sha2-256' }) expect(cid.codec).to.equal('dag-cbor') - cid = cid.toBaseEncodedString('base32') - expect(cid).to.equal('bafyreic6f672hnponukaacmk2mmt7vs324zkagvu4hcww6yba6kby25zce') + expect(cid.toBaseEncodedString('base32')).to.equal('bafyreic6f672hnponukaacmk2mmt7vs324zkagvu4hcww6yba6kby25zce') const result = await ipfs.dag.get(cid, { path: 'foo' diff --git a/packages/ipfs-core/src/components/dag/get.js b/packages/ipfs-core/src/components/dag/get.js index 15b5d01c5f..0ee69cf552 100644 --- a/packages/ipfs-core/src/components/dag/get.js +++ b/packages/ipfs-core/src/components/dag/get.js @@ -3,7 +3,6 @@ const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option') const first = require('it-first') const last = require('it-last') -const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') /** * @param {Object} config @@ -14,16 +13,7 @@ module.exports = ({ ipld, preload }) => { /** * @type {import('ipfs-core-types/src/dag').API["get"]} */ - const get = async function get (ipfsPath, options = {}) { - const { - cid, - path - } = toCidAndPath(ipfsPath) - - if (path) { - options.path = path - } - + const get = async function get (cid, options = {}) { if (options.preload !== false) { preload(cid) } diff --git a/packages/ipfs/test/interface-http-go.js b/packages/ipfs/test/interface-http-go.js index f297424b08..8f434a4711 100644 --- a/packages/ipfs/test/interface-http-go.js +++ b/packages/ipfs/test/interface-http-go.js @@ -138,7 +138,7 @@ describe('interface-ipfs-core over ipfs-http-client tests against go-ipfs', () = reason: 'FIXME vmx 2018-02-22: Currently not supported in go-ipfs, it might be possible once https://github.com/ipfs/go-ipfs/issues/4728 is done' }, { - name: 'should get by CID string + path', + name: 'should get by CID with path option', reason: 'FIXME vmx 2018-02-22: Currently not supported in go-ipfs, it might be possible once https://github.com/ipfs/go-ipfs/issues/4728 is done' }, { From efd147a85762fbe1ff2c5fde3f76be0bb8c05e6e Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Mon, 10 May 2021 11:59:35 +0100 Subject: [PATCH 31/34] chore: rename import types (#3678) Use `ImportCandidate` and `ImportCandidateStream` instead of `ToEntry` and `ImportSource` as they are a bit more descriptive. Plus we already have `BrowserImportCandidate` for `Blob`s so it's more consistent too. --- packages/ipfs-core-types/src/root.d.ts | 6 +++--- packages/ipfs-core-types/src/utils.d.ts | 8 ++++---- .../src/files/normalise-input/index.browser.js | 4 ++-- .../src/files/normalise-input/index.js | 4 ++-- .../src/files/normalise-input/normalise-input.js | 14 +++++++------- .../src/files/normalise-input/utils.js | 2 +- .../ipfs-grpc-client/src/core-api/add-all.js | 2 +- .../src/lib/multipart-request.browser.js | 6 +++--- .../src/lib/multipart-request.node.js | 8 ++++---- .../src/api/resources/files-regular.js | 2 +- packages/ipfs-message-port-client/src/core.js | 16 ++++++++-------- packages/ipfs-message-port-server/src/core.js | 6 +++--- 12 files changed, 39 insertions(+), 39 deletions(-) diff --git a/packages/ipfs-core-types/src/root.d.ts b/packages/ipfs-core-types/src/root.d.ts index 3615811025..f33ceb08f8 100644 --- a/packages/ipfs-core-types/src/root.d.ts +++ b/packages/ipfs-core-types/src/root.d.ts @@ -1,4 +1,4 @@ -import { AbortOptions, PreloadOptions, IPFSPath, ImportSource, ToEntry } from './utils' +import { AbortOptions, PreloadOptions, IPFSPath, ImportCandidateStream, ImportCandidate } from './utils' import CID, { CIDVersion } from 'cids' import { Mtime } from 'ipfs-unixfs' import { Multiaddr } from 'multiaddr' @@ -8,12 +8,12 @@ export interface API { /** * Import a file or data into IPFS */ - add: (entry: ToEntry, options?: AddOptions & OptionExtension) => Promise + add: (entry: ImportCandidate, options?: AddOptions & OptionExtension) => Promise /** * Import multiple files and data into IPFS */ - addAll: (source: ImportSource, options?: AddAllOptions & AbortOptions & OptionExtension) => AsyncIterable + addAll: (source: ImportCandidateStream, options?: AddAllOptions & AbortOptions & OptionExtension) => AsyncIterable /** * Returns content of the file addressed by a valid IPFS Path or CID diff --git a/packages/ipfs-core-types/src/utils.d.ts b/packages/ipfs-core-types/src/utils.d.ts index 3424cfb307..f8d59ac403 100644 --- a/packages/ipfs-core-types/src/utils.d.ts +++ b/packages/ipfs-core-types/src/utils.d.ts @@ -20,11 +20,11 @@ export interface DirectoryEntry extends BaseEntry { content?: undefined } -export type ImportSource = -| AwaitIterable -| ReadableStream +export type ImportCandidateStream = +| AwaitIterable +| ReadableStream -export type ToEntry = +export type ImportCandidate = | ToFile | ToDirectory | ToContent diff --git a/packages/ipfs-core-utils/src/files/normalise-input/index.browser.js b/packages/ipfs-core-utils/src/files/normalise-input/index.browser.js index 97eb2dcd19..15f3750f1c 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/index.browser.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/index.browser.js @@ -4,7 +4,7 @@ const normaliseContent = require('./normalise-content.browser') const normaliseInput = require('./normalise-input') /** - * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource + * @typedef {import('ipfs-core-types/src/utils').ImportCandidateStream} ImportCandidateStream * @typedef {import('ipfs-core-types/src/utils').BrowserImportCandidate} BrowserImportCandidate */ @@ -17,7 +17,7 @@ const normaliseInput = require('./normalise-input') * * See https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/FILES.md#ipfsadddata-options * - * @param {ImportSource} input + * @param {ImportCandidateStream} input * @returns {AsyncGenerator} */ // @ts-ignore diff --git a/packages/ipfs-core-utils/src/files/normalise-input/index.js b/packages/ipfs-core-utils/src/files/normalise-input/index.js index 8a69940471..df15835217 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/index.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/index.js @@ -4,7 +4,7 @@ const normaliseContent = require('./normalise-content') const normaliseInput = require('./normalise-input') /** - * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource + * @typedef {import('ipfs-core-types/src/utils').ImportCandidateStream} ImportCandidateStream * @typedef {import('ipfs-unixfs-importer').ImportCandidate} ImportCandidate */ @@ -17,7 +17,7 @@ const normaliseInput = require('./normalise-input') * * See https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/FILES.md#ipfsadddata-options * - * @param {ImportSource} input + * @param {ImportCandidateStream} input * @returns {AsyncGenerator} */ module.exports = (input) => normaliseInput(input, normaliseContent) diff --git a/packages/ipfs-core-utils/src/files/normalise-input/normalise-input.js b/packages/ipfs-core-utils/src/files/normalise-input/normalise-input.js index 7f1d933a1a..7ea199ba06 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/normalise-input.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/normalise-input.js @@ -17,12 +17,12 @@ const { /** * @typedef {import('ipfs-core-types/src/utils').ToContent} ToContent - * @typedef {import('ipfs-unixfs-importer').ImportCandidate} ImportCandidate - * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + * @typedef {import('ipfs-unixfs-importer').ImportCandidate} ImporterImportCandidate + * @typedef {import('ipfs-core-types/src/utils').ImportCandidate} ImportCandidate */ /** - * @param {import('ipfs-core-types/src/utils').ImportSource} input + * @param {import('ipfs-core-types/src/utils').ImportCandidateStream} input * @param {(content:ToContent) => AsyncIterable} normaliseContent */ // eslint-disable-next-line complexity @@ -76,7 +76,7 @@ module.exports = async function * normaliseInput (input, normaliseContent) { // (Async)Iterable // (Async)Iterable<{ path, content }> if (isFileObject(value) || isBlob(value) || typeof value === 'string' || value instanceof String) { - yield * map(peekable, (/** @type {ToEntry} */ value) => toFileObject(value, normaliseContent)) + yield * map(peekable, (/** @type {ImportCandidate} */ value) => toFileObject(value, normaliseContent)) return } @@ -85,7 +85,7 @@ module.exports = async function * normaliseInput (input, normaliseContent) { // ReadableStream<(Async)Iterable> // ReadableStream> if (value[Symbol.iterator] || value[Symbol.asyncIterator] || isReadableStream(value)) { - yield * map(peekable, (/** @type {ToEntry} */ value) => toFileObject(value, normaliseContent)) + yield * map(peekable, (/** @type {ImportCandidate} */ value) => toFileObject(value, normaliseContent)) return } } @@ -102,14 +102,14 @@ module.exports = async function * normaliseInput (input, normaliseContent) { } /** - * @param {ToEntry} input + * @param {ImportCandidate} input * @param {(content:ToContent) => AsyncIterable} normaliseContent */ async function toFileObject (input, normaliseContent) { // @ts-ignore - Those properties don't exist on most input types const { path, mode, mtime, content } = input - /** @type {ImportCandidate} */ + /** @type {ImporterImportCandidate} */ const file = { path: path || '', mode: parseMode(mode), diff --git a/packages/ipfs-core-utils/src/files/normalise-input/utils.js b/packages/ipfs-core-utils/src/files/normalise-input/utils.js index b118265a01..990546971b 100644 --- a/packages/ipfs-core-utils/src/files/normalise-input/utils.js +++ b/packages/ipfs-core-utils/src/files/normalise-input/utils.js @@ -22,7 +22,7 @@ function isBlob (obj) { * An object with a path or content property * * @param {any} obj - * @returns {obj is import('ipfs-core-types/src/utils').ToEntry} + * @returns {obj is import('ipfs-core-types/src/utils').ImportCandidate} */ function isFileObject (obj) { return typeof obj === 'object' && (obj.path || obj.content) diff --git a/packages/ipfs-grpc-client/src/core-api/add-all.js b/packages/ipfs-grpc-client/src/core-api/add-all.js index 981770069d..2e0dc703b0 100644 --- a/packages/ipfs-grpc-client/src/core-api/add-all.js +++ b/packages/ipfs-grpc-client/src/core-api/add-all.js @@ -86,7 +86,7 @@ async function sendFile (index, sink, content, path, mode, mtime) { } /** - * @param {import('ipfs-core-types/src/utils').ImportSource} stream + * @param {import('ipfs-core-types/src/utils').ImportCandidateStream} stream * @param {import('it-pushable').Pushable} sink */ async function sendFiles (stream, sink) { diff --git a/packages/ipfs-http-client/src/lib/multipart-request.browser.js b/packages/ipfs-http-client/src/lib/multipart-request.browser.js index 290ad0db3c..e5c98001c7 100644 --- a/packages/ipfs-http-client/src/lib/multipart-request.browser.js +++ b/packages/ipfs-http-client/src/lib/multipart-request.browser.js @@ -6,12 +6,12 @@ const normaliseInput = require('ipfs-core-utils/src/files/normalise-input/index. const modeToString = require('./mode-to-string') /** - * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource - * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + * @typedef {import('ipfs-core-types/src/utils').ImportCandidateStream} ImportCandidateStream + * @typedef {import('ipfs-core-types/src/utils').ImportCandidate} ImportCandidate */ /** - * @param {ImportSource|ToEntry} source + * @param {ImportCandidateStream|ImportCandidate} source * @param {AbortController} abortController * @param {Headers|Record} [headers] */ diff --git a/packages/ipfs-http-client/src/lib/multipart-request.node.js b/packages/ipfs-http-client/src/lib/multipart-request.node.js index d2e69ded30..ea1af0237a 100644 --- a/packages/ipfs-http-client/src/lib/multipart-request.node.js +++ b/packages/ipfs-http-client/src/lib/multipart-request.node.js @@ -8,19 +8,19 @@ const merge = require('merge-options').bind({ ignoreUndefined: true }) const toStream = require('it-to-stream') /** - * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource - * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + * @typedef {import('ipfs-core-types/src/utils').ImportCandidateStream} ImportCandidateStream + * @typedef {import('ipfs-core-types/src/utils').ImportCandidate} ImportCandidate */ /** - * @param {ImportSource|ToEntry} source + * @param {ImportCandidateStream|ImportCandidate} source * @param {AbortController} abortController * @param {Headers|Record} [headers] * @param {string} [boundary] */ async function multipartRequest (source, abortController, headers = {}, boundary = `-----------------------------${nanoid()}`) { /** - * @param {ImportSource|ToEntry} source + * @param {ImportCandidateStream|ImportCandidate} source */ async function * streamFiles (source) { try { diff --git a/packages/ipfs-http-server/src/api/resources/files-regular.js b/packages/ipfs-http-server/src/api/resources/files-regular.js index b57da354a2..25e5de9e25 100644 --- a/packages/ipfs-http-server/src/api/resources/files-regular.js +++ b/packages/ipfs-http-server/src/api/resources/files-regular.js @@ -303,7 +303,7 @@ exports.add = { } }, /** - * @param {import('ipfs-core-types/src/utils').ImportSource} source + * @param {import('ipfs-core-types/src/utils').ImportCandidateStream} source */ function (source) { return ipfs.addAll(source, { diff --git a/packages/ipfs-message-port-client/src/core.js b/packages/ipfs-message-port-client/src/core.js index 78793d918f..f308d9996a 100644 --- a/packages/ipfs-message-port-client/src/core.js +++ b/packages/ipfs-message-port-client/src/core.js @@ -39,11 +39,11 @@ const { * @typedef {import('./interface').MessagePortClientOptions} MessagePortClientOptions * @typedef {import('ipfs-core-types/src/root').API} RootAPI * - * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + * @typedef {import('ipfs-core-types/src/utils').ImportCandidate} ImportCandidate * @typedef {import('ipfs-core-types/src/utils').ToFile} ToFile * @typedef {import('ipfs-core-types/src/utils').ToDirectory} ToDirectory * @typedef {import('ipfs-core-types/src/utils').ToContent} ToContent - * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource + * @typedef {import('ipfs-core-types/src/utils').ImportCandidateStream} ImportCandidateStream */ /** @@ -181,7 +181,7 @@ const identity = (v) => v * Encodes input passed to the `ipfs.add` via the best possible strategy for the * given input. * - * @param {ToEntry} input + * @param {ImportCandidate} input * @param {Transferable[]} transfer * @returns {EncodedAddInput} */ @@ -235,7 +235,7 @@ const encodeAddInput = (input, transfer) => { * Encodes input passed to the `ipfs.add` via the best possible strategy for the * given input. * - * @param {ImportSource} input + * @param {ImportCandidateStream} input * @param {Transferable[]} transfer * @returns {EncodedAddAllInput} */ @@ -272,7 +272,7 @@ const encodeAddAllInput = (input, transfer) => { * Function encodes individual item of some `AsyncIterable` by choosing most * effective strategy. * - * @param {ToEntry} content + * @param {ImportCandidate} content * @param {Transferable[]} transfer * @returns {EncodedAddInput} */ @@ -296,7 +296,7 @@ const encodeAsyncIterableContent = (content, transfer) => { } /** - * @param {ToEntry} content + * @param {ImportCandidate} content * @param {Transferable[]} transfer * @returns {EncodedAddInput} */ @@ -388,7 +388,7 @@ const encodeFileContent = (content, transfer) => { * iterable or `null`. * * @template I - * @param {Iterable|ToEntry|ImportSource} input + * @param {Iterable|ImportCandidate|ImportCandidateStream} input * @returns {Iterable|null} */ const asIterable = (input) => { @@ -406,7 +406,7 @@ const asIterable = (input) => { * matched `AsyncIterable` or `null`. * * @template I - * @param {AsyncIterable|ToEntry|ImportSource} input + * @param {AsyncIterable|ImportCandidate|ImportCandidateStream} input * @returns {AsyncIterable|null} */ const asAsyncIterable = (input) => { diff --git a/packages/ipfs-message-port-server/src/core.js b/packages/ipfs-message-port-server/src/core.js index fa58711039..f0961e83d3 100644 --- a/packages/ipfs-message-port-server/src/core.js +++ b/packages/ipfs-message-port-server/src/core.js @@ -16,8 +16,8 @@ const { decodeCID, encodeCID } = require('ipfs-message-port-protocol/src/cid') * @typedef {import('ipfs-core-types/src/root').AddAllOptions} AddAllOptions * @typedef {import('ipfs-core-types/src/root').IPFSEntry} IPFSEntry * @typedef {import('ipfs-message-port-protocol/src/cid').EncodedCID} EncodedCID - * @typedef {import('ipfs-core-types/src/utils').ImportSource} ImportSource - * @typedef {import('ipfs-core-types/src/utils').ToEntry} ToEntry + * @typedef {import('ipfs-core-types/src/utils').ImportCandidateStream} ImportCandidateStream + * @typedef {import('ipfs-core-types/src/utils').ImportCandidate} ImportCandidate * @typedef {import('ipfs-core-types/src/root').AddResult} AddResult * @typedef {import('ipfs-message-port-protocol/src/root').EncodedAddInput} EncodedAddInput * @typedef {import('ipfs-message-port-protocol/src/root').EncodedAddAllInput} EncodedAddAllInput @@ -188,7 +188,7 @@ exports.CoreService = class CoreService { /** * @param {EncodedAddAllInput} input - * @returns {ImportSource} + * @returns {ImportCandidateStream} */ const decodeAddAllInput = input => decodeIterable(input, decodeFileInput) From 71e5f537365d32cd9e2f040eed90637d497c6044 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Mon, 10 May 2021 12:34:44 +0100 Subject: [PATCH 32/34] chore: fix flaky test (#3680) Because the requests are initiated with `Promise.all`, there's no guarantee which order they arrive at the server in so when we check the responses, just make sure the length and contents are correct instead of the order. --- packages/ipfs-http-client/test/node/agent.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/ipfs-http-client/test/node/agent.js b/packages/ipfs-http-client/test/node/agent.js index b0940ae68a..00f62fc93d 100644 --- a/packages/ipfs-http-client/test/node/agent.js +++ b/packages/ipfs-http-client/test/node/agent.js @@ -102,14 +102,16 @@ describe('agent', function () { } const results = await requests - - expect(results).to.deep.equal([{ + expect(results).to.have.lengthOf(3) + expect(results).to.deep.include({ res: 0 - }, { + }) + expect(results).to.deep.include({ res: 1 - }, { + }) + expect(results).to.deep.include({ res: 2 - }]) + }) server.close() }) From de5e701b2394eb46494ce0912d2027361340c1af Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 10 May 2021 15:32:36 +0100 Subject: [PATCH 33/34] chore: update contributors --- package.json | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 07ee2011e1..e0d5d8b32f 100644 --- a/package.json +++ b/package.json @@ -76,14 +76,14 @@ "Friedel Ziegelmayer ", "Juan Batiz-Benet ", "Hugo Dias ", - "Vasco Santos ", + "Vasco Santos ", "Henrique Dias ", "Volker Mische ", "ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ ", "Stephen Whitmore ", + "Marcin Rataj ", "Jacob Heun ", "Francisco Baio Dias ", - "Marcin Rataj ", "Matt Bell ", "Richard Schneider ", "Pedro Teixeira ", @@ -92,15 +92,15 @@ "Dmitriy Ryajov ", "Irakli Gozalishvili ", "nginnever ", - "Richard Littauer ", "Oli Evans ", + "Richard Littauer ", "dirkmc ", "Diogo Silva ", "Connor Keenan ", "Pedro Santos ", "Harlan T Wood ", - "Andrew Nesbitt ", "Pascal Precht ", + "Andrew Nesbitt ", "Maciej Krüger ", "Michael Garvin ", "Steven Allen ", @@ -108,28 +108,28 @@ "João Antunes ", "Christian Couder ", "Enrico Marino ", - "Prabhakar Poudel ", "Rob Brackett ", + "Prabhakar Poudel ", "Mithgol ", "Hector Sanjuan ", + "Xmader ", + "Joonas Koivunen ", "Gavin McDermott ", - "Sangwon Hong ", "Jonathan ", - "Joonas Koivunen ", "Mikeal Rogers ", - "Xmader ", + "Sangwon Hong ", "Dzmitry Das ", "haad ", + "Marius Darila ", "Andrew de Andrade ", "Paulo Rodrigues ", - "Ryan Bell ", "RasmusErik Voel Jensen ", + "Ryan Bell ", "Alex Mingoia ", - "Marius Darila ", "Yahya ", "Matt Ober ", "Jeromy ", - "0xflotus <0xflotus@gmail.com>", + "Mark Robert Henderson ", "Andrey ", "Antonio Tenorio-Fornés ", "Dan Ordille ", @@ -141,7 +141,7 @@ "Jonybang ", "Kevin Simper ", "Kevin Wang ", - "Mark Robert Henderson ", + "0xflotus <0xflotus@gmail.com>", "Maxime Lathuilière ", "Nuno Nogueira ", "Portia Burton ", @@ -154,28 +154,30 @@ "tcme ", "Максим Ильин ", "SeungWon ", + "noah the goodra ", + "Heo Sangmin ", "Lars Gierth ", "Lukas Drgon ", - "Holodisc ", - "Heo Sangmin ", - "Marcus Bernales ", "Henry Rodrick ", + "Marcus Bernales ", "Mat Kelly ", + "Hannah Howard ", + "Guilherme Pacheco ", "Matt Zumwalt ", "priecint ", "Michael Bradley ", - "Guilherme Pacheco ", "Grant Herman ", "Michelle Lee ", - "Mitar ", "Giuseppe Bertone ", + "Mitar ", + "Giles ", "Mohamed Abdulaziz ", "André Cruz ", "Mounish Sai ", "Nate Foss ", "Nick Poulden ", "Nicolás Santángelo ", - "Giles ", + "George Shammas ", "ron litzenberger ", "Níckolas Goline ", "Gabriel Garrido Calvo ", @@ -242,20 +244,20 @@ "isan_rivkin ", "Ayush Mahajan ", "kevingzhang ", + "James Halliday ", + "Jason Carver ", "Jeeyong Um ", "Jessica Schilling ", - "leekt216 ", "Joe Turgeon ", "Joel Gustafson ", "Johannes Wikner ", "John Kane ", "Jon Schlinkert ", - "Jason Carver ", - "Jonathan Commins ", - "James Halliday ", - "Jorropo ", "Jade Meskill ", + "Jonathan Commins ", + "leekt216 ", "Jacob Karlsson ", - "noah the goodra " + "Jorropo ", + "Holodisc " ] } From 99053f721305d1905f36a16631f036e883cb02d0 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 10 May 2021 15:51:25 +0100 Subject: [PATCH 34/34] chore: publish - interface-ipfs-core@0.145.0 - ipfs-cli@0.5.0 - ipfs-client@0.4.0 - ipfs-core-types@0.4.0 - ipfs-core-utils@0.8.0 - ipfs-core@0.6.0 - ipfs-daemon@0.6.0 - ipfs-grpc-client@0.3.0 - ipfs-grpc-protocol@0.3.0 - ipfs-grpc-server@0.3.0 - ipfs-http-client@50.0.0 - ipfs-http-gateway@0.4.0 - ipfs-http-server@0.4.0 - ipfs-message-port-client@0.6.0 - ipfs-message-port-protocol@0.7.0 - ipfs-message-port-server@0.7.0 - ipfs@0.55.0 --- packages/interface-ipfs-core/CHANGELOG.md | 27 ++++++++++++++++ packages/interface-ipfs-core/package.json | 2 +- packages/ipfs-cli/CHANGELOG.md | 23 ++++++++++++++ packages/ipfs-cli/package.json | 12 +++---- packages/ipfs-client/CHANGELOG.md | 16 ++++++++++ packages/ipfs-client/package.json | 6 ++-- packages/ipfs-core-types/CHANGELOG.md | 25 +++++++++++++++ packages/ipfs-core-types/package.json | 2 +- packages/ipfs-core-utils/CHANGELOG.md | 21 +++++++++++++ packages/ipfs-core-utils/package.json | 4 +-- packages/ipfs-core/CHANGELOG.md | 31 +++++++++++++++++++ packages/ipfs-core/package.json | 8 ++--- packages/ipfs-daemon/CHANGELOG.md | 21 +++++++++++++ packages/ipfs-daemon/package.json | 14 ++++----- packages/ipfs-grpc-client/CHANGELOG.md | 21 +++++++++++++ packages/ipfs-grpc-client/package.json | 8 ++--- packages/ipfs-grpc-protocol/CHANGELOG.md | 16 ++++++++++ packages/ipfs-grpc-protocol/package.json | 2 +- packages/ipfs-grpc-server/CHANGELOG.md | 22 +++++++++++++ packages/ipfs-grpc-server/package.json | 8 ++--- packages/ipfs-http-client/CHANGELOG.md | 26 ++++++++++++++++ packages/ipfs-http-client/package.json | 6 ++-- packages/ipfs-http-gateway/CHANGELOG.md | 16 ++++++++++ packages/ipfs-http-gateway/package.json | 8 ++--- packages/ipfs-http-server/CHANGELOG.md | 27 ++++++++++++++++ packages/ipfs-http-server/package.json | 12 +++---- .../ipfs-message-port-client/CHANGELOG.md | 18 +++++++++++ .../ipfs-message-port-client/package.json | 12 +++---- .../ipfs-message-port-protocol/CHANGELOG.md | 18 +++++++++++ .../ipfs-message-port-protocol/package.json | 4 +-- .../ipfs-message-port-server/CHANGELOG.md | 18 +++++++++++ .../ipfs-message-port-server/package.json | 6 ++-- packages/ipfs/CHANGELOG.md | 24 ++++++++++++++ packages/ipfs/package.json | 14 ++++----- 34 files changed, 434 insertions(+), 64 deletions(-) diff --git a/packages/interface-ipfs-core/CHANGELOG.md b/packages/interface-ipfs-core/CHANGELOG.md index b28285f651..98c7d18a9e 100644 --- a/packages/interface-ipfs-core/CHANGELOG.md +++ b/packages/interface-ipfs-core/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.145.0](https://github.com/ipfs/js-ipfs/compare/interface-ipfs-core@0.144.2...interface-ipfs-core@0.145.0) (2021-05-10) + + +### Bug Fixes + +* mark ipld options as partial ([#3669](https://github.com/ipfs/js-ipfs/issues/3669)) ([f98af8e](https://github.com/ipfs/js-ipfs/commit/f98af8ed24784929898bb5d33a64dc442c77074d)) +* only accept cid for ipfs.dag.get ([#3675](https://github.com/ipfs/js-ipfs/issues/3675)) ([bb8f8bc](https://github.com/ipfs/js-ipfs/commit/bb8f8bc501ffc1ee0f064ba61ec0bca4015bf6ad)), closes [#3637](https://github.com/ipfs/js-ipfs/issues/3637) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### Features + +* support identity hash in block.get + dag.get ([#3616](https://github.com/ipfs/js-ipfs/issues/3616)) ([28ad9ad](https://github.com/ipfs/js-ipfs/commit/28ad9ad6e50abb89a366ecd6b5301e848f0e9962)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.144.2](https://github.com/ipfs/js-ipfs/compare/interface-ipfs-core@0.144.1...interface-ipfs-core@0.144.2) (2021-03-09) diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 0f1ea1030f..34a4c85489 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -1,6 +1,6 @@ { "name": "interface-ipfs-core", - "version": "0.144.2", + "version": "0.145.0", "description": "A test suite and interface you can use to implement a IPFS core interface.", "leadMaintainer": "Alex Potsides ", "main": "src/index.js", diff --git a/packages/ipfs-cli/CHANGELOG.md b/packages/ipfs-cli/CHANGELOG.md index fd278e207e..4df2403c07 100644 --- a/packages/ipfs-cli/CHANGELOG.md +++ b/packages/ipfs-cli/CHANGELOG.md @@ -3,6 +3,29 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.5.0](https://github.com/ipfs/js-ipfs/compare/ipfs-cli@0.4.4...ipfs-cli@0.5.0) (2021-05-10) + + +### Bug Fixes + +* mark ipld options as partial ([#3669](https://github.com/ipfs/js-ipfs/issues/3669)) ([f98af8e](https://github.com/ipfs/js-ipfs/commit/f98af8ed24784929898bb5d33a64dc442c77074d)) +* update ipfs repo ([#3671](https://github.com/ipfs/js-ipfs/issues/3671)) ([9029ee5](https://github.com/ipfs/js-ipfs/commit/9029ee591fa74ea65c9600f2d249897e933416fa)) +* update types after feedback from ceramic ([#3657](https://github.com/ipfs/js-ipfs/issues/3657)) ([0ddbb1b](https://github.com/ipfs/js-ipfs/commit/0ddbb1b1deb4e40dac3e365d7f98a5f174c2ce8f)), closes [#3640](https://github.com/ipfs/js-ipfs/issues/3640) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.4.4](https://github.com/ipfs/js-ipfs/compare/ipfs-cli@0.4.3...ipfs-cli@0.4.4) (2021-03-10) **Note:** Version bump only for package ipfs-cli diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index 6211dfe94c..b4537a1492 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-cli", - "version": "0.4.4", + "version": "0.5.0", "description": "JavaScript implementation of the IPFS specification", "keywords": [ "IPFS" @@ -37,11 +37,11 @@ "err-code": "^3.0.1", "execa": "^5.0.0", "get-folder-size": "^2.0.1", - "ipfs-core": "^0.5.4", - "ipfs-core-types": "^0.3.1", - "ipfs-core-utils": "^0.7.2", - "ipfs-daemon": "^0.5.4", - "ipfs-http-client": "^49.0.4", + "ipfs-core": "^0.6.0", + "ipfs-core-types": "^0.4.0", + "ipfs-core-utils": "^0.8.0", + "ipfs-daemon": "^0.6.0", + "ipfs-http-client": "^50.0.0", "ipfs-repo": "^9.1.6", "ipfs-utils": "^7.0.0", "ipld-dag-cbor": "^1.0.0", diff --git a/packages/ipfs-client/CHANGELOG.md b/packages/ipfs-client/CHANGELOG.md index 6a235c9f04..a2acd01152 100644 --- a/packages/ipfs-client/CHANGELOG.md +++ b/packages/ipfs-client/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.4.0](https://github.com/ipfs/js-ipfs/compare/ipfs-client@0.3.4...ipfs-client@0.4.0) (2021-05-10) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.3.4](https://github.com/ipfs/js-ipfs/compare/ipfs-client@0.3.3...ipfs-client@0.3.4) (2021-03-10) **Note:** Version bump only for package ipfs-client diff --git a/packages/ipfs-client/package.json b/packages/ipfs-client/package.json index 8d43aa35d9..e1bc517910 100644 --- a/packages/ipfs-client/package.json +++ b/packages/ipfs-client/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-client", - "version": "0.3.4", + "version": "0.4.0", "description": "A client library to talk to local IPFS daemons", "keywords": [ "ipfs" @@ -32,8 +32,8 @@ "dep-check": "aegir dep-check -i aegir -i rimraf" }, "dependencies": { - "ipfs-grpc-client": "^0.2.4", - "ipfs-http-client": "^49.0.4", + "ipfs-grpc-client": "^0.3.0", + "ipfs-http-client": "^50.0.0", "merge-options": "^3.0.4" }, "devDependencies": { diff --git a/packages/ipfs-core-types/CHANGELOG.md b/packages/ipfs-core-types/CHANGELOG.md index b995dde684..3579ad0116 100644 --- a/packages/ipfs-core-types/CHANGELOG.md +++ b/packages/ipfs-core-types/CHANGELOG.md @@ -3,6 +3,31 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.4.0](https://github.com/ipfs/js-ipfs/compare/ipfs-core-types@0.3.1...ipfs-core-types@0.4.0) (2021-05-10) + + +### Bug Fixes + +* fix types ([#3662](https://github.com/ipfs/js-ipfs/issues/3662)) ([0fe8892](https://github.com/ipfs/js-ipfs/commit/0fe8892361180dab53ed3c3b006479b32a792d44)) +* loosen input type for swarm.connect and swarm.disconnect ([#3673](https://github.com/ipfs/js-ipfs/issues/3673)) ([46618c7](https://github.com/ipfs/js-ipfs/commit/46618c795bf5363ba3186645640fb81349231db7)), closes [#3638](https://github.com/ipfs/js-ipfs/issues/3638) +* mark ipld options as partial ([#3669](https://github.com/ipfs/js-ipfs/issues/3669)) ([f98af8e](https://github.com/ipfs/js-ipfs/commit/f98af8ed24784929898bb5d33a64dc442c77074d)) +* update ipfs repo ([#3671](https://github.com/ipfs/js-ipfs/issues/3671)) ([9029ee5](https://github.com/ipfs/js-ipfs/commit/9029ee591fa74ea65c9600f2d249897e933416fa)) +* update types after feedback from ceramic ([#3657](https://github.com/ipfs/js-ipfs/issues/3657)) ([0ddbb1b](https://github.com/ipfs/js-ipfs/commit/0ddbb1b1deb4e40dac3e365d7f98a5f174c2ce8f)), closes [#3640](https://github.com/ipfs/js-ipfs/issues/3640) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.3.1](https://github.com/ipfs/js-ipfs/compare/ipfs-core-types@0.3.0...ipfs-core-types@0.3.1) (2021-03-09) diff --git a/packages/ipfs-core-types/package.json b/packages/ipfs-core-types/package.json index a131cb475f..ebc7721e2b 100644 --- a/packages/ipfs-core-types/package.json +++ b/packages/ipfs-core-types/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-core-types", - "version": "0.3.1", + "version": "0.4.0", "description": "IPFS interface definitions used by implementations for API compatibility.", "leadMaintainer": "Alex Potsides ", "types": "src/index.d.ts", diff --git a/packages/ipfs-core-utils/CHANGELOG.md b/packages/ipfs-core-utils/CHANGELOG.md index e314a6bfc9..57a595cbe0 100644 --- a/packages/ipfs-core-utils/CHANGELOG.md +++ b/packages/ipfs-core-utils/CHANGELOG.md @@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.8.0](https://github.com/ipfs/js-ipfs/compare/ipfs-core-utils@0.7.2...ipfs-core-utils@0.8.0) (2021-05-10) + + +### Bug Fixes + +* mark ipld options as partial ([#3669](https://github.com/ipfs/js-ipfs/issues/3669)) ([f98af8e](https://github.com/ipfs/js-ipfs/commit/f98af8ed24784929898bb5d33a64dc442c77074d)) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.7.2](https://github.com/ipfs/js-ipfs/compare/ipfs-core-utils@0.7.1...ipfs-core-utils@0.7.2) (2021-03-09) diff --git a/packages/ipfs-core-utils/package.json b/packages/ipfs-core-utils/package.json index f7597b7517..c567f88573 100644 --- a/packages/ipfs-core-utils/package.json +++ b/packages/ipfs-core-utils/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-core-utils", - "version": "0.7.2", + "version": "0.8.0", "description": "Package to share code between ipfs and ipfs-http-client", "author": "Alex Potsides ", "homepage": "https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-core-utils#readme", @@ -46,7 +46,7 @@ "browser-readablestream-to-it": "^1.0.1", "cids": "^1.1.6", "err-code": "^3.0.1", - "ipfs-core-types": "^0.3.1", + "ipfs-core-types": "^0.4.0", "ipfs-unixfs": "^4.0.3", "ipfs-utils": "^7.0.0", "it-all": "^1.0.4", diff --git a/packages/ipfs-core/CHANGELOG.md b/packages/ipfs-core/CHANGELOG.md index bacc11322d..dea98c14ac 100644 --- a/packages/ipfs-core/CHANGELOG.md +++ b/packages/ipfs-core/CHANGELOG.md @@ -3,6 +3,37 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.6.0](https://github.com/ipfs/js-ipfs/compare/ipfs-core@0.5.4...ipfs-core@0.6.0) (2021-05-10) + + +### Bug Fixes + +* do not republish self key twice ([#3634](https://github.com/ipfs/js-ipfs/issues/3634)) ([8545a76](https://github.com/ipfs/js-ipfs/commit/8545a763daa38aefa71cca514016ba400363830a)) +* fix types ([#3662](https://github.com/ipfs/js-ipfs/issues/3662)) ([0fe8892](https://github.com/ipfs/js-ipfs/commit/0fe8892361180dab53ed3c3b006479b32a792d44)) +* mark ipld options as partial ([#3669](https://github.com/ipfs/js-ipfs/issues/3669)) ([f98af8e](https://github.com/ipfs/js-ipfs/commit/f98af8ed24784929898bb5d33a64dc442c77074d)) +* only accept cid for ipfs.dag.get ([#3675](https://github.com/ipfs/js-ipfs/issues/3675)) ([bb8f8bc](https://github.com/ipfs/js-ipfs/commit/bb8f8bc501ffc1ee0f064ba61ec0bca4015bf6ad)), closes [#3637](https://github.com/ipfs/js-ipfs/issues/3637) +* update ipfs repo ([#3671](https://github.com/ipfs/js-ipfs/issues/3671)) ([9029ee5](https://github.com/ipfs/js-ipfs/commit/9029ee591fa74ea65c9600f2d249897e933416fa)) +* update types after feedback from ceramic ([#3657](https://github.com/ipfs/js-ipfs/issues/3657)) ([0ddbb1b](https://github.com/ipfs/js-ipfs/commit/0ddbb1b1deb4e40dac3e365d7f98a5f174c2ce8f)), closes [#3640](https://github.com/ipfs/js-ipfs/issues/3640) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### Features + +* support identity hash in block.get + dag.get ([#3616](https://github.com/ipfs/js-ipfs/issues/3616)) ([28ad9ad](https://github.com/ipfs/js-ipfs/commit/28ad9ad6e50abb89a366ecd6b5301e848f0e9962)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.5.4](https://github.com/ipfs/js-ipfs/compare/ipfs-core@0.5.3...ipfs-core@0.5.4) (2021-03-10) **Note:** Version bump only for package ipfs-core diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index c51ab02681..c1e9984e93 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-core", - "version": "0.5.4", + "version": "0.6.0", "description": "JavaScript implementation of the IPFS specification", "keywords": [ "IPFS" @@ -72,8 +72,8 @@ "interface-datastore": "^4.0.0", "ipfs-bitswap": "^5.0.3", "ipfs-block-service": "^0.19.0", - "ipfs-core-types": "^0.3.1", - "ipfs-core-utils": "^0.7.2", + "ipfs-core-types": "^0.4.0", + "ipfs-core-utils": "^0.8.0", "ipfs-repo": "^9.1.6", "ipfs-unixfs": "^4.0.3", "ipfs-unixfs-exporter": "^5.0.3", @@ -127,7 +127,7 @@ "aegir": "^33.0.0", "delay": "^5.0.0", "go-ipfs": "0.8.0", - "interface-ipfs-core": "^0.144.2", + "interface-ipfs-core": "^0.145.0", "ipfsd-ctl": "^8.0.1", "ipld-git": "^0.6.1", "iso-url": "^1.0.0", diff --git a/packages/ipfs-daemon/CHANGELOG.md b/packages/ipfs-daemon/CHANGELOG.md index 25fee1574d..aaa8fd74d7 100644 --- a/packages/ipfs-daemon/CHANGELOG.md +++ b/packages/ipfs-daemon/CHANGELOG.md @@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.6.0](https://github.com/ipfs/js-ipfs/compare/ipfs-daemon@0.5.4...ipfs-daemon@0.6.0) (2021-05-10) + + +### Bug Fixes + +* mark ipld options as partial ([#3669](https://github.com/ipfs/js-ipfs/issues/3669)) ([f98af8e](https://github.com/ipfs/js-ipfs/commit/f98af8ed24784929898bb5d33a64dc442c77074d)) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.5.4](https://github.com/ipfs/js-ipfs/compare/ipfs-daemon@0.5.3...ipfs-daemon@0.5.4) (2021-03-10) **Note:** Version bump only for package ipfs-daemon diff --git a/packages/ipfs-daemon/package.json b/packages/ipfs-daemon/package.json index d671feb58e..af0a56953c 100644 --- a/packages/ipfs-daemon/package.json +++ b/packages/ipfs-daemon/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-daemon", - "version": "0.5.4", + "version": "0.6.0", "description": "JavaScript implementation of the IPFS specification", "keywords": [ "IPFS" @@ -32,12 +32,12 @@ "dependencies": { "debug": "^4.1.1", "dlv": "^1.1.3", - "ipfs-core": "^0.5.4", - "ipfs-core-types": "^0.3.1", - "ipfs-grpc-server": "^0.2.4", - "ipfs-http-client": "^49.0.4", - "ipfs-http-gateway": "^0.3.2", - "ipfs-http-server": "^0.3.4", + "ipfs-core": "^0.6.0", + "ipfs-core-types": "^0.4.0", + "ipfs-grpc-server": "^0.3.0", + "ipfs-http-client": "^50.0.0", + "ipfs-http-gateway": "^0.4.0", + "ipfs-http-server": "^0.4.0", "ipfs-utils": "^7.0.0", "just-safe-set": "^2.2.1", "libp2p": "^0.31.2", diff --git a/packages/ipfs-grpc-client/CHANGELOG.md b/packages/ipfs-grpc-client/CHANGELOG.md index a54673ef88..6345dbe4f8 100644 --- a/packages/ipfs-grpc-client/CHANGELOG.md +++ b/packages/ipfs-grpc-client/CHANGELOG.md @@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.3.0](https://github.com/ipfs/js-ipfs/compare/ipfs-grpc-client@0.2.4...ipfs-grpc-client@0.3.0) (2021-05-10) + + +### Bug Fixes + +* ignore the ts error caused by the recent protobufjs type change ([#3656](https://github.com/ipfs/js-ipfs/issues/3656)) ([084589c](https://github.com/ipfs/js-ipfs/commit/084589c0116d8f27ce1462424fb93b6037b776a9)) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.2.4](https://github.com/ipfs/js-ipfs/compare/ipfs-grpc-client@0.2.3...ipfs-grpc-client@0.2.4) (2021-03-10) **Note:** Version bump only for package ipfs-grpc-client diff --git a/packages/ipfs-grpc-client/package.json b/packages/ipfs-grpc-client/package.json index c3534e6b47..ba1336aaae 100644 --- a/packages/ipfs-grpc-client/package.json +++ b/packages/ipfs-grpc-client/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-grpc-client", - "version": "0.2.4", + "version": "0.3.0", "description": "A client library for the IPFS gRPC API", "keywords": [ "ipfs" @@ -37,9 +37,9 @@ "cids": "^1.1.6", "debug": "^4.1.1", "err-code": "^3.0.1", - "ipfs-core-types": "^0.3.1", - "ipfs-core-utils": "^0.7.2", - "ipfs-grpc-protocol": "^0.2.0", + "ipfs-core-types": "^0.4.0", + "ipfs-core-utils": "^0.8.0", + "ipfs-grpc-protocol": "^0.3.0", "ipfs-unixfs": "^4.0.3", "it-first": "^1.0.4", "it-pushable": "^1.4.0", diff --git a/packages/ipfs-grpc-protocol/CHANGELOG.md b/packages/ipfs-grpc-protocol/CHANGELOG.md index 87a02537e6..b5b48f9539 100644 --- a/packages/ipfs-grpc-protocol/CHANGELOG.md +++ b/packages/ipfs-grpc-protocol/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.3.0](https://github.com/ipfs/js-ipfs/compare/ipfs-grpc-protocol@0.2.0...ipfs-grpc-protocol@0.3.0) (2021-05-10) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + # [0.2.0](https://github.com/ipfs/js-ipfs/compare/ipfs-grpc-protocol@0.1.0...ipfs-grpc-protocol@0.2.0) (2021-02-01) diff --git a/packages/ipfs-grpc-protocol/package.json b/packages/ipfs-grpc-protocol/package.json index 961a11a199..a6c427a478 100644 --- a/packages/ipfs-grpc-protocol/package.json +++ b/packages/ipfs-grpc-protocol/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-grpc-protocol", - "version": "0.2.0", + "version": "0.3.0", "description": "Protobuf definitions for the IPFS gRPC API", "keywords": [ "ipfs" diff --git a/packages/ipfs-grpc-server/CHANGELOG.md b/packages/ipfs-grpc-server/CHANGELOG.md index a842d5735b..bc4cfc794f 100644 --- a/packages/ipfs-grpc-server/CHANGELOG.md +++ b/packages/ipfs-grpc-server/CHANGELOG.md @@ -3,6 +3,28 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.3.0](https://github.com/ipfs/js-ipfs/compare/ipfs-grpc-server@0.2.4...ipfs-grpc-server@0.3.0) (2021-05-10) + + +### Bug Fixes + +* ignore the ts error caused by the recent protobufjs type change ([#3656](https://github.com/ipfs/js-ipfs/issues/3656)) ([084589c](https://github.com/ipfs/js-ipfs/commit/084589c0116d8f27ce1462424fb93b6037b776a9)) +* update data type for ws message event handler ([#3641](https://github.com/ipfs/js-ipfs/issues/3641)) ([4a14d20](https://github.com/ipfs/js-ipfs/commit/4a14d20e727b50a8d98c14573d9a5b6fa0e8699d)) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.2.4](https://github.com/ipfs/js-ipfs/compare/ipfs-grpc-server@0.2.3...ipfs-grpc-server@0.2.4) (2021-03-10) **Note:** Version bump only for package ipfs-grpc-server diff --git a/packages/ipfs-grpc-server/package.json b/packages/ipfs-grpc-server/package.json index 32d372d657..8352bdc8c4 100644 --- a/packages/ipfs-grpc-server/package.json +++ b/packages/ipfs-grpc-server/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-grpc-server", - "version": "0.2.4", + "version": "0.3.0", "description": "A server library for the IPFS gRPC API", "keywords": [ "ipfs" @@ -34,8 +34,8 @@ "change-case": "^4.1.1", "coercer": "^1.1.2", "debug": "^4.1.1", - "ipfs-core-types": "^0.3.1", - "ipfs-grpc-protocol": "^0.2.0", + "ipfs-core-types": "^0.4.0", + "ipfs-grpc-protocol": "^0.3.0", "it-first": "^1.0.4", "it-map": "^1.0.4", "it-peekable": "^1.0.1", @@ -48,7 +48,7 @@ "devDependencies": { "@types/ws": "^7.4.0", "aegir": "^33.0.0", - "ipfs-core": "^0.5.4", + "ipfs-core": "^0.6.0", "it-all": "^1.0.4", "it-drain": "^1.0.3", "rimraf": "^3.0.2", diff --git a/packages/ipfs-http-client/CHANGELOG.md b/packages/ipfs-http-client/CHANGELOG.md index aa4fe6a1bd..b7f612f6eb 100644 --- a/packages/ipfs-http-client/CHANGELOG.md +++ b/packages/ipfs-http-client/CHANGELOG.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [50.0.0](https://github.com/ipfs/js-ipfs/compare/ipfs-http-client@49.0.4...ipfs-http-client@50.0.0) (2021-05-10) + + +### Bug Fixes + +* add missing type import ([#3664](https://github.com/ipfs/js-ipfs/issues/3664)) ([64cc1e1](https://github.com/ipfs/js-ipfs/commit/64cc1e1ea7da77f1553ac127e9fef1905f7c78da)) +* fix types ([#3662](https://github.com/ipfs/js-ipfs/issues/3662)) ([0fe8892](https://github.com/ipfs/js-ipfs/commit/0fe8892361180dab53ed3c3b006479b32a792d44)) +* loosen input type for swarm.connect and swarm.disconnect ([#3673](https://github.com/ipfs/js-ipfs/issues/3673)) ([46618c7](https://github.com/ipfs/js-ipfs/commit/46618c795bf5363ba3186645640fb81349231db7)), closes [#3638](https://github.com/ipfs/js-ipfs/issues/3638) +* mark ipld options as partial ([#3669](https://github.com/ipfs/js-ipfs/issues/3669)) ([f98af8e](https://github.com/ipfs/js-ipfs/commit/f98af8ed24784929898bb5d33a64dc442c77074d)) + + +### chore + +* update node version in docker build ([#3603](https://github.com/ipfs/js-ipfs/issues/3603)) ([087fd1e](https://github.com/ipfs/js-ipfs/commit/087fd1eb402d1b933730e09c1d0cfb21067e9992)) +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* Minimum supported node version is 14 +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [49.0.4](https://github.com/ipfs/js-ipfs/compare/ipfs-http-client@49.0.3...ipfs-http-client@49.0.4) (2021-03-10) **Note:** Version bump only for package ipfs-http-client diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 80f00e9a2f..03780811ea 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "49.0.4", + "version": "50.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -49,8 +49,8 @@ "cids": "^1.1.6", "debug": "^4.1.1", "form-data": "^4.0.0", - "ipfs-core-types": "^0.3.1", - "ipfs-core-utils": "^0.7.2", + "ipfs-core-types": "^0.4.0", + "ipfs-core-utils": "^0.8.0", "ipfs-unixfs": "^4.0.3", "ipfs-utils": "^7.0.0", "ipld-block": "^0.11.0", diff --git a/packages/ipfs-http-gateway/CHANGELOG.md b/packages/ipfs-http-gateway/CHANGELOG.md index 2875c4dc0f..40be4cd680 100644 --- a/packages/ipfs-http-gateway/CHANGELOG.md +++ b/packages/ipfs-http-gateway/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.4.0](https://github.com/ipfs/js-ipfs/compare/ipfs-http-gateway@0.3.2...ipfs-http-gateway@0.4.0) (2021-05-10) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.3.2](https://github.com/ipfs/js-ipfs/compare/ipfs-http-gateway@0.3.1...ipfs-http-gateway@0.3.2) (2021-03-09) diff --git a/packages/ipfs-http-gateway/package.json b/packages/ipfs-http-gateway/package.json index a6213167e4..0ec36972a9 100644 --- a/packages/ipfs-http-gateway/package.json +++ b/packages/ipfs-http-gateway/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-gateway", - "version": "0.3.2", + "version": "0.4.0", "description": "JavaScript implementation of the IPFS specification", "keywords": [ "IPFS" @@ -47,8 +47,8 @@ "cids": "^1.1.6", "debug": "^4.1.1", "hapi-pino": "^8.3.0", - "ipfs-core-types": "^0.3.1", - "ipfs-core-utils": "^0.7.2", + "ipfs-core-types": "^0.4.0", + "ipfs-core-utils": "^0.8.0", "ipfs-http-response": "^0.6.0", "is-ipfs": "^5.0.0", "it-last": "^1.0.4", @@ -59,8 +59,8 @@ "uri-to-multiaddr": "^5.0.0" }, "devDependencies": { - "@types/hapi__hapi": "^20.0.5", "@types/hapi-pino": "^8.0.1", + "@types/hapi__hapi": "^20.0.5", "aegir": "^33.0.0", "file-type": "^16.0.0", "rimraf": "^3.0.2", diff --git a/packages/ipfs-http-server/CHANGELOG.md b/packages/ipfs-http-server/CHANGELOG.md index 870ef33a5d..2a6f10acf6 100644 --- a/packages/ipfs-http-server/CHANGELOG.md +++ b/packages/ipfs-http-server/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.4.0](https://github.com/ipfs/js-ipfs/compare/ipfs-http-server@0.3.4...ipfs-http-server@0.4.0) (2021-05-10) + + +### Bug Fixes + +* only use public api in http api server ([#3660](https://github.com/ipfs/js-ipfs/issues/3660)) ([61d0981](https://github.com/ipfs/js-ipfs/commit/61d0981c05371c4846dcea3330ac9fb2e810b8fa)), closes [#3639](https://github.com/ipfs/js-ipfs/issues/3639) +* reject requests when cors origin list is empty ([#3674](https://github.com/ipfs/js-ipfs/issues/3674)) ([0b2d98c](https://github.com/ipfs/js-ipfs/commit/0b2d98c53ba18491d7b99ae9cc0955281146610d)) + + +### chore + +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### Features + +* support identity hash in block.get + dag.get ([#3616](https://github.com/ipfs/js-ipfs/issues/3616)) ([28ad9ad](https://github.com/ipfs/js-ipfs/commit/28ad9ad6e50abb89a366ecd6b5301e848f0e9962)) + + +### BREAKING CHANGES + +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.3.4](https://github.com/ipfs/js-ipfs/compare/ipfs-http-server@0.3.3...ipfs-http-server@0.3.4) (2021-03-10) **Note:** Version bump only for package ipfs-http-server diff --git a/packages/ipfs-http-server/package.json b/packages/ipfs-http-server/package.json index 3b5cb073a7..45ac1af21f 100644 --- a/packages/ipfs-http-server/package.json +++ b/packages/ipfs-http-server/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-server", - "version": "0.3.4", + "version": "0.4.0", "description": "JavaScript implementation of the IPFS specification", "keywords": [ "IPFS" @@ -39,9 +39,9 @@ "dlv": "^1.1.3", "err-code": "^3.0.1", "hapi-pino": "^8.3.0", - "ipfs-core-types": "^0.3.1", - "ipfs-core-utils": "^0.7.2", - "ipfs-http-gateway": "^0.3.2", + "ipfs-core-types": "^0.4.0", + "ipfs-core-utils": "^0.8.0", + "ipfs-http-gateway": "^0.4.0", "ipfs-unixfs": "^4.0.3", "ipld-block": "^0.11.1", "ipld-dag-pb": "^0.22.1", @@ -69,11 +69,11 @@ "uri-to-multiaddr": "^5.0.0" }, "devDependencies": { - "@types/hapi__hapi": "^20.0.5", "@types/hapi-pino": "^8.0.1", + "@types/hapi__hapi": "^20.0.5", "aegir": "^33.0.0", "form-data": "^4.0.0", - "ipfs-http-client": "^49.0.4", + "ipfs-http-client": "^50.0.0", "iso-random-stream": "^2.0.0", "it-to-buffer": "^2.0.0", "qs": "^6.9.4", diff --git a/packages/ipfs-message-port-client/CHANGELOG.md b/packages/ipfs-message-port-client/CHANGELOG.md index a2fc168be3..81173563d4 100644 --- a/packages/ipfs-message-port-client/CHANGELOG.md +++ b/packages/ipfs-message-port-client/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.6.0](https://github.com/ipfs/js-ipfs/compare/ipfs-message-port-client@0.5.4...ipfs-message-port-client@0.6.0) (2021-05-10) + + +### chore + +* update node version in docker build ([#3603](https://github.com/ipfs/js-ipfs/issues/3603)) ([087fd1e](https://github.com/ipfs/js-ipfs/commit/087fd1eb402d1b933730e09c1d0cfb21067e9992)) +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* Minimum supported node version is 14 +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.5.4](https://github.com/ipfs/js-ipfs/compare/ipfs-message-port-client@0.5.3...ipfs-message-port-client@0.5.4) (2021-03-10) **Note:** Version bump only for package ipfs-message-port-client diff --git a/packages/ipfs-message-port-client/package.json b/packages/ipfs-message-port-client/package.json index 59b68df236..2c730b9dac 100644 --- a/packages/ipfs-message-port-client/package.json +++ b/packages/ipfs-message-port-client/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-message-port-client", - "version": "0.5.4", + "version": "0.6.0", "description": "IPFS client library for accessing IPFS node over message port", "keywords": [ "ipfs", @@ -35,15 +35,15 @@ "dependencies": { "browser-readablestream-to-it": "^1.0.1", "cids": "^1.1.6", - "ipfs-core-types": "^0.3.1", - "ipfs-message-port-protocol": "^0.6.1", + "ipfs-core-types": "^0.4.0", + "ipfs-message-port-protocol": "^0.7.0", "ipfs-unixfs": "^4.0.3" }, "devDependencies": { "aegir": "^33.0.0", - "interface-ipfs-core": "^0.144.2", - "ipfs-core": "^0.5.4", - "ipfs-message-port-server": "^0.6.3", + "interface-ipfs-core": "^0.145.0", + "ipfs-core": "^0.6.0", + "ipfs-message-port-server": "^0.7.0", "rimraf": "^3.0.2" }, "engines": { diff --git a/packages/ipfs-message-port-protocol/CHANGELOG.md b/packages/ipfs-message-port-protocol/CHANGELOG.md index 2d9b5fb402..451ef88761 100644 --- a/packages/ipfs-message-port-protocol/CHANGELOG.md +++ b/packages/ipfs-message-port-protocol/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.7.0](https://github.com/ipfs/js-ipfs/compare/ipfs-message-port-protocol@0.6.1...ipfs-message-port-protocol@0.7.0) (2021-05-10) + + +### chore + +* update node version in docker build ([#3603](https://github.com/ipfs/js-ipfs/issues/3603)) ([087fd1e](https://github.com/ipfs/js-ipfs/commit/087fd1eb402d1b933730e09c1d0cfb21067e9992)) +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* Minimum supported node version is 14 +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.6.1](https://github.com/ipfs/js-ipfs/compare/ipfs-message-port-protocol@0.6.0...ipfs-message-port-protocol@0.6.1) (2021-03-09) diff --git a/packages/ipfs-message-port-protocol/package.json b/packages/ipfs-message-port-protocol/package.json index 6d62f77113..96d8164aaa 100644 --- a/packages/ipfs-message-port-protocol/package.json +++ b/packages/ipfs-message-port-protocol/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-message-port-protocol", - "version": "0.6.1", + "version": "0.7.0", "description": "IPFS client/server protocol over message port", "keywords": [ "ipfs" @@ -47,7 +47,7 @@ }, "dependencies": { "cids": "^1.1.6", - "ipfs-core-types": "^0.3.1", + "ipfs-core-types": "^0.4.0", "ipld-block": "^0.11.0" }, "devDependencies": { diff --git a/packages/ipfs-message-port-server/CHANGELOG.md b/packages/ipfs-message-port-server/CHANGELOG.md index 1672379e1e..d185b7d932 100644 --- a/packages/ipfs-message-port-server/CHANGELOG.md +++ b/packages/ipfs-message-port-server/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.7.0](https://github.com/ipfs/js-ipfs/compare/ipfs-message-port-server@0.6.3...ipfs-message-port-server@0.7.0) (2021-05-10) + + +### chore + +* update node version in docker build ([#3603](https://github.com/ipfs/js-ipfs/issues/3603)) ([087fd1e](https://github.com/ipfs/js-ipfs/commit/087fd1eb402d1b933730e09c1d0cfb21067e9992)) +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* Minimum supported node version is 14 +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.6.3](https://github.com/ipfs/js-ipfs/compare/ipfs-message-port-server@0.6.2...ipfs-message-port-server@0.6.3) (2021-03-10) **Note:** Version bump only for package ipfs-message-port-server diff --git a/packages/ipfs-message-port-server/package.json b/packages/ipfs-message-port-server/package.json index ff3956fb98..c1a80a755b 100644 --- a/packages/ipfs-message-port-server/package.json +++ b/packages/ipfs-message-port-server/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-message-port-server", - "version": "0.6.3", + "version": "0.7.0", "description": "IPFS server library for exposing IPFS node over message port", "keywords": [ "ipfs", @@ -38,8 +38,8 @@ "dep-check": "aegir dep-check -i rimraf -i ipfs-core-types" }, "dependencies": { - "ipfs-core-types": "^0.3.1", - "ipfs-message-port-protocol": "^0.6.1", + "ipfs-core-types": "^0.4.0", + "ipfs-message-port-protocol": "^0.7.0", "it-all": "^1.0.4" }, "devDependencies": { diff --git a/packages/ipfs/CHANGELOG.md b/packages/ipfs/CHANGELOG.md index 3fe6e6eebd..b864a4984f 100644 --- a/packages/ipfs/CHANGELOG.md +++ b/packages/ipfs/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.55.0](https://github.com/ipfs/js-ipfs/compare/ipfs@0.54.4...ipfs@0.55.0) (2021-05-10) + + +### Bug Fixes + +* mark ipld options as partial ([#3669](https://github.com/ipfs/js-ipfs/issues/3669)) ([f98af8e](https://github.com/ipfs/js-ipfs/commit/f98af8ed24784929898bb5d33a64dc442c77074d)) +* only accept cid for ipfs.dag.get ([#3675](https://github.com/ipfs/js-ipfs/issues/3675)) ([bb8f8bc](https://github.com/ipfs/js-ipfs/commit/bb8f8bc501ffc1ee0f064ba61ec0bca4015bf6ad)), closes [#3637](https://github.com/ipfs/js-ipfs/issues/3637) + + +### chore + +* update node version in docker build ([#3603](https://github.com/ipfs/js-ipfs/issues/3603)) ([087fd1e](https://github.com/ipfs/js-ipfs/commit/087fd1eb402d1b933730e09c1d0cfb21067e9992)) +* upgrade deps with new typedefs ([#3550](https://github.com/ipfs/js-ipfs/issues/3550)) ([a418a52](https://github.com/ipfs/js-ipfs/commit/a418a521574c878d7aabd0ad2fd8d516908a3756)) + + +### BREAKING CHANGES + +* Minimum supported node version is 14 +* all core api methods now have types, some method signatures have changed, named exports are now used by the http, grpc and ipfs client modules + + + + + ## [0.54.4](https://github.com/ipfs/js-ipfs/compare/ipfs@0.54.3...ipfs@0.54.4) (2021-03-10) **Note:** Version bump only for package ipfs diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index 3bd452604a..ce924d2692 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -1,6 +1,6 @@ { "name": "ipfs", - "version": "0.54.4", + "version": "0.55.0", "description": "JavaScript implementation of the IPFS specification", "keywords": [ "IPFS" @@ -39,8 +39,8 @@ }, "dependencies": { "debug": "^4.1.1", - "ipfs-cli": "^0.4.4", - "ipfs-core": "^0.5.4", + "ipfs-cli": "^0.5.0", + "ipfs-core": "^0.6.0", "semver": "^7.3.2", "update-notifier": "^5.0.0" }, @@ -52,10 +52,10 @@ "cross-env": "^7.0.0", "electron-webrtc": "^0.3.0", "go-ipfs": "0.8.0", - "interface-ipfs-core": "^0.144.2", - "ipfs-client": "^0.3.4", - "ipfs-core-types": "^0.3.1", - "ipfs-http-client": "^49.0.4", + "interface-ipfs-core": "^0.145.0", + "ipfs-client": "^0.4.0", + "ipfs-core-types": "^0.4.0", + "ipfs-http-client": "^50.0.0", "ipfs-interop": "^5.0.2", "ipfs-utils": "^7.0.0", "ipfsd-ctl": "^8.0.1",