@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,430 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const handler_1 = require("../../asset-server/handler");
4
+ const createMetadataObject_1 = require("../../metadata-generator/createMetadataObject");
5
+ describe("asset-server handler", () => {
6
+ test("Returns appropriate status codes", async () => {
7
+ const statuses = [301, 302, 303, 307, 308];
8
+ const metadata = createMetadataObjectWithRedirects(statuses
9
+ .map((status) => ({
10
+ status,
11
+ from: `/${status}`,
12
+ to: "/home",
13
+ }))
14
+ .concat({
15
+ status: 302,
16
+ from: "/500",
17
+ to: "/home",
18
+ }));
19
+ const tests = statuses.map(async (status) => {
20
+ const { response } = await getTestResponse({
21
+ request: "https://foo.com/" + status,
22
+ metadata,
23
+ });
24
+ expect(response.status).toBe(status);
25
+ expect(response.headers.get("Location")).toBe("/home");
26
+ });
27
+ await Promise.all(tests);
28
+ const { response } = await getTestResponse({
29
+ request: "https://foo.com/500",
30
+ metadata,
31
+ });
32
+ expect(response.status).toBe(302);
33
+ expect(response.headers.get("Location")).toBe("/home");
34
+ });
35
+ test("Won't redirect to protocol-less double-slashed URLs", async () => {
36
+ const metadata = createMetadataObjectWithRedirects([
37
+ { from: "/", to: "/home", status: 301 },
38
+ { from: "/page.html", to: "/elsewhere", status: 301 },
39
+ ]);
40
+ const findAssetEntryForPath = async (path) => {
41
+ if (path === "/index.html") {
42
+ return "index page";
43
+ }
44
+ if (path === "/page.html") {
45
+ return "some page";
46
+ }
47
+ return null;
48
+ };
49
+ {
50
+ const { response } = await getTestResponse({
51
+ request: "/%2Fwww.example.com/index/",
52
+ metadata,
53
+ findAssetEntryForPath,
54
+ });
55
+ expect(response.status).toBe(308);
56
+ expect(response.headers.get("Location")).toEqual("/www.example.com/");
57
+ }
58
+ {
59
+ const { response } = await getTestResponse({
60
+ request: "/%5Cwww.example.com/index/",
61
+ metadata,
62
+ findAssetEntryForPath,
63
+ });
64
+ expect(response.status).toBe(308);
65
+ expect(response.headers.get("Location")).toEqual("/www.example.com/");
66
+ }
67
+ {
68
+ const { response } = await getTestResponse({
69
+ request: "/%2Fwww.example.com/%2F/index/",
70
+ metadata,
71
+ findAssetEntryForPath,
72
+ });
73
+ expect(response.status).toBe(308);
74
+ expect(response.headers.get("Location")).toEqual("/www.example.com///");
75
+ }
76
+ {
77
+ const { response } = await getTestResponse({
78
+ request: "/%5Cwww.example.com/%5C/index/",
79
+ metadata,
80
+ findAssetEntryForPath,
81
+ });
82
+ expect(response.status).toBe(308);
83
+ expect(response.headers.get("Location")).toEqual("/www.example.com/\\/");
84
+ }
85
+ {
86
+ const { response } = await getTestResponse({
87
+ request: "/%2fwww.example.com/%2f/index/",
88
+ metadata,
89
+ findAssetEntryForPath,
90
+ });
91
+ expect(response.status).toBe(308);
92
+ expect(response.headers.get("Location")).toEqual("/www.example.com///");
93
+ }
94
+ {
95
+ const { response } = await getTestResponse({
96
+ request: "/%5cwww.example.com/%5c/index/",
97
+ metadata,
98
+ findAssetEntryForPath,
99
+ });
100
+ expect(response.status).toBe(308);
101
+ expect(response.headers.get("Location")).toEqual("/www.example.com/\\/");
102
+ }
103
+ {
104
+ const { response } = await getTestResponse({
105
+ request: "/foo/index/",
106
+ metadata,
107
+ findAssetEntryForPath,
108
+ });
109
+ expect(response.status).toBe(308);
110
+ expect(response.headers.get("Location")).toEqual("/foo/");
111
+ }
112
+ });
113
+ test("Match exact pathnames, before any HTML redirection", async () => {
114
+ const metadata = createMetadataObjectWithRedirects([
115
+ { from: "/", to: "/home", status: 301 },
116
+ { from: "/page.html", to: "/elsewhere", status: 301 },
117
+ { from: "/protocol-less-test", to: "/%2fwww.example.com/", status: 308 },
118
+ ]);
119
+ const findAssetEntryForPath = async (path) => {
120
+ if (path === "/index.html") {
121
+ return "index page";
122
+ }
123
+ if (path === "/page.html") {
124
+ return "some page";
125
+ }
126
+ return null;
127
+ };
128
+ {
129
+ const { response } = await getTestResponse({
130
+ request: "/index.html",
131
+ metadata,
132
+ findAssetEntryForPath,
133
+ });
134
+ expect(response.status).toBe(308);
135
+ expect(response.headers.get("Location")).toEqual("/");
136
+ }
137
+ {
138
+ const { response } = await getTestResponse({
139
+ request: "/index",
140
+ metadata,
141
+ findAssetEntryForPath,
142
+ });
143
+ expect(response.status).toBe(308);
144
+ expect(response.headers.get("Location")).toEqual("/");
145
+ }
146
+ {
147
+ const { response } = await getTestResponse({
148
+ request: "/",
149
+ metadata,
150
+ findAssetEntryForPath,
151
+ });
152
+ expect(response.status).toBe(301);
153
+ expect(response.headers.get("Location")).toEqual("/home");
154
+ }
155
+ {
156
+ // The redirect rule takes precedence to the 308s
157
+ const { response } = await getTestResponse({
158
+ request: "/page.html",
159
+ metadata,
160
+ findAssetEntryForPath,
161
+ });
162
+ expect(response.status).toBe(301);
163
+ expect(response.headers.get("Location")).toEqual("/elsewhere");
164
+ }
165
+ {
166
+ // The redirect rule takes precedence to the 308s
167
+ const { response } = await getTestResponse({
168
+ request: "/protocol-less-test",
169
+ metadata,
170
+ findAssetEntryForPath,
171
+ });
172
+ expect(response.status).toBe(308);
173
+ expect(response.headers.get("Location")).toEqual("/%2fwww.example.com/");
174
+ }
175
+ {
176
+ // This serves the HTML even though the redirect rule is present
177
+ const { response, spies } = await getTestResponse({
178
+ request: "/page",
179
+ metadata,
180
+ findAssetEntryForPath,
181
+ });
182
+ expect(response.status).toBe(200);
183
+ expect(spies.fetchAsset).toBe(1);
184
+ }
185
+ });
186
+ test("cross-host static redirects still are executed with line number precedence", async () => {
187
+ const metadata = createMetadataObjectWithRedirects([
188
+ { from: "https://fakehost/home", to: "https://firsthost/", status: 302 },
189
+ { from: "/home", to: "https://secondhost/", status: 302 },
190
+ ]);
191
+ const findAssetEntryForPath = async (path) => {
192
+ if (path === "/index.html") {
193
+ return "index page";
194
+ }
195
+ return null;
196
+ };
197
+ {
198
+ const { response } = await getTestResponse({
199
+ request: "https://yetanotherhost/home",
200
+ metadata,
201
+ findAssetEntryForPath,
202
+ });
203
+ expect(response.status).toBe(302);
204
+ expect(response.headers.get("Location")).toEqual("https://secondhost/");
205
+ }
206
+ {
207
+ const { response } = await getTestResponse({
208
+ request: "https://fakehost/home",
209
+ metadata,
210
+ findAssetEntryForPath,
211
+ });
212
+ expect(response.status).toBe(302);
213
+ expect(response.headers.get("Location")).toEqual("https://firsthost/");
214
+ }
215
+ });
216
+ test("it should preserve querystrings unless to rule includes them", async () => {
217
+ const metadata = createMetadataObjectWithRedirects([
218
+ { from: "/", status: 301, to: "/home" },
219
+ { from: "/recent", status: 301, to: "/home?sort=updated_at" },
220
+ ]);
221
+ const findAssetEntryForPath = async (path) => {
222
+ if (path === "/home.html") {
223
+ return "home page";
224
+ }
225
+ return null;
226
+ };
227
+ {
228
+ const { response } = await getTestResponse({
229
+ request: "/?sort=price",
230
+ metadata,
231
+ findAssetEntryForPath,
232
+ });
233
+ expect(response.status).toBe(301);
234
+ expect(response.headers.get("Location")).toEqual("/home?sort=price");
235
+ }
236
+ {
237
+ const { response } = await getTestResponse({
238
+ request: "/recent",
239
+ metadata,
240
+ findAssetEntryForPath,
241
+ });
242
+ expect(response.status).toBe(301);
243
+ expect(response.headers.get("Location")).toEqual("/home?sort=updated_at");
244
+ }
245
+ {
246
+ const { response } = await getTestResponse({
247
+ request: "/recent?other=query",
248
+ metadata,
249
+ findAssetEntryForPath,
250
+ });
251
+ expect(response.status).toBe(301);
252
+ expect(response.headers.get("Location")).toEqual("/home?sort=updated_at");
253
+ }
254
+ });
255
+ {
256
+ const metadata = createMetadataObjectWithRedirects([
257
+ { from: "/home", status: 301, to: "/" },
258
+ { from: "/blog/*", status: 301, to: "https://blog.example.com/:splat" },
259
+ {
260
+ from: "/products/:code/:name/*",
261
+ status: 301,
262
+ to: "/products?junk=:splat&name=:name&code=:code",
263
+ },
264
+ { from: "/foo", status: 301, to: "/bar" },
265
+ ]);
266
+ const findAssetEntryForPath = async (path) => {
267
+ if (path === "/home.html") {
268
+ return "home page";
269
+ }
270
+ return null;
271
+ };
272
+ test("it should perform splat replacements", async () => {
273
+ const { response } = await getTestResponse({
274
+ request: "/blog/a-blog-posting",
275
+ metadata,
276
+ findAssetEntryForPath,
277
+ });
278
+ expect(response.status).toBe(301);
279
+ expect(response.headers.get("Location")).toEqual("https://blog.example.com/a-blog-posting");
280
+ });
281
+ test("it should perform placeholder replacements", async () => {
282
+ const { response } = await getTestResponse({
283
+ request: "/products/abba_562/tricycle/123abc@~!",
284
+ metadata,
285
+ findAssetEntryForPath,
286
+ });
287
+ expect(response.status).toBe(301);
288
+ expect(response.headers.get("Location")).toEqual("/products?junk=123abc@~!&name=tricycle&code=abba_562");
289
+ });
290
+ test("it should redirect both dynamic and static redirects", async () => {
291
+ {
292
+ const { response } = await getTestResponse({
293
+ request: "/home",
294
+ metadata,
295
+ findAssetEntryForPath,
296
+ });
297
+ expect(response.status).toBe(301);
298
+ expect(response.headers.get("Location")).toEqual("/");
299
+ }
300
+ {
301
+ const { response } = await getTestResponse({
302
+ request: "/blog/post",
303
+ metadata,
304
+ findAssetEntryForPath,
305
+ });
306
+ expect(response.status).toBe(301);
307
+ expect(response.headers.get("Location")).toEqual("https://blog.example.com/post");
308
+ }
309
+ {
310
+ const { response } = await getTestResponse({
311
+ request: "/foo",
312
+ metadata,
313
+ findAssetEntryForPath,
314
+ });
315
+ expect(response.status).toBe(301);
316
+ expect(response.headers.get("Location")).toEqual("/bar");
317
+ }
318
+ });
319
+ }
320
+ // test("Returns a redirect without duplicating the hash component", async () => {
321
+ // const { response, spies } = await getTestResponse({
322
+ // request: "https://foo.com/bar",
323
+ // metadata: createMetadataObjectWithRedirects([
324
+ // { from: "/bar", to: "https://foobar.com/##heading-7", status: 301 },
325
+ // ]),
326
+ // });
327
+ // expect(spies.fetchAsset).toBe(0);
328
+ // expect(spies.findAssetEntryForPath).toBe(0);
329
+ // expect(spies.getAssetKey).toBe(0);
330
+ // expect(spies.negotiateContent).toBe(0);
331
+ // expect(response.status).toBe(301);
332
+ // expect(response.headers.get("Location")).toBe(
333
+ // "https://foobar.com/##heading-7"
334
+ // );
335
+ // });
336
+ test("it should redirect uri-encoded paths", async () => {
337
+ const { response, spies } = await getTestResponse({
338
+ request: "https://foo.com/some%20page",
339
+ metadata: createMetadataObjectWithRedirects([
340
+ { from: "/some%20page", to: "/home", status: 301 },
341
+ ]),
342
+ });
343
+ expect(spies.fetchAsset).toBe(0);
344
+ expect(spies.findAssetEntryForPath).toBe(0);
345
+ expect(spies.getAssetKey).toBe(0);
346
+ expect(spies.negotiateContent).toBe(0);
347
+ expect(response.status).toBe(301);
348
+ expect(response.headers.get("Location")).toBe("/home");
349
+ });
350
+ // test("getResponseFromMatch - same origin paths specified as root-relative", () => {
351
+ // const res = getResponseFromMatch(
352
+ // {
353
+ // to: "/bar",
354
+ // status: 301,
355
+ // },
356
+ // new URL("https://example.com/foo")
357
+ // );
358
+ // expect(res.status).toBe(301);
359
+ // expect(res.headers.get("Location")).toBe("/bar");
360
+ // });
361
+ // test("getResponseFromMatch - same origin paths specified as full URLs", () => {
362
+ // const res = getResponseFromMatch(
363
+ // {
364
+ // to: "https://example.com/bar",
365
+ // status: 301,
366
+ // },
367
+ // new URL("https://example.com/foo")
368
+ // );
369
+ // expect(res.status).toBe(301);
370
+ // expect(res.headers.get("Location")).toBe("/bar");
371
+ // });
372
+ // });
373
+ // test("getResponseFromMatch - different origins", () => {
374
+ // const res = getResponseFromMatch(
375
+ // {
376
+ // to: "https://bar.com/bar",
377
+ // status: 302,
378
+ // },
379
+ // new URL("https://example.com/foo")
380
+ // );
381
+ // expect(res.status).toBe(302);
382
+ // expect(res.headers.get("Location")).toBe("https://bar.com/bar");
383
+ });
384
+ async function getTestResponse({ request, metadata = (0, createMetadataObject_1.createMetadataObject)({
385
+ redirects: {
386
+ invalid: [],
387
+ rules: [],
388
+ },
389
+ }), ...options }) {
390
+ const spies = {
391
+ fetchAsset: 0,
392
+ findAssetEntryForPath: 0,
393
+ getAssetKey: 0,
394
+ negotiateContent: 0,
395
+ };
396
+ const response = await (0, handler_1.generateHandler)({
397
+ request: request instanceof Request ? request : new Request(request),
398
+ metadata,
399
+ xServerEnvHeader: "dev",
400
+ logError: console.error,
401
+ findAssetEntryForPath: async (...args) => {
402
+ spies.findAssetEntryForPath++;
403
+ return options.findAssetEntryForPath?.(...args) ?? null;
404
+ },
405
+ getAssetKey: (assetEntry, content) => {
406
+ spies.getAssetKey++;
407
+ return options.getAssetKey?.(assetEntry, content) ?? assetEntry;
408
+ },
409
+ negotiateContent: (...args) => {
410
+ spies.negotiateContent++;
411
+ return options.negotiateContent?.(...args) ?? { encoding: null };
412
+ },
413
+ fetchAsset: async (...args) => {
414
+ spies.fetchAsset++;
415
+ return (options.fetchAsset?.(...args) ?? {
416
+ body: null,
417
+ contentType: "text/plain",
418
+ });
419
+ },
420
+ });
421
+ return { response, spies };
422
+ }
423
+ function createMetadataObjectWithRedirects(rules) {
424
+ return (0, createMetadataObject_1.createMetadataObject)({
425
+ redirects: {
426
+ invalid: [],
427
+ rules: rules.map((rule, i) => ({ ...rule, lineNumber: i + 1 })),
428
+ },
429
+ });
430
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=responses.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.test.d.ts","sourceRoot":"","sources":["../../../__tests__/asset-server/responses.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const responses_1 = require("../../asset-server/responses");
4
+ describe("stripLeadingDoubleSlashes", () => {
5
+ it("strips extra leading `/`, `%2F` and `%2f`s", () => {
6
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/")).toMatchInlineSnapshot(`"/"`);
7
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/%2Ffoo")).toMatchInlineSnapshot(`"/foo"`);
8
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/%2ffoo")).toMatchInlineSnapshot(`"/foo"`);
9
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/%2F%2f/foo")).toMatchInlineSnapshot(`"/foo"`);
10
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/%5Cfoo")).toMatchInlineSnapshot(`"/foo"`);
11
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/%5cfoo")).toMatchInlineSnapshot(`"/foo"`);
12
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/%5C%5c/foo")).toMatchInlineSnapshot(`"/foo"`);
13
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/%2f%5c/foo")).toMatchInlineSnapshot(`"/foo"`);
14
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/\\/foo")).toMatchInlineSnapshot(`"/foo"`);
15
+ expect((0, responses_1.stripLeadingDoubleSlashes)("%2ffoo")).toMatchInlineSnapshot(`"/foo"`);
16
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/foo/%2f")).toMatchInlineSnapshot(`"/foo/%2f"`);
17
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/foo/%2F")).toMatchInlineSnapshot(`"/foo/%2F"`);
18
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/foo//")).toMatchInlineSnapshot(`"/foo//"`);
19
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/foo//bar")).toMatchInlineSnapshot(`"/foo//bar"`);
20
+ expect((0, responses_1.stripLeadingDoubleSlashes)("/foo/\\/bar")).toMatchInlineSnapshot(`"/foo/\\\\/bar"`);
21
+ });
22
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rulesEngine.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rulesEngine.test.d.ts","sourceRoot":"","sources":["../../../__tests__/asset-server/rulesEngine.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const rulesEngine_1 = require("../..//asset-server/rulesEngine");
4
+ describe("rules engine", () => {
5
+ test("it should match simple pathname hosts", () => {
6
+ const matcher = (0, rulesEngine_1.generateRulesMatcher)({ "/test": 1, "/some%20page": 2 });
7
+ expect(matcher({ request: new Request("/test") })).toEqual([1]);
8
+ expect(matcher({ request: new Request("/some page") })).toEqual([2]);
9
+ });
10
+ test("it should match cross-host requests", () => {
11
+ const matcher = (0, rulesEngine_1.generateRulesMatcher)({
12
+ "/test": 1,
13
+ "/anotherpage": 2,
14
+ "https://custom.domain/test": 3,
15
+ "https://another.domain/test": 4,
16
+ "//fake.host/actually-a-path": 5,
17
+ });
18
+ expect(matcher({ request: new Request("https://custom.domain/test") })).toEqual([1, 3]);
19
+ expect(matcher({
20
+ request: new Request("https://example.com//fake.host/actually-a-path"),
21
+ })).toEqual([5]);
22
+ });
23
+ test("it should escape funky rules", () => {
24
+ const matcher = (0, rulesEngine_1.generateRulesMatcher)({
25
+ "/$~.%20/!+-/[bo|%7Bo%7D]...()": 1,
26
+ });
27
+ expect(matcher({ request: new Request("/$~. \\!+-/[bo|{o}]...()") })).toEqual([1]);
28
+ });
29
+ test("it should support splats and placeholders", () => {
30
+ const matcher = (0, rulesEngine_1.generateRulesMatcher)({
31
+ "/foo/test/*": "1/:splat",
32
+ "/foo/*": "2/:splat",
33
+ "/blog/:code/:name": "3/:name/:code",
34
+ "/blog/*": "4/:splat",
35
+ "https://:subdomain.pages.:tld/*": "5/:subdomain/:tld/:splat",
36
+ "https://next.:subdomain.pages.:tld/*": "6/:subdomain/",
37
+ }, (match, replacements) => (0, rulesEngine_1.replacer)(match, replacements));
38
+ expect(matcher({ request: new Request("/foo/test/yes") })).toEqual([
39
+ "1/yes",
40
+ "2/test/yes",
41
+ ]);
42
+ expect(matcher({ request: new Request("/foo/test/") })).toEqual([
43
+ "1/",
44
+ "2/test/",
45
+ ]);
46
+ expect(matcher({ request: new Request("/foo/test") })).toEqual(["2/test"]);
47
+ expect(matcher({ request: new Request("/foo/") })).toEqual(["2/"]);
48
+ expect(matcher({ request: new Request("/foo") })).toEqual([]);
49
+ expect(matcher({ request: new Request("/blog/123/tricycle") })).toEqual([
50
+ "3/tricycle/123",
51
+ "4/123/tricycle",
52
+ ]);
53
+ expect(matcher({ request: new Request("https://my.pages.dev/magic") })).toEqual(["5/my/dev/magic"]);
54
+ expect(matcher({ request: new Request("https://next.my.pages.dev/magic") })).toEqual(["6/my/"]);
55
+ });
56
+ });
57
+ describe("replacer", () => {
58
+ it("should replace splats", () => {
59
+ expect((0, rulesEngine_1.replacer)("/blog/:splat", { splat: "look/a/value" })).toEqual("/blog/look/a/value");
60
+ });
61
+ it("should replace placeholders", () => {
62
+ expect((0, rulesEngine_1.replacer)("/:code/:name.jpg", { name: "tricycle", code: "123" })).toEqual("/123/tricycle.jpg");
63
+ });
64
+ it("should replace splats and placeholders", () => {
65
+ expect((0, rulesEngine_1.replacer)("/:code/:splat", { splat: "tricycle/images", code: "123" })).toEqual("/123/tricycle/images");
66
+ });
67
+ it("should replace all instances of placeholders", () => {
68
+ expect((0, rulesEngine_1.replacer)("Link: </assets/:value/main.js>; rel=preload; as=script, </assets/:value/lang.js>; rel=preload; as=script", { value: "js" })).toEqual("Link: </assets/js/main.js>; rel=preload; as=script, </assets/js/lang.js>; rel=preload; as=script");
69
+ });
70
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=jest.setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jest.setup.d.ts","sourceRoot":"","sources":["../../__tests__/jest.setup.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const service_worker_mock_1 = __importDefault(require("service-worker-mock"));
7
+ Object.assign(globalThis, (0, service_worker_mock_1.default)());
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createMetadataObject.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMetadataObject.test.d.ts","sourceRoot":"","sources":["../../../__tests__/metadata-generator/createMetadataObject.test.ts"],"names":[],"mappings":""}