wrangler 0.0.0-e2a26a0 → 0.0.0-e3cab74

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 (68) hide show
  1. package/package.json +16 -7
  2. package/pages/functions/filepath-routing.test.ts +112 -36
  3. package/pages/functions/filepath-routing.ts +66 -119
  4. package/pages/functions/routes.ts +8 -17
  5. package/pages/functions/template-worker.ts +3 -9
  6. package/src/__tests__/configuration.test.ts +2185 -0
  7. package/src/__tests__/dev.test.tsx +48 -6
  8. package/src/__tests__/guess-worker-format.test.ts +66 -0
  9. package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
  10. package/src/__tests__/helpers/mock-account-id.ts +6 -6
  11. package/src/__tests__/helpers/mock-bin.ts +4 -1
  12. package/src/__tests__/helpers/mock-cfetch.ts +2 -2
  13. package/src/__tests__/helpers/mock-console.ts +11 -5
  14. package/src/__tests__/helpers/mock-web-socket.ts +29 -0
  15. package/src/__tests__/helpers/run-wrangler.ts +5 -3
  16. package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
  17. package/src/__tests__/index.test.ts +343 -20
  18. package/src/__tests__/jest.setup.ts +21 -1
  19. package/src/__tests__/kv.test.ts +82 -80
  20. package/src/__tests__/package-manager.test.ts +2 -2
  21. package/src/__tests__/parse.test.ts +322 -0
  22. package/src/__tests__/publish.test.ts +1428 -244
  23. package/src/__tests__/r2.test.ts +198 -0
  24. package/src/__tests__/secret.test.ts +176 -60
  25. package/src/__tests__/sentry.test.ts +146 -0
  26. package/src/__tests__/tail.test.ts +564 -0
  27. package/src/api/form_data.ts +106 -23
  28. package/src/api/preview.ts +32 -13
  29. package/src/api/worker.ts +49 -18
  30. package/src/bundle.ts +133 -0
  31. package/src/cfetch/index.ts +8 -6
  32. package/src/cfetch/internal.ts +49 -17
  33. package/src/cli.ts +10 -0
  34. package/src/config/README.md +107 -0
  35. package/src/config/config.ts +265 -0
  36. package/src/config/diagnostics.ts +80 -0
  37. package/src/config/environment.ts +305 -0
  38. package/src/config/index.ts +52 -0
  39. package/src/config/validation-helpers.ts +370 -0
  40. package/src/config/validation.ts +1017 -0
  41. package/src/dev.tsx +338 -211
  42. package/src/entry.ts +57 -0
  43. package/src/environment-variables.ts +33 -0
  44. package/src/guess-worker-format.ts +68 -0
  45. package/src/index.tsx +860 -634
  46. package/src/inspect.ts +16 -3
  47. package/src/kv.tsx +20 -29
  48. package/src/module-collection.ts +141 -34
  49. package/src/open-in-browser.ts +13 -0
  50. package/src/package-manager.ts +21 -15
  51. package/src/pages.tsx +9 -10
  52. package/src/parse.ts +183 -0
  53. package/src/proxy.ts +11 -5
  54. package/src/publish.ts +272 -314
  55. package/src/r2.ts +50 -0
  56. package/src/reporting.ts +115 -0
  57. package/src/sites.tsx +16 -15
  58. package/src/tail/filters.ts +279 -0
  59. package/src/tail/index.ts +299 -0
  60. package/src/tail/printing.ts +62 -0
  61. package/src/user.tsx +74 -44
  62. package/templates/new-worker.js +1 -1
  63. package/templates/new-worker.ts +1 -1
  64. package/templates/tsconfig.json +105 -0
  65. package/wrangler-dist/cli.js +51308 -36440
  66. package/wrangler-dist/cli.js.map +3 -3
  67. package/src/config.ts +0 -641
  68. package/src/tail.tsx +0 -73
@@ -7,12 +7,19 @@ import { mockConsoleMethods } from "./helpers/mock-console";
7
7
  import { mockKeyListRequest } from "./helpers/mock-kv";
8
8
  import { runInTempDir } from "./helpers/run-in-tmp";
9
9
  import { runWrangler } from "./helpers/run-wrangler";
10
+ import writeWranglerToml from "./helpers/write-wrangler-toml";
10
11
  import type { WorkerMetadata } from "../api/form_data";
11
12
  import type { Config } from "../config";
12
13
  import type { KVNamespaceInfo } from "../kv";
13
14
  import type { FormData, File } from "undici";
14
15
 
15
16
  describe("publish", () => {
17
+ beforeEach(() => {
18
+ // @ts-expect-error we're using a very simple setTimeout mock here
19
+ jest.spyOn(global, "setTimeout").mockImplementation((fn, _period) => {
20
+ fn();
21
+ });
22
+ });
16
23
  mockAccountId();
17
24
  mockApiToken();
18
25
  runInTempDir();
@@ -22,6 +29,222 @@ describe("publish", () => {
22
29
  unsetAllMocks();
23
30
  });
24
31
 
32
+ describe("environments", () => {
33
+ it("should use legacy environments by default", async () => {
34
+ writeWranglerToml();
35
+ writeWorkerSource();
36
+ mockSubDomainRequest();
37
+ mockUploadWorkerRequest({
38
+ env: "some-env",
39
+ legacyEnv: true,
40
+ });
41
+ await runWrangler("publish index.js --env some-env");
42
+ expect(std.out).toMatchInlineSnapshot(`
43
+ "Uploaded
44
+ test-name-some-env
45
+ (TIMINGS)
46
+ Published
47
+ test-name-some-env
48
+ (TIMINGS)
49
+
50
+ test-name-some-env.test-sub-domain.workers.dev"
51
+ `);
52
+ expect(std.err).toMatchInlineSnapshot(`""`);
53
+ expect(std.warn).toMatchInlineSnapshot(`""`);
54
+ });
55
+
56
+ describe("legacy", () => {
57
+ it("uses the script name when no environment is specified", async () => {
58
+ writeWranglerToml();
59
+ writeWorkerSource();
60
+ mockSubDomainRequest();
61
+ mockUploadWorkerRequest({
62
+ legacyEnv: true,
63
+ });
64
+ await runWrangler("publish index.js --legacy-env true");
65
+ expect(std.out).toMatchInlineSnapshot(`
66
+ "Uploaded
67
+ test-name
68
+ (TIMINGS)
69
+ Published
70
+ test-name
71
+ (TIMINGS)
72
+
73
+ test-name.test-sub-domain.workers.dev"
74
+ `);
75
+ expect(std.err).toMatchInlineSnapshot(`""`);
76
+ expect(std.warn).toMatchInlineSnapshot(`""`);
77
+ });
78
+
79
+ it("appends the environment name when provided", async () => {
80
+ writeWranglerToml();
81
+ writeWorkerSource();
82
+ mockSubDomainRequest();
83
+ mockUploadWorkerRequest({
84
+ env: "some-env",
85
+ legacyEnv: true,
86
+ });
87
+ await runWrangler("publish index.js --env some-env --legacy-env true");
88
+ expect(std.out).toMatchInlineSnapshot(`
89
+ "Uploaded
90
+ test-name-some-env
91
+ (TIMINGS)
92
+ Published
93
+ test-name-some-env
94
+ (TIMINGS)
95
+
96
+ test-name-some-env.test-sub-domain.workers.dev"
97
+ `);
98
+ expect(std.err).toMatchInlineSnapshot(`""`);
99
+ expect(std.warn).toMatchInlineSnapshot(`""`);
100
+ });
101
+ });
102
+
103
+ describe("services", () => {
104
+ it("uses the script name when no environment is specified", async () => {
105
+ writeWranglerToml();
106
+ writeWorkerSource();
107
+ mockSubDomainRequest();
108
+ mockUploadWorkerRequest({
109
+ legacyEnv: false,
110
+ });
111
+ await runWrangler("publish index.js");
112
+ expect(std.out).toMatchInlineSnapshot(`
113
+ "Uploaded
114
+ test-name
115
+ (TIMINGS)
116
+ Published
117
+ test-name
118
+ (TIMINGS)
119
+
120
+ test-name.test-sub-domain.workers.dev"
121
+ `);
122
+ expect(std.err).toMatchInlineSnapshot(`""`);
123
+ expect(std.warn).toMatchInlineSnapshot(`""`);
124
+ });
125
+
126
+ it("publishes as an environment when provided", async () => {
127
+ writeWranglerToml();
128
+ writeWorkerSource();
129
+ mockSubDomainRequest();
130
+ mockUploadWorkerRequest({
131
+ env: "some-env",
132
+ legacyEnv: false,
133
+ });
134
+ await runWrangler("publish index.js --env some-env --legacy-env false");
135
+ expect(std.out).toMatchInlineSnapshot(`
136
+ "Uploaded
137
+ test-name (some-env)
138
+ (TIMINGS)
139
+ Published
140
+ test-name (some-env)
141
+ (TIMINGS)
142
+
143
+ some-env.test-name.test-sub-domain.workers.dev"
144
+ `);
145
+ expect(std.err).toMatchInlineSnapshot(`""`);
146
+ expect(std.warn).toMatchInlineSnapshot(`""`);
147
+ });
148
+ });
149
+ });
150
+
151
+ it("should resolve wrangler.toml relative to the entrypoint", async () => {
152
+ fs.mkdirSync("./some-path/worker", { recursive: true });
153
+ fs.writeFileSync(
154
+ "./some-path/wrangler.toml",
155
+ TOML.stringify({
156
+ name: "test-name",
157
+ compatibility_date: "2022-01-12",
158
+ vars: { xyz: 123 },
159
+ }),
160
+ "utf-8"
161
+ );
162
+ writeWorkerSource({ basePath: "./some-path/worker" });
163
+ mockUploadWorkerRequest({
164
+ expectedBindings: [
165
+ {
166
+ json: 123,
167
+ name: "xyz",
168
+ type: "json",
169
+ },
170
+ ],
171
+ });
172
+ mockSubDomainRequest();
173
+ await runWrangler("publish ./some-path/worker/index.js");
174
+ expect(std.out).toMatchInlineSnapshot(`
175
+ "Uploaded
176
+ test-name
177
+ (TIMINGS)
178
+ Published
179
+ test-name
180
+ (TIMINGS)
181
+
182
+ test-name.test-sub-domain.workers.dev"
183
+ `);
184
+ expect(std.err).toMatchInlineSnapshot(`""`);
185
+ });
186
+
187
+ describe("routes", () => {
188
+ it("should publish the worker to a route", async () => {
189
+ writeWranglerToml({
190
+ routes: ["example.com/some-route/*"],
191
+ });
192
+ writeWorkerSource();
193
+ mockUpdateWorkerRequest({ enabled: false });
194
+ mockUploadWorkerRequest({ expectedType: "esm" });
195
+ mockPublishRoutesRequest({ routes: ["example.com/some-route/*"] });
196
+ await runWrangler("publish ./index");
197
+ });
198
+
199
+ it("should publish to legacy environment specific routes", async () => {
200
+ writeWranglerToml({
201
+ routes: ["example.com/some-route/*"],
202
+ env: {
203
+ dev: {
204
+ routes: ["dev-example.com/some-route/*"],
205
+ },
206
+ },
207
+ });
208
+ writeWorkerSource();
209
+ mockUpdateWorkerRequest({ enabled: false, legacyEnv: true, env: "dev" });
210
+ mockUploadWorkerRequest({
211
+ expectedType: "esm",
212
+ legacyEnv: true,
213
+ env: "dev",
214
+ });
215
+ mockPublishRoutesRequest({
216
+ routes: ["dev-example.com/some-route/*"],
217
+ legacyEnv: true,
218
+ env: "dev",
219
+ });
220
+ await runWrangler("publish ./index --env dev --legacy-env true");
221
+ });
222
+
223
+ it("services: should publish to service environment specific routes", async () => {
224
+ writeWranglerToml({
225
+ routes: ["example.com/some-route/*"],
226
+ env: {
227
+ dev: {
228
+ routes: ["dev-example.com/some-route/*"],
229
+ },
230
+ },
231
+ });
232
+ writeWorkerSource();
233
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
234
+ mockUploadWorkerRequest({
235
+ expectedType: "esm",
236
+ env: "dev",
237
+ });
238
+ mockPublishRoutesRequest({
239
+ routes: ["dev-example.com/some-route/*"],
240
+ env: "dev",
241
+ });
242
+ await runWrangler("publish ./index --env dev --legacy-env false");
243
+ });
244
+
245
+ it.todo("should error if it's a workers.dev route");
246
+ });
247
+
25
248
  describe("entry-points", () => {
26
249
  it("should be able to use `index` with no extension as the entry-point (esm)", async () => {
27
250
  writeWranglerToml();
@@ -32,17 +255,18 @@ describe("publish", () => {
32
255
  await runWrangler("publish ./index");
33
256
 
34
257
  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
- `);
258
+ "Uploaded
259
+ test-name
260
+ (TIMINGS)
261
+ Published
262
+ test-name
263
+ (TIMINGS)
264
+
265
+ test-name.test-sub-domain.workers.dev"
266
+ `);
44
267
  expect(std.err).toMatchInlineSnapshot(`""`);
45
268
  });
269
+
46
270
  it("should be able to use `index` with no extension as the entry-point (sw)", async () => {
47
271
  writeWranglerToml();
48
272
  writeWorkerSource({ type: "sw" });
@@ -52,20 +276,20 @@ describe("publish", () => {
52
276
  await runWrangler("publish ./index");
53
277
 
54
278
  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
- `);
279
+ "Uploaded
280
+ test-name
281
+ (TIMINGS)
282
+ Published
283
+ test-name
284
+ (TIMINGS)
285
+
286
+ test-name.test-sub-domain.workers.dev"
287
+ `);
64
288
  expect(std.err).toMatchInlineSnapshot(`""`);
65
289
  });
66
290
 
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" } } });
291
+ it("should be able to use the `main` config as the entry-point for ESM sources", async () => {
292
+ writeWranglerToml({ main: "./index.js" });
69
293
  writeWorkerSource();
70
294
  mockUploadWorkerRequest();
71
295
  mockSubDomainRequest();
@@ -73,16 +297,127 @@ describe("publish", () => {
73
297
  await runWrangler("publish");
74
298
 
75
299
  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
- `);
300
+ "Uploaded
301
+ test-name
302
+ (TIMINGS)
303
+ Published
304
+ test-name
305
+ (TIMINGS)
306
+
307
+ test-name.test-sub-domain.workers.dev"
308
+ `);
309
+ expect(std.err).toMatchInlineSnapshot(`""`);
310
+ });
311
+
312
+ it("should use `main` relative to the wrangler.toml not cwd", async () => {
313
+ writeWranglerToml({
314
+ main: "./foo/index.js",
315
+ });
316
+ writeWorkerSource({ basePath: "foo" });
317
+ mockUploadWorkerRequest({ expectedEntry: "var foo = 100;" });
318
+ mockSubDomainRequest();
319
+ process.chdir("foo");
320
+ await runWrangler("publish");
321
+
322
+ expect(std.out).toMatchInlineSnapshot(`
323
+ "Uploaded
324
+ test-name
325
+ (TIMINGS)
326
+ Published
327
+ test-name
328
+ (TIMINGS)
329
+
330
+ test-name.test-sub-domain.workers.dev"
331
+ `);
332
+ expect(std.err).toMatchInlineSnapshot(`""`);
333
+ });
334
+
335
+ it('should use `build.upload.main` as an entry point, where `build.upload.dir` defaults to "./dist", and log a deprecation warning', async () => {
336
+ writeWranglerToml({ build: { upload: { main: "./index.js" } } });
337
+ writeWorkerSource({ basePath: "./dist" });
338
+ mockUploadWorkerRequest();
339
+ mockSubDomainRequest();
340
+
341
+ await runWrangler("publish");
342
+
343
+ expect(std.out).toMatchInlineSnapshot(`
344
+ "Uploaded
345
+ test-name
346
+ (TIMINGS)
347
+ Published
348
+ test-name
349
+ (TIMINGS)
350
+
351
+ test-name.test-sub-domain.workers.dev"
352
+ `);
353
+ expect(std.err).toMatchInlineSnapshot(`""`);
354
+ expect(std.warn).toMatchInlineSnapshot(`
355
+ "Processing wrangler.toml configuration:
356
+ - DEPRECATION: \\"build.upload.main\\":
357
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
358
+ Then add the top level \`main\` field to your configuration file:
359
+ \`\`\`
360
+ main = \\"dist/index.js\\"
361
+ \`\`\`"
362
+ `);
363
+ });
364
+
365
+ it("should use `build.upload.main` relative to `build.upload.dir`", async () => {
366
+ writeWranglerToml({
367
+ build: {
368
+ upload: {
369
+ main: "./index.js",
370
+ dir: "./foo",
371
+ },
372
+ },
373
+ });
374
+ writeWorkerSource({ basePath: "./foo" });
375
+ mockUploadWorkerRequest({ expectedEntry: "var foo = 100;" });
376
+ mockSubDomainRequest();
377
+ process.chdir("foo");
378
+ await runWrangler("publish");
379
+
380
+ expect(std.out).toMatchInlineSnapshot(`
381
+ "Uploaded
382
+ test-name
383
+ (TIMINGS)
384
+ Published
385
+ test-name
386
+ (TIMINGS)
387
+
388
+ test-name.test-sub-domain.workers.dev"
389
+ `);
85
390
  expect(std.err).toMatchInlineSnapshot(`""`);
391
+ expect(std.warn).toMatchInlineSnapshot(`
392
+ "Processing ../wrangler.toml configuration:
393
+ - DEPRECATION: \\"build.upload.main\\":
394
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
395
+ Then add the top level \`main\` field to your configuration file:
396
+ \`\`\`
397
+ main = \\"foo/index.js\\"
398
+ \`\`\`
399
+ - DEPRECATION: \\"build.upload.dir\\":
400
+ Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker."
401
+ `);
402
+ });
403
+
404
+ it("should error when both `main` and `build.upload.main` are used", async () => {
405
+ writeWranglerToml({
406
+ main: "./index.js",
407
+ build: {
408
+ upload: {
409
+ main: "./index.js",
410
+ dir: "./foo",
411
+ },
412
+ },
413
+ });
414
+ await expect(runWrangler("publish")).rejects
415
+ .toThrowErrorMatchingInlineSnapshot(`
416
+ "Processing wrangler.toml configuration:
417
+ - Don't define both the \`main\` and \`build.upload.main\` fields in your configuration.
418
+ They serve the same purpose: to point to the entry-point of your worker.
419
+ Delete the \`build.upload.main\` and \`build.upload.dir\` field from your config."
420
+ `);
86
421
  });
87
422
 
88
423
  it("should be able to transpile TypeScript (esm)", async () => {
@@ -93,15 +428,15 @@ describe("publish", () => {
93
428
  await runWrangler("publish index.ts");
94
429
 
95
430
  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
- `);
431
+ "Uploaded
432
+ test-name
433
+ (TIMINGS)
434
+ Published
435
+ test-name
436
+ (TIMINGS)
437
+
438
+ test-name.test-sub-domain.workers.dev"
439
+ `);
105
440
  expect(std.err).toMatchInlineSnapshot(`""`);
106
441
  });
107
442
 
@@ -116,19 +451,19 @@ describe("publish", () => {
116
451
  await runWrangler("publish index.ts");
117
452
 
118
453
  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
- `);
454
+ "Uploaded
455
+ test-name
456
+ (TIMINGS)
457
+ Published
458
+ test-name
459
+ (TIMINGS)
460
+
461
+ test-name.test-sub-domain.workers.dev"
462
+ `);
128
463
  expect(std.err).toMatchInlineSnapshot(`""`);
129
464
  });
130
465
 
131
- it("should inline referenced text modules into the worker", async () => {
466
+ it("should add referenced text modules into the form upload", async () => {
132
467
  writeWranglerToml();
133
468
  fs.writeFileSync(
134
469
  "./index.js",
@@ -142,17 +477,22 @@ export default{
142
477
  `
143
478
  );
144
479
  fs.writeFileSync("./textfile.txt", "Hello, World!");
145
- mockUploadWorkerRequest({ expectedEntry: "Hello, World!" });
480
+ mockUploadWorkerRequest({
481
+ expectedModules: {
482
+ "./0a0a9f2a6772942557ab5355d76af442f8f65e01-textfile.txt":
483
+ "Hello, World!",
484
+ },
485
+ });
146
486
  mockSubDomainRequest();
147
487
  await runWrangler("publish index.js");
148
488
  expect(std.out).toMatchInlineSnapshot(`
149
489
  "Uploaded
150
490
  test-name
151
491
  (TIMINGS)
152
- Deployed
492
+ Published
153
493
  test-name
154
494
  (TIMINGS)
155
-
495
+
156
496
  test-name.test-sub-domain.workers.dev"
157
497
  `);
158
498
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -167,15 +507,15 @@ export default{
167
507
  await runWrangler("publish ./src/index.js");
168
508
 
169
509
  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
- `);
510
+ "Uploaded
511
+ test-name
512
+ (TIMINGS)
513
+ Published
514
+ test-name
515
+ (TIMINGS)
516
+
517
+ test-name.test-sub-domain.workers.dev"
518
+ `);
179
519
  expect(std.err).toMatchInlineSnapshot(`""`);
180
520
  });
181
521
 
@@ -191,47 +531,43 @@ export default{
191
531
  await runWrangler("publish ./src/index.js");
192
532
 
193
533
  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
- `);
534
+ "Uploaded
535
+ test-name
536
+ (TIMINGS)
537
+ Published
538
+ test-name
539
+ (TIMINGS)
540
+
541
+ test-name.test-sub-domain.workers.dev"
542
+ `);
203
543
  expect(std.err).toMatchInlineSnapshot(`""`);
204
544
  });
205
545
 
206
546
  it('should error if a site definition doesn\'t have a "bucket" field', async () => {
207
547
  writeWranglerToml({
208
- // @ts-expect-error we're purposely missing the required `site.bucket` field
209
548
  site: {
210
549
  "entry-point": "./index.js",
211
- },
550
+ } as Config["site"],
212
551
  });
213
552
  writeWorkerSource();
214
553
  mockUploadWorkerRequest();
215
554
  mockSubDomainRequest();
216
555
 
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
- );
556
+ await expect(runWrangler("publish ./index.js")).rejects
557
+ .toThrowErrorMatchingInlineSnapshot(`
558
+ "Processing wrangler.toml configuration:
559
+ - ERROR: \\"site.bucket\\" is a required field."
560
+ `);
222
561
 
223
562
  expect(std.out).toMatchInlineSnapshot(`""`);
224
563
  expect(std.err).toMatchInlineSnapshot(`
225
- "A [site] definition requires a \`bucket\` field with a path to the site's public directory.
564
+ "Processing wrangler.toml configuration:
565
+ - ERROR: \\"site.bucket\\" is a required field.
226
566
 
227
567
  %s
228
568
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
229
569
  `);
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."
234
- `);
570
+ expect(std.warn).toMatchInlineSnapshot(`""`);
235
571
  });
236
572
 
237
573
  it("should warn if there is a `site.entry-point` configuration", async () => {
@@ -268,16 +604,16 @@ export default{
268
604
  Uploaded
269
605
  test-name
270
606
  (TIMINGS)
271
- Deployed
607
+ Published
272
608
  test-name
273
609
  (TIMINGS)
274
-
610
+
275
611
  test-name.test-sub-domain.workers.dev"
276
612
  `);
277
613
  expect(std.err).toMatchInlineSnapshot(`""`);
278
614
  expect(std.warn).toMatchInlineSnapshot(`
279
615
  "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.
616
+ The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`main\` config field.
281
617
  Please remove the \`site.entry-point\` field from the \`wrangler.toml\` file."
282
618
  `);
283
619
  });
@@ -290,12 +626,12 @@ export default{
290
626
  await expect(
291
627
  runWrangler("publish")
292
628
  ).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."`
629
+ `"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
630
  );
295
631
 
296
632
  expect(std.out).toMatchInlineSnapshot(`""`);
297
633
  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.
634
+ "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
635
 
300
636
  %s
301
637
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
@@ -314,7 +650,7 @@ export default{
314
650
  id: "__test-name-workers_sites_assets-id",
315
651
  };
316
652
  writeWranglerToml({
317
- build: { upload: { main: "./index.js" } },
653
+ main: "./index.js",
318
654
  site: {
319
655
  bucket: "assets",
320
656
  },
@@ -336,16 +672,16 @@ export default{
336
672
  Uploaded
337
673
  test-name
338
674
  (TIMINGS)
339
- Deployed
675
+ Published
340
676
  test-name
341
677
  (TIMINGS)
342
-
678
+
343
679
  test-name.test-sub-domain.workers.dev"
344
680
  `);
345
681
  expect(std.err).toMatchInlineSnapshot(`""`);
346
682
  });
347
683
 
348
- it("when using a service worker type, it should inline an asset manifest, and bind to a namespace", async () => {
684
+ it("when using a service worker type, it should add an asset manifest as a text_blob, and bind to a namespace", async () => {
349
685
  const assets = [
350
686
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
351
687
  { filePath: "assets/file-2.txt", content: "Content of file-2" },
@@ -355,7 +691,7 @@ export default{
355
691
  id: "__test-name-workers_sites_assets-id",
356
692
  };
357
693
  writeWranglerToml({
358
- build: { upload: { main: "./index.js" } },
694
+ main: "./index.js",
359
695
  site: {
360
696
  bucket: "assets",
361
697
  },
@@ -364,13 +700,21 @@ export default{
364
700
  writeAssets(assets);
365
701
  mockUploadWorkerRequest({
366
702
  expectedType: "sw",
367
- expectedEntry: `const __STATIC_CONTENT_MANIFEST = {"file-1.txt":"assets/file-1.2ca234f380.txt","file-2.txt":"assets/file-2.5938485188.txt"};`,
703
+ expectedModules: {
704
+ __STATIC_CONTENT_MANIFEST:
705
+ '{"file-1.txt":"assets/file-1.2ca234f380.txt","file-2.txt":"assets/file-2.5938485188.txt"}',
706
+ },
368
707
  expectedBindings: [
369
708
  {
370
709
  name: "__STATIC_CONTENT",
371
710
  namespace_id: "__test-name-workers_sites_assets-id",
372
711
  type: "kv_namespace",
373
712
  },
713
+ {
714
+ name: "__STATIC_CONTENT_MANIFEST",
715
+ part: "__STATIC_CONTENT_MANIFEST",
716
+ type: "text_blob",
717
+ },
374
718
  ],
375
719
  });
376
720
  mockSubDomainRequest();
@@ -388,10 +732,10 @@ export default{
388
732
  Uploaded
389
733
  test-name
390
734
  (TIMINGS)
391
- Deployed
735
+ Published
392
736
  test-name
393
737
  (TIMINGS)
394
-
738
+
395
739
  test-name.test-sub-domain.workers.dev"
396
740
  `);
397
741
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -407,7 +751,7 @@ export default{
407
751
  id: "__test-name-workers_sites_assets-id",
408
752
  };
409
753
  writeWranglerToml({
410
- build: { upload: { main: "./index.js" } },
754
+ main: "./index.js",
411
755
  site: {
412
756
  bucket: "assets",
413
757
  },
@@ -442,16 +786,16 @@ export default{
442
786
  Uploaded
443
787
  test-name
444
788
  (TIMINGS)
445
- Deployed
789
+ Published
446
790
  test-name
447
791
  (TIMINGS)
448
-
792
+
449
793
  test-name.test-sub-domain.workers.dev"
450
794
  `);
451
795
  expect(std.err).toMatchInlineSnapshot(`""`);
452
796
  });
453
797
 
454
- it("should make environment specific kv namespace for assets", async () => {
798
+ it("should make environment specific kv namespace for assets, even for service envs", async () => {
455
799
  // This is the same test as the one before this, but with an env arg
456
800
  const assets = [
457
801
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
@@ -462,7 +806,7 @@ export default{
462
806
  id: "__test-name-some-env-workers_sites_assets-id",
463
807
  };
464
808
  writeWranglerToml({
465
- build: { upload: { main: "./index.js" } },
809
+ main: "./index.js",
466
810
  site: {
467
811
  bucket: "assets",
468
812
  },
@@ -483,7 +827,7 @@ export default{
483
827
  mockListKVNamespacesRequest(kvNamespace);
484
828
  mockKeyListRequest(kvNamespace.id, []);
485
829
  mockUploadAssetsToKVRequest(kvNamespace.id, assets);
486
- await runWrangler("publish --env some-env");
830
+ await runWrangler("publish --env some-env --legacy-env false");
487
831
 
488
832
  expect(std.out).toMatchInlineSnapshot(`
489
833
  "reading assets/file-1.txt...
@@ -493,15 +837,67 @@ export default{
493
837
  Uploaded
494
838
  test-name (some-env)
495
839
  (TIMINGS)
496
- Deployed
840
+ Published
497
841
  test-name (some-env)
498
842
  (TIMINGS)
499
-
843
+
500
844
  some-env.test-name.test-sub-domain.workers.dev"
501
845
  `);
502
846
  expect(std.err).toMatchInlineSnapshot(`""`);
503
847
  });
504
848
 
849
+ it("should make environment specific kv namespace for assets, even for legacy envs", async () => {
850
+ // And this is the same test as the one before this, but with legacyEnv:true
851
+ const assets = [
852
+ { filePath: "assets/file-1.txt", content: "Content of file-1" },
853
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
854
+ ];
855
+ const kvNamespace = {
856
+ title: "__test-name-some-env-workers_sites_assets",
857
+ id: "__test-name-some-env-workers_sites_assets-id",
858
+ };
859
+ writeWranglerToml({
860
+ main: "./index.js",
861
+ site: {
862
+ bucket: "assets",
863
+ },
864
+ });
865
+ writeWorkerSource();
866
+ writeAssets(assets);
867
+ mockUploadWorkerRequest({
868
+ legacyEnv: true,
869
+ env: "some-env",
870
+ expectedBindings: [
871
+ {
872
+ name: "__STATIC_CONTENT",
873
+ namespace_id: "__test-name-some-env-workers_sites_assets-id",
874
+ type: "kv_namespace",
875
+ },
876
+ ],
877
+ });
878
+ mockSubDomainRequest();
879
+ mockListKVNamespacesRequest(kvNamespace);
880
+ mockKeyListRequest(kvNamespace.id, []);
881
+ mockUploadAssetsToKVRequest(kvNamespace.id, assets);
882
+ await runWrangler("publish --env some-env --legacy-env true");
883
+
884
+ expect(std.out).toMatchInlineSnapshot(`
885
+ "reading assets/file-1.txt...
886
+ uploading as assets/file-1.2ca234f380.txt...
887
+ reading assets/file-2.txt...
888
+ uploading as assets/file-2.5938485188.txt...
889
+ Uploaded
890
+ test-name-some-env
891
+ (TIMINGS)
892
+ Published
893
+ test-name-some-env
894
+ (TIMINGS)
895
+
896
+ test-name-some-env.test-sub-domain.workers.dev"
897
+ `);
898
+ expect(std.err).toMatchInlineSnapshot(`""`);
899
+ });
900
+
505
901
  it("should only upload files that are not already in the KV namespace", async () => {
506
902
  const assets = [
507
903
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
@@ -512,7 +908,7 @@ export default{
512
908
  id: "__test-name-workers_sites_assets-id",
513
909
  };
514
910
  writeWranglerToml({
515
- build: { upload: { main: "./index.js" } },
911
+ main: "./index.js",
516
912
  site: {
517
913
  bucket: "assets",
518
914
  },
@@ -539,10 +935,10 @@ export default{
539
935
  Uploaded
540
936
  test-name
541
937
  (TIMINGS)
542
- Deployed
938
+ Published
543
939
  test-name
544
940
  (TIMINGS)
545
-
941
+
546
942
  test-name.test-sub-domain.workers.dev"
547
943
  `);
548
944
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -558,7 +954,7 @@ export default{
558
954
  id: "__test-name-workers_sites_assets-id",
559
955
  };
560
956
  writeWranglerToml({
561
- build: { upload: { main: "./index.js" } },
957
+ main: "./index.js",
562
958
  site: {
563
959
  bucket: "assets",
564
960
  },
@@ -577,17 +973,17 @@ export default{
577
973
  await runWrangler("publish --site-include file-1.txt");
578
974
 
579
975
  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
- `);
976
+ "reading assets/file-1.txt...
977
+ uploading as assets/file-1.2ca234f380.txt...
978
+ Uploaded
979
+ test-name
980
+ (TIMINGS)
981
+ Published
982
+ test-name
983
+ (TIMINGS)
984
+
985
+ test-name.test-sub-domain.workers.dev"
986
+ `);
591
987
  expect(std.err).toMatchInlineSnapshot(`""`);
592
988
  });
593
989
 
@@ -601,7 +997,7 @@ export default{
601
997
  id: "__test-name-workers_sites_assets-id",
602
998
  };
603
999
  writeWranglerToml({
604
- build: { upload: { main: "./index.js" } },
1000
+ main: "./index.js",
605
1001
  site: {
606
1002
  bucket: "assets",
607
1003
  },
@@ -620,17 +1016,17 @@ export default{
620
1016
  await runWrangler("publish --site-exclude file-2.txt");
621
1017
 
622
1018
  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
- `);
1019
+ "reading assets/file-1.txt...
1020
+ uploading as assets/file-1.2ca234f380.txt...
1021
+ Uploaded
1022
+ test-name
1023
+ (TIMINGS)
1024
+ Published
1025
+ test-name
1026
+ (TIMINGS)
1027
+
1028
+ test-name.test-sub-domain.workers.dev"
1029
+ `);
634
1030
  expect(std.err).toMatchInlineSnapshot(`""`);
635
1031
  });
636
1032
 
@@ -644,7 +1040,7 @@ export default{
644
1040
  id: "__test-name-workers_sites_assets-id",
645
1041
  };
646
1042
  writeWranglerToml({
647
- build: { upload: { main: "./index.js" } },
1043
+ main: "./index.js",
648
1044
  site: {
649
1045
  bucket: "assets",
650
1046
  include: ["file-1.txt"],
@@ -664,17 +1060,17 @@ export default{
664
1060
  await runWrangler("publish");
665
1061
 
666
1062
  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
- `);
1063
+ "reading assets/file-1.txt...
1064
+ uploading as assets/file-1.2ca234f380.txt...
1065
+ Uploaded
1066
+ test-name
1067
+ (TIMINGS)
1068
+ Published
1069
+ test-name
1070
+ (TIMINGS)
1071
+
1072
+ test-name.test-sub-domain.workers.dev"
1073
+ `);
678
1074
  expect(std.err).toMatchInlineSnapshot(`""`);
679
1075
  });
680
1076
 
@@ -688,7 +1084,7 @@ export default{
688
1084
  id: "__test-name-workers_sites_assets-id",
689
1085
  };
690
1086
  writeWranglerToml({
691
- build: { upload: { main: "./index.js" } },
1087
+ main: "./index.js",
692
1088
  site: {
693
1089
  bucket: "assets",
694
1090
  exclude: ["file-2.txt"],
@@ -708,17 +1104,17 @@ export default{
708
1104
  await runWrangler("publish");
709
1105
 
710
1106
  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
- `);
1107
+ "reading assets/file-1.txt...
1108
+ uploading as assets/file-1.2ca234f380.txt...
1109
+ Uploaded
1110
+ test-name
1111
+ (TIMINGS)
1112
+ Published
1113
+ test-name
1114
+ (TIMINGS)
1115
+
1116
+ test-name.test-sub-domain.workers.dev"
1117
+ `);
722
1118
  expect(std.err).toMatchInlineSnapshot(`""`);
723
1119
  });
724
1120
 
@@ -732,7 +1128,7 @@ export default{
732
1128
  id: "__test-name-workers_sites_assets-id",
733
1129
  };
734
1130
  writeWranglerToml({
735
- build: { upload: { main: "./index.js" } },
1131
+ main: "./index.js",
736
1132
  site: {
737
1133
  bucket: "assets",
738
1134
  include: ["file-2.txt"],
@@ -752,17 +1148,17 @@ export default{
752
1148
  await runWrangler("publish --site-include file-1.txt");
753
1149
 
754
1150
  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
- `);
1151
+ "reading assets/file-1.txt...
1152
+ uploading as assets/file-1.2ca234f380.txt...
1153
+ Uploaded
1154
+ test-name
1155
+ (TIMINGS)
1156
+ Published
1157
+ test-name
1158
+ (TIMINGS)
1159
+
1160
+ test-name.test-sub-domain.workers.dev"
1161
+ `);
766
1162
  expect(std.err).toMatchInlineSnapshot(`""`);
767
1163
  });
768
1164
 
@@ -776,7 +1172,7 @@ export default{
776
1172
  id: "__test-name-workers_sites_assets-id",
777
1173
  };
778
1174
  writeWranglerToml({
779
- build: { upload: { main: "./index.js" } },
1175
+ main: "./index.js",
780
1176
  site: {
781
1177
  bucket: "assets",
782
1178
  exclude: ["assets/file-1.txt"],
@@ -796,17 +1192,17 @@ export default{
796
1192
  await runWrangler("publish --site-exclude file-2.txt");
797
1193
 
798
1194
  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
- `);
1195
+ "reading assets/file-1.txt...
1196
+ uploading as assets/file-1.2ca234f380.txt...
1197
+ Uploaded
1198
+ test-name
1199
+ (TIMINGS)
1200
+ Published
1201
+ test-name
1202
+ (TIMINGS)
1203
+
1204
+ test-name.test-sub-domain.workers.dev"
1205
+ `);
810
1206
  expect(std.err).toMatchInlineSnapshot(`""`);
811
1207
  });
812
1208
 
@@ -826,7 +1222,7 @@ export default{
826
1222
  id: "__test-name-workers_sites_assets-id",
827
1223
  };
828
1224
  writeWranglerToml({
829
- build: { upload: { main: "./index.js" } },
1225
+ main: "./index.js",
830
1226
  site: {
831
1227
  bucket: "assets",
832
1228
  },
@@ -847,10 +1243,10 @@ export default{
847
1243
  Uploaded
848
1244
  test-name
849
1245
  (TIMINGS)
850
- Deployed
1246
+ Published
851
1247
  test-name
852
1248
  (TIMINGS)
853
-
1249
+
854
1250
  test-name.test-sub-domain.workers.dev"
855
1251
  `);
856
1252
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -876,7 +1272,7 @@ export default{
876
1272
  id: "__test-name-workers_sites_assets-id",
877
1273
  };
878
1274
  writeWranglerToml({
879
- build: { upload: { main: "./index.js" } },
1275
+ main: "./index.js",
880
1276
  site: {
881
1277
  bucket: "assets",
882
1278
  },
@@ -897,10 +1293,10 @@ export default{
897
1293
  Uploaded
898
1294
  test-name
899
1295
  (TIMINGS)
900
- Deployed
1296
+ Published
901
1297
  test-name
902
1298
  (TIMINGS)
903
-
1299
+
904
1300
  test-name.test-sub-domain.workers.dev"
905
1301
  `);
906
1302
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -923,7 +1319,7 @@ export default{
923
1319
  id: "__test-name-workers_sites_assets-id",
924
1320
  };
925
1321
  writeWranglerToml({
926
- build: { upload: { main: "./index.js" } },
1322
+ main: "./index.js",
927
1323
  site: {
928
1324
  bucket: "assets",
929
1325
  exclude: ["assets/file-1.txt"],
@@ -964,7 +1360,7 @@ export default{
964
1360
  id: "__test-name-workers_sites_assets-id",
965
1361
  };
966
1362
  writeWranglerToml({
967
- build: { upload: { main: "./index.js" } },
1363
+ main: "./index.js",
968
1364
  site: {
969
1365
  bucket: "assets",
970
1366
  },
@@ -994,7 +1390,124 @@ export default{
994
1390
  });
995
1391
  });
996
1392
 
1393
+ describe("workers_dev setting", () => {
1394
+ it("should publish to a workers.dev domain if workers_dev is undefined", async () => {
1395
+ writeWranglerToml();
1396
+ writeWorkerSource();
1397
+ mockUploadWorkerRequest();
1398
+ mockSubDomainRequest();
1399
+
1400
+ await runWrangler("publish ./index");
1401
+
1402
+ expect(std.out).toMatchInlineSnapshot(`
1403
+ "Uploaded
1404
+ test-name
1405
+ (TIMINGS)
1406
+ Published
1407
+ test-name
1408
+ (TIMINGS)
1409
+
1410
+ test-name.test-sub-domain.workers.dev"
1411
+ `);
1412
+ expect(std.err).toMatchInlineSnapshot(`""`);
1413
+ });
1414
+
1415
+ it("should publish to the workers.dev domain if workers_dev is `true`", async () => {
1416
+ writeWranglerToml({
1417
+ workers_dev: true,
1418
+ });
1419
+ writeWorkerSource();
1420
+ mockUploadWorkerRequest();
1421
+ mockSubDomainRequest();
1422
+
1423
+ await runWrangler("publish ./index");
1424
+
1425
+ expect(std.out).toMatchInlineSnapshot(`
1426
+ "Uploaded
1427
+ test-name
1428
+ (TIMINGS)
1429
+ Published
1430
+ test-name
1431
+ (TIMINGS)
1432
+
1433
+ test-name.test-sub-domain.workers.dev"
1434
+ `);
1435
+ expect(std.err).toMatchInlineSnapshot(`""`);
1436
+ });
1437
+
1438
+ it("should disable the workers.dev domain if workers_dev is `false`", async () => {
1439
+ writeWranglerToml({
1440
+ workers_dev: false,
1441
+ });
1442
+ writeWorkerSource();
1443
+ mockUploadWorkerRequest();
1444
+ mockSubDomainRequest();
1445
+ mockUpdateWorkerRequest({ enabled: false });
1446
+
1447
+ await runWrangler("publish ./index");
1448
+
1449
+ expect(std.out).toMatchInlineSnapshot(`
1450
+ "Uploaded
1451
+ test-name
1452
+ (TIMINGS)
1453
+ No publish targets for
1454
+ test-name
1455
+ (TIMINGS)"
1456
+ `);
1457
+ expect(std.err).toMatchInlineSnapshot(`""`);
1458
+ });
1459
+
1460
+ it("should enable the workers.dev domain if workers_dev is undefined and subdomain is not already available", async () => {
1461
+ writeWranglerToml();
1462
+ writeWorkerSource();
1463
+ mockUploadWorkerRequest({ available_on_subdomain: false });
1464
+ mockSubDomainRequest();
1465
+ mockUpdateWorkerRequest({ enabled: true });
1466
+
1467
+ await runWrangler("publish ./index");
1468
+
1469
+ expect(std.out).toMatchInlineSnapshot(`
1470
+ "Uploaded
1471
+ test-name
1472
+ (TIMINGS)
1473
+ Published
1474
+ test-name
1475
+ (TIMINGS)
1476
+
1477
+ test-name.test-sub-domain.workers.dev"
1478
+ `);
1479
+ expect(std.err).toMatchInlineSnapshot(`""`);
1480
+ });
1481
+
1482
+ it("should enable the workers.dev domain if workers_dev is true and subdomain is not already available", async () => {
1483
+ writeWranglerToml({ workers_dev: true });
1484
+ writeWorkerSource();
1485
+ mockUploadWorkerRequest({ available_on_subdomain: false });
1486
+ mockSubDomainRequest();
1487
+ mockUpdateWorkerRequest({ enabled: true });
1488
+
1489
+ await runWrangler("publish ./index");
1490
+
1491
+ expect(std.out).toMatchInlineSnapshot(`
1492
+ "Uploaded
1493
+ test-name
1494
+ (TIMINGS)
1495
+ Published
1496
+ test-name
1497
+ (TIMINGS)
1498
+
1499
+ test-name.test-sub-domain.workers.dev"
1500
+ `);
1501
+ expect(std.err).toMatchInlineSnapshot(`""`);
1502
+ });
1503
+ });
1504
+
997
1505
  describe("custom builds", () => {
1506
+ beforeEach(() => {
1507
+ // @ts-expect-error disable the mock we'd setup earlier
1508
+ // or else custom builds will timeout immediately
1509
+ global.setTimeout.mockRestore();
1510
+ });
998
1511
  it("should run a custom build before publishing", async () => {
999
1512
  writeWranglerToml({
1000
1513
  build: {
@@ -1014,10 +1527,10 @@ export default{
1014
1527
  Uploaded
1015
1528
  test-name
1016
1529
  (TIMINGS)
1017
- Deployed
1530
+ Published
1018
1531
  test-name
1019
1532
  (TIMINGS)
1020
-
1533
+
1021
1534
  test-name.test-sub-domain.workers.dev"
1022
1535
  `);
1023
1536
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -1044,10 +1557,10 @@ export default{
1044
1557
  Uploaded
1045
1558
  test-name
1046
1559
  (TIMINGS)
1047
- Deployed
1560
+ Published
1048
1561
  test-name
1049
1562
  (TIMINGS)
1050
-
1563
+
1051
1564
  test-name.test-sub-domain.workers.dev"
1052
1565
  `);
1053
1566
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -1055,56 +1568,657 @@ export default{
1055
1568
  });
1056
1569
  }
1057
1570
  });
1058
- });
1059
-
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
1571
 
1077
- /** Write a mock Worker script to disk. */
1078
- function writeWorkerSource({
1079
- basePath = ".",
1080
- format = "js",
1081
- type = "esm",
1082
- }: {
1083
- basePath?: string;
1084
- format?: "js" | "ts" | "jsx" | "tsx" | "mjs";
1085
- type?: "esm" | "sw";
1086
- } = {}) {
1087
- if (basePath !== ".") {
1088
- fs.mkdirSync(basePath, { recursive: true });
1089
- }
1090
- fs.writeFileSync(
1091
- `${basePath}/index.${format}`,
1092
- type === "esm"
1093
- ? `import { foo } from "./another";
1094
- export default {
1095
- async fetch(request) {
1096
- return new Response('Hello' + foo);
1572
+ describe("[wasm_modules]", () => {
1573
+ it("should be able to define wasm modules for service-worker format workers", async () => {
1574
+ writeWranglerToml({
1575
+ wasm_modules: {
1576
+ TESTWASMNAME: "./path/to/test.wasm",
1097
1577
  },
1098
- };`
1099
- : `import { foo } from "./another";
1100
- addEventListener('fetch', event => {
1101
- event.respondWith(new Response('Hello' + foo));
1102
- })`
1103
- );
1104
- fs.writeFileSync(`${basePath}/another.${format}`, `export const foo = 100;`);
1105
- }
1578
+ });
1579
+ writeWorkerSource({ type: "sw" });
1580
+ fs.mkdirSync("./path/to", { recursive: true });
1581
+ fs.writeFileSync("./path/to/test.wasm", "SOME WASM CONTENT");
1582
+ mockUploadWorkerRequest({
1583
+ expectedType: "sw",
1584
+ expectedModules: { TESTWASMNAME: "SOME WASM CONTENT" },
1585
+ expectedBindings: [
1586
+ { name: "TESTWASMNAME", part: "TESTWASMNAME", type: "wasm_module" },
1587
+ ],
1588
+ });
1589
+ mockSubDomainRequest();
1590
+ await runWrangler("publish index.js");
1591
+ expect(std.out).toMatchInlineSnapshot(`
1592
+ "Uploaded
1593
+ test-name
1594
+ (TIMINGS)
1595
+ Published
1596
+ test-name
1597
+ (TIMINGS)
1106
1598
 
1107
- /** Write mock assets to the file system so they can be uploaded. */
1599
+ test-name.test-sub-domain.workers.dev"
1600
+ `);
1601
+ expect(std.err).toMatchInlineSnapshot(`""`);
1602
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1603
+ });
1604
+
1605
+ it("should error when defining wasm modules for modules format workers", async () => {
1606
+ writeWranglerToml({
1607
+ wasm_modules: {
1608
+ TESTWASMNAME: "./path/to/test.wasm",
1609
+ },
1610
+ });
1611
+ writeWorkerSource({ type: "esm" });
1612
+ fs.mkdirSync("./path/to", { recursive: true });
1613
+ fs.writeFileSync("./path/to/test.wasm", "SOME WASM CONTENT");
1614
+
1615
+ await expect(
1616
+ runWrangler("publish index.js")
1617
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1618
+ `"You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code"`
1619
+ );
1620
+ expect(std.out).toMatchInlineSnapshot(`""`);
1621
+ expect(std.err).toMatchInlineSnapshot(`
1622
+ "You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code
1623
+
1624
+ %s
1625
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1626
+ `);
1627
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1628
+ });
1629
+
1630
+ it("should resolve wasm modules relative to the wrangler.toml file", async () => {
1631
+ fs.mkdirSync("./path/to/and/the/path/to/", { recursive: true });
1632
+ fs.writeFileSync(
1633
+ "./path/to/wrangler.toml",
1634
+ TOML.stringify({
1635
+ compatibility_date: "2022-01-12",
1636
+ name: "test-name",
1637
+ wasm_modules: {
1638
+ TESTWASMNAME: "./and/the/path/to/test.wasm",
1639
+ },
1640
+ }),
1641
+
1642
+ "utf-8"
1643
+ );
1644
+
1645
+ writeWorkerSource({ type: "sw" });
1646
+ fs.writeFileSync(
1647
+ "./path/to/and/the/path/to/test.wasm",
1648
+ "SOME WASM CONTENT"
1649
+ );
1650
+ mockUploadWorkerRequest({
1651
+ expectedType: "sw",
1652
+ expectedModules: { TESTWASMNAME: "SOME WASM CONTENT" },
1653
+ expectedBindings: [
1654
+ { name: "TESTWASMNAME", part: "TESTWASMNAME", type: "wasm_module" },
1655
+ ],
1656
+ });
1657
+ mockSubDomainRequest();
1658
+ await runWrangler("publish index.js --config ./path/to/wrangler.toml");
1659
+ expect(std.out).toMatchInlineSnapshot(`
1660
+ "Uploaded
1661
+ test-name
1662
+ (TIMINGS)
1663
+ Published
1664
+ test-name
1665
+ (TIMINGS)
1666
+
1667
+ test-name.test-sub-domain.workers.dev"
1668
+ `);
1669
+ expect(std.err).toMatchInlineSnapshot(`""`);
1670
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1671
+ });
1672
+
1673
+ it("should be able to import .wasm modules from service-worker format workers", async () => {
1674
+ writeWranglerToml();
1675
+ fs.writeFileSync("./index.js", "import TESTWASMNAME from './test.wasm';");
1676
+ fs.writeFileSync("./test.wasm", "SOME WASM CONTENT");
1677
+ mockUploadWorkerRequest({
1678
+ expectedType: "sw",
1679
+ expectedModules: {
1680
+ __94b240d0d692281e6467aa42043986e5c7eea034_test_wasm:
1681
+ "SOME WASM CONTENT",
1682
+ },
1683
+ expectedBindings: [
1684
+ {
1685
+ name: "__94b240d0d692281e6467aa42043986e5c7eea034_test_wasm",
1686
+ part: "__94b240d0d692281e6467aa42043986e5c7eea034_test_wasm",
1687
+ type: "wasm_module",
1688
+ },
1689
+ ],
1690
+ });
1691
+ mockSubDomainRequest();
1692
+ await runWrangler("publish index.js");
1693
+ expect(std.out).toMatchInlineSnapshot(`
1694
+ "Uploaded
1695
+ test-name
1696
+ (TIMINGS)
1697
+ Published
1698
+ test-name
1699
+ (TIMINGS)
1700
+
1701
+ test-name.test-sub-domain.workers.dev"
1702
+ `);
1703
+ expect(std.err).toMatchInlineSnapshot(`""`);
1704
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1705
+ });
1706
+ });
1707
+
1708
+ describe("[text_blobs]", () => {
1709
+ it("should be able to define text blobs for service-worker format workers", async () => {
1710
+ writeWranglerToml({
1711
+ text_blobs: {
1712
+ TESTTEXTBLOBNAME: "./path/to/text.file",
1713
+ },
1714
+ });
1715
+ writeWorkerSource({ type: "sw" });
1716
+ fs.mkdirSync("./path/to", { recursive: true });
1717
+ fs.writeFileSync("./path/to/text.file", "SOME TEXT CONTENT");
1718
+ mockUploadWorkerRequest({
1719
+ expectedType: "sw",
1720
+ expectedModules: { TESTTEXTBLOBNAME: "SOME TEXT CONTENT" },
1721
+ expectedBindings: [
1722
+ {
1723
+ name: "TESTTEXTBLOBNAME",
1724
+ part: "TESTTEXTBLOBNAME",
1725
+ type: "text_blob",
1726
+ },
1727
+ ],
1728
+ });
1729
+ mockSubDomainRequest();
1730
+ await runWrangler("publish index.js");
1731
+ expect(std.out).toMatchInlineSnapshot(`
1732
+ "Uploaded
1733
+ test-name
1734
+ (TIMINGS)
1735
+ Published
1736
+ test-name
1737
+ (TIMINGS)
1738
+
1739
+ test-name.test-sub-domain.workers.dev"
1740
+ `);
1741
+ expect(std.err).toMatchInlineSnapshot(`""`);
1742
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1743
+ });
1744
+
1745
+ it("should error when defining text blobs for modules format workers", async () => {
1746
+ writeWranglerToml({
1747
+ text_blobs: {
1748
+ TESTTEXTBLOBNAME: "./path/to/text.file",
1749
+ },
1750
+ });
1751
+ writeWorkerSource({ type: "esm" });
1752
+ fs.mkdirSync("./path/to", { recursive: true });
1753
+ fs.writeFileSync("./path/to/text.file", "SOME TEXT CONTENT");
1754
+
1755
+ await expect(
1756
+ runWrangler("publish index.js")
1757
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1758
+ `"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"`
1759
+ );
1760
+ expect(std.out).toMatchInlineSnapshot(`""`);
1761
+ expect(std.err).toMatchInlineSnapshot(`
1762
+ "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
1763
+
1764
+ %s
1765
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1766
+ `);
1767
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1768
+ });
1769
+
1770
+ it("should resolve text blobs relative to the wrangler.toml file", async () => {
1771
+ fs.mkdirSync("./path/to/and/the/path/to/", { recursive: true });
1772
+ fs.writeFileSync(
1773
+ "./path/to/wrangler.toml",
1774
+ TOML.stringify({
1775
+ compatibility_date: "2022-01-12",
1776
+ name: "test-name",
1777
+ text_blobs: {
1778
+ TESTTEXTBLOBNAME: "./and/the/path/to/text.file",
1779
+ },
1780
+ }),
1781
+
1782
+ "utf-8"
1783
+ );
1784
+
1785
+ writeWorkerSource({ type: "sw" });
1786
+ fs.writeFileSync(
1787
+ "./path/to/and/the/path/to/text.file",
1788
+ "SOME TEXT CONTENT"
1789
+ );
1790
+ mockUploadWorkerRequest({
1791
+ expectedType: "sw",
1792
+ expectedModules: { TESTTEXTBLOBNAME: "SOME TEXT CONTENT" },
1793
+ expectedBindings: [
1794
+ {
1795
+ name: "TESTTEXTBLOBNAME",
1796
+ part: "TESTTEXTBLOBNAME",
1797
+ type: "text_blob",
1798
+ },
1799
+ ],
1800
+ });
1801
+ mockSubDomainRequest();
1802
+ await runWrangler("publish index.js --config ./path/to/wrangler.toml");
1803
+ expect(std.out).toMatchInlineSnapshot(`
1804
+ "Uploaded
1805
+ test-name
1806
+ (TIMINGS)
1807
+ Published
1808
+ test-name
1809
+ (TIMINGS)
1810
+
1811
+ test-name.test-sub-domain.workers.dev"
1812
+ `);
1813
+ expect(std.err).toMatchInlineSnapshot(`""`);
1814
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1815
+ });
1816
+ });
1817
+
1818
+ describe("vars bindings", () => {
1819
+ it("should support json bindings", async () => {
1820
+ writeWranglerToml({
1821
+ vars: {
1822
+ text: "plain ol' string",
1823
+ count: 1,
1824
+ complex: { enabled: true, id: 123 },
1825
+ },
1826
+ });
1827
+ writeWorkerSource();
1828
+ mockSubDomainRequest();
1829
+ mockUploadWorkerRequest({
1830
+ expectedBindings: [
1831
+ { name: "text", type: "plain_text", text: "plain ol' string" },
1832
+ { name: "count", type: "json", json: 1 },
1833
+ {
1834
+ name: "complex",
1835
+ type: "json",
1836
+ json: { enabled: true, id: 123 },
1837
+ },
1838
+ ],
1839
+ });
1840
+
1841
+ await runWrangler("publish index.js");
1842
+ expect(std.out).toMatchInlineSnapshot(`
1843
+ "Uploaded
1844
+ test-name
1845
+ (TIMINGS)
1846
+ Published
1847
+ test-name
1848
+ (TIMINGS)
1849
+
1850
+ test-name.test-sub-domain.workers.dev"
1851
+ `);
1852
+ expect(std.err).toMatchInlineSnapshot(`""`);
1853
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1854
+ });
1855
+ });
1856
+
1857
+ describe("r2 bucket bindings", () => {
1858
+ it("should support r2 bucket bindings", async () => {
1859
+ writeWranglerToml({
1860
+ r2_buckets: [{ binding: "FOO", bucket_name: "foo-bucket" }],
1861
+ });
1862
+ writeWorkerSource();
1863
+ mockSubDomainRequest();
1864
+ mockUploadWorkerRequest({
1865
+ expectedBindings: [
1866
+ { bucket_name: "foo-bucket", name: "FOO", type: "r2_bucket" },
1867
+ ],
1868
+ });
1869
+
1870
+ await runWrangler("publish index.js");
1871
+ expect(std.out).toMatchInlineSnapshot(`
1872
+ "Uploaded
1873
+ test-name
1874
+ (TIMINGS)
1875
+ Published
1876
+ test-name
1877
+ (TIMINGS)
1878
+
1879
+ test-name.test-sub-domain.workers.dev"
1880
+ `);
1881
+ expect(std.err).toMatchInlineSnapshot(`""`);
1882
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1883
+ });
1884
+ });
1885
+
1886
+ describe("unsafe bindings", () => {
1887
+ it("should warn if using unsafe bindings", async () => {
1888
+ writeWranglerToml({
1889
+ unsafe: {
1890
+ bindings: [
1891
+ {
1892
+ name: "my-binding",
1893
+ type: "binding-type",
1894
+ param: "binding-param",
1895
+ },
1896
+ ],
1897
+ },
1898
+ });
1899
+ writeWorkerSource();
1900
+ mockSubDomainRequest();
1901
+ mockUploadWorkerRequest({
1902
+ expectedBindings: [
1903
+ {
1904
+ name: "my-binding",
1905
+ type: "binding-type",
1906
+ param: "binding-param",
1907
+ },
1908
+ ],
1909
+ });
1910
+
1911
+ await runWrangler("publish index.js");
1912
+ expect(std.out).toMatchInlineSnapshot(`
1913
+ "Uploaded
1914
+ test-name
1915
+ (TIMINGS)
1916
+ Published
1917
+ test-name
1918
+ (TIMINGS)
1919
+
1920
+ test-name.test-sub-domain.workers.dev"
1921
+ `);
1922
+ expect(std.err).toMatchInlineSnapshot(`""`);
1923
+ expect(std.warn).toMatchInlineSnapshot(`
1924
+ "Processing wrangler.toml configuration:
1925
+ - \\"unsafe\\" fields are experimental and may change or break at any time."
1926
+ `);
1927
+ });
1928
+ it("should warn if using unsafe bindings already handled by wrangler", async () => {
1929
+ writeWranglerToml({
1930
+ unsafe: {
1931
+ bindings: [
1932
+ {
1933
+ name: "my-binding",
1934
+ type: "plain_text",
1935
+ text: "text",
1936
+ },
1937
+ ],
1938
+ },
1939
+ });
1940
+ writeWorkerSource();
1941
+ mockSubDomainRequest();
1942
+ mockUploadWorkerRequest({
1943
+ expectedBindings: [
1944
+ {
1945
+ name: "my-binding",
1946
+ type: "plain_text",
1947
+ text: "text",
1948
+ },
1949
+ ],
1950
+ });
1951
+
1952
+ await runWrangler("publish index.js");
1953
+ expect(std.out).toMatchInlineSnapshot(`
1954
+ "Uploaded
1955
+ test-name
1956
+ (TIMINGS)
1957
+ Published
1958
+ test-name
1959
+ (TIMINGS)
1960
+
1961
+ test-name.test-sub-domain.workers.dev"
1962
+ `);
1963
+ expect(std.err).toMatchInlineSnapshot(`""`);
1964
+ expect(std.warn).toMatchInlineSnapshot(`
1965
+ "Processing wrangler.toml configuration:
1966
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
1967
+ - \\"unsafe.bindings[0]\\": {\\"name\\":\\"my-binding\\",\\"type\\":\\"plain_text\\",\\"text\\":\\"text\\"}
1968
+ - The binding type \\"plain_text\\" is directly supported by wrangler.
1969
+ Consider migrating this unsafe binding to a format for 'plain_text' bindings that is supported by wrangler for optimal support.
1970
+ For more details, see https://developers.cloudflare.com/workers/cli-wrangler/configuration"
1971
+ `);
1972
+ });
1973
+ });
1974
+
1975
+ describe("upload rules", () => {
1976
+ it("should be able to define rules for uploading non-js modules (sw)", async () => {
1977
+ writeWranglerToml({
1978
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
1979
+ });
1980
+ fs.writeFileSync("./index.js", `import TEXT from './text.file';`);
1981
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
1982
+ mockSubDomainRequest();
1983
+ mockUploadWorkerRequest({
1984
+ expectedType: "sw",
1985
+ expectedBindings: [
1986
+ {
1987
+ name: "__2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file",
1988
+ part: "__2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file",
1989
+ type: "text_blob",
1990
+ },
1991
+ ],
1992
+ expectedModules: {
1993
+ __2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file:
1994
+ "SOME TEXT CONTENT",
1995
+ },
1996
+ });
1997
+ await runWrangler("publish index.js");
1998
+ expect(std.out).toMatchInlineSnapshot(`
1999
+ "Uploaded
2000
+ test-name
2001
+ (TIMINGS)
2002
+ Published
2003
+ test-name
2004
+ (TIMINGS)
2005
+
2006
+ test-name.test-sub-domain.workers.dev"
2007
+ `);
2008
+ expect(std.err).toMatchInlineSnapshot(`""`);
2009
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2010
+ });
2011
+
2012
+ it("should be able to define rules for uploading non-js modules (esm)", async () => {
2013
+ writeWranglerToml({
2014
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
2015
+ });
2016
+ fs.writeFileSync(
2017
+ "./index.js",
2018
+ `import TEXT from './text.file'; export default {};`
2019
+ );
2020
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2021
+ mockSubDomainRequest();
2022
+ mockUploadWorkerRequest({
2023
+ expectedType: "esm",
2024
+ expectedBindings: [],
2025
+ expectedModules: {
2026
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2027
+ "SOME TEXT CONTENT",
2028
+ },
2029
+ });
2030
+ await runWrangler("publish index.js");
2031
+ expect(std.out).toMatchInlineSnapshot(`
2032
+ "Uploaded
2033
+ test-name
2034
+ (TIMINGS)
2035
+ Published
2036
+ test-name
2037
+ (TIMINGS)
2038
+
2039
+ test-name.test-sub-domain.workers.dev"
2040
+ `);
2041
+ expect(std.err).toMatchInlineSnapshot(`""`);
2042
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2043
+ });
2044
+
2045
+ it("should log a deprecation warning when using `build.upload.rules`", async () => {
2046
+ writeWranglerToml({
2047
+ build: {
2048
+ upload: {
2049
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
2050
+ },
2051
+ },
2052
+ });
2053
+ fs.writeFileSync(
2054
+ "./index.js",
2055
+ `import TEXT from './text.file'; export default {};`
2056
+ );
2057
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2058
+ mockSubDomainRequest();
2059
+ mockUploadWorkerRequest({
2060
+ expectedType: "esm",
2061
+ expectedBindings: [],
2062
+ expectedModules: {
2063
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2064
+ "SOME TEXT CONTENT",
2065
+ },
2066
+ });
2067
+ await runWrangler("publish index.js");
2068
+ expect(std.out).toMatchInlineSnapshot(`
2069
+ "Uploaded
2070
+ test-name
2071
+ (TIMINGS)
2072
+ Published
2073
+ test-name
2074
+ (TIMINGS)
2075
+
2076
+ test-name.test-sub-domain.workers.dev"
2077
+ `);
2078
+ expect(std.err).toMatchInlineSnapshot(`""`);
2079
+ expect(std.warn).toMatchInlineSnapshot(`
2080
+ "Processing wrangler.toml configuration:
2081
+ - 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:
2082
+ \`\`\`
2083
+ [[rules]]
2084
+ type = \\"Text\\"
2085
+ globs = [ \\"**/*.file\\" ]
2086
+ fallthrough = true
2087
+ \`\`\`"
2088
+ `);
2089
+ });
2090
+
2091
+ it("should be able to use fallthrough:true for multiple rules", async () => {
2092
+ writeWranglerToml({
2093
+ rules: [
2094
+ { type: "Text", globs: ["**/*.file"], fallthrough: true },
2095
+ { type: "Text", globs: ["**/*.other"], fallthrough: true },
2096
+ ],
2097
+ });
2098
+ fs.writeFileSync(
2099
+ "./index.js",
2100
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
2101
+ );
2102
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2103
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
2104
+ mockSubDomainRequest();
2105
+ mockUploadWorkerRequest({
2106
+ expectedType: "esm",
2107
+ expectedBindings: [],
2108
+ expectedModules: {
2109
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2110
+ "SOME TEXT CONTENT",
2111
+ "./16347a01366873ed80fe45115119de3c92ab8db0-other.other":
2112
+ "SOME OTHER TEXT CONTENT",
2113
+ },
2114
+ });
2115
+ await runWrangler("publish index.js");
2116
+ expect(std.out).toMatchInlineSnapshot(`
2117
+ "Uploaded
2118
+ test-name
2119
+ (TIMINGS)
2120
+ Published
2121
+ test-name
2122
+ (TIMINGS)
2123
+
2124
+ test-name.test-sub-domain.workers.dev"
2125
+ `);
2126
+ expect(std.err).toMatchInlineSnapshot(`""`);
2127
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2128
+ });
2129
+
2130
+ it("should be able to use fallthrough:false for multiple rules", async () => {
2131
+ writeWranglerToml({
2132
+ rules: [
2133
+ { type: "Text", globs: ["**/*.file"], fallthrough: false },
2134
+ { type: "Text", globs: ["**/*.other"] },
2135
+ ],
2136
+ });
2137
+ fs.writeFileSync(
2138
+ "./index.js",
2139
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
2140
+ );
2141
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2142
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
2143
+
2144
+ // We throw an error when we come across a file that matched a rule
2145
+ // but was skipped because of fallthrough = false
2146
+ let err: Error | undefined;
2147
+ try {
2148
+ await runWrangler("publish index.js");
2149
+ } catch (e) {
2150
+ err = e as Error;
2151
+ }
2152
+ expect(err?.message).toMatch(
2153
+ `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\`.`
2154
+ );
2155
+ });
2156
+
2157
+ it("should warn when multiple rules for the same type do not have fallback defined", async () => {
2158
+ writeWranglerToml({
2159
+ rules: [
2160
+ { type: "Text", globs: ["**/*.file"] },
2161
+ { type: "Text", globs: ["**/*.other"] },
2162
+ ],
2163
+ });
2164
+ fs.writeFileSync(
2165
+ "./index.js",
2166
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
2167
+ );
2168
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2169
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
2170
+
2171
+ // We throw an error when we come across a file that matched a rule
2172
+ // but was skipped because of fallthrough = false
2173
+ let err: Error | undefined;
2174
+ try {
2175
+ await runWrangler("publish index.js");
2176
+ } catch (e) {
2177
+ err = e as Error;
2178
+ }
2179
+ expect(err?.message).toMatch(
2180
+ `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\`.`
2181
+ );
2182
+ // and the warnings because fallthrough was not explicitly set
2183
+ expect(std.warn).toMatchInlineSnapshot(`
2184
+ "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.
2185
+ 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."
2186
+ `);
2187
+ });
2188
+ });
2189
+ });
2190
+
2191
+ /** Write a mock Worker script to disk. */
2192
+ function writeWorkerSource({
2193
+ basePath = ".",
2194
+ format = "js",
2195
+ type = "esm",
2196
+ }: {
2197
+ basePath?: string;
2198
+ format?: "js" | "ts" | "jsx" | "tsx" | "mjs";
2199
+ type?: "esm" | "sw";
2200
+ } = {}) {
2201
+ if (basePath !== ".") {
2202
+ fs.mkdirSync(basePath, { recursive: true });
2203
+ }
2204
+ fs.writeFileSync(
2205
+ `${basePath}/index.${format}`,
2206
+ type === "esm"
2207
+ ? `import { foo } from "./another";
2208
+ export default {
2209
+ async fetch(request) {
2210
+ return new Response('Hello' + foo);
2211
+ },
2212
+ };`
2213
+ : `import { foo } from "./another";
2214
+ addEventListener('fetch', event => {
2215
+ event.respondWith(new Response('Hello' + foo));
2216
+ })`
2217
+ );
2218
+ fs.writeFileSync(`${basePath}/another.${format}`, `export const foo = 100;`);
2219
+ }
2220
+
2221
+ /** Write mock assets to the file system so they can be uploaded. */
1108
2222
  function writeAssets(assets: { filePath: string; content: string }[]) {
1109
2223
  for (const asset of assets) {
1110
2224
  fs.mkdirSync(path.dirname(asset.filePath), { recursive: true });
@@ -1120,6 +2234,7 @@ function mockUploadWorkerRequest({
1120
2234
  expectedBindings,
1121
2235
  expectedModules = {},
1122
2236
  env = undefined,
2237
+ legacyEnv = false,
1123
2238
  }: {
1124
2239
  available_on_subdomain?: boolean;
1125
2240
  expectedEntry?: string;
@@ -1127,16 +2242,22 @@ function mockUploadWorkerRequest({
1127
2242
  expectedBindings?: unknown;
1128
2243
  expectedModules?: Record<string, string>;
1129
2244
  env?: string | undefined;
2245
+ legacyEnv?: boolean | undefined;
1130
2246
  } = {}) {
1131
2247
  setMockResponse(
1132
- env
1133
- ? `/accounts/:accountId/workers/services/:scriptName/environments/:envName`
2248
+ env && !legacyEnv
2249
+ ? "/accounts/:accountId/workers/services/:scriptName/environments/:envName"
1134
2250
  : "/accounts/:accountId/workers/scripts/:scriptName",
1135
2251
  "PUT",
1136
- async ([_url, accountId, scriptName], { body }, queryParams) => {
2252
+ async ([_url, accountId, scriptName, envName], { body }, queryParams) => {
1137
2253
  expect(accountId).toEqual("some-account-id");
1138
- expect(scriptName).toEqual("test-name");
1139
- expect(queryParams.get("available_on_subdomains")).toEqual("true");
2254
+ expect(scriptName).toEqual(
2255
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2256
+ );
2257
+ if (!legacyEnv) {
2258
+ expect(envName).toEqual(env);
2259
+ }
2260
+ expect(queryParams.get("available_on_subdomain")).toEqual("true");
1140
2261
  const formBody = body as FormData;
1141
2262
  if (expectedEntry !== undefined) {
1142
2263
  expect(await (formBody.get("index.js") as File).text()).toMatch(
@@ -1156,7 +2277,7 @@ function mockUploadWorkerRequest({
1156
2277
  expect(metadata.bindings).toEqual(expectedBindings);
1157
2278
  }
1158
2279
  for (const [name, content] of Object.entries(expectedModules)) {
1159
- expect(await (formBody.get(name) as File).text()).toMatch(content);
2280
+ expect(await (formBody.get(name) as File).text()).toEqual(content);
1160
2281
  }
1161
2282
 
1162
2283
  return { available_on_subdomain };
@@ -1166,11 +2287,74 @@ function mockUploadWorkerRequest({
1166
2287
 
1167
2288
  /** Create a mock handler for the request to get the account's subdomain. */
1168
2289
  function mockSubDomainRequest(subdomain = "test-sub-domain") {
1169
- setMockResponse("/accounts/:accountId/workers/subdomain", () => {
2290
+ setMockResponse("/accounts/:accountId/workers/subdomain", "GET", () => {
1170
2291
  return { subdomain };
1171
2292
  });
1172
2293
  }
1173
2294
 
2295
+ /** Create a mock handler to toggle a <script>.<user>.workers.dev subdomain */
2296
+ function mockUpdateWorkerRequest({
2297
+ env,
2298
+ enabled,
2299
+ legacyEnv = false,
2300
+ }: {
2301
+ enabled: boolean;
2302
+ env?: string | undefined;
2303
+ legacyEnv?: boolean | undefined;
2304
+ }) {
2305
+ const requests = { count: 0 };
2306
+ const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
2307
+ const environment = env && !legacyEnv ? "/environments/:envName" : "";
2308
+ setMockResponse(
2309
+ `/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/subdomain`,
2310
+ "POST",
2311
+ ([_url, accountId, scriptName, envName], { body }) => {
2312
+ expect(accountId).toEqual("some-account-id");
2313
+ expect(scriptName).toEqual(
2314
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2315
+ );
2316
+ if (!legacyEnv) {
2317
+ expect(envName).toEqual(env);
2318
+ }
2319
+ expect(JSON.parse(body as string)).toEqual({ enabled });
2320
+ return null;
2321
+ }
2322
+ );
2323
+ return requests;
2324
+ }
2325
+
2326
+ function mockPublishRoutesRequest({
2327
+ routes,
2328
+ env = undefined,
2329
+ legacyEnv = false,
2330
+ }: {
2331
+ routes: string[];
2332
+ env?: string | undefined;
2333
+ legacyEnv?: boolean | undefined;
2334
+ }) {
2335
+ const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
2336
+ const environment = env && !legacyEnv ? "/environments/:envName" : "";
2337
+
2338
+ setMockResponse(
2339
+ `/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/routes`,
2340
+ "PUT",
2341
+ ([_url, accountId, scriptName, envName], { body }) => {
2342
+ expect(accountId).toEqual("some-account-id");
2343
+ expect(scriptName).toEqual(
2344
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2345
+ );
2346
+ if (!legacyEnv) {
2347
+ expect(envName).toEqual(env);
2348
+ }
2349
+
2350
+ expect(JSON.parse(body as string)).toEqual(
2351
+ routes.map((pattern) => ({ pattern }))
2352
+ );
2353
+ return null;
2354
+ }
2355
+ );
2356
+ }
2357
+
1174
2358
  /** Create a mock handler for the request to get a list of all KV namespaces. */
1175
2359
  function mockListKVNamespacesRequest(...namespaces: KVNamespaceInfo[]) {
1176
2360
  setMockResponse(