@helia/verified-fetch 2.3.1 → 2.5.0
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 +200 -0
- package/dist/index.min.js +357 -35
- package/dist/src/index.d.ts +220 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +200 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/errors.d.ts +25 -0
- package/dist/src/plugins/errors.d.ts.map +1 -0
- package/dist/src/plugins/errors.js +33 -0
- package/dist/src/plugins/errors.js.map +1 -0
- package/dist/src/plugins/index.d.ts +8 -0
- package/dist/src/plugins/index.d.ts.map +1 -0
- package/dist/src/plugins/index.js +7 -0
- package/dist/src/plugins/index.js.map +1 -0
- package/dist/src/plugins/plugin-base.d.ts +19 -0
- package/dist/src/plugins/plugin-base.d.ts.map +1 -0
- package/dist/src/plugins/plugin-base.js +26 -0
- package/dist/src/plugins/plugin-base.js.map +1 -0
- package/dist/src/plugins/plugin-handle-car.d.ts +11 -0
- package/dist/src/plugins/plugin-handle-car.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-car.js +28 -0
- package/dist/src/plugins/plugin-handle-car.js.map +1 -0
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts +11 -0
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-dag-cbor.js +73 -0
- package/dist/src/plugins/plugin-handle-dag-cbor.js.map +1 -0
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts +15 -0
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-dag-pb.js +152 -0
- package/dist/src/plugins/plugin-handle-dag-pb.js.map +1 -0
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts +16 -0
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-dag-walk.js +45 -0
- package/dist/src/plugins/plugin-handle-dag-walk.js.map +1 -0
- package/dist/src/plugins/plugin-handle-dir-index-html.d.ts +9 -0
- package/dist/src/plugins/plugin-handle-dir-index-html.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-dir-index-html.js +37 -0
- package/dist/src/plugins/plugin-handle-dir-index-html.js.map +1 -0
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts +12 -0
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-ipns-record.js +62 -0
- package/dist/src/plugins/plugin-handle-ipns-record.js.map +1 -0
- package/dist/src/plugins/plugin-handle-json.d.ts +11 -0
- package/dist/src/plugins/plugin-handle-json.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-json.js +51 -0
- package/dist/src/plugins/plugin-handle-json.js.map +1 -0
- package/dist/src/plugins/plugin-handle-raw.d.ts +8 -0
- package/dist/src/plugins/plugin-handle-raw.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-raw.js +80 -0
- package/dist/src/plugins/plugin-handle-raw.js.map +1 -0
- package/dist/src/plugins/plugin-handle-tar.d.ts +12 -0
- package/dist/src/plugins/plugin-handle-tar.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-tar.js +36 -0
- package/dist/src/plugins/plugin-handle-tar.js.map +1 -0
- package/dist/src/plugins/plugins.d.ts +5 -0
- package/dist/src/plugins/plugins.d.ts.map +1 -0
- package/dist/src/plugins/plugins.js +5 -0
- package/dist/src/plugins/plugins.js.map +1 -0
- package/dist/src/plugins/types.d.ts +68 -0
- package/dist/src/plugins/types.d.ts.map +1 -0
- package/dist/src/plugins/types.js +2 -0
- package/dist/src/plugins/types.js.map +1 -0
- package/dist/src/types.d.ts +0 -23
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +1 -2
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/dir-index-html.d.ts +16 -0
- package/dist/src/utils/dir-index-html.d.ts.map +1 -0
- package/dist/src/utils/dir-index-html.js +387 -0
- package/dist/src/utils/dir-index-html.js.map +1 -0
- package/dist/src/utils/get-e-tag.d.ts +1 -1
- package/dist/src/utils/get-e-tag.d.ts.map +1 -1
- package/dist/src/utils/get-e-tag.js +18 -3
- package/dist/src/utils/get-e-tag.js.map +1 -1
- package/dist/src/utils/parse-resource.d.ts +2 -1
- package/dist/src/utils/parse-resource.d.ts.map +1 -1
- package/dist/src/utils/parse-resource.js +4 -3
- package/dist/src/utils/parse-resource.js.map +1 -1
- package/dist/src/utils/parse-url-string.d.ts +8 -3
- package/dist/src/utils/parse-url-string.d.ts.map +1 -1
- package/dist/src/utils/parse-url-string.js +30 -4
- package/dist/src/utils/parse-url-string.js.map +1 -1
- package/dist/src/utils/server-timing.d.ts +13 -0
- package/dist/src/utils/server-timing.d.ts.map +1 -0
- package/dist/src/utils/server-timing.js +19 -0
- package/dist/src/utils/server-timing.js.map +1 -0
- package/dist/src/utils/walk-path.d.ts +3 -2
- package/dist/src/utils/walk-path.d.ts.map +1 -1
- package/dist/src/utils/walk-path.js +1 -1
- package/dist/src/utils/walk-path.js.map +1 -1
- package/dist/src/verified-fetch.d.ts +11 -20
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +174 -367
- package/dist/src/verified-fetch.js.map +1 -1
- package/dist/typedoc-urls.json +32 -24
- package/package.json +6 -2
- package/src/index.ts +223 -0
- package/src/plugins/errors.ts +37 -0
- package/src/plugins/index.ts +8 -0
- package/src/plugins/plugin-base.ts +30 -0
- package/src/plugins/plugin-handle-car.ts +32 -0
- package/src/plugins/plugin-handle-dag-cbor.ts +84 -0
- package/src/plugins/plugin-handle-dag-pb.ts +168 -0
- package/src/plugins/plugin-handle-dag-walk.ts +53 -0
- package/src/plugins/plugin-handle-dir-index-html.ts +44 -0
- package/src/plugins/plugin-handle-ipns-record.ts +69 -0
- package/src/plugins/plugin-handle-json.ts +57 -0
- package/src/plugins/plugin-handle-raw.ts +92 -0
- package/src/plugins/plugin-handle-tar.ts +44 -0
- package/src/plugins/plugins.ts +4 -0
- package/src/plugins/types.ts +73 -0
- package/src/types.ts +0 -29
- package/src/utils/dir-index-html.ts +445 -0
- package/src/utils/get-e-tag.ts +20 -3
- package/src/utils/parse-resource.ts +5 -4
- package/src/utils/parse-url-string.ts +38 -7
- package/src/utils/server-timing.ts +37 -0
- package/src/utils/walk-path.ts +3 -3
- package/src/verified-fetch.ts +198 -403
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
// see https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/assets/templates.go#L19C1-L25C2
|
|
2
|
+
function iconFromExt(name) {
|
|
3
|
+
// not implemented yet
|
|
4
|
+
// TODO: optimize icons: https://github.com/ipfs-shipyard/ipfs-css/issues/71
|
|
5
|
+
return 'ipfs-_blank';
|
|
6
|
+
}
|
|
7
|
+
function itemShortHashCell(item, dirData) {
|
|
8
|
+
const href = dirData.globalData.dnsLink ? `https://inbrowser.dev/ipfs/${item.hash}` : `${dirData.globalData.gatewayURL}/ipfs/${item.hash}?filename=${item.name}`;
|
|
9
|
+
return `<a class="ipfs-hash" translate="no" href="${href}">${item.shortHash}</a>`;
|
|
10
|
+
}
|
|
11
|
+
function dirListingTitle(dirData) {
|
|
12
|
+
if (dirData.path != null) {
|
|
13
|
+
const href = `${dirData.globalData.gatewayURL}/${dirData.path}`;
|
|
14
|
+
return `Index of <a href="${href}">${dirData.name}</a>`;
|
|
15
|
+
}
|
|
16
|
+
return `Index of ${dirData.name} ${dirData.path}`;
|
|
17
|
+
}
|
|
18
|
+
function getAllDirListingRows(dirData) {
|
|
19
|
+
return dirData.listing.map((item) => `<div class="type-icon">
|
|
20
|
+
<div class="${iconFromExt(item.name)}"> </div>
|
|
21
|
+
</div>
|
|
22
|
+
<div>
|
|
23
|
+
<a href="${item.path}">${item.name}</a>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="nowrap">
|
|
26
|
+
${itemShortHashCell(item, dirData)}
|
|
27
|
+
</div>
|
|
28
|
+
<div class="nowrap" title="Cumulative size of IPFS DAG (data + metadata)">${item.size}</div>`).join(' ');
|
|
29
|
+
}
|
|
30
|
+
function getItemPath(item) {
|
|
31
|
+
const itemPathParts = item.path.split('/');
|
|
32
|
+
return itemPathParts.pop() ?? item.path;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* todo: https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/handler_unixfs_dir.go#L200-L208
|
|
36
|
+
*
|
|
37
|
+
* @see https://github.com/ipfs/boxo/blob/09b0013e1c3e09468009b02dfc9b2b9041199d5d/gateway/assets/directory.html
|
|
38
|
+
* @see https://github.com/ipfs/boxo/pull/298
|
|
39
|
+
* @see https://github.com/ipfs/kubo/pull/8555
|
|
40
|
+
*/
|
|
41
|
+
export const dirIndexHtml = (dir, items, { gatewayURL, dnsLink, log }) => {
|
|
42
|
+
log('loading directory html for %s', dir.path);
|
|
43
|
+
const dirData = {
|
|
44
|
+
globalData: {
|
|
45
|
+
gatewayURL,
|
|
46
|
+
dnsLink: dnsLink ?? false
|
|
47
|
+
},
|
|
48
|
+
listing: items.map((item) => {
|
|
49
|
+
return {
|
|
50
|
+
size: item.size.toString(),
|
|
51
|
+
name: item.name,
|
|
52
|
+
path: getItemPath(item),
|
|
53
|
+
hash: item.cid.toString(),
|
|
54
|
+
shortHash: item.cid.toString().slice(0, 8)
|
|
55
|
+
};
|
|
56
|
+
}),
|
|
57
|
+
name: dir.name,
|
|
58
|
+
size: dir.size.toString(),
|
|
59
|
+
path: dir.path,
|
|
60
|
+
breadcrumbs: [],
|
|
61
|
+
backLink: '',
|
|
62
|
+
hash: dir.cid.toString()
|
|
63
|
+
};
|
|
64
|
+
return `
|
|
65
|
+
<!DOCTYPE html>
|
|
66
|
+
<!--{{ $root := . }}-->
|
|
67
|
+
<html lang="en">
|
|
68
|
+
<head>
|
|
69
|
+
<meta charset="utf-8" />
|
|
70
|
+
<meta name="description" content="A directory of content-addressed files hosted on IPFS.">
|
|
71
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
72
|
+
<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==" />
|
|
73
|
+
<title>${dirData.path}</title>
|
|
74
|
+
<style>${style}</style>
|
|
75
|
+
</head>
|
|
76
|
+
<body>
|
|
77
|
+
<!--
|
|
78
|
+
# Some JSON content for debugging:
|
|
79
|
+
|
|
80
|
+
## dirData
|
|
81
|
+
${JSON.stringify(dirData, null, 2)}
|
|
82
|
+
-->
|
|
83
|
+
<header id="header">
|
|
84
|
+
<div class="ipfs-logo"> </div>
|
|
85
|
+
<!--
|
|
86
|
+
<nav>
|
|
87
|
+
<a href="https://ipfs.tech" target="_blank" rel="noopener noreferrer">About<span class="dn-mobile"> IPFS</span></a>
|
|
88
|
+
<a href="https://docs.ipfs.tech/install/" target="_blank" rel="noopener noreferrer">Install<span class="dn-mobile"> IPFS</span></a>
|
|
89
|
+
</nav>
|
|
90
|
+
-->
|
|
91
|
+
</header>
|
|
92
|
+
<main id="main">
|
|
93
|
+
<header class="flex flex-wrap">
|
|
94
|
+
<div>
|
|
95
|
+
<strong>${dirListingTitle(dirData)}</strong>
|
|
96
|
+
${dirData.hash == null
|
|
97
|
+
? ''
|
|
98
|
+
: `<div class="ipfs-hash" translate="no">
|
|
99
|
+
${dirData.hash}
|
|
100
|
+
</div>`}
|
|
101
|
+
</div>
|
|
102
|
+
${dirData.size == null
|
|
103
|
+
? ''
|
|
104
|
+
: `<div class="nowrap flex-shrink ml-auto">
|
|
105
|
+
<strong title="Cumulative size of IPFS DAG (data + metadata)"> ${dirData.size}</strong>
|
|
106
|
+
</div>`}
|
|
107
|
+
</header>
|
|
108
|
+
<section>
|
|
109
|
+
<div class="grid dir">
|
|
110
|
+
<!--{{ if .BackLink }}
|
|
111
|
+
<div class="type-icon">
|
|
112
|
+
<div class="ipfs-_blank"> </div>
|
|
113
|
+
</div>
|
|
114
|
+
<div>
|
|
115
|
+
<a href="{{.BackLink | urlEscape}}">..</a>
|
|
116
|
+
</div>
|
|
117
|
+
<div></div>
|
|
118
|
+
<div></div>
|
|
119
|
+
</tr>
|
|
120
|
+
{{ end }}-->
|
|
121
|
+
${getAllDirListingRows(dirData)}
|
|
122
|
+
</div>
|
|
123
|
+
</section>
|
|
124
|
+
</main>
|
|
125
|
+
</body>
|
|
126
|
+
</html>
|
|
127
|
+
`;
|
|
128
|
+
};
|
|
129
|
+
const style = `
|
|
130
|
+
|
|
131
|
+
.ipfs-_blank {
|
|
132
|
+
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");
|
|
133
|
+
background-repeat: no-repeat;
|
|
134
|
+
background-size: contain
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
:root {
|
|
138
|
+
--sans-serif: "Plex",system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif;
|
|
139
|
+
--monospace: Consolas, monaco, monospace;
|
|
140
|
+
--navy: #073a53;
|
|
141
|
+
--teal: #6bc4ce;
|
|
142
|
+
--turquoise: #47AFB4;
|
|
143
|
+
--steel-gray: #3f5667;
|
|
144
|
+
--dark-white: #d9dbe2;
|
|
145
|
+
--light-white: #edf0f4;
|
|
146
|
+
--near-white: #f7f8fa;
|
|
147
|
+
--radius: 4px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
body {
|
|
151
|
+
color: #34373f;
|
|
152
|
+
font-family: var(--sans-serif);
|
|
153
|
+
line-height: 1.43;
|
|
154
|
+
margin: 0;
|
|
155
|
+
word-break: break-all;
|
|
156
|
+
-webkit-text-size-adjust: 100%;
|
|
157
|
+
-ms-text-size-adjust: 100%;
|
|
158
|
+
-webkit-tap-highlight-color: transparent;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
pre, code {
|
|
162
|
+
font-family: var(--monospace);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
a {
|
|
166
|
+
color: #117eb3;
|
|
167
|
+
text-decoration: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
a:hover {
|
|
171
|
+
color: #00b0e9;
|
|
172
|
+
text-decoration: underline;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
a:active,a:visited {
|
|
176
|
+
color: #00b0e9;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.flex {
|
|
180
|
+
display: flex;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.flex-wrap {
|
|
184
|
+
flex-flow: wrap;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.flex-shrink {
|
|
188
|
+
flex-shrink: 1;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.ml-auto {
|
|
192
|
+
margin-left: auto;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.nowrap {
|
|
196
|
+
white-space: nowrap
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.ipfs-hash {
|
|
200
|
+
color: #7f8491;
|
|
201
|
+
font-family: var(--monospace);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
#header {
|
|
205
|
+
align-items: center;
|
|
206
|
+
background: var(--navy);
|
|
207
|
+
border-bottom: 4px solid var(--teal);
|
|
208
|
+
color: #fff;
|
|
209
|
+
display: flex;
|
|
210
|
+
font-weight: 500;
|
|
211
|
+
justify-content: space-between;
|
|
212
|
+
padding: 0 1em;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
#header a {
|
|
216
|
+
color: var(--teal);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#header a:active {
|
|
220
|
+
color: #9ad4db;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#header a:hover {
|
|
224
|
+
color: #fff;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
#header .ipfs-logo {
|
|
228
|
+
height: 2.25em;
|
|
229
|
+
margin: .7em .7em .7em 0;
|
|
230
|
+
width: 7.15em
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
#header nav {
|
|
234
|
+
align-items: center;
|
|
235
|
+
display: flex;
|
|
236
|
+
margin: .65em 0;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
#header nav a {
|
|
240
|
+
margin: 0 .6em;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
#header nav a:last-child {
|
|
244
|
+
margin: 0 0 0 .6em;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
#header nav svg {
|
|
248
|
+
fill: var(--teal);
|
|
249
|
+
height: 1.8em;
|
|
250
|
+
margin-top: .125em;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
#header nav svg:hover {
|
|
254
|
+
fill: #fff;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
main {
|
|
258
|
+
border: 1px solid var(--dark-white);
|
|
259
|
+
border-radius: var(--radius);
|
|
260
|
+
overflow: hidden;
|
|
261
|
+
margin: 1em;
|
|
262
|
+
font-size: .875em;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
main header,main .container {
|
|
266
|
+
padding-left: 1em;
|
|
267
|
+
padding-right: 1em;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
main header {
|
|
271
|
+
padding-top: .7em;
|
|
272
|
+
padding-bottom: .7em;
|
|
273
|
+
background-color: var(--light-white);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
main header,main section:not(:last-child) {
|
|
277
|
+
border-bottom: 1px solid var(--dark-white);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
main section header {
|
|
281
|
+
background-color: var(--near-white);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.grid {
|
|
285
|
+
display: grid;
|
|
286
|
+
overflow-x: auto;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.grid .grid {
|
|
290
|
+
overflow-x: visible;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.grid > div {
|
|
294
|
+
padding: .7em;
|
|
295
|
+
border-bottom: 1px solid var(--dark-white);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.grid.dir {
|
|
299
|
+
grid-template-columns: min-content 1fr min-content min-content;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.grid.dir > div:nth-of-type(4n+1) {
|
|
303
|
+
padding-left: 1em;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.grid.dir > div:nth-of-type(4n+4) {
|
|
307
|
+
padding-right: 1em;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.grid.dir > div:nth-last-child(-n+4) {
|
|
311
|
+
border-bottom: 0;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.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) {
|
|
315
|
+
background-color: var(--near-white);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.grid.dag {
|
|
319
|
+
grid-template-columns: max-content 1fr;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.grid.dag pre {
|
|
323
|
+
margin: 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.grid.dag .grid {
|
|
327
|
+
padding: 0;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.grid.dag > div:nth-last-child(-n+2) {
|
|
331
|
+
border-bottom: 0;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.grid.dag > div {
|
|
335
|
+
background: white
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.grid.dag > div:nth-child(4n),.grid.dag > div:nth-child(4n+3) {
|
|
339
|
+
background-color: var(--near-white);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
section > .grid.dag > div:nth-of-type(2n+1) {
|
|
343
|
+
padding-left: 1em;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.type-icon,.type-icon > * {
|
|
347
|
+
width: 1.15em
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.terminal {
|
|
351
|
+
background: var(--steel-gray);
|
|
352
|
+
color: white;
|
|
353
|
+
padding: .7em;
|
|
354
|
+
border-radius: var(--radius);
|
|
355
|
+
word-wrap: break-word;
|
|
356
|
+
white-space: break-spaces;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
@media print {
|
|
360
|
+
#header {
|
|
361
|
+
display: none;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
#main header,.ipfs-hash,body {
|
|
365
|
+
color: #000;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
#main,#main header {
|
|
369
|
+
border-color: #000;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
a,a:visited {
|
|
373
|
+
color: #000;
|
|
374
|
+
text-decoration: underline;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
a[href]:after {
|
|
378
|
+
content: " (" attr(href) ")"
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
@media only screen and (max-width: 500px) {
|
|
383
|
+
.dn-mobile {
|
|
384
|
+
display: none;
|
|
385
|
+
}
|
|
386
|
+
}`;
|
|
387
|
+
//# sourceMappingURL=dir-index-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dir-index-html.js","sourceRoot":"","sources":["../../../src/utils/dir-index-html.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,7 +17,7 @@ interface GetETagArg {
|
|
|
17
17
|
/**
|
|
18
18
|
* etag
|
|
19
19
|
* you need to wrap cid with ""
|
|
20
|
-
* we use strong Etags for immutable responses and weak one (prefixed with W/ ) for mutable/generated ones (ipns and generated HTML).
|
|
20
|
+
* we use strong Etags for immutable responses and weak one (prefixed with W/ ) for mutable/generated ones (ipns, car, tar, and generated HTML).
|
|
21
21
|
* block and car responses should have different etag than deserialized one, so you can add some prefix like we do in existing gateway
|
|
22
22
|
*
|
|
23
23
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-e-tag.d.ts","sourceRoot":"","sources":["../../../src/utils/get-e-tag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,UAAU,UAAU;IAClB,GAAG,EAAE,GAAG,CAAA;IACR,SAAS,CAAC,EAAE,sBAAsB,CAAA;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;
|
|
1
|
+
{"version":3,"file":"get-e-tag.d.ts","sourceRoot":"","sources":["../../../src/utils/get-e-tag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,UAAU,UAAU;IAClB,GAAG,EAAE,GAAG,CAAA;IACR,SAAS,CAAC,EAAE,sBAAsB,CAAA;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,UAAU,GAAG,MAAM,CAQ3F"}
|
|
@@ -1,15 +1,30 @@
|
|
|
1
|
+
const getPrefix = ({ weak, reqFormat }) => {
|
|
2
|
+
if (reqFormat === 'tar' || reqFormat === 'car' || reqFormat === 'ipns-record' || weak === true) {
|
|
3
|
+
return 'W/';
|
|
4
|
+
}
|
|
5
|
+
return '';
|
|
6
|
+
};
|
|
7
|
+
const getFormatSuffix = ({ reqFormat }) => {
|
|
8
|
+
if (reqFormat == null) {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
if (reqFormat === 'tar') {
|
|
12
|
+
return '.x-tar';
|
|
13
|
+
}
|
|
14
|
+
return `.${reqFormat}`;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* etag
|
|
3
18
|
* you need to wrap cid with ""
|
|
4
|
-
* we use strong Etags for immutable responses and weak one (prefixed with W/ ) for mutable/generated ones (ipns and generated HTML).
|
|
19
|
+
* we use strong Etags for immutable responses and weak one (prefixed with W/ ) for mutable/generated ones (ipns, car, tar, and generated HTML).
|
|
5
20
|
* block and car responses should have different etag than deserialized one, so you can add some prefix like we do in existing gateway
|
|
6
21
|
*
|
|
7
22
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
|
|
8
23
|
* @see https://specs.ipfs.tech/http-gateways/path-gateway/#etag-response-header
|
|
9
24
|
*/
|
|
10
25
|
export function getETag({ cid, reqFormat, weak, rangeStart, rangeEnd }) {
|
|
11
|
-
const prefix = weak
|
|
12
|
-
let suffix = reqFormat
|
|
26
|
+
const prefix = getPrefix({ weak, reqFormat });
|
|
27
|
+
let suffix = getFormatSuffix({ reqFormat });
|
|
13
28
|
if (rangeStart != null || rangeEnd != null) {
|
|
14
29
|
suffix += `.${rangeStart ?? '0'}-${rangeEnd ?? 'N'}`;
|
|
15
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-e-tag.js","sourceRoot":"","sources":["../../../src/utils/get-e-tag.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-e-tag.js","sourceRoot":"","sources":["../../../src/utils/get-e-tag.ts"],"names":[],"mappings":"AAiBA,MAAM,SAAS,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAuB,EAAU,EAAE;IACrE,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,aAAa,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC/F,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC,CAAA;AAED,MAAM,eAAe,GAAG,CAAC,EAAE,SAAS,EAAuB,EAAU,EAAE;IACrE,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QACtB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,OAAO,IAAI,SAAS,EAAE,CAAA;AACxB,CAAC,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAc;IACjF,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;IAC7C,IAAI,MAAM,GAAG,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;IAC3C,IAAI,UAAU,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC3C,MAAM,IAAI,IAAI,UAAU,IAAI,GAAG,IAAI,QAAQ,IAAI,GAAG,EAAE,CAAA;IACtD,CAAC;IAED,OAAO,GAAG,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAA;AAChD,CAAC"}
|
|
@@ -7,11 +7,12 @@ export interface ParseResourceComponents {
|
|
|
7
7
|
logger: ComponentLogger;
|
|
8
8
|
}
|
|
9
9
|
export interface ParseResourceOptions extends ParseUrlStringOptions {
|
|
10
|
+
withServerTiming?: boolean;
|
|
10
11
|
}
|
|
11
12
|
/**
|
|
12
13
|
* Handles the different use cases for the `resource` argument.
|
|
13
14
|
* The resource can represent an IPFS path, IPNS path, or CID.
|
|
14
15
|
* If the resource represents an IPNS path, we need to resolve it to a CID.
|
|
15
16
|
*/
|
|
16
|
-
export declare function parseResource(resource: Resource, { ipns, logger }: ParseResourceComponents, options?: ParseResourceOptions): Promise<ParsedUrlStringResults>;
|
|
17
|
+
export declare function parseResource(resource: Resource, { ipns, logger }: ParseResourceComponents, { withServerTiming, ...options }?: ParseResourceOptions): Promise<ParsedUrlStringResults>;
|
|
17
18
|
//# sourceMappingURL=parse-resource.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-resource.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-resource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC1F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB;
|
|
1
|
+
{"version":3,"file":"parse-resource.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-resource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC1F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AACD;;;;GAIG;AACH,wBAAsB,aAAa,CAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,uBAAuB,EAAE,EAAE,gBAAwB,EAAE,GAAG,OAAO,EAAE,GAAE,oBAAkD,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAqBjO"}
|
|
@@ -5,9 +5,9 @@ import { parseUrlString } from './parse-url-string.js';
|
|
|
5
5
|
* The resource can represent an IPFS path, IPNS path, or CID.
|
|
6
6
|
* If the resource represents an IPNS path, we need to resolve it to a CID.
|
|
7
7
|
*/
|
|
8
|
-
export async function parseResource(resource, { ipns, logger }, options) {
|
|
8
|
+
export async function parseResource(resource, { ipns, logger }, { withServerTiming = false, ...options } = { withServerTiming: false }) {
|
|
9
9
|
if (typeof resource === 'string') {
|
|
10
|
-
return parseUrlString({ urlString: resource, ipns, logger }, options);
|
|
10
|
+
return parseUrlString({ urlString: resource, ipns, logger, withServerTiming }, options);
|
|
11
11
|
}
|
|
12
12
|
const cid = CID.asCID(resource);
|
|
13
13
|
if (cid != null) {
|
|
@@ -18,7 +18,8 @@ export async function parseResource(resource, { ipns, logger }, options) {
|
|
|
18
18
|
path: '',
|
|
19
19
|
query: {},
|
|
20
20
|
ipfsPath: `/ipfs/${cid.toString()}`,
|
|
21
|
-
ttl: 29030400 // 1 year for ipfs content
|
|
21
|
+
ttl: 29030400, // 1 year for ipfs content
|
|
22
|
+
serverTimings: []
|
|
22
23
|
};
|
|
23
24
|
}
|
|
24
25
|
throw new TypeError(`Invalid resource. Cannot determine CID from resource: ${resource}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-resource.js","sourceRoot":"","sources":["../../../src/utils/parse-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AActD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAE,QAAkB,EAAE,EAAE,IAAI,EAAE,MAAM,EAA2B,EAAE,
|
|
1
|
+
{"version":3,"file":"parse-resource.js","sourceRoot":"","sources":["../../../src/utils/parse-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AActD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAE,QAAkB,EAAE,EAAE,IAAI,EAAE,MAAM,EAA2B,EAAE,EAAE,gBAAgB,GAAG,KAAK,EAAE,GAAG,OAAO,KAA2B,EAAE,gBAAgB,EAAE,KAAK,EAAE;IAC9L,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,cAAc,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,EAAE,OAAO,CAAC,CAAA;IACzF,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IAE/B,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QAChB,gBAAgB;QAChB,OAAO;YACL,GAAG;YACH,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,EAAE;YACT,QAAQ,EAAE,SAAS,GAAG,CAAC,QAAQ,EAAE,EAAE;YACnC,GAAG,EAAE,QAAQ,EAAE,0BAA0B;YACzC,aAAa,EAAE,EAAE;SACe,CAAA;IACpC,CAAC;IAED,MAAM,IAAI,SAAS,CAAC,yDAAyD,QAAQ,EAAE,CAAC,CAAA;AAC1F,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ServerTimingResult } from './server-timing.js';
|
|
1
2
|
import type { RequestFormatShorthand } from '../types.js';
|
|
2
3
|
import type { IPNS, IPNSRoutingEvents, ResolveDNSLinkProgressEvents, ResolveProgressEvents, ResolveResult } from '@helia/ipns';
|
|
3
4
|
import type { AbortOptions, ComponentLogger } from '@libp2p/interface';
|
|
@@ -6,6 +7,7 @@ export interface ParseUrlStringInput {
|
|
|
6
7
|
urlString: string;
|
|
7
8
|
ipns: IPNS;
|
|
8
9
|
logger: ComponentLogger;
|
|
10
|
+
withServerTiming?: boolean;
|
|
9
11
|
}
|
|
10
12
|
export interface ParseUrlStringOptions extends ProgressOptions<ResolveProgressEvents | IPNSRoutingEvents | ResolveDNSLinkProgressEvents>, AbortOptions {
|
|
11
13
|
}
|
|
@@ -14,7 +16,7 @@ export interface ParsedUrlQuery extends Record<string, string | unknown> {
|
|
|
14
16
|
download?: boolean;
|
|
15
17
|
filename?: string;
|
|
16
18
|
}
|
|
17
|
-
interface
|
|
19
|
+
export interface ParsedUrlStringResults extends ResolveResult {
|
|
18
20
|
protocol: 'ipfs' | 'ipns';
|
|
19
21
|
query: ParsedUrlQuery;
|
|
20
22
|
/**
|
|
@@ -30,8 +32,11 @@ interface ParsedUrlStringResultsBase extends ResolveResult {
|
|
|
30
32
|
* seconds as a number
|
|
31
33
|
*/
|
|
32
34
|
ttl?: number;
|
|
35
|
+
/**
|
|
36
|
+
* serverTiming items
|
|
37
|
+
*/
|
|
38
|
+
serverTimings: Array<ServerTimingResult<any>>;
|
|
33
39
|
}
|
|
34
|
-
export type ParsedUrlStringResults = ParsedUrlStringResultsBase;
|
|
35
40
|
interface MatchUrlGroups {
|
|
36
41
|
protocol: 'ipfs' | 'ipns';
|
|
37
42
|
cidOrPeerIdOrDnsLink: string;
|
|
@@ -48,6 +53,6 @@ export declare function matchURLString(urlString: string): MatchUrlGroups;
|
|
|
48
53
|
*
|
|
49
54
|
* @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
|
|
50
55
|
*/
|
|
51
|
-
export declare function parseUrlString({ urlString, ipns, logger }: ParseUrlStringInput, options?: ParseUrlStringOptions): Promise<ParsedUrlStringResults>;
|
|
56
|
+
export declare function parseUrlString({ urlString, ipns, logger, withServerTiming }: ParseUrlStringInput, options?: ParseUrlStringOptions): Promise<ParsedUrlStringResults>;
|
|
52
57
|
export {};
|
|
53
58
|
//# sourceMappingURL=parse-url-string.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-url-string.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parse-url-string.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAwB,IAAI,EAAqB,iBAAiB,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACvK,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAU,MAAM,mBAAmB,CAAA;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAItD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,eAAe,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AACD,MAAM,WAAW,qBAAsB,SAAQ,eAAe,CAAC,qBAAqB,GAAG,iBAAiB,GAAG,4BAA4B,CAAC,EAAE,YAAY;CAErJ;AAED,MAAM,WAAW,cAAe,SAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACtE,MAAM,CAAC,EAAE,sBAAsB,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC3D,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,KAAK,EAAE,cAAc,CAAA;IAErB;;;;;;;OAOG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAA;CAC9C;AAOD,UAAU,cAAc;IACtB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAgBD,wBAAgB,cAAc,CAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAUjE;AAsDD;;;;;;;;GAQG;AAEH,wBAAsB,cAAc,CAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAwB,EAAE,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAkJlL"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CID } from 'multiformats/cid';
|
|
2
2
|
import { getPeerIdFromString } from './get-peer-id-from-string.js';
|
|
3
|
+
import { serverTiming } from './server-timing.js';
|
|
3
4
|
import { TLRU } from './tlru.js';
|
|
4
5
|
const ipnsCache = new TLRU(1000);
|
|
5
6
|
const URL_REGEX = /^(?<protocol>ip[fn]s):\/\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/;
|
|
@@ -86,13 +87,14 @@ function dnsLinkLabelDecoder(linkLabel) {
|
|
|
86
87
|
* @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
|
|
87
88
|
*/
|
|
88
89
|
// eslint-disable-next-line complexity
|
|
89
|
-
export async function parseUrlString({ urlString, ipns, logger }, options) {
|
|
90
|
+
export async function parseUrlString({ urlString, ipns, logger, withServerTiming = false }, options) {
|
|
90
91
|
const log = logger.forComponent('helia:verified-fetch:parse-url-string');
|
|
91
92
|
const { protocol, cidOrPeerIdOrDnsLink, path: urlPath, queryString } = matchURLString(urlString);
|
|
92
93
|
let cid;
|
|
93
94
|
let resolvedPath;
|
|
94
95
|
const errors = [];
|
|
95
96
|
let resolveResult;
|
|
97
|
+
const serverTimings = [];
|
|
96
98
|
if (protocol === 'ipfs') {
|
|
97
99
|
try {
|
|
98
100
|
cid = CID.parse(cidOrPeerIdOrDnsLink);
|
|
@@ -122,7 +124,18 @@ export async function parseUrlString({ urlString, ipns, logger }, options) {
|
|
|
122
124
|
if (peerId.publicKey == null) {
|
|
123
125
|
throw new TypeError('cidOrPeerIdOrDnsLink contains no public key');
|
|
124
126
|
}
|
|
125
|
-
|
|
127
|
+
if (withServerTiming) {
|
|
128
|
+
const resolveResultWithServerTiming = await serverTiming('ipns.resolve', `Resolve IPNS name ${cidOrPeerIdOrDnsLink}`, ipns.resolve.bind(null, peerId.publicKey, options));
|
|
129
|
+
serverTimings.push(resolveResultWithServerTiming);
|
|
130
|
+
// eslint-disable-next-line max-depth
|
|
131
|
+
if (resolveResultWithServerTiming.error != null) {
|
|
132
|
+
throw resolveResultWithServerTiming.error;
|
|
133
|
+
}
|
|
134
|
+
resolveResult = resolveResultWithServerTiming.result;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
resolveResult = await ipns.resolve(peerId.publicKey, options);
|
|
138
|
+
}
|
|
126
139
|
cid = resolveResult?.cid;
|
|
127
140
|
resolvedPath = resolveResult?.path;
|
|
128
141
|
log.trace('resolved %s to %c', cidOrPeerIdOrDnsLink, cid);
|
|
@@ -147,7 +160,19 @@ export async function parseUrlString({ urlString, ipns, logger }, options) {
|
|
|
147
160
|
}
|
|
148
161
|
log.trace('Attempting to resolve DNSLink for %s', decodedDnsLinkLabel);
|
|
149
162
|
try {
|
|
150
|
-
|
|
163
|
+
// eslint-disable-next-line max-depth
|
|
164
|
+
if (withServerTiming) {
|
|
165
|
+
const resolveResultWithServerTiming = await serverTiming('ipns.resolveDNSLink', `Resolve DNSLink ${decodedDnsLinkLabel}`, ipns.resolveDNSLink.bind(ipns, decodedDnsLinkLabel, options));
|
|
166
|
+
serverTimings.push(resolveResultWithServerTiming);
|
|
167
|
+
// eslint-disable-next-line max-depth
|
|
168
|
+
if (resolveResultWithServerTiming.error != null) {
|
|
169
|
+
throw resolveResultWithServerTiming.error;
|
|
170
|
+
}
|
|
171
|
+
resolveResult = resolveResultWithServerTiming.result;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
resolveResult = await ipns.resolveDNSLink(decodedDnsLinkLabel, options);
|
|
175
|
+
}
|
|
151
176
|
cid = resolveResult?.cid;
|
|
152
177
|
resolvedPath = resolveResult?.path;
|
|
153
178
|
log.trace('resolved %s to %c', decodedDnsLinkLabel, cid);
|
|
@@ -195,7 +220,8 @@ export async function parseUrlString({ urlString, ipns, logger }, options) {
|
|
|
195
220
|
path: joinPaths(resolvedPath, urlPath ?? ''),
|
|
196
221
|
query,
|
|
197
222
|
ttl,
|
|
198
|
-
ipfsPath: `/${protocol}/${cidOrPeerIdOrDnsLink}${urlPath != null && urlPath !== '' ? `/${urlPath}` : ''}
|
|
223
|
+
ipfsPath: `/${protocol}/${cidOrPeerIdOrDnsLink}${urlPath != null && urlPath !== '' ? `/${urlPath}` : ''}`,
|
|
224
|
+
serverTimings
|
|
199
225
|
};
|
|
200
226
|
}
|
|
201
227
|
/**
|