@helia/utils 2.5.2-73a28eda → 2.5.2-9114743f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/index.min.js +22 -2
  2. package/dist/index.min.js.map +4 -4
  3. package/dist/src/abstract-session.d.ts +3 -3
  4. package/dist/src/abstract-session.d.ts.map +1 -1
  5. package/dist/src/abstract-session.js.map +1 -1
  6. package/dist/src/graph-walker.d.ts +3 -21
  7. package/dist/src/graph-walker.d.ts.map +1 -1
  8. package/dist/src/graph-walker.js +20 -17
  9. package/dist/src/graph-walker.js.map +1 -1
  10. package/dist/src/index.d.ts +30 -37
  11. package/dist/src/index.d.ts.map +1 -1
  12. package/dist/src/index.js +54 -29
  13. package/dist/src/index.js.map +1 -1
  14. package/dist/src/pins.d.ts.map +1 -1
  15. package/dist/src/pins.js +11 -39
  16. package/dist/src/pins.js.map +1 -1
  17. package/dist/src/routing.d.ts +7 -5
  18. package/dist/src/routing.d.ts.map +1 -1
  19. package/dist/src/routing.js +10 -4
  20. package/dist/src/routing.js.map +1 -1
  21. package/dist/src/utils/is-cid.d.ts +3 -0
  22. package/dist/src/utils/is-cid.d.ts.map +1 -0
  23. package/dist/src/utils/is-cid.js +8 -0
  24. package/dist/src/utils/is-cid.js.map +1 -0
  25. package/dist/src/utils/networked-storage.d.ts +2 -1
  26. package/dist/src/utils/networked-storage.d.ts.map +1 -1
  27. package/dist/src/utils/networked-storage.js.map +1 -1
  28. package/dist/src/utils/session-storage.d.ts +2 -2
  29. package/dist/src/utils/session-storage.d.ts.map +1 -1
  30. package/dist/src/utils/session-storage.js.map +1 -1
  31. package/package.json +19 -19
  32. package/src/abstract-session.ts +4 -4
  33. package/src/graph-walker.ts +30 -43
  34. package/src/index.ts +89 -74
  35. package/src/pins.ts +12 -50
  36. package/src/routing.ts +23 -10
  37. package/src/utils/is-cid.ts +9 -0
  38. package/src/utils/networked-storage.ts +2 -1
  39. package/src/utils/session-storage.ts +2 -2
package/src/index.ts CHANGED
@@ -6,8 +6,11 @@
6
6
  */
7
7
 
8
8
  import { keychain } from '@ipshipyard/keychain'
9
- import { contentRoutingSymbol, peerRoutingSymbol, start, stop, TypedEventEmitter } from '@libp2p/interface'
9
+ import { start, stop, TypedEventEmitter } from '@libp2p/interface'
10
10
  import { dns } from '@multiformats/dns'
11
+ import { defaultLogger } from 'birnam'
12
+ import { MemoryBlockstore } from 'blockstore-core'
13
+ import { MemoryDatastore } from 'datastore-core'
11
14
  import drain from 'it-drain'
12
15
  import { CustomProgressEvent } from 'progress-events'
13
16
  import { PinsImpl } from './pins.ts'
@@ -19,15 +22,14 @@ import { getCrypto } from './utils/get-crypto.ts'
19
22
  import { getHasher } from './utils/get-hasher.ts'
20
23
  import { NetworkedStorage } from './utils/networked-storage.ts'
21
24
  import type { BlockStorageInit } from './storage.ts'
22
- import type { CodecLoader, GCOptions, HasherLoader, Helia as HeliaInterface, HeliaEvents, Routing, CryptoLoader, Crypto } from '@helia/interface'
25
+ import type { CodecLoader, GCOptions, HasherLoader, Helia as HeliaInterface, HeliaEvents, Routing, CryptoLoader, Crypto, NodeInfo, Router, HeliaMixin } from '@helia/interface'
23
26
  import type { BlockBroker } from '@helia/interface/blocks'
24
27
  import type { Pins } from '@helia/interface/pins'
25
28
  import type { Keychain, KeychainInit } from '@ipshipyard/keychain'
26
- import type { ComponentLogger, ContentRouting, Libp2p, Logger, Metrics, PeerRouting } from '@libp2p/interface'
29
+ import type { ComponentLogger, Logger, Metrics } from '@libp2p/interface'
27
30
  import type { DNS } from '@multiformats/dns'
28
31
  import type { Blockstore } from 'interface-blockstore'
29
32
  import type { Datastore } from 'interface-datastore'
30
- import type { Libp2pOptions } from 'libp2p'
31
33
  import type { BlockCodec } from 'multiformats'
32
34
  import type { CID } from 'multiformats/cid'
33
35
  import type { MultihashHasher } from 'multiformats/hashes/interface'
@@ -35,6 +37,8 @@ import type { MultihashHasher } from 'multiformats/hashes/interface'
35
37
  export { AbstractSession } from './abstract-session.ts'
36
38
  export type { AbstractCreateSessionOptions, BlockstoreSessionEvents, AbstractSessionComponents } from './abstract-session.ts'
37
39
 
40
+ export { isCID } from './utils/is-cid.ts'
41
+
38
42
  export type { BlockStorage, BlockStorageInit }
39
43
 
40
44
  export { breadthFirstWalker, depthFirstWalker, naturalOrderWalker } from './graph-walker.ts'
@@ -43,26 +47,7 @@ export type { GraphWalkerComponents, GraphWalkerInit, GraphNode, GraphWalker } f
43
47
  /**
44
48
  * Options used to create a Helia node.
45
49
  */
46
- export interface HeliaInit<T extends Libp2p = Libp2p> {
47
- /**
48
- * A libp2p node is required to perform network operations. Either a
49
- * pre-configured node or options to configure a node can be passed
50
- * here.
51
- *
52
- * If node options are passed, they will be merged with the default
53
- * config for the current platform. In this case all passed config
54
- * keys will replace those from the default config.
55
- *
56
- * The libp2p `start` option is not supported, instead please pass `start` in
57
- * the root of the HeliaInit object.
58
- */
59
- libp2p: T | Omit<Libp2pOptions<any>, 'start'>
60
-
61
- /**
62
- * Pass `false` to not start the Helia node
63
- */
64
- start?: boolean
65
-
50
+ export interface HeliaInit {
66
51
  /**
67
52
  * By default Helia stores the node's PeerId in an encrypted form in a
68
53
  * libp2p keystore. These options control how that keystore is configured.
@@ -72,12 +57,12 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
72
57
  /**
73
58
  * The blockstore is where blocks are stored
74
59
  */
75
- blockstore: Blockstore
60
+ blockstore?: Blockstore
76
61
 
77
62
  /**
78
63
  * The datastore is where data is stored
79
64
  */
80
- datastore: Datastore
65
+ datastore?: Datastore
81
66
 
82
67
  /**
83
68
  * By default sha256, sha512 and identity hashes are supported for
@@ -105,12 +90,6 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
105
90
  */
106
91
  loadCodec?(code: number): BlockCodec<any, any> | Promise<BlockCodec<any, any>>
107
92
 
108
- /**
109
- * A list of strategies used to fetch blocks when they are not present in
110
- * the local blockstore
111
- */
112
- blockBrokers: Array<(components: any) => BlockBroker>
113
-
114
93
  /**
115
94
  * A list of pre-supported public/private key implementations
116
95
  */
@@ -143,11 +122,17 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
143
122
  */
144
123
  logger?: ComponentLogger
145
124
 
125
+ /**
126
+ * A list of strategies used to fetch blocks when they are not present in
127
+ * the local blockstore
128
+ */
129
+ blockBrokers?: Array<BlockBroker | ((components: any) => BlockBroker)>
130
+
146
131
  /**
147
132
  * Routers perform operations such as looking up content providers,
148
133
  * information about network peers or getting/putting records.
149
134
  */
150
- routers?: Array<Partial<Routing> | ((components: any) => Partial<Routing>)>
135
+ routers?: Array<Router | ((components: any) => Router)>
151
136
 
152
137
  /**
153
138
  * During provider lookups, peers can be returned from routing implementations
@@ -192,7 +177,6 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
192
177
  }
193
178
 
194
179
  interface Components {
195
- libp2p: Libp2p
196
180
  blockstore: Blockstore
197
181
  datastore: Datastore
198
182
  logger: ComponentLogger
@@ -206,39 +190,46 @@ interface Components {
206
190
  getCrypto: CryptoLoader
207
191
  }
208
192
 
209
- export class Helia<T extends Libp2p> implements HeliaInterface<T> {
210
- public libp2p: T
193
+ export class Helia implements HeliaInterface {
194
+ public info: NodeInfo
211
195
  public blockstore: BlockStorage
212
196
  public datastore: Datastore
213
- public events: TypedEventEmitter<HeliaEvents<T>>
197
+ public events: TypedEventEmitter<HeliaEvents<this>>
214
198
  public pins: Pins
215
199
  public logger: ComponentLogger
216
- public routing: Routing
200
+ public routing: RoutingClass
217
201
  public getCodec: CodecLoader
218
202
  public getHasher: HasherLoader
219
203
  public getCrypto: CryptoLoader
220
204
  public dns: DNS
221
205
  public keychain: Keychain
222
206
  public metrics?: Metrics
207
+ public status: 'stopped' | 'stopping' | 'starting' | 'started'
223
208
  private readonly log: Logger
209
+ private readonly blockBrokers: BlockBroker[]
210
+ private readonly mixins: HeliaMixin[]
224
211
 
225
- constructor (init: Omit<HeliaInit, 'start' | 'libp2p'> & { libp2p: T }) {
226
- this.logger = init.logger ?? init.libp2p.logger
212
+ constructor (init: HeliaInit & { name: string, version: string }) {
213
+ this.info = {
214
+ name: init.name,
215
+ version: init.version
216
+ }
217
+ this.logger = init.logger ?? defaultLogger()
227
218
  this.log = this.logger.forComponent('helia')
228
219
  this.getHasher = getHasher(init.hashers, init.loadHasher)
229
220
  this.getCodec = getCodec(init.codecs, init.loadCodec)
230
221
  this.getCrypto = getCrypto(init.cryptos, init.loadCrypto)
231
222
  this.dns = init.dns ?? dns()
232
223
  this.metrics = init.metrics
233
- this.libp2p = init.libp2p
234
- this.events = new TypedEventEmitter<HeliaEvents<T>>()
224
+ this.events = new TypedEventEmitter<HeliaEvents<typeof this>>()
225
+ this.status = 'stopped'
226
+ this.mixins = []
235
227
 
236
228
  // @ts-expect-error routing and keychain are not set
237
229
  const components: Components = {
238
- blockstore: init.blockstore,
239
- datastore: init.datastore,
230
+ blockstore: init.blockstore ?? new MemoryBlockstore(),
231
+ datastore: init.datastore ?? new MemoryDatastore(),
240
232
  logger: this.logger,
241
- libp2p: this.libp2p,
242
233
  blockBrokers: [],
243
234
  getHasher: this.getHasher,
244
235
  getCodec: this.getCodec,
@@ -251,7 +242,7 @@ export class Helia<T extends Libp2p> implements HeliaInterface<T> {
251
242
  this.keychain = components.keychain = keychain()(components)
252
243
 
253
244
  this.routing = components.routing = new RoutingClass(components, {
254
- routers: (init.routers ?? []).flatMap((router: Partial<Routing> | ((components: any) => Partial<Routing>)) => {
245
+ routers: (init.routers ?? []).flatMap((router: Router | ((components: any) => Router)) => {
255
246
  if (typeof router === 'function') {
256
247
  router = router(components)
257
248
  }
@@ -261,54 +252,86 @@ export class Helia<T extends Libp2p> implements HeliaInterface<T> {
261
252
  router
262
253
  ]
263
254
 
264
- // if the router provides a libp2p-style ContentRouter
265
- const contentRouting = asContentRouting(router)
266
- if (contentRouting != null) {
267
- routers.push(contentRouting)
268
- }
269
-
270
- // if the router provides a libp2p-style PeerRouter
271
- const peerRouting = asPeerRouting(router)
272
- if (peerRouting != null) {
273
- routers.push(peerRouting)
274
- }
275
-
276
255
  return routers
277
256
  }),
278
257
  providerLookupConcurrency: init.providerLookupConcurrency
279
258
  })
280
259
 
281
- components.blockBrokers = init.blockBrokers.map((fn) => {
282
- return fn(components)
260
+ this.blockBrokers = components.blockBrokers = (init.blockBrokers ?? []).map((broker) => {
261
+ if (typeof broker === 'function') {
262
+ broker = broker(components)
263
+ }
264
+
265
+ return broker
283
266
  })
284
267
 
285
268
  const networkedStorage = new NetworkedStorage(components, init)
286
- this.pins = new PinsImpl(init.datastore, networkedStorage, this.getCodec)
269
+ this.pins = new PinsImpl(components.datastore, networkedStorage, this.getCodec)
287
270
  this.blockstore = new BlockStorage(networkedStorage, this.pins, this.routing, {
288
271
  holdGcLock: init.holdGcLock ?? true
289
272
  })
290
- this.datastore = init.datastore
273
+ this.datastore = components.datastore
274
+ }
275
+
276
+ hasRouter (name: string): boolean {
277
+ return this.routing.hasRouter(name)
278
+ }
279
+
280
+ addRouter (router: Router): void {
281
+ this.routing.addRouter(router)
282
+ }
283
+
284
+ hasBlockBroker (name: string): boolean {
285
+ return this.blockBrokers.findIndex(b => b.name === name) !== -1
291
286
  }
292
287
 
293
- async start (): Promise<void> {
288
+ addBlockBroker (blockBroker: BlockBroker): void {
289
+ this.blockBrokers.push(blockBroker)
290
+ }
291
+
292
+ addMixin (mixin: HeliaMixin): void {
293
+ this.mixins.push(mixin)
294
+ }
295
+
296
+ async start (): Promise<this> {
297
+ this.status = 'starting'
298
+
294
299
  await assertDatastoreVersionIsCurrent(this.datastore)
295
300
  await start(
296
301
  this.blockstore,
297
302
  this.datastore,
298
303
  this.routing,
299
- this.libp2p
304
+ ...this.blockBrokers
300
305
  )
306
+
307
+ for (const mixin of this.mixins) {
308
+ await mixin.start?.(this)
309
+ }
310
+
311
+ this.status = 'started'
301
312
  this.events.dispatchEvent(new CustomEvent('start', { detail: this }))
313
+
314
+ return this
302
315
  }
303
316
 
304
- async stop (): Promise<void> {
317
+ async stop (): Promise<this> {
318
+ this.status = 'stopping'
319
+
320
+ for (const mixin of this.mixins) {
321
+ await mixin.stop?.(this)
322
+ }
323
+
305
324
  await stop(
306
325
  this.blockstore,
307
326
  this.datastore,
308
327
  this.routing,
309
- this.libp2p
328
+ ...this.blockBrokers
310
329
  )
330
+
331
+ this.status = 'stopped'
311
332
  this.events.dispatchEvent(new CustomEvent('stop', { detail: this }))
333
+
334
+ return this
312
335
  }
313
336
 
314
337
  async gc (options: GCOptions = {}): Promise<void> {
@@ -343,11 +366,3 @@ export class Helia<T extends Libp2p> implements HeliaInterface<T> {
343
366
  this.log('gc finished')
344
367
  }
345
368
  }
346
-
347
- function asContentRouting (obj?: any): ContentRouting | undefined {
348
- return obj?.[contentRoutingSymbol]
349
- }
350
-
351
- function asPeerRouting (obj?: any): PeerRouting | undefined {
352
- return obj?.[peerRoutingSymbol]
353
- }
package/src/pins.ts CHANGED
@@ -1,22 +1,18 @@
1
1
  import { InvalidParametersError } from '@libp2p/interface'
2
- import { Queue } from '@libp2p/utils'
3
2
  import * as cborg from 'cborg'
4
3
  import { Key } from 'interface-datastore'
5
- import toBuffer from 'it-to-buffer'
6
4
  import { base36 } from 'multiformats/bases/base36'
7
- import { createUnsafe } from 'multiformats/block'
8
5
  import { CID } from 'multiformats/cid'
9
6
  import { CustomProgressEvent } from 'progress-events'
10
7
  import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
11
8
  import { AlreadyPinnedError } from './errors.ts'
9
+ import { depthFirstWalker } from './graph-walker.ts'
12
10
  import type { CodecLoader } from '@helia/interface'
13
- import type { GetBlockProgressEvents } from '@helia/interface/blocks'
14
- import type { AddOptions, AddPinEvents, IsPinnedOptions, LsOptions, Pin, Pins, RmOptions } from '@helia/interface/pins'
11
+ import type { AddOptions, IsPinnedOptions, LsOptions, Pin, Pins, RmOptions } from '@helia/interface/pins'
15
12
  import type { AbortOptions } from '@libp2p/interface'
16
13
  import type { Blockstore } from 'interface-blockstore'
17
14
  import type { Datastore } from 'interface-datastore'
18
15
  import type { Version } from 'multiformats/cid'
19
- import type { ProgressOptions } from 'progress-events'
20
16
 
21
17
  interface DatastorePin {
22
18
  /**
@@ -49,11 +45,6 @@ interface WithPinnedBlockCallback {
49
45
  const DATASTORE_PIN_PREFIX = '/pin/'
50
46
  const DATASTORE_BLOCK_PREFIX = '/pinned-block/'
51
47
  const DATASTORE_ENCODING = base36
52
- const DAG_WALK_QUEUE_CONCURRENCY = 1
53
-
54
- interface WalkDagOptions extends AbortOptions, ProgressOptions<GetBlockProgressEvents | AddPinEvents> {
55
- depth: number
56
- }
57
48
 
58
49
  function toDSKey (cid: CID): Key {
59
50
  if (cid.version === 0) {
@@ -87,15 +78,13 @@ export class PinsImpl implements Pins {
87
78
  throw new InvalidParametersError('Depth must be greater than or equal to 0')
88
79
  }
89
80
 
90
- // use a queue to walk the DAG instead of recursion so we can traverse very large DAGs
91
- const queue = new Queue<AsyncGenerator<CID>>({
92
- concurrency: DAG_WALK_QUEUE_CONCURRENCY
81
+ const walker = (options.walker ?? depthFirstWalker())({
82
+ blockstore: this.blockstore,
83
+ getCodec: this.getCodec
93
84
  })
94
85
 
95
- for await (const childCid of this.#walkDag(cid, queue, {
96
- ...options,
97
- depth
98
- })) {
86
+ for await (const node of walker.walk(cid, { ...options, depth })) {
87
+ const childCid = node.block.cid
99
88
  await this.#updatePinnedBlock(childCid, (pinnedBlock: DatastorePinnedBlock) => {
100
89
  // do not update pinned block if this block is already pinned by this CID
101
90
  if (pinnedBlock.pinnedBy.find(c => uint8ArrayEquals(c, cid.bytes)) != null) {
@@ -118,31 +107,6 @@ export class PinsImpl implements Pins {
118
107
  await this.datastore.put(pinKey, cborg.encode(pin), options)
119
108
  }
120
109
 
121
- /**
122
- * Walk a DAG in an iterable fashion
123
- */
124
- async * #walkDag (cid: CID, queue: Queue<AsyncGenerator<CID>>, options: WalkDagOptions): AsyncGenerator<CID> {
125
- if (options.depth === -1) {
126
- return
127
- }
128
-
129
- const codec = await this.getCodec(cid.code)
130
- const bytes = await toBuffer(this.blockstore.get(cid, options))
131
- const block = createUnsafe({ bytes, cid, codec })
132
-
133
- yield cid
134
-
135
- // walk dag, ensure all blocks are present
136
- for (const [,cid] of block.links()) {
137
- yield * await queue.add(async () => {
138
- return this.#walkDag(cid, queue, {
139
- ...options,
140
- depth: options.depth - 1
141
- })
142
- })
143
- }
144
- }
145
-
146
110
  /**
147
111
  * Update the pin count for the CID
148
112
  */
@@ -186,15 +150,13 @@ export class PinsImpl implements Pins {
186
150
 
187
151
  await this.datastore.delete(pinKey, options)
188
152
 
189
- // use a queue to walk the DAG instead of recursion so we can traverse very large DAGs
190
- const queue = new Queue<AsyncGenerator<CID>>({
191
- concurrency: DAG_WALK_QUEUE_CONCURRENCY
153
+ const walker = (options.walker ?? depthFirstWalker())({
154
+ blockstore: this.blockstore,
155
+ getCodec: this.getCodec
192
156
  })
193
157
 
194
- for await (const childCid of this.#walkDag(cid, queue, {
195
- ...options,
196
- depth: pin.depth
197
- })) {
158
+ for await (const node of walker.walk(cid, { ...options, depth: pin.depth })) {
159
+ const childCid = node.block.cid
198
160
  await this.#updatePinnedBlock(childCid, (pinnedBlock): boolean => {
199
161
  pinnedBlock.pinCount--
200
162
  pinnedBlock.pinnedBy = pinnedBlock.pinnedBy.filter(c => uint8ArrayEquals(c, cid.bytes))
package/src/routing.ts CHANGED
@@ -1,18 +1,19 @@
1
1
  import { NoRoutersAvailableError } from '@helia/interface'
2
2
  import { NotFoundError, start, stop } from '@libp2p/interface'
3
- import { PeerQueue } from '@libp2p/utils'
3
+ import { Queue } from '@libp2p/utils'
4
4
  import merge from 'it-merge'
5
5
  import { CustomProgressEvent } from 'progress-events'
6
6
  import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
7
7
  import { GetFailedError } from './errors.ts'
8
- import type { Routing as RoutingInterface, Provider, RoutingOptions, RoutingFindProvidersProgressEvents, RoutingProvideProgressEvents, RoutingPutProgressEvents, RoutingGetProgressEvents, RoutingFindPeerProgressEvents, RoutingGetClosestPeersProgressEvents, RoutingCancelReprovideProgressEvents } from '@helia/interface'
9
- import type { ComponentLogger, Logger, Metrics, PeerId, PeerInfo, Startable } from '@libp2p/interface'
8
+ import type { Routing as RoutingInterface, Provider, RoutingOptions, RoutingFindProvidersProgressEvents, RoutingProvideProgressEvents, RoutingPutProgressEvents, RoutingGetProgressEvents, RoutingFindPeerProgressEvents, RoutingGetClosestPeersProgressEvents, RoutingCancelReprovideProgressEvents, Router, Peer } from '@helia/interface'
9
+ import type { ComponentLogger, Logger, Metrics, Startable } from '@libp2p/interface'
10
+ import type { AbortOptions } from 'abort-error'
10
11
  import type { CID } from 'multiformats/cid'
11
12
 
12
13
  const DEFAULT_PROVIDER_LOOKUP_CONCURRENCY = 5
13
14
 
14
15
  export interface RoutingInit {
15
- routers: Array<Partial<RoutingInterface>>
16
+ routers: Router[]
16
17
  providerLookupConcurrency?: number
17
18
  }
18
19
 
@@ -21,11 +22,15 @@ export interface RoutingComponents {
21
22
  metrics?: Metrics
22
23
  }
23
24
 
25
+ interface PeerQueueOptions extends AbortOptions {
26
+ peer: CID
27
+ }
28
+
24
29
  export class Routing implements RoutingInterface, Startable {
25
30
  public name: string
26
31
 
27
32
  private readonly log: Logger
28
- private readonly routers: Array<Partial<RoutingInterface>>
33
+ private readonly routers: Router[]
29
34
  private readonly providerLookupConcurrency: number
30
35
 
31
36
  constructor (components: RoutingComponents, init: RoutingInit) {
@@ -65,6 +70,14 @@ export class Routing implements RoutingInterface, Startable {
65
70
  await stop(...this.routers)
66
71
  }
67
72
 
73
+ hasRouter (name: string): boolean {
74
+ return this.routers.findIndex(r => r.name === name) !== -1
75
+ }
76
+
77
+ addRouter (router: Router): void {
78
+ this.routers.push(router)
79
+ }
80
+
68
81
  /**
69
82
  * Iterates over all content routers in parallel to find providers of the
70
83
  * given key
@@ -78,7 +91,7 @@ export class Routing implements RoutingInterface, Startable {
78
91
  // back as an empty array - when this happens we have to do a FIND_PEER
79
92
  // query to get updated addresses, but we shouldn't block on this so use a
80
93
  // separate bounded queue to perform this lookup
81
- const queue = new PeerQueue<Provider | null>({
94
+ const queue = new Queue<Provider | null, PeerQueueOptions>({
82
95
  concurrency: this.providerLookupConcurrency
83
96
  })
84
97
 
@@ -145,7 +158,7 @@ export class Routing implements RoutingInterface, Startable {
145
158
  // have to refresh peer info for this peer to get updated multiaddrs
146
159
  if (peer.multiaddrs.length === 0) {
147
160
  // already looking this peer up
148
- if (queue.find(peer.id) != null) {
161
+ if (queue.queue.find(job => job.options.peer.equals(peer.id)) != null) {
149
162
  continue
150
163
  }
151
164
 
@@ -167,7 +180,7 @@ export class Routing implements RoutingInterface, Startable {
167
180
  return null
168
181
  }
169
182
  }, {
170
- peerId: peer.id,
183
+ peer: peer.id,
171
184
  signal: options.signal
172
185
  })
173
186
  .catch(err => {
@@ -298,7 +311,7 @@ export class Routing implements RoutingInterface, Startable {
298
311
  /**
299
312
  * Iterates over all peer routers in parallel to find the given peer
300
313
  */
301
- async findPeer (id: PeerId, options?: RoutingOptions<RoutingFindPeerProgressEvents>): Promise<PeerInfo> {
314
+ async findPeer (id: CID, options?: RoutingOptions<RoutingFindPeerProgressEvents>): Promise<Peer> {
302
315
  if (this.routers.length === 0) {
303
316
  throw new NoRoutersAvailableError('No peer routers available')
304
317
  }
@@ -339,7 +352,7 @@ export class Routing implements RoutingInterface, Startable {
339
352
  /**
340
353
  * Attempt to find the closest peers on the network to the given key
341
354
  */
342
- async * getClosestPeers (key: Uint8Array, options: RoutingOptions<RoutingGetClosestPeersProgressEvents> = {}): AsyncIterable<PeerInfo> {
355
+ async * getClosestPeers (key: Uint8Array, options: RoutingOptions<RoutingGetClosestPeersProgressEvents> = {}): AsyncIterable<Peer> {
343
356
  if (this.routers.length === 0) {
344
357
  throw new NoRoutersAvailableError('No peer routers available')
345
358
  }
@@ -0,0 +1,9 @@
1
+ import { CID } from 'multiformats/cid'
2
+
3
+ export function isCID (obj?: any): obj is CID {
4
+ if (obj == null) {
5
+ return false
6
+ }
7
+
8
+ return CID.asCID(obj) != null
9
+ }
@@ -4,7 +4,8 @@ import { SessionStorage } from './session-storage.ts'
4
4
  import { Storage } from './storage.ts'
5
5
  import type { StorageComponents, StorageInit } from './storage.ts'
6
6
  import type { BlockBroker, Blocks, CreateSessionOptions, SessionBlockstore } from '@helia/interface/blocks'
7
- import type { AbortOptions, Startable } from '@libp2p/interface'
7
+ import type { Startable } from '@libp2p/interface'
8
+ import type { AbortOptions } from 'abort-error'
8
9
  import type { Blockstore } from 'interface-blockstore'
9
10
  import type { CID } from 'multiformats/cid'
10
11
 
@@ -3,7 +3,7 @@ import { anySignal } from 'any-signal'
3
3
  import { Storage } from './storage.ts'
4
4
  import type { StorageComponents } from './storage.ts'
5
5
  import type { Pair, DeleteManyBlocksProgressEvents, DeleteBlockProgressEvents, GetBlockProgressEvents, GetManyBlocksProgressEvents, PutManyBlocksProgressEvents, PutBlockProgressEvents, GetAllBlocksProgressEvents, GetOfflineOptions, SessionBlockstore, SessionBlockBroker } from '@helia/interface/blocks'
6
- import type { AbortOptions, PeerId } from '@libp2p/interface'
6
+ import type { AbortOptions } from '@libp2p/interface'
7
7
  import type { Multiaddr } from '@multiformats/multiaddr'
8
8
  import type { InputPair } from 'interface-blockstore'
9
9
  import type { CID } from 'multiformats/cid'
@@ -35,7 +35,7 @@ export class SessionStorage extends Storage<SessionBlockBroker> implements Sessi
35
35
  this.closeController.abort()
36
36
  }
37
37
 
38
- async addPeer (peer: PeerId | Multiaddr | Multiaddr[], options?: AbortOptions): Promise<void> {
38
+ async addPeer (peer: CID | Multiaddr | Multiaddr[], options?: AbortOptions): Promise<void> {
39
39
  await Promise.all(
40
40
  this.blockBrokers
41
41
  .map(broker => broker.addPeer(peer, options))