helia 1.2.0 → 1.2.2

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.
@@ -0,0 +1,146 @@
1
+ import filter from 'it-filter'
2
+ import forEach from 'it-foreach'
3
+ import { CustomProgressEvent, type ProgressOptions } from 'progress-events'
4
+ import type { Blocks, Pair, DeleteManyBlocksProgressEvents, DeleteBlockProgressEvents, GetBlockProgressEvents, GetManyBlocksProgressEvents, PutManyBlocksProgressEvents, PutBlockProgressEvents, GetAllBlocksProgressEvents } from '@helia/interface/blocks'
5
+ import type { AbortOptions } from '@libp2p/interfaces'
6
+ import type { Blockstore } from 'interface-blockstore'
7
+ import type { AwaitIterable } from 'interface-store'
8
+ import type { Bitswap } from 'ipfs-bitswap'
9
+ import type { CID } from 'multiformats/cid'
10
+
11
+ export interface BlockStorageInit {
12
+ holdGcLock?: boolean
13
+ bitswap?: Bitswap
14
+ }
15
+
16
+ export interface GetOptions extends AbortOptions {
17
+ progress?: (evt: Event) => void
18
+ }
19
+
20
+ /**
21
+ * Networked storage wraps a regular blockstore - when getting blocks if the
22
+ * blocks are not present Bitswap will be used to fetch them from network peers.
23
+ */
24
+ export class NetworkedStorage implements Blocks {
25
+ private readonly child: Blockstore
26
+ private readonly bitswap?: Bitswap
27
+
28
+ /**
29
+ * Create a new BlockStorage
30
+ */
31
+ constructor (blockstore: Blockstore, options: BlockStorageInit = {}) {
32
+ this.child = blockstore
33
+ this.bitswap = options.bitswap
34
+ }
35
+
36
+ unwrap (): Blockstore {
37
+ return this.child
38
+ }
39
+
40
+ /**
41
+ * Put a block to the underlying datastore
42
+ */
43
+ async put (cid: CID, block: Uint8Array, options: AbortOptions & ProgressOptions<PutBlockProgressEvents> = {}): Promise<CID> {
44
+ if (await this.child.has(cid)) {
45
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:put:duplicate', cid))
46
+ return cid
47
+ }
48
+
49
+ if (this.bitswap?.isStarted() === true) {
50
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:put:bitswap:notify', cid))
51
+ this.bitswap.notify(cid, block, options)
52
+ }
53
+
54
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:put:blockstore:put', cid))
55
+
56
+ return this.child.put(cid, block, options)
57
+ }
58
+
59
+ /**
60
+ * Put a multiple blocks to the underlying datastore
61
+ */
62
+ async * putMany (blocks: AwaitIterable<{ cid: CID, block: Uint8Array }>, options: AbortOptions & ProgressOptions<PutManyBlocksProgressEvents> = {}): AsyncIterable<CID> {
63
+ const missingBlocks = filter(blocks, async ({ cid }): Promise<boolean> => {
64
+ const has = await this.child.has(cid)
65
+
66
+ if (has) {
67
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:put-many:duplicate', cid))
68
+ }
69
+
70
+ return !has
71
+ })
72
+
73
+ const notifyEach = forEach(missingBlocks, ({ cid, block }): void => {
74
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:put-many:bitswap:notify', cid))
75
+ this.bitswap?.notify(cid, block, options)
76
+ })
77
+
78
+ options.onProgress?.(new CustomProgressEvent('blocks:put-many:blockstore:put-many'))
79
+ yield * this.child.putMany(notifyEach, options)
80
+ }
81
+
82
+ /**
83
+ * Get a block by cid
84
+ */
85
+ async get (cid: CID, options: AbortOptions & ProgressOptions<GetBlockProgressEvents> = {}): Promise<Uint8Array> {
86
+ if (this.bitswap?.isStarted() != null && !(await this.child.has(cid))) {
87
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:get:bitswap:get', cid))
88
+ const block = await this.bitswap.want(cid, options)
89
+
90
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:get:blockstore:put', cid))
91
+ await this.child.put(cid, block, options)
92
+
93
+ return block
94
+ }
95
+
96
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:get:blockstore:get', cid))
97
+
98
+ return this.child.get(cid, options)
99
+ }
100
+
101
+ /**
102
+ * Get multiple blocks back from an (async) iterable of cids
103
+ */
104
+ async * getMany (cids: AwaitIterable<CID>, options: AbortOptions & ProgressOptions<GetManyBlocksProgressEvents> = {}): AsyncIterable<Pair> {
105
+ options.onProgress?.(new CustomProgressEvent('blocks:get-many:blockstore:get-many'))
106
+
107
+ yield * this.child.getMany(forEach(cids, async (cid): Promise<void> => {
108
+ if (this.bitswap?.isStarted() === true && !(await this.child.has(cid))) {
109
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:get-many:bitswap:get', cid))
110
+ const block = await this.bitswap.want(cid, options)
111
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:get-many:blockstore:put', cid))
112
+ await this.child.put(cid, block, options)
113
+ }
114
+ }))
115
+ }
116
+
117
+ /**
118
+ * Delete a block from the blockstore
119
+ */
120
+ async delete (cid: CID, options: AbortOptions & ProgressOptions<DeleteBlockProgressEvents> = {}): Promise<void> {
121
+ options.onProgress?.(new CustomProgressEvent<CID>('blocks:delete:blockstore:delete', cid))
122
+
123
+ await this.child.delete(cid, options)
124
+ }
125
+
126
+ /**
127
+ * Delete multiple blocks from the blockstore
128
+ */
129
+ async * deleteMany (cids: AwaitIterable<CID>, options: AbortOptions & ProgressOptions<DeleteManyBlocksProgressEvents> = {}): AsyncIterable<CID> {
130
+ options.onProgress?.(new CustomProgressEvent('blocks:delete-many:blockstore:delete-many'))
131
+ yield * this.child.deleteMany((async function * (): AsyncGenerator<CID> {
132
+ for await (const cid of cids) {
133
+ yield cid
134
+ }
135
+ }()), options)
136
+ }
137
+
138
+ async has (cid: CID, options: AbortOptions = {}): Promise<boolean> {
139
+ return this.child.has(cid, options)
140
+ }
141
+
142
+ async * getAll (options: AbortOptions & ProgressOptions<GetAllBlocksProgressEvents> = {}): AsyncIterable<Pair> {
143
+ options.onProgress?.(new CustomProgressEvent('blocks:get-all:blockstore:get-many'))
144
+ yield * this.child.getAll(options)
145
+ }
146
+ }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '1.2.0'
1
+ export const version = '1.2.2'
2
2
  export const name = 'helia'