wrangler 0.0.0-e3cab74 → 0.0.0-e3e3243

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 (66) hide show
  1. package/README.md +1 -1
  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 +10 -7
  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 +959 -324
  9. package/src/__tests__/dev.test.tsx +512 -84
  10. package/src/__tests__/guess-worker-format.test.ts +19 -17
  11. package/src/__tests__/helpers/mock-account-id.ts +22 -4
  12. package/src/__tests__/helpers/mock-cfetch.ts +3 -3
  13. package/src/__tests__/helpers/mock-console.ts +17 -9
  14. package/src/__tests__/helpers/mock-kv.ts +9 -16
  15. package/src/__tests__/helpers/mock-stdin.ts +103 -0
  16. package/src/__tests__/helpers/run-in-tmp.ts +3 -0
  17. package/src/__tests__/https-options.test.ts +127 -0
  18. package/src/__tests__/index.test.ts +128 -11
  19. package/src/__tests__/jest.setup.ts +16 -4
  20. package/src/__tests__/kv.test.ts +364 -125
  21. package/src/__tests__/logout.test.ts +15 -13
  22. package/src/__tests__/pages.test.ts +82 -0
  23. package/src/__tests__/publish.test.ts +1838 -735
  24. package/src/__tests__/r2.test.ts +4 -4
  25. package/src/__tests__/route.test.ts +45 -0
  26. package/src/__tests__/secret.test.ts +167 -68
  27. package/src/__tests__/tail.test.ts +2 -4
  28. package/src/__tests__/whoami.test.tsx +21 -7
  29. package/src/bundle.ts +27 -5
  30. package/src/cfetch/internal.ts +11 -5
  31. package/src/config/README.md +6 -6
  32. package/src/config/config.ts +54 -101
  33. package/src/config/environment.ts +67 -1
  34. package/src/config/index.ts +13 -3
  35. package/src/config/validation-helpers.ts +207 -23
  36. package/src/config/validation.ts +344 -129
  37. package/src/{api/preview.ts → create-worker-preview.ts} +39 -20
  38. package/src/{api/form_data.ts → create-worker-upload-form.ts} +1 -1
  39. package/src/dev/dev.tsx +392 -0
  40. package/src/dev/local.tsx +232 -0
  41. package/src/dev/remote.tsx +203 -0
  42. package/src/dev/use-esbuild.ts +104 -0
  43. package/src/entry.ts +192 -9
  44. package/src/https-options.ts +122 -0
  45. package/src/index.tsx +577 -515
  46. package/src/inspect.ts +9 -1
  47. package/src/intl-polyfill.d.ts +139 -0
  48. package/src/{kv.tsx → kv.ts} +97 -53
  49. package/src/miniflare-cli/README.md +30 -0
  50. package/src/miniflare-cli/enum-keys.ts +17 -0
  51. package/src/miniflare-cli/index.ts +37 -0
  52. package/src/module-collection.ts +90 -2
  53. package/src/open-in-browser.ts +14 -2
  54. package/src/pages.tsx +26 -10
  55. package/src/proxy.ts +104 -40
  56. package/src/publish.ts +53 -71
  57. package/src/reporting.ts +25 -9
  58. package/src/selfsigned.d.ts +29 -0
  59. package/src/sites.tsx +68 -29
  60. package/src/user.tsx +163 -85
  61. package/src/{api/worker.ts → worker.ts} +1 -24
  62. package/wrangler-dist/cli.js +5933 -3842
  63. package/wrangler-dist/cli.js.map +3 -3
  64. package/src/__tests__/helpers/mock-user.ts +0 -27
  65. package/src/dev.tsx +0 -961
  66. package/src/guess-worker-format.ts +0 -68
@@ -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,17 +24,18 @@ 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",
31
+ host: undefined,
24
32
  },
25
33
  durable_objects: {
26
34
  bindings: [],
27
35
  },
28
- env: {},
29
36
  jsx_factory: "React.createElement",
30
37
  jsx_fragment: "React.Fragment",
38
+ tsconfig: undefined,
31
39
  kv_namespaces: [],
32
40
  legacy_env: true,
33
41
  main: undefined,
@@ -48,7 +56,7 @@ describe("normalizeAndValidateConfig()", () => {
48
56
  usage_model: undefined,
49
57
  vars: {},
50
58
  wasm_modules: undefined,
51
- workers_dev: true,
59
+ workers_dev: undefined,
52
60
  zone_id: undefined,
53
61
  });
54
62
  expect(diagnostics.hasErrors()).toBe(false);
@@ -57,56 +65,42 @@ describe("normalizeAndValidateConfig()", () => {
57
65
 
58
66
  describe("top-level non-environment configuration", () => {
59
67
  it("should override config defaults with provided values", () => {
60
- const main = "src/index.ts";
61
- const expectedConfig: RawConfig = {
62
- main,
68
+ const expectedConfig: Partial<ConfigFields<RawDevConfig>> = {
63
69
  legacy_env: true,
64
70
  dev: {
65
71
  ip: "255.255.255.255",
66
72
  port: 9999,
67
- local_protocol: "HTTPS",
68
- upstream_protocol: "HTTP",
69
- },
70
- build: {
71
- command: "COMMAND",
72
- cwd: "CWD",
73
- watch_dir: "WATCH_DIR",
73
+ local_protocol: "https",
74
+ upstream_protocol: "http",
74
75
  },
75
76
  };
76
77
 
77
78
  const { config, diagnostics } = normalizeAndValidateConfig(
78
79
  expectedConfig,
79
- undefined
80
+ undefined,
81
+ { env: undefined }
80
82
  );
81
83
 
82
- const resolvedMain = path.resolve(process.cwd(), main);
83
- expect(config).toEqual(
84
- expect.objectContaining({ ...expectedConfig, main: resolvedMain })
85
- );
84
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
86
85
  expect(diagnostics.hasErrors()).toBe(false);
87
86
  expect(diagnostics.hasWarnings()).toBe(false);
88
87
  });
89
88
 
90
89
  it("should error on invalid top level fields", () => {
91
90
  const expectedConfig = {
92
- main: 111,
93
91
  legacy_env: "FOO",
94
92
  dev: {
95
93
  ip: 222,
96
94
  port: "FOO",
97
- local_protocol: 333,
98
- upstream_protocol: 444,
99
- },
100
- build: {
101
- command: 555,
102
- cwd: 666,
103
- watch_dir: 777,
95
+ local_protocol: "wss",
96
+ upstream_protocol: "ws",
104
97
  },
105
98
  };
106
99
 
107
100
  const { config, diagnostics } = normalizeAndValidateConfig(
108
101
  expectedConfig as unknown as RawConfig,
109
- undefined
102
+ undefined,
103
+ { env: undefined }
110
104
  );
111
105
 
112
106
  expect(config).toEqual(
@@ -114,80 +108,54 @@ describe("normalizeAndValidateConfig()", () => {
114
108
  );
115
109
  expect(diagnostics.hasWarnings()).toBe(false);
116
110
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
117
- "Processing wrangler configuration:
118
- - ERROR: \\"build.command\\" should be of type string but got 555.
119
- - ERROR: \\"build.cwd\\" should be of type string but got 666.
120
- - ERROR: \\"build.watch_dir\\" should be of type string but got 777.
121
- - ERROR: \\"legacy_env\\" should be of type boolean but got \\"FOO\\".
122
- - ERROR: \\"main\\" should be a string but got 111
123
- - ERROR: \\"dev.ip\\" should be of type string but got 222.
124
- - ERROR: \\"dev.port\\" should be of type number but got \\"FOO\\".
125
- - ERROR: \\"dev.local_protocol\\" should be of type string but got 333.
126
- - ERROR: \\"dev.upstream_protocol\\" should be of type string but got 444."
127
- `);
111
+ "Processing wrangler configuration:
112
+ - Expected \\"legacy_env\\" to be of type boolean but got \\"FOO\\".
113
+ - Expected \\"dev.ip\\" to be of type string but got 222.
114
+ - Expected \\"dev.port\\" to be of type number but got \\"FOO\\".
115
+ - Expected \\"dev.local_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"wss\\".
116
+ - Expected \\"dev.upstream_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"ws\\"."
117
+ `);
128
118
  });
129
119
 
130
120
  it("should warn on and remove unexpected top level fields", () => {
131
121
  const expectedConfig = {
132
- miniflare: {
133
- host: "127.0.0.1",
122
+ unexpected: {
123
+ subkey: "some-value",
134
124
  },
135
125
  };
136
126
 
137
127
  const { config, diagnostics } = normalizeAndValidateConfig(
138
128
  expectedConfig as unknown as RawConfig,
139
- undefined
129
+ undefined,
130
+ { env: undefined }
140
131
  );
141
132
 
142
- expect("miniflare" in config).toBe(false);
133
+ expect("unexpected" in config).toBe(false);
143
134
  expect(diagnostics.hasErrors()).toBe(false);
144
135
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
145
136
  "Processing wrangler configuration:
146
- - Unexpected fields found in top-level field: \\"miniflare\\""
137
+ - Unexpected fields found in top-level field: \\"unexpected\\""
147
138
  `);
148
139
  });
149
140
 
150
- it("should override build.upload config defaults with provided values and warn about deprecations", () => {
151
- const expectedConfig: RawConfig = {
152
- build: {
153
- upload: {
154
- dir: "src",
155
- format: "modules",
156
- main: "index.ts",
157
- rules: [{ type: "Text", globs: ["GLOB"], fallthrough: true }],
158
- },
141
+ it("should ignore `miniflare` top level fields", () => {
142
+ const expectedConfig = {
143
+ miniflare: {
144
+ host: "localhost",
159
145
  },
160
146
  };
161
147
 
162
148
  const { config, diagnostics } = normalizeAndValidateConfig(
163
- expectedConfig,
164
- path.resolve("project/wrangler.toml")
149
+ expectedConfig as unknown as RawConfig,
150
+ undefined,
151
+ { env: undefined }
165
152
  );
166
153
 
167
- expect(config.main).toEqual(path.resolve("project/src/index.ts"));
168
- expect(config.build.upload).toBeUndefined();
154
+ expect("miniflare" in config).toBe(false);
169
155
  expect(diagnostics.hasErrors()).toBe(false);
170
- expect(diagnostics.hasWarnings()).toBe(true);
171
- expect(normalizePath(diagnostics.renderWarnings()))
172
- .toMatchInlineSnapshot(`
173
- "Processing project/wrangler.toml configuration:
174
- - DEPRECATION: \\"build.upload.format\\":
175
- The format is inferred automatically from the code.
176
- - DEPRECATION: \\"build.upload.main\\":
177
- Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
178
- Then add the top level \`main\` field to your configuration file:
179
- \`\`\`
180
- main = \\"src/index.ts\\"
181
- \`\`\`
182
- - DEPRECATION: \\"build.upload.dir\\":
183
- Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker.
184
- - 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:
185
- \`\`\`
186
- [[rules]]
187
- type = \\"Text\\"
188
- globs = [ \\"GLOB\\" ]
189
- fallthrough = true
190
- \`\`\`"
156
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
157
+ "Processing wrangler configuration:
158
+ "
191
159
  `);
192
160
  });
193
161
 
@@ -210,7 +178,8 @@ describe("normalizeAndValidateConfig()", () => {
210
178
 
211
179
  const { config, diagnostics } = normalizeAndValidateConfig(
212
180
  expectedConfig,
213
- undefined
181
+ undefined,
182
+ { env: undefined }
214
183
  );
215
184
 
216
185
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -237,90 +206,126 @@ describe("normalizeAndValidateConfig()", () => {
237
206
 
238
207
  const { config, diagnostics } = normalizeAndValidateConfig(
239
208
  expectedConfig as unknown as RawConfig,
240
- undefined
209
+ undefined,
210
+ { env: undefined }
241
211
  );
242
212
 
243
213
  expect(config).toEqual(expect.objectContaining(expectedConfig));
244
214
  expect(diagnostics.hasWarnings()).toBe(false);
245
215
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
246
- "Processing wrangler configuration:
247
- - ERROR: \\"migrations[0].tag\\" should be of type string but got 111.
248
- - ERROR: \\"migrations[0].new_classes.[0]\\" should be of type string but got 222.
249
- - ERROR: \\"migrations[0].new_classes.[1]\\" should be of type string but got 333.
250
- - \\"migrations[0].renamed_classes\\" should be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":444,\\"to\\":555}].
251
- - ERROR: \\"migrations[0].deleted_classes.[0]\\" should be of type string but got 666.
252
- - ERROR: \\"migrations[0].deleted_classes.[1]\\" should be of type string but got 777."
253
- `);
216
+ "Processing wrangler configuration:
217
+ - Expected \\"migrations[0].tag\\" to be of type string but got 111.
218
+ - Expected \\"migrations[0].new_classes.[0]\\" to be of type string but got 222.
219
+ - Expected \\"migrations[0].new_classes.[1]\\" to be of type string but got 333.
220
+ - Expected \\"migrations[0].renamed_classes\\" to be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":444,\\"to\\":555}].
221
+ - Expected \\"migrations[0].deleted_classes.[0]\\" to be of type string but got 666.
222
+ - Expected \\"migrations[0].deleted_classes.[1]\\" to be of type string but got 777."
223
+ `);
254
224
  });
255
225
 
256
- it("should override `site` config defaults with provided values", () => {
257
- const expectedConfig: RawConfig = {
258
- site: {
259
- bucket: "BUCKET",
260
- "entry-point": "ENTRY_POINT",
261
- include: ["INCLUDE_1", "INCLUDE_2"],
262
- exclude: ["EXCLUDE_1", "EXCLUDE_2"],
263
- },
264
- };
226
+ describe("site", () => {
227
+ it("should override `site` config defaults with provided values", () => {
228
+ const expectedConfig: RawConfig = {
229
+ site: {
230
+ bucket: "BUCKET",
231
+ include: ["INCLUDE_1", "INCLUDE_2"],
232
+ exclude: ["EXCLUDE_1", "EXCLUDE_2"],
233
+ },
234
+ };
265
235
 
266
- const { config, diagnostics } = normalizeAndValidateConfig(
267
- expectedConfig,
268
- undefined
269
- );
236
+ const { config, diagnostics } = normalizeAndValidateConfig(
237
+ expectedConfig,
238
+ undefined,
239
+ { env: undefined }
240
+ );
270
241
 
271
- expect(config).toEqual(expect.objectContaining(expectedConfig));
272
- expect(diagnostics.hasErrors()).toBe(false);
273
- expect(diagnostics.hasWarnings()).toBe(false);
274
- });
242
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
243
+ expect(diagnostics.hasErrors()).toBe(false);
244
+ expect(diagnostics.hasWarnings()).toBe(false);
245
+ });
275
246
 
276
- it("should error if `site` config is missing `bucket`", () => {
277
- const expectedConfig: RawConfig = {
278
- site: {
279
- "entry-point": "ENTRY_POINT",
280
- include: ["INCLUDE_1", "INCLUDE_2"],
281
- exclude: ["EXCLUDE_1", "EXCLUDE_2"],
282
- },
283
- } as RawConfig;
247
+ it("should error if `site` config is missing `bucket`", () => {
248
+ const expectedConfig: RawConfig = {
249
+ // @ts-expect-error we're intentionally passing an invalid configuration here
250
+ site: {
251
+ include: ["INCLUDE_1", "INCLUDE_2"],
252
+ exclude: ["EXCLUDE_1", "EXCLUDE_2"],
253
+ },
254
+ };
284
255
 
285
- const { config, diagnostics } = normalizeAndValidateConfig(
286
- expectedConfig,
287
- undefined
288
- );
256
+ const { config, diagnostics } = normalizeAndValidateConfig(
257
+ expectedConfig,
258
+ undefined,
259
+ { env: undefined }
260
+ );
289
261
 
290
- expect(config).toEqual(expect.objectContaining(expectedConfig));
291
- expect(diagnostics.hasErrors()).toBe(true);
292
- expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
293
- "Processing wrangler configuration:
294
- - ERROR: \\"site.bucket\\" is a required field."
295
- `);
296
- expect(diagnostics.hasWarnings()).toBe(false);
297
- });
262
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
263
+ expect(diagnostics.hasErrors()).toBe(true);
264
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
265
+ "Processing wrangler configuration:
266
+ - \\"site.bucket\\" is a required field."
267
+ `);
268
+ expect(diagnostics.hasWarnings()).toBe(false);
269
+ });
298
270
 
299
- it("should error on invalid `site` values", () => {
300
- const expectedConfig = {
301
- site: {
302
- bucket: "BUCKET",
303
- "entry-point": 111,
304
- include: [222, 333],
305
- exclude: [444, 555],
306
- },
307
- };
271
+ it("should error on invalid `site` values", () => {
272
+ const expectedConfig = {
273
+ site: {
274
+ bucket: "BUCKET",
275
+ include: [222, 333],
276
+ exclude: [444, 555],
277
+ },
278
+ };
308
279
 
309
- const { config, diagnostics } = normalizeAndValidateConfig(
310
- expectedConfig as unknown as RawConfig,
311
- undefined
312
- );
280
+ const { config, diagnostics } = normalizeAndValidateConfig(
281
+ expectedConfig as unknown as RawConfig,
282
+ undefined,
283
+ { env: undefined }
284
+ );
313
285
 
314
- expect(config).toEqual(expect.objectContaining(expectedConfig));
315
- expect(diagnostics.hasWarnings()).toBe(false);
316
- expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
286
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
287
+ expect(diagnostics.hasWarnings()).toBe(false);
288
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
289
+ "Processing wrangler configuration:
290
+ - Expected \\"sites.include.[0]\\" to be of type string but got 222.
291
+ - Expected \\"sites.include.[1]\\" to be of type string but got 333.
292
+ - Expected \\"sites.exclude.[0]\\" to be of type string but got 444.
293
+ - Expected \\"sites.exclude.[1]\\" to be of type string but got 555."
294
+ `);
295
+ });
296
+
297
+ it("should error with a deprecation warning if entry-point is defined", async () => {
298
+ const { config, diagnostics } = normalizeAndValidateConfig(
299
+ {
300
+ site: {
301
+ bucket: "some/path",
302
+ "entry-point": "some/other/script.js",
303
+ },
304
+ } as unknown as RawConfig,
305
+ undefined,
306
+ { env: undefined }
307
+ );
308
+
309
+ expect(config.site).toMatchInlineSnapshot(`
310
+ Object {
311
+ "bucket": "some/path",
312
+ "exclude": Array [],
313
+ "include": Array [],
314
+ }
315
+ `);
316
+ expect(diagnostics.hasWarnings()).toBe(true);
317
+ expect(diagnostics.hasErrors()).toBe(true);
318
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
319
+ "Processing wrangler configuration:
320
+ - Unexpected fields found in site field: \\"entry-point\\""
321
+ `);
322
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
317
323
  "Processing wrangler configuration:
318
- - ERROR: \\"site.entry_point\\" should be of type string but got 111.
319
- - ERROR: \\"sites.include.[0]\\" should be of type string but got 222.
320
- - ERROR: \\"sites.include.[1]\\" should be of type string but got 333.
321
- - ERROR: \\"sites.exclude.[0]\\" should be of type string but got 444.
322
- - ERROR: \\"sites.exclude.[1]\\" should be of type string but got 555."
324
+ - DEPRECATION: \\"site.entry-point\\":
325
+ The \`site.entry-point\` config field is no longer used.
326
+ The entry-point should be specified via the command line or the \`main\` config field."
323
327
  `);
328
+ });
324
329
  });
325
330
 
326
331
  it("should map `wasm_module` paths from relative to the config path to relative to the cwd", () => {
@@ -333,7 +338,8 @@ describe("normalizeAndValidateConfig()", () => {
333
338
 
334
339
  const { config, diagnostics } = normalizeAndValidateConfig(
335
340
  expectedConfig,
336
- "project/wrangler.toml"
341
+ "project/wrangler.toml",
342
+ { env: undefined }
337
343
  );
338
344
 
339
345
  expect(config).toEqual(
@@ -358,7 +364,8 @@ describe("normalizeAndValidateConfig()", () => {
358
364
 
359
365
  const { config, diagnostics } = normalizeAndValidateConfig(
360
366
  expectedConfig as unknown as RawConfig,
361
- "project/wrangler.toml"
367
+ "project/wrangler.toml",
368
+ { env: undefined }
362
369
  );
363
370
 
364
371
  expect(config).toEqual(
@@ -368,10 +375,10 @@ describe("normalizeAndValidateConfig()", () => {
368
375
  );
369
376
  expect(diagnostics.hasWarnings()).toBe(false);
370
377
  expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
371
- "Processing project/wrangler.toml configuration:
372
- - Expected \\"wasm_modules['MODULE_1']\\" field to be a string but got 111.
373
- - Expected \\"wasm_modules['MODULE_2']\\" field to be a string but got 222."
374
- `);
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
+ `);
375
382
  });
376
383
 
377
384
  it("should map `text_blobs` paths from relative to the config path to relative to the cwd", () => {
@@ -384,7 +391,8 @@ describe("normalizeAndValidateConfig()", () => {
384
391
 
385
392
  const { config, diagnostics } = normalizeAndValidateConfig(
386
393
  expectedConfig,
387
- "project/wrangler.toml"
394
+ "project/wrangler.toml",
395
+ { env: undefined }
388
396
  );
389
397
 
390
398
  expect(config).toEqual(
@@ -409,7 +417,8 @@ describe("normalizeAndValidateConfig()", () => {
409
417
 
410
418
  const { config, diagnostics } = normalizeAndValidateConfig(
411
419
  expectedConfig as unknown as RawConfig,
412
- "project/wrangler.toml"
420
+ "project/wrangler.toml",
421
+ { env: undefined }
413
422
  );
414
423
 
415
424
  expect(config).toEqual(
@@ -419,10 +428,31 @@ describe("normalizeAndValidateConfig()", () => {
419
428
  );
420
429
  expect(diagnostics.hasWarnings()).toBe(false);
421
430
  expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
422
- "Processing project/wrangler.toml configuration:
423
- - Expected \\"text_blobs['MODULE_1']\\" field to be a string but got 111.
424
- - Expected \\"text_blobs['MODULE_2']\\" field to be a string but got 222."
425
- `);
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);
426
456
  });
427
457
 
428
458
  describe("(deprecated)", () => {
@@ -434,7 +464,8 @@ describe("normalizeAndValidateConfig()", () => {
434
464
 
435
465
  const { config, diagnostics } = normalizeAndValidateConfig(
436
466
  rawConfig,
437
- undefined
467
+ undefined,
468
+ { env: undefined }
438
469
  );
439
470
 
440
471
  // Note the `.not.` here...
@@ -459,18 +490,27 @@ describe("normalizeAndValidateConfig()", () => {
459
490
 
460
491
  describe("top-level environment configuration", () => {
461
492
  it("should override config defaults with provided values", () => {
462
- const expectedConfig: RawConfig = {
493
+ const main = "src/index.ts";
494
+ const resolvedMain = path.resolve(process.cwd(), main);
495
+
496
+ const expectedConfig: RawEnvironment = {
463
497
  name: "NAME",
464
498
  account_id: "ACCOUNT_ID",
465
499
  compatibility_date: "2022-01-01",
466
500
  compatibility_flags: ["FLAG1", "FLAG2"],
467
501
  workers_dev: false,
468
502
  routes: ["ROUTE_1", "ROUTE_2"],
469
- route: "ROUTE_3",
470
503
  jsx_factory: "JSX_FACTORY",
471
504
  jsx_fragment: "JSX_FRAGMENT",
505
+ tsconfig: "path/to/tsconfig",
472
506
  triggers: { crons: ["CRON_1", "CRON_2"] },
473
507
  usage_model: "bundled",
508
+ main,
509
+ build: {
510
+ command: "COMMAND",
511
+ cwd: "CWD",
512
+ watch_dir: "WATCH_DIR",
513
+ },
474
514
  vars: {
475
515
  VAR1: "VALUE_1",
476
516
  VAR2: "VALUE_2",
@@ -515,10 +555,13 @@ describe("normalizeAndValidateConfig()", () => {
515
555
 
516
556
  const { config, diagnostics } = normalizeAndValidateConfig(
517
557
  expectedConfig,
518
- undefined
558
+ undefined,
559
+ { env: undefined }
519
560
  );
520
561
 
521
- expect(config).toEqual(expect.objectContaining(expectedConfig));
562
+ expect(config).toEqual(
563
+ expect.objectContaining({ ...expectedConfig, main: resolvedMain })
564
+ );
522
565
  expect(diagnostics.hasErrors()).toBe(false);
523
566
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
524
567
  "Processing wrangler configuration:
@@ -527,7 +570,7 @@ describe("normalizeAndValidateConfig()", () => {
527
570
  });
528
571
 
529
572
  it("should error on invalid environment values", () => {
530
- const expectedConfig: RawConfig = {
573
+ const expectedConfig: RawEnvironment = {
531
574
  name: 111,
532
575
  account_id: 222,
533
576
  compatibility_date: 333,
@@ -537,37 +580,146 @@ describe("normalizeAndValidateConfig()", () => {
537
580
  route: 888,
538
581
  jsx_factory: 999,
539
582
  jsx_fragment: 1000,
583
+ tsconfig: true,
540
584
  triggers: { crons: [1111, 1222] },
541
585
  usage_model: "INVALID",
542
- } 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;
543
593
 
544
594
  const { config, diagnostics } = normalizeAndValidateConfig(
545
595
  expectedConfig,
546
- undefined
596
+ undefined,
597
+ { env: undefined }
547
598
  );
548
599
 
549
600
  expect(config).toEqual(expect.objectContaining(expectedConfig));
550
601
  expect(diagnostics.hasWarnings()).toBe(false);
551
602
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
552
603
  "Processing wrangler configuration:
553
- - Expected \\"route\\" field to be a string but got 888.
554
- - Expected \\"routes\\" field to be an array of strings but got [666,777].
555
- - Expected \\"workers_dev\\" field to be a boolean but got \\"BAD\\".
556
- - Expected \\"account_id\\" field to be a string but got 222.
557
- - Expected \\"compatibility_date\\" field to be a string but got 333.
558
- - Expected \\"compatibility_flags\\" field to be an array of strings but got [444,555].
559
- - Expected \\"jsx_factory\\" field to be a string but got 999.
560
- - Expected \\"jsx_fragment\\" field to be a string but got 1000.
561
- - Expected \\"name\\" field to be a string but got 111.
562
- - Expected \\"usage_model\\" field to be on of bundled,unbound but got \\"INVALID\\"."
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.
619
+ - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
563
620
  `);
564
621
  });
565
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
+
566
717
  describe("durable_objects field", () => {
567
718
  it("should error if durable_objects is an array", () => {
568
719
  const { config, diagnostics } = normalizeAndValidateConfig(
569
720
  { durable_objects: [] } as unknown as RawConfig,
570
- undefined
721
+ undefined,
722
+ { env: undefined }
571
723
  );
572
724
 
573
725
  expect(config).toEqual(
@@ -583,7 +735,8 @@ describe("normalizeAndValidateConfig()", () => {
583
735
  it("should error if durable_objects is a string", () => {
584
736
  const { config, diagnostics } = normalizeAndValidateConfig(
585
737
  { durable_objects: "BAD" } as unknown as RawConfig,
586
- undefined
738
+ undefined,
739
+ { env: undefined }
587
740
  );
588
741
 
589
742
  expect(config).toEqual(
@@ -599,7 +752,8 @@ describe("normalizeAndValidateConfig()", () => {
599
752
  it("should error if durable_objects is a number", () => {
600
753
  const { config, diagnostics } = normalizeAndValidateConfig(
601
754
  { durable_objects: 999 } as unknown as RawConfig,
602
- undefined
755
+ undefined,
756
+ { env: undefined }
603
757
  );
604
758
 
605
759
  expect(config).toEqual(
@@ -615,7 +769,8 @@ describe("normalizeAndValidateConfig()", () => {
615
769
  it("should error if durable_objects is null", () => {
616
770
  const { config, diagnostics } = normalizeAndValidateConfig(
617
771
  { durable_objects: null } as unknown as RawConfig,
618
- undefined
772
+ undefined,
773
+ { env: undefined }
619
774
  );
620
775
 
621
776
  expect(config).toEqual(
@@ -631,7 +786,8 @@ describe("normalizeAndValidateConfig()", () => {
631
786
  it("should error if durable_objects.bindings is not defined", () => {
632
787
  const { config, diagnostics } = normalizeAndValidateConfig(
633
788
  { durable_objects: {} } as unknown as RawConfig,
634
- undefined
789
+ undefined,
790
+ { env: undefined }
635
791
  );
636
792
 
637
793
  expect(config).toEqual(
@@ -647,7 +803,8 @@ describe("normalizeAndValidateConfig()", () => {
647
803
  it("should error if durable_objects.bindings is an object", () => {
648
804
  const { config, diagnostics } = normalizeAndValidateConfig(
649
805
  { durable_objects: { bindings: {} } } as unknown as RawConfig,
650
- undefined
806
+ undefined,
807
+ { env: undefined }
651
808
  );
652
809
 
653
810
  expect(config).toEqual(
@@ -665,7 +822,8 @@ describe("normalizeAndValidateConfig()", () => {
665
822
  it("should error if durable_objects.bindings is a string", () => {
666
823
  const { config, diagnostics } = normalizeAndValidateConfig(
667
824
  { durable_objects: { bindings: "BAD" } } as unknown as RawConfig,
668
- undefined
825
+ undefined,
826
+ { env: undefined }
669
827
  );
670
828
 
671
829
  expect(config).toEqual(
@@ -683,7 +841,8 @@ describe("normalizeAndValidateConfig()", () => {
683
841
  it("should error if durable_objects.bindings is a number", () => {
684
842
  const { config, diagnostics } = normalizeAndValidateConfig(
685
843
  { durable_objects: { bindings: 999 } } as unknown as RawConfig,
686
- undefined
844
+ undefined,
845
+ { env: undefined }
687
846
  );
688
847
 
689
848
  expect(config).toEqual(
@@ -701,7 +860,8 @@ describe("normalizeAndValidateConfig()", () => {
701
860
  it("should error if durable_objects.bindings is null", () => {
702
861
  const { config, diagnostics } = normalizeAndValidateConfig(
703
862
  { durable_objects: { bindings: null } } as unknown as RawConfig,
704
- undefined
863
+ undefined,
864
+ { env: undefined }
705
865
  );
706
866
 
707
867
  expect(config).toEqual(
@@ -732,7 +892,8 @@ describe("normalizeAndValidateConfig()", () => {
732
892
  ],
733
893
  },
734
894
  } as unknown as RawConfig,
735
- undefined
895
+ undefined,
896
+ { env: undefined }
736
897
  );
737
898
 
738
899
  expect(config).toEqual(
@@ -745,20 +906,20 @@ describe("normalizeAndValidateConfig()", () => {
745
906
  "Processing wrangler configuration:
746
907
 
747
908
  - \\"durable_objects.bindings[0]\\": {}
748
- - ERROR: bindings should have a string \\"name\\" field.
749
- - ERROR: should have a string \\"class_name\\" field.
909
+ - binding should have a string \\"name\\" field.
910
+ - binding should have a string \\"class_name\\" field.
750
911
 
751
912
  - \\"durable_objects.bindings[1]\\": {\\"name\\":\\"VALID\\"}
752
- - ERROR: should have a string \\"class_name\\" field.
913
+ - binding should have a string \\"class_name\\" field.
753
914
 
754
915
  - \\"durable_objects.bindings[2]\\": {\\"name\\":1555,\\"class_name\\":1666}
755
- - ERROR: bindings should have a string \\"name\\" field.
756
- - ERROR: should have a string \\"class_name\\" field.
916
+ - binding should have a string \\"name\\" field.
917
+ - binding should have a string \\"class_name\\" field.
757
918
 
758
919
  - \\"durable_objects.bindings[3]\\": {\\"name\\":1777,\\"class_name\\":1888,\\"script_name\\":1999}
759
- - ERROR: bindings should have a string \\"name\\" field.
760
- - ERROR: should have a string \\"class_name\\" field.
761
- - ERROR: should, optionally, have a string \\"script_name\\" field."
920
+ - binding should have a string \\"name\\" field.
921
+ - binding should have a string \\"class_name\\" field.
922
+ - binding should, optionally, have a string \\"script_name\\" field."
762
923
  `);
763
924
  });
764
925
  });
@@ -767,7 +928,8 @@ describe("normalizeAndValidateConfig()", () => {
767
928
  it("should error if kv_namespaces is an object", () => {
768
929
  const { config, diagnostics } = normalizeAndValidateConfig(
769
930
  { kv_namespaces: {} } as unknown as RawConfig,
770
- undefined
931
+ undefined,
932
+ { env: undefined }
771
933
  );
772
934
 
773
935
  expect(config).toEqual(
@@ -783,7 +945,8 @@ describe("normalizeAndValidateConfig()", () => {
783
945
  it("should error if kv_namespaces is a string", () => {
784
946
  const { config, diagnostics } = normalizeAndValidateConfig(
785
947
  { kv_namespaces: "BAD" } as unknown as RawConfig,
786
- undefined
948
+ undefined,
949
+ { env: undefined }
787
950
  );
788
951
 
789
952
  expect(config).toEqual(
@@ -799,7 +962,8 @@ describe("normalizeAndValidateConfig()", () => {
799
962
  it("should error if kv_namespaces is a number", () => {
800
963
  const { config, diagnostics } = normalizeAndValidateConfig(
801
964
  { kv_namespaces: 999 } as unknown as RawConfig,
802
- undefined
965
+ undefined,
966
+ { env: undefined }
803
967
  );
804
968
 
805
969
  expect(config).toEqual(
@@ -815,7 +979,8 @@ describe("normalizeAndValidateConfig()", () => {
815
979
  it("should error if kv_namespaces is null", () => {
816
980
  const { config, diagnostics } = normalizeAndValidateConfig(
817
981
  { kv_namespaces: null } as unknown as RawConfig,
818
- undefined
982
+ undefined,
983
+ { env: undefined }
819
984
  );
820
985
 
821
986
  expect(config).toEqual(
@@ -842,7 +1007,8 @@ describe("normalizeAndValidateConfig()", () => {
842
1007
  },
843
1008
  ],
844
1009
  } as unknown as RawConfig,
845
- undefined
1010
+ undefined,
1011
+ { env: undefined }
846
1012
  );
847
1013
 
848
1014
  expect(config).toEqual(
@@ -867,7 +1033,8 @@ describe("normalizeAndValidateConfig()", () => {
867
1033
  it("should error if r2_buckets is an object", () => {
868
1034
  const { config, diagnostics } = normalizeAndValidateConfig(
869
1035
  { r2_buckets: {} } as unknown as RawConfig,
870
- undefined
1036
+ undefined,
1037
+ { env: undefined }
871
1038
  );
872
1039
 
873
1040
  expect(config).toEqual(
@@ -883,7 +1050,8 @@ describe("normalizeAndValidateConfig()", () => {
883
1050
  it("should error if r2_buckets is a string", () => {
884
1051
  const { config, diagnostics } = normalizeAndValidateConfig(
885
1052
  { r2_buckets: "BAD" } as unknown as RawConfig,
886
- undefined
1053
+ undefined,
1054
+ { env: undefined }
887
1055
  );
888
1056
 
889
1057
  expect(config).toEqual(
@@ -899,7 +1067,8 @@ describe("normalizeAndValidateConfig()", () => {
899
1067
  it("should error if r2_buckets is a number", () => {
900
1068
  const { config, diagnostics } = normalizeAndValidateConfig(
901
1069
  { r2_buckets: 999 } as unknown as RawConfig,
902
- undefined
1070
+ undefined,
1071
+ { env: undefined }
903
1072
  );
904
1073
 
905
1074
  expect(config).toEqual(
@@ -915,7 +1084,8 @@ describe("normalizeAndValidateConfig()", () => {
915
1084
  it("should error if r2_buckets is null", () => {
916
1085
  const { config, diagnostics } = normalizeAndValidateConfig(
917
1086
  { r2_buckets: null } as unknown as RawConfig,
918
- undefined
1087
+ undefined,
1088
+ { env: undefined }
919
1089
  );
920
1090
 
921
1091
  expect(config).toEqual(
@@ -942,7 +1112,8 @@ describe("normalizeAndValidateConfig()", () => {
942
1112
  },
943
1113
  ],
944
1114
  } as unknown as RawConfig,
945
- undefined
1115
+ undefined,
1116
+ { env: undefined }
946
1117
  );
947
1118
 
948
1119
  expect(config).toEqual(
@@ -967,7 +1138,8 @@ describe("normalizeAndValidateConfig()", () => {
967
1138
  it("should error if unsafe is an array", () => {
968
1139
  const { config, diagnostics } = normalizeAndValidateConfig(
969
1140
  { unsafe: [] } as unknown as RawConfig,
970
- undefined
1141
+ undefined,
1142
+ { env: undefined }
971
1143
  );
972
1144
 
973
1145
  expect(config).toEqual(
@@ -986,7 +1158,8 @@ describe("normalizeAndValidateConfig()", () => {
986
1158
  it("should error if unsafe is a string", () => {
987
1159
  const { config, diagnostics } = normalizeAndValidateConfig(
988
1160
  { unsafe: "BAD" } as unknown as RawConfig,
989
- undefined
1161
+ undefined,
1162
+ { env: undefined }
990
1163
  );
991
1164
 
992
1165
  expect(config).toEqual(
@@ -1005,7 +1178,8 @@ describe("normalizeAndValidateConfig()", () => {
1005
1178
  it("should error if unsafe is a number", () => {
1006
1179
  const { config, diagnostics } = normalizeAndValidateConfig(
1007
1180
  { unsafe: 999 } as unknown as RawConfig,
1008
- undefined
1181
+ undefined,
1182
+ { env: undefined }
1009
1183
  );
1010
1184
 
1011
1185
  expect(config).toEqual(
@@ -1024,7 +1198,8 @@ describe("normalizeAndValidateConfig()", () => {
1024
1198
  it("should error if unsafe is null", () => {
1025
1199
  const { config, diagnostics } = normalizeAndValidateConfig(
1026
1200
  { unsafe: null } as unknown as RawConfig,
1027
- undefined
1201
+ undefined,
1202
+ { env: undefined }
1028
1203
  );
1029
1204
 
1030
1205
  expect(config).toEqual(
@@ -1043,7 +1218,8 @@ describe("normalizeAndValidateConfig()", () => {
1043
1218
  it("should error if unsafe.bindings is not defined", () => {
1044
1219
  const { config, diagnostics } = normalizeAndValidateConfig(
1045
1220
  { unsafe: {} } as unknown as RawConfig,
1046
- undefined
1221
+ undefined,
1222
+ { env: undefined }
1047
1223
  );
1048
1224
 
1049
1225
  expect(config).toEqual(
@@ -1062,7 +1238,8 @@ describe("normalizeAndValidateConfig()", () => {
1062
1238
  it("should error if unsafe.bindings is an object", () => {
1063
1239
  const { config, diagnostics } = normalizeAndValidateConfig(
1064
1240
  { unsafe: { bindings: {} } } as unknown as RawConfig,
1065
- undefined
1241
+ undefined,
1242
+ { env: undefined }
1066
1243
  );
1067
1244
 
1068
1245
  expect(config).toEqual(
@@ -1083,7 +1260,8 @@ describe("normalizeAndValidateConfig()", () => {
1083
1260
  it("should error if unsafe.bindings is a string", () => {
1084
1261
  const { config, diagnostics } = normalizeAndValidateConfig(
1085
1262
  { unsafe: { bindings: "BAD" } } as unknown as RawConfig,
1086
- undefined
1263
+ undefined,
1264
+ { env: undefined }
1087
1265
  );
1088
1266
 
1089
1267
  expect(config).toEqual(
@@ -1104,7 +1282,8 @@ describe("normalizeAndValidateConfig()", () => {
1104
1282
  it("should error if unsafe.bindings is a number", () => {
1105
1283
  const { config, diagnostics } = normalizeAndValidateConfig(
1106
1284
  { unsafe: { bindings: 999 } } as unknown as RawConfig,
1107
- undefined
1285
+ undefined,
1286
+ { env: undefined }
1108
1287
  );
1109
1288
 
1110
1289
  expect(config).toEqual(
@@ -1125,7 +1304,8 @@ describe("normalizeAndValidateConfig()", () => {
1125
1304
  it("should error if unsafe.bindings is null", () => {
1126
1305
  const { config, diagnostics } = normalizeAndValidateConfig(
1127
1306
  { unsafe: { bindings: null } } as unknown as RawConfig,
1128
- undefined
1307
+ undefined,
1308
+ { env: undefined }
1129
1309
  );
1130
1310
 
1131
1311
  expect(config).toEqual(
@@ -1159,7 +1339,8 @@ describe("normalizeAndValidateConfig()", () => {
1159
1339
  ],
1160
1340
  },
1161
1341
  } as unknown as RawConfig,
1162
- undefined
1342
+ undefined,
1343
+ { env: undefined }
1163
1344
  );
1164
1345
 
1165
1346
  expect(config).toEqual(
@@ -1175,15 +1356,15 @@ describe("normalizeAndValidateConfig()", () => {
1175
1356
  "Processing wrangler configuration:
1176
1357
 
1177
1358
  - \\"unsafe.bindings[0]\\": {}
1178
- - ERROR: should have a string \\"name\\" field.
1179
- - ERROR: should have a string \\"type\\" field.
1359
+ - binding should have a string \\"name\\" field.
1360
+ - binding should have a string \\"type\\" field.
1180
1361
 
1181
1362
  - \\"unsafe.bindings[1]\\": {\\"name\\":\\"UNSAFE_BINDING_1\\"}
1182
- - ERROR: should have a string \\"type\\" field.
1363
+ - binding should have a string \\"type\\" field.
1183
1364
 
1184
1365
  - \\"unsafe.bindings[2]\\": {\\"name\\":2666,\\"type\\":2777}
1185
- - ERROR: should have a string \\"name\\" field.
1186
- - ERROR: should have a string \\"type\\" field."
1366
+ - binding should have a string \\"name\\" field.
1367
+ - binding should have a string \\"type\\" field."
1187
1368
  `);
1188
1369
  });
1189
1370
  });
@@ -1203,7 +1384,8 @@ describe("normalizeAndValidateConfig()", () => {
1203
1384
 
1204
1385
  const { config, diagnostics } = normalizeAndValidateConfig(
1205
1386
  rawConfig,
1206
- undefined
1387
+ undefined,
1388
+ { env: undefined }
1207
1389
  );
1208
1390
 
1209
1391
  expect("experimental_services" in config).toBe(false);
@@ -1227,75 +1409,247 @@ describe("normalizeAndValidateConfig()", () => {
1227
1409
  `);
1228
1410
  });
1229
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
+ });
1230
1432
  });
1231
1433
 
1232
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
+
1233
1480
  it("should use top-level values for inheritable config fields", () => {
1234
- const expectedConfig: RawConfig = {
1481
+ const main = "src/index.ts";
1482
+ const resolvedMain = path.resolve(process.cwd(), main);
1483
+ const rawConfig: RawConfig = {
1235
1484
  name: "NAME",
1236
1485
  account_id: "ACCOUNT_ID",
1237
1486
  compatibility_date: "2022-01-01",
1238
1487
  compatibility_flags: ["FLAG1", "FLAG2"],
1239
1488
  workers_dev: false,
1240
1489
  routes: ["ROUTE_1", "ROUTE_2"],
1241
- route: "ROUTE_3",
1242
1490
  jsx_factory: "JSX_FACTORY",
1243
1491
  jsx_fragment: "JSX_FRAGMENT",
1492
+ tsconfig: "path/to/tsconfig.json",
1244
1493
  triggers: { crons: ["CRON_1", "CRON_2"] },
1245
1494
  usage_model: "bundled",
1495
+ main,
1496
+ build: {
1497
+ command: "COMMAND",
1498
+ cwd: "CWD",
1499
+ watch_dir: "WATCH_DIR",
1500
+ },
1246
1501
  };
1247
1502
 
1248
1503
  const { config, diagnostics } = normalizeAndValidateConfig(
1249
- { ...expectedConfig, env: { DEV: {} } },
1250
- undefined
1504
+ { ...rawConfig, env: { DEV: {} } },
1505
+ undefined,
1506
+ { env: "DEV" }
1251
1507
  );
1252
1508
 
1253
- 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
+ );
1254
1516
  expect(diagnostics.hasErrors()).toBe(false);
1255
1517
  expect(diagnostics.hasWarnings()).toBe(false);
1256
1518
  });
1257
1519
 
1258
1520
  it("should override top-level values for inheritable config fields", () => {
1259
- const environment: RawEnvironment = {
1521
+ const main = "src/index.ts";
1522
+ const resolvedMain = path.resolve(process.cwd(), main);
1523
+ const rawEnv: RawEnvironment = {
1260
1524
  name: "ENV_NAME",
1261
1525
  account_id: "ENV_ACCOUNT_ID",
1262
1526
  compatibility_date: "2022-02-02",
1263
1527
  compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
1264
1528
  workers_dev: true,
1265
1529
  routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
1266
- route: "ENV_ROUTE_3",
1267
1530
  jsx_factory: "ENV_JSX_FACTORY",
1268
1531
  jsx_fragment: "ENV_JSX_FRAGMENT",
1532
+ tsconfig: "ENV_path/to/tsconfig.json",
1269
1533
  triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
1270
1534
  usage_model: "unbound",
1535
+ main,
1536
+ build: {
1537
+ command: "ENV_COMMAND",
1538
+ cwd: "ENV_CWD",
1539
+ watch_dir: "ENV_WATCH_DIR",
1540
+ },
1271
1541
  };
1272
- const expectedConfig: RawConfig = {
1542
+ const rawConfig: RawConfig = {
1273
1543
  name: "NAME",
1274
1544
  account_id: "ACCOUNT_ID",
1275
1545
  compatibility_date: "2022-01-01",
1276
1546
  compatibility_flags: ["FLAG1", "FLAG2"],
1277
1547
  workers_dev: false,
1278
1548
  routes: ["ROUTE_1", "ROUTE_2"],
1279
- route: "ROUTE_3",
1280
1549
  jsx_factory: "JSX_FACTORY",
1281
1550
  jsx_fragment: "JSX_FRAGMENT",
1551
+ tsconfig: "path/to/tsconfig.json",
1282
1552
  triggers: { crons: ["CRON_1", "CRON_2"] },
1283
1553
  usage_model: "bundled",
1554
+ main: "top-level.js",
1555
+ build: {
1556
+ command: "COMMAND",
1557
+ cwd: "CWD",
1558
+ watch_dir: "WATCH_DIR",
1559
+ },
1284
1560
  env: {
1285
- ENV1: environment,
1561
+ ENV1: rawEnv,
1286
1562
  },
1287
1563
  };
1288
1564
 
1289
1565
  const { config, diagnostics } = normalizeAndValidateConfig(
1290
- expectedConfig,
1291
- undefined
1566
+ rawConfig,
1567
+ undefined,
1568
+ { env: "ENV1" }
1292
1569
  );
1293
1570
 
1294
- expect(config.env.ENV1).toEqual(expect.objectContaining(environment));
1571
+ expect(config).toEqual(
1572
+ expect.objectContaining({ ...rawEnv, main: resolvedMain })
1573
+ );
1295
1574
  expect(diagnostics.hasErrors()).toBe(false);
1296
1575
  expect(diagnostics.hasWarnings()).toBe(false);
1297
1576
  });
1298
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
+
1299
1653
  it("should warn for non-inherited fields that are missing in environments", () => {
1300
1654
  const vars: RawConfig["vars"] = {
1301
1655
  FOO: "foo",
@@ -1319,10 +1673,11 @@ describe("normalizeAndValidateConfig()", () => {
1319
1673
 
1320
1674
  const { config, diagnostics } = normalizeAndValidateConfig(
1321
1675
  rawConfig,
1322
- undefined
1676
+ undefined,
1677
+ { env: "ENV1" }
1323
1678
  );
1324
1679
 
1325
- expect(config.env.ENV1).toEqual(
1680
+ expect(config).toEqual(
1326
1681
  expect.not.objectContaining({
1327
1682
  vars,
1328
1683
  durable_objects,
@@ -1365,31 +1720,45 @@ describe("normalizeAndValidateConfig()", () => {
1365
1720
  route: 888,
1366
1721
  jsx_factory: 999,
1367
1722
  jsx_fragment: 1000,
1723
+ tsconfig: 123,
1368
1724
  triggers: { crons: [1111, 1222] },
1369
1725
  usage_model: "INVALID",
1726
+ main: 1333,
1727
+ build: {
1728
+ command: 1444,
1729
+ cwd: 1555,
1730
+ watch_dir: 1666,
1731
+ },
1370
1732
  } as unknown as RawEnvironment;
1371
1733
 
1372
1734
  const { config, diagnostics } = normalizeAndValidateConfig(
1373
1735
  { env: { ENV1: expectedConfig } },
1374
- undefined
1736
+ undefined,
1737
+ { env: "ENV1" }
1375
1738
  );
1376
1739
 
1377
- expect(config.env.ENV1).toEqual(expect.objectContaining(expectedConfig));
1740
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
1378
1741
  expect(diagnostics.hasWarnings()).toBe(false);
1379
1742
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1380
1743
  "Processing wrangler configuration:
1381
1744
 
1382
1745
  - \\"env.ENV1\\" environment configuration
1383
- - Expected \\"route\\" field to be a string but got 888.
1384
- - Expected \\"routes\\" field to be an array of strings but got [666,777].
1385
- - Expected \\"workers_dev\\" field to be a boolean but got \\"BAD\\".
1386
- - Expected \\"account_id\\" field to be a string but got 222.
1387
- - Expected \\"compatibility_date\\" field to be a string but got 333.
1388
- - Expected \\"compatibility_flags\\" field to be an array of strings but got [444,555].
1389
- - Expected \\"jsx_factory\\" field to be a string but got 999.
1390
- - Expected \\"jsx_fragment\\" field to be a string but got 1000.
1391
- - Expected \\"name\\" field to be a string but got 111.
1392
- - Expected \\"usage_model\\" field to be on of bundled,unbound but got \\"INVALID\\"."
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.
1761
+ - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
1393
1762
  `);
1394
1763
  });
1395
1764
 
@@ -1397,10 +1766,11 @@ describe("normalizeAndValidateConfig()", () => {
1397
1766
  it("should error if durable_objects is an array", () => {
1398
1767
  const { config, diagnostics } = normalizeAndValidateConfig(
1399
1768
  { env: { ENV1: { durable_objects: [] } } } as unknown as RawConfig,
1400
- undefined
1769
+ undefined,
1770
+ { env: "ENV1" }
1401
1771
  );
1402
1772
 
1403
- expect(config.env.ENV1).toEqual(
1773
+ expect(config).toEqual(
1404
1774
  expect.not.objectContaining({ durable_objects: expect.anything })
1405
1775
  );
1406
1776
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1415,10 +1785,11 @@ describe("normalizeAndValidateConfig()", () => {
1415
1785
  it("should error if durable_objects is a string", () => {
1416
1786
  const { config, diagnostics } = normalizeAndValidateConfig(
1417
1787
  { env: { ENV1: { durable_objects: "BAD" } } } as unknown as RawConfig,
1418
- undefined
1788
+ undefined,
1789
+ { env: "ENV1" }
1419
1790
  );
1420
1791
 
1421
- expect(config.env.ENV1).toEqual(
1792
+ expect(config).toEqual(
1422
1793
  expect.not.objectContaining({ durable_objects: expect.anything })
1423
1794
  );
1424
1795
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1433,10 +1804,11 @@ describe("normalizeAndValidateConfig()", () => {
1433
1804
  it("should error if durable_objects is a number", () => {
1434
1805
  const { config, diagnostics } = normalizeAndValidateConfig(
1435
1806
  { env: { ENV1: { durable_objects: 999 } } } as unknown as RawConfig,
1436
- undefined
1807
+ undefined,
1808
+ { env: "ENV1" }
1437
1809
  );
1438
1810
 
1439
- expect(config.env.ENV1).toEqual(
1811
+ expect(config).toEqual(
1440
1812
  expect.not.objectContaining({ durable_objects: expect.anything })
1441
1813
  );
1442
1814
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1451,10 +1823,11 @@ describe("normalizeAndValidateConfig()", () => {
1451
1823
  it("should error if durable_objects is null", () => {
1452
1824
  const { config, diagnostics } = normalizeAndValidateConfig(
1453
1825
  { env: { ENV1: { durable_objects: null } } } as unknown as RawConfig,
1454
- undefined
1826
+ undefined,
1827
+ { env: "ENV1" }
1455
1828
  );
1456
1829
 
1457
- expect(config.env.ENV1).toEqual(
1830
+ expect(config).toEqual(
1458
1831
  expect.not.objectContaining({ durable_objects: expect.anything })
1459
1832
  );
1460
1833
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1469,10 +1842,11 @@ describe("normalizeAndValidateConfig()", () => {
1469
1842
  it("should error if durable_objects.bindings is not defined", () => {
1470
1843
  const { config, diagnostics } = normalizeAndValidateConfig(
1471
1844
  { env: { ENV1: { durable_objects: {} } } } as unknown as RawConfig,
1472
- undefined
1845
+ undefined,
1846
+ { env: "ENV1" }
1473
1847
  );
1474
1848
 
1475
- expect(config.env.ENV1).toEqual(
1849
+ expect(config).toEqual(
1476
1850
  expect.not.objectContaining({ durable_objects: expect.anything })
1477
1851
  );
1478
1852
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1489,10 +1863,11 @@ describe("normalizeAndValidateConfig()", () => {
1489
1863
  {
1490
1864
  env: { ENV1: { durable_objects: { bindings: {} } } },
1491
1865
  } as unknown as RawConfig,
1492
- undefined
1866
+ undefined,
1867
+ { env: "ENV1" }
1493
1868
  );
1494
1869
 
1495
- expect(config.env.ENV1).toEqual(
1870
+ expect(config).toEqual(
1496
1871
  expect.not.objectContaining({
1497
1872
  durable_objects: { bindings: expect.anything },
1498
1873
  })
@@ -1511,10 +1886,11 @@ describe("normalizeAndValidateConfig()", () => {
1511
1886
  {
1512
1887
  env: { ENV1: { durable_objects: { bindings: "BAD" } } },
1513
1888
  } as unknown as RawConfig,
1514
- undefined
1889
+ undefined,
1890
+ { env: "ENV1" }
1515
1891
  );
1516
1892
 
1517
- expect(config.env.ENV1).toEqual(
1893
+ expect(config).toEqual(
1518
1894
  expect.not.objectContaining({
1519
1895
  durable_objects: { bindings: expect.anything },
1520
1896
  })
@@ -1533,10 +1909,11 @@ describe("normalizeAndValidateConfig()", () => {
1533
1909
  {
1534
1910
  env: { ENV1: { durable_objects: { bindings: 999 } } },
1535
1911
  } as unknown as RawConfig,
1536
- undefined
1912
+ undefined,
1913
+ { env: "ENV1" }
1537
1914
  );
1538
1915
 
1539
- expect(config.env.ENV1).toEqual(
1916
+ expect(config).toEqual(
1540
1917
  expect.not.objectContaining({
1541
1918
  durable_objects: { bindings: expect.anything },
1542
1919
  })
@@ -1555,10 +1932,11 @@ describe("normalizeAndValidateConfig()", () => {
1555
1932
  {
1556
1933
  env: { ENV1: { durable_objects: { bindings: null } } },
1557
1934
  } as unknown as RawConfig,
1558
- undefined
1935
+ undefined,
1936
+ { env: "ENV1" }
1559
1937
  );
1560
1938
 
1561
- expect(config.env.ENV1).toEqual(
1939
+ expect(config).toEqual(
1562
1940
  expect.not.objectContaining({
1563
1941
  durable_objects: { bindings: expect.anything },
1564
1942
  })
@@ -1592,10 +1970,11 @@ describe("normalizeAndValidateConfig()", () => {
1592
1970
  },
1593
1971
  },
1594
1972
  } as unknown as RawConfig,
1595
- undefined
1973
+ undefined,
1974
+ { env: "ENV1" }
1596
1975
  );
1597
1976
 
1598
- expect(config.env.ENV1).toEqual(
1977
+ expect(config).toEqual(
1599
1978
  expect.not.objectContaining({
1600
1979
  durable_objects: { bindings: expect.anything },
1601
1980
  })
@@ -1607,20 +1986,20 @@ describe("normalizeAndValidateConfig()", () => {
1607
1986
  - \\"env.ENV1\\" environment configuration
1608
1987
 
1609
1988
  - \\"env.ENV1.durable_objects.bindings[0]\\": {}
1610
- - ERROR: bindings should have a string \\"name\\" field.
1611
- - ERROR: should have a string \\"class_name\\" field.
1989
+ - binding should have a string \\"name\\" field.
1990
+ - binding should have a string \\"class_name\\" field.
1612
1991
 
1613
1992
  - \\"env.ENV1.durable_objects.bindings[1]\\": {\\"name\\":\\"VALID\\"}
1614
- - ERROR: should have a string \\"class_name\\" field.
1993
+ - binding should have a string \\"class_name\\" field.
1615
1994
 
1616
1995
  - \\"env.ENV1.durable_objects.bindings[2]\\": {\\"name\\":1555,\\"class_name\\":1666}
1617
- - ERROR: bindings should have a string \\"name\\" field.
1618
- - ERROR: should have a string \\"class_name\\" field.
1996
+ - binding should have a string \\"name\\" field.
1997
+ - binding should have a string \\"class_name\\" field.
1619
1998
 
1620
1999
  - \\"env.ENV1.durable_objects.bindings[3]\\": {\\"name\\":1777,\\"class_name\\":1888,\\"script_name\\":1999}
1621
- - ERROR: bindings should have a string \\"name\\" field.
1622
- - ERROR: should have a string \\"class_name\\" field.
1623
- - ERROR: should, optionally, have a string \\"script_name\\" field."
2000
+ - binding should have a string \\"name\\" field.
2001
+ - binding should have a string \\"class_name\\" field.
2002
+ - binding should, optionally, have a string \\"script_name\\" field."
1624
2003
  `);
1625
2004
  });
1626
2005
  });
@@ -1629,10 +2008,11 @@ describe("normalizeAndValidateConfig()", () => {
1629
2008
  it("should error if kv_namespaces is an object", () => {
1630
2009
  const { config, diagnostics } = normalizeAndValidateConfig(
1631
2010
  { env: { ENV1: { kv_namespaces: {} } } } as unknown as RawConfig,
1632
- undefined
2011
+ undefined,
2012
+ { env: "ENV1" }
1633
2013
  );
1634
2014
 
1635
- expect(config.env.ENV1).toEqual(
2015
+ expect(config).toEqual(
1636
2016
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1637
2017
  );
1638
2018
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1647,10 +2027,11 @@ describe("normalizeAndValidateConfig()", () => {
1647
2027
  it("should error if kv_namespaces is a string", () => {
1648
2028
  const { config, diagnostics } = normalizeAndValidateConfig(
1649
2029
  { env: { ENV1: { kv_namespaces: "BAD" } } } as unknown as RawConfig,
1650
- undefined
2030
+ undefined,
2031
+ { env: "ENV1" }
1651
2032
  );
1652
2033
 
1653
- expect(config.env.ENV1).toEqual(
2034
+ expect(config).toEqual(
1654
2035
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1655
2036
  );
1656
2037
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1665,10 +2046,11 @@ describe("normalizeAndValidateConfig()", () => {
1665
2046
  it("should error if kv_namespaces is a number", () => {
1666
2047
  const { config, diagnostics } = normalizeAndValidateConfig(
1667
2048
  { env: { ENV1: { kv_namespaces: 999 } } } as unknown as RawConfig,
1668
- undefined
2049
+ undefined,
2050
+ { env: "ENV1" }
1669
2051
  );
1670
2052
 
1671
- expect(config.env.ENV1).toEqual(
2053
+ expect(config).toEqual(
1672
2054
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1673
2055
  );
1674
2056
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1683,10 +2065,11 @@ describe("normalizeAndValidateConfig()", () => {
1683
2065
  it("should error if kv_namespaces is null", () => {
1684
2066
  const { config, diagnostics } = normalizeAndValidateConfig(
1685
2067
  { env: { ENV1: { kv_namespaces: null } } } as unknown as RawConfig,
1686
- undefined
2068
+ undefined,
2069
+ { env: "ENV1" }
1687
2070
  );
1688
2071
 
1689
- expect(config.env.ENV1).toEqual(
2072
+ expect(config).toEqual(
1690
2073
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1691
2074
  );
1692
2075
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1716,10 +2099,11 @@ describe("normalizeAndValidateConfig()", () => {
1716
2099
  },
1717
2100
  },
1718
2101
  } as unknown as RawConfig,
1719
- undefined
2102
+ undefined,
2103
+ { env: "ENV1" }
1720
2104
  );
1721
2105
 
1722
- expect(config.env.ENV1).toEqual(
2106
+ expect(config).toEqual(
1723
2107
  expect.not.objectContaining({
1724
2108
  kv_namespaces: { bindings: expect.anything },
1725
2109
  })
@@ -1743,10 +2127,11 @@ describe("normalizeAndValidateConfig()", () => {
1743
2127
  it("should error if r2_buckets is an object", () => {
1744
2128
  const { config, diagnostics } = normalizeAndValidateConfig(
1745
2129
  { env: { ENV1: { r2_buckets: {} } } } as unknown as RawConfig,
1746
- undefined
2130
+ undefined,
2131
+ { env: "ENV1" }
1747
2132
  );
1748
2133
 
1749
- expect(config.env.ENV1).toEqual(
2134
+ expect(config).toEqual(
1750
2135
  expect.not.objectContaining({ r2_buckets: expect.anything })
1751
2136
  );
1752
2137
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1761,10 +2146,11 @@ describe("normalizeAndValidateConfig()", () => {
1761
2146
  it("should error if r2_buckets is a string", () => {
1762
2147
  const { config, diagnostics } = normalizeAndValidateConfig(
1763
2148
  { env: { ENV1: { r2_buckets: "BAD" } } } as unknown as RawConfig,
1764
- undefined
2149
+ undefined,
2150
+ { env: "ENV1" }
1765
2151
  );
1766
2152
 
1767
- expect(config.env.ENV1).toEqual(
2153
+ expect(config).toEqual(
1768
2154
  expect.not.objectContaining({ r2_buckets: expect.anything })
1769
2155
  );
1770
2156
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1779,10 +2165,11 @@ describe("normalizeAndValidateConfig()", () => {
1779
2165
  it("should error if r2_buckets is a number", () => {
1780
2166
  const { config, diagnostics } = normalizeAndValidateConfig(
1781
2167
  { env: { ENV1: { r2_buckets: 999 } } } as unknown as RawConfig,
1782
- undefined
2168
+ undefined,
2169
+ { env: "ENV1" }
1783
2170
  );
1784
2171
 
1785
- expect(config.env.ENV1).toEqual(
2172
+ expect(config).toEqual(
1786
2173
  expect.not.objectContaining({ r2_buckets: expect.anything })
1787
2174
  );
1788
2175
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1797,10 +2184,11 @@ describe("normalizeAndValidateConfig()", () => {
1797
2184
  it("should error if r2_buckets is null", () => {
1798
2185
  const { config, diagnostics } = normalizeAndValidateConfig(
1799
2186
  { env: { ENV1: { r2_buckets: null } } } as unknown as RawConfig,
1800
- undefined
2187
+ undefined,
2188
+ { env: "ENV1" }
1801
2189
  );
1802
2190
 
1803
- expect(config.env.ENV1).toEqual(
2191
+ expect(config).toEqual(
1804
2192
  expect.not.objectContaining({ r2_buckets: expect.anything })
1805
2193
  );
1806
2194
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1830,10 +2218,11 @@ describe("normalizeAndValidateConfig()", () => {
1830
2218
  },
1831
2219
  },
1832
2220
  } as unknown as RawConfig,
1833
- undefined
2221
+ undefined,
2222
+ { env: "ENV1" }
1834
2223
  );
1835
2224
 
1836
- expect(config.env.ENV1).toEqual(
2225
+ expect(config).toEqual(
1837
2226
  expect.not.objectContaining({
1838
2227
  r2_buckets: { bindings: expect.anything },
1839
2228
  })
@@ -1857,10 +2246,11 @@ describe("normalizeAndValidateConfig()", () => {
1857
2246
  it("should error if unsafe is an array", () => {
1858
2247
  const { config, diagnostics } = normalizeAndValidateConfig(
1859
2248
  { env: { ENV1: { unsafe: [] } } } as unknown as RawConfig,
1860
- undefined
2249
+ undefined,
2250
+ { env: "ENV1" }
1861
2251
  );
1862
2252
 
1863
- expect(config.env.ENV1).toEqual(
2253
+ expect(config).toEqual(
1864
2254
  expect.not.objectContaining({ unsafe: expect.anything })
1865
2255
  );
1866
2256
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1880,10 +2270,11 @@ describe("normalizeAndValidateConfig()", () => {
1880
2270
  it("should error if unsafe is a string", () => {
1881
2271
  const { config, diagnostics } = normalizeAndValidateConfig(
1882
2272
  { env: { ENV1: { unsafe: "BAD" } } } as unknown as RawConfig,
1883
- undefined
2273
+ undefined,
2274
+ { env: "ENV1" }
1884
2275
  );
1885
2276
 
1886
- expect(config.env.ENV1).toEqual(
2277
+ expect(config).toEqual(
1887
2278
  expect.not.objectContaining({ unsafe: expect.anything })
1888
2279
  );
1889
2280
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1903,10 +2294,11 @@ describe("normalizeAndValidateConfig()", () => {
1903
2294
  it("should error if unsafe is a number", () => {
1904
2295
  const { config, diagnostics } = normalizeAndValidateConfig(
1905
2296
  { env: { ENV1: { unsafe: 999 } } } as unknown as RawConfig,
1906
- undefined
2297
+ undefined,
2298
+ { env: "ENV1" }
1907
2299
  );
1908
2300
 
1909
- expect(config.env.ENV1).toEqual(
2301
+ expect(config).toEqual(
1910
2302
  expect.not.objectContaining({ unsafe: expect.anything })
1911
2303
  );
1912
2304
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1926,10 +2318,11 @@ describe("normalizeAndValidateConfig()", () => {
1926
2318
  it("should error if unsafe is null", () => {
1927
2319
  const { config, diagnostics } = normalizeAndValidateConfig(
1928
2320
  { env: { ENV1: { unsafe: null } } } as unknown as RawConfig,
1929
- undefined
2321
+ undefined,
2322
+ { env: "ENV1" }
1930
2323
  );
1931
2324
 
1932
- expect(config.env.ENV1).toEqual(
2325
+ expect(config).toEqual(
1933
2326
  expect.not.objectContaining({ unsafe: expect.anything })
1934
2327
  );
1935
2328
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1949,10 +2342,11 @@ describe("normalizeAndValidateConfig()", () => {
1949
2342
  it("should error if unsafe.bindings is not defined", () => {
1950
2343
  const { config, diagnostics } = normalizeAndValidateConfig(
1951
2344
  { env: { ENV1: { unsafe: {} } } } as unknown as RawConfig,
1952
- undefined
2345
+ undefined,
2346
+ { env: "ENV1" }
1953
2347
  );
1954
2348
 
1955
- expect(config.env.ENV1).toEqual(
2349
+ expect(config).toEqual(
1956
2350
  expect.not.objectContaining({ unsafe: expect.anything })
1957
2351
  );
1958
2352
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1974,10 +2368,11 @@ describe("normalizeAndValidateConfig()", () => {
1974
2368
  {
1975
2369
  env: { ENV1: { unsafe: { bindings: {} } } },
1976
2370
  } as unknown as RawConfig,
1977
- undefined
2371
+ undefined,
2372
+ { env: "ENV1" }
1978
2373
  );
1979
2374
 
1980
- expect(config.env.ENV1).toEqual(
2375
+ expect(config).toEqual(
1981
2376
  expect.not.objectContaining({
1982
2377
  unsafe: { bindings: expect.anything },
1983
2378
  })
@@ -2001,10 +2396,11 @@ describe("normalizeAndValidateConfig()", () => {
2001
2396
  {
2002
2397
  env: { ENV1: { unsafe: { bindings: "BAD" } } },
2003
2398
  } as unknown as RawConfig,
2004
- undefined
2399
+ undefined,
2400
+ { env: "ENV1" }
2005
2401
  );
2006
2402
 
2007
- expect(config.env.ENV1).toEqual(
2403
+ expect(config).toEqual(
2008
2404
  expect.not.objectContaining({
2009
2405
  unsafe: { bindings: expect.anything },
2010
2406
  })
@@ -2028,10 +2424,11 @@ describe("normalizeAndValidateConfig()", () => {
2028
2424
  {
2029
2425
  env: { ENV1: { unsafe: { bindings: 999 } } },
2030
2426
  } as unknown as RawConfig,
2031
- undefined
2427
+ undefined,
2428
+ { env: "ENV1" }
2032
2429
  );
2033
2430
 
2034
- expect(config.env.ENV1).toEqual(
2431
+ expect(config).toEqual(
2035
2432
  expect.not.objectContaining({
2036
2433
  unsafe: { bindings: expect.anything },
2037
2434
  })
@@ -2055,10 +2452,11 @@ describe("normalizeAndValidateConfig()", () => {
2055
2452
  {
2056
2453
  env: { ENV1: { unsafe: { bindings: null } } },
2057
2454
  } as unknown as RawConfig,
2058
- undefined
2455
+ undefined,
2456
+ { env: "ENV1" }
2059
2457
  );
2060
2458
 
2061
- expect(config.env.ENV1).toEqual(
2459
+ expect(config).toEqual(
2062
2460
  expect.not.objectContaining({
2063
2461
  unsafe: { bindings: expect.anything },
2064
2462
  })
@@ -2097,10 +2495,11 @@ describe("normalizeAndValidateConfig()", () => {
2097
2495
  },
2098
2496
  },
2099
2497
  } as unknown as RawConfig,
2100
- undefined
2498
+ undefined,
2499
+ { env: "ENV1" }
2101
2500
  );
2102
2501
 
2103
- expect(config.env.ENV1).toEqual(
2502
+ expect(config).toEqual(
2104
2503
  expect.not.objectContaining({
2105
2504
  durable_objects: { bindings: expect.anything },
2106
2505
  })
@@ -2117,15 +2516,15 @@ describe("normalizeAndValidateConfig()", () => {
2117
2516
  - \\"env.ENV1\\" environment configuration
2118
2517
 
2119
2518
  - \\"env.ENV1.unsafe.bindings[0]\\": {}
2120
- - ERROR: should have a string \\"name\\" field.
2121
- - ERROR: should have a string \\"type\\" field.
2519
+ - binding should have a string \\"name\\" field.
2520
+ - binding should have a string \\"type\\" field.
2122
2521
 
2123
2522
  - \\"env.ENV1.unsafe.bindings[1]\\": {\\"name\\":\\"UNSAFE_BINDING_1\\"}
2124
- - ERROR: should have a string \\"type\\" field.
2523
+ - binding should have a string \\"type\\" field.
2125
2524
 
2126
2525
  - \\"env.ENV1.unsafe.bindings[2]\\": {\\"name\\":2666,\\"type\\":2777}
2127
- - ERROR: should have a string \\"name\\" field.
2128
- - ERROR: should have a string \\"type\\" field."
2526
+ - binding should have a string \\"name\\" field.
2527
+ - binding should have a string \\"type\\" field."
2129
2528
  `);
2130
2529
  });
2131
2530
  });
@@ -2149,12 +2548,13 @@ describe("normalizeAndValidateConfig()", () => {
2149
2548
  ENV1: environment,
2150
2549
  },
2151
2550
  },
2152
- undefined
2551
+ undefined,
2552
+ { env: "ENV1" }
2153
2553
  );
2154
2554
 
2155
- expect("experimental_services" in config.env.ENV1).toBe(false);
2555
+ expect("experimental_services" in config).toBe(false);
2156
2556
  // Zone is not removed yet, since `route` commands might use it
2157
- expect(config.env.ENV1.zone_id).toEqual("ZONE_ID");
2557
+ expect(config.zone_id).toEqual("ZONE_ID");
2158
2558
  expect(diagnostics.hasErrors()).toBe(false);
2159
2559
  expect(diagnostics.hasWarnings()).toBe(true);
2160
2560
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -2175,6 +2575,241 @@ describe("normalizeAndValidateConfig()", () => {
2175
2575
  `);
2176
2576
  });
2177
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
+ });
2178
2813
  });
2179
2814
  });
2180
2815