@cloudflare/pages-shared 0.0.0-ship-js

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 (91) hide show
  1. package/README.md +5 -0
  2. package/asset-server/handler.ts +625 -0
  3. package/asset-server/metadata.ts +67 -0
  4. package/asset-server/patchUrl.ts +22 -0
  5. package/asset-server/responses.ts +196 -0
  6. package/asset-server/rulesEngine.ts +82 -0
  7. package/dist/__tests__/asset-server/handler.test.d.ts +2 -0
  8. package/dist/__tests__/asset-server/handler.test.d.ts.map +1 -0
  9. package/dist/__tests__/asset-server/handler.test.js +430 -0
  10. package/dist/__tests__/asset-server/responses.test.d.ts +2 -0
  11. package/dist/__tests__/asset-server/responses.test.d.ts.map +1 -0
  12. package/dist/__tests__/asset-server/responses.test.js +22 -0
  13. package/dist/__tests__/asset-server/rulesEngine.test.d.ts +2 -0
  14. package/dist/__tests__/asset-server/rulesEngine.test.d.ts.map +1 -0
  15. package/dist/__tests__/asset-server/rulesEngine.test.js +70 -0
  16. package/dist/__tests__/jest.setup.d.ts +2 -0
  17. package/dist/__tests__/jest.setup.d.ts.map +1 -0
  18. package/dist/__tests__/jest.setup.js +7 -0
  19. package/dist/__tests__/metadata-generator/createMetadataObject.test.d.ts +2 -0
  20. package/dist/__tests__/metadata-generator/createMetadataObject.test.d.ts.map +1 -0
  21. package/dist/__tests__/metadata-generator/createMetadataObject.test.js +293 -0
  22. package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.d.ts +2 -0
  23. package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.d.ts.map +1 -0
  24. package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.js +194 -0
  25. package/dist/__tests__/metadata-generator/parseHeaders.valid.test.d.ts +2 -0
  26. package/dist/__tests__/metadata-generator/parseHeaders.valid.test.d.ts.map +1 -0
  27. package/dist/__tests__/metadata-generator/parseHeaders.valid.test.js +132 -0
  28. package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.d.ts +2 -0
  29. package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.d.ts.map +1 -0
  30. package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.js +243 -0
  31. package/dist/__tests__/metadata-generator/parseRedirects.valid.test.d.ts +2 -0
  32. package/dist/__tests__/metadata-generator/parseRedirects.valid.test.d.ts.map +1 -0
  33. package/dist/__tests__/metadata-generator/parseRedirects.valid.test.js +88 -0
  34. package/dist/asset-server/handler.d.ts +44 -0
  35. package/dist/asset-server/handler.d.ts.map +1 -0
  36. package/dist/asset-server/handler.js +420 -0
  37. package/dist/asset-server/metadata.d.ts +52 -0
  38. package/dist/asset-server/metadata.d.ts.map +1 -0
  39. package/dist/asset-server/metadata.js +3 -0
  40. package/dist/asset-server/patchUrl.d.ts +2 -0
  41. package/dist/asset-server/patchUrl.d.ts.map +1 -0
  42. package/dist/asset-server/patchUrl.js +19 -0
  43. package/dist/asset-server/responses.d.ts +45 -0
  44. package/dist/asset-server/responses.d.ts.map +1 -0
  45. package/dist/asset-server/responses.js +165 -0
  46. package/dist/asset-server/rulesEngine.d.ts +7 -0
  47. package/dist/asset-server/rulesEngine.d.ts.map +1 -0
  48. package/dist/asset-server/rulesEngine.js +68 -0
  49. package/dist/environment-polyfills/index.d.ts +3 -0
  50. package/dist/environment-polyfills/index.d.ts.map +1 -0
  51. package/dist/environment-polyfills/index.js +14 -0
  52. package/dist/environment-polyfills/miniflare-tre.d.ts +3 -0
  53. package/dist/environment-polyfills/miniflare-tre.d.ts.map +1 -0
  54. package/dist/environment-polyfills/miniflare-tre.js +35 -0
  55. package/dist/environment-polyfills/miniflare.d.ts +3 -0
  56. package/dist/environment-polyfills/miniflare.d.ts.map +1 -0
  57. package/dist/environment-polyfills/miniflare.js +35 -0
  58. package/dist/environment-polyfills/types.d.ts +34 -0
  59. package/dist/environment-polyfills/types.d.ts.map +1 -0
  60. package/dist/environment-polyfills/types.js +5 -0
  61. package/dist/metadata-generator/constants.d.ts +14 -0
  62. package/dist/metadata-generator/constants.d.ts.map +1 -0
  63. package/dist/metadata-generator/constants.js +16 -0
  64. package/dist/metadata-generator/createMetadataObject.d.ts +10 -0
  65. package/dist/metadata-generator/createMetadataObject.d.ts.map +1 -0
  66. package/dist/metadata-generator/createMetadataObject.js +105 -0
  67. package/dist/metadata-generator/parseHeaders.d.ts +3 -0
  68. package/dist/metadata-generator/parseHeaders.d.ts.map +1 -0
  69. package/dist/metadata-generator/parseHeaders.js +146 -0
  70. package/dist/metadata-generator/parseRedirects.d.ts +3 -0
  71. package/dist/metadata-generator/parseRedirects.d.ts.map +1 -0
  72. package/dist/metadata-generator/parseRedirects.js +100 -0
  73. package/dist/metadata-generator/types.d.ts +74 -0
  74. package/dist/metadata-generator/types.d.ts.map +1 -0
  75. package/dist/metadata-generator/types.js +3 -0
  76. package/dist/metadata-generator/validateURL.d.ts +3 -0
  77. package/dist/metadata-generator/validateURL.d.ts.map +1 -0
  78. package/dist/metadata-generator/validateURL.js +46 -0
  79. package/dist/tsconfig.tsbuildinfo +1 -0
  80. package/environment-polyfills/index.ts +14 -0
  81. package/environment-polyfills/miniflare-tre.ts +12 -0
  82. package/environment-polyfills/miniflare.ts +12 -0
  83. package/environment-polyfills/types.ts +42 -0
  84. package/metadata-generator/constants.ts +15 -0
  85. package/metadata-generator/createMetadataObject.ts +164 -0
  86. package/metadata-generator/parseHeaders.ts +168 -0
  87. package/metadata-generator/parseRedirects.ts +129 -0
  88. package/metadata-generator/types.ts +90 -0
  89. package/metadata-generator/validateURL.ts +57 -0
  90. package/package.json +63 -0
  91. package/tsconfig.json +13 -0
@@ -0,0 +1,420 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseQualityWeightedList = exports.generateHandler = exports.normaliseHeaders = exports.ANALYTICS_VERSION = exports.HEADERS_VERSION_V1 = exports.HEADERS_VERSION = exports.REDIRECTS_VERSION = exports.CACHE_CONTROL_BROWSER = exports.ASSET_PRESERVATION_CACHE = void 0;
4
+ const responses_1 = require("./responses");
5
+ const rulesEngine_1 = require("./rulesEngine");
6
+ // Before serving a 404, we check the cache to see if we've served this asset recently
7
+ // and if so, serve it from the cache instead of responding with a 404.
8
+ // This gives a bit of a grace period between deployments for any clients browsing the old deployment.
9
+ exports.ASSET_PRESERVATION_CACHE = "assetPreservationCache";
10
+ const CACHE_CONTROL_PRESERVATION = "public, s-maxage=604800"; // 1 week
11
+ exports.CACHE_CONTROL_BROWSER = "public, max-age=0, must-revalidate"; // have the browser check in with the server to make sure its local cache is valid before using it
12
+ exports.REDIRECTS_VERSION = 1;
13
+ exports.HEADERS_VERSION = 2;
14
+ exports.HEADERS_VERSION_V1 = 1;
15
+ exports.ANALYTICS_VERSION = 1;
16
+ // In rolling this out, we're taking a conservative approach to only generate these Link headers from <link> elements that have these attributes.
17
+ // We'll ignore any <link> elements that contain other attributes (e.g. `fetchpriority`, `crossorigin` or `data-please-dont-generate-a-header`).
18
+ // We're not confident in browser support for all of these additional attributes, so we'll wait until we have that information before proceeding further.
19
+ const ALLOWED_EARLY_HINT_LINK_ATTRIBUTES = ["rel", "as", "href"];
20
+ // Takes metadata headers and "normalise" them
21
+ // to the latest version
22
+ function normaliseHeaders(headers) {
23
+ if (headers.version === exports.HEADERS_VERSION) {
24
+ return headers.rules;
25
+ }
26
+ else if (headers.version === exports.HEADERS_VERSION_V1) {
27
+ return Object.keys(headers.rules).reduce((acc, key) => {
28
+ acc[key] = {
29
+ set: headers.rules[key],
30
+ };
31
+ return acc;
32
+ }, {});
33
+ }
34
+ else {
35
+ return {};
36
+ }
37
+ }
38
+ exports.normaliseHeaders = normaliseHeaders;
39
+ async function generateHandler({ request, metadata, xServerEnvHeader, logError, findAssetEntryForPath, getAssetKey, negotiateContent, fetchAsset, generateNotFoundResponse = async (notFoundRequest, notFoundFindAssetEntryForPath, notFoundServeAsset) => {
40
+ let assetEntry;
41
+ // No custom 404 page, so try serving as a single-page app
42
+ if ((assetEntry = await notFoundFindAssetEntryForPath("/index.html"))) {
43
+ return notFoundServeAsset(assetEntry, { preserve: false });
44
+ }
45
+ return new responses_1.NotFoundResponse();
46
+ }, attachAdditionalHeaders = () => { }, caches, waitUntil, }) {
47
+ const url = new URL(request.url);
48
+ const { protocol, host, search } = url;
49
+ let { pathname } = url;
50
+ const earlyHintsCache = metadata.deploymentId
51
+ ? await caches?.open(`eh:${metadata.deploymentId}`)
52
+ : undefined;
53
+ const headerRules = metadata.headers
54
+ ? normaliseHeaders(metadata.headers)
55
+ : {};
56
+ const staticRules = metadata.redirects?.version === exports.REDIRECTS_VERSION
57
+ ? metadata.redirects.staticRules || {}
58
+ : {};
59
+ const staticRedirectsMatcher = () => {
60
+ const withHostMatch = staticRules[`https://${host}${pathname}`];
61
+ const withoutHostMatch = staticRules[pathname];
62
+ if (withHostMatch && withoutHostMatch) {
63
+ if (withHostMatch.lineNumber < withoutHostMatch.lineNumber) {
64
+ return withHostMatch;
65
+ }
66
+ else {
67
+ return withoutHostMatch;
68
+ }
69
+ }
70
+ return withHostMatch || withoutHostMatch;
71
+ };
72
+ const generateRedirectsMatcher = () => (0, rulesEngine_1.generateRulesMatcher)(metadata.redirects?.version === exports.REDIRECTS_VERSION
73
+ ? metadata.redirects.rules
74
+ : {}, ({ status, to }, replacements) => ({
75
+ status,
76
+ to: (0, rulesEngine_1.replacer)(to, replacements),
77
+ }));
78
+ let assetEntry;
79
+ async function generateResponse() {
80
+ const match = staticRedirectsMatcher() || generateRedirectsMatcher()({ request })[0];
81
+ if (match) {
82
+ const { status, to } = match;
83
+ const destination = new URL(to, request.url);
84
+ const location = destination.origin === new URL(request.url).origin
85
+ ? `${destination.pathname}${destination.search || search}${destination.hash}`
86
+ : `${destination.href}${destination.search ? "" : search}${destination.hash}`;
87
+ switch (status) {
88
+ case 301:
89
+ return new responses_1.MovedPermanentlyResponse(location, undefined, {
90
+ preventLeadingDoubleSlash: false,
91
+ });
92
+ case 303:
93
+ return new responses_1.SeeOtherResponse(location, undefined, {
94
+ preventLeadingDoubleSlash: false,
95
+ });
96
+ case 307:
97
+ return new responses_1.TemporaryRedirectResponse(location, undefined, {
98
+ preventLeadingDoubleSlash: false,
99
+ });
100
+ case 308:
101
+ return new responses_1.PermanentRedirectResponse(location, undefined, {
102
+ preventLeadingDoubleSlash: false,
103
+ });
104
+ case 302:
105
+ default:
106
+ return new responses_1.FoundResponse(location, undefined, {
107
+ preventLeadingDoubleSlash: false,
108
+ });
109
+ }
110
+ }
111
+ if (!request.method.match(/^(get|head)$/i)) {
112
+ return new responses_1.MethodNotAllowedResponse();
113
+ }
114
+ try {
115
+ pathname = globalThis.decodeURIComponent(pathname);
116
+ }
117
+ catch (err) { }
118
+ if (pathname.endsWith("/")) {
119
+ if ((assetEntry = await findAssetEntryForPath(`${pathname}index.html`))) {
120
+ return serveAsset(assetEntry);
121
+ }
122
+ else if (pathname.endsWith("/index/")) {
123
+ return new responses_1.PermanentRedirectResponse(`/${pathname.slice(1, -"index/".length)}${search}`);
124
+ }
125
+ else if ((assetEntry = await findAssetEntryForPath(`${pathname.replace(/\/$/, ".html")}`))) {
126
+ return new responses_1.PermanentRedirectResponse(`/${pathname.slice(1, -1)}${search}`);
127
+ }
128
+ else {
129
+ return notFound();
130
+ }
131
+ }
132
+ if ((assetEntry = await findAssetEntryForPath(pathname))) {
133
+ if (pathname.endsWith(".html")) {
134
+ const extensionlessPath = pathname.slice(0, -".html".length);
135
+ // Don't redirect to an extensionless URL if another asset exists there
136
+ // or if pathname is /.html
137
+ // FIXME: this doesn't handle files in directories ie: /foobar/.html
138
+ if (extensionlessPath.endsWith("/index")) {
139
+ return new responses_1.PermanentRedirectResponse(`${extensionlessPath.replace(/\/index$/, "/")}${search}`);
140
+ }
141
+ else if ((await findAssetEntryForPath(extensionlessPath)) ||
142
+ extensionlessPath === "/") {
143
+ return serveAsset(assetEntry);
144
+ }
145
+ else {
146
+ return new responses_1.PermanentRedirectResponse(`${extensionlessPath}${search}`);
147
+ }
148
+ }
149
+ else {
150
+ return serveAsset(assetEntry);
151
+ }
152
+ }
153
+ else if (pathname.endsWith("/index")) {
154
+ return new responses_1.PermanentRedirectResponse(`/${pathname.slice(1, -"index".length)}${search}`);
155
+ }
156
+ else if ((assetEntry = await findAssetEntryForPath(`${pathname}.html`))) {
157
+ return serveAsset(assetEntry);
158
+ }
159
+ else if (hasFileExtension(pathname)) {
160
+ return notFound();
161
+ }
162
+ if ((assetEntry = await findAssetEntryForPath(`${pathname}/index.html`))) {
163
+ return new responses_1.PermanentRedirectResponse(`${pathname}/${search}`);
164
+ }
165
+ else {
166
+ return notFound();
167
+ }
168
+ }
169
+ async function attachHeaders(response) {
170
+ const existingHeaders = new Headers(response.headers);
171
+ const extraHeaders = new Headers({
172
+ "access-control-allow-origin": "*",
173
+ "referrer-policy": "strict-origin-when-cross-origin",
174
+ ...(existingHeaders.has("content-type")
175
+ ? { "x-content-type-options": "nosniff" }
176
+ : {}),
177
+ });
178
+ const headers = new Headers({
179
+ // But we intentionally override existing headers
180
+ ...Object.fromEntries(existingHeaders.entries()),
181
+ ...Object.fromEntries(extraHeaders.entries()),
182
+ });
183
+ if (earlyHintsCache) {
184
+ const preEarlyHintsHeaders = new Headers(headers);
185
+ // "Early Hints cache entries are keyed by request URI and ignore query strings."
186
+ // https://developers.cloudflare.com/cache/about/early-hints/
187
+ const earlyHintsCacheKey = `${protocol}//${host}${pathname}`;
188
+ const earlyHintsResponse = await earlyHintsCache.match(earlyHintsCacheKey);
189
+ if (earlyHintsResponse) {
190
+ const earlyHintsLinkHeader = earlyHintsResponse.headers.get("Link");
191
+ if (earlyHintsLinkHeader) {
192
+ headers.set("Link", earlyHintsLinkHeader);
193
+ }
194
+ }
195
+ const clonedResponse = response.clone();
196
+ if (waitUntil) {
197
+ waitUntil((async () => {
198
+ try {
199
+ const links = [];
200
+ const transformedResponse = new HTMLRewriter()
201
+ .on("link[rel~=preconnect],link[rel~=preload]", {
202
+ element(element) {
203
+ for (const [attributeName] of element.attributes) {
204
+ if (!ALLOWED_EARLY_HINT_LINK_ATTRIBUTES.includes(attributeName.toLowerCase())) {
205
+ return;
206
+ }
207
+ }
208
+ const href = element.getAttribute("href") || undefined;
209
+ const rel = element.getAttribute("rel") || undefined;
210
+ const as = element.getAttribute("as") || undefined;
211
+ if (href && !href.startsWith("data:") && rel) {
212
+ links.push({ href, rel, as });
213
+ }
214
+ },
215
+ })
216
+ .transform(clonedResponse);
217
+ // Needed to actually execute the HTMLRewriter handlers
218
+ await transformedResponse.text();
219
+ links.forEach(({ href, rel, as }) => {
220
+ let link = `<${href}>; rel="${rel}"`;
221
+ if (as) {
222
+ link += `; as=${as}`;
223
+ }
224
+ preEarlyHintsHeaders.append("Link", link);
225
+ });
226
+ const linkHeader = preEarlyHintsHeaders.get("Link");
227
+ if (linkHeader) {
228
+ await earlyHintsCache.put(earlyHintsCacheKey, new Response(null, { headers: { Link: linkHeader } }));
229
+ }
230
+ }
231
+ catch (err) {
232
+ // Nbd if we fail here in the deferred 'waitUntil' work. We're probably trying to parse a malformed page or something.
233
+ // Totally fine to skip over any errors.
234
+ // If we need to debug something, you can uncomment the following:
235
+ // logError(err)
236
+ }
237
+ })());
238
+ }
239
+ }
240
+ // Iterate through rules and find rules that match the path
241
+ const headersMatcher = (0, rulesEngine_1.generateRulesMatcher)(headerRules, ({ set = {}, unset = [] }, replacements) => {
242
+ const replacedSet = {};
243
+ Object.keys(set).forEach((key) => {
244
+ replacedSet[key] = (0, rulesEngine_1.replacer)(set[key], replacements);
245
+ });
246
+ return {
247
+ set: replacedSet,
248
+ unset,
249
+ };
250
+ });
251
+ const matches = headersMatcher({ request });
252
+ // This keeps track of every header that we've set from _headers
253
+ // because we want to combine user declared headers but overwrite
254
+ // existing and extra ones
255
+ const setMap = new Set();
256
+ // Apply every matched rule in order
257
+ matches.forEach(({ set = {}, unset = [] }) => {
258
+ unset.forEach((key) => {
259
+ headers.delete(key);
260
+ });
261
+ Object.keys(set).forEach((key) => {
262
+ if (setMap.has(key.toLowerCase())) {
263
+ headers.append(key, set[key]);
264
+ }
265
+ else {
266
+ headers.set(key, set[key]);
267
+ setMap.add(key.toLowerCase());
268
+ }
269
+ });
270
+ });
271
+ // https://fetch.spec.whatwg.org/#null-body-status
272
+ return new Response([101, 204, 205, 304].includes(response.status) ? null : response.body, {
273
+ headers: headers,
274
+ status: response.status,
275
+ statusText: response.statusText,
276
+ });
277
+ }
278
+ return await attachHeaders(await generateResponse());
279
+ async function serveAsset(servingAssetEntry, options = { preserve: true }) {
280
+ let content;
281
+ try {
282
+ content = negotiateContent(request, servingAssetEntry);
283
+ }
284
+ catch (err) {
285
+ return new responses_1.NotAcceptableResponse();
286
+ }
287
+ const assetKey = getAssetKey(servingAssetEntry, content);
288
+ // https://support.cloudflare.com/hc/en-us/articles/218505467-Using-ETag-Headers-with-Cloudflare
289
+ // We sometimes remove etags unless they are wrapped in quotes
290
+ const etag = `"${assetKey}"`;
291
+ const weakEtag = `W/${etag}`;
292
+ const ifNoneMatch = request.headers.get("if-none-match");
293
+ // We sometimes downgrade strong etags to a weak ones, so we need to check for both
294
+ if (ifNoneMatch === weakEtag || ifNoneMatch === etag) {
295
+ return new responses_1.NotModifiedResponse();
296
+ }
297
+ try {
298
+ const asset = await fetchAsset(assetKey);
299
+ const headers = {
300
+ etag,
301
+ "content-type": asset.contentType,
302
+ };
303
+ let encodeBody = "automatic";
304
+ if (xServerEnvHeader) {
305
+ headers["x-server-env"] = xServerEnvHeader;
306
+ }
307
+ if (content.encoding) {
308
+ encodeBody = "manual";
309
+ headers["cache-control"] = "no-transform";
310
+ headers["content-encoding"] = content.encoding;
311
+ }
312
+ const response = new responses_1.OkResponse(request.method === "HEAD" ? null : asset.body, {
313
+ headers,
314
+ encodeBody,
315
+ });
316
+ if (isCacheable(request)) {
317
+ response.headers.append("cache-control", exports.CACHE_CONTROL_BROWSER);
318
+ }
319
+ attachAdditionalHeaders(response, content, servingAssetEntry, asset);
320
+ if (isPreview(new URL(request.url))) {
321
+ response.headers.set("x-robots-tag", "noindex");
322
+ }
323
+ if (options.preserve) {
324
+ // https://fetch.spec.whatwg.org/#null-body-status
325
+ const preservedResponse = new Response([101, 204, 205, 304].includes(response.status)
326
+ ? null
327
+ : response.clone().body, response);
328
+ preservedResponse.headers.set("cache-control", CACHE_CONTROL_PRESERVATION);
329
+ preservedResponse.headers.set("x-robots-tag", "noindex");
330
+ if (waitUntil && caches) {
331
+ waitUntil(caches
332
+ .open(exports.ASSET_PRESERVATION_CACHE)
333
+ .then((assetPreservationCache) => assetPreservationCache.put(request.url, preservedResponse))
334
+ .catch((err) => {
335
+ logError(err);
336
+ }));
337
+ }
338
+ }
339
+ if (asset.contentType.startsWith("text/html") &&
340
+ metadata.analytics?.version === exports.ANALYTICS_VERSION) {
341
+ return new HTMLRewriter()
342
+ .on("body", {
343
+ element(e) {
344
+ e.append(`<!-- Cloudflare Pages Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "${metadata.analytics?.token}"}'></script><!-- Cloudflare Pages Analytics -->`, { html: true });
345
+ },
346
+ })
347
+ .transform(response);
348
+ }
349
+ return response;
350
+ }
351
+ catch (err) {
352
+ logError(err);
353
+ return new responses_1.InternalServerErrorResponse(err);
354
+ }
355
+ }
356
+ async function notFound() {
357
+ if (caches) {
358
+ const assetPreservationCache = await caches.open(exports.ASSET_PRESERVATION_CACHE);
359
+ const preservedResponse = await assetPreservationCache.match(request.url);
360
+ if (preservedResponse) {
361
+ return preservedResponse;
362
+ }
363
+ }
364
+ // Traverse upwards from the current path looking for a custom 404 page
365
+ let cwd = pathname;
366
+ while (cwd) {
367
+ cwd = cwd.slice(0, cwd.lastIndexOf("/"));
368
+ if ((assetEntry = await findAssetEntryForPath(`${cwd}/404.html`))) {
369
+ let content;
370
+ try {
371
+ content = negotiateContent(request, assetEntry);
372
+ }
373
+ catch (err) {
374
+ return new responses_1.NotAcceptableResponse();
375
+ }
376
+ const assetKey = getAssetKey(assetEntry, content);
377
+ try {
378
+ const { body, contentType } = await fetchAsset(assetKey);
379
+ const response = new responses_1.NotFoundResponse(body);
380
+ response.headers.set("content-type", contentType);
381
+ return response;
382
+ }
383
+ catch (err) {
384
+ logError(err);
385
+ return new responses_1.InternalServerErrorResponse(err);
386
+ }
387
+ }
388
+ }
389
+ return await generateNotFoundResponse(request, findAssetEntryForPath, serveAsset);
390
+ }
391
+ }
392
+ exports.generateHandler = generateHandler;
393
+ // Parses a list such as "deflate, gzip;q=1.0, *;q=0.5" into
394
+ // {deflate: 1, gzip: 1, *: 0.5}
395
+ function parseQualityWeightedList(list = "") {
396
+ const items = {};
397
+ list
398
+ .replace(/\s/g, "")
399
+ .split(",")
400
+ .forEach((el) => {
401
+ const [item, weight] = el.split(";q=");
402
+ items[item] = weight ? parseFloat(weight) : 1;
403
+ });
404
+ return items;
405
+ }
406
+ exports.parseQualityWeightedList = parseQualityWeightedList;
407
+ function isCacheable(request) {
408
+ return !request.headers.has("authorization") && !request.headers.has("range");
409
+ }
410
+ function hasFileExtension(path) {
411
+ return /\/.+\.[a-z0-9]+$/i.test(path);
412
+ }
413
+ // Parses a request URL hostname to determine if the request
414
+ // is from a project served in "preview" mode.
415
+ function isPreview(url) {
416
+ if (url.hostname.endsWith(".pages.dev")) {
417
+ return url.hostname.split(".").length > 3 ? true : false;
418
+ }
419
+ return false;
420
+ }
@@ -0,0 +1,52 @@
1
+ export declare type MetadataStaticRedirectEntry = {
2
+ status: number;
3
+ to: string;
4
+ lineNumber: number;
5
+ };
6
+ export declare type MetadataRedirectEntry = {
7
+ status: number;
8
+ to: string;
9
+ lineNumber?: number;
10
+ };
11
+ export declare type MetadataStaticRedirects = {
12
+ [path: string]: MetadataStaticRedirectEntry;
13
+ };
14
+ export declare type MetadataRedirects = {
15
+ [path: string]: MetadataRedirectEntry;
16
+ };
17
+ export declare type MetadataHeadersEntries = Record<string, string>;
18
+ export declare type MetadataHeadersRulesV1 = {
19
+ [path: string]: MetadataHeadersEntries;
20
+ };
21
+ export declare type MetadataHeadersV1 = {
22
+ version: number;
23
+ rules: MetadataHeadersRulesV1;
24
+ };
25
+ export declare type SetHeaders = MetadataHeadersEntries;
26
+ export declare type UnsetHeaders = Array<string>;
27
+ export declare type MetadataHeadersRulesV2 = {
28
+ [path: string]: MetadataHeaderEntry;
29
+ };
30
+ export declare type MetadataHeaderEntry = {
31
+ set?: SetHeaders;
32
+ unset?: UnsetHeaders;
33
+ };
34
+ export declare type MetadataHeadersV2 = {
35
+ version: number;
36
+ rules: MetadataHeadersRulesV2;
37
+ };
38
+ export declare type Metadata = {
39
+ redirects?: {
40
+ version: number;
41
+ staticRules?: MetadataStaticRedirects;
42
+ rules: MetadataRedirects;
43
+ };
44
+ headers?: MetadataHeadersV1 | MetadataHeadersV2;
45
+ analytics?: {
46
+ version: number;
47
+ token: string;
48
+ };
49
+ deploymentId?: string;
50
+ failOpen?: boolean;
51
+ };
52
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../asset-server/metadata.ts"],"names":[],"mappings":"AAEA,oBAAY,2BAA2B,GAAG;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,oBAAY,qBAAqB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,oBAAY,uBAAuB,GAAG;IACrC,CAAC,IAAI,EAAE,MAAM,GAAG,2BAA2B,CAAC;CAC5C,CAAC;AAEF,oBAAY,iBAAiB,GAAG;IAC/B,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,CAAC;CACtC,CAAC;AAGF,oBAAY,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE5D,oBAAY,sBAAsB,GAAG;IACpC,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,CAAC;CACvC,CAAC;AAEF,oBAAY,iBAAiB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,sBAAsB,CAAC;CAC9B,CAAC;AAGF,oBAAY,UAAU,GAAG,sBAAsB,CAAC;AAEhD,oBAAY,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;AAEzC,oBAAY,sBAAsB,GAAG;IACpC,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAAC;CACpC,CAAC;AAEF,oBAAY,mBAAmB,GAAG;IACjC,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,oBAAY,iBAAiB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,sBAAsB,CAAC;CAC9B,CAAC;AAEF,oBAAY,QAAQ,GAAG;IACtB,SAAS,CAAC,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,uBAAuB,CAAC;QACtC,KAAK,EAAE,iBAAiB,CAAC;KACzB,CAAC;IACF,OAAO,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAAC;IAChD,SAAS,CAAC,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACd,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // TODO: Use types from metadata-generator instead
3
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=patchUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patchUrl.d.ts","sourceRoot":"","sources":["../../asset-server/patchUrl.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4
+ // @ts-nocheck
5
+ globalThis.URL = (function (globalURL) {
6
+ PatchedURL.prototype = globalURL.prototype;
7
+ PatchedURL.createObjectURL = globalURL.createObjectURL;
8
+ PatchedURL.revokeObjectURL = globalURL.revokeObjectURL;
9
+ return PatchedURL;
10
+ function PatchedURL(input, base) {
11
+ const url = new globalURL(encodeURI(input), base);
12
+ return new Proxy(url, {
13
+ get(target, prop) {
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ return globalThis.decodeURIComponent(target[prop]);
16
+ },
17
+ });
18
+ }
19
+ })(URL);
@@ -0,0 +1,45 @@
1
+ export declare function stripLeadingDoubleSlashes(location: string): string;
2
+ export declare class OkResponse extends Response {
3
+ constructor(...[body, init]: ConstructorParameters<typeof Response>);
4
+ }
5
+ export declare class MovedPermanentlyResponse extends Response {
6
+ constructor(location: string, init?: ConstructorParameters<typeof Response>[1], { preventLeadingDoubleSlash, }?: {
7
+ preventLeadingDoubleSlash: boolean;
8
+ });
9
+ }
10
+ export declare class FoundResponse extends Response {
11
+ constructor(location: string, init?: ConstructorParameters<typeof Response>[1], { preventLeadingDoubleSlash, }?: {
12
+ preventLeadingDoubleSlash: boolean;
13
+ });
14
+ }
15
+ export declare class NotModifiedResponse extends Response {
16
+ constructor(...[_body, _init]: ConstructorParameters<typeof Response>);
17
+ }
18
+ export declare class PermanentRedirectResponse extends Response {
19
+ constructor(location: string, init?: ConstructorParameters<typeof Response>[1], { preventLeadingDoubleSlash, }?: {
20
+ preventLeadingDoubleSlash: boolean;
21
+ });
22
+ }
23
+ export declare class NotFoundResponse extends Response {
24
+ constructor(...[body, init]: ConstructorParameters<typeof Response>);
25
+ }
26
+ export declare class MethodNotAllowedResponse extends Response {
27
+ constructor(...[body, init]: ConstructorParameters<typeof Response>);
28
+ }
29
+ export declare class NotAcceptableResponse extends Response {
30
+ constructor(...[body, init]: ConstructorParameters<typeof Response>);
31
+ }
32
+ export declare class InternalServerErrorResponse extends Response {
33
+ constructor(err: Error, init?: ConstructorParameters<typeof Response>[1]);
34
+ }
35
+ export declare class SeeOtherResponse extends Response {
36
+ constructor(location: string, init?: ConstructorParameters<typeof Response>[1], { preventLeadingDoubleSlash, }?: {
37
+ preventLeadingDoubleSlash: boolean;
38
+ });
39
+ }
40
+ export declare class TemporaryRedirectResponse extends Response {
41
+ constructor(location: string, init?: ConstructorParameters<typeof Response>[1], { preventLeadingDoubleSlash, }?: {
42
+ preventLeadingDoubleSlash: boolean;
43
+ });
44
+ }
45
+ //# sourceMappingURL=responses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../asset-server/responses.ts"],"names":[],"mappings":"AAYA,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,UAEzD;AAED,qBAAa,UAAW,SAAQ,QAAQ;gBAC3B,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC;CAOnE;AAED,qBAAa,wBAAyB,SAAQ,QAAQ;gBAEpD,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EAChD,EACC,yBAAgC,GAChC,GAAE;QAAE,yBAAyB,EAAE,OAAO,CAAA;KAEtC;CAcF;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAEzC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EAChD,EACC,yBAAgC,GAChC,GAAE;QAAE,yBAAyB,EAAE,OAAO,CAAA;KAEtC;CAcF;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;gBACpC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC;CAMrE;AAED,qBAAa,yBAA0B,SAAQ,QAAQ;gBAErD,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EAChD,EACC,yBAAgC,GAChC,GAAE;QAAE,yBAAyB,EAAE,OAAO,CAAA;KAEtC;CAcF;AAED,qBAAa,gBAAiB,SAAQ,QAAQ;gBACjC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC;CAOnE;AAED,qBAAa,wBAAyB,SAAQ,QAAQ;gBACzC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC;CAOnE;AAED,qBAAa,qBAAsB,SAAQ,QAAQ;gBACtC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC;CAOnE;AAED,qBAAa,2BAA4B,SAAQ,QAAQ;gBAC5C,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;CAaxE;AAED,qBAAa,gBAAiB,SAAQ,QAAQ;gBAE5C,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EAChD,EACC,yBAAgC,GAChC,GAAE;QAAE,yBAAyB,EAAE,OAAO,CAAA;KAEtC;CAYF;AAED,qBAAa,yBAA0B,SAAQ,QAAQ;gBAErD,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EAChD,EACC,yBAAgC,GAChC,GAAE;QAAE,yBAAyB,EAAE,OAAO,CAAA;KAEtC;CAYF"}