@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.
- package/README.md +5 -0
- package/asset-server/handler.ts +625 -0
- package/asset-server/metadata.ts +67 -0
- package/asset-server/patchUrl.ts +22 -0
- package/asset-server/responses.ts +196 -0
- package/asset-server/rulesEngine.ts +82 -0
- package/dist/__tests__/asset-server/handler.test.d.ts +2 -0
- package/dist/__tests__/asset-server/handler.test.d.ts.map +1 -0
- package/dist/__tests__/asset-server/handler.test.js +430 -0
- package/dist/__tests__/asset-server/responses.test.d.ts +2 -0
- package/dist/__tests__/asset-server/responses.test.d.ts.map +1 -0
- package/dist/__tests__/asset-server/responses.test.js +22 -0
- package/dist/__tests__/asset-server/rulesEngine.test.d.ts +2 -0
- package/dist/__tests__/asset-server/rulesEngine.test.d.ts.map +1 -0
- package/dist/__tests__/asset-server/rulesEngine.test.js +70 -0
- package/dist/__tests__/jest.setup.d.ts +2 -0
- package/dist/__tests__/jest.setup.d.ts.map +1 -0
- package/dist/__tests__/jest.setup.js +7 -0
- package/dist/__tests__/metadata-generator/createMetadataObject.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/createMetadataObject.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/createMetadataObject.test.js +293 -0
- package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.js +194 -0
- package/dist/__tests__/metadata-generator/parseHeaders.valid.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/parseHeaders.valid.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/parseHeaders.valid.test.js +132 -0
- package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.js +243 -0
- package/dist/__tests__/metadata-generator/parseRedirects.valid.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/parseRedirects.valid.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/parseRedirects.valid.test.js +88 -0
- package/dist/asset-server/handler.d.ts +44 -0
- package/dist/asset-server/handler.d.ts.map +1 -0
- package/dist/asset-server/handler.js +420 -0
- package/dist/asset-server/metadata.d.ts +52 -0
- package/dist/asset-server/metadata.d.ts.map +1 -0
- package/dist/asset-server/metadata.js +3 -0
- package/dist/asset-server/patchUrl.d.ts +2 -0
- package/dist/asset-server/patchUrl.d.ts.map +1 -0
- package/dist/asset-server/patchUrl.js +19 -0
- package/dist/asset-server/responses.d.ts +45 -0
- package/dist/asset-server/responses.d.ts.map +1 -0
- package/dist/asset-server/responses.js +165 -0
- package/dist/asset-server/rulesEngine.d.ts +7 -0
- package/dist/asset-server/rulesEngine.d.ts.map +1 -0
- package/dist/asset-server/rulesEngine.js +68 -0
- package/dist/environment-polyfills/index.d.ts +3 -0
- package/dist/environment-polyfills/index.d.ts.map +1 -0
- package/dist/environment-polyfills/index.js +14 -0
- package/dist/environment-polyfills/miniflare-tre.d.ts +3 -0
- package/dist/environment-polyfills/miniflare-tre.d.ts.map +1 -0
- package/dist/environment-polyfills/miniflare-tre.js +35 -0
- package/dist/environment-polyfills/miniflare.d.ts +3 -0
- package/dist/environment-polyfills/miniflare.d.ts.map +1 -0
- package/dist/environment-polyfills/miniflare.js +35 -0
- package/dist/environment-polyfills/types.d.ts +34 -0
- package/dist/environment-polyfills/types.d.ts.map +1 -0
- package/dist/environment-polyfills/types.js +5 -0
- package/dist/metadata-generator/constants.d.ts +14 -0
- package/dist/metadata-generator/constants.d.ts.map +1 -0
- package/dist/metadata-generator/constants.js +16 -0
- package/dist/metadata-generator/createMetadataObject.d.ts +10 -0
- package/dist/metadata-generator/createMetadataObject.d.ts.map +1 -0
- package/dist/metadata-generator/createMetadataObject.js +105 -0
- package/dist/metadata-generator/parseHeaders.d.ts +3 -0
- package/dist/metadata-generator/parseHeaders.d.ts.map +1 -0
- package/dist/metadata-generator/parseHeaders.js +146 -0
- package/dist/metadata-generator/parseRedirects.d.ts +3 -0
- package/dist/metadata-generator/parseRedirects.d.ts.map +1 -0
- package/dist/metadata-generator/parseRedirects.js +100 -0
- package/dist/metadata-generator/types.d.ts +74 -0
- package/dist/metadata-generator/types.d.ts.map +1 -0
- package/dist/metadata-generator/types.js +3 -0
- package/dist/metadata-generator/validateURL.d.ts +3 -0
- package/dist/metadata-generator/validateURL.d.ts.map +1 -0
- package/dist/metadata-generator/validateURL.js +46 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/environment-polyfills/index.ts +14 -0
- package/environment-polyfills/miniflare-tre.ts +12 -0
- package/environment-polyfills/miniflare.ts +12 -0
- package/environment-polyfills/types.ts +42 -0
- package/metadata-generator/constants.ts +15 -0
- package/metadata-generator/createMetadataObject.ts +164 -0
- package/metadata-generator/parseHeaders.ts +168 -0
- package/metadata-generator/parseRedirects.ts +129 -0
- package/metadata-generator/types.ts +90 -0
- package/metadata-generator/validateURL.ts +57 -0
- package/package.json +63 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
globalThis.URL = (function (globalURL) {
|
|
4
|
+
PatchedURL.prototype = globalURL.prototype;
|
|
5
|
+
PatchedURL.createObjectURL = globalURL.createObjectURL;
|
|
6
|
+
PatchedURL.revokeObjectURL = globalURL.revokeObjectURL;
|
|
7
|
+
|
|
8
|
+
return PatchedURL as unknown as typeof globalURL;
|
|
9
|
+
|
|
10
|
+
function PatchedURL(input: string, base?: string | URL) {
|
|
11
|
+
const url = new globalURL(encodeURI(input), base);
|
|
12
|
+
|
|
13
|
+
return new Proxy(url, {
|
|
14
|
+
get(target, prop) {
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
return globalThis.decodeURIComponent((target as any)[prop]);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
})(URL);
|
|
21
|
+
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
type HeadersInit = ConstructorParameters<typeof Headers>[0];
|
|
2
|
+
|
|
3
|
+
function mergeHeaders(base: HeadersInit, extra: HeadersInit) {
|
|
4
|
+
base = new Headers(base ?? {});
|
|
5
|
+
extra = new Headers(extra ?? {});
|
|
6
|
+
|
|
7
|
+
return new Headers({
|
|
8
|
+
...Object.fromEntries(base.entries()),
|
|
9
|
+
...Object.fromEntries(extra.entries()),
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function stripLeadingDoubleSlashes(location: string) {
|
|
14
|
+
return location.replace(/^(\/|%2F|%2f|%5C|%5c|\\)+(.*)/, "/$2");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class OkResponse extends Response {
|
|
18
|
+
constructor(...[body, init]: ConstructorParameters<typeof Response>) {
|
|
19
|
+
super(body, {
|
|
20
|
+
...init,
|
|
21
|
+
status: 200,
|
|
22
|
+
statusText: "OK",
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class MovedPermanentlyResponse extends Response {
|
|
28
|
+
constructor(
|
|
29
|
+
location: string,
|
|
30
|
+
init?: ConstructorParameters<typeof Response>[1],
|
|
31
|
+
{
|
|
32
|
+
preventLeadingDoubleSlash = true,
|
|
33
|
+
}: { preventLeadingDoubleSlash: boolean } = {
|
|
34
|
+
preventLeadingDoubleSlash: true,
|
|
35
|
+
}
|
|
36
|
+
) {
|
|
37
|
+
location = preventLeadingDoubleSlash
|
|
38
|
+
? stripLeadingDoubleSlashes(location)
|
|
39
|
+
: location;
|
|
40
|
+
super(`Redirecting to ${location}`, {
|
|
41
|
+
...init,
|
|
42
|
+
status: 301,
|
|
43
|
+
statusText: "Moved Permanently",
|
|
44
|
+
headers: mergeHeaders(init?.headers, {
|
|
45
|
+
location,
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export class FoundResponse extends Response {
|
|
52
|
+
constructor(
|
|
53
|
+
location: string,
|
|
54
|
+
init?: ConstructorParameters<typeof Response>[1],
|
|
55
|
+
{
|
|
56
|
+
preventLeadingDoubleSlash = true,
|
|
57
|
+
}: { preventLeadingDoubleSlash: boolean } = {
|
|
58
|
+
preventLeadingDoubleSlash: true,
|
|
59
|
+
}
|
|
60
|
+
) {
|
|
61
|
+
location = preventLeadingDoubleSlash
|
|
62
|
+
? stripLeadingDoubleSlashes(location)
|
|
63
|
+
: location;
|
|
64
|
+
super(`Redirecting to ${location}`, {
|
|
65
|
+
...init,
|
|
66
|
+
status: 302,
|
|
67
|
+
statusText: "Found",
|
|
68
|
+
headers: mergeHeaders(init?.headers, {
|
|
69
|
+
location,
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class NotModifiedResponse extends Response {
|
|
76
|
+
constructor(...[_body, _init]: ConstructorParameters<typeof Response>) {
|
|
77
|
+
super(undefined, {
|
|
78
|
+
status: 304,
|
|
79
|
+
statusText: "Not Modified",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export class PermanentRedirectResponse extends Response {
|
|
85
|
+
constructor(
|
|
86
|
+
location: string,
|
|
87
|
+
init?: ConstructorParameters<typeof Response>[1],
|
|
88
|
+
{
|
|
89
|
+
preventLeadingDoubleSlash = true,
|
|
90
|
+
}: { preventLeadingDoubleSlash: boolean } = {
|
|
91
|
+
preventLeadingDoubleSlash: true,
|
|
92
|
+
}
|
|
93
|
+
) {
|
|
94
|
+
location = preventLeadingDoubleSlash
|
|
95
|
+
? stripLeadingDoubleSlashes(location)
|
|
96
|
+
: location;
|
|
97
|
+
super(undefined, {
|
|
98
|
+
...init,
|
|
99
|
+
status: 308,
|
|
100
|
+
statusText: "Permanent Redirect",
|
|
101
|
+
headers: mergeHeaders(init?.headers, {
|
|
102
|
+
location,
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export class NotFoundResponse extends Response {
|
|
109
|
+
constructor(...[body, init]: ConstructorParameters<typeof Response>) {
|
|
110
|
+
super(body, {
|
|
111
|
+
...init,
|
|
112
|
+
status: 404,
|
|
113
|
+
statusText: "Not Found",
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export class MethodNotAllowedResponse extends Response {
|
|
119
|
+
constructor(...[body, init]: ConstructorParameters<typeof Response>) {
|
|
120
|
+
super(body, {
|
|
121
|
+
...init,
|
|
122
|
+
status: 405,
|
|
123
|
+
statusText: "Method Not Allowed",
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export class NotAcceptableResponse extends Response {
|
|
129
|
+
constructor(...[body, init]: ConstructorParameters<typeof Response>) {
|
|
130
|
+
super(body, {
|
|
131
|
+
...init,
|
|
132
|
+
status: 406,
|
|
133
|
+
statusText: "Not Acceptable",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export class InternalServerErrorResponse extends Response {
|
|
139
|
+
constructor(err: Error, init?: ConstructorParameters<typeof Response>[1]) {
|
|
140
|
+
let body: string | undefined = undefined;
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
142
|
+
if ((globalThis as any).DEBUG) {
|
|
143
|
+
body = `${err.message}\n\n${err.stack}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
super(body, {
|
|
147
|
+
...init,
|
|
148
|
+
status: 500,
|
|
149
|
+
statusText: "Internal Server Error",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export class SeeOtherResponse extends Response {
|
|
155
|
+
constructor(
|
|
156
|
+
location: string,
|
|
157
|
+
init?: ConstructorParameters<typeof Response>[1],
|
|
158
|
+
{
|
|
159
|
+
preventLeadingDoubleSlash = true,
|
|
160
|
+
}: { preventLeadingDoubleSlash: boolean } = {
|
|
161
|
+
preventLeadingDoubleSlash: true,
|
|
162
|
+
}
|
|
163
|
+
) {
|
|
164
|
+
location = preventLeadingDoubleSlash
|
|
165
|
+
? stripLeadingDoubleSlashes(location)
|
|
166
|
+
: location;
|
|
167
|
+
super(`Redirecting to ${location}`, {
|
|
168
|
+
...init,
|
|
169
|
+
status: 303,
|
|
170
|
+
statusText: "See Other",
|
|
171
|
+
headers: mergeHeaders(init?.headers, { location }),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export class TemporaryRedirectResponse extends Response {
|
|
177
|
+
constructor(
|
|
178
|
+
location: string,
|
|
179
|
+
init?: ConstructorParameters<typeof Response>[1],
|
|
180
|
+
{
|
|
181
|
+
preventLeadingDoubleSlash = true,
|
|
182
|
+
}: { preventLeadingDoubleSlash: boolean } = {
|
|
183
|
+
preventLeadingDoubleSlash: true,
|
|
184
|
+
}
|
|
185
|
+
) {
|
|
186
|
+
location = preventLeadingDoubleSlash
|
|
187
|
+
? stripLeadingDoubleSlashes(location)
|
|
188
|
+
: location;
|
|
189
|
+
super(`Redirecting to ${location}`, {
|
|
190
|
+
...init,
|
|
191
|
+
status: 307,
|
|
192
|
+
statusText: "Temporary Redirect",
|
|
193
|
+
headers: mergeHeaders(init?.headers, { location }),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Taken from https://stackoverflow.com/a/3561711
|
|
2
|
+
// which is everything from the tc39 proposal, plus the following two characters: ^/
|
|
3
|
+
// It's also everything included in the URLPattern escape (https://wicg.github.io/urlpattern/#escape-a-regexp-string), plus the following: -
|
|
4
|
+
// As the answer says, there's no downside to escaping these extra characters, so better safe than sorry
|
|
5
|
+
const ESCAPE_REGEX_CHARACTERS = /[-/\\^$*+?.()|[\]{}]/g;
|
|
6
|
+
const escapeRegex = (str: string) => {
|
|
7
|
+
return str.replace(ESCAPE_REGEX_CHARACTERS, "\\$&");
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// Placeholder names must begin with a colon, be alphanumeric and optionally contain underscores.
|
|
11
|
+
// e.g. :place_123_holder
|
|
12
|
+
const HOST_PLACEHOLDER_REGEX = /(?<=^https:\\\/\\\/[^/]*?):([^\\]+)(?=\\)/g;
|
|
13
|
+
const PLACEHOLDER_REGEX = /:(\w+)/g;
|
|
14
|
+
|
|
15
|
+
export type Replacements = Record<string, string>;
|
|
16
|
+
|
|
17
|
+
export type Removals = string[];
|
|
18
|
+
|
|
19
|
+
export const replacer = (str: string, replacements: Replacements) => {
|
|
20
|
+
for (const [replacement, value] of Object.entries(replacements)) {
|
|
21
|
+
str = str.replaceAll(`:${replacement}`, value);
|
|
22
|
+
}
|
|
23
|
+
return str;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const generateRulesMatcher = <T>(
|
|
27
|
+
rules?: Record<string, T>,
|
|
28
|
+
replacerFn: (match: T, replacements: Replacements) => T = (match) => match
|
|
29
|
+
) => {
|
|
30
|
+
if (!rules) return () => [];
|
|
31
|
+
|
|
32
|
+
const compiledRules = Object.entries(rules)
|
|
33
|
+
.map(([rule, match]) => {
|
|
34
|
+
const crossHost = rule.startsWith("https://");
|
|
35
|
+
|
|
36
|
+
// Create :splat capturer then escape.
|
|
37
|
+
rule = rule.split("*").map(escapeRegex).join("(?<splat>.*)");
|
|
38
|
+
|
|
39
|
+
// Create :placeholder capturers (already escaped).
|
|
40
|
+
// For placeholders in the host, we separate at forward slashes and periods.
|
|
41
|
+
// For placeholders in the path, we separate at forward slashes.
|
|
42
|
+
// This matches the behavior of URLPattern.
|
|
43
|
+
// e.g. https://:subdomain.domain/ -> https://(here).domain/
|
|
44
|
+
// e.g. /static/:file -> /static/(image.jpg)
|
|
45
|
+
// e.g. /blog/:post -> /blog/(an-exciting-post)
|
|
46
|
+
const host_matches = rule.matchAll(HOST_PLACEHOLDER_REGEX);
|
|
47
|
+
for (const host_match of host_matches) {
|
|
48
|
+
rule = rule.split(host_match[0]).join(`(?<${host_match[1]}>[^/.]+)`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const path_matches = rule.matchAll(PLACEHOLDER_REGEX);
|
|
52
|
+
for (const path_match of path_matches) {
|
|
53
|
+
rule = rule.split(path_match[0]).join(`(?<${path_match[1]}>[^/]+)`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Wrap in line terminators to be safe.
|
|
57
|
+
rule = "^" + rule + "$";
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const regExp = new RegExp(rule);
|
|
61
|
+
return [{ crossHost, regExp }, match];
|
|
62
|
+
} catch {}
|
|
63
|
+
})
|
|
64
|
+
.filter((value) => value !== undefined) as [
|
|
65
|
+
{ crossHost: boolean; regExp: RegExp },
|
|
66
|
+
T
|
|
67
|
+
][];
|
|
68
|
+
|
|
69
|
+
return ({ request }: { request: Request }) => {
|
|
70
|
+
const { pathname, host } = new URL(request.url);
|
|
71
|
+
|
|
72
|
+
return compiledRules
|
|
73
|
+
.map(([{ crossHost, regExp }, match]) => {
|
|
74
|
+
const test = crossHost ? `https://${host}${pathname}` : pathname;
|
|
75
|
+
const result = regExp.exec(test);
|
|
76
|
+
if (result) {
|
|
77
|
+
return replacerFn(match, result.groups || {});
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
.filter((value) => value !== undefined) as T[];
|
|
81
|
+
};
|
|
82
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.test.d.ts","sourceRoot":"","sources":["../../../__tests__/asset-server/handler.test.ts"],"names":[],"mappings":""}
|