wrangler 0.0.0-e178d6fb → 0.0.0-e1c2f5b9

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 (239) hide show
  1. package/README.md +16 -2
  2. package/bin/wrangler.js +31 -11
  3. package/miniflare-dist/index.mjs +1340 -330
  4. package/package.json +40 -13
  5. package/src/__tests__/access.test.ts +25 -0
  6. package/src/__tests__/api-dev.test.ts +238 -0
  7. package/src/__tests__/api-devregistry.test.js +64 -0
  8. package/src/__tests__/api.test.ts +80 -0
  9. package/src/__tests__/configuration.test.ts +683 -470
  10. package/src/__tests__/d1.test.ts +123 -0
  11. package/src/__tests__/delete.test.ts +263 -0
  12. package/src/__tests__/deployments.test.ts +105 -0
  13. package/src/__tests__/dev.test.tsx +453 -70
  14. package/src/__tests__/dialogs.test.tsx +40 -0
  15. package/src/__tests__/generate.test.ts +235 -0
  16. package/src/__tests__/get-host-from-url.test.ts +16 -0
  17. package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
  18. package/src/__tests__/helpers/mock-cfetch.ts +92 -26
  19. package/src/__tests__/helpers/mock-console.ts +11 -2
  20. package/src/__tests__/helpers/mock-dialogs.ts +1 -1
  21. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
  22. package/src/__tests__/helpers/mock-known-routes.ts +7 -0
  23. package/src/__tests__/helpers/mock-kv.ts +1 -1
  24. package/src/__tests__/helpers/mock-oauth-flow.ts +74 -53
  25. package/src/__tests__/helpers/mock-process.ts +8 -13
  26. package/src/__tests__/helpers/msw/handlers/access.ts +13 -0
  27. package/src/__tests__/helpers/msw/handlers/deployments.ts +59 -0
  28. package/src/__tests__/helpers/msw/handlers/namespaces.ts +104 -0
  29. package/src/__tests__/helpers/msw/handlers/oauth.ts +31 -0
  30. package/src/__tests__/helpers/msw/handlers/r2.ts +80 -0
  31. package/src/__tests__/helpers/msw/handlers/script.ts +75 -0
  32. package/src/__tests__/helpers/msw/handlers/user.ts +63 -0
  33. package/src/__tests__/helpers/msw/handlers/zones.ts +22 -0
  34. package/src/__tests__/helpers/msw/index.ts +21 -0
  35. package/src/__tests__/helpers/worker-scripts/child-wrangler.toml +1 -0
  36. package/src/__tests__/helpers/worker-scripts/hello-world-worker.js +5 -0
  37. package/src/__tests__/helpers/worker-scripts/hello-world-wrangler.toml +1 -0
  38. package/src/__tests__/helpers/worker-scripts/parent-worker.js +8 -0
  39. package/src/__tests__/helpers/worker-scripts/parent-wrangler.toml +5 -0
  40. package/src/__tests__/index.test.ts +103 -97
  41. package/src/__tests__/init.test.ts +1484 -382
  42. package/src/__tests__/jest.setup.ts +88 -5
  43. package/src/__tests__/kv.test.ts +655 -540
  44. package/src/__tests__/logout.test.ts +47 -0
  45. package/src/__tests__/metrics.test.ts +95 -45
  46. package/src/__tests__/middleware.scheduled.test.ts +145 -0
  47. package/src/__tests__/middleware.test.ts +750 -0
  48. package/src/__tests__/pages-deployment-tail.test.ts +884 -0
  49. package/src/__tests__/pages.test.ts +1301 -119
  50. package/src/__tests__/paths.test.ts +39 -0
  51. package/src/__tests__/publish.test.ts +2266 -1180
  52. package/src/__tests__/pubsub.test.ts +211 -88
  53. package/src/__tests__/queues.test.ts +522 -0
  54. package/src/__tests__/r2.test.ts +363 -203
  55. package/src/__tests__/secret.test.ts +261 -59
  56. package/src/__tests__/tail.test.ts +352 -151
  57. package/src/__tests__/test-old-node-version.js +3 -3
  58. package/src/__tests__/tsconfig-sanity.ts +12 -0
  59. package/src/__tests__/tsconfig.json +8 -0
  60. package/src/__tests__/tsconfig.tsbuildinfo +1 -0
  61. package/src/__tests__/type-generation.test.ts +233 -0
  62. package/src/__tests__/user.test.ts +59 -73
  63. package/src/__tests__/utils-collectKeyValues.test.ts +47 -0
  64. package/src/__tests__/validate-dev-props.test.ts +56 -0
  65. package/src/__tests__/whoami.test.tsx +114 -66
  66. package/src/__tests__/worker-namespace.test.ts +154 -155
  67. package/src/api/dev.ts +170 -38
  68. package/src/api/index.ts +1 -0
  69. package/src/bundle-reporter.tsx +41 -2
  70. package/src/bundle.ts +668 -81
  71. package/src/cfetch/index.ts +40 -3
  72. package/src/cfetch/internal.ts +144 -32
  73. package/src/cli.ts +4 -3
  74. package/src/config/config.ts +27 -3
  75. package/src/config/environment.ts +131 -7
  76. package/src/config/index.ts +128 -8
  77. package/src/config/validation-helpers.ts +19 -6
  78. package/src/config/validation.ts +411 -14
  79. package/src/config-cache.ts +3 -2
  80. package/src/create-worker-preview.ts +31 -6
  81. package/src/create-worker-upload-form.ts +84 -22
  82. package/src/d1/backups.tsx +223 -0
  83. package/src/d1/constants.ts +2 -0
  84. package/src/d1/create.tsx +63 -0
  85. package/src/d1/delete.tsx +56 -0
  86. package/src/d1/execute.tsx +352 -0
  87. package/src/d1/formatTimeAgo.ts +14 -0
  88. package/src/d1/index.ts +101 -0
  89. package/src/d1/list.tsx +48 -0
  90. package/src/d1/migrations/apply.tsx +196 -0
  91. package/src/d1/migrations/create.tsx +77 -0
  92. package/src/d1/migrations/helpers.ts +147 -0
  93. package/src/d1/migrations/index.tsx +3 -0
  94. package/src/d1/migrations/list.tsx +79 -0
  95. package/src/d1/migrations/options.ts +18 -0
  96. package/src/d1/options.ts +22 -0
  97. package/src/d1/types.tsx +24 -0
  98. package/src/d1/utils.ts +48 -0
  99. package/src/delete.ts +108 -0
  100. package/src/deployments.ts +83 -0
  101. package/src/deprecated/index.ts +145 -0
  102. package/src/dev/dev-vars.ts +11 -8
  103. package/src/dev/dev.tsx +220 -58
  104. package/src/dev/get-local-persistence-path.tsx +31 -0
  105. package/src/dev/local.tsx +740 -181
  106. package/src/dev/remote.tsx +340 -123
  107. package/src/dev/start-server.ts +543 -0
  108. package/src/dev/use-esbuild.ts +61 -7
  109. package/src/dev/validate-dev-props.ts +31 -0
  110. package/src/dev-registry.tsx +201 -0
  111. package/src/dev.tsx +614 -258
  112. package/src/dialogs.tsx +41 -8
  113. package/src/{worker-namespace.ts → dispatch-namespace.ts} +23 -22
  114. package/src/docs/index.ts +97 -0
  115. package/src/entry.ts +3 -2
  116. package/src/environment-variables/factory.ts +88 -0
  117. package/src/environment-variables/misc-variables.ts +30 -0
  118. package/src/generate/index.ts +300 -0
  119. package/src/git-client.ts +100 -7
  120. package/src/index.tsx +249 -1560
  121. package/src/init.ts +626 -150
  122. package/src/inspect.ts +137 -32
  123. package/src/{metrics/is-ci.ts → is-ci.ts} +0 -0
  124. package/src/is-interactive.ts +4 -0
  125. package/src/jest.d.ts +4 -0
  126. package/src/{kv.ts → kv/helpers.ts} +3 -3
  127. package/src/kv/index.ts +596 -0
  128. package/src/logger.ts +27 -8
  129. package/src/metrics/index.ts +1 -0
  130. package/src/metrics/metrics-config.ts +4 -4
  131. package/src/metrics/metrics-dispatcher.ts +1 -0
  132. package/src/metrics/metrics-usage-headers.ts +24 -0
  133. package/src/metrics/send-event.ts +13 -8
  134. package/src/miniflare-cli/assets.ts +172 -465
  135. package/src/miniflare-cli/index.ts +149 -24
  136. package/src/miniflare-cli/tsconfig.json +9 -0
  137. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
  138. package/src/miniflare-cli/types.ts +11 -0
  139. package/src/module-collection.ts +12 -3
  140. package/src/pages/build.tsx +108 -42
  141. package/src/pages/constants.ts +11 -0
  142. package/src/pages/deployment-tails.tsx +284 -0
  143. package/src/pages/deployments.tsx +9 -31
  144. package/src/pages/dev.tsx +417 -108
  145. package/src/pages/errors.ts +66 -0
  146. package/src/pages/functions/buildPlugin.ts +86 -84
  147. package/src/pages/functions/buildWorker.ts +121 -106
  148. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  149. package/src/pages/functions/routes-consolidation.ts +73 -0
  150. package/src/pages/functions/routes-transformation.test.ts +282 -0
  151. package/src/pages/functions/routes-transformation.ts +115 -0
  152. package/src/pages/functions/routes-validation.test.ts +403 -0
  153. package/src/pages/functions/routes-validation.ts +202 -0
  154. package/src/pages/functions/tsconfig.json +8 -0
  155. package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
  156. package/src/pages/functions.tsx +82 -0
  157. package/src/pages/hash.tsx +13 -0
  158. package/src/pages/index.tsx +73 -55
  159. package/src/pages/projects.tsx +9 -3
  160. package/src/pages/prompt-select-project.tsx +31 -0
  161. package/src/pages/publish.tsx +183 -60
  162. package/src/pages/types.ts +1 -0
  163. package/src/pages/upload.tsx +107 -56
  164. package/src/pages/utils.ts +13 -2
  165. package/src/paths.ts +49 -4
  166. package/src/proxy.ts +375 -157
  167. package/src/publish/index.ts +270 -0
  168. package/src/{publish.ts → publish/publish.ts} +431 -188
  169. package/src/pubsub/pubsub-commands.tsx +4 -3
  170. package/src/queues/cli/commands/consumer/add.ts +71 -0
  171. package/src/queues/cli/commands/consumer/index.ts +22 -0
  172. package/src/queues/cli/commands/consumer/remove.ts +38 -0
  173. package/src/queues/cli/commands/create.ts +25 -0
  174. package/src/queues/cli/commands/delete.ts +26 -0
  175. package/src/queues/cli/commands/index.ts +36 -0
  176. package/src/queues/cli/commands/list.ts +25 -0
  177. package/src/queues/client.ts +135 -0
  178. package/src/queues/utils.ts +18 -0
  179. package/src/r2/constants.ts +4 -0
  180. package/src/r2/helpers.ts +131 -0
  181. package/src/r2/index.ts +289 -0
  182. package/src/routes.ts +140 -0
  183. package/src/secret/index.ts +379 -0
  184. package/src/sites.tsx +3 -3
  185. package/src/tail/createTail.ts +379 -0
  186. package/src/tail/filters.ts +4 -6
  187. package/src/tail/index.ts +199 -284
  188. package/src/tail/printing.ts +43 -3
  189. package/src/tsconfig-sanity.ts +16 -0
  190. package/src/type-generation.ts +181 -0
  191. package/src/user/access.ts +68 -0
  192. package/src/user/auth-variables.ts +113 -0
  193. package/src/user/choose-account.tsx +1 -1
  194. package/src/user/index.ts +0 -1
  195. package/src/user/user.tsx +116 -49
  196. package/src/utils/collectKeyValues.ts +14 -0
  197. package/src/whoami.tsx +80 -2
  198. package/src/worker.ts +69 -9
  199. package/src/yargs-types.ts +24 -0
  200. package/src/zones.ts +124 -9
  201. package/templates/__tests__/pages-dev-util.test.ts +128 -0
  202. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  203. package/templates/__tests__/tsconfig.json +8 -0
  204. package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
  205. package/templates/d1-beta-facade.js +205 -0
  206. package/templates/facade.d.ts +14 -0
  207. package/templates/first-party-worker-module-facade.ts +19 -0
  208. package/templates/format-dev-errors.ts +33 -0
  209. package/templates/init-tests/test-jest-new-worker.js +23 -0
  210. package/templates/init-tests/test-vitest-new-worker.js +24 -0
  211. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  212. package/templates/middleware/common.ts +62 -0
  213. package/templates/middleware/loader-modules.ts +82 -0
  214. package/templates/middleware/loader-sw.ts +233 -0
  215. package/templates/middleware/middleware-miniflare3-json-error.ts +20 -0
  216. package/templates/middleware/middleware-pretty-error.ts +40 -0
  217. package/templates/middleware/middleware-scheduled.ts +15 -0
  218. package/templates/new-worker.js +1 -1
  219. package/templates/pages-dev-pipeline.ts +31 -0
  220. package/templates/pages-dev-util.ts +52 -0
  221. package/templates/pages-shim.ts +4 -1
  222. package/templates/pages-template-plugin.ts +21 -5
  223. package/templates/pages-template-worker.ts +37 -9
  224. package/templates/{static-asset-facade.js → serve-static-assets.ts} +23 -7
  225. package/templates/service-bindings-module-facade.js +54 -0
  226. package/templates/service-bindings-sw-facade.js +42 -0
  227. package/templates/tsconfig-sanity.ts +11 -0
  228. package/templates/tsconfig.init.json +106 -0
  229. package/templates/tsconfig.json +5 -102
  230. package/templates/tsconfig.tsbuildinfo +1 -0
  231. package/wrangler-dist/cli.d.ts +621 -42
  232. package/wrangler-dist/cli.js +144441 -102606
  233. package/src/environment-variables.ts +0 -35
  234. package/src/faye-websocket.d.ts +0 -6
  235. package/src/generate.ts +0 -33
  236. package/src/miniflare-cli/enum-keys.ts +0 -17
  237. package/src/preview.ts +0 -31
  238. package/src/r2.ts +0 -50
  239. package/src/user/env-vars.ts +0 -46
@@ -1,21 +1,55 @@
1
1
  import * as fs from "node:fs";
2
2
  import getPort from "get-port";
3
+ import { rest } from "msw";
3
4
  import patchConsole from "patch-console";
4
5
  import dedent from "ts-dedent";
5
6
  import Dev from "../dev/dev";
6
- import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
7
+ import { CI } from "../is-ci";
8
+ import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
7
9
  import { mockConsoleMethods } from "./helpers/mock-console";
10
+ import {
11
+ msw,
12
+ mswSuccessOauthHandlers,
13
+ mswSuccessUserHandlers,
14
+ mswZoneHandlers,
15
+ } from "./helpers/msw";
8
16
  import { runInTempDir } from "./helpers/run-in-tmp";
9
17
  import { runWrangler } from "./helpers/run-wrangler";
10
18
  import writeWranglerToml from "./helpers/write-wrangler-toml";
11
19
 
12
20
  describe("wrangler dev", () => {
21
+ beforeEach(() => {
22
+ msw.use(
23
+ ...mswZoneHandlers,
24
+ ...mswSuccessOauthHandlers,
25
+ ...mswSuccessUserHandlers
26
+ );
27
+ });
28
+
13
29
  runInTempDir();
30
+ mockAccountId();
31
+ mockApiToken();
14
32
  const std = mockConsoleMethods();
15
33
  afterEach(() => {
16
34
  (Dev as jest.Mock).mockClear();
17
35
  patchConsole(() => {});
18
- unsetAllMocks();
36
+ msw.resetHandlers();
37
+ });
38
+
39
+ describe("authorization", () => {
40
+ mockApiToken({ apiToken: null });
41
+ const isCISpy = jest.spyOn(CI, "isCI").mockReturnValue(true);
42
+
43
+ it("should kick you to the login flow when running wrangler dev in remote mode without authorization", async () => {
44
+ fs.writeFileSync("index.js", `export default {};`);
45
+ await expect(
46
+ runWrangler("dev index.js")
47
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
48
+ `"You must be logged in to use wrangler dev in remote mode. Try logging in, or run wrangler dev --local."`
49
+ );
50
+ });
51
+
52
+ isCISpy.mockClear();
19
53
  });
20
54
 
21
55
  describe("compatibility-date", () => {
@@ -48,7 +82,7 @@ describe("wrangler dev", () => {
48
82
  \`\`\`
49
83
  --compatibility-date=<current-date>
50
84
  \`\`\`
51
- See https://developers.cloudflare.com/workers/platform/compatibility-dates for more information.
85
+ See https://developers.cloudflare.com/workers/platform/compatibility-dates/ for more information.
52
86
 
53
87
  "
54
88
  `);
@@ -68,6 +102,28 @@ describe("wrangler dev", () => {
68
102
  });
69
103
  });
70
104
 
105
+ describe("usage-model", () => {
106
+ it("should read wrangler.toml's usage_model", async () => {
107
+ writeWranglerToml({
108
+ main: "index.js",
109
+ usage_model: "unbound",
110
+ });
111
+ fs.writeFileSync("index.js", `export default {};`);
112
+ await runWrangler("dev");
113
+ expect((Dev as jest.Mock).mock.calls[0][0].usageModel).toEqual("unbound");
114
+ });
115
+
116
+ it("should read wrangler.toml's usage_model in local mode", async () => {
117
+ writeWranglerToml({
118
+ main: "index.js",
119
+ usage_model: "unbound",
120
+ });
121
+ fs.writeFileSync("index.js", `export default {};`);
122
+ await runWrangler("dev --local");
123
+ expect((Dev as jest.Mock).mock.calls[0][0].usageModel).toEqual("unbound");
124
+ });
125
+ });
126
+
71
127
  describe("entry-points", () => {
72
128
  it("should error if there is no entry-point specified", async () => {
73
129
  writeWranglerToml();
@@ -161,7 +217,6 @@ describe("wrangler dev", () => {
161
217
  );
162
218
  });
163
219
  });
164
-
165
220
  describe("host", () => {
166
221
  it("should resolve a host to its zone", async () => {
167
222
  writeWranglerToml({
@@ -280,7 +335,10 @@ describe("wrangler dev", () => {
280
335
  writeWranglerToml({
281
336
  main: "index.js",
282
337
  routes: [
283
- { pattern: "https://some-domain.com/*", zone_name: "some-zone.com" },
338
+ {
339
+ pattern: "https://some-zone.com/*",
340
+ zone_name: "some-zone.com",
341
+ },
284
342
  ],
285
343
  });
286
344
  fs.writeFileSync("index.js", `export default {};`);
@@ -295,21 +353,130 @@ describe("wrangler dev", () => {
295
353
  );
296
354
  });
297
355
 
356
+ it("should find the host from the given pattern, not zone_name", async () => {
357
+ writeWranglerToml({
358
+ main: "index.js",
359
+ routes: [
360
+ {
361
+ pattern: "https://subdomain.exists.com/*",
362
+ zone_name: "does-not-exist.com",
363
+ },
364
+ ],
365
+ });
366
+ await fs.promises.writeFile("index.js", `export default {};`);
367
+ await runWrangler("dev");
368
+ expect(std.out).toMatchInlineSnapshot(`""`);
369
+ expect(std.err).toMatchInlineSnapshot(`""`);
370
+ });
371
+
372
+ it("should fail for non-existing zones", async () => {
373
+ writeWranglerToml({
374
+ main: "index.js",
375
+ routes: [
376
+ {
377
+ pattern: "https://subdomain.does-not-exist.com/*",
378
+ zone_name: "exists.com",
379
+ },
380
+ ],
381
+ });
382
+ await fs.promises.writeFile("index.js", `export default {};`);
383
+ await expect(runWrangler("dev")).rejects.toEqual(
384
+ new Error("Could not find zone for subdomain.does-not-exist.com")
385
+ );
386
+ });
387
+
388
+ it("should fail for non-existing zones, when falling back from */*", async () => {
389
+ writeWranglerToml({
390
+ main: "index.js",
391
+ routes: [
392
+ {
393
+ pattern: "*/*",
394
+ zone_name: "does-not-exist.com",
395
+ },
396
+ ],
397
+ });
398
+ await fs.promises.writeFile("index.js", `export default {};`);
399
+ await expect(runWrangler("dev")).rejects.toEqual(
400
+ new Error("Could not find zone for does-not-exist.com")
401
+ );
402
+ });
403
+
404
+ it("should fallback to zone_name when given the pattern */*", async () => {
405
+ writeWranglerToml({
406
+ main: "index.js",
407
+ routes: [
408
+ {
409
+ pattern: "*/*",
410
+ zone_name: "exists.com",
411
+ },
412
+ ],
413
+ });
414
+ await fs.promises.writeFile("index.js", `export default {};`);
415
+ await runWrangler("dev");
416
+ expect(std.out).toMatchInlineSnapshot(`""`);
417
+ expect(std.err).toMatchInlineSnapshot(`""`);
418
+ });
419
+ it("fails when given the pattern */* and no zone_name", async () => {
420
+ writeWranglerToml({
421
+ main: "index.js",
422
+ routes: [
423
+ {
424
+ pattern: "*/*",
425
+ zone_id: "exists-com",
426
+ },
427
+ ],
428
+ });
429
+ await fs.promises.writeFile("index.js", `export default {};`);
430
+ const err = new TypeError() as unknown as { code: string; input: string };
431
+ err.code = "ERR_INVALID_URL";
432
+ err.input = "http:///";
433
+
434
+ await expect(runWrangler("dev")).rejects.toEqual(err);
435
+ });
436
+
298
437
  it("given a long host, it should use the longest subdomain that resolves to a zone", async () => {
299
438
  writeWranglerToml({
300
439
  main: "index.js",
301
440
  });
302
441
  fs.writeFileSync("index.js", `export default {};`);
303
- mockGetZones("111.222.333.some-host.com", []);
304
- mockGetZones("222.333.some-host.com", []);
305
- mockGetZones("333.some-host.com", [{ id: "some-zone-id" }]);
306
- await runWrangler("dev --host 111.222.333.some-host.com");
307
- expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
308
- expect.objectContaining({
309
- host: "111.222.333.some-host.com",
310
- zone: "some-zone-id",
442
+
443
+ msw.use(
444
+ rest.get("*/zones", (req, res, ctx) => {
445
+ let zone: [] | [{ id: "some-zone-id" }] = [];
446
+ if (
447
+ req.url.searchParams.get("name") === "111.222.333.some-host.com"
448
+ ) {
449
+ zone = [];
450
+ } else if (
451
+ req.url.searchParams.get("name") === "222.333.some-host.com"
452
+ ) {
453
+ zone = [];
454
+ } else if (req.url.searchParams.get("name") === "333.some-host.com") {
455
+ zone = [{ id: "some-zone-id" }];
456
+ }
457
+
458
+ return res(
459
+ ctx.status(200),
460
+ ctx.json({
461
+ success: true,
462
+ errors: [],
463
+ messages: [],
464
+ result: zone,
465
+ })
466
+ );
311
467
  })
312
468
  );
469
+
470
+ await runWrangler("dev --host 111.222.333.some-host.com");
471
+
472
+ const devMockCall = (Dev as jest.Mock).mock.calls[0][0];
473
+
474
+ expect(devMockCall).toHaveProperty("host", "111.222.333.some-host.com");
475
+ expect(devMockCall).toHaveProperty(
476
+ "localUpstream",
477
+ "111.222.333.some-host.com"
478
+ );
479
+ expect(devMockCall).toHaveProperty("zone", "some-zone-id");
313
480
  });
314
481
 
315
482
  it("should, in order, use args.host/config.dev.host/args.routes/(config.route|config.routes)", async () => {
@@ -525,9 +692,9 @@ describe("wrangler dev", () => {
525
692
 
526
693
  await expect(runWrangler("dev")).rejects
527
694
  .toThrowErrorMatchingInlineSnapshot(`
528
- "The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
529
- The \`main\` property in wrangler.toml should point to the file generated by the custom build."
530
- `);
695
+ "The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
696
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build."
697
+ `);
531
698
  expect(std.out).toMatchInlineSnapshot(`
532
699
  "Running custom build: node -e \\"console.log('custom build');\\"
533
700
 
@@ -542,6 +709,40 @@ describe("wrangler dev", () => {
542
709
  `);
543
710
  expect(std.warn).toMatchInlineSnapshot(`""`);
544
711
  });
712
+
713
+ describe(".env", () => {
714
+ beforeEach(() => {
715
+ fs.writeFileSync(".env", "CUSTOM_BUILD_VAR=default");
716
+ fs.writeFileSync(".env.custom", "CUSTOM_BUILD_VAR=custom");
717
+ fs.writeFileSync("index.js", `export default {};`);
718
+ writeWranglerToml({
719
+ main: "index.js",
720
+ env: { custom: {} },
721
+ build: {
722
+ // Ideally, we'd just log the var here and match it in `std.out`,
723
+ // but stdout from custom builds is piped directly to
724
+ // `process.stdout` which we don't capture.
725
+ command: `node -e "require('fs').writeFileSync('var.txt', process.env.CUSTOM_BUILD_VAR)"`,
726
+ },
727
+ });
728
+
729
+ // We won't overwrite existing process.env keys with .env values (to
730
+ // allow .env overrides to specified on then shell), so make sure this
731
+ // key definitely doesn't exist.
732
+ delete process.env.CUSTOM_BUILD_VAR;
733
+ });
734
+
735
+ it("should load environment variables from `.env`", async () => {
736
+ await runWrangler("dev");
737
+ const output = fs.readFileSync("var.txt", "utf8");
738
+ expect(output).toMatch("default");
739
+ });
740
+ it("should prefer to load environment variables from `.env.<environment>` if `--env <environment>` is set", async () => {
741
+ await runWrangler("dev --env custom");
742
+ const output = fs.readFileSync("var.txt", "utf8");
743
+ expect(output).toMatch("custom");
744
+ });
745
+ });
545
746
  });
546
747
 
547
748
  describe("upstream-protocol", () => {
@@ -630,13 +831,13 @@ describe("wrangler dev", () => {
630
831
  });
631
832
 
632
833
  describe("ip", () => {
633
- it("should default ip to localhost", async () => {
834
+ it("should default ip to 0.0.0.0", async () => {
634
835
  writeWranglerToml({
635
836
  main: "index.js",
636
837
  });
637
838
  fs.writeFileSync("index.js", `export default {};`);
638
839
  await runWrangler("dev");
639
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
840
+ expect((Dev as jest.Mock).mock.calls[0][0].initialIp).toEqual("0.0.0.0");
640
841
  expect(std.out).toMatchInlineSnapshot(`""`);
641
842
  expect(std.warn).toMatchInlineSnapshot(`""`);
642
843
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -646,12 +847,12 @@ describe("wrangler dev", () => {
646
847
  writeWranglerToml({
647
848
  main: "index.js",
648
849
  dev: {
649
- ip: "0.0.0.0",
850
+ ip: "1.2.3.4",
650
851
  },
651
852
  });
652
853
  fs.writeFileSync("index.js", `export default {};`);
653
854
  await runWrangler("dev");
654
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
855
+ expect((Dev as jest.Mock).mock.calls[0][0].initialIp).toEqual("1.2.3.4");
655
856
  expect(std.out).toMatchInlineSnapshot(`""`);
656
857
  expect(std.warn).toMatchInlineSnapshot(`""`);
657
858
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -661,18 +862,115 @@ describe("wrangler dev", () => {
661
862
  writeWranglerToml({
662
863
  main: "index.js",
663
864
  dev: {
664
- ip: "1.1.1.1",
865
+ ip: "1.2.3.4",
665
866
  },
666
867
  });
667
868
  fs.writeFileSync("index.js", `export default {};`);
668
- await runWrangler("dev --ip=0.0.0.0");
669
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
869
+ await runWrangler("dev --ip=5.6.7.8");
870
+ expect((Dev as jest.Mock).mock.calls[0][0].initialIp).toEqual("5.6.7.8");
670
871
  expect(std.out).toMatchInlineSnapshot(`""`);
671
872
  expect(std.warn).toMatchInlineSnapshot(`""`);
672
873
  expect(std.err).toMatchInlineSnapshot(`""`);
673
874
  });
674
875
  });
675
876
 
877
+ describe("inspector port", () => {
878
+ it("should connect WebSocket server with --experimental-local", async () => {
879
+ writeWranglerToml({
880
+ main: "./index.js",
881
+ });
882
+ fs.writeFileSync(
883
+ "index.js",
884
+ `export default {
885
+ async fetch(request, env, ctx ){
886
+ console.log('Hello World LOGGING');
887
+ },
888
+ };`
889
+ );
890
+ await runWrangler("dev --experimental-local");
891
+
892
+ expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9229);
893
+ expect(std).toMatchInlineSnapshot(`
894
+ Object {
895
+ "debug": "",
896
+ "err": "",
897
+ "out": "",
898
+ "warn": "",
899
+ }
900
+ `);
901
+ });
902
+
903
+ it("should use 9229 as the default port", async () => {
904
+ writeWranglerToml({
905
+ main: "index.js",
906
+ });
907
+ fs.writeFileSync("index.js", `export default {};`);
908
+ await runWrangler("dev");
909
+ expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9229);
910
+ expect(std).toMatchInlineSnapshot(`
911
+ Object {
912
+ "debug": "",
913
+ "err": "",
914
+ "out": "",
915
+ "warn": "",
916
+ }
917
+ `);
918
+ });
919
+
920
+ it("should read --inspector-port", async () => {
921
+ writeWranglerToml({
922
+ main: "index.js",
923
+ });
924
+ fs.writeFileSync("index.js", `export default {};`);
925
+ await runWrangler("dev --inspector-port=9999");
926
+ expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9999);
927
+ expect(std).toMatchInlineSnapshot(`
928
+ Object {
929
+ "debug": "",
930
+ "err": "",
931
+ "out": "",
932
+ "warn": "",
933
+ }
934
+ `);
935
+ });
936
+
937
+ it("should read dev.inspector_port from wrangler.toml", async () => {
938
+ writeWranglerToml({
939
+ main: "index.js",
940
+ dev: {
941
+ inspector_port: 9999,
942
+ },
943
+ });
944
+ fs.writeFileSync("index.js", `export default {};`);
945
+ await runWrangler("dev");
946
+ expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9999);
947
+ expect(std).toMatchInlineSnapshot(`
948
+ Object {
949
+ "debug": "",
950
+ "err": "",
951
+ "out": "",
952
+ "warn": "",
953
+ }
954
+ `);
955
+ });
956
+
957
+ it("should error if a bad dev.inspector_port config is provided", async () => {
958
+ writeWranglerToml({
959
+ main: "index.js",
960
+ dev: {
961
+ // @ts-expect-error intentionally bad port
962
+ inspector_port: "some string",
963
+ },
964
+ });
965
+ fs.writeFileSync("index.js", `export default {};`);
966
+ await expect(runWrangler("dev")).rejects
967
+ .toThrowErrorMatchingInlineSnapshot(`
968
+ "Processing wrangler.toml configuration:
969
+ - Expected \\"dev.inspector_port\\" to be of type number but got \\"some string\\"."
970
+ `);
971
+ });
972
+ });
973
+
676
974
  describe("port", () => {
677
975
  it("should default port to 8787 if it is not in use", async () => {
678
976
  writeWranglerToml({
@@ -680,13 +978,13 @@ describe("wrangler dev", () => {
680
978
  });
681
979
  fs.writeFileSync("index.js", `export default {};`);
682
980
  await runWrangler("dev");
683
- expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8787);
981
+ expect((Dev as jest.Mock).mock.calls[0][0].initialPort).toEqual(8787);
684
982
  expect(std.out).toMatchInlineSnapshot(`""`);
685
983
  expect(std.warn).toMatchInlineSnapshot(`""`);
686
984
  expect(std.err).toMatchInlineSnapshot(`""`);
687
985
  });
688
986
 
689
- it("should use to `port` from `wrangler.toml`, if available", async () => {
987
+ it("should use `port` from `wrangler.toml`, if available", async () => {
690
988
  writeWranglerToml({
691
989
  main: "index.js",
692
990
  dev: {
@@ -698,12 +996,28 @@ describe("wrangler dev", () => {
698
996
  (getPort as jest.Mock).mockResolvedValue(98765);
699
997
 
700
998
  await runWrangler("dev");
701
- expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8888);
999
+ expect((Dev as jest.Mock).mock.calls[0][0].initialPort).toEqual(8888);
702
1000
  expect(std.out).toMatchInlineSnapshot(`""`);
703
1001
  expect(std.warn).toMatchInlineSnapshot(`""`);
704
1002
  expect(std.err).toMatchInlineSnapshot(`""`);
705
1003
  });
706
1004
 
1005
+ it("should error if a bad dev.port config is provided", async () => {
1006
+ writeWranglerToml({
1007
+ main: "index.js",
1008
+ dev: {
1009
+ // @ts-expect-error intentionally bad port
1010
+ port: "some string",
1011
+ },
1012
+ });
1013
+ fs.writeFileSync("index.js", `export default {};`);
1014
+ await expect(runWrangler("dev")).rejects
1015
+ .toThrowErrorMatchingInlineSnapshot(`
1016
+ "Processing wrangler.toml configuration:
1017
+ - Expected \\"dev.port\\" to be of type number but got \\"some string\\"."
1018
+ `);
1019
+ });
1020
+
707
1021
  it("should use --port command line arg, if provided", async () => {
708
1022
  writeWranglerToml({
709
1023
  main: "index.js",
@@ -716,7 +1030,7 @@ describe("wrangler dev", () => {
716
1030
  (getPort as jest.Mock).mockResolvedValue(98765);
717
1031
 
718
1032
  await runWrangler("dev --port=9999");
719
- expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(9999);
1033
+ expect((Dev as jest.Mock).mock.calls[0][0].initialPort).toEqual(9999);
720
1034
  expect(std.out).toMatchInlineSnapshot(`""`);
721
1035
  expect(std.warn).toMatchInlineSnapshot(`""`);
722
1036
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -731,7 +1045,7 @@ describe("wrangler dev", () => {
731
1045
  (getPort as jest.Mock).mockResolvedValue(98765);
732
1046
 
733
1047
  await runWrangler("dev");
734
- expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(98765);
1048
+ expect((Dev as jest.Mock).mock.calls[0][0].initialPort).toEqual(98765);
735
1049
  expect(std.out).toMatchInlineSnapshot(`""`);
736
1050
  expect(std.warn).toMatchInlineSnapshot(`""`);
737
1051
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -761,7 +1075,7 @@ describe("wrangler dev", () => {
761
1075
  });
762
1076
  fs.writeFileSync("index.js", `export default {};`);
763
1077
  await runWrangler("dev");
764
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
1078
+ expect((Dev as jest.Mock).mock.calls[0][0].initialIp).toEqual("0.0.0.0");
765
1079
  expect(std.out).toMatchInlineSnapshot(`
766
1080
  "Your worker has access to the following bindings:
767
1081
  - Durable Objects:
@@ -858,6 +1172,27 @@ describe("wrangler dev", () => {
858
1172
  expect(std.warn).toMatchInlineSnapshot(`""`);
859
1173
  expect(std.err).toMatchInlineSnapshot(`""`);
860
1174
  });
1175
+
1176
+ it("should prefer `.dev.vars.<environment>` if `--env <environment> set`", async () => {
1177
+ fs.writeFileSync("index.js", `export default {};`);
1178
+ fs.writeFileSync(".dev.vars", "DEFAULT_VAR=default");
1179
+ fs.writeFileSync(".dev.vars.custom", "CUSTOM_VAR=custom");
1180
+
1181
+ writeWranglerToml({ main: "index.js", env: { custom: {} } });
1182
+ await runWrangler("dev --env custom");
1183
+ const varBindings: Record<string, unknown> = (Dev as jest.Mock).mock
1184
+ .calls[0][0].bindings.vars;
1185
+
1186
+ expect(varBindings).toEqual({ CUSTOM_VAR: "custom" });
1187
+ expect(std.out).toMatchInlineSnapshot(`
1188
+ "Using vars defined in .dev.vars.custom
1189
+ Your worker has access to the following bindings:
1190
+ - Vars:
1191
+ - CUSTOM_VAR: \\"(hidden)\\""
1192
+ `);
1193
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1194
+ expect(std.err).toMatchInlineSnapshot(`""`);
1195
+ });
861
1196
  });
862
1197
 
863
1198
  describe("serve static assets", () => {
@@ -884,18 +1219,17 @@ describe("wrangler dev", () => {
884
1219
 
885
1220
  Flags:
886
1221
  -c, --config Path to .toml configuration file [string]
1222
+ -e, --env Environment to use for operations and .env files [string]
887
1223
  -h, --help Show help [boolean]
888
1224
  -v, --version Show version number [boolean]
889
1225
 
890
1226
  Options:
891
1227
  --name Name of the worker [string]
892
1228
  --no-bundle Skip internal build steps and directly publish script [boolean] [default: false]
893
- --format Choose an entry type [deprecated] [choices: \\"modules\\", \\"service-worker\\"]
894
- -e, --env Perform on a specific environment [string]
895
1229
  --compatibility-date Date to use for compatibility checks [string]
896
1230
  --compatibility-flags, --compatibility-flag Flags to use for compatibility checks [array]
897
1231
  --latest Use the latest version of the worker runtime [boolean] [default: true]
898
- --ip IP address to listen on, defaults to \`localhost\` [string]
1232
+ --ip IP address to listen on [string]
899
1233
  --port Port to listen on [number]
900
1234
  --inspector-port Port for devtools to connect to [number]
901
1235
  --routes, --route Routes to upload [array]
@@ -907,14 +1241,21 @@ describe("wrangler dev", () => {
907
1241
  --site-include Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded. [array]
908
1242
  --site-exclude Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded. [array]
909
1243
  --upstream-protocol Protocol to forward requests to host on, defaults to https. [choices: \\"http\\", \\"https\\"]
1244
+ --var A key-value pair to be injected into the script as a variable [array]
1245
+ --define A key-value pair to be substituted in the script [array]
910
1246
  --jsx-factory The function that is called for each JSX element [string]
911
1247
  --jsx-fragment The function that is called for each JSX fragment [string]
912
1248
  --tsconfig Path to a custom tsconfig.json file [string]
913
1249
  -l, --local Run on my machine [boolean] [default: false]
1250
+ --experimental-local Run on my machine using the Cloudflare Workers runtime [boolean] [default: false]
1251
+ --experimental-local-remote-kv Read/write KV data from/to real namespaces on the Cloudflare network [boolean] [default: false]
914
1252
  --minify Minify the script [boolean]
915
1253
  --node-compat Enable node.js compatibility [boolean]
916
- --experimental-enable-local-persistence Enable persistence for this session (only for local mode) [boolean]
917
- --inspect Enable dev tools [deprecated] [boolean]",
1254
+ --persist Enable persistence for local mode, using default path: .wrangler/state [boolean]
1255
+ --persist-to Specify directory to use for local persistence (implies --persist) [string]
1256
+ --live-reload Auto reload HTML pages when change is detected in local mode [boolean]
1257
+ --test-scheduled Test scheduled events by visiting /__scheduled in browser [boolean] [default: false]
1258
+ --log-level Specify logging level [choices: \\"debug\\", \\"info\\", \\"log\\", \\"warn\\", \\"error\\", \\"none\\"] [default: \\"log\\"]",
918
1259
  "warn": "",
919
1260
  }
920
1261
  `);
@@ -950,6 +1291,7 @@ describe("wrangler dev", () => {
950
1291
  it("should error if config.assets and --site are used together", async () => {
951
1292
  writeWranglerToml({
952
1293
  main: "./index.js",
1294
+ // @ts-expect-error we allow string inputs here
953
1295
  assets: "abc",
954
1296
  });
955
1297
  fs.writeFileSync("index.js", `export default {};`);
@@ -963,6 +1305,7 @@ describe("wrangler dev", () => {
963
1305
  it("should error if config.assets and config.site are used together", async () => {
964
1306
  writeWranglerToml({
965
1307
  main: "./index.js",
1308
+ // @ts-expect-error we allow string inputs here
966
1309
  assets: "abc",
967
1310
  site: {
968
1311
  bucket: "xyz",
@@ -991,7 +1334,6 @@ describe("wrangler dev", () => {
991
1334
  await runWrangler("dev --assets abc");
992
1335
  expect((Dev as jest.Mock).mock.calls[2][0].isWorkersSite).toEqual(false);
993
1336
  });
994
-
995
1337
  it("should warn if --assets is used", async () => {
996
1338
  writeWranglerToml({
997
1339
  main: "./index.js",
@@ -1014,6 +1356,7 @@ describe("wrangler dev", () => {
1014
1356
  it("should warn if config.assets is used", async () => {
1015
1357
  writeWranglerToml({
1016
1358
  main: "./index.js",
1359
+ // @ts-expect-error we allow string inputs here
1017
1360
  assets: "./assets",
1018
1361
  });
1019
1362
  fs.writeFileSync("index.js", `export default {};`);
@@ -1095,6 +1438,42 @@ describe("wrangler dev", () => {
1095
1438
  });
1096
1439
  });
1097
1440
 
1441
+ describe("--log-level", () => {
1442
+ it("should not output warnings with log-level 'none'", async () => {
1443
+ fs.writeFileSync("index.js", `export default {};`);
1444
+ await runWrangler("dev index.js --inspect --log-level none");
1445
+ expect(std).toMatchInlineSnapshot(`
1446
+ Object {
1447
+ "debug": "",
1448
+ "err": "",
1449
+ "out": "",
1450
+ "warn": "",
1451
+ }
1452
+ `);
1453
+ });
1454
+
1455
+ it("should output warnings with log-level 'warn'", async () => {
1456
+ fs.writeFileSync("index.js", `export default {};`);
1457
+ await runWrangler("dev index.js --inspect --log-level warn");
1458
+ expect(std).toMatchInlineSnapshot(`
1459
+ Object {
1460
+ "debug": "",
1461
+ "err": "",
1462
+ "out": "",
1463
+ "warn": "▲ [WARNING] Passing --inspect is unnecessary, now you can always connect to devtools.
1464
+
1465
+ ",
1466
+ }
1467
+ `);
1468
+ });
1469
+
1470
+ it("should not output Errors with log-level error", async () => {
1471
+ fs.writeFileSync("index.js", `export default {};`);
1472
+ await runWrangler("dev index.js --inspect --log-level debug");
1473
+ expect(std.debug.length > 1).toBe(true);
1474
+ });
1475
+ });
1476
+
1098
1477
  describe("service bindings", () => {
1099
1478
  it("should warn when using service bindings", async () => {
1100
1479
  writeWranglerToml({
@@ -1105,24 +1484,23 @@ describe("wrangler dev", () => {
1105
1484
  });
1106
1485
  fs.writeFileSync("index.js", `export default {};`);
1107
1486
  await runWrangler("dev index.js");
1108
- expect(std).toMatchInlineSnapshot(`
1109
- Object {
1110
- "debug": "",
1111
- "err": "",
1112
- "out": "Your worker has access to the following bindings:
1113
- - Services:
1114
- - WorkerA: A
1115
- - WorkerB: B - staging",
1116
- "warn": "▲ [WARNING] Processing wrangler.toml configuration:
1487
+ expect(std.out).toMatchInlineSnapshot(`
1488
+ "Your worker has access to the following bindings:
1489
+ - Services:
1490
+ - WorkerA: A
1491
+ - WorkerB: B - staging"
1492
+ `);
1493
+ expect(std.warn).toMatchInlineSnapshot(`
1494
+ "▲ [WARNING] Processing wrangler.toml configuration:
1117
1495
 
1118
- - \\"services\\" fields are experimental and may change or break at any time.
1496
+ - \\"services\\" fields are experimental and may change or break at any time.
1119
1497
 
1120
1498
 
1121
- ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
1499
+ ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
1122
1500
 
1123
- ",
1124
- }
1125
- `);
1501
+ "
1502
+ `);
1503
+ expect(std.err).toMatchInlineSnapshot(`""`);
1126
1504
  });
1127
1505
  });
1128
1506
 
@@ -1173,31 +1551,36 @@ describe("wrangler dev", () => {
1173
1551
  fs.writeFileSync("index.js", `export default {};`);
1174
1552
  await runWrangler("dev index.js");
1175
1553
  expect(std).toMatchInlineSnapshot(`
1176
- Object {
1177
- "debug": "",
1178
- "err": "",
1179
- "out": "Using vars defined in .dev.vars
1180
- Your worker has access to the following bindings:
1181
- - Vars:
1182
- - variable: \\"123\\"
1183
- - overriden: \\"(hidden)\\"
1184
- - SECRET: \\"(hidden)\\"",
1185
- "warn": "",
1186
- }
1187
- `);
1554
+ Object {
1555
+ "debug": "",
1556
+ "err": "",
1557
+ "out": "Using vars defined in .dev.vars
1558
+ Your worker has access to the following bindings:
1559
+ - Vars:
1560
+ - variable: 123
1561
+ - overriden: \\"(hidden)\\"
1562
+ - SECRET: \\"(hidden)\\"",
1563
+ "warn": "",
1564
+ }
1565
+ `);
1188
1566
  });
1189
1567
  });
1190
1568
  });
1191
1569
 
1192
1570
  function mockGetZones(domain: string, zones: { id: string }[] = []) {
1193
- const removeMock = setMockResponse(
1194
- "/zones",
1195
- "GET",
1196
- (_urlPieces, _init, queryParams) => {
1197
- expect([...queryParams.entries()]).toEqual([["name", domain]]);
1198
- // Because the API URL `/zones` is the same for each request, we can get into a situation where earlier mocks get triggered for later requests. So, we simply clear the mock on every trigger.
1199
- removeMock();
1200
- return zones;
1201
- }
1571
+ msw.use(
1572
+ rest.get("*/zones", (req, res, ctx) => {
1573
+ expect([...req.url.searchParams.entries()]).toEqual([["name", domain]]);
1574
+
1575
+ return res(
1576
+ ctx.status(200),
1577
+ ctx.json({
1578
+ success: true,
1579
+ errors: [],
1580
+ messages: [],
1581
+ result: zones,
1582
+ })
1583
+ );
1584
+ })
1202
1585
  );
1203
1586
  }