@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,243 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Snapshot values
4
+ const maxDynamicRedirectRules = 100;
5
+ const maxLineLength = 2000;
6
+ const maxStaticRedirectRules = 2000;
7
+ const parseRedirects_1 = require("../..//metadata-generator/parseRedirects");
8
+ test("parseRedirects should reject malformed lines", () => {
9
+ const input = `
10
+ # Single token
11
+ /c
12
+ # Four tokens
13
+ /d /e 302 !important
14
+ `;
15
+ const result = (0, parseRedirects_1.parseRedirects)(input);
16
+ expect(result).toEqual({
17
+ rules: [],
18
+ invalid: [
19
+ {
20
+ line: `/c`,
21
+ lineNumber: 3,
22
+ message: "Expected exactly 2 or 3 whitespace-separated tokens. Got 1.",
23
+ },
24
+ {
25
+ line: `/d /e 302 !important`,
26
+ lineNumber: 5,
27
+ message: "Expected exactly 2 or 3 whitespace-separated tokens. Got 4.",
28
+ },
29
+ ],
30
+ });
31
+ });
32
+ test("parseRedirects should reject invalid status codes", () => {
33
+ const input = `
34
+ # Valid token sails through
35
+ /a /b 301
36
+ # 200 NOT OK
37
+ /c /d 200
38
+ `;
39
+ const result = (0, parseRedirects_1.parseRedirects)(input);
40
+ expect(result).toEqual({
41
+ rules: [{ from: "/a", status: 301, to: "/b", lineNumber: 3 }],
42
+ invalid: [
43
+ {
44
+ line: `/c /d 200`,
45
+ lineNumber: 5,
46
+ message: "Valid status codes are 301, 302 (default), 303, 307, or 308. Got 200.",
47
+ },
48
+ ],
49
+ });
50
+ });
51
+ test(`parseRedirects should reject duplicate 'from' paths`, () => {
52
+ const input = `
53
+ # Valid entry
54
+ /a /b
55
+ # Nonsensical but permitted (for now)
56
+ /b /a
57
+ # Duplicate 'from'
58
+ /a /c
59
+ `;
60
+ const result = (0, parseRedirects_1.parseRedirects)(input);
61
+ expect(result).toEqual({
62
+ rules: [
63
+ { from: "/a", status: 302, to: "/b", lineNumber: 3 },
64
+ { from: "/b", status: 302, to: "/a", lineNumber: 5 },
65
+ ],
66
+ invalid: [
67
+ {
68
+ line: `/a /c`,
69
+ lineNumber: 7,
70
+ message: `Ignoring duplicate rule for path /a.`,
71
+ },
72
+ ],
73
+ });
74
+ });
75
+ test(`parseRedirects should reject lines longer than ${maxLineLength} chars`, () => {
76
+ const huge_line = `/${Array(maxLineLength).fill("a").join("")} /${Array(maxLineLength)
77
+ .fill("b")
78
+ .join("")} 301`;
79
+ const input = `
80
+ # Valid entry
81
+ /a /b
82
+ # Jumbo comment line OK, ignored as normal
83
+ ${Array(maxLineLength + 1)
84
+ .fill("#")
85
+ .join("")}
86
+ # Huge path names rejected
87
+ ${huge_line}
88
+ `;
89
+ const result = (0, parseRedirects_1.parseRedirects)(input);
90
+ expect(result).toEqual({
91
+ rules: [{ from: "/a", status: 302, to: "/b", lineNumber: 3 }],
92
+ invalid: [
93
+ {
94
+ message: `Ignoring line 7 as it exceeds the maximum allowed length of ${maxLineLength}.`,
95
+ },
96
+ ],
97
+ });
98
+ });
99
+ test("parseRedirects should reject any dynamic rules after the first 100", () => {
100
+ const input = `
101
+ # COMMENTS DON'T COUNT TOWARDS TOTAL VALID RULES
102
+ ${Array(150)
103
+ .fill(undefined)
104
+ .map((_, i) => `/a/${i}/* /b/${i}/:splat`)
105
+ .join("\n")}
106
+ # BUT DO GET COUNTED AS TOTAL LINES SKIPPED
107
+ `;
108
+ expect((0, parseRedirects_1.parseRedirects)(input)).toEqual({
109
+ rules: Array(100)
110
+ .fill(undefined)
111
+ .map((_, i) => ({
112
+ from: `/a/${i}/*`,
113
+ to: `/b/${i}/:splat`,
114
+ status: 302,
115
+ lineNumber: i + 3,
116
+ })),
117
+ invalid: [
118
+ {
119
+ message: `Maximum number of dynamic rules supported is 100. Skipping remaining 52 lines of file.`,
120
+ },
121
+ ],
122
+ });
123
+ });
124
+ test(`parseRedirects should reject any static rules after the first ${maxStaticRedirectRules}`, () => {
125
+ const input = `
126
+ # COMMENTS DON'T COUNT TOWARDS TOTAL VALID RULES
127
+ ${Array(maxStaticRedirectRules + 50)
128
+ .fill(undefined)
129
+ .map((_, i) => `/a/${i} /b/${i}`)
130
+ .join("\n")}
131
+ # BUT DO GET COUNTED AS TOTAL LINES SKIPPED
132
+ `;
133
+ expect((0, parseRedirects_1.parseRedirects)(input)).toEqual({
134
+ rules: Array(maxStaticRedirectRules)
135
+ .fill(undefined)
136
+ .map((_, i) => ({
137
+ from: `/a/${i}`,
138
+ to: `/b/${i}`,
139
+ status: 302,
140
+ lineNumber: i + 3,
141
+ })),
142
+ invalid: Array(50)
143
+ .fill(undefined)
144
+ .map(() => ({
145
+ message: `Maximum number of static rules supported is ${maxStaticRedirectRules}. Skipping line.`,
146
+ })),
147
+ });
148
+ });
149
+ test("parseRedirects should reject a combination of lots of static and dynamic rules", () => {
150
+ const input = `
151
+ # COMMENTS DON'T COUNT TOWARDS TOTAL VALID RULES
152
+ ${Array(maxStaticRedirectRules + 50)
153
+ .fill(undefined)
154
+ .map((_, i) => `/a/${i} /b/${i}`)
155
+ .join("\n")}
156
+ ${Array(maxDynamicRedirectRules + 50)
157
+ .fill(undefined)
158
+ .map((_, i) => `/a/${i}/* /b/${i}/:splat`)
159
+ .join("\n")}
160
+ # BUT DO GET COUNTED AS TOTAL LINES SKIPPED
161
+ `;
162
+ expect((0, parseRedirects_1.parseRedirects)(input)).toEqual({
163
+ rules: [
164
+ ...Array(maxStaticRedirectRules)
165
+ .fill(undefined)
166
+ .map((_, i) => ({
167
+ from: `/a/${i}`,
168
+ to: `/b/${i}`,
169
+ status: 302,
170
+ lineNumber: i + 3,
171
+ })),
172
+ ...Array(maxDynamicRedirectRules)
173
+ .fill(undefined)
174
+ .map((_, i) => ({
175
+ from: `/a/${i}/*`,
176
+ to: `/b/${i}/:splat`,
177
+ status: 302,
178
+ lineNumber: i + maxStaticRedirectRules + 53,
179
+ })),
180
+ ],
181
+ invalid: [
182
+ ...Array(50)
183
+ .fill(undefined)
184
+ .map(() => ({
185
+ message: `Maximum number of static rules supported is ${maxStaticRedirectRules}. Skipping line.`,
186
+ })),
187
+ {
188
+ message: `Maximum number of dynamic rules supported is ${maxDynamicRedirectRules}. Skipping remaining 52 lines of file.`,
189
+ },
190
+ ],
191
+ });
192
+ });
193
+ test("parseRedirects should reject malformed URLs", () => {
194
+ const input = `
195
+ # Spaces rejected on token length
196
+ /some page /somewhere else
197
+ # OK with URL escaped encoding
198
+ /some%20page /somewhere%20else
199
+ # Unescaped URLs are handled OK by Deno, so escape & pass them through
200
+ /://so;\`me /nons:/&@%+~{}ense
201
+ # Absolute URLs aren't OK for 'from', but are fine for 'to'
202
+ https://yeah.com https://nah.com
203
+ /nah https://yeah.com
204
+ # This is actually parsed as /yeah.com, which we might want to detect but is ok for now
205
+ yeah.com https://nah.com
206
+ `;
207
+ const result = (0, parseRedirects_1.parseRedirects)(input);
208
+ expect(result).toEqual({
209
+ invalid: [
210
+ {
211
+ line: `/some page /somewhere else`,
212
+ lineNumber: 3,
213
+ message: "Expected exactly 2 or 3 whitespace-separated tokens. Got 4.",
214
+ },
215
+ {
216
+ line: `https://yeah.com https://nah.com`,
217
+ lineNumber: 9,
218
+ message: "Only relative URLs are allowed. Skipping absolute URL https://yeah.com.",
219
+ },
220
+ ],
221
+ rules: [
222
+ {
223
+ from: "/some%20page",
224
+ status: 302,
225
+ to: "/somewhere%20else",
226
+ lineNumber: 5,
227
+ },
228
+ {
229
+ from: "/://so;%60me",
230
+ status: 302,
231
+ to: "/nons:/&@%+~%7B%7Dense",
232
+ lineNumber: 7,
233
+ },
234
+ { from: "/nah", status: 302, to: "https://yeah.com/", lineNumber: 10 },
235
+ {
236
+ from: "/yeah.com",
237
+ status: 302,
238
+ to: "https://nah.com/",
239
+ lineNumber: 12,
240
+ },
241
+ ],
242
+ });
243
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parseRedirects.valid.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseRedirects.valid.test.d.ts","sourceRoot":"","sources":["../../../__tests__/metadata-generator/parseRedirects.valid.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const parseRedirects_1 = require("../../metadata-generator/parseRedirects");
4
+ test("parseRedirects should handle a single rule", () => {
5
+ const input = `/a /b 301`;
6
+ const result = (0, parseRedirects_1.parseRedirects)(input);
7
+ expect(result).toEqual({
8
+ rules: [{ from: "/a", status: 301, to: "/b", lineNumber: 1 }],
9
+ invalid: [],
10
+ });
11
+ });
12
+ test("parseRedirects should ignore blank lines", () => {
13
+ const input = `
14
+ /a /b 301
15
+ `;
16
+ const result = (0, parseRedirects_1.parseRedirects)(input);
17
+ expect(result).toEqual({
18
+ rules: [{ from: "/a", status: 301, to: "/b", lineNumber: 2 }],
19
+ invalid: [],
20
+ });
21
+ });
22
+ test("parseRedirects should trim whitespace", () => {
23
+ const input = `
24
+ /a /b 301
25
+ `;
26
+ const result = (0, parseRedirects_1.parseRedirects)(input);
27
+ expect(result).toEqual({
28
+ rules: [{ from: "/a", status: 301, to: "/b", lineNumber: 2 }],
29
+ invalid: [],
30
+ });
31
+ });
32
+ test("parseRedirects should ignore comments", () => {
33
+ const input = `
34
+ # This is a comment
35
+ /a /b 301
36
+ # And one here too.
37
+ `;
38
+ const result = (0, parseRedirects_1.parseRedirects)(input);
39
+ expect(result).toEqual({
40
+ rules: [{ from: "/a", status: 301, to: "/b", lineNumber: 3 }],
41
+ invalid: [],
42
+ });
43
+ });
44
+ test("parseRedirects should default to 302", () => {
45
+ const input = `
46
+ /a /b 302
47
+ /c /d
48
+ `;
49
+ const result = (0, parseRedirects_1.parseRedirects)(input);
50
+ expect(result).toEqual({
51
+ rules: [
52
+ { from: "/a", status: 302, to: "/b", lineNumber: 2 },
53
+ { from: "/c", status: 302, to: "/d", lineNumber: 3 },
54
+ ],
55
+ invalid: [],
56
+ });
57
+ });
58
+ test("parseRedirects should preserve querystrings on to", () => {
59
+ const input = `
60
+ /a /b?query=string 302
61
+ /c?this=rejected /d 301
62
+ /ext https://some.domain:1234/route?q=string#anchor
63
+ `;
64
+ const result = (0, parseRedirects_1.parseRedirects)(input);
65
+ expect(result).toEqual({
66
+ rules: [
67
+ { from: "/a", status: 302, to: "/b?query=string", lineNumber: 2 },
68
+ { from: "/c", status: 301, to: "/d", lineNumber: 3 },
69
+ {
70
+ from: "/ext",
71
+ status: 302,
72
+ to: "https://some.domain:1234/route?q=string#anchor",
73
+ lineNumber: 4,
74
+ },
75
+ ],
76
+ invalid: [],
77
+ });
78
+ });
79
+ test("parseRedirects should preserve fragments", () => {
80
+ const input = `
81
+ /a /b#blah 302
82
+ `;
83
+ const result = (0, parseRedirects_1.parseRedirects)(input);
84
+ expect(result).toEqual({
85
+ rules: [{ from: "/a", status: 302, to: "/b#blah", lineNumber: 2 }],
86
+ invalid: [],
87
+ });
88
+ });
@@ -0,0 +1,44 @@
1
+ import type { Metadata, MetadataHeadersRulesV2, MetadataHeadersV1, MetadataHeadersV2 } from "./metadata";
2
+ export declare const ASSET_PRESERVATION_CACHE = "assetPreservationCache";
3
+ export declare const CACHE_CONTROL_BROWSER = "public, max-age=0, must-revalidate";
4
+ export declare const REDIRECTS_VERSION = 1;
5
+ export declare const HEADERS_VERSION = 2;
6
+ export declare const HEADERS_VERSION_V1 = 1;
7
+ export declare const ANALYTICS_VERSION = 1;
8
+ export declare function normaliseHeaders(headers: MetadataHeadersV1 | MetadataHeadersV2): MetadataHeadersRulesV2;
9
+ declare type FindAssetEntryForPath<AssetEntry> = (path: string) => Promise<null | AssetEntry>;
10
+ declare type ServeAsset<AssetEntry> = (assetEntry: AssetEntry, options?: {
11
+ preserve: boolean;
12
+ }) => Promise<Response>;
13
+ declare type FullHandlerContext<AssetEntry, ContentNegotiation, Asset> = {
14
+ request: Request;
15
+ metadata: Metadata;
16
+ xServerEnvHeader?: string;
17
+ logError: (err: Error) => void;
18
+ findAssetEntryForPath: FindAssetEntryForPath<AssetEntry>;
19
+ getAssetKey(assetEntry: AssetEntry, content: ContentNegotiation): string;
20
+ negotiateContent(request: Request, assetEntry: AssetEntry): ContentNegotiation;
21
+ fetchAsset: (assetKey: string) => Promise<Asset>;
22
+ generateNotFoundResponse?: (request: Request, findAssetEntryForPath: FindAssetEntryForPath<AssetEntry>, serveAsset: ServeAsset<AssetEntry>) => Promise<Response>;
23
+ attachAdditionalHeaders?: (response: Response, content: ContentNegotiation, assetEntry: AssetEntry, asset: Asset) => void;
24
+ caches: CacheStorage;
25
+ waitUntil: (promise: Promise<unknown>) => void;
26
+ };
27
+ export declare type HandlerContext<AssetEntry, ContentNegotiation, Asset> = FullHandlerContext<AssetEntry, ContentNegotiation, Asset> | (Omit<FullHandlerContext<AssetEntry, ContentNegotiation, Asset>, "caches" | "waitUntil"> & {
28
+ caches?: undefined;
29
+ waitUntil?: undefined;
30
+ });
31
+ export declare function generateHandler<AssetEntry, ContentNegotiation extends {
32
+ encoding: string | null;
33
+ } = {
34
+ encoding: string | null;
35
+ }, Asset extends {
36
+ body: ReadableStream | null;
37
+ contentType: string;
38
+ } = {
39
+ body: ReadableStream | null;
40
+ contentType: string;
41
+ }>({ request, metadata, xServerEnvHeader, logError, findAssetEntryForPath, getAssetKey, negotiateContent, fetchAsset, generateNotFoundResponse, attachAdditionalHeaders, caches, waitUntil, }: HandlerContext<AssetEntry, ContentNegotiation, Asset>): Promise<Response>;
42
+ export declare function parseQualityWeightedList(list?: string): Record<string, number>;
43
+ export {};
44
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../asset-server/handler.ts"],"names":[],"mappings":"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"}