wrangler 0.0.0-e151223 → 0.0.0-e29a241

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 (92) hide show
  1. package/miniflare-dist/index.mjs +79 -0
  2. package/miniflare-dist/index.mjs.map +7 -0
  3. package/package.json +29 -13
  4. package/pages/functions/filepath-routing.test.ts +212 -36
  5. package/pages/functions/filepath-routing.ts +69 -119
  6. package/pages/functions/routes.ts +8 -17
  7. package/pages/functions/template-worker.ts +3 -9
  8. package/src/__tests__/configuration.test.ts +2754 -0
  9. package/src/__tests__/dev.test.tsx +488 -63
  10. package/src/__tests__/dev2.test.tsx +154 -0
  11. package/src/__tests__/guess-worker-format.test.ts +58 -0
  12. package/src/__tests__/helpers/cmd-shim.d.ts +11 -0
  13. package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
  14. package/src/__tests__/helpers/mock-account-id.ts +26 -8
  15. package/src/__tests__/helpers/mock-bin.ts +36 -0
  16. package/src/__tests__/helpers/mock-cfetch.ts +44 -10
  17. package/src/__tests__/helpers/mock-console.ts +21 -7
  18. package/src/__tests__/helpers/mock-kv.ts +9 -16
  19. package/src/__tests__/helpers/mock-stdin.ts +103 -0
  20. package/src/__tests__/helpers/mock-web-socket.ts +29 -0
  21. package/src/__tests__/helpers/run-in-tmp.ts +3 -0
  22. package/src/__tests__/helpers/run-wrangler.ts +5 -3
  23. package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
  24. package/src/__tests__/https-options.test.ts +127 -0
  25. package/src/__tests__/index.test.ts +617 -32
  26. package/src/__tests__/jest.setup.ts +41 -6
  27. package/src/__tests__/kv.test.ts +455 -222
  28. package/src/__tests__/logout.test.ts +15 -13
  29. package/src/__tests__/package-manager.test.ts +206 -0
  30. package/src/__tests__/pages.test.ts +44 -0
  31. package/src/__tests__/parse.test.ts +322 -0
  32. package/src/__tests__/publish.test.ts +1919 -437
  33. package/src/__tests__/r2.test.ts +198 -0
  34. package/src/__tests__/route.test.ts +45 -0
  35. package/src/__tests__/secret.test.ts +301 -86
  36. package/src/__tests__/sentry.test.ts +146 -0
  37. package/src/__tests__/tail.test.ts +564 -0
  38. package/src/__tests__/whoami.test.tsx +21 -7
  39. package/src/bundle.ts +142 -0
  40. package/src/cfetch/index.ts +9 -16
  41. package/src/cfetch/internal.ts +89 -22
  42. package/src/cli.ts +10 -0
  43. package/src/config/README.md +107 -0
  44. package/src/config/config.ts +274 -0
  45. package/src/config/diagnostics.ts +80 -0
  46. package/src/config/environment.ts +310 -0
  47. package/src/config/index.ts +56 -0
  48. package/src/config/validation-helpers.ts +486 -0
  49. package/src/config/validation.ts +1096 -0
  50. package/src/{api/preview.ts → create-worker-preview.ts} +59 -21
  51. package/src/create-worker-upload-form.ts +217 -0
  52. package/src/dev/dev.tsx +364 -0
  53. package/src/dev/local.tsx +226 -0
  54. package/src/dev/remote.tsx +203 -0
  55. package/src/dev/use-esbuild.ts +100 -0
  56. package/src/entry.ts +208 -0
  57. package/src/environment-variables.ts +33 -0
  58. package/src/https-options.ts +122 -0
  59. package/src/index.tsx +1079 -766
  60. package/src/inspect.ts +25 -4
  61. package/src/{kv.tsx → kv.ts} +104 -61
  62. package/src/miniflare-cli/README.md +30 -0
  63. package/src/miniflare-cli/enum-keys.ts +17 -0
  64. package/src/miniflare-cli/index.ts +37 -0
  65. package/src/module-collection.ts +226 -31
  66. package/src/open-in-browser.ts +25 -0
  67. package/src/package-manager.ts +126 -0
  68. package/src/pages.tsx +11 -11
  69. package/src/parse.ts +183 -0
  70. package/src/proxy.ts +115 -45
  71. package/src/publish.ts +265 -328
  72. package/src/r2.ts +50 -0
  73. package/src/reporting.ts +131 -0
  74. package/src/selfsigned.d.ts +29 -0
  75. package/src/sites.tsx +83 -43
  76. package/src/tail/filters.ts +279 -0
  77. package/src/tail/index.ts +299 -0
  78. package/src/tail/printing.ts +62 -0
  79. package/src/user.tsx +223 -124
  80. package/src/{api/worker.ts → worker.ts} +44 -36
  81. package/templates/new-worker.js +15 -0
  82. package/templates/new-worker.ts +15 -0
  83. package/{static-asset-facade.js → templates/static-asset-facade.js} +0 -0
  84. package/templates/tsconfig.json +105 -0
  85. package/wrangler-dist/cli.js +60837 -43876
  86. package/wrangler-dist/cli.js.map +3 -3
  87. package/src/__tests__/helpers/mock-user.ts +0 -27
  88. package/src/api/form_data.ts +0 -134
  89. package/src/config.ts +0 -641
  90. package/src/dev.tsx +0 -834
  91. package/src/npm-installer.ts +0 -20
  92. package/src/tail.tsx +0 -73
@@ -2,17 +2,29 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import * as TOML from "@iarna/toml";
4
4
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
5
- import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
5
+ import {
6
+ createFetchResult,
7
+ setMockRawResponse,
8
+ setMockResponse,
9
+ unsetAllMocks,
10
+ unsetMockFetchKVGetValues,
11
+ } from "./helpers/mock-cfetch";
6
12
  import { mockConsoleMethods } from "./helpers/mock-console";
7
13
  import { mockKeyListRequest } from "./helpers/mock-kv";
8
14
  import { runInTempDir } from "./helpers/run-in-tmp";
9
15
  import { runWrangler } from "./helpers/run-wrangler";
10
- import type { WorkerMetadata } from "../api/form_data";
11
- import type { Config } from "../config";
16
+ import writeWranglerToml from "./helpers/write-wrangler-toml";
17
+ import type { WorkerMetadata } from "../create-worker-upload-form";
12
18
  import type { KVNamespaceInfo } from "../kv";
13
19
  import type { FormData, File } from "undici";
14
20
 
15
21
  describe("publish", () => {
22
+ beforeEach(() => {
23
+ // @ts-expect-error we're using a very simple setTimeout mock here
24
+ jest.spyOn(global, "setTimeout").mockImplementation((fn, _period) => {
25
+ fn();
26
+ });
27
+ });
16
28
  mockAccountId();
17
29
  mockApiToken();
18
30
  runInTempDir();
@@ -20,6 +32,194 @@ describe("publish", () => {
20
32
 
21
33
  afterEach(() => {
22
34
  unsetAllMocks();
35
+ unsetMockFetchKVGetValues();
36
+ });
37
+
38
+ describe("environments", () => {
39
+ it("should use legacy environments by default", async () => {
40
+ writeWranglerToml({ env: { "some-env": {} } });
41
+ writeWorkerSource();
42
+ mockSubDomainRequest();
43
+ mockUploadWorkerRequest({
44
+ env: "some-env",
45
+ legacyEnv: true,
46
+ });
47
+ await runWrangler("publish index.js --env some-env");
48
+ expect(std.out).toMatchInlineSnapshot(`
49
+ "Uploaded test-name-some-env (TIMINGS)
50
+ Published test-name-some-env (TIMINGS)
51
+ test-name-some-env.test-sub-domain.workers.dev"
52
+ `);
53
+ expect(std.err).toMatchInlineSnapshot(`""`);
54
+ expect(std.warn).toMatchInlineSnapshot(`""`);
55
+ });
56
+
57
+ describe("legacy", () => {
58
+ it("uses the script name when no environment is specified", async () => {
59
+ writeWranglerToml();
60
+ writeWorkerSource();
61
+ mockSubDomainRequest();
62
+ mockUploadWorkerRequest({
63
+ legacyEnv: true,
64
+ });
65
+ await runWrangler("publish index.js --legacy-env true");
66
+ expect(std.out).toMatchInlineSnapshot(`
67
+ "Uploaded test-name (TIMINGS)
68
+ Published test-name (TIMINGS)
69
+ test-name.test-sub-domain.workers.dev"
70
+ `);
71
+ expect(std.err).toMatchInlineSnapshot(`""`);
72
+ expect(std.warn).toMatchInlineSnapshot(`""`);
73
+ });
74
+
75
+ it("appends the environment name when provided", async () => {
76
+ writeWranglerToml({ env: { "some-env": {} } });
77
+ writeWorkerSource();
78
+ mockSubDomainRequest();
79
+ mockUploadWorkerRequest({
80
+ env: "some-env",
81
+ legacyEnv: true,
82
+ });
83
+ await runWrangler("publish index.js --env some-env --legacy-env true");
84
+ expect(std.out).toMatchInlineSnapshot(`
85
+ "Uploaded test-name-some-env (TIMINGS)
86
+ Published test-name-some-env (TIMINGS)
87
+ test-name-some-env.test-sub-domain.workers.dev"
88
+ `);
89
+ expect(std.err).toMatchInlineSnapshot(`""`);
90
+ expect(std.warn).toMatchInlineSnapshot(`""`);
91
+ });
92
+ });
93
+
94
+ describe("services", () => {
95
+ it("uses the script name when no environment is specified", async () => {
96
+ writeWranglerToml();
97
+ writeWorkerSource();
98
+ mockSubDomainRequest();
99
+ mockUploadWorkerRequest({
100
+ legacyEnv: false,
101
+ });
102
+ await runWrangler("publish index.js");
103
+ expect(std.out).toMatchInlineSnapshot(`
104
+ "Uploaded test-name (TIMINGS)
105
+ Published test-name (TIMINGS)
106
+ test-name.test-sub-domain.workers.dev"
107
+ `);
108
+ expect(std.err).toMatchInlineSnapshot(`""`);
109
+ expect(std.warn).toMatchInlineSnapshot(`""`);
110
+ });
111
+
112
+ it("publishes as an environment when provided", async () => {
113
+ writeWranglerToml({ env: { "some-env": {} } });
114
+ writeWorkerSource();
115
+ mockSubDomainRequest();
116
+ mockUploadWorkerRequest({
117
+ env: "some-env",
118
+ legacyEnv: false,
119
+ });
120
+ await runWrangler("publish index.js --env some-env --legacy-env false");
121
+ expect(std.out).toMatchInlineSnapshot(`
122
+ "Uploaded test-name (some-env) (TIMINGS)
123
+ Published test-name (some-env) (TIMINGS)
124
+ some-env.test-name.test-sub-domain.workers.dev"
125
+ `);
126
+ expect(std.err).toMatchInlineSnapshot(`""`);
127
+ expect(std.warn).toMatchInlineSnapshot(`""`);
128
+ });
129
+ });
130
+ });
131
+
132
+ it("should resolve wrangler.toml relative to the entrypoint", async () => {
133
+ fs.mkdirSync("./some-path/worker", { recursive: true });
134
+ fs.writeFileSync(
135
+ "./some-path/wrangler.toml",
136
+ TOML.stringify({
137
+ name: "test-name",
138
+ compatibility_date: "2022-01-12",
139
+ vars: { xyz: 123 },
140
+ }),
141
+ "utf-8"
142
+ );
143
+ writeWorkerSource({ basePath: "./some-path/worker" });
144
+ mockUploadWorkerRequest({
145
+ expectedBindings: [
146
+ {
147
+ json: 123,
148
+ name: "xyz",
149
+ type: "json",
150
+ },
151
+ ],
152
+ expectedCompatibilityDate: "2022-01-12",
153
+ });
154
+ mockSubDomainRequest();
155
+ await runWrangler("publish ./some-path/worker/index.js");
156
+ expect(std.out).toMatchInlineSnapshot(`
157
+ "Uploaded test-name (TIMINGS)
158
+ Published test-name (TIMINGS)
159
+ test-name.test-sub-domain.workers.dev"
160
+ `);
161
+ expect(std.err).toMatchInlineSnapshot(`""`);
162
+ });
163
+
164
+ describe("routes", () => {
165
+ it("should publish the worker to a route", async () => {
166
+ writeWranglerToml({
167
+ routes: ["example.com/some-route/*"],
168
+ });
169
+ writeWorkerSource();
170
+ mockUpdateWorkerRequest({ enabled: false });
171
+ mockUploadWorkerRequest({ expectedType: "esm" });
172
+ mockPublishRoutesRequest({ routes: ["example.com/some-route/*"] });
173
+ await runWrangler("publish ./index");
174
+ });
175
+
176
+ it("should publish to legacy environment specific routes", async () => {
177
+ writeWranglerToml({
178
+ routes: ["example.com/some-route/*"],
179
+ env: {
180
+ dev: {
181
+ routes: ["dev-example.com/some-route/*"],
182
+ },
183
+ },
184
+ });
185
+ writeWorkerSource();
186
+ mockUpdateWorkerRequest({ enabled: false, legacyEnv: true, env: "dev" });
187
+ mockUploadWorkerRequest({
188
+ expectedType: "esm",
189
+ legacyEnv: true,
190
+ env: "dev",
191
+ });
192
+ mockPublishRoutesRequest({
193
+ routes: ["dev-example.com/some-route/*"],
194
+ legacyEnv: true,
195
+ env: "dev",
196
+ });
197
+ await runWrangler("publish ./index --env dev --legacy-env true");
198
+ });
199
+
200
+ it("services: should publish to service environment specific routes", async () => {
201
+ writeWranglerToml({
202
+ routes: ["example.com/some-route/*"],
203
+ env: {
204
+ dev: {
205
+ routes: ["dev-example.com/some-route/*"],
206
+ },
207
+ },
208
+ });
209
+ writeWorkerSource();
210
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
211
+ mockUploadWorkerRequest({
212
+ expectedType: "esm",
213
+ env: "dev",
214
+ });
215
+ mockPublishRoutesRequest({
216
+ routes: ["dev-example.com/some-route/*"],
217
+ env: "dev",
218
+ });
219
+ await runWrangler("publish ./index --env dev --legacy-env false");
220
+ });
221
+
222
+ it.todo("should error if it's a workers.dev route");
23
223
  });
24
224
 
25
225
  describe("entry-points", () => {
@@ -32,17 +232,13 @@ describe("publish", () => {
32
232
  await runWrangler("publish ./index");
33
233
 
34
234
  expect(std.out).toMatchInlineSnapshot(`
35
- "Uploaded
36
- test-name
37
- (TIMINGS)
38
- Deployed
39
- test-name
40
- (TIMINGS)
41
-
42
- test-name.test-sub-domain.workers.dev"
43
- `);
235
+ "Uploaded test-name (TIMINGS)
236
+ Published test-name (TIMINGS)
237
+ test-name.test-sub-domain.workers.dev"
238
+ `);
44
239
  expect(std.err).toMatchInlineSnapshot(`""`);
45
240
  });
241
+
46
242
  it("should be able to use `index` with no extension as the entry-point (sw)", async () => {
47
243
  writeWranglerToml();
48
244
  writeWorkerSource({ type: "sw" });
@@ -52,20 +248,15 @@ describe("publish", () => {
52
248
  await runWrangler("publish ./index");
53
249
 
54
250
  expect(std.out).toMatchInlineSnapshot(`
55
- "Uploaded
56
- test-name
57
- (TIMINGS)
58
- Deployed
59
- test-name
60
- (TIMINGS)
61
-
62
- test-name.test-sub-domain.workers.dev"
63
- `);
251
+ "Uploaded test-name (TIMINGS)
252
+ Published test-name (TIMINGS)
253
+ test-name.test-sub-domain.workers.dev"
254
+ `);
64
255
  expect(std.err).toMatchInlineSnapshot(`""`);
65
256
  });
66
257
 
67
- it("should be able to use the `build.upload.main` config as the entry-point for ESM sources", async () => {
68
- writeWranglerToml({ build: { upload: { main: "./index.js" } } });
258
+ it("should be able to use the `main` config as the entry-point for ESM sources", async () => {
259
+ writeWranglerToml({ main: "./index.js" });
69
260
  writeWorkerSource();
70
261
  mockUploadWorkerRequest();
71
262
  mockSubDomainRequest();
@@ -73,16 +264,107 @@ describe("publish", () => {
73
264
  await runWrangler("publish");
74
265
 
75
266
  expect(std.out).toMatchInlineSnapshot(`
76
- "Uploaded
77
- test-name
78
- (TIMINGS)
79
- Deployed
80
- test-name
81
- (TIMINGS)
82
-
83
- test-name.test-sub-domain.workers.dev"
84
- `);
267
+ "Uploaded test-name (TIMINGS)
268
+ Published test-name (TIMINGS)
269
+ test-name.test-sub-domain.workers.dev"
270
+ `);
271
+ expect(std.err).toMatchInlineSnapshot(`""`);
272
+ });
273
+
274
+ it("should use `main` relative to the wrangler.toml not cwd", async () => {
275
+ writeWranglerToml({
276
+ main: "./foo/index.js",
277
+ });
278
+ writeWorkerSource({ basePath: "foo" });
279
+ mockUploadWorkerRequest({ expectedEntry: "var foo = 100;" });
280
+ mockSubDomainRequest();
281
+ process.chdir("foo");
282
+ await runWrangler("publish");
283
+
284
+ expect(std.out).toMatchInlineSnapshot(`
285
+ "Uploaded test-name (TIMINGS)
286
+ Published test-name (TIMINGS)
287
+ test-name.test-sub-domain.workers.dev"
288
+ `);
289
+ expect(std.err).toMatchInlineSnapshot(`""`);
290
+ });
291
+
292
+ it('should use `build.upload.main` as an entry point, where `build.upload.dir` defaults to "./dist", and log a deprecation warning', async () => {
293
+ writeWranglerToml({ build: { upload: { main: "./index.js" } } });
294
+ writeWorkerSource({ basePath: "./dist" });
295
+ mockUploadWorkerRequest();
296
+ mockSubDomainRequest();
297
+
298
+ await runWrangler("publish");
299
+
300
+ expect(std.out).toMatchInlineSnapshot(`
301
+ "Uploaded test-name (TIMINGS)
302
+ Published test-name (TIMINGS)
303
+ test-name.test-sub-domain.workers.dev"
304
+ `);
305
+ expect(std.err).toMatchInlineSnapshot(`""`);
306
+ expect(std.warn).toMatchInlineSnapshot(`
307
+ "Processing wrangler.toml configuration:
308
+ - DEPRECATION: \\"build.upload.main\\":
309
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
310
+ Then add the top level \`main\` field to your configuration file:
311
+ \`\`\`
312
+ main = \\"dist/index.js\\"
313
+ \`\`\`"
314
+ `);
315
+ });
316
+
317
+ it("should use `build.upload.main` relative to `build.upload.dir`", async () => {
318
+ writeWranglerToml({
319
+ build: {
320
+ upload: {
321
+ main: "./index.js",
322
+ dir: "./foo",
323
+ },
324
+ },
325
+ });
326
+ writeWorkerSource({ basePath: "./foo" });
327
+ mockUploadWorkerRequest({ expectedEntry: "var foo = 100;" });
328
+ mockSubDomainRequest();
329
+ process.chdir("foo");
330
+ await runWrangler("publish");
331
+
332
+ expect(std.out).toMatchInlineSnapshot(`
333
+ "Uploaded test-name (TIMINGS)
334
+ Published test-name (TIMINGS)
335
+ test-name.test-sub-domain.workers.dev"
336
+ `);
85
337
  expect(std.err).toMatchInlineSnapshot(`""`);
338
+ expect(std.warn).toMatchInlineSnapshot(`
339
+ "Processing ../wrangler.toml configuration:
340
+ - DEPRECATION: \\"build.upload.main\\":
341
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
342
+ Then add the top level \`main\` field to your configuration file:
343
+ \`\`\`
344
+ main = \\"foo/index.js\\"
345
+ \`\`\`
346
+ - DEPRECATION: \\"build.upload.dir\\":
347
+ Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker."
348
+ `);
349
+ });
350
+
351
+ it("should error when both `main` and `build.upload.main` are used", async () => {
352
+ writeWranglerToml({
353
+ main: "./index.js",
354
+ build: {
355
+ upload: {
356
+ main: "./index.js",
357
+ dir: "./foo",
358
+ },
359
+ },
360
+ });
361
+ await expect(runWrangler("publish")).rejects
362
+ .toThrowErrorMatchingInlineSnapshot(`
363
+ "Processing wrangler.toml configuration:
364
+ - Don't define both the \`main\` and \`build.upload.main\` fields in your configuration.
365
+ They serve the same purpose: to point to the entry-point of your worker.
366
+ Delete the \`build.upload.main\` and \`build.upload.dir\` field from your config."
367
+ `);
86
368
  });
87
369
 
88
370
  it("should be able to transpile TypeScript (esm)", async () => {
@@ -93,15 +375,10 @@ describe("publish", () => {
93
375
  await runWrangler("publish index.ts");
94
376
 
95
377
  expect(std.out).toMatchInlineSnapshot(`
96
- "Uploaded
97
- test-name
98
- (TIMINGS)
99
- Deployed
100
- test-name
101
- (TIMINGS)
102
-
103
- test-name.test-sub-domain.workers.dev"
104
- `);
378
+ "Uploaded test-name (TIMINGS)
379
+ Published test-name (TIMINGS)
380
+ test-name.test-sub-domain.workers.dev"
381
+ `);
105
382
  expect(std.err).toMatchInlineSnapshot(`""`);
106
383
  });
107
384
 
@@ -116,19 +393,14 @@ describe("publish", () => {
116
393
  await runWrangler("publish index.ts");
117
394
 
118
395
  expect(std.out).toMatchInlineSnapshot(`
119
- "Uploaded
120
- test-name
121
- (TIMINGS)
122
- Deployed
123
- test-name
124
- (TIMINGS)
125
-
126
- test-name.test-sub-domain.workers.dev"
127
- `);
396
+ "Uploaded test-name (TIMINGS)
397
+ Published test-name (TIMINGS)
398
+ test-name.test-sub-domain.workers.dev"
399
+ `);
128
400
  expect(std.err).toMatchInlineSnapshot(`""`);
129
401
  });
130
402
 
131
- it("should inline referenced text modules into the worker", async () => {
403
+ it("should add referenced text modules into the form upload", async () => {
132
404
  writeWranglerToml();
133
405
  fs.writeFileSync(
134
406
  "./index.js",
@@ -142,18 +414,18 @@ export default{
142
414
  `
143
415
  );
144
416
  fs.writeFileSync("./textfile.txt", "Hello, World!");
145
- mockUploadWorkerRequest({ expectedEntry: "Hello, World!" });
417
+ mockUploadWorkerRequest({
418
+ expectedModules: {
419
+ "./0a0a9f2a6772942557ab5355d76af442f8f65e01-textfile.txt":
420
+ "Hello, World!",
421
+ },
422
+ });
146
423
  mockSubDomainRequest();
147
424
  await runWrangler("publish index.js");
148
425
  expect(std.out).toMatchInlineSnapshot(`
149
- "Uploaded
150
- test-name
151
- (TIMINGS)
152
- Deployed
153
- test-name
154
- (TIMINGS)
155
-
156
- test-name.test-sub-domain.workers.dev"
426
+ "Uploaded test-name (TIMINGS)
427
+ Published test-name (TIMINGS)
428
+ test-name.test-sub-domain.workers.dev"
157
429
  `);
158
430
  expect(std.err).toMatchInlineSnapshot(`""`);
159
431
  });
@@ -167,15 +439,10 @@ export default{
167
439
  await runWrangler("publish ./src/index.js");
168
440
 
169
441
  expect(std.out).toMatchInlineSnapshot(`
170
- "Uploaded
171
- test-name
172
- (TIMINGS)
173
- Deployed
174
- test-name
175
- (TIMINGS)
176
-
177
- test-name.test-sub-domain.workers.dev"
178
- `);
442
+ "Uploaded test-name (TIMINGS)
443
+ Published test-name (TIMINGS)
444
+ test-name.test-sub-domain.workers.dev"
445
+ `);
179
446
  expect(std.err).toMatchInlineSnapshot(`""`);
180
447
  });
181
448
 
@@ -191,50 +458,39 @@ export default{
191
458
  await runWrangler("publish ./src/index.js");
192
459
 
193
460
  expect(std.out).toMatchInlineSnapshot(`
194
- "Uploaded
195
- test-name
196
- (TIMINGS)
197
- Deployed
198
- test-name
199
- (TIMINGS)
200
-
201
- test-name.test-sub-domain.workers.dev"
202
- `);
461
+ "Uploaded test-name (TIMINGS)
462
+ Published test-name (TIMINGS)
463
+ test-name.test-sub-domain.workers.dev"
464
+ `);
203
465
  expect(std.err).toMatchInlineSnapshot(`""`);
204
466
  });
205
467
 
206
468
  it('should error if a site definition doesn\'t have a "bucket" field', async () => {
207
469
  writeWranglerToml({
208
- // @ts-expect-error we're purposely missing the required `site.bucket` field
209
- site: {
210
- "entry-point": "./index.js",
211
- },
470
+ // @ts-expect-error we're intentionally setting an invalid config
471
+ site: {},
212
472
  });
213
473
  writeWorkerSource();
214
474
  mockUploadWorkerRequest();
215
475
  mockSubDomainRequest();
216
476
 
217
- await expect(
218
- runWrangler("publish ./index.js")
219
- ).rejects.toThrowErrorMatchingInlineSnapshot(
220
- `"A [site] definition requires a \`bucket\` field with a path to the site's public directory."`
221
- );
477
+ await expect(runWrangler("publish ./index.js")).rejects
478
+ .toThrowErrorMatchingInlineSnapshot(`
479
+ "Processing wrangler.toml configuration:
480
+ - \\"site.bucket\\" is a required field."
481
+ `);
222
482
 
223
483
  expect(std.out).toMatchInlineSnapshot(`""`);
224
484
  expect(std.err).toMatchInlineSnapshot(`
225
- "A [site] definition requires a \`bucket\` field with a path to the site's public directory.
485
+ "Processing wrangler.toml configuration:
486
+ - \\"site.bucket\\" is a required field.
226
487
 
227
- %s
228
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
229
- `);
230
- expect(std.warn).toMatchInlineSnapshot(`
231
- "Deprecation notice: The \`site.entry-point\` config field is no longer used.
232
- The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`build.upload.main\` config field.
233
- Please remove the \`site.entry-point\` field from the \`wrangler.toml\` file."
488
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
234
489
  `);
490
+ expect(std.warn).toMatchInlineSnapshot(`""`);
235
491
  });
236
492
 
237
- it("should warn if there is a `site.entry-point` configuration", async () => {
493
+ it("should error if there is a `site.entry-point` configuration", async () => {
238
494
  const assets = [
239
495
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
240
496
  { filePath: "assets/file-2.txt", content: "Content of file-2" },
@@ -258,27 +514,26 @@ export default{
258
514
  mockKeyListRequest(kvNamespace.id, []);
259
515
  mockUploadAssetsToKVRequest(kvNamespace.id, assets);
260
516
 
261
- await runWrangler("publish ./index.js");
517
+ await expect(runWrangler("publish ./index.js")).rejects
518
+ .toThrowErrorMatchingInlineSnapshot(`
519
+ "Processing wrangler.toml configuration:
520
+ - DEPRECATION: \\"site.entry-point\\":
521
+ The \`site.entry-point\` config field is no longer used.
522
+ The entry-point should be specified via the command line or the \`main\` config field."
523
+ `);
262
524
 
263
- expect(std.out).toMatchInlineSnapshot(`
264
- "reading assets/file-1.txt...
265
- uploading as assets/file-1.2ca234f380.txt...
266
- reading assets/file-2.txt...
267
- uploading as assets/file-2.5938485188.txt...
268
- Uploaded
269
- test-name
270
- (TIMINGS)
271
- Deployed
272
- test-name
273
- (TIMINGS)
274
-
275
- test-name.test-sub-domain.workers.dev"
525
+ expect(std.out).toMatchInlineSnapshot(`""`);
526
+ expect(std.err).toMatchInlineSnapshot(`
527
+ "Processing wrangler.toml configuration:
528
+ - DEPRECATION: \\"site.entry-point\\":
529
+ The \`site.entry-point\` config field is no longer used.
530
+ The entry-point should be specified via the command line or the \`main\` config field.
531
+
532
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
276
533
  `);
277
- expect(std.err).toMatchInlineSnapshot(`""`);
278
534
  expect(std.warn).toMatchInlineSnapshot(`
279
- "Deprecation notice: The \`site.entry-point\` config field is no longer used.
280
- The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`build.upload.main\` config field.
281
- Please remove the \`site.entry-point\` field from the \`wrangler.toml\` file."
535
+ "Processing wrangler.toml configuration:
536
+ - Unexpected fields found in site field: \\"entry-point\\""
282
537
  `);
283
538
  });
284
539
 
@@ -290,15 +545,14 @@ export default{
290
545
  await expect(
291
546
  runWrangler("publish")
292
547
  ).rejects.toThrowErrorMatchingInlineSnapshot(
293
- `"Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`build.upload.main\` config field."`
548
+ `"Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`main\` config field."`
294
549
  );
295
550
 
296
551
  expect(std.out).toMatchInlineSnapshot(`""`);
297
552
  expect(std.err).toMatchInlineSnapshot(`
298
- "Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`build.upload.main\` config field.
553
+ "Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`main\` config field.
299
554
 
300
- %s
301
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
555
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
302
556
  `);
303
557
  });
304
558
  });
@@ -314,7 +568,7 @@ export default{
314
568
  id: "__test-name-workers_sites_assets-id",
315
569
  };
316
570
  writeWranglerToml({
317
- build: { upload: { main: "./index.js" } },
571
+ main: "./index.js",
318
572
  site: {
319
573
  bucket: "assets",
320
574
  },
@@ -333,19 +587,15 @@ export default{
333
587
  uploading as assets/file-1.2ca234f380.txt...
334
588
  reading assets/file-2.txt...
335
589
  uploading as assets/file-2.5938485188.txt...
336
- Uploaded
337
- test-name
338
- (TIMINGS)
339
- Deployed
340
- test-name
341
- (TIMINGS)
342
-
343
- test-name.test-sub-domain.workers.dev"
590
+ ↗️ Done syncing assets
591
+ Uploaded test-name (TIMINGS)
592
+ Published test-name (TIMINGS)
593
+ test-name.test-sub-domain.workers.dev"
344
594
  `);
345
595
  expect(std.err).toMatchInlineSnapshot(`""`);
346
596
  });
347
597
 
348
- it("when using a service worker type, it should inline an asset manifest, and bind to a namespace", async () => {
598
+ it("when using a service worker type, it should add an asset manifest as a text_blob, and bind to a namespace", async () => {
349
599
  const assets = [
350
600
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
351
601
  { filePath: "assets/file-2.txt", content: "Content of file-2" },
@@ -355,7 +605,7 @@ export default{
355
605
  id: "__test-name-workers_sites_assets-id",
356
606
  };
357
607
  writeWranglerToml({
358
- build: { upload: { main: "./index.js" } },
608
+ main: "./index.js",
359
609
  site: {
360
610
  bucket: "assets",
361
611
  },
@@ -364,13 +614,21 @@ export default{
364
614
  writeAssets(assets);
365
615
  mockUploadWorkerRequest({
366
616
  expectedType: "sw",
367
- expectedEntry: `const __STATIC_CONTENT_MANIFEST = {"file-1.txt":"assets/file-1.2ca234f380.txt","file-2.txt":"assets/file-2.5938485188.txt"};`,
617
+ expectedModules: {
618
+ __STATIC_CONTENT_MANIFEST:
619
+ '{"file-1.txt":"assets/file-1.2ca234f380.txt","file-2.txt":"assets/file-2.5938485188.txt"}',
620
+ },
368
621
  expectedBindings: [
369
622
  {
370
623
  name: "__STATIC_CONTENT",
371
624
  namespace_id: "__test-name-workers_sites_assets-id",
372
625
  type: "kv_namespace",
373
626
  },
627
+ {
628
+ name: "__STATIC_CONTENT_MANIFEST",
629
+ part: "__STATIC_CONTENT_MANIFEST",
630
+ type: "text_blob",
631
+ },
374
632
  ],
375
633
  });
376
634
  mockSubDomainRequest();
@@ -385,14 +643,10 @@ export default{
385
643
  uploading as assets/file-1.2ca234f380.txt...
386
644
  reading assets/file-2.txt...
387
645
  uploading as assets/file-2.5938485188.txt...
388
- Uploaded
389
- test-name
390
- (TIMINGS)
391
- Deployed
392
- test-name
393
- (TIMINGS)
394
-
395
- test-name.test-sub-domain.workers.dev"
646
+ ↗️ Done syncing assets
647
+ Uploaded test-name (TIMINGS)
648
+ Published test-name (TIMINGS)
649
+ test-name.test-sub-domain.workers.dev"
396
650
  `);
397
651
  expect(std.err).toMatchInlineSnapshot(`""`);
398
652
  });
@@ -407,7 +661,7 @@ export default{
407
661
  id: "__test-name-workers_sites_assets-id",
408
662
  };
409
663
  writeWranglerToml({
410
- build: { upload: { main: "./index.js" } },
664
+ main: "./index.js",
411
665
  site: {
412
666
  bucket: "assets",
413
667
  },
@@ -439,19 +693,15 @@ export default{
439
693
  uploading as assets/file-1.2ca234f380.txt...
440
694
  reading assets/file-2.txt...
441
695
  uploading as assets/file-2.5938485188.txt...
442
- Uploaded
443
- test-name
444
- (TIMINGS)
445
- Deployed
446
- test-name
447
- (TIMINGS)
448
-
449
- test-name.test-sub-domain.workers.dev"
696
+ ↗️ Done syncing assets
697
+ Uploaded test-name (TIMINGS)
698
+ Published test-name (TIMINGS)
699
+ test-name.test-sub-domain.workers.dev"
450
700
  `);
451
701
  expect(std.err).toMatchInlineSnapshot(`""`);
452
702
  });
453
703
 
454
- it("should make environment specific kv namespace for assets", async () => {
704
+ it("should make environment specific kv namespace for assets, even for service envs", async () => {
455
705
  // This is the same test as the one before this, but with an env arg
456
706
  const assets = [
457
707
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
@@ -462,14 +712,64 @@ export default{
462
712
  id: "__test-name-some-env-workers_sites_assets-id",
463
713
  };
464
714
  writeWranglerToml({
465
- build: { upload: { main: "./index.js" } },
715
+ main: "./index.js",
716
+ site: {
717
+ bucket: "assets",
718
+ },
719
+ env: { "some-env": {} },
720
+ });
721
+ writeWorkerSource();
722
+ writeAssets(assets);
723
+ mockUploadWorkerRequest({
724
+ env: "some-env",
725
+ expectedBindings: [
726
+ {
727
+ name: "__STATIC_CONTENT",
728
+ namespace_id: "__test-name-some-env-workers_sites_assets-id",
729
+ type: "kv_namespace",
730
+ },
731
+ ],
732
+ });
733
+ mockSubDomainRequest();
734
+ mockListKVNamespacesRequest(kvNamespace);
735
+ mockKeyListRequest(kvNamespace.id, []);
736
+ mockUploadAssetsToKVRequest(kvNamespace.id, assets);
737
+ await runWrangler("publish --env some-env --legacy-env false");
738
+
739
+ expect(std.out).toMatchInlineSnapshot(`
740
+ "reading assets/file-1.txt...
741
+ uploading as assets/file-1.2ca234f380.txt...
742
+ reading assets/file-2.txt...
743
+ uploading as assets/file-2.5938485188.txt...
744
+ ↗️ Done syncing assets
745
+ Uploaded test-name (some-env) (TIMINGS)
746
+ Published test-name (some-env) (TIMINGS)
747
+ some-env.test-name.test-sub-domain.workers.dev"
748
+ `);
749
+ expect(std.err).toMatchInlineSnapshot(`""`);
750
+ });
751
+
752
+ it("should make environment specific kv namespace for assets, even for legacy envs", async () => {
753
+ // And this is the same test as the one before this, but with legacyEnv:true
754
+ const assets = [
755
+ { filePath: "assets/file-1.txt", content: "Content of file-1" },
756
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
757
+ ];
758
+ const kvNamespace = {
759
+ title: "__test-name-some-env-workers_sites_assets",
760
+ id: "__test-name-some-env-workers_sites_assets-id",
761
+ };
762
+ writeWranglerToml({
763
+ main: "./index.js",
466
764
  site: {
467
765
  bucket: "assets",
468
766
  },
767
+ env: { "some-env": {} },
469
768
  });
470
769
  writeWorkerSource();
471
770
  writeAssets(assets);
472
771
  mockUploadWorkerRequest({
772
+ legacyEnv: true,
473
773
  env: "some-env",
474
774
  expectedBindings: [
475
775
  {
@@ -483,21 +783,17 @@ export default{
483
783
  mockListKVNamespacesRequest(kvNamespace);
484
784
  mockKeyListRequest(kvNamespace.id, []);
485
785
  mockUploadAssetsToKVRequest(kvNamespace.id, assets);
486
- await runWrangler("publish --env some-env");
786
+ await runWrangler("publish --env some-env --legacy-env true");
487
787
 
488
788
  expect(std.out).toMatchInlineSnapshot(`
489
789
  "reading assets/file-1.txt...
490
790
  uploading as assets/file-1.2ca234f380.txt...
491
791
  reading assets/file-2.txt...
492
792
  uploading as assets/file-2.5938485188.txt...
493
- Uploaded
494
- test-name (some-env)
495
- (TIMINGS)
496
- Deployed
497
- test-name (some-env)
498
- (TIMINGS)
499
-
500
- some-env.test-name.test-sub-domain.workers.dev"
793
+ ↗️ Done syncing assets
794
+ Uploaded test-name-some-env (TIMINGS)
795
+ Published test-name-some-env (TIMINGS)
796
+ test-name-some-env.test-sub-domain.workers.dev"
501
797
  `);
502
798
  expect(std.err).toMatchInlineSnapshot(`""`);
503
799
  });
@@ -512,7 +808,7 @@ export default{
512
808
  id: "__test-name-workers_sites_assets-id",
513
809
  };
514
810
  writeWranglerToml({
515
- build: { upload: { main: "./index.js" } },
811
+ main: "./index.js",
516
812
  site: {
517
813
  bucket: "assets",
518
814
  },
@@ -523,7 +819,9 @@ export default{
523
819
  mockSubDomainRequest();
524
820
  mockListKVNamespacesRequest(kvNamespace);
525
821
  // Put file-1 in the KV namespace
526
- mockKeyListRequest(kvNamespace.id, ["assets/file-1.2ca234f380.txt"]);
822
+ mockKeyListRequest(kvNamespace.id, [
823
+ { name: "assets/file-1.2ca234f380.txt" },
824
+ ]);
527
825
  // Check we do not upload file-1
528
826
  mockUploadAssetsToKVRequest(
529
827
  kvNamespace.id,
@@ -536,14 +834,10 @@ export default{
536
834
  skipping - already uploaded
537
835
  reading assets/file-2.txt...
538
836
  uploading as assets/file-2.5938485188.txt...
539
- Uploaded
540
- test-name
541
- (TIMINGS)
542
- Deployed
543
- test-name
544
- (TIMINGS)
545
-
546
- test-name.test-sub-domain.workers.dev"
837
+ ↗️ Done syncing assets
838
+ Uploaded test-name (TIMINGS)
839
+ Published test-name (TIMINGS)
840
+ test-name.test-sub-domain.workers.dev"
547
841
  `);
548
842
  expect(std.err).toMatchInlineSnapshot(`""`);
549
843
  });
@@ -558,7 +852,7 @@ export default{
558
852
  id: "__test-name-workers_sites_assets-id",
559
853
  };
560
854
  writeWranglerToml({
561
- build: { upload: { main: "./index.js" } },
855
+ main: "./index.js",
562
856
  site: {
563
857
  bucket: "assets",
564
858
  },
@@ -577,17 +871,13 @@ export default{
577
871
  await runWrangler("publish --site-include file-1.txt");
578
872
 
579
873
  expect(std.out).toMatchInlineSnapshot(`
580
- "reading assets/file-1.txt...
581
- uploading as assets/file-1.2ca234f380.txt...
582
- Uploaded
583
- test-name
584
- (TIMINGS)
585
- Deployed
586
- test-name
587
- (TIMINGS)
588
-
589
- test-name.test-sub-domain.workers.dev"
590
- `);
874
+ "reading assets/file-1.txt...
875
+ uploading as assets/file-1.2ca234f380.txt...
876
+ ↗️ Done syncing assets
877
+ Uploaded test-name (TIMINGS)
878
+ Published test-name (TIMINGS)
879
+ test-name.test-sub-domain.workers.dev"
880
+ `);
591
881
  expect(std.err).toMatchInlineSnapshot(`""`);
592
882
  });
593
883
 
@@ -601,7 +891,7 @@ export default{
601
891
  id: "__test-name-workers_sites_assets-id",
602
892
  };
603
893
  writeWranglerToml({
604
- build: { upload: { main: "./index.js" } },
894
+ main: "./index.js",
605
895
  site: {
606
896
  bucket: "assets",
607
897
  },
@@ -620,17 +910,13 @@ export default{
620
910
  await runWrangler("publish --site-exclude file-2.txt");
621
911
 
622
912
  expect(std.out).toMatchInlineSnapshot(`
623
- "reading assets/file-1.txt...
624
- uploading as assets/file-1.2ca234f380.txt...
625
- Uploaded
626
- test-name
627
- (TIMINGS)
628
- Deployed
629
- test-name
630
- (TIMINGS)
631
-
632
- test-name.test-sub-domain.workers.dev"
633
- `);
913
+ "reading assets/file-1.txt...
914
+ uploading as assets/file-1.2ca234f380.txt...
915
+ ↗️ Done syncing assets
916
+ Uploaded test-name (TIMINGS)
917
+ Published test-name (TIMINGS)
918
+ test-name.test-sub-domain.workers.dev"
919
+ `);
634
920
  expect(std.err).toMatchInlineSnapshot(`""`);
635
921
  });
636
922
 
@@ -644,7 +930,7 @@ export default{
644
930
  id: "__test-name-workers_sites_assets-id",
645
931
  };
646
932
  writeWranglerToml({
647
- build: { upload: { main: "./index.js" } },
933
+ main: "./index.js",
648
934
  site: {
649
935
  bucket: "assets",
650
936
  include: ["file-1.txt"],
@@ -664,17 +950,13 @@ export default{
664
950
  await runWrangler("publish");
665
951
 
666
952
  expect(std.out).toMatchInlineSnapshot(`
667
- "reading assets/file-1.txt...
668
- uploading as assets/file-1.2ca234f380.txt...
669
- Uploaded
670
- test-name
671
- (TIMINGS)
672
- Deployed
673
- test-name
674
- (TIMINGS)
675
-
676
- test-name.test-sub-domain.workers.dev"
677
- `);
953
+ "reading assets/file-1.txt...
954
+ uploading as assets/file-1.2ca234f380.txt...
955
+ ↗️ Done syncing assets
956
+ Uploaded test-name (TIMINGS)
957
+ Published test-name (TIMINGS)
958
+ test-name.test-sub-domain.workers.dev"
959
+ `);
678
960
  expect(std.err).toMatchInlineSnapshot(`""`);
679
961
  });
680
962
 
@@ -688,7 +970,7 @@ export default{
688
970
  id: "__test-name-workers_sites_assets-id",
689
971
  };
690
972
  writeWranglerToml({
691
- build: { upload: { main: "./index.js" } },
973
+ main: "./index.js",
692
974
  site: {
693
975
  bucket: "assets",
694
976
  exclude: ["file-2.txt"],
@@ -708,17 +990,13 @@ export default{
708
990
  await runWrangler("publish");
709
991
 
710
992
  expect(std.out).toMatchInlineSnapshot(`
711
- "reading assets/file-1.txt...
712
- uploading as assets/file-1.2ca234f380.txt...
713
- Uploaded
714
- test-name
715
- (TIMINGS)
716
- Deployed
717
- test-name
718
- (TIMINGS)
719
-
720
- test-name.test-sub-domain.workers.dev"
721
- `);
993
+ "reading assets/file-1.txt...
994
+ uploading as assets/file-1.2ca234f380.txt...
995
+ ↗️ Done syncing assets
996
+ Uploaded test-name (TIMINGS)
997
+ Published test-name (TIMINGS)
998
+ test-name.test-sub-domain.workers.dev"
999
+ `);
722
1000
  expect(std.err).toMatchInlineSnapshot(`""`);
723
1001
  });
724
1002
 
@@ -732,7 +1010,7 @@ export default{
732
1010
  id: "__test-name-workers_sites_assets-id",
733
1011
  };
734
1012
  writeWranglerToml({
735
- build: { upload: { main: "./index.js" } },
1013
+ main: "./index.js",
736
1014
  site: {
737
1015
  bucket: "assets",
738
1016
  include: ["file-2.txt"],
@@ -752,17 +1030,13 @@ export default{
752
1030
  await runWrangler("publish --site-include file-1.txt");
753
1031
 
754
1032
  expect(std.out).toMatchInlineSnapshot(`
755
- "reading assets/file-1.txt...
756
- uploading as assets/file-1.2ca234f380.txt...
757
- Uploaded
758
- test-name
759
- (TIMINGS)
760
- Deployed
761
- test-name
762
- (TIMINGS)
763
-
764
- test-name.test-sub-domain.workers.dev"
765
- `);
1033
+ "reading assets/file-1.txt...
1034
+ uploading as assets/file-1.2ca234f380.txt...
1035
+ ↗️ Done syncing assets
1036
+ Uploaded test-name (TIMINGS)
1037
+ Published test-name (TIMINGS)
1038
+ test-name.test-sub-domain.workers.dev"
1039
+ `);
766
1040
  expect(std.err).toMatchInlineSnapshot(`""`);
767
1041
  });
768
1042
 
@@ -776,7 +1050,7 @@ export default{
776
1050
  id: "__test-name-workers_sites_assets-id",
777
1051
  };
778
1052
  writeWranglerToml({
779
- build: { upload: { main: "./index.js" } },
1053
+ main: "./index.js",
780
1054
  site: {
781
1055
  bucket: "assets",
782
1056
  exclude: ["assets/file-1.txt"],
@@ -796,17 +1070,13 @@ export default{
796
1070
  await runWrangler("publish --site-exclude file-2.txt");
797
1071
 
798
1072
  expect(std.out).toMatchInlineSnapshot(`
799
- "reading assets/file-1.txt...
800
- uploading as assets/file-1.2ca234f380.txt...
801
- Uploaded
802
- test-name
803
- (TIMINGS)
804
- Deployed
805
- test-name
806
- (TIMINGS)
807
-
808
- test-name.test-sub-domain.workers.dev"
809
- `);
1073
+ "reading assets/file-1.txt...
1074
+ uploading as assets/file-1.2ca234f380.txt...
1075
+ ↗️ Done syncing assets
1076
+ Uploaded test-name (TIMINGS)
1077
+ Published test-name (TIMINGS)
1078
+ test-name.test-sub-domain.workers.dev"
1079
+ `);
810
1080
  expect(std.err).toMatchInlineSnapshot(`""`);
811
1081
  });
812
1082
 
@@ -826,7 +1096,7 @@ export default{
826
1096
  id: "__test-name-workers_sites_assets-id",
827
1097
  };
828
1098
  writeWranglerToml({
829
- build: { upload: { main: "./index.js" } },
1099
+ main: "./index.js",
830
1100
  site: {
831
1101
  bucket: "assets",
832
1102
  },
@@ -844,236 +1114,1331 @@ export default{
844
1114
  expect(std.out).toMatchInlineSnapshot(`
845
1115
  "reading assets/directory-1/file-1.txt...
846
1116
  uploading as assets/directory-1/file-1.2ca234f380.txt...
847
- Uploaded
848
- test-name
849
- (TIMINGS)
850
- Deployed
851
- test-name
852
- (TIMINGS)
853
-
854
- test-name.test-sub-domain.workers.dev"
1117
+ ↗️ Done syncing assets
1118
+ Uploaded test-name (TIMINGS)
1119
+ Published test-name (TIMINGS)
1120
+ test-name.test-sub-domain.workers.dev"
1121
+ `);
1122
+ expect(std.err).toMatchInlineSnapshot(`""`);
1123
+ });
1124
+
1125
+ it("should skip hidden files and directories except `.well-known`", async () => {
1126
+ const assets = [
1127
+ {
1128
+ filePath: "assets/.hidden-file.txt",
1129
+ content: "Content of hidden-file",
1130
+ },
1131
+ {
1132
+ filePath: "assets/.hidden/file-1.txt",
1133
+ content: "Content of file-1",
1134
+ },
1135
+ {
1136
+ filePath: "assets/.well-known/file-2.txt",
1137
+ content: "Content of file-2",
1138
+ },
1139
+ ];
1140
+ const kvNamespace = {
1141
+ title: "__test-name-workers_sites_assets",
1142
+ id: "__test-name-workers_sites_assets-id",
1143
+ };
1144
+ writeWranglerToml({
1145
+ main: "./index.js",
1146
+ site: {
1147
+ bucket: "assets",
1148
+ },
1149
+ });
1150
+ writeWorkerSource();
1151
+ writeAssets(assets);
1152
+ mockUploadWorkerRequest();
1153
+ mockSubDomainRequest();
1154
+ mockListKVNamespacesRequest(kvNamespace);
1155
+ mockKeyListRequest(kvNamespace.id, []);
1156
+ // Only expect file-2 to be uploaded
1157
+ mockUploadAssetsToKVRequest(kvNamespace.id, assets.slice(2));
1158
+ await runWrangler("publish");
1159
+
1160
+ expect(std.out).toMatchInlineSnapshot(`
1161
+ "reading assets/.well-known/file-2.txt...
1162
+ uploading as assets/.well-known/file-2.5938485188.txt...
1163
+ ↗️ Done syncing assets
1164
+ Uploaded test-name (TIMINGS)
1165
+ Published test-name (TIMINGS)
1166
+ test-name.test-sub-domain.workers.dev"
1167
+ `);
1168
+ expect(std.err).toMatchInlineSnapshot(`""`);
1169
+ });
1170
+
1171
+ it("should error if the asset is over 25Mb", async () => {
1172
+ const assets = [
1173
+ {
1174
+ filePath: "assets/large-file.txt",
1175
+ // This file is greater than 25MiB when base64 encoded but small enough to be uploaded.
1176
+ content: "X".repeat(25 * 1024 * 1024 * 0.8 + 1),
1177
+ },
1178
+ {
1179
+ filePath: "assets/too-large-file.txt",
1180
+ content: "X".repeat(25 * 1024 * 1024 + 1),
1181
+ },
1182
+ ];
1183
+ const kvNamespace = {
1184
+ title: "__test-name-workers_sites_assets",
1185
+ id: "__test-name-workers_sites_assets-id",
1186
+ };
1187
+ writeWranglerToml({
1188
+ main: "./index.js",
1189
+ site: {
1190
+ bucket: "assets",
1191
+ exclude: ["assets/file-1.txt"],
1192
+ },
1193
+ });
1194
+ writeWorkerSource();
1195
+ writeAssets(assets);
1196
+ mockUploadWorkerRequest();
1197
+ mockSubDomainRequest();
1198
+ mockListKVNamespacesRequest(kvNamespace);
1199
+ mockKeyListRequest(kvNamespace.id, []);
1200
+
1201
+ await expect(
1202
+ runWrangler("publish")
1203
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1204
+ `"File assets/too-large-file.txt is too big, it should be under 25 MiB. See https://developers.cloudflare.com/workers/platform/limits#kv-limits"`
1205
+ );
1206
+
1207
+ expect(std.out).toMatchInlineSnapshot(`
1208
+ "reading assets/large-file.txt...
1209
+ uploading as assets/large-file.0ea0637a45.txt..."
1210
+ `);
1211
+ expect(std.err).toMatchInlineSnapshot(`
1212
+ "File assets/too-large-file.txt is too big, it should be under 25 MiB. See https://developers.cloudflare.com/workers/platform/limits#kv-limits
1213
+
1214
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1215
+ `);
1216
+ });
1217
+
1218
+ it("should error if the asset key is over 512 characters", async () => {
1219
+ const longFilePathAsset = {
1220
+ filePath: "assets/" + "folder/".repeat(100) + "file.txt",
1221
+ content: "content of file",
1222
+ };
1223
+ const kvNamespace = {
1224
+ title: "__test-name-workers_sites_assets",
1225
+ id: "__test-name-workers_sites_assets-id",
1226
+ };
1227
+ writeWranglerToml({
1228
+ main: "./index.js",
1229
+ site: {
1230
+ bucket: "assets",
1231
+ },
1232
+ });
1233
+ writeWorkerSource();
1234
+ writeAssets([longFilePathAsset]);
1235
+ mockUploadWorkerRequest();
1236
+ mockSubDomainRequest();
1237
+ mockListKVNamespacesRequest(kvNamespace);
1238
+ mockKeyListRequest(kvNamespace.id, []);
1239
+
1240
+ await expect(
1241
+ runWrangler("publish")
1242
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1243
+ `"The asset path key \\"assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.3da0d0cd12.txt\\" exceeds the maximum key size limit of 512. See https://developers.cloudflare.com/workers/platform/limits#kv-limits\\","`
1244
+ );
1245
+
1246
+ expect(std.out).toMatchInlineSnapshot(
1247
+ `"reading assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.txt..."`
1248
+ );
1249
+ expect(std.err).toMatchInlineSnapshot(`
1250
+ "The asset path key \\"assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.3da0d0cd12.txt\\" exceeds the maximum key size limit of 512. See https://developers.cloudflare.com/workers/platform/limits#kv-limits\\",
1251
+
1252
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1253
+ `);
1254
+ });
1255
+
1256
+ it("should delete uploaded assets that aren't included anymore", async () => {
1257
+ const assets = [
1258
+ { filePath: "assets/file-1.txt", content: "Content of file-1" },
1259
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
1260
+ ];
1261
+ const kvNamespace = {
1262
+ title: "__test-name-workers_sites_assets",
1263
+ id: "__test-name-workers_sites_assets-id",
1264
+ };
1265
+ writeWranglerToml({
1266
+ main: "./index.js",
1267
+ site: {
1268
+ bucket: "assets",
1269
+ },
1270
+ });
1271
+ writeWorkerSource();
1272
+ writeAssets(assets);
1273
+ mockUploadWorkerRequest();
1274
+ mockSubDomainRequest();
1275
+ mockListKVNamespacesRequest(kvNamespace);
1276
+ mockKeyListRequest(kvNamespace.id, [
1277
+ // Put file-1 in the KV namespace
1278
+ { name: "assets/file-1.2ca234f380.txt" },
1279
+ // As well as a couple from a previous upload
1280
+ { name: "assets/file-3.somehash.txt" },
1281
+ { name: "assets/file-4.anotherhash.txt" },
1282
+ ]);
1283
+
1284
+ // we upload only file-1.txt
1285
+ mockUploadAssetsToKVRequest(kvNamespace.id, [
1286
+ ...assets.filter((a) => a.filePath !== "assets/file-1.txt"),
1287
+ ]);
1288
+
1289
+ // and mark file-3 and file-4 for deletion
1290
+ mockDeleteUnusedAssetsRequest(kvNamespace.id, [
1291
+ "assets/file-3.somehash.txt",
1292
+ "assets/file-4.anotherhash.txt",
1293
+ ]);
1294
+
1295
+ await runWrangler("publish");
1296
+
1297
+ expect(std.out).toMatchInlineSnapshot(`
1298
+ "reading assets/file-1.txt...
1299
+ skipping - already uploaded
1300
+ reading assets/file-2.txt...
1301
+ uploading as assets/file-2.5938485188.txt...
1302
+ deleting assets/file-3.somehash.txt from the asset store...
1303
+ deleting assets/file-4.anotherhash.txt from the asset store...
1304
+ ↗️ Done syncing assets
1305
+ Uploaded test-name (TIMINGS)
1306
+ Published test-name (TIMINGS)
1307
+ test-name.test-sub-domain.workers.dev"
1308
+ `);
1309
+ expect(std.err).toMatchInlineSnapshot(`""`);
1310
+ });
1311
+ });
1312
+
1313
+ describe("workers_dev setting", () => {
1314
+ it("should publish to a workers.dev domain if workers_dev is undefined", async () => {
1315
+ writeWranglerToml();
1316
+ writeWorkerSource();
1317
+ mockUploadWorkerRequest();
1318
+ mockSubDomainRequest();
1319
+
1320
+ await runWrangler("publish ./index");
1321
+
1322
+ expect(std.out).toMatchInlineSnapshot(`
1323
+ "Uploaded test-name (TIMINGS)
1324
+ Published test-name (TIMINGS)
1325
+ test-name.test-sub-domain.workers.dev"
1326
+ `);
1327
+ expect(std.err).toMatchInlineSnapshot(`""`);
1328
+ });
1329
+
1330
+ it("should publish to the workers.dev domain if workers_dev is `true`", async () => {
1331
+ writeWranglerToml({
1332
+ workers_dev: true,
1333
+ });
1334
+ writeWorkerSource();
1335
+ mockUploadWorkerRequest();
1336
+ mockSubDomainRequest();
1337
+
1338
+ await runWrangler("publish ./index");
1339
+
1340
+ expect(std.out).toMatchInlineSnapshot(`
1341
+ "Uploaded test-name (TIMINGS)
1342
+ Published test-name (TIMINGS)
1343
+ test-name.test-sub-domain.workers.dev"
1344
+ `);
1345
+ expect(std.err).toMatchInlineSnapshot(`""`);
1346
+ });
1347
+
1348
+ it("should disable the workers.dev domain if workers_dev is `false`", async () => {
1349
+ writeWranglerToml({
1350
+ workers_dev: false,
1351
+ });
1352
+ writeWorkerSource();
1353
+ mockUploadWorkerRequest();
1354
+ mockUpdateWorkerRequest({ enabled: false });
1355
+
1356
+ await runWrangler("publish ./index");
1357
+
1358
+ expect(std.out).toMatchInlineSnapshot(`
1359
+ "Uploaded test-name (TIMINGS)
1360
+ No publish targets for test-name (TIMINGS)"
1361
+ `);
1362
+ expect(std.err).toMatchInlineSnapshot(`""`);
1363
+ });
1364
+
1365
+ it("should disable the workers.dev domain if workers_dev is undefined but overwritten to `false` in environment", async () => {
1366
+ writeWranglerToml({
1367
+ env: {
1368
+ dev: {
1369
+ workers_dev: false,
1370
+ },
1371
+ },
1372
+ });
1373
+ writeWorkerSource();
1374
+ mockUploadWorkerRequest({
1375
+ env: "dev",
1376
+ });
1377
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
1378
+
1379
+ await runWrangler("publish ./index --env dev --legacy-env false");
1380
+
1381
+ expect(std.out).toMatchInlineSnapshot(`
1382
+ "Uploaded test-name (dev) (TIMINGS)
1383
+ No publish targets for test-name (dev) (TIMINGS)"
1384
+ `);
1385
+ expect(std.err).toMatchInlineSnapshot(`""`);
1386
+ });
1387
+
1388
+ it("should disable the workers.dev domain if workers_dev is `true` but overwritten to `false` in environment", async () => {
1389
+ writeWranglerToml({
1390
+ workers_dev: true,
1391
+ env: {
1392
+ dev: {
1393
+ workers_dev: false,
1394
+ },
1395
+ },
1396
+ });
1397
+ writeWorkerSource();
1398
+ mockUploadWorkerRequest({
1399
+ env: "dev",
1400
+ });
1401
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
1402
+
1403
+ await runWrangler("publish ./index --env dev --legacy-env false");
1404
+
1405
+ expect(std.out).toMatchInlineSnapshot(`
1406
+ "Uploaded test-name (dev) (TIMINGS)
1407
+ No publish targets for test-name (dev) (TIMINGS)"
1408
+ `);
1409
+ expect(std.err).toMatchInlineSnapshot(`""`);
1410
+ });
1411
+
1412
+ it("should publish to a workers.dev domain if workers_dev is undefined but overwritten to `true` in environment", async () => {
1413
+ writeWranglerToml({
1414
+ env: {
1415
+ dev: {
1416
+ workers_dev: true,
1417
+ },
1418
+ },
1419
+ });
1420
+ writeWorkerSource();
1421
+ mockUploadWorkerRequest({
1422
+ env: "dev",
1423
+ });
1424
+ mockSubDomainRequest();
1425
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1426
+
1427
+ await runWrangler("publish ./index --env dev --legacy-env false");
1428
+
1429
+ expect(std.out).toMatchInlineSnapshot(`
1430
+ "Uploaded test-name (dev) (TIMINGS)
1431
+ Published test-name (dev) (TIMINGS)
1432
+ dev.test-name.test-sub-domain.workers.dev"
1433
+ `);
1434
+ expect(std.err).toMatchInlineSnapshot(`""`);
1435
+ });
1436
+
1437
+ it("should publish to a workers.dev domain if workers_dev is `false` but overwritten to `true` in environment", async () => {
1438
+ writeWranglerToml({
1439
+ workers_dev: false,
1440
+ env: {
1441
+ dev: {
1442
+ workers_dev: true,
1443
+ },
1444
+ },
1445
+ });
1446
+ writeWorkerSource();
1447
+ mockUploadWorkerRequest({
1448
+ env: "dev",
1449
+ });
1450
+ mockSubDomainRequest();
1451
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1452
+
1453
+ await runWrangler("publish ./index --env dev --legacy-env false");
1454
+
1455
+ expect(std.out).toMatchInlineSnapshot(`
1456
+ "Uploaded test-name (dev) (TIMINGS)
1457
+ Published test-name (dev) (TIMINGS)
1458
+ dev.test-name.test-sub-domain.workers.dev"
1459
+ `);
1460
+ expect(std.err).toMatchInlineSnapshot(`""`);
1461
+ });
1462
+
1463
+ it("should use the global compatibility_date and compatibility_flags if they are not overwritten by the environment", async () => {
1464
+ writeWranglerToml({
1465
+ compatibility_date: "2022-01-12",
1466
+ compatibility_flags: ["no_global_navigator"],
1467
+ env: {
1468
+ dev: {},
1469
+ },
1470
+ });
1471
+ writeWorkerSource();
1472
+ mockUploadWorkerRequest({
1473
+ env: "dev",
1474
+ expectedCompatibilityDate: "2022-01-12",
1475
+ expectedCompatibilityFlags: ["no_global_navigator"],
1476
+ });
1477
+ mockSubDomainRequest();
1478
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1479
+
1480
+ await runWrangler("publish ./index --env dev --legacy-env false");
1481
+
1482
+ expect(std.out).toMatchInlineSnapshot(`
1483
+ "Uploaded test-name (dev) (TIMINGS)
1484
+ Published test-name (dev) (TIMINGS)
1485
+ dev.test-name.test-sub-domain.workers.dev"
1486
+ `);
1487
+ expect(std.err).toMatchInlineSnapshot(`""`);
1488
+ });
1489
+
1490
+ it("should use the environment specific compatibility_date and compatibility_flags", async () => {
1491
+ writeWranglerToml({
1492
+ compatibility_date: "2022-01-12",
1493
+ compatibility_flags: ["no_global_navigator"],
1494
+ env: {
1495
+ dev: {
1496
+ compatibility_date: "2022-01-13",
1497
+ compatibility_flags: ["global_navigator"],
1498
+ },
1499
+ },
1500
+ });
1501
+ writeWorkerSource();
1502
+ mockUploadWorkerRequest({
1503
+ env: "dev",
1504
+ expectedCompatibilityDate: "2022-01-13",
1505
+ expectedCompatibilityFlags: ["global_navigator"],
1506
+ });
1507
+ mockSubDomainRequest();
1508
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1509
+
1510
+ await runWrangler("publish ./index --env dev --legacy-env false");
1511
+
1512
+ expect(std.out).toMatchInlineSnapshot(`
1513
+ "Uploaded test-name (dev) (TIMINGS)
1514
+ Published test-name (dev) (TIMINGS)
1515
+ dev.test-name.test-sub-domain.workers.dev"
1516
+ `);
1517
+ expect(std.err).toMatchInlineSnapshot(`""`);
1518
+ });
1519
+
1520
+ it("should use the command line --compatibility-date and --compatibility-flags if they are specified", async () => {
1521
+ writeWranglerToml({
1522
+ compatibility_date: "2022-01-12",
1523
+ compatibility_flags: ["no_global_navigator"],
1524
+ env: {
1525
+ dev: {
1526
+ compatibility_date: "2022-01-13",
1527
+ compatibility_flags: ["global_navigator"],
1528
+ },
1529
+ },
1530
+ });
1531
+ writeWorkerSource();
1532
+ mockUploadWorkerRequest({
1533
+ env: "dev",
1534
+ expectedCompatibilityDate: "2022-01-14",
1535
+ expectedCompatibilityFlags: ["url_standard"],
1536
+ });
1537
+ mockSubDomainRequest();
1538
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1539
+
1540
+ await runWrangler(
1541
+ "publish ./index --env dev --legacy-env false --compatibility-date 2022-01-14 --compatibility-flags url_standard"
1542
+ );
1543
+
1544
+ expect(std.out).toMatchInlineSnapshot(`
1545
+ "Uploaded test-name (dev) (TIMINGS)
1546
+ Published test-name (dev) (TIMINGS)
1547
+ dev.test-name.test-sub-domain.workers.dev"
1548
+ `);
1549
+ expect(std.err).toMatchInlineSnapshot(`""`);
1550
+ });
1551
+
1552
+ it("should enable the workers.dev domain if workers_dev is undefined and subdomain is not already available", async () => {
1553
+ writeWranglerToml();
1554
+ writeWorkerSource();
1555
+ mockUploadWorkerRequest({ available_on_subdomain: false });
1556
+ mockSubDomainRequest();
1557
+ mockUpdateWorkerRequest({ enabled: true });
1558
+
1559
+ await runWrangler("publish ./index");
1560
+
1561
+ expect(std.out).toMatchInlineSnapshot(`
1562
+ "Uploaded test-name (TIMINGS)
1563
+ Published test-name (TIMINGS)
1564
+ test-name.test-sub-domain.workers.dev"
1565
+ `);
1566
+ expect(std.err).toMatchInlineSnapshot(`""`);
1567
+ });
1568
+
1569
+ it("should enable the workers.dev domain if workers_dev is true and subdomain is not already available", async () => {
1570
+ writeWranglerToml({ workers_dev: true });
1571
+ writeWorkerSource();
1572
+ mockUploadWorkerRequest({ available_on_subdomain: false });
1573
+ mockSubDomainRequest();
1574
+ mockUpdateWorkerRequest({ enabled: true });
1575
+
1576
+ await runWrangler("publish ./index");
1577
+
1578
+ expect(std.out).toMatchInlineSnapshot(`
1579
+ "Uploaded test-name (TIMINGS)
1580
+ Published test-name (TIMINGS)
1581
+ test-name.test-sub-domain.workers.dev"
1582
+ `);
1583
+ expect(std.err).toMatchInlineSnapshot(`""`);
1584
+ });
1585
+
1586
+ it("should error politely when publishing to workers_dev when there is no workers.dev subdomain", async () => {
1587
+ writeWranglerToml({
1588
+ workers_dev: true,
1589
+ });
1590
+ writeWorkerSource();
1591
+ mockUploadWorkerRequest();
1592
+ mockSubDomainRequest("does-not-exist", false);
1593
+
1594
+ await expect(runWrangler("publish ./index")).rejects
1595
+ .toThrowErrorMatchingInlineSnapshot(`
1596
+ "Error: You need to register a workers.dev subdomain before publishing to workers.dev
1597
+ You can either publish your worker to one or more routes by specifying them in wrangler.toml, or register a workers.dev subdomain here:
1598
+ https://dash.cloudflare.com/some-account-id/workers/onboarding"
1599
+ `);
1600
+ });
1601
+ });
1602
+
1603
+ describe("custom builds", () => {
1604
+ beforeEach(() => {
1605
+ // @ts-expect-error disable the mock we'd setup earlier
1606
+ // or else custom builds will timeout immediately
1607
+ global.setTimeout.mockRestore();
1608
+ });
1609
+ it("should run a custom build before publishing", async () => {
1610
+ writeWranglerToml({
1611
+ build: {
1612
+ command: `node -e "console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')"`,
1613
+ },
1614
+ });
1615
+
1616
+ mockUploadWorkerRequest({
1617
+ expectedEntry: "return new Response(123)",
1618
+ });
1619
+ mockSubDomainRequest();
1620
+
1621
+ await runWrangler("publish index.js");
1622
+ expect(std.out).toMatchInlineSnapshot(`
1623
+ "running: node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\"
1624
+ Uploaded test-name (TIMINGS)
1625
+ Published test-name (TIMINGS)
1626
+ test-name.test-sub-domain.workers.dev"
1627
+ `);
1628
+ expect(std.err).toMatchInlineSnapshot(`""`);
1629
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1630
+ });
1631
+
1632
+ if (process.platform !== "win32") {
1633
+ it("should run a custom build of multiple steps combined by && before publishing", async () => {
1634
+ writeWranglerToml({
1635
+ build: {
1636
+ command: `echo "custom build" && echo "export default { fetch(){ return new Response(123) } }" > index.js`,
1637
+ },
1638
+ });
1639
+
1640
+ mockUploadWorkerRequest({
1641
+ expectedEntry: "return new Response(123)",
1642
+ });
1643
+ mockSubDomainRequest();
1644
+
1645
+ await runWrangler("publish index.js");
1646
+ expect(std.out).toMatchInlineSnapshot(`
1647
+ "running: echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js
1648
+ Uploaded test-name (TIMINGS)
1649
+ Published test-name (TIMINGS)
1650
+ test-name.test-sub-domain.workers.dev"
1651
+ `);
1652
+ expect(std.err).toMatchInlineSnapshot(`""`);
1653
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1654
+ });
1655
+ }
1656
+
1657
+ it("should throw an error if the entry doesn't exist after the build finishes", async () => {
1658
+ writeWranglerToml({
1659
+ main: "index.js",
1660
+ build: {
1661
+ command: `node -e "console.log('custom build');"`,
1662
+ },
1663
+ });
1664
+
1665
+ await expect(
1666
+ runWrangler("publish index.js")
1667
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1668
+ `"Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\""`
1669
+ );
1670
+ expect(std.out).toMatchInlineSnapshot(
1671
+ `"running: node -e \\"console.log('custom build');\\""`
1672
+ );
1673
+ expect(std.err).toMatchInlineSnapshot(`
1674
+ "Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\"
1675
+
1676
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1677
+ `);
1678
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1679
+ });
1680
+ });
1681
+
1682
+ describe("[wasm_modules]", () => {
1683
+ it("should be able to define wasm modules for service-worker format workers", async () => {
1684
+ writeWranglerToml({
1685
+ wasm_modules: {
1686
+ TESTWASMNAME: "./path/to/test.wasm",
1687
+ },
1688
+ });
1689
+ writeWorkerSource({ type: "sw" });
1690
+ fs.mkdirSync("./path/to", { recursive: true });
1691
+ fs.writeFileSync("./path/to/test.wasm", "SOME WASM CONTENT");
1692
+ mockUploadWorkerRequest({
1693
+ expectedType: "sw",
1694
+ expectedModules: { TESTWASMNAME: "SOME WASM CONTENT" },
1695
+ expectedBindings: [
1696
+ { name: "TESTWASMNAME", part: "TESTWASMNAME", type: "wasm_module" },
1697
+ ],
1698
+ });
1699
+ mockSubDomainRequest();
1700
+ await runWrangler("publish index.js");
1701
+ expect(std.out).toMatchInlineSnapshot(`
1702
+ "Uploaded test-name (TIMINGS)
1703
+ Published test-name (TIMINGS)
1704
+ test-name.test-sub-domain.workers.dev"
1705
+ `);
1706
+ expect(std.err).toMatchInlineSnapshot(`""`);
1707
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1708
+ });
1709
+
1710
+ it("should error when defining wasm modules for modules format workers", async () => {
1711
+ writeWranglerToml({
1712
+ wasm_modules: {
1713
+ TESTWASMNAME: "./path/to/test.wasm",
1714
+ },
1715
+ });
1716
+ writeWorkerSource({ type: "esm" });
1717
+ fs.mkdirSync("./path/to", { recursive: true });
1718
+ fs.writeFileSync("./path/to/test.wasm", "SOME WASM CONTENT");
1719
+
1720
+ await expect(
1721
+ runWrangler("publish index.js")
1722
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1723
+ `"You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code"`
1724
+ );
1725
+ expect(std.out).toMatchInlineSnapshot(`""`);
1726
+ expect(std.err).toMatchInlineSnapshot(`
1727
+ "You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code
1728
+
1729
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1730
+ `);
1731
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1732
+ });
1733
+
1734
+ it("should resolve wasm modules relative to the wrangler.toml file", async () => {
1735
+ fs.mkdirSync("./path/to/and/the/path/to/", { recursive: true });
1736
+ fs.writeFileSync(
1737
+ "./path/to/wrangler.toml",
1738
+ TOML.stringify({
1739
+ compatibility_date: "2022-01-12",
1740
+ name: "test-name",
1741
+ wasm_modules: {
1742
+ TESTWASMNAME: "./and/the/path/to/test.wasm",
1743
+ },
1744
+ }),
1745
+
1746
+ "utf-8"
1747
+ );
1748
+
1749
+ writeWorkerSource({ type: "sw" });
1750
+ fs.writeFileSync(
1751
+ "./path/to/and/the/path/to/test.wasm",
1752
+ "SOME WASM CONTENT"
1753
+ );
1754
+ mockUploadWorkerRequest({
1755
+ expectedType: "sw",
1756
+ expectedModules: { TESTWASMNAME: "SOME WASM CONTENT" },
1757
+ expectedBindings: [
1758
+ { name: "TESTWASMNAME", part: "TESTWASMNAME", type: "wasm_module" },
1759
+ ],
1760
+ expectedCompatibilityDate: "2022-01-12",
1761
+ });
1762
+ mockSubDomainRequest();
1763
+ await runWrangler("publish index.js --config ./path/to/wrangler.toml");
1764
+ expect(std.out).toMatchInlineSnapshot(`
1765
+ "Uploaded test-name (TIMINGS)
1766
+ Published test-name (TIMINGS)
1767
+ test-name.test-sub-domain.workers.dev"
1768
+ `);
1769
+ expect(std.err).toMatchInlineSnapshot(`""`);
1770
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1771
+ });
1772
+
1773
+ it("should be able to import .wasm modules from service-worker format workers", async () => {
1774
+ writeWranglerToml();
1775
+ fs.writeFileSync("./index.js", "import TESTWASMNAME from './test.wasm';");
1776
+ fs.writeFileSync("./test.wasm", "SOME WASM CONTENT");
1777
+ mockUploadWorkerRequest({
1778
+ expectedType: "sw",
1779
+ expectedModules: {
1780
+ __94b240d0d692281e6467aa42043986e5c7eea034_test_wasm:
1781
+ "SOME WASM CONTENT",
1782
+ },
1783
+ expectedBindings: [
1784
+ {
1785
+ name: "__94b240d0d692281e6467aa42043986e5c7eea034_test_wasm",
1786
+ part: "__94b240d0d692281e6467aa42043986e5c7eea034_test_wasm",
1787
+ type: "wasm_module",
1788
+ },
1789
+ ],
1790
+ });
1791
+ mockSubDomainRequest();
1792
+ await runWrangler("publish index.js");
1793
+ expect(std.out).toMatchInlineSnapshot(`
1794
+ "Uploaded test-name (TIMINGS)
1795
+ Published test-name (TIMINGS)
1796
+ test-name.test-sub-domain.workers.dev"
1797
+ `);
1798
+ expect(std.err).toMatchInlineSnapshot(`""`);
1799
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1800
+ });
1801
+ });
1802
+
1803
+ describe("[text_blobs]", () => {
1804
+ it("should be able to define text blobs for service-worker format workers", async () => {
1805
+ writeWranglerToml({
1806
+ text_blobs: {
1807
+ TESTTEXTBLOBNAME: "./path/to/text.file",
1808
+ },
1809
+ });
1810
+ writeWorkerSource({ type: "sw" });
1811
+ fs.mkdirSync("./path/to", { recursive: true });
1812
+ fs.writeFileSync("./path/to/text.file", "SOME TEXT CONTENT");
1813
+ mockUploadWorkerRequest({
1814
+ expectedType: "sw",
1815
+ expectedModules: { TESTTEXTBLOBNAME: "SOME TEXT CONTENT" },
1816
+ expectedBindings: [
1817
+ {
1818
+ name: "TESTTEXTBLOBNAME",
1819
+ part: "TESTTEXTBLOBNAME",
1820
+ type: "text_blob",
1821
+ },
1822
+ ],
1823
+ });
1824
+ mockSubDomainRequest();
1825
+ await runWrangler("publish index.js");
1826
+ expect(std.out).toMatchInlineSnapshot(`
1827
+ "Uploaded test-name (TIMINGS)
1828
+ Published test-name (TIMINGS)
1829
+ test-name.test-sub-domain.workers.dev"
1830
+ `);
1831
+ expect(std.err).toMatchInlineSnapshot(`""`);
1832
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1833
+ });
1834
+
1835
+ it("should error when defining text blobs for modules format workers", async () => {
1836
+ writeWranglerToml({
1837
+ text_blobs: {
1838
+ TESTTEXTBLOBNAME: "./path/to/text.file",
1839
+ },
1840
+ });
1841
+ writeWorkerSource({ type: "esm" });
1842
+ fs.mkdirSync("./path/to", { recursive: true });
1843
+ fs.writeFileSync("./path/to/text.file", "SOME TEXT CONTENT");
1844
+
1845
+ await expect(
1846
+ runWrangler("publish index.js")
1847
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1848
+ `"You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[build.upload.rules]\` in your wrangler.toml"`
1849
+ );
1850
+ expect(std.out).toMatchInlineSnapshot(`""`);
1851
+ expect(std.err).toMatchInlineSnapshot(`
1852
+ "You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[build.upload.rules]\` in your wrangler.toml
1853
+
1854
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1855
+ `);
1856
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1857
+ });
1858
+
1859
+ it("should resolve text blobs relative to the wrangler.toml file", async () => {
1860
+ fs.mkdirSync("./path/to/and/the/path/to/", { recursive: true });
1861
+ fs.writeFileSync(
1862
+ "./path/to/wrangler.toml",
1863
+ TOML.stringify({
1864
+ compatibility_date: "2022-01-12",
1865
+ name: "test-name",
1866
+ text_blobs: {
1867
+ TESTTEXTBLOBNAME: "./and/the/path/to/text.file",
1868
+ },
1869
+ }),
1870
+
1871
+ "utf-8"
1872
+ );
1873
+
1874
+ writeWorkerSource({ type: "sw" });
1875
+ fs.writeFileSync(
1876
+ "./path/to/and/the/path/to/text.file",
1877
+ "SOME TEXT CONTENT"
1878
+ );
1879
+ mockUploadWorkerRequest({
1880
+ expectedType: "sw",
1881
+ expectedModules: { TESTTEXTBLOBNAME: "SOME TEXT CONTENT" },
1882
+ expectedBindings: [
1883
+ {
1884
+ name: "TESTTEXTBLOBNAME",
1885
+ part: "TESTTEXTBLOBNAME",
1886
+ type: "text_blob",
1887
+ },
1888
+ ],
1889
+ expectedCompatibilityDate: "2022-01-12",
1890
+ });
1891
+ mockSubDomainRequest();
1892
+ await runWrangler("publish index.js --config ./path/to/wrangler.toml");
1893
+ expect(std.out).toMatchInlineSnapshot(`
1894
+ "Uploaded test-name (TIMINGS)
1895
+ Published test-name (TIMINGS)
1896
+ test-name.test-sub-domain.workers.dev"
1897
+ `);
1898
+ expect(std.err).toMatchInlineSnapshot(`""`);
1899
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1900
+ });
1901
+ });
1902
+
1903
+ describe("vars bindings", () => {
1904
+ it("should support json bindings", async () => {
1905
+ writeWranglerToml({
1906
+ vars: {
1907
+ text: "plain ol' string",
1908
+ count: 1,
1909
+ complex: { enabled: true, id: 123 },
1910
+ },
1911
+ });
1912
+ writeWorkerSource();
1913
+ mockSubDomainRequest();
1914
+ mockUploadWorkerRequest({
1915
+ expectedBindings: [
1916
+ { name: "text", type: "plain_text", text: "plain ol' string" },
1917
+ { name: "count", type: "json", json: 1 },
1918
+ {
1919
+ name: "complex",
1920
+ type: "json",
1921
+ json: { enabled: true, id: 123 },
1922
+ },
1923
+ ],
1924
+ });
1925
+
1926
+ await runWrangler("publish index.js");
1927
+ expect(std.out).toMatchInlineSnapshot(`
1928
+ "Uploaded test-name (TIMINGS)
1929
+ Published test-name (TIMINGS)
1930
+ test-name.test-sub-domain.workers.dev"
1931
+ `);
1932
+ expect(std.err).toMatchInlineSnapshot(`""`);
1933
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1934
+ });
1935
+ });
1936
+
1937
+ describe("r2 bucket bindings", () => {
1938
+ it("should support r2 bucket bindings", async () => {
1939
+ writeWranglerToml({
1940
+ r2_buckets: [{ binding: "FOO", bucket_name: "foo-bucket" }],
1941
+ });
1942
+ writeWorkerSource();
1943
+ mockSubDomainRequest();
1944
+ mockUploadWorkerRequest({
1945
+ expectedBindings: [
1946
+ { bucket_name: "foo-bucket", name: "FOO", type: "r2_bucket" },
1947
+ ],
1948
+ });
1949
+
1950
+ await runWrangler("publish index.js");
1951
+ expect(std.out).toMatchInlineSnapshot(`
1952
+ "Uploaded test-name (TIMINGS)
1953
+ Published test-name (TIMINGS)
1954
+ test-name.test-sub-domain.workers.dev"
1955
+ `);
1956
+ expect(std.err).toMatchInlineSnapshot(`""`);
1957
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1958
+ });
1959
+ });
1960
+
1961
+ describe("durable object bindings", () => {
1962
+ it("should support durable object bindings", async () => {
1963
+ writeWranglerToml({
1964
+ durable_objects: {
1965
+ bindings: [
1966
+ { name: "EXAMPLE_DO_BINDING", class_name: "ExampleDurableObject" },
1967
+ ],
1968
+ },
1969
+ });
1970
+ writeWorkerSource({ type: "esm" });
1971
+ mockSubDomainRequest();
1972
+ mockUploadWorkerRequest({
1973
+ expectedBindings: [
1974
+ {
1975
+ class_name: "ExampleDurableObject",
1976
+ name: "EXAMPLE_DO_BINDING",
1977
+ type: "durable_object_namespace",
1978
+ },
1979
+ ],
1980
+ });
1981
+
1982
+ await runWrangler("publish index.js");
1983
+ expect(std.out).toMatchInlineSnapshot(`
1984
+ "Uploaded test-name (TIMINGS)
1985
+ Published test-name (TIMINGS)
1986
+ test-name.test-sub-domain.workers.dev"
1987
+ `);
1988
+ expect(std.err).toMatchInlineSnapshot(`""`);
1989
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1990
+ });
1991
+
1992
+ it("should support service-workers binding to external durable objects", async () => {
1993
+ writeWranglerToml({
1994
+ durable_objects: {
1995
+ bindings: [
1996
+ {
1997
+ name: "EXAMPLE_DO_BINDING",
1998
+ class_name: "ExampleDurableObject",
1999
+ script_name: "example-do-binding-worker",
2000
+ },
2001
+ ],
2002
+ },
2003
+ });
2004
+ writeWorkerSource({ type: "sw" });
2005
+ mockSubDomainRequest();
2006
+ mockUploadWorkerRequest({
2007
+ expectedType: "sw",
2008
+ expectedBindings: [
2009
+ {
2010
+ name: "EXAMPLE_DO_BINDING",
2011
+ class_name: "ExampleDurableObject",
2012
+ script_name: "example-do-binding-worker",
2013
+ type: "durable_object_namespace",
2014
+ },
2015
+ ],
2016
+ });
2017
+
2018
+ await runWrangler("publish index.js");
2019
+ expect(std.out).toMatchInlineSnapshot(`
2020
+ "Uploaded test-name (TIMINGS)
2021
+ Published test-name (TIMINGS)
2022
+ test-name.test-sub-domain.workers.dev"
2023
+ `);
2024
+ expect(std.err).toMatchInlineSnapshot(`""`);
2025
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2026
+ });
2027
+
2028
+ it("should support module workers implementing durable objects", async () => {
2029
+ writeWranglerToml({
2030
+ durable_objects: {
2031
+ bindings: [
2032
+ {
2033
+ name: "EXAMPLE_DO_BINDING",
2034
+ class_name: "ExampleDurableObject",
2035
+ },
2036
+ ],
2037
+ },
2038
+ });
2039
+ writeWorkerSource({ type: "esm" });
2040
+ mockSubDomainRequest();
2041
+ mockUploadWorkerRequest({
2042
+ expectedType: "esm",
2043
+ expectedBindings: [
2044
+ {
2045
+ name: "EXAMPLE_DO_BINDING",
2046
+ class_name: "ExampleDurableObject",
2047
+ type: "durable_object_namespace",
2048
+ },
2049
+ ],
2050
+ });
2051
+
2052
+ await runWrangler("publish index.js");
2053
+ expect(std.out).toMatchInlineSnapshot(`
2054
+ "Uploaded test-name (TIMINGS)
2055
+ Published test-name (TIMINGS)
2056
+ test-name.test-sub-domain.workers.dev"
2057
+ `);
2058
+ expect(std.err).toMatchInlineSnapshot(`""`);
2059
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2060
+ });
2061
+
2062
+ it("should error when detecting service workers implementing durable objects", async () => {
2063
+ writeWranglerToml({
2064
+ durable_objects: {
2065
+ bindings: [
2066
+ {
2067
+ name: "EXAMPLE_DO_BINDING",
2068
+ class_name: "ExampleDurableObject",
2069
+ },
2070
+ ],
2071
+ },
2072
+ });
2073
+ writeWorkerSource({ type: "sw" });
2074
+ mockSubDomainRequest();
2075
+
2076
+ await expect(runWrangler("publish index.js")).rejects
2077
+ .toThrowErrorMatchingInlineSnapshot(`
2078
+ "You seem to be trying to use Durable Objects in a Worker written with Service Worker syntax.
2079
+ You can use Durable Objects defined in other Workers by specifying a \`script_name\` in your wrangler.toml, where \`script_name\` is the name of the Worker that implements that Durable Object. For example:
2080
+ { name = EXAMPLE_DO_BINDING, class_name = ExampleDurableObject } ==> { name = EXAMPLE_DO_BINDING, class_name = ExampleDurableObject, script_name = example-do-binding-worker }
2081
+ Alternatively, migrate your worker to ES Module syntax to implement a Durable Object in this Worker:
2082
+ https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/"
2083
+ `);
2084
+ });
2085
+ });
2086
+
2087
+ describe("unsafe bindings", () => {
2088
+ it("should warn if using unsafe bindings", async () => {
2089
+ writeWranglerToml({
2090
+ unsafe: {
2091
+ bindings: [
2092
+ {
2093
+ name: "my-binding",
2094
+ type: "binding-type",
2095
+ param: "binding-param",
2096
+ },
2097
+ ],
2098
+ },
2099
+ });
2100
+ writeWorkerSource();
2101
+ mockSubDomainRequest();
2102
+ mockUploadWorkerRequest({
2103
+ expectedBindings: [
2104
+ {
2105
+ name: "my-binding",
2106
+ type: "binding-type",
2107
+ param: "binding-param",
2108
+ },
2109
+ ],
2110
+ });
2111
+
2112
+ await runWrangler("publish index.js");
2113
+ expect(std.out).toMatchInlineSnapshot(`
2114
+ "Uploaded test-name (TIMINGS)
2115
+ Published test-name (TIMINGS)
2116
+ test-name.test-sub-domain.workers.dev"
2117
+ `);
2118
+ expect(std.err).toMatchInlineSnapshot(`""`);
2119
+ expect(std.warn).toMatchInlineSnapshot(`
2120
+ "Processing wrangler.toml configuration:
2121
+ - \\"unsafe\\" fields are experimental and may change or break at any time."
2122
+ `);
2123
+ });
2124
+ it("should warn if using unsafe bindings already handled by wrangler", async () => {
2125
+ writeWranglerToml({
2126
+ unsafe: {
2127
+ bindings: [
2128
+ {
2129
+ name: "my-binding",
2130
+ type: "plain_text",
2131
+ text: "text",
2132
+ },
2133
+ ],
2134
+ },
2135
+ });
2136
+ writeWorkerSource();
2137
+ mockSubDomainRequest();
2138
+ mockUploadWorkerRequest({
2139
+ expectedBindings: [
2140
+ {
2141
+ name: "my-binding",
2142
+ type: "plain_text",
2143
+ text: "text",
2144
+ },
2145
+ ],
2146
+ });
2147
+
2148
+ await runWrangler("publish index.js");
2149
+ expect(std.out).toMatchInlineSnapshot(`
2150
+ "Uploaded test-name (TIMINGS)
2151
+ Published test-name (TIMINGS)
2152
+ test-name.test-sub-domain.workers.dev"
2153
+ `);
2154
+ expect(std.err).toMatchInlineSnapshot(`""`);
2155
+ expect(std.warn).toMatchInlineSnapshot(`
2156
+ "Processing wrangler.toml configuration:
2157
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
2158
+ - \\"unsafe.bindings[0]\\": {\\"name\\":\\"my-binding\\",\\"type\\":\\"plain_text\\",\\"text\\":\\"text\\"}
2159
+ - The binding type \\"plain_text\\" is directly supported by wrangler.
2160
+ Consider migrating this unsafe binding to a format for 'plain_text' bindings that is supported by wrangler for optimal support.
2161
+ For more details, see https://developers.cloudflare.com/workers/cli-wrangler/configuration"
2162
+ `);
2163
+ });
2164
+ });
2165
+
2166
+ describe("upload rules", () => {
2167
+ it("should be able to define rules for uploading non-js modules (sw)", async () => {
2168
+ writeWranglerToml({
2169
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
2170
+ });
2171
+ fs.writeFileSync("./index.js", `import TEXT from './text.file';`);
2172
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2173
+ mockSubDomainRequest();
2174
+ mockUploadWorkerRequest({
2175
+ expectedType: "sw",
2176
+ expectedBindings: [
2177
+ {
2178
+ name: "__2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file",
2179
+ part: "__2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file",
2180
+ type: "text_blob",
2181
+ },
2182
+ ],
2183
+ expectedModules: {
2184
+ __2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file:
2185
+ "SOME TEXT CONTENT",
2186
+ },
2187
+ });
2188
+ await runWrangler("publish index.js");
2189
+ expect(std.out).toMatchInlineSnapshot(`
2190
+ "Uploaded test-name (TIMINGS)
2191
+ Published test-name (TIMINGS)
2192
+ test-name.test-sub-domain.workers.dev"
855
2193
  `);
856
2194
  expect(std.err).toMatchInlineSnapshot(`""`);
2195
+ expect(std.warn).toMatchInlineSnapshot(`""`);
857
2196
  });
858
2197
 
859
- it("should skip hidden files and directories except `.well-known`", async () => {
860
- const assets = [
861
- {
862
- filePath: "assets/.hidden-file.txt",
863
- content: "Content of hidden-file",
864
- },
865
- {
866
- filePath: "assets/.hidden/file-1.txt",
867
- content: "Content of file-1",
868
- },
869
- {
870
- filePath: "assets/.well-known/file-2.txt",
871
- content: "Content of file-2",
872
- },
873
- ];
874
- const kvNamespace = {
875
- title: "__test-name-workers_sites_assets",
876
- id: "__test-name-workers_sites_assets-id",
877
- };
2198
+ it("should be able to define rules for uploading non-js modules (esm)", async () => {
878
2199
  writeWranglerToml({
879
- build: { upload: { main: "./index.js" } },
880
- site: {
881
- bucket: "assets",
882
- },
2200
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
883
2201
  });
884
- writeWorkerSource();
885
- writeAssets(assets);
886
- mockUploadWorkerRequest();
2202
+ fs.writeFileSync(
2203
+ "./index.js",
2204
+ `import TEXT from './text.file'; export default {};`
2205
+ );
2206
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
887
2207
  mockSubDomainRequest();
888
- mockListKVNamespacesRequest(kvNamespace);
889
- mockKeyListRequest(kvNamespace.id, []);
890
- // Only expect file-2 to be uploaded
891
- mockUploadAssetsToKVRequest(kvNamespace.id, assets.slice(2));
892
- await runWrangler("publish");
893
-
2208
+ mockUploadWorkerRequest({
2209
+ expectedType: "esm",
2210
+ expectedBindings: [],
2211
+ expectedModules: {
2212
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2213
+ "SOME TEXT CONTENT",
2214
+ },
2215
+ });
2216
+ await runWrangler("publish index.js");
894
2217
  expect(std.out).toMatchInlineSnapshot(`
895
- "reading assets/.well-known/file-2.txt...
896
- uploading as assets/.well-known/file-2.5938485188.txt...
897
- Uploaded
898
- test-name
899
- (TIMINGS)
900
- Deployed
901
- test-name
902
- (TIMINGS)
903
-
904
- test-name.test-sub-domain.workers.dev"
2218
+ "Uploaded test-name (TIMINGS)
2219
+ Published test-name (TIMINGS)
2220
+ test-name.test-sub-domain.workers.dev"
905
2221
  `);
906
2222
  expect(std.err).toMatchInlineSnapshot(`""`);
2223
+ expect(std.warn).toMatchInlineSnapshot(`""`);
907
2224
  });
908
2225
 
909
- it("should error if the asset is over 25Mb", async () => {
910
- const assets = [
911
- {
912
- filePath: "assets/large-file.txt",
913
- // This file is greater than 25MiB when base64 encoded but small enough to be uploaded.
914
- content: "X".repeat(25 * 1024 * 1024 * 0.8 + 1),
915
- },
916
- {
917
- filePath: "assets/too-large-file.txt",
918
- content: "X".repeat(25 * 1024 * 1024 + 1),
919
- },
920
- ];
921
- const kvNamespace = {
922
- title: "__test-name-workers_sites_assets",
923
- id: "__test-name-workers_sites_assets-id",
924
- };
2226
+ it("should log a deprecation warning when using `build.upload.rules`", async () => {
925
2227
  writeWranglerToml({
926
- build: { upload: { main: "./index.js" } },
927
- site: {
928
- bucket: "assets",
929
- exclude: ["assets/file-1.txt"],
2228
+ build: {
2229
+ upload: {
2230
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
2231
+ },
930
2232
  },
931
2233
  });
932
- writeWorkerSource();
933
- writeAssets(assets);
934
- mockUploadWorkerRequest();
935
- mockSubDomainRequest();
936
- mockListKVNamespacesRequest(kvNamespace);
937
- mockKeyListRequest(kvNamespace.id, []);
938
-
939
- await expect(
940
- runWrangler("publish")
941
- ).rejects.toThrowErrorMatchingInlineSnapshot(
942
- `"File assets/too-large-file.txt is too big, it should be under 25 MiB. See https://developers.cloudflare.com/workers/platform/limits#kv-limits"`
2234
+ fs.writeFileSync(
2235
+ "./index.js",
2236
+ `import TEXT from './text.file'; export default {};`
943
2237
  );
944
-
2238
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2239
+ mockSubDomainRequest();
2240
+ mockUploadWorkerRequest({
2241
+ expectedType: "esm",
2242
+ expectedBindings: [],
2243
+ expectedModules: {
2244
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2245
+ "SOME TEXT CONTENT",
2246
+ },
2247
+ });
2248
+ await runWrangler("publish index.js");
945
2249
  expect(std.out).toMatchInlineSnapshot(`
946
- "reading assets/large-file.txt...
947
- uploading as assets/large-file.0ea0637a45.txt..."
2250
+ "Uploaded test-name (TIMINGS)
2251
+ Published test-name (TIMINGS)
2252
+ test-name.test-sub-domain.workers.dev"
948
2253
  `);
949
- expect(std.err).toMatchInlineSnapshot(`
950
- "File assets/too-large-file.txt is too big, it should be under 25 MiB. See https://developers.cloudflare.com/workers/platform/limits#kv-limits
951
-
952
- %s
953
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2254
+ expect(std.err).toMatchInlineSnapshot(`""`);
2255
+ expect(std.warn).toMatchInlineSnapshot(`
2256
+ "Processing wrangler.toml configuration:
2257
+ - DEPRECATION: The \`build.upload.rules\` config field is no longer used, the rules should be specified via the \`rules\` config field. Delete the \`build.upload\` field from the configuration file, and add this:
2258
+ \`\`\`
2259
+ [[rules]]
2260
+ type = \\"Text\\"
2261
+ globs = [ \\"**/*.file\\" ]
2262
+ fallthrough = true
2263
+ \`\`\`"
954
2264
  `);
955
2265
  });
956
2266
 
957
- it("should error if the asset key is over 512 characters", async () => {
958
- const longFilePathAsset = {
959
- filePath: "assets/" + "folder/".repeat(100) + "file.txt",
960
- content: "content of file",
961
- };
962
- const kvNamespace = {
963
- title: "__test-name-workers_sites_assets",
964
- id: "__test-name-workers_sites_assets-id",
965
- };
2267
+ it("should be able to use fallthrough:true for multiple rules", async () => {
966
2268
  writeWranglerToml({
967
- build: { upload: { main: "./index.js" } },
968
- site: {
969
- bucket: "assets",
970
- },
2269
+ rules: [
2270
+ { type: "Text", globs: ["**/*.file"], fallthrough: true },
2271
+ { type: "Text", globs: ["**/*.other"], fallthrough: true },
2272
+ ],
971
2273
  });
972
- writeWorkerSource();
973
- writeAssets([longFilePathAsset]);
974
- mockUploadWorkerRequest();
2274
+ fs.writeFileSync(
2275
+ "./index.js",
2276
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
2277
+ );
2278
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2279
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
975
2280
  mockSubDomainRequest();
976
- mockListKVNamespacesRequest(kvNamespace);
977
- mockKeyListRequest(kvNamespace.id, []);
2281
+ mockUploadWorkerRequest({
2282
+ expectedType: "esm",
2283
+ expectedBindings: [],
2284
+ expectedModules: {
2285
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2286
+ "SOME TEXT CONTENT",
2287
+ "./16347a01366873ed80fe45115119de3c92ab8db0-other.other":
2288
+ "SOME OTHER TEXT CONTENT",
2289
+ },
2290
+ });
2291
+ await runWrangler("publish index.js");
2292
+ expect(std.out).toMatchInlineSnapshot(`
2293
+ "Uploaded test-name (TIMINGS)
2294
+ Published test-name (TIMINGS)
2295
+ test-name.test-sub-domain.workers.dev"
2296
+ `);
2297
+ expect(std.err).toMatchInlineSnapshot(`""`);
2298
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2299
+ });
978
2300
 
979
- await expect(
980
- runWrangler("publish")
981
- ).rejects.toThrowErrorMatchingInlineSnapshot(
982
- `"The asset path key \\"assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.3da0d0cd12.txt\\" exceeds the maximum key size limit of 512. See https://developers.cloudflare.com/workers/platform/limits#kv-limits\\","`
2301
+ it("should be able to use fallthrough:false for multiple rules", async () => {
2302
+ writeWranglerToml({
2303
+ rules: [
2304
+ { type: "Text", globs: ["**/*.file"], fallthrough: false },
2305
+ { type: "Text", globs: ["**/*.other"] },
2306
+ ],
2307
+ });
2308
+ fs.writeFileSync(
2309
+ "./index.js",
2310
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
983
2311
  );
2312
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2313
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
984
2314
 
985
- expect(std.out).toMatchInlineSnapshot(
986
- `"reading assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.txt..."`
2315
+ // We throw an error when we come across a file that matched a rule
2316
+ // but was skipped because of fallthrough = false
2317
+ let err: Error | undefined;
2318
+ try {
2319
+ await runWrangler("publish index.js");
2320
+ } catch (e) {
2321
+ err = e as Error;
2322
+ }
2323
+ expect(err?.message).toMatch(
2324
+ `The file ./other.other matched a module rule in your configuration ({"type":"Text","globs":["**/*.other"]}), but was ignored because a previous rule with the same type was not marked as \`fallthrough = true\`.`
987
2325
  );
988
- expect(std.err).toMatchInlineSnapshot(`
989
- "The asset path key \\"assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.3da0d0cd12.txt\\" exceeds the maximum key size limit of 512. See https://developers.cloudflare.com/workers/platform/limits#kv-limits\\",
2326
+ });
2327
+
2328
+ it("should warn when multiple rules for the same type do not have fallback defined", async () => {
2329
+ writeWranglerToml({
2330
+ rules: [
2331
+ { type: "Text", globs: ["**/*.file"] },
2332
+ { type: "Text", globs: ["**/*.other"] },
2333
+ ],
2334
+ });
2335
+ fs.writeFileSync(
2336
+ "./index.js",
2337
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
2338
+ );
2339
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2340
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
990
2341
 
991
- %s
992
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2342
+ // We throw an error when we come across a file that matched a rule
2343
+ // but was skipped because of fallthrough = false
2344
+ let err: Error | undefined;
2345
+ try {
2346
+ await runWrangler("publish index.js");
2347
+ } catch (e) {
2348
+ err = e as Error;
2349
+ }
2350
+ expect(err?.message).toMatch(
2351
+ `The file ./other.other matched a module rule in your configuration ({"type":"Text","globs":["**/*.other"]}), but was ignored because a previous rule with the same type was not marked as \`fallthrough = true\`.`
2352
+ );
2353
+ // and the warnings because fallthrough was not explicitly set
2354
+ expect(std.warn).toMatchInlineSnapshot(`
2355
+ "The module rule at position 1 ({\\"type\\":\\"Text\\",\\"globs\\":[\\"**/*.other\\"]}) has the same type as a previous rule (at position 0, {\\"type\\":\\"Text\\",\\"globs\\":[\\"**/*.file\\"]}). This rule will be ignored. To the previous rule, add \`fallthrough = true\` to allow this one to also be used, or \`fallthrough = false\` to silence this warning.
2356
+ The default module rule {\\"type\\":\\"Text\\",\\"globs\\":[\\"**/*.txt\\",\\"**/*.html\\"]} has the same type as a previous rule (at position 0, {\\"type\\":\\"Text\\",\\"globs\\":[\\"**/*.file\\"]}). This rule will be ignored. To the previous rule, add \`fallthrough = true\` to allow the default one to also be used, or \`fallthrough = false\` to silence this warning."
993
2357
  `);
994
2358
  });
995
2359
  });
996
2360
 
997
- describe("custom builds", () => {
998
- it("should run a custom build before publishing", async () => {
2361
+ describe("legacy module specifiers", () => {
2362
+ it("should work with legacy module specifiers, with a deprecation warning (1)", async () => {
999
2363
  writeWranglerToml({
1000
- build: {
1001
- command: `node -e "console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')"`,
1002
- },
2364
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: false }],
1003
2365
  });
1004
-
2366
+ fs.writeFileSync(
2367
+ "./index.js",
2368
+ `import TEXT from 'text.file'; export default {};`
2369
+ );
2370
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2371
+ mockSubDomainRequest();
1005
2372
  mockUploadWorkerRequest({
1006
- expectedEntry: "return new Response(123)",
2373
+ expectedModules: {
2374
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2375
+ "SOME TEXT CONTENT",
2376
+ },
1007
2377
  });
1008
- mockSubDomainRequest();
1009
-
1010
2378
  await runWrangler("publish index.js");
1011
2379
  expect(std.out).toMatchInlineSnapshot(`
1012
- "running:
1013
- node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\"
1014
- Uploaded
1015
- test-name
1016
- (TIMINGS)
1017
- Deployed
1018
- test-name
1019
- (TIMINGS)
1020
-
1021
- test-name.test-sub-domain.workers.dev"
2380
+ "Uploaded test-name (TIMINGS)
2381
+ Published test-name (TIMINGS)
2382
+ test-name.test-sub-domain.workers.dev"
1022
2383
  `);
1023
2384
  expect(std.err).toMatchInlineSnapshot(`""`);
1024
- expect(std.warn).toMatchInlineSnapshot(`""`);
2385
+ expect(std.warn).toMatchInlineSnapshot(
2386
+ `"Deprecation warning: detected a legacy module import in \\"./index.js\\". This will stop working in the future. Replace references to \\"text.file\\" with \\"./text.file\\";"`
2387
+ );
1025
2388
  });
2389
+ });
1026
2390
 
1027
- if (process.platform !== "win32") {
1028
- it("should run a custom build of multiple steps combined by && before publishing", async () => {
1029
- writeWranglerToml({
1030
- build: {
1031
- command: `echo "custom build" && echo "export default { fetch(){ return new Response(123) } }" > index.js`,
1032
- },
1033
- });
1034
-
1035
- mockUploadWorkerRequest({
1036
- expectedEntry: "return new Response(123)",
1037
- });
1038
- mockSubDomainRequest();
2391
+ it("should work with legacy module specifiers, with a deprecation warning (2)", async () => {
2392
+ writeWranglerToml();
2393
+ fs.writeFileSync(
2394
+ "./index.js",
2395
+ `import WASM from 'index.wasm'; export default {};`
2396
+ );
2397
+ fs.writeFileSync("./index.wasm", "SOME WASM CONTENT");
2398
+ mockSubDomainRequest();
2399
+ mockUploadWorkerRequest({
2400
+ expectedModules: {
2401
+ "./94b240d0d692281e6467aa42043986e5c7eea034-index.wasm":
2402
+ "SOME WASM CONTENT",
2403
+ },
2404
+ });
2405
+ await runWrangler("publish index.js");
2406
+ expect(std.out).toMatchInlineSnapshot(`
2407
+ "Uploaded test-name (TIMINGS)
2408
+ Published test-name (TIMINGS)
2409
+ test-name.test-sub-domain.workers.dev"
2410
+ `);
2411
+ expect(std.err).toMatchInlineSnapshot(`""`);
2412
+ expect(std.warn).toMatchInlineSnapshot(
2413
+ `"Deprecation warning: detected a legacy module import in \\"./index.js\\". This will stop working in the future. Replace references to \\"index.wasm\\" with \\"./index.wasm\\";"`
2414
+ );
2415
+ });
1039
2416
 
1040
- await runWrangler("publish index.js");
1041
- expect(std.out).toMatchInlineSnapshot(`
1042
- "running:
1043
- echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js
1044
- Uploaded
1045
- test-name
1046
- (TIMINGS)
1047
- Deployed
1048
- test-name
1049
- (TIMINGS)
1050
-
1051
- test-name.test-sub-domain.workers.dev"
1052
- `);
1053
- expect(std.err).toMatchInlineSnapshot(`""`);
1054
- expect(std.warn).toMatchInlineSnapshot(`""`);
1055
- });
1056
- }
2417
+ it("should not match regular module specifiers when there aren't any possible legacy module matches", async () => {
2418
+ // see https://github.com/cloudflare/wrangler2/issues/655 for bug details
2419
+
2420
+ fs.writeFileSync(
2421
+ "./index.js",
2422
+ `import inner from './inner/index.js'; export default {};`
2423
+ );
2424
+ fs.mkdirSync("./inner", { recursive: true });
2425
+ fs.writeFileSync("./inner/index.js", `export default 123`);
2426
+ mockSubDomainRequest();
2427
+ mockUploadWorkerRequest();
2428
+
2429
+ await runWrangler(
2430
+ "publish index.js --compatibility-date 2022-03-17 --name test-name"
2431
+ );
2432
+ expect(std.out).toMatchInlineSnapshot(`
2433
+ "Uploaded test-name (TIMINGS)
2434
+ Published test-name (TIMINGS)
2435
+ test-name.test-sub-domain.workers.dev"
2436
+ `);
2437
+ expect(std.err).toMatchInlineSnapshot(`""`);
2438
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1057
2439
  });
1058
2440
  });
1059
2441
 
1060
- /** Write a mock wrangler.toml file to disk. */
1061
- function writeWranglerToml(config: Omit<Config, "env"> = {}) {
1062
- // We Omit `env` from config because TOML.stringify() appears to
1063
- // have a weird type signature that appears to fail. We'll revisit this
1064
- // when we write tests for publishing environments
1065
- fs.writeFileSync(
1066
- "./wrangler.toml",
1067
- TOML.stringify({
1068
- compatibility_date: "2022-01-12",
1069
- name: "test-name",
1070
- ...config,
1071
- }),
1072
-
1073
- "utf-8"
1074
- );
1075
- }
1076
-
1077
2442
  /** Write a mock Worker script to disk. */
1078
2443
  function writeWorkerSource({
1079
2444
  basePath = ".",
@@ -1119,31 +2484,41 @@ function mockUploadWorkerRequest({
1119
2484
  expectedType = "esm",
1120
2485
  expectedBindings,
1121
2486
  expectedModules = {},
2487
+ expectedCompatibilityDate,
2488
+ expectedCompatibilityFlags,
1122
2489
  env = undefined,
2490
+ legacyEnv = false,
1123
2491
  }: {
1124
2492
  available_on_subdomain?: boolean;
1125
2493
  expectedEntry?: string;
1126
2494
  expectedType?: "esm" | "sw";
1127
2495
  expectedBindings?: unknown;
1128
2496
  expectedModules?: Record<string, string>;
1129
- env?: string | undefined;
2497
+ expectedCompatibilityDate?: string;
2498
+ expectedCompatibilityFlags?: string[];
2499
+ env?: string;
2500
+ legacyEnv?: boolean;
1130
2501
  } = {}) {
1131
2502
  setMockResponse(
1132
- env
1133
- ? `/accounts/:accountId/workers/services/:scriptName/environments/:envName`
2503
+ env && !legacyEnv
2504
+ ? "/accounts/:accountId/workers/services/:scriptName/environments/:envName"
1134
2505
  : "/accounts/:accountId/workers/scripts/:scriptName",
1135
2506
  "PUT",
1136
- async ([_url, accountId, scriptName], { body }, queryParams) => {
2507
+ async ([_url, accountId, scriptName, envName], { body }, queryParams) => {
1137
2508
  expect(accountId).toEqual("some-account-id");
1138
- expect(scriptName).toEqual("test-name");
1139
- expect(queryParams.get("available_on_subdomains")).toEqual("true");
2509
+ expect(scriptName).toEqual(
2510
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2511
+ );
2512
+ if (!legacyEnv) {
2513
+ expect(envName).toEqual(env);
2514
+ }
2515
+ expect(queryParams.get("available_on_subdomain")).toEqual("true");
1140
2516
  const formBody = body as FormData;
1141
2517
  if (expectedEntry !== undefined) {
1142
2518
  expect(await (formBody.get("index.js") as File).text()).toMatch(
1143
2519
  expectedEntry
1144
2520
  );
1145
2521
  }
1146
-
1147
2522
  const metadata = JSON.parse(
1148
2523
  formBody.get("metadata") as string
1149
2524
  ) as WorkerMetadata;
@@ -1155,8 +2530,16 @@ function mockUploadWorkerRequest({
1155
2530
  if (expectedBindings !== undefined) {
1156
2531
  expect(metadata.bindings).toEqual(expectedBindings);
1157
2532
  }
2533
+ if (expectedCompatibilityDate !== undefined) {
2534
+ expect(metadata.compatibility_date).toEqual(expectedCompatibilityDate);
2535
+ }
2536
+ if (expectedCompatibilityFlags !== undefined) {
2537
+ expect(metadata.compatibility_flags).toEqual(
2538
+ expectedCompatibilityFlags
2539
+ );
2540
+ }
1158
2541
  for (const [name, content] of Object.entries(expectedModules)) {
1159
- expect(await (formBody.get(name) as File).text()).toMatch(content);
2542
+ expect(await (formBody.get(name) as File).text()).toEqual(content);
1160
2543
  }
1161
2544
 
1162
2545
  return { available_on_subdomain };
@@ -1165,10 +2548,84 @@ function mockUploadWorkerRequest({
1165
2548
  }
1166
2549
 
1167
2550
  /** Create a mock handler for the request to get the account's subdomain. */
1168
- function mockSubDomainRequest(subdomain = "test-sub-domain") {
1169
- setMockResponse("/accounts/:accountId/workers/subdomain", () => {
1170
- return { subdomain };
1171
- });
2551
+ function mockSubDomainRequest(
2552
+ subdomain = "test-sub-domain",
2553
+ registeredWorkersDev = true
2554
+ ) {
2555
+ if (registeredWorkersDev) {
2556
+ setMockResponse("/accounts/:accountId/workers/subdomain", "GET", () => {
2557
+ return { subdomain };
2558
+ });
2559
+ } else {
2560
+ setMockRawResponse("/accounts/:accountId/workers/subdomain", "GET", () => {
2561
+ return createFetchResult(null, false, [
2562
+ { code: 10007, message: "haven't registered workers.dev" },
2563
+ ]);
2564
+ });
2565
+ }
2566
+ }
2567
+
2568
+ /** Create a mock handler to toggle a <script>.<user>.workers.dev subdomain */
2569
+ function mockUpdateWorkerRequest({
2570
+ env,
2571
+ enabled,
2572
+ legacyEnv = false,
2573
+ }: {
2574
+ enabled: boolean;
2575
+ env?: string | undefined;
2576
+ legacyEnv?: boolean | undefined;
2577
+ }) {
2578
+ const requests = { count: 0 };
2579
+ const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
2580
+ const environment = env && !legacyEnv ? "/environments/:envName" : "";
2581
+ setMockResponse(
2582
+ `/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/subdomain`,
2583
+ "POST",
2584
+ ([_url, accountId, scriptName, envName], { body }) => {
2585
+ expect(accountId).toEqual("some-account-id");
2586
+ expect(scriptName).toEqual(
2587
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2588
+ );
2589
+ if (!legacyEnv) {
2590
+ expect(envName).toEqual(env);
2591
+ }
2592
+ expect(JSON.parse(body as string)).toEqual({ enabled });
2593
+ return null;
2594
+ }
2595
+ );
2596
+ return requests;
2597
+ }
2598
+
2599
+ function mockPublishRoutesRequest({
2600
+ routes,
2601
+ env = undefined,
2602
+ legacyEnv = false,
2603
+ }: {
2604
+ routes: string[];
2605
+ env?: string | undefined;
2606
+ legacyEnv?: boolean | undefined;
2607
+ }) {
2608
+ const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
2609
+ const environment = env && !legacyEnv ? "/environments/:envName" : "";
2610
+
2611
+ setMockResponse(
2612
+ `/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/routes`,
2613
+ "PUT",
2614
+ ([_url, accountId, scriptName, envName], { body }) => {
2615
+ expect(accountId).toEqual("some-account-id");
2616
+ expect(scriptName).toEqual(
2617
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2618
+ );
2619
+ if (!legacyEnv) {
2620
+ expect(envName).toEqual(env);
2621
+ }
2622
+
2623
+ expect(JSON.parse(body as string)).toEqual(
2624
+ routes.map((pattern) => ({ pattern }))
2625
+ );
2626
+ return null;
2627
+ }
2628
+ );
1172
2629
  }
1173
2630
 
1174
2631
  /** Create a mock handler for the request to get a list of all KV namespaces. */
@@ -1186,7 +2643,12 @@ function mockListKVNamespacesRequest(...namespaces: KVNamespaceInfo[]) {
1186
2643
  /** Create a mock handler for the request that tries to do a bulk upload of assets to a KV namespace. */
1187
2644
  function mockUploadAssetsToKVRequest(
1188
2645
  expectedNamespaceId: string,
1189
- assets: { filePath: string; content: string }[]
2646
+ assets: {
2647
+ filePath: string;
2648
+ content: string;
2649
+ expiration?: number;
2650
+ expiration_ttl?: number;
2651
+ }[]
1190
2652
  ) {
1191
2653
  setMockResponse(
1192
2654
  "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
@@ -1215,8 +2677,28 @@ function mockUploadAssetsToKVRequest(
1215
2677
  expect(Buffer.from(upload.value, "base64").toString()).toEqual(
1216
2678
  asset.content
1217
2679
  );
2680
+ expect(upload.expiration).toEqual(asset.expiration);
2681
+ expect(upload.expiration_ttl).toEqual(asset.expiration_ttl);
1218
2682
  }
1219
2683
  return null;
1220
2684
  }
1221
2685
  );
1222
2686
  }
2687
+
2688
+ /** Create a mock handler for thr request that does a bulk delete of unused assets */
2689
+ function mockDeleteUnusedAssetsRequest(
2690
+ expectedNamespaceId: string,
2691
+ assets: string[]
2692
+ ) {
2693
+ setMockResponse(
2694
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
2695
+ "DELETE",
2696
+ ([_url, accountId, namespaceId], { body }) => {
2697
+ expect(accountId).toEqual("some-account-id");
2698
+ expect(namespaceId).toEqual(expectedNamespaceId);
2699
+ const deletes = JSON.parse(body as string);
2700
+ expect(assets).toEqual(deletes);
2701
+ return null;
2702
+ }
2703
+ );
2704
+ }