@helia/utils 2.1.0 → 2.1.1-3eb6f3a7
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.
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +3 -3
- package/dist/src/abstract-session.d.ts.map +1 -1
- package/dist/src/abstract-session.js +3 -2
- package/dist/src/abstract-session.js.map +1 -1
- package/dist/src/errors.d.ts +5 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +7 -3
- package/dist/src/errors.js.map +1 -1
- package/dist/src/graph-walker.d.ts +4 -1
- package/dist/src/graph-walker.d.ts.map +1 -1
- package/dist/src/graph-walker.js +54 -72
- package/dist/src/graph-walker.js.map +1 -1
- package/dist/src/utils/datastore-version.js +2 -2
- package/dist/src/utils/datastore-version.js.map +1 -1
- package/dist/src/utils/networked-storage.d.ts.map +1 -1
- package/dist/src/utils/networked-storage.js +6 -0
- package/dist/src/utils/networked-storage.js.map +1 -1
- package/package.json +3 -3
- package/src/abstract-session.ts +3 -2
- package/src/errors.ts +8 -3
- package/src/graph-walker.ts +64 -84
- package/src/utils/datastore-version.ts +2 -2
- package/src/utils/networked-storage.ts +7 -0
- package/dist/typedoc-urls.json +0 -18
package/src/graph-walker.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Queue } from '@libp2p/utils'
|
|
2
|
+
import filter from 'it-filter'
|
|
2
3
|
import toBuffer from 'it-to-buffer'
|
|
3
4
|
import { createUnsafe } from 'multiformats/block'
|
|
4
5
|
import type { CodecLoader } from '@helia/interface'
|
|
@@ -22,7 +23,7 @@ export interface GraphNode <T = unknown, C extends number = number, A extends nu
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export interface GraphWalker {
|
|
25
|
-
walk <T = any> (cid: CID, options?:
|
|
26
|
+
walk <T = any> (cid: CID, options?: WalkOptions<T>): AsyncGenerator<GraphNode<T>>
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
export function depthFirstWalker (components: GraphWalkerComponents, init: GraphWalkerInit = {}): GraphWalker {
|
|
@@ -39,57 +40,56 @@ interface JobOptions extends AbortOptions {
|
|
|
39
40
|
path: CID[]
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
export interface WalkOptions<T> extends AbortOptions {
|
|
44
|
+
includeChild?(child: CID, parent: BlockView<T, number, number, 0 | 1>): boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
abstract class AbstractGraphWalker {
|
|
43
48
|
private readonly components: GraphWalkerComponents
|
|
44
49
|
|
|
45
|
-
constructor (components: GraphWalkerComponents, init: GraphWalkerInit
|
|
50
|
+
constructor (components: GraphWalkerComponents, init: GraphWalkerInit) {
|
|
46
51
|
this.components = components
|
|
47
52
|
}
|
|
48
53
|
|
|
49
|
-
async * walk <T = any> (cid: CID, options
|
|
50
|
-
const queue =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (a.options.depth === b.options.depth) {
|
|
54
|
-
return 0
|
|
55
|
-
}
|
|
54
|
+
async * walk <T = any> (cid: CID, options?: WalkOptions<T>): AsyncGenerator<GraphNode<T>> {
|
|
55
|
+
const queue = this.getQueue()
|
|
56
|
+
const gen = filter(queue.toGenerator(options), (node) => node != null) as AsyncGenerator<GraphNode<T>>
|
|
57
|
+
let finished = false
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return -1
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
const gen = queue.toGenerator()
|
|
66
|
-
|
|
67
|
-
const job = async (options: JobOptions): Promise<GraphNode<T>> => {
|
|
68
|
-
const cid = options.cid
|
|
69
|
-
const bytes = await toBuffer(this.components.blockstore.get(cid, options))
|
|
70
|
-
const block = createUnsafe({
|
|
59
|
+
const job = async (opts: JobOptions): Promise<GraphNode<T> | undefined> => {
|
|
60
|
+
const cid = opts.cid
|
|
61
|
+
const bytes = await toBuffer(this.components.blockstore.get(cid, opts))
|
|
62
|
+
const block = createUnsafe<T, number, number, 0 | 1>({
|
|
71
63
|
cid,
|
|
72
64
|
bytes,
|
|
73
65
|
codec: await this.components.getCodec(cid.code)
|
|
74
66
|
})
|
|
75
67
|
|
|
76
68
|
for (const [, linkedCid] of block.links()) {
|
|
69
|
+
if (options?.includeChild?.(linkedCid, block) === false) {
|
|
70
|
+
continue
|
|
71
|
+
}
|
|
72
|
+
|
|
77
73
|
queue.add(job, {
|
|
78
|
-
...
|
|
74
|
+
...opts,
|
|
79
75
|
cid: linkedCid,
|
|
80
|
-
depth:
|
|
81
|
-
path: [...
|
|
76
|
+
depth: opts.depth + 1,
|
|
77
|
+
path: [...opts.path, linkedCid]
|
|
82
78
|
})
|
|
79
|
+
// eslint-disable-next-line no-loop-func
|
|
83
80
|
.catch(err => {
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
// only throw if the generator is still yielding results, otherwise
|
|
82
|
+
// it can cause unhandled promise rejections
|
|
83
|
+
if (!finished) {
|
|
84
|
+
gen.throw(err)
|
|
85
|
+
}
|
|
86
86
|
})
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
return {
|
|
90
90
|
block,
|
|
91
|
-
depth:
|
|
92
|
-
path:
|
|
91
|
+
depth: opts.depth,
|
|
92
|
+
path: opts.path
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -100,23 +100,28 @@ class DepthFirstGraphWalker {
|
|
|
100
100
|
path: [cid]
|
|
101
101
|
})
|
|
102
102
|
.catch(err => {
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
// only throw if the generator is still yielding results, otherwise it
|
|
104
|
+
// can cause unhandled promise rejections
|
|
105
|
+
if (!finished) {
|
|
106
|
+
gen.throw(err)
|
|
107
|
+
}
|
|
105
108
|
})
|
|
106
109
|
|
|
107
|
-
|
|
110
|
+
try {
|
|
111
|
+
yield * gen
|
|
112
|
+
} finally {
|
|
113
|
+
finished = true
|
|
114
|
+
// abort any in-progress operations
|
|
115
|
+
queue.abort()
|
|
116
|
+
}
|
|
108
117
|
}
|
|
109
|
-
}
|
|
110
118
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
constructor (components: GraphWalkerComponents, init: GraphWalkerInit = {}) {
|
|
115
|
-
this.components = components
|
|
116
|
-
}
|
|
119
|
+
abstract getQueue <T> (): Queue<GraphNode<T> | undefined, JobOptions>
|
|
120
|
+
}
|
|
117
121
|
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
class DepthFirstGraphWalker extends AbstractGraphWalker {
|
|
123
|
+
getQueue<T>(): Queue<GraphNode<T> | undefined, JobOptions> {
|
|
124
|
+
return new Queue<GraphNode<T> | undefined, JobOptions>({
|
|
120
125
|
concurrency: 1,
|
|
121
126
|
sort: (a, b) => {
|
|
122
127
|
if (a.options.depth === b.options.depth) {
|
|
@@ -124,55 +129,30 @@ class BreadthFirstGraphWalker {
|
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
if (a.options.depth < b.options.depth) {
|
|
127
|
-
return
|
|
132
|
+
return 1
|
|
128
133
|
}
|
|
129
134
|
|
|
130
|
-
return 1
|
|
135
|
+
return -1
|
|
131
136
|
}
|
|
132
137
|
})
|
|
138
|
+
}
|
|
139
|
+
}
|
|
133
140
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
codec: await this.components.getCodec(cid.code)
|
|
143
|
-
})
|
|
141
|
+
class BreadthFirstGraphWalker extends AbstractGraphWalker {
|
|
142
|
+
getQueue<T>(): Queue<GraphNode<T> | undefined, JobOptions> {
|
|
143
|
+
return new Queue<GraphNode<T> | undefined, JobOptions>({
|
|
144
|
+
concurrency: 1,
|
|
145
|
+
sort: (a, b) => {
|
|
146
|
+
if (a.options.depth === b.options.depth) {
|
|
147
|
+
return 0
|
|
148
|
+
}
|
|
144
149
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
cid: linkedCid,
|
|
149
|
-
depth: options.depth + 1,
|
|
150
|
-
path: [...options.path, linkedCid]
|
|
151
|
-
})
|
|
152
|
-
.catch(err => {
|
|
153
|
-
gen.throw(err)
|
|
154
|
-
queue.abort()
|
|
155
|
-
})
|
|
156
|
-
}
|
|
150
|
+
if (a.options.depth < b.options.depth) {
|
|
151
|
+
return -1
|
|
152
|
+
}
|
|
157
153
|
|
|
158
|
-
|
|
159
|
-
block,
|
|
160
|
-
depth: options.depth,
|
|
161
|
-
path: options.path
|
|
154
|
+
return 1
|
|
162
155
|
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
queue.add(job, {
|
|
166
|
-
...options,
|
|
167
|
-
cid,
|
|
168
|
-
depth: 0,
|
|
169
|
-
path: [cid]
|
|
170
156
|
})
|
|
171
|
-
.catch(err => {
|
|
172
|
-
gen.throw(err)
|
|
173
|
-
queue.abort()
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
yield * gen
|
|
177
157
|
}
|
|
178
158
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Key } from 'interface-datastore'
|
|
2
2
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
3
3
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
4
|
-
import {
|
|
4
|
+
import { InvalidDatastoreVersionError } from '../errors.js'
|
|
5
5
|
import type { Datastore } from 'interface-datastore'
|
|
6
6
|
|
|
7
7
|
const DS_VERSION_KEY = new Key('/version')
|
|
@@ -20,6 +20,6 @@ export async function assertDatastoreVersionIsCurrent (datastore: Datastore): Pr
|
|
|
20
20
|
|
|
21
21
|
if (version !== CURRENT_VERSION) {
|
|
22
22
|
// TODO: write migrations when we break compatibility - for an example, see https://github.com/ipfs/js-ipfs-repo/tree/master/packages/ipfs-repo-migrations
|
|
23
|
-
throw new
|
|
23
|
+
throw new InvalidDatastoreVersionError('Invalid datastore version, a datastore migration may be required')
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -5,6 +5,7 @@ import filter from 'it-filter'
|
|
|
5
5
|
import forEach from 'it-foreach'
|
|
6
6
|
import { CustomProgressEvent } from 'progress-events'
|
|
7
7
|
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
|
|
8
|
+
import { InvalidConfigurationError } from '../errors.ts'
|
|
8
9
|
import { isPromise } from './is-promise.js'
|
|
9
10
|
import type { HasherLoader } from '@helia/interface'
|
|
10
11
|
import type { BlockBroker, Blocks, Pair, DeleteManyBlocksProgressEvents, DeleteBlockProgressEvents, GetBlockProgressEvents, GetManyBlocksProgressEvents, PutManyBlocksProgressEvents, PutBlockProgressEvents, GetAllBlocksProgressEvents, GetOfflineOptions, BlockRetrievalOptions, CreateSessionOptions, SessionBlockstore } from '@helia/interface/blocks'
|
|
@@ -446,6 +447,10 @@ async function raceBlockRetrievers (cid: CID, blockBrokers: BlockBroker[], hashe
|
|
|
446
447
|
}
|
|
447
448
|
}
|
|
448
449
|
|
|
450
|
+
if (retrievers.length === 0) {
|
|
451
|
+
throw new InvalidConfigurationError(`No block brokers capable of retrieving blocks are configured, the CID ${cid} cannot be fetched from the network`)
|
|
452
|
+
}
|
|
453
|
+
|
|
449
454
|
try {
|
|
450
455
|
return await Promise.any(
|
|
451
456
|
retrievers
|
|
@@ -457,6 +462,7 @@ async function raceBlockRetrievers (cid: CID, blockBrokers: BlockBroker[], hashe
|
|
|
457
462
|
signal,
|
|
458
463
|
validateFn: async (block: Uint8Array): Promise<void> => {
|
|
459
464
|
await validateFn(block)
|
|
465
|
+
options.signal?.throwIfAborted()
|
|
460
466
|
blocksWereValidated = true
|
|
461
467
|
}
|
|
462
468
|
})
|
|
@@ -465,6 +471,7 @@ async function raceBlockRetrievers (cid: CID, blockBrokers: BlockBroker[], hashe
|
|
|
465
471
|
// the blockBroker either did not throw an error when attempting to validate the block
|
|
466
472
|
// or did not call the validateFn at all. We should validate the block ourselves
|
|
467
473
|
await validateFn(block)
|
|
474
|
+
options.signal?.throwIfAborted()
|
|
468
475
|
}
|
|
469
476
|
|
|
470
477
|
return block
|
package/dist/typedoc-urls.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"AbstractSession": "https://ipfs.github.io/helia/classes/_helia_utils.AbstractSession.html",
|
|
3
|
-
"Helia": "https://ipfs.github.io/helia/classes/_helia_utils.Helia.html",
|
|
4
|
-
".:Helia": "https://ipfs.github.io/helia/classes/_helia_utils.Helia.html",
|
|
5
|
-
"AbstractCreateSessionOptions": "https://ipfs.github.io/helia/interfaces/_helia_utils.AbstractCreateSessionOptions.html",
|
|
6
|
-
"AbstractSessionComponents": "https://ipfs.github.io/helia/interfaces/_helia_utils.AbstractSessionComponents.html",
|
|
7
|
-
"BlockStorage": "https://ipfs.github.io/helia/interfaces/_helia_utils.BlockStorage.html",
|
|
8
|
-
"BlockStorageInit": "https://ipfs.github.io/helia/interfaces/_helia_utils.BlockStorageInit.html",
|
|
9
|
-
"BlockstoreSessionEvents": "https://ipfs.github.io/helia/interfaces/_helia_utils.BlockstoreSessionEvents.html",
|
|
10
|
-
"GraphNode": "https://ipfs.github.io/helia/interfaces/_helia_utils.GraphNode.html",
|
|
11
|
-
"GraphWalker": "https://ipfs.github.io/helia/interfaces/_helia_utils.GraphWalker.html",
|
|
12
|
-
"GraphWalkerComponents": "https://ipfs.github.io/helia/interfaces/_helia_utils.GraphWalkerComponents.html",
|
|
13
|
-
"GraphWalkerInit": "https://ipfs.github.io/helia/interfaces/_helia_utils.GraphWalkerInit.html",
|
|
14
|
-
"HeliaInit": "https://ipfs.github.io/helia/interfaces/_helia_utils.HeliaInit.html",
|
|
15
|
-
".:HeliaInit": "https://ipfs.github.io/helia/interfaces/helia.HeliaInit.html",
|
|
16
|
-
"breadthFirstWalker": "https://ipfs.github.io/helia/functions/_helia_utils.breadthFirstWalker.html",
|
|
17
|
-
"depthFirstWalker": "https://ipfs.github.io/helia/functions/_helia_utils.depthFirstWalker.html"
|
|
18
|
-
}
|