Skip to content
This repository has been archived by the owner on Aug 11, 2021. It is now read-only.

feat: add types #136

Merged
merged 4 commits into from
Mar 5, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,51 @@
language: node_js
dist: bionic
cache: npm
stages:
- check
- test
- cov

branches:
only:
- master
- /^release\/.*$/

node_js:
- '10'
- 'lts/*'
- 'node'

os:
- linux
- osx
- windows

before_install:
# modules with pre-built binaries may not have deployed versions for bleeding-edge node so this lets us fall back to building from source
- npm install -g @mapbox/node-pre-gyp

script: npx nyc -s npm run test:node -- --bail
after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov

jobs:
include:
- stage: check
script:
- npx aegir commitlint --travis
- npx aegir dep-check
- npm run lint

- stage: test
name: chrome
addons:
chrome: stable
script: npx aegir test -t browser -t webworker
script:
- npx aegir test -t browser -t webworker

- stage: test
name: firefox
addons:
firefox: latest
script: npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless
script: npx aegir test -t browser -t webworker -- --browser firefox

notifications:
email: false
22 changes: 13 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@
"description": "JavaScript Implementation of BlockService",
"leadMaintainer": "Volker Mische <[email protected]>",
"main": "src/index.js",
"types": "dist/src/index.d.ts",
"scripts": {
"prepare": "aegir build --no-bundle",
"lint": "aegir lint",
"build": "aegir build",
"prepublishOnly": "aegir build",
"test": "aegir test",
"test:node": "aegir test --target node",
"test:browser": "aegir test --target browser",
"release": "aegir release --docs",
"release-minor": "aegir release --type minor --docs",
"release-major": "aegir release --type major --docs",
"coverage": "aegir coverage",
"coverage-publish": "aegir coverage --provider coveralls",
"coverage": "aegir test -t node --cov && nyc report --reporter=html",
"docs": "aegir docs"
},
"repository": {
Expand All @@ -30,14 +31,17 @@
},
"homepage": "https://github.com/ipfs/js-ipfs-block-service#readme",
"devDependencies": {
"@types/fs-extra": "^9.0.8",
"@types/lodash.range": "^3.2.6",
"abort-controller": "^3.0.0",
"aegir": "^22.0.0",
"aegir": "^31.0.4",
"cids": "^1.0.0",
"fs-extra": "^9.0.0",
"ipfs-repo": "^6.0.0",
"ipld-block": "^0.10.0",
"ipfs-repo": "^9.0.0",
"ipld-block": "^0.11.1",
"it-all": "^1.0.5",
"it-drain": "^1.0.1",
"lodash": "^4.17.11",
"lodash.range": "^3.2.0",
"multihashing-async": "^2.0.1",
"uint8arrays": "^2.1.2"
},
Expand All @@ -46,8 +50,8 @@
"npm": ">=3.0.0"
},
"dependencies": {
"err-code": "^2.0.0",
"streaming-iterables": "^5.0.2"
"err-code": "^3.0.1",
"it-map": "^1.0.5"
},
"contributors": [
"David Dias <[email protected]>",
Expand Down
44 changes: 21 additions & 23 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
'use strict'

const { map } = require('streaming-iterables')
const map = require('it-map')
const errcode = require('err-code')

/**
* @typedef {import('ipfs-repo')} IPFSRepo
* @typedef {import('ipld-block')} Block
* @typedef {import('cids')} CID
*/

/**
* BlockService is a hybrid block datastore. It stores data in a local
* datastore and may retrieve data from a remote Exchange.
Expand All @@ -26,26 +32,21 @@ class BlockService {
* If the node is online all requests for blocks first
* check locally and afterwards ask the network for the blocks.
*
* @param {Bitswap} bitswap
* @returns {void}
* @param {any} bitswap
*/
setExchange (bitswap) {
this._bitswap = bitswap
}

/**
* Go offline, i.e. drop the reference to bitswap.
*
* @returns {void}
*/
unsetExchange () {
this._bitswap = null
}

/**
* Is the blockservice online, i.e. is bitswap present.
*
* @returns {bool}
*/
hasExchange () {
return this._bitswap != null
Expand All @@ -55,9 +56,9 @@ class BlockService {
* Put a block to the underlying datastore.
*
* @param {Block} block
* @param {Object} [options] - Options is an object with the following properties
* @param {object} [options] - Options is an object with the following properties
* @param {AbortSignal} [options.signal] - A signal that can be used to abort any long-lived operations that are started as a result of this operation
* @returns {Promise}
* @returns {Promise<Block>}
*/
put (block, options) {
if (this.hasExchange()) {
Expand All @@ -70,10 +71,10 @@ class BlockService {
/**
* Put a multiple blocks to the underlying datastore.
*
* @param {AsyncIterator<Block>} blocks
* @param {Object} [options] - Options is an object with the following properties
* @param {AsyncIterable<Block> | Iterable<Block>} blocks
* @param {object} [options] - Options is an object with the following properties
* @param {AbortSignal} [options.signal] - A signal that can be used to abort any long-lived operations that are started as a result of this operation
* @returns {Promise}
* @returns {AsyncIterable<Block>}
*/
putMany (blocks, options) {
if (this.hasExchange()) {
Expand All @@ -87,7 +88,7 @@ class BlockService {
* Get a block by cid.
*
* @param {CID} cid
* @param {Object} [options] - Options is an object with the following properties
* @param {object} [options] - Options is an object with the following properties
* @param {AbortSignal} [options.signal] - A signal that can be used to abort any long-lived operations that are started as a result of this operation
* @returns {Promise<Block>}
*/
Expand All @@ -102,10 +103,10 @@ class BlockService {
/**
* Get multiple blocks back from an array of cids.
*
* @param {AsyncIterator<CID>} cids
* @param {Object} [options] - Options is an object with the following properties
* @param {AsyncIterable<CID> | Iterable<CID>} cids
* @param {object} [options] - Options is an object with the following properties
* @param {AbortSignal} [options.signal] - A signal that can be used to abort any long-lived operations that are started as a result of this operation
* @returns {AsyncIterator<Block>}
* @returns {AsyncIterable<Block>}
*/
getMany (cids, options) {
if (!Array.isArray(cids)) {
Expand All @@ -115,18 +116,16 @@ class BlockService {
if (this.hasExchange()) {
return this._bitswap.getMany(cids, options)
} else {
const getRepoBlocks = map((cid) => this._repo.blocks.get(cid, options))
return getRepoBlocks(cids)
return map(cids, (cid) => this._repo.blocks.get(cid, options))
}
}

/**
* Delete a block from the blockstore.
*
* @param {CID} cid
* @param {Object} [options] - Options is an object with the following properties
* @param {object} [options] - Options is an object with the following properties
* @param {AbortSignal} [options.signal] - A signal that can be used to abort any long-lived operations that are started as a result of this operation
* @returns {Promise}
*/
async delete (cid, options) {
if (!await this._repo.blocks.has(cid)) {
Expand All @@ -139,10 +138,9 @@ class BlockService {
/**
* Delete multiple blocks from the blockstore.
*
* @param {AsyncIterator<CID>} cids
* @param {Object} [options] - Options is an object with the following properties
* @param {AsyncIterable<CID> | Iterable<CID>} cids
* @param {object} [options] - Options is an object with the following properties
* @param {AbortSignal} [options.signal] - A signal that can be used to abort any long-lived operations that are started as a result of this operation
* @returns {Promise}
*/
deleteMany (cids, options) {
const repo = this._repo
Expand Down
25 changes: 21 additions & 4 deletions test/aborting-requests.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@

const { expect } = require('aegir/utils/chai')

const { collect } = require('streaming-iterables')
const AbortController = require('abort-controller')
const all = require('it-all')
const { AbortController } = require('abort-controller')

const BlockService = require('../src')

/**
* @typedef {import('ipfs-repo')} IPFSRepo
*/

describe('aborting requests', () => {
/** @type {Error} */
let abortedErr
/** @type {BlockService} */
let r

beforeEach(() => {
abortedErr = new Error('Aborted!')
/**
* @param {...any} args
*/
const abortOnSignal = (...args) => {
const { signal } = args[args.length - 1]

Expand All @@ -24,14 +33,17 @@ describe('aborting requests', () => {
})
}

/** @type {IPFSRepo} */
const repo = {
blocks: {
put: abortOnSignal,
// @ts-ignore should return async iterable
putMany: abortOnSignal,
get: abortOnSignal,
delete: abortOnSignal,
// @ts-ignore should return async iterable
deleteMany: abortOnSignal,
has: () => true
has: () => Promise.resolve(true)
}
}
r = new BlockService(repo)
Expand All @@ -41,6 +53,7 @@ describe('aborting requests', () => {
const controller = new AbortController()
setTimeout(() => controller.abort(), 1)

// @ts-expect-error does not take string
await expect(r.put('block', {
signal: controller.signal
})).to.eventually.rejectedWith(abortedErr)
Expand All @@ -50,6 +63,7 @@ describe('aborting requests', () => {
const controller = new AbortController()
setTimeout(() => controller.abort(), 1)

// @ts-expect-error does not take string array
await expect(r.putMany(['block'], {
signal: controller.signal
})).to.eventually.rejectedWith(abortedErr)
Expand All @@ -59,6 +73,7 @@ describe('aborting requests', () => {
const controller = new AbortController()
setTimeout(() => controller.abort(), 1)

// @ts-expect-error does not take string
await expect(r.get('cid', {
signal: controller.signal
})).to.eventually.rejectedWith(abortedErr)
Expand All @@ -68,7 +83,8 @@ describe('aborting requests', () => {
const controller = new AbortController()
setTimeout(() => controller.abort(), 1)

await expect(collect(r.getMany(['cid'], {
// @ts-expect-error does not take string array
await expect(all(r.getMany(['cid'], {
signal: controller.signal
}))).to.eventually.rejectedWith(abortedErr)
})
Expand All @@ -77,6 +93,7 @@ describe('aborting requests', () => {
const controller = new AbortController()
setTimeout(() => controller.abort(), 1)

// @ts-expect-error does not take string
await expect(r.delete('cid', {
signal: controller.signal
})).to.eventually.rejectedWith(abortedErr)
Expand Down
24 changes: 20 additions & 4 deletions test/block-service-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@
const { expect } = require('aegir/utils/chai')

const Block = require('ipld-block')
const _ = require('lodash')
const { collect } = require('streaming-iterables')
const range = require('lodash.range')
const all = require('it-all')
const CID = require('cids')
const multihashing = require('multihashing-async')
const uint8ArrayFromString = require('uint8arrays/from-string')
const drain = require('it-drain')

/**
* @typedef {import('ipfs-repo')} IPFSRepo
*/

const BlockService = require('../src')

/**
* @param {IPFSRepo} repo
*/
module.exports = (repo) => {
describe('block-service', () => {
/** @type {BlockService} */
let bs
/** @type {Block[]} */
let testBlocks

before(async () => {
Expand Down Expand Up @@ -72,7 +81,7 @@ module.exports = (repo) => {

it('get many blocks through .getMany', async () => {
const cids = testBlocks.map(b => b.cid)
const blocks = await collect(bs.getMany(cids))
const blocks = await all(bs.getMany(cids))
expect(blocks).to.eql(testBlocks)
})

Expand Down Expand Up @@ -121,7 +130,7 @@ module.exports = (repo) => {
it('stores and gets lots of blocks', async function () {
this.timeout(20 * 1000)

const data = _.range(1000).map((i) => {
const data = range(1000).map((i) => {
return uint8ArrayFromString(`hello-${i}-${Math.random()}`)
})

Expand Down Expand Up @@ -158,6 +167,9 @@ module.exports = (repo) => {
it('retrieves a block through bitswap', async () => {
// returns a block with a value equal to its key
const bitswap = {
/**
* @param {CID} cid
*/
get (cid) {
return new Block(uint8ArrayFromString('secret'), cid)
}
Expand All @@ -174,8 +186,12 @@ module.exports = (repo) => {
})

it('puts the block through bitswap', async () => {
/** @type {Block[]} */
const puts = []
const bitswap = {
/**
* @param {Block} block
*/
put (block) {
puts.push(block)
}
Expand Down
Loading