wrangler 0.0.0-e95bea2 → 0.0.0-ea8e701

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 (55) hide show
  1. package/README.md +3 -3
  2. package/bin/wrangler.js +10 -1
  3. package/miniflare-dist/index.mjs +79 -0
  4. package/miniflare-dist/index.mjs.map +7 -0
  5. package/package.json +7 -6
  6. package/pages/functions/filepath-routing.test.ts +125 -25
  7. package/pages/functions/filepath-routing.ts +6 -3
  8. package/src/__tests__/configuration.test.ts +826 -223
  9. package/src/__tests__/dev.test.tsx +145 -9
  10. package/src/__tests__/guess-worker-format.test.ts +26 -1
  11. package/src/__tests__/helpers/mock-account-id.ts +4 -0
  12. package/src/__tests__/helpers/mock-kv.ts +9 -16
  13. package/src/__tests__/helpers/mock-oauth-flow.ts +178 -0
  14. package/src/__tests__/helpers/run-in-tmp.ts +3 -0
  15. package/src/__tests__/index.test.ts +9 -13
  16. package/src/__tests__/jest.setup.ts +5 -0
  17. package/src/__tests__/kv.test.ts +43 -71
  18. package/src/__tests__/pages.test.ts +48 -10
  19. package/src/__tests__/publish.test.ts +1456 -327
  20. package/src/__tests__/r2.test.ts +4 -4
  21. package/src/__tests__/tail.test.ts +78 -4
  22. package/src/__tests__/user.test.ts +83 -0
  23. package/src/__tests__/whoami.test.tsx +16 -7
  24. package/src/bundle.ts +15 -2
  25. package/src/cfetch/internal.ts +9 -5
  26. package/src/config/README.md +6 -6
  27. package/src/config/config.ts +17 -78
  28. package/src/config/environment.ts +67 -1
  29. package/src/config/index.ts +13 -3
  30. package/src/config/validation-helpers.ts +177 -11
  31. package/src/config/validation.ts +305 -100
  32. package/src/dev/dev.tsx +76 -41
  33. package/src/dev/local.tsx +105 -114
  34. package/src/dev/remote.tsx +2 -0
  35. package/src/dev/use-esbuild.ts +4 -0
  36. package/src/entry.ts +103 -6
  37. package/src/index.tsx +251 -189
  38. package/src/intl-polyfill.d.ts +139 -0
  39. package/src/{kv/index.tsx → kv.ts} +8 -28
  40. package/src/miniflare-cli/README.md +30 -0
  41. package/src/miniflare-cli/enum-keys.ts +17 -0
  42. package/src/miniflare-cli/index.ts +37 -0
  43. package/src/module-collection.ts +58 -53
  44. package/src/pages.tsx +26 -10
  45. package/src/proxy.ts +5 -3
  46. package/src/publish.ts +17 -21
  47. package/src/sites.tsx +67 -25
  48. package/src/tail/index.ts +1 -1
  49. package/src/tail/printing.ts +2 -2
  50. package/src/user.tsx +161 -81
  51. package/wrangler-dist/cli.js +3418 -1437
  52. package/wrangler-dist/cli.js.map +3 -3
  53. package/src/__tests__/dev2.test.tsx +0 -152
  54. package/src/__tests__/helpers/mock-user.ts +0 -27
  55. package/src/__tests__/logout.test.ts +0 -50
@@ -1,10 +1,17 @@
1
1
  import path from "node:path";
2
2
  import { normalizeAndValidateConfig } from "../config/validation";
3
- import type { RawConfig, RawEnvironment } from "../config";
3
+ import type {
4
+ ConfigFields,
5
+ RawDevConfig,
6
+ RawConfig,
7
+ RawEnvironment,
8
+ } from "../config";
4
9
 
5
10
  describe("normalizeAndValidateConfig()", () => {
6
11
  it("should use defaults for empty configuration", () => {
7
- const { config, diagnostics } = normalizeAndValidateConfig({}, undefined);
12
+ const { config, diagnostics } = normalizeAndValidateConfig({}, undefined, {
13
+ env: undefined,
14
+ });
8
15
 
9
16
  expect(config).toEqual({
10
17
  account_id: undefined,
@@ -17,7 +24,7 @@ describe("normalizeAndValidateConfig()", () => {
17
24
  compatibility_flags: [],
18
25
  configPath: undefined,
19
26
  dev: {
20
- ip: "127.0.0.1",
27
+ ip: "localhost",
21
28
  local_protocol: "http",
22
29
  port: 8787,
23
30
  upstream_protocol: "https",
@@ -26,9 +33,9 @@ describe("normalizeAndValidateConfig()", () => {
26
33
  durable_objects: {
27
34
  bindings: [],
28
35
  },
29
- env: {},
30
36
  jsx_factory: "React.createElement",
31
37
  jsx_fragment: "React.Fragment",
38
+ tsconfig: undefined,
32
39
  kv_namespaces: [],
33
40
  legacy_env: true,
34
41
  main: undefined,
@@ -49,7 +56,7 @@ describe("normalizeAndValidateConfig()", () => {
49
56
  usage_model: undefined,
50
57
  vars: {},
51
58
  wasm_modules: undefined,
52
- workers_dev: true,
59
+ workers_dev: undefined,
53
60
  zone_id: undefined,
54
61
  });
55
62
  expect(diagnostics.hasErrors()).toBe(false);
@@ -58,9 +65,7 @@ describe("normalizeAndValidateConfig()", () => {
58
65
 
59
66
  describe("top-level non-environment configuration", () => {
60
67
  it("should override config defaults with provided values", () => {
61
- const main = "src/index.ts";
62
- const expectedConfig: RawConfig = {
63
- main,
68
+ const expectedConfig: Partial<ConfigFields<RawDevConfig>> = {
64
69
  legacy_env: true,
65
70
  dev: {
66
71
  ip: "255.255.255.255",
@@ -68,29 +73,21 @@ describe("normalizeAndValidateConfig()", () => {
68
73
  local_protocol: "https",
69
74
  upstream_protocol: "http",
70
75
  },
71
- build: {
72
- command: "COMMAND",
73
- cwd: "CWD",
74
- watch_dir: "WATCH_DIR",
75
- },
76
76
  };
77
77
 
78
78
  const { config, diagnostics } = normalizeAndValidateConfig(
79
79
  expectedConfig,
80
- undefined
80
+ undefined,
81
+ { env: undefined }
81
82
  );
82
83
 
83
- const resolvedMain = path.resolve(process.cwd(), main);
84
- expect(config).toEqual(
85
- expect.objectContaining({ ...expectedConfig, main: resolvedMain })
86
- );
84
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
87
85
  expect(diagnostics.hasErrors()).toBe(false);
88
86
  expect(diagnostics.hasWarnings()).toBe(false);
89
87
  });
90
88
 
91
89
  it("should error on invalid top level fields", () => {
92
90
  const expectedConfig = {
93
- main: 111,
94
91
  legacy_env: "FOO",
95
92
  dev: {
96
93
  ip: 222,
@@ -98,16 +95,12 @@ describe("normalizeAndValidateConfig()", () => {
98
95
  local_protocol: "wss",
99
96
  upstream_protocol: "ws",
100
97
  },
101
- build: {
102
- command: 555,
103
- cwd: 666,
104
- watch_dir: 777,
105
- },
106
98
  };
107
99
 
108
100
  const { config, diagnostics } = normalizeAndValidateConfig(
109
101
  expectedConfig as unknown as RawConfig,
110
- undefined
102
+ undefined,
103
+ { env: undefined }
111
104
  );
112
105
 
113
106
  expect(config).toEqual(
@@ -116,11 +109,7 @@ describe("normalizeAndValidateConfig()", () => {
116
109
  expect(diagnostics.hasWarnings()).toBe(false);
117
110
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
118
111
  "Processing wrangler configuration:
119
- - Expected \\"build.command\\" to be of type string but got 555.
120
- - Expected \\"build.cwd\\" to be of type string but got 666.
121
- - Expected \\"build.watch_dir\\" to be of type string but got 777.
122
112
  - Expected \\"legacy_env\\" to be of type boolean but got \\"FOO\\".
123
- - Expected \\"main\\" to be a string but got 111
124
113
  - Expected \\"dev.ip\\" to be of type string but got 222.
125
114
  - Expected \\"dev.port\\" to be of type number but got \\"FOO\\".
126
115
  - Expected \\"dev.local_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"wss\\".
@@ -130,65 +119,43 @@ describe("normalizeAndValidateConfig()", () => {
130
119
 
131
120
  it("should warn on and remove unexpected top level fields", () => {
132
121
  const expectedConfig = {
133
- miniflare: {
134
- host: "127.0.0.1",
122
+ unexpected: {
123
+ subkey: "some-value",
135
124
  },
136
125
  };
137
126
 
138
127
  const { config, diagnostics } = normalizeAndValidateConfig(
139
128
  expectedConfig as unknown as RawConfig,
140
- undefined
129
+ undefined,
130
+ { env: undefined }
141
131
  );
142
132
 
143
- expect("miniflare" in config).toBe(false);
133
+ expect("unexpected" in config).toBe(false);
144
134
  expect(diagnostics.hasErrors()).toBe(false);
145
135
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
146
136
  "Processing wrangler configuration:
147
- - Unexpected fields found in top-level field: \\"miniflare\\""
137
+ - Unexpected fields found in top-level field: \\"unexpected\\""
148
138
  `);
149
139
  });
150
140
 
151
- it("should override build.upload config defaults with provided values and warn about deprecations", () => {
152
- const expectedConfig: RawConfig = {
153
- build: {
154
- upload: {
155
- dir: "src",
156
- format: "modules",
157
- main: "index.ts",
158
- rules: [{ type: "Text", globs: ["GLOB"], fallthrough: true }],
159
- },
141
+ it("should ignore `miniflare` top level fields", () => {
142
+ const expectedConfig = {
143
+ miniflare: {
144
+ host: "localhost",
160
145
  },
161
146
  };
162
147
 
163
148
  const { config, diagnostics } = normalizeAndValidateConfig(
164
- expectedConfig,
165
- path.resolve("project/wrangler.toml")
149
+ expectedConfig as unknown as RawConfig,
150
+ undefined,
151
+ { env: undefined }
166
152
  );
167
153
 
168
- expect(config.main).toEqual(path.resolve("project/src/index.ts"));
169
- expect(config.build.upload).toBeUndefined();
154
+ expect("miniflare" in config).toBe(false);
170
155
  expect(diagnostics.hasErrors()).toBe(false);
171
- expect(diagnostics.hasWarnings()).toBe(true);
172
- expect(normalizePath(diagnostics.renderWarnings()))
173
- .toMatchInlineSnapshot(`
174
- "Processing project/wrangler.toml configuration:
175
- - DEPRECATION: \\"build.upload.format\\":
176
- The format is inferred automatically from the code.
177
- - DEPRECATION: \\"build.upload.main\\":
178
- Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
179
- Then add the top level \`main\` field to your configuration file:
180
- \`\`\`
181
- main = \\"src/index.ts\\"
182
- \`\`\`
183
- - DEPRECATION: \\"build.upload.dir\\":
184
- Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker.
185
- - 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:
186
- \`\`\`
187
- [[rules]]
188
- type = \\"Text\\"
189
- globs = [ \\"GLOB\\" ]
190
- fallthrough = true
191
- \`\`\`"
156
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
157
+ "Processing wrangler configuration:
158
+ "
192
159
  `);
193
160
  });
194
161
 
@@ -211,7 +178,8 @@ describe("normalizeAndValidateConfig()", () => {
211
178
 
212
179
  const { config, diagnostics } = normalizeAndValidateConfig(
213
180
  expectedConfig,
214
- undefined
181
+ undefined,
182
+ { env: undefined }
215
183
  );
216
184
 
217
185
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -238,7 +206,8 @@ describe("normalizeAndValidateConfig()", () => {
238
206
 
239
207
  const { config, diagnostics } = normalizeAndValidateConfig(
240
208
  expectedConfig as unknown as RawConfig,
241
- undefined
209
+ undefined,
210
+ { env: undefined }
242
211
  );
243
212
 
244
213
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -266,7 +235,8 @@ describe("normalizeAndValidateConfig()", () => {
266
235
 
267
236
  const { config, diagnostics } = normalizeAndValidateConfig(
268
237
  expectedConfig,
269
- undefined
238
+ undefined,
239
+ { env: undefined }
270
240
  );
271
241
 
272
242
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -285,7 +255,8 @@ describe("normalizeAndValidateConfig()", () => {
285
255
 
286
256
  const { config, diagnostics } = normalizeAndValidateConfig(
287
257
  expectedConfig,
288
- undefined
258
+ undefined,
259
+ { env: undefined }
289
260
  );
290
261
 
291
262
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -308,7 +279,8 @@ describe("normalizeAndValidateConfig()", () => {
308
279
 
309
280
  const { config, diagnostics } = normalizeAndValidateConfig(
310
281
  expectedConfig as unknown as RawConfig,
311
- undefined
282
+ undefined,
283
+ { env: undefined }
312
284
  );
313
285
 
314
286
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -330,7 +302,8 @@ describe("normalizeAndValidateConfig()", () => {
330
302
  "entry-point": "some/other/script.js",
331
303
  },
332
304
  } as unknown as RawConfig,
333
- undefined
305
+ undefined,
306
+ { env: undefined }
334
307
  );
335
308
 
336
309
  expect(config.site).toMatchInlineSnapshot(`
@@ -365,7 +338,8 @@ describe("normalizeAndValidateConfig()", () => {
365
338
 
366
339
  const { config, diagnostics } = normalizeAndValidateConfig(
367
340
  expectedConfig,
368
- "project/wrangler.toml"
341
+ "project/wrangler.toml",
342
+ { env: undefined }
369
343
  );
370
344
 
371
345
  expect(config).toEqual(
@@ -390,7 +364,8 @@ describe("normalizeAndValidateConfig()", () => {
390
364
 
391
365
  const { config, diagnostics } = normalizeAndValidateConfig(
392
366
  expectedConfig as unknown as RawConfig,
393
- "project/wrangler.toml"
367
+ "project/wrangler.toml",
368
+ { env: undefined }
394
369
  );
395
370
 
396
371
  expect(config).toEqual(
@@ -400,10 +375,10 @@ describe("normalizeAndValidateConfig()", () => {
400
375
  );
401
376
  expect(diagnostics.hasWarnings()).toBe(false);
402
377
  expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
403
- "Processing project/wrangler.toml configuration:
404
- - Expected \\"wasm_modules['MODULE_1']\\" field to be a string but got 111.
405
- - Expected \\"wasm_modules['MODULE_2']\\" field to be a string but got 222."
406
- `);
378
+ "Processing project/wrangler.toml configuration:
379
+ - Expected \\"wasm_modules['MODULE_1']\\" to be of type string but got 111.
380
+ - Expected \\"wasm_modules['MODULE_2']\\" to be of type string but got 222."
381
+ `);
407
382
  });
408
383
 
409
384
  it("should map `text_blobs` paths from relative to the config path to relative to the cwd", () => {
@@ -416,7 +391,8 @@ describe("normalizeAndValidateConfig()", () => {
416
391
 
417
392
  const { config, diagnostics } = normalizeAndValidateConfig(
418
393
  expectedConfig,
419
- "project/wrangler.toml"
394
+ "project/wrangler.toml",
395
+ { env: undefined }
420
396
  );
421
397
 
422
398
  expect(config).toEqual(
@@ -441,7 +417,8 @@ describe("normalizeAndValidateConfig()", () => {
441
417
 
442
418
  const { config, diagnostics } = normalizeAndValidateConfig(
443
419
  expectedConfig as unknown as RawConfig,
444
- "project/wrangler.toml"
420
+ "project/wrangler.toml",
421
+ { env: undefined }
445
422
  );
446
423
 
447
424
  expect(config).toEqual(
@@ -451,10 +428,31 @@ describe("normalizeAndValidateConfig()", () => {
451
428
  );
452
429
  expect(diagnostics.hasWarnings()).toBe(false);
453
430
  expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
454
- "Processing project/wrangler.toml configuration:
455
- - Expected \\"text_blobs['MODULE_1']\\" field to be a string but got 111.
456
- - Expected \\"text_blobs['MODULE_2']\\" field to be a string but got 222."
457
- `);
431
+ "Processing project/wrangler.toml configuration:
432
+ - Expected \\"text_blobs['MODULE_1']\\" to be of type string but got 111.
433
+ - Expected \\"text_blobs['MODULE_2']\\" to be of type string but got 222."
434
+ `);
435
+ });
436
+
437
+ it("should resolve tsconfig relative to wrangler.toml", async () => {
438
+ const expectedConfig: RawEnvironment = {
439
+ tsconfig: "path/to/some-tsconfig.json",
440
+ };
441
+
442
+ const { config, diagnostics } = normalizeAndValidateConfig(
443
+ expectedConfig,
444
+ "project/wrangler.toml",
445
+ { env: undefined }
446
+ );
447
+
448
+ expect(config).toEqual(
449
+ expect.objectContaining({
450
+ tsconfig: path.normalize("project/path/to/some-tsconfig.json"),
451
+ })
452
+ );
453
+
454
+ expect(diagnostics.hasErrors()).toBe(false);
455
+ expect(diagnostics.hasWarnings()).toBe(false);
458
456
  });
459
457
 
460
458
  describe("(deprecated)", () => {
@@ -466,7 +464,8 @@ describe("normalizeAndValidateConfig()", () => {
466
464
 
467
465
  const { config, diagnostics } = normalizeAndValidateConfig(
468
466
  rawConfig,
469
- undefined
467
+ undefined,
468
+ { env: undefined }
470
469
  );
471
470
 
472
471
  // Note the `.not.` here...
@@ -491,18 +490,27 @@ describe("normalizeAndValidateConfig()", () => {
491
490
 
492
491
  describe("top-level environment configuration", () => {
493
492
  it("should override config defaults with provided values", () => {
494
- const expectedConfig: RawConfig = {
493
+ const main = "src/index.ts";
494
+ const resolvedMain = path.resolve(process.cwd(), main);
495
+
496
+ const expectedConfig: RawEnvironment = {
495
497
  name: "NAME",
496
498
  account_id: "ACCOUNT_ID",
497
499
  compatibility_date: "2022-01-01",
498
500
  compatibility_flags: ["FLAG1", "FLAG2"],
499
501
  workers_dev: false,
500
502
  routes: ["ROUTE_1", "ROUTE_2"],
501
- route: "ROUTE_3",
502
503
  jsx_factory: "JSX_FACTORY",
503
504
  jsx_fragment: "JSX_FRAGMENT",
505
+ tsconfig: "path/to/tsconfig",
504
506
  triggers: { crons: ["CRON_1", "CRON_2"] },
505
507
  usage_model: "bundled",
508
+ main,
509
+ build: {
510
+ command: "COMMAND",
511
+ cwd: "CWD",
512
+ watch_dir: "WATCH_DIR",
513
+ },
506
514
  vars: {
507
515
  VAR1: "VALUE_1",
508
516
  VAR2: "VALUE_2",
@@ -547,10 +555,13 @@ describe("normalizeAndValidateConfig()", () => {
547
555
 
548
556
  const { config, diagnostics } = normalizeAndValidateConfig(
549
557
  expectedConfig,
550
- undefined
558
+ undefined,
559
+ { env: undefined }
551
560
  );
552
561
 
553
- expect(config).toEqual(expect.objectContaining(expectedConfig));
562
+ expect(config).toEqual(
563
+ expect.objectContaining({ ...expectedConfig, main: resolvedMain })
564
+ );
554
565
  expect(diagnostics.hasErrors()).toBe(false);
555
566
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
556
567
  "Processing wrangler configuration:
@@ -559,7 +570,7 @@ describe("normalizeAndValidateConfig()", () => {
559
570
  });
560
571
 
561
572
  it("should error on invalid environment values", () => {
562
- const expectedConfig: RawConfig = {
573
+ const expectedConfig: RawEnvironment = {
563
574
  name: 111,
564
575
  account_id: 222,
565
576
  compatibility_date: 333,
@@ -569,37 +580,146 @@ describe("normalizeAndValidateConfig()", () => {
569
580
  route: 888,
570
581
  jsx_factory: 999,
571
582
  jsx_fragment: 1000,
583
+ tsconfig: true,
572
584
  triggers: { crons: [1111, 1222] },
573
585
  usage_model: "INVALID",
574
- } as unknown as RawConfig;
586
+ main: 1333,
587
+ build: {
588
+ command: 1444,
589
+ cwd: 1555,
590
+ watch_dir: 1666,
591
+ },
592
+ } as unknown as RawEnvironment;
575
593
 
576
594
  const { config, diagnostics } = normalizeAndValidateConfig(
577
595
  expectedConfig,
578
- undefined
596
+ undefined,
597
+ { env: undefined }
579
598
  );
580
599
 
581
600
  expect(config).toEqual(expect.objectContaining(expectedConfig));
582
601
  expect(diagnostics.hasWarnings()).toBe(false);
583
602
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
584
603
  "Processing wrangler configuration:
585
- - Expected \\"route\\" field to be a string but got 888.
586
- - Expected \\"routes\\" field to be an array of strings but got [666,777].
587
- - Expected \\"workers_dev\\" field to be a boolean but got \\"BAD\\".
588
- - Expected \\"account_id\\" field to be a string but got 222.
589
- - Expected \\"compatibility_date\\" field to be a string but got 333.
590
- - Expected \\"compatibility_flags\\" field to be an array of strings but got [444,555].
591
- - Expected \\"jsx_factory\\" field to be a string but got 999.
592
- - Expected \\"jsx_fragment\\" field to be a string but got 1000.
593
- - Expected \\"name\\" field to be a string but got 111.
604
+ - Expected \\"route\\" to be of type string but got 888.
605
+ - Expected \\"routes\\" to be of type string array but got [666,777].
606
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"].
607
+ - Expected \\"workers_dev\\" to be of type boolean but got \\"BAD\\".
608
+ - Expected \\"build.command\\" to be of type string but got 1444.
609
+ - Expected \\"build.cwd\\" to be of type string but got 1555.
610
+ - Expected \\"build.watch_dir\\" to be of type string but got 1666.
611
+ - Expected \\"account_id\\" to be of type string but got 222.
612
+ - Expected \\"compatibility_date\\" to be of type string but got 333.
613
+ - Expected \\"compatibility_flags\\" to be of type string array but got [444,555].
614
+ - Expected \\"jsx_factory\\" to be of type string but got 999.
615
+ - Expected \\"jsx_fragment\\" to be of type string but got 1000.
616
+ - Expected \\"tsconfig\\" to be of type string but got true.
617
+ - Expected \\"name\\" to be of type string but got 111.
618
+ - Expected \\"main\\" to be of type string but got 1333.
594
619
  - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
595
620
  `);
596
621
  });
597
622
 
623
+ it("should override build.upload config defaults with provided values and warn about deprecations", () => {
624
+ const expectedConfig: RawEnvironment = {
625
+ build: {
626
+ upload: {
627
+ dir: "src",
628
+ format: "modules",
629
+ main: "index.ts",
630
+ rules: [{ type: "Text", globs: ["GLOB"], fallthrough: true }],
631
+ },
632
+ },
633
+ };
634
+
635
+ const { config, diagnostics } = normalizeAndValidateConfig(
636
+ expectedConfig,
637
+ path.resolve("project/wrangler.toml"),
638
+ { env: undefined }
639
+ );
640
+
641
+ expect(config.main).toEqual(path.resolve("project/src/index.ts"));
642
+ expect(config.build.upload).toBeUndefined();
643
+ expect(diagnostics.hasErrors()).toBe(false);
644
+ expect(diagnostics.hasWarnings()).toBe(true);
645
+ expect(normalizePath(diagnostics.renderWarnings()))
646
+ .toMatchInlineSnapshot(`
647
+ "Processing project/wrangler.toml configuration:
648
+ - DEPRECATION: \\"build.upload.format\\":
649
+ The format is inferred automatically from the code.
650
+ - DEPRECATION: \\"build.upload.main\\":
651
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
652
+ Then add the top level \`main\` field to your configuration file:
653
+ \`\`\`
654
+ main = \\"src/index.ts\\"
655
+ \`\`\`
656
+ - DEPRECATION: \\"build.upload.dir\\":
657
+ Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker.
658
+ - 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:
659
+ \`\`\`
660
+ [[rules]]
661
+ type = \\"Text\\"
662
+ globs = [ \\"GLOB\\" ]
663
+ fallthrough = true
664
+ \`\`\`"
665
+ `);
666
+ });
667
+
668
+ it("should default custom build watch directories to src", () => {
669
+ const expectedConfig: RawEnvironment = {
670
+ build: {
671
+ command: "execute some --build",
672
+ },
673
+ };
674
+
675
+ const { config, diagnostics } = normalizeAndValidateConfig(
676
+ expectedConfig,
677
+ undefined,
678
+ { env: undefined }
679
+ );
680
+
681
+ expect(config.build).toEqual(
682
+ expect.objectContaining({
683
+ command: "execute some --build",
684
+ watch_dir: "./src",
685
+ })
686
+ );
687
+
688
+ expect(diagnostics.hasErrors()).toBe(false);
689
+ expect(diagnostics.hasWarnings()).toBe(false);
690
+ });
691
+
692
+ it("should resolve custom build watch directories relative to wrangler.toml", async () => {
693
+ const expectedConfig: RawEnvironment = {
694
+ build: {
695
+ command: "execute some --build",
696
+ watch_dir: "some/path",
697
+ },
698
+ };
699
+
700
+ const { config, diagnostics } = normalizeAndValidateConfig(
701
+ expectedConfig,
702
+ "project/wrangler.toml",
703
+ { env: undefined }
704
+ );
705
+
706
+ expect(config.build).toEqual(
707
+ expect.objectContaining({
708
+ command: "execute some --build",
709
+ watch_dir: path.normalize("project/some/path"),
710
+ })
711
+ );
712
+
713
+ expect(diagnostics.hasErrors()).toBe(false);
714
+ expect(diagnostics.hasWarnings()).toBe(false);
715
+ });
716
+
598
717
  describe("durable_objects field", () => {
599
718
  it("should error if durable_objects is an array", () => {
600
719
  const { config, diagnostics } = normalizeAndValidateConfig(
601
720
  { durable_objects: [] } as unknown as RawConfig,
602
- undefined
721
+ undefined,
722
+ { env: undefined }
603
723
  );
604
724
 
605
725
  expect(config).toEqual(
@@ -615,7 +735,8 @@ describe("normalizeAndValidateConfig()", () => {
615
735
  it("should error if durable_objects is a string", () => {
616
736
  const { config, diagnostics } = normalizeAndValidateConfig(
617
737
  { durable_objects: "BAD" } as unknown as RawConfig,
618
- undefined
738
+ undefined,
739
+ { env: undefined }
619
740
  );
620
741
 
621
742
  expect(config).toEqual(
@@ -631,7 +752,8 @@ describe("normalizeAndValidateConfig()", () => {
631
752
  it("should error if durable_objects is a number", () => {
632
753
  const { config, diagnostics } = normalizeAndValidateConfig(
633
754
  { durable_objects: 999 } as unknown as RawConfig,
634
- undefined
755
+ undefined,
756
+ { env: undefined }
635
757
  );
636
758
 
637
759
  expect(config).toEqual(
@@ -647,7 +769,8 @@ describe("normalizeAndValidateConfig()", () => {
647
769
  it("should error if durable_objects is null", () => {
648
770
  const { config, diagnostics } = normalizeAndValidateConfig(
649
771
  { durable_objects: null } as unknown as RawConfig,
650
- undefined
772
+ undefined,
773
+ { env: undefined }
651
774
  );
652
775
 
653
776
  expect(config).toEqual(
@@ -663,7 +786,8 @@ describe("normalizeAndValidateConfig()", () => {
663
786
  it("should error if durable_objects.bindings is not defined", () => {
664
787
  const { config, diagnostics } = normalizeAndValidateConfig(
665
788
  { durable_objects: {} } as unknown as RawConfig,
666
- undefined
789
+ undefined,
790
+ { env: undefined }
667
791
  );
668
792
 
669
793
  expect(config).toEqual(
@@ -679,7 +803,8 @@ describe("normalizeAndValidateConfig()", () => {
679
803
  it("should error if durable_objects.bindings is an object", () => {
680
804
  const { config, diagnostics } = normalizeAndValidateConfig(
681
805
  { durable_objects: { bindings: {} } } as unknown as RawConfig,
682
- undefined
806
+ undefined,
807
+ { env: undefined }
683
808
  );
684
809
 
685
810
  expect(config).toEqual(
@@ -697,7 +822,8 @@ describe("normalizeAndValidateConfig()", () => {
697
822
  it("should error if durable_objects.bindings is a string", () => {
698
823
  const { config, diagnostics } = normalizeAndValidateConfig(
699
824
  { durable_objects: { bindings: "BAD" } } as unknown as RawConfig,
700
- undefined
825
+ undefined,
826
+ { env: undefined }
701
827
  );
702
828
 
703
829
  expect(config).toEqual(
@@ -715,7 +841,8 @@ describe("normalizeAndValidateConfig()", () => {
715
841
  it("should error if durable_objects.bindings is a number", () => {
716
842
  const { config, diagnostics } = normalizeAndValidateConfig(
717
843
  { durable_objects: { bindings: 999 } } as unknown as RawConfig,
718
- undefined
844
+ undefined,
845
+ { env: undefined }
719
846
  );
720
847
 
721
848
  expect(config).toEqual(
@@ -733,7 +860,8 @@ describe("normalizeAndValidateConfig()", () => {
733
860
  it("should error if durable_objects.bindings is null", () => {
734
861
  const { config, diagnostics } = normalizeAndValidateConfig(
735
862
  { durable_objects: { bindings: null } } as unknown as RawConfig,
736
- undefined
863
+ undefined,
864
+ { env: undefined }
737
865
  );
738
866
 
739
867
  expect(config).toEqual(
@@ -764,7 +892,8 @@ describe("normalizeAndValidateConfig()", () => {
764
892
  ],
765
893
  },
766
894
  } as unknown as RawConfig,
767
- undefined
895
+ undefined,
896
+ { env: undefined }
768
897
  );
769
898
 
770
899
  expect(config).toEqual(
@@ -799,7 +928,8 @@ describe("normalizeAndValidateConfig()", () => {
799
928
  it("should error if kv_namespaces is an object", () => {
800
929
  const { config, diagnostics } = normalizeAndValidateConfig(
801
930
  { kv_namespaces: {} } as unknown as RawConfig,
802
- undefined
931
+ undefined,
932
+ { env: undefined }
803
933
  );
804
934
 
805
935
  expect(config).toEqual(
@@ -815,7 +945,8 @@ describe("normalizeAndValidateConfig()", () => {
815
945
  it("should error if kv_namespaces is a string", () => {
816
946
  const { config, diagnostics } = normalizeAndValidateConfig(
817
947
  { kv_namespaces: "BAD" } as unknown as RawConfig,
818
- undefined
948
+ undefined,
949
+ { env: undefined }
819
950
  );
820
951
 
821
952
  expect(config).toEqual(
@@ -831,7 +962,8 @@ describe("normalizeAndValidateConfig()", () => {
831
962
  it("should error if kv_namespaces is a number", () => {
832
963
  const { config, diagnostics } = normalizeAndValidateConfig(
833
964
  { kv_namespaces: 999 } as unknown as RawConfig,
834
- undefined
965
+ undefined,
966
+ { env: undefined }
835
967
  );
836
968
 
837
969
  expect(config).toEqual(
@@ -847,7 +979,8 @@ describe("normalizeAndValidateConfig()", () => {
847
979
  it("should error if kv_namespaces is null", () => {
848
980
  const { config, diagnostics } = normalizeAndValidateConfig(
849
981
  { kv_namespaces: null } as unknown as RawConfig,
850
- undefined
982
+ undefined,
983
+ { env: undefined }
851
984
  );
852
985
 
853
986
  expect(config).toEqual(
@@ -874,7 +1007,8 @@ describe("normalizeAndValidateConfig()", () => {
874
1007
  },
875
1008
  ],
876
1009
  } as unknown as RawConfig,
877
- undefined
1010
+ undefined,
1011
+ { env: undefined }
878
1012
  );
879
1013
 
880
1014
  expect(config).toEqual(
@@ -899,7 +1033,8 @@ describe("normalizeAndValidateConfig()", () => {
899
1033
  it("should error if r2_buckets is an object", () => {
900
1034
  const { config, diagnostics } = normalizeAndValidateConfig(
901
1035
  { r2_buckets: {} } as unknown as RawConfig,
902
- undefined
1036
+ undefined,
1037
+ { env: undefined }
903
1038
  );
904
1039
 
905
1040
  expect(config).toEqual(
@@ -915,7 +1050,8 @@ describe("normalizeAndValidateConfig()", () => {
915
1050
  it("should error if r2_buckets is a string", () => {
916
1051
  const { config, diagnostics } = normalizeAndValidateConfig(
917
1052
  { r2_buckets: "BAD" } as unknown as RawConfig,
918
- undefined
1053
+ undefined,
1054
+ { env: undefined }
919
1055
  );
920
1056
 
921
1057
  expect(config).toEqual(
@@ -931,7 +1067,8 @@ describe("normalizeAndValidateConfig()", () => {
931
1067
  it("should error if r2_buckets is a number", () => {
932
1068
  const { config, diagnostics } = normalizeAndValidateConfig(
933
1069
  { r2_buckets: 999 } as unknown as RawConfig,
934
- undefined
1070
+ undefined,
1071
+ { env: undefined }
935
1072
  );
936
1073
 
937
1074
  expect(config).toEqual(
@@ -947,7 +1084,8 @@ describe("normalizeAndValidateConfig()", () => {
947
1084
  it("should error if r2_buckets is null", () => {
948
1085
  const { config, diagnostics } = normalizeAndValidateConfig(
949
1086
  { r2_buckets: null } as unknown as RawConfig,
950
- undefined
1087
+ undefined,
1088
+ { env: undefined }
951
1089
  );
952
1090
 
953
1091
  expect(config).toEqual(
@@ -974,7 +1112,8 @@ describe("normalizeAndValidateConfig()", () => {
974
1112
  },
975
1113
  ],
976
1114
  } as unknown as RawConfig,
977
- undefined
1115
+ undefined,
1116
+ { env: undefined }
978
1117
  );
979
1118
 
980
1119
  expect(config).toEqual(
@@ -999,7 +1138,8 @@ describe("normalizeAndValidateConfig()", () => {
999
1138
  it("should error if unsafe is an array", () => {
1000
1139
  const { config, diagnostics } = normalizeAndValidateConfig(
1001
1140
  { unsafe: [] } as unknown as RawConfig,
1002
- undefined
1141
+ undefined,
1142
+ { env: undefined }
1003
1143
  );
1004
1144
 
1005
1145
  expect(config).toEqual(
@@ -1018,7 +1158,8 @@ describe("normalizeAndValidateConfig()", () => {
1018
1158
  it("should error if unsafe is a string", () => {
1019
1159
  const { config, diagnostics } = normalizeAndValidateConfig(
1020
1160
  { unsafe: "BAD" } as unknown as RawConfig,
1021
- undefined
1161
+ undefined,
1162
+ { env: undefined }
1022
1163
  );
1023
1164
 
1024
1165
  expect(config).toEqual(
@@ -1037,7 +1178,8 @@ describe("normalizeAndValidateConfig()", () => {
1037
1178
  it("should error if unsafe is a number", () => {
1038
1179
  const { config, diagnostics } = normalizeAndValidateConfig(
1039
1180
  { unsafe: 999 } as unknown as RawConfig,
1040
- undefined
1181
+ undefined,
1182
+ { env: undefined }
1041
1183
  );
1042
1184
 
1043
1185
  expect(config).toEqual(
@@ -1056,7 +1198,8 @@ describe("normalizeAndValidateConfig()", () => {
1056
1198
  it("should error if unsafe is null", () => {
1057
1199
  const { config, diagnostics } = normalizeAndValidateConfig(
1058
1200
  { unsafe: null } as unknown as RawConfig,
1059
- undefined
1201
+ undefined,
1202
+ { env: undefined }
1060
1203
  );
1061
1204
 
1062
1205
  expect(config).toEqual(
@@ -1075,7 +1218,8 @@ describe("normalizeAndValidateConfig()", () => {
1075
1218
  it("should error if unsafe.bindings is not defined", () => {
1076
1219
  const { config, diagnostics } = normalizeAndValidateConfig(
1077
1220
  { unsafe: {} } as unknown as RawConfig,
1078
- undefined
1221
+ undefined,
1222
+ { env: undefined }
1079
1223
  );
1080
1224
 
1081
1225
  expect(config).toEqual(
@@ -1094,7 +1238,8 @@ describe("normalizeAndValidateConfig()", () => {
1094
1238
  it("should error if unsafe.bindings is an object", () => {
1095
1239
  const { config, diagnostics } = normalizeAndValidateConfig(
1096
1240
  { unsafe: { bindings: {} } } as unknown as RawConfig,
1097
- undefined
1241
+ undefined,
1242
+ { env: undefined }
1098
1243
  );
1099
1244
 
1100
1245
  expect(config).toEqual(
@@ -1115,7 +1260,8 @@ describe("normalizeAndValidateConfig()", () => {
1115
1260
  it("should error if unsafe.bindings is a string", () => {
1116
1261
  const { config, diagnostics } = normalizeAndValidateConfig(
1117
1262
  { unsafe: { bindings: "BAD" } } as unknown as RawConfig,
1118
- undefined
1263
+ undefined,
1264
+ { env: undefined }
1119
1265
  );
1120
1266
 
1121
1267
  expect(config).toEqual(
@@ -1136,7 +1282,8 @@ describe("normalizeAndValidateConfig()", () => {
1136
1282
  it("should error if unsafe.bindings is a number", () => {
1137
1283
  const { config, diagnostics } = normalizeAndValidateConfig(
1138
1284
  { unsafe: { bindings: 999 } } as unknown as RawConfig,
1139
- undefined
1285
+ undefined,
1286
+ { env: undefined }
1140
1287
  );
1141
1288
 
1142
1289
  expect(config).toEqual(
@@ -1157,7 +1304,8 @@ describe("normalizeAndValidateConfig()", () => {
1157
1304
  it("should error if unsafe.bindings is null", () => {
1158
1305
  const { config, diagnostics } = normalizeAndValidateConfig(
1159
1306
  { unsafe: { bindings: null } } as unknown as RawConfig,
1160
- undefined
1307
+ undefined,
1308
+ { env: undefined }
1161
1309
  );
1162
1310
 
1163
1311
  expect(config).toEqual(
@@ -1191,7 +1339,8 @@ describe("normalizeAndValidateConfig()", () => {
1191
1339
  ],
1192
1340
  },
1193
1341
  } as unknown as RawConfig,
1194
- undefined
1342
+ undefined,
1343
+ { env: undefined }
1195
1344
  );
1196
1345
 
1197
1346
  expect(config).toEqual(
@@ -1235,7 +1384,8 @@ describe("normalizeAndValidateConfig()", () => {
1235
1384
 
1236
1385
  const { config, diagnostics } = normalizeAndValidateConfig(
1237
1386
  rawConfig,
1238
- undefined
1387
+ undefined,
1388
+ { env: undefined }
1239
1389
  );
1240
1390
 
1241
1391
  expect("experimental_services" in config).toBe(false);
@@ -1259,75 +1409,247 @@ describe("normalizeAndValidateConfig()", () => {
1259
1409
  `);
1260
1410
  });
1261
1411
  });
1412
+
1413
+ describe("route & routes fields", () => {
1414
+ it("should error if both route and routes are specified", () => {
1415
+ const rawConfig: RawConfig = {
1416
+ route: "route1",
1417
+ routes: ["route2", "route3"],
1418
+ };
1419
+
1420
+ const { diagnostics } = normalizeAndValidateConfig(
1421
+ rawConfig,
1422
+ undefined,
1423
+ { env: undefined }
1424
+ );
1425
+
1426
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1427
+ "Processing wrangler configuration:
1428
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
1429
+ `);
1430
+ });
1431
+ });
1262
1432
  });
1263
1433
 
1264
1434
  describe("named environments", () => {
1435
+ it("should warn if we specify an environment but there are no named environments", () => {
1436
+ const rawConfig: RawConfig = {};
1437
+ const { diagnostics } = normalizeAndValidateConfig(rawConfig, undefined, {
1438
+ env: "DEV",
1439
+ });
1440
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1441
+ "Processing wrangler configuration:
1442
+ "
1443
+ `);
1444
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1445
+ "Processing wrangler configuration:
1446
+ - No environment found in configuration with name \\"DEV\\".
1447
+ Before using \`--env=DEV\` there should be an equivalent environment section in the configuration.
1448
+
1449
+ Consider adding an environment configuration section to the wrangler.toml file:
1450
+ \`\`\`
1451
+ [env.DEV]
1452
+ \`\`\`
1453
+ "
1454
+ `);
1455
+ });
1456
+
1457
+ it("should error if we specify an environment that does not match the named environments", () => {
1458
+ const rawConfig: RawConfig = { env: { ENV1: {} } };
1459
+ const { diagnostics } = normalizeAndValidateConfig(rawConfig, undefined, {
1460
+ env: "DEV",
1461
+ });
1462
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1463
+ "Processing wrangler configuration:
1464
+ - No environment found in configuration with name \\"DEV\\".
1465
+ Before using \`--env=DEV\` there should be an equivalent environment section in the configuration.
1466
+ The available configured environment names are: [\\"ENV1\\"]
1467
+
1468
+ Consider adding an environment configuration section to the wrangler.toml file:
1469
+ \`\`\`
1470
+ [env.DEV]
1471
+ \`\`\`
1472
+ "
1473
+ `);
1474
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1475
+ "Processing wrangler configuration:
1476
+ "
1477
+ `);
1478
+ });
1479
+
1265
1480
  it("should use top-level values for inheritable config fields", () => {
1266
- const expectedConfig: RawConfig = {
1481
+ const main = "src/index.ts";
1482
+ const resolvedMain = path.resolve(process.cwd(), main);
1483
+ const rawConfig: RawConfig = {
1267
1484
  name: "NAME",
1268
1485
  account_id: "ACCOUNT_ID",
1269
1486
  compatibility_date: "2022-01-01",
1270
1487
  compatibility_flags: ["FLAG1", "FLAG2"],
1271
1488
  workers_dev: false,
1272
1489
  routes: ["ROUTE_1", "ROUTE_2"],
1273
- route: "ROUTE_3",
1274
1490
  jsx_factory: "JSX_FACTORY",
1275
1491
  jsx_fragment: "JSX_FRAGMENT",
1492
+ tsconfig: "path/to/tsconfig.json",
1276
1493
  triggers: { crons: ["CRON_1", "CRON_2"] },
1277
1494
  usage_model: "bundled",
1495
+ main,
1496
+ build: {
1497
+ command: "COMMAND",
1498
+ cwd: "CWD",
1499
+ watch_dir: "WATCH_DIR",
1500
+ },
1278
1501
  };
1279
1502
 
1280
1503
  const { config, diagnostics } = normalizeAndValidateConfig(
1281
- { ...expectedConfig, env: { DEV: {} } },
1282
- undefined
1504
+ { ...rawConfig, env: { DEV: {} } },
1505
+ undefined,
1506
+ { env: "DEV" }
1283
1507
  );
1284
1508
 
1285
- expect(config.env.DEV).toEqual(expect.objectContaining(expectedConfig));
1509
+ expect(config).toEqual(
1510
+ expect.objectContaining({
1511
+ ...rawConfig,
1512
+ main: resolvedMain,
1513
+ name: "NAME-DEV",
1514
+ })
1515
+ );
1286
1516
  expect(diagnostics.hasErrors()).toBe(false);
1287
1517
  expect(diagnostics.hasWarnings()).toBe(false);
1288
1518
  });
1289
1519
 
1290
1520
  it("should override top-level values for inheritable config fields", () => {
1291
- const environment: RawEnvironment = {
1521
+ const main = "src/index.ts";
1522
+ const resolvedMain = path.resolve(process.cwd(), main);
1523
+ const rawEnv: RawEnvironment = {
1292
1524
  name: "ENV_NAME",
1293
1525
  account_id: "ENV_ACCOUNT_ID",
1294
1526
  compatibility_date: "2022-02-02",
1295
1527
  compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
1296
1528
  workers_dev: true,
1297
1529
  routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
1298
- route: "ENV_ROUTE_3",
1299
1530
  jsx_factory: "ENV_JSX_FACTORY",
1300
1531
  jsx_fragment: "ENV_JSX_FRAGMENT",
1532
+ tsconfig: "ENV_path/to/tsconfig.json",
1301
1533
  triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
1302
1534
  usage_model: "unbound",
1535
+ main,
1536
+ build: {
1537
+ command: "ENV_COMMAND",
1538
+ cwd: "ENV_CWD",
1539
+ watch_dir: "ENV_WATCH_DIR",
1540
+ },
1303
1541
  };
1304
- const expectedConfig: RawConfig = {
1542
+ const rawConfig: RawConfig = {
1305
1543
  name: "NAME",
1306
1544
  account_id: "ACCOUNT_ID",
1307
1545
  compatibility_date: "2022-01-01",
1308
1546
  compatibility_flags: ["FLAG1", "FLAG2"],
1309
1547
  workers_dev: false,
1310
1548
  routes: ["ROUTE_1", "ROUTE_2"],
1311
- route: "ROUTE_3",
1312
1549
  jsx_factory: "JSX_FACTORY",
1313
1550
  jsx_fragment: "JSX_FRAGMENT",
1551
+ tsconfig: "path/to/tsconfig.json",
1314
1552
  triggers: { crons: ["CRON_1", "CRON_2"] },
1315
1553
  usage_model: "bundled",
1554
+ main: "top-level.js",
1555
+ build: {
1556
+ command: "COMMAND",
1557
+ cwd: "CWD",
1558
+ watch_dir: "WATCH_DIR",
1559
+ },
1316
1560
  env: {
1317
- ENV1: environment,
1561
+ ENV1: rawEnv,
1318
1562
  },
1319
1563
  };
1320
1564
 
1321
1565
  const { config, diagnostics } = normalizeAndValidateConfig(
1322
- expectedConfig,
1323
- undefined
1566
+ rawConfig,
1567
+ undefined,
1568
+ { env: "ENV1" }
1324
1569
  );
1325
1570
 
1326
- expect(config.env.ENV1).toEqual(expect.objectContaining(environment));
1571
+ expect(config).toEqual(
1572
+ expect.objectContaining({ ...rawEnv, main: resolvedMain })
1573
+ );
1327
1574
  expect(diagnostics.hasErrors()).toBe(false);
1328
1575
  expect(diagnostics.hasWarnings()).toBe(false);
1329
1576
  });
1330
1577
 
1578
+ describe("non-legacy", () => {
1579
+ it("should use top-level `name` field", () => {
1580
+ const rawConfig: RawConfig = {
1581
+ name: "NAME",
1582
+ legacy_env: false,
1583
+ env: { DEV: {} },
1584
+ };
1585
+
1586
+ const { config, diagnostics } = normalizeAndValidateConfig(
1587
+ rawConfig,
1588
+ undefined,
1589
+ { env: "DEV" }
1590
+ );
1591
+
1592
+ expect(config.name).toEqual("NAME");
1593
+ expect(diagnostics.hasErrors()).toBe(false);
1594
+ expect(diagnostics.hasWarnings()).toBe(false);
1595
+ });
1596
+
1597
+ it("should error if named environment contains a `name` field, even if there is no top-level name", () => {
1598
+ const rawConfig: RawConfig = {
1599
+ legacy_env: false,
1600
+ env: {
1601
+ DEV: {
1602
+ name: "ENV_NAME",
1603
+ },
1604
+ },
1605
+ };
1606
+
1607
+ const { config, diagnostics } = normalizeAndValidateConfig(
1608
+ rawConfig,
1609
+ undefined,
1610
+ { env: "DEV" }
1611
+ );
1612
+
1613
+ expect(config.name).toBeUndefined();
1614
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1615
+ "Processing wrangler configuration:
1616
+
1617
+ - \\"env.DEV\\" environment configuration
1618
+ - The \\"name\\" field is not allowed in named service environments.
1619
+ Please remove the field from this environment."
1620
+ `);
1621
+ expect(diagnostics.hasWarnings()).toBe(false);
1622
+ });
1623
+
1624
+ it("should error if top-level config and a named environment both contain a `name` field", () => {
1625
+ const rawConfig: RawConfig = {
1626
+ name: "NAME",
1627
+ legacy_env: false,
1628
+ env: {
1629
+ DEV: {
1630
+ name: "ENV_NAME",
1631
+ },
1632
+ },
1633
+ };
1634
+
1635
+ const { config, diagnostics } = normalizeAndValidateConfig(
1636
+ rawConfig,
1637
+ undefined,
1638
+ { env: "DEV" }
1639
+ );
1640
+
1641
+ expect(config.name).toEqual("NAME");
1642
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1643
+ "Processing wrangler configuration:
1644
+
1645
+ - \\"env.DEV\\" environment configuration
1646
+ - The \\"name\\" field is not allowed in named service environments.
1647
+ Please remove the field from this environment."
1648
+ `);
1649
+ expect(diagnostics.hasWarnings()).toBe(false);
1650
+ });
1651
+ });
1652
+
1331
1653
  it("should warn for non-inherited fields that are missing in environments", () => {
1332
1654
  const vars: RawConfig["vars"] = {
1333
1655
  FOO: "foo",
@@ -1351,10 +1673,11 @@ describe("normalizeAndValidateConfig()", () => {
1351
1673
 
1352
1674
  const { config, diagnostics } = normalizeAndValidateConfig(
1353
1675
  rawConfig,
1354
- undefined
1676
+ undefined,
1677
+ { env: "ENV1" }
1355
1678
  );
1356
1679
 
1357
- expect(config.env.ENV1).toEqual(
1680
+ expect(config).toEqual(
1358
1681
  expect.not.objectContaining({
1359
1682
  vars,
1360
1683
  durable_objects,
@@ -1397,30 +1720,44 @@ describe("normalizeAndValidateConfig()", () => {
1397
1720
  route: 888,
1398
1721
  jsx_factory: 999,
1399
1722
  jsx_fragment: 1000,
1723
+ tsconfig: 123,
1400
1724
  triggers: { crons: [1111, 1222] },
1401
1725
  usage_model: "INVALID",
1726
+ main: 1333,
1727
+ build: {
1728
+ command: 1444,
1729
+ cwd: 1555,
1730
+ watch_dir: 1666,
1731
+ },
1402
1732
  } as unknown as RawEnvironment;
1403
1733
 
1404
1734
  const { config, diagnostics } = normalizeAndValidateConfig(
1405
1735
  { env: { ENV1: expectedConfig } },
1406
- undefined
1736
+ undefined,
1737
+ { env: "ENV1" }
1407
1738
  );
1408
1739
 
1409
- expect(config.env.ENV1).toEqual(expect.objectContaining(expectedConfig));
1740
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
1410
1741
  expect(diagnostics.hasWarnings()).toBe(false);
1411
1742
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1412
1743
  "Processing wrangler configuration:
1413
1744
 
1414
1745
  - \\"env.ENV1\\" environment configuration
1415
- - Expected \\"route\\" field to be a string but got 888.
1416
- - Expected \\"routes\\" field to be an array of strings but got [666,777].
1417
- - Expected \\"workers_dev\\" field to be a boolean but got \\"BAD\\".
1418
- - Expected \\"account_id\\" field to be a string but got 222.
1419
- - Expected \\"compatibility_date\\" field to be a string but got 333.
1420
- - Expected \\"compatibility_flags\\" field to be an array of strings but got [444,555].
1421
- - Expected \\"jsx_factory\\" field to be a string but got 999.
1422
- - Expected \\"jsx_fragment\\" field to be a string but got 1000.
1423
- - Expected \\"name\\" field to be a string but got 111.
1746
+ - Expected \\"route\\" to be of type string but got 888.
1747
+ - Expected \\"routes\\" to be of type string array but got [666,777].
1748
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"].
1749
+ - Expected \\"workers_dev\\" to be of type boolean but got \\"BAD\\".
1750
+ - Expected \\"build.command\\" to be of type string but got 1444.
1751
+ - Expected \\"build.cwd\\" to be of type string but got 1555.
1752
+ - Expected \\"build.watch_dir\\" to be of type string but got 1666.
1753
+ - Expected \\"account_id\\" to be of type string but got 222.
1754
+ - Expected \\"compatibility_date\\" to be of type string but got 333.
1755
+ - Expected \\"compatibility_flags\\" to be of type string array but got [444,555].
1756
+ - Expected \\"jsx_factory\\" to be of type string but got 999.
1757
+ - Expected \\"jsx_fragment\\" to be of type string but got 1000.
1758
+ - Expected \\"tsconfig\\" to be of type string but got 123.
1759
+ - Expected \\"name\\" to be of type string but got 111.
1760
+ - Expected \\"main\\" to be of type string but got 1333.
1424
1761
  - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
1425
1762
  `);
1426
1763
  });
@@ -1429,10 +1766,11 @@ describe("normalizeAndValidateConfig()", () => {
1429
1766
  it("should error if durable_objects is an array", () => {
1430
1767
  const { config, diagnostics } = normalizeAndValidateConfig(
1431
1768
  { env: { ENV1: { durable_objects: [] } } } as unknown as RawConfig,
1432
- undefined
1769
+ undefined,
1770
+ { env: "ENV1" }
1433
1771
  );
1434
1772
 
1435
- expect(config.env.ENV1).toEqual(
1773
+ expect(config).toEqual(
1436
1774
  expect.not.objectContaining({ durable_objects: expect.anything })
1437
1775
  );
1438
1776
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1447,10 +1785,11 @@ describe("normalizeAndValidateConfig()", () => {
1447
1785
  it("should error if durable_objects is a string", () => {
1448
1786
  const { config, diagnostics } = normalizeAndValidateConfig(
1449
1787
  { env: { ENV1: { durable_objects: "BAD" } } } as unknown as RawConfig,
1450
- undefined
1788
+ undefined,
1789
+ { env: "ENV1" }
1451
1790
  );
1452
1791
 
1453
- expect(config.env.ENV1).toEqual(
1792
+ expect(config).toEqual(
1454
1793
  expect.not.objectContaining({ durable_objects: expect.anything })
1455
1794
  );
1456
1795
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1465,10 +1804,11 @@ describe("normalizeAndValidateConfig()", () => {
1465
1804
  it("should error if durable_objects is a number", () => {
1466
1805
  const { config, diagnostics } = normalizeAndValidateConfig(
1467
1806
  { env: { ENV1: { durable_objects: 999 } } } as unknown as RawConfig,
1468
- undefined
1807
+ undefined,
1808
+ { env: "ENV1" }
1469
1809
  );
1470
1810
 
1471
- expect(config.env.ENV1).toEqual(
1811
+ expect(config).toEqual(
1472
1812
  expect.not.objectContaining({ durable_objects: expect.anything })
1473
1813
  );
1474
1814
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1483,10 +1823,11 @@ describe("normalizeAndValidateConfig()", () => {
1483
1823
  it("should error if durable_objects is null", () => {
1484
1824
  const { config, diagnostics } = normalizeAndValidateConfig(
1485
1825
  { env: { ENV1: { durable_objects: null } } } as unknown as RawConfig,
1486
- undefined
1826
+ undefined,
1827
+ { env: "ENV1" }
1487
1828
  );
1488
1829
 
1489
- expect(config.env.ENV1).toEqual(
1830
+ expect(config).toEqual(
1490
1831
  expect.not.objectContaining({ durable_objects: expect.anything })
1491
1832
  );
1492
1833
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1501,10 +1842,11 @@ describe("normalizeAndValidateConfig()", () => {
1501
1842
  it("should error if durable_objects.bindings is not defined", () => {
1502
1843
  const { config, diagnostics } = normalizeAndValidateConfig(
1503
1844
  { env: { ENV1: { durable_objects: {} } } } as unknown as RawConfig,
1504
- undefined
1845
+ undefined,
1846
+ { env: "ENV1" }
1505
1847
  );
1506
1848
 
1507
- expect(config.env.ENV1).toEqual(
1849
+ expect(config).toEqual(
1508
1850
  expect.not.objectContaining({ durable_objects: expect.anything })
1509
1851
  );
1510
1852
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1521,10 +1863,11 @@ describe("normalizeAndValidateConfig()", () => {
1521
1863
  {
1522
1864
  env: { ENV1: { durable_objects: { bindings: {} } } },
1523
1865
  } as unknown as RawConfig,
1524
- undefined
1866
+ undefined,
1867
+ { env: "ENV1" }
1525
1868
  );
1526
1869
 
1527
- expect(config.env.ENV1).toEqual(
1870
+ expect(config).toEqual(
1528
1871
  expect.not.objectContaining({
1529
1872
  durable_objects: { bindings: expect.anything },
1530
1873
  })
@@ -1543,10 +1886,11 @@ describe("normalizeAndValidateConfig()", () => {
1543
1886
  {
1544
1887
  env: { ENV1: { durable_objects: { bindings: "BAD" } } },
1545
1888
  } as unknown as RawConfig,
1546
- undefined
1889
+ undefined,
1890
+ { env: "ENV1" }
1547
1891
  );
1548
1892
 
1549
- expect(config.env.ENV1).toEqual(
1893
+ expect(config).toEqual(
1550
1894
  expect.not.objectContaining({
1551
1895
  durable_objects: { bindings: expect.anything },
1552
1896
  })
@@ -1565,10 +1909,11 @@ describe("normalizeAndValidateConfig()", () => {
1565
1909
  {
1566
1910
  env: { ENV1: { durable_objects: { bindings: 999 } } },
1567
1911
  } as unknown as RawConfig,
1568
- undefined
1912
+ undefined,
1913
+ { env: "ENV1" }
1569
1914
  );
1570
1915
 
1571
- expect(config.env.ENV1).toEqual(
1916
+ expect(config).toEqual(
1572
1917
  expect.not.objectContaining({
1573
1918
  durable_objects: { bindings: expect.anything },
1574
1919
  })
@@ -1587,10 +1932,11 @@ describe("normalizeAndValidateConfig()", () => {
1587
1932
  {
1588
1933
  env: { ENV1: { durable_objects: { bindings: null } } },
1589
1934
  } as unknown as RawConfig,
1590
- undefined
1935
+ undefined,
1936
+ { env: "ENV1" }
1591
1937
  );
1592
1938
 
1593
- expect(config.env.ENV1).toEqual(
1939
+ expect(config).toEqual(
1594
1940
  expect.not.objectContaining({
1595
1941
  durable_objects: { bindings: expect.anything },
1596
1942
  })
@@ -1624,10 +1970,11 @@ describe("normalizeAndValidateConfig()", () => {
1624
1970
  },
1625
1971
  },
1626
1972
  } as unknown as RawConfig,
1627
- undefined
1973
+ undefined,
1974
+ { env: "ENV1" }
1628
1975
  );
1629
1976
 
1630
- expect(config.env.ENV1).toEqual(
1977
+ expect(config).toEqual(
1631
1978
  expect.not.objectContaining({
1632
1979
  durable_objects: { bindings: expect.anything },
1633
1980
  })
@@ -1661,10 +2008,11 @@ describe("normalizeAndValidateConfig()", () => {
1661
2008
  it("should error if kv_namespaces is an object", () => {
1662
2009
  const { config, diagnostics } = normalizeAndValidateConfig(
1663
2010
  { env: { ENV1: { kv_namespaces: {} } } } as unknown as RawConfig,
1664
- undefined
2011
+ undefined,
2012
+ { env: "ENV1" }
1665
2013
  );
1666
2014
 
1667
- expect(config.env.ENV1).toEqual(
2015
+ expect(config).toEqual(
1668
2016
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1669
2017
  );
1670
2018
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1679,10 +2027,11 @@ describe("normalizeAndValidateConfig()", () => {
1679
2027
  it("should error if kv_namespaces is a string", () => {
1680
2028
  const { config, diagnostics } = normalizeAndValidateConfig(
1681
2029
  { env: { ENV1: { kv_namespaces: "BAD" } } } as unknown as RawConfig,
1682
- undefined
2030
+ undefined,
2031
+ { env: "ENV1" }
1683
2032
  );
1684
2033
 
1685
- expect(config.env.ENV1).toEqual(
2034
+ expect(config).toEqual(
1686
2035
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1687
2036
  );
1688
2037
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1697,10 +2046,11 @@ describe("normalizeAndValidateConfig()", () => {
1697
2046
  it("should error if kv_namespaces is a number", () => {
1698
2047
  const { config, diagnostics } = normalizeAndValidateConfig(
1699
2048
  { env: { ENV1: { kv_namespaces: 999 } } } as unknown as RawConfig,
1700
- undefined
2049
+ undefined,
2050
+ { env: "ENV1" }
1701
2051
  );
1702
2052
 
1703
- expect(config.env.ENV1).toEqual(
2053
+ expect(config).toEqual(
1704
2054
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1705
2055
  );
1706
2056
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1715,10 +2065,11 @@ describe("normalizeAndValidateConfig()", () => {
1715
2065
  it("should error if kv_namespaces is null", () => {
1716
2066
  const { config, diagnostics } = normalizeAndValidateConfig(
1717
2067
  { env: { ENV1: { kv_namespaces: null } } } as unknown as RawConfig,
1718
- undefined
2068
+ undefined,
2069
+ { env: "ENV1" }
1719
2070
  );
1720
2071
 
1721
- expect(config.env.ENV1).toEqual(
2072
+ expect(config).toEqual(
1722
2073
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1723
2074
  );
1724
2075
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1748,10 +2099,11 @@ describe("normalizeAndValidateConfig()", () => {
1748
2099
  },
1749
2100
  },
1750
2101
  } as unknown as RawConfig,
1751
- undefined
2102
+ undefined,
2103
+ { env: "ENV1" }
1752
2104
  );
1753
2105
 
1754
- expect(config.env.ENV1).toEqual(
2106
+ expect(config).toEqual(
1755
2107
  expect.not.objectContaining({
1756
2108
  kv_namespaces: { bindings: expect.anything },
1757
2109
  })
@@ -1775,10 +2127,11 @@ describe("normalizeAndValidateConfig()", () => {
1775
2127
  it("should error if r2_buckets is an object", () => {
1776
2128
  const { config, diagnostics } = normalizeAndValidateConfig(
1777
2129
  { env: { ENV1: { r2_buckets: {} } } } as unknown as RawConfig,
1778
- undefined
2130
+ undefined,
2131
+ { env: "ENV1" }
1779
2132
  );
1780
2133
 
1781
- expect(config.env.ENV1).toEqual(
2134
+ expect(config).toEqual(
1782
2135
  expect.not.objectContaining({ r2_buckets: expect.anything })
1783
2136
  );
1784
2137
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1793,10 +2146,11 @@ describe("normalizeAndValidateConfig()", () => {
1793
2146
  it("should error if r2_buckets is a string", () => {
1794
2147
  const { config, diagnostics } = normalizeAndValidateConfig(
1795
2148
  { env: { ENV1: { r2_buckets: "BAD" } } } as unknown as RawConfig,
1796
- undefined
2149
+ undefined,
2150
+ { env: "ENV1" }
1797
2151
  );
1798
2152
 
1799
- expect(config.env.ENV1).toEqual(
2153
+ expect(config).toEqual(
1800
2154
  expect.not.objectContaining({ r2_buckets: expect.anything })
1801
2155
  );
1802
2156
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1811,10 +2165,11 @@ describe("normalizeAndValidateConfig()", () => {
1811
2165
  it("should error if r2_buckets is a number", () => {
1812
2166
  const { config, diagnostics } = normalizeAndValidateConfig(
1813
2167
  { env: { ENV1: { r2_buckets: 999 } } } as unknown as RawConfig,
1814
- undefined
2168
+ undefined,
2169
+ { env: "ENV1" }
1815
2170
  );
1816
2171
 
1817
- expect(config.env.ENV1).toEqual(
2172
+ expect(config).toEqual(
1818
2173
  expect.not.objectContaining({ r2_buckets: expect.anything })
1819
2174
  );
1820
2175
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1829,10 +2184,11 @@ describe("normalizeAndValidateConfig()", () => {
1829
2184
  it("should error if r2_buckets is null", () => {
1830
2185
  const { config, diagnostics } = normalizeAndValidateConfig(
1831
2186
  { env: { ENV1: { r2_buckets: null } } } as unknown as RawConfig,
1832
- undefined
2187
+ undefined,
2188
+ { env: "ENV1" }
1833
2189
  );
1834
2190
 
1835
- expect(config.env.ENV1).toEqual(
2191
+ expect(config).toEqual(
1836
2192
  expect.not.objectContaining({ r2_buckets: expect.anything })
1837
2193
  );
1838
2194
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1862,10 +2218,11 @@ describe("normalizeAndValidateConfig()", () => {
1862
2218
  },
1863
2219
  },
1864
2220
  } as unknown as RawConfig,
1865
- undefined
2221
+ undefined,
2222
+ { env: "ENV1" }
1866
2223
  );
1867
2224
 
1868
- expect(config.env.ENV1).toEqual(
2225
+ expect(config).toEqual(
1869
2226
  expect.not.objectContaining({
1870
2227
  r2_buckets: { bindings: expect.anything },
1871
2228
  })
@@ -1889,10 +2246,11 @@ describe("normalizeAndValidateConfig()", () => {
1889
2246
  it("should error if unsafe is an array", () => {
1890
2247
  const { config, diagnostics } = normalizeAndValidateConfig(
1891
2248
  { env: { ENV1: { unsafe: [] } } } as unknown as RawConfig,
1892
- undefined
2249
+ undefined,
2250
+ { env: "ENV1" }
1893
2251
  );
1894
2252
 
1895
- expect(config.env.ENV1).toEqual(
2253
+ expect(config).toEqual(
1896
2254
  expect.not.objectContaining({ unsafe: expect.anything })
1897
2255
  );
1898
2256
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1912,10 +2270,11 @@ describe("normalizeAndValidateConfig()", () => {
1912
2270
  it("should error if unsafe is a string", () => {
1913
2271
  const { config, diagnostics } = normalizeAndValidateConfig(
1914
2272
  { env: { ENV1: { unsafe: "BAD" } } } as unknown as RawConfig,
1915
- undefined
2273
+ undefined,
2274
+ { env: "ENV1" }
1916
2275
  );
1917
2276
 
1918
- expect(config.env.ENV1).toEqual(
2277
+ expect(config).toEqual(
1919
2278
  expect.not.objectContaining({ unsafe: expect.anything })
1920
2279
  );
1921
2280
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1935,10 +2294,11 @@ describe("normalizeAndValidateConfig()", () => {
1935
2294
  it("should error if unsafe is a number", () => {
1936
2295
  const { config, diagnostics } = normalizeAndValidateConfig(
1937
2296
  { env: { ENV1: { unsafe: 999 } } } as unknown as RawConfig,
1938
- undefined
2297
+ undefined,
2298
+ { env: "ENV1" }
1939
2299
  );
1940
2300
 
1941
- expect(config.env.ENV1).toEqual(
2301
+ expect(config).toEqual(
1942
2302
  expect.not.objectContaining({ unsafe: expect.anything })
1943
2303
  );
1944
2304
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1958,10 +2318,11 @@ describe("normalizeAndValidateConfig()", () => {
1958
2318
  it("should error if unsafe is null", () => {
1959
2319
  const { config, diagnostics } = normalizeAndValidateConfig(
1960
2320
  { env: { ENV1: { unsafe: null } } } as unknown as RawConfig,
1961
- undefined
2321
+ undefined,
2322
+ { env: "ENV1" }
1962
2323
  );
1963
2324
 
1964
- expect(config.env.ENV1).toEqual(
2325
+ expect(config).toEqual(
1965
2326
  expect.not.objectContaining({ unsafe: expect.anything })
1966
2327
  );
1967
2328
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1981,10 +2342,11 @@ describe("normalizeAndValidateConfig()", () => {
1981
2342
  it("should error if unsafe.bindings is not defined", () => {
1982
2343
  const { config, diagnostics } = normalizeAndValidateConfig(
1983
2344
  { env: { ENV1: { unsafe: {} } } } as unknown as RawConfig,
1984
- undefined
2345
+ undefined,
2346
+ { env: "ENV1" }
1985
2347
  );
1986
2348
 
1987
- expect(config.env.ENV1).toEqual(
2349
+ expect(config).toEqual(
1988
2350
  expect.not.objectContaining({ unsafe: expect.anything })
1989
2351
  );
1990
2352
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -2006,10 +2368,11 @@ describe("normalizeAndValidateConfig()", () => {
2006
2368
  {
2007
2369
  env: { ENV1: { unsafe: { bindings: {} } } },
2008
2370
  } as unknown as RawConfig,
2009
- undefined
2371
+ undefined,
2372
+ { env: "ENV1" }
2010
2373
  );
2011
2374
 
2012
- expect(config.env.ENV1).toEqual(
2375
+ expect(config).toEqual(
2013
2376
  expect.not.objectContaining({
2014
2377
  unsafe: { bindings: expect.anything },
2015
2378
  })
@@ -2033,10 +2396,11 @@ describe("normalizeAndValidateConfig()", () => {
2033
2396
  {
2034
2397
  env: { ENV1: { unsafe: { bindings: "BAD" } } },
2035
2398
  } as unknown as RawConfig,
2036
- undefined
2399
+ undefined,
2400
+ { env: "ENV1" }
2037
2401
  );
2038
2402
 
2039
- expect(config.env.ENV1).toEqual(
2403
+ expect(config).toEqual(
2040
2404
  expect.not.objectContaining({
2041
2405
  unsafe: { bindings: expect.anything },
2042
2406
  })
@@ -2060,10 +2424,11 @@ describe("normalizeAndValidateConfig()", () => {
2060
2424
  {
2061
2425
  env: { ENV1: { unsafe: { bindings: 999 } } },
2062
2426
  } as unknown as RawConfig,
2063
- undefined
2427
+ undefined,
2428
+ { env: "ENV1" }
2064
2429
  );
2065
2430
 
2066
- expect(config.env.ENV1).toEqual(
2431
+ expect(config).toEqual(
2067
2432
  expect.not.objectContaining({
2068
2433
  unsafe: { bindings: expect.anything },
2069
2434
  })
@@ -2087,10 +2452,11 @@ describe("normalizeAndValidateConfig()", () => {
2087
2452
  {
2088
2453
  env: { ENV1: { unsafe: { bindings: null } } },
2089
2454
  } as unknown as RawConfig,
2090
- undefined
2455
+ undefined,
2456
+ { env: "ENV1" }
2091
2457
  );
2092
2458
 
2093
- expect(config.env.ENV1).toEqual(
2459
+ expect(config).toEqual(
2094
2460
  expect.not.objectContaining({
2095
2461
  unsafe: { bindings: expect.anything },
2096
2462
  })
@@ -2129,10 +2495,11 @@ describe("normalizeAndValidateConfig()", () => {
2129
2495
  },
2130
2496
  },
2131
2497
  } as unknown as RawConfig,
2132
- undefined
2498
+ undefined,
2499
+ { env: "ENV1" }
2133
2500
  );
2134
2501
 
2135
- expect(config.env.ENV1).toEqual(
2502
+ expect(config).toEqual(
2136
2503
  expect.not.objectContaining({
2137
2504
  durable_objects: { bindings: expect.anything },
2138
2505
  })
@@ -2181,12 +2548,13 @@ describe("normalizeAndValidateConfig()", () => {
2181
2548
  ENV1: environment,
2182
2549
  },
2183
2550
  },
2184
- undefined
2551
+ undefined,
2552
+ { env: "ENV1" }
2185
2553
  );
2186
2554
 
2187
- expect("experimental_services" in config.env.ENV1).toBe(false);
2555
+ expect("experimental_services" in config).toBe(false);
2188
2556
  // Zone is not removed yet, since `route` commands might use it
2189
- expect(config.env.ENV1.zone_id).toEqual("ZONE_ID");
2557
+ expect(config.zone_id).toEqual("ZONE_ID");
2190
2558
  expect(diagnostics.hasErrors()).toBe(false);
2191
2559
  expect(diagnostics.hasWarnings()).toBe(true);
2192
2560
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -2207,6 +2575,241 @@ describe("normalizeAndValidateConfig()", () => {
2207
2575
  `);
2208
2576
  });
2209
2577
  });
2578
+
2579
+ describe("route & routes fields", () => {
2580
+ it("should error if both route and routes are specified in the same environment", () => {
2581
+ const environment: RawEnvironment = {
2582
+ name: "ENV_NAME",
2583
+ account_id: "ENV_ACCOUNT_ID",
2584
+ compatibility_date: "2022-02-02",
2585
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2586
+ workers_dev: true,
2587
+ route: "ENV_ROUTE_1",
2588
+ routes: ["ENV_ROUTE_2", "ENV_ROUTE_3"],
2589
+ jsx_factory: "ENV_JSX_FACTORY",
2590
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2591
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2592
+ usage_model: "unbound",
2593
+ };
2594
+ const expectedConfig: RawConfig = {
2595
+ name: "NAME",
2596
+ account_id: "ACCOUNT_ID",
2597
+ compatibility_date: "2022-01-01",
2598
+ compatibility_flags: ["FLAG1", "FLAG2"],
2599
+ workers_dev: false,
2600
+ routes: ["ROUTE_1", "ROUTE_2"],
2601
+ jsx_factory: "JSX_FACTORY",
2602
+ jsx_fragment: "JSX_FRAGMENT",
2603
+ triggers: { crons: ["CRON_1", "CRON_2"] },
2604
+ usage_model: "bundled",
2605
+ env: {
2606
+ ENV1: environment,
2607
+ },
2608
+ };
2609
+
2610
+ const { config, diagnostics } = normalizeAndValidateConfig(
2611
+ expectedConfig,
2612
+ undefined,
2613
+ { env: "ENV1" }
2614
+ );
2615
+
2616
+ expect(config).toEqual(expect.objectContaining(environment));
2617
+ expect(diagnostics.hasErrors()).toBe(true);
2618
+ expect(diagnostics.hasWarnings()).toBe(false);
2619
+
2620
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2621
+ "Processing wrangler configuration:
2622
+
2623
+ - \\"env.ENV1\\" environment configuration
2624
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
2625
+ `);
2626
+ });
2627
+
2628
+ it("should error if both route and routes are specified in the top-level environment", () => {
2629
+ const environment: RawEnvironment = {
2630
+ name: "ENV_NAME",
2631
+ account_id: "ENV_ACCOUNT_ID",
2632
+ compatibility_date: "2022-02-02",
2633
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2634
+ workers_dev: true,
2635
+ routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
2636
+ jsx_factory: "ENV_JSX_FACTORY",
2637
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2638
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2639
+ usage_model: "unbound",
2640
+ };
2641
+ const expectedConfig: RawConfig = {
2642
+ name: "NAME",
2643
+ account_id: "ACCOUNT_ID",
2644
+ compatibility_date: "2022-01-01",
2645
+ compatibility_flags: ["FLAG1", "FLAG2"],
2646
+ workers_dev: false,
2647
+ route: "ROUTE_1",
2648
+ routes: ["ROUTE_2", "ROUTE_3"],
2649
+ jsx_factory: "JSX_FACTORY",
2650
+ jsx_fragment: "JSX_FRAGMENT",
2651
+ triggers: { crons: ["CRON_1", "CRON_2"] },
2652
+ usage_model: "bundled",
2653
+ env: {
2654
+ ENV1: environment,
2655
+ },
2656
+ };
2657
+
2658
+ const { config, diagnostics } = normalizeAndValidateConfig(
2659
+ expectedConfig,
2660
+ undefined,
2661
+ { env: "ENV1" }
2662
+ );
2663
+
2664
+ expect(config).toEqual(expect.objectContaining(environment));
2665
+ expect(diagnostics.hasErrors()).toBe(true);
2666
+ expect(diagnostics.hasWarnings()).toBe(false);
2667
+
2668
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2669
+ "Processing wrangler configuration:
2670
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
2671
+ `);
2672
+ });
2673
+
2674
+ it("should not error if <env>.route and <top-level>.routes are specified", () => {
2675
+ const environment: RawEnvironment = {
2676
+ name: "ENV_NAME",
2677
+ account_id: "ENV_ACCOUNT_ID",
2678
+ compatibility_date: "2022-02-02",
2679
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2680
+ workers_dev: true,
2681
+ route: "ENV_ROUTE_1",
2682
+ jsx_factory: "ENV_JSX_FACTORY",
2683
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2684
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2685
+ usage_model: "unbound",
2686
+ };
2687
+ const expectedConfig: RawConfig = {
2688
+ name: "NAME",
2689
+ account_id: "ACCOUNT_ID",
2690
+ compatibility_date: "2022-01-01",
2691
+ compatibility_flags: ["FLAG1", "FLAG2"],
2692
+ workers_dev: false,
2693
+ routes: ["ROUTE_1", "ROUTE_2"],
2694
+ jsx_factory: "JSX_FACTORY",
2695
+ jsx_fragment: "JSX_FRAGMENT",
2696
+ triggers: { crons: ["CRON_1", "CRON_2"] },
2697
+ usage_model: "bundled",
2698
+ env: {
2699
+ ENV1: environment,
2700
+ },
2701
+ };
2702
+
2703
+ const { config, diagnostics } = normalizeAndValidateConfig(
2704
+ expectedConfig,
2705
+ undefined,
2706
+ { env: "ENV1" }
2707
+ );
2708
+
2709
+ expect(config).toEqual(expect.objectContaining(environment));
2710
+ expect(diagnostics.hasErrors()).toBe(false);
2711
+ expect(diagnostics.hasWarnings()).toBe(false);
2712
+ });
2713
+
2714
+ it("should not error if <env>.routes and <top-level>.route are specified", () => {
2715
+ const environment: RawEnvironment = {
2716
+ name: "ENV_NAME",
2717
+ account_id: "ENV_ACCOUNT_ID",
2718
+ compatibility_date: "2022-02-02",
2719
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2720
+ workers_dev: true,
2721
+ routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
2722
+ jsx_factory: "ENV_JSX_FACTORY",
2723
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2724
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2725
+ usage_model: "unbound",
2726
+ };
2727
+ const expectedConfig: RawConfig = {
2728
+ name: "NAME",
2729
+ account_id: "ACCOUNT_ID",
2730
+ compatibility_date: "2022-01-01",
2731
+ compatibility_flags: ["FLAG1", "FLAG2"],
2732
+ workers_dev: false,
2733
+ route: "ROUTE_1",
2734
+ jsx_factory: "JSX_FACTORY",
2735
+ jsx_fragment: "JSX_FRAGMENT",
2736
+ triggers: { crons: ["CRON_1", "CRON_2"] },
2737
+ usage_model: "bundled",
2738
+ env: {
2739
+ ENV1: environment,
2740
+ },
2741
+ };
2742
+
2743
+ const { config, diagnostics } = normalizeAndValidateConfig(
2744
+ expectedConfig,
2745
+ undefined,
2746
+ { env: "ENV1" }
2747
+ );
2748
+
2749
+ expect(config).toEqual(expect.objectContaining(environment));
2750
+ expect(diagnostics.hasErrors()).toBe(false);
2751
+ expect(diagnostics.hasWarnings()).toBe(false);
2752
+ });
2753
+
2754
+ it("should not error if <env1>.route and <env2>.routes are specified", () => {
2755
+ const environment1: RawEnvironment = {
2756
+ name: "ENV_NAME",
2757
+ account_id: "ENV_ACCOUNT_ID",
2758
+ compatibility_date: "2022-02-02",
2759
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2760
+ workers_dev: true,
2761
+ routes: ["ENV1_ROUTE_1", "ENV2_ROUTE_2"],
2762
+ jsx_factory: "ENV_JSX_FACTORY",
2763
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2764
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2765
+ usage_model: "unbound",
2766
+ };
2767
+ const environment2: RawEnvironment = {
2768
+ name: "ENV_NAME",
2769
+ account_id: "ENV_ACCOUNT_ID",
2770
+ compatibility_date: "2022-02-02",
2771
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2772
+ workers_dev: true,
2773
+ route: "ENV2_ROUTE_1",
2774
+ jsx_factory: "ENV_JSX_FACTORY",
2775
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2776
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2777
+ usage_model: "unbound",
2778
+ };
2779
+ const expectedConfig: RawConfig = {
2780
+ name: "NAME",
2781
+ account_id: "ACCOUNT_ID",
2782
+ compatibility_date: "2022-01-01",
2783
+ compatibility_flags: ["FLAG1", "FLAG2"],
2784
+ workers_dev: false,
2785
+ route: "ROUTE_1",
2786
+ jsx_factory: "JSX_FACTORY",
2787
+ jsx_fragment: "JSX_FRAGMENT",
2788
+ triggers: { crons: ["CRON_1", "CRON_2"] },
2789
+ usage_model: "bundled",
2790
+ env: {
2791
+ ENV1: environment1,
2792
+ ENV2: environment2,
2793
+ },
2794
+ };
2795
+
2796
+ const result1 = normalizeAndValidateConfig(expectedConfig, undefined, {
2797
+ env: "ENV1",
2798
+ });
2799
+
2800
+ expect(result1.config).toEqual(expect.objectContaining(environment1));
2801
+ expect(result1.diagnostics.hasErrors()).toBe(false);
2802
+ expect(result1.diagnostics.hasWarnings()).toBe(false);
2803
+
2804
+ const result2 = normalizeAndValidateConfig(expectedConfig, undefined, {
2805
+ env: "ENV2",
2806
+ });
2807
+
2808
+ expect(result2.config).toEqual(expect.objectContaining(environment2));
2809
+ expect(result2.diagnostics.hasErrors()).toBe(false);
2810
+ expect(result2.diagnostics.hasWarnings()).toBe(false);
2811
+ });
2812
+ });
2210
2813
  });
2211
2814
  });
2212
2815