diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index d401a774..589a3341 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,11 +1,30 @@
version: 2
updates:
- package-ecosystem: npm
- directory: "/"
+ directories:
+ - "/"
schedule:
interval: daily
time: "10:00"
open-pull-requests-limit: 20
commit-message:
prefix: "deps"
- prefix-development: "deps(dev)"
+ prefix-development: "chore"
+ groups:
+ interplanetary-deps: # Helia/libp2p deps
+ patterns:
+ - "*helia*"
+ - "*libp2p*"
+ - "*multiformats*"
+ - "*blockstore*"
+ - "*datastore*"
+ kubo-deps: # kubo deps
+ patterns:
+ - "*kubo*"
+ - "ipfsd-ctl"
+- package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ commit-message:
+ prefix: chore
diff --git a/.github/workflows/generated-pr.yml b/.github/workflows/generated-pr.yml
new file mode 100644
index 00000000..b8c5cc63
--- /dev/null
+++ b/.github/workflows/generated-pr.yml
@@ -0,0 +1,14 @@
+name: Close Generated PRs
+
+on:
+ schedule:
+ - cron: '0 0 * * *'
+ workflow_dispatch:
+
+permissions:
+ issues: write
+ pull-requests: write
+
+jobs:
+ stale:
+ uses: ipdxco/unified-github-workflows/.github/workflows/reusable-generated-pr.yml@v1
diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml
index 1d7ff79c..28068134 100644
--- a/.github/workflows/js-test-and-release.yml
+++ b/.github/workflows/js-test-and-release.yml
@@ -19,9 +19,10 @@ concurrency:
jobs:
js-test-and-release:
- uses: pl-strflt/uci/.github/workflows/js-test-and-release.yml@v0.0
+ uses: ipdxco/unified-github-workflows/.github/workflows/js-test-and-release.yml@v1.0
secrets:
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
UCI_GITHUB_TOKEN: ${{ secrets.UCI_GITHUB_TOKEN }}
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/semantic-pull-request.yml b/.github/workflows/semantic-pull-request.yml
index bd00f090..8c0b9eaf 100644
--- a/.github/workflows/semantic-pull-request.yml
+++ b/.github/workflows/semantic-pull-request.yml
@@ -9,4 +9,4 @@ on:
jobs:
main:
- uses: pl-strflt/.github/.github/workflows/reusable-semantic-pull-request.yml@v0.3
+ uses: ipdxco/unified-github-workflows/.github/workflows/reusable-semantic-pull-request.yml@v1
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 16d65d72..7c955c41 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -1,8 +1,9 @@
-name: Close and mark stale issue
+name: Close Stale Issues
on:
schedule:
- cron: '0 0 * * *'
+ workflow_dispatch:
permissions:
issues: write
@@ -10,4 +11,4 @@ permissions:
jobs:
stale:
- uses: pl-strflt/.github/.github/workflows/reusable-stale-issue.yml@v0.3
+ uses: ipdxco/unified-github-workflows/.github/workflows/reusable-stale-issue.yml@v1
diff --git a/.gitignore b/.gitignore
index 7ad9e674..f115d26b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@ node_modules
package-lock.json
yarn.lock
.vscode
+.tmp-compiled-docs
+tsconfig-doc-check.aegir.json
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..ef904d81
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,392 @@
+## 1.0.0 (2024-08-02)
+
+### ⚠ BREAKING CHANGES
+
+* To detect the type of error thrown, use `.name` instead of `.code`
+* s3 filenames are now all base32upper
+* the output of store.getMany is now a stream of pairs
+* open/close/batch/query methods have been removed from store interface, query/batch added to datastore, getAll added to blockstore
+* bump multiformats from 10.0.3 to 11.0.0 (#182)
+* this module is now ESM only
+* deep requires/imports are no longer possible, moves adapters/in-memory impls etc to core packages
+* the compliance tests for interface-datastore have been removed - use the interface-datastore-tests module instead
+
+### Features
+
+* add all blockstore and datastore implementations ([#197](https://github.com/ipfs/js-stores/issues/197)) ([0d85128](https://github.com/ipfs/js-stores/commit/0d851286d48c357b07df3f7419c1e903ed0e7fac))
+* add black hole stores ([#227](https://github.com/ipfs/js-stores/issues/227)) ([6074f0f](https://github.com/ipfs/js-stores/commit/6074f0fa831abc45b40177ea498a2e0fbb3eeb32))
+* add identity blockstore ([#298](https://github.com/ipfs/js-stores/issues/298)) ([b8dce49](https://github.com/ipfs/js-stores/commit/b8dce49fc005a76b86bca751b7d703d321cd12d6))
+* add in-memory blockstore implementation ([#1](https://github.com/ipfs/js-stores/issues/1)) ([ab37d40](https://github.com/ipfs/js-stores/commit/ab37d40c62875a976eb55054e0d604e237d5a8aa))
+* add Key.asKey method ([#41](https://github.com/ipfs/js-stores/issues/41)) ([783dcc8](https://github.com/ipfs/js-stores/commit/783dcc866e4ca6784d2801a8e18fa1135a137a6b))
+* add tiered blockstore ([#238](https://github.com/ipfs/js-stores/issues/238)) ([5143948](https://github.com/ipfs/js-stores/commit/51439486d5fcd719b9af9182b35565e87da96c99))
+* add unwrap method ([0c22c9f](https://github.com/ipfs/js-stores/commit/0c22c9ff4fe12ac92e38bcfb6ced626077fdb0ed))
+* allow extending store method options ([#193](https://github.com/ipfs/js-stores/issues/193)) ([007e8ac](https://github.com/ipfs/js-stores/commit/007e8ac83a43ec185368cfad57193f57ef700c45))
+* import interface-datastore ([294b249](https://github.com/ipfs/js-stores/commit/294b249de30e6fa80c4246a6a253db0ab493886b))
+* prep for v1 release ([b95a516](https://github.com/ipfs/js-stores/commit/b95a51610738e8ce6b5e29e9769f19f98e525a94))
+* release prep ([b38a533](https://github.com/ipfs/js-stores/commit/b38a53341d84cbef0aee75be149342e74eadfcc6))
+* simplify store interface, move query/batch to datastore, add getAll to blockstore ([#189](https://github.com/ipfs/js-stores/issues/189)) ([0b8f1a0](https://github.com/ipfs/js-stores/commit/0b8f1a0d7644b32395059db250b301d3d5f024cb))
+* use `.name` property for errors instead of `.code` ([#315](https://github.com/ipfs/js-stores/issues/315)) ([dacd6ce](https://github.com/ipfs/js-stores/commit/dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd))
+
+### Bug Fixes
+
+* add sharding to s3 blockstore ([#202](https://github.com/ipfs/js-stores/issues/202)) ([e1324a1](https://github.com/ipfs/js-stores/commit/e1324a16dcfae0a39a325e7a9929eb1c2f8ca6c8))
+* bump aegir to 42.2.3, update project config and fix deps ([#297](https://github.com/ipfs/js-stores/issues/297)) ([d521ef2](https://github.com/ipfs/js-stores/commit/d521ef251815527baee0a70705f775c0e47481ad))
+* cleanup references to datastore in blockstores ([#274](https://github.com/ipfs/js-stores/issues/274)) ([f550624](https://github.com/ipfs/js-stores/commit/f5506243b2cb1e6462457241a1614bd5f0755c12))
+* encode/decode blockstore-s3 keys in base32upper ([#201](https://github.com/ipfs/js-stores/issues/201)) ([513fd9c](https://github.com/ipfs/js-stores/commit/513fd9ca35059c422d440ad955d34042c6bc301e))
+* export key properly ([749b656](https://github.com/ipfs/js-stores/commit/749b656c23fb91aa13bfaf9a5ad99703490b24b4))
+* identity blockstore should wrap child ([#303](https://github.com/ipfs/js-stores/issues/303)) ([3d84dd0](https://github.com/ipfs/js-stores/commit/3d84dd0ab164fb5749c34487a217c763d1d09ccb))
+* incorrect export path ([#273](https://github.com/ipfs/js-stores/issues/273)) ([e840ed4](https://github.com/ipfs/js-stores/commit/e840ed4f0e601062c7cb727bd71390381644caa6))
+* increase timeouts ([#131](https://github.com/ipfs/js-stores/issues/131)) ([733c2ed](https://github.com/ipfs/js-stores/commit/733c2edb32a3aa3a54c6cf2d39f780bd6018010b))
+* lower amount ([b7f9aab](https://github.com/ipfs/js-stores/commit/b7f9aab399b026d34521aad5a9c3757baa60cb4d))
+* make datastore batch commit option extension optional ([#194](https://github.com/ipfs/js-stores/issues/194)) ([7bb6729](https://github.com/ipfs/js-stores/commit/7bb6729f616546284c107eaf5dacf12598ea37a0))
+* make tests more stable ([#38](https://github.com/ipfs/js-stores/issues/38)) ([595de43](https://github.com/ipfs/js-stores/commit/595de438cbb5bda7444bdd8c4ce561215855d190))
+* open and close blockstore during interface tests ([#188](https://github.com/ipfs/js-stores/issues/188)) ([a61a54b](https://github.com/ipfs/js-stores/commit/a61a54ba53fa06800e91ea933924615fe6df5b01))
+* publish with limited concurrency ([85bcc4a](https://github.com/ipfs/js-stores/commit/85bcc4acc09d76d7938c55163c81d9b948c53803))
+* readme update ([3bcfb6d](https://github.com/ipfs/js-stores/commit/3bcfb6d311d32a00f24c64cb55c3ba90ca495dba))
+* remove nanoid ([#283](https://github.com/ipfs/js-stores/issues/283)) ([da03ee2](https://github.com/ipfs/js-stores/commit/da03ee29970fdc860eead076ccedb5eea8ff4266))
+* rename test from blocks to getMany ([#190](https://github.com/ipfs/js-stores/issues/190)) ([60e6c3f](https://github.com/ipfs/js-stores/commit/60e6c3f44596ff8fc7906f7d5fe86f8ebdf227d1))
+* replace datastore references in blockstore-s3 ([#214](https://github.com/ipfs/js-stores/issues/214)) ([1a65042](https://github.com/ipfs/js-stores/commit/1a65042cc37aa0f074b64cf070ed32df174ef1a1))
+* restore empty object default ([#228](https://github.com/ipfs/js-stores/issues/228)) ([f82d02c](https://github.com/ipfs/js-stores/commit/f82d02cc8742b595939b58e2eae0a86bb1cec6b1))
+* return key from put and put many ([#196](https://github.com/ipfs/js-stores/issues/196)) ([dfc4697](https://github.com/ipfs/js-stores/commit/dfc4697868d23b3a62154ddda3ae0747e124e3e1))
+* return stream of pairs from getmany ([#195](https://github.com/ipfs/js-stores/issues/195)) ([252bced](https://github.com/ipfs/js-stores/commit/252bced0ad3111711bd502e8d2a5932d6289e0f9))
+* stop namespaced datastore throwing when queried ([#296](https://github.com/ipfs/js-stores/issues/296)) ([9163490](https://github.com/ipfs/js-stores/commit/916349054a3f83a7c9c4bb692edebcce409c7fee)), closes [#236](https://github.com/ipfs/js-stores/issues/236) [#236](https://github.com/ipfs/js-stores/issues/236)
+* throw read error on read error ([#304](https://github.com/ipfs/js-stores/issues/304)) ([f14c824](https://github.com/ipfs/js-stores/commit/f14c8249dfd7bbd1385bbf3513b2b3d5e0e6860c)), closes [#299](https://github.com/ipfs/js-stores/issues/299)
+* update project config to publish ESM only ([#172](https://github.com/ipfs/js-stores/issues/172)) ([8c9d21f](https://github.com/ipfs/js-stores/commit/8c9d21fdb97f055569984101d573864c808d90d9))
+
+### Trivial Changes
+
+* add blockstore adapter ([05ddff4](https://github.com/ipfs/js-stores/commit/05ddff401ddb2d94f4440e07bfb0405f9ae8795e))
+* add clean script and control published files ([c58873d](https://github.com/ipfs/js-stores/commit/c58873dfd849a5164f64c507ede719342ffe3561))
+* add description ([2aef1ba](https://github.com/ipfs/js-stores/commit/2aef1ba53ba8e0424b18be540bafe42751849124))
+* add modules for interface-blockstore and interface-datastore tests ([da0ac9c](https://github.com/ipfs/js-stores/commit/da0ac9c2218eb0efef79f6455ba671b44b24c9dc))
+* add or force update .github/workflows/js-test-and-release.yml ([#243](https://github.com/ipfs/js-stores/issues/243)) ([7bdc56b](https://github.com/ipfs/js-stores/commit/7bdc56bddd6a58846d86fd7596ef7af81f22cc63))
+* add release script ([c2e11ab](https://github.com/ipfs/js-stores/commit/c2e11ab55dafaf846787e47612e10a855671d317))
+* build before publish and export all blockstore types ([21980fe](https://github.com/ipfs/js-stores/commit/21980fe533dc03ef2e1303058ca1c5cf5a67385a))
+* change version ([f65249d](https://github.com/ipfs/js-stores/commit/f65249d3801a59c0e84217979bf93c7b079bf59f))
+* delete templates [skip ci] ([#242](https://github.com/ipfs/js-stores/issues/242)) ([c0ecb8a](https://github.com/ipfs/js-stores/commit/c0ecb8a76c477115e7fe6f01e41f0491cef6baca))
+* **deps-dev:** bump rimraf from 1.0.9 to 3.0.2 in /packages/interface-datastore-tests ([#40](https://github.com/ipfs/js-stores/issues/40)) ([5d92f17](https://github.com/ipfs/js-stores/commit/5d92f17bd1580bd25e72d70250eabc0ce02a109c))
+* **deps:** bump nanoid from 3.3.4 to 4.0.0 in /packages/interface-datastore ([#110](https://github.com/ipfs/js-stores/issues/110)) ([5e40d9c](https://github.com/ipfs/js-stores/commit/5e40d9c86170fc4c7f0d6c6ee54161327a5493f1))
+* disable tests that stringify cids ([72c93f9](https://github.com/ipfs/js-stores/commit/72c93f90c7204276ad47cd8d18ae07020a1f2c4c))
+* dual licensed ([dbc6615](https://github.com/ipfs/js-stores/commit/dbc66159d3d3a604bb711d4bfb37ff394a3b057c))
+* enable query tests for blockstores ([d2ce541](https://github.com/ipfs/js-stores/commit/d2ce54170c5dbab65882018d9d2e0063e4260779))
+* export options ([00dbf60](https://github.com/ipfs/js-stores/commit/00dbf604e248eaa5bfb6c27a9e0475cdc32bedd5))
+* fix import ([1ab80a7](https://github.com/ipfs/js-stores/commit/1ab80a7131990d8190262e5773f117b3f1d549bc))
+* fix slow ci ([1a6736f](https://github.com/ipfs/js-stores/commit/1a6736fb6e8354b9f94da3bc91a1defc35ebd2c9))
+* initial commit ([e3e73df](https://github.com/ipfs/js-stores/commit/e3e73df19d543afd98bfbf4cbb76537979bd1a3b))
+* publish ([ca0fc50](https://github.com/ipfs/js-stores/commit/ca0fc50134b164e5afc557c5a1aedb7af1623f9c))
+* publish ([c256fa6](https://github.com/ipfs/js-stores/commit/c256fa6c3ca30047fc9edc9f7e7a16e464e5b333))
+* publish ([1b8c053](https://github.com/ipfs/js-stores/commit/1b8c053b925421566adca356d1116e8169691718))
+* publish ([17a18d9](https://github.com/ipfs/js-stores/commit/17a18d9af34a39ea7b066d523893c3254439f50b))
+* publish ([24becc0](https://github.com/ipfs/js-stores/commit/24becc0ba9ba3e75a7ee87a006b67962f6d510b1))
+* publish ([2059883](https://github.com/ipfs/js-stores/commit/2059883fd39cad552baf13ae0fdbb65493bc74ee))
+* publish ([4f99c21](https://github.com/ipfs/js-stores/commit/4f99c21214ce9f1fb6f808c2fe69b5233ee5d31b))
+* publish ([604a2b2](https://github.com/ipfs/js-stores/commit/604a2b2d9e37781627cbc1382c2e19f1fbeb0317))
+* publish ([5073988](https://github.com/ipfs/js-stores/commit/50739882f922000d389ed50d0452dea06c6bb502))
+* publish ([e246d97](https://github.com/ipfs/js-stores/commit/e246d974c52e9087598c5f78c417f25b08811fb9))
+* publish ([f5d59e8](https://github.com/ipfs/js-stores/commit/f5d59e8f70f72a5900504ef4c4cd7af2b69cb7fb))
+* publish ([b4a2514](https://github.com/ipfs/js-stores/commit/b4a251475df060773c9e3fd5218c95a92b6008b8))
+* publish ([6febcf2](https://github.com/ipfs/js-stores/commit/6febcf2a879e6791ea5ecb617ab6c5f98f77847d))
+* publish ([143ba26](https://github.com/ipfs/js-stores/commit/143ba26d8b2c521640bb0c790758ab82bfc6d1a0))
+* publish ([be5e39a](https://github.com/ipfs/js-stores/commit/be5e39a76dd50104bf4fa3e6ec8221ba4decddb5))
+* publish ([f6a0102](https://github.com/ipfs/js-stores/commit/f6a010286de4db5141ce2eb5617e618bafbb1d71))
+* publish ([05e3072](https://github.com/ipfs/js-stores/commit/05e30725cfe5161dbdcdcaacc18b7820108dddcf))
+* publish ([1e1bdd2](https://github.com/ipfs/js-stores/commit/1e1bdd2bae62f2e55b95635e2f42040c62cf65fa))
+* publish ([f55c465](https://github.com/ipfs/js-stores/commit/f55c465df32023e5e3978834ee5aab3e19af212a))
+* publish ([4e8bf56](https://github.com/ipfs/js-stores/commit/4e8bf56afb37619231b08963ffbf04105dbfeae7))
+* publish ([8edd47d](https://github.com/ipfs/js-stores/commit/8edd47d7a0b358e17e68e117089b954857536885))
+* publish ([67d1667](https://github.com/ipfs/js-stores/commit/67d16675fed0c52e2929fa6df19c4dda12987012))
+* publish ([634387a](https://github.com/ipfs/js-stores/commit/634387adab2d83a51472ae22ff01c955bd889dd2))
+* publish ([33020e4](https://github.com/ipfs/js-stores/commit/33020e403c81530df453dc2f7643fe7d79665f8b))
+* publish ([6aa50db](https://github.com/ipfs/js-stores/commit/6aa50dbcdd23f8c5ef3658fa3c2ed9cbc3abf323))
+* publish ([1c1a4ae](https://github.com/ipfs/js-stores/commit/1c1a4ae7035ec0d164636a0b4742f17c063db7bf))
+* readme update ([56e4826](https://github.com/ipfs/js-stores/commit/56e48266d662cb0b83ea52c99c1a1749b242f177))
+* **release:** 0.1.0 [skip ci] ([10476eb](https://github.com/ipfs/js-stores/commit/10476ebdb2f19324e5dae4f1532b3f1e6bbfffc1)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 1.0.0 [skip ci] ([405250f](https://github.com/ipfs/js-stores/commit/405250fc792bf1ebb993b79ed290645fe1f22c11)), closes [#201](https://github.com/ipfs/js-stores/issues/201) [#200](https://github.com/ipfs/js-stores/issues/200)
+* **release:** 1.0.1 [skip ci] ([8dfe4e5](https://github.com/ipfs/js-stores/commit/8dfe4e5261d5dfe0f086c81145077f819806d247)), closes [#202](https://github.com/ipfs/js-stores/issues/202)
+* **release:** 1.0.10 [skip ci] ([f87dd44](https://github.com/ipfs/js-stores/commit/f87dd444ff0cc27ed81f9ecf19de1d06df4ab03e)), closes [#273](https://github.com/ipfs/js-stores/issues/273)
+* **release:** 1.0.11 [skip ci] ([d292758](https://github.com/ipfs/js-stores/commit/d292758334aa3960d30513dd238afab2765f68f5)), closes [#274](https://github.com/ipfs/js-stores/issues/274)
+* **release:** 1.0.12 [skip ci] ([33f9197](https://github.com/ipfs/js-stores/commit/33f9197ef9d80018ca8c5fde8694668e90fc0037)), closes [#282](https://github.com/ipfs/js-stores/issues/282)
+* **release:** 1.0.14 [skip ci] ([5d5b295](https://github.com/ipfs/js-stores/commit/5d5b295a4d1840810a423c637899b341422c82fd))
+* **release:** 1.0.15 [skip ci] ([e8e3a1e](https://github.com/ipfs/js-stores/commit/e8e3a1eba91f62842c0f3701ce4f56f9a44fa4a9)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 1.0.16 [skip ci] ([9a62492](https://github.com/ipfs/js-stores/commit/9a62492ee04c97cf7ad6f548b72eeae672a5440b)), closes [#308](https://github.com/ipfs/js-stores/issues/308)
+* **release:** 1.0.2 [skip ci] ([642c41f](https://github.com/ipfs/js-stores/commit/642c41f7b3b50286b9ed9a448de54faeaa604883)), closes [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 1.0.3 [skip ci] ([03c8959](https://github.com/ipfs/js-stores/commit/03c89590acca0c475086d12166efa3bec1e20c1c)), closes [#214](https://github.com/ipfs/js-stores/issues/214)
+* **release:** 1.0.4 [skip ci] ([db9a101](https://github.com/ipfs/js-stores/commit/db9a101218b3ec5f7278024f259fdaed5df29873)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 1.0.5 [skip ci] ([9e43dd3](https://github.com/ipfs/js-stores/commit/9e43dd339560284082a88b42454c023636c65765)), closes [#231](https://github.com/ipfs/js-stores/issues/231)
+* **release:** 1.0.6 [skip ci] ([515b378](https://github.com/ipfs/js-stores/commit/515b378b6e35c68e87936e1b190a008e3452a44e)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 1.0.7 [skip ci] ([0be8503](https://github.com/ipfs/js-stores/commit/0be8503a94cc7c2afa9d2a00b4f20c367dc3feb4)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 1.0.8 [skip ci] ([2cd965e](https://github.com/ipfs/js-stores/commit/2cd965ed62254aef02148c5a824b876932d7480f)), closes [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 1.0.9 [skip ci] ([f496d4f](https://github.com/ipfs/js-stores/commit/f496d4fb81149b454c0b3bd6a7e58c3bc1e2508a)), closes [#265](https://github.com/ipfs/js-stores/issues/265)
+* **release:** 1.1.0 [skip ci] ([dcfcfd2](https://github.com/ipfs/js-stores/commit/dcfcfd238687541fbc44f54742e45eb2636805e5)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 1.1.0 [skip ci] ([d49cbfb](https://github.com/ipfs/js-stores/commit/d49cbfbc12c46ff2455bb06c85199d81383249ce)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 1.1.0 [skip ci] ([6fa0f7a](https://github.com/ipfs/js-stores/commit/6fa0f7aa79b76db52265d449f0df275b70542465)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 1.1.1 [skip ci] ([6bfda0a](https://github.com/ipfs/js-stores/commit/6bfda0a42dd537c038b4a2d668cd64577b8b0a9a)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 1.1.1 [skip ci] ([5884aa1](https://github.com/ipfs/js-stores/commit/5884aa1698de5ec6c9af39330fc79a0103fd11cf)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 1.1.1 [skip ci] ([2ec12ba](https://github.com/ipfs/js-stores/commit/2ec12ba13df924654312d0120e6a4e1b5dc90771)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 1.1.10 [skip ci] ([7374423](https://github.com/ipfs/js-stores/commit/7374423d9ebc26b895ac78116750439fff39c50e)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 1.1.11 [skip ci] ([3c15bbf](https://github.com/ipfs/js-stores/commit/3c15bbfbcbceea8ddc20db5259eeda125a3604a1)), closes [#306](https://github.com/ipfs/js-stores/issues/306)
+* **release:** 1.1.2 [skip ci] ([d089988](https://github.com/ipfs/js-stores/commit/d08998868e5a4c9fb00216e5505bb28d330aca90)), closes [#231](https://github.com/ipfs/js-stores/issues/231)
+* **release:** 1.1.2 [skip ci] ([27e5880](https://github.com/ipfs/js-stores/commit/27e588048598f5206e3675b726a09f9c9ff9fa6e)), closes [#231](https://github.com/ipfs/js-stores/issues/231)
+* **release:** 1.1.2 [skip ci] ([ab61569](https://github.com/ipfs/js-stores/commit/ab61569a6557cc52758e4801492bf2a3f55d8a1f)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 1.1.3 [skip ci] ([45ec187](https://github.com/ipfs/js-stores/commit/45ec1876eef13c0d95369c0f2c5ef85f9eac5e7e)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 1.1.3 [skip ci] ([fe95b02](https://github.com/ipfs/js-stores/commit/fe95b021d78fb2f33980646b0a0016b02c669bb3)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 1.1.3 [skip ci] ([61f56da](https://github.com/ipfs/js-stores/commit/61f56da188adfae4a1eaa6d0e9098a18a7411482)), closes [#226](https://github.com/ipfs/js-stores/issues/226)
+* **release:** 1.1.4 [skip ci] ([9ee3162](https://github.com/ipfs/js-stores/commit/9ee316256629783b6281542d7073973c4eb14a64)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 1.1.4 [skip ci] ([4258c30](https://github.com/ipfs/js-stores/commit/4258c300e69b70bd4d18b26c93a7164cf38d0465)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 1.1.4 [skip ci] ([3e07e46](https://github.com/ipfs/js-stores/commit/3e07e46e7395f3fe05657bae4cee8d6044000a04)), closes [#231](https://github.com/ipfs/js-stores/issues/231)
+* **release:** 1.1.5 [skip ci] ([e2b96fd](https://github.com/ipfs/js-stores/commit/e2b96fdd4b390c32b4341ab2401d609a44db527c)), closes [#245](https://github.com/ipfs/js-stores/issues/245) [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 1.1.5 [skip ci] ([01f0820](https://github.com/ipfs/js-stores/commit/01f08206896b9181ab0a80158d43dc52c7ca6ec8)), closes [#245](https://github.com/ipfs/js-stores/issues/245) [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 1.1.5 [skip ci] ([38883cc](https://github.com/ipfs/js-stores/commit/38883cc9145a1b1e63a1c76c97227a36b2a5ff37)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 1.1.6 [skip ci] ([91e4845](https://github.com/ipfs/js-stores/commit/91e4845e6b431c96d76223f402c42395d4089db6)), closes [#274](https://github.com/ipfs/js-stores/issues/274)
+* **release:** 1.1.6 [skip ci] ([c786bdc](https://github.com/ipfs/js-stores/commit/c786bdc58a173910865ad2cd5c1544b17ecaf3a4)), closes [#274](https://github.com/ipfs/js-stores/issues/274)
+* **release:** 1.1.6 [skip ci] ([2f7be23](https://github.com/ipfs/js-stores/commit/2f7be23d7d8897a9ab54eba564bcf492ecbc89c5)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 1.1.7 [skip ci] ([2401e95](https://github.com/ipfs/js-stores/commit/2401e9572cd3daf3ae1dca723dbbbb4997143f43)), closes [#281](https://github.com/ipfs/js-stores/issues/281) [#286](https://github.com/ipfs/js-stores/issues/286)
+* **release:** 1.1.7 [skip ci] ([3423745](https://github.com/ipfs/js-stores/commit/34237454fae8adcf2dd07cde3f8fc23ae83d04ea)), closes [#286](https://github.com/ipfs/js-stores/issues/286)
+* **release:** 1.1.7 [skip ci] ([20907ff](https://github.com/ipfs/js-stores/commit/20907ffb5813995bba89a8015f36003775b08e3e)), closes [#245](https://github.com/ipfs/js-stores/issues/245) [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 1.1.8 [skip ci] ([a5f10ba](https://github.com/ipfs/js-stores/commit/a5f10badf593669380edd6b0035b67774161c9b7)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 1.1.8 [skip ci] ([479ba70](https://github.com/ipfs/js-stores/commit/479ba709ca54f9b6f7aadec87e6699b2d87f9992)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 1.1.8 [skip ci] ([48b6a70](https://github.com/ipfs/js-stores/commit/48b6a70ba24c8c98829d1017e77cc094621305c3)), closes [#274](https://github.com/ipfs/js-stores/issues/274)
+* **release:** 1.1.9 [skip ci] ([5307449](https://github.com/ipfs/js-stores/commit/530744952275f7be66ca53f3a3b58c81d2057cd4)), closes [#286](https://github.com/ipfs/js-stores/issues/286)
+* **release:** 10.0.0 [skip ci] ([ae52bfc](https://github.com/ipfs/js-stores/commit/ae52bfc5aa6503ac656ed6312694e2e0445a53dd)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 10.0.0 [skip ci] ([89aa5e1](https://github.com/ipfs/js-stores/commit/89aa5e1b33e6ba7b1db4605155cd66aa56181f8b)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 10.1.0 [skip ci] ([b500ee8](https://github.com/ipfs/js-stores/commit/b500ee87f1dcc32ade8bba95a539b57604fa1b06)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 10.1.1 [skip ci] ([42fd4f3](https://github.com/ipfs/js-stores/commit/42fd4f3be0fc0152cdaa0e0d4cde8d510ced29e6)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 10.1.2 [skip ci] ([cdc3f04](https://github.com/ipfs/js-stores/commit/cdc3f045cc487277b9d9a37817b55cd4cd444eb3)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 10.1.3 [skip ci] ([b02129c](https://github.com/ipfs/js-stores/commit/b02129cbd367deab0cf199620605012d5af07f0d)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 10.1.4 [skip ci] ([ce5247b](https://github.com/ipfs/js-stores/commit/ce5247b57f8a00c1cc0f204760ad984339115396)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 10.1.5 [skip ci] ([50763d0](https://github.com/ipfs/js-stores/commit/50763d0ae947918aa9a8da05332a37d2229a6412)), closes [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 10.1.6 [skip ci] ([67541e9](https://github.com/ipfs/js-stores/commit/67541e94f0c4579e782d732a5db590a0cc2a015c))
+* **release:** 10.1.7 [skip ci] ([bf0b007](https://github.com/ipfs/js-stores/commit/bf0b0074045dcfe460db115021cd48346694a211)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 10.1.8 [skip ci] ([92d5933](https://github.com/ipfs/js-stores/commit/92d59330bc539e3134f285c3d8d60b4468f84ace)), closes [#299](https://github.com/ipfs/js-stores/issues/299)
+* **release:** 11.0.0 [skip ci] ([2cd66f5](https://github.com/ipfs/js-stores/commit/2cd66f5b07476946c25fe7fa915ecdd02bb824a2)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 11.1.0 [skip ci] ([cfcb39d](https://github.com/ipfs/js-stores/commit/cfcb39d33ece55af7aa6c13965e70b1e79f722f1)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 11.1.1 [skip ci] ([5f60f27](https://github.com/ipfs/js-stores/commit/5f60f278449a856cc8b55c5722fe4233eab0aa4b)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 11.1.10 [skip ci] ([a9d62bd](https://github.com/ipfs/js-stores/commit/a9d62bd1ed9d10e603211fb279b9d7dec4bcebc5))
+* **release:** 11.1.11 [skip ci] ([7353d28](https://github.com/ipfs/js-stores/commit/7353d280ae23f8040cf26cc60388799491fd399f)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 11.1.12 [skip ci] ([7877a67](https://github.com/ipfs/js-stores/commit/7877a67817dcc46e4d48904dd576eb728700cb76)), closes [#308](https://github.com/ipfs/js-stores/issues/308)
+* **release:** 11.1.2 [skip ci] ([b3148e9](https://github.com/ipfs/js-stores/commit/b3148e9dc9a477072ff2562c8a99e0b886ce339c)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 11.1.3 [skip ci] ([d8999ba](https://github.com/ipfs/js-stores/commit/d8999ba0b992b83f7f439732f5514f5fc8eb93a2)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 11.1.4 [skip ci] ([8083f44](https://github.com/ipfs/js-stores/commit/8083f448aa447fc71949c54514d2c1b05207109c)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 11.1.5 [skip ci] ([a9218cd](https://github.com/ipfs/js-stores/commit/a9218cddfed1c25995927d060fdc97e85845b83a)), closes [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 11.1.6 [skip ci] ([17a8e76](https://github.com/ipfs/js-stores/commit/17a8e76ad30eb57c0d05a33b9e36ef9da670a9e0)), closes [#265](https://github.com/ipfs/js-stores/issues/265)
+* **release:** 11.1.7 [skip ci] ([663ae05](https://github.com/ipfs/js-stores/commit/663ae051d6b23ed76bf7533db767f6de183690a5)), closes [#273](https://github.com/ipfs/js-stores/issues/273)
+* **release:** 11.1.8 [skip ci] ([c5c79d0](https://github.com/ipfs/js-stores/commit/c5c79d098109ee58e1fa2698569e9ce452013b11)), closes [#274](https://github.com/ipfs/js-stores/issues/274)
+* **release:** 11.1.9 [skip ci] ([edb7c80](https://github.com/ipfs/js-stores/commit/edb7c80b5e24b34c53e2d1eda1d1a96a02d19048)), closes [#282](https://github.com/ipfs/js-stores/issues/282)
+* **release:** 12.0.0 [skip ci] ([8ef4ed4](https://github.com/ipfs/js-stores/commit/8ef4ed48537ced54cf8c1ea47fb796f942b97241)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 2.0.0 [skip ci] ([a8dce3e](https://github.com/ipfs/js-stores/commit/a8dce3e53d18bf8b9499f85862b9fc182424ec19)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 2.0.0 [skip ci] ([5b8f461](https://github.com/ipfs/js-stores/commit/5b8f4615ba5cab9737a0582af6a8486bcc3b02e0)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 2.0.0 [skip ci] ([2368fb3](https://github.com/ipfs/js-stores/commit/2368fb35cadcaeeaa5c52df9d95f18fc3d5bda64)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 2.0.0 [skip ci] ([4f4b9ee](https://github.com/ipfs/js-stores/commit/4f4b9ee96dd1195f213391198f4cc62e08281262)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 2.1.0 [skip ci] ([6c92ec7](https://github.com/ipfs/js-stores/commit/6c92ec73b82eac0bf446718f1b1d24fb9b740ce6)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 2.1.1 [skip ci] ([351c496](https://github.com/ipfs/js-stores/commit/351c49680be94a162153b6d71858382ae79cf0e7)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 2.1.2 [skip ci] ([1b2c5e7](https://github.com/ipfs/js-stores/commit/1b2c5e78b6c6c42f0bf100574c72789f83998c2c)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 2.1.3 [skip ci] ([c1091f3](https://github.com/ipfs/js-stores/commit/c1091f37cacc826d8f6130a73dec7ea6cea81d2a)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 2.1.4 [skip ci] ([03121dc](https://github.com/ipfs/js-stores/commit/03121dcd4db817b58d7304b179fbeb21d5a18a03)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 2.1.5 [skip ci] ([bf900b9](https://github.com/ipfs/js-stores/commit/bf900b969cd18b9f3e83ff0b87d04f61af7614b0)), closes [#245](https://github.com/ipfs/js-stores/issues/245) [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 2.1.6 [skip ci] ([1ca88ca](https://github.com/ipfs/js-stores/commit/1ca88ca943756ea3bc6a465c3267b1bed2738789)), closes [#274](https://github.com/ipfs/js-stores/issues/274)
+* **release:** 2.1.7 [skip ci] ([191ab3d](https://github.com/ipfs/js-stores/commit/191ab3d3e093ea5b7dd106a6ff66f4a6e01b2568)), closes [#281](https://github.com/ipfs/js-stores/issues/281)
+* **release:** 2.1.8 [skip ci] ([135a09b](https://github.com/ipfs/js-stores/commit/135a09b0ae32beb6a6f51c8239f0800a01e9c95b)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 2.1.9 [skip ci] ([81a54e7](https://github.com/ipfs/js-stores/commit/81a54e73eec48a8a29723ea0a74ce8d7ac17d92e)), closes [#299](https://github.com/ipfs/js-stores/issues/299)
+* **release:** 3.0.0 [skip ci] ([cc92722](https://github.com/ipfs/js-stores/commit/cc9272215453b23b72cec2e43f8de7f18d2ff703)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 3.0.1 [skip ci] ([62dd620](https://github.com/ipfs/js-stores/commit/62dd620a03be88a74844fb1da32c7937542dc689)), closes [#175](https://github.com/ipfs/js-stores/issues/175)
+* **release:** 3.0.1 [skip ci] ([0a73ce9](https://github.com/ipfs/js-stores/commit/0a73ce9d30d77cdb4cfebdaa7f1381668818d39e)), closes [#174](https://github.com/ipfs/js-stores/issues/174) [#175](https://github.com/ipfs/js-stores/issues/175)
+* **release:** 3.0.1 [skip ci] ([d896eec](https://github.com/ipfs/js-stores/commit/d896eec3387e60b47367ed92e10f19914a48fd27)), closes [#174](https://github.com/ipfs/js-stores/issues/174) [#175](https://github.com/ipfs/js-stores/issues/175)
+* **release:** 3.0.1 [skip ci] ([75f3006](https://github.com/ipfs/js-stores/commit/75f3006a4ba7b226b0946902356b27fa264431bb)), closes [#175](https://github.com/ipfs/js-stores/issues/175)
+* **release:** 3.0.2 [skip ci] ([5a24743](https://github.com/ipfs/js-stores/commit/5a2474328c0260060fe965fc88b54eb3a0df931a)), closes [#181](https://github.com/ipfs/js-stores/issues/181)
+* **release:** 3.0.2 [skip ci] ([7c6d0de](https://github.com/ipfs/js-stores/commit/7c6d0de3cb5e329deadc3d9cd5abedfe9fc69d6c)), closes [#181](https://github.com/ipfs/js-stores/issues/181)
+* **release:** 3.0.2 [skip ci] ([09aa693](https://github.com/ipfs/js-stores/commit/09aa693dab68009890665ffa4e95e630a0912c0b)), closes [#181](https://github.com/ipfs/js-stores/issues/181)
+* **release:** 3.0.2 [skip ci] ([4f9fad1](https://github.com/ipfs/js-stores/commit/4f9fad1c48007ee9d761eed7a9b91b05661f95ef)), closes [#181](https://github.com/ipfs/js-stores/issues/181)
+* **release:** 3.0.3 [skip ci] ([20a044d](https://github.com/ipfs/js-stores/commit/20a044d9591612611261f027bef93e707933b9af)), closes [#183](https://github.com/ipfs/js-stores/issues/183)
+* **release:** 3.0.3 [skip ci] ([102a8bd](https://github.com/ipfs/js-stores/commit/102a8bd0662afa6fb38d675bae9c159c431c0151)), closes [#28](https://github.com/ipfs/js-stores/issues/28) [#28](https://github.com/ipfs/js-stores/issues/28) [#27](https://github.com/ipfs/js-stores/issues/27) [#24](https://github.com/ipfs/js-stores/issues/24) [#28](https://github.com/ipfs/js-stores/issues/28) [#28](https://github.com/ipfs/js-stores/issues/28) [#27](https://github.com/ipfs/js-stores/issues/27) [#24](https://github.com/ipfs/js-stores/issues/24) [#183](https://github.com/ipfs/js-stores/issues/183)
+* **release:** 3.0.3 [skip ci] ([88363b0](https://github.com/ipfs/js-stores/commit/88363b0361358e27676263430da496482925d2cf)), closes [#28](https://github.com/ipfs/js-stores/issues/28) [#28](https://github.com/ipfs/js-stores/issues/28) [#27](https://github.com/ipfs/js-stores/issues/27) [#24](https://github.com/ipfs/js-stores/issues/24) [#28](https://github.com/ipfs/js-stores/issues/28) [#28](https://github.com/ipfs/js-stores/issues/28) [#27](https://github.com/ipfs/js-stores/issues/27) [#24](https://github.com/ipfs/js-stores/issues/24) [#28](https://github.com/ipfs/js-stores/issues/28) [#183](https://github.com/ipfs/js-stores/issues/183)
+* **release:** 3.0.4 [skip ci] ([13bc59c](https://github.com/ipfs/js-stores/commit/13bc59c78c4ce5c9dfe13d806ce3fb8d5e1f5e55)), closes [#184](https://github.com/ipfs/js-stores/issues/184)
+* **release:** 3.0.4 [skip ci] ([47ce4d7](https://github.com/ipfs/js-stores/commit/47ce4d7a64db63ae36a2a13ad2999f800f3ec3e9))
+* **release:** 3.0.5 [skip ci] ([62aaee2](https://github.com/ipfs/js-stores/commit/62aaee205159135ea744c7e661a8614ed6c422ac)), closes [#184](https://github.com/ipfs/js-stores/issues/184)
+* **release:** 4.0.0 [skip ci] ([1d1079c](https://github.com/ipfs/js-stores/commit/1d1079c510799cc2f84f4f78730a8cb691f6c2b8)), closes [#189](https://github.com/ipfs/js-stores/issues/189)
+* **release:** 4.0.0 [skip ci] ([756cc83](https://github.com/ipfs/js-stores/commit/756cc8337c5024623f61a5f9c38d13e89b93e989)), closes [#189](https://github.com/ipfs/js-stores/issues/189)
+* **release:** 4.0.0 [skip ci] ([2207d7a](https://github.com/ipfs/js-stores/commit/2207d7a81387bb0c41320bc52cd2c5ed32a44c45)), closes [#182](https://github.com/ipfs/js-stores/issues/182) [#234](https://github.com/ipfs/js-stores/issues/234) [#226](https://github.com/ipfs/js-stores/issues/226) [#234](https://github.com/ipfs/js-stores/issues/234) [#226](https://github.com/ipfs/js-stores/issues/226) [#226](https://github.com/ipfs/js-stores/issues/226)
+* **release:** 4.0.0 [skip ci] ([fd6a8aa](https://github.com/ipfs/js-stores/commit/fd6a8aaecc724daf80bd0f2dfbef29031e5b82fe)), closes [#182](https://github.com/ipfs/js-stores/issues/182) [#183](https://github.com/ipfs/js-stores/issues/183) [#234](https://github.com/ipfs/js-stores/issues/234) [#226](https://github.com/ipfs/js-stores/issues/226) [#234](https://github.com/ipfs/js-stores/issues/234) [#226](https://github.com/ipfs/js-stores/issues/226) [#226](https://github.com/ipfs/js-stores/issues/226)
+* **release:** 4.0.1 [skip ci] ([8e69010](https://github.com/ipfs/js-stores/commit/8e6901010f2600a46cb426a05d0d9b7753f7dc3a)), closes [#184](https://github.com/ipfs/js-stores/issues/184)
+* **release:** 4.0.1 [skip ci] ([e8d30c0](https://github.com/ipfs/js-stores/commit/e8d30c0131016d818c791754ffa587a7d3c13466)), closes [#184](https://github.com/ipfs/js-stores/issues/184)
+* **release:** 4.0.2 [skip ci] ([54f3eee](https://github.com/ipfs/js-stores/commit/54f3eee5aa128c2ef2cde192037fa694dbd7a73a)), closes [#188](https://github.com/ipfs/js-stores/issues/188)
+* **release:** 4.1.0 [skip ci] ([df06919](https://github.com/ipfs/js-stores/commit/df06919855f16d0cdad1892c5ef56af037020f06)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 4.1.0 [skip ci] ([5ed90c4](https://github.com/ipfs/js-stores/commit/5ed90c40e86cae04095fec8624a5c87c51dd0ed5)), closes [#193](https://github.com/ipfs/js-stores/issues/193)
+* **release:** 4.1.1 [skip ci] ([346ee0f](https://github.com/ipfs/js-stores/commit/346ee0fc9ec164586704b861ead4b774aae42ae8)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 4.2.0 [skip ci] ([ceb244c](https://github.com/ipfs/js-stores/commit/ceb244c0bbbcae8b36de36c3617e544c1ff6465c)), closes [#227](https://github.com/ipfs/js-stores/issues/227)
+* **release:** 4.3.0 [skip ci] ([725e0dd](https://github.com/ipfs/js-stores/commit/725e0dd8f7e4c9dfa6857b54f3cf7d97ff3a56e2)), closes [#238](https://github.com/ipfs/js-stores/issues/238)
+* **release:** 4.3.1 [skip ci] ([27f88c0](https://github.com/ipfs/js-stores/commit/27f88c0cf4d6da1e61633b9564305fd8dbbd496a)), closes [#240](https://github.com/ipfs/js-stores/issues/240)
+* **release:** 4.3.10 [skip ci] ([d5bdd95](https://github.com/ipfs/js-stores/commit/d5bdd953e0c6b5ea2f69c68447aa119567abd8db))
+* **release:** 4.3.11 [skip ci] ([6173c27](https://github.com/ipfs/js-stores/commit/6173c27a1a66fd106798f2a41aae2458765ad779)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 4.3.2 [skip ci] ([bad53b9](https://github.com/ipfs/js-stores/commit/bad53b98e5361cb44e24ee057e7d7ad8fcd90c48)), closes [#231](https://github.com/ipfs/js-stores/issues/231)
+* **release:** 4.3.3 [skip ci] ([04510b1](https://github.com/ipfs/js-stores/commit/04510b149e954442a0ff983c0fa6404cff69f794)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 4.3.4 [skip ci] ([d8552a2](https://github.com/ipfs/js-stores/commit/d8552a2181b409990e44a3fa45cc67c2f883a21e)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 4.3.5 [skip ci] ([c961d00](https://github.com/ipfs/js-stores/commit/c961d009857aec77031107e04040aa99bfa7db5b)), closes [#245](https://github.com/ipfs/js-stores/issues/245) [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 4.3.6 [skip ci] ([a67f66a](https://github.com/ipfs/js-stores/commit/a67f66a205b1326ec69335a3b5211421c70cab1e)), closes [#280](https://github.com/ipfs/js-stores/issues/280)
+* **release:** 4.3.7 [skip ci] ([ee2203a](https://github.com/ipfs/js-stores/commit/ee2203a2c7ea14dc73286f58feb5e0af9fb9075c)), closes [#274](https://github.com/ipfs/js-stores/issues/274)
+* **release:** 4.3.8 [skip ci] ([e3ecb03](https://github.com/ipfs/js-stores/commit/e3ecb03a033bc31d1bc6e7950c1612e3ebf3ef30)), closes [#282](https://github.com/ipfs/js-stores/issues/282)
+* **release:** 4.4.0 [skip ci] ([58c48eb](https://github.com/ipfs/js-stores/commit/58c48eba21ad1e54bf4a2e49d95bb2f55e1218d3)), closes [#298](https://github.com/ipfs/js-stores/issues/298)
+* **release:** 4.4.1 [skip ci] ([2e8f8db](https://github.com/ipfs/js-stores/commit/2e8f8db26b07d24ff0f56ce82eb7ce47a918d492)), closes [#303](https://github.com/ipfs/js-stores/issues/303)
+* **release:** 5.0.0 [skip ci] ([225da7e](https://github.com/ipfs/js-stores/commit/225da7ebae152f59d11c125f3adc24d3ef6b6e95)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 5.0.0 [skip ci] ([5230741](https://github.com/ipfs/js-stores/commit/523074172b590f6708f92f2e3f8e94317cf565dc)), closes [#196](https://github.com/ipfs/js-stores/issues/196) [#195](https://github.com/ipfs/js-stores/issues/195)
+* **release:** 5.0.0 [skip ci] ([3d69492](https://github.com/ipfs/js-stores/commit/3d6949202b8bdf1e923429ec9114640e972ffd5f)), closes [#195](https://github.com/ipfs/js-stores/issues/195)
+* **release:** 5.0.0 [skip ci] ([44b12bd](https://github.com/ipfs/js-stores/commit/44b12bd8972607a2907ef25955d5c5732098acf8)), closes [#189](https://github.com/ipfs/js-stores/issues/189)
+* **release:** 5.0.0 [skip ci] ([9c25d3f](https://github.com/ipfs/js-stores/commit/9c25d3fa41a774aae2da985b23309e6248c6bbd9)), closes [#189](https://github.com/ipfs/js-stores/issues/189)
+* **release:** 5.0.1 [skip ci] ([060e74b](https://github.com/ipfs/js-stores/commit/060e74bf4b3ed23b4b223422f871f1ce612e2cb1)), closes [#196](https://github.com/ipfs/js-stores/issues/196)
+* **release:** 5.0.1 [skip ci] ([c1c6add](https://github.com/ipfs/js-stores/commit/c1c6add3474446138939db38f24ebb3cb4922035)), closes [#190](https://github.com/ipfs/js-stores/issues/190)
+* **release:** 5.1.0 [skip ci] ([30735a2](https://github.com/ipfs/js-stores/commit/30735a273af3418c5dae30cf754c1e187abc8184)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 5.1.0 [skip ci] ([a571532](https://github.com/ipfs/js-stores/commit/a5715323a8694dfda7d8ec0411da76fe024a36fc)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 5.1.0 [skip ci] ([e24ce0b](https://github.com/ipfs/js-stores/commit/e24ce0b558d62078617335f5c453106b57693c41)), closes [#193](https://github.com/ipfs/js-stores/issues/193)
+* **release:** 5.1.1 [skip ci] ([2a1d9bd](https://github.com/ipfs/js-stores/commit/2a1d9bda4158ff740e3515f995061e2c531c591f)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 5.1.1 [skip ci] ([146bc5c](https://github.com/ipfs/js-stores/commit/146bc5c87d5376d1d758c2ee3f3f4bdee2e4c267)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 5.1.1 [skip ci] ([9db13e0](https://github.com/ipfs/js-stores/commit/9db13e0435730e3147d2e3bcde301f6bac1563f7))
+* **release:** 5.1.2 [skip ci] ([f32c9a4](https://github.com/ipfs/js-stores/commit/f32c9a46340eee3498967fa918c31d03885ffd91)), closes [#228](https://github.com/ipfs/js-stores/issues/228)
+* **release:** 5.1.2 [skip ci] ([970f81d](https://github.com/ipfs/js-stores/commit/970f81d00f753aed885aceff6ff6abcd9163e69e)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 5.1.3 [skip ci] ([fc95c0f](https://github.com/ipfs/js-stores/commit/fc95c0f555a1e3b02f3875047f2badad3ebc0d43)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 5.1.3 [skip ci] ([a970ceb](https://github.com/ipfs/js-stores/commit/a970ceb4e6cb0531e994b26fc1c9852fca8df897)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 5.1.4 [skip ci] ([596fde8](https://github.com/ipfs/js-stores/commit/596fde8f16f51bc947e3907150e110c4f62d007b)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 5.1.4 [skip ci] ([238872f](https://github.com/ipfs/js-stores/commit/238872fa0c5c09a0f229d851c56cd6a2933951de)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 5.1.5 [skip ci] ([9997757](https://github.com/ipfs/js-stores/commit/9997757101a34dbd61c71841932433296b7f4038)), closes [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 5.1.5 [skip ci] ([980c8c6](https://github.com/ipfs/js-stores/commit/980c8c69001bc2570884bc9574909215de091bc7)), closes [#245](https://github.com/ipfs/js-stores/issues/245) [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 5.1.6 [skip ci] ([3aee60f](https://github.com/ipfs/js-stores/commit/3aee60ff311be560ae1e8b8f5c304d32df926e40))
+* **release:** 5.1.6 [skip ci] ([55c5855](https://github.com/ipfs/js-stores/commit/55c5855091ddc426a68cea22453e58bdee05f808)), closes [#282](https://github.com/ipfs/js-stores/issues/282)
+* **release:** 5.1.7 [skip ci] ([dd7cb8c](https://github.com/ipfs/js-stores/commit/dd7cb8c8c2ab231894462c89ab22e6e37267cdc9))
+* **release:** 5.1.7 [skip ci] ([8f08f7f](https://github.com/ipfs/js-stores/commit/8f08f7f978a9bf8b585d364dddd8cb3e56d85b02))
+* **release:** 5.1.8 [skip ci] ([e151fcd](https://github.com/ipfs/js-stores/commit/e151fcd0938f55ec1b16c51fd25107a23d6a5871)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 5.1.8 [skip ci] ([3494590](https://github.com/ipfs/js-stores/commit/34945900e6f7d29f8998a6674e1049e432d3e64f)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 5.2.0 [skip ci] ([496c177](https://github.com/ipfs/js-stores/commit/496c1770ff96a072655236597d492aab260cacd4)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 5.2.1 [skip ci] ([b40b32e](https://github.com/ipfs/js-stores/commit/b40b32effe26508e62b7b84cbc4ffa9bbcee6753)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 5.2.10 [skip ci] ([235ed35](https://github.com/ipfs/js-stores/commit/235ed35861f17d17b2f042fc63e2981a6335e908)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 5.2.2 [skip ci] ([7d70be5](https://github.com/ipfs/js-stores/commit/7d70be55d69cf988991d9af6bae014066a31f2c2)), closes [#224](https://github.com/ipfs/js-stores/issues/224)
+* **release:** 5.2.3 [skip ci] ([eb59834](https://github.com/ipfs/js-stores/commit/eb59834bfb29a7b61fb361ae2ecc90d3d19b908b)), closes [#228](https://github.com/ipfs/js-stores/issues/228)
+* **release:** 5.2.4 [skip ci] ([20faf4a](https://github.com/ipfs/js-stores/commit/20faf4a68b4560d648cd92fd387b5a40ced37dff)), closes [#231](https://github.com/ipfs/js-stores/issues/231)
+* **release:** 5.2.5 [skip ci] ([0876da6](https://github.com/ipfs/js-stores/commit/0876da6fbf3eb63ba19d1e5e71835342615eba91)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 5.2.6 [skip ci] ([50496de](https://github.com/ipfs/js-stores/commit/50496de5a85abfbfc59003f3e216fe53babb264c)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 5.2.7 [skip ci] ([866b4c5](https://github.com/ipfs/js-stores/commit/866b4c581d110955a07b9c80b4af849f0fc5719f)), closes [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 5.2.9 [skip ci] ([2680073](https://github.com/ipfs/js-stores/commit/2680073d393d2763feaa5c21053fac234097d7c8))
+* **release:** 5.2.9 [skip ci] ([e183a4e](https://github.com/ipfs/js-stores/commit/e183a4ea2ac0b1bd585d6673d80827035e0d8d6e))
+* **release:** 5.3.0 [skip ci] ([49e0618](https://github.com/ipfs/js-stores/commit/49e06180f2061cd6b293596d9d0df76f3d45020e))
+* **release:** 6.0.0 [skip ci] ([2f24f58](https://github.com/ipfs/js-stores/commit/2f24f583138ce3934b020e504c35a276d143456b)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 6.0.0 [skip ci] ([c097d58](https://github.com/ipfs/js-stores/commit/c097d58d0f7ee39aecae9cce0c1bf0069215b6df)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 6.0.0 [skip ci] ([96958c0](https://github.com/ipfs/js-stores/commit/96958c08bf728c536663e569d44011487065f3f7)), closes [#196](https://github.com/ipfs/js-stores/issues/196) [#195](https://github.com/ipfs/js-stores/issues/195)
+* **release:** 6.1.0 [skip ci] ([1d518f6](https://github.com/ipfs/js-stores/commit/1d518f6894a4ebfc8538390b718fb77061a879bd)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 6.1.1 [skip ci] ([d3c1041](https://github.com/ipfs/js-stores/commit/d3c10416f5bab8c067adc7ee714fd2809b34e558)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 6.1.10 [skip ci] ([03fd5d3](https://github.com/ipfs/js-stores/commit/03fd5d3020989157493a95720d85a9ee00e12572)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 6.1.2 [skip ci] ([6d0043c](https://github.com/ipfs/js-stores/commit/6d0043cceaab83a6065d5a287b24394db6db2473)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 6.1.3 [skip ci] ([72b6e10](https://github.com/ipfs/js-stores/commit/72b6e10e7d7f269d98ba1559bf5f96d229430bb9)), closes [#231](https://github.com/ipfs/js-stores/issues/231)
+* **release:** 6.1.4 [skip ci] ([095c274](https://github.com/ipfs/js-stores/commit/095c2740284f75616d7e8086563616959912693a)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 6.1.5 [skip ci] ([11acd12](https://github.com/ipfs/js-stores/commit/11acd12dd420907b52fab24fd4c22607665b8010)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 6.1.6 [skip ci] ([6407f97](https://github.com/ipfs/js-stores/commit/6407f97cf4139841f9dd902a9dfaa6bce30edb80)), closes [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 6.1.7 [skip ci] ([4807b1f](https://github.com/ipfs/js-stores/commit/4807b1f92353320eecef97583eb1d43bf0c1dc4b)), closes [#282](https://github.com/ipfs/js-stores/issues/282)
+* **release:** 6.1.9 [skip ci] ([d446381](https://github.com/ipfs/js-stores/commit/d446381f7b4a391bb249023e534f1c4fd05f1b17))
+* **release:** 7.0.0 [skip ci] ([027cfa6](https://github.com/ipfs/js-stores/commit/027cfa600bd15206dadb53d8e4d3127642bacb57)), closes [#315](https://github.com/ipfs/js-stores/issues/315)
+* **release:** 7.0.1 [skip ci] ([dc879fb](https://github.com/ipfs/js-stores/commit/dc879fb141475fb99a1347f4d511856a30ffd413)), closes [#110](https://github.com/ipfs/js-stores/issues/110) [#175](https://github.com/ipfs/js-stores/issues/175)
+* **release:** 7.0.2 [skip ci] ([bfdc00d](https://github.com/ipfs/js-stores/commit/bfdc00dd598d7d468d4134007b4dafa460eb8a5f)), closes [#181](https://github.com/ipfs/js-stores/issues/181)
+* **release:** 7.0.3 [skip ci] ([6180190](https://github.com/ipfs/js-stores/commit/6180190b98b184ecc5f93afeaeefa4dd628dfc06)), closes [#183](https://github.com/ipfs/js-stores/issues/183)
+* **release:** 7.0.4 [skip ci] ([3430b6c](https://github.com/ipfs/js-stores/commit/3430b6cf00f8512b67dc9034fa22f6355c92197a)), closes [#184](https://github.com/ipfs/js-stores/issues/184)
+* **release:** 8.0.0 [skip ci] ([0d01201](https://github.com/ipfs/js-stores/commit/0d01201d665cde0a5d17cf3c65bc28a1930f536f)), closes [#189](https://github.com/ipfs/js-stores/issues/189)
+* **release:** 8.1.0 [skip ci] ([9ad0ce5](https://github.com/ipfs/js-stores/commit/9ad0ce5e80e653ed9675f80736a1a58a93308f2e)), closes [#193](https://github.com/ipfs/js-stores/issues/193)
+* **release:** 8.1.1 [skip ci] ([40f500b](https://github.com/ipfs/js-stores/commit/40f500be4fd820bdd901bde6a6be2ff1683bb800)), closes [#194](https://github.com/ipfs/js-stores/issues/194)
+* **release:** 8.1.2 [skip ci] ([8c312d3](https://github.com/ipfs/js-stores/commit/8c312d3f9702f307fc180a9289d4f55f141c27a4))
+* **release:** 8.2.0 [skip ci] ([2c6f2ae](https://github.com/ipfs/js-stores/commit/2c6f2ae40a6181d6f33c469f851245755d6bf389)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 8.2.1 [skip ci] ([44d0d5c](https://github.com/ipfs/js-stores/commit/44d0d5c2508638a4f19e7f9a981998879effe92e)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 8.2.10 [skip ci] ([7f26bc8](https://github.com/ipfs/js-stores/commit/7f26bc855e23aebbce19c8f19fc642493aab6298))
+* **release:** 8.2.10 [skip ci] ([a8c793e](https://github.com/ipfs/js-stores/commit/a8c793ed72f3e1442f6ead18361f428f6b698bf8))
+* **release:** 8.2.11 [skip ci] ([15369b7](https://github.com/ipfs/js-stores/commit/15369b79ed3ac75342530757811cc31c22e99631)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 8.2.2 [skip ci] ([3b2280a](https://github.com/ipfs/js-stores/commit/3b2280a3aa56c5a515ea79adfbacb52e88ada113)), closes [#224](https://github.com/ipfs/js-stores/issues/224)
+* **release:** 8.2.3 [skip ci] ([fc2925e](https://github.com/ipfs/js-stores/commit/fc2925e2b39c9093b157e7424232f6cfac968ad6)), closes [#228](https://github.com/ipfs/js-stores/issues/228)
+* **release:** 8.2.4 [skip ci] ([7d4b28e](https://github.com/ipfs/js-stores/commit/7d4b28ef254a73906c9d05665752c413e6791c96)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 8.2.5 [skip ci] ([d440496](https://github.com/ipfs/js-stores/commit/d4404969ce7db0846ee986c6f66ce6c424f8f309)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 8.2.6 [skip ci] ([49d9e86](https://github.com/ipfs/js-stores/commit/49d9e868d6ae990df38d93cf71895b540ff24106)), closes [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 8.2.7 [skip ci] ([becf59f](https://github.com/ipfs/js-stores/commit/becf59fe0849f29644906bc1fe06409a7c3513ef)), closes [#269](https://github.com/ipfs/js-stores/issues/269)
+* **release:** 8.2.8 [skip ci] ([23fbc88](https://github.com/ipfs/js-stores/commit/23fbc88fb73114e3999feddc397b3c349941bbc8)), closes [#282](https://github.com/ipfs/js-stores/issues/282)
+* **release:** 8.2.9 [skip ci] ([7dad9a4](https://github.com/ipfs/js-stores/commit/7dad9a43fdec367895467752a6fee3ac7f912ca4)), closes [#283](https://github.com/ipfs/js-stores/issues/283)
+* **release:** 8.3.0 [skip ci] ([63d45ec](https://github.com/ipfs/js-stores/commit/63d45ec246c5607157334631a44ee09b24bf1c39))
+* **release:** 9.1.0 [skip ci] ([d39c6a9](https://github.com/ipfs/js-stores/commit/d39c6a92ffc8bbc5ae9790abfed9ce7f6fde6c68)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 9.1.0 [skip ci] ([228bd8b](https://github.com/ipfs/js-stores/commit/228bd8b63f4da1169cfb395bd9d483359ee8be56)), closes [#197](https://github.com/ipfs/js-stores/issues/197)
+* **release:** 9.1.1 [skip ci] ([7c7f97a](https://github.com/ipfs/js-stores/commit/7c7f97ab4d2b138dcb30dfaccec300ce5ca8281a)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 9.1.1 [skip ci] ([aa3a63f](https://github.com/ipfs/js-stores/commit/aa3a63ffeca74634f7ba279aff93d7dd981d92aa)), closes [#200](https://github.com/ipfs/js-stores/issues/200) [#213](https://github.com/ipfs/js-stores/issues/213)
+* **release:** 9.1.2 [skip ci] ([842bdc4](https://github.com/ipfs/js-stores/commit/842bdc4832c526d9b6411f40781bee6a46c9fe49)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 9.1.2 [skip ci] ([2ebd1ad](https://github.com/ipfs/js-stores/commit/2ebd1ad5f71a109661a0cb30785960abe1c0c810)), closes [#225](https://github.com/ipfs/js-stores/issues/225)
+* **release:** 9.1.3 [skip ci] ([4279b47](https://github.com/ipfs/js-stores/commit/4279b4706685d79fe23e680dcef6b32fc0ae24fb)), closes [#232](https://github.com/ipfs/js-stores/issues/232)
+* **release:** 9.1.4 [skip ci] ([bcf6004](https://github.com/ipfs/js-stores/commit/bcf6004fe818fa9c24a18aa8eddc1ac4aaae51d7)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 9.1.5 [skip ci] ([050210c](https://github.com/ipfs/js-stores/commit/050210c977afd46e2cac161f21d46fb6d3fee88c)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 9.1.6 [skip ci] ([e11f15f](https://github.com/ipfs/js-stores/commit/e11f15feebcd31a7638004463b9a2fb2225bbeb2)), closes [#245](https://github.com/ipfs/js-stores/issues/245) [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 9.1.7 [skip ci] ([87681d2](https://github.com/ipfs/js-stores/commit/87681d2e21238c2d9f4d9127ba2c45cdb59dfc8f))
+* **release:** 9.1.8 [skip ci] ([0d41afa](https://github.com/ipfs/js-stores/commit/0d41afa8a6da0cfc1853e8d54debce115a3f8b0d)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 9.1.9 [skip ci] ([e860279](https://github.com/ipfs/js-stores/commit/e8602799bf6cb8082fc75717bc4a3e86801c033a)), closes [#306](https://github.com/ipfs/js-stores/issues/306)
+* **release:** 9.2.0 [skip ci] ([05f253f](https://github.com/ipfs/js-stores/commit/05f253f7b14a5002be9f153847d081080d3875cb)), closes [#227](https://github.com/ipfs/js-stores/issues/227)
+* **release:** 9.2.1 [skip ci] ([caf7841](https://github.com/ipfs/js-stores/commit/caf78416f32857edd965872994745a5ccf13545d)), closes [#240](https://github.com/ipfs/js-stores/issues/240)
+* **release:** 9.2.2 [skip ci] ([23df262](https://github.com/ipfs/js-stores/commit/23df262439ee6fa1eb9b02ada314995306a309df)), closes [#241](https://github.com/ipfs/js-stores/issues/241)
+* **release:** 9.2.3 [skip ci] ([01898e5](https://github.com/ipfs/js-stores/commit/01898e50f354eae9b1e7baaabbbd600ce42f294a)), closes [#244](https://github.com/ipfs/js-stores/issues/244)
+* **release:** 9.2.4 [skip ci] ([b0073e2](https://github.com/ipfs/js-stores/commit/b0073e21997cac333c8237f31f414dc0dfc5d5fd)), closes [#245](https://github.com/ipfs/js-stores/issues/245) [#268](https://github.com/ipfs/js-stores/issues/268)
+* **release:** 9.2.5 [skip ci] ([be4f27d](https://github.com/ipfs/js-stores/commit/be4f27d0eefaa873382f2b01bcd298b592197834)), closes [#280](https://github.com/ipfs/js-stores/issues/280)
+* **release:** 9.2.6 [skip ci] ([c8e42f3](https://github.com/ipfs/js-stores/commit/c8e42f352feeae2aeeb586bdfdaef325fd820218)), closes [#282](https://github.com/ipfs/js-stores/issues/282)
+* **release:** 9.2.7 [skip ci] ([44d2d0e](https://github.com/ipfs/js-stores/commit/44d2d0e01865a2a6007f7c71f6c30d0712c9ea8f))
+* **release:** 9.2.8 [skip ci] ([330060a](https://github.com/ipfs/js-stores/commit/330060abc34512047961f9f585154d23480e355a)), closes [#297](https://github.com/ipfs/js-stores/issues/297)
+* **release:** 9.2.9 [skip ci] ([9d1f29e](https://github.com/ipfs/js-stores/commit/9d1f29e6e5fce22399a3a05440dac225138ca6ab)), closes [#236](https://github.com/ipfs/js-stores/issues/236) [#236](https://github.com/ipfs/js-stores/issues/236)
+* remove / from CID prefix query ([b07aa1d](https://github.com/ipfs/js-stores/commit/b07aa1ddc46b7f44f6827df306a4d4fb200b0b26))
+* remove lerna ([#183](https://github.com/ipfs/js-stores/issues/183)) ([04e77ec](https://github.com/ipfs/js-stores/commit/04e77ec37ca5857b6156dd211f07a61eddcf19b0))
+* rename master to main ([#200](https://github.com/ipfs/js-stores/issues/200)) ([f85d719](https://github.com/ipfs/js-stores/commit/f85d719b711cd60237bdaa6a0bcd418e69a98598))
+* revert ([2c8d1a2](https://github.com/ipfs/js-stores/commit/2c8d1a25194989410326f3cedd65f94aa3b28ed5))
+* switch to ESM ([#39](https://github.com/ipfs/js-stores/issues/39)) ([c04aa80](https://github.com/ipfs/js-stores/commit/c04aa80d48a84b681962cae227dd2628e7d35cb5))
+* Update .github/workflows/stale.yml [skip ci] ([5d78301](https://github.com/ipfs/js-stores/commit/5d783010c8e1919561614fd6612c65a0c610ec29))
+* Update .github/workflows/stale.yml [skip ci] ([d6e5dd6](https://github.com/ipfs/js-stores/commit/d6e5dd67f60524a450563b8b66ed44c0016a9c09))
+* Update .github/workflows/stale.yml [skip ci] ([f4ff277](https://github.com/ipfs/js-stores/commit/f4ff277aa3cebd33e41c115e3bb4f4d0f859d210))
+* Update .github/workflows/stale.yml [skip ci] ([35e23f1](https://github.com/ipfs/js-stores/commit/35e23f14d84fe9e52b72ea63546a0926bf83edf8))
+* Update .github/workflows/stale.yml [skip ci] ([9d285a1](https://github.com/ipfs/js-stores/commit/9d285a11bbeae5f84f0845b13b7d71ab65a83771))
+* update aegir ([#68](https://github.com/ipfs/js-stores/issues/68)) ([56593d4](https://github.com/ipfs/js-stores/commit/56593d4eed78b918c09d8a96359ec3100f5f4608))
+* update config ([c6d9c09](https://github.com/ipfs/js-stores/commit/c6d9c09a1199c02e7b8be859bc5f71849b3ac85a))
+* update multiformats ([755788e](https://github.com/ipfs/js-stores/commit/755788e78cfaa4faec2bbf2ee6bdafcf20de97c2))
+* update package config ([5998ec2](https://github.com/ipfs/js-stores/commit/5998ec2776132919c24d2a855c22662f1494a191))
+* update sibling dependencies ([a4fb1c5](https://github.com/ipfs/js-stores/commit/a4fb1c5f97650d6ee80084e8c59c7a081f9a09e0))
+* update sibling dependencies ([7a15bcd](https://github.com/ipfs/js-stores/commit/7a15bcdb47bcade4d205fc04b4ffdfd3a1220f11))
+* update sibling dependencies ([65dccef](https://github.com/ipfs/js-stores/commit/65dccef376a9eb140ce0cef5b18e02c8515ab698))
+* update sibling dependencies ([66506a8](https://github.com/ipfs/js-stores/commit/66506a8313894bd65bb30d2015b8e9a65d212746))
+* update uint8arrays ([#28](https://github.com/ipfs/js-stores/issues/28)) ([b1427cd](https://github.com/ipfs/js-stores/commit/b1427cd2771b350ac532750d008442de90c4cf2d))
+
+### Documentation
+
+* fix capitalization in readme of datastore-fs. ([#232](https://github.com/ipfs/js-stores/issues/232)) ([01492bf](https://github.com/ipfs/js-stores/commit/01492bfc90ab3025ff81f098a9bb7e60475be196))
+* fix capitalization of import ([#226](https://github.com/ipfs/js-stores/issues/226)) ([837221a](https://github.com/ipfs/js-stores/commit/837221aff3ef4d217063eb17953aff03764e7600))
+* fix interface-tests readme usage ([#247](https://github.com/ipfs/js-stores/issues/247)) ([e179933](https://github.com/ipfs/js-stores/commit/e179933277b589cf442a372392138067bb2df44b))
+* publish api docs ([#181](https://github.com/ipfs/js-stores/issues/181)) ([64f8473](https://github.com/ipfs/js-stores/commit/64f8473a1d646eda431972afb489ac81d23248fa))
+* remove duplicate readme section ([851a110](https://github.com/ipfs/js-stores/commit/851a11033140e7ae0996adeaf880d6554d12837c))
+* update api docs ([#244](https://github.com/ipfs/js-stores/issues/244)) ([e0f6145](https://github.com/ipfs/js-stores/commit/e0f614575d675fe4db2ab30ea6a2a854e892d635))
+* Update Blockstore and Datastore implementation lists ([#224](https://github.com/ipfs/js-stores/issues/224)) ([ab3b31b](https://github.com/ipfs/js-stores/commit/ab3b31b5ae2dba4b5ddb4b79740afb7c003aedae))
+* update datastore core readme and package config ([#245](https://github.com/ipfs/js-stores/issues/245)) ([c08d29a](https://github.com/ipfs/js-stores/commit/c08d29ab18ddea26a1d9dd73d673847469d28a13))
+
+### Dependencies
+
+* bump @libp2p/logger from 2.1.1 to 3.0.0 ([#240](https://github.com/ipfs/js-stores/issues/240)) ([cc958ef](https://github.com/ipfs/js-stores/commit/cc958ef7ebca61a5355cfa2bc18769e374d76ae6))
+* bump @libp2p/logger from 3.1.0 to 4.0.1 ([#280](https://github.com/ipfs/js-stores/issues/280)) ([ab4731f](https://github.com/ipfs/js-stores/commit/ab4731f49a1a6f9163fb9c246121b3392503ba8b))
+* bump aegir from 37.12.1 to 38.1.0 ([#184](https://github.com/ipfs/js-stores/issues/184)) ([c8ab418](https://github.com/ipfs/js-stores/commit/c8ab418db835a6beefbb44c3ba9176779cebcd0d))
+* bump aegir from 38.1.8 to 39.0.9 ([#225](https://github.com/ipfs/js-stores/issues/225)) ([d0f301b](https://github.com/ipfs/js-stores/commit/d0f301b1243a0f4f692011449567b51b2706e70f))
+* bump idb from 7.1.1 to 8.0.0 ([#281](https://github.com/ipfs/js-stores/issues/281)) ([4d0bdbc](https://github.com/ipfs/js-stores/commit/4d0bdbc600b226c489259e5100af5c8c7031fb79))
+* bump it-all from 1.0.6 to 2.0.0 ([#177](https://github.com/ipfs/js-stores/issues/177)) ([b648877](https://github.com/ipfs/js-stores/commit/b648877c5afb625c7d1e13efd3e0f72d125de734)), closes [#28](https://github.com/ipfs/js-stores/issues/28) [#28](https://github.com/ipfs/js-stores/issues/28) [#27](https://github.com/ipfs/js-stores/issues/27) [#24](https://github.com/ipfs/js-stores/issues/24)
+* bump it-drain from 1.0.5 to 2.0.0 ([#178](https://github.com/ipfs/js-stores/issues/178)) ([73e4cfc](https://github.com/ipfs/js-stores/commit/73e4cfcf41178fe6e27f0c7b431fb9511e1dda47)), closes [#28](https://github.com/ipfs/js-stores/issues/28) [#28](https://github.com/ipfs/js-stores/issues/28) [#27](https://github.com/ipfs/js-stores/issues/27) [#24](https://github.com/ipfs/js-stores/issues/24)
+* bump it-glob from 2.0.7 to 3.0.1 ([#306](https://github.com/ipfs/js-stores/issues/306)) ([8f6313f](https://github.com/ipfs/js-stores/commit/8f6313f8a22cb537aeeac2a048aad644d3c9a7d2))
+* bump it-length from 1.0.4 to 2.0.0 ([#179](https://github.com/ipfs/js-stores/issues/179)) ([d1919b4](https://github.com/ipfs/js-stores/commit/d1919b40f4ec7ec0a20e0283d063e8b030ddc875)), closes [#28](https://github.com/ipfs/js-stores/issues/28)
+* bump lerna from 5.6.2 to 6.0.0 ([#176](https://github.com/ipfs/js-stores/issues/176)) ([e583cce](https://github.com/ipfs/js-stores/commit/e583cced412e675b49bcbb9dad3010cf0d55f7b5))
+* bump multiformats from 10.0.3 to 11.0.0 ([#182](https://github.com/ipfs/js-stores/issues/182)) ([2342b17](https://github.com/ipfs/js-stores/commit/2342b170dd69b1e055c6eda07cdd4e07ed1f9a4c)), closes [#234](https://github.com/ipfs/js-stores/issues/234) [#226](https://github.com/ipfs/js-stores/issues/226) [#234](https://github.com/ipfs/js-stores/issues/234) [#226](https://github.com/ipfs/js-stores/issues/226) [#226](https://github.com/ipfs/js-stores/issues/226)
+* bump multiformats from 11.0.2 to 12.0.1 ([#231](https://github.com/ipfs/js-stores/issues/231)) ([93b7c13](https://github.com/ipfs/js-stores/commit/93b7c13d0dd0508b04bae2ac5a9fb9c265fc5589))
+* bump multiformats from 12.1.3 to 13.0.0 ([#286](https://github.com/ipfs/js-stores/issues/286)) ([c8ccd1d](https://github.com/ipfs/js-stores/commit/c8ccd1de91883d1a1cbd394c21a51b021d52baa3))
+* bump multiformats from 9.9.0 to 10.0.0 ([#174](https://github.com/ipfs/js-stores/issues/174)) ([2a4f529](https://github.com/ipfs/js-stores/commit/2a4f529e4a4087fb048b337fbaeedffb939f2ebd))
+* bump nanoid from 4.0.2 to 5.0.3 ([#269](https://github.com/ipfs/js-stores/issues/269)) ([02cb8cd](https://github.com/ipfs/js-stores/commit/02cb8cd82de4174e7c417ea7e45ef7111f38e990))
+* bump uint8arrays from 3.0.0 to 4.0.1 ([#175](https://github.com/ipfs/js-stores/issues/175)) ([e8d5ea6](https://github.com/ipfs/js-stores/commit/e8d5ea63feaaaf379890171f4660bfd8f1cfef5e))
+* bump uint8arrays from 4.0.10 to 5.0.0 ([#282](https://github.com/ipfs/js-stores/issues/282)) ([2cbfd52](https://github.com/ipfs/js-stores/commit/2cbfd52257e9358786962d94e144df9583a45c30))
+* **dev:** bump aegir from 39.0.13 to 40.0.8 ([#241](https://github.com/ipfs/js-stores/issues/241)) ([00741ff](https://github.com/ipfs/js-stores/commit/00741ff043b40cf10ecc185665fcb705160c9877))
+* **dev:** bump aegir from 40.0.13 to 41.1.9 ([#268](https://github.com/ipfs/js-stores/issues/268)) ([0aa0944](https://github.com/ipfs/js-stores/commit/0aa0944d42798d1f6fd589e8a58de7d791760644))
+* **dev:** bump aegir from 42.2.11 to 44.1.0 ([#316](https://github.com/ipfs/js-stores/issues/316)) ([581a467](https://github.com/ipfs/js-stores/commit/581a46720832916bea11efa2476eb85a00bae9d4))
+* **dev:** bump sinon from 15.2.0 to 17.0.1 ([#265](https://github.com/ipfs/js-stores/issues/265)) ([316d3c5](https://github.com/ipfs/js-stores/commit/316d3c54c3a113a8deebc8e53480ac38d40f3a41))
+* **dev:** bump sinon from 17.0.2 to 18.0.0 ([#308](https://github.com/ipfs/js-stores/issues/308)) ([0fbfe11](https://github.com/ipfs/js-stores/commit/0fbfe1112a102055d75f077ff799fbb1001e6aa7))
+* update all it-* deps ([#213](https://github.com/ipfs/js-stores/issues/213)) ([e963497](https://github.com/ipfs/js-stores/commit/e963497fdb33e61e2fe702866abbd42fba648fee))
+* update sibling dependencies ([7c84601](https://github.com/ipfs/js-stores/commit/7c84601df3a17b5e163de68b224c0efef5d5b746))
+* update sibling dependencies ([5ac1112](https://github.com/ipfs/js-stores/commit/5ac1112fd613ef8cb66265ee7b6c89c368bcd0f7))
+* update sibling dependencies ([9adf0bc](https://github.com/ipfs/js-stores/commit/9adf0bc4c1b63ef0ae06ab5cb2f3dc19d83bc1a7))
+* update sibling dependencies ([8f7928c](https://github.com/ipfs/js-stores/commit/8f7928c28b5869001728cc997f0204a40f51978d))
+* update sibling dependencies ([bbfb89c](https://github.com/ipfs/js-stores/commit/bbfb89cbae37e0442df774e4dab63399c1e76d15))
+* update sibling dependencies ([dae86fd](https://github.com/ipfs/js-stores/commit/dae86fd39a133969cd4355fb1e7099a560a75baa))
+* update sibling dependencies ([713c9a4](https://github.com/ipfs/js-stores/commit/713c9a4bda345f488c273b3d55959fb47e9420ed))
+* update sibling dependencies ([94dec57](https://github.com/ipfs/js-stores/commit/94dec576ae4c259f5bd10c811f1d57785445beab))
+* update sibling dependencies ([9aedadd](https://github.com/ipfs/js-stores/commit/9aedadd99b72768124ef4b7f3640f0b6527e55ca))
+* update sibling dependencies ([79100b3](https://github.com/ipfs/js-stores/commit/79100b3fd4a7f88e18a09976e194e8461869b92f))
diff --git a/FUNDING.json b/FUNDING.json
new file mode 100644
index 00000000..9085792a
--- /dev/null
+++ b/FUNDING.json
@@ -0,0 +1,5 @@
+{
+ "opRetro": {
+ "projectId": "0x7f330267969cf845a983a9d4e7b7dbcca5c700a5191269af377836d109e0bb69"
+ }
+}
diff --git a/README.md b/README.md
index 1dd9ec84..ea6b756e 100644
--- a/README.md
+++ b/README.md
@@ -9,21 +9,21 @@
# Packages
-- [`/packages/blockstore-core`](./packages/blockstore-core) Contains various implementations of the API contract described in interface-blockstore
-- [`/packages/blockstore-fs`](./packages/blockstore-fs) Blockstore implementation with file system backend
-- [`/packages/blockstore-idb`](./packages/blockstore-idb) Blockstore implementation with IndexedDB backend
-- [`/packages/blockstore-level`](./packages/blockstore-level) Blockstore implementation with level(up|down) backend
-- [`/packages/blockstore-s3`](./packages/blockstore-s3) IPFS blockstore implementation backed by s3
-- [`/packages/datastore-core`](./packages/datastore-core) Wrapper implementation for interface-datastore
-- [`/packages/datastore-fs`](./packages/datastore-fs) Datastore implementation with file system backend
-- [`/packages/datastore-idb`](./packages/datastore-idb) Datastore implementation with IndexedDB backend.
-- [`/packages/datastore-level`](./packages/datastore-level) Datastore implementation with level(up|down) backend
-- [`/packages/datastore-s3`](./packages/datastore-s3) IPFS datastore implementation backed by s3
-- [`/packages/interface-blockstore`](./packages/interface-blockstore) An interface for storing and retrieving blocks
-- [`/packages/interface-blockstore-tests`](./packages/interface-blockstore-tests) Compliance tests for the blockstore interface
-- [`/packages/interface-datastore`](./packages/interface-datastore) datastore interface
-- [`/packages/interface-datastore-tests`](./packages/interface-datastore-tests) Compliance tests for the datastore interface
-- [`/packages/interface-store`](./packages/interface-store) A generic interface for storing and retrieving data
+- [`packages/blockstore-core`](https://github.com/ipfs/js-stores/tree/main/packages/blockstore-core) Contains various implementations of the API contract described in interface-blockstore
+- [`packages/blockstore-fs`](https://github.com/ipfs/js-stores/tree/main/packages/blockstore-fs) Blockstore implementation with file system backend
+- [`packages/blockstore-idb`](https://github.com/ipfs/js-stores/tree/main/packages/blockstore-idb) Blockstore implementation with IndexedDB backend
+- [`packages/blockstore-level`](https://github.com/ipfs/js-stores/tree/main/packages/blockstore-level) Blockstore implementation with level(up|down) backend
+- [`packages/blockstore-s3`](https://github.com/ipfs/js-stores/tree/main/packages/blockstore-s3) IPFS blockstore implementation backed by s3
+- [`packages/datastore-core`](https://github.com/ipfs/js-stores/tree/main/packages/datastore-core) Wrapper implementation for interface-datastore
+- [`packages/datastore-fs`](https://github.com/ipfs/js-stores/tree/main/packages/datastore-fs) Datastore implementation with file system backend
+- [`packages/datastore-idb`](https://github.com/ipfs/js-stores/tree/main/packages/datastore-idb) Datastore implementation with IndexedDB backend.
+- [`packages/datastore-level`](https://github.com/ipfs/js-stores/tree/main/packages/datastore-level) Datastore implementation with level(up|down) backend
+- [`packages/datastore-s3`](https://github.com/ipfs/js-stores/tree/main/packages/datastore-s3) IPFS datastore implementation backed by s3
+- [`packages/interface-blockstore`](https://github.com/ipfs/js-stores/tree/main/packages/interface-blockstore) An interface for storing and retrieving blocks
+- [`packages/interface-blockstore-tests`](https://github.com/ipfs/js-stores/tree/main/packages/interface-blockstore-tests) Compliance tests for the blockstore interface
+- [`packages/interface-datastore`](https://github.com/ipfs/js-stores/tree/main/packages/interface-datastore) datastore interface
+- [`packages/interface-datastore-tests`](https://github.com/ipfs/js-stores/tree/main/packages/interface-datastore-tests) Compliance tests for the datastore interface
+- [`packages/interface-store`](https://github.com/ipfs/js-stores/tree/main/packages/interface-store) A generic interface for storing and retrieving data
# API Docs
@@ -33,8 +33,8 @@
Licensed under either of
-- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / )
-- MIT ([LICENSE-MIT](LICENSE-MIT) / )
+- Apache 2.0, ([LICENSE-APACHE](https://github.com/ipfs/js-stores/blob/main/LICENSE-APACHE) / )
+- MIT ([LICENSE-MIT](https://github.com/ipfs/js-stores/blob/main/LICENSE-MIT) / )
# Contribute
diff --git a/package.json b/package.json
index f6902bd1..83e8670d 100644
--- a/package.json
+++ b/package.json
@@ -12,91 +12,6 @@
"url": "https://github.com/ipfs/js-stores/issues"
},
"private": true,
- "release": {
- "branches": [
- "main"
- ],
- "plugins": [
- [
- "@semantic-release/commit-analyzer",
- {
- "preset": "conventionalcommits",
- "releaseRules": [
- {
- "breaking": true,
- "release": "major"
- },
- {
- "revert": true,
- "release": "patch"
- },
- {
- "type": "feat",
- "release": "minor"
- },
- {
- "type": "fix",
- "release": "patch"
- },
- {
- "type": "docs",
- "release": "patch"
- },
- {
- "type": "test",
- "release": "patch"
- },
- {
- "type": "deps",
- "release": "patch"
- },
- {
- "scope": "no-release",
- "release": false
- }
- ]
- }
- ],
- [
- "@semantic-release/release-notes-generator",
- {
- "preset": "conventionalcommits",
- "presetConfig": {
- "types": [
- {
- "type": "feat",
- "section": "Features"
- },
- {
- "type": "fix",
- "section": "Bug Fixes"
- },
- {
- "type": "chore",
- "section": "Trivial Changes"
- },
- {
- "type": "docs",
- "section": "Documentation"
- },
- {
- "type": "deps",
- "section": "Dependencies"
- },
- {
- "type": "test",
- "section": "Tests"
- }
- ]
- }
- }
- ],
- "@semantic-release/changelog",
- "@semantic-release/npm",
- "@semantic-release/github",
- "@semantic-release/git"
- ]
- },
"scripts": {
"reset": "aegir run clean && aegir clean **/node_modules **/package-lock.json",
"test": "aegir run test",
@@ -113,12 +28,12 @@
"lint": "aegir run lint",
"dep-check": "aegir run dep-check",
"release": "run-s build docs:no-publish npm:release docs",
- "npm:release": "aegir release",
+ "npm:release": "aegir run release --concurrency 1",
"docs": "aegir docs",
"docs:no-publish": "aegir docs --publish false"
},
"devDependencies": {
- "aegir": "^42.2.3",
+ "aegir": "^47.0.16",
"npm-run-all": "^4.1.5"
},
"workspaces": [
diff --git a/packages/blockstore-core/CHANGELOG.md b/packages/blockstore-core/CHANGELOG.md
index 879349c9..0a2ea7d7 100644
--- a/packages/blockstore-core/CHANGELOG.md
+++ b/packages/blockstore-core/CHANGELOG.md
@@ -1,3 +1,91 @@
+## [blockstore-core-v6.1.2](https://github.com/ipfs/js-stores/compare/blockstore-core-6.1.1...blockstore-core-6.1.2) (2026-01-08)
+
+### Bug Fixes
+
+* identity supports async get and getAll ([#365](https://github.com/ipfs/js-stores/issues/365)) ([a1b95fc](https://github.com/ipfs/js-stores/commit/a1b95fc173c066d69bf0f1145d7b458941065be6))
+
+## [blockstore-core-v6.1.1](https://github.com/ipfs/js-stores/compare/blockstore-core-6.1.0...blockstore-core-6.1.1) (2025-10-09)
+
+### Bug Fixes
+
+* update error name ([304ec71](https://github.com/ipfs/js-stores/commit/304ec7142b16ad0cd70537d48eb69294faacffe5))
+
+## [blockstore-core-v6.1.0](https://github.com/ipfs/js-stores/compare/blockstore-core-6.0.2...blockstore-core-6.1.0) (2025-10-09)
+
+### Features
+
+* enforce max digest length ([#360](https://github.com/ipfs/js-stores/issues/360)) ([c5b039a](https://github.com/ipfs/js-stores/commit/c5b039ae248cce82bf02fbf0383da8e65e140786))
+
+## [blockstore-core-v6.0.2](https://github.com/ipfs/js-stores/compare/blockstore-core-6.0.1...blockstore-core-6.0.2) (2025-10-03)
+
+### Dependencies
+
+* bump level from 8.0.1 to 10.0.0 ([#356](https://github.com/ipfs/js-stores/issues/356)) ([c0ec61f](https://github.com/ipfs/js-stores/commit/c0ec61fe965e3bad9d607a0bd3a3c750f00f41d0))
+
+## [blockstore-core-v6.0.1](https://github.com/ipfs/js-stores/compare/blockstore-core-6.0.0...blockstore-core-6.0.1) (2025-10-03)
+
+### Bug Fixes
+
+* update sibling deps ([3f73b3d](https://github.com/ipfs/js-stores/commit/3f73b3d53ea2d86d0f5c3f06785c0bfc30e8b5e9))
+
+## [blockstore-core-v6.0.0](https://github.com/ipfs/js-stores/compare/blockstore-core-5.0.4...blockstore-core-6.0.0) (2025-10-03)
+
+### ⚠ BREAKING CHANGES
+
+* blockstore.get and similar now return streams of bytes
+
+### Features
+
+* streaming blockstores ([#358](https://github.com/ipfs/js-stores/issues/358)) ([4dbb136](https://github.com/ipfs/js-stores/commit/4dbb1362d20fc87fcdd261568dca297972f9bc08))
+
+### Dependencies
+
+* bump @libp2p/logger ([#359](https://github.com/ipfs/js-stores/issues/359)) ([edb5a1f](https://github.com/ipfs/js-stores/commit/edb5a1f8b575a27ad28bc2e1c4e4d52e1f114ebc))
+
+## [blockstore-core-v5.0.4](https://github.com/ipfs/js-stores/compare/blockstore-core-5.0.3...blockstore-core-5.0.4) (2025-05-28)
+
+### Bug Fixes
+
+* improve abort signal support ([#350](https://github.com/ipfs/js-stores/issues/350)) ([e17d770](https://github.com/ipfs/js-stores/commit/e17d770cc2fcee77cb0152a855abf162e5a91a99))
+
+## [blockstore-core-v5.0.3](https://github.com/ipfs/js-stores/compare/blockstore-core-5.0.2...blockstore-core-5.0.3) (2025-05-26)
+
+### Dependencies
+
+* bump aegir from 44.1.4 to 47.0.16 ([#349](https://github.com/ipfs/js-stores/issues/349)) ([d33d15f](https://github.com/ipfs/js-stores/commit/d33d15f0638856530d0e1868c723e5567abf27e6))
+
+## [blockstore-core-v5.0.2](https://github.com/ipfs/js-stores/compare/blockstore-core-5.0.1...blockstore-core-5.0.2) (2024-09-13)
+
+### Bug Fixes
+
+* restore release config to package.json ([#321](https://github.com/ipfs/js-stores/issues/321)) ([4f14fb0](https://github.com/ipfs/js-stores/commit/4f14fb09d65a3460b548b59557af108412dc9156))
+
+## blockstore-core [5.0.0](https://github.com/ipfs/js-stores/compare/blockstore-core-4.4.1...blockstore-core-5.0.0) (2024-08-02)
+
+
+### ⚠ BREAKING CHANGES
+
+* To detect the type of error thrown, use `.name` instead of `.code`
+
+### Features
+
+* use `.name` property for errors instead of `.code` ([#315](https://github.com/ipfs/js-stores/issues/315)) ([dacd6ce](https://github.com/ipfs/js-stores/commit/dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd))
+
+
+
+### Dependencies
+
+* **interface-blockstore:** upgraded to 5.3.0
+* **interface-store:** upgraded to 6.0.0
+* **interface-blockstore-tests:** upgraded to 7.0.0
+
+## blockstore-core [4.4.1](https://github.com/ipfs/js-stores/compare/blockstore-core-4.4.0...blockstore-core-4.4.1) (2024-04-09)
+
+
+### Bug Fixes
+
+* identity blockstore should wrap child ([#303](https://github.com/ipfs/js-stores/issues/303)) ([3d84dd0](https://github.com/ipfs/js-stores/commit/3d84dd0ab164fb5749c34487a217c763d1d09ccb))
+
## blockstore-core [4.4.0](https://github.com/ipfs/js-stores/compare/blockstore-core-4.3.11...blockstore-core-4.4.0) (2024-02-12)
diff --git a/packages/blockstore-core/CODE_OF_CONDUCT.md b/packages/blockstore-core/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..6b0fa54c
--- /dev/null
+++ b/packages/blockstore-core/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Contributor Code of Conduct
+
+This project follows the [`IPFS Community Code of Conduct`](https://github.com/ipfs/community/blob/master/code-of-conduct.md)
diff --git a/packages/blockstore-core/LICENSE b/packages/blockstore-core/LICENSE
deleted file mode 100644
index 20ce483c..00000000
--- a/packages/blockstore-core/LICENSE
+++ /dev/null
@@ -1,4 +0,0 @@
-This project is dual licensed under MIT and Apache-2.0.
-
-MIT: https://www.opensource.org/licenses/mit
-Apache-2.0: https://www.apache.org/licenses/license-2.0
diff --git a/packages/blockstore-core/LICENSE-APACHE b/packages/blockstore-core/LICENSE-APACHE
index 14478a3b..b09cd785 100644
--- a/packages/blockstore-core/LICENSE-APACHE
+++ b/packages/blockstore-core/LICENSE-APACHE
@@ -1,5 +1,201 @@
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-http://www.apache.org/licenses/LICENSE-2.0
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/blockstore-core/README.md b/packages/blockstore-core/README.md
index 94943a86..166d6902 100644
--- a/packages/blockstore-core/README.md
+++ b/packages/blockstore-core/README.md
@@ -9,14 +9,29 @@
# About
+
+
Various Blockstore implementations are available.
## Implementations
-- Base: [`src/base`](src/base.ts)
-- Memory: [`src/memory`](src/memory.ts)
-- BlackHole: ['src/black-hole](src/black-hole.ts)
-- Tiered: ['src/tiered](src/tiered.ts)
+- Base: [`src/base`](./src/base.ts)
+- Memory: [`src/memory`](./src/memory.ts)
+- BlackHole: ['src/black-hole](./src/black-hole.ts)
+- Tiered: ['src/tiered](./src/tiered.ts)
## Example - BaseBlockstore
@@ -97,7 +112,7 @@ $ npm i blockstore-core
## Browser `
@@ -111,8 +126,8 @@ Loading this module through a script tag will make it's exports available as `Bl
Licensed under either of
-- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / )
-- MIT ([LICENSE-MIT](LICENSE-MIT) / )
+- Apache 2.0, ([LICENSE-APACHE](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-core/LICENSE-APACHE) / )
+- MIT ([LICENSE-MIT](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-core/LICENSE-MIT) / )
# Contribute
diff --git a/packages/blockstore-core/package.json b/packages/blockstore-core/package.json
index abc4fe5d..84d94561 100644
--- a/packages/blockstore-core/package.json
+++ b/packages/blockstore-core/package.json
@@ -1,6 +1,6 @@
{
"name": "blockstore-core",
- "version": "4.4.0",
+ "version": "6.1.2",
"description": "Contains various implementations of the API contract described in interface-blockstore",
"author": "Alex Potsides ",
"license": "Apache-2.0 OR MIT",
@@ -76,12 +76,98 @@
"import": "./dist/src/tiered.js"
}
},
- "eslintConfig": {
- "extends": "ipfs",
- "parserOptions": {
- "project": true,
- "sourceType": "module"
- }
+ "release": {
+ "branches": [
+ "main"
+ ],
+ "plugins": [
+ [
+ "@semantic-release/commit-analyzer",
+ {
+ "preset": "conventionalcommits",
+ "releaseRules": [
+ {
+ "breaking": true,
+ "release": "major"
+ },
+ {
+ "revert": true,
+ "release": "patch"
+ },
+ {
+ "type": "feat",
+ "release": "minor"
+ },
+ {
+ "type": "fix",
+ "release": "patch"
+ },
+ {
+ "type": "docs",
+ "release": "patch"
+ },
+ {
+ "type": "test",
+ "release": "patch"
+ },
+ {
+ "type": "deps",
+ "release": "patch"
+ },
+ {
+ "scope": "no-release",
+ "release": false
+ }
+ ]
+ }
+ ],
+ [
+ "@semantic-release/release-notes-generator",
+ {
+ "preset": "conventionalcommits",
+ "presetConfig": {
+ "types": [
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "chore",
+ "section": "Trivial Changes"
+ },
+ {
+ "type": "docs",
+ "section": "Documentation"
+ },
+ {
+ "type": "deps",
+ "section": "Dependencies"
+ },
+ {
+ "type": "test",
+ "section": "Tests"
+ }
+ ]
+ }
+ }
+ ],
+ "@semantic-release/changelog",
+ "@semantic-release/npm",
+ "@semantic-release/github",
+ [
+ "@semantic-release/git",
+ {
+ "assets": [
+ "CHANGELOG.md",
+ "package.json"
+ ]
+ }
+ ]
+ ]
},
"scripts": {
"clean": "aegir clean",
@@ -94,22 +180,23 @@
"test:firefox": "aegir test -t browser -- --browser firefox",
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
"test:electron-main": "aegir test -t electron-main",
- "dep-check": "aegir dep-check"
+ "dep-check": "aegir dep-check",
+ "release": "aegir release"
},
"dependencies": {
- "@libp2p/logger": "^4.0.6",
- "err-code": "^3.0.1",
- "interface-blockstore": "^5.0.0",
- "interface-store": "^5.0.0",
- "it-drain": "^3.0.5",
- "it-filter": "^3.0.4",
- "it-merge": "^3.0.3",
- "it-pushable": "^3.2.3",
- "multiformats": "^13.0.1"
+ "@libp2p/logger": "^6.0.0",
+ "interface-blockstore": "^6.0.0",
+ "interface-store": "^7.0.0",
+ "it-all": "^3.0.9",
+ "it-filter": "^3.1.3",
+ "it-merge": "^3.0.11",
+ "multiformats": "^13.3.6"
},
"devDependencies": {
- "aegir": "^42.2.3",
- "interface-blockstore-tests": "^6.0.0",
- "uint8arrays": "^5.0.2"
+ "aegir": "^47.0.16",
+ "interface-blockstore-tests": "^8.0.0",
+ "it-drain": "^3.0.9",
+ "it-to-buffer": "^4.0.10",
+ "uint8arrays": "^5.1.0"
}
}
diff --git a/packages/blockstore-core/src/base.ts b/packages/blockstore-core/src/base.ts
index 87b1d966..dcb216a0 100644
--- a/packages/blockstore-core/src/base.ts
+++ b/packages/blockstore-core/src/base.ts
@@ -1,5 +1,5 @@
-import type { Blockstore, Pair } from 'interface-blockstore'
-import type { AbortOptions, Await, AwaitIterable } from 'interface-store'
+import type { Blockstore, InputPair, Pair } from 'interface-blockstore'
+import type { AbortOptions, Await, AwaitGenerator, AwaitIterable } from 'interface-store'
import type { CID } from 'multiformats/cid'
export class BaseBlockstore implements Blockstore {
@@ -7,26 +7,26 @@ export class BaseBlockstore implements Blockstore {
return Promise.reject(new Error('.has is not implemented'))
}
- put (key: CID, val: Uint8Array, options?: AbortOptions): Await {
+ put (key: CID, val: Uint8Array | AwaitIterable, options?: AbortOptions): Await {
return Promise.reject(new Error('.put is not implemented'))
}
- async * putMany (source: AwaitIterable, options?: AbortOptions): AwaitIterable {
- for await (const { cid, block } of source) {
- await this.put(cid, block, options)
+ async * putMany (source: AwaitIterable, options?: AbortOptions): AwaitGenerator {
+ for await (const { cid, bytes } of source) {
+ await this.put(cid, bytes, options)
yield cid
}
}
- get (key: CID, options?: AbortOptions): Await {
- return Promise.reject(new Error('.get is not implemented'))
+ get (key: CID, options?: AbortOptions): AwaitGenerator {
+ throw new Error('.get is not implemented')
}
- async * getMany (source: AwaitIterable, options?: AbortOptions): AwaitIterable {
+ async * getMany (source: AwaitIterable, options?: AbortOptions): AwaitGenerator {
for await (const key of source) {
yield {
cid: key,
- block: await this.get(key, options)
+ bytes: this.get(key, options)
}
}
}
@@ -35,7 +35,7 @@ export class BaseBlockstore implements Blockstore {
return Promise.reject(new Error('.delete is not implemented'))
}
- async * deleteMany (source: AwaitIterable, options?: AbortOptions): AwaitIterable {
+ async * deleteMany (source: AwaitIterable, options?: AbortOptions): AwaitGenerator {
for await (const key of source) {
await this.delete(key, options)
yield key
@@ -45,7 +45,7 @@ export class BaseBlockstore implements Blockstore {
/**
* Extending classes should override `query` or implement this method
*/
- async * getAll (options?: AbortOptions): AwaitIterable { // eslint-disable-line require-yield
+ async * getAll (options?: AbortOptions): AwaitGenerator { // eslint-disable-line require-yield
throw new Error('.getAll is not implemented')
}
}
diff --git a/packages/blockstore-core/src/black-hole.ts b/packages/blockstore-core/src/black-hole.ts
index ab1b5a61..c71e52c1 100644
--- a/packages/blockstore-core/src/black-hole.ts
+++ b/packages/blockstore-core/src/black-hole.ts
@@ -1,27 +1,31 @@
+import { NotFoundError } from 'interface-store'
import { BaseBlockstore } from './base.js'
-import * as Errors from './errors.js'
import type { Pair } from 'interface-blockstore'
-import type { Await, AwaitIterable } from 'interface-store'
+import type { AbortOptions, Await, AwaitGenerator, AwaitIterable } from 'interface-store'
import type { CID } from 'multiformats/cid'
export class BlackHoleBlockstore extends BaseBlockstore {
- put (key: CID): Await {
+ put (key: CID, value: Uint8Array | AwaitIterable, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
return key
}
- get (): Await {
- throw Errors.notFoundError()
+ get (key: CID, options?: AbortOptions): AwaitGenerator {
+ options?.signal?.throwIfAborted()
+ throw new NotFoundError()
}
- has (): Await {
+ has (key: CID, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
return false
}
- async delete (): Promise {
-
+ async delete (cid: CID, options?: AbortOptions): Promise {
+ options?.signal?.throwIfAborted()
}
- async * getAll (): AwaitIterable {
-
+ // eslint-disable-next-line require-yield
+ async * getAll (options?: AbortOptions): AwaitGenerator {
+ options?.signal?.throwIfAborted()
}
}
diff --git a/packages/blockstore-core/src/errors.ts b/packages/blockstore-core/src/errors.ts
deleted file mode 100644
index d4533c91..00000000
--- a/packages/blockstore-core/src/errors.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import errCode from 'err-code'
-
-export function openFailedError (err?: Error): Error {
- err = err ?? new Error('Open failed')
- return errCode(err, 'ERR_OPEN_FAILED')
-}
-
-export function closeFailedError (err?: Error): Error {
- err = err ?? new Error('Close failed')
- return errCode(err, 'ERR_CLOSE_FAILED')
-}
-
-export function putFailedError (err?: Error): Error {
- err = err ?? new Error('Put failed')
- return errCode(err, 'ERR_PUT_FAILED')
-}
-
-export function getFailedError (err?: Error): Error {
- err = err ?? new Error('Get failed')
- return errCode(err, 'ERR_GET_FAILED')
-}
-
-export function deleteFailedError (err?: Error): Error {
- err = err ?? new Error('Delete failed')
- return errCode(err, 'ERR_DELETE_FAILED')
-}
-
-export function hasFailedError (err?: Error): Error {
- err = err ?? new Error('Has failed')
- return errCode(err, 'ERR_HAS_FAILED')
-}
-
-export function notFoundError (err?: Error): Error {
- err = err ?? new Error('Not Found')
- return errCode(err, 'ERR_NOT_FOUND')
-}
-
-export function abortedError (err?: Error): Error {
- err = err ?? new Error('Aborted')
- return errCode(err, 'ERR_ABORTED')
-}
diff --git a/packages/blockstore-core/src/identity.ts b/packages/blockstore-core/src/identity.ts
index 059902df..3c861178 100644
--- a/packages/blockstore-core/src/identity.ts
+++ b/packages/blockstore-core/src/identity.ts
@@ -1,34 +1,107 @@
+import { NotFoundError } from 'interface-store'
import { BaseBlockstore } from './base.js'
-import * as Errors from './errors.js'
-import type { Pair } from 'interface-blockstore'
-import type { Await, AwaitIterable } from 'interface-store'
+import type { Blockstore, Pair } from 'interface-blockstore'
+import type { AbortOptions, Await, AwaitIterable } from 'interface-store'
import type { CID } from 'multiformats/cid'
// https://github.com/multiformats/multicodec/blob/d06fc6194710e8909bac64273c43f16b56ca4c34/table.csv#L2
const IDENTITY_CODEC = 0x00
+class IdentityHashDigestTooLongError extends Error {
+ static name = 'IdentityHashDigestTooLongError'
+ name = 'IdentityHashDigestTooLongError'
+}
+
+export interface IdentityBlockstoreInit {
+ maxDigestLength?: number
+}
+
export class IdentityBlockstore extends BaseBlockstore {
- put (key: CID): CID {
- return key
+ private readonly child?: Blockstore
+ private readonly maxDigestLength?: number
+
+ constructor (child?: Blockstore, init?: IdentityBlockstoreInit) {
+ super()
+
+ this.child = child
+ this.maxDigestLength = init?.maxDigestLength
}
- get (key: CID): Await {
- if (key.code === IDENTITY_CODEC) {
- return key.multihash.digest
+ put (key: CID, block: Uint8Array | AwaitIterable, options?: AbortOptions): Await {
+ if (key.multihash.code === IDENTITY_CODEC) {
+ if (this.maxDigestLength != null && key.multihash.digest.byteLength > this.maxDigestLength) {
+ throw new IdentityHashDigestTooLongError(`Identity digest too long - ${key.multihash.digest.byteLength} > this.maxDigestLength`)
+ }
+
+ options?.signal?.throwIfAborted()
+ return key
+ }
+
+ if (this.child == null) {
+ options?.signal?.throwIfAborted()
+ return key
}
- throw Errors.notFoundError()
+ return this.child.put(key, block, options)
}
- has (key: CID): boolean {
- return key.code === IDENTITY_CODEC
+ async * get (key: CID, options?: AbortOptions): AsyncGenerator {
+ if (key.multihash.code === IDENTITY_CODEC) {
+ if (this.maxDigestLength != null && key.multihash.digest.byteLength > this.maxDigestLength) {
+ throw new IdentityHashDigestTooLongError(`Identity digest too long - ${key.multihash.digest.byteLength} > this.maxDigestLength`)
+ }
+
+ options?.signal?.throwIfAborted()
+ yield key.multihash.digest
+ return
+ }
+
+ if (this.child == null) {
+ options?.signal?.throwIfAborted()
+ throw new NotFoundError()
+ }
+
+ yield * this.child.get(key, options)
}
- delete (): void {
+ has (key: CID, options?: AbortOptions): Await {
+ if (key.multihash.code === IDENTITY_CODEC) {
+ if (this.maxDigestLength != null && key.multihash.digest.byteLength > this.maxDigestLength) {
+ throw new IdentityHashDigestTooLongError(`Identity digest too long - ${key.multihash.digest.byteLength} > this.maxDigestLength`)
+ }
+
+ options?.signal?.throwIfAborted()
+ return true
+ }
+ if (this.child == null) {
+ options?.signal?.throwIfAborted()
+ return false
+ }
+
+ return this.child.has(key, options)
}
- * getAll (): AwaitIterable {
+ delete (key: CID, options?: AbortOptions): Await {
+ if (key.code === IDENTITY_CODEC) {
+ if (this.maxDigestLength != null && key.multihash.digest.byteLength > this.maxDigestLength) {
+ throw new IdentityHashDigestTooLongError(`Identity digest too long - ${key.multihash.digest.byteLength} > this.maxDigestLength`)
+ }
+
+ options?.signal?.throwIfAborted()
+ return
+ }
+
+ if (this.child != null) {
+ return this.child.delete(key, options)
+ }
+ }
+
+ async * getAll (options?: AbortOptions): AsyncGenerator {
+ if (this.child != null) {
+ yield * this.child.getAll(options)
+ }
+ options?.signal?.throwIfAborted()
}
}
diff --git a/packages/blockstore-core/src/index.ts b/packages/blockstore-core/src/index.ts
index 0bab631f..a47ed278 100644
--- a/packages/blockstore-core/src/index.ts
+++ b/packages/blockstore-core/src/index.ts
@@ -5,10 +5,10 @@
*
* ## Implementations
*
- * - Base: [`src/base`](src/base.ts)
- * - Memory: [`src/memory`](src/memory.ts)
- * - BlackHole: ['src/black-hole](src/black-hole.ts)
- * - Tiered: ['src/tiered](src/tiered.ts)
+ * - Base: [`src/base`](./src/base.ts)
+ * - Memory: [`src/memory`](./src/memory.ts)
+ * - BlackHole: ['src/black-hole](./src/black-hole.ts)
+ * - Tiered: ['src/tiered](./src/tiered.ts)
*
* @example BaseBlockstore
*
@@ -82,13 +82,7 @@
* ```
*/
-import * as ErrorsImport from './errors.js'
-
export { BaseBlockstore } from './base.js'
export { MemoryBlockstore } from './memory.js'
export { BlackHoleBlockstore } from './black-hole.js'
export { TieredBlockstore } from './tiered.js'
-
-export const Errors = {
- ...ErrorsImport
-}
diff --git a/packages/blockstore-core/src/memory.ts b/packages/blockstore-core/src/memory.ts
index 72686d89..a62d1ba3 100644
--- a/packages/blockstore-core/src/memory.ts
+++ b/packages/blockstore-core/src/memory.ts
@@ -1,14 +1,19 @@
+import { NotFoundError } from 'interface-store'
+import all from 'it-all'
import { base32 } from 'multiformats/bases/base32'
import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import * as Digest from 'multiformats/hashes/digest'
import { BaseBlockstore } from './base.js'
-import * as Errors from './errors.js'
import type { Pair } from 'interface-blockstore'
-import type { Await, AwaitIterable } from 'interface-store'
+import type { AbortOptions, Await, AwaitGenerator, AwaitIterable } from 'interface-store'
+
+function isPromise (p?: any): p is Promise {
+ return typeof p?.then === 'function'
+}
export class MemoryBlockstore extends BaseBlockstore {
- private readonly data: Map
+ private readonly data: Map
constructor () {
super()
@@ -16,36 +21,68 @@ export class MemoryBlockstore extends BaseBlockstore {
this.data = new Map()
}
- put (key: CID, val: Uint8Array): Await { // eslint-disable-line require-await
+ put (key: CID, val: Uint8Array | AwaitIterable, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
+
+ let buf: Uint8Array[]
+
+ if (val instanceof Uint8Array) {
+ buf = [val]
+ } else {
+ const result = all(val)
+
+ if (isPromise(result)) {
+ return result.then(val => {
+ return this._put(key, val, options)
+ })
+ } else {
+ buf = result
+ }
+ }
+
+ return this._put(key, buf, options)
+ }
+
+ private _put (key: CID, val: Uint8Array[], options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
+
this.data.set(base32.encode(key.multihash.bytes), val)
return key
}
- get (key: CID): Await {
+ * get (key: CID, options?: AbortOptions): AwaitGenerator {
+ options?.signal?.throwIfAborted()
const buf = this.data.get(base32.encode(key.multihash.bytes))
if (buf == null) {
- throw Errors.notFoundError()
+ throw new NotFoundError()
}
- return buf
+ yield * buf
}
- has (key: CID): Await {
+ has (key: CID, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
return this.data.has(base32.encode(key.multihash.bytes))
}
- async delete (key: CID): Promise {
+ async delete (key: CID, options?: AbortOptions): Promise {
+ options?.signal?.throwIfAborted()
this.data.delete(base32.encode(key.multihash.bytes))
}
- async * getAll (): AwaitIterable {
+ * getAll (options?: AbortOptions): AwaitGenerator {
+ options?.signal?.throwIfAborted()
+
for (const [key, value] of this.data.entries()) {
yield {
cid: CID.createV1(raw.code, Digest.decode(base32.decode(key))),
- block: value
+ bytes: (async function * () {
+ yield * value
+ })()
}
+ options?.signal?.throwIfAborted()
}
}
}
diff --git a/packages/blockstore-core/src/tiered.ts b/packages/blockstore-core/src/tiered.ts
index ce5c39f1..5e09a939 100644
--- a/packages/blockstore-core/src/tiered.ts
+++ b/packages/blockstore-core/src/tiered.ts
@@ -1,12 +1,10 @@
import { logger } from '@libp2p/logger'
-import drain from 'it-drain'
+import { NotFoundError } from 'interface-store'
import filter from 'it-filter'
import merge from 'it-merge'
-import { pushable } from 'it-pushable'
import { BaseBlockstore } from './base.js'
-import * as Errors from './errors.js'
-import type { Blockstore, Pair } from 'interface-blockstore'
-import type { AbortOptions, AwaitIterable } from 'interface-store'
+import type { Blockstore, InputPair, Pair } from 'interface-blockstore'
+import type { AbortOptions, AwaitGenerator, AwaitIterable } from 'interface-store'
import type { CID } from 'multiformats/cid'
const log = logger('blockstore:core:tiered')
@@ -26,25 +24,30 @@ export class TieredBlockstore extends BaseBlockstore {
this.stores = stores.slice()
}
- async put (key: CID, value: Uint8Array, options?: AbortOptions): Promise {
- try {
- await Promise.all(this.stores.map(async store => { await store.put(key, value, options) }))
- return key
- } catch (err: any) {
- throw Errors.putFailedError(err)
- }
+ async put (key: CID, value: Uint8Array | AwaitIterable, options?: AbortOptions): Promise {
+ await Promise.all(
+ this.stores.map(async store => {
+ await store.put(key, value, options)
+ })
+ )
+
+ return key
}
- async get (key: CID, options?: AbortOptions): Promise {
+ async * get (key: CID, options?: AbortOptions): AwaitGenerator {
+ let error: Error | undefined
+
for (const store of this.stores) {
try {
- const res = await store.get(key, options)
- if (res != null) return res
- } catch (err) {
+ yield * store.get(key, options)
+ return
+ } catch (err: any) {
+ error = err
log.error(err)
}
}
- throw Errors.notFoundError()
+
+ throw error ?? new NotFoundError()
}
async has (key: CID, options?: AbortOptions): Promise {
@@ -58,76 +61,28 @@ export class TieredBlockstore extends BaseBlockstore {
}
async delete (key: CID, options?: AbortOptions): Promise {
- try {
- await Promise.all(this.stores.map(async store => { await store.delete(key, options) }))
- } catch (err: any) {
- throw Errors.deleteFailedError(err)
- }
- }
-
- async * putMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
- let error: Error | undefined
- const pushables = this.stores.map(store => {
- const source = pushable({
- objectMode: true
+ await Promise.all(
+ this.stores.map(async store => {
+ await store.delete(key, options)
})
+ )
+ }
- drain(store.putMany(source, options))
- .catch(err => {
- // store threw while putting, make sure we bubble the error up
- error = err
- })
-
- return source
- })
-
- try {
- for await (const pair of source) {
- if (error != null) {
- throw error
- }
-
- pushables.forEach(p => p.push(pair))
-
- yield pair.cid
- }
- } finally {
- pushables.forEach(p => p.end())
+ async * putMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
+ for await (const pair of source) {
+ await this.put(pair.cid, pair.bytes, options)
+ yield pair.cid
}
}
- async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
- let error: Error | undefined
- const pushables = this.stores.map(store => {
- const source = pushable({
- objectMode: true
- })
-
- drain(store.deleteMany(source, options))
- .catch(err => {
- // store threw while deleting, make sure we bubble the error up
- error = err
- })
-
- return source
- })
-
- try {
- for await (const key of source) {
- if (error != null) {
- throw error
- }
-
- pushables.forEach(p => p.push(key))
-
- yield key
- }
- } finally {
- pushables.forEach(p => p.end())
+ async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
+ for await (const cid of source) {
+ await this.delete(cid, options)
+ yield cid
}
}
- async * getAll (options?: AbortOptions): AwaitIterable { // eslint-disable-line require-yield
+ async * getAll (options?: AbortOptions): AwaitGenerator {
// deduplicate yielded pairs
const seen = new Set()
diff --git a/packages/blockstore-core/test/identity.spec.ts b/packages/blockstore-core/test/identity.spec.ts
index e0bfcdfc..7809da69 100644
--- a/packages/blockstore-core/test/identity.spec.ts
+++ b/packages/blockstore-core/test/identity.spec.ts
@@ -1,28 +1,34 @@
/* eslint-env mocha */
import { expect } from 'aegir/chai'
+import all from 'it-all'
import drain from 'it-drain'
+import toBuffer from 'it-to-buffer'
import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import { identity } from 'multiformats/hashes/identity'
import { sha256 } from 'multiformats/hashes/sha2'
import { IdentityBlockstore } from '../src/identity.js'
+import { MemoryBlockstore } from '../src/memory.js'
import type { Blockstore } from 'interface-blockstore'
+import type { AbortOptions } from 'interface-store'
describe('identity', () => {
let blockstore: Blockstore
+ let child: Blockstore
beforeEach(() => {
blockstore = new IdentityBlockstore()
+ child = new MemoryBlockstore()
})
- it('has an identity CID', () => {
+ it('has an identity CID', async () => {
const block = Uint8Array.from([0, 1, 2, 3, 4])
const multihash = identity.digest(block)
const cid = CID.createV1(identity.code, multihash)
expect(blockstore.has(cid)).to.be.true()
- expect(blockstore.get(cid)).to.equalBytes(block)
+ expect(toBuffer(await all(blockstore.get(cid)))).to.equalBytes(block)
})
it('does not have a non-identity CID', async () => {
@@ -56,4 +62,125 @@ describe('identity', () => {
expect(blockstore.has(cid)).to.be.true()
})
+
+ it('puts CIDs to child', async () => {
+ const block = Uint8Array.from([0, 1, 2, 3, 4])
+ const multihash = await sha256.digest(block)
+ const cid = CID.createV1(raw.code, multihash)
+
+ blockstore = new IdentityBlockstore(child)
+
+ await blockstore.put(cid, block)
+ expect(child.has(cid)).to.be.true()
+ expect(toBuffer(await all(child.get(cid)))).to.equalBytes(block)
+ })
+
+ it('gets CIDs from child', async () => {
+ const block = Uint8Array.from([0, 1, 2, 3, 4])
+ const multihash = await sha256.digest(block)
+ const cid = CID.createV1(raw.code, multihash)
+
+ await child.put(cid, block)
+
+ blockstore = new IdentityBlockstore(child)
+ expect(blockstore.has(cid)).to.be.true()
+ expect(toBuffer(await all(blockstore.get(cid)))).to.equalBytes(block)
+ })
+
+ it('gets CIDs from child (async)', async () => {
+ const block = Uint8Array.from([0, 1, 2, 3, 4])
+ const multihash = await sha256.digest(block)
+ const cid = CID.createV1(raw.code, multihash)
+
+ await child.put(cid, block)
+
+ const { get } = child
+ child.get = async function * (key: CID, options: AbortOptions) { yield * get.bind(child)(key, options) }
+ blockstore = new IdentityBlockstore(child)
+ expect(blockstore.has(cid)).to.be.true()
+ expect(toBuffer(await all(blockstore.get(cid)))).to.equalBytes(block)
+ })
+
+ it('has CIDs from child', async () => {
+ const block = Uint8Array.from([0, 1, 2, 3, 4])
+ const multihash = await sha256.digest(block)
+ const cid = CID.createV1(raw.code, multihash)
+
+ await child.put(cid, block)
+
+ blockstore = new IdentityBlockstore(child)
+ expect(blockstore.has(cid)).to.be.true()
+ })
+
+ it('deletes CIDs from child', async () => {
+ const block = Uint8Array.from([0, 1, 2, 3, 4])
+ const multihash = await sha256.digest(block)
+ const cid = CID.createV1(raw.code, multihash)
+
+ await child.put(cid, block)
+
+ blockstore = new IdentityBlockstore(child)
+ expect(blockstore.has(cid)).to.be.true()
+
+ await blockstore.delete(cid)
+
+ expect(blockstore.has(cid)).to.be.false()
+ })
+
+ it('gets all pairs from child', async () => {
+ const block = Uint8Array.from([0, 1, 2, 3, 4])
+ const multihash = await sha256.digest(block)
+ const cid = CID.createV1(raw.code, multihash)
+
+ await child.put(cid, block)
+
+ blockstore = new IdentityBlockstore(child)
+ expect(blockstore.has(cid)).to.be.true()
+
+ const result = await all(blockstore.getAll())
+
+ expect(result).to.have.lengthOf(1)
+ expect(result[0].cid.toString()).to.equal(cid.toString())
+ })
+
+ it('gets all pairs from child (async)', async () => {
+ const block = Uint8Array.from([0, 1, 2, 3, 4])
+ const multihash = await sha256.digest(block)
+ const cid = CID.createV1(raw.code, multihash)
+
+ await child.put(cid, block)
+
+ const { getAll } = child
+ child.getAll = async function * (options?: AbortOptions) { yield * getAll.bind(child)(options) }
+ blockstore = new IdentityBlockstore(child)
+ expect(blockstore.has(cid)).to.be.true()
+
+ const result = await all(blockstore.getAll())
+
+ expect(result).to.have.lengthOf(1)
+ expect(result[0].cid.toString()).to.equal(cid.toString())
+ })
+
+ it('should enforce a maximum digest size', async () => {
+ blockstore = new IdentityBlockstore(child, {
+ maxDigestLength: 5
+ })
+
+ const tooLong = Uint8Array.from([0, 1, 2, 3, 4, 5])
+ const ok = Uint8Array.from([0, 1, 2, 3, 4])
+ const buf = Uint8Array.from([])
+
+ expect(blockstore.get(CID.createV1(raw.code, identity.digest(ok)))).to.be.ok()
+ expect(blockstore.put(CID.createV1(raw.code, identity.digest(ok)), buf)).to.be.ok()
+ expect(blockstore.has(CID.createV1(raw.code, identity.digest(ok)))).to.be.ok()
+
+ await expect(all(blockstore.get(CID.createV1(raw.code, identity.digest(tooLong))))).to.eventually.be.rejected()
+ .with.property('name', 'IdentityHashDigestTooLongError')
+
+ expect(() => blockstore.put(CID.createV1(raw.code, identity.digest(tooLong)), buf)).to.throw()
+ .with.property('name', 'IdentityHashDigestTooLongError')
+
+ expect(() => blockstore.has(CID.createV1(raw.code, identity.digest(tooLong)))).to.throw()
+ .with.property('name', 'IdentityHashDigestTooLongError')
+ })
})
diff --git a/packages/blockstore-core/test/tiered.spec.ts b/packages/blockstore-core/test/tiered.spec.ts
index f56dd7b9..2b32c333 100644
--- a/packages/blockstore-core/test/tiered.spec.ts
+++ b/packages/blockstore-core/test/tiered.spec.ts
@@ -2,6 +2,7 @@
import { expect } from 'aegir/chai'
import { interfaceBlockstoreTests } from 'interface-blockstore-tests'
+import all from 'it-all'
import { CID } from 'multiformats/cid'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import { MemoryBlockstore } from '../src/memory.js'
@@ -22,9 +23,9 @@ describe('Tiered', () => {
const k = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL')
const v = uint8ArrayFromString('world')
await store.put(k, v)
- const res = await Promise.all([ms[0].get(k), ms[1].get(k)])
+ const res = await Promise.all([all(ms[0].get(k)), all(ms[1].get(k))])
res.forEach((val) => {
- expect(val).to.be.eql(v)
+ expect(val).to.deep.equal([v])
})
})
@@ -32,14 +33,14 @@ describe('Tiered', () => {
const k = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL')
const v = uint8ArrayFromString('world')
await ms[1].put(k, v)
- const val = await store.get(k)
- expect(val).to.be.eql(v)
+ const val = await all(store.get(k))
+ expect(val).to.deep.equal([v])
const exists = await store.has(k)
- expect(exists).to.be.eql(true)
+ expect(exists).to.equal(true)
})
it('has - key not found', async () => {
- expect(await store.has(CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnA'))).to.be.eql(false)
+ expect(await store.has(CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnA'))).to.be.false()
})
it('has and delete', async () => {
@@ -47,10 +48,10 @@ describe('Tiered', () => {
const v = uint8ArrayFromString('world')
await store.put(k, v)
let res = await Promise.all([ms[0].has(k), ms[1].has(k)])
- expect(res).to.be.eql([true, true])
+ expect(res).to.deep.equal([true, true])
await store.delete(k)
res = await Promise.all([ms[0].has(k), ms[1].has(k)])
- expect(res).to.be.eql([false, false])
+ expect(res).to.deep.equal([false, false])
})
})
diff --git a/packages/blockstore-core/typedoc.json b/packages/blockstore-core/typedoc.json
index 57c0b938..b22a681e 100644
--- a/packages/blockstore-core/typedoc.json
+++ b/packages/blockstore-core/typedoc.json
@@ -1,4 +1,5 @@
{
+ "readme": "none",
"entryPoints": [
"./src/index.ts",
"./src/base.ts",
diff --git a/packages/blockstore-fs/CHANGELOG.md b/packages/blockstore-fs/CHANGELOG.md
index 8de9b176..d8256f6d 100644
--- a/packages/blockstore-fs/CHANGELOG.md
+++ b/packages/blockstore-fs/CHANGELOG.md
@@ -1,3 +1,85 @@
+## [blockstore-fs-v3.0.2](https://github.com/ipfs/js-stores/compare/blockstore-fs-3.0.1...blockstore-fs-3.0.2) (2025-10-03)
+
+### Bug Fixes
+
+* accept iterables, return generators ([a685552](https://github.com/ipfs/js-stores/commit/a685552f330c5871e60dcee2632c393900cf36f5))
+
+## [blockstore-fs-v3.0.1](https://github.com/ipfs/js-stores/compare/blockstore-fs-3.0.0...blockstore-fs-3.0.1) (2025-10-03)
+
+### Bug Fixes
+
+* update sibling deps ([3f73b3d](https://github.com/ipfs/js-stores/commit/3f73b3d53ea2d86d0f5c3f06785c0bfc30e8b5e9))
+
+## [blockstore-fs-v3.0.0](https://github.com/ipfs/js-stores/compare/blockstore-fs-2.0.5...blockstore-fs-3.0.0) (2025-10-03)
+
+### ⚠ BREAKING CHANGES
+
+* blockstore.get and similar now return streams of bytes
+
+### Features
+
+* streaming blockstores ([#358](https://github.com/ipfs/js-stores/issues/358)) ([4dbb136](https://github.com/ipfs/js-stores/commit/4dbb1362d20fc87fcdd261568dca297972f9bc08))
+
+## [blockstore-fs-v2.0.5](https://github.com/ipfs/js-stores/compare/blockstore-fs-2.0.4...blockstore-fs-2.0.5) (2025-09-02)
+
+### Dependencies
+
+* bump race-signal from 1.1.3 to 2.0.0 ([#355](https://github.com/ipfs/js-stores/issues/355)) ([518fee8](https://github.com/ipfs/js-stores/commit/518fee89d3430534c0ec39551e920447fd558581))
+
+## [blockstore-fs-v2.0.4](https://github.com/ipfs/js-stores/compare/blockstore-fs-2.0.3...blockstore-fs-2.0.4) (2025-05-28)
+
+### Bug Fixes
+
+* improve abort signal support ([#350](https://github.com/ipfs/js-stores/issues/350)) ([e17d770](https://github.com/ipfs/js-stores/commit/e17d770cc2fcee77cb0152a855abf162e5a91a99))
+
+## [blockstore-fs-v2.0.3](https://github.com/ipfs/js-stores/compare/blockstore-fs-2.0.2...blockstore-fs-2.0.3) (2025-05-26)
+
+### Dependencies
+
+* bump aegir from 44.1.4 to 47.0.16 ([#349](https://github.com/ipfs/js-stores/issues/349)) ([d33d15f](https://github.com/ipfs/js-stores/commit/d33d15f0638856530d0e1868c723e5567abf27e6))
+
+## [blockstore-fs-v2.0.2](https://github.com/ipfs/js-stores/compare/blockstore-fs-2.0.1...blockstore-fs-2.0.2) (2024-09-17)
+
+### Tests
+
+* add separate-thread concurrency test ([#305](https://github.com/ipfs/js-stores/issues/305)) ([5e3114e](https://github.com/ipfs/js-stores/commit/5e3114e0160ba8366067359f724c6e49807dfb21)), closes [#285](https://github.com/ipfs/js-stores/issues/285) [#284](https://github.com/ipfs/js-stores/issues/284)
+
+## [blockstore-fs-v2.0.1](https://github.com/ipfs/js-stores/compare/blockstore-fs-2.0.0...blockstore-fs-2.0.1) (2024-09-13)
+
+### Bug Fixes
+
+* restore release config to package.json ([#321](https://github.com/ipfs/js-stores/issues/321)) ([4f14fb0](https://github.com/ipfs/js-stores/commit/4f14fb09d65a3460b548b59557af108412dc9156))
+
+### Dependencies
+
+* **dev:** bump aegir from 42.2.11 to 44.1.0 ([#316](https://github.com/ipfs/js-stores/issues/316)) ([581a467](https://github.com/ipfs/js-stores/commit/581a46720832916bea11efa2476eb85a00bae9d4))
+
+## blockstore-fs [2.0.0](https://github.com/ipfs/js-stores/compare/blockstore-fs-1.1.11...blockstore-fs-2.0.0) (2024-08-02)
+
+
+### ⚠ BREAKING CHANGES
+
+* To detect the type of error thrown, use `.name` instead of `.code`
+
+### Features
+
+* use `.name` property for errors instead of `.code` ([#315](https://github.com/ipfs/js-stores/issues/315)) ([dacd6ce](https://github.com/ipfs/js-stores/commit/dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd))
+
+
+
+### Dependencies
+
+* **interface-blockstore:** upgraded to 5.3.0
+* **interface-store:** upgraded to 6.0.0
+* **interface-blockstore-tests:** upgraded to 7.0.0
+
+## blockstore-fs [1.1.11](https://github.com/ipfs/js-stores/compare/blockstore-fs-1.1.10...blockstore-fs-1.1.11) (2024-08-01)
+
+
+### Dependencies
+
+* bump it-glob from 2.0.7 to 3.0.1 ([#306](https://github.com/ipfs/js-stores/issues/306)) ([8f6313f](https://github.com/ipfs/js-stores/commit/8f6313f8a22cb537aeeac2a048aad644d3c9a7d2))
+
## blockstore-fs [1.1.10](https://github.com/ipfs/js-stores/compare/blockstore-fs-v1.1.9...blockstore-fs-1.1.10) (2024-02-12)
diff --git a/packages/blockstore-fs/CODE_OF_CONDUCT.md b/packages/blockstore-fs/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..6b0fa54c
--- /dev/null
+++ b/packages/blockstore-fs/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Contributor Code of Conduct
+
+This project follows the [`IPFS Community Code of Conduct`](https://github.com/ipfs/community/blob/master/code-of-conduct.md)
diff --git a/packages/blockstore-fs/LICENSE b/packages/blockstore-fs/LICENSE
deleted file mode 100644
index 20ce483c..00000000
--- a/packages/blockstore-fs/LICENSE
+++ /dev/null
@@ -1,4 +0,0 @@
-This project is dual licensed under MIT and Apache-2.0.
-
-MIT: https://www.opensource.org/licenses/mit
-Apache-2.0: https://www.apache.org/licenses/license-2.0
diff --git a/packages/blockstore-fs/LICENSE-APACHE b/packages/blockstore-fs/LICENSE-APACHE
index 14478a3b..b09cd785 100644
--- a/packages/blockstore-fs/LICENSE-APACHE
+++ b/packages/blockstore-fs/LICENSE-APACHE
@@ -1,5 +1,201 @@
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-http://www.apache.org/licenses/LICENSE-2.0
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/blockstore-fs/README.md b/packages/blockstore-fs/README.md
index a7e4b185..61af9aeb 100644
--- a/packages/blockstore-fs/README.md
+++ b/packages/blockstore-fs/README.md
@@ -9,6 +9,21 @@
# About
+
+
A Blockstore implementation that stores blocks in the local filesystem.
## Example
@@ -33,8 +48,8 @@ $ npm i blockstore-fs
Licensed under either of
-- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / )
-- MIT ([LICENSE-MIT](LICENSE-MIT) / )
+- Apache 2.0, ([LICENSE-APACHE](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-fs/LICENSE-APACHE) / )
+- MIT ([LICENSE-MIT](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-fs/LICENSE-MIT) / )
# Contribute
diff --git a/packages/blockstore-fs/package.json b/packages/blockstore-fs/package.json
index 469a2e91..1919c70e 100644
--- a/packages/blockstore-fs/package.json
+++ b/packages/blockstore-fs/package.json
@@ -1,6 +1,6 @@
{
"name": "blockstore-fs",
- "version": "1.1.10",
+ "version": "3.0.2",
"description": "Blockstore implementation with file system backend",
"license": "Apache-2.0 OR MIT",
"homepage": "https://github.com/ipfs/js-stores/tree/main/packages/blockstore-fs#readme",
@@ -56,15 +56,98 @@
"import": "./dist/src/sharding.js"
}
},
- "eslintConfig": {
- "extends": "ipfs",
- "parserOptions": {
- "project": [
- "tsconfig.json",
- "benchmarks/encoding/tsconfig.json"
+ "release": {
+ "branches": [
+ "main"
+ ],
+ "plugins": [
+ [
+ "@semantic-release/commit-analyzer",
+ {
+ "preset": "conventionalcommits",
+ "releaseRules": [
+ {
+ "breaking": true,
+ "release": "major"
+ },
+ {
+ "revert": true,
+ "release": "patch"
+ },
+ {
+ "type": "feat",
+ "release": "minor"
+ },
+ {
+ "type": "fix",
+ "release": "patch"
+ },
+ {
+ "type": "docs",
+ "release": "patch"
+ },
+ {
+ "type": "test",
+ "release": "patch"
+ },
+ {
+ "type": "deps",
+ "release": "patch"
+ },
+ {
+ "scope": "no-release",
+ "release": false
+ }
+ ]
+ }
],
- "sourceType": "module"
- }
+ [
+ "@semantic-release/release-notes-generator",
+ {
+ "preset": "conventionalcommits",
+ "presetConfig": {
+ "types": [
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "chore",
+ "section": "Trivial Changes"
+ },
+ {
+ "type": "docs",
+ "section": "Documentation"
+ },
+ {
+ "type": "deps",
+ "section": "Dependencies"
+ },
+ {
+ "type": "test",
+ "section": "Tests"
+ }
+ ]
+ }
+ }
+ ],
+ "@semantic-release/changelog",
+ "@semantic-release/npm",
+ "@semantic-release/github",
+ [
+ "@semantic-release/git",
+ {
+ "assets": [
+ "CHANGELOG.md",
+ "package.json"
+ ]
+ }
+ ]
+ ]
},
"scripts": {
"clean": "aegir clean",
@@ -73,20 +156,23 @@
"test": "aegir test -t node -t electron-main",
"test:node": "aegir test -t node",
"test:electron-main": "aegir test -t electron-main",
- "dep-check": "aegir dep-check"
+ "dep-check": "aegir dep-check",
+ "release": "aegir release"
},
"dependencies": {
- "blockstore-core": "^4.0.0",
- "fast-write-atomic": "^0.2.1",
- "interface-blockstore": "^5.0.0",
- "interface-store": "^5.0.0",
- "it-glob": "^2.0.6",
- "it-map": "^3.0.5",
- "it-parallel-batch": "^3.0.4",
- "multiformats": "^13.0.1"
+ "interface-blockstore": "^6.0.0",
+ "interface-store": "^7.0.0",
+ "it-glob": "^3.0.3",
+ "it-map": "^3.1.3",
+ "it-parallel-batch": "^3.0.8",
+ "multiformats": "^13.3.6",
+ "race-signal": "^2.0.0",
+ "steno": "^4.0.2"
},
"devDependencies": {
- "aegir": "^42.2.3",
- "interface-blockstore-tests": "^6.0.0"
+ "aegir": "^47.0.16",
+ "interface-blockstore-tests": "^8.0.0",
+ "it-all": "^3.0.9",
+ "threads": "^1.7.0"
}
}
diff --git a/packages/blockstore-fs/src/index.ts b/packages/blockstore-fs/src/index.ts
index b2e0af65..d2e9b293 100644
--- a/packages/blockstore-fs/src/index.ts
+++ b/packages/blockstore-fs/src/index.ts
@@ -14,41 +14,46 @@
import fs from 'node:fs/promises'
import path from 'node:path'
-import { promisify } from 'node:util'
-import {
- Errors
-} from 'blockstore-core'
-// @ts-expect-error no types
-import fwa from 'fast-write-atomic'
+import { OpenFailedError, PutFailedError, NotFoundError, DeleteFailedError } from 'interface-store'
import glob from 'it-glob'
import map from 'it-map'
import parallelBatch from 'it-parallel-batch'
-import { NextToLast, type ShardingStrategy } from './sharding.js'
+import { raceSignal } from 'race-signal'
+import { Writer } from 'steno'
+import { NextToLast } from './sharding.js'
+import type { ShardingStrategy } from './sharding.js'
import type { Blockstore, Pair } from 'interface-blockstore'
-import type { AwaitIterable } from 'interface-store'
+import type { AbortOptions, AwaitGenerator, AwaitIterable } from 'interface-store'
import type { CID } from 'multiformats/cid'
-
-const writeAtomic = promisify(fwa)
+import type { FileHandle } from 'node:fs/promises'
/**
* Write a file atomically
*/
-async function writeFile (file: string, contents: Uint8Array): Promise {
+async function writeFile (file: string, contents: Uint8Array | AwaitIterable, options?: AbortOptions): Promise {
try {
- await writeAtomic(file, contents)
+ options?.signal?.throwIfAborted()
+ await raceSignal(fs.mkdir(path.dirname(file), {
+ recursive: true
+ }), options?.signal)
+
+ const writer = new Writer(file)
+
+ options?.signal?.throwIfAborted()
+
+ await writer.write(contents)
} catch (err: any) {
- if (err.code === 'EPERM' && err.syscall === 'rename') {
- // fast-write-atomic writes a file to a temp location before renaming it.
- // On Windows, if the final file already exists this error is thrown.
- // No such error is thrown on Linux/Mac
+ if (err.syscall === 'rename' && ['ENOENT', 'EPERM'].includes(err.code)) {
+ // steno writes a file to a temp location before renaming it.
+ // If the final file already exists this error is thrown.
// Make sure we can read & write to this file
- await fs.access(file, fs.constants.F_OK | fs.constants.W_OK)
+ options?.signal?.throwIfAborted()
+ await raceSignal(fs.access(file, fs.constants.F_OK | fs.constants.W_OK), options?.signal)
// The file was created by another context - this means there were
// attempts to write the same block by two different function calls
return
}
-
throw err
}
}
@@ -122,7 +127,7 @@ export class FsBlockstore implements Blockstore {
await fs.access(this.path, fs.constants.F_OK | fs.constants.W_OK)
if (this.errorIfExists) {
- throw Errors.openFailedError(new Error(`Blockstore directory: ${this.path} already exists`))
+ throw new OpenFailedError(`Blockstore directory: ${this.path} already exists`)
}
} catch (err: any) {
if (err.code === 'ENOENT') {
@@ -130,7 +135,7 @@ export class FsBlockstore implements Blockstore {
await fs.mkdir(this.path, { recursive: true })
return
} else {
- throw Errors.openFailedError(new Error(`Blockstore directory: ${this.path} does not exist`))
+ throw new OpenFailedError(`Blockstore directory: ${this.path} does not exist`)
}
}
@@ -142,29 +147,23 @@ export class FsBlockstore implements Blockstore {
await Promise.resolve()
}
- async put (key: CID, val: Uint8Array): Promise {
+ async put (key: CID, val: Uint8Array | AwaitIterable, options?: AbortOptions): Promise {
const { dir, file } = this.shardingStrategy.encode(key)
try {
- if (dir != null && dir !== '') {
- await fs.mkdir(path.join(this.path, dir), {
- recursive: true
- })
- }
-
- await writeFile(path.join(this.path, dir, file), val)
+ await writeFile(path.join(this.path, dir, file), val, options)
return key
} catch (err: any) {
- throw Errors.putFailedError(err)
+ throw new PutFailedError(String(err))
}
}
- async * putMany (source: AwaitIterable): AsyncIterable {
+ async * putMany (source: AwaitIterable, options?: AbortOptions): AsyncGenerator {
yield * parallelBatch(
- map(source, ({ cid, block }) => {
+ map(source, ({ cid, bytes }) => {
return async () => {
- await this.put(cid, block)
+ await this.put(cid, bytes, options)
return cid
}
@@ -173,23 +172,32 @@ export class FsBlockstore implements Blockstore {
)
}
- async get (key: CID): Promise {
+ async * get (key: CID, options?: AbortOptions): AsyncGenerator {
const { dir, file } = this.shardingStrategy.encode(key)
+ let handle: fs.FileHandle | undefined
try {
- return await fs.readFile(path.join(this.path, dir, file))
+ options?.signal?.throwIfAborted()
+
+ handle = await raceSignal(fs.open(path.join(this.path, dir, file)), options?.signal)
+
+ yield * handle.createReadStream()
} catch (err: any) {
- throw Errors.notFoundError(err)
+ if (handle != null) {
+ await raceSignal(handle.close(), options?.signal)
+ }
+
+ throw new NotFoundError(String(err))
}
}
- async * getMany (source: AwaitIterable): AsyncIterable {
+ async * getMany (source: AwaitIterable, options?: AbortOptions): AsyncGenerator {
yield * parallelBatch(
map(source, key => {
return async () => {
return {
cid: key,
- block: await this.get(key)
+ bytes: this.get(key, options)
}
}
}),
@@ -197,25 +205,26 @@ export class FsBlockstore implements Blockstore {
)
}
- async delete (key: CID): Promise {
+ async delete (key: CID, options?: AbortOptions): Promise {
const { dir, file } = this.shardingStrategy.encode(key)
try {
- await fs.unlink(path.join(this.path, dir, file))
+ options?.signal?.throwIfAborted()
+ await raceSignal(fs.unlink(path.join(this.path, dir, file)), options?.signal)
} catch (err: any) {
if (err.code === 'ENOENT') {
return
}
- throw Errors.deleteFailedError(err)
+ throw new DeleteFailedError(String(err))
}
}
- async * deleteMany (source: AwaitIterable): AsyncIterable {
+ async * deleteMany (source: AwaitIterable, options?: AbortOptions): AsyncGenerator {
yield * parallelBatch(
map(source, key => {
return async () => {
- await this.delete(key)
+ await this.delete(key, options)
return key
}
@@ -224,21 +233,19 @@ export class FsBlockstore implements Blockstore {
)
}
- /**
- * Check for the existence of the given key
- */
- async has (key: CID): Promise {
+ async has (key: CID, options?: AbortOptions): Promise {
const { dir, file } = this.shardingStrategy.encode(key)
try {
- await fs.access(path.join(this.path, dir, file))
+ options?.signal?.throwIfAborted()
+ await raceSignal(fs.access(path.join(this.path, dir, file)), options?.signal)
} catch (err: any) {
return false
}
return true
}
- async * getAll (): AsyncIterable {
+ async * getAll (options?: AbortOptions): AwaitGenerator {
const pattern = `**/*${this.shardingStrategy.extension}`
.split(path.sep)
.join('/')
@@ -248,14 +255,26 @@ export class FsBlockstore implements Blockstore {
for await (const file of files) {
try {
- const buf = await fs.readFile(file)
-
+ options?.signal?.throwIfAborted()
const pair: Pair = {
cid: this.shardingStrategy.decode(file),
- block: buf
+ bytes: (async function * () {
+ let handle: FileHandle | undefined
+
+ try {
+ handle = await raceSignal(fs.open(file), options?.signal)
+
+ yield * handle.createReadStream()
+ } finally {
+ if (handle != null) {
+ await raceSignal(handle.close(), options?.signal)
+ }
+ }
+ })()
}
yield pair
+ options?.signal?.throwIfAborted()
} catch (err: any) {
// if keys are removed from the blockstore while the query is
// running, we may encounter missing files.
diff --git a/packages/blockstore-fs/test/fixtures/writer-worker.ts b/packages/blockstore-fs/test/fixtures/writer-worker.ts
new file mode 100644
index 00000000..1103c33f
--- /dev/null
+++ b/packages/blockstore-fs/test/fixtures/writer-worker.ts
@@ -0,0 +1,31 @@
+import { CID } from 'multiformats/cid'
+// @ts-expect-error types are broken: https://github.com/andywer/threads.js/pull/470
+import { expose } from 'threads/worker'
+import { FsBlockstore } from '../../src/index.js'
+
+let fs: FsBlockstore
+expose({
+ async isReady (path: string) {
+ fs = new FsBlockstore(path)
+ try {
+ await fs.open()
+ return true
+ } catch (err) {
+ // eslint-disable-next-line no-console
+ console.error('Error opening blockstore', err)
+ throw err
+ }
+ },
+ async put (cidString: string, value: Uint8Array) {
+ const key = CID.parse(cidString)
+ try {
+ return await fs.put(key, (async function * () {
+ yield value
+ })())
+ } catch (err) {
+ // eslint-disable-next-line no-console
+ console.error('Error putting block', err)
+ throw err
+ }
+ }
+})
diff --git a/packages/blockstore-fs/test/index.spec.ts b/packages/blockstore-fs/test/index.spec.ts
index 696bacbc..4582521c 100644
--- a/packages/blockstore-fs/test/index.spec.ts
+++ b/packages/blockstore-fs/test/index.spec.ts
@@ -1,11 +1,14 @@
-/* eslint-env mocha */
+import { setMaxListeners } from 'node:events'
import fs from 'node:fs/promises'
import os from 'node:os'
import path from 'node:path'
import { expect } from 'aegir/chai'
import { interfaceBlockstoreTests } from 'interface-blockstore-tests'
+import all from 'it-all'
import { base32 } from 'multiformats/bases/base32'
import { CID } from 'multiformats/cid'
+// @ts-expect-error types are broken: https://github.com/andywer/threads.js/pull/470
+import { spawn, Thread, Worker } from 'threads'
import { FsBlockstore } from '../src/index.js'
import { FlatDirectory, NextToLast } from '../src/sharding.js'
@@ -44,7 +47,7 @@ describe('FsBlockstore', () => {
const dir = path.join(os.tmpdir(), `test-${Math.random()}`)
const store = new FsBlockstore(dir, { createIfMissing: false })
await expect(store.open()).to.eventually.be.rejected
- .with.property('code', 'ERR_OPEN_FAILED')
+ .with.property('name', 'OpenFailedError')
})
it('errorIfExists: true - folder exists', async () => {
@@ -54,7 +57,7 @@ describe('FsBlockstore', () => {
})
const store = new FsBlockstore(dir, { errorIfExists: true })
await expect(store.open()).to.eventually.be.rejected
- .with.property('code', 'ERR_OPEN_FAILED')
+ .with.property('name', 'OpenFailedError')
})
})
@@ -64,11 +67,13 @@ describe('FsBlockstore', () => {
await fs.open()
const key = CID.parse('QmeimKZyjcBnuXmAD9zMnSjM9JodTbgGT3gutofkTqz9rE')
- await fs.put(key, Uint8Array.from([0, 1, 2, 3]))
+ await fs.put(key, (async function * () {
+ yield Uint8Array.from([0, 1, 2, 3])
+ })())
await fs.delete(key)
- await expect(fs.get(key)).to.eventually.be.rejected
- .with.property('code', 'ERR_NOT_FOUND')
+ await expect(all(fs.get(key))).to.eventually.be.rejected
+ .with.property('name', 'NotFoundError')
})
it('deleting non-existent files', async () => {
@@ -80,8 +85,8 @@ describe('FsBlockstore', () => {
await fs.delete(key)
- await expect(fs.get(key)).to.eventually.be.rejected
- .with.property('code', 'ERR_NOT_FOUND')
+ await expect(all(fs.get(key))).to.eventually.be.rejected
+ .with.property('name', 'NotFoundError')
})
describe('interface-blockstore (flat directory)', () => {
@@ -97,7 +102,10 @@ describe('FsBlockstore', () => {
teardown: async (store) => {
await store.close()
await fs.rm(store.path, {
- recursive: true
+ recursive: true,
+ force: true,
+ maxRetries: 5,
+ retryDelay: 1_000
})
}
})
@@ -114,7 +122,10 @@ describe('FsBlockstore', () => {
teardown: async (store) => {
await store.close()
await fs.rm(store.path, {
- recursive: true
+ recursive: true,
+ force: true,
+ maxRetries: 5,
+ retryDelay: 1_000
})
}
})
@@ -136,7 +147,10 @@ describe('FsBlockstore', () => {
teardown: async (store) => {
await store.close()
await fs.rm(store.path, {
- recursive: true
+ recursive: true,
+ force: true,
+ maxRetries: 5,
+ retryDelay: 1_000
})
}
})
@@ -151,11 +165,48 @@ describe('FsBlockstore', () => {
const value = utf8Encoder.encode('Hello world')
await Promise.all(
- new Array(100).fill(0).map(async () => { await fs.put(key, value) })
+ new Array(100).fill(0).map(async () => {
+ await fs.put(key, (async function * () {
+ yield value
+ })())
+ })
)
- const res = await fs.get(key)
+ const res = await all(fs.get(key))
+
+ expect(res).to.deep.equal([value])
+ })
- expect(res).to.deep.equal(value)
+ /**
+ * This test spawns 10 workers that concurrently write to the same blockstore.
+ * it's different from the previous test because it uses workers to write to the blockstore
+ * which means that the writes are happening in parallel in different threads.
+ */
+ it('can survive concurrent worker writes', async () => {
+ const dir = path.join(os.tmpdir(), `test-${Math.random()}`)
+ const key = CID.parse('QmeimKZyjcBnuXmAD9zMnSjM9JodTbgGT3gutofkTqz9rE')
+ const workers = await Promise.all(new Array(10).fill(0).map(async () => {
+ const w = new Worker('./fixtures/writer-worker.js')
+ setMaxListeners(Infinity, w)
+ const worker = await spawn(w)
+ await worker.isReady(dir)
+ return worker
+ }))
+
+ try {
+ const value = utf8Encoder.encode('Hello world')
+ // 100 iterations of looping over all workers and putting the same key value pair
+ await Promise.all(new Array(100).fill(0).map(async () => {
+ return Promise.all(workers.map(async (worker: any) => worker.put(key.toString(), value)))
+ }))
+
+ const fs = new FsBlockstore(dir)
+ await fs.open()
+ const res = await all(fs.get(key))
+
+ expect(res).to.deep.equal([value])
+ } finally {
+ await Promise.all(workers.map(async (worker: any) => Thread.terminate(worker)))
+ }
})
})
diff --git a/packages/blockstore-fs/tsconfig.json b/packages/blockstore-fs/tsconfig.json
index e27c7fa6..73395b59 100644
--- a/packages/blockstore-fs/tsconfig.json
+++ b/packages/blockstore-fs/tsconfig.json
@@ -8,9 +8,6 @@
"test"
],
"references": [
- {
- "path": "../blockstore-core"
- },
{
"path": "../interface-blockstore"
},
diff --git a/packages/blockstore-fs/typedoc.json b/packages/blockstore-fs/typedoc.json
index 332ef6a2..9d7f31b2 100644
--- a/packages/blockstore-fs/typedoc.json
+++ b/packages/blockstore-fs/typedoc.json
@@ -1,4 +1,5 @@
{
+ "readme": "none",
"entryPoints": [
"./src/index.ts",
"./src/sharding.ts"
diff --git a/packages/blockstore-idb/CHANGELOG.md b/packages/blockstore-idb/CHANGELOG.md
index ee7a45aa..f29869f5 100644
--- a/packages/blockstore-idb/CHANGELOG.md
+++ b/packages/blockstore-idb/CHANGELOG.md
@@ -1,3 +1,67 @@
+## [blockstore-idb-v3.0.1](https://github.com/ipfs/js-stores/compare/blockstore-idb-3.0.0...blockstore-idb-3.0.1) (2025-10-03)
+
+### Bug Fixes
+
+* update sibling deps ([3f73b3d](https://github.com/ipfs/js-stores/commit/3f73b3d53ea2d86d0f5c3f06785c0bfc30e8b5e9))
+
+## [blockstore-idb-v3.0.0](https://github.com/ipfs/js-stores/compare/blockstore-idb-2.0.4...blockstore-idb-3.0.0) (2025-10-03)
+
+### ⚠ BREAKING CHANGES
+
+* blockstore.get and similar now return streams of bytes
+
+### Features
+
+* streaming blockstores ([#358](https://github.com/ipfs/js-stores/issues/358)) ([4dbb136](https://github.com/ipfs/js-stores/commit/4dbb1362d20fc87fcdd261568dca297972f9bc08))
+
+## [blockstore-idb-v2.0.4](https://github.com/ipfs/js-stores/compare/blockstore-idb-2.0.3...blockstore-idb-2.0.4) (2025-09-02)
+
+### Dependencies
+
+* bump race-signal from 1.1.3 to 2.0.0 ([#355](https://github.com/ipfs/js-stores/issues/355)) ([518fee8](https://github.com/ipfs/js-stores/commit/518fee89d3430534c0ec39551e920447fd558581))
+
+## [blockstore-idb-v2.0.3](https://github.com/ipfs/js-stores/compare/blockstore-idb-2.0.2...blockstore-idb-2.0.3) (2025-05-28)
+
+### Bug Fixes
+
+* improve abort signal support ([#350](https://github.com/ipfs/js-stores/issues/350)) ([e17d770](https://github.com/ipfs/js-stores/commit/e17d770cc2fcee77cb0152a855abf162e5a91a99))
+
+## [blockstore-idb-v2.0.2](https://github.com/ipfs/js-stores/compare/blockstore-idb-2.0.1...blockstore-idb-2.0.2) (2025-05-26)
+
+### Dependencies
+
+* bump aegir from 44.1.4 to 47.0.16 ([#349](https://github.com/ipfs/js-stores/issues/349)) ([d33d15f](https://github.com/ipfs/js-stores/commit/d33d15f0638856530d0e1868c723e5567abf27e6))
+
+## [blockstore-idb-v2.0.1](https://github.com/ipfs/js-stores/compare/blockstore-idb-2.0.0...blockstore-idb-2.0.1) (2024-09-13)
+
+### Bug Fixes
+
+* restore release config to package.json ([#321](https://github.com/ipfs/js-stores/issues/321)) ([4f14fb0](https://github.com/ipfs/js-stores/commit/4f14fb09d65a3460b548b59557af108412dc9156))
+
+### Dependencies
+
+* **dev:** bump aegir from 42.2.11 to 44.1.0 ([#316](https://github.com/ipfs/js-stores/issues/316)) ([581a467](https://github.com/ipfs/js-stores/commit/581a46720832916bea11efa2476eb85a00bae9d4))
+
+## blockstore-idb [2.0.0](https://github.com/ipfs/js-stores/compare/blockstore-idb-1.1.8...blockstore-idb-2.0.0) (2024-08-02)
+
+
+### ⚠ BREAKING CHANGES
+
+* To detect the type of error thrown, use `.name` instead of `.code`
+
+### Features
+
+* use `.name` property for errors instead of `.code` ([#315](https://github.com/ipfs/js-stores/issues/315)) ([dacd6ce](https://github.com/ipfs/js-stores/commit/dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd))
+
+
+
+### Dependencies
+
+* **blockstore-core:** upgraded to 5.0.0
+* **interface-blockstore:** upgraded to 5.3.0
+* **interface-store:** upgraded to 6.0.0
+* **interface-blockstore-tests:** upgraded to 7.0.0
+
## blockstore-idb [1.1.8](https://github.com/ipfs/js-stores/compare/blockstore-idb-v1.1.7...blockstore-idb-1.1.8) (2024-02-12)
diff --git a/packages/blockstore-idb/CODE_OF_CONDUCT.md b/packages/blockstore-idb/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..6b0fa54c
--- /dev/null
+++ b/packages/blockstore-idb/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Contributor Code of Conduct
+
+This project follows the [`IPFS Community Code of Conduct`](https://github.com/ipfs/community/blob/master/code-of-conduct.md)
diff --git a/packages/blockstore-idb/LICENSE b/packages/blockstore-idb/LICENSE
deleted file mode 100644
index 20ce483c..00000000
--- a/packages/blockstore-idb/LICENSE
+++ /dev/null
@@ -1,4 +0,0 @@
-This project is dual licensed under MIT and Apache-2.0.
-
-MIT: https://www.opensource.org/licenses/mit
-Apache-2.0: https://www.apache.org/licenses/license-2.0
diff --git a/packages/blockstore-idb/LICENSE-APACHE b/packages/blockstore-idb/LICENSE-APACHE
index 14478a3b..b09cd785 100644
--- a/packages/blockstore-idb/LICENSE-APACHE
+++ b/packages/blockstore-idb/LICENSE-APACHE
@@ -1,5 +1,201 @@
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-http://www.apache.org/licenses/LICENSE-2.0
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/blockstore-idb/README.md b/packages/blockstore-idb/README.md
index 7009d9ac..906b5879 100644
--- a/packages/blockstore-idb/README.md
+++ b/packages/blockstore-idb/README.md
@@ -9,6 +9,21 @@
# About
+
+
A Blockstore implementation for browsers that stores blocks in [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).
## Example
@@ -27,7 +42,7 @@ $ npm i blockstore-idb
## Browser `
@@ -41,8 +56,8 @@ Loading this module through a script tag will make it's exports available as `Bl
Licensed under either of
-- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / )
-- MIT ([LICENSE-MIT](LICENSE-MIT) / )
+- Apache 2.0, ([LICENSE-APACHE](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-idb/LICENSE-APACHE) / )
+- MIT ([LICENSE-MIT](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-idb/LICENSE-MIT) / )
# Contribute
diff --git a/packages/blockstore-idb/package.json b/packages/blockstore-idb/package.json
index f4a3ee04..c94a3c39 100644
--- a/packages/blockstore-idb/package.json
+++ b/packages/blockstore-idb/package.json
@@ -1,6 +1,6 @@
{
"name": "blockstore-idb",
- "version": "1.1.8",
+ "version": "3.0.1",
"description": "Blockstore implementation with IndexedDB backend",
"license": "Apache-2.0 OR MIT",
"homepage": "https://github.com/ipfs/js-stores/tree/main/packages/blockstore-idb#readme",
@@ -37,12 +37,98 @@
"import": "./dist/src/index.js"
}
},
- "eslintConfig": {
- "extends": "ipfs",
- "parserOptions": {
- "project": true,
- "sourceType": "module"
- }
+ "release": {
+ "branches": [
+ "main"
+ ],
+ "plugins": [
+ [
+ "@semantic-release/commit-analyzer",
+ {
+ "preset": "conventionalcommits",
+ "releaseRules": [
+ {
+ "breaking": true,
+ "release": "major"
+ },
+ {
+ "revert": true,
+ "release": "patch"
+ },
+ {
+ "type": "feat",
+ "release": "minor"
+ },
+ {
+ "type": "fix",
+ "release": "patch"
+ },
+ {
+ "type": "docs",
+ "release": "patch"
+ },
+ {
+ "type": "test",
+ "release": "patch"
+ },
+ {
+ "type": "deps",
+ "release": "patch"
+ },
+ {
+ "scope": "no-release",
+ "release": false
+ }
+ ]
+ }
+ ],
+ [
+ "@semantic-release/release-notes-generator",
+ {
+ "preset": "conventionalcommits",
+ "presetConfig": {
+ "types": [
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "chore",
+ "section": "Trivial Changes"
+ },
+ {
+ "type": "docs",
+ "section": "Documentation"
+ },
+ {
+ "type": "deps",
+ "section": "Dependencies"
+ },
+ {
+ "type": "test",
+ "section": "Tests"
+ }
+ ]
+ }
+ }
+ ],
+ "@semantic-release/changelog",
+ "@semantic-release/npm",
+ "@semantic-release/github",
+ [
+ "@semantic-release/git",
+ {
+ "assets": [
+ "CHANGELOG.md",
+ "package.json"
+ ]
+ }
+ ]
+ ]
},
"scripts": {
"clean": "aegir clean",
@@ -53,17 +139,22 @@
"test:chrome-webworker": "aegir test -t webworker",
"test:firefox": "aegir test -t browser -- --browser firefox",
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
- "dep-check": "aegir dep-check"
+ "dep-check": "aegir dep-check",
+ "release": "aegir release"
},
"dependencies": {
- "blockstore-core": "^4.0.0",
- "idb": "^8.0.0",
- "interface-blockstore": "^5.0.0",
- "interface-store": "^5.0.0",
- "multiformats": "^13.0.1"
+ "blockstore-core": "^6.0.0",
+ "idb": "^8.0.3",
+ "interface-blockstore": "^6.0.0",
+ "interface-store": "^7.0.0",
+ "it-all": "^3.0.9",
+ "it-to-buffer": "^4.0.10",
+ "multiformats": "^13.3.6",
+ "race-signal": "^2.0.0"
},
"devDependencies": {
- "aegir": "^42.2.3",
- "interface-blockstore-tests": "^6.0.0"
+ "aegir": "^47.0.16",
+ "interface-blockstore-tests": "^8.0.0",
+ "it-drain": "^3.0.10"
}
}
diff --git a/packages/blockstore-idb/src/index.ts b/packages/blockstore-idb/src/index.ts
index 51048a1d..c75ba256 100644
--- a/packages/blockstore-idb/src/index.ts
+++ b/packages/blockstore-idb/src/index.ts
@@ -12,17 +12,19 @@
* ```
*/
-import {
- BaseBlockstore,
- Errors
-} from 'blockstore-core'
-import { openDB, type IDBPDatabase, deleteDB } from 'idb'
+import { BaseBlockstore } from 'blockstore-core'
+import { openDB, deleteDB } from 'idb'
+import { OpenFailedError, PutFailedError, NotFoundError } from 'interface-store'
+import all from 'it-all'
+import toBuffer from 'it-to-buffer'
import { base32upper } from 'multiformats/bases/base32'
import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import * as Digest from 'multiformats/hashes/digest'
+import { raceSignal } from 'race-signal'
+import type { IDBPDatabase } from 'idb'
import type { Pair } from 'interface-blockstore'
-import type { AbortOptions, AwaitIterable } from 'interface-store'
+import type { AbortOptions, AwaitGenerator, AwaitIterable } from 'interface-store'
import type { MultibaseCodec } from 'multiformats/bases/interface'
export interface IDBBlockstoreInit {
@@ -77,7 +79,7 @@ export class IDBBlockstore extends BaseBlockstore {
}
})
} catch (err: any) {
- throw Errors.openFailedError(err)
+ throw new OpenFailedError(String(err))
}
}
@@ -85,21 +87,30 @@ export class IDBBlockstore extends BaseBlockstore {
this.db?.close()
}
- async put (key: CID, val: Uint8Array): Promise {
+ async put (key: CID, val: Uint8Array | AwaitIterable, options?: AbortOptions): Promise {
if (this.db == null) {
throw new Error('Blockstore needs to be opened.')
}
- try {
- await this.db.put(this.location, val, this.#encode(key))
+ let buf: Uint8Array
+
+ if (val instanceof Uint8Array) {
+ buf = val
+ } else {
+ buf = toBuffer(await all(val))
+ }
- return key
+ try {
+ options?.signal?.throwIfAborted()
+ await raceSignal(this.db.put(this.location, buf, this.#encode(key)), options?.signal)
} catch (err: any) {
- throw Errors.putFailedError(err)
+ throw new PutFailedError(String(err))
}
+
+ return key
}
- async get (key: CID): Promise {
+ async * get (key: CID, options?: AbortOptions): AwaitGenerator {
if (this.db == null) {
throw new Error('Blockstore needs to be opened.')
}
@@ -107,52 +118,64 @@ export class IDBBlockstore extends BaseBlockstore {
let val: Uint8Array | undefined
try {
- val = await this.db.get(this.location, this.#encode(key))
+ options?.signal?.throwIfAborted()
+ val = await raceSignal(this.db.get(this.location, this.#encode(key)), options?.signal)
} catch (err: any) {
- throw Errors.putFailedError(err)
+ throw new PutFailedError(String(err))
}
if (val === undefined) {
- throw Errors.notFoundError()
+ throw new NotFoundError()
}
- return val
+ yield val
}
- async delete (key: CID): Promise {
+ async delete (key: CID, options?: AbortOptions): Promise {
if (this.db == null) {
throw new Error('Blockstore needs to be opened.')
}
try {
- await this.db.delete(this.location, this.#encode(key))
+ options?.signal?.throwIfAborted()
+ await raceSignal(this.db.delete(this.location, this.#encode(key)), options?.signal)
} catch (err: any) {
- throw Errors.putFailedError(err)
+ throw new PutFailedError(String(err))
}
}
- async has (key: CID): Promise {
+ async has (key: CID, options?: AbortOptions): Promise {
if (this.db == null) {
throw new Error('Blockstore needs to be opened.')
}
try {
- return Boolean(await this.db.getKey(this.location, this.#encode(key)))
+ options?.signal?.throwIfAborted()
+ const result = await raceSignal(this.db.getKey(this.location, this.#encode(key)), options?.signal)
+
+ return Boolean(result)
} catch (err: any) {
- throw Errors.putFailedError(err)
+ throw new PutFailedError(String(err))
}
}
- async * getAll (options?: AbortOptions): AwaitIterable {
+ async * getAll (options?: AbortOptions): AwaitGenerator {
if (this.db == null) {
throw new Error('Blockstore needs to be opened.')
}
+ options?.signal?.throwIfAborted()
+
for (const key of await this.db.getAllKeys(this.location)) {
- const cid = this.#decode(key.toString()) // eslint-disable-line @typescript-eslint/no-base-to-string
- const block = await this.get(cid)
+ options?.signal?.throwIfAborted()
+ const cid = this.#decode(key.toString())
+
+ yield {
+ cid,
+ bytes: this.get(cid, options)
+ }
- yield { cid, block }
+ options?.signal?.throwIfAborted()
}
}
diff --git a/packages/blockstore-idb/test/index.spec.ts b/packages/blockstore-idb/test/index.spec.ts
index e4b9434a..3fca5e7e 100644
--- a/packages/blockstore-idb/test/index.spec.ts
+++ b/packages/blockstore-idb/test/index.spec.ts
@@ -2,10 +2,12 @@
import { expect } from 'aegir/chai'
import { interfaceBlockstoreTests } from 'interface-blockstore-tests'
+import all from 'it-all'
+import drain from 'it-drain'
import { CID } from 'multiformats/cid'
import { IDBBlockstore } from '../src/index.js'
-describe('IndexedDB Blockstore', function () {
+describe('IndexedDB Blockstore', () => {
describe('interface-blockstore (idb)', () => {
interfaceBlockstoreTests({
async setup () {
@@ -31,13 +33,13 @@ describe('IndexedDB Blockstore', function () {
it('should not explode under unreasonable load', function (done) {
this.timeout(10000)
- const updater = setInterval(async () => { // eslint-disable-line @typescript-eslint/no-misused-promises
+ const updater = setInterval(async () => {
try {
const key = CID.parse('QmaQwYWpchozXhFv8nvxprECWBSCEppN9dfd2VQiJfRo3F')
await store.put(key, Uint8Array.from([0, 1, 2, 3]))
await store.has(key)
- await store.get(key)
+ await drain(store.get(key))
} catch (err) {
clearInterval(updater)
clearInterval(mutatorQuery)
@@ -46,16 +48,16 @@ describe('IndexedDB Blockstore', function () {
}
}, 0)
- const mutatorQuery = setInterval(async () => { // eslint-disable-line @typescript-eslint/no-misused-promises
+ const mutatorQuery = setInterval(async () => {
try {
for await (const { cid } of store.getAll()) {
- await store.get(cid)
+ await drain(store.get(cid))
const otherKey = CID.parse('QmaQwYWpchozXhFv8nvxprECWBSCEppN9dfd2VQiJfRo3F')
const otherValue = Uint8Array.from([0, 1, 2, 3])
await store.put(otherKey, otherValue)
- const res = await store.get(otherKey)
- expect(res).to.deep.equal(otherValue)
+ const res = await all(store.get(otherKey))
+ expect(res).to.deep.equal([otherValue])
}
} catch (err) {
clearInterval(updater)
@@ -65,7 +67,7 @@ describe('IndexedDB Blockstore', function () {
}
}, 0)
- const readOnlyQuery = setInterval(async () => { // eslint-disable-line @typescript-eslint/no-misused-promises
+ const readOnlyQuery = setInterval(async () => {
try {
for await (const { cid } of store.getAll()) {
await store.has(cid)
diff --git a/packages/blockstore-idb/typedoc.json b/packages/blockstore-idb/typedoc.json
index f599dc72..db0b0747 100644
--- a/packages/blockstore-idb/typedoc.json
+++ b/packages/blockstore-idb/typedoc.json
@@ -1,4 +1,5 @@
{
+ "readme": "none",
"entryPoints": [
"./src/index.ts"
]
diff --git a/packages/blockstore-level/CHANGELOG.md b/packages/blockstore-level/CHANGELOG.md
index dd3a82f7..83a4f445 100644
--- a/packages/blockstore-level/CHANGELOG.md
+++ b/packages/blockstore-level/CHANGELOG.md
@@ -1,3 +1,83 @@
+## [blockstore-level-v3.0.2](https://github.com/ipfs/js-stores/compare/blockstore-level-3.0.1...blockstore-level-3.0.2) (2025-10-03)
+
+### Dependencies
+
+* bump level from 8.0.1 to 10.0.0 ([#356](https://github.com/ipfs/js-stores/issues/356)) ([c0ec61f](https://github.com/ipfs/js-stores/commit/c0ec61fe965e3bad9d607a0bd3a3c750f00f41d0))
+
+## [blockstore-level-v3.0.1](https://github.com/ipfs/js-stores/compare/blockstore-level-3.0.0...blockstore-level-3.0.1) (2025-10-03)
+
+### Bug Fixes
+
+* update sibling deps ([3f73b3d](https://github.com/ipfs/js-stores/commit/3f73b3d53ea2d86d0f5c3f06785c0bfc30e8b5e9))
+
+## [blockstore-level-v3.0.0](https://github.com/ipfs/js-stores/compare/blockstore-level-2.0.5...blockstore-level-3.0.0) (2025-10-03)
+
+### ⚠ BREAKING CHANGES
+
+* blockstore.get and similar now return streams of bytes
+
+### Features
+
+* streaming blockstores ([#358](https://github.com/ipfs/js-stores/issues/358)) ([4dbb136](https://github.com/ipfs/js-stores/commit/4dbb1362d20fc87fcdd261568dca297972f9bc08))
+
+## [blockstore-level-v2.0.5](https://github.com/ipfs/js-stores/compare/blockstore-level-2.0.4...blockstore-level-2.0.5) (2025-09-02)
+
+### Bug Fixes
+
+* readme typos ([e6b5653](https://github.com/ipfs/js-stores/commit/e6b56533b68e6ed9b90ca3e3f35af8577041a9a2))
+
+### Dependencies
+
+* bump race-signal from 1.1.3 to 2.0.0 ([#355](https://github.com/ipfs/js-stores/issues/355)) ([518fee8](https://github.com/ipfs/js-stores/commit/518fee89d3430534c0ec39551e920447fd558581))
+
+## [blockstore-level-v2.0.4](https://github.com/ipfs/js-stores/compare/blockstore-level-2.0.3...blockstore-level-2.0.4) (2025-09-02)
+
+### Bug Fixes
+
+* deprecate blockstore-level and datastore-fs ([#353](https://github.com/ipfs/js-stores/issues/353)) ([ebc7912](https://github.com/ipfs/js-stores/commit/ebc7912696d5bd9dc991ece5f0c0d4acfb1f9400))
+
+## [blockstore-level-v2.0.3](https://github.com/ipfs/js-stores/compare/blockstore-level-2.0.2...blockstore-level-2.0.3) (2025-05-28)
+
+### Bug Fixes
+
+* improve abort signal support ([#350](https://github.com/ipfs/js-stores/issues/350)) ([e17d770](https://github.com/ipfs/js-stores/commit/e17d770cc2fcee77cb0152a855abf162e5a91a99))
+
+## [blockstore-level-v2.0.2](https://github.com/ipfs/js-stores/compare/blockstore-level-2.0.1...blockstore-level-2.0.2) (2025-05-26)
+
+### Dependencies
+
+* bump aegir from 44.1.4 to 47.0.16 ([#349](https://github.com/ipfs/js-stores/issues/349)) ([d33d15f](https://github.com/ipfs/js-stores/commit/d33d15f0638856530d0e1868c723e5567abf27e6))
+
+## [blockstore-level-v2.0.1](https://github.com/ipfs/js-stores/compare/blockstore-level-2.0.0...blockstore-level-2.0.1) (2024-09-13)
+
+### Bug Fixes
+
+* restore release config to package.json ([#321](https://github.com/ipfs/js-stores/issues/321)) ([4f14fb0](https://github.com/ipfs/js-stores/commit/4f14fb09d65a3460b548b59557af108412dc9156))
+
+### Dependencies
+
+* **dev:** bump aegir from 42.2.11 to 44.1.0 ([#316](https://github.com/ipfs/js-stores/issues/316)) ([581a467](https://github.com/ipfs/js-stores/commit/581a46720832916bea11efa2476eb85a00bae9d4))
+
+## blockstore-level [2.0.0](https://github.com/ipfs/js-stores/compare/blockstore-level-1.1.8...blockstore-level-2.0.0) (2024-08-02)
+
+
+### ⚠ BREAKING CHANGES
+
+* To detect the type of error thrown, use `.name` instead of `.code`
+
+### Features
+
+* use `.name` property for errors instead of `.code` ([#315](https://github.com/ipfs/js-stores/issues/315)) ([dacd6ce](https://github.com/ipfs/js-stores/commit/dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd))
+
+
+
+### Dependencies
+
+* **blockstore-core:** upgraded to 5.0.0
+* **interface-blockstore:** upgraded to 5.3.0
+* **interface-store:** upgraded to 6.0.0
+* **interface-blockstore-tests:** upgraded to 7.0.0
+
## blockstore-level [1.1.8](https://github.com/ipfs/js-stores/compare/blockstore-level-v1.1.7...blockstore-level-1.1.8) (2024-02-12)
diff --git a/packages/blockstore-level/CODE_OF_CONDUCT.md b/packages/blockstore-level/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..6b0fa54c
--- /dev/null
+++ b/packages/blockstore-level/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Contributor Code of Conduct
+
+This project follows the [`IPFS Community Code of Conduct`](https://github.com/ipfs/community/blob/master/code-of-conduct.md)
diff --git a/packages/blockstore-level/LICENSE b/packages/blockstore-level/LICENSE
deleted file mode 100644
index 20ce483c..00000000
--- a/packages/blockstore-level/LICENSE
+++ /dev/null
@@ -1,4 +0,0 @@
-This project is dual licensed under MIT and Apache-2.0.
-
-MIT: https://www.opensource.org/licenses/mit
-Apache-2.0: https://www.apache.org/licenses/license-2.0
diff --git a/packages/blockstore-level/LICENSE-APACHE b/packages/blockstore-level/LICENSE-APACHE
index 14478a3b..b09cd785 100644
--- a/packages/blockstore-level/LICENSE-APACHE
+++ b/packages/blockstore-level/LICENSE-APACHE
@@ -1,5 +1,201 @@
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-http://www.apache.org/licenses/LICENSE-2.0
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/blockstore-level/README.md b/packages/blockstore-level/README.md
index a7cdfd73..134deee1 100644
--- a/packages/blockstore-level/README.md
+++ b/packages/blockstore-level/README.md
@@ -1,5 +1,9 @@
# blockstore-level
+## ⚠️ Deprecation Warning
+
+**This package is deprecated. Instead, use `blockstore-fs` in Node.js, and `blockstore-idb` in browsers.**
+
[](https://ipfs.tech)
[](https://discuss.ipfs.tech)
[](https://codecov.io/gh/ipfs/js-stores)
@@ -9,9 +13,24 @@
# About
-A Blockstore implementation that uses a flavour of [Level](https://leveljs.org/) as a backend.
+
+
+⚠️ This package is deprecated. Instead, use `blockstore-fs` in Node.js, and `blockstore-idb` in browsers.
+
+A Blockstore implementation that uses a flavour of [Level](https://leveljs.org/) as a backend.
## Example
@@ -29,7 +48,7 @@ $ npm i blockstore-level
## Browser `
@@ -43,8 +62,8 @@ Loading this module through a script tag will make it's exports available as `Bl
Licensed under either of
-- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / )
-- MIT ([LICENSE-MIT](LICENSE-MIT) / )
+- Apache 2.0, ([LICENSE-APACHE](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-level/LICENSE-APACHE) / )
+- MIT ([LICENSE-MIT](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-level/LICENSE-MIT) / )
# Contribute
diff --git a/packages/blockstore-level/package.json b/packages/blockstore-level/package.json
index 20cb946d..d313ac1c 100644
--- a/packages/blockstore-level/package.json
+++ b/packages/blockstore-level/package.json
@@ -1,6 +1,6 @@
{
"name": "blockstore-level",
- "version": "1.1.8",
+ "version": "3.0.2",
"description": "Blockstore implementation with level(up|down) backend",
"license": "Apache-2.0 OR MIT",
"homepage": "https://github.com/ipfs/js-stores/tree/main/packages/blockstore-level#readme",
@@ -38,12 +38,98 @@
"import": "./dist/src/index.js"
}
},
- "eslintConfig": {
- "extends": "ipfs",
- "parserOptions": {
- "project": true,
- "sourceType": "module"
- }
+ "release": {
+ "branches": [
+ "main"
+ ],
+ "plugins": [
+ [
+ "@semantic-release/commit-analyzer",
+ {
+ "preset": "conventionalcommits",
+ "releaseRules": [
+ {
+ "breaking": true,
+ "release": "major"
+ },
+ {
+ "revert": true,
+ "release": "patch"
+ },
+ {
+ "type": "feat",
+ "release": "minor"
+ },
+ {
+ "type": "fix",
+ "release": "patch"
+ },
+ {
+ "type": "docs",
+ "release": "patch"
+ },
+ {
+ "type": "test",
+ "release": "patch"
+ },
+ {
+ "type": "deps",
+ "release": "patch"
+ },
+ {
+ "scope": "no-release",
+ "release": false
+ }
+ ]
+ }
+ ],
+ [
+ "@semantic-release/release-notes-generator",
+ {
+ "preset": "conventionalcommits",
+ "presetConfig": {
+ "types": [
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "chore",
+ "section": "Trivial Changes"
+ },
+ {
+ "type": "docs",
+ "section": "Documentation"
+ },
+ {
+ "type": "deps",
+ "section": "Dependencies"
+ },
+ {
+ "type": "test",
+ "section": "Tests"
+ }
+ ]
+ }
+ }
+ ],
+ "@semantic-release/changelog",
+ "@semantic-release/npm",
+ "@semantic-release/github",
+ [
+ "@semantic-release/git",
+ {
+ "assets": [
+ "CHANGELOG.md",
+ "package.json"
+ ]
+ }
+ ]
+ ]
},
"scripts": {
"clean": "aegir clean",
@@ -56,19 +142,24 @@
"test:firefox": "aegir test -t browser -- --browser firefox",
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
"test:electron-main": "aegir test -t electron-main",
- "dep-check": "aegir dep-check"
+ "dep-check": "aegir dep-check",
+ "release": "aegir release"
},
"dependencies": {
- "blockstore-core": "^4.0.0",
- "interface-blockstore": "^5.0.0",
- "interface-store": "^5.0.0",
- "level": "^8.0.1",
- "multiformats": "^13.0.1"
+ "blockstore-core": "^6.0.0",
+ "interface-blockstore": "^6.0.0",
+ "interface-store": "^7.0.0",
+ "it-all": "^3.0.9",
+ "it-to-buffer": "^4.0.10",
+ "level": "^10.0.0",
+ "multiformats": "^13.3.6",
+ "race-signal": "^2.0.0",
+ "uint8arrays": "^5.1.0"
},
"devDependencies": {
- "aegir": "^42.2.3",
- "interface-blockstore-tests": "^6.0.0",
+ "aegir": "^47.0.16",
+ "interface-blockstore-tests": "^8.0.0",
"ipfs-utils": "^9.0.14",
- "memory-level": "^1.0.0"
+ "memory-level": "^3.1.0"
}
}
diff --git a/packages/blockstore-level/src/index.ts b/packages/blockstore-level/src/index.ts
index 21383ce3..a1094391 100644
--- a/packages/blockstore-level/src/index.ts
+++ b/packages/blockstore-level/src/index.ts
@@ -1,9 +1,9 @@
/**
* @packageDocumentation
*
- * A Blockstore implementation that uses a flavour of [Level](https://leveljs.org/) as a backend.
+ * ⚠️ This package is deprecated. Instead, use `blockstore-fs` in Node.js, and `blockstore-idb` in browsers.
*
- * N.b. this is here largely for the sake of completeness, in node you should probably use FSDatastore, in browsers you should probably use IDBDatastore.
+ * A Blockstore implementation that uses a flavour of [Level](https://leveljs.org/) as a backend.
*
* @example
*
@@ -14,14 +14,19 @@
* ```
*/
-import { BaseBlockstore, Errors } from 'blockstore-core'
+import { BaseBlockstore } from 'blockstore-core'
+import { DeleteFailedError, GetFailedError, NotFoundError, OpenFailedError, PutFailedError } from 'interface-store'
+import all from 'it-all'
+import toBuffer from 'it-to-buffer'
import { Level } from 'level'
import { base32upper } from 'multiformats/bases/base32'
import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import * as Digest from 'multiformats/hashes/digest'
+import { raceSignal } from 'race-signal'
+import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
import type { Pair } from 'interface-blockstore'
-import type { AbortOptions, AwaitIterable } from 'interface-store'
+import type { AbortOptions, AwaitGenerator, AwaitIterable } from 'interface-store'
import type { DatabaseOptions, OpenOptions, IteratorOptions } from 'level'
import type { MultibaseCodec } from 'multiformats/bases/interface'
@@ -73,52 +78,60 @@ export class LevelBlockstore extends BaseBlockstore {
try {
await this.db.open(this.opts)
} catch (err: any) {
- throw Errors.openFailedError(err)
+ throw new OpenFailedError(String(err))
}
}
- async put (key: CID, value: Uint8Array): Promise {
+ async put (key: CID, value: Uint8Array | AwaitIterable, options?: AbortOptions): Promise {
try {
- await this.db.put(this.#encode(key), value)
+ options?.signal?.throwIfAborted()
+
+ let buf: Uint8Array
+
+ if (value instanceof Uint8Array) {
+ buf = value
+ } else {
+ buf = toBuffer(await raceSignal(all(value), options?.signal))
+ }
- return key
+ await raceSignal(this.db.put(this.#encode(key), buf), options?.signal)
} catch (err: any) {
- throw Errors.putFailedError(err)
+ throw new PutFailedError(String(err))
}
+
+ return key
}
- async get (key: CID): Promise {
- let data
+ async * get (key: CID, options?: AbortOptions): AwaitGenerator {
+ let buf
+
try {
- data = await this.db.get(this.#encode(key))
+ options?.signal?.throwIfAborted()
+ buf = await raceSignal(this.db.get(this.#encode(key)), options?.signal)
} catch (err: any) {
- if (err.notFound != null) {
- throw Errors.notFoundError(err)
- }
+ throw new GetFailedError(String(err))
+ }
- throw Errors.getFailedError(err)
+ if (buf == null) {
+ throw new NotFoundError()
}
- return data
+
+ yield buf
}
- async has (key: CID): Promise {
- try {
- await this.db.get(this.#encode(key))
- } catch (err: any) {
- if (err.notFound != null) {
- return false
- }
+ async has (key: CID, options?: AbortOptions): Promise {
+ options?.signal?.throwIfAborted()
+ const buf = await raceSignal(this.db.get(this.#encode(key)), options?.signal)
- throw err
- }
- return true
+ return buf != null
}
- async delete (key: CID): Promise {
+ async delete (key: CID, options?: AbortOptions): Promise {
try {
- await this.db.del(this.#encode(key))
+ options?.signal?.throwIfAborted()
+ await raceSignal(this.db.del(this.#encode(key)), options?.signal)
} catch (err: any) {
- throw Errors.deleteFailedError(err)
+ throw new DeleteFailedError(String(err))
}
}
@@ -126,13 +139,17 @@ export class LevelBlockstore extends BaseBlockstore {
await this.db.close()
}
- async * getAll (options?: AbortOptions | undefined): AwaitIterable {
- for await (const { key, value } of this.#query({ values: true })) {
- yield { cid: this.#decode(key), block: value }
+ async * getAll (options?: AbortOptions | undefined): AwaitGenerator {
+ options?.signal?.throwIfAborted()
+
+ for await (const { key, value } of this.#query({ values: true }, options)) {
+ yield { cid: this.#decode(key), bytes: value }
}
}
- async * #query (opts: { values: boolean, prefix?: string }): AsyncIterable<{ key: string, value: Uint8Array }> {
+ async * #query (opts: { values: boolean, prefix?: string }, options?: AbortOptions): AwaitGenerator<{ key: string, value: AwaitGenerator }> {
+ options?.signal?.throwIfAborted()
+
const iteratorOpts: IteratorOptions = {
keys: true,
keyEncoding: 'buffer',
@@ -152,8 +169,16 @@ export class LevelBlockstore extends BaseBlockstore {
try {
for await (const [key, value] of li) {
- // @ts-expect-error key is a buffer because keyEncoding is "buffer"
- yield { key: new TextDecoder().decode(key), value }
+ options?.signal?.throwIfAborted()
+
+ yield {
+ // @ts-expect-error key is buffer even though types say string
+ key: uint8ArrayToString(key),
+ value: (async function * () {
+ yield value
+ })()
+ }
+ options?.signal?.throwIfAborted()
}
} finally {
await li.close()
diff --git a/packages/blockstore-level/typedoc.json b/packages/blockstore-level/typedoc.json
index f599dc72..db0b0747 100644
--- a/packages/blockstore-level/typedoc.json
+++ b/packages/blockstore-level/typedoc.json
@@ -1,4 +1,5 @@
{
+ "readme": "none",
"entryPoints": [
"./src/index.ts"
]
diff --git a/packages/blockstore-s3/CHANGELOG.md b/packages/blockstore-s3/CHANGELOG.md
index 7e43b561..0f98f360 100644
--- a/packages/blockstore-s3/CHANGELOG.md
+++ b/packages/blockstore-s3/CHANGELOG.md
@@ -1,3 +1,85 @@
+## [blockstore-s3-v3.0.1](https://github.com/ipfs/js-stores/compare/blockstore-s3-3.0.0...blockstore-s3-3.0.1) (2025-10-03)
+
+### Bug Fixes
+
+* update sibling deps ([3f73b3d](https://github.com/ipfs/js-stores/commit/3f73b3d53ea2d86d0f5c3f06785c0bfc30e8b5e9))
+
+## [blockstore-s3-v3.0.0](https://github.com/ipfs/js-stores/compare/blockstore-s3-2.0.5...blockstore-s3-3.0.0) (2025-10-03)
+
+### ⚠ BREAKING CHANGES
+
+* blockstore.get and similar now return streams of bytes
+
+### Features
+
+* streaming blockstores ([#358](https://github.com/ipfs/js-stores/issues/358)) ([4dbb136](https://github.com/ipfs/js-stores/commit/4dbb1362d20fc87fcdd261568dca297972f9bc08))
+
+### Trivial Changes
+
+* bump sinon from 20.0.0 to 21.0.0 ([#351](https://github.com/ipfs/js-stores/issues/351)) ([f24dd4f](https://github.com/ipfs/js-stores/commit/f24dd4f9b6eb681b1f9652409a558a8bcc50f4a4))
+
+## [blockstore-s3-v2.0.5](https://github.com/ipfs/js-stores/compare/blockstore-s3-2.0.4...blockstore-s3-2.0.5) (2025-09-02)
+
+### Bug Fixes
+
+* deprecate blockstore-level and datastore-fs ([#353](https://github.com/ipfs/js-stores/issues/353)) ([ebc7912](https://github.com/ipfs/js-stores/commit/ebc7912696d5bd9dc991ece5f0c0d4acfb1f9400))
+
+## [blockstore-s3-v2.0.4](https://github.com/ipfs/js-stores/compare/blockstore-s3-2.0.3...blockstore-s3-2.0.4) (2025-05-28)
+
+### Bug Fixes
+
+* improve abort signal support ([#350](https://github.com/ipfs/js-stores/issues/350)) ([e17d770](https://github.com/ipfs/js-stores/commit/e17d770cc2fcee77cb0152a855abf162e5a91a99))
+
+## [blockstore-s3-v2.0.3](https://github.com/ipfs/js-stores/compare/blockstore-s3-2.0.2...blockstore-s3-2.0.3) (2025-05-26)
+
+### Dependencies
+
+* bump aegir from 44.1.4 to 47.0.16 ([#349](https://github.com/ipfs/js-stores/issues/349)) ([d33d15f](https://github.com/ipfs/js-stores/commit/d33d15f0638856530d0e1868c723e5567abf27e6))
+* **dev:** bump sinon from 19.0.5 to 20.0.0 ([#337](https://github.com/ipfs/js-stores/issues/337)) ([ec2a54a](https://github.com/ipfs/js-stores/commit/ec2a54a1ef2ecbee862d17710430a51b79063183))
+
+## [blockstore-s3-v2.0.2](https://github.com/ipfs/js-stores/compare/blockstore-s3-2.0.1...blockstore-s3-2.0.2) (2024-09-13)
+
+### Dependencies
+
+* **dev:** bump sinon from 18.0.1 to 19.0.2 ([#322](https://github.com/ipfs/js-stores/issues/322)) ([8ea2df5](https://github.com/ipfs/js-stores/commit/8ea2df5c8f531b086b10130b8a3ce59a4d5bc2ba))
+
+## [blockstore-s3-v2.0.1](https://github.com/ipfs/js-stores/compare/blockstore-s3-2.0.0...blockstore-s3-2.0.1) (2024-09-13)
+
+### Bug Fixes
+
+* restore release config to package.json ([#321](https://github.com/ipfs/js-stores/issues/321)) ([4f14fb0](https://github.com/ipfs/js-stores/commit/4f14fb09d65a3460b548b59557af108412dc9156))
+
+### Dependencies
+
+* **dev:** bump aegir from 42.2.11 to 44.1.0 ([#316](https://github.com/ipfs/js-stores/issues/316)) ([581a467](https://github.com/ipfs/js-stores/commit/581a46720832916bea11efa2476eb85a00bae9d4))
+
+## blockstore-s3 [2.0.0](https://github.com/ipfs/js-stores/compare/blockstore-s3-1.0.16...blockstore-s3-2.0.0) (2024-08-02)
+
+
+### ⚠ BREAKING CHANGES
+
+* To detect the type of error thrown, use `.name` instead of `.code`
+
+### Features
+
+* use `.name` property for errors instead of `.code` ([#315](https://github.com/ipfs/js-stores/issues/315)) ([dacd6ce](https://github.com/ipfs/js-stores/commit/dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd))
+
+
+
+### Dependencies
+
+* **blockstore-core:** upgraded to 5.0.0
+* **interface-blockstore:** upgraded to 5.3.0
+* **interface-store:** upgraded to 6.0.0
+* **interface-blockstore-tests:** upgraded to 7.0.0
+
+## blockstore-s3 [1.0.16](https://github.com/ipfs/js-stores/compare/blockstore-s3-1.0.15...blockstore-s3-1.0.16) (2024-08-01)
+
+
+### Dependencies
+
+* **dev:** bump sinon from 17.0.2 to 18.0.0 ([#308](https://github.com/ipfs/js-stores/issues/308)) ([0fbfe11](https://github.com/ipfs/js-stores/commit/0fbfe1112a102055d75f077ff799fbb1001e6aa7))
+
## blockstore-s3 [1.0.15](https://github.com/ipfs/js-stores/compare/blockstore-s3-v1.0.14...blockstore-s3-1.0.15) (2024-02-12)
diff --git a/packages/blockstore-s3/CODE_OF_CONDUCT.md b/packages/blockstore-s3/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..6b0fa54c
--- /dev/null
+++ b/packages/blockstore-s3/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Contributor Code of Conduct
+
+This project follows the [`IPFS Community Code of Conduct`](https://github.com/ipfs/community/blob/master/code-of-conduct.md)
diff --git a/packages/blockstore-s3/LICENSE b/packages/blockstore-s3/LICENSE
deleted file mode 100644
index 20ce483c..00000000
--- a/packages/blockstore-s3/LICENSE
+++ /dev/null
@@ -1,4 +0,0 @@
-This project is dual licensed under MIT and Apache-2.0.
-
-MIT: https://www.opensource.org/licenses/mit
-Apache-2.0: https://www.apache.org/licenses/license-2.0
diff --git a/packages/blockstore-s3/LICENSE-APACHE b/packages/blockstore-s3/LICENSE-APACHE
index 14478a3b..b09cd785 100644
--- a/packages/blockstore-s3/LICENSE-APACHE
+++ b/packages/blockstore-s3/LICENSE-APACHE
@@ -1,5 +1,201 @@
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-http://www.apache.org/licenses/LICENSE-2.0
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/blockstore-s3/README.md b/packages/blockstore-s3/README.md
index fa1f519e..9e36a0e3 100644
--- a/packages/blockstore-s3/README.md
+++ b/packages/blockstore-s3/README.md
@@ -9,6 +9,21 @@
# About
+
+
A Blockstore implementation that stores blocks on Amazon S3.
## Example - Quickstart
@@ -50,7 +65,7 @@ $ npm i blockstore-s3
## Browser `
@@ -64,8 +79,8 @@ Loading this module through a script tag will make it's exports available as `Bl
Licensed under either of
-- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / )
-- MIT ([LICENSE-MIT](LICENSE-MIT) / )
+- Apache 2.0, ([LICENSE-APACHE](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-s3/LICENSE-APACHE) / )
+- MIT ([LICENSE-MIT](https://github.com/ipfs/js-stores/blob/main/packages/blockstore-s3/LICENSE-MIT) / )
# Contribute
diff --git a/packages/blockstore-s3/examples/helia/index.js b/packages/blockstore-s3/examples/helia/index.js
index 6940f74a..4a989374 100644
--- a/packages/blockstore-s3/examples/helia/index.js
+++ b/packages/blockstore-s3/examples/helia/index.js
@@ -1,8 +1,10 @@
-import { createHelia } from 'helia'
-import { unixfs } from '@helia/unixfs'
-import toBuffer from 'it-to-buffer'
+/* eslint-disable no-console */
+
import { S3 } from '@aws-sdk/client-s3'
+import { unixfs } from '@helia/unixfs'
import { BlockstoreS3 } from 'blockstore-s3'
+import { createHelia } from 'helia'
+import toBuffer from 'it-to-buffer'
async function main () {
// Configure S3 as normal
@@ -18,7 +20,7 @@ async function main () {
// Create a new Helia node with our S3 backed Repo
console.log('Start Helia')
- const node = await createHelia({
+ const helia = await createHelia({
blockstore
})
@@ -45,7 +47,7 @@ async function main () {
// After everything is done, shut the node down
// We don't need to worry about catching errors here
console.log('\n\nStopping the node')
- await node.stop()
+ await helia.stop()
}
main()
diff --git a/packages/blockstore-s3/package.json b/packages/blockstore-s3/package.json
index 134f3244..57d34df5 100644
--- a/packages/blockstore-s3/package.json
+++ b/packages/blockstore-s3/package.json
@@ -1,6 +1,6 @@
{
"name": "blockstore-s3",
- "version": "1.0.15",
+ "version": "3.0.1",
"description": "IPFS blockstore implementation backed by s3",
"license": "Apache-2.0 OR MIT",
"homepage": "https://github.com/ipfs/js-stores/tree/main/packages/blockstore-s3#readme",
@@ -36,12 +36,98 @@
"import": "./dist/src/index.js"
}
},
- "eslintConfig": {
- "extends": "ipfs",
- "parserOptions": {
- "project": true,
- "sourceType": "module"
- }
+ "release": {
+ "branches": [
+ "main"
+ ],
+ "plugins": [
+ [
+ "@semantic-release/commit-analyzer",
+ {
+ "preset": "conventionalcommits",
+ "releaseRules": [
+ {
+ "breaking": true,
+ "release": "major"
+ },
+ {
+ "revert": true,
+ "release": "patch"
+ },
+ {
+ "type": "feat",
+ "release": "minor"
+ },
+ {
+ "type": "fix",
+ "release": "patch"
+ },
+ {
+ "type": "docs",
+ "release": "patch"
+ },
+ {
+ "type": "test",
+ "release": "patch"
+ },
+ {
+ "type": "deps",
+ "release": "patch"
+ },
+ {
+ "scope": "no-release",
+ "release": false
+ }
+ ]
+ }
+ ],
+ [
+ "@semantic-release/release-notes-generator",
+ {
+ "preset": "conventionalcommits",
+ "presetConfig": {
+ "types": [
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "chore",
+ "section": "Trivial Changes"
+ },
+ {
+ "type": "docs",
+ "section": "Documentation"
+ },
+ {
+ "type": "deps",
+ "section": "Dependencies"
+ },
+ {
+ "type": "test",
+ "section": "Tests"
+ }
+ ]
+ }
+ }
+ ],
+ "@semantic-release/changelog",
+ "@semantic-release/npm",
+ "@semantic-release/github",
+ [
+ "@semantic-release/git",
+ {
+ "assets": [
+ "CHANGELOG.md",
+ "package.json"
+ ]
+ }
+ ]
+ ]
},
"scripts": {
"clean": "aegir clean",
@@ -54,22 +140,25 @@
"test:firefox": "aegir test -t browser -- --browser firefox",
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
"test:electron-main": "aegir test -t electron-main",
- "dep-check": "aegir dep-check"
+ "dep-check": "aegir dep-check",
+ "release": "aegir release"
},
"dependencies": {
- "@aws-sdk/client-s3": "^3.511.0",
- "blockstore-core": "^4.0.0",
- "interface-blockstore": "^5.0.0",
- "interface-store": "^5.0.0",
- "it-to-buffer": "^4.0.5",
- "multiformats": "^13.0.1",
- "uint8arrays": "^5.0.2"
+ "@aws-sdk/client-s3": "^3.817.0",
+ "blockstore-core": "^6.0.0",
+ "interface-blockstore": "^6.0.0",
+ "interface-store": "^7.0.0",
+ "multiformats": "^13.3.6",
+ "uint8arrays": "^5.1.0"
},
"devDependencies": {
- "@types/sinon": "^17.0.3",
- "aegir": "^42.2.3",
- "interface-blockstore-tests": "^6.0.0",
- "p-defer": "^4.0.0",
- "sinon": "^17.0.1"
+ "@types/sinon": "^21.0.0",
+ "@types/xmldom": "^0.1.34",
+ "aegir": "^47.0.16",
+ "interface-blockstore-tests": "^8.0.0",
+ "it-drain": "^3.0.10",
+ "p-defer": "^4.0.1",
+ "sinon": "^21.0.0",
+ "xmldom": "^0.6.0"
}
}
diff --git a/packages/blockstore-s3/src/index.ts b/packages/blockstore-s3/src/index.ts
index c41b6397..02535bb3 100644
--- a/packages/blockstore-s3/src/index.ts
+++ b/packages/blockstore-s3/src/index.ts
@@ -40,13 +40,13 @@ import {
ListObjectsV2Command
} from '@aws-sdk/client-s3'
import { BaseBlockstore } from 'blockstore-core/base'
-import * as Errors from 'blockstore-core/errors'
-import toBuffer from 'it-to-buffer'
-import { fromString as unint8arrayFromString } from 'uint8arrays'
-import { NextToLast, type ShardingStrategy } from './sharding.js'
+import { DeleteFailedError, GetFailedError, HasFailedError, NotFoundError, OpenFailedError, PutFailedError } from 'interface-store'
+import { fromString as uint8arrayFromString } from 'uint8arrays'
+import { NextToLast } from './sharding.js'
+import type { ShardingStrategy } from './sharding.js'
import type { S3 } from '@aws-sdk/client-s3'
import type { Pair } from 'interface-blockstore'
-import type { AbortOptions } from 'interface-store'
+import type { AbortOptions, AwaitGenerator } from 'interface-store'
import type { CID } from 'multiformats/cid'
export type { ShardingStrategy }
@@ -94,6 +94,7 @@ export class S3Blockstore extends BaseBlockstore {
*/
async put (key: CID, val: Uint8Array, options?: AbortOptions): Promise {
try {
+ options?.signal?.throwIfAborted()
await this.s3.send(
new PutObjectCommand({
Bucket: this.bucket,
@@ -106,15 +107,16 @@ export class S3Blockstore extends BaseBlockstore {
return key
} catch (err: any) {
- throw Errors.putFailedError(err)
+ throw new PutFailedError(String(err))
}
}
/**
* Read from s3
*/
- async get (key: CID, options?: AbortOptions): Promise {
+ async * get (key: CID, options?: AbortOptions): AwaitGenerator {
try {
+ options?.signal?.throwIfAborted()
const data = await this.s3.send(
new GetObjectCommand({
Bucket: this.bucket,
@@ -130,26 +132,32 @@ export class S3Blockstore extends BaseBlockstore {
// If a body was returned, ensure it's a Uint8Array
if (data.Body instanceof Uint8Array) {
- return data.Body
+ yield data.Body
+ return
}
if (typeof data.Body === 'string') {
- return unint8arrayFromString(data.Body)
+ yield uint8arrayFromString(data.Body)
+ return
}
if (data.Body instanceof Blob) {
- const buf = await data.Body.arrayBuffer()
+ yield * data.Body.stream()
+ return
+ }
- return new Uint8Array(buf, 0, buf.byteLength)
+ if (data.Body[Symbol.asyncIterator] != null) {
+ yield * data.Body
+ return
}
- // @ts-expect-error s3 types define their own Blob as an empty interface
- return await toBuffer(data.Body)
+ throw new Error(`Unknown body type ${data.Body} (typeof ${typeof data.Body})`)
} catch (err: any) {
if (err.statusCode === 404) {
- throw Errors.notFoundError(err)
+ throw new NotFoundError(String(err))
}
- throw err
+
+ throw new GetFailedError(String(err))
}
}
@@ -158,6 +166,7 @@ export class S3Blockstore extends BaseBlockstore {
*/
async has (key: CID, options?: AbortOptions): Promise {
try {
+ options?.signal?.throwIfAborted()
await this.s3.send(
new HeadObjectCommand({
Bucket: this.bucket,
@@ -179,7 +188,7 @@ export class S3Blockstore extends BaseBlockstore {
return false
}
- throw err
+ throw new HasFailedError(String(err))
}
}
@@ -188,6 +197,7 @@ export class S3Blockstore extends BaseBlockstore {
*/
async delete (key: CID, options?: AbortOptions): Promise {
try {
+ options?.signal?.throwIfAborted()
await this.s3.send(
new DeleteObjectCommand({
Bucket: this.bucket,
@@ -197,15 +207,17 @@ export class S3Blockstore extends BaseBlockstore {
}
)
} catch (err: any) {
- throw Errors.deleteFailedError(err)
+ throw new DeleteFailedError(String(err))
}
}
- async * getAll (options?: AbortOptions): AsyncIterable {
+ async * getAll (options?: AbortOptions): AwaitGenerator {
const params: Record = {}
try {
while (true) {
+ options?.signal?.throwIfAborted()
+
const data = await this.s3.send(
new ListObjectsV2Command({
Bucket: this.bucket,
@@ -219,7 +231,7 @@ export class S3Blockstore extends BaseBlockstore {
return
}
- if (data == null || data.Contents == null) {
+ if (data?.Contents == null) {
throw new Error('Not found')
}
@@ -233,7 +245,7 @@ export class S3Blockstore extends BaseBlockstore {
yield {
cid,
- block: await this.get(cid, options)
+ bytes: this.get(cid, options)
}
}
@@ -249,7 +261,7 @@ export class S3Blockstore extends BaseBlockstore {
break
}
} catch (err: any) {
- throw new Error(err.code)
+ throw new GetFailedError(String(err))
}
}
@@ -279,7 +291,7 @@ export class S3Blockstore extends BaseBlockstore {
return
}
- throw Errors.openFailedError(err)
+ throw new OpenFailedError(String(err))
}
}
}
diff --git a/packages/blockstore-s3/test/index.spec.ts b/packages/blockstore-s3/test/index.spec.ts
index 7e849e17..702196da 100644
--- a/packages/blockstore-s3/test/index.spec.ts
+++ b/packages/blockstore-s3/test/index.spec.ts
@@ -1,13 +1,16 @@
/* eslint-env mocha */
-import { type CreateBucketCommand, type HeadObjectCommand, S3 } from '@aws-sdk/client-s3'
+import './utils/domparser-polyfill.js'
+import { S3 } from '@aws-sdk/client-s3'
import { expect } from 'aegir/chai'
import { interfaceBlockstoreTests } from 'interface-blockstore-tests'
+import drain from 'it-drain'
import { CID } from 'multiformats/cid'
import defer from 'p-defer'
import sinon from 'sinon'
import { S3Blockstore } from '../src/index.js'
import { s3Resolve, s3Reject, S3Error, s3Mock } from './utils/s3-mock.js'
+import type { CreateBucketCommand, HeadObjectCommand } from '@aws-sdk/client-s3'
const cid = CID.parse('QmeimKZyjcBnuXmAD9zMnSjM9JodTbgGT3gutofkTqz9rE')
@@ -55,7 +58,7 @@ describe('S3Blockstore', () => {
})
await expect(store.put(cid, new TextEncoder().encode('test data'))).to.eventually.rejected
- .with.property('code', 'ERR_PUT_FAILED')
+ .with.property('name', 'PutFailedError')
})
})
@@ -72,8 +75,8 @@ describe('S3Blockstore', () => {
return s3Reject(new S3Error('UnknownCommand'))
})
- await expect(store.get(cid)).to.eventually.rejected
- .with.property('code', 'ERR_NOT_FOUND')
+ await expect(drain(store.get(cid))).to.eventually.be.rejected
+ .with.property('name', 'NotFoundError')
})
})
@@ -91,7 +94,7 @@ describe('S3Blockstore', () => {
})
await expect(store.delete(cid)).to.eventually.rejected
- .with.property('code', 'ERR_DELETE_FAILED')
+ .with.property('name', 'DeleteFailedError')
})
})
@@ -146,7 +149,7 @@ describe('S3Blockstore', () => {
})
await expect(store.open()).to.eventually.rejected
- .with.property('code', 'ERR_OPEN_FAILED')
+ .with.property('name', 'OpenFailedError')
const headObjectCommand = await bucketTested.promise
expect(headObjectCommand).to.have.nested.property('input.Bucket', 'test')
@@ -165,7 +168,7 @@ describe('S3Blockstore', () => {
})
await expect(store.open()).to.eventually.rejected
- .with.property('code', 'ERR_OPEN_FAILED')
+ .with.property('name', 'OpenFailedError')
})
})
diff --git a/packages/blockstore-s3/test/utils/domparser-polyfill.ts b/packages/blockstore-s3/test/utils/domparser-polyfill.ts
new file mode 100644
index 00000000..5225bed6
--- /dev/null
+++ b/packages/blockstore-s3/test/utils/domparser-polyfill.ts
@@ -0,0 +1,3 @@
+import { DOMParser } from 'xmldom'
+
+globalThis.DOMParser = globalThis.DOMParser ?? DOMParser
diff --git a/packages/blockstore-s3/test/utils/s3-mock.ts b/packages/blockstore-s3/test/utils/s3-mock.ts
index 1b4aadd5..06118f5c 100644
--- a/packages/blockstore-s3/test/utils/s3-mock.ts
+++ b/packages/blockstore-s3/test/utils/s3-mock.ts
@@ -17,11 +17,11 @@ export class S3Error extends Error {
}
}
-export const s3Resolve = (res?: any): any => {
+export function s3Resolve (res?: any): any {
return Promise.resolve(res)
}
-export const s3Reject = (err: T): any => {
+export function s3Reject (err: Error): any {
return Promise.reject(err)
}
diff --git a/packages/blockstore-s3/typedoc.json b/packages/blockstore-s3/typedoc.json
index f599dc72..db0b0747 100644
--- a/packages/blockstore-s3/typedoc.json
+++ b/packages/blockstore-s3/typedoc.json
@@ -1,4 +1,5 @@
{
+ "readme": "none",
"entryPoints": [
"./src/index.ts"
]
diff --git a/packages/datastore-core/CHANGELOG.md b/packages/datastore-core/CHANGELOG.md
index a214bfbc..b253b41d 100644
--- a/packages/datastore-core/CHANGELOG.md
+++ b/packages/datastore-core/CHANGELOG.md
@@ -1,3 +1,73 @@
+## [datastore-core-v11.0.2](https://github.com/ipfs/js-stores/compare/datastore-core-11.0.1...datastore-core-11.0.2) (2025-10-03)
+
+### Dependencies
+
+* bump level from 8.0.1 to 10.0.0 ([#356](https://github.com/ipfs/js-stores/issues/356)) ([c0ec61f](https://github.com/ipfs/js-stores/commit/c0ec61fe965e3bad9d607a0bd3a3c750f00f41d0))
+
+## [datastore-core-v11.0.1](https://github.com/ipfs/js-stores/compare/datastore-core-11.0.0...datastore-core-11.0.1) (2025-10-03)
+
+### Bug Fixes
+
+* update sibling deps ([3f73b3d](https://github.com/ipfs/js-stores/commit/3f73b3d53ea2d86d0f5c3f06785c0bfc30e8b5e9))
+
+## [datastore-core-v11.0.0](https://github.com/ipfs/js-stores/compare/datastore-core-10.0.4...datastore-core-11.0.0) (2025-10-03)
+
+### ⚠ BREAKING CHANGES
+
+* blockstore.get and similar now return streams of bytes
+
+### Features
+
+* streaming blockstores ([#358](https://github.com/ipfs/js-stores/issues/358)) ([4dbb136](https://github.com/ipfs/js-stores/commit/4dbb1362d20fc87fcdd261568dca297972f9bc08))
+
+### Dependencies
+
+* bump @libp2p/logger ([#359](https://github.com/ipfs/js-stores/issues/359)) ([edb5a1f](https://github.com/ipfs/js-stores/commit/edb5a1f8b575a27ad28bc2e1c4e4d52e1f114ebc))
+
+## [datastore-core-v10.0.4](https://github.com/ipfs/js-stores/compare/datastore-core-10.0.3...datastore-core-10.0.4) (2025-05-28)
+
+### Bug Fixes
+
+* improve abort signal support ([#350](https://github.com/ipfs/js-stores/issues/350)) ([e17d770](https://github.com/ipfs/js-stores/commit/e17d770cc2fcee77cb0152a855abf162e5a91a99))
+
+## [datastore-core-v10.0.3](https://github.com/ipfs/js-stores/compare/datastore-core-10.0.2...datastore-core-10.0.3) (2025-05-26)
+
+### Dependencies
+
+* bump aegir from 44.1.4 to 47.0.16 ([#349](https://github.com/ipfs/js-stores/issues/349)) ([d33d15f](https://github.com/ipfs/js-stores/commit/d33d15f0638856530d0e1868c723e5567abf27e6))
+
+## [datastore-core-v10.0.2](https://github.com/ipfs/js-stores/compare/datastore-core-10.0.1...datastore-core-10.0.2) (2024-09-13)
+
+### Bug Fixes
+
+* restore release config to package.json ([#321](https://github.com/ipfs/js-stores/issues/321)) ([4f14fb0](https://github.com/ipfs/js-stores/commit/4f14fb09d65a3460b548b59557af108412dc9156))
+
+## datastore-core [10.0.0](https://github.com/ipfs/js-stores/compare/datastore-core-9.2.9...datastore-core-10.0.0) (2024-08-02)
+
+
+### ⚠ BREAKING CHANGES
+
+* To detect the type of error thrown, use `.name` instead of `.code`
+
+### Features
+
+* use `.name` property for errors instead of `.code` ([#315](https://github.com/ipfs/js-stores/issues/315)) ([dacd6ce](https://github.com/ipfs/js-stores/commit/dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd))
+
+
+
+### Dependencies
+
+* **interface-datastore:** upgraded to 8.3.0
+* **interface-store:** upgraded to 6.0.0
+* **interface-datastore-tests:** upgraded to 6.0.0
+
+## datastore-core [9.2.9](https://github.com/ipfs/js-stores/compare/datastore-core-9.2.8...datastore-core-9.2.9) (2024-02-28)
+
+
+### Bug Fixes
+
+* stop namespaced datastore throwing when queried ([#296](https://github.com/ipfs/js-stores/issues/296)) ([9163490](https://github.com/ipfs/js-stores/commit/916349054a3f83a7c9c4bb692edebcce409c7fee)), closes [#236](https://github.com/ipfs/js-stores/issues/236) [#236](https://github.com/ipfs/js-stores/issues/236)
+
## datastore-core [9.2.8](https://github.com/ipfs/js-stores/compare/datastore-core-v9.2.7...datastore-core-9.2.8) (2024-02-12)
diff --git a/packages/datastore-core/CODE_OF_CONDUCT.md b/packages/datastore-core/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..6b0fa54c
--- /dev/null
+++ b/packages/datastore-core/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Contributor Code of Conduct
+
+This project follows the [`IPFS Community Code of Conduct`](https://github.com/ipfs/community/blob/master/code-of-conduct.md)
diff --git a/packages/datastore-core/LICENSE b/packages/datastore-core/LICENSE
deleted file mode 100644
index 20ce483c..00000000
--- a/packages/datastore-core/LICENSE
+++ /dev/null
@@ -1,4 +0,0 @@
-This project is dual licensed under MIT and Apache-2.0.
-
-MIT: https://www.opensource.org/licenses/mit
-Apache-2.0: https://www.apache.org/licenses/license-2.0
diff --git a/packages/datastore-core/LICENSE-APACHE b/packages/datastore-core/LICENSE-APACHE
index 14478a3b..b09cd785 100644
--- a/packages/datastore-core/LICENSE-APACHE
+++ b/packages/datastore-core/LICENSE-APACHE
@@ -1,5 +1,201 @@
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-http://www.apache.org/licenses/LICENSE-2.0
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/datastore-core/README.md b/packages/datastore-core/README.md
index 66a1aa0f..be5f07af 100644
--- a/packages/datastore-core/README.md
+++ b/packages/datastore-core/README.md
@@ -9,16 +9,31 @@
# About
+
+
Various Datastore implementations are available.
## Implementations
-- Mount: [`src/mount`](src/mount.ts)
-- Keytransform: [`src/keytransform`](src/keytransform.ts)
-- Sharding: [`src/sharding`](src/sharding.ts)
-- Tiered: [`src/tiered`](src/tirered.ts)
-- Namespace: [`src/namespace`](src/namespace.ts)
-- BlackHole: [`src/black-hole`](src/black-hole.ts)
+- Mount: [`src/mount`](./src/mount.ts)
+- Keytransform: [`src/keytransform`](./src/keytransform.ts)
+- Sharding: [`src/sharding`](./src/sharding.ts)
+- Tiered: [`src/tiered`](./src/tirered.ts)
+- Namespace: [`src/namespace`](./src/namespace.ts)
+- BlackHole: [`src/black-hole`](./src/black-hole.ts)
## Example - BaseDatastore
@@ -76,7 +91,7 @@ $ npm i datastore-core
## Browser `
@@ -90,8 +105,8 @@ Loading this module through a script tag will make it's exports available as `Da
Licensed under either of
-- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / )
-- MIT ([LICENSE-MIT](LICENSE-MIT) / )
+- Apache 2.0, ([LICENSE-APACHE](https://github.com/ipfs/js-stores/blob/main/packages/datastore-core/LICENSE-APACHE) / )
+- MIT ([LICENSE-MIT](https://github.com/ipfs/js-stores/blob/main/packages/datastore-core/LICENSE-MIT) / )
# Contribute
diff --git a/packages/datastore-core/package.json b/packages/datastore-core/package.json
index a27fc72f..6a552a3f 100644
--- a/packages/datastore-core/package.json
+++ b/packages/datastore-core/package.json
@@ -1,6 +1,6 @@
{
"name": "datastore-core",
- "version": "9.2.8",
+ "version": "11.0.2",
"description": "Wrapper implementation for interface-datastore",
"author": "Friedel Ziegelmayer ",
"license": "Apache-2.0 OR MIT",
@@ -92,12 +92,98 @@
"import": "./dist/src/tiered.js"
}
},
- "eslintConfig": {
- "extends": "ipfs",
- "parserOptions": {
- "project": true,
- "sourceType": "module"
- }
+ "release": {
+ "branches": [
+ "main"
+ ],
+ "plugins": [
+ [
+ "@semantic-release/commit-analyzer",
+ {
+ "preset": "conventionalcommits",
+ "releaseRules": [
+ {
+ "breaking": true,
+ "release": "major"
+ },
+ {
+ "revert": true,
+ "release": "patch"
+ },
+ {
+ "type": "feat",
+ "release": "minor"
+ },
+ {
+ "type": "fix",
+ "release": "patch"
+ },
+ {
+ "type": "docs",
+ "release": "patch"
+ },
+ {
+ "type": "test",
+ "release": "patch"
+ },
+ {
+ "type": "deps",
+ "release": "patch"
+ },
+ {
+ "scope": "no-release",
+ "release": false
+ }
+ ]
+ }
+ ],
+ [
+ "@semantic-release/release-notes-generator",
+ {
+ "preset": "conventionalcommits",
+ "presetConfig": {
+ "types": [
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "chore",
+ "section": "Trivial Changes"
+ },
+ {
+ "type": "docs",
+ "section": "Documentation"
+ },
+ {
+ "type": "deps",
+ "section": "Dependencies"
+ },
+ {
+ "type": "test",
+ "section": "Tests"
+ }
+ ]
+ }
+ }
+ ],
+ "@semantic-release/changelog",
+ "@semantic-release/npm",
+ "@semantic-release/github",
+ [
+ "@semantic-release/git",
+ {
+ "assets": [
+ "CHANGELOG.md",
+ "package.json"
+ ]
+ }
+ ]
+ ]
},
"scripts": {
"clean": "aegir clean",
@@ -110,26 +196,25 @@
"test:firefox": "aegir test -t browser -- --browser firefox",
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
"test:electron-main": "aegir test -t electron-main",
- "dep-check": "aegir dep-check"
+ "dep-check": "aegir dep-check",
+ "release": "aegir release"
},
"dependencies": {
- "@libp2p/logger": "^4.0.6",
- "err-code": "^3.0.1",
- "interface-datastore": "^8.0.0",
- "interface-store": "^5.0.0",
- "it-drain": "^3.0.5",
- "it-filter": "^3.0.4",
- "it-map": "^3.0.5",
- "it-merge": "^3.0.3",
+ "@libp2p/logger": "^6.0.0",
+ "interface-datastore": "^9.0.0",
+ "interface-store": "^7.0.0",
+ "it-drain": "^3.0.9",
+ "it-filter": "^3.1.3",
+ "it-map": "^3.1.3",
+ "it-merge": "^3.0.11",
"it-pipe": "^3.0.1",
- "it-pushable": "^3.2.3",
- "it-sort": "^3.0.4",
- "it-take": "^3.0.4"
+ "it-sort": "^3.0.8",
+ "it-take": "^3.0.8"
},
"devDependencies": {
- "aegir": "^42.2.3",
- "interface-datastore-tests": "^5.0.0",
- "it-all": "^3.0.4",
- "uint8arrays": "^5.0.2"
+ "aegir": "^47.0.16",
+ "interface-datastore-tests": "^6.0.0",
+ "it-all": "^3.0.8",
+ "uint8arrays": "^5.1.0"
}
}
diff --git a/packages/datastore-core/src/base.ts b/packages/datastore-core/src/base.ts
index 9108be3f..9a97af7f 100644
--- a/packages/datastore-core/src/base.ts
+++ b/packages/datastore-core/src/base.ts
@@ -3,7 +3,7 @@ import filter from 'it-filter'
import sort from 'it-sort'
import take from 'it-take'
import type { Batch, Datastore, Key, KeyQuery, Pair, Query } from 'interface-datastore'
-import type { AbortOptions, Await, AwaitIterable } from 'interface-store'
+import type { AbortOptions, Await, AwaitGenerator, AwaitIterable } from 'interface-store'
export class BaseDatastore implements Datastore {
put (key: Key, val: Uint8Array, options?: AbortOptions): Await {
@@ -22,14 +22,14 @@ export class BaseDatastore implements Datastore {
return Promise.reject(new Error('.delete is not implemented'))
}
- async * putMany (source: AwaitIterable, options: AbortOptions = {}): AwaitIterable {
+ async * putMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
for await (const { key, value } of source) {
await this.put(key, value, options)
yield key
}
}
- async * getMany (source: AwaitIterable, options: AbortOptions = {}): AwaitIterable {
+ async * getMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
for await (const key of source) {
yield {
key,
@@ -38,7 +38,7 @@ export class BaseDatastore implements Datastore {
}
}
- async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AwaitIterable {
+ async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
for await (const key of source) {
await this.delete(key, options)
yield key
@@ -70,7 +70,7 @@ export class BaseDatastore implements Datastore {
* Extending classes should override `query` or implement this method
*/
// eslint-disable-next-line require-yield
- async * _all (q: Query, options?: AbortOptions): AwaitIterable {
+ async * _all (q: Query, options?: AbortOptions): AwaitGenerator {
throw new Error('._all is not implemented')
}
@@ -78,11 +78,11 @@ export class BaseDatastore implements Datastore {
* Extending classes should override `queryKeys` or implement this method
*/
// eslint-disable-next-line require-yield
- async * _allKeys (q: KeyQuery, options?: AbortOptions): AwaitIterable {
+ async * _allKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
throw new Error('._allKeys is not implemented')
}
- query (q: Query, options?: AbortOptions): AwaitIterable {
+ query (q: Query, options?: AbortOptions): AwaitGenerator {
let it = this._all(q, options)
if (q.prefix != null) {
@@ -111,7 +111,7 @@ export class BaseDatastore implements Datastore {
return it
}
- queryKeys (q: KeyQuery, options?: AbortOptions): AwaitIterable {
+ queryKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
let it = this._allKeys(q, options)
if (q.prefix != null) {
diff --git a/packages/datastore-core/src/black-hole.ts b/packages/datastore-core/src/black-hole.ts
index 9c7b3d3e..00b63c3a 100644
--- a/packages/datastore-core/src/black-hole.ts
+++ b/packages/datastore-core/src/black-hole.ts
@@ -1,31 +1,36 @@
+import { NotFoundError } from 'interface-store'
import { BaseDatastore } from './base.js'
-import * as Errors from './errors.js'
-import type { Pair } from 'interface-datastore'
+import type { Pair, Query, KeyQuery } from 'interface-datastore'
import type { Key } from 'interface-datastore/key'
-import type { Await, AwaitIterable } from 'interface-store'
+import type { AbortOptions, Await, AwaitGenerator } from 'interface-store'
export class BlackHoleDatastore extends BaseDatastore {
- put (key: Key): Await {
+ put (key: Key, value: Uint8Array, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
return key
}
- get (): Await {
- throw Errors.notFoundError()
+ get (key: Key, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
+ throw new NotFoundError()
}
- has (key: Key): Await {
+ has (key: Key, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
return false
}
- delete (key: Key): Await {
-
+ delete (key: Key, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
}
- * _all (): AwaitIterable {
-
+ // eslint-disable-next-line require-yield
+ * _all (q: Query, options?: AbortOptions): AwaitGenerator {
+ options?.signal?.throwIfAborted()
}
- * _allKeys (): AwaitIterable {
-
+ // eslint-disable-next-line require-yield
+ * _allKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
+ options?.signal?.throwIfAborted()
}
}
diff --git a/packages/datastore-core/src/errors.ts b/packages/datastore-core/src/errors.ts
deleted file mode 100644
index 8009aff7..00000000
--- a/packages/datastore-core/src/errors.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import errCode from 'err-code'
-
-export function dbOpenFailedError (err?: Error): Error {
- err = err ?? new Error('Cannot open database')
- return errCode(err, 'ERR_DB_OPEN_FAILED')
-}
-
-export function dbDeleteFailedError (err?: Error): Error {
- err = err ?? new Error('Delete failed')
- return errCode(err, 'ERR_DB_DELETE_FAILED')
-}
-
-export function dbWriteFailedError (err?: Error): Error {
- err = err ?? new Error('Write failed')
- return errCode(err, 'ERR_DB_WRITE_FAILED')
-}
-
-export function dbReadFailedError (err?: Error): Error {
- err = err ?? new Error('Read failed')
- return errCode(err, 'ERR_DB_READ_FAILED')
-}
-
-export function notFoundError (err?: Error): Error {
- err = err ?? new Error('Not Found')
- return errCode(err, 'ERR_NOT_FOUND')
-}
-
-export function abortedError (err?: Error): Error {
- err = err ?? new Error('Aborted')
- return errCode(err, 'ERR_ABORTED')
-}
diff --git a/packages/datastore-core/src/index.ts b/packages/datastore-core/src/index.ts
index 5ec96a75..b050078f 100644
--- a/packages/datastore-core/src/index.ts
+++ b/packages/datastore-core/src/index.ts
@@ -5,12 +5,12 @@
*
* ## Implementations
*
- * - Mount: [`src/mount`](src/mount.ts)
- * - Keytransform: [`src/keytransform`](src/keytransform.ts)
- * - Sharding: [`src/sharding`](src/sharding.ts)
- * - Tiered: [`src/tiered`](src/tirered.ts)
- * - Namespace: [`src/namespace`](src/namespace.ts)
- * - BlackHole: [`src/black-hole`](src/black-hole.ts)
+ * - Mount: [`src/mount`](./src/mount.ts)
+ * - Keytransform: [`src/keytransform`](./src/keytransform.ts)
+ * - Sharding: [`src/sharding`](./src/sharding.ts)
+ * - Tiered: [`src/tiered`](./src/tirered.ts)
+ * - Namespace: [`src/namespace`](./src/namespace.ts)
+ * - BlackHole: [`src/black-hole`](./src/black-hole.ts)
*
* @example BaseDatastore
*
@@ -61,7 +61,6 @@
* ```
*/
-import * as Errors from './errors.js'
import * as shard from './shard.js'
import type { Key } from 'interface-datastore'
@@ -73,7 +72,6 @@ export { MountDatastore } from './mount.js'
export { TieredDatastore } from './tiered.js'
export { NamespaceDatastore } from './namespace.js'
-export { Errors }
export { shard }
export interface Shard {
diff --git a/packages/datastore-core/src/keytransform.ts b/packages/datastore-core/src/keytransform.ts
index 6b33e134..faa029dd 100644
--- a/packages/datastore-core/src/keytransform.ts
+++ b/packages/datastore-core/src/keytransform.ts
@@ -3,7 +3,7 @@ import { pipe } from 'it-pipe'
import { BaseDatastore } from './base.js'
import type { KeyTransform } from './index.js'
import type { Batch, Datastore, Key, KeyQuery, Pair, Query } from 'interface-datastore'
-import type { AbortOptions, AwaitIterable } from 'interface-store'
+import type { AbortOptions, AwaitGenerator, AwaitIterable } from 'interface-store'
/**
* A datastore shim, that wraps around a given datastore, changing
@@ -39,7 +39,7 @@ export class KeyTransformDatastore extends BaseDatastore {
await this.child.delete(this.transform.convert(key), options)
}
- async * putMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
+ async * putMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
const transform = this.transform
const child = this.child
@@ -60,7 +60,7 @@ export class KeyTransformDatastore extends BaseDatastore {
)
}
- async * getMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
+ async * getMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
const transform = this.transform
const child = this.child
@@ -81,7 +81,7 @@ export class KeyTransformDatastore extends BaseDatastore {
)
}
- async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
+ async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
const transform = this.transform
const child = this.child
@@ -114,7 +114,7 @@ export class KeyTransformDatastore extends BaseDatastore {
}
}
- query (q: Query, options?: AbortOptions): AsyncIterable {
+ query (q: Query, options?: AbortOptions): AwaitGenerator {
const query: Query = {
...q
}
@@ -148,7 +148,7 @@ export class KeyTransformDatastore extends BaseDatastore {
})
}
- queryKeys (q: KeyQuery, options?: AbortOptions): AsyncIterable {
+ queryKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
const query = {
...q
}
diff --git a/packages/datastore-core/src/memory.ts b/packages/datastore-core/src/memory.ts
index df87fd4b..5d7fe19d 100644
--- a/packages/datastore-core/src/memory.ts
+++ b/packages/datastore-core/src/memory.ts
@@ -1,8 +1,8 @@
import { Key } from 'interface-datastore/key'
+import { NotFoundError } from 'interface-store'
import { BaseDatastore } from './base.js'
-import * as Errors from './errors.js'
-import type { Pair } from 'interface-datastore'
-import type { Await, AwaitIterable } from 'interface-store'
+import type { KeyQuery, Pair, Query } from 'interface-datastore'
+import type { AbortOptions, Await, AwaitGenerator } from 'interface-store'
export class MemoryDatastore extends BaseDatastore {
private readonly data: Map
@@ -13,39 +13,49 @@ export class MemoryDatastore extends BaseDatastore {
this.data = new Map()
}
- put (key: Key, val: Uint8Array): Await { // eslint-disable-line require-await
+ put (key: Key, val: Uint8Array, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
+
this.data.set(key.toString(), val)
return key
}
- get (key: Key): Await {
+ get (key: Key, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
+
const result = this.data.get(key.toString())
if (result == null) {
- throw Errors.notFoundError()
+ throw new NotFoundError()
}
return result
}
- has (key: Key): Await { // eslint-disable-line require-await
+ has (key: Key, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
return this.data.has(key.toString())
}
- delete (key: Key): Await { // eslint-disable-line require-await
+ delete (key: Key, options?: AbortOptions): Await {
+ options?.signal?.throwIfAborted()
this.data.delete(key.toString())
}
- * _all (): AwaitIterable {
+ * _all (q: Query, options?: AbortOptions): AwaitGenerator {
+ options?.signal?.throwIfAborted()
for (const [key, value] of this.data.entries()) {
yield { key: new Key(key), value }
+ options?.signal?.throwIfAborted()
}
}
- * _allKeys (): AwaitIterable {
+ * _allKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
+ options?.signal?.throwIfAborted()
for (const key of this.data.keys()) {
yield new Key(key)
+ options?.signal?.throwIfAborted()
}
}
}
diff --git a/packages/datastore-core/src/mount.ts b/packages/datastore-core/src/mount.ts
index 15b74bfb..bb0fef18 100644
--- a/packages/datastore-core/src/mount.ts
+++ b/packages/datastore-core/src/mount.ts
@@ -1,11 +1,11 @@
+import { DeleteFailedError, NotFoundError, PutFailedError } from 'interface-store'
import filter from 'it-filter'
import merge from 'it-merge'
import sort from 'it-sort'
import take from 'it-take'
import { BaseDatastore } from './base.js'
-import * as Errors from './errors.js'
import type { Batch, Datastore, Key, KeyQuery, Pair, Query } from 'interface-datastore'
-import type { AbortOptions } from 'interface-store'
+import type { AbortOptions, AwaitGenerator } from 'interface-store'
/**
* A datastore that can combine multiple stores inside various
@@ -37,7 +37,7 @@ export class MountDatastore extends BaseDatastore {
async put (key: Key, value: Uint8Array, options?: AbortOptions): Promise {
const match = this._lookup(key)
if (match == null) {
- throw Errors.dbWriteFailedError(new Error('No datastore mounted for this key'))
+ throw new PutFailedError('No datastore mounted for this key')
}
await match.datastore.put(key, value, options)
@@ -52,7 +52,7 @@ export class MountDatastore extends BaseDatastore {
async get (key: Key, options: AbortOptions = {}): Promise {
const match = this._lookup(key)
if (match == null) {
- throw Errors.notFoundError(new Error('No datastore mounted for this key'))
+ throw new NotFoundError('No datastore mounted for this key')
}
return match.datastore.get(key, options)
}
@@ -68,7 +68,7 @@ export class MountDatastore extends BaseDatastore {
async delete (key: Key, options?: AbortOptions): Promise {
const match = this._lookup(key)
if (match == null) {
- throw Errors.dbDeleteFailedError(new Error('No datastore mounted for this key'))
+ throw new DeleteFailedError('No datastore mounted for this key')
}
await match.datastore.delete(key, options)
@@ -108,7 +108,7 @@ export class MountDatastore extends BaseDatastore {
}
}
- query (q: Query, options?: AbortOptions): AsyncIterable {
+ query (q: Query, options?: AbortOptions): AwaitGenerator {
const qs = this.mounts.map(m => {
return m.datastore.query({
prefix: q.prefix,
@@ -117,19 +117,19 @@ export class MountDatastore extends BaseDatastore {
})
let it = merge(...qs)
- if (q.filters != null) q.filters.forEach(f => { it = filter(it, f) })
- if (q.orders != null) q.orders.forEach(o => { it = sort(it, o) })
+ if (q.filters != null) { q.filters.forEach(f => { it = filter(it, f) }) }
+ if (q.orders != null) { q.orders.forEach(o => { it = sort(it, o) }) }
if (q.offset != null) {
let i = 0
const offset = q.offset
it = filter(it, () => i++ >= offset)
}
- if (q.limit != null) it = take(it, q.limit)
+ if (q.limit != null) { it = take(it, q.limit) }
return it
}
- queryKeys (q: KeyQuery, options?: AbortOptions): AsyncIterable {
+ queryKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
const qs = this.mounts.map(m => {
return m.datastore.queryKeys({
prefix: q.prefix,
@@ -137,16 +137,15 @@ export class MountDatastore extends BaseDatastore {
}, options)
})
- /** @type AsyncIterable */
let it = merge(...qs)
- if (q.filters != null) q.filters.forEach(f => { it = filter(it, f) })
- if (q.orders != null) q.orders.forEach(o => { it = sort(it, o) })
+ if (q.filters != null) { q.filters.forEach(f => { it = filter(it, f) }) }
+ if (q.orders != null) { q.orders.forEach(o => { it = sort(it, o) }) }
if (q.offset != null) {
let i = 0
const offset = q.offset
it = filter(it, () => i++ >= offset)
}
- if (q.limit != null) it = take(it, q.limit)
+ if (q.limit != null) { it = take(it, q.limit) }
return it
}
diff --git a/packages/datastore-core/src/namespace.ts b/packages/datastore-core/src/namespace.ts
index 02c20601..b476149e 100644
--- a/packages/datastore-core/src/namespace.ts
+++ b/packages/datastore-core/src/namespace.ts
@@ -1,6 +1,8 @@
import { Key } from 'interface-datastore'
+import map from 'it-map'
import { KeyTransformDatastore } from './keytransform.js'
-import type { Datastore } from 'interface-datastore'
+import type { Datastore, Query, Pair, KeyQuery } from 'interface-datastore'
+import type { AbortOptions, AwaitGenerator } from 'interface-store'
/**
* Wraps a given datastore into a keytransform which
@@ -11,6 +13,9 @@ import type { Datastore } from 'interface-datastore'
* `/hello/world`.
*/
export class NamespaceDatastore extends KeyTransformDatastore {
+ private readonly iChild: Datastore
+ private readonly iKey: Key
+
constructor (child: Datastore, prefix: Key) {
super(child, {
convert (key) {
@@ -28,5 +33,77 @@ export class NamespaceDatastore extends KeyTransformDatastore {
return new Key(key.toString().slice(prefix.toString().length), false)
}
})
+
+ this.iChild = child
+ this.iKey = prefix
+ }
+
+ query (q: Query, options?: AbortOptions): AwaitGenerator {
+ const query: Query = {
+ ...q
+ }
+
+ query.filters = (query.filters ?? []).map(filter => {
+ return ({ key, value }) => filter({ key: this.transform.invert(key), value })
+ })
+
+ const { prefix } = q
+ if (prefix != null && prefix !== '/') {
+ delete query.prefix
+ query.filters.push(({ key }) => {
+ return this.transform.invert(key).toString().startsWith(prefix)
+ })
+ }
+
+ if (query.orders != null) {
+ query.orders = query.orders.map(order => {
+ return (a, b) => order(
+ { key: this.transform.invert(a.key), value: a.value },
+ { key: this.transform.invert(b.key), value: b.value }
+ )
+ })
+ }
+
+ query.filters.unshift(({ key }) => this.iKey.isAncestorOf(key))
+
+ return map(this.iChild.query(query, options), ({ key, value }) => {
+ return {
+ key: this.transform.invert(key),
+ value
+ }
+ })
+ }
+
+ queryKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
+ const query = {
+ ...q
+ }
+
+ query.filters = (query.filters ?? []).map(filter => {
+ return (key) => filter(this.transform.invert(key))
+ })
+
+ const { prefix } = q
+ if (prefix != null && prefix !== '/') {
+ delete query.prefix
+ query.filters.push((key) => {
+ return this.transform.invert(key).toString().startsWith(prefix)
+ })
+ }
+
+ if (query.orders != null) {
+ query.orders = query.orders.map(order => {
+ return (a, b) => order(
+ this.transform.invert(a),
+ this.transform.invert(b)
+ )
+ })
+ }
+
+ query.filters.unshift(key => this.iKey.isAncestorOf(key))
+
+ return map(this.iChild.queryKeys(query, options), key => {
+ return this.transform.invert(key)
+ })
}
}
diff --git a/packages/datastore-core/src/sharding.ts b/packages/datastore-core/src/sharding.ts
index 6244bb2b..3f34c08c 100644
--- a/packages/datastore-core/src/sharding.ts
+++ b/packages/datastore-core/src/sharding.ts
@@ -1,13 +1,14 @@
-import { type Batch, Key, type KeyQuery, type KeyQueryFilter, type Pair, type Query, type QueryFilter, type Datastore } from 'interface-datastore'
+import { Key } from 'interface-datastore'
+import { OpenFailedError } from 'interface-store'
import { BaseDatastore } from './base.js'
-import * as Errors from './errors.js'
import { KeyTransformDatastore } from './keytransform.js'
import {
readShardFun,
SHARDING_FN
} from './shard.js'
import type { Shard } from './index.js'
-import type { AbortOptions, AwaitIterable } from 'interface-store'
+import type { Batch, KeyQuery, KeyQueryFilter, Pair, Query, QueryFilter, Datastore } from 'interface-datastore'
+import type { AbortOptions, AwaitGenerator, AwaitIterable } from 'interface-store'
const shardKey = new Key(SHARDING_FN)
@@ -58,7 +59,7 @@ export class ShardingDatastore extends BaseDatastore {
if (!hasShard) {
if (shard == null) {
- throw Errors.dbOpenFailedError(Error('Shard is required when datastore doesn\'t have a shard key already.'))
+ throw new OpenFailedError('Shard is required when datastore doesn\'t have a shard key already')
}
await store.put(shardKey, new TextEncoder().encode(shard.toString() + '\n'))
@@ -98,15 +99,15 @@ export class ShardingDatastore extends BaseDatastore {
await this.child.delete(key, options)
}
- async * putMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
+ async * putMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
yield * this.child.putMany(source, options)
}
- async * getMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
+ async * getMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
yield * this.child.getMany(source, options)
}
- async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
+ async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
yield * this.child.deleteMany(source, options)
}
@@ -114,7 +115,7 @@ export class ShardingDatastore extends BaseDatastore {
return this.child.batch()
}
- query (q: Query, options?: AbortOptions): AsyncIterable {
+ query (q: Query, options?: AbortOptions): AwaitGenerator {
const omitShard: QueryFilter = ({ key }) => key.toString() !== shardKey.toString()
const tq: Query = {
@@ -127,7 +128,7 @@ export class ShardingDatastore extends BaseDatastore {
return this.child.query(tq, options)
}
- queryKeys (q: KeyQuery, options?: AbortOptions): AsyncIterable {
+ queryKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
const omitShard: KeyQueryFilter = (key) => key.toString() !== shardKey.toString()
const tq: KeyQuery = {
diff --git a/packages/datastore-core/src/tiered.ts b/packages/datastore-core/src/tiered.ts
index e76db6f1..c418bce5 100644
--- a/packages/datastore-core/src/tiered.ts
+++ b/packages/datastore-core/src/tiered.ts
@@ -1,10 +1,8 @@
import { logger } from '@libp2p/logger'
-import drain from 'it-drain'
-import { pushable } from 'it-pushable'
+import { NotFoundError } from 'interface-store'
import { BaseDatastore } from './base.js'
-import * as Errors from './errors.js'
import type { Batch, Datastore, Key, KeyQuery, Pair, Query } from 'interface-datastore'
-import type { AbortOptions, AwaitIterable } from 'interface-store'
+import type { AbortOptions, AwaitGenerator, AwaitIterable } from 'interface-store'
const log = logger('datastore:core:tiered')
@@ -25,24 +23,32 @@ export class TieredDatastore extends BaseDatastore {
}
async put (key: Key, value: Uint8Array, options?: AbortOptions): Promise {
- try {
- await Promise.all(this.stores.map(async store => { await store.put(key, value, options) }))
- return key
- } catch (err: any) {
- throw Errors.dbWriteFailedError(err)
- }
+ await Promise.all(
+ this.stores.map(async store => {
+ await store.put(key, value, options)
+ })
+ )
+
+ return key
}
async get (key: Key, options?: AbortOptions): Promise {
+ let error: Error | undefined
+
for (const store of this.stores) {
try {
const res = await store.get(key, options)
- if (res != null) return res
- } catch (err) {
+
+ if (res != null) {
+ return res
+ }
+ } catch (err: any) {
+ error = err
log.error(err)
}
}
- throw Errors.notFoundError()
+
+ throw error ?? new NotFoundError()
}
async has (key: Key, options?: AbortOptions): Promise {
@@ -56,72 +62,24 @@ export class TieredDatastore extends BaseDatastore {
}
async delete (key: Key, options?: AbortOptions): Promise {
- try {
- await Promise.all(this.stores.map(async store => { await store.delete(key, options) }))
- } catch (err: any) {
- throw Errors.dbDeleteFailedError(err)
- }
- }
-
- async * putMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
- let error: Error | undefined
- const pushables = this.stores.map(store => {
- const source = pushable({
- objectMode: true
+ await Promise.all(
+ this.stores.map(async store => {
+ await store.delete(key, options)
})
+ )
+ }
- drain(store.putMany(source, options))
- .catch(err => {
- // store threw while putting, make sure we bubble the error up
- error = err
- })
-
- return source
- })
-
- try {
- for await (const pair of source) {
- if (error != null) {
- throw error
- }
-
- pushables.forEach(p => p.push(pair))
-
- yield pair.key
- }
- } finally {
- pushables.forEach(p => p.end())
+ async * putMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
+ for await (const pair of source) {
+ await this.put(pair.key, pair.value, options)
+ yield pair.key
}
}
- async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AsyncIterable {
- let error: Error | undefined
- const pushables = this.stores.map(store => {
- const source = pushable({
- objectMode: true
- })
-
- drain(store.deleteMany(source, options))
- .catch(err => {
- // store threw while deleting, make sure we bubble the error up
- error = err
- })
-
- return source
- })
-
- try {
- for await (const key of source) {
- if (error != null) {
- throw error
- }
-
- pushables.forEach(p => p.push(key))
-
- yield key
- }
- } finally {
- pushables.forEach(p => p.end())
+ async * deleteMany (source: AwaitIterable, options: AbortOptions = {}): AwaitGenerator {
+ for await (const key of source) {
+ await this.delete(key, options)
+ yield key
}
}
@@ -143,11 +101,11 @@ export class TieredDatastore extends BaseDatastore {
}
}
- query (q: Query, options?: AbortOptions): AwaitIterable {
+ query (q: Query, options?: AbortOptions): AwaitGenerator {
return this.stores[this.stores.length - 1].query(q, options)
}
- queryKeys (q: KeyQuery, options?: AbortOptions): AwaitIterable {
+ queryKeys (q: KeyQuery, options?: AbortOptions): AwaitGenerator {
return this.stores[this.stores.length - 1].queryKeys(q, options)
}
}
diff --git a/packages/datastore-core/test/namespace.spec.ts b/packages/datastore-core/test/namespace.spec.ts
index 54f57f98..9b1918ff 100644
--- a/packages/datastore-core/test/namespace.spec.ts
+++ b/packages/datastore-core/test/namespace.spec.ts
@@ -13,19 +13,20 @@ describe('NamespaceDatastore', () => {
'abc',
''
]
+
+ const keys = [
+ 'foo',
+ 'foo/bar',
+ 'foo/bar/baz',
+ 'foo/barb',
+ 'foo/bar/bazb',
+ 'foo/bar/baz/barb'
+ ].map((s) => new Key(s))
+
prefixes.forEach((prefix) => it(`basic '${prefix}'`, async () => {
const mStore = new MemoryDatastore()
const store = new NamespaceDatastore(mStore, new Key(prefix))
- const keys = [
- 'foo',
- 'foo/bar',
- 'foo/bar/baz',
- 'foo/barb',
- 'foo/bar/bazb',
- 'foo/bar/baz/barb'
- ].map((s) => new Key(s))
-
await Promise.all(keys.map(async key => { await store.put(key, uint8ArrayFromString(key.toString())) }))
const nResults = Promise.all(keys.map(async (key) => store.get(key)))
const mResults = Promise.all(keys.map(async (key) => mStore.get(new Key(prefix).child(key))))
@@ -45,6 +46,80 @@ describe('NamespaceDatastore', () => {
expect(results[0]).to.eql(results[1])
}))
+ const setupStores = async (keys: Key[]): Promise => {
+ const prefixes = ['abc', '123', 'sub/prefix']
+ const mStore = new MemoryDatastore()
+
+ return Promise.all(prefixes.map(async prefix => {
+ const store = new NamespaceDatastore(mStore, new Key(prefix))
+
+ await Promise.all(keys.map(async key => { await store.put(key, uint8ArrayFromString(key.toString())) }))
+
+ return store
+ }))
+ }
+
+ const setupNestedStores = async (keys: Key[]): Promise => {
+ const prefixes = ['abc', '123', 'sub/prefix']
+ const mStore = new MemoryDatastore()
+
+ return (await Promise.all(prefixes.map(async prefix => {
+ const store = new NamespaceDatastore(mStore, new Key(prefix))
+
+ return Promise.all(prefixes.map(async prefix => {
+ const child = new NamespaceDatastore(store, new Key(prefix))
+
+ await Promise.all(keys.map(async key => { await child.put(key, uint8ArrayFromString(key.toString())) }))
+
+ return child
+ }))
+ }))).reduce((a, c) => [...a, ...c], [])
+ }
+
+ it('queries keys under each prefix', async () => {
+ const stores = await setupStores(keys)
+
+ for (const store of stores) {
+ const nRes = await all(store.queryKeys({}))
+
+ expect(nRes).deep.equal(keys)
+ }
+ })
+
+ it('queries values under each prefix', async () => {
+ const stores = await setupStores(keys)
+
+ for (const store of stores) {
+ const nRes = await all(store.query({}))
+ const values = keys.map(key => uint8ArrayFromString(key.toString()))
+
+ expect(nRes.map(p => p.key)).deep.equal(keys)
+ expect(nRes.map(p => p.value)).deep.equal(values)
+ }
+ })
+
+ it('queries keys under each prefix in nested stores', async () => {
+ const stores = await setupNestedStores(keys)
+
+ for (const store of stores) {
+ const nRes = await all(store.queryKeys({}))
+
+ expect(nRes).deep.equal(keys)
+ }
+ })
+
+ it('queries values under each prefix in nested stores', async () => {
+ const stores = await setupNestedStores(keys)
+
+ for (const store of stores) {
+ const nRes = await all(store.query({}))
+ const values = keys.map(key => uint8ArrayFromString(key.toString()))
+
+ expect(nRes.map(p => p.key)).deep.equal(keys)
+ expect(nRes.map(p => p.value)).deep.equal(values)
+ }
+ })
+
prefixes.forEach((prefix) => {
describe(`interface-datastore: '${prefix}'`, () => {
interfaceDatastoreTests({
diff --git a/packages/datastore-core/test/sharding.spec.ts b/packages/datastore-core/test/sharding.spec.ts
index b4c8b2a6..b02f5bad 100644
--- a/packages/datastore-core/test/sharding.spec.ts
+++ b/packages/datastore-core/test/sharding.spec.ts
@@ -32,7 +32,7 @@ describe('ShardingDatastore', () => {
const store = new ShardingDatastore(ms)
return expect(store.open())
.to.eventually.be.rejected()
- .with.property('code', 'ERR_DB_OPEN_FAILED')
+ .with.property('name', 'OpenFailedError')
})
it('open - existing', () => {
diff --git a/packages/datastore-core/test/tiered.spec.ts b/packages/datastore-core/test/tiered.spec.ts
index f2dc73c7..eab536e0 100644
--- a/packages/datastore-core/test/tiered.spec.ts
+++ b/packages/datastore-core/test/tiered.spec.ts
@@ -39,11 +39,11 @@ describe('Tiered', () => {
const val = await store.get(k)
expect(val).to.be.eql(v)
const exists = await store.has(k)
- expect(exists).to.be.eql(true)
+ expect(exists).to.be.true()
})
it('has - key not found', async () => {
- expect(await store.has(new Key('hello1'))).to.be.eql(false)
+ expect(await store.has(new Key('hello1'))).to.be.false()
})
it('has and delete', async () => {
diff --git a/packages/datastore-core/typedoc.json b/packages/datastore-core/typedoc.json
index 6e02e0f9..84f710c5 100644
--- a/packages/datastore-core/typedoc.json
+++ b/packages/datastore-core/typedoc.json
@@ -1,4 +1,5 @@
{
+ "readme": "none",
"entryPoints": [
"./src/index.ts",
"./src/base.ts",
diff --git a/packages/datastore-fs/CHANGELOG.md b/packages/datastore-fs/CHANGELOG.md
index e5bdb960..a14b9dc6 100644
--- a/packages/datastore-fs/CHANGELOG.md
+++ b/packages/datastore-fs/CHANGELOG.md
@@ -1,3 +1,96 @@
+## [datastore-fs-v11.0.2](https://github.com/ipfs/js-stores/compare/datastore-fs-11.0.1...datastore-fs-11.0.2) (2025-10-03)
+
+### Dependencies
+
+* bump level from 8.0.1 to 10.0.0 ([#356](https://github.com/ipfs/js-stores/issues/356)) ([c0ec61f](https://github.com/ipfs/js-stores/commit/c0ec61fe965e3bad9d607a0bd3a3c750f00f41d0))
+
+## [datastore-fs-v11.0.1](https://github.com/ipfs/js-stores/compare/datastore-fs-11.0.0...datastore-fs-11.0.1) (2025-10-03)
+
+### Bug Fixes
+
+* update sibling deps ([3f73b3d](https://github.com/ipfs/js-stores/commit/3f73b3d53ea2d86d0f5c3f06785c0bfc30e8b5e9))
+
+## [datastore-fs-v11.0.0](https://github.com/ipfs/js-stores/compare/datastore-fs-10.0.6...datastore-fs-11.0.0) (2025-10-03)
+
+### ⚠ BREAKING CHANGES
+
+* blockstore.get and similar now return streams of bytes
+
+### Features
+
+* streaming blockstores ([#358](https://github.com/ipfs/js-stores/issues/358)) ([4dbb136](https://github.com/ipfs/js-stores/commit/4dbb1362d20fc87fcdd261568dca297972f9bc08))
+
+## [datastore-fs-v10.0.6](https://github.com/ipfs/js-stores/compare/datastore-fs-10.0.5...datastore-fs-10.0.6) (2025-09-02)
+
+### Bug Fixes
+
+* readme typos ([e6b5653](https://github.com/ipfs/js-stores/commit/e6b56533b68e6ed9b90ca3e3f35af8577041a9a2))
+
+### Dependencies
+
+* bump race-signal from 1.1.3 to 2.0.0 ([#355](https://github.com/ipfs/js-stores/issues/355)) ([518fee8](https://github.com/ipfs/js-stores/commit/518fee89d3430534c0ec39551e920447fd558581))
+
+## [datastore-fs-v10.0.5](https://github.com/ipfs/js-stores/compare/datastore-fs-10.0.4...datastore-fs-10.0.5) (2025-09-02)
+
+### Bug Fixes
+
+* deprecate blockstore-level and datastore-fs ([#353](https://github.com/ipfs/js-stores/issues/353)) ([ebc7912](https://github.com/ipfs/js-stores/commit/ebc7912696d5bd9dc991ece5f0c0d4acfb1f9400))
+
+## [datastore-fs-v10.0.4](https://github.com/ipfs/js-stores/compare/datastore-fs-10.0.3...datastore-fs-10.0.4) (2025-05-28)
+
+### Bug Fixes
+
+* improve abort signal support ([#350](https://github.com/ipfs/js-stores/issues/350)) ([e17d770](https://github.com/ipfs/js-stores/commit/e17d770cc2fcee77cb0152a855abf162e5a91a99))
+
+## [datastore-fs-v10.0.3](https://github.com/ipfs/js-stores/compare/datastore-fs-10.0.2...datastore-fs-10.0.3) (2025-05-26)
+
+### Dependencies
+
+* bump aegir from 44.1.4 to 47.0.16 ([#349](https://github.com/ipfs/js-stores/issues/349)) ([d33d15f](https://github.com/ipfs/js-stores/commit/d33d15f0638856530d0e1868c723e5567abf27e6))
+
+## [datastore-fs-v10.0.2](https://github.com/ipfs/js-stores/compare/datastore-fs-10.0.1...datastore-fs-10.0.2) (2024-09-17)
+
+### Tests
+
+* add separate-thread concurrency test ([#305](https://github.com/ipfs/js-stores/issues/305)) ([5e3114e](https://github.com/ipfs/js-stores/commit/5e3114e0160ba8366067359f724c6e49807dfb21)), closes [#285](https://github.com/ipfs/js-stores/issues/285) [#284](https://github.com/ipfs/js-stores/issues/284)
+
+## [datastore-fs-v10.0.1](https://github.com/ipfs/js-stores/compare/datastore-fs-10.0.0...datastore-fs-10.0.1) (2024-09-13)
+
+### Bug Fixes
+
+* restore release config to package.json ([#321](https://github.com/ipfs/js-stores/issues/321)) ([4f14fb0](https://github.com/ipfs/js-stores/commit/4f14fb09d65a3460b548b59557af108412dc9156))
+
+### Dependencies
+
+* **dev:** bump aegir from 42.2.11 to 44.1.0 ([#316](https://github.com/ipfs/js-stores/issues/316)) ([581a467](https://github.com/ipfs/js-stores/commit/581a46720832916bea11efa2476eb85a00bae9d4))
+
+## datastore-fs [10.0.0](https://github.com/ipfs/js-stores/compare/datastore-fs-9.1.9...datastore-fs-10.0.0) (2024-08-02)
+
+
+### ⚠ BREAKING CHANGES
+
+* To detect the type of error thrown, use `.name` instead of `.code`
+
+### Features
+
+* use `.name` property for errors instead of `.code` ([#315](https://github.com/ipfs/js-stores/issues/315)) ([dacd6ce](https://github.com/ipfs/js-stores/commit/dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd))
+
+
+
+### Dependencies
+
+* **datastore-core:** upgraded to 10.0.0
+* **interface-datastore:** upgraded to 8.3.0
+* **interface-store:** upgraded to 6.0.0
+* **interface-datastore-tests:** upgraded to 6.0.0
+
+## datastore-fs [9.1.9](https://github.com/ipfs/js-stores/compare/datastore-fs-9.1.8...datastore-fs-9.1.9) (2024-08-01)
+
+
+### Dependencies
+
+* bump it-glob from 2.0.7 to 3.0.1 ([#306](https://github.com/ipfs/js-stores/issues/306)) ([8f6313f](https://github.com/ipfs/js-stores/commit/8f6313f8a22cb537aeeac2a048aad644d3c9a7d2))
+
## datastore-fs [9.1.8](https://github.com/ipfs/js-stores/compare/datastore-fs-v9.1.7...datastore-fs-9.1.8) (2024-02-12)
diff --git a/packages/datastore-fs/CODE_OF_CONDUCT.md b/packages/datastore-fs/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..6b0fa54c
--- /dev/null
+++ b/packages/datastore-fs/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Contributor Code of Conduct
+
+This project follows the [`IPFS Community Code of Conduct`](https://github.com/ipfs/community/blob/master/code-of-conduct.md)
diff --git a/packages/datastore-fs/LICENSE b/packages/datastore-fs/LICENSE
deleted file mode 100644
index 20ce483c..00000000
--- a/packages/datastore-fs/LICENSE
+++ /dev/null
@@ -1,4 +0,0 @@
-This project is dual licensed under MIT and Apache-2.0.
-
-MIT: https://www.opensource.org/licenses/mit
-Apache-2.0: https://www.apache.org/licenses/license-2.0
diff --git a/packages/datastore-fs/LICENSE-APACHE b/packages/datastore-fs/LICENSE-APACHE
index 14478a3b..b09cd785 100644
--- a/packages/datastore-fs/LICENSE-APACHE
+++ b/packages/datastore-fs/LICENSE-APACHE
@@ -1,5 +1,201 @@
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-http://www.apache.org/licenses/LICENSE-2.0
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/datastore-fs/README.md b/packages/datastore-fs/README.md
index 04454a72..70d7aee2 100644
--- a/packages/datastore-fs/README.md
+++ b/packages/datastore-fs/README.md
@@ -1,5 +1,9 @@
# datastore-fs
+## ⚠️ Deprecation Warning
+
+**This package is deprecated. Instead, use `datastore-level` in Node.js, and `datastore-idb` in browsers.**
+
[](https://ipfs.tech)
[](https://discuss.ipfs.tech)
[](https://codecov.io/gh/ipfs/js-stores)
@@ -9,6 +13,23 @@
# About
+
+
+⚠️ This package is deprecated. Instead, use `datastore-level` in Node.js, and `datastore-idb` in browsers.
+
A Datastore implementation with a file system backend.
## Example
@@ -33,8 +54,8 @@ $ npm i datastore-fs
Licensed under either of
-- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / )
-- MIT ([LICENSE-MIT](LICENSE-MIT) / )
+- Apache 2.0, ([LICENSE-APACHE](https://github.com/ipfs/js-stores/blob/main/packages/datastore-fs/LICENSE-APACHE) / )
+- MIT ([LICENSE-MIT](https://github.com/ipfs/js-stores/blob/main/packages/datastore-fs/LICENSE-MIT) / )
# Contribute
diff --git a/packages/datastore-fs/package.json b/packages/datastore-fs/package.json
index db04aeeb..aa7518ce 100644
--- a/packages/datastore-fs/package.json
+++ b/packages/datastore-fs/package.json
@@ -1,6 +1,6 @@
{
"name": "datastore-fs",
- "version": "9.1.8",
+ "version": "11.0.2",
"description": "Datastore implementation with file system backend",
"author": "Friedel Ziegelmayer",
"license": "Apache-2.0 OR MIT",
@@ -37,36 +37,123 @@
"import": "./dist/src/index.js"
}
},
- "eslintConfig": {
- "extends": "ipfs",
- "parserOptions": {
- "project": true,
- "sourceType": "module"
- }
+ "release": {
+ "branches": [
+ "main"
+ ],
+ "plugins": [
+ [
+ "@semantic-release/commit-analyzer",
+ {
+ "preset": "conventionalcommits",
+ "releaseRules": [
+ {
+ "breaking": true,
+ "release": "major"
+ },
+ {
+ "revert": true,
+ "release": "patch"
+ },
+ {
+ "type": "feat",
+ "release": "minor"
+ },
+ {
+ "type": "fix",
+ "release": "patch"
+ },
+ {
+ "type": "docs",
+ "release": "patch"
+ },
+ {
+ "type": "test",
+ "release": "patch"
+ },
+ {
+ "type": "deps",
+ "release": "patch"
+ },
+ {
+ "scope": "no-release",
+ "release": false
+ }
+ ]
+ }
+ ],
+ [
+ "@semantic-release/release-notes-generator",
+ {
+ "preset": "conventionalcommits",
+ "presetConfig": {
+ "types": [
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "chore",
+ "section": "Trivial Changes"
+ },
+ {
+ "type": "docs",
+ "section": "Documentation"
+ },
+ {
+ "type": "deps",
+ "section": "Dependencies"
+ },
+ {
+ "type": "test",
+ "section": "Tests"
+ }
+ ]
+ }
+ }
+ ],
+ "@semantic-release/changelog",
+ "@semantic-release/npm",
+ "@semantic-release/github",
+ [
+ "@semantic-release/git",
+ {
+ "assets": [
+ "CHANGELOG.md",
+ "package.json"
+ ]
+ }
+ ]
+ ]
},
"scripts": {
"clean": "aegir clean",
"lint": "aegir lint",
"build": "aegir build --bundle false",
- "release": "aegir release",
"test": "aegir test -t node -t electron-main",
"test:node": "aegir test -t node",
"test:electron-main": "aegir test -t electron-main",
- "dep-check": "aegir dep-check"
+ "dep-check": "aegir dep-check",
+ "release": "aegir release"
},
"dependencies": {
- "datastore-core": "^9.0.0",
- "fast-write-atomic": "^0.2.1",
- "interface-datastore": "^8.0.0",
- "interface-store": "^5.0.0",
- "it-glob": "^2.0.6",
- "it-map": "^3.0.5",
- "it-parallel-batch": "^3.0.4"
+ "datastore-core": "^11.0.0",
+ "interface-datastore": "^9.0.0",
+ "interface-store": "^7.0.0",
+ "it-glob": "^3.0.3",
+ "it-map": "^3.1.3",
+ "it-parallel-batch": "^3.0.8",
+ "race-signal": "^2.0.0",
+ "steno": "^4.0.2"
},
"devDependencies": {
- "@types/mkdirp": "^2.0.0",
- "aegir": "^42.2.3",
- "interface-datastore-tests": "^5.0.0",
- "ipfs-utils": "^9.0.14"
+ "aegir": "^47.0.16",
+ "interface-datastore-tests": "^6.0.0",
+ "ipfs-utils": "^9.0.14",
+ "threads": "^1.7.0"
}
}
diff --git a/packages/datastore-fs/src/index.ts b/packages/datastore-fs/src/index.ts
index bd19b657..d3403ac9 100644
--- a/packages/datastore-fs/src/index.ts
+++ b/packages/datastore-fs/src/index.ts
@@ -1,6 +1,8 @@
/**
* @packageDocumentation
*
+ * ⚠️ This package is deprecated. Instead, use `datastore-level` in Node.js, and `datastore-idb` in browsers.
+ *
* A Datastore implementation with a file system backend.
*
* @example
@@ -14,35 +16,37 @@
import fs from 'node:fs/promises'
import path from 'node:path'
-import { promisify } from 'util'
-import {
- BaseDatastore, Errors
-} from 'datastore-core'
-// @ts-expect-error no types
-import fwa from 'fast-write-atomic'
-import {
- Key, type KeyQuery, type Pair, type Query
-} from 'interface-datastore'
+import { BaseDatastore } from 'datastore-core'
+import { Key } from 'interface-datastore'
+import { OpenFailedError, NotFoundError, PutFailedError, DeleteFailedError } from 'interface-store'
import glob from 'it-glob'
import map from 'it-map'
import parallel from 'it-parallel-batch'
-import type { AwaitIterable } from 'interface-store'
-
-const writeAtomic = promisify(fwa)
+import { raceSignal } from 'race-signal'
+import { Writer } from 'steno'
+import type { KeyQuery, Pair, Query } from 'interface-datastore'
+import type { AbortOptions, AwaitGenerator, AwaitIterable } from 'interface-store'
/**
* Write a file atomically
*/
-async function writeFile (path: string, contents: Uint8Array): Promise {
+async function writeFile (file: string, contents: Uint8Array, options?: AbortOptions): Promise {
try {
- await writeAtomic(path, contents)
+ options?.signal?.throwIfAborted()
+ await raceSignal(fs.mkdir(path.dirname(file), {
+ recursive: true
+ }), options?.signal)
+
+ const writer = new Writer(file)
+ options?.signal?.throwIfAborted()
+ await raceSignal(writer.write(contents), options?.signal)
} catch (err: any) {
- if (err.code === 'EPERM' && err.syscall === 'rename') {
- // fast-write-atomic writes a file to a temp location before renaming it.
- // On Windows, if the final file already exists this error is thrown.
- // No such error is thrown on Linux/Mac
+ if (err.syscall === 'rename' && ['ENOENT', 'EPERM'].includes(err.code)) {
+ // steno writes a file to a temp location before renaming it.
+ // If the final file already exists this error is thrown.
// Make sure we can read & write to this file
- await fs.access(path, fs.constants.F_OK | fs.constants.W_OK)
+ options?.signal?.throwIfAborted()
+ await raceSignal(fs.access(file, fs.constants.F_OK | fs.constants.W_OK), options?.signal)
// The file was created by another context - this means there were
// attempts to write the same block by two different function calls
@@ -94,7 +98,7 @@ export class FsDatastore extends BaseDatastore {
await fs.access(this.path, fs.constants.F_OK | fs.constants.W_OK)
if (this.errorIfExists) {
- throw Errors.dbOpenFailedError(new Error(`Datastore directory: ${this.path} already exists`))
+ throw new OpenFailedError(`Datastore directory: ${this.path} already exists`)
}
} catch (err: any) {
if (err.code === 'ENOENT') {
@@ -102,7 +106,7 @@ export class FsDatastore extends BaseDatastore {
await fs.mkdir(this.path, { recursive: true })
return
} else {
- throw Errors.notFoundError(new Error(`Datastore directory: ${this.path} does not exist`))
+ throw new NotFoundError(`Datastore directory: ${this.path} does not exist`)
}
}
@@ -146,29 +150,23 @@ export class FsDatastore extends BaseDatastore {
return new Key(keyname)
}
- /**
- * Store the given value under the key
- */
- async put (key: Key, val: Uint8Array): Promise {
+ async put (key: Key, val: Uint8Array, options?: AbortOptions): Promise {
const parts = this._encode(key)
try {
- await fs.mkdir(parts.dir, {
- recursive: true
- })
- await writeFile(parts.file, val)
+ await writeFile(parts.file, val, options)
return key
} catch (err: any) {
- throw Errors.dbWriteFailedError(err)
+ throw new PutFailedError(String(err))
}
}
- async * putMany (source: AwaitIterable): AsyncIterable {
+ async * putMany (source: AwaitIterable, options?: AbortOptions): AwaitGenerator {
yield * parallel(
map(source, ({ key, value }) => {
return async () => {
- await this.put(key, value)
+ await this.put(key, value, options)
return key
}
@@ -177,27 +175,23 @@ export class FsDatastore extends BaseDatastore {
)
}
- /**
- * Read from the file system
- */
- async get (key: Key): Promise