wrangler 0.0.0-e043479 → 0.0.0-e0a0509

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 (96) hide show
  1. package/README.md +27 -14
  2. package/bin/wrangler.js +13 -1
  3. package/miniflare-dist/index.mjs +4886 -0
  4. package/package.json +38 -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 +1294 -355
  14. package/src/__tests__/dev.test.tsx +592 -12
  15. package/src/__tests__/guess-worker-format.test.ts +37 -18
  16. package/src/__tests__/helpers/mock-account-id.ts +4 -0
  17. package/src/__tests__/helpers/mock-cfetch.ts +8 -4
  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 +130 -0
  27. package/src/__tests__/index.test.ts +129 -753
  28. package/src/__tests__/init.test.ts +1516 -0
  29. package/src/__tests__/jest.setup.ts +13 -5
  30. package/src/__tests__/kv.test.ts +208 -174
  31. package/src/__tests__/logger.test.ts +115 -0
  32. package/src/__tests__/pages.test.ts +327 -0
  33. package/src/__tests__/parse.test.ts +4 -0
  34. package/src/__tests__/publish.test.ts +3313 -505
  35. package/src/__tests__/r2.test.ts +38 -26
  36. package/src/__tests__/route.test.ts +45 -0
  37. package/src/__tests__/secret.test.ts +55 -34
  38. package/src/__tests__/tail.test.ts +146 -20
  39. package/src/__tests__/user.test.ts +131 -0
  40. package/src/__tests__/whoami.test.tsx +26 -7
  41. package/src/bundle.ts +43 -7
  42. package/src/cfetch/internal.ts +9 -5
  43. package/src/cli.ts +5 -11
  44. package/src/config/README.md +7 -7
  45. package/src/config/config.ts +69 -105
  46. package/src/config/environment.ts +93 -4
  47. package/src/config/index.ts +15 -4
  48. package/src/config/validation-helpers.ts +228 -23
  49. package/src/config/validation.ts +559 -154
  50. package/src/config-cache.ts +45 -0
  51. package/src/{api/preview.ts → create-worker-preview.ts} +41 -13
  52. package/src/{api/form_data.ts → create-worker-upload-form.ts} +33 -10
  53. package/src/dev/dev-vars.ts +36 -0
  54. package/src/dev/dev.tsx +418 -0
  55. package/src/dev/local.tsx +312 -0
  56. package/src/dev/remote.tsx +213 -0
  57. package/src/dev/use-esbuild.ts +118 -0
  58. package/src/dialogs.tsx +16 -6
  59. package/src/entry.ts +222 -12
  60. package/src/environment-variables.ts +3 -1
  61. package/src/errors.ts +11 -0
  62. package/src/https-options.ts +123 -0
  63. package/src/index.tsx +878 -482
  64. package/src/inspect.ts +25 -11
  65. package/src/intl-polyfill.d.ts +139 -0
  66. package/src/{kv.tsx → kv.ts} +7 -27
  67. package/src/logger.ts +66 -0
  68. package/src/miniflare-cli/README.md +30 -0
  69. package/src/miniflare-cli/enum-keys.ts +17 -0
  70. package/src/miniflare-cli/index.ts +41 -0
  71. package/src/miniflare-cli/request-context.ts +40 -0
  72. package/src/module-collection.ts +94 -6
  73. package/src/open-in-browser.ts +18 -5
  74. package/src/package-manager.ts +9 -8
  75. package/src/pages.tsx +892 -62
  76. package/src/parse.ts +4 -2
  77. package/src/proxy.ts +128 -55
  78. package/src/publish.ts +305 -199
  79. package/src/selfsigned.d.ts +29 -0
  80. package/src/sites.tsx +88 -33
  81. package/src/tail/index.ts +2 -2
  82. package/src/tail/printing.ts +13 -8
  83. package/src/update-check.ts +19 -0
  84. package/src/user.tsx +244 -104
  85. package/src/whoami.tsx +2 -1
  86. package/src/{api/worker.ts → worker.ts} +15 -29
  87. package/templates/gitignore +171 -0
  88. package/templates/static-asset-facade.js +1 -1
  89. package/wrangler-dist/cli.js +23568 -50489
  90. package/src/__tests__/helpers/mock-user.ts +0 -27
  91. package/src/__tests__/logout.test.ts +0 -50
  92. package/src/__tests__/sentry.test.ts +0 -146
  93. package/src/dev.tsx +0 -960
  94. package/src/guess-worker-format.ts +0 -68
  95. package/src/reporting.ts +0 -115
  96. 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,18 +25,18 @@ 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
- port: 8787,
30
+ port: undefined, // the default of 8787 is set at runtime
23
31
  upstream_protocol: "https",
24
32
  host: undefined,
25
33
  },
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,56 +67,42 @@ 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",
67
74
  port: 9999,
68
- local_protocol: "HTTPS",
69
- upstream_protocol: "HTTP",
70
- },
71
- build: {
72
- command: "COMMAND",
73
- cwd: "CWD",
74
- watch_dir: "WATCH_DIR",
75
+ local_protocol: "https",
76
+ upstream_protocol: "http",
75
77
  },
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,
97
96
  port: "FOO",
98
- local_protocol: 333,
99
- upstream_protocol: 444,
100
- },
101
- build: {
102
- command: 555,
103
- cwd: 666,
104
- watch_dir: 777,
97
+ local_protocol: "wss",
98
+ upstream_protocol: "ws",
105
99
  },
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(
@@ -115,80 +110,55 @@ describe("normalizeAndValidateConfig()", () => {
115
110
  );
116
111
  expect(diagnostics.hasWarnings()).toBe(false);
117
112
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
118
- "Processing wrangler configuration:
119
- - ERROR: \\"build.command\\" should be of type string but got 555.
120
- - ERROR: \\"build.cwd\\" should be of type string but got 666.
121
- - ERROR: \\"build.watch_dir\\" should be of type string but got 777.
122
- - ERROR: \\"legacy_env\\" should be of type boolean but got \\"FOO\\".
123
- - ERROR: \\"main\\" should be a string but got 111
124
- - ERROR: \\"dev.ip\\" should be of type string but got 222.
125
- - ERROR: \\"dev.port\\" should be of type number but got \\"FOO\\".
126
- - ERROR: \\"dev.local_protocol\\" should be of type string but got 333.
127
- - ERROR: \\"dev.upstream_protocol\\" should be of type string but got 444."
128
- `);
113
+ "Processing wrangler configuration:
114
+ - Expected \\"legacy_env\\" to be of type boolean but got \\"FOO\\".
115
+ - Expected \\"dev.ip\\" to be of type string but got 222.
116
+ - Expected \\"dev.port\\" to be of type number but got \\"FOO\\".
117
+ - Expected \\"dev.local_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"wss\\".
118
+ - Expected \\"dev.upstream_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"ws\\"."
119
+ `);
129
120
  });
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,90 +209,162 @@ 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));
245
217
  expect(diagnostics.hasWarnings()).toBe(false);
246
218
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
219
+ "Processing wrangler configuration:
220
+ - Expected \\"migrations[0].tag\\" to be of type string but got 111.
221
+ - Expected \\"migrations[0].new_classes.[0]\\" to be of type string but got 222.
222
+ - Expected \\"migrations[0].new_classes.[1]\\" to be of type string but got 333.
223
+ - Expected \\"migrations[0].renamed_classes\\" to be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":444,\\"to\\":555}].
224
+ - Expected \\"migrations[0].deleted_classes.[0]\\" to be of type string but got 666.
225
+ - Expected \\"migrations[0].deleted_classes.[1]\\" to be of type string but got 777."
226
+ `);
227
+ });
228
+
229
+ describe("site", () => {
230
+ it("should override `site` config defaults with provided values", () => {
231
+ const expectedConfig: RawConfig = {
232
+ site: {
233
+ bucket: "BUCKET",
234
+ "entry-point": "my-site",
235
+ exclude: ["EXCLUDE_1", "EXCLUDE_2"],
236
+ include: ["INCLUDE_1", "INCLUDE_2"],
237
+ },
238
+ };
239
+
240
+ const { config, diagnostics } = normalizeAndValidateConfig(
241
+ expectedConfig,
242
+ undefined,
243
+ { env: undefined }
244
+ );
245
+
246
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
247
+ expect(diagnostics.hasErrors()).toBe(false);
248
+ expect(diagnostics.hasWarnings()).toBe(true);
249
+
250
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
251
+ .toMatchInlineSnapshot(`
247
252
  "Processing wrangler configuration:
248
- - ERROR: \\"migrations[0].tag\\" should be of type string but got 111.
249
- - ERROR: \\"migrations[0].new_classes.[0]\\" should be of type string but got 222.
250
- - ERROR: \\"migrations[0].new_classes.[1]\\" should be of type string but got 333.
251
- - \\"migrations[0].renamed_classes\\" should be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":444,\\"to\\":555}].
252
- - ERROR: \\"migrations[0].deleted_classes.[0]\\" should be of type string but got 666.
253
- - ERROR: \\"migrations[0].deleted_classes.[1]\\" should be of type string but got 777."
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
+ \`\`\`"
254
258
  `);
255
- });
259
+ });
256
260
 
257
- it("should override `site` config defaults with provided values", () => {
258
- const expectedConfig: RawConfig = {
259
- site: {
260
- bucket: "BUCKET",
261
- "entry-point": "ENTRY_POINT",
262
- include: ["INCLUDE_1", "INCLUDE_2"],
263
- exclude: ["EXCLUDE_1", "EXCLUDE_2"],
264
- },
265
- };
261
+ it("should error if `site` config is missing `bucket`", () => {
262
+ const expectedConfig: RawConfig = {
263
+ // @ts-expect-error we're intentionally passing an invalid configuration here
264
+ site: {
265
+ "entry-point": "workers-site",
266
+ include: ["INCLUDE_1", "INCLUDE_2"],
267
+ exclude: ["EXCLUDE_1", "EXCLUDE_2"],
268
+ },
269
+ };
266
270
 
267
- const { config, diagnostics } = normalizeAndValidateConfig(
268
- expectedConfig,
269
- undefined
270
- );
271
+ const { config, diagnostics } = normalizeAndValidateConfig(
272
+ expectedConfig,
273
+ undefined,
274
+ { env: undefined }
275
+ );
271
276
 
272
- expect(config).toEqual(expect.objectContaining(expectedConfig));
273
- expect(diagnostics.hasErrors()).toBe(false);
274
- expect(diagnostics.hasWarnings()).toBe(false);
275
- });
277
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
278
+ expect(diagnostics.hasWarnings()).toBe(true);
279
+ expect(diagnostics.hasErrors()).toBe(true);
276
280
 
277
- it("should error if `site` config is missing `bucket`", () => {
278
- const expectedConfig: RawConfig = {
279
- site: {
280
- "entry-point": "ENTRY_POINT",
281
- include: ["INCLUDE_1", "INCLUDE_2"],
282
- exclude: ["EXCLUDE_1", "EXCLUDE_2"],
283
- },
284
- } as RawConfig;
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
+ `);
285
290
 
286
- const { config, diagnostics } = normalizeAndValidateConfig(
287
- expectedConfig,
288
- undefined
289
- );
291
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
292
+ "Processing wrangler configuration:
293
+ - \\"site.bucket\\" is a required field."
294
+ `);
295
+ });
290
296
 
291
- expect(config).toEqual(expect.objectContaining(expectedConfig));
292
- expect(diagnostics.hasErrors()).toBe(true);
293
- expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
294
- "Processing wrangler configuration:
295
- - ERROR: \\"site.bucket\\" is a required field."
296
- `);
297
- expect(diagnostics.hasWarnings()).toBe(false);
298
- });
297
+ it("should error on invalid `site` values", () => {
298
+ const expectedConfig = {
299
+ site: {
300
+ bucket: "BUCKET",
301
+ "entry-point": 111,
302
+ include: [222, 333],
303
+ exclude: [444, 555],
304
+ },
305
+ };
299
306
 
300
- it("should error on invalid `site` values", () => {
301
- const expectedConfig = {
302
- site: {
303
- bucket: "BUCKET",
304
- "entry-point": 111,
305
- include: [222, 333],
306
- exclude: [444, 555],
307
- },
308
- };
307
+ const { config, diagnostics } = normalizeAndValidateConfig(
308
+ expectedConfig as unknown as RawConfig,
309
+ undefined,
310
+ { env: undefined }
311
+ );
309
312
 
310
- const { config, diagnostics } = normalizeAndValidateConfig(
311
- expectedConfig as unknown as RawConfig,
312
- undefined
313
- );
313
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
314
+ expect(diagnostics.hasWarnings()).toBe(true);
315
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
316
+ "Processing wrangler configuration:
317
+ - Expected \\"sites.include.[0]\\" to be of type string but got 222.
318
+ - Expected \\"sites.include.[1]\\" to be of type string but got 333.
319
+ - Expected \\"sites.exclude.[0]\\" to be of type string but got 444.
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
+ `);
314
323
 
315
- expect(config).toEqual(expect.objectContaining(expectedConfig));
316
- expect(diagnostics.hasWarnings()).toBe(false);
317
- expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
324
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
325
+ .toMatchInlineSnapshot(`
318
326
  "Processing wrangler configuration:
319
- - ERROR: \\"site.entry_point\\" should be of type string but got 111.
320
- - ERROR: \\"sites.include.[0]\\" should be of type string but got 222.
321
- - ERROR: \\"sites.include.[1]\\" should be of type string but got 333.
322
- - ERROR: \\"sites.exclude.[0]\\" should be of type string but got 444.
323
- - ERROR: \\"sites.exclude.[1]\\" should be of type string but got 555."
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
+ \`\`\`"
324
332
  `);
333
+ });
334
+
335
+ it("should log a deprecation warning if entry-point is defined", async () => {
336
+ const { config, diagnostics } = normalizeAndValidateConfig(
337
+ {
338
+ site: {
339
+ bucket: "some/path",
340
+ "entry-point": "some/other/script.js",
341
+ },
342
+ } as unknown as RawConfig,
343
+ undefined,
344
+ { env: undefined }
345
+ );
346
+
347
+ expect(config.site).toMatchInlineSnapshot(`
348
+ Object {
349
+ "bucket": "some/path",
350
+ "entry-point": "some/other/script.js",
351
+ "exclude": Array [],
352
+ "include": Array [],
353
+ }
354
+ `);
355
+ expect(diagnostics.hasWarnings()).toBe(true);
356
+ expect(diagnostics.hasErrors()).toBe(false);
357
+
358
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
359
+ .toMatchInlineSnapshot(`
360
+ "Processing wrangler configuration:
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
+ \`\`\`"
366
+ `);
367
+ });
325
368
  });
326
369
 
327
370
  it("should map `wasm_module` paths from relative to the config path to relative to the cwd", () => {
@@ -334,7 +377,8 @@ describe("normalizeAndValidateConfig()", () => {
334
377
 
335
378
  const { config, diagnostics } = normalizeAndValidateConfig(
336
379
  expectedConfig,
337
- "project/wrangler.toml"
380
+ "project/wrangler.toml",
381
+ { env: undefined }
338
382
  );
339
383
 
340
384
  expect(config).toEqual(
@@ -349,7 +393,7 @@ describe("normalizeAndValidateConfig()", () => {
349
393
  expect(diagnostics.hasWarnings()).toBe(false);
350
394
  });
351
395
 
352
- it("should error on invalid `wasm_module` paths", () => {
396
+ it("should error on invalid `wasm_modules` paths", () => {
353
397
  const expectedConfig = {
354
398
  wasm_modules: {
355
399
  MODULE_1: 111,
@@ -359,7 +403,8 @@ describe("normalizeAndValidateConfig()", () => {
359
403
 
360
404
  const { config, diagnostics } = normalizeAndValidateConfig(
361
405
  expectedConfig as unknown as RawConfig,
362
- "project/wrangler.toml"
406
+ "project/wrangler.toml",
407
+ { env: undefined }
363
408
  );
364
409
 
365
410
  expect(config).toEqual(
@@ -369,10 +414,10 @@ describe("normalizeAndValidateConfig()", () => {
369
414
  );
370
415
  expect(diagnostics.hasWarnings()).toBe(false);
371
416
  expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
372
- "Processing project/wrangler.toml configuration:
373
- - Expected \\"wasm_modules['MODULE_1']\\" field to be a string but got 111.
374
- - Expected \\"wasm_modules['MODULE_2']\\" field to be a string but got 222."
375
- `);
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
+ `);
376
421
  });
377
422
 
378
423
  it("should map `text_blobs` paths from relative to the config path to relative to the cwd", () => {
@@ -385,7 +430,8 @@ describe("normalizeAndValidateConfig()", () => {
385
430
 
386
431
  const { config, diagnostics } = normalizeAndValidateConfig(
387
432
  expectedConfig,
388
- "project/wrangler.toml"
433
+ "project/wrangler.toml",
434
+ { env: undefined }
389
435
  );
390
436
 
391
437
  expect(config).toEqual(
@@ -410,7 +456,8 @@ describe("normalizeAndValidateConfig()", () => {
410
456
 
411
457
  const { config, diagnostics } = normalizeAndValidateConfig(
412
458
  expectedConfig as unknown as RawConfig,
413
- "project/wrangler.toml"
459
+ "project/wrangler.toml",
460
+ { env: undefined }
414
461
  );
415
462
 
416
463
  expect(config).toEqual(
@@ -420,10 +467,84 @@ describe("normalizeAndValidateConfig()", () => {
420
467
  );
421
468
  expect(diagnostics.hasWarnings()).toBe(false);
422
469
  expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
423
- "Processing project/wrangler.toml configuration:
424
- - Expected \\"text_blobs['MODULE_1']\\" field to be a string but got 111.
425
- - Expected \\"text_blobs['MODULE_2']\\" field to be a string but got 222."
426
- `);
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);
427
548
  });
428
549
 
429
550
  describe("(deprecated)", () => {
@@ -435,7 +556,8 @@ describe("normalizeAndValidateConfig()", () => {
435
556
 
436
557
  const { config, diagnostics } = normalizeAndValidateConfig(
437
558
  rawConfig,
438
- undefined
559
+ undefined,
560
+ { env: undefined }
439
561
  );
440
562
 
441
563
  // Note the `.not.` here...
@@ -448,30 +570,44 @@ describe("normalizeAndValidateConfig()", () => {
448
570
  expect(diagnostics.hasErrors()).toBe(false);
449
571
  expect(diagnostics.hasWarnings()).toBe(true);
450
572
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
451
- "Processing wrangler configuration:
452
- - DEPRECATION: \\"type\\":
453
- 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.
454
- - DEPRECATION: \\"webpack_config\\":
455
- 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."
456
- `);
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
+ `);
457
579
  });
458
580
  });
459
581
  });
460
582
 
461
583
  describe("top-level environment configuration", () => {
462
584
  it("should override config defaults with provided values", () => {
463
- const expectedConfig: RawConfig = {
464
- 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",
465
590
  account_id: "ACCOUNT_ID",
466
591
  compatibility_date: "2022-01-01",
467
592
  compatibility_flags: ["FLAG1", "FLAG2"],
468
593
  workers_dev: false,
469
- routes: ["ROUTE_1", "ROUTE_2"],
470
- route: "ROUTE_3",
594
+ routes: [
595
+ "ROUTE_1",
596
+ "ROUTE_2",
597
+ { pattern: "ROUTE3", zone_id: "ZONE_ID_3" },
598
+ "ROUTE_4",
599
+ ],
471
600
  jsx_factory: "JSX_FACTORY",
472
601
  jsx_fragment: "JSX_FRAGMENT",
602
+ tsconfig: "path/to/tsconfig",
473
603
  triggers: { crons: ["CRON_1", "CRON_2"] },
474
604
  usage_model: "bundled",
605
+ main,
606
+ build: {
607
+ command: "COMMAND",
608
+ cwd: "CWD",
609
+ watch_dir: "WATCH_DIR",
610
+ },
475
611
  vars: {
476
612
  VAR1: "VALUE_1",
477
613
  VAR2: "VALUE_2",
@@ -516,10 +652,13 @@ describe("normalizeAndValidateConfig()", () => {
516
652
 
517
653
  const { config, diagnostics } = normalizeAndValidateConfig(
518
654
  expectedConfig,
519
- undefined
655
+ undefined,
656
+ { env: undefined }
520
657
  );
521
658
 
522
- expect(config).toEqual(expect.objectContaining(expectedConfig));
659
+ expect(config).toEqual(
660
+ expect.objectContaining({ ...expectedConfig, main: resolvedMain })
661
+ );
523
662
  expect(diagnostics.hasErrors()).toBe(false);
524
663
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
525
664
  "Processing wrangler configuration:
@@ -528,47 +667,283 @@ describe("normalizeAndValidateConfig()", () => {
528
667
  });
529
668
 
530
669
  it("should error on invalid environment values", () => {
531
- const expectedConfig: RawConfig = {
670
+ const expectedConfig: RawEnvironment = {
532
671
  name: 111,
533
672
  account_id: 222,
534
673
  compatibility_date: 333,
535
674
  compatibility_flags: [444, 555],
536
675
  workers_dev: "BAD",
537
- 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
+ ],
538
696
  route: 888,
539
697
  jsx_factory: 999,
540
698
  jsx_fragment: 1000,
699
+ tsconfig: true,
541
700
  triggers: { crons: [1111, 1222] },
542
701
  usage_model: "INVALID",
543
- } 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;
709
+
710
+ const { config, diagnostics } = normalizeAndValidateConfig(
711
+ expectedConfig,
712
+ undefined,
713
+ { env: undefined }
714
+ );
715
+
716
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
717
+ expect(diagnostics.hasWarnings()).toBe(false);
718
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
719
+ "Processing wrangler configuration:
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.
770
+ - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
771
+ `);
772
+ });
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;
544
832
 
545
833
  const { config, diagnostics } = normalizeAndValidateConfig(
546
834
  expectedConfig,
547
- undefined
835
+ undefined,
836
+ { env: undefined }
548
837
  );
549
838
 
550
839
  expect(config).toEqual(expect.objectContaining(expectedConfig));
551
840
  expect(diagnostics.hasWarnings()).toBe(false);
552
841
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
553
842
  "Processing wrangler configuration:
554
- - Expected \\"route\\" field to be a string but got 888.
555
- - Expected \\"routes\\" field to be an array of strings but got [666,777].
556
- - Expected \\"workers_dev\\" field to be a boolean but got \\"BAD\\".
557
- - Expected \\"account_id\\" field to be a string but got 222.
558
- - Expected \\"compatibility_date\\" field to be a string but got 333.
559
- - Expected \\"compatibility_flags\\" field to be an array of strings but got [444,555].
560
- - Expected \\"jsx_factory\\" field to be a string but got 999.
561
- - Expected \\"jsx_fragment\\" field to be a string but got 1000.
562
- - Expected \\"name\\" field to be a string but got 111.
563
- - Expected \\"usage_model\\" field to be on of bundled,unbound but got \\"INVALID\\"."
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
+ \`\`\`"
564
889
  `);
565
890
  });
566
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
+
567
941
  describe("durable_objects field", () => {
568
942
  it("should error if durable_objects is an array", () => {
569
943
  const { config, diagnostics } = normalizeAndValidateConfig(
570
944
  { durable_objects: [] } as unknown as RawConfig,
571
- undefined
945
+ undefined,
946
+ { env: undefined }
572
947
  );
573
948
 
574
949
  expect(config).toEqual(
@@ -584,7 +959,8 @@ describe("normalizeAndValidateConfig()", () => {
584
959
  it("should error if durable_objects is a string", () => {
585
960
  const { config, diagnostics } = normalizeAndValidateConfig(
586
961
  { durable_objects: "BAD" } as unknown as RawConfig,
587
- undefined
962
+ undefined,
963
+ { env: undefined }
588
964
  );
589
965
 
590
966
  expect(config).toEqual(
@@ -600,7 +976,8 @@ describe("normalizeAndValidateConfig()", () => {
600
976
  it("should error if durable_objects is a number", () => {
601
977
  const { config, diagnostics } = normalizeAndValidateConfig(
602
978
  { durable_objects: 999 } as unknown as RawConfig,
603
- undefined
979
+ undefined,
980
+ { env: undefined }
604
981
  );
605
982
 
606
983
  expect(config).toEqual(
@@ -616,7 +993,8 @@ describe("normalizeAndValidateConfig()", () => {
616
993
  it("should error if durable_objects is null", () => {
617
994
  const { config, diagnostics } = normalizeAndValidateConfig(
618
995
  { durable_objects: null } as unknown as RawConfig,
619
- undefined
996
+ undefined,
997
+ { env: undefined }
620
998
  );
621
999
 
622
1000
  expect(config).toEqual(
@@ -632,7 +1010,8 @@ describe("normalizeAndValidateConfig()", () => {
632
1010
  it("should error if durable_objects.bindings is not defined", () => {
633
1011
  const { config, diagnostics } = normalizeAndValidateConfig(
634
1012
  { durable_objects: {} } as unknown as RawConfig,
635
- undefined
1013
+ undefined,
1014
+ { env: undefined }
636
1015
  );
637
1016
 
638
1017
  expect(config).toEqual(
@@ -648,7 +1027,8 @@ describe("normalizeAndValidateConfig()", () => {
648
1027
  it("should error if durable_objects.bindings is an object", () => {
649
1028
  const { config, diagnostics } = normalizeAndValidateConfig(
650
1029
  { durable_objects: { bindings: {} } } as unknown as RawConfig,
651
- undefined
1030
+ undefined,
1031
+ { env: undefined }
652
1032
  );
653
1033
 
654
1034
  expect(config).toEqual(
@@ -666,7 +1046,8 @@ describe("normalizeAndValidateConfig()", () => {
666
1046
  it("should error if durable_objects.bindings is a string", () => {
667
1047
  const { config, diagnostics } = normalizeAndValidateConfig(
668
1048
  { durable_objects: { bindings: "BAD" } } as unknown as RawConfig,
669
- undefined
1049
+ undefined,
1050
+ { env: undefined }
670
1051
  );
671
1052
 
672
1053
  expect(config).toEqual(
@@ -684,7 +1065,8 @@ describe("normalizeAndValidateConfig()", () => {
684
1065
  it("should error if durable_objects.bindings is a number", () => {
685
1066
  const { config, diagnostics } = normalizeAndValidateConfig(
686
1067
  { durable_objects: { bindings: 999 } } as unknown as RawConfig,
687
- undefined
1068
+ undefined,
1069
+ { env: undefined }
688
1070
  );
689
1071
 
690
1072
  expect(config).toEqual(
@@ -702,7 +1084,8 @@ describe("normalizeAndValidateConfig()", () => {
702
1084
  it("should error if durable_objects.bindings is null", () => {
703
1085
  const { config, diagnostics } = normalizeAndValidateConfig(
704
1086
  { durable_objects: { bindings: null } } as unknown as RawConfig,
705
- undefined
1087
+ undefined,
1088
+ { env: undefined }
706
1089
  );
707
1090
 
708
1091
  expect(config).toEqual(
@@ -733,7 +1116,8 @@ describe("normalizeAndValidateConfig()", () => {
733
1116
  ],
734
1117
  },
735
1118
  } as unknown as RawConfig,
736
- undefined
1119
+ undefined,
1120
+ { env: undefined }
737
1121
  );
738
1122
 
739
1123
  expect(config).toEqual(
@@ -746,20 +1130,20 @@ describe("normalizeAndValidateConfig()", () => {
746
1130
  "Processing wrangler configuration:
747
1131
 
748
1132
  - \\"durable_objects.bindings[0]\\": {}
749
- - ERROR: bindings should have a string \\"name\\" field.
750
- - ERROR: should have a string \\"class_name\\" field.
1133
+ - binding should have a string \\"name\\" field.
1134
+ - binding should have a string \\"class_name\\" field.
751
1135
 
752
1136
  - \\"durable_objects.bindings[1]\\": {\\"name\\":\\"VALID\\"}
753
- - ERROR: should have a string \\"class_name\\" field.
1137
+ - binding should have a string \\"class_name\\" field.
754
1138
 
755
1139
  - \\"durable_objects.bindings[2]\\": {\\"name\\":1555,\\"class_name\\":1666}
756
- - ERROR: bindings should have a string \\"name\\" field.
757
- - ERROR: should have a string \\"class_name\\" field.
1140
+ - binding should have a string \\"name\\" field.
1141
+ - binding should have a string \\"class_name\\" field.
758
1142
 
759
1143
  - \\"durable_objects.bindings[3]\\": {\\"name\\":1777,\\"class_name\\":1888,\\"script_name\\":1999}
760
- - ERROR: bindings should have a string \\"name\\" field.
761
- - ERROR: should have a string \\"class_name\\" field.
762
- - ERROR: should, optionally, have a string \\"script_name\\" field."
1144
+ - binding should have a string \\"name\\" field.
1145
+ - binding should have a string \\"class_name\\" field.
1146
+ - binding should, optionally, have a string \\"script_name\\" field."
763
1147
  `);
764
1148
  });
765
1149
  });
@@ -768,7 +1152,8 @@ describe("normalizeAndValidateConfig()", () => {
768
1152
  it("should error if kv_namespaces is an object", () => {
769
1153
  const { config, diagnostics } = normalizeAndValidateConfig(
770
1154
  { kv_namespaces: {} } as unknown as RawConfig,
771
- undefined
1155
+ undefined,
1156
+ { env: undefined }
772
1157
  );
773
1158
 
774
1159
  expect(config).toEqual(
@@ -784,7 +1169,8 @@ describe("normalizeAndValidateConfig()", () => {
784
1169
  it("should error if kv_namespaces is a string", () => {
785
1170
  const { config, diagnostics } = normalizeAndValidateConfig(
786
1171
  { kv_namespaces: "BAD" } as unknown as RawConfig,
787
- undefined
1172
+ undefined,
1173
+ { env: undefined }
788
1174
  );
789
1175
 
790
1176
  expect(config).toEqual(
@@ -800,7 +1186,8 @@ describe("normalizeAndValidateConfig()", () => {
800
1186
  it("should error if kv_namespaces is a number", () => {
801
1187
  const { config, diagnostics } = normalizeAndValidateConfig(
802
1188
  { kv_namespaces: 999 } as unknown as RawConfig,
803
- undefined
1189
+ undefined,
1190
+ { env: undefined }
804
1191
  );
805
1192
 
806
1193
  expect(config).toEqual(
@@ -816,7 +1203,8 @@ describe("normalizeAndValidateConfig()", () => {
816
1203
  it("should error if kv_namespaces is null", () => {
817
1204
  const { config, diagnostics } = normalizeAndValidateConfig(
818
1205
  { kv_namespaces: null } as unknown as RawConfig,
819
- undefined
1206
+ undefined,
1207
+ { env: undefined }
820
1208
  );
821
1209
 
822
1210
  expect(config).toEqual(
@@ -843,7 +1231,8 @@ describe("normalizeAndValidateConfig()", () => {
843
1231
  },
844
1232
  ],
845
1233
  } as unknown as RawConfig,
846
- undefined
1234
+ undefined,
1235
+ { env: undefined }
847
1236
  );
848
1237
 
849
1238
  expect(config).toEqual(
@@ -868,7 +1257,8 @@ describe("normalizeAndValidateConfig()", () => {
868
1257
  it("should error if r2_buckets is an object", () => {
869
1258
  const { config, diagnostics } = normalizeAndValidateConfig(
870
1259
  { r2_buckets: {} } as unknown as RawConfig,
871
- undefined
1260
+ undefined,
1261
+ { env: undefined }
872
1262
  );
873
1263
 
874
1264
  expect(config).toEqual(
@@ -884,7 +1274,8 @@ describe("normalizeAndValidateConfig()", () => {
884
1274
  it("should error if r2_buckets is a string", () => {
885
1275
  const { config, diagnostics } = normalizeAndValidateConfig(
886
1276
  { r2_buckets: "BAD" } as unknown as RawConfig,
887
- undefined
1277
+ undefined,
1278
+ { env: undefined }
888
1279
  );
889
1280
 
890
1281
  expect(config).toEqual(
@@ -900,7 +1291,8 @@ describe("normalizeAndValidateConfig()", () => {
900
1291
  it("should error if r2_buckets is a number", () => {
901
1292
  const { config, diagnostics } = normalizeAndValidateConfig(
902
1293
  { r2_buckets: 999 } as unknown as RawConfig,
903
- undefined
1294
+ undefined,
1295
+ { env: undefined }
904
1296
  );
905
1297
 
906
1298
  expect(config).toEqual(
@@ -916,7 +1308,8 @@ describe("normalizeAndValidateConfig()", () => {
916
1308
  it("should error if r2_buckets is null", () => {
917
1309
  const { config, diagnostics } = normalizeAndValidateConfig(
918
1310
  { r2_buckets: null } as unknown as RawConfig,
919
- undefined
1311
+ undefined,
1312
+ { env: undefined }
920
1313
  );
921
1314
 
922
1315
  expect(config).toEqual(
@@ -943,7 +1336,8 @@ describe("normalizeAndValidateConfig()", () => {
943
1336
  },
944
1337
  ],
945
1338
  } as unknown as RawConfig,
946
- undefined
1339
+ undefined,
1340
+ { env: undefined }
947
1341
  );
948
1342
 
949
1343
  expect(config).toEqual(
@@ -968,7 +1362,8 @@ describe("normalizeAndValidateConfig()", () => {
968
1362
  it("should error if unsafe is an array", () => {
969
1363
  const { config, diagnostics } = normalizeAndValidateConfig(
970
1364
  { unsafe: [] } as unknown as RawConfig,
971
- undefined
1365
+ undefined,
1366
+ { env: undefined }
972
1367
  );
973
1368
 
974
1369
  expect(config).toEqual(
@@ -987,7 +1382,8 @@ describe("normalizeAndValidateConfig()", () => {
987
1382
  it("should error if unsafe is a string", () => {
988
1383
  const { config, diagnostics } = normalizeAndValidateConfig(
989
1384
  { unsafe: "BAD" } as unknown as RawConfig,
990
- undefined
1385
+ undefined,
1386
+ { env: undefined }
991
1387
  );
992
1388
 
993
1389
  expect(config).toEqual(
@@ -1006,7 +1402,8 @@ describe("normalizeAndValidateConfig()", () => {
1006
1402
  it("should error if unsafe is a number", () => {
1007
1403
  const { config, diagnostics } = normalizeAndValidateConfig(
1008
1404
  { unsafe: 999 } as unknown as RawConfig,
1009
- undefined
1405
+ undefined,
1406
+ { env: undefined }
1010
1407
  );
1011
1408
 
1012
1409
  expect(config).toEqual(
@@ -1025,7 +1422,8 @@ describe("normalizeAndValidateConfig()", () => {
1025
1422
  it("should error if unsafe is null", () => {
1026
1423
  const { config, diagnostics } = normalizeAndValidateConfig(
1027
1424
  { unsafe: null } as unknown as RawConfig,
1028
- undefined
1425
+ undefined,
1426
+ { env: undefined }
1029
1427
  );
1030
1428
 
1031
1429
  expect(config).toEqual(
@@ -1044,7 +1442,8 @@ describe("normalizeAndValidateConfig()", () => {
1044
1442
  it("should error if unsafe.bindings is not defined", () => {
1045
1443
  const { config, diagnostics } = normalizeAndValidateConfig(
1046
1444
  { unsafe: {} } as unknown as RawConfig,
1047
- undefined
1445
+ undefined,
1446
+ { env: undefined }
1048
1447
  );
1049
1448
 
1050
1449
  expect(config).toEqual(
@@ -1063,7 +1462,8 @@ describe("normalizeAndValidateConfig()", () => {
1063
1462
  it("should error if unsafe.bindings is an object", () => {
1064
1463
  const { config, diagnostics } = normalizeAndValidateConfig(
1065
1464
  { unsafe: { bindings: {} } } as unknown as RawConfig,
1066
- undefined
1465
+ undefined,
1466
+ { env: undefined }
1067
1467
  );
1068
1468
 
1069
1469
  expect(config).toEqual(
@@ -1084,7 +1484,8 @@ describe("normalizeAndValidateConfig()", () => {
1084
1484
  it("should error if unsafe.bindings is a string", () => {
1085
1485
  const { config, diagnostics } = normalizeAndValidateConfig(
1086
1486
  { unsafe: { bindings: "BAD" } } as unknown as RawConfig,
1087
- undefined
1487
+ undefined,
1488
+ { env: undefined }
1088
1489
  );
1089
1490
 
1090
1491
  expect(config).toEqual(
@@ -1105,7 +1506,8 @@ describe("normalizeAndValidateConfig()", () => {
1105
1506
  it("should error if unsafe.bindings is a number", () => {
1106
1507
  const { config, diagnostics } = normalizeAndValidateConfig(
1107
1508
  { unsafe: { bindings: 999 } } as unknown as RawConfig,
1108
- undefined
1509
+ undefined,
1510
+ { env: undefined }
1109
1511
  );
1110
1512
 
1111
1513
  expect(config).toEqual(
@@ -1126,7 +1528,8 @@ describe("normalizeAndValidateConfig()", () => {
1126
1528
  it("should error if unsafe.bindings is null", () => {
1127
1529
  const { config, diagnostics } = normalizeAndValidateConfig(
1128
1530
  { unsafe: { bindings: null } } as unknown as RawConfig,
1129
- undefined
1531
+ undefined,
1532
+ { env: undefined }
1130
1533
  );
1131
1534
 
1132
1535
  expect(config).toEqual(
@@ -1160,7 +1563,8 @@ describe("normalizeAndValidateConfig()", () => {
1160
1563
  ],
1161
1564
  },
1162
1565
  } as unknown as RawConfig,
1163
- undefined
1566
+ undefined,
1567
+ { env: undefined }
1164
1568
  );
1165
1569
 
1166
1570
  expect(config).toEqual(
@@ -1176,15 +1580,15 @@ describe("normalizeAndValidateConfig()", () => {
1176
1580
  "Processing wrangler configuration:
1177
1581
 
1178
1582
  - \\"unsafe.bindings[0]\\": {}
1179
- - ERROR: should have a string \\"name\\" field.
1180
- - ERROR: should have a string \\"type\\" field.
1583
+ - binding should have a string \\"name\\" field.
1584
+ - binding should have a string \\"type\\" field.
1181
1585
 
1182
1586
  - \\"unsafe.bindings[1]\\": {\\"name\\":\\"UNSAFE_BINDING_1\\"}
1183
- - ERROR: should have a string \\"type\\" field.
1587
+ - binding should have a string \\"type\\" field.
1184
1588
 
1185
1589
  - \\"unsafe.bindings[2]\\": {\\"name\\":2666,\\"type\\":2777}
1186
- - ERROR: should have a string \\"name\\" field.
1187
- - ERROR: should have a string \\"type\\" field."
1590
+ - binding should have a string \\"name\\" field.
1591
+ - binding should have a string \\"type\\" field."
1188
1592
  `);
1189
1593
  });
1190
1594
  });
@@ -1195,7 +1599,7 @@ describe("normalizeAndValidateConfig()", () => {
1195
1599
  zone_id: "ZONE_ID",
1196
1600
  experimental_services: [
1197
1601
  {
1198
- name: "NAME",
1602
+ name: "mock-name",
1199
1603
  service: "SERVICE",
1200
1604
  environment: "ENV",
1201
1605
  },
@@ -1204,7 +1608,8 @@ describe("normalizeAndValidateConfig()", () => {
1204
1608
 
1205
1609
  const { config, diagnostics } = normalizeAndValidateConfig(
1206
1610
  rawConfig,
1207
- undefined
1611
+ undefined,
1612
+ { env: undefined }
1208
1613
  );
1209
1614
 
1210
1615
  expect("experimental_services" in config).toBe(false);
@@ -1213,90 +1618,340 @@ describe("normalizeAndValidateConfig()", () => {
1213
1618
  expect(diagnostics.hasErrors()).toBe(false);
1214
1619
  expect(diagnostics.hasWarnings()).toBe(true);
1215
1620
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1216
- "Processing wrangler configuration:
1217
- - DEPRECATION: \\"zone_id\\":
1218
- This is unnecessary since we can deduce this from routes directly.
1219
- - DEPRECATION: \\"experimental_services\\":
1220
- The \\"experimental_services\\" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
1221
- \`\`\`
1222
- [[unsafe.bindings]]
1223
- name = \\"NAME\\"
1224
- type = \\"service\\"
1225
- service = \\"SERVICE\\"
1226
- environment = \\"ENV\\"
1227
- \`\`\`"
1228
- `);
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
+ `);
1229
1654
  });
1230
1655
  });
1231
1656
  });
1232
1657
 
1233
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",
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
+ `);
1702
+ });
1703
+
1234
1704
  it("should use top-level values for inheritable config fields", () => {
1235
- const expectedConfig: RawConfig = {
1236
- name: "NAME",
1705
+ const main = "src/index.ts";
1706
+ const resolvedMain = path.resolve(process.cwd(), main);
1707
+ const rawConfig: RawConfig = {
1708
+ name: "mock-name",
1237
1709
  account_id: "ACCOUNT_ID",
1238
1710
  compatibility_date: "2022-01-01",
1239
1711
  compatibility_flags: ["FLAG1", "FLAG2"],
1240
1712
  workers_dev: false,
1241
1713
  routes: ["ROUTE_1", "ROUTE_2"],
1242
- route: "ROUTE_3",
1243
1714
  jsx_factory: "JSX_FACTORY",
1244
1715
  jsx_fragment: "JSX_FRAGMENT",
1716
+ tsconfig: "path/to/tsconfig.json",
1245
1717
  triggers: { crons: ["CRON_1", "CRON_2"] },
1246
1718
  usage_model: "bundled",
1719
+ main,
1720
+ build: {
1721
+ command: "COMMAND",
1722
+ cwd: "CWD",
1723
+ watch_dir: "WATCH_DIR",
1724
+ },
1247
1725
  };
1248
1726
 
1249
1727
  const { config, diagnostics } = normalizeAndValidateConfig(
1250
- { ...expectedConfig, env: { DEV: {} } },
1251
- undefined
1728
+ { ...rawConfig, env: { dev: {} } },
1729
+ undefined,
1730
+ { env: "dev" }
1252
1731
  );
1253
1732
 
1254
- 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
+ );
1255
1740
  expect(diagnostics.hasErrors()).toBe(false);
1256
1741
  expect(diagnostics.hasWarnings()).toBe(false);
1257
1742
  });
1258
1743
 
1259
1744
  it("should override top-level values for inheritable config fields", () => {
1260
- const environment: RawEnvironment = {
1261
- 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",
1262
1749
  account_id: "ENV_ACCOUNT_ID",
1263
1750
  compatibility_date: "2022-02-02",
1264
1751
  compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
1265
1752
  workers_dev: true,
1266
1753
  routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
1267
- route: "ENV_ROUTE_3",
1268
1754
  jsx_factory: "ENV_JSX_FACTORY",
1269
1755
  jsx_fragment: "ENV_JSX_FRAGMENT",
1756
+ tsconfig: "ENV_path/to/tsconfig.json",
1270
1757
  triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
1271
1758
  usage_model: "unbound",
1759
+ main,
1760
+ build: {
1761
+ command: "ENV_COMMAND",
1762
+ cwd: "ENV_CWD",
1763
+ watch_dir: "ENV_WATCH_DIR",
1764
+ },
1272
1765
  };
1273
- const expectedConfig: RawConfig = {
1274
- name: "NAME",
1766
+ const rawConfig: RawConfig = {
1767
+ name: "mock-name",
1275
1768
  account_id: "ACCOUNT_ID",
1276
1769
  compatibility_date: "2022-01-01",
1277
1770
  compatibility_flags: ["FLAG1", "FLAG2"],
1278
1771
  workers_dev: false,
1279
1772
  routes: ["ROUTE_1", "ROUTE_2"],
1280
- route: "ROUTE_3",
1281
1773
  jsx_factory: "JSX_FACTORY",
1282
1774
  jsx_fragment: "JSX_FRAGMENT",
1775
+ tsconfig: "path/to/tsconfig.json",
1283
1776
  triggers: { crons: ["CRON_1", "CRON_2"] },
1284
1777
  usage_model: "bundled",
1778
+ main: "top-level.js",
1779
+ build: {
1780
+ command: "COMMAND",
1781
+ cwd: "CWD",
1782
+ watch_dir: "WATCH_DIR",
1783
+ },
1285
1784
  env: {
1286
- ENV1: environment,
1785
+ ENV1: rawEnv,
1287
1786
  },
1288
1787
  };
1289
1788
 
1290
1789
  const { config, diagnostics } = normalizeAndValidateConfig(
1291
- expectedConfig,
1292
- undefined
1790
+ rawConfig,
1791
+ undefined,
1792
+ { env: "ENV1" }
1293
1793
  );
1294
1794
 
1295
- expect(config.env.ENV1).toEqual(expect.objectContaining(environment));
1795
+ expect(config).toEqual(
1796
+ expect.objectContaining({ ...rawEnv, main: resolvedMain })
1797
+ );
1296
1798
  expect(diagnostics.hasErrors()).toBe(false);
1297
1799
  expect(diagnostics.hasWarnings()).toBe(false);
1298
1800
  });
1299
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
+
1300
1955
  it("should warn for non-inherited fields that are missing in environments", () => {
1301
1956
  const vars: RawConfig["vars"] = {
1302
1957
  FOO: "foo",
@@ -1320,10 +1975,11 @@ describe("normalizeAndValidateConfig()", () => {
1320
1975
 
1321
1976
  const { config, diagnostics } = normalizeAndValidateConfig(
1322
1977
  rawConfig,
1323
- undefined
1978
+ undefined,
1979
+ { env: "ENV1" }
1324
1980
  );
1325
1981
 
1326
- expect(config.env.ENV1).toEqual(
1982
+ expect(config).toEqual(
1327
1983
  expect.not.objectContaining({
1328
1984
  vars,
1329
1985
  durable_objects,
@@ -1366,31 +2022,48 @@ describe("normalizeAndValidateConfig()", () => {
1366
2022
  route: 888,
1367
2023
  jsx_factory: 999,
1368
2024
  jsx_fragment: 1000,
2025
+ tsconfig: 123,
1369
2026
  triggers: { crons: [1111, 1222] },
1370
2027
  usage_model: "INVALID",
2028
+ main: 1333,
2029
+ build: {
2030
+ command: 1444,
2031
+ cwd: 1555,
2032
+ watch_dir: 1666,
2033
+ },
1371
2034
  } as unknown as RawEnvironment;
1372
2035
 
1373
2036
  const { config, diagnostics } = normalizeAndValidateConfig(
1374
2037
  { env: { ENV1: expectedConfig } },
1375
- undefined
2038
+ undefined,
2039
+ { env: "ENV1" }
1376
2040
  );
1377
2041
 
1378
- expect(config.env.ENV1).toEqual(expect.objectContaining(expectedConfig));
2042
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
1379
2043
  expect(diagnostics.hasWarnings()).toBe(false);
1380
2044
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1381
2045
  "Processing wrangler configuration:
1382
2046
 
1383
2047
  - \\"env.ENV1\\" environment configuration
1384
- - Expected \\"route\\" field to be a string but got 888.
1385
- - Expected \\"routes\\" field to be an array of strings but got [666,777].
1386
- - Expected \\"workers_dev\\" field to be a boolean but got \\"BAD\\".
1387
- - Expected \\"account_id\\" field to be a string but got 222.
1388
- - Expected \\"compatibility_date\\" field to be a string but got 333.
1389
- - Expected \\"compatibility_flags\\" field to be an array of strings but got [444,555].
1390
- - Expected \\"jsx_factory\\" field to be a string but got 999.
1391
- - Expected \\"jsx_fragment\\" field to be a string but got 1000.
1392
- - Expected \\"name\\" field to be a string but got 111.
1393
- - Expected \\"usage_model\\" field to be on of bundled,unbound but got \\"INVALID\\"."
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.
2066
+ - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
1394
2067
  `);
1395
2068
  });
1396
2069
 
@@ -1398,10 +2071,11 @@ describe("normalizeAndValidateConfig()", () => {
1398
2071
  it("should error if durable_objects is an array", () => {
1399
2072
  const { config, diagnostics } = normalizeAndValidateConfig(
1400
2073
  { env: { ENV1: { durable_objects: [] } } } as unknown as RawConfig,
1401
- undefined
2074
+ undefined,
2075
+ { env: "ENV1" }
1402
2076
  );
1403
2077
 
1404
- expect(config.env.ENV1).toEqual(
2078
+ expect(config).toEqual(
1405
2079
  expect.not.objectContaining({ durable_objects: expect.anything })
1406
2080
  );
1407
2081
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1416,10 +2090,11 @@ describe("normalizeAndValidateConfig()", () => {
1416
2090
  it("should error if durable_objects is a string", () => {
1417
2091
  const { config, diagnostics } = normalizeAndValidateConfig(
1418
2092
  { env: { ENV1: { durable_objects: "BAD" } } } as unknown as RawConfig,
1419
- undefined
2093
+ undefined,
2094
+ { env: "ENV1" }
1420
2095
  );
1421
2096
 
1422
- expect(config.env.ENV1).toEqual(
2097
+ expect(config).toEqual(
1423
2098
  expect.not.objectContaining({ durable_objects: expect.anything })
1424
2099
  );
1425
2100
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1434,10 +2109,11 @@ describe("normalizeAndValidateConfig()", () => {
1434
2109
  it("should error if durable_objects is a number", () => {
1435
2110
  const { config, diagnostics } = normalizeAndValidateConfig(
1436
2111
  { env: { ENV1: { durable_objects: 999 } } } as unknown as RawConfig,
1437
- undefined
2112
+ undefined,
2113
+ { env: "ENV1" }
1438
2114
  );
1439
2115
 
1440
- expect(config.env.ENV1).toEqual(
2116
+ expect(config).toEqual(
1441
2117
  expect.not.objectContaining({ durable_objects: expect.anything })
1442
2118
  );
1443
2119
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1452,10 +2128,11 @@ describe("normalizeAndValidateConfig()", () => {
1452
2128
  it("should error if durable_objects is null", () => {
1453
2129
  const { config, diagnostics } = normalizeAndValidateConfig(
1454
2130
  { env: { ENV1: { durable_objects: null } } } as unknown as RawConfig,
1455
- undefined
2131
+ undefined,
2132
+ { env: "ENV1" }
1456
2133
  );
1457
2134
 
1458
- expect(config.env.ENV1).toEqual(
2135
+ expect(config).toEqual(
1459
2136
  expect.not.objectContaining({ durable_objects: expect.anything })
1460
2137
  );
1461
2138
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1470,10 +2147,11 @@ describe("normalizeAndValidateConfig()", () => {
1470
2147
  it("should error if durable_objects.bindings is not defined", () => {
1471
2148
  const { config, diagnostics } = normalizeAndValidateConfig(
1472
2149
  { env: { ENV1: { durable_objects: {} } } } as unknown as RawConfig,
1473
- undefined
2150
+ undefined,
2151
+ { env: "ENV1" }
1474
2152
  );
1475
2153
 
1476
- expect(config.env.ENV1).toEqual(
2154
+ expect(config).toEqual(
1477
2155
  expect.not.objectContaining({ durable_objects: expect.anything })
1478
2156
  );
1479
2157
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1490,10 +2168,11 @@ describe("normalizeAndValidateConfig()", () => {
1490
2168
  {
1491
2169
  env: { ENV1: { durable_objects: { bindings: {} } } },
1492
2170
  } as unknown as RawConfig,
1493
- undefined
2171
+ undefined,
2172
+ { env: "ENV1" }
1494
2173
  );
1495
2174
 
1496
- expect(config.env.ENV1).toEqual(
2175
+ expect(config).toEqual(
1497
2176
  expect.not.objectContaining({
1498
2177
  durable_objects: { bindings: expect.anything },
1499
2178
  })
@@ -1512,10 +2191,11 @@ describe("normalizeAndValidateConfig()", () => {
1512
2191
  {
1513
2192
  env: { ENV1: { durable_objects: { bindings: "BAD" } } },
1514
2193
  } as unknown as RawConfig,
1515
- undefined
2194
+ undefined,
2195
+ { env: "ENV1" }
1516
2196
  );
1517
2197
 
1518
- expect(config.env.ENV1).toEqual(
2198
+ expect(config).toEqual(
1519
2199
  expect.not.objectContaining({
1520
2200
  durable_objects: { bindings: expect.anything },
1521
2201
  })
@@ -1534,10 +2214,11 @@ describe("normalizeAndValidateConfig()", () => {
1534
2214
  {
1535
2215
  env: { ENV1: { durable_objects: { bindings: 999 } } },
1536
2216
  } as unknown as RawConfig,
1537
- undefined
2217
+ undefined,
2218
+ { env: "ENV1" }
1538
2219
  );
1539
2220
 
1540
- expect(config.env.ENV1).toEqual(
2221
+ expect(config).toEqual(
1541
2222
  expect.not.objectContaining({
1542
2223
  durable_objects: { bindings: expect.anything },
1543
2224
  })
@@ -1556,10 +2237,11 @@ describe("normalizeAndValidateConfig()", () => {
1556
2237
  {
1557
2238
  env: { ENV1: { durable_objects: { bindings: null } } },
1558
2239
  } as unknown as RawConfig,
1559
- undefined
2240
+ undefined,
2241
+ { env: "ENV1" }
1560
2242
  );
1561
2243
 
1562
- expect(config.env.ENV1).toEqual(
2244
+ expect(config).toEqual(
1563
2245
  expect.not.objectContaining({
1564
2246
  durable_objects: { bindings: expect.anything },
1565
2247
  })
@@ -1593,10 +2275,11 @@ describe("normalizeAndValidateConfig()", () => {
1593
2275
  },
1594
2276
  },
1595
2277
  } as unknown as RawConfig,
1596
- undefined
2278
+ undefined,
2279
+ { env: "ENV1" }
1597
2280
  );
1598
2281
 
1599
- expect(config.env.ENV1).toEqual(
2282
+ expect(config).toEqual(
1600
2283
  expect.not.objectContaining({
1601
2284
  durable_objects: { bindings: expect.anything },
1602
2285
  })
@@ -1608,20 +2291,20 @@ describe("normalizeAndValidateConfig()", () => {
1608
2291
  - \\"env.ENV1\\" environment configuration
1609
2292
 
1610
2293
  - \\"env.ENV1.durable_objects.bindings[0]\\": {}
1611
- - ERROR: bindings should have a string \\"name\\" field.
1612
- - ERROR: should have a string \\"class_name\\" field.
2294
+ - binding should have a string \\"name\\" field.
2295
+ - binding should have a string \\"class_name\\" field.
1613
2296
 
1614
2297
  - \\"env.ENV1.durable_objects.bindings[1]\\": {\\"name\\":\\"VALID\\"}
1615
- - ERROR: should have a string \\"class_name\\" field.
2298
+ - binding should have a string \\"class_name\\" field.
1616
2299
 
1617
2300
  - \\"env.ENV1.durable_objects.bindings[2]\\": {\\"name\\":1555,\\"class_name\\":1666}
1618
- - ERROR: bindings should have a string \\"name\\" field.
1619
- - ERROR: should have a string \\"class_name\\" field.
2301
+ - binding should have a string \\"name\\" field.
2302
+ - binding should have a string \\"class_name\\" field.
1620
2303
 
1621
2304
  - \\"env.ENV1.durable_objects.bindings[3]\\": {\\"name\\":1777,\\"class_name\\":1888,\\"script_name\\":1999}
1622
- - ERROR: bindings should have a string \\"name\\" field.
1623
- - ERROR: should have a string \\"class_name\\" field.
1624
- - ERROR: should, optionally, have a string \\"script_name\\" field."
2305
+ - binding should have a string \\"name\\" field.
2306
+ - binding should have a string \\"class_name\\" field.
2307
+ - binding should, optionally, have a string \\"script_name\\" field."
1625
2308
  `);
1626
2309
  });
1627
2310
  });
@@ -1630,10 +2313,11 @@ describe("normalizeAndValidateConfig()", () => {
1630
2313
  it("should error if kv_namespaces is an object", () => {
1631
2314
  const { config, diagnostics } = normalizeAndValidateConfig(
1632
2315
  { env: { ENV1: { kv_namespaces: {} } } } as unknown as RawConfig,
1633
- undefined
2316
+ undefined,
2317
+ { env: "ENV1" }
1634
2318
  );
1635
2319
 
1636
- expect(config.env.ENV1).toEqual(
2320
+ expect(config).toEqual(
1637
2321
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1638
2322
  );
1639
2323
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1648,10 +2332,11 @@ describe("normalizeAndValidateConfig()", () => {
1648
2332
  it("should error if kv_namespaces is a string", () => {
1649
2333
  const { config, diagnostics } = normalizeAndValidateConfig(
1650
2334
  { env: { ENV1: { kv_namespaces: "BAD" } } } as unknown as RawConfig,
1651
- undefined
2335
+ undefined,
2336
+ { env: "ENV1" }
1652
2337
  );
1653
2338
 
1654
- expect(config.env.ENV1).toEqual(
2339
+ expect(config).toEqual(
1655
2340
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1656
2341
  );
1657
2342
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1666,10 +2351,11 @@ describe("normalizeAndValidateConfig()", () => {
1666
2351
  it("should error if kv_namespaces is a number", () => {
1667
2352
  const { config, diagnostics } = normalizeAndValidateConfig(
1668
2353
  { env: { ENV1: { kv_namespaces: 999 } } } as unknown as RawConfig,
1669
- undefined
2354
+ undefined,
2355
+ { env: "ENV1" }
1670
2356
  );
1671
2357
 
1672
- expect(config.env.ENV1).toEqual(
2358
+ expect(config).toEqual(
1673
2359
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1674
2360
  );
1675
2361
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1684,10 +2370,11 @@ describe("normalizeAndValidateConfig()", () => {
1684
2370
  it("should error if kv_namespaces is null", () => {
1685
2371
  const { config, diagnostics } = normalizeAndValidateConfig(
1686
2372
  { env: { ENV1: { kv_namespaces: null } } } as unknown as RawConfig,
1687
- undefined
2373
+ undefined,
2374
+ { env: "ENV1" }
1688
2375
  );
1689
2376
 
1690
- expect(config.env.ENV1).toEqual(
2377
+ expect(config).toEqual(
1691
2378
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1692
2379
  );
1693
2380
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1717,10 +2404,11 @@ describe("normalizeAndValidateConfig()", () => {
1717
2404
  },
1718
2405
  },
1719
2406
  } as unknown as RawConfig,
1720
- undefined
2407
+ undefined,
2408
+ { env: "ENV1" }
1721
2409
  );
1722
2410
 
1723
- expect(config.env.ENV1).toEqual(
2411
+ expect(config).toEqual(
1724
2412
  expect.not.objectContaining({
1725
2413
  kv_namespaces: { bindings: expect.anything },
1726
2414
  })
@@ -1744,10 +2432,11 @@ describe("normalizeAndValidateConfig()", () => {
1744
2432
  it("should error if r2_buckets is an object", () => {
1745
2433
  const { config, diagnostics } = normalizeAndValidateConfig(
1746
2434
  { env: { ENV1: { r2_buckets: {} } } } as unknown as RawConfig,
1747
- undefined
2435
+ undefined,
2436
+ { env: "ENV1" }
1748
2437
  );
1749
2438
 
1750
- expect(config.env.ENV1).toEqual(
2439
+ expect(config).toEqual(
1751
2440
  expect.not.objectContaining({ r2_buckets: expect.anything })
1752
2441
  );
1753
2442
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1762,10 +2451,11 @@ describe("normalizeAndValidateConfig()", () => {
1762
2451
  it("should error if r2_buckets is a string", () => {
1763
2452
  const { config, diagnostics } = normalizeAndValidateConfig(
1764
2453
  { env: { ENV1: { r2_buckets: "BAD" } } } as unknown as RawConfig,
1765
- undefined
2454
+ undefined,
2455
+ { env: "ENV1" }
1766
2456
  );
1767
2457
 
1768
- expect(config.env.ENV1).toEqual(
2458
+ expect(config).toEqual(
1769
2459
  expect.not.objectContaining({ r2_buckets: expect.anything })
1770
2460
  );
1771
2461
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1780,10 +2470,11 @@ describe("normalizeAndValidateConfig()", () => {
1780
2470
  it("should error if r2_buckets is a number", () => {
1781
2471
  const { config, diagnostics } = normalizeAndValidateConfig(
1782
2472
  { env: { ENV1: { r2_buckets: 999 } } } as unknown as RawConfig,
1783
- undefined
2473
+ undefined,
2474
+ { env: "ENV1" }
1784
2475
  );
1785
2476
 
1786
- expect(config.env.ENV1).toEqual(
2477
+ expect(config).toEqual(
1787
2478
  expect.not.objectContaining({ r2_buckets: expect.anything })
1788
2479
  );
1789
2480
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1798,10 +2489,11 @@ describe("normalizeAndValidateConfig()", () => {
1798
2489
  it("should error if r2_buckets is null", () => {
1799
2490
  const { config, diagnostics } = normalizeAndValidateConfig(
1800
2491
  { env: { ENV1: { r2_buckets: null } } } as unknown as RawConfig,
1801
- undefined
2492
+ undefined,
2493
+ { env: "ENV1" }
1802
2494
  );
1803
2495
 
1804
- expect(config.env.ENV1).toEqual(
2496
+ expect(config).toEqual(
1805
2497
  expect.not.objectContaining({ r2_buckets: expect.anything })
1806
2498
  );
1807
2499
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1831,10 +2523,11 @@ describe("normalizeAndValidateConfig()", () => {
1831
2523
  },
1832
2524
  },
1833
2525
  } as unknown as RawConfig,
1834
- undefined
2526
+ undefined,
2527
+ { env: "ENV1" }
1835
2528
  );
1836
2529
 
1837
- expect(config.env.ENV1).toEqual(
2530
+ expect(config).toEqual(
1838
2531
  expect.not.objectContaining({
1839
2532
  r2_buckets: { bindings: expect.anything },
1840
2533
  })
@@ -1858,10 +2551,11 @@ describe("normalizeAndValidateConfig()", () => {
1858
2551
  it("should error if unsafe is an array", () => {
1859
2552
  const { config, diagnostics } = normalizeAndValidateConfig(
1860
2553
  { env: { ENV1: { unsafe: [] } } } as unknown as RawConfig,
1861
- undefined
2554
+ undefined,
2555
+ { env: "ENV1" }
1862
2556
  );
1863
2557
 
1864
- expect(config.env.ENV1).toEqual(
2558
+ expect(config).toEqual(
1865
2559
  expect.not.objectContaining({ unsafe: expect.anything })
1866
2560
  );
1867
2561
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1881,10 +2575,11 @@ describe("normalizeAndValidateConfig()", () => {
1881
2575
  it("should error if unsafe is a string", () => {
1882
2576
  const { config, diagnostics } = normalizeAndValidateConfig(
1883
2577
  { env: { ENV1: { unsafe: "BAD" } } } as unknown as RawConfig,
1884
- undefined
2578
+ undefined,
2579
+ { env: "ENV1" }
1885
2580
  );
1886
2581
 
1887
- expect(config.env.ENV1).toEqual(
2582
+ expect(config).toEqual(
1888
2583
  expect.not.objectContaining({ unsafe: expect.anything })
1889
2584
  );
1890
2585
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1904,10 +2599,11 @@ describe("normalizeAndValidateConfig()", () => {
1904
2599
  it("should error if unsafe is a number", () => {
1905
2600
  const { config, diagnostics } = normalizeAndValidateConfig(
1906
2601
  { env: { ENV1: { unsafe: 999 } } } as unknown as RawConfig,
1907
- undefined
2602
+ undefined,
2603
+ { env: "ENV1" }
1908
2604
  );
1909
2605
 
1910
- expect(config.env.ENV1).toEqual(
2606
+ expect(config).toEqual(
1911
2607
  expect.not.objectContaining({ unsafe: expect.anything })
1912
2608
  );
1913
2609
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1927,10 +2623,11 @@ describe("normalizeAndValidateConfig()", () => {
1927
2623
  it("should error if unsafe is null", () => {
1928
2624
  const { config, diagnostics } = normalizeAndValidateConfig(
1929
2625
  { env: { ENV1: { unsafe: null } } } as unknown as RawConfig,
1930
- undefined
2626
+ undefined,
2627
+ { env: "ENV1" }
1931
2628
  );
1932
2629
 
1933
- expect(config.env.ENV1).toEqual(
2630
+ expect(config).toEqual(
1934
2631
  expect.not.objectContaining({ unsafe: expect.anything })
1935
2632
  );
1936
2633
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1950,10 +2647,11 @@ describe("normalizeAndValidateConfig()", () => {
1950
2647
  it("should error if unsafe.bindings is not defined", () => {
1951
2648
  const { config, diagnostics } = normalizeAndValidateConfig(
1952
2649
  { env: { ENV1: { unsafe: {} } } } as unknown as RawConfig,
1953
- undefined
2650
+ undefined,
2651
+ { env: "ENV1" }
1954
2652
  );
1955
2653
 
1956
- expect(config.env.ENV1).toEqual(
2654
+ expect(config).toEqual(
1957
2655
  expect.not.objectContaining({ unsafe: expect.anything })
1958
2656
  );
1959
2657
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1975,10 +2673,11 @@ describe("normalizeAndValidateConfig()", () => {
1975
2673
  {
1976
2674
  env: { ENV1: { unsafe: { bindings: {} } } },
1977
2675
  } as unknown as RawConfig,
1978
- undefined
2676
+ undefined,
2677
+ { env: "ENV1" }
1979
2678
  );
1980
2679
 
1981
- expect(config.env.ENV1).toEqual(
2680
+ expect(config).toEqual(
1982
2681
  expect.not.objectContaining({
1983
2682
  unsafe: { bindings: expect.anything },
1984
2683
  })
@@ -2002,10 +2701,11 @@ describe("normalizeAndValidateConfig()", () => {
2002
2701
  {
2003
2702
  env: { ENV1: { unsafe: { bindings: "BAD" } } },
2004
2703
  } as unknown as RawConfig,
2005
- undefined
2704
+ undefined,
2705
+ { env: "ENV1" }
2006
2706
  );
2007
2707
 
2008
- expect(config.env.ENV1).toEqual(
2708
+ expect(config).toEqual(
2009
2709
  expect.not.objectContaining({
2010
2710
  unsafe: { bindings: expect.anything },
2011
2711
  })
@@ -2029,10 +2729,11 @@ describe("normalizeAndValidateConfig()", () => {
2029
2729
  {
2030
2730
  env: { ENV1: { unsafe: { bindings: 999 } } },
2031
2731
  } as unknown as RawConfig,
2032
- undefined
2732
+ undefined,
2733
+ { env: "ENV1" }
2033
2734
  );
2034
2735
 
2035
- expect(config.env.ENV1).toEqual(
2736
+ expect(config).toEqual(
2036
2737
  expect.not.objectContaining({
2037
2738
  unsafe: { bindings: expect.anything },
2038
2739
  })
@@ -2056,10 +2757,11 @@ describe("normalizeAndValidateConfig()", () => {
2056
2757
  {
2057
2758
  env: { ENV1: { unsafe: { bindings: null } } },
2058
2759
  } as unknown as RawConfig,
2059
- undefined
2760
+ undefined,
2761
+ { env: "ENV1" }
2060
2762
  );
2061
2763
 
2062
- expect(config.env.ENV1).toEqual(
2764
+ expect(config).toEqual(
2063
2765
  expect.not.objectContaining({
2064
2766
  unsafe: { bindings: expect.anything },
2065
2767
  })
@@ -2098,10 +2800,11 @@ describe("normalizeAndValidateConfig()", () => {
2098
2800
  },
2099
2801
  },
2100
2802
  } as unknown as RawConfig,
2101
- undefined
2803
+ undefined,
2804
+ { env: "ENV1" }
2102
2805
  );
2103
2806
 
2104
- expect(config.env.ENV1).toEqual(
2807
+ expect(config).toEqual(
2105
2808
  expect.not.objectContaining({
2106
2809
  durable_objects: { bindings: expect.anything },
2107
2810
  })
@@ -2118,15 +2821,15 @@ describe("normalizeAndValidateConfig()", () => {
2118
2821
  - \\"env.ENV1\\" environment configuration
2119
2822
 
2120
2823
  - \\"env.ENV1.unsafe.bindings[0]\\": {}
2121
- - ERROR: should have a string \\"name\\" field.
2122
- - ERROR: should have a string \\"type\\" field.
2824
+ - binding should have a string \\"name\\" field.
2825
+ - binding should have a string \\"type\\" field.
2123
2826
 
2124
2827
  - \\"env.ENV1.unsafe.bindings[1]\\": {\\"name\\":\\"UNSAFE_BINDING_1\\"}
2125
- - ERROR: should have a string \\"type\\" field.
2828
+ - binding should have a string \\"type\\" field.
2126
2829
 
2127
2830
  - \\"env.ENV1.unsafe.bindings[2]\\": {\\"name\\":2666,\\"type\\":2777}
2128
- - ERROR: should have a string \\"name\\" field.
2129
- - ERROR: should have a string \\"type\\" field."
2831
+ - binding should have a string \\"name\\" field.
2832
+ - binding should have a string \\"type\\" field."
2130
2833
  `);
2131
2834
  });
2132
2835
  });
@@ -2137,7 +2840,7 @@ describe("normalizeAndValidateConfig()", () => {
2137
2840
  zone_id: "ZONE_ID",
2138
2841
  experimental_services: [
2139
2842
  {
2140
- name: "NAME",
2843
+ name: "mock-name",
2141
2844
  service: "SERVICE",
2142
2845
  environment: "ENV",
2143
2846
  },
@@ -2150,25 +2853,26 @@ describe("normalizeAndValidateConfig()", () => {
2150
2853
  ENV1: environment,
2151
2854
  },
2152
2855
  },
2153
- undefined
2856
+ undefined,
2857
+ { env: "ENV1" }
2154
2858
  );
2155
2859
 
2156
- expect("experimental_services" in config.env.ENV1).toBe(false);
2860
+ expect("experimental_services" in config).toBe(false);
2157
2861
  // Zone is not removed yet, since `route` commands might use it
2158
- expect(config.env.ENV1.zone_id).toEqual("ZONE_ID");
2862
+ expect(config.zone_id).toEqual("ZONE_ID");
2159
2863
  expect(diagnostics.hasErrors()).toBe(false);
2160
2864
  expect(diagnostics.hasWarnings()).toBe(true);
2161
2865
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2162
2866
  "Processing wrangler configuration:
2163
2867
 
2164
2868
  - \\"env.ENV1\\" environment configuration
2165
- - DEPRECATION: \\"zone_id\\":
2869
+ - Deprecation: \\"zone_id\\":
2166
2870
  This is unnecessary since we can deduce this from routes directly.
2167
- - DEPRECATION: \\"experimental_services\\":
2871
+ - Deprecation: \\"experimental_services\\":
2168
2872
  The \\"experimental_services\\" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
2169
2873
  \`\`\`
2170
2874
  [[unsafe.bindings]]
2171
- name = \\"NAME\\"
2875
+ name = \\"mock-name\\"
2172
2876
  type = \\"service\\"
2173
2877
  service = \\"SERVICE\\"
2174
2878
  environment = \\"ENV\\"
@@ -2176,6 +2880,241 @@ describe("normalizeAndValidateConfig()", () => {
2176
2880
  `);
2177
2881
  });
2178
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
+ });
2179
3118
  });
2180
3119
  });
2181
3120