wrangler 0.0.0-e2f9bb2 → 0.0.0-e322475
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/Cloudflare_CA.pem +18 -0
- package/README.md +3 -1
- package/bin/wrangler.js +36 -4
- package/kv-asset-handler.js +1 -0
- package/package.json +15 -7
- package/pages/functions/buildPlugin.ts +13 -0
- package/pages/functions/buildWorker.ts +14 -1
- package/pages/functions/template-plugin.ts +3 -2
- package/src/__tests__/configuration.test.ts +652 -229
- package/src/__tests__/dev.test.tsx +372 -79
- package/src/__tests__/helpers/mock-cfetch.ts +2 -2
- package/src/__tests__/helpers/mock-console.ts +11 -1
- package/src/__tests__/helpers/mock-dialogs.ts +75 -11
- package/src/__tests__/helpers/mock-process.ts +24 -0
- package/src/__tests__/index.test.ts +81 -72
- package/src/__tests__/init.test.ts +1360 -410
- package/src/__tests__/jest.setup.ts +38 -0
- package/src/__tests__/kv.test.ts +218 -152
- package/src/__tests__/logger.test.ts +26 -0
- package/src/__tests__/package-manager.test.ts +154 -7
- package/src/__tests__/pages.test.ts +478 -53
- package/src/__tests__/parse.test.ts +8 -0
- package/src/__tests__/publish.test.ts +1614 -333
- package/src/__tests__/r2.test.ts +55 -36
- package/src/__tests__/secret.test.ts +39 -4
- package/src/__tests__/user.test.ts +1 -0
- package/src/__tests__/whoami.test.tsx +34 -0
- package/src/abort.d.ts +3 -0
- package/src/bundle-reporter.tsx +29 -0
- package/src/bundle.ts +42 -7
- package/src/cfetch/index.ts +21 -4
- package/src/cfetch/internal.ts +25 -20
- package/src/config/config.ts +11 -2
- package/src/config/environment.ts +41 -15
- package/src/config/index.ts +162 -0
- package/src/config/validation-helpers.ts +10 -1
- package/src/config/validation.ts +234 -78
- package/src/create-worker-preview.ts +32 -22
- package/src/create-worker-upload-form.ts +22 -8
- package/src/dev/dev.tsx +48 -67
- package/src/dev/local.tsx +16 -7
- package/src/dev/remote.tsx +57 -21
- package/src/dev/use-esbuild.ts +1 -7
- package/src/dialogs.tsx +48 -0
- package/src/durable.ts +102 -0
- package/src/entry.ts +71 -10
- package/src/generate-auth-url.ts +33 -0
- package/src/generate-random-state.ts +16 -0
- package/src/git-client.ts +42 -0
- package/src/index.tsx +619 -338
- package/src/inspect.ts +39 -0
- package/src/kv.ts +116 -27
- package/src/logger.ts +8 -1
- package/src/open-in-browser.ts +3 -12
- package/src/package-manager.ts +50 -3
- package/src/pages.tsx +434 -207
- package/src/parse.ts +44 -5
- package/src/proxy.ts +66 -44
- package/src/publish.ts +407 -137
- package/src/sites.tsx +103 -28
- package/src/user.tsx +35 -26
- package/src/whoami.tsx +3 -2
- package/src/worker.ts +10 -1
- package/src/zones.ts +73 -0
- package/templates/new-worker-scheduled.js +17 -0
- package/templates/new-worker-scheduled.ts +32 -0
- package/templates/new-worker.ts +16 -1
- package/templates/no-op-worker.js +10 -0
- package/templates/static-asset-facade.js +2 -6
- package/wrangler-dist/cli.js +46122 -32396
- package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
- package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
- package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
- package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
- package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
- package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
- package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
- package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
- package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
- package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
- package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
- package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
- package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
- package/vendor/wrangler-mime/CHANGELOG.md +0 -289
- package/vendor/wrangler-mime/LICENSE +0 -21
- package/vendor/wrangler-mime/Mime.js +0 -97
- package/vendor/wrangler-mime/README.md +0 -187
- package/vendor/wrangler-mime/cli.js +0 -46
- package/vendor/wrangler-mime/index.js +0 -4
- package/vendor/wrangler-mime/lite.js +0 -4
- package/vendor/wrangler-mime/package.json +0 -52
- package/vendor/wrangler-mime/types/other.js +0 -1
- package/vendor/wrangler-mime/types/standard.js +0 -1
package/src/__tests__/r2.test.ts
CHANGED
|
@@ -17,6 +17,33 @@ describe("wrangler", () => {
|
|
|
17
17
|
|
|
18
18
|
describe("r2", () => {
|
|
19
19
|
describe("bucket", () => {
|
|
20
|
+
it("should show the correct help when an invalid command is passed", async () => {
|
|
21
|
+
await expect(() =>
|
|
22
|
+
runWrangler("r2 bucket foo")
|
|
23
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(`"Unknown argument: foo"`);
|
|
24
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
25
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown argument: foo[0m
|
|
26
|
+
|
|
27
|
+
"
|
|
28
|
+
`);
|
|
29
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
30
|
+
"
|
|
31
|
+
wrangler r2 bucket
|
|
32
|
+
|
|
33
|
+
Manage R2 buckets
|
|
34
|
+
|
|
35
|
+
Commands:
|
|
36
|
+
wrangler r2 bucket create <name> Create a new R2 bucket
|
|
37
|
+
wrangler r2 bucket list List R2 buckets
|
|
38
|
+
wrangler r2 bucket delete <name> Delete an R2 bucket
|
|
39
|
+
|
|
40
|
+
Flags:
|
|
41
|
+
-c, --config Path to .toml configuration file [string]
|
|
42
|
+
-h, --help Show help [boolean]
|
|
43
|
+
-v, --version Show version number [boolean]"
|
|
44
|
+
`);
|
|
45
|
+
});
|
|
46
|
+
|
|
20
47
|
describe("list", () => {
|
|
21
48
|
function mockListRequest(buckets: R2BucketInfo[]) {
|
|
22
49
|
const requests = { count: 0 };
|
|
@@ -69,10 +96,7 @@ describe("wrangler", () => {
|
|
|
69
96
|
);
|
|
70
97
|
expect(std.out).toMatchInlineSnapshot(`
|
|
71
98
|
"
|
|
72
|
-
|
|
73
|
-
`);
|
|
74
|
-
expect(std.err).toMatchInlineSnapshot(`
|
|
75
|
-
"wrangler r2 bucket create <name>
|
|
99
|
+
wrangler r2 bucket create <name>
|
|
76
100
|
|
|
77
101
|
Create a new R2 bucket
|
|
78
102
|
|
|
@@ -80,11 +104,12 @@ describe("wrangler", () => {
|
|
|
80
104
|
name The name of the new bucket [string] [required]
|
|
81
105
|
|
|
82
106
|
Flags:
|
|
83
|
-
-c, --config
|
|
84
|
-
-h, --help
|
|
85
|
-
-v, --version
|
|
86
|
-
|
|
87
|
-
|
|
107
|
+
-c, --config Path to .toml configuration file [string]
|
|
108
|
+
-h, --help Show help [boolean]
|
|
109
|
+
-v, --version Show version number [boolean]"
|
|
110
|
+
`);
|
|
111
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
112
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
|
|
88
113
|
|
|
89
114
|
"
|
|
90
115
|
`);
|
|
@@ -98,10 +123,7 @@ describe("wrangler", () => {
|
|
|
98
123
|
);
|
|
99
124
|
expect(std.out).toMatchInlineSnapshot(`
|
|
100
125
|
"
|
|
101
|
-
|
|
102
|
-
`);
|
|
103
|
-
expect(std.err).toMatchInlineSnapshot(`
|
|
104
|
-
"wrangler r2 bucket create <name>
|
|
126
|
+
wrangler r2 bucket create <name>
|
|
105
127
|
|
|
106
128
|
Create a new R2 bucket
|
|
107
129
|
|
|
@@ -109,11 +131,12 @@ describe("wrangler", () => {
|
|
|
109
131
|
name The name of the new bucket [string] [required]
|
|
110
132
|
|
|
111
133
|
Flags:
|
|
112
|
-
-c, --config
|
|
113
|
-
-h, --help
|
|
114
|
-
-v, --version
|
|
115
|
-
|
|
116
|
-
|
|
134
|
+
-c, --config Path to .toml configuration file [string]
|
|
135
|
+
-h, --help Show help [boolean]
|
|
136
|
+
-v, --version Show version number [boolean]"
|
|
137
|
+
`);
|
|
138
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
139
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
|
|
117
140
|
|
|
118
141
|
"
|
|
119
142
|
`);
|
|
@@ -153,10 +176,7 @@ describe("wrangler", () => {
|
|
|
153
176
|
);
|
|
154
177
|
expect(std.out).toMatchInlineSnapshot(`
|
|
155
178
|
"
|
|
156
|
-
|
|
157
|
-
`);
|
|
158
|
-
expect(std.err).toMatchInlineSnapshot(`
|
|
159
|
-
"wrangler r2 bucket delete <name>
|
|
179
|
+
wrangler r2 bucket delete <name>
|
|
160
180
|
|
|
161
181
|
Delete an R2 bucket
|
|
162
182
|
|
|
@@ -164,11 +184,12 @@ describe("wrangler", () => {
|
|
|
164
184
|
name The name of the bucket to delete [string] [required]
|
|
165
185
|
|
|
166
186
|
Flags:
|
|
167
|
-
-c, --config
|
|
168
|
-
-h, --help
|
|
169
|
-
-v, --version
|
|
170
|
-
|
|
171
|
-
|
|
187
|
+
-c, --config Path to .toml configuration file [string]
|
|
188
|
+
-h, --help Show help [boolean]
|
|
189
|
+
-v, --version Show version number [boolean]"
|
|
190
|
+
`);
|
|
191
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
192
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
|
|
172
193
|
|
|
173
194
|
"
|
|
174
195
|
`);
|
|
@@ -182,10 +203,7 @@ describe("wrangler", () => {
|
|
|
182
203
|
);
|
|
183
204
|
expect(std.out).toMatchInlineSnapshot(`
|
|
184
205
|
"
|
|
185
|
-
|
|
186
|
-
`);
|
|
187
|
-
expect(std.err).toMatchInlineSnapshot(`
|
|
188
|
-
"wrangler r2 bucket delete <name>
|
|
206
|
+
wrangler r2 bucket delete <name>
|
|
189
207
|
|
|
190
208
|
Delete an R2 bucket
|
|
191
209
|
|
|
@@ -193,11 +211,12 @@ describe("wrangler", () => {
|
|
|
193
211
|
name The name of the bucket to delete [string] [required]
|
|
194
212
|
|
|
195
213
|
Flags:
|
|
196
|
-
-c, --config
|
|
197
|
-
-h, --help
|
|
198
|
-
-v, --version
|
|
199
|
-
|
|
200
|
-
|
|
214
|
+
-c, --config Path to .toml configuration file [string]
|
|
215
|
+
-h, --help Show help [boolean]
|
|
216
|
+
-v, --version Show version number [boolean]"
|
|
217
|
+
`);
|
|
218
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
219
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
|
|
201
220
|
|
|
202
221
|
"
|
|
203
222
|
`);
|
|
@@ -60,6 +60,22 @@ describe("wrangler secret", () => {
|
|
|
60
60
|
describe("interactive", () => {
|
|
61
61
|
useMockStdin({ isTTY: true });
|
|
62
62
|
|
|
63
|
+
it("should trim stdin secret value", async () => {
|
|
64
|
+
mockPrompt({
|
|
65
|
+
text: "Enter a secret value:",
|
|
66
|
+
type: "password",
|
|
67
|
+
result: `hunter2
|
|
68
|
+
`,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
mockPutRequest({ name: `secret-name`, text: `hunter2` });
|
|
72
|
+
await runWrangler("secret put secret-name --name script-name");
|
|
73
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
74
|
+
"🌀 Creating the secret for script script-name
|
|
75
|
+
✨ Success! Uploaded secret secret-name"
|
|
76
|
+
`);
|
|
77
|
+
});
|
|
78
|
+
|
|
63
79
|
it("should create a secret", async () => {
|
|
64
80
|
mockPrompt({
|
|
65
81
|
text: "Enter a secret value:",
|
|
@@ -132,7 +148,7 @@ describe("wrangler secret", () => {
|
|
|
132
148
|
}
|
|
133
149
|
expect(std.out).toMatchInlineSnapshot(`
|
|
134
150
|
"
|
|
135
|
-
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new
|
|
151
|
+
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose[0m"
|
|
136
152
|
`);
|
|
137
153
|
expect(std.err).toMatchInlineSnapshot(`
|
|
138
154
|
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mMissing script name[0m
|
|
@@ -146,6 +162,25 @@ describe("wrangler secret", () => {
|
|
|
146
162
|
describe("non-interactive", () => {
|
|
147
163
|
const mockStdIn = useMockStdin({ isTTY: false });
|
|
148
164
|
|
|
165
|
+
it("should trim stdin secret value, from piped input", async () => {
|
|
166
|
+
mockPutRequest({ name: "the-key", text: "the-secret" });
|
|
167
|
+
// Pipe the secret in as three chunks to test that we reconstitute it correctly.
|
|
168
|
+
mockStdIn.send(
|
|
169
|
+
`the`,
|
|
170
|
+
`-`,
|
|
171
|
+
`secret
|
|
172
|
+
` // whitespace & newline being removed
|
|
173
|
+
);
|
|
174
|
+
await runWrangler("secret put the-key --name script-name");
|
|
175
|
+
|
|
176
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
177
|
+
"🌀 Creating the secret for script script-name
|
|
178
|
+
✨ Success! Uploaded secret the-key"
|
|
179
|
+
`);
|
|
180
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
181
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
182
|
+
});
|
|
183
|
+
|
|
149
184
|
it("should create a secret, from piped input", async () => {
|
|
150
185
|
mockPutRequest({ name: "the-key", text: "the-secret" });
|
|
151
186
|
// Pipe the secret in as three chunks to test that we reconstitute it correctly.
|
|
@@ -169,7 +204,7 @@ describe("wrangler secret", () => {
|
|
|
169
204
|
|
|
170
205
|
expect(std.out).toMatchInlineSnapshot(`
|
|
171
206
|
"
|
|
172
|
-
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new
|
|
207
|
+
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose[0m"
|
|
173
208
|
`);
|
|
174
209
|
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
175
210
|
});
|
|
@@ -337,7 +372,7 @@ describe("wrangler secret", () => {
|
|
|
337
372
|
}
|
|
338
373
|
expect(std.out).toMatchInlineSnapshot(`
|
|
339
374
|
"
|
|
340
|
-
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new
|
|
375
|
+
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose[0m"
|
|
341
376
|
`);
|
|
342
377
|
expect(std.err).toMatchInlineSnapshot(`
|
|
343
378
|
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mMissing script name[0m
|
|
@@ -433,7 +468,7 @@ describe("wrangler secret", () => {
|
|
|
433
468
|
}
|
|
434
469
|
expect(std.out).toMatchInlineSnapshot(`
|
|
435
470
|
"
|
|
436
|
-
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new
|
|
471
|
+
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose[0m"
|
|
437
472
|
`);
|
|
438
473
|
expect(std.err).toMatchInlineSnapshot(`
|
|
439
474
|
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mMissing script name[0m
|
|
@@ -46,6 +46,7 @@ describe("User", () => {
|
|
|
46
46
|
|
|
47
47
|
expect(std.out).toMatchInlineSnapshot(`
|
|
48
48
|
"Attempting to login via OAuth...
|
|
49
|
+
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20pages%3Awrite%20zone%3Aread%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
|
|
49
50
|
Successfully logged in."
|
|
50
51
|
`);
|
|
51
52
|
|
|
@@ -9,6 +9,8 @@ import { runInTempDir } from "./helpers/run-in-tmp";
|
|
|
9
9
|
import type { UserInfo } from "../whoami";
|
|
10
10
|
|
|
11
11
|
describe("getUserInfo()", () => {
|
|
12
|
+
const ENV_COPY = process.env;
|
|
13
|
+
|
|
12
14
|
runInTempDir({ homedir: "./home" });
|
|
13
15
|
const std = mockConsoleMethods();
|
|
14
16
|
const { setIsTTY } = useMockIsTTY();
|
|
@@ -17,6 +19,10 @@ describe("getUserInfo()", () => {
|
|
|
17
19
|
setIsTTY(true);
|
|
18
20
|
});
|
|
19
21
|
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
process.env = ENV_COPY;
|
|
24
|
+
});
|
|
25
|
+
|
|
20
26
|
it("should return undefined if there is no config file", async () => {
|
|
21
27
|
const userInfo = await getUserInfo();
|
|
22
28
|
expect(userInfo).toBeUndefined();
|
|
@@ -28,6 +34,34 @@ describe("getUserInfo()", () => {
|
|
|
28
34
|
expect(userInfo).toBeUndefined();
|
|
29
35
|
});
|
|
30
36
|
|
|
37
|
+
it("should say it's using an API token when one is set", async () => {
|
|
38
|
+
process.env = {
|
|
39
|
+
CLOUDFLARE_API_TOKEN: "123456789",
|
|
40
|
+
};
|
|
41
|
+
setMockResponse("/user", () => {
|
|
42
|
+
return { email: "user@example.com" };
|
|
43
|
+
});
|
|
44
|
+
setMockResponse("/accounts", () => {
|
|
45
|
+
return [
|
|
46
|
+
{ name: "Account One", id: "account-1" },
|
|
47
|
+
{ name: "Account Two", id: "account-2" },
|
|
48
|
+
{ name: "Account Three", id: "account-3" },
|
|
49
|
+
];
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const userInfo = await getUserInfo();
|
|
53
|
+
expect(userInfo).toEqual({
|
|
54
|
+
authType: "API",
|
|
55
|
+
apiToken: "123456789",
|
|
56
|
+
email: "user@example.com",
|
|
57
|
+
accounts: [
|
|
58
|
+
{ name: "Account One", id: "account-1" },
|
|
59
|
+
{ name: "Account Two", id: "account-2" },
|
|
60
|
+
{ name: "Account Three", id: "account-3" },
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
31
65
|
it("should return the user's email and accounts if authenticated via config token", async () => {
|
|
32
66
|
writeAuthConfigFile({ oauth_token: "some-oauth-token" });
|
|
33
67
|
|
package/src/abort.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Blob } from "node:buffer";
|
|
2
|
+
import { gzipSync } from "node:zlib";
|
|
3
|
+
import { logger } from "./logger";
|
|
4
|
+
import type { CfModule } from "./worker";
|
|
5
|
+
|
|
6
|
+
async function getSize(modules: CfModule[]) {
|
|
7
|
+
const gzipSize = gzipSync(
|
|
8
|
+
await new Blob(modules.map((file) => file.content)).arrayBuffer()
|
|
9
|
+
).byteLength;
|
|
10
|
+
const aggregateSize = new Blob(modules.map((file) => file.content)).size;
|
|
11
|
+
|
|
12
|
+
return { size: aggregateSize, gzipSize };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function printBundleSize(
|
|
16
|
+
main: {
|
|
17
|
+
name: string;
|
|
18
|
+
content: string;
|
|
19
|
+
},
|
|
20
|
+
modules: CfModule[]
|
|
21
|
+
) {
|
|
22
|
+
const { size, gzipSize } = await getSize([...modules, main]);
|
|
23
|
+
|
|
24
|
+
const bundleReport = `${(size / 1024).toFixed(2)} KiB / gzip: ${(
|
|
25
|
+
gzipSize / 1024
|
|
26
|
+
).toFixed(2)} KiB`;
|
|
27
|
+
|
|
28
|
+
logger.log(`Total Upload: ${bundleReport}`);
|
|
29
|
+
}
|
package/src/bundle.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
|
+
import { builtinModules } from "node:module";
|
|
3
4
|
import * as path from "node:path";
|
|
4
5
|
import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
|
|
5
6
|
import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
|
|
@@ -16,6 +17,33 @@ type BundleResult = {
|
|
|
16
17
|
stop: (() => void) | undefined;
|
|
17
18
|
};
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Searches for any uses of node's builtin modules, and throws an error if it
|
|
22
|
+
* finds anything. This plugin is only used when nodeCompat is not enabled.
|
|
23
|
+
* Supports both regular node builtins, and the new "node:<MODULE>" format.
|
|
24
|
+
*/
|
|
25
|
+
const checkForNodeBuiltinsPlugin = {
|
|
26
|
+
name: "checkForNodeBuiltins",
|
|
27
|
+
setup(build: esbuild.PluginBuild) {
|
|
28
|
+
build.onResolve(
|
|
29
|
+
{
|
|
30
|
+
filter: new RegExp(
|
|
31
|
+
"^(" +
|
|
32
|
+
builtinModules.join("|") +
|
|
33
|
+
"|" +
|
|
34
|
+
builtinModules.map((module) => "node:" + module).join("|") +
|
|
35
|
+
")$"
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
() => {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Detected a Node builtin module import while Node compatibility is disabled.\nAdd node_compat = true to your wrangler.toml file to enable Node compatibility.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
19
47
|
/**
|
|
20
48
|
* Generate a bundle for the worker identified by the arguments passed in.
|
|
21
49
|
*/
|
|
@@ -60,13 +88,14 @@ export async function bundleWorker(
|
|
|
60
88
|
format: entry.format,
|
|
61
89
|
rules,
|
|
62
90
|
});
|
|
91
|
+
|
|
63
92
|
const result = await esbuild.build({
|
|
64
93
|
...getEntryPoint(entry.file, serveAssetsFromWorker),
|
|
65
94
|
bundle: true,
|
|
66
95
|
absWorkingDir: entry.directory,
|
|
67
96
|
outdir: destination,
|
|
68
97
|
external: ["__STATIC_CONTENT_MANIFEST"],
|
|
69
|
-
format: "esm",
|
|
98
|
+
format: entry.format === "modules" ? "esm" : "iife",
|
|
70
99
|
target: "es2020",
|
|
71
100
|
sourcemap: true,
|
|
72
101
|
minify,
|
|
@@ -87,7 +116,9 @@ export async function bundleWorker(
|
|
|
87
116
|
moduleCollector.plugin,
|
|
88
117
|
...(nodeCompat
|
|
89
118
|
? [NodeGlobalsPolyfills({ buffer: true }), NodeModulesPolyfills()]
|
|
90
|
-
:
|
|
119
|
+
: // we use checkForNodeBuiltinsPlugin to throw a nicer error
|
|
120
|
+
// if we find node builtins when nodeCompat isn't turned on
|
|
121
|
+
[checkForNodeBuiltinsPlugin]),
|
|
91
122
|
],
|
|
92
123
|
...(jsxFactory && { jsxFactory }),
|
|
93
124
|
...(jsxFragment && { jsxFragment }),
|
|
@@ -123,9 +154,7 @@ export async function bundleWorker(
|
|
|
123
154
|
};
|
|
124
155
|
}
|
|
125
156
|
|
|
126
|
-
type EntryPoint =
|
|
127
|
-
| { stdin: esbuild.StdinOptions; nodePaths: string[] }
|
|
128
|
-
| { entryPoints: string[] };
|
|
157
|
+
type EntryPoint = { stdin: esbuild.StdinOptions } | { entryPoints: string[] };
|
|
129
158
|
|
|
130
159
|
/**
|
|
131
160
|
* Create an object that describes the entry point for esbuild.
|
|
@@ -146,11 +175,17 @@ function getEntryPoint(
|
|
|
146
175
|
path.join(__dirname, "../templates/static-asset-facade.js"),
|
|
147
176
|
"utf8"
|
|
148
177
|
)
|
|
149
|
-
|
|
178
|
+
// on windows, escape backslashes in the path (`\`)
|
|
179
|
+
.replace("__ENTRY_POINT__", entryFile.replaceAll("\\", "\\\\"))
|
|
180
|
+
.replace(
|
|
181
|
+
"__KV_ASSET_HANDLER__",
|
|
182
|
+
path
|
|
183
|
+
.join(__dirname, "../kv-asset-handler.js")
|
|
184
|
+
.replaceAll("\\", "\\\\")
|
|
185
|
+
),
|
|
150
186
|
sourcefile: "static-asset-facade.js",
|
|
151
187
|
resolveDir: path.dirname(entryFile),
|
|
152
188
|
},
|
|
153
|
-
nodePaths: [path.join(__dirname, "../vendor")],
|
|
154
189
|
};
|
|
155
190
|
} else {
|
|
156
191
|
return { entryPoints: [entryFile] };
|
package/src/cfetch/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { getCloudflareAPIBaseURL as getCloudflareApiBaseUrl } from "./internal";
|
|
|
10
10
|
export interface FetchError {
|
|
11
11
|
code: number;
|
|
12
12
|
message: string;
|
|
13
|
+
error_chain?: FetchError[];
|
|
13
14
|
}
|
|
14
15
|
export interface FetchResult<ResponseType = unknown> {
|
|
15
16
|
success: boolean;
|
|
@@ -27,12 +28,14 @@ export { fetchKVGetValue } from "./internal";
|
|
|
27
28
|
export async function fetchResult<ResponseType>(
|
|
28
29
|
resource: string,
|
|
29
30
|
init: RequestInit = {},
|
|
30
|
-
queryParams?: URLSearchParams
|
|
31
|
+
queryParams?: URLSearchParams,
|
|
32
|
+
abortSignal?: AbortSignal
|
|
31
33
|
): Promise<ResponseType> {
|
|
32
34
|
const json = await fetchInternal<FetchResult<ResponseType>>(
|
|
33
35
|
resource,
|
|
34
36
|
init,
|
|
35
|
-
queryParams
|
|
37
|
+
queryParams,
|
|
38
|
+
abortSignal
|
|
36
39
|
);
|
|
37
40
|
if (json.success) {
|
|
38
41
|
return json.result;
|
|
@@ -83,9 +86,9 @@ function throwFetchError(
|
|
|
83
86
|
response: FetchResult<unknown>
|
|
84
87
|
): never {
|
|
85
88
|
const error = new ParseError({
|
|
86
|
-
text:
|
|
89
|
+
text: `A request to the Cloudflare API (${resource}) failed.`,
|
|
87
90
|
notes: response.errors.map((err) => ({
|
|
88
|
-
text: err
|
|
91
|
+
text: renderError(err),
|
|
89
92
|
})),
|
|
90
93
|
});
|
|
91
94
|
// add the first error code directly to this error
|
|
@@ -102,3 +105,17 @@ function hasCursor(result_info: unknown): result_info is { cursor: string } {
|
|
|
102
105
|
const cursor = (result_info as { cursor: string } | undefined)?.cursor;
|
|
103
106
|
return cursor !== undefined && cursor !== null && cursor !== "";
|
|
104
107
|
}
|
|
108
|
+
|
|
109
|
+
function renderError(err: FetchError, level = 0): string {
|
|
110
|
+
const chainedMessages =
|
|
111
|
+
err.error_chain
|
|
112
|
+
?.map(
|
|
113
|
+
(chainedError) =>
|
|
114
|
+
`\n${" ".repeat(level)}- ${renderError(chainedError, level + 1)}`
|
|
115
|
+
)
|
|
116
|
+
.join("\n") ?? "";
|
|
117
|
+
return (
|
|
118
|
+
(err.code ? `${err.message} [code: ${err.code}]` : err.message) +
|
|
119
|
+
chainedMessages
|
|
120
|
+
);
|
|
121
|
+
}
|
package/src/cfetch/internal.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
1
2
|
import { fetch, Headers } from "undici";
|
|
3
|
+
import { version as wranglerVersion } from "../../package.json";
|
|
2
4
|
import { getEnvironmentVariableFactory } from "../environment-variables";
|
|
3
5
|
import { ParseError, parseJSON } from "../parse";
|
|
4
|
-
import {
|
|
6
|
+
import { loginOrRefreshIfRequired, requireApiToken } from "../user";
|
|
5
7
|
import type { URLSearchParams } from "node:url";
|
|
6
8
|
import type { RequestInit, HeadersInit } from "undici";
|
|
7
9
|
|
|
@@ -26,12 +28,18 @@ export const getCloudflareAPIBaseURL = getEnvironmentVariableFactory({
|
|
|
26
28
|
export async function fetchInternal<ResponseType>(
|
|
27
29
|
resource: string,
|
|
28
30
|
init: RequestInit = {},
|
|
29
|
-
queryParams?: URLSearchParams
|
|
31
|
+
queryParams?: URLSearchParams,
|
|
32
|
+
abortSignal?: AbortSignal
|
|
30
33
|
): Promise<ResponseType> {
|
|
34
|
+
assert(
|
|
35
|
+
resource.startsWith("/"),
|
|
36
|
+
`CF API fetch - resource path must start with a "/" but got "${resource}"`
|
|
37
|
+
);
|
|
31
38
|
await requireLoggedIn();
|
|
32
39
|
const apiToken = requireApiToken();
|
|
33
40
|
const headers = cloneHeaders(init.headers);
|
|
34
|
-
|
|
41
|
+
addAuthorizationHeaderIfUnspecified(headers, apiToken);
|
|
42
|
+
addUserAgent(headers);
|
|
35
43
|
|
|
36
44
|
const queryString = queryParams ? `?${queryParams.toString()}` : "";
|
|
37
45
|
const method = init.method ?? "GET";
|
|
@@ -41,11 +49,12 @@ export async function fetchInternal<ResponseType>(
|
|
|
41
49
|
method,
|
|
42
50
|
...init,
|
|
43
51
|
headers,
|
|
52
|
+
signal: abortSignal,
|
|
44
53
|
}
|
|
45
54
|
);
|
|
46
55
|
const jsonText = await response.text();
|
|
47
56
|
try {
|
|
48
|
-
return parseJSON(jsonText)
|
|
57
|
+
return parseJSON<ResponseType>(jsonText);
|
|
49
58
|
} catch (err) {
|
|
50
59
|
throw new ParseError({
|
|
51
60
|
text: "Received a malformed response from the API",
|
|
@@ -86,24 +95,17 @@ async function requireLoggedIn(): Promise<void> {
|
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
97
|
|
|
89
|
-
function
|
|
90
|
-
const authToken = getAPIToken();
|
|
91
|
-
if (!authToken) {
|
|
92
|
-
throw new Error("No API token found.");
|
|
93
|
-
}
|
|
94
|
-
return authToken;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function addAuthorizationHeader(
|
|
98
|
+
function addAuthorizationHeaderIfUnspecified(
|
|
98
99
|
headers: Record<string, string>,
|
|
99
100
|
apiToken: string
|
|
100
101
|
): void {
|
|
101
|
-
if ("Authorization" in headers) {
|
|
102
|
-
|
|
103
|
-
"The request already specifies an authorisation header - cannot add a new one."
|
|
104
|
-
);
|
|
102
|
+
if (!("Authorization" in headers)) {
|
|
103
|
+
headers["Authorization"] = `Bearer ${apiToken}`;
|
|
105
104
|
}
|
|
106
|
-
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function addUserAgent(headers: Record<string, string>): void {
|
|
108
|
+
headers["User-Agent"] = `wrangler/${wranglerVersion}`;
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
/**
|
|
@@ -112,13 +114,16 @@ function addAuthorizationHeader(
|
|
|
112
114
|
* doesn't return json. We inline the implementation and try not to share
|
|
113
115
|
* any code with the other calls. We should push back on any new APIs that
|
|
114
116
|
* try to introduce non-"standard" response structures.
|
|
117
|
+
*
|
|
118
|
+
* Note: any calls to fetchKVGetValue must call encodeURIComponent on key
|
|
119
|
+
* before passing it
|
|
115
120
|
*/
|
|
116
121
|
|
|
117
122
|
export async function fetchKVGetValue(
|
|
118
123
|
accountId: string,
|
|
119
124
|
namespaceId: string,
|
|
120
125
|
key: string
|
|
121
|
-
): Promise<
|
|
126
|
+
): Promise<ArrayBuffer> {
|
|
122
127
|
await requireLoggedIn();
|
|
123
128
|
const apiToken = requireApiToken();
|
|
124
129
|
const headers = { Authorization: `Bearer ${apiToken}` };
|
|
@@ -128,7 +133,7 @@ export async function fetchKVGetValue(
|
|
|
128
133
|
headers,
|
|
129
134
|
});
|
|
130
135
|
if (response.ok) {
|
|
131
|
-
return await response.
|
|
136
|
+
return await response.arrayBuffer();
|
|
132
137
|
} else {
|
|
133
138
|
throw new Error(
|
|
134
139
|
`Failed to fetch ${resource} - ${response.status}: ${response.statusText});`
|
package/src/config/config.ts
CHANGED
|
@@ -114,6 +114,15 @@ export interface ConfigFields<Dev extends RawDevConfig> {
|
|
|
114
114
|
}
|
|
115
115
|
| undefined;
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Serve a folder of static assets with your Worker, without any additional code.
|
|
119
|
+
* This can either be a string, or an object with additional config fields.
|
|
120
|
+
*/
|
|
121
|
+
assets:
|
|
122
|
+
| string
|
|
123
|
+
| { bucket: string; include: string[]; exclude: string[] }
|
|
124
|
+
| undefined;
|
|
125
|
+
|
|
117
126
|
/**
|
|
118
127
|
* A list of wasm modules that your worker should be bound to. This is
|
|
119
128
|
* the "legacy" way of binding to a wasm module. ES module workers should
|
|
@@ -161,7 +170,7 @@ export interface DevConfig {
|
|
|
161
170
|
*
|
|
162
171
|
* @default `8787`
|
|
163
172
|
*/
|
|
164
|
-
port: number;
|
|
173
|
+
port: number | undefined;
|
|
165
174
|
|
|
166
175
|
/**
|
|
167
176
|
* Protocol that local wrangler dev server listens to requests on.
|
|
@@ -184,7 +193,7 @@ export interface DevConfig {
|
|
|
184
193
|
/**
|
|
185
194
|
* Host to forward requests to, defaults to the host of the first route of project
|
|
186
195
|
*/
|
|
187
|
-
host:
|
|
196
|
+
host: string | undefined;
|
|
188
197
|
}
|
|
189
198
|
|
|
190
199
|
export type RawDevConfig = Partial<DevConfig>;
|