@helia/verified-fetch 2.6.17 → 2.6.19

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.
Files changed (47) hide show
  1. package/dist/index.min.js +49 -49
  2. package/dist/index.min.js.map +4 -4
  3. package/dist/src/index.d.ts +5 -5
  4. package/dist/src/index.js +5 -5
  5. package/dist/src/plugins/plugin-handle-dag-pb.d.ts.map +1 -1
  6. package/dist/src/plugins/plugin-handle-dag-pb.js +7 -2
  7. package/dist/src/plugins/plugin-handle-dag-pb.js.map +1 -1
  8. package/dist/src/plugins/plugin-handle-dag-walk.d.ts.map +1 -1
  9. package/dist/src/plugins/plugin-handle-dag-walk.js +2 -2
  10. package/dist/src/plugins/plugin-handle-dag-walk.js.map +1 -1
  11. package/dist/src/types.d.ts +1 -1
  12. package/dist/src/types.d.ts.map +1 -1
  13. package/dist/src/utils/byte-range-context.d.ts.map +1 -1
  14. package/dist/src/utils/dir-index-html.d.ts.map +1 -1
  15. package/dist/src/utils/get-stream-from-async-iterable.js +1 -1
  16. package/dist/src/utils/get-stream-from-async-iterable.js.map +1 -1
  17. package/dist/src/utils/parse-url-string.d.ts +2 -2
  18. package/dist/src/utils/parse-url-string.d.ts.map +1 -1
  19. package/dist/src/utils/parse-url-string.js +17 -9
  20. package/dist/src/utils/parse-url-string.js.map +1 -1
  21. package/dist/src/utils/responses.d.ts +4 -4
  22. package/dist/src/utils/responses.d.ts.map +1 -1
  23. package/dist/src/utils/responses.js +3 -3
  24. package/dist/src/utils/tlru.d.ts.map +1 -1
  25. package/dist/src/utils/tlru.js +7 -13
  26. package/dist/src/utils/tlru.js.map +1 -1
  27. package/dist/src/utils/walk-path.d.ts.map +1 -1
  28. package/dist/src/utils/walk-path.js +4 -1
  29. package/dist/src/utils/walk-path.js.map +1 -1
  30. package/dist/src/verified-fetch.d.ts.map +1 -1
  31. package/dist/src/verified-fetch.js +12 -7
  32. package/dist/src/verified-fetch.js.map +1 -1
  33. package/dist/typedoc-urls.json +5 -3
  34. package/package.json +14 -22
  35. package/src/index.ts +5 -5
  36. package/src/plugins/plugin-handle-dag-pb.ts +7 -2
  37. package/src/plugins/plugin-handle-dag-walk.ts +3 -2
  38. package/src/types.ts +1 -1
  39. package/src/utils/dir-index-html.ts +2 -2
  40. package/src/utils/get-stream-from-async-iterable.ts +1 -1
  41. package/src/utils/libp2p-defaults.browser.ts +1 -1
  42. package/src/utils/libp2p-defaults.ts +1 -1
  43. package/src/utils/parse-url-string.ts +15 -9
  44. package/src/utils/responses.ts +4 -4
  45. package/src/utils/tlru.ts +8 -18
  46. package/src/utils/walk-path.ts +5 -1
  47. package/src/verified-fetch.ts +13 -8
@@ -1,4 +1,6 @@
1
1
  {
2
+ "start": "https://ipfs.github.io/helia-verified-fetch/functions/index.verifiedFetch.start.html",
3
+ "stop": "https://ipfs.github.io/helia-verified-fetch/functions/index.verifiedFetch.stop.html",
2
4
  "BasePlugin": "https://ipfs.github.io/helia-verified-fetch/classes/index.BasePlugin.html",
3
5
  "DirIndexHtmlPlugin": "https://ipfs.github.io/helia-verified-fetch/classes/index.DirIndexHtmlPlugin.html",
4
6
  "PluginError": "https://ipfs.github.io/helia-verified-fetch/classes/index.PluginError.html",
@@ -27,8 +29,8 @@
27
29
  ".:Resource": "https://ipfs.github.io/helia-verified-fetch/types/index.Resource.html",
28
30
  "VerifiedFetchProgressEvents": "https://ipfs.github.io/helia-verified-fetch/types/index.VerifiedFetchProgressEvents.html",
29
31
  ".:VerifiedFetchProgressEvents": "https://ipfs.github.io/helia-verified-fetch/types/index.VerifiedFetchProgressEvents.html",
32
+ "dirIndexHtmlPluginFactory": "https://ipfs.github.io/helia-verified-fetch/variables/index.dirIndexHtmlPluginFactory.html",
33
+ "verifiedFetch": "https://ipfs.github.io/helia-verified-fetch/variables/index.verifiedFetch.html",
30
34
  "createVerifiedFetch": "https://ipfs.github.io/helia-verified-fetch/functions/index.createVerifiedFetch.html",
31
- ".:createVerifiedFetch": "https://ipfs.github.io/helia-verified-fetch/functions/index.createVerifiedFetch.html",
32
- "dirIndexHtmlPluginFactory": "https://ipfs.github.io/helia-verified-fetch/functions/index.dirIndexHtmlPluginFactory.html",
33
- "verifiedFetch": "https://ipfs.github.io/helia-verified-fetch/functions/index.verifiedFetch-1.html"
35
+ ".:createVerifiedFetch": "https://ipfs.github.io/helia-verified-fetch/functions/index.createVerifiedFetch.html"
34
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helia/verified-fetch",
3
- "version": "2.6.17",
3
+ "version": "2.6.19",
4
4
  "description": "A fetch-like API for obtaining verified & trustless IPFS content on the web",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/ipfs/helia-verified-fetch/tree/main/packages/verified-fetch#readme",
@@ -54,13 +54,6 @@
54
54
  "import": "./dist/src/plugins/plugins.js"
55
55
  }
56
56
  },
57
- "eslintConfig": {
58
- "extends": "ipfs",
59
- "parserOptions": {
60
- "project": true,
61
- "sourceType": "module"
62
- }
63
- },
64
57
  "release": {
65
58
  "branches": [
66
59
  "main"
@@ -180,17 +173,16 @@
180
173
  "@helia/unixfs": "^5.0.2",
181
174
  "@ipld/dag-cbor": "^9.2.3",
182
175
  "@ipld/dag-json": "^10.2.4",
183
- "@ipld/dag-pb": "^4.1.4",
184
- "@libp2p/interface": "^2.9.0",
185
- "@libp2p/kad-dht": "^15.0.2",
186
- "@libp2p/logger": "^5.1.15",
187
- "@libp2p/peer-id": "^5.1.2",
188
- "@libp2p/webrtc": "^5.2.12",
189
- "@libp2p/websockets": "^9.2.10",
176
+ "@ipld/dag-pb": "^4.1.5",
177
+ "@libp2p/interface": "^2.10.1",
178
+ "@libp2p/kad-dht": "^15.1.1",
179
+ "@libp2p/logger": "^5.1.17",
180
+ "@libp2p/peer-id": "^5.1.4",
181
+ "@libp2p/webrtc": "^5.2.14",
182
+ "@libp2p/websockets": "^9.2.12",
190
183
  "@multiformats/dns": "^1.0.6",
191
- "cborg": "^4.2.10",
184
+ "cborg": "^4.2.11",
192
185
  "file-type": "^20.5.0",
193
- "hashlru": "^2.3.0",
194
186
  "helia": "^5.4.1",
195
187
  "interface-blockstore": "^5.3.1",
196
188
  "interface-datastore": "^8.3.1",
@@ -200,10 +192,10 @@
200
192
  "it-pipe": "^3.0.1",
201
193
  "it-tar": "^6.0.5",
202
194
  "it-to-browser-readablestream": "^2.0.11",
203
- "libp2p": "^2.8.5",
204
- "lru-cache": "^11.1.0",
205
- "multiformats": "^13.3.3",
195
+ "libp2p": "^2.8.7",
196
+ "multiformats": "^13.3.6",
206
197
  "progress-events": "^1.0.1",
198
+ "quick-lru": "^7.0.1",
207
199
  "uint8arrays": "^5.1.0"
208
200
  },
209
201
  "devDependencies": {
@@ -212,9 +204,9 @@
212
204
  "@helia/http": "^2.1.1",
213
205
  "@helia/json": "^4.0.5",
214
206
  "@ipld/car": "^5.4.1",
215
- "@libp2p/crypto": "^5.1.1",
207
+ "@libp2p/crypto": "^5.1.3",
216
208
  "@types/sinon": "^17.0.4",
217
- "aegir": "^46.0.1",
209
+ "aegir": "^47.0.11",
218
210
  "blockstore-core": "^5.0.2",
219
211
  "browser-readablestream-to-it": "^2.0.9",
220
212
  "datastore-core": "^10.0.2",
package/src/index.ts CHANGED
@@ -591,8 +591,8 @@
591
591
  *
592
592
  * #### Unsupported response types
593
593
  *
594
- * * Returning IPLD nodes or DAGs as JS objects is not supported, as there is no currently well-defined structure for representing this data in an [HTTP Response](https://developer.mozilla.org/en-US/docs/Web/API/Response). Instead, users should request `aplication/vnd.ipld.car` or use the [`helia`](https://github.com/ipfs/helia) library directly for this use case.
595
- * * Others? Open an issue or PR!
594
+ * - Returning IPLD nodes or DAGs as JS objects is not supported, as there is no currently well-defined structure for representing this data in an [HTTP Response](https://developer.mozilla.org/en-US/docs/Web/API/Response). Instead, users should request `aplication/vnd.ipld.car` or use the [`helia`](https://github.com/ipfs/helia) library directly for this use case.
595
+ * - Others? Open an issue or PR!
596
596
  *
597
597
  * ### Response headers
598
598
  *
@@ -600,9 +600,9 @@
600
600
  *
601
601
  * Some known header specifications:
602
602
  *
603
- * * https://specs.ipfs.tech/http-gateways/path-gateway/#response-headers
604
- * * https://specs.ipfs.tech/http-gateways/trustless-gateway/#response-headers
605
- * * https://specs.ipfs.tech/http-gateways/subdomain-gateway/#response-headers
603
+ * - https://specs.ipfs.tech/http-gateways/path-gateway/#response-headers
604
+ * - https://specs.ipfs.tech/http-gateways/trustless-gateway/#response-headers
605
+ * - https://specs.ipfs.tech/http-gateways/subdomain-gateway/#response-headers
606
606
  *
607
607
  * #### Server Timing headers
608
608
  *
@@ -1,5 +1,6 @@
1
1
  import { unixfs } from '@helia/unixfs'
2
2
  import { code as dagPbCode } from '@ipld/dag-pb'
3
+ import { AbortError } from '@libp2p/interface'
3
4
  import { exporter } from 'ipfs-unixfs-exporter'
4
5
  import { CustomProgressEvent } from 'progress-events'
5
6
  import { getStreamFromAsyncIterable } from '../utils/get-stream-from-async-iterable.js'
@@ -98,8 +99,10 @@ export class DagPbPlugin extends BasePlugin {
98
99
  path = rootFilePath
99
100
  resolvedCID = entry.cid
100
101
  } catch (err: any) {
102
+ if (options?.signal?.aborted) {
103
+ throw new AbortError(options?.signal?.reason)
104
+ }
101
105
  this.log.error('error loading path %c/%s', dirCid, rootFilePath, err)
102
- options?.signal?.throwIfAborted()
103
106
  context.isDirectory = true
104
107
  context.directoryEntries = []
105
108
  context.modified++
@@ -161,7 +164,9 @@ export class DagPbPlugin extends BasePlugin {
161
164
 
162
165
  return response
163
166
  } catch (err: any) {
164
- options?.signal?.throwIfAborted()
167
+ if (options?.signal?.aborted) {
168
+ throw new AbortError(options?.signal?.reason)
169
+ }
165
170
  log.error('error streaming %c/%s', cid, path, err)
166
171
  if (byteRangeContext.isRangeRequest && err.code === 'ERR_INVALID_PARAMS') {
167
172
  return badRangeResponse(resource)
@@ -29,10 +29,10 @@ export class DagWalkPlugin extends BasePlugin {
29
29
  const { cid, resource, options, withServerTiming = false } = context
30
30
  const { getBlockstore, handleServerTiming } = this.pluginOptions
31
31
  const blockstore = getBlockstore(cid, resource, options?.session ?? true, options)
32
+
32
33
  // TODO: migrate handlePathWalking into this plugin
33
34
  const pathDetails = await handleServerTiming('path-walking', '', async () => handlePathWalking({ ...context, blockstore, log: this.log }), withServerTiming)
34
35
 
35
- context.modified++
36
36
  if (pathDetails instanceof Response) {
37
37
  this.log.trace('path walking failed')
38
38
 
@@ -42,10 +42,11 @@ export class DagWalkPlugin extends BasePlugin {
42
42
  return pathDetails
43
43
  }
44
44
 
45
- // some error walking the path
45
+ // some other error walking the path (codec doesn't support pathing, etc..), let the next plugin try to handle it
46
46
  return null
47
47
  }
48
48
 
49
+ context.modified++
49
50
  context.pathDetails = pathDetails
50
51
 
51
52
  return null
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export type RequestFormatShorthand = 'raw' | 'car' | 'tar' | 'ipns-record' | 'dag-json' | 'dag-cbor' | 'json' | 'cbor'
2
2
 
3
- export type SupportedBodyTypes = string | ArrayBuffer | Blob | ReadableStream<Uint8Array> | null
3
+ export type SupportedBodyTypes = string | Uint8Array | ArrayBuffer | Blob | ReadableStream<Uint8Array> | null
4
4
 
5
5
  /**
6
6
  * A ContentTypeParser attempts to return the mime type of a given file. It
@@ -4,8 +4,8 @@ import type { UnixFSEntry } from 'ipfs-unixfs-exporter'
4
4
  /**
5
5
  * Types taken from:
6
6
  *
7
- * * https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/assets/assets.go#L92C1-L96C2
8
- * * https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/assets/assets.go#L114C1-L135C2
7
+ * - https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/assets/assets.go#L92C1-L96C2
8
+ * - https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/assets/assets.go#L114C1-L135C2
9
9
  */
10
10
 
11
11
  interface GlobalData {
@@ -25,7 +25,7 @@ export async function getStreamFromAsyncIterable (iterator: AsyncIterable<Uint8A
25
25
  },
26
26
  async pull (controller) {
27
27
  const { value, done } = await reader.next()
28
- if (options?.signal?.aborted === true) {
28
+ if (options?.signal?.aborted) {
29
29
  controller.error(new AbortError(options.signal.reason ?? 'signal aborted by user'))
30
30
  controller.close()
31
31
  return
@@ -1,7 +1,7 @@
1
1
  import { webRTCDirect } from '@libp2p/webrtc'
2
2
  import { webSockets } from '@libp2p/websockets'
3
3
  import { libp2pDefaults } from 'helia'
4
- import type { ServiceFactoryMap } from './libp2p-types'
4
+ import type { ServiceFactoryMap } from './libp2p-types.js'
5
5
  import type { DefaultLibp2pServices } from 'helia'
6
6
  import type { Libp2pOptions } from 'libp2p'
7
7
 
@@ -2,7 +2,7 @@ import { kadDHT } from '@libp2p/kad-dht'
2
2
  import { libp2pDefaults } from 'helia'
3
3
  import { ipnsSelector } from 'ipns/selector'
4
4
  import { ipnsValidator } from 'ipns/validator'
5
- import type { ServiceFactoryMap } from './libp2p-types'
5
+ import type { ServiceFactoryMap } from './libp2p-types.js'
6
6
  import type { DefaultLibp2pServices } from 'helia'
7
7
  import type { Libp2pOptions } from 'libp2p'
8
8
 
@@ -1,3 +1,4 @@
1
+ import { AbortError } from '@libp2p/interface'
1
2
  import { CID } from 'multiformats/cid'
2
3
  import { getPeerIdFromString } from './get-peer-id-from-string.js'
3
4
  import { serverTiming } from './server-timing.js'
@@ -65,9 +66,9 @@ interface MatchUrlGroups {
65
66
 
66
67
  function matchUrlGroupsGuard (groups?: null | { [key in string]: string; } | MatchUrlGroups): groups is MatchUrlGroups {
67
68
  const protocol = groups?.protocol
68
- if (protocol == null) return false
69
+ if (protocol == null) { return false }
69
70
  const cidOrPeerIdOrDnsLink = groups?.cidOrPeerIdOrDnsLink
70
- if (cidOrPeerIdOrDnsLink == null) return false
71
+ if (cidOrPeerIdOrDnsLink == null) { return false }
71
72
  const path = groups?.path
72
73
  const queryString = groups?.queryString
73
74
 
@@ -132,8 +133,8 @@ function isInlinedDnsLink (label: string): boolean {
132
133
 
133
134
  /**
134
135
  * DNSLink label decoding
135
- * * Every standalone - is replaced with .
136
- * * Every remaining -- is replaced with -
136
+ * - Every standalone - is replaced with .
137
+ * - Every remaining -- is replaced with -
137
138
  *
138
139
  * @example en-wikipedia--on--ipfs-org.ipns.example.net -> example.net/ipns/en.wikipedia-on-ipfs.org
139
140
  */
@@ -145,8 +146,8 @@ function dnsLinkLabelDecoder (linkLabel: string): string {
145
146
  * A function that parses ipfs:// and ipns:// URLs, returning an object with easily recognizable properties.
146
147
  *
147
148
  * After determining the protocol successfully, we process the cidOrPeerIdOrDnsLink:
148
- * * If it's ipfs, it parses the CID or throws Error[]
149
- * * If it's ipns, it attempts to resolve the PeerId and then the DNSLink. If both fail, Error[] is thrown.
149
+ * - If it's ipfs, it parses the CID or throws Error[]
150
+ * - If it's ipns, it attempts to resolve the PeerId and then the DNSLink. If both fail, Error[] is thrown.
150
151
  *
151
152
  * @todo we need to break out each step of this function (cid parsing, ipns resolving, dnslink resolving) into separate functions and then remove the eslint-disable comment
152
153
  *
@@ -212,7 +213,9 @@ export async function parseUrlString ({ urlString, ipns, logger, withServerTimin
212
213
  resolvedPath = resolveResult?.path
213
214
  log.trace('resolved %s to %c', cidOrPeerIdOrDnsLink, cid)
214
215
  } catch (err) {
215
- options?.signal?.throwIfAborted()
216
+ if (options?.signal?.aborted) {
217
+ throw new AbortError(options?.signal?.reason)
218
+ }
216
219
  if (peerId == null) {
217
220
  log.error('could not parse PeerId string "%s"', cidOrPeerIdOrDnsLink, err)
218
221
  errors.push(new TypeError(`Could not parse PeerId in ipns url "${cidOrPeerIdOrDnsLink}", ${(err as Error).message}`))
@@ -249,7 +252,10 @@ export async function parseUrlString ({ urlString, ipns, logger, withServerTimin
249
252
  resolvedPath = resolveResult?.path
250
253
  log.trace('resolved %s to %c', decodedDnsLinkLabel, cid)
251
254
  } catch (err: any) {
252
- options?.signal?.throwIfAborted()
255
+ // eslint-disable-next-line max-depth
256
+ if (options?.signal?.aborted) {
257
+ throw new AbortError(options?.signal?.reason)
258
+ }
253
259
  log.error('could not resolve DnsLink for "%s"', cidOrPeerIdOrDnsLink, err)
254
260
  errors.push(err)
255
261
  }
@@ -264,7 +270,7 @@ export async function parseUrlString ({ urlString, ipns, logger, withServerTimin
264
270
 
265
271
  errors.push(new Error(`Invalid resource. Cannot determine CID from URL "${urlString}".`))
266
272
 
267
- // eslint-disable-next-line @typescript-eslint/no-throw-literal
273
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
268
274
  throw errors
269
275
  }
270
276
 
@@ -1,4 +1,4 @@
1
- import type { ByteRangeContext } from './byte-range-context'
1
+ import type { ByteRangeContext } from './byte-range-context.js'
2
2
  import type { SupportedBodyTypes } from '../types.js'
3
3
  import type { Logger } from '@libp2p/interface'
4
4
 
@@ -193,9 +193,9 @@ export function okRangeResponse (url: string, body: SupportedBodyTypes, { byteRa
193
193
 
194
194
  /**
195
195
  * We likely need to catch errors handled by upstream helia libraries if range-request throws an error. Some examples:
196
- * * The range is out of bounds
197
- * * The range is invalid
198
- * * The range is not supported for the given type
196
+ * - The range is out of bounds
197
+ * - The range is invalid
198
+ * - The range is not supported for the given type
199
199
  */
200
200
  export function badRangeResponse (url: string, body?: SupportedBodyTypes, init?: ResponseInit): Response {
201
201
  const response = new Response(body, {
package/src/utils/tlru.ts CHANGED
@@ -1,4 +1,4 @@
1
- import hashlru from 'hashlru'
1
+ import QuickLRU from 'quick-lru'
2
2
 
3
3
  /**
4
4
  * Time Aware Least Recent Used Cache
@@ -6,30 +6,20 @@ import hashlru from 'hashlru'
6
6
  * @see https://arxiv.org/pdf/1801.00390
7
7
  */
8
8
  export class TLRU<T> {
9
- private readonly lru: ReturnType<typeof hashlru>
9
+ private readonly lru: QuickLRU<string, T>
10
10
 
11
11
  constructor (maxSize: number) {
12
- this.lru = hashlru(maxSize)
12
+ this.lru = new QuickLRU({ maxSize })
13
13
  }
14
14
 
15
15
  get (key: string): T | undefined {
16
- const value = this.lru.get(key)
17
-
18
- if (value != null) {
19
- if (value.expire != null && value.expire < Date.now()) {
20
- this.lru.remove(key)
21
-
22
- return undefined
23
- }
24
-
25
- return value.value
26
- }
27
-
28
- return undefined
16
+ return this.lru.get(key)
29
17
  }
30
18
 
31
19
  set (key: string, value: T, ttlMs: number): void {
32
- this.lru.set(key, { value, expire: Date.now() + ttlMs })
20
+ this.lru.set(key, value, {
21
+ maxAge: Date.now() + ttlMs
22
+ })
33
23
  }
34
24
 
35
25
  has (key: string): boolean {
@@ -43,7 +33,7 @@ export class TLRU<T> {
43
33
  }
44
34
 
45
35
  remove (key: string): void {
46
- this.lru.remove(key)
36
+ this.lru.delete(key)
47
37
  }
48
38
 
49
39
  clear (): void {
@@ -1,4 +1,5 @@
1
1
  import { DoesNotExistError } from '@helia/unixfs/errors'
2
+ import { AbortError } from '@libp2p/interface'
2
3
  import { walkPath as exporterWalk } from 'ipfs-unixfs-exporter'
3
4
  import { badGatewayResponse, notFoundResponse } from './responses.js'
4
5
  import type { PluginContext } from '../plugins/types.js'
@@ -53,7 +54,10 @@ export async function handlePathWalking ({ cid, path, resource, options, blockst
53
54
  try {
54
55
  return await walkPath(blockstore, `${cid.toString()}/${path}`, options)
55
56
  } catch (err: any) {
56
- options?.signal?.throwIfAborted()
57
+ if (options?.signal?.aborted) {
58
+ throw new AbortError(options?.signal?.reason)
59
+ }
60
+
57
61
  if (['ERR_NO_PROP', 'ERR_NO_TERMINAL_ELEMENT', 'ERR_NOT_FOUND'].includes(err.code)) {
58
62
  return notFoundResponse(resource)
59
63
  }
@@ -1,7 +1,8 @@
1
1
  import { ipns as heliaIpns } from '@helia/ipns'
2
+ import { AbortError } from '@libp2p/interface'
2
3
  import { prefixLogger } from '@libp2p/logger'
3
- import { LRUCache } from 'lru-cache'
4
4
  import { CustomProgressEvent } from 'progress-events'
5
+ import QuickLRU from 'quick-lru'
5
6
  import { ByteRangeContextPlugin } from './plugins/plugin-handle-byte-range-context.js'
6
7
  import { CarPlugin } from './plugins/plugin-handle-car.js'
7
8
  import { DagCborPlugin } from './plugins/plugin-handle-dag-cbor.js'
@@ -62,7 +63,7 @@ export class VerifiedFetch {
62
63
  private readonly ipns: IPNS
63
64
  private readonly log: Logger
64
65
  private readonly contentTypeParser: ContentTypeParser | undefined
65
- private readonly blockstoreSessions: LRUCache<string, SessionBlockstore>
66
+ private readonly blockstoreSessions: QuickLRU<string, SessionBlockstore>
66
67
  private serverTimingHeaders: string[] = []
67
68
  private readonly withServerTiming: boolean
68
69
  private readonly plugins: VerifiedFetchPlugin[] = []
@@ -72,10 +73,10 @@ export class VerifiedFetch {
72
73
  this.log = helia.logger.forComponent('helia:verified-fetch')
73
74
  this.ipns = ipns ?? heliaIpns(helia)
74
75
  this.contentTypeParser = init?.contentTypeParser ?? contentTypeParser
75
- this.blockstoreSessions = new LRUCache({
76
- max: init?.sessionCacheSize ?? SESSION_CACHE_MAX_SIZE,
77
- ttl: init?.sessionTTLms ?? SESSION_CACHE_TTL_MS,
78
- dispose: (store) => {
76
+ this.blockstoreSessions = new QuickLRU({
77
+ maxSize: init?.sessionCacheSize ?? SESSION_CACHE_MAX_SIZE,
78
+ maxAge: init?.sessionTTLms ?? SESSION_CACHE_TTL_MS,
79
+ onEviction: (key, store) => {
79
80
  store.close()
80
81
  }
81
82
  })
@@ -282,7 +283,9 @@ export class VerifiedFetch {
282
283
  break
283
284
  }
284
285
  } catch (err: any) {
285
- context.options?.signal?.throwIfAborted()
286
+ if (context.options?.signal?.aborted) {
287
+ throw new AbortError(context.options?.signal?.reason)
288
+ }
286
289
  this.log.error('Error in plugin:', plugin.constructor.name, err)
287
290
  // if fatal, short-circuit the pipeline
288
291
  if (err.name === 'PluginFatalError') {
@@ -341,7 +344,9 @@ export class VerifiedFetch {
341
344
  parsedResult = await this.handleServerTiming('parse-resource', '', async () => parseResource(resource, { ipns: this.ipns, logger: this.helia.logger }, { withServerTiming, ...options }), withServerTiming)
342
345
  this.serverTimingHeaders.push(...parsedResult.serverTimings.map(({ header }) => header))
343
346
  } catch (err: any) {
344
- options?.signal?.throwIfAborted()
347
+ if (options?.signal?.aborted) {
348
+ throw new AbortError(options?.signal?.reason)
349
+ }
345
350
  this.log.error('error parsing resource %s', resource, err)
346
351
 
347
352
  return this.handleFinalResponse(badRequestResponse(resource.toString(), err))