From 69cab660ad927f8e99bfc5a3777723b972b7e4b2 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 19 Oct 2022 12:06:51 +0100 Subject: [PATCH] feat!: publish as esm-only (#99) Following on from the conversation in https://github.com/ipld/ipld/issues/224 this converts this repo to use the latest aegir with Unified CI. 1. Remove all build related dev deps apart from `aegir` 1. Run the `npx aegir check-project` command to update project config 1. Remove non-Unified-CI github actions 1. Moved source files into `src` 1. Rename `test/*.js` to `test/*.spec.js` so aegir can find them 1. Update `tsconfig.json` to extend config from `aegir` 1. Remove `"main"` and other unused fields from `package.json` 1. Use `chai` from `aegir` pre-configured with plugins we use 1. Fixes everything the linter complains about 1. Updates `multiformats` to 10.x.x BREAKING CHANGE: this module is now ESM-only --- .github/dependabot.yml | 41 ++- .github/workflows/automerge.yml | 8 + .github/workflows/js-test-and-release.yml | 145 +++++++++ .github/workflows/test-and-release.yml | 63 ---- .gitignore | 2 +- .npmignore | 12 - LICENSE | 4 + LICENSE-APACHE | 14 +- LICENSE-MIT | 20 +- README.md | 16 +- car-browser.js | 14 - car.js | 16 - lib/coding.ts | 56 ---- lib/header-validator.js | 33 -- package.json | 282 +++++++----------- api.ts => src/api.ts | 28 +- {lib => src}/buffer-writer.js | 10 +- src/coding.ts | 56 ++++ {lib => src}/decoder.js | 8 +- {lib => src}/encoder.js | 2 +- src/header-validator.js | 74 +++++ {lib => src}/header.ipldsch | 0 src/index-browser.js | 14 + src/index.js | 16 + {lib => src}/indexed-reader-browser.js | 0 {lib => src}/indexed-reader.js | 18 +- {lib => src}/indexer.js | 8 +- {lib => src}/iterator-channel.js | 0 {lib => src}/iterator.js | 8 +- {lib => src}/reader-browser.js | 14 +- {lib => src}/reader.js | 10 +- {lib => src}/writer-browser.js | 14 +- {lib => src}/writer.js | 6 +- test/common.js | 11 +- test/node-test-file-streams.js | 4 +- test/node-test-indexed-reader.js | 2 +- test/node-test-large.js | 6 +- test/node-test-raw.js | 4 +- test/node-test-updateroots.js | 4 +- test/node.js | 6 + ...r-writer.js => test-buffer-writer.spec.js} | 6 +- test/{test-errors.js => test-errors.spec.js} | 2 +- .../{test-indexer.js => test-indexer.spec.js} | 13 +- ...st-interface.js => test-interface.spec.js} | 10 +- ...test-iterator.js => test-iterator.spec.js} | 13 +- test/{test-reader.js => test-reader.spec.js} | 23 +- test/{test-writer.js => test-writer.spec.js} | 31 +- test/verify-store-reader.js | 10 +- tsconfig.json | 48 +-- 49 files changed, 621 insertions(+), 584 deletions(-) create mode 100644 .github/workflows/automerge.yml create mode 100644 .github/workflows/js-test-and-release.yml delete mode 100644 .github/workflows/test-and-release.yml delete mode 100644 .npmignore create mode 100644 LICENSE delete mode 100644 car-browser.js delete mode 100644 car.js delete mode 100644 lib/coding.ts delete mode 100644 lib/header-validator.js rename api.ts => src/api.ts (68%) rename {lib => src}/buffer-writer.js (96%) create mode 100644 src/coding.ts rename {lib => src}/decoder.js (98%) rename {lib => src}/encoder.js (97%) create mode 100644 src/header-validator.js rename {lib => src}/header.ipldsch (100%) create mode 100644 src/index-browser.js create mode 100644 src/index.js rename {lib => src}/indexed-reader-browser.js (100%) rename {lib => src}/indexed-reader.js (96%) rename {lib => src}/indexer.js (96%) rename {lib => src}/iterator-channel.js (100%) rename {lib => src}/iterator.js (98%) rename {lib => src}/reader-browser.js (97%) rename {lib => src}/reader.js (85%) rename {lib => src}/writer-browser.js (95%) rename {lib => src}/writer.js (93%) create mode 100644 test/node.js rename test/{test-buffer-writer.js => test-buffer-writer.spec.js} (98%) rename test/{test-errors.js => test-errors.spec.js} (98%) rename test/{test-indexer.js => test-indexer.spec.js} (82%) rename test/{test-interface.js => test-interface.spec.js} (69%) rename test/{test-iterator.js => test-iterator.spec.js} (78%) rename test/{test-reader.js => test-reader.spec.js} (91%) rename test/{test-writer.js => test-writer.spec.js} (88%) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fcba1ef..e95739a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,25 +1,20 @@ version: 2 updates: - - package-ecosystem: 'github-actions' - directory: '/' - schedule: - interval: 'daily' - commit-message: - prefix: 'chore' - include: 'scope' - - package-ecosystem: 'npm' - directory: '/' - schedule: - interval: 'daily' - commit-message: - prefix: 'chore' - include: 'scope' - - package-ecosystem: 'npm' - directory: '/examples/' - schedule: - interval: 'daily' - ignore: - - dependency-name: "@ipld/car" - commit-message: - prefix: 'chore' - include: 'scope' +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "10:00" + open-pull-requests-limit: 10 + commit-message: + prefix: "deps" + prefix-development: "deps(dev)" +- package-ecosystem: 'npm' + directory: '/examples/' + schedule: + interval: 'daily' + ignore: + - dependency-name: "@ipld/car" + commit-message: + prefix: 'chore' + include: 'scope' diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 0000000..d57c2a0 --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,8 @@ +name: Automerge +on: [ pull_request ] + +jobs: + automerge: + uses: protocol/.github/.github/workflows/automerge.yml@master + with: + job: 'automerge' diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml new file mode 100644 index 0000000..d155996 --- /dev/null +++ b/.github/workflows/js-test-and-release.yml @@ -0,0 +1,145 @@ +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@v3 + - uses: actions/setup-node@v3 + 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@v3 + - uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node }} + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:node + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: node + + test-chrome: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:chrome + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: chrome + + test-chrome-webworker: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:chrome-webworker + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: chrome-webworker + + test-firefox: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:firefox + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: firefox + + test-firefox-webworker: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:firefox-webworker + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: firefox-webworker + + test-electron-main: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + 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@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: electron-main + + test-electron-renderer: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + 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@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + 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@v3 + with: + fetch-depth: 0 + - uses: actions/setup-node@v3 + 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/.github/workflows/test-and-release.yml b/.github/workflows/test-and-release.yml deleted file mode 100644 index 636846f..0000000 --- a/.github/workflows/test-and-release.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Test & Maybe Release -on: [push, pull_request] -jobs: - test: - strategy: - fail-fast: false - matrix: - node: [14.x, 16.x] - os: [macos-latest, ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout Repository - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v3.5.1 - with: - node-version: ${{ matrix.node }} - - name: Install Dependencies - run: | - npm install --no-progress - - name: Run tests - run: | - npm config set script-shell bash - npm run test:ci - - name: Typecheck - uses: gozala/typescript-error-reporter-action@v1.0.8 - release: - name: Release - needs: test - runs-on: ubuntu-latest - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Setup Node.js - uses: actions/setup-node@v3.5.1 - with: - node-version: 14 - - name: Install dependencies - run: | - npm install --no-progress --no-package-lock --no-save - - name: Build - run: | - npm run build - - name: Install plugins - run: | - npm install \ - @semantic-release/commit-analyzer \ - conventional-changelog-conventionalcommits \ - @semantic-release/release-notes-generator \ - @semantic-release/npm \ - @semantic-release/github \ - @semantic-release/git \ - @semantic-release/changelog \ - --no-progress --no-package-lock --no-save - - name: Release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: npx semantic-release - diff --git a/.gitignore b/.gitignore index 4e2c177..b5f733a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ package-lock.json node_modules/ .nyc_output/ -coverage/ +.coverage/ build/ dist/ types/ diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 62e4bf3..0000000 --- a/.npmignore +++ /dev/null @@ -1,12 +0,0 @@ -test/fixtures/ -test/fixtures.js -test/fixtures-expectations.js -esm/browser-test/fixtures.js -esm/node-test/fixtures.js -cjs/browser-test/fixtures.js -cjs/node-test/fixtures.js -test/fixtures-expectations.js -esm/browser-test/fixtures-expectations.js -esm/node-test/fixtures-expectations.js -cjs/browser-test/fixtures-expectations.js -cjs/node-test/fixtures-expectations.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/LICENSE @@ -0,0 +1,4 @@ +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 index fcd6df3..14478a3 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -1,13 +1,5 @@ -Copyright 2020 Protocol Labs +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 -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 - 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. +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 index 9bddb3e..72dc60d 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,7 +1,19 @@ -Copyright 2020 Protocol Labs +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: +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 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. +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 06070b6..4421e43 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,21 @@ # @ipld/car -A JavaScript Content Addressable aRchive (CAR) file reader and writer. +[![codecov](https://img.shields.io/codecov/c/github/ipld/js-car.svg?style=flat-square)](https://codecov.io/gh/ipld/js-car) +[![CI](https://img.shields.io/github/workflow/status/ipld/js-car/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipld/js-car/actions/workflows/js-test-and-release.yml) + +> Content Addressable aRchive format reader and writer + +## Install + +```console +$ npm i @ipld/car +``` See also: * Original [Go implementation](https://github.com/ipfs/go-car) * [CAR specification](https://github.com/ipld/specs/blob/master/block-layer/content-addressable-archives.md) * [IPLD](https://ipld.io) - ## Contents @@ -944,8 +952,8 @@ to `byteLimit` bytes. It _does not_ update `pos` of the original Licensed under either of - * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) - * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) + * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) + * MIT ([LICENSE-MIT](LICENSE-MIT) / ) ### Contribution diff --git a/car-browser.js b/car-browser.js deleted file mode 100644 index 0a29d45..0000000 --- a/car-browser.js +++ /dev/null @@ -1,14 +0,0 @@ -import { CarReader } from './lib/reader-browser.js' -import { CarIndexer } from './lib/indexer.js' -import { CarBlockIterator, CarCIDIterator } from './lib/iterator.js' -import { CarWriter } from './lib/writer-browser.js' -import { CarIndexedReader } from './lib/indexed-reader-browser.js' - -export { - CarReader, - CarIndexer, - CarBlockIterator, - CarCIDIterator, - CarWriter, - CarIndexedReader -} diff --git a/car.js b/car.js deleted file mode 100644 index f956e27..0000000 --- a/car.js +++ /dev/null @@ -1,16 +0,0 @@ -import { CarReader } from './lib/reader.js' -import { CarIndexer } from './lib/indexer.js' -import { CarBlockIterator, CarCIDIterator } from './lib/iterator.js' -import { CarWriter } from './lib/writer.js' -import { CarIndexedReader } from './lib/indexed-reader.js' -import * as CarBufferWriter from './lib/buffer-writer.js' - -export { - CarReader, - CarIndexer, - CarBlockIterator, - CarCIDIterator, - CarWriter, - CarIndexedReader, - CarBufferWriter -} diff --git a/lib/coding.ts b/lib/coding.ts deleted file mode 100644 index a5a0fca..0000000 --- a/lib/coding.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { CID } from 'multiformats/cid' -import { Block, BlockIndex } from '../api' - -export interface CarEncoder { - setRoots(roots: CID[]): Promise - - writeBlock(block: Block): Promise - - close(): Promise -} - -export interface IteratorChannel_Writer { - write(chunk: T): Promise - end(): Promise -} - -export interface IteratorChannel { - writer: IteratorChannel_Writer - - iterator: AsyncIterator -} - -export interface CarHeader { - version: 1, - roots: CID[] -} - -export interface CarV2FixedHeader { - characteristics: [bigint, bigint], - dataOffset: number, - dataSize: number, - indexOffset: number -} - -export interface CarV2Header extends CarV2FixedHeader { - version: 2, - roots: CID[], -} - -export interface CarDecoder { - header(): Promise - - blocks(): AsyncGenerator - - blocksIndex(): AsyncGenerator -} - -export interface BytesReader { - upTo(length: number): Promise - - exactly(length: number): Promise - - seek(length: number): void - - pos: number -} diff --git a/lib/header-validator.js b/lib/header-validator.js deleted file mode 100644 index 634e64b..0000000 --- a/lib/header-validator.js +++ /dev/null @@ -1,33 +0,0 @@ -/** Auto-generated with ipld-schema-validator@0.0.0-dev at Thu Jun 17 2021 from IPLD Schema: - * - * type CarHeader struct { - * version Int - * roots optional [&Any] - * # roots is _not_ optional for CarV1 but we defer that check within code to - * # gracefully handle the >V1 case where it's just {version:X} - * } - * - */ - -const Kinds = { - Null: /** @returns {boolean} */ (/** @type {any} */ obj) => obj === null, - Int: /** @returns {boolean} */ (/** @type {any} */ obj) => Number.isInteger(obj), - Float: /** @returns {boolean} */ (/** @type {any} */ obj) => typeof obj === 'number' && Number.isFinite(obj), - String: /** @returns {boolean} */ (/** @type {any} */ obj) => typeof obj === 'string', - Bool: /** @returns {boolean} */ (/** @type {any} */ obj) => typeof obj === 'boolean', - Bytes: /** @returns {boolean} */ (/** @type {any} */ obj) => obj instanceof Uint8Array, - Link: /** @returns {boolean} */ (/** @type {any} */ obj) => !Kinds.Null(obj) && typeof obj === 'object' && obj.asCID === obj, - List: /** @returns {boolean} */ (/** @type {any} */ obj) => Array.isArray(obj), - Map: /** @returns {boolean} */ (/** @type {any} */ obj) => !Kinds.Null(obj) && typeof obj === 'object' && obj.asCID !== obj && !Kinds.List(obj) && !Kinds.Bytes(obj) -} -/** @type {{ [k in string]: (obj:any)=>boolean}} */ -const Types = { - Int: Kinds.Int, - 'CarHeader > version': /** @returns {boolean} */ (/** @type {any} */ obj) => Types.Int(obj), - 'CarHeader > roots (anon) > valueType (anon)': Kinds.Link, - 'CarHeader > roots (anon)': /** @returns {boolean} */ (/** @type {any} */ obj) => Kinds.List(obj) && Array.prototype.every.call(obj, Types['CarHeader > roots (anon) > valueType (anon)']), - 'CarHeader > roots': /** @returns {boolean} */ (/** @type {any} */ obj) => Types['CarHeader > roots (anon)'](obj), - CarHeader: /** @returns {boolean} */ (/** @type {any} */ obj) => { const keys = obj && Object.keys(obj); return Kinds.Map(obj) && ['version'].every((k) => keys.includes(k)) && Object.entries(obj).every(([name, value]) => Types['CarHeader > ' + name] && Types['CarHeader > ' + name](value)) } -} - -export const CarHeader = Types.CarHeader diff --git a/package.json b/package.json index b4e5c9c..1cf86bb 100644 --- a/package.json +++ b/package.json @@ -2,220 +2,142 @@ "name": "@ipld/car", "version": "0.0.0-dev", "description": "Content Addressable aRchive format reader and writer", - "main": "car.js", - "types": "./types/car.d.ts", - "type": "module", - "scripts": { - "lint": "standard", - "build": "npm run build:js && npm run build:types", - "build:js": "ipjs build --tests --main && npm run build:copy", - "build:copy": "mkdir -p dist/examples/ && cp -a tsconfig.json .npmignore *.js *.ts lib test dist/ && cp examples/*.* dist/examples/ && rm -rf dist/test/fixtures/", - "build:types": "tsc --build && mv types dist", - "test:cjs": "rm -rf dist && npm run build && cp test/go.car dist/cjs/node-test/ && mocha dist/cjs/node-test/test-*.js && mocha dist/cjs/node-test/node-test-*.js && npm run test:cjs:browser", - "test:esm": "rm -rf dist && npm run build && cp test/go.car dist/esm/node-test/ && mocha dist/esm/node-test/test-*.js && mocha dist/esm/node-test/node-test-*.js && npm run test:esm:browser", - "test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --exclude lib/header-validator.js --exclude test/ mocha test/test-*.js test/node-test-*.js", - "test:cjs:browser": "polendina --page --worker --serviceworker --cleanup dist/cjs/browser-test/test-*.js", - "test:esm:browser": "polendina --page --worker --serviceworker --cleanup dist/esm/browser-test/test-*.js", - "test": "npm run lint && npm run test:node && npm run test:cjs && npm run test --prefix examples/", - "test:ci": "npm run lint && npm run test:node && npm run test:esm && npm run test:cjs && npm run test --prefix examples/", - "coverage": "c8 --reporter=html --reporter=text mocha test/test-*.js && npx st -d coverage -p 8888", - "docs": "jsdoc4readme --readme --description-only lib/reader*.js lib/indexed-reader.js lib/iterator.js lib/indexer.js lib/writer*.js lib/buffer-writer.js lib/decoder.js" + "author": "Rod (http://r.va.gg/)", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/ipld/js-car#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/ipld/js-car.git" + }, + "bugs": { + "url": "https://github.com/ipld/js-car/issues" }, "keywords": [ "car", - "ipld", "ipfs", + "ipld", "multiformats" ], - "author": "Rod (http://r.va.gg/)", - "license": "(Apache-2.0 AND MIT)", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ], + "src/*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ] + } + }, + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], "exports": { ".": { - "browser": "./car-browser.js", - "import": "./car.js" + "types": "./dist/src/index.d.ts", + "import": "./src/index.js", + "browser": "./src/index-browser.js" }, - "./decoder": { - "import": "./lib/decoder.js" + "./buffer-writer": { + "types": "./dist/src/buffer-writer.d.ts", + "import": "./src/buffer-writer.js" }, - "./reader": { - "browser": "./lib/reader-browser.js", - "import": "./lib/reader.js" + "./decoder": { + "types": "./dist/src/decoder.d.ts", + "import": "./src/decoder.js" }, "./indexed-reader": { - "browser": "./lib/indexed-reader-browser.js", - "import": "./lib/indexed-reader.js" + "types": "./dist/src/indexed-reader.d.ts", + "browser": "./src/indexed-reader-browser.js", + "import": "./src/indexed-reader.js" }, "./indexer": { - "import": "./lib/indexer.js" + "types": "./dist/src/indexer.d.ts", + "import": "./src/indexer.js" }, "./iterator": { - "import": "./lib/iterator.js" + "types": "./dist/src/iterator.d.ts", + "import": "./src/iterator.js" }, - "./writer": { - "browser": "./lib/writer-browser.js", - "import": "./lib/writer.js" + "./reader": { + "types": "./dist/src/reader.d.ts", + "browser": "./src/reader-browser.js", + "import": "./src/reader.js" }, - "./buffer-writer": { - "import": "./lib/buffer-writer.js" + "./writer": { + "types": "./dist/src/writer.d.ts", + "browser": "./src/writer-browser.js", + "import": "./src/writer.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" } }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "build": "aegir build", + "release": "aegir release", + "test": "npm run lint && aegir test && npm run test:examples", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "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", + "test:examples": "npm run test --prefix examples/", + "dep-check": "aegir dep-check", + "coverage": "c8 --reporter=html --reporter=text mocha test/test-*.js && npx st -d coverage -p 8888", + "docs": "jsdoc4readme --readme --description-only src/reader*.js src/indexed-reader.js src/iterator.js src/indexer.js src/writer*.js src/buffer-writer.js src/decoder.js" + }, "dependencies": { - "@ipld/dag-cbor": "^7.0.0", + "@ipld/dag-cbor": "^8.0.0", "cborg": "^1.9.0", - "multiformats": "^9.5.4", + "multiformats": "^10.0.2", "varint": "^6.0.0" }, "devDependencies": { - "@ipld/dag-pb": "^2.1.14", - "@types/chai": "^4.3.0", - "@types/chai-as-promised": "^7.1.4", - "@types/mocha": "^10.0.0", + "@ipld/dag-pb": "^3.0.0", + "@ipld/garbage": "^6.0.0", "@types/node": "^18.0.0", "@types/varint": "^6.0.0", "@typescript-eslint/eslint-plugin": "^5.6.0", "@typescript-eslint/parser": "^5.6.0", - "c8": "^7.10.0", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.1", - "ipjs": "^5.2.0", - "ipld-garbage": "^5.0.0", - "jsdoc4readme": "^1.4.0", - "mocha": "^10.0.0", - "polendina": "~3.1.0", - "standard": "^17.0.0", - "typescript": "~4.8.2" + "aegir": "^37.5.6", + "jsdoc4readme": "^1.4.0" + }, + "directories": { + "test": "test" }, "standard": { "ignore": [ "dist" ] }, - "directories": { - "test": "test" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/ipld/js-car.git" - }, - "bugs": { - "url": "https://github.com/ipld/js-car/issues" - }, - "homepage": "https://github.com/ipld/js-car#readme", - "typesVersions": { - "*": { - "reader": [ - "types/lib/reader.d.ts" - ], - "decoder": [ - "types/lib/decoder.d.ts" - ], - "indexed-reader": [ - "types/lib/indexed-reader.d.ts" - ], - "indexer": [ - "types/lib/indexer.d.ts" - ], - "iterator": [ - "types/lib/iterator.d.ts" - ], - "writer": [ - "types/lib/writer.d.ts" - ], - "buffer-writer": [ - "types/lib/buffer-writer.d.ts" - ], - "*": [ - "types/*" - ], - "types/*": [ - "types/*" - ] - } - }, - "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", - { - "pkgRoot": "dist" - } - ], - "@semantic-release/github", - "@semantic-release/git" - ] + "browser": { + "./src/index.js": "./src/index-browser.js", + "./src/index-reader.js": "./src/index-reader-browser.js", + "./src/reader.js": "./src/reader-browser.js", + "./src/writer.js": "./src/writer-browser.js", + "fs": false, + "util": false, + "stream": false } } diff --git a/api.ts b/src/api.ts similarity index 68% rename from api.ts rename to src/api.ts index 44882b7..9d4fd48 100644 --- a/api.ts +++ b/src/api.ts @@ -1,27 +1,27 @@ -import { CID } from 'multiformats/cid' +import type { CID } from 'multiformats/cid' export type { CID } /* Generic types for interfacing with block storage */ -export type Block = { +export interface Block { cid: CID bytes: Uint8Array } -export type BlockHeader = { +export interface BlockHeader { cid: CID length: number blockLength: number } -export type BlockIndex = BlockHeader & { +export interface BlockIndex extends BlockHeader { offset: number blockOffset: number } export interface RootsReader { version: number - getRoots(): Promise + getRoots: () => Promise } export interface BlockIterator extends AsyncIterable {} @@ -29,21 +29,21 @@ export interface BlockIterator extends AsyncIterable {} export interface CIDIterator extends AsyncIterable {} export interface BlockReader { - has(key: CID): Promise - get(key: CID): Promise - blocks(): BlockIterator - cids(): CIDIterator + has: (key: CID) => Promise + get: (key: CID) => Promise + blocks: () => BlockIterator + cids: () => CIDIterator } export interface BlockWriter { - put(block: Block): Promise - close(): Promise + put: (block: Block) => Promise + close: () => Promise } export interface CarBufferWriter { - addRoot(root:CID, options?:{ resize?: boolean }):CarBufferWriter - write(block: Block): CarBufferWriter - close(options?:{ resize?: boolean }): Uint8Array + addRoot: (root: CID, options?: { resize?: boolean }) => CarBufferWriter + write: (block: Block) => CarBufferWriter + close: (options?: { resize?: boolean }) => Uint8Array } export interface CarBufferWriterOptions { diff --git a/lib/buffer-writer.js b/src/buffer-writer.js similarity index 96% rename from lib/buffer-writer.js rename to src/buffer-writer.js index cc91363..c28f8a9 100644 --- a/lib/buffer-writer.js +++ b/src/buffer-writer.js @@ -4,10 +4,10 @@ import { tokensToLength } from 'cborg/length' import * as CBOR from '@ipld/dag-cbor' /** - * @typedef {import('../api').CID} CID - * @typedef {import('../api').Block} Block - * @typedef {import('../api').CarBufferWriter} Writer - * @typedef {import('../api').CarBufferWriterOptions} Options + * @typedef {import('./api').CID} CID + * @typedef {import('./api').Block} Block + * @typedef {import('./api').CarBufferWriter} Writer + * @typedef {import('./api').CarBufferWriterOptions} Options * @typedef {import('./coding').CarEncoder} CarEncoder */ @@ -53,7 +53,7 @@ class CarBufferWriter { * Write a `Block` (a `{ cid:CID, bytes:Uint8Array }` pair) to the archive. * Throws if there is not enough capacity. * - * @param {Block} block A `{ cid:CID, bytes:Uint8Array }` pair. + * @param {Block} block - A `{ cid:CID, bytes:Uint8Array }` pair. * @returns {CarBufferWriter} */ write (block) { diff --git a/src/coding.ts b/src/coding.ts new file mode 100644 index 0000000..508b408 --- /dev/null +++ b/src/coding.ts @@ -0,0 +1,56 @@ +import type { CID } from 'multiformats/cid' +import type { Block, BlockIndex } from './api.js' + +export interface CarEncoder { + setRoots: (roots: CID[]) => Promise + + writeBlock: (block: Block) => Promise + + close: () => Promise +} + +export interface IteratorChannel_Writer { + write: (chunk: T) => Promise + end: () => Promise +} + +export interface IteratorChannel { + writer: IteratorChannel_Writer + + iterator: AsyncIterator +} + +export interface CarHeader { + version: 1 + roots: CID[] +} + +export interface CarV2FixedHeader { + characteristics: [bigint, bigint] + dataOffset: number + dataSize: number + indexOffset: number +} + +export interface CarV2Header extends CarV2FixedHeader { + version: 2 + roots: CID[] +} + +export interface CarDecoder { + header: () => Promise + + blocks: () => AsyncGenerator + + blocksIndex: () => AsyncGenerator +} + +export interface BytesReader { + upTo: (length: number) => Promise + + exactly: (length: number) => Promise + + seek: (length: number) => void + + pos: number +} diff --git a/lib/decoder.js b/src/decoder.js similarity index 98% rename from lib/decoder.js rename to src/decoder.js index a4f3042..ccf7b54 100644 --- a/lib/decoder.js +++ b/src/decoder.js @@ -5,9 +5,9 @@ import { decode as decodeDagCbor } from '@ipld/dag-cbor' import { CarHeader as headerValidator } from './header-validator.js' /** - * @typedef {import('../api').Block} Block - * @typedef {import('../api').BlockHeader} BlockHeader - * @typedef {import('../api').BlockIndex} BlockIndex + * @typedef {import('./api').Block} Block + * @typedef {import('./api').BlockHeader} BlockHeader + * @typedef {import('./api').BlockIndex} BlockIndex * @typedef {import('./coding').BytesReader} BytesReader * @typedef {import('./coding').CarHeader} CarHeader * @typedef {import('./coding').CarV2Header} CarV2Header @@ -183,7 +183,7 @@ export async function readBlockHead (reader) { /** * @param {BytesReader} reader - * @return {Promise} + * @returns {Promise} */ async function readBlock (reader) { const { cid, blockLength } = await readBlockHead(reader) diff --git a/lib/encoder.js b/src/encoder.js similarity index 97% rename from lib/encoder.js rename to src/encoder.js index e22c5fe..5dba02c 100644 --- a/lib/encoder.js +++ b/src/encoder.js @@ -3,7 +3,7 @@ import { encode as dagCborEncode } from '@ipld/dag-cbor' /** * @typedef {import('multiformats').CID} CID - * @typedef {import('../api').Block} Block + * @typedef {import('./api').Block} Block * @typedef {import('./coding').CarEncoder} CarEncoder * @typedef {import('./coding').IteratorChannel_Writer} IteratorChannel_Writer */ diff --git a/src/header-validator.js b/src/header-validator.js new file mode 100644 index 0000000..d666537 --- /dev/null +++ b/src/header-validator.js @@ -0,0 +1,74 @@ +/* eslint-disable jsdoc/check-indentation */ + +/** Auto-generated with ipld-schema-validator@0.0.0-dev at Thu Jun 17 2021 from IPLD Schema: + * + * type CarHeader struct { + * version Int + * roots optional [&Any] + * # roots is _not_ optional for CarV1 but we defer that check within code to + * # gracefully handle the >V1 case where it's just {version:X} + * } + * + */ + +const Kinds = { + Null: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => obj === null, + Int: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => Number.isInteger(obj), + Float: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => typeof obj === 'number' && Number.isFinite(obj), + String: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => typeof obj === 'string', + Bool: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => typeof obj === 'boolean', + Bytes: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => obj instanceof Uint8Array, + Link: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => !Kinds.Null(obj) && typeof obj === 'object' && obj.asCID === obj, + List: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => Array.isArray(obj), + Map: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => !Kinds.Null(obj) && typeof obj === 'object' && obj.asCID !== obj && !Kinds.List(obj) && !Kinds.Bytes(obj) +} +/** @type {{ [k in string]: (obj:any)=>boolean}} */ +const Types = { + Int: Kinds.Int, + 'CarHeader > version': /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => Types.Int(obj), + 'CarHeader > roots (anon) > valueType (anon)': Kinds.Link, + 'CarHeader > roots (anon)': /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => Kinds.List(obj) && Array.prototype.every.call(obj, Types['CarHeader > roots (anon) > valueType (anon)']), + 'CarHeader > roots': /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => Types['CarHeader > roots (anon)'](obj), + CarHeader: /** + * @param {any} obj + * @returns {boolean} + */ (/** @type {any} */ obj) => { const keys = obj && Object.keys(obj); return Kinds.Map(obj) && ['version'].every((k) => keys.includes(k)) && Object.entries(obj).every(([name, value]) => Types['CarHeader > ' + name] && Types['CarHeader > ' + name](value)) } +} + +export const CarHeader = Types.CarHeader diff --git a/lib/header.ipldsch b/src/header.ipldsch similarity index 100% rename from lib/header.ipldsch rename to src/header.ipldsch diff --git a/src/index-browser.js b/src/index-browser.js new file mode 100644 index 0000000..a08b035 --- /dev/null +++ b/src/index-browser.js @@ -0,0 +1,14 @@ +import { CarReader } from './reader-browser.js' +import { CarIndexer } from './indexer.js' +import { CarBlockIterator, CarCIDIterator } from './iterator.js' +import { CarWriter } from './writer-browser.js' +import { CarIndexedReader } from './indexed-reader-browser.js' + +export { + CarReader, + CarIndexer, + CarBlockIterator, + CarCIDIterator, + CarWriter, + CarIndexedReader +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..5a11c69 --- /dev/null +++ b/src/index.js @@ -0,0 +1,16 @@ +import { CarReader } from './reader.js' +import { CarIndexer } from './indexer.js' +import { CarBlockIterator, CarCIDIterator } from './iterator.js' +import { CarWriter } from './writer.js' +import { CarIndexedReader } from './indexed-reader.js' +import * as CarBufferWriter from './buffer-writer.js' + +export { + CarReader, + CarIndexer, + CarBlockIterator, + CarCIDIterator, + CarWriter, + CarIndexedReader, + CarBufferWriter +} diff --git a/lib/indexed-reader-browser.js b/src/indexed-reader-browser.js similarity index 100% rename from lib/indexed-reader-browser.js rename to src/indexed-reader-browser.js diff --git a/lib/indexed-reader.js b/src/indexed-reader.js similarity index 96% rename from lib/indexed-reader.js rename to src/indexed-reader.js index cd83d34..39d9ee3 100644 --- a/lib/indexed-reader.js +++ b/src/indexed-reader.js @@ -6,9 +6,9 @@ import { CarReader as NodeCarReader } from './reader.js' /** * @typedef {import('fs').promises.FileHandle} FileHandle - * @typedef {import('../api').Block} Block - * @typedef {import('../api').BlockIndex} BlockIndex - * @typedef {import('../api').CarReader} CarReaderIface + * @typedef {import('./api').Block} Block + * @typedef {import('./api').BlockIndex} BlockIndex + * @typedef {import('./api').CarReader} CarReaderIface * @typedef {import('./reader-browser').CarReader} CarReader * @typedef {{ blockLength:number, blockOffset:number }} RawLocation */ @@ -68,7 +68,7 @@ export class CarIndexedReader { /** * See {@link CarReader#getRoots} * - * @method + * @function * @memberof CarIndexedReader * @instance * @async @@ -83,7 +83,7 @@ export class CarIndexedReader { /** * See {@link CarReader#has} * - * @method + * @function * @memberof CarIndexedReader * @instance * @async @@ -99,7 +99,7 @@ export class CarIndexedReader { /** * See {@link CarReader#get} * - * @method + * @function * @memberof CarIndexedReader * @instance * @async @@ -129,7 +129,7 @@ export class CarIndexedReader { /** * See {@link CarReader#blocks} * - * @method + * @function * @memberof CarIndexedReader * @instance * @async @@ -150,7 +150,7 @@ export class CarIndexedReader { /** * See {@link CarReader#cids} * - * @method + * @function * @memberof CarIndexedReader * @instance * @async @@ -167,7 +167,7 @@ export class CarIndexedReader { * Close the underlying file descriptor maintained by this `CarIndexedReader`. * This must be called for proper resource clean-up to occur. * - * @method + * @function * @memberof CarIndexedReader * @instance * @async diff --git a/lib/indexer.js b/src/indexer.js similarity index 96% rename from lib/indexer.js rename to src/indexer.js index f29de3d..d82bc76 100644 --- a/lib/indexer.js +++ b/src/indexer.js @@ -6,9 +6,9 @@ import { /** * @typedef {import('multiformats').CID} CID - * @typedef {import('../api').Block} Block - * @typedef {import('../api').RootsReader} RootsReader - * @typedef {import('../api').BlockIndex} BlockIndex + * @typedef {import('./api').Block} Block + * @typedef {import('./api').RootsReader} RootsReader + * @typedef {import('./api').BlockIndex} BlockIndex * @typedef {import('./coding').BytesReader} BytesReader */ @@ -62,7 +62,7 @@ export class CarIndexer { * Get the list of roots defined by the CAR referenced by this indexer. May be * zero or more `CID`s. * - * @method + * @function * @memberof CarIndexer * @instance * @async diff --git a/lib/iterator-channel.js b/src/iterator-channel.js similarity index 100% rename from lib/iterator-channel.js rename to src/iterator-channel.js diff --git a/lib/iterator.js b/src/iterator.js similarity index 98% rename from lib/iterator.js rename to src/iterator.js index 3104c89..a1014d8 100644 --- a/lib/iterator.js +++ b/src/iterator.js @@ -6,8 +6,8 @@ import { /** * @typedef {import('multiformats').CID} CID - * @typedef {import('../api').Block} Block - * @typedef {import('../api').RootsReader} RootsReader + * @typedef {import('./api').Block} Block + * @typedef {import('./api').RootsReader} RootsReader * @typedef {import('./coding').BytesReader} BytesReader */ @@ -77,7 +77,7 @@ export class CarBlockIterator extends CarIteratorBase { * Get the list of roots defined by the CAR referenced by this iterator. May be * zero or more `CID`s. * - * @method getRoots + * @function getRoots * @memberof CarBlockIterator * @instance * @async @@ -172,7 +172,7 @@ export class CarCIDIterator extends CarIteratorBase { * Get the list of roots defined by the CAR referenced by this iterator. May be * zero or more `CID`s. * - * @method getRoots + * @function getRoots * @memberof CarCIDIterator * @instance * @async diff --git a/lib/reader-browser.js b/src/reader-browser.js similarity index 97% rename from lib/reader-browser.js rename to src/reader-browser.js index 471f551..b12fad1 100644 --- a/lib/reader-browser.js +++ b/src/reader-browser.js @@ -2,8 +2,8 @@ import { asyncIterableReader, bytesReader, createDecoder } from './decoder.js' /** * @typedef {import('multiformats').CID} CID - * @typedef {import('../api').Block} Block - * @typedef {import('../api').CarReader} CarReaderIface + * @typedef {import('./api').Block} Block + * @typedef {import('./api').CarReader} CarReaderIface * @typedef {import('./coding').BytesReader} BytesReader * @typedef {import('./coding').CarHeader} CarHeader * @typedef {import('./coding').CarV2Header} CarV2Header @@ -55,7 +55,7 @@ export class CarReader { * Get the list of roots defined by the CAR referenced by this reader. May be * zero or more `CID`s. * - * @method + * @function * @memberof CarReader * @instance * @async @@ -71,7 +71,7 @@ export class CarReader { * Check whether a given `CID` exists within the CAR referenced by this * reader. * - * @method + * @function * @memberof CarReader * @instance * @async @@ -90,7 +90,7 @@ export class CarReader { * the provided `CID` doesn't exist within the CAR, `undefined` will be * returned. * - * @method + * @function * @memberof CarReader * @instance * @async @@ -109,7 +109,7 @@ export class CarReader { * of the `Block`s (`{ cid:CID, bytes:Uint8Array }` pairs) contained within * the CAR referenced by this reader. * - * @method + * @function * @memberof CarReader * @instance * @async @@ -126,7 +126,7 @@ export class CarReader { * Returns a `CIDIterator` (`AsyncIterable`) that iterates over all of * the `CID`s contained within the CAR referenced by this reader. * - * @method + * @function * @memberof CarReader * @instance * @async diff --git a/lib/reader.js b/src/reader.js similarity index 85% rename from lib/reader.js rename to src/reader.js index 0cc37b4..af64b36 100644 --- a/lib/reader.js +++ b/src/reader.js @@ -3,9 +3,9 @@ import { promisify } from 'util' import { CarReader as BrowserCarReader } from './reader-browser.js' /** - * @typedef {import('../api').Block} Block - * @typedef {import('../api').BlockIndex} BlockIndex - * @typedef {import('../api').CarReader} CarReaderIface + * @typedef {import('./api').Block} Block + * @typedef {import('./api').BlockIndex} BlockIndex + * @typedef {import('./api').CarReader} CarReaderIface */ const fsread = promisify(fs.read) @@ -27,10 +27,10 @@ export class CarReader extends BrowserCarReader { * @async * @static * @memberof CarReader - * @param {fs.promises.FileHandle | number} fd A file descriptor from the + * @param {fs.promises.FileHandle | number} fd - A file descriptor from the * Node.js `fs` module. Either an integer, from `fs.open()` or a `FileHandle` * from `fs.promises.open()`. - * @param {BlockIndex} blockIndex An index pointing to the location of the + * @param {BlockIndex} blockIndex - An index pointing to the location of the * Block required. This `BlockIndex` should take the form: * `{cid:CID, blockLength:number, blockOffset:number}`. * @returns {Promise} A `{ cid:CID, bytes:Uint8Array }` pair. diff --git a/lib/writer-browser.js b/src/writer-browser.js similarity index 95% rename from lib/writer-browser.js rename to src/writer-browser.js index 9273aea..f35d4a1 100644 --- a/lib/writer-browser.js +++ b/src/writer-browser.js @@ -4,9 +4,9 @@ import { create as iteratorChannel } from './iterator-channel.js' import { bytesReader, readHeader } from './decoder.js' /** - * @typedef {import('../api').Block} Block - * @typedef {import('../api').BlockWriter} BlockWriter - * @typedef {import('../api').WriterChannel} WriterChannel + * @typedef {import('./api').Block} Block + * @typedef {import('./api').BlockWriter} BlockWriter + * @typedef {import('./api').WriterChannel} WriterChannel * @typedef {import('./coding').CarEncoder} CarEncoder * @typedef {import('./coding').IteratorChannel} IteratorChannel */ @@ -62,11 +62,11 @@ export class CarWriter { /** * Write a `Block` (a `{ cid:CID, bytes:Uint8Array }` pair) to the archive. * - * @method + * @function * @memberof CarWriter * @instance * @async - * @param {Block} block A `{ cid:CID, bytes:Uint8Array }` pair. + * @param {Block} block - A `{ cid:CID, bytes:Uint8Array }` pair. * @returns {Promise} The returned promise will only resolve once the * bytes this block generates are written to the `out` iterable. */ @@ -91,7 +91,7 @@ export class CarWriter { * Finalise the CAR archive and signal that the `out` iterable should end once * any remaining bytes are written. * - * @method + * @function * @memberof CarWriter * @instance * @async @@ -166,7 +166,7 @@ export class CarWriter { * @static * @memberof CarWriter * @param {Uint8Array} bytes - * @param {CID[]} roots A new list of roots to replace the existing list in + * @param {CID[]} roots - A new list of roots to replace the existing list in * the CAR header. The new header must take up the same number of bytes as the * existing header, so the roots should collectively be the same byte length * as the existing roots. diff --git a/lib/writer.js b/src/writer.js similarity index 93% rename from lib/writer.js rename to src/writer.js index 764be09..75d0851 100644 --- a/lib/writer.js +++ b/src/writer.js @@ -9,7 +9,7 @@ const fswrite = promisify(fs.write) /** * @typedef {import('multiformats/cid').CID} CID - * @typedef {import('../api').BlockWriter} BlockWriter + * @typedef {import('./api').BlockWriter} BlockWriter */ /** @@ -35,10 +35,10 @@ export class CarWriter extends BrowserCarWriter { * @async * @static * @memberof CarWriter - * @param {fs.promises.FileHandle | number} fd A file descriptor from the + * @param {fs.promises.FileHandle | number} fd - A file descriptor from the * Node.js `fs` module. Either an integer, from `fs.open()` or a `FileHandle` * from `fs.promises.open()`. - * @param {CID[]} roots A new list of roots to replace the existing list in + * @param {CID[]} roots - A new list of roots to replace the existing list in * the CAR header. The new header must take up the same number of bytes as the * existing header, so the roots should collectively be the same byte length * as the existing roots. diff --git a/test/common.js b/test/common.js index 9b6ecaa..cfb880e 100644 --- a/test/common.js +++ b/test/common.js @@ -3,12 +3,10 @@ import { sha256 } from 'multiformats/hashes/sha2' import * as raw from 'multiformats/codecs/raw' import * as dagCbor from '@ipld/dag-cbor' import * as dagPb from '@ipld/dag-pb' - -import chai from 'chai' -import chaiAsPromised from 'chai-as-promised' +import { assert } from 'aegir/chai' /** - * @typedef {import('../api').Block} Block + * @typedef {import('../src/api').Block} Block * @typedef {import('@ipld/dag-pb').PBNode} PBNode */ @@ -28,9 +26,6 @@ class TestBlock { } } -chai.use(chaiAsPromised) -const { assert } = chai - /** @type {TestBlock[]} */ let rawBlocks /** @type {TestBlock[]} */ @@ -47,7 +42,7 @@ const rndCid = CID.parse('bafyreihyrpefhacm6kkp4ql6j6udakdit7g3dmkzfriqfykhjw6ca /** * @param {any} object * @param {{code: number, encode: (obj: any) => Uint8Array}} codec - * @param {import('multiformats/cid').CIDVersion} version + * @param {import('multiformats/cid').Version} version * @returns {Promise} */ async function toBlock (object, codec, version = 1) { diff --git a/test/node-test-file-streams.js b/test/node-test-file-streams.js index 8e1b146..7c1f067 100644 --- a/test/node-test-file-streams.js +++ b/test/node-test-file-streams.js @@ -7,7 +7,7 @@ import { fileURLToPath } from 'url' import fs from 'fs' import { Readable, pipeline } from 'stream' import { promisify } from 'util' -import { CarReader, CarWriter } from '@ipld/car' +import { CarReader, CarWriter } from '../src/index.js' import { makeData, assert } from './common.js' import { verifyRoots, @@ -18,7 +18,7 @@ import { } from './verify-store-reader.js' /** @typedef {import('multiformats').CID} CID */ -/** @typedef {import('../api').Block} Block */ +/** @typedef {import('../src/api').Block} Block */ const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) diff --git a/test/node-test-indexed-reader.js b/test/node-test-indexed-reader.js index 7215747..4021a66 100644 --- a/test/node-test-indexed-reader.js +++ b/test/node-test-indexed-reader.js @@ -2,7 +2,7 @@ import path from 'path' import { fileURLToPath } from 'url' -import { CarIndexedReader } from '@ipld/car/indexed-reader' +import { CarIndexedReader } from '../src/indexed-reader.js' import { assert, goCarIndex } from './common.js' import { verifyRoots, diff --git a/test/node-test-large.js b/test/node-test-large.js index 32132de..bc07af3 100644 --- a/test/node-test-large.js +++ b/test/node-test-large.js @@ -4,15 +4,15 @@ import fs from 'fs' import { Readable } from 'stream' -import { garbage } from 'ipld-garbage' +import { garbage } from '@ipld/garbage' import varint from 'varint' import * as dagCbor from '@ipld/dag-cbor' import { sha256 } from 'multiformats/hashes/sha2' import { CID } from 'multiformats/cid' -import { CarWriter, CarIndexer, CarReader, CarIndexedReader } from '@ipld/car' +import { CarWriter, CarIndexer, CarReader, CarIndexedReader } from '../src/index.js' import { assert } from './common.js' -/** @typedef {import('../api').BlockIndex} BlockIndex */ +/** @typedef {import('../src/api').BlockIndex} BlockIndex */ describe('Large CAR', () => { /** @type {any[]} */ diff --git a/test/node-test-raw.js b/test/node-test-raw.js index cfa61cf..5db81b7 100644 --- a/test/node-test-raw.js +++ b/test/node-test-raw.js @@ -7,10 +7,10 @@ import fs from 'fs' import { promisify } from 'util' import { fileURLToPath } from 'url' import { bytes } from 'multiformats' -import { CarReader } from '@ipld/car' +import { CarReader } from '../src/index.js' import { assert, makeData, goCarIndex } from './common.js' -/** @typedef {import('../api').Block} Block */ +/** @typedef {import('../src/api').Block} Block */ const fsopen = promisify(fs.open) const fsclose = promisify(fs.close) diff --git a/test/node-test-updateroots.js b/test/node-test-updateroots.js index d0bbdc6..df2011d 100644 --- a/test/node-test-updateroots.js +++ b/test/node-test-updateroots.js @@ -7,8 +7,8 @@ import { fileURLToPath } from 'url' import fs from 'fs' import { promisify } from 'util' import { CID } from 'multiformats/cid' -import { CarReader } from '@ipld/car/reader' -import { CarWriter } from '@ipld/car/writer' +import { CarReader } from '../src/reader.js' +import { CarWriter } from '../src/writer.js' import { verifyRoots, verifyHas, diff --git a/test/node.js b/test/node.js new file mode 100644 index 0000000..4f57e71 --- /dev/null +++ b/test/node.js @@ -0,0 +1,6 @@ + +import './node-test-file-streams.js' +import './node-test-indexed-reader.js' +import './node-test-large.js' +import './node-test-raw.js' +import './node-test-updateroots.js' diff --git a/test/test-buffer-writer.js b/test/test-buffer-writer.spec.js similarity index 98% rename from test/test-buffer-writer.js rename to test/test-buffer-writer.spec.js index 1142a20..dcd93b0 100644 --- a/test/test-buffer-writer.js +++ b/test/test-buffer-writer.spec.js @@ -1,8 +1,8 @@ /* eslint-env mocha */ -import * as CarBufferWriter from '@ipld/car/buffer-writer' -import { CarReader } from '@ipld/car/reader' -import { createHeader } from '../lib/encoder.js' +import * as CarBufferWriter from '../src/buffer-writer.js' +import { CarReader } from '../src/reader.js' +import { createHeader } from '../src/encoder.js' import { assert } from './common.js' import { CID, varint } from 'multiformats' import * as CBOR from '@ipld/dag-cbor' diff --git a/test/test-errors.js b/test/test-errors.spec.js similarity index 98% rename from test/test-errors.js rename to test/test-errors.spec.js index 6b8929b..805d15a 100644 --- a/test/test-errors.js +++ b/test/test-errors.spec.js @@ -2,7 +2,7 @@ import { bytes } from 'multiformats' import { encode as cbEncode } from '@ipld/dag-cbor' import { encode as vEncode } from 'varint' -import { CarReader } from '@ipld/car/reader' +import { CarReader } from '../src/reader.js' import { carBytes, assert, goCarV2Bytes } from './common.js' /** diff --git a/test/test-indexer.js b/test/test-indexer.spec.js similarity index 82% rename from test/test-indexer.js rename to test/test-indexer.spec.js index baeaffb..b4db9eb 100644 --- a/test/test-indexer.js +++ b/test/test-indexer.spec.js @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { CarIndexer } from '@ipld/car/indexer' +import { CarIndexer } from '../src/indexer.js' import { goCarBytes, goCarIndex, @@ -11,6 +11,7 @@ import { assert } from './common.js' import { verifyRoots } from './verify-store-reader.js' +import { expect } from 'aegir/chai' describe('CarIndexer fromBytes()', () => { it('complete', async () => { @@ -43,8 +44,9 @@ describe('CarIndexer fromBytes()', () => { it('bad argument', async () => { for (const arg of [true, false, null, undefined, 'string', 100, { obj: 'nope' }]) { - // @ts-ignore - await assert.isRejected(CarIndexer.fromBytes(arg)) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(CarIndexer.fromBytes(arg)).to.eventually.be.rejected() } }) }) @@ -80,8 +82,9 @@ describe('CarIndexer fromIterable()', () => { it('bad argument', async () => { for (const arg of [new Uint8Array(0), true, false, null, undefined, 'string', 100, { obj: 'nope' }]) { - // @ts-ignore - await assert.isRejected(CarIndexer.fromIterable(arg)) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(CarIndexer.fromIterable(arg)).to.eventually.be.rejected() } }) }) diff --git a/test/test-interface.js b/test/test-interface.spec.js similarity index 69% rename from test/test-interface.js rename to test/test-interface.spec.js index dd71204..0552779 100644 --- a/test/test-interface.js +++ b/test/test-interface.spec.js @@ -1,9 +1,9 @@ /* eslint-env mocha */ -import * as car from '@ipld/car' -import { CarReader, __browser } from '@ipld/car/reader' -import { CarIndexer } from '@ipld/car/indexer' -import { CarBlockIterator, CarCIDIterator } from '@ipld/car/iterator' -import { CarWriter } from '@ipld/car/writer' +import * as car from '../src/index.js' +import { CarReader, __browser } from '../src/reader.js' +import { CarIndexer } from '../src/indexer.js' +import { CarBlockIterator, CarCIDIterator } from '../src/iterator.js' +import { CarWriter } from '../src/writer.js' import { assert } from './common.js' diff --git a/test/test-iterator.js b/test/test-iterator.spec.js similarity index 78% rename from test/test-iterator.js rename to test/test-iterator.spec.js index e69e82c..5864b80 100644 --- a/test/test-iterator.js +++ b/test/test-iterator.spec.js @@ -1,8 +1,9 @@ /* eslint-env mocha */ -import { CarBlockIterator, CarCIDIterator } from '@ipld/car/iterator' +import { CarBlockIterator, CarCIDIterator } from '../src/iterator.js' import { carBytes, makeIterable, assert } from './common.js' import { verifyRoots, verifyBlocks, verifyCids } from './verify-store-reader.js' +import { expect } from 'aegir/chai' /** * @param {CarBlockIterator} iter @@ -48,15 +49,17 @@ for (const type of ['Block', 'CID']) { it('fromBytes() bad argument', async () => { for (const arg of [true, false, null, undefined, 'string', 100, { obj: 'nope' }]) { - // @ts-ignore - await assert.isRejected((type === 'Block' ? CarBlockIterator : CarCIDIterator).fromBytes(arg)) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect((type === 'Block' ? CarBlockIterator : CarCIDIterator).fromBytes(arg)).to.eventually.be.rejected() } }) it('fromIterable() bad argument', async () => { for (const arg of [new Uint8Array(0), true, false, null, undefined, 'string', 100, { obj: 'nope' }]) { - // @ts-ignore - await assert.isRejected((type === 'Block' ? CarBlockIterator : CarCIDIterator).fromIterable(arg)) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect((type === 'Block' ? CarBlockIterator : CarCIDIterator).fromIterable(arg)).to.eventually.be.rejected() } }) diff --git a/test/test-reader.js b/test/test-reader.spec.js similarity index 91% rename from test/test-reader.js rename to test/test-reader.spec.js index af5cbf8..7ebbb6d 100644 --- a/test/test-reader.js +++ b/test/test-reader.spec.js @@ -1,8 +1,8 @@ /* eslint-env mocha */ -import { CarReader } from '@ipld/car/reader' -import { CarWriter } from '@ipld/car/writer' -import { bytesReader, readHeader } from '@ipld/car/decoder' +import { CarReader } from '../src/reader.js' +import { CarWriter } from '../src/writer.js' +import { bytesReader, readHeader } from '../src/decoder.js' import * as Block from 'multiformats/block' import { sha256 } from 'multiformats/hashes/sha2' import * as raw from 'multiformats/codecs/raw' @@ -26,6 +26,7 @@ import { } from './verify-store-reader.js' import { data as fixtures } from './fixtures.js' import { expectations as fixtureExpectations } from './fixtures-expectations.js' +import { expect } from 'aegir/chai' describe('CarReader fromBytes()', () => { it('complete', async () => { @@ -49,8 +50,9 @@ describe('CarReader fromBytes()', () => { it('bad argument', async () => { for (const arg of [true, false, null, undefined, 'string', 100, { obj: 'nope' }]) { - // @ts-ignore - await assert.isRejected(CarReader.fromBytes(arg)) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(CarReader.fromBytes(arg)).to.eventually.be.rejected() } }) @@ -90,7 +92,7 @@ describe('CarReader fromBytes()', () => { bytes.set(carBytes) try { await CarReader.fromBytes(bytes) - } catch (err) { + } catch (/** @type {any} */ err) { assert.strictEqual(err.message, 'Invalid CAR section (zero length)') return } @@ -103,7 +105,7 @@ describe('CarReader fromBytes()', () => { bytes[0] = 0 try { await CarReader.fromBytes(bytes) - } catch (err) { + } catch (/** @type {any} */ err) { assert.strictEqual(err.message, 'Invalid CAR header (zero length)') return } @@ -175,8 +177,9 @@ describe('CarReader fromIterable()', () => { it('bad argument', async () => { for (const arg of [new Uint8Array(0), true, false, null, undefined, 'string', 100, { obj: 'nope' }]) { - // @ts-ignore - await assert.isRejected(CarReader.fromIterable(arg)) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(CarReader.fromIterable(arg)).to.eventually.be.rejected() } }) @@ -208,7 +211,7 @@ describe('Shared fixtures', () => { let header try { header = await readHeader(bytesReader(data)) - } catch (err) { + } catch (/** @type {any} */ err) { if (expectedError != null) { assert.equal(err.message, expectedError) return diff --git a/test/test-writer.js b/test/test-writer.spec.js similarity index 88% rename from test/test-writer.js rename to test/test-writer.spec.js index 2f2d020..7ac42ed 100644 --- a/test/test-writer.js +++ b/test/test-writer.spec.js @@ -1,8 +1,8 @@ /* eslint-env mocha */ /* globals describe, it */ -import { CarWriter } from '@ipld/car/writer' -import { CarReader } from '@ipld/car/reader' +import { CarWriter } from '../src/writer.js' +import { CarReader } from '../src/reader.js' import { bytes, CID } from 'multiformats' import { carBytes, makeData, assert, rndCid } from './common.js' import { @@ -12,9 +12,10 @@ import { verifyBlocks, verifyCids } from './verify-store-reader.js' +import { expect } from 'aegir/chai' /** - * @typedef {import('../api').Block} Block + * @typedef {import('../src/api').Block} Block */ const { toHex } = bytes @@ -57,7 +58,8 @@ const newRoots = [ */ async function verifyUpdateRoots (bytes) { const reader = await CarReader.fromBytes(bytes) - await assert.isRejected(verifyRoots(reader)) // whoa, different roots? like magic + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(verifyRoots(reader)).to.eventually.be.rejected() // whoa, different roots? like magic assert.deepEqual(await reader.getRoots(), newRoots) await verifyHas(reader) await verifyGet(reader) @@ -276,7 +278,7 @@ describe('CarWriter', () => { it('bad argument for create()', () => { for (const arg of [new Uint8Array(0), true, false, null, 'string', 100, { obj: 'nope' }, [false]]) { - // @ts-ignore + // @ts-expect-error arg is wrong type assert.throws(() => CarWriter.create(arg)) } }) @@ -284,18 +286,21 @@ describe('CarWriter', () => { it('bad argument for put()', async () => { const { writer } = CarWriter.create() for (const arg of [new Uint8Array(0), true, false, null, 'string', 100, { obj: 'nope' }, [false]]) { - // @ts-ignore - await assert.isRejected(writer.put(arg)) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(writer.put(arg)).to.eventually.be.rejected() } for (const arg of [true, false, null, 'string', 100, { obj: 'nope' }, [false]]) { - // @ts-ignore - await assert.isRejected(writer.put({ bytes: new Uint8Array(0), cid: arg })) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(writer.put({ bytes: new Uint8Array(0), cid: arg })).to.eventually.be.rejected() } for (const arg of [true, false, null, 'string', 100, { obj: 'nope' }, [false]]) { - // @ts-ignore - await assert.isRejected(writer.put({ cid: rndCid, bytes: arg })) + // @ts-expect-error arg is wrong type + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(writer.put({ cid: rndCid, bytes: arg })).to.eventually.be.rejected() } }) @@ -318,7 +323,9 @@ describe('CarWriter', () => { const { writer, out } = CarWriter.create() collector(out) await writer.close() - await assert.isRejected(writer.close(), /closed/i) + + // the assert.isRejected form of this causes an uncatchable error in Chrome + await expect(writer.close()).to.eventually.be.rejectedWith(/closed/i) }) it('update roots (fd)', async () => { diff --git a/test/verify-store-reader.js b/test/verify-store-reader.js index 797cacb..dd95866 100644 --- a/test/verify-store-reader.js +++ b/test/verify-store-reader.js @@ -4,11 +4,11 @@ import { toBlock, assert, makeData } from './common.js' /** * @typedef {import('multiformats').CID} CID - * @typedef {import('../api').Block} Block - * @typedef {import('../api').RootsReader} RootsReader - * @typedef {import('../api').BlockIterator} BlockIterator - * @typedef {import('../api').CIDIterator} CIDIterator - * @typedef {import('../api').BlockReader} BlockReader + * @typedef {import('../src/api').Block} Block + * @typedef {import('../src/api').RootsReader} RootsReader + * @typedef {import('../src/api').BlockIterator} BlockIterator + * @typedef {import('../src/api').CIDIterator} CIDIterator + * @typedef {import('../src/api').BlockReader} BlockReader */ /** diff --git a/tsconfig.json b/tsconfig.json index b34d5fc..4752a7e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,48 +1,16 @@ { + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { - "allowJs": true, - "checkJs": true, - "forceConsistentCasingInFileNames": true, - "noImplicitReturns": false, - "noImplicitAny": true, - "noImplicitThis": true, - "noFallthroughCasesInSwitch": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "strictFunctionTypes": false, - "strictNullChecks": true, - "strictPropertyInitialization": true, - "strictBindCallApply": true, - "strict": true, - "useUnknownInCatchVariables": false, - "alwaysStrict": true, - "esModuleInterop": true, - "target": "ES2018", - "module": "ESNext", - "moduleResolution": "node", - "declaration": true, - "declarationMap": true, - "outDir": "types", - "skipLibCheck": true, - "stripInternal": true, - "resolveJsonModule": true, - "emitDeclarationOnly": true, - "baseUrl": ".", - "paths": { - "@ipld/car": [ "car.js", "car-browser.js", "lib/" ], - "@ipld/car/writer": [ "./lib/writer.js" ], - "@ipld/car/buffer-writer": ["./lib/buffer-writer.js"], - "@ipld/car/reader": [ "./lib/reader.js" ], - "@ipld/car/indexed-reader": [ "./lib/indexed-reader.js" ], - "@ipld/car/iterator": [ "./lib/iterator.js" ], - "@ipld/car/indexer": [ "./lib/indexer.js" ], - "@ipld/car/decoder": [ "./lib/decoder.js" ], - } + "outDir": "dist", + "emitDeclarationOnly": true }, + "include": [ + "src", + "test" + ], "exclude": [ "node_modules", "dist", "examples" - ], - "compileOnSave": false + ] }