From d5c454cae9fcb6aba0e26096f4ade645b7574a3e Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 21 Feb 2022 16:31:39 +0200 Subject: [PATCH 1/2] chore: switch to unified CI Removes travis, replace with GH actions. BREAKING CHANGE: this module is ESM-only now --- .github/dependabot.yml | 8 + .github/workflows/automerge.yml | 50 +++++++ .github/workflows/js-test-and-release.yml | 152 +++++++++++++++++++ .npmignore | 33 ----- .travis.yml | 58 -------- LICENSE | 24 +-- LICENSE-APACHE | 5 + LICENSE-MIT | 19 +++ README.md | 51 +++---- package.json | 169 ++++++++++++++++------ test/browser.ts | 1 - test/node.ts | 3 - 12 files changed, 387 insertions(+), 186 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/automerge.yml create mode 100644 .github/workflows/js-test-and-release.yml delete mode 100644 .npmignore delete mode 100644 .travis.yml create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT delete mode 100644 test/browser.ts delete mode 100644 test/node.ts diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..290ad02 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "10:00" + open-pull-requests-limit: 10 diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 0000000..13da9c1 --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,50 @@ +# Automatically merge pull requests opened by web3-bot, as soon as (and only if) all tests pass. +# This reduces the friction associated with updating with our workflows. + +on: [ pull_request ] +name: Automerge + +jobs: + automerge-check: + if: github.event.pull_request.user.login == 'web3-bot' + runs-on: ubuntu-latest + outputs: + status: ${{ steps.should-automerge.outputs.status }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Check if we should automerge + id: should-automerge + run: | + for commit in $(git rev-list --first-parent origin/${{ github.event.pull_request.base.ref }}..${{ github.event.pull_request.head.sha }}); do + committer=$(git show --format=$'%ce' -s $commit) + echo "Committer: $committer" + if [[ "$committer" != "web3-bot@users.noreply.github.com" ]]; then + echo "Commit $commit wasn't committed by web3-bot, but by $committer." + echo "::set-output name=status::false" + exit + fi + done + echo "::set-output name=status::true" + automerge: + needs: automerge-check + runs-on: ubuntu-latest + # The check for the user is redundant here, as this job depends on the automerge-check job, + # but it prevents this job from spinning up, just to be skipped shortly after. + if: github.event.pull_request.user.login == 'web3-bot' && needs.automerge-check.outputs.status == 'true' + steps: + - name: Wait on tests + uses: lewagon/wait-on-check-action@bafe56a6863672c681c3cf671f5e10b20abf2eaa # v0.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + repo-token: ${{ secrets.GITHUB_TOKEN }} + wait-interval: 10 + running-workflow-name: 'automerge' # the name of this job + - name: Merge PR + uses: pascalgn/automerge-action@741c311a47881be9625932b0a0de1b0937aab1ae # v0.13.1 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + MERGE_LABELS: "" + MERGE_METHOD: "squash" + MERGE_DELETE_BRANCH: true diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml new file mode 100644 index 0000000..8630dc5 --- /dev/null +++ b/.github/workflows/js-test-and-release.yml @@ -0,0 +1,152 @@ +name: test & maybe release +on: + push: + branches: + - master # with #262 - ${{{ github.default_branch }}} + pull_request: + branches: + - master # with #262 - ${{{ github.default_branch }}} + +jobs: + + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present lint + - run: npm run --if-present dep-check + + test-node: + needs: check + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + node: [16] + fail-fast: true + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node }} + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:node + - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + with: + directory: ./.nyc_output + flags: node + + test-chrome: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:chrome + - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + with: + directory: ./.nyc_output + flags: chrome + + test-chrome-webworker: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:chrome-webworker + - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + with: + directory: ./.nyc_output + flags: chrome-webworker + + test-firefox: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:firefox + - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + with: + directory: ./.nyc_output + flags: firefox + + test-firefox-webworker: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:firefox-webworker + - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + with: + directory: ./.nyc_output + flags: firefox-webworker + + test-electron-main: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npx xvfb-maybe npm run --if-present test:electron-main + - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + with: + directory: ./.nyc_output + flags: electron-main + + test-electron-renderer: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npx xvfb-maybe npm run --if-present test:electron-renderer + - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + with: + directory: ./.nyc_output + flags: electron-renderer + + release: + needs: [test-node, test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer] + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/master' # with #262 - 'refs/heads/${{{ github.default_branch }}}' + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - uses: ipfs/aegir/actions/docker-login@master + with: + docker-token: ${{ secrets.DOCKER_TOKEN }} + docker-username: ${{ secrets.DOCKER_USERNAME }} + - run: npm run --if-present release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 70ea7a6..0000000 --- a/.npmignore +++ /dev/null @@ -1,33 +0,0 @@ - -.DS_Store -tests/repo-tests* - -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directory -# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git -node_modules - -test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7b330e9..0000000 --- a/.travis.yml +++ /dev/null @@ -1,58 +0,0 @@ -language: node_js -cache: npm -dist: bionic -stages: - - check - - test - - cov - -branches: - only: - - master - - /^release\/.*$/ - -node_js: - - 'lts/*' - - 'node' - -os: - - linux - - osx - - windows - -script: npx aegir test -t node --cov --bail -after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov - -jobs: - include: - - stage: check - script: - - npx aegir dep-check - - npm run lint - - - stage: test - name: chrome - addons: - chrome: stable - script: npx aegir test -t browser -t webworker - - - stage: test - name: firefox - addons: - firefox: latest - script: npx aegir test -t browser -t webworker -- --browser firefox - - - stage: test - name: electron-main - os: osx - script: - - npx aegir test -t electron-main --bail - - - stage: test - name: electron-renderer - os: osx - script: - - npx aegir test -t electron-renderer --bail - -notifications: - email: false \ No newline at end of file diff --git a/LICENSE b/LICENSE index b7cf9f5..20ce483 100644 --- a/LICENSE +++ b/LICENSE @@ -1,22 +1,4 @@ -The MIT License (MIT) - -Copyright (c) 2016 David Dias - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +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/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,5 @@ +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/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index 245bdce..1641be8 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# hamt-sharding +# hamt-sharding [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) [![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) -[![Build Status](https://flat.badgen.net/travis/ipfs-shipyard/js-hamt-sharding)](https://travis-ci.com/ipfs-shipyard/js-hamt-sharding) +[![Build Status](https://github.com/ipfs/js-hamt-sharding/actions/workflows/js-test-and-release.yml/badge.svg?branch=main)](https://github.com/ipfs/js-hamt-sharding/actions/workflows/js-test-and-release.yml) [![Codecov](https://codecov.io/gh/ipfs-shipyard/js-hamt-sharding/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs-shipyard/js-hamt-sharding) [![Dependency Status](https://david-dm.org/ipfs-shipyard/js-hamt-sharding.svg?style=flat-square)](https://david-dm.org/ipfs/js-hamt-sharding) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) @@ -13,33 +13,26 @@ > JavaScript implementation of hamt for use in sharding -## Lead Maintainer - -[Alex Potsides](https://github.com/achingbrain) - -## Table of Contents - -- [hamt-sharding](#hamt-sharding) - - [Lead Maintainer](#lead-maintainer) - - [Table of Contents](#table-of-contents) - - [Install](#install) - - [Usage](#usage) - - [Example](#example) - - [API](#api) - - [`bucket.put(key, value)`](#bucketputkey-value) - - [`bucket.get(key)`](#bucketgetkey) - - [`bucket.del(key)`](#bucketdelkey) - - [`bucket.leafCount()`](#bucketleafcount) - - [`bucket.childrenCount()`](#bucketchildrencount) - - [`bucket.onlyChild()`](#bucketonlychild) - - [`bucket.eachLeafSeries()`](#bucketeachleafseries) - - [`bucket.serialize(map, reduce)`](#bucketserializemap-reduce) - - [`bucket.asyncTransform(asyncMap, asyncReduce)`](#bucketasynctransformasyncmap-asyncreduce) - - [`bucket.toJSON()`](#buckettojson) - - [`bucket.prettyPrint()`](#bucketprettyprint) - - [`bucket.tableSize()`](#buckettablesize) - - [Contribute](#contribute) - - [License](#license) +## Table of Contents + +- [Install](#install) +- [Usage](#usage) + - [Example](#example) +- [API](#api) + - [`bucket.put(key, value)`](#bucketputkey-value) + - [`bucket.get(key)`](#bucketgetkey) + - [`bucket.del(key)`](#bucketdelkey) + - [`bucket.leafCount()`](#bucketleafcount) + - [`bucket.childrenCount()`](#bucketchildrencount) + - [`bucket.onlyChild()`](#bucketonlychild) + - [`bucket.eachLeafSeries()`](#bucketeachleafseries) + - [`bucket.serialize(map, reduce)`](#bucketserializemap-reduce) + - [`bucket.asyncTransform(asyncMap, asyncReduce)`](#bucketasynctransformasyncmap-asyncreduce) + - [`bucket.toJSON()`](#buckettojson) + - [`bucket.prettyPrint()`](#bucketprettyprint) + - [`bucket.tableSize()`](#buckettablesize) +- [Contribute](#contribute) +- [License](#license) ## Install diff --git a/package.json b/package.json index 3039ce6..8e6caf4 100644 --- a/package.json +++ b/package.json @@ -2,60 +2,147 @@ "name": "hamt-sharding", "version": "2.0.1", "description": "JavaScript implementation of sharding using hash array mapped tries", - "leadMaintainer": "Alex Potsides ", - "main": "dist/src/index.js", - "type": "module", - "scripts": { - "pretest": "npm run build", - "test": "aegir test -f ./dist/test/*.js", - "prepare": "npm run build", - "lint": "aegir ts -p check && aegir lint", - "release": "aegir release", - "release-minor": "aegir release --type minor", - "release-major": "aegir release --type major", - "coverage": "aegir coverage", - "build": "tsc" - }, + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/ipfs/js-hamt-sharding#readme", "repository": { "type": "git", - "url": "git+https://github.com/ipfs-shipyard/js-hamt-sharding.git" + "url": "git+https://github.com/ipfs/js-hamt-sharding.git" + }, + "bugs": { + "url": "https://github.com/ipfs/js-hamt-sharding/issues" }, "keywords": [ "IPFS", "hamt", "sharding" ], - "license": "MIT", - "bugs": { - "url": "https://github.com/ipfs-shipyard/js-hamt-sharding/issues" - }, "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" + "node": ">=16.0.0", + "npm": ">=7.0.0" }, - "homepage": "https://github.com/ipfs-shipyard/js-hamt-sharding#readme", - "devDependencies": { - "aegir": "^35.0.2", - "it-length": "^1.0.3", - "multihashing-async": "^2.1.0", - "util": "^0.12.4" + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "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": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "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": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "tsc", + "pretest": "npm run build", + "test": "aegir test -f ./dist/test/*.js -f ./dist/test/**/*.js", + "test:node": "npm run test -- -t node", + "test:chrome": "npm run test -- -t browser", + "test:chrome-webworker": "npm run test -- -t webworker", + "test:firefox": "npm run test -- -t browser -- --browser firefox", + "test:firefox-webworker": "npm run test -- -t webworker -- --browser firefox", + "test:electron-main": "npm run test -- -t electron-main", + "prepare": "npm run build", + "lint": "aegir lint", + "dep-check": "aegir dep-check dist/src/**/*.js dist/test/**/*.js", + "release": "semantic-release" }, "dependencies": { "sparse-array": "^1.3.1", "uint8arrays": "^3.0.0" }, - "contributors": [ - "achingbrain " - ], - "typesVersions": { - "*": { - "src/*": [ - "dist/src/*", - "dist/src/*/index" - ] - } - }, - "files": [ - "dist/src" - ] + "devDependencies": { + "aegir": "^36.1.3", + "it-length": "^1.0.3", + "multihashing-async": "^2.1.0", + "util": "^0.12.4" + } } diff --git a/test/browser.ts b/test/browser.ts deleted file mode 100644 index 4640a0e..0000000 --- a/test/browser.ts +++ /dev/null @@ -1 +0,0 @@ -import './node.js' diff --git a/test/node.ts b/test/node.ts deleted file mode 100644 index bdceee7..0000000 --- a/test/node.ts +++ /dev/null @@ -1,3 +0,0 @@ -import './hamt.spec.js' -import './hamt-consumable-buffer.spec.js' -import './hamt-consumable-hash.spec.js' From a680124dd1e2afd4b2f3cf6852f675a63165ee68 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 21 Feb 2022 16:50:03 +0200 Subject: [PATCH 2/2] chore: fix linting --- package.json | 3 +-- src/bucket.ts | 30 +++++++++++++++--------------- src/consumable-buffer.ts | 2 +- src/consumable-hash.ts | 2 +- src/index.ts | 4 ++-- test/hamt.spec.ts | 8 ++++---- 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 8e6caf4..99454e5 100644 --- a/package.json +++ b/package.json @@ -142,7 +142,6 @@ "devDependencies": { "aegir": "^36.1.3", "it-length": "^1.0.3", - "multihashing-async": "^2.1.0", - "util": "^0.12.4" + "multihashing-async": "^2.1.0" } } diff --git a/src/bucket.ts b/src/bucket.ts index 2212bd1..acaee54 100644 --- a/src/bucket.ts +++ b/src/bucket.ts @@ -1,4 +1,4 @@ -// @ts-ignore +// @ts-expect-error import SparseArray from 'sparse-array' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import type { InfiniteHash } from './consumable-hash.js' @@ -59,7 +59,7 @@ export class Bucket { async get (key: string) { const child = await this._findChild(key) - if (child) { + if (child != null) { return child.value } } @@ -68,7 +68,7 @@ export class Bucket { const place = await this._findPlace(key) const child = place.bucket._at(place.pos) - if (child && child.key === key) { + if (child != null && child.key === key) { place.bucket._delAt(place.pos) } } @@ -109,7 +109,7 @@ export class Bucket { const acc: T[] = [] // serialize to a custom non-sparse representation return reduce(this._children.reduce((acc, child, index) => { - if (child) { + if (child != null) { if (child instanceof Bucket) { acc.push(child.serialize(map, reduce)) } else { @@ -120,8 +120,8 @@ export class Bucket { }, acc)) } - asyncTransform (asyncMap: (value: BucketChild) => Promise, asyncReduce: (reduced: any) => Promise) { - return asyncTransformBucket(this, asyncMap, asyncReduce) + async asyncTransform (asyncMap: (value: BucketChild) => Promise, asyncReduce: (reduced: any) => Promise) { + return await asyncTransformBucket(this, asyncMap, asyncReduce) } toJSON () { @@ -146,7 +146,7 @@ export class Bucket { return undefined } - if (child && child.key === key) { + if (child != null && child.key === key) { return child } } @@ -158,7 +158,7 @@ export class Bucket { const child = this._children.get(index) if (child instanceof Bucket) { - return child._findPlace(hashValue) + return await child._findPlace(hashValue) } return { @@ -172,7 +172,7 @@ export class Bucket { async _findNewBucketAndPos (key: string | InfiniteHash): Promise> { const place = await this._findPlace(key) - if (place.existingChild && place.existingChild.key !== key) { + if ((place.existingChild != null) && place.existingChild.key !== key) { // conflict const bucket = new Bucket(this._options, place.bucket, place.pos) place.bucket._putObjectAt(place.pos, bucket) @@ -181,7 +181,7 @@ export class Bucket { const newPlace = await bucket._findPlace(place.existingChild.hash) newPlace.bucket._putAt(newPlace, place.existingChild.key, place.existingChild.value) - return bucket._findNewBucketAndPos(place.hash) + return await bucket._findNewBucketAndPos(place.hash) } // no conflict, we found the place @@ -197,7 +197,7 @@ export class Bucket { } _putObjectAt (pos: number, object: Bucket | BucketChild) { - if (!this._children.get(pos)) { + if (this._children.get(pos) == null) { this._popCount++ } this._children.set(pos, object) @@ -208,7 +208,7 @@ export class Bucket { throw new Error('Invalid position') } - if (this._children.get(pos)) { + if (this._children.get(pos) != null) { this._popCount-- } this._children.unset(pos) @@ -216,12 +216,12 @@ export class Bucket { } _level () { - if (this._parent && this._popCount <= 1) { + if (this._parent != null && this._popCount <= 1) { if (this._popCount === 1) { // remove myself from parent, replacing me with my only child const onlyChild = this._children.find(exists) - if (onlyChild && !(onlyChild instanceof Bucket)) { + if ((onlyChild != null) && !(onlyChild instanceof Bucket)) { const hash = onlyChild.hash hash.untake(this._options.bits) const place = { @@ -270,5 +270,5 @@ async function asyncTransformBucket (bucket: Bucket, asyncMap: (value: Buc } } - return asyncReduce(output) + return await asyncReduce(output) } diff --git a/src/consumable-buffer.ts b/src/consumable-buffer.ts index deb2a0a..d1103a6 100644 --- a/src/consumable-buffer.ts +++ b/src/consumable-buffer.ts @@ -42,7 +42,7 @@ export class ConsumableBuffer { take (bits: number) { let pendingBits = bits let result = 0 - while (pendingBits && this._haveBits()) { + while (pendingBits > 0 && this._haveBits()) { const byte = this._value[this._currentBytePos] const availableBits = this._currentBitPos + 1 const taking = Math.min(availableBits, pendingBits) diff --git a/src/consumable-hash.ts b/src/consumable-hash.ts index 5cfc36a..819be16 100644 --- a/src/consumable-hash.ts +++ b/src/consumable-hash.ts @@ -80,7 +80,7 @@ export class InfiniteHash { async _produceMoreBits () { this._depth++ - const value = this._depth ? uint8ArrayConcat([this._value, Uint8Array.from([this._depth])]) : this._value + const value = this._depth > 0 ? uint8ArrayConcat([this._value, Uint8Array.from([this._depth])]) : this._value const hashValue = await this._hashFn(value) const buffer = new ConsumableBuffer(hashValue) diff --git a/src/index.ts b/src/index.ts index e3d3bc6..8f4aa96 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,12 +8,12 @@ interface UserBucketOptions { } export function createHAMT (options: UserBucketOptions) { - if (!options || !options.hashFn) { + if (options == null || options.hashFn == null) { throw new Error('please define an options.hashFn') } const bucketOptions = { - bits: options.bits || 8, + bits: options.bits ?? 8, hash: wrapHash(options.hashFn) } diff --git a/test/hamt.spec.ts b/test/hamt.spec.ts index 12a3b14..095f622 100644 --- a/test/hamt.spec.ts +++ b/test/hamt.spec.ts @@ -27,7 +27,7 @@ describe('HAMT', () => { it('should require a hash function', () => { try { - // @ts-ignore options are not optional + // @ts-expect-error options are not optional createHAMT() throw new Error('Should have required a hash function') @@ -38,7 +38,7 @@ describe('HAMT', () => { it('should require a hash function with options', () => { try { - // @ts-ignore hashFn is required + // @ts-expect-error hashFn is required createHAMT({}) throw new Error('Should have required a hash function') @@ -155,7 +155,7 @@ describe('HAMT', () => { it('accepts putting many keys in parallel', async () => { const keys = Array.from({ length: 400 }, (_, i) => i.toString()) - await Promise.all(keys.map(key => bucket.put(key, key))) + await Promise.all(keys.map(async key => await bucket.put(key, key))) }) it('can remove all the keys and still find remaining', async function () { @@ -165,7 +165,7 @@ describe('HAMT', () => { const masterHead = keys.pop() - if (!masterHead) { + if (masterHead == null) { throw new Error('masterHead not found') }