diff --git a/packages/helia/src/storage.ts b/packages/helia/src/storage.ts index 527f9849c..ffda475f2 100644 --- a/packages/helia/src/storage.ts +++ b/packages/helia/src/storage.ts @@ -1,6 +1,6 @@ import filter from 'it-filter' import type { Blockstore } from 'interface-blockstore' -import type { Blocks, Pair, DeleteManyBlocksProgressEvents, DeleteBlockProgressEvents, GetBlockProgressEvents, GetManyBlocksProgressEvents, PutManyBlocksProgressEvents, PutBlockProgressEvents } from '@helia/interface/blocks' +import type { Blocks, Pair, DeleteManyBlocksProgressEvents, DeleteBlockProgressEvents, GetBlockProgressEvents, GetManyBlocksProgressEvents, PutManyBlocksProgressEvents, PutBlockProgressEvents, GetAllBlocksProgressEvents } from '@helia/interface/blocks' import type { Bitswap } from 'ipfs-bitswap' import type { CID } from 'multiformats/cid' import type { AbortOptions } from '@libp2p/interfaces' @@ -196,4 +196,15 @@ export class BlockStorage implements Blocks { releaseLock() } } + + async * getAll (options: AbortOptions & ProgressOptions = {}): AsyncIterable { + const releaseLock = await this.lock.readLock() + + try { + options.onProgress?.(new CustomProgressEvent('blocks:get-all:blockstore:get-many')) + yield * this.child.getAll(options) + } finally { + releaseLock() + } + } } diff --git a/packages/helia/test/fixtures/create-block.ts b/packages/helia/test/fixtures/create-block.ts index ec2e20348..417696490 100644 --- a/packages/helia/test/fixtures/create-block.ts +++ b/packages/helia/test/fixtures/create-block.ts @@ -1,4 +1,4 @@ -import type { Blocks } from '@helia/interface/blocks' +import type { Blockstore } from 'interface-blockstore' import { CID } from 'multiformats/cid' import { sha256 } from 'multiformats/hashes/sha2' @@ -9,7 +9,7 @@ export async function createBlock (codec: Codec, block: U return { cid, block } } -export async function createAndPutBlock (codec: Codec, block: Uint8Array, blockstore: Blocks): Promise> { +export async function createAndPutBlock (codec: Codec, block: Uint8Array, blockstore: Blockstore): Promise> { const result = await createBlock(codec, block) await blockstore.put(result.cid, block) diff --git a/packages/helia/test/fixtures/create-dag.ts b/packages/helia/test/fixtures/create-dag.ts index 132002a52..16a8cd79f 100644 --- a/packages/helia/test/fixtures/create-dag.ts +++ b/packages/helia/test/fixtures/create-dag.ts @@ -1,4 +1,4 @@ -import type { Blocks } from '@helia/interface/blocks' +import type { Blockstore } from 'interface-blockstore' import type { CID } from 'multiformats/cid' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' import { createAndPutBlock } from './create-block.js' @@ -58,7 +58,7 @@ export interface DAGNode { * } * ``` */ -export async function createDag (codec: number, blocks: Blocks, depth: number, children: number): Promise> { +export async function createDag (codec: number, blocks: Blockstore, depth: number, children: number): Promise> { const dag: Record = {} const root = await createAndPutBlock(codec, uint8arrayFromString('level-0'), blocks) @@ -67,7 +67,7 @@ export async function createDag (codec: number, blocks: Blocks, depth: number, c return dag } -async function addChildren (cid: CID, name: string, level: number, index: number, depth: number, children: number, dag: Record, codec: number, blocks: Blocks): Promise { +async function addChildren (cid: CID, name: string, level: number, index: number, depth: number, children: number, dag: Record, codec: number, blocks: Blockstore): Promise { if (depth === 0) { return } diff --git a/packages/interface/src/blocks.ts b/packages/interface/src/blocks.ts index c2da33312..d2abdba44 100644 --- a/packages/interface/src/blocks.ts +++ b/packages/interface/src/blocks.ts @@ -33,6 +33,9 @@ export type GetManyBlocksProgressEvents = ProgressEvent<'blocks:get-many:blockstore:put', CID> | BitswapWantProgressEvents +export type GetAllBlocksProgressEvents = + ProgressEvent<'blocks:get-all:blockstore:get-many'> + export type DeleteBlockProgressEvents = ProgressEvent<'blocks:delete:blockstore:delete', CID> @@ -40,63 +43,39 @@ export type DeleteManyBlocksProgressEvents = ProgressEvent<'blocks:delete-many:blockstore:delete-many'> export interface Blocks { - /** - * Store the passed block under the passed CID - * - * @example - * - * ```js - * await store.put([{ key: new Key('awesome'), value: new Uint8Array([0, 1, 2, 3]) }]) - * ``` - */ - put: (key: CID, val: Uint8Array, options?: AbortOptions & ProgressOptions) => Promise - - /** - * Retrieve the value stored under the given key - * - * @example - * ```js - * const value = await store.get(new Key('awesome')) - * console.log('got content: %s', value.toString('utf8')) - * // => got content: datastore - * ``` - */ - get: (key: CID, options?: AbortOptions & ProgressOptions) => Promise - /** * Check for the existence of a value for the passed key * * @example * ```js - *const exists = await store.has(new Key('awesome')) + * const exists = await store.has(CID('bafyfoo')) * - *if (exists) { - * console.log('it is there') - *} else { - * console.log('it is not there') - *} + * if (exists) { + * console.log('it is there') + * } else { + * console.log('it is not there') + * } *``` */ has: (key: CID, options?: AbortOptions) => Promise /** - * Remove the record for the passed key + * Store the passed block under the passed CID * * @example * * ```js - * await store.delete(new Key('awesome')) - * console.log('deleted awesome content :(') + * await store.put(CID('bafyfoo'), new Uint8Array([0, 1, 2, 3])) * ``` */ - delete: (key: CID, options?: AbortOptions & ProgressOptions) => Promise + put: (key: CID, val: Uint8Array, options?: AbortOptions & ProgressOptions) => Promise /** * Store the given key/value pairs * * @example * ```js - * const source = [{ key: new Key('awesome'), value: new Uint8Array([0, 1, 2, 3]) }] + * const source = [{ cid: CID('bafyfoo'), block: new Uint8Array([0, 1, 2, 3]) }] * * for await (const { key, value } of store.putMany(source)) { * console.info(`put content for key ${key}`) @@ -108,12 +87,24 @@ export interface Blocks { options?: AbortOptions & ProgressOptions ) => AsyncIterable + /** + * Retrieve the value stored under the given key + * + * @example + * ```js + * const value = await store.get(CID('bafyfoo')) + * console.log('got content: %s', value.toString('utf8')) + * // => got content: datastore + * ``` + */ + get: (key: CID, options?: AbortOptions & ProgressOptions) => Promise + /** * Retrieve values for the passed keys * * @example * ```js - * for await (const value of store.getMany([new Key('awesome')])) { + * for await (const value of store.getMany([CID('bafyfoo')])) { * console.log('got content:', new TextDecoder('utf8').decode(value)) * // => got content: datastore * } @@ -124,13 +115,40 @@ export interface Blocks { options?: AbortOptions & ProgressOptions ) => AsyncIterable + /** + * Retrieve all blocks in the blockstore + * + * @example + * ```js + * for await (const value of store.getAll()) { + * console.log('got content:', new TextDecoder('utf8').decode(value)) + * // => got content: datastore + * } + * ``` + */ + getAll: ( + options?: AbortOptions & ProgressOptions + ) => AsyncIterable + + /** + * Remove the record for the passed key + * + * @example + * + * ```js + * await store.delete(CID('bafyfoo')) + * console.log('deleted awesome content :(') + * ``` + */ + delete: (key: CID, options?: AbortOptions & ProgressOptions) => Promise + /** * Remove values for the passed keys * * @example * * ```js - * const source = [new Key('awesome')] + * const source = [CID('bafyfoo')] * * for await (const key of store.deleteMany(source)) { * console.log(`deleted content with key ${key}`)