@helia/verified-fetch 4.1.1 → 5.0.1
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/README.md +6 -40
- package/dist/index.min.js +73 -534
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +2 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +162 -68
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -40
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/index.d.ts +0 -5
- package/dist/src/plugins/index.d.ts.map +1 -1
- package/dist/src/plugins/index.js +0 -4
- package/dist/src/plugins/index.js.map +1 -1
- package/dist/src/plugins/plugin-base.d.ts +8 -9
- package/dist/src/plugins/plugin-base.d.ts.map +1 -1
- package/dist/src/plugins/plugin-base.js +5 -6
- package/dist/src/plugins/plugin-base.js.map +1 -1
- package/dist/src/plugins/plugin-handle-car.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-car.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-car.js +38 -39
- package/dist/src/plugins/plugin-handle-car.js.map +1 -1
- package/dist/src/plugins/plugin-handle-ipld.d.ts +12 -0
- package/dist/src/plugins/plugin-handle-ipld.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-ipld.js +83 -0
- package/dist/src/plugins/plugin-handle-ipld.js.map +1 -0
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-ipns-record.js +25 -34
- package/dist/src/plugins/plugin-handle-ipns-record.js.map +1 -1
- package/dist/src/plugins/plugin-handle-tar.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-tar.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-tar.js +20 -22
- package/dist/src/plugins/plugin-handle-tar.js.map +1 -1
- package/dist/src/plugins/plugin-handle-unixfs.d.ts +14 -0
- package/dist/src/plugins/plugin-handle-unixfs.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-unixfs.js +180 -0
- package/dist/src/plugins/plugin-handle-unixfs.js.map +1 -0
- package/dist/src/plugins/types.d.ts +1 -77
- package/dist/src/plugins/types.d.ts.map +1 -1
- package/dist/src/url-resolver.d.ts +29 -11
- package/dist/src/url-resolver.d.ts.map +1 -1
- package/dist/src/url-resolver.js +152 -74
- package/dist/src/url-resolver.js.map +1 -1
- package/dist/src/utils/content-type-parser.d.ts.map +1 -1
- package/dist/src/utils/content-type-parser.js +4 -3
- package/dist/src/utils/content-type-parser.js.map +1 -1
- package/dist/src/utils/content-types.d.ts +26 -0
- package/dist/src/utils/content-types.d.ts.map +1 -0
- package/dist/src/utils/content-types.js +137 -0
- package/dist/src/utils/content-types.js.map +1 -0
- package/dist/src/utils/convert-output.d.ts +17 -0
- package/dist/src/utils/convert-output.d.ts.map +1 -0
- package/dist/src/utils/convert-output.js +176 -0
- package/dist/src/utils/convert-output.js.map +1 -0
- package/dist/src/utils/error-to-response.d.ts +3 -0
- package/dist/src/utils/error-to-response.d.ts.map +1 -0
- package/dist/src/utils/error-to-response.js +40 -0
- package/dist/src/utils/error-to-response.js.map +1 -0
- package/dist/src/utils/get-content-disposition-filename.d.ts +1 -1
- package/dist/src/utils/get-content-disposition-filename.d.ts.map +1 -1
- package/dist/src/utils/get-content-disposition-filename.js +4 -0
- package/dist/src/utils/get-content-disposition-filename.js.map +1 -1
- package/dist/src/utils/get-e-tag.d.ts +20 -15
- package/dist/src/utils/get-e-tag.d.ts.map +1 -1
- package/dist/src/utils/get-e-tag.js +8 -22
- package/dist/src/utils/get-e-tag.js.map +1 -1
- package/dist/src/utils/get-offset-and-length.d.ts +12 -2
- package/dist/src/utils/get-offset-and-length.d.ts.map +1 -1
- package/dist/src/utils/get-offset-and-length.js +63 -21
- package/dist/src/utils/get-offset-and-length.js.map +1 -1
- package/dist/src/utils/get-range-header.d.ts +22 -0
- package/dist/src/utils/get-range-header.d.ts.map +1 -0
- package/dist/src/utils/get-range-header.js +69 -0
- package/dist/src/utils/get-range-header.js.map +1 -0
- package/dist/src/utils/parse-url-string.d.ts +2 -1
- package/dist/src/utils/parse-url-string.d.ts.map +1 -1
- package/dist/src/utils/parse-url-string.js +46 -71
- package/dist/src/utils/parse-url-string.js.map +1 -1
- package/dist/src/utils/resource-to-cache-key.d.ts +3 -3
- package/dist/src/utils/resource-to-cache-key.js +5 -5
- package/dist/src/utils/resource-to-cache-key.js.map +1 -1
- package/dist/src/utils/response-headers.d.ts +4 -14
- package/dist/src/utils/response-headers.d.ts.map +1 -1
- package/dist/src/utils/response-headers.js +36 -36
- package/dist/src/utils/response-headers.js.map +1 -1
- package/dist/src/utils/responses.d.ts +30 -11
- package/dist/src/utils/responses.d.ts.map +1 -1
- package/dist/src/utils/responses.js +146 -39
- package/dist/src/utils/responses.js.map +1 -1
- package/dist/src/verified-fetch.d.ts +16 -15
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +302 -238
- package/dist/src/verified-fetch.js.map +1 -1
- package/dist/typedoc-urls.json +64 -45
- package/package.json +4 -3
- package/src/constants.ts +3 -0
- package/src/index.ts +199 -68
- package/src/plugins/index.ts +0 -6
- package/src/plugins/plugin-base.ts +8 -10
- package/src/plugins/plugin-handle-car.ts +48 -46
- package/src/plugins/plugin-handle-ipld.ts +93 -0
- package/src/plugins/plugin-handle-ipns-record.ts +31 -41
- package/src/plugins/plugin-handle-tar.ts +25 -29
- package/src/plugins/plugin-handle-unixfs.ts +217 -0
- package/src/plugins/types.ts +0 -86
- package/src/url-resolver.ts +197 -83
- package/src/utils/content-type-parser.ts +4 -3
- package/src/utils/content-types.ts +159 -0
- package/src/utils/convert-output.ts +187 -0
- package/src/utils/error-to-response.ts +49 -0
- package/src/utils/get-content-disposition-filename.ts +7 -1
- package/src/utils/get-e-tag.ts +26 -35
- package/src/utils/get-offset-and-length.ts +75 -21
- package/src/utils/get-range-header.ts +107 -0
- package/src/utils/parse-url-string.ts +51 -80
- package/src/utils/resource-to-cache-key.ts +5 -5
- package/src/utils/response-headers.ts +40 -41
- package/src/utils/responses.ts +186 -45
- package/src/verified-fetch.ts +353 -270
- package/dist/src/plugins/plugin-handle-byte-range-context.d.ts +0 -14
- package/dist/src/plugins/plugin-handle-byte-range-context.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-byte-range-context.js +0 -25
- package/dist/src/plugins/plugin-handle-byte-range-context.js.map +0 -1
- package/dist/src/plugins/plugin-handle-cbor.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-cbor.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-cbor.js +0 -94
- package/dist/src/plugins/plugin-handle-cbor.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts +0 -27
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js +0 -279
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.js +0 -66
- package/dist/src/plugins/plugin-handle-dag-cbor.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-pb.js +0 -209
- package/dist/src/plugins/plugin-handle-dag-pb.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts +0 -21
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-walk.js +0 -95
- package/dist/src/plugins/plugin-handle-dag-walk.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dir-index-html.d.ts +0 -10
- package/dist/src/plugins/plugin-handle-dir-index-html.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dir-index-html.js +0 -59
- package/dist/src/plugins/plugin-handle-dir-index-html.js.map +0 -1
- package/dist/src/plugins/plugin-handle-json.d.ts +0 -12
- package/dist/src/plugins/plugin-handle-json.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-json.js +0 -73
- package/dist/src/plugins/plugin-handle-json.js.map +0 -1
- package/dist/src/plugins/plugin-handle-raw.d.ts +0 -9
- package/dist/src/plugins/plugin-handle-raw.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-raw.js +0 -92
- package/dist/src/plugins/plugin-handle-raw.js.map +0 -1
- package/dist/src/plugins/plugins.d.ts +0 -6
- package/dist/src/plugins/plugins.d.ts.map +0 -1
- package/dist/src/plugins/plugins.js +0 -6
- package/dist/src/plugins/plugins.js.map +0 -1
- package/dist/src/utils/byte-range-context.d.ts +0 -103
- package/dist/src/utils/byte-range-context.d.ts.map +0 -1
- package/dist/src/utils/byte-range-context.js +0 -504
- package/dist/src/utils/byte-range-context.js.map +0 -1
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts +0 -15
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts.map +0 -1
- package/dist/src/utils/dag-cbor-to-safe-json.js +0 -54
- package/dist/src/utils/dag-cbor-to-safe-json.js.map +0 -1
- package/dist/src/utils/dir-index-html.d.ts +0 -19
- package/dist/src/utils/dir-index-html.d.ts.map +0 -1
- package/dist/src/utils/dir-index-html.js +0 -438
- package/dist/src/utils/dir-index-html.js.map +0 -1
- package/dist/src/utils/get-peer-id-from-string.d.ts +0 -3
- package/dist/src/utils/get-peer-id-from-string.d.ts.map +0 -1
- package/dist/src/utils/get-peer-id-from-string.js +0 -10
- package/dist/src/utils/get-peer-id-from-string.js.map +0 -1
- package/dist/src/utils/get-resolved-accept-header.d.ts +0 -9
- package/dist/src/utils/get-resolved-accept-header.d.ts.map +0 -1
- package/dist/src/utils/get-resolved-accept-header.js +0 -27
- package/dist/src/utils/get-resolved-accept-header.js.map +0 -1
- package/dist/src/utils/get-stream-from-async-iterable.d.ts +0 -9
- package/dist/src/utils/get-stream-from-async-iterable.d.ts.map +0 -1
- package/dist/src/utils/get-stream-from-async-iterable.js +0 -43
- package/dist/src/utils/get-stream-from-async-iterable.js.map +0 -1
- package/dist/src/utils/handle-redirects.d.ts +0 -16
- package/dist/src/utils/handle-redirects.d.ts.map +0 -1
- package/dist/src/utils/handle-redirects.js +0 -84
- package/dist/src/utils/handle-redirects.js.map +0 -1
- package/dist/src/utils/is-accept-explicit.d.ts +0 -15
- package/dist/src/utils/is-accept-explicit.d.ts.map +0 -1
- package/dist/src/utils/is-accept-explicit.js +0 -26
- package/dist/src/utils/is-accept-explicit.js.map +0 -1
- package/dist/src/utils/request-headers.d.ts +0 -13
- package/dist/src/utils/request-headers.d.ts.map +0 -1
- package/dist/src/utils/request-headers.js +0 -63
- package/dist/src/utils/request-headers.js.map +0 -1
- package/dist/src/utils/select-output-type.d.ts +0 -17
- package/dist/src/utils/select-output-type.d.ts.map +0 -1
- package/dist/src/utils/select-output-type.js +0 -153
- package/dist/src/utils/select-output-type.js.map +0 -1
- package/dist/src/utils/tlru.d.ts +0 -15
- package/dist/src/utils/tlru.d.ts.map +0 -1
- package/dist/src/utils/tlru.js +0 -34
- package/dist/src/utils/tlru.js.map +0 -1
- package/dist/src/utils/walk-path.d.ts +0 -27
- package/dist/src/utils/walk-path.d.ts.map +0 -1
- package/dist/src/utils/walk-path.js +0 -45
- package/dist/src/utils/walk-path.js.map +0 -1
- package/src/plugins/plugin-handle-byte-range-context.ts +0 -30
- package/src/plugins/plugin-handle-cbor.ts +0 -107
- package/src/plugins/plugin-handle-dag-cbor-html-preview.ts +0 -295
- package/src/plugins/plugin-handle-dag-cbor.ts +0 -83
- package/src/plugins/plugin-handle-dag-pb.ts +0 -248
- package/src/plugins/plugin-handle-dag-walk.ts +0 -110
- package/src/plugins/plugin-handle-dir-index-html.ts +0 -72
- package/src/plugins/plugin-handle-json.ts +0 -80
- package/src/plugins/plugin-handle-raw.ts +0 -110
- package/src/plugins/plugins.ts +0 -5
- package/src/utils/byte-range-context.ts +0 -597
- package/src/utils/dag-cbor-to-safe-json.ts +0 -63
- package/src/utils/dir-index-html.ts +0 -505
- package/src/utils/get-peer-id-from-string.ts +0 -12
- package/src/utils/get-resolved-accept-header.ts +0 -42
- package/src/utils/get-stream-from-async-iterable.ts +0 -49
- package/src/utils/handle-redirects.ts +0 -109
- package/src/utils/is-accept-explicit.ts +0 -38
- package/src/utils/request-headers.ts +0 -65
- package/src/utils/select-output-type.ts +0 -175
- package/src/utils/tlru.ts +0 -42
- package/src/utils/walk-path.ts +0 -69
|
@@ -1,505 +0,0 @@
|
|
|
1
|
-
import type { Logger } from '@libp2p/interface'
|
|
2
|
-
import type { UnixFSEntry } from 'ipfs-unixfs-exporter'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Types taken from:
|
|
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
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
interface GlobalData {
|
|
12
|
-
// Menu []MenuItem
|
|
13
|
-
gatewayURL: string
|
|
14
|
-
gatewayURLWithoutSubdomain: URL
|
|
15
|
-
dnsLink: boolean
|
|
16
|
-
// root: UnixFSEntry
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface DirectoryTemplateData {
|
|
20
|
-
globalData: GlobalData
|
|
21
|
-
listing: DirectoryItem[]
|
|
22
|
-
size: string
|
|
23
|
-
path: string
|
|
24
|
-
breadcrumbs: Breadcrumb[]
|
|
25
|
-
backLink: string
|
|
26
|
-
hash: string
|
|
27
|
-
name: string
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface DirectoryItem {
|
|
31
|
-
size: string
|
|
32
|
-
name: string
|
|
33
|
-
path: string
|
|
34
|
-
hash: string
|
|
35
|
-
shortHash: string
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface Breadcrumb {
|
|
39
|
-
name: string
|
|
40
|
-
path: string
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface DirIndexHtmlOptions {
|
|
44
|
-
/**
|
|
45
|
-
* The URL of the requested resource
|
|
46
|
-
*/
|
|
47
|
-
gatewayURL: string
|
|
48
|
-
dnsLink?: boolean
|
|
49
|
-
log: Logger
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// see https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/assets/templates.go#L19C1-L25C2
|
|
53
|
-
function iconFromExt (name: string): string {
|
|
54
|
-
// not implemented yet
|
|
55
|
-
// TODO: optimize icons: https://github.com/ipfs-shipyard/ipfs-css/issues/71
|
|
56
|
-
return 'ipfs-_blank'
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* If they click on the short hash, it should link to the host-without-subdomain + /ipfs/ + hash + ?filename={filename}
|
|
61
|
-
*/
|
|
62
|
-
function itemShortHashCell (item: DirectoryItem, dirData: DirectoryTemplateData): string {
|
|
63
|
-
const host = dirData.globalData.gatewayURLWithoutSubdomain.host
|
|
64
|
-
const protocol = dirData.globalData.gatewayURLWithoutSubdomain.protocol
|
|
65
|
-
|
|
66
|
-
return `<a class="ipfs-hash" translate="no" href="${protocol}//${host}/ipfs/${item.hash}?filename=${item.name}">${item.shortHash}</a>`
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Returns a new host with the subdomain removed if it includes "ipfs" or "ipns".
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* subdomain.ipfs.dweb.link -> dweb.link
|
|
74
|
-
* abc.ipns.localhost -> localhost
|
|
75
|
-
* bafyfoo.ipfs.localhost:3441 -> localhost:3441
|
|
76
|
-
* bafyfoo.ipfs.foo.localhost:3441 -> foo.localhost:3441
|
|
77
|
-
*/
|
|
78
|
-
function removeIpfsOrIpnsSubdomain (host: string): string {
|
|
79
|
-
const segments = host.split('.')
|
|
80
|
-
const keepSegments: string[] = []
|
|
81
|
-
|
|
82
|
-
// Walk from the right to the left
|
|
83
|
-
for (let i = segments.length - 1; i >= 0; i--) {
|
|
84
|
-
const seg = segments[i]
|
|
85
|
-
// If we hit "ipfs" or "ipns", stop (ignore everything to the left)
|
|
86
|
-
if (seg === 'ipfs' || seg === 'ipns') {
|
|
87
|
-
break
|
|
88
|
-
}
|
|
89
|
-
keepSegments.push(seg)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Reverse because we collected from right to left
|
|
93
|
-
keepSegments.reverse()
|
|
94
|
-
|
|
95
|
-
// If keepSegments is empty, it means "ipfs" or "ipns" was at the TLD level
|
|
96
|
-
// but typically that means the next domain is empty; just return empty string
|
|
97
|
-
return keepSegments.join('.')
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function getGatewayURLWithoutSubdomain (gatewayURL: string): URL {
|
|
101
|
-
let currentUrl: URL
|
|
102
|
-
try {
|
|
103
|
-
currentUrl = new URL(gatewayURL)
|
|
104
|
-
} catch {
|
|
105
|
-
// If the gatewayURL is invalid (ipfs:// or ipns:// or just a CID), use inbrowser.link as a fallback
|
|
106
|
-
currentUrl = new URL('https://inbrowser.link')
|
|
107
|
-
}
|
|
108
|
-
currentUrl.host = removeIpfsOrIpnsSubdomain(currentUrl.host)
|
|
109
|
-
return currentUrl
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function dirListingTitle (dirData: DirectoryTemplateData): string {
|
|
113
|
-
if (dirData.path != null) {
|
|
114
|
-
const href = `${dirData.globalData.gatewayURL}/${dirData.path}`
|
|
115
|
-
return `Index of <a href="${href}">${dirData.name}</a>`
|
|
116
|
-
}
|
|
117
|
-
return `Index of ${dirData.name} ${dirData.path}`
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function getAllDirListingRows (dirData: DirectoryTemplateData): string {
|
|
121
|
-
return dirData.listing.map((item) => `<div class="type-icon">
|
|
122
|
-
<div class="${iconFromExt(item.name)}"> </div>
|
|
123
|
-
</div>
|
|
124
|
-
<div>
|
|
125
|
-
<a href="${item.path}">${item.name}</a>
|
|
126
|
-
</div>
|
|
127
|
-
<div class="nowrap">
|
|
128
|
-
${itemShortHashCell(item, dirData)}
|
|
129
|
-
</div>
|
|
130
|
-
<div class="nowrap" title="Cumulative size of IPFS DAG (data + metadata)">${item.size}</div>`).join(' ')
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function getItemPath (item: UnixFSEntry): string {
|
|
134
|
-
const itemPathParts = item.path.split('/')
|
|
135
|
-
|
|
136
|
-
return itemPathParts.pop() ?? item.path
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* if <= 11, return the hash as is
|
|
141
|
-
* if > 11, return the first 4 and last 4 characters of the hash, separated by '...'
|
|
142
|
-
*
|
|
143
|
-
* e.g. QmabcccHnzA
|
|
144
|
-
* e.g. Qmab...HnzA
|
|
145
|
-
*/
|
|
146
|
-
function getShortHash (hash: string): string {
|
|
147
|
-
return hash.length <= 11 ? hash : `${hash.slice(0, 4)}...${hash.slice(-4)}`
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* todo: https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/handler_unixfs_dir.go#L200-L208
|
|
152
|
-
*
|
|
153
|
-
* @see https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/assets/directory.html
|
|
154
|
-
* @see https://github.com/ipfs/boxo/pull/298
|
|
155
|
-
* @see https://github.com/ipfs/kubo/pull/8555
|
|
156
|
-
*/
|
|
157
|
-
export const dirIndexHtml = (dir: UnixFSEntry, items: UnixFSEntry[], { gatewayURL, dnsLink, log }: DirIndexHtmlOptions): string => {
|
|
158
|
-
log('loading directory html for %s', dir.path)
|
|
159
|
-
|
|
160
|
-
const dirData: DirectoryTemplateData = {
|
|
161
|
-
globalData: {
|
|
162
|
-
gatewayURL,
|
|
163
|
-
gatewayURLWithoutSubdomain: getGatewayURLWithoutSubdomain(gatewayURL),
|
|
164
|
-
dnsLink: dnsLink ?? false
|
|
165
|
-
},
|
|
166
|
-
listing: items.map((item) => {
|
|
167
|
-
return {
|
|
168
|
-
size: item.size?.toString() ?? '?',
|
|
169
|
-
name: item.name,
|
|
170
|
-
path: getItemPath(item),
|
|
171
|
-
hash: item.cid.toString(),
|
|
172
|
-
shortHash: getShortHash(item.cid.toString())
|
|
173
|
-
} satisfies DirectoryItem
|
|
174
|
-
}),
|
|
175
|
-
name: dir.name,
|
|
176
|
-
size: dir.size.toString(),
|
|
177
|
-
path: dir.path,
|
|
178
|
-
breadcrumbs: [],
|
|
179
|
-
backLink: '',
|
|
180
|
-
hash: dir.cid.toString()
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return `<!DOCTYPE html>
|
|
184
|
-
<html lang="en">
|
|
185
|
-
<head>
|
|
186
|
-
<meta charset="utf-8">
|
|
187
|
-
<meta name="description" content="A directory of content-addressed files hosted on IPFS.">
|
|
188
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
189
|
-
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlo89/56ZQ/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUjDu1lo89/6mhTP+zrVP/nplD/5+aRK8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHNiIS6Wjz3/ubFY/761W/+vp1D/urRZ/8vDZf/GvmH/nplD/1BNIm8AAAAAAAAAAAAAAAAAAAAAAAAAAJaPPf+knEj/vrVb/761W/++tVv/r6dQ/7q0Wf/Lw2X/y8Nl/8vDZf+tpk7/nplD/wAAAAAAAAAAAAAAAJaPPf+2rVX/vrVb/761W/++tVv/vrVb/6+nUP+6tFn/y8Nl/8vDZf/Lw2X/y8Nl/8G6Xv+emUP/AAAAAAAAAACWjz3/vrVb/761W/++tVv/vrVb/761W/+vp1D/urRZ/8vDZf/Lw2X/y8Nl/8vDZf/Lw2X/nplD/wAAAAAAAAAAlo89/761W/++tVv/vrVb/761W/++tVv/r6dQ/7q0Wf/Lw2X/y8Nl/8vDZf/Lw2X/y8Nl/56ZQ/8AAAAAAAAAAJaPPf++tVv/vrVb/761W/++tVv/vbRa/5aPPf+emUP/y8Nl/8vDZf/Lw2X/y8Nl/8vDZf+emUP/AAAAAAAAAACWjz3/vrVb/761W/++tVv/vrVb/5qTQP+inkb/op5G/6KdRv/Lw2X/y8Nl/8vDZf/Lw2X/nplD/wAAAAAAAAAAlo89/761W/++tVv/sqlS/56ZQ//LxWb/0Mlp/9DJaf/Kw2X/oJtE/7+3XP/Lw2X/y8Nl/56ZQ/8AAAAAAAAAAJaPPf+9tFr/mJE+/7GsUv/Rymr/0cpq/9HKav/Rymr/0cpq/9HKav+xrFL/nplD/8vDZf+emUP/AAAAAAAAAACWjz3/op5G/9HKav/Rymr/0cpq/9HKav/Rymr/0cpq/9HKav/Rymr/0cpq/9HKav+inkb/nplD/wAAAAAAAAAAAAAAAKKeRv+3slb/0cpq/9HKav/Rymr/0cpq/9HKav/Rymr/0cpq/9HKav+1sFX/op5G/wAAAAAAAAAAAAAAAAAAAAAAAAAAop5GUKKeRv/Nxmf/0cpq/9HKav/Rymr/0cpq/83GZ/+inkb/op5GSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAop5G16KeRv/LxWb/y8Vm/6KeRv+inkaPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAop5G/6KeRtcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/n8AAPgfAADwDwAAwAMAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAwAMAAPAPAAD4HwAA/n8AAA==">
|
|
190
|
-
<title>${dirData.path}</title>
|
|
191
|
-
<style>${style}</style>
|
|
192
|
-
</head>
|
|
193
|
-
<body>
|
|
194
|
-
<!--
|
|
195
|
-
# Some JSON content for debugging:
|
|
196
|
-
|
|
197
|
-
## dirData
|
|
198
|
-
${JSON.stringify(dirData, null, 2)}
|
|
199
|
-
-->
|
|
200
|
-
<header id="header">
|
|
201
|
-
<div class="ipfs-logo"> </div>
|
|
202
|
-
<!--
|
|
203
|
-
<nav>
|
|
204
|
-
<a href="https://ipfs.tech" target="_blank" rel="noopener noreferrer">About<span class="dn-mobile"> IPFS</span></a>
|
|
205
|
-
<a href="https://docs.ipfs.tech/install/" target="_blank" rel="noopener noreferrer">Install<span class="dn-mobile"> IPFS</span></a>
|
|
206
|
-
</nav>
|
|
207
|
-
-->
|
|
208
|
-
</header>
|
|
209
|
-
<main id="main">
|
|
210
|
-
<header class="flex flex-wrap">
|
|
211
|
-
<div>
|
|
212
|
-
<strong>${dirListingTitle(dirData)}</strong>
|
|
213
|
-
${dirData.hash == null
|
|
214
|
-
? ''
|
|
215
|
-
: `<div class="ipfs-hash" translate="no">
|
|
216
|
-
${dirData.hash}
|
|
217
|
-
</div>`
|
|
218
|
-
}
|
|
219
|
-
</div>
|
|
220
|
-
${dirData.size == null
|
|
221
|
-
? ''
|
|
222
|
-
: `<div class="nowrap flex-shrink ml-auto">
|
|
223
|
-
<strong title="Cumulative size of IPFS DAG (data + metadata)"> ${dirData.size}</strong>
|
|
224
|
-
</div>`
|
|
225
|
-
}
|
|
226
|
-
</header>
|
|
227
|
-
<div>
|
|
228
|
-
<div class="grid dir">
|
|
229
|
-
<!--{{ if .BackLink }}
|
|
230
|
-
<div class="type-icon">
|
|
231
|
-
<div class="ipfs-_blank"> </div>
|
|
232
|
-
</div>
|
|
233
|
-
<div>
|
|
234
|
-
<a href="{{.BackLink | urlEscape}}">..</a>
|
|
235
|
-
</div>
|
|
236
|
-
<div></div>
|
|
237
|
-
<div></div>
|
|
238
|
-
</tr>
|
|
239
|
-
{{ end }}-->
|
|
240
|
-
${getAllDirListingRows(dirData)}
|
|
241
|
-
</div>
|
|
242
|
-
</div>
|
|
243
|
-
</main>
|
|
244
|
-
</body>
|
|
245
|
-
</html>`
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const style = `
|
|
249
|
-
|
|
250
|
-
.ipfs-_blank {
|
|
251
|
-
background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 72 100'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='36' y1='1' x2='36' y2='99' gradientTransform='matrix(1 0 0 -1 0 100)'%3E%3Cstop offset='0' stop-color='%23c8d4db'/%3E%3Cstop offset='.139' stop-color='%23d8e1e6'/%3E%3Cstop offset='.359' stop-color='%23ebf0f3'/%3E%3Cstop offset='.617' stop-color='%23f9fafb'/%3E%3Cstop offset='1' stop-color='%23fff'/%3E%3C/linearGradient%3E%3Cpath d='M45 1l27 26.7V99H0V1h45z' fill='url(%23a)'/%3E%3Cpath d='M45 1l27 26.7V99H0V1h45z' fill-opacity='0' stroke='%237191a1' stroke-width='2'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='45.068' y1='72.204' x2='58.568' y2='85.705' gradientTransform='matrix(1 0 0 -1 0 100)'%3E%3Cstop offset='0' stop-color='%23fff'/%3E%3Cstop offset='.35' stop-color='%23fafbfb'/%3E%3Cstop offset='.532' stop-color='%23edf1f4'/%3E%3Cstop offset='.675' stop-color='%23dde5e9'/%3E%3Cstop offset='.799' stop-color='%23c7d3da'/%3E%3Cstop offset='.908' stop-color='%23adbdc7'/%3E%3Cstop offset='1' stop-color='%2392a5b0'/%3E%3C/linearGradient%3E%3Cpath d='M45 1l27 26.7H45V1z' fill='url(%23b)'/%3E%3Cpath d='M45 1l27 26.7H45V1z' fill-opacity='0' stroke='%237191a1' stroke-width='2' stroke-linejoin='bevel'/%3E%3C/svg%3E");
|
|
252
|
-
background-repeat: no-repeat;
|
|
253
|
-
background-size: contain
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
:root {
|
|
257
|
-
--sans-serif: "Plex",system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif;
|
|
258
|
-
--monospace: Consolas, monaco, monospace;
|
|
259
|
-
--navy: #073a53;
|
|
260
|
-
--teal: #6bc4ce;
|
|
261
|
-
--turquoise: #47AFB4;
|
|
262
|
-
--steel-gray: #3f5667;
|
|
263
|
-
--dark-white: #d9dbe2;
|
|
264
|
-
--light-white: #edf0f4;
|
|
265
|
-
--near-white: #f7f8fa;
|
|
266
|
-
--radius: 4px;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
body {
|
|
270
|
-
color: #34373f;
|
|
271
|
-
font-family: var(--sans-serif);
|
|
272
|
-
line-height: 1.43;
|
|
273
|
-
margin: 0;
|
|
274
|
-
word-break: break-all;
|
|
275
|
-
-webkit-text-size-adjust: 100%;
|
|
276
|
-
-ms-text-size-adjust: 100%;
|
|
277
|
-
-webkit-tap-highlight-color: transparent;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
pre, code {
|
|
281
|
-
font-family: var(--monospace);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
a {
|
|
285
|
-
color: #117eb3;
|
|
286
|
-
text-decoration: none;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
a:hover {
|
|
290
|
-
color: #00b0e9;
|
|
291
|
-
text-decoration: underline;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
a:active,a:visited {
|
|
295
|
-
color: #00b0e9;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.flex {
|
|
299
|
-
display: flex;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
.flex-wrap {
|
|
303
|
-
flex-flow: wrap;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.flex-shrink {
|
|
307
|
-
flex-shrink: 1;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
.ml-auto {
|
|
311
|
-
margin-left: auto;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
.nowrap {
|
|
315
|
-
white-space: nowrap
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
.ipfs-hash {
|
|
319
|
-
color: #7f8491;
|
|
320
|
-
font-family: var(--monospace);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
#header {
|
|
324
|
-
align-items: center;
|
|
325
|
-
background: var(--navy);
|
|
326
|
-
border-bottom: 4px solid var(--teal);
|
|
327
|
-
color: #fff;
|
|
328
|
-
display: flex;
|
|
329
|
-
font-weight: 500;
|
|
330
|
-
justify-content: space-between;
|
|
331
|
-
padding: 0 1em;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
#header a {
|
|
335
|
-
color: var(--teal);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
#header a:active {
|
|
339
|
-
color: #9ad4db;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
#header a:hover {
|
|
343
|
-
color: #fff;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
#header .ipfs-logo {
|
|
347
|
-
height: 2.25em;
|
|
348
|
-
margin: .7em .7em .7em 0;
|
|
349
|
-
width: 7.15em
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
#header nav {
|
|
353
|
-
align-items: center;
|
|
354
|
-
display: flex;
|
|
355
|
-
margin: .65em 0;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
#header nav a {
|
|
359
|
-
margin: 0 .6em;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
#header nav a:last-child {
|
|
363
|
-
margin: 0 0 0 .6em;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
#header nav svg {
|
|
367
|
-
fill: var(--teal);
|
|
368
|
-
height: 1.8em;
|
|
369
|
-
margin-top: .125em;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
#header nav svg:hover {
|
|
373
|
-
fill: #fff;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
main {
|
|
377
|
-
border: 1px solid var(--dark-white);
|
|
378
|
-
border-radius: var(--radius);
|
|
379
|
-
overflow: hidden;
|
|
380
|
-
margin: 1em;
|
|
381
|
-
font-size: .875em;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
main header,main .container {
|
|
385
|
-
padding-left: 1em;
|
|
386
|
-
padding-right: 1em;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
main header {
|
|
390
|
-
padding-top: .7em;
|
|
391
|
-
padding-bottom: .7em;
|
|
392
|
-
background-color: var(--light-white);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
main header,main section:not(:last-child) {
|
|
396
|
-
border-bottom: 1px solid var(--dark-white);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
main section header {
|
|
400
|
-
background-color: var(--near-white);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
.grid {
|
|
404
|
-
display: grid;
|
|
405
|
-
overflow-x: auto;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.grid .grid {
|
|
409
|
-
overflow-x: visible;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.grid > div {
|
|
413
|
-
padding: .7em;
|
|
414
|
-
border-bottom: 1px solid var(--dark-white);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
.grid.dir {
|
|
418
|
-
grid-template-columns: min-content 1fr min-content min-content;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
.grid.dir > div:nth-of-type(4n+1) {
|
|
422
|
-
padding-left: 1em;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
.grid.dir > div:nth-of-type(4n+4) {
|
|
426
|
-
padding-right: 1em;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
.grid.dir > div:nth-last-child(-n+4) {
|
|
430
|
-
border-bottom: 0;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
.grid.dir > div:nth-of-type(8n+5),.grid.dir > div:nth-of-type(8n+6),.grid.dir > div:nth-of-type(8n+7),.grid.dir > div:nth-of-type(8n+8) {
|
|
434
|
-
background-color: var(--near-white);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
.grid.dag {
|
|
438
|
-
grid-template-columns: max-content 1fr;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
.grid.dag pre {
|
|
442
|
-
margin: 0;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
.grid.dag .grid {
|
|
446
|
-
padding: 0;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
.grid.dag > div:nth-last-child(-n+2) {
|
|
450
|
-
border-bottom: 0;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
.grid.dag > div {
|
|
454
|
-
background: white
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
.grid.dag > div:nth-child(4n),.grid.dag > div:nth-child(4n+3) {
|
|
458
|
-
background-color: var(--near-white);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
section > .grid.dag > div:nth-of-type(2n+1) {
|
|
462
|
-
padding-left: 1em;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
.type-icon,.type-icon > * {
|
|
466
|
-
width: 1.15em
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
.terminal {
|
|
470
|
-
background: var(--steel-gray);
|
|
471
|
-
color: white;
|
|
472
|
-
padding: .7em;
|
|
473
|
-
border-radius: var(--radius);
|
|
474
|
-
word-wrap: break-word;
|
|
475
|
-
white-space: break-spaces;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
@media print {
|
|
479
|
-
#header {
|
|
480
|
-
display: none;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
#main header,.ipfs-hash,body {
|
|
484
|
-
color: #000;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
#main,#main header {
|
|
488
|
-
border-color: #000;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
a,a:visited {
|
|
492
|
-
color: #000;
|
|
493
|
-
text-decoration: underline;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
a[href]:after {
|
|
497
|
-
content: " (" attr(href) ")"
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
@media only screen and (max-width: 500px) {
|
|
502
|
-
.dn-mobile {
|
|
503
|
-
display: none;
|
|
504
|
-
}
|
|
505
|
-
}`
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { peerIdFromCID, peerIdFromString } from '@libp2p/peer-id'
|
|
2
|
-
import { CID } from 'multiformats/cid'
|
|
3
|
-
import type { PeerId } from '@libp2p/interface'
|
|
4
|
-
|
|
5
|
-
export function getPeerIdFromString (peerIdString: string): PeerId {
|
|
6
|
-
if (peerIdString.charAt(0) === '1' || peerIdString.charAt(0) === 'Q') {
|
|
7
|
-
return peerIdFromString(peerIdString)
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// try resolving as a base36 CID
|
|
11
|
-
return peerIdFromCID(CID.parse(peerIdString))
|
|
12
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { isExplicitAcceptHeader, isExplicitFormatQuery, isExplicitIpldAcceptRequest } from './is-accept-explicit.js'
|
|
2
|
-
import { queryFormatToAcceptHeader } from './select-output-type.js'
|
|
3
|
-
import type { UrlQuery } from '../index.ts'
|
|
4
|
-
import type { ComponentLogger } from '@libp2p/interface'
|
|
5
|
-
|
|
6
|
-
export interface ResolvedAcceptHeaderOptions {
|
|
7
|
-
query?: UrlQuery
|
|
8
|
-
headers?: RequestInit['headers']
|
|
9
|
-
logger: ComponentLogger
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function getResolvedAcceptHeader ({ query, headers, logger }: ResolvedAcceptHeaderOptions): string | undefined {
|
|
13
|
-
const log = logger.forComponent('helia:verified-fetch:get-resolved-accept-header')
|
|
14
|
-
const requestHeaders = new Headers(headers)
|
|
15
|
-
const incomingAcceptHeader = requestHeaders.get('accept') ?? undefined
|
|
16
|
-
|
|
17
|
-
if (incomingAcceptHeader != null) {
|
|
18
|
-
log('incoming accept header "%s"', incomingAcceptHeader)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!isExplicitIpldAcceptRequest({ query, headers: requestHeaders })) {
|
|
22
|
-
log('no explicit IPLD content-type requested, returning incoming accept header %s', incomingAcceptHeader)
|
|
23
|
-
return incomingAcceptHeader
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const queryFormatMapping = queryFormatToAcceptHeader(query?.format)
|
|
27
|
-
|
|
28
|
-
if (query?.format != null) {
|
|
29
|
-
log('incoming query format "%s", mapped to %s', query.format, queryFormatMapping)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
let acceptHeader = incomingAcceptHeader
|
|
33
|
-
// if the incomingAcceptHeader is autogenerated by the requesting client (browser/curl/fetch/etc) then we may need to override it if query.format is specified
|
|
34
|
-
if (!isExplicitAcceptHeader(requestHeaders) && isExplicitFormatQuery(query)) {
|
|
35
|
-
log('accept header not recognized, but query format provided, setting accept header to %s', queryFormatMapping)
|
|
36
|
-
acceptHeader = queryFormatMapping
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
log('resolved accept header to "%s"', acceptHeader)
|
|
40
|
-
|
|
41
|
-
return acceptHeader
|
|
42
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { AbortError } from '@libp2p/interface'
|
|
2
|
-
import { CustomProgressEvent } from 'progress-events'
|
|
3
|
-
import { NoContentError } from '../errors.js'
|
|
4
|
-
import type { VerifiedFetchInit } from '../index.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Converts an async iterator of Uint8Array bytes to a stream and returns the first chunk of bytes
|
|
8
|
-
*/
|
|
9
|
-
export async function getStreamFromAsyncIterable (iterator: AsyncIterable<Uint8Array>, options?: Pick<VerifiedFetchInit, 'onProgress' | 'signal'>): Promise<{ stream: ReadableStream<Uint8Array>, firstChunk: Uint8Array }> {
|
|
10
|
-
const reader = iterator[Symbol.asyncIterator]()
|
|
11
|
-
const { value: firstChunk, done } = await reader.next()
|
|
12
|
-
|
|
13
|
-
if (done === true) {
|
|
14
|
-
throw new NoContentError()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const stream = new ReadableStream({
|
|
18
|
-
async start (controller) {
|
|
19
|
-
// the initial value is already available
|
|
20
|
-
options?.onProgress?.(new CustomProgressEvent<void>('verified-fetch:request:progress:chunk'))
|
|
21
|
-
controller.enqueue(firstChunk)
|
|
22
|
-
},
|
|
23
|
-
async pull (controller) {
|
|
24
|
-
const { value, done } = await reader.next()
|
|
25
|
-
if (options?.signal?.aborted) {
|
|
26
|
-
controller.error(new AbortError(options.signal.reason ?? 'signal aborted by user'))
|
|
27
|
-
controller.close()
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (done === true) {
|
|
32
|
-
if (value != null) {
|
|
33
|
-
options?.onProgress?.(new CustomProgressEvent<void>('verified-fetch:request:progress:chunk'))
|
|
34
|
-
controller.enqueue(value)
|
|
35
|
-
}
|
|
36
|
-
controller.close()
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
options?.onProgress?.(new CustomProgressEvent<void>('verified-fetch:request:progress:chunk'))
|
|
41
|
-
controller.enqueue(value)
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
stream,
|
|
47
|
-
firstChunk
|
|
48
|
-
}
|
|
49
|
-
}
|