wrangler 0.0.0-e3cab74 → 0.0.0-e452a35

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 (102) hide show
  1. package/Cloudflare_CA.pem +18 -0
  2. package/README.md +27 -14
  3. package/bin/wrangler.js +49 -5
  4. package/miniflare-dist/index.mjs +4886 -0
  5. package/package.json +42 -28
  6. package/pages/functions/buildPlugin.ts +105 -0
  7. package/pages/functions/buildWorker.ts +93 -4
  8. package/pages/functions/filepath-routing.test.ts +136 -25
  9. package/pages/functions/filepath-routing.ts +14 -3
  10. package/pages/functions/routes.ts +6 -1
  11. package/pages/functions/template-plugin.ts +147 -0
  12. package/pages/functions/template-worker.ts +21 -8
  13. package/src/__tests__/config-cache.test.ts +36 -0
  14. package/src/__tests__/configuration.test.ts +1514 -367
  15. package/src/__tests__/dev.test.tsx +870 -84
  16. package/src/__tests__/guess-worker-format.test.ts +37 -18
  17. package/src/__tests__/helpers/mock-account-id.ts +22 -4
  18. package/src/__tests__/helpers/mock-cfetch.ts +8 -4
  19. package/src/__tests__/helpers/mock-console.ts +35 -10
  20. package/src/__tests__/helpers/mock-dialogs.ts +26 -1
  21. package/src/__tests__/helpers/mock-http-server.ts +46 -0
  22. package/src/__tests__/helpers/mock-istty.ts +27 -0
  23. package/src/__tests__/helpers/mock-kv.ts +9 -16
  24. package/src/__tests__/helpers/mock-oauth-flow.ts +255 -0
  25. package/src/__tests__/helpers/mock-stdin.ts +103 -0
  26. package/src/__tests__/helpers/run-in-tmp.ts +10 -0
  27. package/src/__tests__/helpers/write-worker-source.ts +31 -0
  28. package/src/__tests__/https-options.test.ts +130 -0
  29. package/src/__tests__/index.test.ts +137 -747
  30. package/src/__tests__/init.test.ts +1557 -0
  31. package/src/__tests__/jest.setup.ts +28 -8
  32. package/src/__tests__/kv.test.ts +598 -258
  33. package/src/__tests__/logger.test.ts +115 -0
  34. package/src/__tests__/pages.test.ts +657 -0
  35. package/src/__tests__/parse.test.ts +8 -0
  36. package/src/__tests__/publish.test.ts +4003 -941
  37. package/src/__tests__/r2.test.ts +69 -34
  38. package/src/__tests__/route.test.ts +45 -0
  39. package/src/__tests__/secret.test.ts +228 -73
  40. package/src/__tests__/tail.test.ts +146 -20
  41. package/src/__tests__/user.test.ts +131 -0
  42. package/src/__tests__/whoami.test.tsx +26 -7
  43. package/src/abort.d.ts +3 -0
  44. package/src/bundle.ts +74 -7
  45. package/src/cfetch/index.ts +21 -4
  46. package/src/cfetch/internal.ts +20 -14
  47. package/src/cli.ts +5 -11
  48. package/src/config/README.md +7 -7
  49. package/src/config/config.ts +69 -100
  50. package/src/config/environment.ts +119 -4
  51. package/src/config/index.ts +177 -4
  52. package/src/config/validation-helpers.ts +228 -23
  53. package/src/config/validation.ts +687 -174
  54. package/src/config-cache.ts +45 -0
  55. package/src/{api/preview.ts → create-worker-preview.ts} +74 -36
  56. package/src/{api/form_data.ts → create-worker-upload-form.ts} +55 -18
  57. package/src/dev/dev-vars.ts +36 -0
  58. package/src/dev/dev.tsx +422 -0
  59. package/src/dev/local.tsx +318 -0
  60. package/src/dev/remote.tsx +227 -0
  61. package/src/dev/use-esbuild.ts +118 -0
  62. package/src/dialogs.tsx +16 -6
  63. package/src/durable.ts +102 -0
  64. package/src/entry.ts +279 -14
  65. package/src/environment-variables.ts +3 -1
  66. package/src/errors.ts +11 -0
  67. package/src/https-options.ts +123 -0
  68. package/src/index.tsx +1268 -806
  69. package/src/inspect.ts +64 -11
  70. package/src/intl-polyfill.d.ts +139 -0
  71. package/src/{kv.tsx → kv.ts} +195 -62
  72. package/src/logger.ts +66 -0
  73. package/src/miniflare-cli/README.md +30 -0
  74. package/src/miniflare-cli/enum-keys.ts +17 -0
  75. package/src/miniflare-cli/index.ts +41 -0
  76. package/src/miniflare-cli/request-context.ts +40 -0
  77. package/src/module-collection.ts +94 -6
  78. package/src/open-in-browser.ts +9 -3
  79. package/src/package-manager.ts +9 -8
  80. package/src/pages.tsx +1057 -75
  81. package/src/parse.ts +24 -5
  82. package/src/proxy.ts +143 -54
  83. package/src/publish.ts +444 -229
  84. package/src/selfsigned.d.ts +29 -0
  85. package/src/sites.tsx +98 -44
  86. package/src/tail/index.ts +2 -2
  87. package/src/tail/printing.ts +13 -8
  88. package/src/update-check.ts +19 -0
  89. package/src/user.tsx +263 -109
  90. package/src/whoami.tsx +2 -1
  91. package/src/{api/worker.ts → worker.ts} +24 -30
  92. package/templates/gitignore +171 -0
  93. package/templates/new-worker.ts +16 -1
  94. package/templates/static-asset-facade.js +1 -1
  95. package/wrangler-dist/cli.js +55345 -69246
  96. package/src/__tests__/helpers/mock-user.ts +0 -27
  97. package/src/__tests__/logout.test.ts +0 -50
  98. package/src/__tests__/sentry.test.ts +0 -146
  99. package/src/dev.tsx +0 -961
  100. package/src/guess-worker-format.ts +0 -68
  101. package/src/reporting.ts +0 -115
  102. 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,23 +25,25 @@ 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",
32
+ host: undefined,
24
33
  },
25
34
  durable_objects: {
26
35
  bindings: [],
27
36
  },
28
- env: {},
29
37
  jsx_factory: "React.createElement",
30
38
  jsx_fragment: "React.Fragment",
39
+ tsconfig: undefined,
31
40
  kv_namespaces: [],
32
41
  legacy_env: true,
33
42
  main: undefined,
34
43
  migrations: [],
35
44
  name: undefined,
36
45
  r2_buckets: [],
46
+ services: [],
37
47
  route: undefined,
38
48
  routes: undefined,
39
49
  rules: [],
@@ -48,8 +58,11 @@ describe("normalizeAndValidateConfig()", () => {
48
58
  usage_model: undefined,
49
59
  vars: {},
50
60
  wasm_modules: undefined,
51
- workers_dev: true,
61
+ data_blobs: undefined,
62
+ workers_dev: undefined,
52
63
  zone_id: undefined,
64
+ minify: undefined,
65
+ node_compat: undefined,
53
66
  });
54
67
  expect(diagnostics.hasErrors()).toBe(false);
55
68
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -57,56 +70,42 @@ describe("normalizeAndValidateConfig()", () => {
57
70
 
58
71
  describe("top-level non-environment configuration", () => {
59
72
  it("should override config defaults with provided values", () => {
60
- const main = "src/index.ts";
61
- const expectedConfig: RawConfig = {
62
- main,
73
+ const expectedConfig: Partial<ConfigFields<RawDevConfig>> = {
63
74
  legacy_env: true,
64
75
  dev: {
65
76
  ip: "255.255.255.255",
66
77
  port: 9999,
67
- local_protocol: "HTTPS",
68
- upstream_protocol: "HTTP",
69
- },
70
- build: {
71
- command: "COMMAND",
72
- cwd: "CWD",
73
- watch_dir: "WATCH_DIR",
78
+ local_protocol: "https",
79
+ upstream_protocol: "http",
74
80
  },
75
81
  };
76
82
 
77
83
  const { config, diagnostics } = normalizeAndValidateConfig(
78
84
  expectedConfig,
79
- undefined
85
+ undefined,
86
+ { env: undefined }
80
87
  );
81
88
 
82
- const resolvedMain = path.resolve(process.cwd(), main);
83
- expect(config).toEqual(
84
- expect.objectContaining({ ...expectedConfig, main: resolvedMain })
85
- );
89
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
86
90
  expect(diagnostics.hasErrors()).toBe(false);
87
91
  expect(diagnostics.hasWarnings()).toBe(false);
88
92
  });
89
93
 
90
94
  it("should error on invalid top level fields", () => {
91
95
  const expectedConfig = {
92
- main: 111,
93
96
  legacy_env: "FOO",
94
97
  dev: {
95
98
  ip: 222,
96
99
  port: "FOO",
97
- local_protocol: 333,
98
- upstream_protocol: 444,
99
- },
100
- build: {
101
- command: 555,
102
- cwd: 666,
103
- watch_dir: 777,
100
+ local_protocol: "wss",
101
+ upstream_protocol: "ws",
104
102
  },
105
103
  };
106
104
 
107
105
  const { config, diagnostics } = normalizeAndValidateConfig(
108
106
  expectedConfig as unknown as RawConfig,
109
- undefined
107
+ undefined,
108
+ { env: undefined }
110
109
  );
111
110
 
112
111
  expect(config).toEqual(
@@ -114,80 +113,55 @@ describe("normalizeAndValidateConfig()", () => {
114
113
  );
115
114
  expect(diagnostics.hasWarnings()).toBe(false);
116
115
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
117
- "Processing wrangler configuration:
118
- - ERROR: \\"build.command\\" should be of type string but got 555.
119
- - ERROR: \\"build.cwd\\" should be of type string but got 666.
120
- - ERROR: \\"build.watch_dir\\" should be of type string but got 777.
121
- - ERROR: \\"legacy_env\\" should be of type boolean but got \\"FOO\\".
122
- - ERROR: \\"main\\" should be a string but got 111
123
- - ERROR: \\"dev.ip\\" should be of type string but got 222.
124
- - ERROR: \\"dev.port\\" should be of type number but got \\"FOO\\".
125
- - ERROR: \\"dev.local_protocol\\" should be of type string but got 333.
126
- - ERROR: \\"dev.upstream_protocol\\" should be of type string but got 444."
127
- `);
116
+ "Processing wrangler configuration:
117
+ - Expected \\"legacy_env\\" to be of type boolean but got \\"FOO\\".
118
+ - Expected \\"dev.ip\\" to be of type string but got 222.
119
+ - Expected \\"dev.port\\" to be of type number but got \\"FOO\\".
120
+ - Expected \\"dev.local_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"wss\\".
121
+ - Expected \\"dev.upstream_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"ws\\"."
122
+ `);
128
123
  });
129
124
 
130
125
  it("should warn on and remove unexpected top level fields", () => {
131
126
  const expectedConfig = {
132
- miniflare: {
133
- host: "127.0.0.1",
127
+ unexpected: {
128
+ subkey: "some-value",
134
129
  },
135
130
  };
136
131
 
137
132
  const { config, diagnostics } = normalizeAndValidateConfig(
138
133
  expectedConfig as unknown as RawConfig,
139
- undefined
134
+ undefined,
135
+ { env: undefined }
140
136
  );
141
137
 
142
- expect("miniflare" in config).toBe(false);
138
+ expect("unexpected" in config).toBe(false);
143
139
  expect(diagnostics.hasErrors()).toBe(false);
144
140
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
145
141
  "Processing wrangler configuration:
146
- - Unexpected fields found in top-level field: \\"miniflare\\""
142
+ - Unexpected fields found in top-level field: \\"unexpected\\""
147
143
  `);
148
144
  });
149
145
 
150
- it("should override build.upload config defaults with provided values and warn about deprecations", () => {
151
- const expectedConfig: RawConfig = {
152
- build: {
153
- upload: {
154
- dir: "src",
155
- format: "modules",
156
- main: "index.ts",
157
- rules: [{ type: "Text", globs: ["GLOB"], fallthrough: true }],
158
- },
146
+ it("should report a deprecation warning if `miniflare` appears at the top level", () => {
147
+ const expectedConfig = {
148
+ miniflare: {
149
+ host: "localhost",
159
150
  },
160
151
  };
161
152
 
162
153
  const { config, diagnostics } = normalizeAndValidateConfig(
163
- expectedConfig,
164
- path.resolve("project/wrangler.toml")
154
+ expectedConfig as unknown as RawConfig,
155
+ undefined,
156
+ { env: undefined }
165
157
  );
166
158
 
167
- expect(config.main).toEqual(path.resolve("project/src/index.ts"));
168
- expect(config.build.upload).toBeUndefined();
159
+ expect("miniflare" in config).toBe(false);
169
160
  expect(diagnostics.hasErrors()).toBe(false);
170
- expect(diagnostics.hasWarnings()).toBe(true);
171
- expect(normalizePath(diagnostics.renderWarnings()))
172
- .toMatchInlineSnapshot(`
173
- "Processing project/wrangler.toml configuration:
174
- - DEPRECATION: \\"build.upload.format\\":
175
- The format is inferred automatically from the code.
176
- - DEPRECATION: \\"build.upload.main\\":
177
- Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
178
- Then add the top level \`main\` field to your configuration file:
179
- \`\`\`
180
- main = \\"src/index.ts\\"
181
- \`\`\`
182
- - DEPRECATION: \\"build.upload.dir\\":
183
- Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker.
184
- - DEPRECATION: The \`build.upload.rules\` config field is no longer used, the rules should be specified via the \`rules\` config field. Delete the \`build.upload\` field from the configuration file, and add this:
185
- \`\`\`
186
- [[rules]]
187
- type = \\"Text\\"
188
- globs = [ \\"GLOB\\" ]
189
- fallthrough = true
190
- \`\`\`"
161
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
162
+ "Processing wrangler configuration:
163
+ - 😶 Ignored: \\"miniflare\\":
164
+ Wrangler does not use configuration in the \`miniflare\` section. Unless you are using Miniflare directly you can remove this section."
191
165
  `);
192
166
  });
193
167
 
@@ -210,7 +184,8 @@ describe("normalizeAndValidateConfig()", () => {
210
184
 
211
185
  const { config, diagnostics } = normalizeAndValidateConfig(
212
186
  expectedConfig,
213
- undefined
187
+ undefined,
188
+ { env: undefined }
214
189
  );
215
190
 
216
191
  expect(config).toEqual(expect.objectContaining(expectedConfig));
@@ -237,90 +212,162 @@ describe("normalizeAndValidateConfig()", () => {
237
212
 
238
213
  const { config, diagnostics } = normalizeAndValidateConfig(
239
214
  expectedConfig as unknown as RawConfig,
240
- undefined
215
+ undefined,
216
+ { env: undefined }
241
217
  );
242
218
 
243
219
  expect(config).toEqual(expect.objectContaining(expectedConfig));
244
220
  expect(diagnostics.hasWarnings()).toBe(false);
245
221
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
222
+ "Processing wrangler configuration:
223
+ - Expected \\"migrations[0].tag\\" to be of type string but got 111.
224
+ - Expected \\"migrations[0].new_classes.[0]\\" to be of type string but got 222.
225
+ - Expected \\"migrations[0].new_classes.[1]\\" to be of type string but got 333.
226
+ - Expected \\"migrations[0].renamed_classes\\" to be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":444,\\"to\\":555}].
227
+ - Expected \\"migrations[0].deleted_classes.[0]\\" to be of type string but got 666.
228
+ - Expected \\"migrations[0].deleted_classes.[1]\\" to be of type string but got 777."
229
+ `);
230
+ });
231
+
232
+ describe("site", () => {
233
+ it("should override `site` config defaults with provided values", () => {
234
+ const expectedConfig: RawConfig = {
235
+ site: {
236
+ bucket: "BUCKET",
237
+ "entry-point": "my-site",
238
+ exclude: ["EXCLUDE_1", "EXCLUDE_2"],
239
+ include: ["INCLUDE_1", "INCLUDE_2"],
240
+ },
241
+ };
242
+
243
+ const { config, diagnostics } = normalizeAndValidateConfig(
244
+ expectedConfig,
245
+ undefined,
246
+ { env: undefined }
247
+ );
248
+
249
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
250
+ expect(diagnostics.hasErrors()).toBe(false);
251
+ expect(diagnostics.hasWarnings()).toBe(true);
252
+
253
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
254
+ .toMatchInlineSnapshot(`
246
255
  "Processing wrangler configuration:
247
- - ERROR: \\"migrations[0].tag\\" should be of type string but got 111.
248
- - ERROR: \\"migrations[0].new_classes.[0]\\" should be of type string but got 222.
249
- - ERROR: \\"migrations[0].new_classes.[1]\\" should be of type string but got 333.
250
- - \\"migrations[0].renamed_classes\\" should be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":444,\\"to\\":555}].
251
- - ERROR: \\"migrations[0].deleted_classes.[0]\\" should be of type string but got 666.
252
- - ERROR: \\"migrations[0].deleted_classes.[1]\\" should be of type string but got 777."
256
+ - Deprecation: \\"site.entry-point\\":
257
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
258
+ \`\`\`
259
+ main = \\"my-site/index.js\\"
260
+ \`\`\`"
253
261
  `);
254
- });
262
+ });
255
263
 
256
- it("should override `site` config defaults with provided values", () => {
257
- const expectedConfig: RawConfig = {
258
- site: {
259
- bucket: "BUCKET",
260
- "entry-point": "ENTRY_POINT",
261
- include: ["INCLUDE_1", "INCLUDE_2"],
262
- exclude: ["EXCLUDE_1", "EXCLUDE_2"],
263
- },
264
- };
264
+ it("should error if `site` config is missing `bucket`", () => {
265
+ const expectedConfig: RawConfig = {
266
+ // @ts-expect-error we're intentionally passing an invalid configuration here
267
+ site: {
268
+ "entry-point": "workers-site",
269
+ include: ["INCLUDE_1", "INCLUDE_2"],
270
+ exclude: ["EXCLUDE_1", "EXCLUDE_2"],
271
+ },
272
+ };
265
273
 
266
- const { config, diagnostics } = normalizeAndValidateConfig(
267
- expectedConfig,
268
- undefined
269
- );
274
+ const { config, diagnostics } = normalizeAndValidateConfig(
275
+ expectedConfig,
276
+ undefined,
277
+ { env: undefined }
278
+ );
270
279
 
271
- expect(config).toEqual(expect.objectContaining(expectedConfig));
272
- expect(diagnostics.hasErrors()).toBe(false);
273
- expect(diagnostics.hasWarnings()).toBe(false);
274
- });
280
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
281
+ expect(diagnostics.hasWarnings()).toBe(true);
282
+ expect(diagnostics.hasErrors()).toBe(true);
275
283
 
276
- it("should error if `site` config is missing `bucket`", () => {
277
- const expectedConfig: RawConfig = {
278
- site: {
279
- "entry-point": "ENTRY_POINT",
280
- include: ["INCLUDE_1", "INCLUDE_2"],
281
- exclude: ["EXCLUDE_1", "EXCLUDE_2"],
282
- },
283
- } as RawConfig;
284
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
285
+ .toMatchInlineSnapshot(`
286
+ "Processing wrangler configuration:
287
+ - Deprecation: \\"site.entry-point\\":
288
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
289
+ \`\`\`
290
+ main = \\"workers-site/index.js\\"
291
+ \`\`\`"
292
+ `);
284
293
 
285
- const { config, diagnostics } = normalizeAndValidateConfig(
286
- expectedConfig,
287
- undefined
288
- );
294
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
295
+ "Processing wrangler configuration:
296
+ - \\"site.bucket\\" is a required field."
297
+ `);
298
+ });
289
299
 
290
- expect(config).toEqual(expect.objectContaining(expectedConfig));
291
- expect(diagnostics.hasErrors()).toBe(true);
292
- expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
293
- "Processing wrangler configuration:
294
- - ERROR: \\"site.bucket\\" is a required field."
295
- `);
296
- expect(diagnostics.hasWarnings()).toBe(false);
297
- });
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
+ };
298
309
 
299
- it("should error on invalid `site` values", () => {
300
- const expectedConfig = {
301
- site: {
302
- bucket: "BUCKET",
303
- "entry-point": 111,
304
- include: [222, 333],
305
- exclude: [444, 555],
306
- },
307
- };
310
+ const { config, diagnostics } = normalizeAndValidateConfig(
311
+ expectedConfig as unknown as RawConfig,
312
+ undefined,
313
+ { env: undefined }
314
+ );
308
315
 
309
- const { config, diagnostics } = normalizeAndValidateConfig(
310
- expectedConfig as unknown as RawConfig,
311
- undefined
312
- );
316
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
317
+ expect(diagnostics.hasWarnings()).toBe(true);
318
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
319
+ "Processing wrangler configuration:
320
+ - Expected \\"sites.include.[0]\\" to be of type string but got 222.
321
+ - Expected \\"sites.include.[1]\\" to be of type string but got 333.
322
+ - Expected \\"sites.exclude.[0]\\" to be of type string but got 444.
323
+ - Expected \\"sites.exclude.[1]\\" to be of type string but got 555.
324
+ - Expected \\"site.entry-point\\" to be of type string but got 111."
325
+ `);
313
326
 
314
- expect(config).toEqual(expect.objectContaining(expectedConfig));
315
- expect(diagnostics.hasWarnings()).toBe(false);
316
- expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
327
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
328
+ .toMatchInlineSnapshot(`
329
+ "Processing wrangler configuration:
330
+ - Deprecation: \\"site.entry-point\\":
331
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
332
+ \`\`\`
333
+ main = \\"111/index.js\\"
334
+ \`\`\`"
335
+ `);
336
+ });
337
+
338
+ it("should log a deprecation warning if entry-point is defined", async () => {
339
+ const { config, diagnostics } = normalizeAndValidateConfig(
340
+ {
341
+ site: {
342
+ bucket: "some/path",
343
+ "entry-point": "some/other/script.js",
344
+ },
345
+ } as unknown as RawConfig,
346
+ undefined,
347
+ { env: undefined }
348
+ );
349
+
350
+ expect(config.site).toMatchInlineSnapshot(`
351
+ Object {
352
+ "bucket": "some/path",
353
+ "entry-point": "some/other/script.js",
354
+ "exclude": Array [],
355
+ "include": Array [],
356
+ }
357
+ `);
358
+ expect(diagnostics.hasWarnings()).toBe(true);
359
+ expect(diagnostics.hasErrors()).toBe(false);
360
+
361
+ expect(normalizeSlashes(diagnostics.renderWarnings()))
362
+ .toMatchInlineSnapshot(`
317
363
  "Processing wrangler configuration:
318
- - ERROR: \\"site.entry_point\\" should be of type string but got 111.
319
- - ERROR: \\"sites.include.[0]\\" should be of type string but got 222.
320
- - ERROR: \\"sites.include.[1]\\" should be of type string but got 333.
321
- - ERROR: \\"sites.exclude.[0]\\" should be of type string but got 444.
322
- - ERROR: \\"sites.exclude.[1]\\" should be of type string but got 555."
364
+ - Deprecation: \\"site.entry-point\\":
365
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
366
+ \`\`\`
367
+ main = \\"some/other/script.js\\"
368
+ \`\`\`"
323
369
  `);
370
+ });
324
371
  });
325
372
 
326
373
  it("should map `wasm_module` paths from relative to the config path to relative to the cwd", () => {
@@ -333,7 +380,8 @@ describe("normalizeAndValidateConfig()", () => {
333
380
 
334
381
  const { config, diagnostics } = normalizeAndValidateConfig(
335
382
  expectedConfig,
336
- "project/wrangler.toml"
383
+ "project/wrangler.toml",
384
+ { env: undefined }
337
385
  );
338
386
 
339
387
  expect(config).toEqual(
@@ -348,7 +396,7 @@ describe("normalizeAndValidateConfig()", () => {
348
396
  expect(diagnostics.hasWarnings()).toBe(false);
349
397
  });
350
398
 
351
- it("should error on invalid `wasm_module` paths", () => {
399
+ it("should error on invalid `wasm_modules` paths", () => {
352
400
  const expectedConfig = {
353
401
  wasm_modules: {
354
402
  MODULE_1: 111,
@@ -358,7 +406,8 @@ describe("normalizeAndValidateConfig()", () => {
358
406
 
359
407
  const { config, diagnostics } = normalizeAndValidateConfig(
360
408
  expectedConfig as unknown as RawConfig,
361
- "project/wrangler.toml"
409
+ "project/wrangler.toml",
410
+ { env: undefined }
362
411
  );
363
412
 
364
413
  expect(config).toEqual(
@@ -368,10 +417,10 @@ describe("normalizeAndValidateConfig()", () => {
368
417
  );
369
418
  expect(diagnostics.hasWarnings()).toBe(false);
370
419
  expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
371
- "Processing project/wrangler.toml configuration:
372
- - Expected \\"wasm_modules['MODULE_1']\\" field to be a string but got 111.
373
- - Expected \\"wasm_modules['MODULE_2']\\" field to be a string but got 222."
374
- `);
420
+ "Processing project/wrangler.toml configuration:
421
+ - Expected \\"wasm_modules['MODULE_1']\\" to be of type string but got 111.
422
+ - Expected \\"wasm_modules['MODULE_2']\\" to be of type string but got 222."
423
+ `);
375
424
  });
376
425
 
377
426
  it("should map `text_blobs` paths from relative to the config path to relative to the cwd", () => {
@@ -384,7 +433,8 @@ describe("normalizeAndValidateConfig()", () => {
384
433
 
385
434
  const { config, diagnostics } = normalizeAndValidateConfig(
386
435
  expectedConfig,
387
- "project/wrangler.toml"
436
+ "project/wrangler.toml",
437
+ { env: undefined }
388
438
  );
389
439
 
390
440
  expect(config).toEqual(
@@ -409,7 +459,8 @@ describe("normalizeAndValidateConfig()", () => {
409
459
 
410
460
  const { config, diagnostics } = normalizeAndValidateConfig(
411
461
  expectedConfig as unknown as RawConfig,
412
- "project/wrangler.toml"
462
+ "project/wrangler.toml",
463
+ { env: undefined }
413
464
  );
414
465
 
415
466
  expect(config).toEqual(
@@ -419,10 +470,84 @@ describe("normalizeAndValidateConfig()", () => {
419
470
  );
420
471
  expect(diagnostics.hasWarnings()).toBe(false);
421
472
  expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
422
- "Processing project/wrangler.toml configuration:
423
- - Expected \\"text_blobs['MODULE_1']\\" field to be a string but got 111.
424
- - Expected \\"text_blobs['MODULE_2']\\" field to be a string but got 222."
425
- `);
473
+ "Processing project/wrangler.toml configuration:
474
+ - Expected \\"text_blobs['MODULE_1']\\" to be of type string but got 111.
475
+ - Expected \\"text_blobs['MODULE_2']\\" to be of type string but got 222."
476
+ `);
477
+ });
478
+
479
+ it("should map `data_blobs` paths from relative to the config path to relative to the cwd", () => {
480
+ const expectedConfig: RawConfig = {
481
+ data_blobs: {
482
+ BLOB_1: "path/to/data1.bin",
483
+ BLOB_2: "data2.bin",
484
+ },
485
+ };
486
+
487
+ const { config, diagnostics } = normalizeAndValidateConfig(
488
+ expectedConfig,
489
+ "project/wrangler.toml",
490
+ { env: undefined }
491
+ );
492
+
493
+ expect(config).toEqual(
494
+ expect.objectContaining({
495
+ data_blobs: {
496
+ BLOB_1: path.normalize("project/path/to/data1.bin"),
497
+ BLOB_2: path.normalize("project/data2.bin"),
498
+ },
499
+ })
500
+ );
501
+ expect(diagnostics.hasErrors()).toBe(false);
502
+ expect(diagnostics.hasWarnings()).toBe(false);
503
+ });
504
+
505
+ it("should error on invalid `data_blob` paths", () => {
506
+ const expectedConfig = {
507
+ data_blobs: {
508
+ MODULE_1: 111,
509
+ MODULE_2: 222,
510
+ },
511
+ };
512
+
513
+ const { config, diagnostics } = normalizeAndValidateConfig(
514
+ expectedConfig as unknown as RawConfig,
515
+ "project/wrangler.toml",
516
+ { env: undefined }
517
+ );
518
+
519
+ expect(config).toEqual(
520
+ expect.objectContaining({
521
+ data_blobs: {},
522
+ })
523
+ );
524
+ expect(diagnostics.hasWarnings()).toBe(false);
525
+ expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
526
+ "Processing project/wrangler.toml configuration:
527
+ - Expected \\"data_blobs['MODULE_1']\\" to be of type string but got 111.
528
+ - Expected \\"data_blobs['MODULE_2']\\" to be of type string but got 222."
529
+ `);
530
+ });
531
+
532
+ it("should resolve tsconfig relative to wrangler.toml", async () => {
533
+ const expectedConfig: RawEnvironment = {
534
+ tsconfig: "path/to/some-tsconfig.json",
535
+ };
536
+
537
+ const { config, diagnostics } = normalizeAndValidateConfig(
538
+ expectedConfig,
539
+ "project/wrangler.toml",
540
+ { env: undefined }
541
+ );
542
+
543
+ expect(config).toEqual(
544
+ expect.objectContaining({
545
+ tsconfig: path.normalize("project/path/to/some-tsconfig.json"),
546
+ })
547
+ );
548
+
549
+ expect(diagnostics.hasErrors()).toBe(false);
550
+ expect(diagnostics.hasWarnings()).toBe(false);
426
551
  });
427
552
 
428
553
  describe("(deprecated)", () => {
@@ -434,7 +559,8 @@ describe("normalizeAndValidateConfig()", () => {
434
559
 
435
560
  const { config, diagnostics } = normalizeAndValidateConfig(
436
561
  rawConfig,
437
- undefined
562
+ undefined,
563
+ { env: undefined }
438
564
  );
439
565
 
440
566
  // Note the `.not.` here...
@@ -447,30 +573,44 @@ describe("normalizeAndValidateConfig()", () => {
447
573
  expect(diagnostics.hasErrors()).toBe(false);
448
574
  expect(diagnostics.hasWarnings()).toBe(true);
449
575
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
450
- "Processing wrangler configuration:
451
- - DEPRECATION: \\"type\\":
452
- 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.
453
- - DEPRECATION: \\"webpack_config\\":
454
- 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."
455
- `);
576
+ "Processing wrangler configuration:
577
+ - 😶 Ignored: \\"type\\":
578
+ 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.
579
+ - 😶 Ignored: \\"webpack_config\\":
580
+ 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."
581
+ `);
456
582
  });
457
583
  });
458
584
  });
459
585
 
460
586
  describe("top-level environment configuration", () => {
461
587
  it("should override config defaults with provided values", () => {
462
- const expectedConfig: RawConfig = {
463
- name: "NAME",
588
+ const main = "src/index.ts";
589
+ const resolvedMain = path.resolve(process.cwd(), main);
590
+
591
+ const expectedConfig: RawEnvironment = {
592
+ name: "mock-name",
464
593
  account_id: "ACCOUNT_ID",
465
594
  compatibility_date: "2022-01-01",
466
595
  compatibility_flags: ["FLAG1", "FLAG2"],
467
596
  workers_dev: false,
468
- routes: ["ROUTE_1", "ROUTE_2"],
469
- route: "ROUTE_3",
597
+ routes: [
598
+ "ROUTE_1",
599
+ "ROUTE_2",
600
+ { pattern: "ROUTE3", zone_id: "ZONE_ID_3" },
601
+ "ROUTE_4",
602
+ ],
470
603
  jsx_factory: "JSX_FACTORY",
471
604
  jsx_fragment: "JSX_FRAGMENT",
605
+ tsconfig: "path/to/tsconfig",
472
606
  triggers: { crons: ["CRON_1", "CRON_2"] },
473
607
  usage_model: "bundled",
608
+ main,
609
+ build: {
610
+ command: "COMMAND",
611
+ cwd: "CWD",
612
+ watch_dir: "WATCH_DIR",
613
+ },
474
614
  vars: {
475
615
  VAR1: "VALUE_1",
476
616
  VAR2: "VALUE_2",
@@ -483,6 +623,12 @@ describe("normalizeAndValidateConfig()", () => {
483
623
  class_name: "CLASS2",
484
624
  script_name: "SCRIPT2",
485
625
  },
626
+ {
627
+ name: "DO_BINDING_3",
628
+ class_name: "CLASS3",
629
+ script_name: "SCRIPT3",
630
+ environment: "ENV3",
631
+ },
486
632
  ],
487
633
  },
488
634
  kv_namespaces: [
@@ -501,6 +647,13 @@ describe("normalizeAndValidateConfig()", () => {
501
647
  preview_bucket_name: "R2_PREVIEW_2",
502
648
  },
503
649
  ],
650
+ services: [
651
+ {
652
+ binding: "SERVICE_BINDING_1",
653
+ service: "SERVICE_TYPE_1",
654
+ environment: "SERVICE_BINDING_ENVIRONMENT_1",
655
+ },
656
+ ],
504
657
  unsafe: {
505
658
  bindings: [
506
659
  { name: "UNSAFE_BINDING_1", type: "UNSAFE_TYPE_1" },
@@ -511,63 +664,318 @@ describe("normalizeAndValidateConfig()", () => {
511
664
  },
512
665
  ],
513
666
  },
667
+ minify: true,
668
+ node_compat: true,
514
669
  };
515
670
 
516
671
  const { config, diagnostics } = normalizeAndValidateConfig(
517
672
  expectedConfig,
518
- undefined
673
+ undefined,
674
+ { env: undefined }
519
675
  );
520
676
 
521
- expect(config).toEqual(expect.objectContaining(expectedConfig));
677
+ expect(config).toEqual(
678
+ expect.objectContaining({ ...expectedConfig, main: resolvedMain })
679
+ );
522
680
  expect(diagnostics.hasErrors()).toBe(false);
523
681
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
524
- "Processing wrangler configuration:
525
- - \\"unsafe\\" fields are experimental and may change or break at any time."
526
- `);
682
+ "Processing wrangler configuration:
683
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
684
+ - \\"services\\" fields are experimental and may change or break at any time.
685
+ - In wrangler.toml, you have configured [durable_objects] exported by this Worker (CLASS1), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml. Add this configuration to your wrangler.toml:
686
+
687
+ \`\`\`
688
+ [[migrations]]
689
+ tag = \\"v1\\" # Should be unique for each entry
690
+ new_classes = [\\"CLASS1\\"]
691
+ \`\`\`
692
+
693
+ Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details."
694
+ `);
527
695
  });
528
696
 
529
697
  it("should error on invalid environment values", () => {
530
- const expectedConfig: RawConfig = {
698
+ const expectedConfig: RawEnvironment = {
531
699
  name: 111,
532
700
  account_id: 222,
533
701
  compatibility_date: 333,
534
702
  compatibility_flags: [444, 555],
535
703
  workers_dev: "BAD",
536
- routes: [666, 777],
704
+ routes: [
705
+ 666,
706
+ 777,
707
+ // this one's valid, but we add it here to make sure
708
+ // it doesn't get included in the error message
709
+ "example.com/*",
710
+ { pattern: 123, zone_id: "zone_id_1" },
711
+ { pattern: "route_2", zone_id: 123 },
712
+ { pattern: "route_2", zone_name: 123 },
713
+ { pattern: "route_3" },
714
+ { zone_id: "zone_id_4" },
715
+ { zone_name: "zone_name_4" },
716
+ { pattern: undefined },
717
+ { pattern: "route_5", zone_id: "zone_id_5", some_other_key: 123 },
718
+ { pattern: "route_5", zone_name: "zone_name_5", some_other_key: 123 },
719
+ // this one's valid too
720
+ { pattern: "route_6", zone_id: "zone_id_6" },
721
+ // as well as this one
722
+ { pattern: "route_6", zone_name: "zone_name_6" },
723
+ ],
537
724
  route: 888,
538
725
  jsx_factory: 999,
539
726
  jsx_fragment: 1000,
727
+ tsconfig: true,
540
728
  triggers: { crons: [1111, 1222] },
541
729
  usage_model: "INVALID",
542
- } as unknown as RawConfig;
730
+ main: 1333,
731
+ build: {
732
+ command: 1444,
733
+ cwd: 1555,
734
+ watch_dir: 1666,
735
+ },
736
+ minify: "INVALID",
737
+ node_compat: "INVALID",
738
+ } as unknown as RawEnvironment;
739
+
740
+ const { config, diagnostics } = normalizeAndValidateConfig(
741
+ expectedConfig,
742
+ undefined,
743
+ { env: undefined }
744
+ );
745
+
746
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
747
+ expect(diagnostics.hasWarnings()).toBe(false);
748
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
749
+ "Processing wrangler configuration:
750
+ - Expected \\"route\\" to be either a string, or an object with shape { pattern, custom_domain, zone_id | zone_name }, but got 888.
751
+ - Expected \\"routes\\" to be an array of either strings or objects with the shape { pattern, custom_domain, zone_id | zone_name }, but these weren't valid: [
752
+ 666,
753
+ 777,
754
+ {
755
+ \\"pattern\\": 123,
756
+ \\"zone_id\\": \\"zone_id_1\\"
757
+ },
758
+ {
759
+ \\"pattern\\": \\"route_2\\",
760
+ \\"zone_id\\": 123
761
+ },
762
+ {
763
+ \\"pattern\\": \\"route_2\\",
764
+ \\"zone_name\\": 123
765
+ },
766
+ {
767
+ \\"pattern\\": \\"route_3\\"
768
+ },
769
+ {
770
+ \\"zone_id\\": \\"zone_id_4\\"
771
+ },
772
+ {
773
+ \\"zone_name\\": \\"zone_name_4\\"
774
+ },
775
+ {},
776
+ {
777
+ \\"pattern\\": \\"route_5\\",
778
+ \\"zone_id\\": \\"zone_id_5\\",
779
+ \\"some_other_key\\": 123
780
+ },
781
+ {
782
+ \\"pattern\\": \\"route_5\\",
783
+ \\"zone_name\\": \\"zone_name_5\\",
784
+ \\"some_other_key\\": 123
785
+ }
786
+ ].
787
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"].
788
+ - Expected \\"workers_dev\\" to be of type boolean but got \\"BAD\\".
789
+ - Expected \\"build.command\\" to be of type string but got 1444.
790
+ - Expected \\"build.cwd\\" to be of type string but got 1555.
791
+ - Expected \\"build.watch_dir\\" to be of type string but got 1666.
792
+ - Expected \\"account_id\\" to be of type string but got 222.
793
+ - Expected \\"compatibility_date\\" to be of type string but got 333.
794
+ - Expected \\"compatibility_flags\\" to be of type string array but got [444,555].
795
+ - Expected \\"jsx_factory\\" to be of type string but got 999.
796
+ - Expected \\"jsx_fragment\\" to be of type string but got 1000.
797
+ - Expected \\"tsconfig\\" to be of type string but got true.
798
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got 111.
799
+ - Expected \\"main\\" to be of type string but got 1333.
800
+ - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\".
801
+ - Expected \\"minify\\" to be of type boolean but got \\"INVALID\\".
802
+ - Expected \\"node_compat\\" to be of type boolean but got \\"INVALID\\"."
803
+ `);
804
+ });
805
+
806
+ it("should error on invalid `name` value with spaces", () => {
807
+ const expectedConfig: RawEnvironment = {
808
+ name: "NCC 1701 D",
809
+ } as unknown as RawEnvironment;
810
+
811
+ const { config, diagnostics } = normalizeAndValidateConfig(
812
+ expectedConfig,
813
+ undefined,
814
+ { env: undefined }
815
+ );
816
+
817
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
818
+ expect(diagnostics.hasWarnings()).toBe(false);
819
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
820
+ "Processing wrangler configuration:
821
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got \\"NCC 1701 D\\"."
822
+ `);
823
+ });
824
+
825
+ it("should be valid `name` with underscores", () => {
826
+ const expectedConfig: RawEnvironment = {
827
+ name: "enterprise_nx_01",
828
+ } as unknown as RawEnvironment;
829
+
830
+ const { config, diagnostics } = normalizeAndValidateConfig(
831
+ expectedConfig,
832
+ undefined,
833
+ { env: undefined }
834
+ );
835
+
836
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
837
+ expect(diagnostics.hasWarnings()).toBe(false);
838
+ expect(diagnostics.hasErrors()).toBe(false);
839
+ });
840
+
841
+ it("should error on invalid `name` value with special characters", () => {
842
+ const expectedConfig: RawEnvironment = {
843
+ name: "Thy'lek-Shran",
844
+ } as unknown as RawEnvironment;
543
845
 
544
846
  const { config, diagnostics } = normalizeAndValidateConfig(
545
847
  expectedConfig,
546
- undefined
848
+ undefined,
849
+ { env: undefined }
547
850
  );
548
851
 
549
852
  expect(config).toEqual(expect.objectContaining(expectedConfig));
550
853
  expect(diagnostics.hasWarnings()).toBe(false);
551
854
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
552
855
  "Processing wrangler configuration:
553
- - Expected \\"route\\" field to be a string but got 888.
554
- - Expected \\"routes\\" field to be an array of strings but got [666,777].
555
- - Expected \\"workers_dev\\" field to be a boolean but got \\"BAD\\".
556
- - Expected \\"account_id\\" field to be a string but got 222.
557
- - Expected \\"compatibility_date\\" field to be a string but got 333.
558
- - Expected \\"compatibility_flags\\" field to be an array of strings but got [444,555].
559
- - Expected \\"jsx_factory\\" field to be a string but got 999.
560
- - Expected \\"jsx_fragment\\" field to be a string but got 1000.
561
- - Expected \\"name\\" field to be a string but got 111.
562
- - Expected \\"usage_model\\" field to be on of bundled,unbound but got \\"INVALID\\"."
856
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got \\"Thy'lek-Shran\\"."
563
857
  `);
564
858
  });
565
859
 
860
+ it("should error on invalid `name` value with only special characters", () => {
861
+ const expectedConfig: RawEnvironment = {
862
+ name: "!@#$%^&*(()",
863
+ } as unknown as RawEnvironment;
864
+
865
+ const { config, diagnostics } = normalizeAndValidateConfig(
866
+ expectedConfig,
867
+ undefined,
868
+ { env: undefined }
869
+ );
870
+
871
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
872
+ expect(diagnostics.hasWarnings()).toBe(false);
873
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
874
+ "Processing wrangler configuration:
875
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got \\"!@#$%^&*(()\\"."
876
+ `);
877
+ });
878
+
879
+ it("should override build.upload config defaults with provided values and warn about deprecations", () => {
880
+ const expectedConfig: RawEnvironment = {
881
+ build: {
882
+ upload: {
883
+ dir: "src",
884
+ format: "modules",
885
+ main: "index.ts",
886
+ rules: [{ type: "Text", globs: ["GLOB"], fallthrough: true }],
887
+ },
888
+ },
889
+ };
890
+
891
+ const { config, diagnostics } = normalizeAndValidateConfig(
892
+ expectedConfig,
893
+ path.resolve("project/wrangler.toml"),
894
+ { env: undefined }
895
+ );
896
+
897
+ expect(config.main).toEqual(path.resolve("project/src/index.ts"));
898
+ expect(config.build.upload).toBeUndefined();
899
+ expect(diagnostics.hasErrors()).toBe(false);
900
+ expect(diagnostics.hasWarnings()).toBe(true);
901
+ expect(normalizePath(diagnostics.renderWarnings()))
902
+ .toMatchInlineSnapshot(`
903
+ "Processing project/wrangler.toml configuration:
904
+ - Deprecation: \\"build.upload.format\\":
905
+ The format is inferred automatically from the code.
906
+ - Deprecation: \\"build.upload.main\\":
907
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
908
+ Then add the top level \`main\` field to your configuration file:
909
+ \`\`\`
910
+ main = \\"src/index.ts\\"
911
+ \`\`\`
912
+ - Deprecation: \\"build.upload.dir\\":
913
+ Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker.
914
+ - 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:
915
+ \`\`\`
916
+ [[rules]]
917
+ type = \\"Text\\"
918
+ globs = [ \\"GLOB\\" ]
919
+ fallthrough = true
920
+ \`\`\`"
921
+ `);
922
+ });
923
+
924
+ it("should default custom build watch directories to src", () => {
925
+ const expectedConfig: RawEnvironment = {
926
+ build: {
927
+ command: "execute some --build",
928
+ },
929
+ };
930
+
931
+ const { config, diagnostics } = normalizeAndValidateConfig(
932
+ expectedConfig,
933
+ undefined,
934
+ { env: undefined }
935
+ );
936
+
937
+ expect(config.build).toEqual(
938
+ expect.objectContaining({
939
+ command: "execute some --build",
940
+ watch_dir: "./src",
941
+ })
942
+ );
943
+
944
+ expect(diagnostics.hasErrors()).toBe(false);
945
+ expect(diagnostics.hasWarnings()).toBe(false);
946
+ });
947
+
948
+ it("should resolve custom build watch directories relative to wrangler.toml", async () => {
949
+ const expectedConfig: RawEnvironment = {
950
+ build: {
951
+ command: "execute some --build",
952
+ watch_dir: "some/path",
953
+ },
954
+ };
955
+
956
+ const { config, diagnostics } = normalizeAndValidateConfig(
957
+ expectedConfig,
958
+ "project/wrangler.toml",
959
+ { env: undefined }
960
+ );
961
+
962
+ expect(config.build).toEqual(
963
+ expect.objectContaining({
964
+ command: "execute some --build",
965
+ watch_dir: path.normalize("project/some/path"),
966
+ })
967
+ );
968
+
969
+ expect(diagnostics.hasErrors()).toBe(false);
970
+ expect(diagnostics.hasWarnings()).toBe(false);
971
+ });
972
+
566
973
  describe("durable_objects field", () => {
567
974
  it("should error if durable_objects is an array", () => {
568
975
  const { config, diagnostics } = normalizeAndValidateConfig(
569
976
  { durable_objects: [] } as unknown as RawConfig,
570
- undefined
977
+ undefined,
978
+ { env: undefined }
571
979
  );
572
980
 
573
981
  expect(config).toEqual(
@@ -583,7 +991,8 @@ describe("normalizeAndValidateConfig()", () => {
583
991
  it("should error if durable_objects is a string", () => {
584
992
  const { config, diagnostics } = normalizeAndValidateConfig(
585
993
  { durable_objects: "BAD" } as unknown as RawConfig,
586
- undefined
994
+ undefined,
995
+ { env: undefined }
587
996
  );
588
997
 
589
998
  expect(config).toEqual(
@@ -599,7 +1008,8 @@ describe("normalizeAndValidateConfig()", () => {
599
1008
  it("should error if durable_objects is a number", () => {
600
1009
  const { config, diagnostics } = normalizeAndValidateConfig(
601
1010
  { durable_objects: 999 } as unknown as RawConfig,
602
- undefined
1011
+ undefined,
1012
+ { env: undefined }
603
1013
  );
604
1014
 
605
1015
  expect(config).toEqual(
@@ -615,7 +1025,8 @@ describe("normalizeAndValidateConfig()", () => {
615
1025
  it("should error if durable_objects is null", () => {
616
1026
  const { config, diagnostics } = normalizeAndValidateConfig(
617
1027
  { durable_objects: null } as unknown as RawConfig,
618
- undefined
1028
+ undefined,
1029
+ { env: undefined }
619
1030
  );
620
1031
 
621
1032
  expect(config).toEqual(
@@ -631,7 +1042,8 @@ describe("normalizeAndValidateConfig()", () => {
631
1042
  it("should error if durable_objects.bindings is not defined", () => {
632
1043
  const { config, diagnostics } = normalizeAndValidateConfig(
633
1044
  { durable_objects: {} } as unknown as RawConfig,
634
- undefined
1045
+ undefined,
1046
+ { env: undefined }
635
1047
  );
636
1048
 
637
1049
  expect(config).toEqual(
@@ -647,7 +1059,8 @@ describe("normalizeAndValidateConfig()", () => {
647
1059
  it("should error if durable_objects.bindings is an object", () => {
648
1060
  const { config, diagnostics } = normalizeAndValidateConfig(
649
1061
  { durable_objects: { bindings: {} } } as unknown as RawConfig,
650
- undefined
1062
+ undefined,
1063
+ { env: undefined }
651
1064
  );
652
1065
 
653
1066
  expect(config).toEqual(
@@ -665,7 +1078,8 @@ describe("normalizeAndValidateConfig()", () => {
665
1078
  it("should error if durable_objects.bindings is a string", () => {
666
1079
  const { config, diagnostics } = normalizeAndValidateConfig(
667
1080
  { durable_objects: { bindings: "BAD" } } as unknown as RawConfig,
668
- undefined
1081
+ undefined,
1082
+ { env: undefined }
669
1083
  );
670
1084
 
671
1085
  expect(config).toEqual(
@@ -683,7 +1097,8 @@ describe("normalizeAndValidateConfig()", () => {
683
1097
  it("should error if durable_objects.bindings is a number", () => {
684
1098
  const { config, diagnostics } = normalizeAndValidateConfig(
685
1099
  { durable_objects: { bindings: 999 } } as unknown as RawConfig,
686
- undefined
1100
+ undefined,
1101
+ { env: undefined }
687
1102
  );
688
1103
 
689
1104
  expect(config).toEqual(
@@ -701,7 +1116,8 @@ describe("normalizeAndValidateConfig()", () => {
701
1116
  it("should error if durable_objects.bindings is null", () => {
702
1117
  const { config, diagnostics } = normalizeAndValidateConfig(
703
1118
  { durable_objects: { bindings: null } } as unknown as RawConfig,
704
- undefined
1119
+ undefined,
1120
+ { env: undefined }
705
1121
  );
706
1122
 
707
1123
  expect(config).toEqual(
@@ -722,17 +1138,34 @@ describe("normalizeAndValidateConfig()", () => {
722
1138
  durable_objects: {
723
1139
  bindings: [
724
1140
  {},
725
- { name: "VALID" },
1141
+ { name: "MISSING_CLASS" },
726
1142
  { name: 1555, class_name: 1666 },
727
1143
  {
728
1144
  name: 1777,
729
1145
  class_name: 1888,
730
1146
  script_name: 1999,
731
1147
  },
1148
+ {
1149
+ name: "SOMENAME",
1150
+ class_name: "SomeClass",
1151
+ environment: "staging",
1152
+ },
1153
+ {
1154
+ name: 1778,
1155
+ class_name: 1889,
1156
+ script_name: 1992,
1157
+ environment: 2111,
1158
+ },
1159
+ {
1160
+ name: 1772,
1161
+ class_name: 1883,
1162
+ environment: 2112,
1163
+ },
732
1164
  ],
733
1165
  },
734
1166
  } as unknown as RawConfig,
735
- undefined
1167
+ undefined,
1168
+ { env: undefined }
736
1169
  );
737
1170
 
738
1171
  expect(config).toEqual(
@@ -741,24 +1174,41 @@ describe("normalizeAndValidateConfig()", () => {
741
1174
  })
742
1175
  );
743
1176
  expect(diagnostics.hasWarnings()).toBe(false);
1177
+
1178
+ expect(diagnostics.hasErrors()).toBe(true);
744
1179
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
745
1180
  "Processing wrangler configuration:
746
1181
 
747
1182
  - \\"durable_objects.bindings[0]\\": {}
748
- - ERROR: bindings should have a string \\"name\\" field.
749
- - ERROR: should have a string \\"class_name\\" field.
1183
+ - binding should have a string \\"name\\" field.
1184
+ - binding should have a string \\"class_name\\" field.
750
1185
 
751
- - \\"durable_objects.bindings[1]\\": {\\"name\\":\\"VALID\\"}
752
- - ERROR: should have a string \\"class_name\\" field.
1186
+ - \\"durable_objects.bindings[1]\\": {\\"name\\":\\"MISSING_CLASS\\"}
1187
+ - binding should have a string \\"class_name\\" field.
753
1188
 
754
1189
  - \\"durable_objects.bindings[2]\\": {\\"name\\":1555,\\"class_name\\":1666}
755
- - ERROR: bindings should have a string \\"name\\" field.
756
- - ERROR: should have a string \\"class_name\\" field.
1190
+ - binding should have a string \\"name\\" field.
1191
+ - binding should have a string \\"class_name\\" field.
757
1192
 
758
1193
  - \\"durable_objects.bindings[3]\\": {\\"name\\":1777,\\"class_name\\":1888,\\"script_name\\":1999}
759
- - ERROR: bindings should have a string \\"name\\" field.
760
- - ERROR: should have a string \\"class_name\\" field.
761
- - ERROR: should, optionally, have a string \\"script_name\\" field."
1194
+ - binding should have a string \\"name\\" field.
1195
+ - binding should have a string \\"class_name\\" field.
1196
+ - the field \\"script_name\\", when present, should be a string.
1197
+
1198
+ - \\"durable_objects.bindings[4]\\": {\\"name\\":\\"SOMENAME\\",\\"class_name\\":\\"SomeClass\\",\\"environment\\":\\"staging\\"}
1199
+ - binding should have a \\"script_name\\" field if \\"environment\\" is present.
1200
+
1201
+ - \\"durable_objects.bindings[5]\\": {\\"name\\":1778,\\"class_name\\":1889,\\"script_name\\":1992,\\"environment\\":2111}
1202
+ - binding should have a string \\"name\\" field.
1203
+ - binding should have a string \\"class_name\\" field.
1204
+ - the field \\"script_name\\", when present, should be a string.
1205
+ - the field \\"environment\\", when present, should be a string.
1206
+
1207
+ - \\"durable_objects.bindings[6]\\": {\\"name\\":1772,\\"class_name\\":1883,\\"environment\\":2112}
1208
+ - binding should have a string \\"name\\" field.
1209
+ - binding should have a string \\"class_name\\" field.
1210
+ - the field \\"environment\\", when present, should be a string.
1211
+ - binding should have a \\"script_name\\" field if \\"environment\\" is present."
762
1212
  `);
763
1213
  });
764
1214
  });
@@ -767,7 +1217,8 @@ describe("normalizeAndValidateConfig()", () => {
767
1217
  it("should error if kv_namespaces is an object", () => {
768
1218
  const { config, diagnostics } = normalizeAndValidateConfig(
769
1219
  { kv_namespaces: {} } as unknown as RawConfig,
770
- undefined
1220
+ undefined,
1221
+ { env: undefined }
771
1222
  );
772
1223
 
773
1224
  expect(config).toEqual(
@@ -783,7 +1234,8 @@ describe("normalizeAndValidateConfig()", () => {
783
1234
  it("should error if kv_namespaces is a string", () => {
784
1235
  const { config, diagnostics } = normalizeAndValidateConfig(
785
1236
  { kv_namespaces: "BAD" } as unknown as RawConfig,
786
- undefined
1237
+ undefined,
1238
+ { env: undefined }
787
1239
  );
788
1240
 
789
1241
  expect(config).toEqual(
@@ -799,7 +1251,8 @@ describe("normalizeAndValidateConfig()", () => {
799
1251
  it("should error if kv_namespaces is a number", () => {
800
1252
  const { config, diagnostics } = normalizeAndValidateConfig(
801
1253
  { kv_namespaces: 999 } as unknown as RawConfig,
802
- undefined
1254
+ undefined,
1255
+ { env: undefined }
803
1256
  );
804
1257
 
805
1258
  expect(config).toEqual(
@@ -815,7 +1268,8 @@ describe("normalizeAndValidateConfig()", () => {
815
1268
  it("should error if kv_namespaces is null", () => {
816
1269
  const { config, diagnostics } = normalizeAndValidateConfig(
817
1270
  { kv_namespaces: null } as unknown as RawConfig,
818
- undefined
1271
+ undefined,
1272
+ { env: undefined }
819
1273
  );
820
1274
 
821
1275
  expect(config).toEqual(
@@ -842,7 +1296,8 @@ describe("normalizeAndValidateConfig()", () => {
842
1296
  },
843
1297
  ],
844
1298
  } as unknown as RawConfig,
845
- undefined
1299
+ undefined,
1300
+ { env: undefined }
846
1301
  );
847
1302
 
848
1303
  expect(config).toEqual(
@@ -867,7 +1322,8 @@ describe("normalizeAndValidateConfig()", () => {
867
1322
  it("should error if r2_buckets is an object", () => {
868
1323
  const { config, diagnostics } = normalizeAndValidateConfig(
869
1324
  { r2_buckets: {} } as unknown as RawConfig,
870
- undefined
1325
+ undefined,
1326
+ { env: undefined }
871
1327
  );
872
1328
 
873
1329
  expect(config).toEqual(
@@ -883,7 +1339,8 @@ describe("normalizeAndValidateConfig()", () => {
883
1339
  it("should error if r2_buckets is a string", () => {
884
1340
  const { config, diagnostics } = normalizeAndValidateConfig(
885
1341
  { r2_buckets: "BAD" } as unknown as RawConfig,
886
- undefined
1342
+ undefined,
1343
+ { env: undefined }
887
1344
  );
888
1345
 
889
1346
  expect(config).toEqual(
@@ -899,7 +1356,8 @@ describe("normalizeAndValidateConfig()", () => {
899
1356
  it("should error if r2_buckets is a number", () => {
900
1357
  const { config, diagnostics } = normalizeAndValidateConfig(
901
1358
  { r2_buckets: 999 } as unknown as RawConfig,
902
- undefined
1359
+ undefined,
1360
+ { env: undefined }
903
1361
  );
904
1362
 
905
1363
  expect(config).toEqual(
@@ -915,7 +1373,8 @@ describe("normalizeAndValidateConfig()", () => {
915
1373
  it("should error if r2_buckets is null", () => {
916
1374
  const { config, diagnostics } = normalizeAndValidateConfig(
917
1375
  { r2_buckets: null } as unknown as RawConfig,
918
- undefined
1376
+ undefined,
1377
+ { env: undefined }
919
1378
  );
920
1379
 
921
1380
  expect(config).toEqual(
@@ -942,7 +1401,8 @@ describe("normalizeAndValidateConfig()", () => {
942
1401
  },
943
1402
  ],
944
1403
  } as unknown as RawConfig,
945
- undefined
1404
+ undefined,
1405
+ { env: undefined }
946
1406
  );
947
1407
 
948
1408
  expect(config).toEqual(
@@ -963,11 +1423,157 @@ describe("normalizeAndValidateConfig()", () => {
963
1423
  });
964
1424
  });
965
1425
 
1426
+ describe("services field", () => {
1427
+ it("should error if services is an object", () => {
1428
+ const { config, diagnostics } = normalizeAndValidateConfig(
1429
+ { services: {} } as unknown as RawConfig,
1430
+ undefined,
1431
+ { env: undefined }
1432
+ );
1433
+
1434
+ expect(config).toEqual(
1435
+ expect.not.objectContaining({ services: expect.anything })
1436
+ );
1437
+ expect(diagnostics.hasWarnings()).toBe(true);
1438
+ expect(diagnostics.hasErrors()).toBe(true);
1439
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1440
+ "Processing wrangler configuration:
1441
+ - \\"services\\" fields are experimental and may change or break at any time."
1442
+ `);
1443
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1444
+ "Processing wrangler configuration:
1445
+ - The field \\"services\\" should be an array but got {}."
1446
+ `);
1447
+ });
1448
+
1449
+ it("should error if services is a string", () => {
1450
+ const { config, diagnostics } = normalizeAndValidateConfig(
1451
+ { services: "BAD" } as unknown as RawConfig,
1452
+ undefined,
1453
+ { env: undefined }
1454
+ );
1455
+
1456
+ expect(config).toEqual(
1457
+ expect.not.objectContaining({ services: expect.anything })
1458
+ );
1459
+ expect(diagnostics.hasWarnings()).toBe(true);
1460
+ expect(diagnostics.hasErrors()).toBe(true);
1461
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1462
+ "Processing wrangler configuration:
1463
+ - \\"services\\" fields are experimental and may change or break at any time."
1464
+ `);
1465
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1466
+ "Processing wrangler configuration:
1467
+ - The field \\"services\\" should be an array but got \\"BAD\\"."
1468
+ `);
1469
+ });
1470
+
1471
+ it("should error if services is a number", () => {
1472
+ const { config, diagnostics } = normalizeAndValidateConfig(
1473
+ { services: 999 } as unknown as RawConfig,
1474
+ undefined,
1475
+ { env: undefined }
1476
+ );
1477
+
1478
+ expect(config).toEqual(
1479
+ expect.not.objectContaining({ services: expect.anything })
1480
+ );
1481
+ expect(diagnostics.hasWarnings()).toBe(true);
1482
+ expect(diagnostics.hasErrors()).toBe(true);
1483
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1484
+ "Processing wrangler configuration:
1485
+ - \\"services\\" fields are experimental and may change or break at any time."
1486
+ `);
1487
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1488
+ "Processing wrangler configuration:
1489
+ - The field \\"services\\" should be an array but got 999."
1490
+ `);
1491
+ });
1492
+
1493
+ it("should error if services is null", () => {
1494
+ const { config, diagnostics } = normalizeAndValidateConfig(
1495
+ { services: null } as unknown as RawConfig,
1496
+ undefined,
1497
+ { env: undefined }
1498
+ );
1499
+
1500
+ expect(config).toEqual(
1501
+ expect.not.objectContaining({ services: expect.anything })
1502
+ );
1503
+ expect(diagnostics.hasWarnings()).toBe(true);
1504
+ expect(diagnostics.hasErrors()).toBe(true);
1505
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1506
+ "Processing wrangler configuration:
1507
+ - \\"services\\" fields are experimental and may change or break at any time."
1508
+ `);
1509
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1510
+ "Processing wrangler configuration:
1511
+ - The field \\"services\\" should be an array but got null."
1512
+ `);
1513
+ });
1514
+
1515
+ it("should error if services bindings are not valid", () => {
1516
+ const { config, diagnostics } = normalizeAndValidateConfig(
1517
+ {
1518
+ services: [
1519
+ {},
1520
+ { binding: "SERVICE_BINDING_1" },
1521
+ { binding: 123, service: 456 },
1522
+ { binding: 123, service: 456, environment: 789 },
1523
+ { binding: "SERVICE_BINDING_1", service: 456, environment: 789 },
1524
+ {
1525
+ binding: 123,
1526
+ service: "SERVICE_BINDING_SERVICE_1",
1527
+ environment: 789,
1528
+ },
1529
+ {
1530
+ binding: 123,
1531
+ service: 456,
1532
+ environment: "SERVICE_BINDING_ENVIRONMENT_1",
1533
+ },
1534
+ ],
1535
+ } as unknown as RawConfig,
1536
+ undefined,
1537
+ { env: undefined }
1538
+ );
1539
+
1540
+ expect(config).toEqual(
1541
+ expect.not.objectContaining({
1542
+ services: { bindings: expect.anything },
1543
+ })
1544
+ );
1545
+ expect(diagnostics.hasWarnings()).toBe(true);
1546
+ expect(diagnostics.hasErrors()).toBe(true);
1547
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1548
+ "Processing wrangler configuration:
1549
+ - \\"services\\" fields are experimental and may change or break at any time."
1550
+ `);
1551
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1552
+ "Processing wrangler configuration:
1553
+ - \\"services[0]\\" bindings should have a string \\"binding\\" field but got {}.
1554
+ - \\"services[0]\\" bindings should have a string \\"service\\" field but got {}.
1555
+ - \\"services[1]\\" bindings should have a string \\"service\\" field but got {\\"binding\\":\\"SERVICE_BINDING_1\\"}.
1556
+ - \\"services[2]\\" bindings should have a string \\"binding\\" field but got {\\"binding\\":123,\\"service\\":456}.
1557
+ - \\"services[2]\\" bindings should have a string \\"service\\" field but got {\\"binding\\":123,\\"service\\":456}.
1558
+ - \\"services[3]\\" bindings should have a string \\"binding\\" field but got {\\"binding\\":123,\\"service\\":456,\\"environment\\":789}.
1559
+ - \\"services[3]\\" bindings should have a string \\"service\\" field but got {\\"binding\\":123,\\"service\\":456,\\"environment\\":789}.
1560
+ - \\"services[3]\\" bindings should have a string \\"environment\\" field but got {\\"binding\\":123,\\"service\\":456,\\"environment\\":789}.
1561
+ - \\"services[4]\\" bindings should have a string \\"service\\" field but got {\\"binding\\":\\"SERVICE_BINDING_1\\",\\"service\\":456,\\"environment\\":789}.
1562
+ - \\"services[4]\\" bindings should have a string \\"environment\\" field but got {\\"binding\\":\\"SERVICE_BINDING_1\\",\\"service\\":456,\\"environment\\":789}.
1563
+ - \\"services[5]\\" bindings should have a string \\"binding\\" field but got {\\"binding\\":123,\\"service\\":\\"SERVICE_BINDING_SERVICE_1\\",\\"environment\\":789}.
1564
+ - \\"services[5]\\" bindings should have a string \\"environment\\" field but got {\\"binding\\":123,\\"service\\":\\"SERVICE_BINDING_SERVICE_1\\",\\"environment\\":789}.
1565
+ - \\"services[6]\\" bindings should have a string \\"binding\\" field but got {\\"binding\\":123,\\"service\\":456,\\"environment\\":\\"SERVICE_BINDING_ENVIRONMENT_1\\"}.
1566
+ - \\"services[6]\\" bindings should have a string \\"service\\" field but got {\\"binding\\":123,\\"service\\":456,\\"environment\\":\\"SERVICE_BINDING_ENVIRONMENT_1\\"}."
1567
+ `);
1568
+ });
1569
+ });
1570
+
966
1571
  describe("unsafe field", () => {
967
1572
  it("should error if unsafe is an array", () => {
968
1573
  const { config, diagnostics } = normalizeAndValidateConfig(
969
1574
  { unsafe: [] } as unknown as RawConfig,
970
- undefined
1575
+ undefined,
1576
+ { env: undefined }
971
1577
  );
972
1578
 
973
1579
  expect(config).toEqual(
@@ -986,7 +1592,8 @@ describe("normalizeAndValidateConfig()", () => {
986
1592
  it("should error if unsafe is a string", () => {
987
1593
  const { config, diagnostics } = normalizeAndValidateConfig(
988
1594
  { unsafe: "BAD" } as unknown as RawConfig,
989
- undefined
1595
+ undefined,
1596
+ { env: undefined }
990
1597
  );
991
1598
 
992
1599
  expect(config).toEqual(
@@ -1005,7 +1612,8 @@ describe("normalizeAndValidateConfig()", () => {
1005
1612
  it("should error if unsafe is a number", () => {
1006
1613
  const { config, diagnostics } = normalizeAndValidateConfig(
1007
1614
  { unsafe: 999 } as unknown as RawConfig,
1008
- undefined
1615
+ undefined,
1616
+ { env: undefined }
1009
1617
  );
1010
1618
 
1011
1619
  expect(config).toEqual(
@@ -1024,7 +1632,8 @@ describe("normalizeAndValidateConfig()", () => {
1024
1632
  it("should error if unsafe is null", () => {
1025
1633
  const { config, diagnostics } = normalizeAndValidateConfig(
1026
1634
  { unsafe: null } as unknown as RawConfig,
1027
- undefined
1635
+ undefined,
1636
+ { env: undefined }
1028
1637
  );
1029
1638
 
1030
1639
  expect(config).toEqual(
@@ -1043,7 +1652,8 @@ describe("normalizeAndValidateConfig()", () => {
1043
1652
  it("should error if unsafe.bindings is not defined", () => {
1044
1653
  const { config, diagnostics } = normalizeAndValidateConfig(
1045
1654
  { unsafe: {} } as unknown as RawConfig,
1046
- undefined
1655
+ undefined,
1656
+ { env: undefined }
1047
1657
  );
1048
1658
 
1049
1659
  expect(config).toEqual(
@@ -1062,7 +1672,8 @@ describe("normalizeAndValidateConfig()", () => {
1062
1672
  it("should error if unsafe.bindings is an object", () => {
1063
1673
  const { config, diagnostics } = normalizeAndValidateConfig(
1064
1674
  { unsafe: { bindings: {} } } as unknown as RawConfig,
1065
- undefined
1675
+ undefined,
1676
+ { env: undefined }
1066
1677
  );
1067
1678
 
1068
1679
  expect(config).toEqual(
@@ -1083,7 +1694,8 @@ describe("normalizeAndValidateConfig()", () => {
1083
1694
  it("should error if unsafe.bindings is a string", () => {
1084
1695
  const { config, diagnostics } = normalizeAndValidateConfig(
1085
1696
  { unsafe: { bindings: "BAD" } } as unknown as RawConfig,
1086
- undefined
1697
+ undefined,
1698
+ { env: undefined }
1087
1699
  );
1088
1700
 
1089
1701
  expect(config).toEqual(
@@ -1104,7 +1716,8 @@ describe("normalizeAndValidateConfig()", () => {
1104
1716
  it("should error if unsafe.bindings is a number", () => {
1105
1717
  const { config, diagnostics } = normalizeAndValidateConfig(
1106
1718
  { unsafe: { bindings: 999 } } as unknown as RawConfig,
1107
- undefined
1719
+ undefined,
1720
+ { env: undefined }
1108
1721
  );
1109
1722
 
1110
1723
  expect(config).toEqual(
@@ -1125,7 +1738,8 @@ describe("normalizeAndValidateConfig()", () => {
1125
1738
  it("should error if unsafe.bindings is null", () => {
1126
1739
  const { config, diagnostics } = normalizeAndValidateConfig(
1127
1740
  { unsafe: { bindings: null } } as unknown as RawConfig,
1128
- undefined
1741
+ undefined,
1742
+ { env: undefined }
1129
1743
  );
1130
1744
 
1131
1745
  expect(config).toEqual(
@@ -1159,7 +1773,8 @@ describe("normalizeAndValidateConfig()", () => {
1159
1773
  ],
1160
1774
  },
1161
1775
  } as unknown as RawConfig,
1162
- undefined
1776
+ undefined,
1777
+ { env: undefined }
1163
1778
  );
1164
1779
 
1165
1780
  expect(config).toEqual(
@@ -1175,15 +1790,15 @@ describe("normalizeAndValidateConfig()", () => {
1175
1790
  "Processing wrangler configuration:
1176
1791
 
1177
1792
  - \\"unsafe.bindings[0]\\": {}
1178
- - ERROR: should have a string \\"name\\" field.
1179
- - ERROR: should have a string \\"type\\" field.
1793
+ - binding should have a string \\"name\\" field.
1794
+ - binding should have a string \\"type\\" field.
1180
1795
 
1181
1796
  - \\"unsafe.bindings[1]\\": {\\"name\\":\\"UNSAFE_BINDING_1\\"}
1182
- - ERROR: should have a string \\"type\\" field.
1797
+ - binding should have a string \\"type\\" field.
1183
1798
 
1184
1799
  - \\"unsafe.bindings[2]\\": {\\"name\\":2666,\\"type\\":2777}
1185
- - ERROR: should have a string \\"name\\" field.
1186
- - ERROR: should have a string \\"type\\" field."
1800
+ - binding should have a string \\"name\\" field.
1801
+ - binding should have a string \\"type\\" field."
1187
1802
  `);
1188
1803
  });
1189
1804
  });
@@ -1194,7 +1809,7 @@ describe("normalizeAndValidateConfig()", () => {
1194
1809
  zone_id: "ZONE_ID",
1195
1810
  experimental_services: [
1196
1811
  {
1197
- name: "NAME",
1812
+ name: "mock-name",
1198
1813
  service: "SERVICE",
1199
1814
  environment: "ENV",
1200
1815
  },
@@ -1203,7 +1818,8 @@ describe("normalizeAndValidateConfig()", () => {
1203
1818
 
1204
1819
  const { config, diagnostics } = normalizeAndValidateConfig(
1205
1820
  rawConfig,
1206
- undefined
1821
+ undefined,
1822
+ { env: undefined }
1207
1823
  );
1208
1824
 
1209
1825
  expect("experimental_services" in config).toBe(false);
@@ -1212,90 +1828,339 @@ describe("normalizeAndValidateConfig()", () => {
1212
1828
  expect(diagnostics.hasErrors()).toBe(false);
1213
1829
  expect(diagnostics.hasWarnings()).toBe(true);
1214
1830
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1215
- "Processing wrangler configuration:
1216
- - DEPRECATION: \\"zone_id\\":
1217
- This is unnecessary since we can deduce this from routes directly.
1218
- - DEPRECATION: \\"experimental_services\\":
1219
- The \\"experimental_services\\" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
1220
- \`\`\`
1221
- [[unsafe.bindings]]
1222
- name = \\"NAME\\"
1223
- type = \\"service\\"
1224
- service = \\"SERVICE\\"
1225
- environment = \\"ENV\\"
1226
- \`\`\`"
1227
- `);
1831
+ "Processing wrangler configuration:
1832
+ - Deprecation: \\"zone_id\\":
1833
+ This is unnecessary since we can deduce this from routes directly.
1834
+ - Deprecation: \\"experimental_services\\":
1835
+ The \\"experimental_services\\" field is no longer supported. Simply rename the [experimental_services] field to [services]."
1836
+ `);
1837
+ });
1838
+ });
1839
+
1840
+ describe("route & routes fields", () => {
1841
+ it("should error if both route and routes are specified", () => {
1842
+ const rawConfig: RawConfig = {
1843
+ route: "route1",
1844
+ routes: ["route2", "route3"],
1845
+ };
1846
+
1847
+ const { diagnostics } = normalizeAndValidateConfig(
1848
+ rawConfig,
1849
+ undefined,
1850
+ { env: undefined }
1851
+ );
1852
+
1853
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1854
+ "Processing wrangler configuration:
1855
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
1856
+ `);
1228
1857
  });
1229
1858
  });
1230
1859
  });
1231
1860
 
1232
1861
  describe("named environments", () => {
1862
+ it("should warn if we specify an environment but there are no named environments", () => {
1863
+ const rawConfig: RawConfig = {};
1864
+ const { diagnostics } = normalizeAndValidateConfig(rawConfig, undefined, {
1865
+ env: "DEV",
1866
+ });
1867
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1868
+ "Processing wrangler configuration:
1869
+ "
1870
+ `);
1871
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1872
+ "Processing wrangler configuration:
1873
+ - No environment found in configuration with name \\"DEV\\".
1874
+ Before using \`--env=DEV\` there should be an equivalent environment section in the configuration.
1875
+
1876
+ Consider adding an environment configuration section to the wrangler.toml file:
1877
+ \`\`\`
1878
+ [env.DEV]
1879
+ \`\`\`
1880
+ "
1881
+ `);
1882
+ });
1883
+
1884
+ it("should error if we specify an environment that does not match the named environments", () => {
1885
+ const rawConfig: RawConfig = { env: { ENV1: {} } };
1886
+ const { diagnostics } = normalizeAndValidateConfig(rawConfig, undefined, {
1887
+ env: "DEV",
1888
+ });
1889
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1890
+ "Processing wrangler configuration:
1891
+ - No environment found in configuration with name \\"DEV\\".
1892
+ Before using \`--env=DEV\` there should be an equivalent environment section in the configuration.
1893
+ The available configured environment names are: [\\"ENV1\\"]
1894
+
1895
+ Consider adding an environment configuration section to the wrangler.toml file:
1896
+ \`\`\`
1897
+ [env.DEV]
1898
+ \`\`\`
1899
+ "
1900
+ `);
1901
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1902
+ "Processing wrangler configuration:
1903
+ "
1904
+ `);
1905
+ });
1906
+
1233
1907
  it("should use top-level values for inheritable config fields", () => {
1234
- const expectedConfig: RawConfig = {
1235
- name: "NAME",
1908
+ const main = "src/index.ts";
1909
+ const resolvedMain = path.resolve(process.cwd(), main);
1910
+ const rawConfig: RawConfig = {
1911
+ name: "mock-name",
1236
1912
  account_id: "ACCOUNT_ID",
1237
1913
  compatibility_date: "2022-01-01",
1238
1914
  compatibility_flags: ["FLAG1", "FLAG2"],
1239
1915
  workers_dev: false,
1240
1916
  routes: ["ROUTE_1", "ROUTE_2"],
1241
- route: "ROUTE_3",
1242
1917
  jsx_factory: "JSX_FACTORY",
1243
1918
  jsx_fragment: "JSX_FRAGMENT",
1919
+ tsconfig: "path/to/tsconfig.json",
1244
1920
  triggers: { crons: ["CRON_1", "CRON_2"] },
1245
1921
  usage_model: "bundled",
1922
+ main,
1923
+ build: {
1924
+ command: "COMMAND",
1925
+ cwd: "CWD",
1926
+ watch_dir: "WATCH_DIR",
1927
+ },
1928
+ minify: true,
1929
+ node_compat: true,
1246
1930
  };
1247
1931
 
1248
1932
  const { config, diagnostics } = normalizeAndValidateConfig(
1249
- { ...expectedConfig, env: { DEV: {} } },
1250
- undefined
1933
+ { ...rawConfig, env: { dev: {} } },
1934
+ undefined,
1935
+ { env: "dev" }
1251
1936
  );
1252
1937
 
1253
- expect(config.env.DEV).toEqual(expect.objectContaining(expectedConfig));
1938
+ expect(config).toEqual(
1939
+ expect.objectContaining({
1940
+ ...rawConfig,
1941
+ main: resolvedMain,
1942
+ name: "mock-name-dev",
1943
+ })
1944
+ );
1254
1945
  expect(diagnostics.hasErrors()).toBe(false);
1255
1946
  expect(diagnostics.hasWarnings()).toBe(false);
1256
1947
  });
1257
1948
 
1258
1949
  it("should override top-level values for inheritable config fields", () => {
1259
- const environment: RawEnvironment = {
1260
- name: "ENV_NAME",
1950
+ const main = "src/index.ts";
1951
+ const resolvedMain = path.resolve(process.cwd(), main);
1952
+ const rawEnv: RawEnvironment = {
1953
+ name: "mock-env-name",
1261
1954
  account_id: "ENV_ACCOUNT_ID",
1262
1955
  compatibility_date: "2022-02-02",
1263
1956
  compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
1264
1957
  workers_dev: true,
1265
1958
  routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
1266
- route: "ENV_ROUTE_3",
1267
1959
  jsx_factory: "ENV_JSX_FACTORY",
1268
1960
  jsx_fragment: "ENV_JSX_FRAGMENT",
1961
+ tsconfig: "ENV_path/to/tsconfig.json",
1269
1962
  triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
1270
1963
  usage_model: "unbound",
1964
+ main,
1965
+ build: {
1966
+ command: "ENV_COMMAND",
1967
+ cwd: "ENV_CWD",
1968
+ watch_dir: "ENV_WATCH_DIR",
1969
+ },
1970
+ minify: false,
1971
+ node_compat: false,
1271
1972
  };
1272
- const expectedConfig: RawConfig = {
1273
- name: "NAME",
1973
+ const rawConfig: RawConfig = {
1974
+ name: "mock-name",
1274
1975
  account_id: "ACCOUNT_ID",
1275
1976
  compatibility_date: "2022-01-01",
1276
1977
  compatibility_flags: ["FLAG1", "FLAG2"],
1277
1978
  workers_dev: false,
1278
1979
  routes: ["ROUTE_1", "ROUTE_2"],
1279
- route: "ROUTE_3",
1280
1980
  jsx_factory: "JSX_FACTORY",
1281
1981
  jsx_fragment: "JSX_FRAGMENT",
1982
+ tsconfig: "path/to/tsconfig.json",
1282
1983
  triggers: { crons: ["CRON_1", "CRON_2"] },
1283
1984
  usage_model: "bundled",
1985
+ main: "top-level.js",
1986
+ build: {
1987
+ command: "COMMAND",
1988
+ cwd: "CWD",
1989
+ watch_dir: "WATCH_DIR",
1990
+ },
1991
+ minify: true,
1992
+ node_compat: true,
1284
1993
  env: {
1285
- ENV1: environment,
1994
+ ENV1: rawEnv,
1286
1995
  },
1287
1996
  };
1288
1997
 
1289
1998
  const { config, diagnostics } = normalizeAndValidateConfig(
1290
- expectedConfig,
1291
- undefined
1999
+ rawConfig,
2000
+ undefined,
2001
+ { env: "ENV1" }
1292
2002
  );
1293
2003
 
1294
- expect(config.env.ENV1).toEqual(expect.objectContaining(environment));
2004
+ expect(config).toEqual(
2005
+ expect.objectContaining({ ...rawEnv, main: resolvedMain })
2006
+ );
1295
2007
  expect(diagnostics.hasErrors()).toBe(false);
1296
2008
  expect(diagnostics.hasWarnings()).toBe(false);
1297
2009
  });
1298
2010
 
2011
+ describe("non-legacy", () => {
2012
+ it("should use top-level `name` field", () => {
2013
+ const rawConfig: RawConfig = {
2014
+ name: "mock-name",
2015
+ legacy_env: false,
2016
+ env: { DEV: {} },
2017
+ };
2018
+
2019
+ const { config, diagnostics } = normalizeAndValidateConfig(
2020
+ rawConfig,
2021
+ undefined,
2022
+ { env: "DEV" }
2023
+ );
2024
+
2025
+ expect(config.name).toEqual("mock-name");
2026
+ expect(diagnostics.hasErrors()).toBe(false);
2027
+ expect(diagnostics.hasWarnings()).toBe(true);
2028
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2029
+ "Processing wrangler configuration:
2030
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
2031
+ `);
2032
+ });
2033
+
2034
+ it("should error if named environment contains a `name` field, even if there is no top-level name", () => {
2035
+ const rawConfig: RawConfig = {
2036
+ legacy_env: false,
2037
+ env: {
2038
+ DEV: {
2039
+ name: "mock-env-name",
2040
+ },
2041
+ },
2042
+ };
2043
+
2044
+ const { config, diagnostics } = normalizeAndValidateConfig(
2045
+ rawConfig,
2046
+ undefined,
2047
+ { env: "DEV" }
2048
+ );
2049
+
2050
+ expect(config.name).toBeUndefined();
2051
+ expect(diagnostics.hasWarnings()).toBe(true);
2052
+ expect(diagnostics.hasErrors()).toBe(true);
2053
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2054
+ "Processing wrangler configuration:
2055
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
2056
+ `);
2057
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2058
+ "Processing wrangler configuration:
2059
+
2060
+ - \\"env.DEV\\" environment configuration
2061
+ - The \\"name\\" field is not allowed in named service environments.
2062
+ Please remove the field from this environment."
2063
+ `);
2064
+ });
2065
+
2066
+ it("should error if top-level config and a named environment both contain a `name` field", () => {
2067
+ const rawConfig: RawConfig = {
2068
+ name: "mock-name",
2069
+ legacy_env: false,
2070
+ env: {
2071
+ DEV: {
2072
+ name: "mock-env-name",
2073
+ },
2074
+ },
2075
+ };
2076
+
2077
+ const { config, diagnostics } = normalizeAndValidateConfig(
2078
+ rawConfig,
2079
+ undefined,
2080
+ { env: "DEV" }
2081
+ );
2082
+
2083
+ expect(config.name).toEqual("mock-name");
2084
+ expect(diagnostics.hasWarnings()).toBe(true);
2085
+ expect(diagnostics.hasErrors()).toBe(true);
2086
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2087
+ "Processing wrangler configuration:
2088
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
2089
+ `);
2090
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2091
+ "Processing wrangler configuration:
2092
+
2093
+ - \\"env.DEV\\" environment configuration
2094
+ - The \\"name\\" field is not allowed in named service environments.
2095
+ Please remove the field from this environment."
2096
+ `);
2097
+ });
2098
+ });
2099
+
2100
+ it("should error if named environment contains a `account_id` field, even if there is no top-level name", () => {
2101
+ const rawConfig: RawConfig = {
2102
+ legacy_env: false,
2103
+ env: {
2104
+ DEV: {
2105
+ account_id: "some_account_id",
2106
+ },
2107
+ },
2108
+ };
2109
+
2110
+ const { config, diagnostics } = normalizeAndValidateConfig(
2111
+ rawConfig,
2112
+ undefined,
2113
+ { env: "DEV" }
2114
+ );
2115
+
2116
+ expect(diagnostics.hasWarnings()).toBe(true);
2117
+ expect(config.account_id).toBeUndefined();
2118
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2119
+ "Processing wrangler configuration:
2120
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
2121
+ `);
2122
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2123
+ "Processing wrangler configuration:
2124
+
2125
+ - \\"env.DEV\\" environment configuration
2126
+ - The \\"account_id\\" field is not allowed in named service environments.
2127
+ Please remove the field from this environment."
2128
+ `);
2129
+ });
2130
+
2131
+ it("should error if top-level config and a named environment both contain a `account_id` field", () => {
2132
+ const rawConfig: RawConfig = {
2133
+ account_id: "ACCOUNT_ID",
2134
+ legacy_env: false,
2135
+ env: {
2136
+ DEV: {
2137
+ account_id: "ENV_ACCOUNT_ID",
2138
+ },
2139
+ },
2140
+ };
2141
+
2142
+ const { config, diagnostics } = normalizeAndValidateConfig(
2143
+ rawConfig,
2144
+ undefined,
2145
+ { env: "DEV" }
2146
+ );
2147
+
2148
+ expect(config.account_id).toEqual("ACCOUNT_ID");
2149
+ expect(diagnostics.hasErrors()).toBe(true);
2150
+ expect(diagnostics.hasWarnings()).toBe(true);
2151
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2152
+ "Processing wrangler configuration:
2153
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in the future. DO NOT USE IN PRODUCTION."
2154
+ `);
2155
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2156
+ "Processing wrangler configuration:
2157
+
2158
+ - \\"env.DEV\\" environment configuration
2159
+ - The \\"account_id\\" field is not allowed in named service environments.
2160
+ Please remove the field from this environment."
2161
+ `);
2162
+ });
2163
+
1299
2164
  it("should warn for non-inherited fields that are missing in environments", () => {
1300
2165
  const vars: RawConfig["vars"] = {
1301
2166
  FOO: "foo",
@@ -1319,10 +2184,11 @@ describe("normalizeAndValidateConfig()", () => {
1319
2184
 
1320
2185
  const { config, diagnostics } = normalizeAndValidateConfig(
1321
2186
  rawConfig,
1322
- undefined
2187
+ undefined,
2188
+ { env: "ENV1" }
1323
2189
  );
1324
2190
 
1325
- expect(config.env.ENV1).toEqual(
2191
+ expect(config).toEqual(
1326
2192
  expect.not.objectContaining({
1327
2193
  vars,
1328
2194
  durable_objects,
@@ -1365,31 +2231,52 @@ describe("normalizeAndValidateConfig()", () => {
1365
2231
  route: 888,
1366
2232
  jsx_factory: 999,
1367
2233
  jsx_fragment: 1000,
2234
+ tsconfig: 123,
1368
2235
  triggers: { crons: [1111, 1222] },
1369
2236
  usage_model: "INVALID",
2237
+ main: 1333,
2238
+ build: {
2239
+ command: 1444,
2240
+ cwd: 1555,
2241
+ watch_dir: 1666,
2242
+ },
2243
+ minify: "INVALID",
2244
+ node_compat: "INVALID",
1370
2245
  } as unknown as RawEnvironment;
1371
2246
 
1372
2247
  const { config, diagnostics } = normalizeAndValidateConfig(
1373
2248
  { env: { ENV1: expectedConfig } },
1374
- undefined
2249
+ undefined,
2250
+ { env: "ENV1" }
1375
2251
  );
1376
2252
 
1377
- expect(config.env.ENV1).toEqual(expect.objectContaining(expectedConfig));
2253
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
1378
2254
  expect(diagnostics.hasWarnings()).toBe(false);
1379
2255
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1380
2256
  "Processing wrangler configuration:
1381
2257
 
1382
2258
  - \\"env.ENV1\\" environment configuration
1383
- - Expected \\"route\\" field to be a string but got 888.
1384
- - Expected \\"routes\\" field to be an array of strings but got [666,777].
1385
- - Expected \\"workers_dev\\" field to be a boolean but got \\"BAD\\".
1386
- - Expected \\"account_id\\" field to be a string but got 222.
1387
- - Expected \\"compatibility_date\\" field to be a string but got 333.
1388
- - Expected \\"compatibility_flags\\" field to be an array of strings but got [444,555].
1389
- - Expected \\"jsx_factory\\" field to be a string but got 999.
1390
- - Expected \\"jsx_fragment\\" field to be a string but got 1000.
1391
- - Expected \\"name\\" field to be a string but got 111.
1392
- - Expected \\"usage_model\\" field to be on of bundled,unbound but got \\"INVALID\\"."
2259
+ - Expected \\"route\\" to be either a string, or an object with shape { pattern, custom_domain, zone_id | zone_name }, but got 888.
2260
+ - Expected \\"routes\\" to be an array of either strings or objects with the shape { pattern, custom_domain, zone_id | zone_name }, but these weren't valid: [
2261
+ 666,
2262
+ 777
2263
+ ].
2264
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"].
2265
+ - Expected \\"workers_dev\\" to be of type boolean but got \\"BAD\\".
2266
+ - Expected \\"build.command\\" to be of type string but got 1444.
2267
+ - Expected \\"build.cwd\\" to be of type string but got 1555.
2268
+ - Expected \\"build.watch_dir\\" to be of type string but got 1666.
2269
+ - Expected \\"account_id\\" to be of type string but got 222.
2270
+ - Expected \\"compatibility_date\\" to be of type string but got 333.
2271
+ - Expected \\"compatibility_flags\\" to be of type string array but got [444,555].
2272
+ - Expected \\"jsx_factory\\" to be of type string but got 999.
2273
+ - Expected \\"jsx_fragment\\" to be of type string but got 1000.
2274
+ - Expected \\"tsconfig\\" to be of type string but got 123.
2275
+ - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got 111.
2276
+ - Expected \\"main\\" to be of type string but got 1333.
2277
+ - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\".
2278
+ - Expected \\"minify\\" to be of type boolean but got \\"INVALID\\".
2279
+ - Expected \\"node_compat\\" to be of type boolean but got \\"INVALID\\"."
1393
2280
  `);
1394
2281
  });
1395
2282
 
@@ -1397,10 +2284,11 @@ describe("normalizeAndValidateConfig()", () => {
1397
2284
  it("should error if durable_objects is an array", () => {
1398
2285
  const { config, diagnostics } = normalizeAndValidateConfig(
1399
2286
  { env: { ENV1: { durable_objects: [] } } } as unknown as RawConfig,
1400
- undefined
2287
+ undefined,
2288
+ { env: "ENV1" }
1401
2289
  );
1402
2290
 
1403
- expect(config.env.ENV1).toEqual(
2291
+ expect(config).toEqual(
1404
2292
  expect.not.objectContaining({ durable_objects: expect.anything })
1405
2293
  );
1406
2294
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1415,10 +2303,11 @@ describe("normalizeAndValidateConfig()", () => {
1415
2303
  it("should error if durable_objects is a string", () => {
1416
2304
  const { config, diagnostics } = normalizeAndValidateConfig(
1417
2305
  { env: { ENV1: { durable_objects: "BAD" } } } as unknown as RawConfig,
1418
- undefined
2306
+ undefined,
2307
+ { env: "ENV1" }
1419
2308
  );
1420
2309
 
1421
- expect(config.env.ENV1).toEqual(
2310
+ expect(config).toEqual(
1422
2311
  expect.not.objectContaining({ durable_objects: expect.anything })
1423
2312
  );
1424
2313
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1433,10 +2322,11 @@ describe("normalizeAndValidateConfig()", () => {
1433
2322
  it("should error if durable_objects is a number", () => {
1434
2323
  const { config, diagnostics } = normalizeAndValidateConfig(
1435
2324
  { env: { ENV1: { durable_objects: 999 } } } as unknown as RawConfig,
1436
- undefined
2325
+ undefined,
2326
+ { env: "ENV1" }
1437
2327
  );
1438
2328
 
1439
- expect(config.env.ENV1).toEqual(
2329
+ expect(config).toEqual(
1440
2330
  expect.not.objectContaining({ durable_objects: expect.anything })
1441
2331
  );
1442
2332
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1451,10 +2341,11 @@ describe("normalizeAndValidateConfig()", () => {
1451
2341
  it("should error if durable_objects is null", () => {
1452
2342
  const { config, diagnostics } = normalizeAndValidateConfig(
1453
2343
  { env: { ENV1: { durable_objects: null } } } as unknown as RawConfig,
1454
- undefined
2344
+ undefined,
2345
+ { env: "ENV1" }
1455
2346
  );
1456
2347
 
1457
- expect(config.env.ENV1).toEqual(
2348
+ expect(config).toEqual(
1458
2349
  expect.not.objectContaining({ durable_objects: expect.anything })
1459
2350
  );
1460
2351
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1469,10 +2360,11 @@ describe("normalizeAndValidateConfig()", () => {
1469
2360
  it("should error if durable_objects.bindings is not defined", () => {
1470
2361
  const { config, diagnostics } = normalizeAndValidateConfig(
1471
2362
  { env: { ENV1: { durable_objects: {} } } } as unknown as RawConfig,
1472
- undefined
2363
+ undefined,
2364
+ { env: "ENV1" }
1473
2365
  );
1474
2366
 
1475
- expect(config.env.ENV1).toEqual(
2367
+ expect(config).toEqual(
1476
2368
  expect.not.objectContaining({ durable_objects: expect.anything })
1477
2369
  );
1478
2370
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1489,10 +2381,11 @@ describe("normalizeAndValidateConfig()", () => {
1489
2381
  {
1490
2382
  env: { ENV1: { durable_objects: { bindings: {} } } },
1491
2383
  } as unknown as RawConfig,
1492
- undefined
2384
+ undefined,
2385
+ { env: "ENV1" }
1493
2386
  );
1494
2387
 
1495
- expect(config.env.ENV1).toEqual(
2388
+ expect(config).toEqual(
1496
2389
  expect.not.objectContaining({
1497
2390
  durable_objects: { bindings: expect.anything },
1498
2391
  })
@@ -1511,10 +2404,11 @@ describe("normalizeAndValidateConfig()", () => {
1511
2404
  {
1512
2405
  env: { ENV1: { durable_objects: { bindings: "BAD" } } },
1513
2406
  } as unknown as RawConfig,
1514
- undefined
2407
+ undefined,
2408
+ { env: "ENV1" }
1515
2409
  );
1516
2410
 
1517
- expect(config.env.ENV1).toEqual(
2411
+ expect(config).toEqual(
1518
2412
  expect.not.objectContaining({
1519
2413
  durable_objects: { bindings: expect.anything },
1520
2414
  })
@@ -1533,10 +2427,11 @@ describe("normalizeAndValidateConfig()", () => {
1533
2427
  {
1534
2428
  env: { ENV1: { durable_objects: { bindings: 999 } } },
1535
2429
  } as unknown as RawConfig,
1536
- undefined
2430
+ undefined,
2431
+ { env: "ENV1" }
1537
2432
  );
1538
2433
 
1539
- expect(config.env.ENV1).toEqual(
2434
+ expect(config).toEqual(
1540
2435
  expect.not.objectContaining({
1541
2436
  durable_objects: { bindings: expect.anything },
1542
2437
  })
@@ -1555,10 +2450,11 @@ describe("normalizeAndValidateConfig()", () => {
1555
2450
  {
1556
2451
  env: { ENV1: { durable_objects: { bindings: null } } },
1557
2452
  } as unknown as RawConfig,
1558
- undefined
2453
+ undefined,
2454
+ { env: "ENV1" }
1559
2455
  );
1560
2456
 
1561
- expect(config.env.ENV1).toEqual(
2457
+ expect(config).toEqual(
1562
2458
  expect.not.objectContaining({
1563
2459
  durable_objects: { bindings: expect.anything },
1564
2460
  })
@@ -1592,35 +2488,37 @@ describe("normalizeAndValidateConfig()", () => {
1592
2488
  },
1593
2489
  },
1594
2490
  } as unknown as RawConfig,
1595
- undefined
2491
+ undefined,
2492
+ { env: "ENV1" }
1596
2493
  );
1597
2494
 
1598
- expect(config.env.ENV1).toEqual(
2495
+ expect(config).toEqual(
1599
2496
  expect.not.objectContaining({
1600
2497
  durable_objects: { bindings: expect.anything },
1601
2498
  })
1602
2499
  );
1603
2500
  expect(diagnostics.hasWarnings()).toBe(false);
2501
+ expect(diagnostics.hasErrors()).toBe(true);
1604
2502
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1605
2503
  "Processing wrangler configuration:
1606
2504
 
1607
2505
  - \\"env.ENV1\\" environment configuration
1608
2506
 
1609
2507
  - \\"env.ENV1.durable_objects.bindings[0]\\": {}
1610
- - ERROR: bindings should have a string \\"name\\" field.
1611
- - ERROR: should have a string \\"class_name\\" field.
2508
+ - binding should have a string \\"name\\" field.
2509
+ - binding should have a string \\"class_name\\" field.
1612
2510
 
1613
2511
  - \\"env.ENV1.durable_objects.bindings[1]\\": {\\"name\\":\\"VALID\\"}
1614
- - ERROR: should have a string \\"class_name\\" field.
2512
+ - binding should have a string \\"class_name\\" field.
1615
2513
 
1616
2514
  - \\"env.ENV1.durable_objects.bindings[2]\\": {\\"name\\":1555,\\"class_name\\":1666}
1617
- - ERROR: bindings should have a string \\"name\\" field.
1618
- - ERROR: should have a string \\"class_name\\" field.
2515
+ - binding should have a string \\"name\\" field.
2516
+ - binding should have a string \\"class_name\\" field.
1619
2517
 
1620
2518
  - \\"env.ENV1.durable_objects.bindings[3]\\": {\\"name\\":1777,\\"class_name\\":1888,\\"script_name\\":1999}
1621
- - ERROR: bindings should have a string \\"name\\" field.
1622
- - ERROR: should have a string \\"class_name\\" field.
1623
- - ERROR: should, optionally, have a string \\"script_name\\" field."
2519
+ - binding should have a string \\"name\\" field.
2520
+ - binding should have a string \\"class_name\\" field.
2521
+ - the field \\"script_name\\", when present, should be a string."
1624
2522
  `);
1625
2523
  });
1626
2524
  });
@@ -1629,10 +2527,11 @@ describe("normalizeAndValidateConfig()", () => {
1629
2527
  it("should error if kv_namespaces is an object", () => {
1630
2528
  const { config, diagnostics } = normalizeAndValidateConfig(
1631
2529
  { env: { ENV1: { kv_namespaces: {} } } } as unknown as RawConfig,
1632
- undefined
2530
+ undefined,
2531
+ { env: "ENV1" }
1633
2532
  );
1634
2533
 
1635
- expect(config.env.ENV1).toEqual(
2534
+ expect(config).toEqual(
1636
2535
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1637
2536
  );
1638
2537
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1647,10 +2546,11 @@ describe("normalizeAndValidateConfig()", () => {
1647
2546
  it("should error if kv_namespaces is a string", () => {
1648
2547
  const { config, diagnostics } = normalizeAndValidateConfig(
1649
2548
  { env: { ENV1: { kv_namespaces: "BAD" } } } as unknown as RawConfig,
1650
- undefined
2549
+ undefined,
2550
+ { env: "ENV1" }
1651
2551
  );
1652
2552
 
1653
- expect(config.env.ENV1).toEqual(
2553
+ expect(config).toEqual(
1654
2554
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1655
2555
  );
1656
2556
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1665,10 +2565,11 @@ describe("normalizeAndValidateConfig()", () => {
1665
2565
  it("should error if kv_namespaces is a number", () => {
1666
2566
  const { config, diagnostics } = normalizeAndValidateConfig(
1667
2567
  { env: { ENV1: { kv_namespaces: 999 } } } as unknown as RawConfig,
1668
- undefined
2568
+ undefined,
2569
+ { env: "ENV1" }
1669
2570
  );
1670
2571
 
1671
- expect(config.env.ENV1).toEqual(
2572
+ expect(config).toEqual(
1672
2573
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1673
2574
  );
1674
2575
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1683,10 +2584,11 @@ describe("normalizeAndValidateConfig()", () => {
1683
2584
  it("should error if kv_namespaces is null", () => {
1684
2585
  const { config, diagnostics } = normalizeAndValidateConfig(
1685
2586
  { env: { ENV1: { kv_namespaces: null } } } as unknown as RawConfig,
1686
- undefined
2587
+ undefined,
2588
+ { env: "ENV1" }
1687
2589
  );
1688
2590
 
1689
- expect(config.env.ENV1).toEqual(
2591
+ expect(config).toEqual(
1690
2592
  expect.not.objectContaining({ kv_namespaces: expect.anything })
1691
2593
  );
1692
2594
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1716,10 +2618,11 @@ describe("normalizeAndValidateConfig()", () => {
1716
2618
  },
1717
2619
  },
1718
2620
  } as unknown as RawConfig,
1719
- undefined
2621
+ undefined,
2622
+ { env: "ENV1" }
1720
2623
  );
1721
2624
 
1722
- expect(config.env.ENV1).toEqual(
2625
+ expect(config).toEqual(
1723
2626
  expect.not.objectContaining({
1724
2627
  kv_namespaces: { bindings: expect.anything },
1725
2628
  })
@@ -1743,10 +2646,11 @@ describe("normalizeAndValidateConfig()", () => {
1743
2646
  it("should error if r2_buckets is an object", () => {
1744
2647
  const { config, diagnostics } = normalizeAndValidateConfig(
1745
2648
  { env: { ENV1: { r2_buckets: {} } } } as unknown as RawConfig,
1746
- undefined
2649
+ undefined,
2650
+ { env: "ENV1" }
1747
2651
  );
1748
2652
 
1749
- expect(config.env.ENV1).toEqual(
2653
+ expect(config).toEqual(
1750
2654
  expect.not.objectContaining({ r2_buckets: expect.anything })
1751
2655
  );
1752
2656
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1761,10 +2665,11 @@ describe("normalizeAndValidateConfig()", () => {
1761
2665
  it("should error if r2_buckets is a string", () => {
1762
2666
  const { config, diagnostics } = normalizeAndValidateConfig(
1763
2667
  { env: { ENV1: { r2_buckets: "BAD" } } } as unknown as RawConfig,
1764
- undefined
2668
+ undefined,
2669
+ { env: "ENV1" }
1765
2670
  );
1766
2671
 
1767
- expect(config.env.ENV1).toEqual(
2672
+ expect(config).toEqual(
1768
2673
  expect.not.objectContaining({ r2_buckets: expect.anything })
1769
2674
  );
1770
2675
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1779,10 +2684,11 @@ describe("normalizeAndValidateConfig()", () => {
1779
2684
  it("should error if r2_buckets is a number", () => {
1780
2685
  const { config, diagnostics } = normalizeAndValidateConfig(
1781
2686
  { env: { ENV1: { r2_buckets: 999 } } } as unknown as RawConfig,
1782
- undefined
2687
+ undefined,
2688
+ { env: "ENV1" }
1783
2689
  );
1784
2690
 
1785
- expect(config.env.ENV1).toEqual(
2691
+ expect(config).toEqual(
1786
2692
  expect.not.objectContaining({ r2_buckets: expect.anything })
1787
2693
  );
1788
2694
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1797,10 +2703,11 @@ describe("normalizeAndValidateConfig()", () => {
1797
2703
  it("should error if r2_buckets is null", () => {
1798
2704
  const { config, diagnostics } = normalizeAndValidateConfig(
1799
2705
  { env: { ENV1: { r2_buckets: null } } } as unknown as RawConfig,
1800
- undefined
2706
+ undefined,
2707
+ { env: "ENV1" }
1801
2708
  );
1802
2709
 
1803
- expect(config.env.ENV1).toEqual(
2710
+ expect(config).toEqual(
1804
2711
  expect.not.objectContaining({ r2_buckets: expect.anything })
1805
2712
  );
1806
2713
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -1830,10 +2737,11 @@ describe("normalizeAndValidateConfig()", () => {
1830
2737
  },
1831
2738
  },
1832
2739
  } as unknown as RawConfig,
1833
- undefined
2740
+ undefined,
2741
+ { env: "ENV1" }
1834
2742
  );
1835
2743
 
1836
- expect(config.env.ENV1).toEqual(
2744
+ expect(config).toEqual(
1837
2745
  expect.not.objectContaining({
1838
2746
  r2_buckets: { bindings: expect.anything },
1839
2747
  })
@@ -1857,10 +2765,11 @@ describe("normalizeAndValidateConfig()", () => {
1857
2765
  it("should error if unsafe is an array", () => {
1858
2766
  const { config, diagnostics } = normalizeAndValidateConfig(
1859
2767
  { env: { ENV1: { unsafe: [] } } } as unknown as RawConfig,
1860
- undefined
2768
+ undefined,
2769
+ { env: "ENV1" }
1861
2770
  );
1862
2771
 
1863
- expect(config.env.ENV1).toEqual(
2772
+ expect(config).toEqual(
1864
2773
  expect.not.objectContaining({ unsafe: expect.anything })
1865
2774
  );
1866
2775
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1880,10 +2789,11 @@ describe("normalizeAndValidateConfig()", () => {
1880
2789
  it("should error if unsafe is a string", () => {
1881
2790
  const { config, diagnostics } = normalizeAndValidateConfig(
1882
2791
  { env: { ENV1: { unsafe: "BAD" } } } as unknown as RawConfig,
1883
- undefined
2792
+ undefined,
2793
+ { env: "ENV1" }
1884
2794
  );
1885
2795
 
1886
- expect(config.env.ENV1).toEqual(
2796
+ expect(config).toEqual(
1887
2797
  expect.not.objectContaining({ unsafe: expect.anything })
1888
2798
  );
1889
2799
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1903,10 +2813,11 @@ describe("normalizeAndValidateConfig()", () => {
1903
2813
  it("should error if unsafe is a number", () => {
1904
2814
  const { config, diagnostics } = normalizeAndValidateConfig(
1905
2815
  { env: { ENV1: { unsafe: 999 } } } as unknown as RawConfig,
1906
- undefined
2816
+ undefined,
2817
+ { env: "ENV1" }
1907
2818
  );
1908
2819
 
1909
- expect(config.env.ENV1).toEqual(
2820
+ expect(config).toEqual(
1910
2821
  expect.not.objectContaining({ unsafe: expect.anything })
1911
2822
  );
1912
2823
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1926,10 +2837,11 @@ describe("normalizeAndValidateConfig()", () => {
1926
2837
  it("should error if unsafe is null", () => {
1927
2838
  const { config, diagnostics } = normalizeAndValidateConfig(
1928
2839
  { env: { ENV1: { unsafe: null } } } as unknown as RawConfig,
1929
- undefined
2840
+ undefined,
2841
+ { env: "ENV1" }
1930
2842
  );
1931
2843
 
1932
- expect(config.env.ENV1).toEqual(
2844
+ expect(config).toEqual(
1933
2845
  expect.not.objectContaining({ unsafe: expect.anything })
1934
2846
  );
1935
2847
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1949,10 +2861,11 @@ describe("normalizeAndValidateConfig()", () => {
1949
2861
  it("should error if unsafe.bindings is not defined", () => {
1950
2862
  const { config, diagnostics } = normalizeAndValidateConfig(
1951
2863
  { env: { ENV1: { unsafe: {} } } } as unknown as RawConfig,
1952
- undefined
2864
+ undefined,
2865
+ { env: "ENV1" }
1953
2866
  );
1954
2867
 
1955
- expect(config.env.ENV1).toEqual(
2868
+ expect(config).toEqual(
1956
2869
  expect.not.objectContaining({ unsafe: expect.anything })
1957
2870
  );
1958
2871
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
@@ -1974,10 +2887,11 @@ describe("normalizeAndValidateConfig()", () => {
1974
2887
  {
1975
2888
  env: { ENV1: { unsafe: { bindings: {} } } },
1976
2889
  } as unknown as RawConfig,
1977
- undefined
2890
+ undefined,
2891
+ { env: "ENV1" }
1978
2892
  );
1979
2893
 
1980
- expect(config.env.ENV1).toEqual(
2894
+ expect(config).toEqual(
1981
2895
  expect.not.objectContaining({
1982
2896
  unsafe: { bindings: expect.anything },
1983
2897
  })
@@ -2001,10 +2915,11 @@ describe("normalizeAndValidateConfig()", () => {
2001
2915
  {
2002
2916
  env: { ENV1: { unsafe: { bindings: "BAD" } } },
2003
2917
  } as unknown as RawConfig,
2004
- undefined
2918
+ undefined,
2919
+ { env: "ENV1" }
2005
2920
  );
2006
2921
 
2007
- expect(config.env.ENV1).toEqual(
2922
+ expect(config).toEqual(
2008
2923
  expect.not.objectContaining({
2009
2924
  unsafe: { bindings: expect.anything },
2010
2925
  })
@@ -2028,10 +2943,11 @@ describe("normalizeAndValidateConfig()", () => {
2028
2943
  {
2029
2944
  env: { ENV1: { unsafe: { bindings: 999 } } },
2030
2945
  } as unknown as RawConfig,
2031
- undefined
2946
+ undefined,
2947
+ { env: "ENV1" }
2032
2948
  );
2033
2949
 
2034
- expect(config.env.ENV1).toEqual(
2950
+ expect(config).toEqual(
2035
2951
  expect.not.objectContaining({
2036
2952
  unsafe: { bindings: expect.anything },
2037
2953
  })
@@ -2055,10 +2971,11 @@ describe("normalizeAndValidateConfig()", () => {
2055
2971
  {
2056
2972
  env: { ENV1: { unsafe: { bindings: null } } },
2057
2973
  } as unknown as RawConfig,
2058
- undefined
2974
+ undefined,
2975
+ { env: "ENV1" }
2059
2976
  );
2060
2977
 
2061
- expect(config.env.ENV1).toEqual(
2978
+ expect(config).toEqual(
2062
2979
  expect.not.objectContaining({
2063
2980
  unsafe: { bindings: expect.anything },
2064
2981
  })
@@ -2097,10 +3014,11 @@ describe("normalizeAndValidateConfig()", () => {
2097
3014
  },
2098
3015
  },
2099
3016
  } as unknown as RawConfig,
2100
- undefined
3017
+ undefined,
3018
+ { env: "ENV1" }
2101
3019
  );
2102
3020
 
2103
- expect(config.env.ENV1).toEqual(
3021
+ expect(config).toEqual(
2104
3022
  expect.not.objectContaining({
2105
3023
  durable_objects: { bindings: expect.anything },
2106
3024
  })
@@ -2117,15 +3035,15 @@ describe("normalizeAndValidateConfig()", () => {
2117
3035
  - \\"env.ENV1\\" environment configuration
2118
3036
 
2119
3037
  - \\"env.ENV1.unsafe.bindings[0]\\": {}
2120
- - ERROR: should have a string \\"name\\" field.
2121
- - ERROR: should have a string \\"type\\" field.
3038
+ - binding should have a string \\"name\\" field.
3039
+ - binding should have a string \\"type\\" field.
2122
3040
 
2123
3041
  - \\"env.ENV1.unsafe.bindings[1]\\": {\\"name\\":\\"UNSAFE_BINDING_1\\"}
2124
- - ERROR: should have a string \\"type\\" field.
3042
+ - binding should have a string \\"type\\" field.
2125
3043
 
2126
3044
  - \\"env.ENV1.unsafe.bindings[2]\\": {\\"name\\":2666,\\"type\\":2777}
2127
- - ERROR: should have a string \\"name\\" field.
2128
- - ERROR: should have a string \\"type\\" field."
3045
+ - binding should have a string \\"name\\" field.
3046
+ - binding should have a string \\"type\\" field."
2129
3047
  `);
2130
3048
  });
2131
3049
  });
@@ -2136,7 +3054,7 @@ describe("normalizeAndValidateConfig()", () => {
2136
3054
  zone_id: "ZONE_ID",
2137
3055
  experimental_services: [
2138
3056
  {
2139
- name: "NAME",
3057
+ name: "mock-name",
2140
3058
  service: "SERVICE",
2141
3059
  environment: "ENV",
2142
3060
  },
@@ -2149,31 +3067,260 @@ describe("normalizeAndValidateConfig()", () => {
2149
3067
  ENV1: environment,
2150
3068
  },
2151
3069
  },
2152
- undefined
3070
+ undefined,
3071
+ { env: "ENV1" }
2153
3072
  );
2154
3073
 
2155
- expect("experimental_services" in config.env.ENV1).toBe(false);
3074
+ expect("experimental_services" in config).toBe(false);
2156
3075
  // Zone is not removed yet, since `route` commands might use it
2157
- expect(config.env.ENV1.zone_id).toEqual("ZONE_ID");
3076
+ expect(config.zone_id).toEqual("ZONE_ID");
2158
3077
  expect(diagnostics.hasErrors()).toBe(false);
2159
3078
  expect(diagnostics.hasWarnings()).toBe(true);
2160
3079
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2161
3080
  "Processing wrangler configuration:
2162
3081
 
2163
3082
  - \\"env.ENV1\\" environment configuration
2164
- - DEPRECATION: \\"zone_id\\":
3083
+ - Deprecation: \\"zone_id\\":
2165
3084
  This is unnecessary since we can deduce this from routes directly.
2166
- - DEPRECATION: \\"experimental_services\\":
2167
- The \\"experimental_services\\" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
2168
- \`\`\`
2169
- [[unsafe.bindings]]
2170
- name = \\"NAME\\"
2171
- type = \\"service\\"
2172
- service = \\"SERVICE\\"
2173
- environment = \\"ENV\\"
2174
- \`\`\`"
3085
+ - Deprecation: \\"experimental_services\\":
3086
+ The \\"experimental_services\\" field is no longer supported. Simply rename the [experimental_services] field to [services]."
3087
+ `);
3088
+ });
3089
+ });
3090
+
3091
+ describe("route & routes fields", () => {
3092
+ it("should error if both route and routes are specified in the same environment", () => {
3093
+ const environment: RawEnvironment = {
3094
+ name: "mock-env-name",
3095
+ account_id: "ENV_ACCOUNT_ID",
3096
+ compatibility_date: "2022-02-02",
3097
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3098
+ workers_dev: true,
3099
+ route: "ENV_ROUTE_1",
3100
+ routes: ["ENV_ROUTE_2", "ENV_ROUTE_3"],
3101
+ jsx_factory: "ENV_JSX_FACTORY",
3102
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3103
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3104
+ usage_model: "unbound",
3105
+ };
3106
+ const expectedConfig: RawConfig = {
3107
+ name: "mock-name",
3108
+ account_id: "ACCOUNT_ID",
3109
+ compatibility_date: "2022-01-01",
3110
+ compatibility_flags: ["FLAG1", "FLAG2"],
3111
+ workers_dev: false,
3112
+ routes: ["ROUTE_1", "ROUTE_2"],
3113
+ jsx_factory: "JSX_FACTORY",
3114
+ jsx_fragment: "JSX_FRAGMENT",
3115
+ triggers: { crons: ["CRON_1", "CRON_2"] },
3116
+ usage_model: "bundled",
3117
+ env: {
3118
+ ENV1: environment,
3119
+ },
3120
+ };
3121
+
3122
+ const { config, diagnostics } = normalizeAndValidateConfig(
3123
+ expectedConfig,
3124
+ undefined,
3125
+ { env: "ENV1" }
3126
+ );
3127
+
3128
+ expect(config).toEqual(expect.objectContaining(environment));
3129
+ expect(diagnostics.hasErrors()).toBe(true);
3130
+ expect(diagnostics.hasWarnings()).toBe(false);
3131
+
3132
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
3133
+ "Processing wrangler configuration:
3134
+
3135
+ - \\"env.ENV1\\" environment configuration
3136
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
3137
+ `);
3138
+ });
3139
+
3140
+ it("should error if both route and routes are specified in the top-level environment", () => {
3141
+ const environment: RawEnvironment = {
3142
+ name: "mock-env-name",
3143
+ account_id: "ENV_ACCOUNT_ID",
3144
+ compatibility_date: "2022-02-02",
3145
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3146
+ workers_dev: true,
3147
+ routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
3148
+ jsx_factory: "ENV_JSX_FACTORY",
3149
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3150
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3151
+ usage_model: "unbound",
3152
+ };
3153
+ const expectedConfig: RawConfig = {
3154
+ name: "mock-name",
3155
+ account_id: "ACCOUNT_ID",
3156
+ compatibility_date: "2022-01-01",
3157
+ compatibility_flags: ["FLAG1", "FLAG2"],
3158
+ workers_dev: false,
3159
+ route: "ROUTE_1",
3160
+ routes: ["ROUTE_2", "ROUTE_3"],
3161
+ jsx_factory: "JSX_FACTORY",
3162
+ jsx_fragment: "JSX_FRAGMENT",
3163
+ triggers: { crons: ["CRON_1", "CRON_2"] },
3164
+ usage_model: "bundled",
3165
+ env: {
3166
+ ENV1: environment,
3167
+ },
3168
+ };
3169
+
3170
+ const { config, diagnostics } = normalizeAndValidateConfig(
3171
+ expectedConfig,
3172
+ undefined,
3173
+ { env: "ENV1" }
3174
+ );
3175
+
3176
+ expect(config).toEqual(expect.objectContaining(environment));
3177
+ expect(diagnostics.hasErrors()).toBe(true);
3178
+ expect(diagnostics.hasWarnings()).toBe(false);
3179
+
3180
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
3181
+ "Processing wrangler configuration:
3182
+ - Expected exactly one of the following fields [\\"routes\\",\\"route\\"]."
2175
3183
  `);
2176
3184
  });
3185
+
3186
+ it("should not error if <env>.route and <top-level>.routes are specified", () => {
3187
+ const environment: RawEnvironment = {
3188
+ name: "mock-env-name",
3189
+ account_id: "ENV_ACCOUNT_ID",
3190
+ compatibility_date: "2022-02-02",
3191
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3192
+ workers_dev: true,
3193
+ route: "ENV_ROUTE_1",
3194
+ jsx_factory: "ENV_JSX_FACTORY",
3195
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3196
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3197
+ usage_model: "unbound",
3198
+ };
3199
+ const expectedConfig: RawConfig = {
3200
+ name: "mock-name",
3201
+ account_id: "ACCOUNT_ID",
3202
+ compatibility_date: "2022-01-01",
3203
+ compatibility_flags: ["FLAG1", "FLAG2"],
3204
+ workers_dev: false,
3205
+ routes: ["ROUTE_1", "ROUTE_2"],
3206
+ jsx_factory: "JSX_FACTORY",
3207
+ jsx_fragment: "JSX_FRAGMENT",
3208
+ triggers: { crons: ["CRON_1", "CRON_2"] },
3209
+ usage_model: "bundled",
3210
+ env: {
3211
+ ENV1: environment,
3212
+ },
3213
+ };
3214
+
3215
+ const { config, diagnostics } = normalizeAndValidateConfig(
3216
+ expectedConfig,
3217
+ undefined,
3218
+ { env: "ENV1" }
3219
+ );
3220
+
3221
+ expect(config).toEqual(expect.objectContaining(environment));
3222
+ expect(diagnostics.hasErrors()).toBe(false);
3223
+ expect(diagnostics.hasWarnings()).toBe(false);
3224
+ });
3225
+
3226
+ it("should not error if <env>.routes and <top-level>.route are specified", () => {
3227
+ const environment: RawEnvironment = {
3228
+ name: "mock-env-name",
3229
+ account_id: "ENV_ACCOUNT_ID",
3230
+ compatibility_date: "2022-02-02",
3231
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3232
+ workers_dev: true,
3233
+ routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
3234
+ jsx_factory: "ENV_JSX_FACTORY",
3235
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3236
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3237
+ usage_model: "unbound",
3238
+ };
3239
+ const expectedConfig: RawConfig = {
3240
+ name: "mock-name",
3241
+ account_id: "ACCOUNT_ID",
3242
+ compatibility_date: "2022-01-01",
3243
+ compatibility_flags: ["FLAG1", "FLAG2"],
3244
+ workers_dev: false,
3245
+ route: "ROUTE_1",
3246
+ jsx_factory: "JSX_FACTORY",
3247
+ jsx_fragment: "JSX_FRAGMENT",
3248
+ triggers: { crons: ["CRON_1", "CRON_2"] },
3249
+ usage_model: "bundled",
3250
+ env: {
3251
+ ENV1: environment,
3252
+ },
3253
+ };
3254
+
3255
+ const { config, diagnostics } = normalizeAndValidateConfig(
3256
+ expectedConfig,
3257
+ undefined,
3258
+ { env: "ENV1" }
3259
+ );
3260
+
3261
+ expect(config).toEqual(expect.objectContaining(environment));
3262
+ expect(diagnostics.hasErrors()).toBe(false);
3263
+ expect(diagnostics.hasWarnings()).toBe(false);
3264
+ });
3265
+
3266
+ it("should not error if <env1>.route and <env2>.routes are specified", () => {
3267
+ const environment1: RawEnvironment = {
3268
+ name: "mock-env-name",
3269
+ account_id: "ENV_ACCOUNT_ID",
3270
+ compatibility_date: "2022-02-02",
3271
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3272
+ workers_dev: true,
3273
+ routes: ["ENV1_ROUTE_1", "ENV2_ROUTE_2"],
3274
+ jsx_factory: "ENV_JSX_FACTORY",
3275
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3276
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3277
+ usage_model: "unbound",
3278
+ };
3279
+ const environment2: RawEnvironment = {
3280
+ name: "mock-env-name",
3281
+ account_id: "ENV_ACCOUNT_ID",
3282
+ compatibility_date: "2022-02-02",
3283
+ compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
3284
+ workers_dev: true,
3285
+ route: "ENV2_ROUTE_1",
3286
+ jsx_factory: "ENV_JSX_FACTORY",
3287
+ jsx_fragment: "ENV_JSX_FRAGMENT",
3288
+ triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
3289
+ usage_model: "unbound",
3290
+ };
3291
+ const expectedConfig: RawConfig = {
3292
+ name: "mock-name",
3293
+ account_id: "ACCOUNT_ID",
3294
+ compatibility_date: "2022-01-01",
3295
+ compatibility_flags: ["FLAG1", "FLAG2"],
3296
+ workers_dev: false,
3297
+ route: "ROUTE_1",
3298
+ jsx_factory: "JSX_FACTORY",
3299
+ jsx_fragment: "JSX_FRAGMENT",
3300
+ triggers: { crons: ["CRON_1", "CRON_2"] },
3301
+ usage_model: "bundled",
3302
+ env: {
3303
+ ENV1: environment1,
3304
+ ENV2: environment2,
3305
+ },
3306
+ };
3307
+
3308
+ const result1 = normalizeAndValidateConfig(expectedConfig, undefined, {
3309
+ env: "ENV1",
3310
+ });
3311
+
3312
+ expect(result1.config).toEqual(expect.objectContaining(environment1));
3313
+ expect(result1.diagnostics.hasErrors()).toBe(false);
3314
+ expect(result1.diagnostics.hasWarnings()).toBe(false);
3315
+
3316
+ const result2 = normalizeAndValidateConfig(expectedConfig, undefined, {
3317
+ env: "ENV2",
3318
+ });
3319
+
3320
+ expect(result2.config).toEqual(expect.objectContaining(environment2));
3321
+ expect(result2.diagnostics.hasErrors()).toBe(false);
3322
+ expect(result2.diagnostics.hasWarnings()).toBe(false);
3323
+ });
2177
3324
  });
2178
3325
  });
2179
3326
  });