import { CID } from "multiformats/basics.js" ; import { getName } from "multicodec" ; import { BlockService } from "./blockservice" ; import { Block } from "../utils" ; /**
 * AddOptions represents the set of default parameters to use when adding an IPLD Node via the DAG service.
 */ export interface AddOptions { /**
     * hashAlg is the hashing algorithm that is used to calculate the CID. The default comes from the given codec.
     */ hashAlg ? : string ; /**
     * onlyHash controls whether or not the serialized form of the IPLD Node will be passed to the underlying block store.
     */ onlyHash ? : boolean ; /**
     * cidVersion specifies which version of CID to use. This option is currently ignored (and defaults to v1).
     */ cidVersion ? : number ; } /**
 * DAGOptions represents the set of parameters to use when initializing a DAG service.
 */ export interface DAGOptions extends AddOptions { /**
     * The underlying block service for adding, deleting, and retrieving blocks. It is required.
     */ blockService : BlockService ; } /**
 * ResolveResult represents an IPLD Node that was traversed during path resolving.
 */ export interface ResolveResult { /**
     * remainderPath is the part of the path that wasn’t resolved yet.
     */ remainderPath ? : string ; remainder ? : string ; /**
     * value is what the resolved path points to. If further traversing is possible, then `value` is a CID object
     * linking to another IPLD node. If it was possible to fully resolve the path, `value` is the value the path points
     * to. So if you need the CID of the IPLD node you’re currently at, just take the `value` of the previously returned
     * IPLD node.
     */ value : CID | never ; } /**
 * DAGService is a content-addressable store for adding, removing, and getting Merkle directed acyclic graphs (DAGs).
 * A DAG service provides an API for creating and resolving IPLD nodes, making it possible for apps and services to
 * integrate with the IPFS IPLD Merkle-forest.
 *
 * It satisfies the default IPLD interface: https://github.com/ipld/js-ipld.
 */ export class DAGService { /**
     * A set of default parameters to use when adding an IPLD Node via the DAG service.
     */ public defaultOptions : AddOptions ; /**
     * The underlying block service for adding, deleting, and retrieving blocks.
     */ public blockService : BlockService ; param { DAGOptions } options constructor ( options ) { const { blockService , ... opts } = options ; this . blockService = blockService ; this . defaultOptions = opts ; } param { CID } cid param { string } path async * resolve ( cid , path ) { const data = await this . blockService . get ( cid ) ; const block = Block . create ( data . data , data . cid ) ; const reader = block . reader ( ) ; const node = reader . get ( path ) ; yield { value : node . value , remainderPath : node . remainderPath || node . remaining || "" , } ; if ( CID . asCID ( node . value ) ) { for await ( const res of this . resolve ( node . value , node . remainderPath || node . remaining || "" ) ) { yield res ; } } } param { CID } cid param { string } offsetPath param { object } options async * tree ( cid , offsetPath = "" , options = { recursive : false } ) { const data = await this . blockService . get ( cid ) ; const block = Block . create ( data . data , data . cid ) ; const reader = block . reader ( ) ; for await ( let path of reader . tree ( ) ) { if ( path . startsWith ( offsetPath ) && path . length > offsetPath . length ) { if ( offsetPath . length > 0 ) { path = path . slice ( offsetPath . length + 1 ) ; } yield path ; } } if ( options . recursive ) { for await ( const [ path , sub ] of reader . links ( ) ) { for await ( const subPath of this . tree ( sub , undefined , options ) ) { let fullPath = `${ path }/${ subPath }` ; if ( fullPath . startsWith ( offsetPath ) && fullPath . length > offsetPath . length ) { if ( offsetPath . length > 0 ) { fullPath = fullPath . slice ( offsetPath . length + 1 ) ; } yield fullPath ; } } } } } param { CID } cid async get ( cid ) { const data = await this . blockService . get ( cid ) ; const wrap = CID . asCID ( data . cid ) ; const block = Block . create ( data . data , wrap ) ; return block . decode ( ) ; } param { Iterable < CID > } cids async * getMany ( cids ) { for await ( const cid of cids ) { yield this . get ( cid ) ; } } param { any } node param { string | number } codec param { AddOptions } options async put ( node , codec = "dag-cbor" , options ? ) { const opts = options || this . defaultOptions || { } ; if ( typeof codec === "number" ) { codec = getName ( codec ) ; } const block = Block . encoder ( node , codec , opts . hashAlg ) ; const data = block . encode ( ) ; let cid = await block . cid ( ) ; if ( opts . cidVersion === 0 ) { cid = cid . toV0 ( ) ; } if ( ! opts . onlyHash ) { await this . blockService . put ( { data , cid } ) ; } return cid ; } param { Iterable < any > } nodes param { string | number } codec param { AddOptions } options async * putMany ( nodes , codec = "dag-cbor" , options ? ) { const opts = options || this . defaultOptions || { } ; if ( typeof codec === "number" ) { codec = getName ( codec ) ; } for await ( const node of nodes ) { yield this . put ( node , codec , opts ) ; } } param { CID } cid async remove ( cid ) { const wrap = CID . asCID ( cid ) ; return this . blockService . delete ( wrap ) ; } param { Iterable < CID > } cids async * removeMany ( cids ) { for await ( const cid of cids ) { yield this . remove ( cid ) ; } } }