Skip to content

Commit

Permalink
fix: remove libp2p from helia interface, add to helia module
Browse files Browse the repository at this point in the history
Removes all libp2p/bitswap deps from `@helia/interface` but retains
them in `helia`.

Adds a general `Routing` interface to `@helia/interface` that can
be used to resolve IPNS names amoung other things.

This means `@helia/http` can be libp2p-free.
  • Loading branch information
achingbrain committed Jan 15, 2024
1 parent bbdda97 commit 26f4327
Show file tree
Hide file tree
Showing 46 changed files with 644 additions and 529 deletions.
79 changes: 0 additions & 79 deletions packages/core/.aegir.js

This file was deleted.

13 changes: 3 additions & 10 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
"@ipld/dag-json": "^10.1.5",
"@ipld/dag-pb": "^4.0.6",
"@libp2p/interface": "^1.1.1",
"@libp2p/logger": "^4.0.4",
"@libp2p/peer-collections": "^5.1.4",
"@libp2p/utils": "^5.2.0",
"any-signal": "^4.1.1",
"cborg": "^4.0.3",
Expand All @@ -67,28 +69,19 @@
"it-drain": "^3.0.5",
"it-filter": "^3.0.4",
"it-foreach": "^2.0.6",
"it-merge": "^3.0.3",
"mortice": "^3.0.1",
"multiformats": "^13.0.0",
"progress-events": "^1.0.0",
"uint8arrays": "^5.0.1"
},
"devDependencies": {
"@chainsafe/libp2p-noise": "^14.1.0",
"@chainsafe/libp2p-yamux": "^6.0.1",
"@helia/block-brokers": "~0.0.0",
"@libp2p/circuit-relay-v2": "^1.0.10",
"@libp2p/identify": "^1.0.9",
"@libp2p/logger": "^4.0.4",
"@libp2p/websockets": "^8.0.10",
"@multiformats/mafmt": "^12.1.5",
"@multiformats/multiaddr": "^12.1.7",
"@types/sinon": "^17.0.2",
"aegir": "^42.1.0",
"blockstore-core": "^4.3.10",
"datastore-core": "^9.2.7",
"delay": "^6.0.0",
"it-all": "^3.0.4",
"libp2p": "^1.1.1",
"sinon": "^17.0.1",
"sinon-ts": "^2.0.0"
},
Expand Down
87 changes: 51 additions & 36 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,21 @@
* ```
*/

import { start, stop } from '@libp2p/interface'
import { contentRoutingSymbol, peerRoutingSymbol, start, stop } from '@libp2p/interface'
import { defaultLogger } from '@libp2p/logger'
import drain from 'it-drain'
import { CustomProgressEvent } from 'progress-events'
import { PinsImpl } from './pins.js'
import { Routing as RoutingClass } from './routing.js'
import { BlockStorage } from './storage.js'
import { defaultDagWalkers } from './utils/dag-walkers.js'
import { assertDatastoreVersionIsCurrent } from './utils/datastore-version.js'
import { defaultHashers } from './utils/default-hashers.js'
import { NetworkedStorage } from './utils/networked-storage.js'
import type { DAGWalker, GCOptions, Helia as HeliaInterface } from '@helia/interface'
import type { DAGWalker, GCOptions, Helia as HeliaInterface, Routing } from '@helia/interface'
import type { BlockBroker } from '@helia/interface/blocks'
import type { Pins } from '@helia/interface/pins'
import type { ComponentLogger, Libp2p, Logger } from '@libp2p/interface'
import type { ComponentLogger, Logger } from '@libp2p/interface'
import type { Blockstore } from 'interface-blockstore'
import type { Datastore } from 'interface-datastore'
import type { CID } from 'multiformats/cid'
Expand All @@ -38,18 +40,7 @@ import type { MultihashHasher } from 'multiformats/hashes/interface'
/**
* Options used to create a Helia node.
*/
export interface HeliaInit<T extends Libp2p = Libp2p> {
/**
* A libp2p node is required to perform network operations. Either a
* preconfigured node or options to configure a node can be passed
* here.
*
* If node options are passed, they will be merged with the default
* config for the current platform. In this case all passed config
* keys will replace those from the default config.
*/
libp2p: T

export interface HeliaInit {
/**
* The blockstore is where blocks are stored
*/
Expand Down Expand Up @@ -102,27 +93,38 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
* default implementation from libp2p will be used.
*/
logger?: ComponentLogger

/**
* Routers perform operations such as looking up content providers,
* information about network peers or getting/putting records.
*/
routers?: Array<Partial<Routing>>

/**
* Components used by subclasses
*/
components?: Record<string, any>
}

export class Helia implements HeliaInterface {
public libp2p: Libp2p
public blockstore: BlockStorage
public datastore: Datastore
public pins: Pins
public logger: ComponentLogger
public routing: Routing
private readonly log: Logger

constructor (init: HeliaInit) {
this.logger = init.libp2p.logger
this.logger = init.logger ?? defaultLogger()
this.log = this.logger.forComponent('helia')
const hashers = defaultHashers(init.hashers)

const components = {
blockstore: init.blockstore,
datastore: init.datastore,
libp2p: init.libp2p,
hashers,
logger: init.libp2p.logger
logger: this.logger,
...(init.components ?? {})
}

const blockBrokers = init.blockBrokers.map((fn) => {
Expand All @@ -136,22 +138,47 @@ export class Helia implements HeliaInterface {

this.pins = new PinsImpl(init.datastore, networkedStorage, defaultDagWalkers(init.dagWalkers))

this.libp2p = init.libp2p
this.blockstore = new BlockStorage(networkedStorage, this.pins, {
holdGcLock: init.holdGcLock
})
this.datastore = init.datastore
this.routing = new RoutingClass(components, {
routers: (init.routers ?? []).flatMap((router: any) => {
// if the router itself is a router
const routers = [
router
]

// if the router provides a libp2p-style ContentRouter
if (router[contentRoutingSymbol] != null) {
routers.push(router[contentRoutingSymbol])
}

// if the router provides a libp2p-style PeerRouter
if (router[peerRoutingSymbol] != null) {
routers.push(router[peerRoutingSymbol])
}

return routers
})
})
}

async start (): Promise<void> {
await assertDatastoreVersionIsCurrent(this.datastore)
await start(this.blockstore)
await this.libp2p.start()
await start(
this.blockstore,
this.datastore,
this.routing
)
}

async stop (): Promise<void> {
await this.libp2p.stop()
await stop(this.blockstore)
await stop(
this.blockstore,
this.datastore,
this.routing
)
}

async gc (options: GCOptions = {}): Promise<void> {
Expand Down Expand Up @@ -186,15 +213,3 @@ export class Helia implements HeliaInterface {
this.log('gc finished')
}
}

export function isLibp2p (obj: any): obj is Libp2p {
if (obj == null) {
return false
}

// a non-exhaustive list of methods found on the libp2p object
const funcs = ['dial', 'dialProtocol', 'hangUp', 'handle', 'unhandle', 'getMultiaddrs', 'getProtocols']

// if these are all functions it's probably a libp2p object
return funcs.every(m => typeof obj[m] === 'function')
}
Loading

0 comments on commit 26f4327

Please sign in to comment.