wrangler 0.0.0-e95bea2 → 0.0.0-e95e5a0

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 (93) hide show
  1. package/README.md +25 -14
  2. package/bin/wrangler.js +13 -1
  3. package/miniflare-dist/index.mjs +4886 -0
  4. package/package.json +33 -25
  5. package/pages/functions/buildPlugin.ts +92 -0
  6. package/pages/functions/buildWorker.ts +80 -4
  7. package/pages/functions/filepath-routing.test.ts +136 -25
  8. package/pages/functions/filepath-routing.ts +14 -3
  9. package/pages/functions/routes.ts +6 -1
  10. package/pages/functions/template-plugin.ts +146 -0
  11. package/pages/functions/template-worker.ts +21 -8
  12. package/src/__tests__/config-cache.test.ts +36 -0
  13. package/src/__tests__/configuration.test.ts +1179 -271
  14. package/src/__tests__/dev.test.tsx +382 -25
  15. package/src/__tests__/guess-worker-format.test.ts +28 -1
  16. package/src/__tests__/helpers/mock-account-id.ts +4 -0
  17. package/src/__tests__/helpers/mock-cfetch.ts +5 -1
  18. package/src/__tests__/helpers/mock-console.ts +20 -3
  19. package/src/__tests__/helpers/mock-dialogs.ts +26 -1
  20. package/src/__tests__/helpers/mock-http-server.ts +46 -0
  21. package/src/__tests__/helpers/mock-istty.ts +27 -0
  22. package/src/__tests__/helpers/mock-kv.ts +9 -16
  23. package/src/__tests__/helpers/mock-oauth-flow.ts +255 -0
  24. package/src/__tests__/helpers/run-in-tmp.ts +10 -0
  25. package/src/__tests__/helpers/write-worker-source.ts +31 -0
  26. package/src/__tests__/https-options.test.ts +5 -2
  27. package/src/__tests__/index.test.ts +27 -769
  28. package/src/__tests__/init.test.ts +1516 -0
  29. package/src/__tests__/jest.setup.ts +4 -4
  30. package/src/__tests__/kv.test.ts +172 -126
  31. package/src/__tests__/logger.test.ts +115 -0
  32. package/src/__tests__/pages.test.ts +311 -26
  33. package/src/__tests__/publish.test.ts +2946 -524
  34. package/src/__tests__/r2.test.ts +26 -10
  35. package/src/__tests__/route.test.ts +4 -4
  36. package/src/__tests__/secret.test.ts +55 -34
  37. package/src/__tests__/tail.test.ts +146 -20
  38. package/src/__tests__/user.test.ts +131 -0
  39. package/src/__tests__/whoami.test.tsx +26 -7
  40. package/src/bundle.ts +30 -3
  41. package/src/cfetch/internal.ts +9 -7
  42. package/src/cli.ts +5 -11
  43. package/src/config/README.md +7 -7
  44. package/src/config/config.ts +33 -78
  45. package/src/config/environment.ts +93 -4
  46. package/src/config/index.ts +15 -4
  47. package/src/config/validation-helpers.ts +202 -15
  48. package/src/config/validation.ts +530 -133
  49. package/src/config-cache.ts +45 -0
  50. package/src/create-worker-preview.ts +22 -13
  51. package/src/create-worker-upload-form.ts +32 -9
  52. package/src/dev/dev-vars.ts +36 -0
  53. package/src/dev/dev.tsx +136 -75
  54. package/src/dev/local.tsx +196 -125
  55. package/src/dev/remote.tsx +25 -13
  56. package/src/dev/use-esbuild.ts +23 -5
  57. package/src/dialogs.tsx +16 -6
  58. package/src/entry.ts +119 -11
  59. package/src/environment-variables.ts +3 -1
  60. package/src/errors.ts +11 -0
  61. package/src/https-options.ts +3 -2
  62. package/src/index.tsx +739 -400
  63. package/src/inspect.ts +17 -11
  64. package/src/intl-polyfill.d.ts +139 -0
  65. package/src/{kv/index.tsx → kv.ts} +8 -28
  66. package/src/logger.ts +66 -0
  67. package/src/miniflare-cli/README.md +30 -0
  68. package/src/miniflare-cli/enum-keys.ts +17 -0
  69. package/src/miniflare-cli/index.ts +41 -0
  70. package/src/miniflare-cli/request-context.ts +40 -0
  71. package/src/module-collection.ts +63 -58
  72. package/src/open-in-browser.ts +5 -4
  73. package/src/package-manager.ts +9 -8
  74. package/src/pages.tsx +883 -62
  75. package/src/parse.ts +1 -1
  76. package/src/proxy.ts +32 -21
  77. package/src/publish.ts +276 -161
  78. package/src/sites.tsx +88 -33
  79. package/src/tail/index.ts +2 -2
  80. package/src/tail/printing.ts +13 -8
  81. package/src/update-check.ts +19 -0
  82. package/src/user.tsx +231 -103
  83. package/src/whoami.tsx +2 -1
  84. package/src/worker.ts +15 -6
  85. package/templates/gitignore +171 -0
  86. package/templates/static-asset-facade.js +1 -1
  87. package/wrangler-dist/cli.js +22087 -49340
  88. package/src/__tests__/dev2.test.tsx +0 -152
  89. package/src/__tests__/helpers/mock-user.ts +0 -27
  90. package/src/__tests__/logout.test.ts +0 -50
  91. package/src/__tests__/sentry.test.ts +0 -146
  92. package/src/reporting.ts +0 -131
  93. package/wrangler-dist/cli.js.map +0 -7
@@ -1,10 +1,18 @@
1
1
  import path from "node:path";
2
2
  import { normalizeAndValidateConfig } from "../config/validation";
3
- import type { RawConfig, RawEnvironment } from "../config";
3
+ import { normalizeSlashes } from "./helpers/mock-console";
4
+ import type {
5
+ ConfigFields,
6
+ RawDevConfig,
7
+ RawConfig,
8
+ RawEnvironment,
9
+ } from "../config";
4
10
 
5
11
  describe("normalizeAndValidateConfig()", () => {
6
12
  it("should use defaults for empty configuration", () => {
7
- const { config, diagnostics } = normalizeAndValidateConfig({}, undefined);
13
+ const { config, diagnostics } = normalizeAndValidateConfig({}, undefined, {
14
+ env: undefined,
15
+ });
8
16
 
9
17
  expect(config).toEqual({
10
18
  account_id: undefined,
@@ -17,7 +25,7 @@ describe("normalizeAndValidateConfig()", () => {
17
25
  compatibility_flags: [],
18
26
  configPath: undefined,
19
27
  dev: {
20
- ip: "127.0.0.1",
28
+ ip: "localhost",
21
29
  local_protocol: "http",
22
30
  port: 8787,
23
31
  upstream_protocol: "https",
@@ -26,9 +34,9 @@ describe("normalizeAndValidateConfig()", () => {
26
34
  durable_objects: {
27
35
  bindings: [],
28
36
  },
29
- env: {},
30
37
  jsx_factory: "React.createElement",
31
38
  jsx_fragment: "React.Fragment",
39
+ tsconfig: undefined,
32
40
  kv_namespaces: [],
33
41
  legacy_env: true,
34
42
  main: undefined,
@@ -49,7 +57,8 @@ describe("normalizeAndValidateConfig()", () => {
49
57
  usage_model: undefined,
50
58
  vars: {},
51
59
  wasm_modules: undefined,
52
- workers_dev: true,
60
+ data_blobs: undefined,
61
+ workers_dev: undefined,
53
62
  zone_id: undefined,
54
63
  });
55
64
  expect(diagnostics.hasErrors()).toBe(false);
@@ -58,9 +67,7 @@ describe("normalizeAndValidateConfig()", () => {
58
67
 
59
68
  describe("top-level non-environment configuration", () => {
60
69
  it("should override config defaults with provided values", () => {
61
- const main = "src/index.ts";
62
- const expectedConfig: RawConfig = {
63
- main,
70
+ const expectedConfig: Partial<ConfigFields<RawDevConfig>> = {
64
71
  legacy_env: true,
65
72
  dev: {
66
73
  ip: "255.255.255.255",
@@ -68,29 +75,21 @@ describe("normalizeAndValidateConfig()", () => {
68
75
  local_protocol: "https",
69
76
  upstream_protocol: "http",
70
77
  },
71
- build: {
72
- command: "COMMAND",
73
- cwd: "CWD",
74
- watch_dir: "WATCH_DIR",
75
- },
76
78
  };
77
79
 
78
80
  const { config, diagnostics } = normalizeAndValidateConfig(
79
81
  expectedConfig,
80
- undefined
82
+ undefined,
83
+ { env: undefined }
81
84
  );
82
85
 
83
- const resolvedMain = path.resolve(process.cwd(), main);
84
- expect(config).toEqual(
85
- expect.objectContaining({ ...expectedConfig, main: resolvedMain })
86
- );
86
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
87
87
  expect(diagnostics.hasErrors()).toBe(false);
88
88
  expect(diagnostics.hasWarnings()).toBe(false);
89
89
  });
90
90
 
91
91
  it("should error on invalid top level fields", () => {
92
92
  const expectedConfig = {
93
- main: 111,
94
93
  legacy_env: "FOO",
95
94
  dev: {
96
95
  ip: 222,
@@ -98,16 +97,12 @@ describe("normalizeAndValidateConfig()", () => {
98
97
  local_protocol: "wss",
99
98
  upstream_protocol: "ws",
100
99
  },
101
- build: {
102
- command: 555,
103
- cwd: 666,
104
- watch_dir: 777,
105
- },
106
100
  };
107
101
 
108
102
  const { config, diagnostics } = normalizeAndValidateConfig(
109
103
  expectedConfig as unknown as RawConfig,
110
- undefined
104
+ undefined,
105
+ { env: undefined }
111
106
  );
112
107
 
113
108
  expect(config).toEqual(
@@ -116,11 +111,7 @@ describe("normalizeAndValidateConfig()", () => {
116
111
  expect(diagnostics.hasWarnings()).toBe(false);
117
112
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
118
113
  "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
114
  - Expected \\"legacy_env\\" to be of type boolean but got \\"FOO\\".
123
- - Expected \\"main\\" to be a string but got 111
124
115
  - Expected \\"dev.ip\\" to be of type string but got 222.
125
116
  - Expected \\"dev.port\\" to be of type number but got \\"FOO\\".
126
117
  - Expected \\"dev.local_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"wss\\".
@@ -130,65 +121,44 @@ describe("normalizeAndValidateConfig()", () => {
130
121
 
131
122
  it("should warn on and remove unexpected top level fields", () => {
132
123
  const expectedConfig = {
133
- miniflare: {
134
- host: "127.0.0.1",
124
+ unexpected: {
125
+ subkey: "some-value",
135
126
  },
136
127
  };
137
128
 
138
129
  const { config, diagnostics } = normalizeAndValidateConfig(
139
130
  expectedConfig as unknown as RawConfig,
140
- undefined
131
+ undefined,
132
+ { env: undefined }
141
133
  );
142
134
 
143
- expect("miniflare" in config).toBe(false);
135
+ expect("unexpected" in config).toBe(false);
144
136
  expect(diagnostics.hasErrors()).toBe(false);
145
137
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
146
138
  "Processing wrangler configuration:
147
- - Unexpected fields found in top-level field: \\"miniflare\\""
139
+ - Unexpected fields found in top-level field: \\"unexpected\\""
148
140
  `);
149
141
  });
150
142
 
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
- },
143
+ it("should report a deprecation warning if `miniflare` appears at the top level", () => {
144
+ const expectedConfig = {
145
+ miniflare: {
146
+ host: "localhost",
160
147
  },
161
148
  };
162
149
 
163
150
  const { config, diagnostics } = normalizeAndValidateConfig(
164
- expectedConfig,
165
- path.resolve("project/wrangler.toml")
151
+ expectedConfig as unknown as RawConfig,
152
+ undefined,
153
+ { env: undefined }
166
154
  );
167
155
 
168
- expect(config.main).toEqual(path.resolve("project/src/index.ts"));
169
- expect(config.build.upload).toBeUndefined();
156
+ expect("miniflare" in config).toBe(false);
170
157
  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
- \`\`\`"
158
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
159
+ "Processing wrangler configuration:
160
+ - 😶 Ignored: \\"miniflare\\":
161
+ Wrangler does not use configuration in the \`miniflare\` section. Unless you are using Miniflare directly you can remove this section."
192
162
  `);
193
163
  });
194
164
 
@@ -211,7 +181,8 @@ describe("normalizeAndValidateConfig()", () => {
211
181
 
212
182
  const { config, diagnostics } = normalizeAndValidateConfig(
213
183
  expectedConfig,
214
- undefined
184
+ undefined,
185
+ { env: undefined }
215
186
  );
216
187
 
217
188
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -238,7 +209,8 @@ describe("normalizeAndValidateConfig()", () => {
238
209
 
239
210
  const { config, diagnostics } = normalizeAndValidateConfig(
240
211
  expectedConfig as unknown as RawConfig,
241
- undefined
212
+ undefined,
213
+ { env: undefined }
242
214
  );
243
215
 
244
216
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -259,25 +231,38 @@ describe("normalizeAndValidateConfig()", () => {
259
231
  const expectedConfig: RawConfig = {
260
232
  site: {
261
233
  bucket: "BUCKET",
262
- include: ["INCLUDE_1", "INCLUDE_2"],
234
+ "entry-point": "my-site",
263
235
  exclude: ["EXCLUDE_1", "EXCLUDE_2"],
236
+ include: ["INCLUDE_1", "INCLUDE_2"],
264
237
  },
265
238
  };
266
239
 
267
240
  const { config, diagnostics } = normalizeAndValidateConfig(
268
241
  expectedConfig,
269
- undefined
242
+ undefined,
243
+ { env: undefined }
270
244
  );
271
245
 
272
246
  expect(config).toEqual(expect.objectContaining(expectedConfig));
273
247
  expect(diagnostics.hasErrors()).toBe(false);
274
- expect(diagnostics.hasWarnings()).toBe(false);
248
+ expect(diagnostics.hasWarnings()).toBe(true);
249
+
250
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
251
+ .toMatchInlineSnapshot(`
252
+ "Processing wrangler configuration:
253
+ - Deprecation: \\"site.entry-point\\":
254
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
255
+ \`\`\`
256
+ main = \\"my-site/index.js\\"
257
+ \`\`\`"
258
+ `);
275
259
  });
276
260
 
277
261
  it("should error if `site` config is missing `bucket`", () => {
278
262
  const expectedConfig: RawConfig = {
279
263
  // @ts-expect-error we're intentionally passing an invalid configuration here
280
264
  site: {
265
+ "entry-point": "workers-site",
281
266
  include: ["INCLUDE_1", "INCLUDE_2"],
282
267
  exclude: ["EXCLUDE_1", "EXCLUDE_2"],
283
268
  },
@@ -285,22 +270,35 @@ describe("normalizeAndValidateConfig()", () => {
285
270
 
286
271
  const { config, diagnostics } = normalizeAndValidateConfig(
287
272
  expectedConfig,
288
- undefined
273
+ undefined,
274
+ { env: undefined }
289
275
  );
290
276
 
291
277
  expect(config).toEqual(expect.objectContaining(expectedConfig));
278
+ expect(diagnostics.hasWarnings()).toBe(true);
292
279
  expect(diagnostics.hasErrors()).toBe(true);
280
+
281
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
282
+ .toMatchInlineSnapshot(`
283
+ "Processing wrangler configuration:
284
+ - Deprecation: \\"site.entry-point\\":
285
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
286
+ \`\`\`
287
+ main = \\"workers-site/index.js\\"
288
+ \`\`\`"
289
+ `);
290
+
293
291
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
294
292
  "Processing wrangler configuration:
295
293
  - \\"site.bucket\\" is a required field."
296
294
  `);
297
- expect(diagnostics.hasWarnings()).toBe(false);
298
295
  });
299
296
 
300
297
  it("should error on invalid `site` values", () => {
301
298
  const expectedConfig = {
302
299
  site: {
303
300
  bucket: "BUCKET",
301
+ "entry-point": 111,
304
302
  include: [222, 333],
305
303
  exclude: [444, 555],
306
304
  },
@@ -308,21 +306,33 @@ describe("normalizeAndValidateConfig()", () => {
308
306
 
309
307
  const { config, diagnostics } = normalizeAndValidateConfig(
310
308
  expectedConfig as unknown as RawConfig,
311
- undefined
309
+ undefined,
310
+ { env: undefined }
312
311
  );
313
312
 
314
313
  expect(config).toEqual(expect.objectContaining(expectedConfig));
315
- expect(diagnostics.hasWarnings()).toBe(false);
314
+ expect(diagnostics.hasWarnings()).toBe(true);
316
315
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
317
316
  "Processing wrangler configuration:
318
317
  - Expected \\"sites.include.[0]\\" to be of type string but got 222.
319
318
  - Expected \\"sites.include.[1]\\" to be of type string but got 333.
320
319
  - Expected \\"sites.exclude.[0]\\" to be of type string but got 444.
321
- - Expected \\"sites.exclude.[1]\\" to be of type string but got 555."
320
+ - Expected \\"sites.exclude.[1]\\" to be of type string but got 555.
321
+ - Expected \\"site.entry-point\\" to be of type string but got 111."
322
+ `);
323
+
324
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
325
+ .toMatchInlineSnapshot(`
326
+ "Processing wrangler configuration:
327
+ - Deprecation: \\"site.entry-point\\":
328
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
329
+ \`\`\`
330
+ main = \\"111/index.js\\"
331
+ \`\`\`"
322
332
  `);
323
333
  });
324
334
 
325
- it("should error with a deprecation warning if entry-point is defined", async () => {
335
+ it("should log a deprecation warning if entry-point is defined", async () => {
326
336
  const { config, diagnostics } = normalizeAndValidateConfig(
327
337
  {
328
338
  site: {
@@ -330,27 +340,29 @@ describe("normalizeAndValidateConfig()", () => {
330
340
  "entry-point": "some/other/script.js",
331
341
  },
332
342
  } as unknown as RawConfig,
333
- undefined
343
+ undefined,
344
+ { env: undefined }
334
345
  );
335
346
 
336
347
  expect(config.site).toMatchInlineSnapshot(`
337
348
  Object {
338
349
  "bucket": "some/path",
350
+ "entry-point": "some/other/script.js",
339
351
  "exclude": Array [],
340
352
  "include": Array [],
341
353
  }
342
354
  `);
343
355
  expect(diagnostics.hasWarnings()).toBe(true);
344
- expect(diagnostics.hasErrors()).toBe(true);
345
- expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
346
- "Processing wrangler configuration:
347
- - Unexpected fields found in site field: \\"entry-point\\""
348
- `);
349
- expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
356
+ expect(diagnostics.hasErrors()).toBe(false);
357
+
358
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
359
+ .toMatchInlineSnapshot(`
350
360
  "Processing wrangler configuration:
351
- - DEPRECATION: \\"site.entry-point\\":
352
- The \`site.entry-point\` config field is no longer used.
353
- The entry-point should be specified via the command line or the \`main\` config field."
361
+ - Deprecation: \\"site.entry-point\\":
362
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
363
+ \`\`\`
364
+ main = \\"some/other/script.js\\"
365
+ \`\`\`"
354
366
  `);
355
367
  });
356
368
  });
@@ -365,7 +377,8 @@ describe("normalizeAndValidateConfig()", () => {
365
377
 
366
378
  const { config, diagnostics } = normalizeAndValidateConfig(
367
379
  expectedConfig,
368
- "project/wrangler.toml"
380
+ "project/wrangler.toml",
381
+ { env: undefined }
369
382
  );
370
383
 
371
384
  expect(config).toEqual(
@@ -380,7 +393,7 @@ describe("normalizeAndValidateConfig()", () => {
380
393
  expect(diagnostics.hasWarnings()).toBe(false);
381
394
  });
382
395
 
383
- it("should error on invalid `wasm_module` paths", () => {
396
+ it("should error on invalid `wasm_modules` paths", () => {
384
397
  const expectedConfig = {
385
398
  wasm_modules: {
386
399
  MODULE_1: 111,
@@ -390,7 +403,8 @@ describe("normalizeAndValidateConfig()", () => {
390
403
 
391
404
  const { config, diagnostics } = normalizeAndValidateConfig(
392
405
  expectedConfig as unknown as RawConfig,
393
- "project/wrangler.toml"
406
+ "project/wrangler.toml",
407
+ { env: undefined }
394
408
  );
395
409
 
396
410
  expect(config).toEqual(
@@ -400,10 +414,10 @@ describe("normalizeAndValidateConfig()", () => {
400
414
  );
401
415
  expect(diagnostics.hasWarnings()).toBe(false);
402
416
  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
- `);
417
+ "Processing project/wrangler.toml configuration:
418
+ - Expected \\"wasm_modules['MODULE_1']\\" to be of type string but got 111.
419
+ - Expected \\"wasm_modules['MODULE_2']\\" to be of type string but got 222."
420
+ `);
407
421
  });
408
422
 
409
423
  it("should map `text_blobs` paths from relative to the config path to relative to the cwd", () => {
@@ -416,7 +430,8 @@ describe("normalizeAndValidateConfig()", () => {
416
430
 
417
431
  const { config, diagnostics } = normalizeAndValidateConfig(
418
432
  expectedConfig,
419
- "project/wrangler.toml"
433
+ "project/wrangler.toml",
434
+ { env: undefined }
420
435
  );
421
436
 
422
437
  expect(config).toEqual(
@@ -441,7 +456,8 @@ describe("normalizeAndValidateConfig()", () => {
441
456
 
442
457
  const { config, diagnostics } = normalizeAndValidateConfig(
443
458
  expectedConfig as unknown as RawConfig,
444
- "project/wrangler.toml"
459
+ "project/wrangler.toml",
460
+ { env: undefined }
445
461
  );
446
462
 
447
463
  expect(config).toEqual(
@@ -451,10 +467,84 @@ describe("normalizeAndValidateConfig()", () => {
451
467
  );
452
468
  expect(diagnostics.hasWarnings()).toBe(false);
453
469
  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
- `);
470
+ "Processing project/wrangler.toml configuration:
471
+ - Expected \\"text_blobs['MODULE_1']\\" to be of type string but got 111.
472
+ - Expected \\"text_blobs['MODULE_2']\\" to be of type string but got 222."
473
+ `);
474
+ });
475
+
476
+ it("should map `data_blobs` paths from relative to the config path to relative to the cwd", () => {
477
+ const expectedConfig: RawConfig = {
478
+ data_blobs: {
479
+ BLOB_1: "path/to/data1.bin",
480
+ BLOB_2: "data2.bin",
481
+ },
482
+ };
483
+
484
+ const { config, diagnostics } = normalizeAndValidateConfig(
485
+ expectedConfig,
486
+ "project/wrangler.toml",
487
+ { env: undefined }
488
+ );
489
+
490
+ expect(config).toEqual(
491
+ expect.objectContaining({
492
+ data_blobs: {
493
+ BLOB_1: path.normalize("project/path/to/data1.bin"),
494
+ BLOB_2: path.normalize("project/data2.bin"),
495
+ },
496
+ })
497
+ );
498
+ expect(diagnostics.hasErrors()).toBe(false);
499
+ expect(diagnostics.hasWarnings()).toBe(false);
500
+ });
501
+
502
+ it("should error on invalid `data_blob` paths", () => {
503
+ const expectedConfig = {
504
+ data_blobs: {
505
+ MODULE_1: 111,
506
+ MODULE_2: 222,
507
+ },
508
+ };
509
+
510
+ const { config, diagnostics } = normalizeAndValidateConfig(
511
+ expectedConfig as unknown as RawConfig,
512
+ "project/wrangler.toml",
513
+ { env: undefined }
514
+ );
515
+
516
+ expect(config).toEqual(
517
+ expect.objectContaining({
518
+ data_blobs: {},
519
+ })
520
+ );
521
+ expect(diagnostics.hasWarnings()).toBe(false);
522
+ expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
523
+ "Processing project/wrangler.toml configuration:
524
+ - Expected \\"data_blobs['MODULE_1']\\" to be of type string but got 111.
525
+ - Expected \\"data_blobs['MODULE_2']\\" to be of type string but got 222."
526
+ `);
527
+ });
528
+
529
+ it("should resolve tsconfig relative to wrangler.toml", async () => {
530
+ const expectedConfig: RawEnvironment = {
531
+ tsconfig: "path/to/some-tsconfig.json",
532
+ };
533
+
534
+ const { config, diagnostics } = normalizeAndValidateConfig(
535
+ expectedConfig,
536
+ "project/wrangler.toml",
537
+ { env: undefined }
538
+ );
539
+
540
+ expect(config).toEqual(
541
+ expect.objectContaining({
542
+ tsconfig: path.normalize("project/path/to/some-tsconfig.json"),
543
+ })
544
+ );
545
+
546
+ expect(diagnostics.hasErrors()).toBe(false);
547
+ expect(diagnostics.hasWarnings()).toBe(false);
458
548
  });
459
549
 
460
550
  describe("(deprecated)", () => {
@@ -466,7 +556,8 @@ describe("normalizeAndValidateConfig()", () => {
466
556
 
467
557
  const { config, diagnostics } = normalizeAndValidateConfig(
468
558
  rawConfig,
469
- undefined
559
+ undefined,
560
+ { env: undefined }
470
561
  );
471
562
 
472
563
  // Note the `.not.` here...
@@ -479,30 +570,44 @@ describe("normalizeAndValidateConfig()", () => {
479
570
  expect(diagnostics.hasErrors()).toBe(false);
480
571
  expect(diagnostics.hasWarnings()).toBe(true);
481
572
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
482
- "Processing wrangler configuration:
483
- - DEPRECATION: \\"type\\":
484
- DO NOT USE THIS. Most common features now work out of the box with wrangler, including modules, jsx, typescript, etc. If you need anything more, use a custom build.
485
- - DEPRECATION: \\"webpack_config\\":
486
- DO NOT USE THIS. Most common features now work out of the box with wrangler, including modules, jsx, typescript, etc. If you need anything more, use a custom build."
487
- `);
573
+ "Processing wrangler configuration:
574
+ - 😶 Ignored: \\"type\\":
575
+ Most common features now work out of the box with wrangler, including modules, jsx, typescript, etc. If you need anything more, use a custom build.
576
+ - 😶 Ignored: \\"webpack_config\\":
577
+ Most common features now work out of the box with wrangler, including modules, jsx, typescript, etc. If you need anything more, use a custom build."
578
+ `);
488
579
  });
489
580
  });
490
581
  });
491
582
 
492
583
  describe("top-level environment configuration", () => {
493
584
  it("should override config defaults with provided values", () => {
494
- const expectedConfig: RawConfig = {
495
- name: "NAME",
585
+ const main = "src/index.ts";
586
+ const resolvedMain = path.resolve(process.cwd(), main);
587
+
588
+ const expectedConfig: RawEnvironment = {
589
+ name: "mock-name",
496
590
  account_id: "ACCOUNT_ID",
497
591
  compatibility_date: "2022-01-01",
498
592
  compatibility_flags: ["FLAG1", "FLAG2"],
499
593
  workers_dev: false,
500
- routes: ["ROUTE_1", "ROUTE_2"],
501
- route: "ROUTE_3",
594
+ routes: [
595
+ "ROUTE_1",
596
+ "ROUTE_2",
597
+ { pattern: "ROUTE3", zone_id: "ZONE_ID_3" },
598
+ "ROUTE_4",
599
+ ],
502
600
  jsx_factory: "JSX_FACTORY",
503
601
  jsx_fragment: "JSX_FRAGMENT",
602
+ tsconfig: "path/to/tsconfig",
504
603
  triggers: { crons: ["CRON_1", "CRON_2"] },
505
604
  usage_model: "bundled",
605
+ main,
606
+ build: {
607
+ command: "COMMAND",
608
+ cwd: "CWD",
609
+ watch_dir: "WATCH_DIR",
610
+ },
506
611
  vars: {
507
612
  VAR1: "VALUE_1",
508
613
  VAR2: "VALUE_2",
@@ -547,10 +652,13 @@ describe("normalizeAndValidateConfig()", () => {
547
652
 
548
653
  const { config, diagnostics } = normalizeAndValidateConfig(
549
654
  expectedConfig,
550
- undefined
655
+ undefined,
656
+ { env: undefined }
551
657
  );
552
658
 
553
- expect(config).toEqual(expect.objectContaining(expectedConfig));
659
+ expect(config).toEqual(
660
+ expect.objectContaining({ ...expectedConfig, main: resolvedMain })
661
+ );
554
662
  expect(diagnostics.hasErrors()).toBe(false);
555
663
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
556
664
  "Processing wrangler configuration:
@@ -559,47 +667,283 @@ describe("normalizeAndValidateConfig()", () => {
559
667
  });
560
668
 
561
669
  it("should error on invalid environment values", () => {
562
- const expectedConfig: RawConfig = {
670
+ const expectedConfig: RawEnvironment = {
563
671
  name: 111,
564
672
  account_id: 222,
565
673
  compatibility_date: 333,
566
674
  compatibility_flags: [444, 555],
567
675
  workers_dev: "BAD",
568
- routes: [666, 777],
676
+ routes: [
677
+ 666,
678
+ 777,
679
+ // this one's valid, but we add it here to make sure
680
+ // it doesn't get included in the error message
681
+ "example.com/*",
682
+ { pattern: 123, zone_id: "zone_id_1" },
683
+ { pattern: "route_2", zone_id: 123 },
684
+ { pattern: "route_2", zone_name: 123 },
685
+ { pattern: "route_3" },
686
+ { zone_id: "zone_id_4" },
687
+ { zone_name: "zone_name_4" },
688
+ { pattern: undefined },
689
+ { pattern: "route_5", zone_id: "zone_id_5", some_other_key: 123 },
690
+ { pattern: "route_5", zone_name: "zone_name_5", some_other_key: 123 },
691
+ // this one's valid too
692
+ { pattern: "route_6", zone_id: "zone_id_6" },
693
+ // as well as this one
694
+ { pattern: "route_6", zone_name: "zone_name_6" },
695
+ ],
569
696
  route: 888,
570
697
  jsx_factory: 999,
571
698
  jsx_fragment: 1000,
699
+ tsconfig: true,
572
700
  triggers: { crons: [1111, 1222] },
573
701
  usage_model: "INVALID",
574
- } as unknown as RawConfig;
702
+ main: 1333,
703
+ build: {
704
+ command: 1444,
705
+ cwd: 1555,
706
+ watch_dir: 1666,
707
+ },
708
+ } as unknown as RawEnvironment;
575
709
 
576
710
  const { config, diagnostics } = normalizeAndValidateConfig(
577
711
  expectedConfig,
578
- undefined
712
+ undefined,
713
+ { env: undefined }
579
714
  );
580
715
 
581
716
  expect(config).toEqual(expect.objectContaining(expectedConfig));
582
717
  expect(diagnostics.hasWarnings()).toBe(false);
583
718
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
584
719
  "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.
720
+ - Expected \\"route\\" to be either a string, or an object with shape { pattern, zone_id | zone_name }, but got 888.
721
+ - Expected \\"routes\\" to be an array of either strings or objects with the shape { pattern, zone_id | zone_name }, but these weren't valid: [
722
+ 666,
723
+ 777,
724
+ {
725
+ \\"pattern\\": 123,
726
+ \\"zone_id\\": \\"zone_id_1\\"
727
+ },
728
+ {
729
+ \\"pattern\\": \\"route_2\\",
730
+ \\"zone_id\\": 123
731
+ },
732
+ {
733
+ \\"pattern\\": \\"route_2\\",
734
+ \\"zone_name\\": 123
735
+ },
736
+ {
737
+ \\"pattern\\": \\"route_3\\"
738
+ },
739
+ {
740
+ \\"zone_id\\": \\"zone_id_4\\"
741
+ },
742
+ {
743
+ \\"zone_name\\": \\"zone_name_4\\"
744
+ },
745
+ {},
746
+ {
747
+ \\"pattern\\": \\"route_5\\",
748
+ \\"zone_id\\": \\"zone_id_5\\",
749
+ \\"some_other_key\\": 123
750
+ },
751
+ {
752
+ \\"pattern\\": \\"route_5\\",
753
+ \\"zone_name\\": \\"zone_name_5\\",
754
+ \\"some_other_key\\": 123
755
+ }
756
+ ].
757
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"].
758
+ - Expected \\"workers_dev\\" to be of type boolean but got \\"BAD\\".
759
+ - Expected \\"build.command\\" to be of type string but got 1444.
760
+ - Expected \\"build.cwd\\" to be of type string but got 1555.
761
+ - Expected \\"build.watch_dir\\" to be of type string but got 1666.
762
+ - Expected \\"account_id\\" to be of type string but got 222.
763
+ - Expected \\"compatibility_date\\" to be of type string but got 333.
764
+ - Expected \\"compatibility_flags\\" to be of type string array but got [444,555].
765
+ - Expected \\"jsx_factory\\" to be of type string but got 999.
766
+ - Expected \\"jsx_fragment\\" to be of type string but got 1000.
767
+ - Expected \\"tsconfig\\" to be of type string but got true.
768
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got 111.
769
+ - Expected \\"main\\" to be of type string but got 1333.
594
770
  - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
595
771
  `);
596
772
  });
597
773
 
774
+ it("should error on invalid `name` value with spaces", () => {
775
+ const expectedConfig: RawEnvironment = {
776
+ name: "NCC 1701 D",
777
+ } as unknown as RawEnvironment;
778
+
779
+ const { config, diagnostics } = normalizeAndValidateConfig(
780
+ expectedConfig,
781
+ undefined,
782
+ { env: undefined }
783
+ );
784
+
785
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
786
+ expect(diagnostics.hasWarnings()).toBe(false);
787
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
788
+ "Processing wrangler configuration:
789
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got \\"NCC 1701 D\\"."
790
+ `);
791
+ });
792
+
793
+ it("should be valid `name` with underscores", () => {
794
+ const expectedConfig: RawEnvironment = {
795
+ name: "enterprise_nx_01",
796
+ } as unknown as RawEnvironment;
797
+
798
+ const { config, diagnostics } = normalizeAndValidateConfig(
799
+ expectedConfig,
800
+ undefined,
801
+ { env: undefined }
802
+ );
803
+
804
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
805
+ expect(diagnostics.hasWarnings()).toBe(false);
806
+ expect(diagnostics.hasErrors()).toBe(false);
807
+ });
808
+
809
+ it("should error on invalid `name` value with special characters", () => {
810
+ const expectedConfig: RawEnvironment = {
811
+ name: "Thy'lek-Shran",
812
+ } as unknown as RawEnvironment;
813
+
814
+ const { config, diagnostics } = normalizeAndValidateConfig(
815
+ expectedConfig,
816
+ undefined,
817
+ { env: undefined }
818
+ );
819
+
820
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
821
+ expect(diagnostics.hasWarnings()).toBe(false);
822
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
823
+ "Processing wrangler configuration:
824
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got \\"Thy'lek-Shran\\"."
825
+ `);
826
+ });
827
+
828
+ it("should error on invalid `name` value with only special characters", () => {
829
+ const expectedConfig: RawEnvironment = {
830
+ name: "!@#$%^&*(()",
831
+ } as unknown as RawEnvironment;
832
+
833
+ const { config, diagnostics } = normalizeAndValidateConfig(
834
+ expectedConfig,
835
+ undefined,
836
+ { env: undefined }
837
+ );
838
+
839
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
840
+ expect(diagnostics.hasWarnings()).toBe(false);
841
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
842
+ "Processing wrangler configuration:
843
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got \\"!@#$%^&*(()\\"."
844
+ `);
845
+ });
846
+
847
+ it("should override build.upload config defaults with provided values and warn about deprecations", () => {
848
+ const expectedConfig: RawEnvironment = {
849
+ build: {
850
+ upload: {
851
+ dir: "src",
852
+ format: "modules",
853
+ main: "index.ts",
854
+ rules: [{ type: "Text", globs: ["GLOB"], fallthrough: true }],
855
+ },
856
+ },
857
+ };
858
+
859
+ const { config, diagnostics } = normalizeAndValidateConfig(
860
+ expectedConfig,
861
+ path.resolve("project/wrangler.toml"),
862
+ { env: undefined }
863
+ );
864
+
865
+ expect(config.main).toEqual(path.resolve("project/src/index.ts"));
866
+ expect(config.build.upload).toBeUndefined();
867
+ expect(diagnostics.hasErrors()).toBe(false);
868
+ expect(diagnostics.hasWarnings()).toBe(true);
869
+ expect(normalizePath(diagnostics.renderWarnings()))
870
+ .toMatchInlineSnapshot(`
871
+ "Processing project/wrangler.toml configuration:
872
+ - Deprecation: \\"build.upload.format\\":
873
+ The format is inferred automatically from the code.
874
+ - Deprecation: \\"build.upload.main\\":
875
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
876
+ Then add the top level \`main\` field to your configuration file:
877
+ \`\`\`
878
+ main = \\"src/index.ts\\"
879
+ \`\`\`
880
+ - Deprecation: \\"build.upload.dir\\":
881
+ Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker.
882
+ - 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:
883
+ \`\`\`
884
+ [[rules]]
885
+ type = \\"Text\\"
886
+ globs = [ \\"GLOB\\" ]
887
+ fallthrough = true
888
+ \`\`\`"
889
+ `);
890
+ });
891
+
892
+ it("should default custom build watch directories to src", () => {
893
+ const expectedConfig: RawEnvironment = {
894
+ build: {
895
+ command: "execute some --build",
896
+ },
897
+ };
898
+
899
+ const { config, diagnostics } = normalizeAndValidateConfig(
900
+ expectedConfig,
901
+ undefined,
902
+ { env: undefined }
903
+ );
904
+
905
+ expect(config.build).toEqual(
906
+ expect.objectContaining({
907
+ command: "execute some --build",
908
+ watch_dir: "./src",
909
+ })
910
+ );
911
+
912
+ expect(diagnostics.hasErrors()).toBe(false);
913
+ expect(diagnostics.hasWarnings()).toBe(false);
914
+ });
915
+
916
+ it("should resolve custom build watch directories relative to wrangler.toml", async () => {
917
+ const expectedConfig: RawEnvironment = {
918
+ build: {
919
+ command: "execute some --build",
920
+ watch_dir: "some/path",
921
+ },
922
+ };
923
+
924
+ const { config, diagnostics } = normalizeAndValidateConfig(
925
+ expectedConfig,
926
+ "project/wrangler.toml",
927
+ { env: undefined }
928
+ );
929
+
930
+ expect(config.build).toEqual(
931
+ expect.objectContaining({
932
+ command: "execute some --build",
933
+ watch_dir: path.normalize("project/some/path"),
934
+ })
935
+ );
936
+
937
+ expect(diagnostics.hasErrors()).toBe(false);
938
+ expect(diagnostics.hasWarnings()).toBe(false);
939
+ });
940
+
598
941
  describe("durable_objects field", () => {
599
942
  it("should error if durable_objects is an array", () => {
600
943
  const { config, diagnostics } = normalizeAndValidateConfig(
601
944
  { durable_objects: [] } as unknown as RawConfig,
602
- undefined
945
+ undefined,
946
+ { env: undefined }
603
947
  );
604
948
 
605
949
  expect(config).toEqual(
@@ -615,7 +959,8 @@ describe("normalizeAndValidateConfig()", () => {
615
959
  it("should error if durable_objects is a string", () => {
616
960
  const { config, diagnostics } = normalizeAndValidateConfig(
617
961
  { durable_objects: "BAD" } as unknown as RawConfig,
618
- undefined
962
+ undefined,
963
+ { env: undefined }
619
964
  );
620
965
 
621
966
  expect(config).toEqual(
@@ -631,7 +976,8 @@ describe("normalizeAndValidateConfig()", () => {
631
976
  it("should error if durable_objects is a number", () => {
632
977
  const { config, diagnostics } = normalizeAndValidateConfig(
633
978
  { durable_objects: 999 } as unknown as RawConfig,
634
- undefined
979
+ undefined,
980
+ { env: undefined }
635
981
  );
636
982
 
637
983
  expect(config).toEqual(
@@ -647,7 +993,8 @@ describe("normalizeAndValidateConfig()", () => {
647
993
  it("should error if durable_objects is null", () => {
648
994
  const { config, diagnostics } = normalizeAndValidateConfig(
649
995
  { durable_objects: null } as unknown as RawConfig,
650
- undefined
996
+ undefined,
997
+ { env: undefined }
651
998
  );
652
999
 
653
1000
  expect(config).toEqual(
@@ -663,7 +1010,8 @@ describe("normalizeAndValidateConfig()", () => {
663
1010
  it("should error if durable_objects.bindings is not defined", () => {
664
1011
  const { config, diagnostics } = normalizeAndValidateConfig(
665
1012
  { durable_objects: {} } as unknown as RawConfig,
666
- undefined
1013
+ undefined,
1014
+ { env: undefined }
667
1015
  );
668
1016
 
669
1017
  expect(config).toEqual(
@@ -679,7 +1027,8 @@ describe("normalizeAndValidateConfig()", () => {
679
1027
  it("should error if durable_objects.bindings is an object", () => {
680
1028
  const { config, diagnostics } = normalizeAndValidateConfig(
681
1029
  { durable_objects: { bindings: {} } } as unknown as RawConfig,
682
- undefined
1030
+ undefined,
1031
+ { env: undefined }
683
1032
  );
684
1033
 
685
1034
  expect(config).toEqual(
@@ -697,7 +1046,8 @@ describe("normalizeAndValidateConfig()", () => {
697
1046
  it("should error if durable_objects.bindings is a string", () => {
698
1047
  const { config, diagnostics } = normalizeAndValidateConfig(
699
1048
  { durable_objects: { bindings: "BAD" } } as unknown as RawConfig,
700
- undefined
1049
+ undefined,
1050
+ { env: undefined }
701
1051
  );
702
1052
 
703
1053
  expect(config).toEqual(
@@ -715,7 +1065,8 @@ describe("normalizeAndValidateConfig()", () => {
715
1065
  it("should error if durable_objects.bindings is a number", () => {
716
1066
  const { config, diagnostics } = normalizeAndValidateConfig(
717
1067
  { durable_objects: { bindings: 999 } } as unknown as RawConfig,
718
- undefined
1068
+ undefined,
1069
+ { env: undefined }
719
1070
  );
720
1071
 
721
1072
  expect(config).toEqual(
@@ -733,7 +1084,8 @@ describe("normalizeAndValidateConfig()", () => {
733
1084
  it("should error if durable_objects.bindings is null", () => {
734
1085
  const { config, diagnostics } = normalizeAndValidateConfig(
735
1086
  { durable_objects: { bindings: null } } as unknown as RawConfig,
736
- undefined
1087
+ undefined,
1088
+ { env: undefined }
737
1089
  );
738
1090
 
739
1091
  expect(config).toEqual(
@@ -764,7 +1116,8 @@ describe("normalizeAndValidateConfig()", () => {
764
1116
  ],
765
1117
  },
766
1118
  } as unknown as RawConfig,
767
- undefined
1119
+ undefined,
1120
+ { env: undefined }
768
1121
  );
769
1122
 
770
1123
  expect(config).toEqual(
@@ -799,7 +1152,8 @@ describe("normalizeAndValidateConfig()", () => {
799
1152
  it("should error if kv_namespaces is an object", () => {
800
1153
  const { config, diagnostics } = normalizeAndValidateConfig(
801
1154
  { kv_namespaces: {} } as unknown as RawConfig,
802
- undefined
1155
+ undefined,
1156
+ { env: undefined }
803
1157
  );
804
1158
 
805
1159
  expect(config).toEqual(
@@ -815,7 +1169,8 @@ describe("normalizeAndValidateConfig()", () => {
815
1169
  it("should error if kv_namespaces is a string", () => {
816
1170
  const { config, diagnostics } = normalizeAndValidateConfig(
817
1171
  { kv_namespaces: "BAD" } as unknown as RawConfig,
818
- undefined
1172
+ undefined,
1173
+ { env: undefined }
819
1174
  );
820
1175
 
821
1176
  expect(config).toEqual(
@@ -831,7 +1186,8 @@ describe("normalizeAndValidateConfig()", () => {
831
1186
  it("should error if kv_namespaces is a number", () => {
832
1187
  const { config, diagnostics } = normalizeAndValidateConfig(
833
1188
  { kv_namespaces: 999 } as unknown as RawConfig,
834
- undefined
1189
+ undefined,
1190
+ { env: undefined }
835
1191
  );
836
1192
 
837
1193
  expect(config).toEqual(
@@ -847,7 +1203,8 @@ describe("normalizeAndValidateConfig()", () => {
847
1203
  it("should error if kv_namespaces is null", () => {
848
1204
  const { config, diagnostics } = normalizeAndValidateConfig(
849
1205
  { kv_namespaces: null } as unknown as RawConfig,
850
- undefined
1206
+ undefined,
1207
+ { env: undefined }
851
1208
  );
852
1209
 
853
1210
  expect(config).toEqual(
@@ -874,7 +1231,8 @@ describe("normalizeAndValidateConfig()", () => {
874
1231
  },
875
1232
  ],
876
1233
  } as unknown as RawConfig,
877
- undefined
1234
+ undefined,
1235
+ { env: undefined }
878
1236
  );
879
1237
 
880
1238
  expect(config).toEqual(
@@ -899,7 +1257,8 @@ describe("normalizeAndValidateConfig()", () => {
899
1257
  it("should error if r2_buckets is an object", () => {
900
1258
  const { config, diagnostics } = normalizeAndValidateConfig(
901
1259
  { r2_buckets: {} } as unknown as RawConfig,
902
- undefined
1260
+ undefined,
1261
+ { env: undefined }
903
1262
  );
904
1263
 
905
1264
  expect(config).toEqual(
@@ -915,7 +1274,8 @@ describe("normalizeAndValidateConfig()", () => {
915
1274
  it("should error if r2_buckets is a string", () => {
916
1275
  const { config, diagnostics } = normalizeAndValidateConfig(
917
1276
  { r2_buckets: "BAD" } as unknown as RawConfig,
918
- undefined
1277
+ undefined,
1278
+ { env: undefined }
919
1279
  );
920
1280
 
921
1281
  expect(config).toEqual(
@@ -931,7 +1291,8 @@ describe("normalizeAndValidateConfig()", () => {
931
1291
  it("should error if r2_buckets is a number", () => {
932
1292
  const { config, diagnostics } = normalizeAndValidateConfig(
933
1293
  { r2_buckets: 999 } as unknown as RawConfig,
934
- undefined
1294
+ undefined,
1295
+ { env: undefined }
935
1296
  );
936
1297
 
937
1298
  expect(config).toEqual(
@@ -947,7 +1308,8 @@ describe("normalizeAndValidateConfig()", () => {
947
1308
  it("should error if r2_buckets is null", () => {
948
1309
  const { config, diagnostics } = normalizeAndValidateConfig(
949
1310
  { r2_buckets: null } as unknown as RawConfig,
950
- undefined
1311
+ undefined,
1312
+ { env: undefined }
951
1313
  );
952
1314
 
953
1315
  expect(config).toEqual(
@@ -974,7 +1336,8 @@ describe("normalizeAndValidateConfig()", () => {
974
1336
  },
975
1337
  ],
976
1338
  } as unknown as RawConfig,
977
- undefined
1339
+ undefined,
1340
+ { env: undefined }
978
1341
  );
979
1342
 
980
1343
  expect(config).toEqual(
@@ -999,7 +1362,8 @@ describe("normalizeAndValidateConfig()", () => {
999
1362
  it("should error if unsafe is an array", () => {
1000
1363
  const { config, diagnostics } = normalizeAndValidateConfig(
1001
1364
  { unsafe: [] } as unknown as RawConfig,
1002
- undefined
1365
+ undefined,
1366
+ { env: undefined }
1003
1367
  );
1004
1368
 
1005
1369
  expect(config).toEqual(
@@ -1018,7 +1382,8 @@ describe("normalizeAndValidateConfig()", () => {
1018
1382
  it("should error if unsafe is a string", () => {
1019
1383
  const { config, diagnostics } = normalizeAndValidateConfig(
1020
1384
  { unsafe: "BAD" } as unknown as RawConfig,
1021
- undefined
1385
+ undefined,
1386
+ { env: undefined }
1022
1387
  );
1023
1388
 
1024
1389
  expect(config).toEqual(
@@ -1037,7 +1402,8 @@ describe("normalizeAndValidateConfig()", () => {
1037
1402
  it("should error if unsafe is a number", () => {
1038
1403
  const { config, diagnostics } = normalizeAndValidateConfig(
1039
1404
  { unsafe: 999 } as unknown as RawConfig,
1040
- undefined
1405
+ undefined,
1406
+ { env: undefined }
1041
1407
  );
1042
1408
 
1043
1409
  expect(config).toEqual(
@@ -1056,7 +1422,8 @@ describe("normalizeAndValidateConfig()", () => {
1056
1422
  it("should error if unsafe is null", () => {
1057
1423
  const { config, diagnostics } = normalizeAndValidateConfig(
1058
1424
  { unsafe: null } as unknown as RawConfig,
1059
- undefined
1425
+ undefined,
1426
+ { env: undefined }
1060
1427
  );
1061
1428
 
1062
1429
  expect(config).toEqual(
@@ -1075,7 +1442,8 @@ describe("normalizeAndValidateConfig()", () => {
1075
1442
  it("should error if unsafe.bindings is not defined", () => {
1076
1443
  const { config, diagnostics } = normalizeAndValidateConfig(
1077
1444
  { unsafe: {} } as unknown as RawConfig,
1078
- undefined
1445
+ undefined,
1446
+ { env: undefined }
1079
1447
  );
1080
1448
 
1081
1449
  expect(config).toEqual(
@@ -1094,7 +1462,8 @@ describe("normalizeAndValidateConfig()", () => {
1094
1462
  it("should error if unsafe.bindings is an object", () => {
1095
1463
  const { config, diagnostics } = normalizeAndValidateConfig(
1096
1464
  { unsafe: { bindings: {} } } as unknown as RawConfig,
1097
- undefined
1465
+ undefined,
1466
+ { env: undefined }
1098
1467
  );
1099
1468
 
1100
1469
  expect(config).toEqual(
@@ -1115,7 +1484,8 @@ describe("normalizeAndValidateConfig()", () => {
1115
1484
  it("should error if unsafe.bindings is a string", () => {
1116
1485
  const { config, diagnostics } = normalizeAndValidateConfig(
1117
1486
  { unsafe: { bindings: "BAD" } } as unknown as RawConfig,
1118
- undefined
1487
+ undefined,
1488
+ { env: undefined }
1119
1489
  );
1120
1490
 
1121
1491
  expect(config).toEqual(
@@ -1136,7 +1506,8 @@ describe("normalizeAndValidateConfig()", () => {
1136
1506
  it("should error if unsafe.bindings is a number", () => {
1137
1507
  const { config, diagnostics } = normalizeAndValidateConfig(
1138
1508
  { unsafe: { bindings: 999 } } as unknown as RawConfig,
1139
- undefined
1509
+ undefined,
1510
+ { env: undefined }
1140
1511
  );
1141
1512
 
1142
1513
  expect(config).toEqual(
@@ -1157,7 +1528,8 @@ describe("normalizeAndValidateConfig()", () => {
1157
1528
  it("should error if unsafe.bindings is null", () => {
1158
1529
  const { config, diagnostics } = normalizeAndValidateConfig(
1159
1530
  { unsafe: { bindings: null } } as unknown as RawConfig,
1160
- undefined
1531
+ undefined,
1532
+ { env: undefined }
1161
1533
  );
1162
1534
 
1163
1535
  expect(config).toEqual(
@@ -1191,7 +1563,8 @@ describe("normalizeAndValidateConfig()", () => {
1191
1563
  ],
1192
1564
  },
1193
1565
  } as unknown as RawConfig,
1194
- undefined
1566
+ undefined,
1567
+ { env: undefined }
1195
1568
  );
1196
1569
 
1197
1570
  expect(config).toEqual(
@@ -1226,7 +1599,7 @@ describe("normalizeAndValidateConfig()", () => {
1226
1599
  zone_id: "ZONE_ID",
1227
1600
  experimental_services: [
1228
1601
  {
1229
- name: "NAME",
1602
+ name: "mock-name",
1230
1603
  service: "SERVICE",
1231
1604
  environment: "ENV",
1232
1605
  },
@@ -1235,7 +1608,8 @@ describe("normalizeAndValidateConfig()", () => {
1235
1608
 
1236
1609
  const { config, diagnostics } = normalizeAndValidateConfig(
1237
1610
  rawConfig,
1238
- undefined
1611
+ undefined,
1612
+ { env: undefined }
1239
1613
  );
1240
1614
 
1241
1615
  expect("experimental_services" in config).toBe(false);
@@ -1244,90 +1618,340 @@ describe("normalizeAndValidateConfig()", () => {
1244
1618
  expect(diagnostics.hasErrors()).toBe(false);
1245
1619
  expect(diagnostics.hasWarnings()).toBe(true);
1246
1620
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1247
- "Processing wrangler configuration:
1248
- - DEPRECATION: \\"zone_id\\":
1249
- This is unnecessary since we can deduce this from routes directly.
1250
- - DEPRECATION: \\"experimental_services\\":
1251
- The \\"experimental_services\\" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
1252
- \`\`\`
1253
- [[unsafe.bindings]]
1254
- name = \\"NAME\\"
1255
- type = \\"service\\"
1256
- service = \\"SERVICE\\"
1257
- environment = \\"ENV\\"
1258
- \`\`\`"
1259
- `);
1621
+ "Processing wrangler configuration:
1622
+ - Deprecation: \\"zone_id\\":
1623
+ This is unnecessary since we can deduce this from routes directly.
1624
+ - Deprecation: \\"experimental_services\\":
1625
+ The \\"experimental_services\\" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
1626
+ \`\`\`
1627
+ [[unsafe.bindings]]
1628
+ name = \\"mock-name\\"
1629
+ type = \\"service\\"
1630
+ service = \\"SERVICE\\"
1631
+ environment = \\"ENV\\"
1632
+ \`\`\`"
1633
+ `);
1634
+ });
1635
+ });
1636
+
1637
+ describe("route & routes fields", () => {
1638
+ it("should error if both route and routes are specified", () => {
1639
+ const rawConfig: RawConfig = {
1640
+ route: "route1",
1641
+ routes: ["route2", "route3"],
1642
+ };
1643
+
1644
+ const { diagnostics } = normalizeAndValidateConfig(
1645
+ rawConfig,
1646
+ undefined,
1647
+ { env: undefined }
1648
+ );
1649
+
1650
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1651
+ "Processing wrangler configuration:
1652
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
1653
+ `);
1654
+ });
1655
+ });
1656
+ });
1657
+
1658
+ describe("named environments", () => {
1659
+ it("should warn if we specify an environment but there are no named environments", () => {
1660
+ const rawConfig: RawConfig = {};
1661
+ const { diagnostics } = normalizeAndValidateConfig(rawConfig, undefined, {
1662
+ env: "DEV",
1663
+ });
1664
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1665
+ "Processing wrangler configuration:
1666
+ "
1667
+ `);
1668
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1669
+ "Processing wrangler configuration:
1670
+ - No environment found in configuration with name \\"DEV\\".
1671
+ Before using \`--env=DEV\` there should be an equivalent environment section in the configuration.
1672
+
1673
+ Consider adding an environment configuration section to the wrangler.toml file:
1674
+ \`\`\`
1675
+ [env.DEV]
1676
+ \`\`\`
1677
+ "
1678
+ `);
1679
+ });
1680
+
1681
+ it("should error if we specify an environment that does not match the named environments", () => {
1682
+ const rawConfig: RawConfig = { env: { ENV1: {} } };
1683
+ const { diagnostics } = normalizeAndValidateConfig(rawConfig, undefined, {
1684
+ env: "DEV",
1260
1685
  });
1686
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1687
+ "Processing wrangler configuration:
1688
+ - No environment found in configuration with name \\"DEV\\".
1689
+ Before using \`--env=DEV\` there should be an equivalent environment section in the configuration.
1690
+ The available configured environment names are: [\\"ENV1\\"]
1691
+
1692
+ Consider adding an environment configuration section to the wrangler.toml file:
1693
+ \`\`\`
1694
+ [env.DEV]
1695
+ \`\`\`
1696
+ "
1697
+ `);
1698
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1699
+ "Processing wrangler configuration:
1700
+ "
1701
+ `);
1261
1702
  });
1262
- });
1263
1703
 
1264
- describe("named environments", () => {
1265
1704
  it("should use top-level values for inheritable config fields", () => {
1266
- const expectedConfig: RawConfig = {
1267
- name: "NAME",
1705
+ const main = "src/index.ts";
1706
+ const resolvedMain = path.resolve(process.cwd(), main);
1707
+ const rawConfig: RawConfig = {
1708
+ name: "mock-name",
1268
1709
  account_id: "ACCOUNT_ID",
1269
1710
  compatibility_date: "2022-01-01",
1270
1711
  compatibility_flags: ["FLAG1", "FLAG2"],
1271
1712
  workers_dev: false,
1272
1713
  routes: ["ROUTE_1", "ROUTE_2"],
1273
- route: "ROUTE_3",
1274
1714
  jsx_factory: "JSX_FACTORY",
1275
1715
  jsx_fragment: "JSX_FRAGMENT",
1716
+ tsconfig: "path/to/tsconfig.json",
1276
1717
  triggers: { crons: ["CRON_1", "CRON_2"] },
1277
1718
  usage_model: "bundled",
1719
+ main,
1720
+ build: {
1721
+ command: "COMMAND",
1722
+ cwd: "CWD",
1723
+ watch_dir: "WATCH_DIR",
1724
+ },
1278
1725
  };
1279
1726
 
1280
1727
  const { config, diagnostics } = normalizeAndValidateConfig(
1281
- { ...expectedConfig, env: { DEV: {} } },
1282
- undefined
1728
+ { ...rawConfig, env: { dev: {} } },
1729
+ undefined,
1730
+ { env: "dev" }
1283
1731
  );
1284
1732
 
1285
- expect(config.env.DEV).toEqual(expect.objectContaining(expectedConfig));
1733
+ expect(config).toEqual(
1734
+ expect.objectContaining({
1735
+ ...rawConfig,
1736
+ main: resolvedMain,
1737
+ name: "mock-name-dev",
1738
+ })
1739
+ );
1286
1740
  expect(diagnostics.hasErrors()).toBe(false);
1287
1741
  expect(diagnostics.hasWarnings()).toBe(false);
1288
1742
  });
1289
1743
 
1290
1744
  it("should override top-level values for inheritable config fields", () => {
1291
- const environment: RawEnvironment = {
1292
- name: "ENV_NAME",
1745
+ const main = "src/index.ts";
1746
+ const resolvedMain = path.resolve(process.cwd(), main);
1747
+ const rawEnv: RawEnvironment = {
1748
+ name: "mock-env-name",
1293
1749
  account_id: "ENV_ACCOUNT_ID",
1294
1750
  compatibility_date: "2022-02-02",
1295
1751
  compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
1296
1752
  workers_dev: true,
1297
1753
  routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
1298
- route: "ENV_ROUTE_3",
1299
1754
  jsx_factory: "ENV_JSX_FACTORY",
1300
1755
  jsx_fragment: "ENV_JSX_FRAGMENT",
1756
+ tsconfig: "ENV_path/to/tsconfig.json",
1301
1757
  triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
1302
1758
  usage_model: "unbound",
1759
+ main,
1760
+ build: {
1761
+ command: "ENV_COMMAND",
1762
+ cwd: "ENV_CWD",
1763
+ watch_dir: "ENV_WATCH_DIR",
1764
+ },
1303
1765
  };
1304
- const expectedConfig: RawConfig = {
1305
- name: "NAME",
1766
+ const rawConfig: RawConfig = {
1767
+ name: "mock-name",
1306
1768
  account_id: "ACCOUNT_ID",
1307
1769
  compatibility_date: "2022-01-01",
1308
1770
  compatibility_flags: ["FLAG1", "FLAG2"],
1309
1771
  workers_dev: false,
1310
1772
  routes: ["ROUTE_1", "ROUTE_2"],
1311
- route: "ROUTE_3",
1312
1773
  jsx_factory: "JSX_FACTORY",
1313
1774
  jsx_fragment: "JSX_FRAGMENT",
1775
+ tsconfig: "path/to/tsconfig.json",
1314
1776
  triggers: { crons: ["CRON_1", "CRON_2"] },
1315
1777
  usage_model: "bundled",
1778
+ main: "top-level.js",
1779
+ build: {
1780
+ command: "COMMAND",
1781
+ cwd: "CWD",
1782
+ watch_dir: "WATCH_DIR",
1783
+ },
1316
1784
  env: {
1317
- ENV1: environment,
1785
+ ENV1: rawEnv,
1318
1786
  },
1319
1787
  };
1320
1788
 
1321
1789
  const { config, diagnostics } = normalizeAndValidateConfig(
1322
- expectedConfig,
1323
- undefined
1790
+ rawConfig,
1791
+ undefined,
1792
+ { env: "ENV1" }
1324
1793
  );
1325
1794
 
1326
- expect(config.env.ENV1).toEqual(expect.objectContaining(environment));
1795
+ expect(config).toEqual(
1796
+ expect.objectContaining({ ...rawEnv, main: resolvedMain })
1797
+ );
1327
1798
  expect(diagnostics.hasErrors()).toBe(false);
1328
1799
  expect(diagnostics.hasWarnings()).toBe(false);
1329
1800
  });
1330
1801
 
1802
+ describe("non-legacy", () => {
1803
+ it("should use top-level `name` field", () => {
1804
+ const rawConfig: RawConfig = {
1805
+ name: "mock-name",
1806
+ legacy_env: false,
1807
+ env: { DEV: {} },
1808
+ };
1809
+
1810
+ const { config, diagnostics } = normalizeAndValidateConfig(
1811
+ rawConfig,
1812
+ undefined,
1813
+ { env: "DEV" }
1814
+ );
1815
+
1816
+ expect(config.name).toEqual("mock-name");
1817
+ expect(diagnostics.hasErrors()).toBe(false);
1818
+ expect(diagnostics.hasWarnings()).toBe(true);
1819
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1820
+ "Processing wrangler configuration:
1821
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
1822
+ `);
1823
+ });
1824
+
1825
+ it("should error if named environment contains a `name` field, even if there is no top-level name", () => {
1826
+ const rawConfig: RawConfig = {
1827
+ legacy_env: false,
1828
+ env: {
1829
+ DEV: {
1830
+ name: "mock-env-name",
1831
+ },
1832
+ },
1833
+ };
1834
+
1835
+ const { config, diagnostics } = normalizeAndValidateConfig(
1836
+ rawConfig,
1837
+ undefined,
1838
+ { env: "DEV" }
1839
+ );
1840
+
1841
+ expect(config.name).toBeUndefined();
1842
+ expect(diagnostics.hasWarnings()).toBe(true);
1843
+ expect(diagnostics.hasErrors()).toBe(true);
1844
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1845
+ "Processing wrangler configuration:
1846
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
1847
+ `);
1848
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1849
+ "Processing wrangler configuration:
1850
+
1851
+ - \\"env.DEV\\" environment configuration
1852
+ - The \\"name\\" field is not allowed in named service environments.
1853
+ Please remove the field from this environment."
1854
+ `);
1855
+ });
1856
+
1857
+ it("should error if top-level config and a named environment both contain a `name` field", () => {
1858
+ const rawConfig: RawConfig = {
1859
+ name: "mock-name",
1860
+ legacy_env: false,
1861
+ env: {
1862
+ DEV: {
1863
+ name: "mock-env-name",
1864
+ },
1865
+ },
1866
+ };
1867
+
1868
+ const { config, diagnostics } = normalizeAndValidateConfig(
1869
+ rawConfig,
1870
+ undefined,
1871
+ { env: "DEV" }
1872
+ );
1873
+
1874
+ expect(config.name).toEqual("mock-name");
1875
+ expect(diagnostics.hasWarnings()).toBe(true);
1876
+ expect(diagnostics.hasErrors()).toBe(true);
1877
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1878
+ "Processing wrangler configuration:
1879
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
1880
+ `);
1881
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1882
+ "Processing wrangler configuration:
1883
+
1884
+ - \\"env.DEV\\" environment configuration
1885
+ - The \\"name\\" field is not allowed in named service environments.
1886
+ Please remove the field from this environment."
1887
+ `);
1888
+ });
1889
+ });
1890
+
1891
+ it("should error if named environment contains a `account_id` field, even if there is no top-level name", () => {
1892
+ const rawConfig: RawConfig = {
1893
+ legacy_env: false,
1894
+ env: {
1895
+ DEV: {
1896
+ account_id: "some_account_id",
1897
+ },
1898
+ },
1899
+ };
1900
+
1901
+ const { config, diagnostics } = normalizeAndValidateConfig(
1902
+ rawConfig,
1903
+ undefined,
1904
+ { env: "DEV" }
1905
+ );
1906
+
1907
+ expect(diagnostics.hasWarnings()).toBe(true);
1908
+ expect(config.account_id).toBeUndefined();
1909
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1910
+ "Processing wrangler configuration:
1911
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
1912
+ `);
1913
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1914
+ "Processing wrangler configuration:
1915
+
1916
+ - \\"env.DEV\\" environment configuration
1917
+ - The \\"account_id\\" field is not allowed in named service environments.
1918
+ Please remove the field from this environment."
1919
+ `);
1920
+ });
1921
+
1922
+ it("should error if top-level config and a named environment both contain a `account_id` field", () => {
1923
+ const rawConfig: RawConfig = {
1924
+ account_id: "ACCOUNT_ID",
1925
+ legacy_env: false,
1926
+ env: {
1927
+ DEV: {
1928
+ account_id: "ENV_ACCOUNT_ID",
1929
+ },
1930
+ },
1931
+ };
1932
+
1933
+ const { config, diagnostics } = normalizeAndValidateConfig(
1934
+ rawConfig,
1935
+ undefined,
1936
+ { env: "DEV" }
1937
+ );
1938
+
1939
+ expect(config.account_id).toEqual("ACCOUNT_ID");
1940
+ expect(diagnostics.hasErrors()).toBe(true);
1941
+ expect(diagnostics.hasWarnings()).toBe(true);
1942
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1943
+ "Processing wrangler configuration:
1944
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
1945
+ `);
1946
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1947
+ "Processing wrangler configuration:
1948
+
1949
+ - \\"env.DEV\\" environment configuration
1950
+ - The \\"account_id\\" field is not allowed in named service environments.
1951
+ Please remove the field from this environment."
1952
+ `);
1953
+ });
1954
+
1331
1955
  it("should warn for non-inherited fields that are missing in environments", () => {
1332
1956
  const vars: RawConfig["vars"] = {
1333
1957
  FOO: "foo",
@@ -1351,10 +1975,11 @@ describe("normalizeAndValidateConfig()", () => {
1351
1975
 
1352
1976
  const { config, diagnostics } = normalizeAndValidateConfig(
1353
1977
  rawConfig,
1354
- undefined
1978
+ undefined,
1979
+ { env: "ENV1" }
1355
1980
  );
1356
1981
 
1357
- expect(config.env.ENV1).toEqual(
1982
+ expect(config).toEqual(
1358
1983
  expect.not.objectContaining({
1359
1984
  vars,
1360
1985
  durable_objects,
@@ -1397,30 +2022,47 @@ describe("normalizeAndValidateConfig()", () => {
1397
2022
  route: 888,
1398
2023
  jsx_factory: 999,
1399
2024
  jsx_fragment: 1000,
2025
+ tsconfig: 123,
1400
2026
  triggers: { crons: [1111, 1222] },
1401
2027
  usage_model: "INVALID",
2028
+ main: 1333,
2029
+ build: {
2030
+ command: 1444,
2031
+ cwd: 1555,
2032
+ watch_dir: 1666,
2033
+ },
1402
2034
  } as unknown as RawEnvironment;
1403
2035
 
1404
2036
  const { config, diagnostics } = normalizeAndValidateConfig(
1405
2037
  { env: { ENV1: expectedConfig } },
1406
- undefined
2038
+ undefined,
2039
+ { env: "ENV1" }
1407
2040
  );
1408
2041
 
1409
- expect(config.env.ENV1).toEqual(expect.objectContaining(expectedConfig));
2042
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
1410
2043
  expect(diagnostics.hasWarnings()).toBe(false);
1411
2044
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1412
2045
  "Processing wrangler configuration:
1413
2046
 
1414
2047
  - \\"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.
2048
+ - Expected \\"route\\" to be either a string, or an object with shape { pattern, zone_id | zone_name }, but got 888.
2049
+ - Expected \\"routes\\" to be an array of either strings or objects with the shape { pattern, zone_id | zone_name }, but these weren't valid: [
2050
+ 666,
2051
+ 777
2052
+ ].
2053
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"].
2054
+ - Expected \\"workers_dev\\" to be of type boolean but got \\"BAD\\".
2055
+ - Expected \\"build.command\\" to be of type string but got 1444.
2056
+ - Expected \\"build.cwd\\" to be of type string but got 1555.
2057
+ - Expected \\"build.watch_dir\\" to be of type string but got 1666.
2058
+ - Expected \\"account_id\\" to be of type string but got 222.
2059
+ - Expected \\"compatibility_date\\" to be of type string but got 333.
2060
+ - Expected \\"compatibility_flags\\" to be of type string array but got [444,555].
2061
+ - Expected \\"jsx_factory\\" to be of type string but got 999.
2062
+ - Expected \\"jsx_fragment\\" to be of type string but got 1000.
2063
+ - Expected \\"tsconfig\\" to be of type string but got 123.
2064
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got 111.
2065
+ - Expected \\"main\\" to be of type string but got 1333.
1424
2066
  - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
1425
2067
  `);
1426
2068
  });
@@ -1429,10 +2071,11 @@ describe("normalizeAndValidateConfig()", () => {
1429
2071
  it("should error if durable_objects is an array", () => {
1430
2072
  const { config, diagnostics } = normalizeAndValidateConfig(
1431
2073
  { env: { ENV1: { durable_objects: [] } } } as unknown as RawConfig,
1432
- undefined
2074
+ undefined,
2075
+ { env: "ENV1" }
1433
2076
  );
1434
2077
 
1435
- expect(config.env.ENV1).toEqual(
2078
+ expect(config).toEqual(
1436
2079
  expect.not.objectContaining({ durable_objects: expect.anything })
1437
2080
  );
1438
2081
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1447,10 +2090,11 @@ describe("normalizeAndValidateConfig()", () => {
1447
2090
  it("should error if durable_objects is a string", () => {
1448
2091
  const { config, diagnostics } = normalizeAndValidateConfig(
1449
2092
  { env: { ENV1: { durable_objects: "BAD" } } } as unknown as RawConfig,
1450
- undefined
2093
+ undefined,
2094
+ { env: "ENV1" }
1451
2095
  );
1452
2096
 
1453
- expect(config.env.ENV1).toEqual(
2097
+ expect(config).toEqual(
1454
2098
  expect.not.objectContaining({ durable_objects: expect.anything })
1455
2099
  );
1456
2100
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1465,10 +2109,11 @@ describe("normalizeAndValidateConfig()", () => {
1465
2109
  it("should error if durable_objects is a number", () => {
1466
2110
  const { config, diagnostics } = normalizeAndValidateConfig(
1467
2111
  { env: { ENV1: { durable_objects: 999 } } } as unknown as RawConfig,
1468
- undefined
2112
+ undefined,
2113
+ { env: "ENV1" }
1469
2114
  );
1470
2115
 
1471
- expect(config.env.ENV1).toEqual(
2116
+ expect(config).toEqual(
1472
2117
  expect.not.objectContaining({ durable_objects: expect.anything })
1473
2118
  );
1474
2119
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1483,10 +2128,11 @@ describe("normalizeAndValidateConfig()", () => {
1483
2128
  it("should error if durable_objects is null", () => {
1484
2129
  const { config, diagnostics } = normalizeAndValidateConfig(
1485
2130
  { env: { ENV1: { durable_objects: null } } } as unknown as RawConfig,
1486
- undefined
2131
+ undefined,
2132
+ { env: "ENV1" }
1487
2133
  );
1488
2134
 
1489
- expect(config.env.ENV1).toEqual(
2135
+ expect(config).toEqual(
1490
2136
  expect.not.objectContaining({ durable_objects: expect.anything })
1491
2137
  );
1492
2138
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1501,10 +2147,11 @@ describe("normalizeAndValidateConfig()", () => {
1501
2147
  it("should error if durable_objects.bindings is not defined", () => {
1502
2148
  const { config, diagnostics } = normalizeAndValidateConfig(
1503
2149
  { env: { ENV1: { durable_objects: {} } } } as unknown as RawConfig,
1504
- undefined
2150
+ undefined,
2151
+ { env: "ENV1" }
1505
2152
  );
1506
2153
 
1507
- expect(config.env.ENV1).toEqual(
2154
+ expect(config).toEqual(
1508
2155
  expect.not.objectContaining({ durable_objects: expect.anything })
1509
2156
  );
1510
2157
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1521,10 +2168,11 @@ describe("normalizeAndValidateConfig()", () => {
1521
2168
  {
1522
2169
  env: { ENV1: { durable_objects: { bindings: {} } } },
1523
2170
  } as unknown as RawConfig,
1524
- undefined
2171
+ undefined,
2172
+ { env: "ENV1" }
1525
2173
  );
1526
2174
 
1527
- expect(config.env.ENV1).toEqual(
2175
+ expect(config).toEqual(
1528
2176
  expect.not.objectContaining({
1529
2177
  durable_objects: { bindings: expect.anything },
1530
2178
  })
@@ -1543,10 +2191,11 @@ describe("normalizeAndValidateConfig()", () => {
1543
2191
  {
1544
2192
  env: { ENV1: { durable_objects: { bindings: "BAD" } } },
1545
2193
  } as unknown as RawConfig,
1546
- undefined
2194
+ undefined,
2195
+ { env: "ENV1" }
1547
2196
  );
1548
2197
 
1549
- expect(config.env.ENV1).toEqual(
2198
+ expect(config).toEqual(
1550
2199
  expect.not.objectContaining({
1551
2200
  durable_objects: { bindings: expect.anything },
1552
2201
  })
@@ -1565,10 +2214,11 @@ describe("normalizeAndValidateConfig()", () => {
1565
2214
  {
1566
2215
  env: { ENV1: { durable_objects: { bindings: 999 } } },
1567
2216
  } as unknown as RawConfig,
1568
- undefined
2217
+ undefined,
2218
+ { env: "ENV1" }
1569
2219
  );
1570
2220
 
1571
- expect(config.env.ENV1).toEqual(
2221
+ expect(config).toEqual(
1572
2222
  expect.not.objectContaining({
1573
2223
  durable_objects: { bindings: expect.anything },
1574
2224
  })
@@ -1587,10 +2237,11 @@ describe("normalizeAndValidateConfig()", () => {
1587
2237
  {
1588
2238
  env: { ENV1: { durable_objects: { bindings: null } } },
1589
2239
  } as unknown as RawConfig,
1590
- undefined
2240
+ undefined,
2241
+ { env: "ENV1" }
1591
2242
  );
1592
2243
 
1593
- expect(config.env.ENV1).toEqual(
2244
+ expect(config).toEqual(
1594
2245
  expect.not.objectContaining({
1595
2246
  durable_objects: { bindings: expect.anything },
1596
2247
  })
@@ -1624,10 +2275,11 @@ describe("normalizeAndValidateConfig()", () => {
1624
2275
  },
1625
2276
  },
1626
2277
  } as unknown as RawConfig,
1627
- undefined
2278
+ undefined,
2279
+ { env: "ENV1" }
1628
2280
  );
1629
2281
 
1630
- expect(config.env.ENV1).toEqual(
2282
+ expect(config).toEqual(
1631
2283
  expect.not.objectContaining({
1632
2284
  durable_objects: { bindings: expect.anything },
1633
2285
  })
@@ -1661,10 +2313,11 @@ describe("normalizeAndValidateConfig()", () => {
1661
2313
  it("should error if kv_namespaces is an object", () => {
1662
2314
  const { config, diagnostics } = normalizeAndValidateConfig(
1663
2315
  { env: { ENV1: { kv_namespaces: {} } } } as unknown as RawConfig,
1664
- undefined
2316
+ undefined,
2317
+ { env: "ENV1" }
1665
2318
  );
1666
2319
 
1667
- expect(config.env.ENV1).toEqual(
2320
+ expect(config).toEqual(
1668
2321
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1669
2322
  );
1670
2323
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1679,10 +2332,11 @@ describe("normalizeAndValidateConfig()", () => {
1679
2332
  it("should error if kv_namespaces is a string", () => {
1680
2333
  const { config, diagnostics } = normalizeAndValidateConfig(
1681
2334
  { env: { ENV1: { kv_namespaces: "BAD" } } } as unknown as RawConfig,
1682
- undefined
2335
+ undefined,
2336
+ { env: "ENV1" }
1683
2337
  );
1684
2338
 
1685
- expect(config.env.ENV1).toEqual(
2339
+ expect(config).toEqual(
1686
2340
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1687
2341
  );
1688
2342
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1697,10 +2351,11 @@ describe("normalizeAndValidateConfig()", () => {
1697
2351
  it("should error if kv_namespaces is a number", () => {
1698
2352
  const { config, diagnostics } = normalizeAndValidateConfig(
1699
2353
  { env: { ENV1: { kv_namespaces: 999 } } } as unknown as RawConfig,
1700
- undefined
2354
+ undefined,
2355
+ { env: "ENV1" }
1701
2356
  );
1702
2357
 
1703
- expect(config.env.ENV1).toEqual(
2358
+ expect(config).toEqual(
1704
2359
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1705
2360
  );
1706
2361
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1715,10 +2370,11 @@ describe("normalizeAndValidateConfig()", () => {
1715
2370
  it("should error if kv_namespaces is null", () => {
1716
2371
  const { config, diagnostics } = normalizeAndValidateConfig(
1717
2372
  { env: { ENV1: { kv_namespaces: null } } } as unknown as RawConfig,
1718
- undefined
2373
+ undefined,
2374
+ { env: "ENV1" }
1719
2375
  );
1720
2376
 
1721
- expect(config.env.ENV1).toEqual(
2377
+ expect(config).toEqual(
1722
2378
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1723
2379
  );
1724
2380
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1748,10 +2404,11 @@ describe("normalizeAndValidateConfig()", () => {
1748
2404
  },
1749
2405
  },
1750
2406
  } as unknown as RawConfig,
1751
- undefined
2407
+ undefined,
2408
+ { env: "ENV1" }
1752
2409
  );
1753
2410
 
1754
- expect(config.env.ENV1).toEqual(
2411
+ expect(config).toEqual(
1755
2412
  expect.not.objectContaining({
1756
2413
  kv_namespaces: { bindings: expect.anything },
1757
2414
  })
@@ -1775,10 +2432,11 @@ describe("normalizeAndValidateConfig()", () => {
1775
2432
  it("should error if r2_buckets is an object", () => {
1776
2433
  const { config, diagnostics } = normalizeAndValidateConfig(
1777
2434
  { env: { ENV1: { r2_buckets: {} } } } as unknown as RawConfig,
1778
- undefined
2435
+ undefined,
2436
+ { env: "ENV1" }
1779
2437
  );
1780
2438
 
1781
- expect(config.env.ENV1).toEqual(
2439
+ expect(config).toEqual(
1782
2440
  expect.not.objectContaining({ r2_buckets: expect.anything })
1783
2441
  );
1784
2442
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1793,10 +2451,11 @@ describe("normalizeAndValidateConfig()", () => {
1793
2451
  it("should error if r2_buckets is a string", () => {
1794
2452
  const { config, diagnostics } = normalizeAndValidateConfig(
1795
2453
  { env: { ENV1: { r2_buckets: "BAD" } } } as unknown as RawConfig,
1796
- undefined
2454
+ undefined,
2455
+ { env: "ENV1" }
1797
2456
  );
1798
2457
 
1799
- expect(config.env.ENV1).toEqual(
2458
+ expect(config).toEqual(
1800
2459
  expect.not.objectContaining({ r2_buckets: expect.anything })
1801
2460
  );
1802
2461
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1811,10 +2470,11 @@ describe("normalizeAndValidateConfig()", () => {
1811
2470
  it("should error if r2_buckets is a number", () => {
1812
2471
  const { config, diagnostics } = normalizeAndValidateConfig(
1813
2472
  { env: { ENV1: { r2_buckets: 999 } } } as unknown as RawConfig,
1814
- undefined
2473
+ undefined,
2474
+ { env: "ENV1" }
1815
2475
  );
1816
2476
 
1817
- expect(config.env.ENV1).toEqual(
2477
+ expect(config).toEqual(
1818
2478
  expect.not.objectContaining({ r2_buckets: expect.anything })
1819
2479
  );
1820
2480
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1829,10 +2489,11 @@ describe("normalizeAndValidateConfig()", () => {
1829
2489
  it("should error if r2_buckets is null", () => {
1830
2490
  const { config, diagnostics } = normalizeAndValidateConfig(
1831
2491
  { env: { ENV1: { r2_buckets: null } } } as unknown as RawConfig,
1832
- undefined
2492
+ undefined,
2493
+ { env: "ENV1" }
1833
2494
  );
1834
2495
 
1835
- expect(config.env.ENV1).toEqual(
2496
+ expect(config).toEqual(
1836
2497
  expect.not.objectContaining({ r2_buckets: expect.anything })
1837
2498
  );
1838
2499
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1862,10 +2523,11 @@ describe("normalizeAndValidateConfig()", () => {
1862
2523
  },
1863
2524
  },
1864
2525
  } as unknown as RawConfig,
1865
- undefined
2526
+ undefined,
2527
+ { env: "ENV1" }
1866
2528
  );
1867
2529
 
1868
- expect(config.env.ENV1).toEqual(
2530
+ expect(config).toEqual(
1869
2531
  expect.not.objectContaining({
1870
2532
  r2_buckets: { bindings: expect.anything },
1871
2533
  })
@@ -1889,10 +2551,11 @@ describe("normalizeAndValidateConfig()", () => {
1889
2551
  it("should error if unsafe is an array", () => {
1890
2552
  const { config, diagnostics } = normalizeAndValidateConfig(
1891
2553
  { env: { ENV1: { unsafe: [] } } } as unknown as RawConfig,
1892
- undefined
2554
+ undefined,
2555
+ { env: "ENV1" }
1893
2556
  );
1894
2557
 
1895
- expect(config.env.ENV1).toEqual(
2558
+ expect(config).toEqual(
1896
2559
  expect.not.objectContaining({ unsafe: expect.anything })
1897
2560
  );
1898
2561
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1912,10 +2575,11 @@ describe("normalizeAndValidateConfig()", () => {
1912
2575
  it("should error if unsafe is a string", () => {
1913
2576
  const { config, diagnostics } = normalizeAndValidateConfig(
1914
2577
  { env: { ENV1: { unsafe: "BAD" } } } as unknown as RawConfig,
1915
- undefined
2578
+ undefined,
2579
+ { env: "ENV1" }
1916
2580
  );
1917
2581
 
1918
- expect(config.env.ENV1).toEqual(
2582
+ expect(config).toEqual(
1919
2583
  expect.not.objectContaining({ unsafe: expect.anything })
1920
2584
  );
1921
2585
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1935,10 +2599,11 @@ describe("normalizeAndValidateConfig()", () => {
1935
2599
  it("should error if unsafe is a number", () => {
1936
2600
  const { config, diagnostics } = normalizeAndValidateConfig(
1937
2601
  { env: { ENV1: { unsafe: 999 } } } as unknown as RawConfig,
1938
- undefined
2602
+ undefined,
2603
+ { env: "ENV1" }
1939
2604
  );
1940
2605
 
1941
- expect(config.env.ENV1).toEqual(
2606
+ expect(config).toEqual(
1942
2607
  expect.not.objectContaining({ unsafe: expect.anything })
1943
2608
  );
1944
2609
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1958,10 +2623,11 @@ describe("normalizeAndValidateConfig()", () => {
1958
2623
  it("should error if unsafe is null", () => {
1959
2624
  const { config, diagnostics } = normalizeAndValidateConfig(
1960
2625
  { env: { ENV1: { unsafe: null } } } as unknown as RawConfig,
1961
- undefined
2626
+ undefined,
2627
+ { env: "ENV1" }
1962
2628
  );
1963
2629
 
1964
- expect(config.env.ENV1).toEqual(
2630
+ expect(config).toEqual(
1965
2631
  expect.not.objectContaining({ unsafe: expect.anything })
1966
2632
  );
1967
2633
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1981,10 +2647,11 @@ describe("normalizeAndValidateConfig()", () => {
1981
2647
  it("should error if unsafe.bindings is not defined", () => {
1982
2648
  const { config, diagnostics } = normalizeAndValidateConfig(
1983
2649
  { env: { ENV1: { unsafe: {} } } } as unknown as RawConfig,
1984
- undefined
2650
+ undefined,
2651
+ { env: "ENV1" }
1985
2652
  );
1986
2653
 
1987
- expect(config.env.ENV1).toEqual(
2654
+ expect(config).toEqual(
1988
2655
  expect.not.objectContaining({ unsafe: expect.anything })
1989
2656
  );
1990
2657
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -2006,10 +2673,11 @@ describe("normalizeAndValidateConfig()", () => {
2006
2673
  {
2007
2674
  env: { ENV1: { unsafe: { bindings: {} } } },
2008
2675
  } as unknown as RawConfig,
2009
- undefined
2676
+ undefined,
2677
+ { env: "ENV1" }
2010
2678
  );
2011
2679
 
2012
- expect(config.env.ENV1).toEqual(
2680
+ expect(config).toEqual(
2013
2681
  expect.not.objectContaining({
2014
2682
  unsafe: { bindings: expect.anything },
2015
2683
  })
@@ -2033,10 +2701,11 @@ describe("normalizeAndValidateConfig()", () => {
2033
2701
  {
2034
2702
  env: { ENV1: { unsafe: { bindings: "BAD" } } },
2035
2703
  } as unknown as RawConfig,
2036
- undefined
2704
+ undefined,
2705
+ { env: "ENV1" }
2037
2706
  );
2038
2707
 
2039
- expect(config.env.ENV1).toEqual(
2708
+ expect(config).toEqual(
2040
2709
  expect.not.objectContaining({
2041
2710
  unsafe: { bindings: expect.anything },
2042
2711
  })
@@ -2060,10 +2729,11 @@ describe("normalizeAndValidateConfig()", () => {
2060
2729
  {
2061
2730
  env: { ENV1: { unsafe: { bindings: 999 } } },
2062
2731
  } as unknown as RawConfig,
2063
- undefined
2732
+ undefined,
2733
+ { env: "ENV1" }
2064
2734
  );
2065
2735
 
2066
- expect(config.env.ENV1).toEqual(
2736
+ expect(config).toEqual(
2067
2737
  expect.not.objectContaining({
2068
2738
  unsafe: { bindings: expect.anything },
2069
2739
  })
@@ -2087,10 +2757,11 @@ describe("normalizeAndValidateConfig()", () => {
2087
2757
  {
2088
2758
  env: { ENV1: { unsafe: { bindings: null } } },
2089
2759
  } as unknown as RawConfig,
2090
- undefined
2760
+ undefined,
2761
+ { env: "ENV1" }
2091
2762
  );
2092
2763
 
2093
- expect(config.env.ENV1).toEqual(
2764
+ expect(config).toEqual(
2094
2765
  expect.not.objectContaining({
2095
2766
  unsafe: { bindings: expect.anything },
2096
2767
  })
@@ -2129,10 +2800,11 @@ describe("normalizeAndValidateConfig()", () => {
2129
2800
  },
2130
2801
  },
2131
2802
  } as unknown as RawConfig,
2132
- undefined
2803
+ undefined,
2804
+ { env: "ENV1" }
2133
2805
  );
2134
2806
 
2135
- expect(config.env.ENV1).toEqual(
2807
+ expect(config).toEqual(
2136
2808
  expect.not.objectContaining({
2137
2809
  durable_objects: { bindings: expect.anything },
2138
2810
  })
@@ -2168,7 +2840,7 @@ describe("normalizeAndValidateConfig()", () => {
2168
2840
  zone_id: "ZONE_ID",
2169
2841
  experimental_services: [
2170
2842
  {
2171
- name: "NAME",
2843
+ name: "mock-name",
2172
2844
  service: "SERVICE",
2173
2845
  environment: "ENV",
2174
2846
  },
@@ -2181,25 +2853,26 @@ describe("normalizeAndValidateConfig()", () => {
2181
2853
  ENV1: environment,
2182
2854
  },
2183
2855
  },
2184
- undefined
2856
+ undefined,
2857
+ { env: "ENV1" }
2185
2858
  );
2186
2859
 
2187
- expect("experimental_services" in config.env.ENV1).toBe(false);
2860
+ expect("experimental_services" in config).toBe(false);
2188
2861
  // Zone is not removed yet, since `route` commands might use it
2189
- expect(config.env.ENV1.zone_id).toEqual("ZONE_ID");
2862
+ expect(config.zone_id).toEqual("ZONE_ID");
2190
2863
  expect(diagnostics.hasErrors()).toBe(false);
2191
2864
  expect(diagnostics.hasWarnings()).toBe(true);
2192
2865
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2193
2866
  "Processing wrangler configuration:
2194
2867
 
2195
2868
  - \\"env.ENV1\\" environment configuration
2196
- - DEPRECATION: \\"zone_id\\":
2869
+ - Deprecation: \\"zone_id\\":
2197
2870
  This is unnecessary since we can deduce this from routes directly.
2198
- - DEPRECATION: \\"experimental_services\\":
2871
+ - Deprecation: \\"experimental_services\\":
2199
2872
  The \\"experimental_services\\" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
2200
2873
  \`\`\`
2201
2874
  [[unsafe.bindings]]
2202
- name = \\"NAME\\"
2875
+ name = \\"mock-name\\"
2203
2876
  type = \\"service\\"
2204
2877
  service = \\"SERVICE\\"
2205
2878
  environment = \\"ENV\\"
@@ -2207,6 +2880,241 @@ describe("normalizeAndValidateConfig()", () => {
2207
2880
  `);
2208
2881
  });
2209
2882
  });
2883
+
2884
+ describe("route & routes fields", () => {
2885
+ it("should error if both route and routes are specified in the same environment", () => {
2886
+ const environment: RawEnvironment = {
2887
+ name: "mock-env-name",
2888
+ account_id: "ENV_ACCOUNT_ID",
2889
+ compatibility_date: "2022-02-02",
2890
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2891
+ workers_dev: true,
2892
+ route: "ENV_ROUTE_1",
2893
+ routes: ["ENV_ROUTE_2", "ENV_ROUTE_3"],
2894
+ jsx_factory: "ENV_JSX_FACTORY",
2895
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2896
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2897
+ usage_model: "unbound",
2898
+ };
2899
+ const expectedConfig: RawConfig = {
2900
+ name: "mock-name",
2901
+ account_id: "ACCOUNT_ID",
2902
+ compatibility_date: "2022-01-01",
2903
+ compatibility_flags: ["FLAG1", "FLAG2"],
2904
+ workers_dev: false,
2905
+ routes: ["ROUTE_1", "ROUTE_2"],
2906
+ jsx_factory: "JSX_FACTORY",
2907
+ jsx_fragment: "JSX_FRAGMENT",
2908
+ triggers: { crons: ["CRON_1", "CRON_2"] },
2909
+ usage_model: "bundled",
2910
+ env: {
2911
+ ENV1: environment,
2912
+ },
2913
+ };
2914
+
2915
+ const { config, diagnostics } = normalizeAndValidateConfig(
2916
+ expectedConfig,
2917
+ undefined,
2918
+ { env: "ENV1" }
2919
+ );
2920
+
2921
+ expect(config).toEqual(expect.objectContaining(environment));
2922
+ expect(diagnostics.hasErrors()).toBe(true);
2923
+ expect(diagnostics.hasWarnings()).toBe(false);
2924
+
2925
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2926
+ "Processing wrangler configuration:
2927
+
2928
+ - \\"env.ENV1\\" environment configuration
2929
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
2930
+ `);
2931
+ });
2932
+
2933
+ it("should error if both route and routes are specified in the top-level environment", () => {
2934
+ const environment: RawEnvironment = {
2935
+ name: "mock-env-name",
2936
+ account_id: "ENV_ACCOUNT_ID",
2937
+ compatibility_date: "2022-02-02",
2938
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2939
+ workers_dev: true,
2940
+ routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
2941
+ jsx_factory: "ENV_JSX_FACTORY",
2942
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2943
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2944
+ usage_model: "unbound",
2945
+ };
2946
+ const expectedConfig: RawConfig = {
2947
+ name: "mock-name",
2948
+ account_id: "ACCOUNT_ID",
2949
+ compatibility_date: "2022-01-01",
2950
+ compatibility_flags: ["FLAG1", "FLAG2"],
2951
+ workers_dev: false,
2952
+ route: "ROUTE_1",
2953
+ routes: ["ROUTE_2", "ROUTE_3"],
2954
+ jsx_factory: "JSX_FACTORY",
2955
+ jsx_fragment: "JSX_FRAGMENT",
2956
+ triggers: { crons: ["CRON_1", "CRON_2"] },
2957
+ usage_model: "bundled",
2958
+ env: {
2959
+ ENV1: environment,
2960
+ },
2961
+ };
2962
+
2963
+ const { config, diagnostics } = normalizeAndValidateConfig(
2964
+ expectedConfig,
2965
+ undefined,
2966
+ { env: "ENV1" }
2967
+ );
2968
+
2969
+ expect(config).toEqual(expect.objectContaining(environment));
2970
+ expect(diagnostics.hasErrors()).toBe(true);
2971
+ expect(diagnostics.hasWarnings()).toBe(false);
2972
+
2973
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2974
+ "Processing wrangler configuration:
2975
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
2976
+ `);
2977
+ });
2978
+
2979
+ it("should not error if <env>.route and <top-level>.routes are specified", () => {
2980
+ const environment: RawEnvironment = {
2981
+ name: "mock-env-name",
2982
+ account_id: "ENV_ACCOUNT_ID",
2983
+ compatibility_date: "2022-02-02",
2984
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
2985
+ workers_dev: true,
2986
+ route: "ENV_ROUTE_1",
2987
+ jsx_factory: "ENV_JSX_FACTORY",
2988
+ jsx_fragment: "ENV_JSX_FRAGMENT",
2989
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
2990
+ usage_model: "unbound",
2991
+ };
2992
+ const expectedConfig: RawConfig = {
2993
+ name: "mock-name",
2994
+ account_id: "ACCOUNT_ID",
2995
+ compatibility_date: "2022-01-01",
2996
+ compatibility_flags: ["FLAG1", "FLAG2"],
2997
+ workers_dev: false,
2998
+ routes: ["ROUTE_1", "ROUTE_2"],
2999
+ jsx_factory: "JSX_FACTORY",
3000
+ jsx_fragment: "JSX_FRAGMENT",
3001
+ triggers: { crons: ["CRON_1", "CRON_2"] },
3002
+ usage_model: "bundled",
3003
+ env: {
3004
+ ENV1: environment,
3005
+ },
3006
+ };
3007
+
3008
+ const { config, diagnostics } = normalizeAndValidateConfig(
3009
+ expectedConfig,
3010
+ undefined,
3011
+ { env: "ENV1" }
3012
+ );
3013
+
3014
+ expect(config).toEqual(expect.objectContaining(environment));
3015
+ expect(diagnostics.hasErrors()).toBe(false);
3016
+ expect(diagnostics.hasWarnings()).toBe(false);
3017
+ });
3018
+
3019
+ it("should not error if <env>.routes and <top-level>.route are specified", () => {
3020
+ const environment: RawEnvironment = {
3021
+ name: "mock-env-name",
3022
+ account_id: "ENV_ACCOUNT_ID",
3023
+ compatibility_date: "2022-02-02",
3024
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3025
+ workers_dev: true,
3026
+ routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
3027
+ jsx_factory: "ENV_JSX_FACTORY",
3028
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3029
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3030
+ usage_model: "unbound",
3031
+ };
3032
+ const expectedConfig: RawConfig = {
3033
+ name: "mock-name",
3034
+ account_id: "ACCOUNT_ID",
3035
+ compatibility_date: "2022-01-01",
3036
+ compatibility_flags: ["FLAG1", "FLAG2"],
3037
+ workers_dev: false,
3038
+ route: "ROUTE_1",
3039
+ jsx_factory: "JSX_FACTORY",
3040
+ jsx_fragment: "JSX_FRAGMENT",
3041
+ triggers: { crons: ["CRON_1", "CRON_2"] },
3042
+ usage_model: "bundled",
3043
+ env: {
3044
+ ENV1: environment,
3045
+ },
3046
+ };
3047
+
3048
+ const { config, diagnostics } = normalizeAndValidateConfig(
3049
+ expectedConfig,
3050
+ undefined,
3051
+ { env: "ENV1" }
3052
+ );
3053
+
3054
+ expect(config).toEqual(expect.objectContaining(environment));
3055
+ expect(diagnostics.hasErrors()).toBe(false);
3056
+ expect(diagnostics.hasWarnings()).toBe(false);
3057
+ });
3058
+
3059
+ it("should not error if <env1>.route and <env2>.routes are specified", () => {
3060
+ const environment1: RawEnvironment = {
3061
+ name: "mock-env-name",
3062
+ account_id: "ENV_ACCOUNT_ID",
3063
+ compatibility_date: "2022-02-02",
3064
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3065
+ workers_dev: true,
3066
+ routes: ["ENV1_ROUTE_1", "ENV2_ROUTE_2"],
3067
+ jsx_factory: "ENV_JSX_FACTORY",
3068
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3069
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3070
+ usage_model: "unbound",
3071
+ };
3072
+ const environment2: RawEnvironment = {
3073
+ name: "mock-env-name",
3074
+ account_id: "ENV_ACCOUNT_ID",
3075
+ compatibility_date: "2022-02-02",
3076
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3077
+ workers_dev: true,
3078
+ route: "ENV2_ROUTE_1",
3079
+ jsx_factory: "ENV_JSX_FACTORY",
3080
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3081
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3082
+ usage_model: "unbound",
3083
+ };
3084
+ const expectedConfig: RawConfig = {
3085
+ name: "mock-name",
3086
+ account_id: "ACCOUNT_ID",
3087
+ compatibility_date: "2022-01-01",
3088
+ compatibility_flags: ["FLAG1", "FLAG2"],
3089
+ workers_dev: false,
3090
+ route: "ROUTE_1",
3091
+ jsx_factory: "JSX_FACTORY",
3092
+ jsx_fragment: "JSX_FRAGMENT",
3093
+ triggers: { crons: ["CRON_1", "CRON_2"] },
3094
+ usage_model: "bundled",
3095
+ env: {
3096
+ ENV1: environment1,
3097
+ ENV2: environment2,
3098
+ },
3099
+ };
3100
+
3101
+ const result1 = normalizeAndValidateConfig(expectedConfig, undefined, {
3102
+ env: "ENV1",
3103
+ });
3104
+
3105
+ expect(result1.config).toEqual(expect.objectContaining(environment1));
3106
+ expect(result1.diagnostics.hasErrors()).toBe(false);
3107
+ expect(result1.diagnostics.hasWarnings()).toBe(false);
3108
+
3109
+ const result2 = normalizeAndValidateConfig(expectedConfig, undefined, {
3110
+ env: "ENV2",
3111
+ });
3112
+
3113
+ expect(result2.config).toEqual(expect.objectContaining(environment2));
3114
+ expect(result2.diagnostics.hasErrors()).toBe(false);
3115
+ expect(result2.diagnostics.hasWarnings()).toBe(false);
3116
+ });
3117
+ });
2210
3118
  });
2211
3119
  });
2212
3120