Skip to content

Commit 843fba4

Browse files
authored
feat: expose configured dag walkers and hashers on helia interface (#381)
To allow modules like `@helia/car` to re-use configured dag walkers instead of having to bundle their own, expose configured dag walkers and hashers on the helia interface and have them consume those. Fixes #375
1 parent 76220cd commit 843fba4

File tree

13 files changed

+119
-277
lines changed

13 files changed

+119
-277
lines changed

packages/block-brokers/src/bitswap.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { ProgressOptions } from 'progress-events'
1010
interface BitswapComponents {
1111
libp2p: Libp2p
1212
blockstore: Blockstore
13-
hashers: MultihashHasher[]
13+
hashers: Record<string, MultihashHasher>
1414
}
1515

1616
export interface BitswapInit extends BitswapOptions {
@@ -29,9 +29,15 @@ ProgressOptions<BitswapWantBlockProgressEvents>
2929
this.bitswap = createBitswap(libp2p, blockstore, {
3030
hashLoader: {
3131
getHasher: async (codecOrName: string | number): Promise<MultihashHasher<number>> => {
32-
const hasher = hashers.find(hasher => {
33-
return hasher.code === codecOrName || hasher.name === codecOrName
34-
})
32+
let hasher: MultihashHasher | undefined
33+
34+
if (typeof codecOrName === 'string') {
35+
hasher = Object.values(hashers).find(hasher => {
36+
return hasher.name === codecOrName
37+
})
38+
} else {
39+
hasher = hashers[codecOrName]
40+
}
3541

3642
if (hasher != null) {
3743
return hasher

packages/car/package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,7 @@
141141
"dependencies": {
142142
"@helia/interface": "^3.0.1",
143143
"@ipld/car": "^5.1.1",
144-
"@ipld/dag-pb": "^4.0.6",
145144
"@libp2p/interfaces": "^3.3.1",
146-
"cborg": "^4.0.3",
147145
"it-drain": "^3.0.5",
148146
"it-map": "^3.0.3",
149147
"multiformats": "^13.0.0",
@@ -153,6 +151,7 @@
153151
},
154152
"devDependencies": {
155153
"@helia/unixfs": "^2.0.1",
154+
"@ipld/dag-pb": "^4.0.8",
156155
"aegir": "^42.1.0",
157156
"blockstore-core": "^4.3.10",
158157
"interface-blockstore": "^5.2.9",

packages/car/src/index.ts

+6-36
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ import drain from 'it-drain'
6262
import map from 'it-map'
6363
import defer from 'p-defer'
6464
import PQueue from 'p-queue'
65-
import { cborWalker, dagPbWalker, jsonWalker, rawWalker } from './utils/dag-walkers.js'
65+
import type { DAGWalker } from '@helia/interface'
6666
import type { Blocks, GetBlockProgressEvents, PutManyBlocksProgressEvents } from '@helia/interface/blocks'
6767
import type { CarReader, CarWriter } from '@ipld/car'
6868
import type { AbortOptions } from '@libp2p/interfaces'
@@ -71,23 +71,7 @@ import type { ProgressOptions } from 'progress-events'
7171

7272
export interface CarComponents {
7373
blockstore: Blocks
74-
}
75-
76-
export interface CarInit {
77-
/**
78-
* In order to export CIDs that correspond to a DAG, it's necessary to know
79-
* how to traverse that DAG. DAGWalkers take a block and yield any CIDs
80-
* encoded within that block.
81-
*/
82-
dagWalkers?: DAGWalker[]
83-
}
84-
85-
/**
86-
* DAGWalkers take a block and yield CIDs encoded in that block
87-
*/
88-
export interface DAGWalker {
89-
codec: number
90-
walk(block: Uint8Array): AsyncGenerator<CID, void, undefined>
74+
dagWalkers: Record<number, DAGWalker>
9175
}
9276

9377
/**
@@ -146,27 +130,13 @@ export interface Car {
146130
export(root: CID | CID[], writer: Pick<CarWriter, 'put' | 'close'>, options?: AbortOptions & ProgressOptions<GetBlockProgressEvents>): Promise<void>
147131
}
148132

149-
const DEFAULT_DAG_WALKERS = [
150-
rawWalker,
151-
dagPbWalker,
152-
cborWalker,
153-
jsonWalker
154-
]
155-
156133
const DAG_WALK_QUEUE_CONCURRENCY = 1
157134

158135
class DefaultCar implements Car {
159136
private readonly components: CarComponents
160-
private dagWalkers: Record<number, DAGWalker>
161137

162-
constructor (components: CarComponents, init: CarInit) {
138+
constructor (components: CarComponents, init: any) {
163139
this.components = components
164-
165-
this.dagWalkers = {}
166-
167-
;[...DEFAULT_DAG_WALKERS, ...(init.dagWalkers ?? [])].forEach(dagWalker => {
168-
this.dagWalkers[dagWalker.codec] = dagWalker
169-
})
170140
}
171141

172142
async import (reader: Pick<CarReader, 'blocks'>, options?: AbortOptions & ProgressOptions<PutManyBlocksProgressEvents>): Promise<void> {
@@ -188,7 +158,7 @@ class DefaultCar implements Car {
188158
deferred.resolve()
189159
})
190160
queue.on('error', (err) => {
191-
deferred.resolve(err)
161+
deferred.reject(err)
192162
})
193163

194164
for (const root of roots) {
@@ -212,7 +182,7 @@ class DefaultCar implements Car {
212182
* and update the pin count for them
213183
*/
214184
async #walkDag (cid: CID, queue: PQueue, withBlock: (cid: CID, block: Uint8Array) => Promise<void>, options?: AbortOptions & ProgressOptions<GetBlockProgressEvents>): Promise<void> {
215-
const dagWalker = this.dagWalkers[cid.code]
185+
const dagWalker = this.components.dagWalkers[cid.code]
216186

217187
if (dagWalker == null) {
218188
throw new Error(`No dag walker found for cid codec ${cid.code}`)
@@ -234,6 +204,6 @@ class DefaultCar implements Car {
234204
/**
235205
* Create a {@link Car} instance for use with {@link https://github.com/ipfs/helia Helia}
236206
*/
237-
export function car (helia: { blockstore: Blocks }, init: CarInit = {}): Car {
207+
export function car (helia: { blockstore: Blocks, dagWalkers: Record<number, DAGWalker> }, init: any = {}): Car {
238208
return new DefaultCar(helia, init)
239209
}

packages/car/src/utils/dag-walkers.ts

-176
This file was deleted.

packages/car/test/index.spec.ts

+32-5
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,58 @@
22

33
import { type UnixFS, unixfs } from '@helia/unixfs'
44
import { CarReader } from '@ipld/car'
5+
import * as dagPb from '@ipld/dag-pb'
56
import { expect } from 'aegir/chai'
67
import { MemoryBlockstore } from 'blockstore-core'
78
import { fixedSize } from 'ipfs-unixfs-importer/chunker'
89
import toBuffer from 'it-to-buffer'
10+
import * as raw from 'multiformats/codecs/raw'
911
import { car, type Car } from '../src/index.js'
1012
import { largeFile, smallFile } from './fixtures/files.js'
1113
import { memoryCarWriter } from './fixtures/memory-car.js'
14+
import type { DAGWalker } from '@helia/interface'
1215
import type { Blockstore } from 'interface-blockstore'
1316

17+
/**
18+
* Dag walker for dag-pb CIDs
19+
*/
20+
const dagPbWalker: DAGWalker = {
21+
codec: dagPb.code,
22+
* walk (block) {
23+
const node = dagPb.decode(block)
24+
25+
yield * node.Links.map(l => l.Hash)
26+
}
27+
}
28+
29+
const rawWalker: DAGWalker = {
30+
codec: raw.code,
31+
* walk () {
32+
// no embedded CIDs in a raw block
33+
}
34+
}
35+
1436
describe('import', () => {
1537
let blockstore: Blockstore
1638
let c: Car
1739
let u: UnixFS
40+
let dagWalkers: Record<number, DAGWalker>
1841

1942
beforeEach(async () => {
2043
blockstore = new MemoryBlockstore()
44+
dagWalkers = {
45+
[dagPb.code]: dagPbWalker,
46+
[raw.code]: rawWalker
47+
}
2148

22-
c = car({ blockstore })
49+
c = car({ blockstore, dagWalkers })
2350
u = unixfs({ blockstore })
2451
})
2552

2653
it('exports and imports a car file', async () => {
2754
const otherBlockstore = new MemoryBlockstore()
2855
const otherUnixFS = unixfs({ blockstore: otherBlockstore })
29-
const otherCar = car({ blockstore: otherBlockstore })
56+
const otherCar = car({ blockstore: otherBlockstore, dagWalkers })
3057
const cid = await otherUnixFS.addBytes(smallFile)
3158

3259
const writer = memoryCarWriter(cid)
@@ -46,7 +73,7 @@ describe('import', () => {
4673

4774
const otherBlockstore = new MemoryBlockstore()
4875
const otherUnixFS = unixfs({ blockstore: otherBlockstore })
49-
const otherCar = car({ blockstore: otherBlockstore })
76+
const otherCar = car({ blockstore: otherBlockstore, dagWalkers })
5077
const cid1 = await otherUnixFS.addBytes(fileData1)
5178
const cid2 = await otherUnixFS.addBytes(fileData2)
5279
const cid3 = await otherUnixFS.addBytes(fileData3)
@@ -66,7 +93,7 @@ describe('import', () => {
6693
it('exports and imports a multiple block car file', async () => {
6794
const otherBlockstore = new MemoryBlockstore()
6895
const otherUnixFS = unixfs({ blockstore: otherBlockstore })
69-
const otherCar = car({ blockstore: otherBlockstore })
96+
const otherCar = car({ blockstore: otherBlockstore, dagWalkers })
7097
const cid = await otherUnixFS.addBytes(largeFile, {
7198
chunker: fixedSize({
7299
chunkSize: 1024
@@ -90,7 +117,7 @@ describe('import', () => {
90117

91118
const otherBlockstore = new MemoryBlockstore()
92119
const otherUnixFS = unixfs({ blockstore: otherBlockstore })
93-
const otherCar = car({ blockstore: otherBlockstore })
120+
const otherCar = car({ blockstore: otherBlockstore, dagWalkers })
94121
const cid1 = await otherUnixFS.addBytes(fileData1, {
95122
chunker: fixedSize({
96123
chunkSize: 2

0 commit comments

Comments
 (0)