diff --git a/packages/helia/package.json b/packages/helia/package.json index e7b4e67d4..e15fb2dd2 100644 --- a/packages/helia/package.json +++ b/packages/helia/package.json @@ -51,7 +51,7 @@ "@chainsafe/libp2p-noise": "^17.0.0", "@chainsafe/libp2p-yamux": "^8.0.0", "@helia/block-brokers": "^5.0.7", - "@helia/delegated-routing-v1-http-api-client": "^5.0.0", + "@helia/delegated-routing-v1-http-api-client": "^5.1.2", "@helia/interface": "^6.0.2", "@helia/routers": "^4.0.3", "@helia/utils": "^2.2.3", diff --git a/packages/http/package.json b/packages/http/package.json index 1d02a6a34..1ccc363dd 100644 --- a/packages/http/package.json +++ b/packages/http/package.json @@ -48,7 +48,7 @@ }, "dependencies": { "@helia/block-brokers": "^5.0.7", - "@helia/delegated-routing-v1-http-api-client": "^5.0.0", + "@helia/delegated-routing-v1-http-api-client": "^5.1.2", "@helia/interface": "^6.0.2", "@helia/routers": "^4.0.3", "@helia/utils": "^2.2.3", diff --git a/packages/routers/package.json b/packages/routers/package.json index b45f4d26d..c21cee335 100644 --- a/packages/routers/package.json +++ b/packages/routers/package.json @@ -47,9 +47,10 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@helia/delegated-routing-v1-http-api-client": "^5.0.0", + "@helia/delegated-routing-v1-http-api-client": "^5.1.2", "@helia/interface": "^6.0.2", "@libp2p/interface": "^3.1.0", + "@libp2p/logger": "^6.2.0", "@libp2p/peer-id": "^6.0.3", "@multiformats/uri-to-multiaddr": "^10.0.0", "ipns": "^10.1.2", diff --git a/packages/routers/src/delegated-http-routing.ts b/packages/routers/src/delegated-http-routing.ts index 3bfd824c6..e15a0f8e5 100644 --- a/packages/routers/src/delegated-http-routing.ts +++ b/packages/routers/src/delegated-http-routing.ts @@ -1,5 +1,6 @@ -import { createDelegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client' +import { delegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client' import { NotFoundError } from '@libp2p/interface' +import { defaultLogger } from '@libp2p/logger' import { marshalIPNSRecord, multihashFromIPNSRoutingKey, unmarshalIPNSRecord } from 'ipns' import first from 'it-first' import map from 'it-map' @@ -7,7 +8,7 @@ import { CID } from 'multiformats/cid' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { delegatedHTTPRoutingDefaults } from './utils/delegated-http-routing-defaults.js' -import type { DelegatedRoutingV1HttpApiClient, DelegatedRoutingV1HttpApiClientInit } from '@helia/delegated-routing-v1-http-api-client' +import type { DelegatedRoutingV1HttpApiClient, DelegatedRoutingV1HttpApiClientComponents, DelegatedRoutingV1HttpApiClientInit } from '@helia/delegated-routing-v1-http-api-client' import type { Provider, Routing, RoutingOptions } from '@helia/interface' import type { PeerId, PeerInfo } from '@libp2p/interface' import type { Version } from 'multiformats' @@ -21,8 +22,8 @@ function isIPNSKey (key: Uint8Array): boolean { class DelegatedHTTPRouter implements Routing { private readonly client: DelegatedRoutingV1HttpApiClient - constructor (url: URL, init: DelegatedRoutingV1HttpApiClientInit = {}) { - this.client = createDelegatedRoutingV1HttpApiClient(url, init) + constructor (components: DelegatedRoutingV1HttpApiClientComponents, init: DelegatedRoutingV1HttpApiClientInit & { url: string | URL }) { + this.client = delegatedRoutingV1HttpApiClient(init)(components) } async provide (cid: CID, options?: RoutingOptions): Promise { @@ -100,7 +101,24 @@ class DelegatedHTTPRouter implements Routing { /** * Creates a Helia Router that connects to an endpoint that supports the [Delegated Routing V1 HTTP API](https://specs.ipfs.tech/routing/http-routing-v1/) spec. */ -export function delegatedHTTPRouting (url: string | URL, init?: DelegatedRoutingV1HttpApiClientInit): Routing { - const config = init ?? delegatedHTTPRoutingDefaults() - return new DelegatedHTTPRouter(new URL(url), config) +export function delegatedHTTPRouting (init: DelegatedRoutingV1HttpApiClientInit & { url: string | URL }): (components: any) => Routing +/** + * @deprecated Use `delegatedHTTPRouting(init)` instead + */ +export function delegatedHTTPRouting (url: string | URL, init?: DelegatedRoutingV1HttpApiClientInit): Routing +export function delegatedHTTPRouting (url: string | URL | (DelegatedRoutingV1HttpApiClientInit & { url: string | URL }), init?: DelegatedRoutingV1HttpApiClientInit): Routing | ((components: any) => Routing) { + if (typeof url === 'string' || url instanceof URL) { + return new DelegatedHTTPRouter({ + logger: defaultLogger() + }, { + ...delegatedHTTPRoutingDefaults(), + ...init, + url: new URL(url) + }) + } + + return (components: any) => new DelegatedHTTPRouter(components, { + ...delegatedHTTPRoutingDefaults(), + ...url + }) } diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 052cc133e..1f56db42c 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -21,7 +21,7 @@ import type { BlockStorageInit } from './storage.js' import type { Await, CodecLoader, GCOptions, HasherLoader, Helia as HeliaInterface, HeliaEvents, Routing } from '@helia/interface' import type { BlockBroker } from '@helia/interface/blocks' import type { Pins } from '@helia/interface/pins' -import type { ComponentLogger, Libp2p, Logger, Metrics } from '@libp2p/interface' +import type { ComponentLogger, ContentRouting, Libp2p, Logger, Metrics, PeerRouting } from '@libp2p/interface' import type { KeychainInit } from '@libp2p/keychain' import type { DNS } from '@multiformats/dns' import type { Blockstore } from 'interface-blockstore' @@ -136,7 +136,7 @@ export interface HeliaInit { * Routers perform operations such as looking up content providers, * information about network peers or getting/putting records. */ - routers?: Array> + routers?: Array | ((components: any) => Partial)> /** * During provider lookups, peers can be returned from routing implementations @@ -232,20 +232,26 @@ export class Helia implements HeliaInterface { } this.routing = components.routing = new RoutingClass(components, { - routers: (init.routers ?? []).flatMap((router: any) => { + routers: (init.routers ?? []).flatMap((router: Partial | ((components: any) => Partial)) => { + if (typeof router === 'function') { + router = router(components) + } + // 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]) + const contentRouting = asContentRouting(router) + if (contentRouting != null) { + routers.push(contentRouting) } // if the router provides a libp2p-style PeerRouter - if (router[peerRoutingSymbol] != null) { - routers.push(router[peerRoutingSymbol]) + const peerRouting = asPeerRouting(router) + if (peerRouting != null) { + routers.push(peerRouting) } return routers @@ -318,3 +324,11 @@ export class Helia implements HeliaInterface { this.log('gc finished') } } + +function asContentRouting (obj?: any): ContentRouting | undefined { + return obj?.[contentRoutingSymbol] +} + +function asPeerRouting (obj?: any): PeerRouting | undefined { + return obj?.[peerRoutingSymbol] +}