wrangler 0.0.0-e043479 → 0.0.0-e0a0509

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +27 -14
  2. package/bin/wrangler.js +13 -1
  3. package/miniflare-dist/index.mjs +4886 -0
  4. package/package.json +38 -25
  5. package/pages/functions/buildPlugin.ts +92 -0
  6. package/pages/functions/buildWorker.ts +80 -4
  7. package/pages/functions/filepath-routing.test.ts +136 -25
  8. package/pages/functions/filepath-routing.ts +14 -3
  9. package/pages/functions/routes.ts +6 -1
  10. package/pages/functions/template-plugin.ts +146 -0
  11. package/pages/functions/template-worker.ts +21 -8
  12. package/src/__tests__/config-cache.test.ts +36 -0
  13. package/src/__tests__/configuration.test.ts +1294 -355
  14. package/src/__tests__/dev.test.tsx +592 -12
  15. package/src/__tests__/guess-worker-format.test.ts +37 -18
  16. package/src/__tests__/helpers/mock-account-id.ts +4 -0
  17. package/src/__tests__/helpers/mock-cfetch.ts +8 -4
  18. package/src/__tests__/helpers/mock-console.ts +20 -3
  19. package/src/__tests__/helpers/mock-dialogs.ts +26 -1
  20. package/src/__tests__/helpers/mock-http-server.ts +46 -0
  21. package/src/__tests__/helpers/mock-istty.ts +27 -0
  22. package/src/__tests__/helpers/mock-kv.ts +9 -16
  23. package/src/__tests__/helpers/mock-oauth-flow.ts +255 -0
  24. package/src/__tests__/helpers/run-in-tmp.ts +10 -0
  25. package/src/__tests__/helpers/write-worker-source.ts +31 -0
  26. package/src/__tests__/https-options.test.ts +130 -0
  27. package/src/__tests__/index.test.ts +129 -753
  28. package/src/__tests__/init.test.ts +1516 -0
  29. package/src/__tests__/jest.setup.ts +13 -5
  30. package/src/__tests__/kv.test.ts +208 -174
  31. package/src/__tests__/logger.test.ts +115 -0
  32. package/src/__tests__/pages.test.ts +327 -0
  33. package/src/__tests__/parse.test.ts +4 -0
  34. package/src/__tests__/publish.test.ts +3313 -505
  35. package/src/__tests__/r2.test.ts +38 -26
  36. package/src/__tests__/route.test.ts +45 -0
  37. package/src/__tests__/secret.test.ts +55 -34
  38. package/src/__tests__/tail.test.ts +146 -20
  39. package/src/__tests__/user.test.ts +131 -0
  40. package/src/__tests__/whoami.test.tsx +26 -7
  41. package/src/bundle.ts +43 -7
  42. package/src/cfetch/internal.ts +9 -5
  43. package/src/cli.ts +5 -11
  44. package/src/config/README.md +7 -7
  45. package/src/config/config.ts +69 -105
  46. package/src/config/environment.ts +93 -4
  47. package/src/config/index.ts +15 -4
  48. package/src/config/validation-helpers.ts +228 -23
  49. package/src/config/validation.ts +559 -154
  50. package/src/config-cache.ts +45 -0
  51. package/src/{api/preview.ts → create-worker-preview.ts} +41 -13
  52. package/src/{api/form_data.ts → create-worker-upload-form.ts} +33 -10
  53. package/src/dev/dev-vars.ts +36 -0
  54. package/src/dev/dev.tsx +418 -0
  55. package/src/dev/local.tsx +312 -0
  56. package/src/dev/remote.tsx +213 -0
  57. package/src/dev/use-esbuild.ts +118 -0
  58. package/src/dialogs.tsx +16 -6
  59. package/src/entry.ts +222 -12
  60. package/src/environment-variables.ts +3 -1
  61. package/src/errors.ts +11 -0
  62. package/src/https-options.ts +123 -0
  63. package/src/index.tsx +878 -482
  64. package/src/inspect.ts +25 -11
  65. package/src/intl-polyfill.d.ts +139 -0
  66. package/src/{kv.tsx → kv.ts} +7 -27
  67. package/src/logger.ts +66 -0
  68. package/src/miniflare-cli/README.md +30 -0
  69. package/src/miniflare-cli/enum-keys.ts +17 -0
  70. package/src/miniflare-cli/index.ts +41 -0
  71. package/src/miniflare-cli/request-context.ts +40 -0
  72. package/src/module-collection.ts +94 -6
  73. package/src/open-in-browser.ts +18 -5
  74. package/src/package-manager.ts +9 -8
  75. package/src/pages.tsx +892 -62
  76. package/src/parse.ts +4 -2
  77. package/src/proxy.ts +128 -55
  78. package/src/publish.ts +305 -199
  79. package/src/selfsigned.d.ts +29 -0
  80. package/src/sites.tsx +88 -33
  81. package/src/tail/index.ts +2 -2
  82. package/src/tail/printing.ts +13 -8
  83. package/src/update-check.ts +19 -0
  84. package/src/user.tsx +244 -104
  85. package/src/whoami.tsx +2 -1
  86. package/src/{api/worker.ts → worker.ts} +15 -29
  87. package/templates/gitignore +171 -0
  88. package/templates/static-asset-facade.js +1 -1
  89. package/wrangler-dist/cli.js +23568 -50489
  90. package/src/__tests__/helpers/mock-user.ts +0 -27
  91. package/src/__tests__/logout.test.ts +0 -50
  92. package/src/__tests__/sentry.test.ts +0 -146
  93. package/src/dev.tsx +0 -960
  94. package/src/guess-worker-format.ts +0 -68
  95. package/src/reporting.ts +0 -115
  96. package/wrangler-dist/cli.js.map +0 -7
@@ -1,6 +1,8 @@
1
1
  import * as fs from "node:fs";
2
+ import getPort from "get-port";
2
3
  import patchConsole from "patch-console";
3
- import Dev from "../dev";
4
+ import dedent from "ts-dedent";
5
+ import Dev from "../dev/dev";
4
6
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
5
7
  import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
6
8
  import { mockConsoleMethods } from "./helpers/mock-console";
@@ -8,8 +10,7 @@ import { runInTempDir } from "./helpers/run-in-tmp";
8
10
  import { runWrangler } from "./helpers/run-wrangler";
9
11
  import writeWranglerToml from "./helpers/write-wrangler-toml";
10
12
 
11
- describe("Dev component", () => {
12
- beforeEach(() => {});
13
+ describe("wrangler dev", () => {
13
14
  mockAccountId();
14
15
  mockApiToken();
15
16
  runInTempDir();
@@ -20,6 +21,56 @@ describe("Dev component", () => {
20
21
  unsetAllMocks();
21
22
  });
22
23
 
24
+ describe("compatibility-date", () => {
25
+ it("should not warn if there is no wrangler.toml and no compatibility-date specified", async () => {
26
+ fs.writeFileSync("index.js", `export default {};`);
27
+ await runWrangler("dev index.js");
28
+ expect(std.out).toMatchInlineSnapshot(`""`);
29
+ expect(std.warn).toMatchInlineSnapshot(`""`);
30
+ expect(std.err).toMatchInlineSnapshot(`""`);
31
+ });
32
+
33
+ it("should warn if there is a wrangler.toml but no compatibility-date", async () => {
34
+ writeWranglerToml({
35
+ main: "index.js",
36
+ compatibility_date: undefined,
37
+ });
38
+ fs.writeFileSync("index.js", `export default {};`);
39
+ await runWrangler("dev");
40
+ const currentDate = new Date().toISOString().substring(0, 10);
41
+ expect(std.out).toMatchInlineSnapshot(`""`);
42
+ expect(std.warn.replaceAll(currentDate, "<current-date>"))
43
+ .toMatchInlineSnapshot(`
44
+ "▲ [WARNING] No compatibility_date was specified. Using today's date: <current-date>.
45
+
46
+ Add one to your wrangler.toml file:
47
+ \`\`\`
48
+ compatibility_date = \\"<current-date>\\"
49
+ \`\`\`
50
+ or pass it in your terminal:
51
+ \`\`\`
52
+ --compatibility-date=<current-date>
53
+ \`\`\`
54
+ See https://developers.cloudflare.com/workers/platform/compatibility-dates for more information.
55
+
56
+ "
57
+ `);
58
+ expect(std.err).toMatchInlineSnapshot(`""`);
59
+ });
60
+
61
+ it("should not warn if there is a wrangler.toml but compatibility-date is specified at the command line", async () => {
62
+ writeWranglerToml({
63
+ main: "index.js",
64
+ compatibility_date: undefined,
65
+ });
66
+ fs.writeFileSync("index.js", `export default {};`);
67
+ await runWrangler("dev --compatibility-date=2020-01-01");
68
+ expect(std.out).toMatchInlineSnapshot(`""`);
69
+ expect(std.warn).toMatchInlineSnapshot(`""`);
70
+ expect(std.err).toMatchInlineSnapshot(`""`);
71
+ });
72
+ });
73
+
23
74
  describe("entry-points", () => {
24
75
  it("should error if there is no entry-point specified", async () => {
25
76
  writeWranglerToml();
@@ -30,13 +81,67 @@ describe("Dev component", () => {
30
81
  `"Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler dev path/to/script\`) or the \`main\` config field."`
31
82
  );
32
83
 
33
- expect(std.out).toMatchInlineSnapshot(`""`);
84
+ expect(std.out).toMatchInlineSnapshot(`
85
+ "
86
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
87
+ `);
34
88
  expect(std.err).toMatchInlineSnapshot(`
35
- "Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler dev path/to/script\`) or the \`main\` config field.
89
+ "X [ERROR] Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler dev path/to/script\`) or the \`main\` config field.
36
90
 
37
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
91
+ "
38
92
  `);
39
93
  });
94
+
95
+ it("should use `main` from the top-level environment", async () => {
96
+ writeWranglerToml({
97
+ main: "index.js",
98
+ });
99
+ fs.writeFileSync("index.js", `export default {};`);
100
+ await runWrangler("dev");
101
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
102
+ /index\.js$/
103
+ );
104
+ expect(std.out).toMatchInlineSnapshot(`""`);
105
+ expect(std.warn).toMatchInlineSnapshot(`""`);
106
+ expect(std.err).toMatchInlineSnapshot(`""`);
107
+ });
108
+
109
+ it("should use `main` from a named environment", async () => {
110
+ writeWranglerToml({
111
+ env: {
112
+ ENV1: {
113
+ main: "index.js",
114
+ },
115
+ },
116
+ });
117
+ fs.writeFileSync("index.js", `export default {};`);
118
+ await runWrangler("dev --env=ENV1");
119
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
120
+ /index\.js$/
121
+ );
122
+ expect(std.out).toMatchInlineSnapshot(`""`);
123
+ expect(std.warn).toMatchInlineSnapshot(`""`);
124
+ expect(std.err).toMatchInlineSnapshot(`""`);
125
+ });
126
+
127
+ it("should use `main` from a named environment, rather than the top-level", async () => {
128
+ writeWranglerToml({
129
+ main: "other.js",
130
+ env: {
131
+ ENV1: {
132
+ main: "index.js",
133
+ },
134
+ },
135
+ });
136
+ fs.writeFileSync("index.js", `export default {};`);
137
+ await runWrangler("dev --env=ENV1");
138
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
139
+ /index\.js$/
140
+ );
141
+ expect(std.out).toMatchInlineSnapshot(`""`);
142
+ expect(std.warn).toMatchInlineSnapshot(`""`);
143
+ expect(std.err).toMatchInlineSnapshot(`""`);
144
+ });
40
145
  });
41
146
 
42
147
  describe("host", () => {
@@ -120,6 +225,38 @@ describe("Dev component", () => {
120
225
  );
121
226
  });
122
227
 
228
+ it("should, when provided, use a configured zone_id", async () => {
229
+ writeWranglerToml({
230
+ main: "index.js",
231
+ routes: [
232
+ { pattern: "https://some-domain.com/*", zone_id: "some-zone-id" },
233
+ ],
234
+ });
235
+ fs.writeFileSync("index.js", `export default {};`);
236
+ await runWrangler("dev");
237
+ expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
238
+ host: "some-domain.com",
239
+ id: "some-zone-id",
240
+ });
241
+ });
242
+
243
+ it("should, when provided, use a zone_name to get a zone_id", async () => {
244
+ writeWranglerToml({
245
+ main: "index.js",
246
+ routes: [
247
+ { pattern: "https://some-domain.com/*", zone_name: "some-zone.com" },
248
+ ],
249
+ });
250
+ fs.writeFileSync("index.js", `export default {};`);
251
+ mockGetZones("some-zone.com", [{ id: "a-zone-id" }]);
252
+ await runWrangler("dev");
253
+ expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
254
+ // note that it uses the provided zone_name as a host too
255
+ host: "some-zone.com",
256
+ id: "a-zone-id",
257
+ });
258
+ });
259
+
123
260
  it("given a long host, it should use the longest subdomain that resolves to a zone", async () => {
124
261
  writeWranglerToml({
125
262
  main: "index.js",
@@ -135,8 +272,8 @@ describe("Dev component", () => {
135
272
  });
136
273
  });
137
274
 
138
- it("should, in order, use args.host/config.dev.host/args.routes/config.route/config.routes", async () => {
139
- // This test might seem like it's testing implmentation details, but let's be specific and consider it a spec
275
+ it("should, in order, use args.host/config.dev.host/args.routes/(config.route|config.routes)", async () => {
276
+ // This test might seem like it's testing implementation details, but let's be specific and consider it a spec
140
277
 
141
278
  fs.writeFileSync("index.js", `export default {};`);
142
279
 
@@ -158,7 +295,6 @@ describe("Dev component", () => {
158
295
  writeWranglerToml({
159
296
  main: "index.js",
160
297
  route: "https://4.some-host.com/some/path/*",
161
- routes: ["http://5.some-host.com/some/path/*"],
162
298
  });
163
299
  await runWrangler("dev");
164
300
  expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
@@ -172,7 +308,6 @@ describe("Dev component", () => {
172
308
  writeWranglerToml({
173
309
  main: "index.js",
174
310
  route: "https://4.some-host.com/some/path/*",
175
- routes: ["http://5.some-host.com/some/path/*"],
176
311
  });
177
312
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
178
313
  expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
@@ -189,7 +324,6 @@ describe("Dev component", () => {
189
324
  host: `2.some-host.com`,
190
325
  },
191
326
  route: "4.some-host.com/some/path/*",
192
- routes: ["5.some-host.com/some/path/*"],
193
327
  });
194
328
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
195
329
  expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
@@ -206,7 +340,6 @@ describe("Dev component", () => {
206
340
  host: `2.some-host.com`,
207
341
  },
208
342
  route: "4.some-host.com/some/path/*",
209
- routes: ["5.some-host.com/some/path/*"],
210
343
  });
211
344
  await runWrangler(
212
345
  "dev --routes http://3.some-host.com/some/path/* --host 1.some-host.com"
@@ -230,6 +363,453 @@ describe("Dev component", () => {
230
363
  `"Could not find zone for some-host.com"`
231
364
  );
232
365
  });
366
+
367
+ it("should not try to resolve a zone when starting in local mode", async () => {
368
+ writeWranglerToml({
369
+ main: "index.js",
370
+ });
371
+ fs.writeFileSync("index.js", `export default {};`);
372
+ await runWrangler("dev --host some-host.com --local");
373
+ expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual(undefined);
374
+ });
375
+ });
376
+
377
+ describe("custom builds", () => {
378
+ it("should run a custom build before starting `dev`", async () => {
379
+ writeWranglerToml({
380
+ build: {
381
+ command: `node -e "console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')"`,
382
+ },
383
+ });
384
+
385
+ await runWrangler("dev index.js");
386
+
387
+ expect(fs.readFileSync("index.js", "utf-8")).toMatchInlineSnapshot(
388
+ `"export default { fetch(){ return new Response(123) } }"`
389
+ );
390
+
391
+ // and the command would pass through
392
+ expect((Dev as jest.Mock).mock.calls[0][0].build).toEqual({
393
+ command:
394
+ "node -e \"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\"",
395
+ cwd: undefined,
396
+ watch_dir: "src",
397
+ });
398
+ expect(std.out).toMatchInlineSnapshot(
399
+ `"Running custom build: node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\""`
400
+ );
401
+ expect(std.err).toMatchInlineSnapshot(`""`);
402
+ expect(std.warn).toMatchInlineSnapshot(`""`);
403
+ });
404
+
405
+ if (process.platform !== "win32") {
406
+ it("should run a custom build of multiple steps combined by && before starting `dev`", async () => {
407
+ writeWranglerToml({
408
+ build: {
409
+ command: `echo "custom build" && echo "export default { fetch(){ return new Response(123) } }" > index.js`,
410
+ },
411
+ });
412
+
413
+ await runWrangler("dev index.js");
414
+
415
+ expect(fs.readFileSync("index.js", "utf-8")).toMatchInlineSnapshot(`
416
+ "export default { fetch(){ return new Response(123) } }
417
+ "
418
+ `);
419
+
420
+ expect(std.out).toMatchInlineSnapshot(
421
+ `"Running custom build: echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js"`
422
+ );
423
+ expect(std.err).toMatchInlineSnapshot(`""`);
424
+ expect(std.warn).toMatchInlineSnapshot(`""`);
425
+ });
426
+ }
427
+
428
+ it("should throw an error if the entry doesn't exist after the build finishes", async () => {
429
+ writeWranglerToml({
430
+ main: "index.js",
431
+ build: {
432
+ command: `node -e "console.log('custom build');"`,
433
+ },
434
+ });
435
+
436
+ await expect(
437
+ runWrangler("dev")
438
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
439
+ `"Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\""`
440
+ );
441
+ expect(std.out).toMatchInlineSnapshot(`
442
+ "Running custom build: node -e \\"console.log('custom build');\\"
443
+
444
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
445
+ `);
446
+ expect(std.err).toMatchInlineSnapshot(`
447
+ "X [ERROR] Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\"
448
+
449
+ "
450
+ `);
451
+ expect(std.warn).toMatchInlineSnapshot(`""`);
452
+ });
453
+ });
454
+
455
+ describe("upstream-protocol", () => {
456
+ it("should default upstream-protocol to `https`", async () => {
457
+ writeWranglerToml({
458
+ main: "index.js",
459
+ });
460
+ fs.writeFileSync("index.js", `export default {};`);
461
+ await runWrangler("dev");
462
+ expect((Dev as jest.Mock).mock.calls[0][0].upstreamProtocol).toEqual(
463
+ "https"
464
+ );
465
+ expect(std.out).toMatchInlineSnapshot(`""`);
466
+ expect(std.warn).toMatchInlineSnapshot(`""`);
467
+ expect(std.err).toMatchInlineSnapshot(`""`);
468
+ });
469
+
470
+ it("should warn if `--upstream-protocol=http` is used", async () => {
471
+ writeWranglerToml({
472
+ main: "index.js",
473
+ });
474
+ fs.writeFileSync("index.js", `export default {};`);
475
+ await runWrangler("dev --upstream-protocol=http");
476
+ expect((Dev as jest.Mock).mock.calls[0][0].upstreamProtocol).toEqual(
477
+ "http"
478
+ );
479
+ expect(std.out).toMatchInlineSnapshot(`""`);
480
+ expect(std.warn).toMatchInlineSnapshot(`
481
+ "▲ [WARNING] Setting upstream-protocol to http is not currently implemented.
482
+
483
+ If this is required in your project, please add your use case to the following issue:
484
+ https://github.com/cloudflare/wrangler2/issues/583.
485
+
486
+ "
487
+ `);
488
+ expect(std.err).toMatchInlineSnapshot(`""`);
489
+ });
490
+ });
491
+
492
+ describe("local-protocol", () => {
493
+ it("should default local-protocol to `http`", async () => {
494
+ writeWranglerToml({
495
+ main: "index.js",
496
+ });
497
+ fs.writeFileSync("index.js", `export default {};`);
498
+ await runWrangler("dev");
499
+ expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual("http");
500
+ expect(std.out).toMatchInlineSnapshot(`""`);
501
+ expect(std.warn).toMatchInlineSnapshot(`""`);
502
+ expect(std.err).toMatchInlineSnapshot(`""`);
503
+ });
504
+
505
+ it("should use `local_protocol` from `wrangler.toml`, if available", async () => {
506
+ writeWranglerToml({
507
+ main: "index.js",
508
+ dev: {
509
+ local_protocol: "https",
510
+ },
511
+ });
512
+ fs.writeFileSync("index.js", `export default {};`);
513
+ await runWrangler("dev");
514
+ expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual(
515
+ "https"
516
+ );
517
+ expect(std.out).toMatchInlineSnapshot(`""`);
518
+ expect(std.warn).toMatchInlineSnapshot(`""`);
519
+ expect(std.err).toMatchInlineSnapshot(`""`);
520
+ });
521
+
522
+ it("should use --local-protocol command line arg, if provided", async () => {
523
+ // Here we show that the command line overrides the wrangler.toml by
524
+ // setting the config to https, and then setting it back to http on the command line.
525
+ writeWranglerToml({
526
+ main: "index.js",
527
+ dev: {
528
+ local_protocol: "https",
529
+ },
530
+ });
531
+ fs.writeFileSync("index.js", `export default {};`);
532
+ await runWrangler("dev --local-protocol=http");
533
+ expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual("http");
534
+ expect(std.out).toMatchInlineSnapshot(`""`);
535
+ expect(std.warn).toMatchInlineSnapshot(`""`);
536
+ expect(std.err).toMatchInlineSnapshot(`""`);
537
+ });
538
+ });
539
+
540
+ describe("ip", () => {
541
+ it("should default ip to localhost", async () => {
542
+ writeWranglerToml({
543
+ main: "index.js",
544
+ });
545
+ fs.writeFileSync("index.js", `export default {};`);
546
+ await runWrangler("dev");
547
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
548
+ expect(std.out).toMatchInlineSnapshot(`""`);
549
+ expect(std.warn).toMatchInlineSnapshot(`""`);
550
+ expect(std.err).toMatchInlineSnapshot(`""`);
551
+ });
552
+
553
+ it("should use to `ip` from `wrangler.toml`, if available", async () => {
554
+ writeWranglerToml({
555
+ main: "index.js",
556
+ dev: {
557
+ ip: "0.0.0.0",
558
+ },
559
+ });
560
+ fs.writeFileSync("index.js", `export default {};`);
561
+ await runWrangler("dev");
562
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
563
+ expect(std.out).toMatchInlineSnapshot(`""`);
564
+ expect(std.warn).toMatchInlineSnapshot(`""`);
565
+ expect(std.err).toMatchInlineSnapshot(`""`);
566
+ });
567
+
568
+ it("should use --ip command line arg, if provided", async () => {
569
+ writeWranglerToml({
570
+ main: "index.js",
571
+ dev: {
572
+ ip: "1.1.1.1",
573
+ },
574
+ });
575
+ fs.writeFileSync("index.js", `export default {};`);
576
+ await runWrangler("dev --ip=0.0.0.0");
577
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
578
+ expect(std.out).toMatchInlineSnapshot(`""`);
579
+ expect(std.warn).toMatchInlineSnapshot(`""`);
580
+ expect(std.err).toMatchInlineSnapshot(`""`);
581
+ });
582
+ });
583
+
584
+ describe("port", () => {
585
+ it("should default port to 8787 if it is not in use", async () => {
586
+ writeWranglerToml({
587
+ main: "index.js",
588
+ });
589
+ fs.writeFileSync("index.js", `export default {};`);
590
+ await runWrangler("dev");
591
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8787);
592
+ expect(std.out).toMatchInlineSnapshot(`""`);
593
+ expect(std.warn).toMatchInlineSnapshot(`""`);
594
+ expect(std.err).toMatchInlineSnapshot(`""`);
595
+ });
596
+
597
+ it("should use to `port` from `wrangler.toml`, if available", async () => {
598
+ writeWranglerToml({
599
+ main: "index.js",
600
+ dev: {
601
+ port: 8888,
602
+ },
603
+ });
604
+ fs.writeFileSync("index.js", `export default {};`);
605
+ // Mock `getPort()` to resolve to a completely different port.
606
+ (getPort as jest.Mock).mockResolvedValue(98765);
607
+
608
+ await runWrangler("dev");
609
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8888);
610
+ expect(std.out).toMatchInlineSnapshot(`""`);
611
+ expect(std.warn).toMatchInlineSnapshot(`""`);
612
+ expect(std.err).toMatchInlineSnapshot(`""`);
613
+ });
614
+
615
+ it("should use --port command line arg, if provided", async () => {
616
+ writeWranglerToml({
617
+ main: "index.js",
618
+ dev: {
619
+ port: 8888,
620
+ },
621
+ });
622
+ fs.writeFileSync("index.js", `export default {};`);
623
+ // Mock `getPort()` to resolve to a completely different port.
624
+ (getPort as jest.Mock).mockResolvedValue(98765);
625
+
626
+ await runWrangler("dev --port=9999");
627
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(9999);
628
+ expect(std.out).toMatchInlineSnapshot(`""`);
629
+ expect(std.warn).toMatchInlineSnapshot(`""`);
630
+ expect(std.err).toMatchInlineSnapshot(`""`);
631
+ });
632
+
633
+ it("should use a different port to the default if it is in use", async () => {
634
+ writeWranglerToml({
635
+ main: "index.js",
636
+ });
637
+ fs.writeFileSync("index.js", `export default {};`);
638
+ // Mock `getPort()` to resolve to a completely different port.
639
+ (getPort as jest.Mock).mockResolvedValue(98765);
640
+
641
+ await runWrangler("dev");
642
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(98765);
643
+ expect(std.out).toMatchInlineSnapshot(`""`);
644
+ expect(std.warn).toMatchInlineSnapshot(`""`);
645
+ expect(std.err).toMatchInlineSnapshot(`""`);
646
+ });
647
+ });
648
+
649
+ describe("durable_objects", () => {
650
+ it("should warn if there is one or more remote Durable Object", async () => {
651
+ writeWranglerToml({
652
+ main: "index.js",
653
+ durable_objects: {
654
+ bindings: [
655
+ { name: "NAME_1", class_name: "CLASS_1" },
656
+ {
657
+ name: "NAME_2",
658
+ class_name: "CLASS_2",
659
+ script_name: "SCRIPT_A",
660
+ },
661
+ { name: "NAME_3", class_name: "CLASS_3" },
662
+ {
663
+ name: "NAME_4",
664
+ class_name: "CLASS_4",
665
+ script_name: "SCRIPT_B",
666
+ },
667
+ ],
668
+ },
669
+ });
670
+ fs.writeFileSync("index.js", `export default {};`);
671
+ await runWrangler("dev");
672
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
673
+ expect(std.out).toMatchInlineSnapshot(`""`);
674
+ expect(std.warn).toMatchInlineSnapshot(`
675
+ "▲ [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed.
676
+
677
+ Be aware that changes to the data stored in these Durable Objects will be permanent and affect the
678
+ live instances.
679
+ Remote Durable Objects that are affected:
680
+ - {\\"name\\":\\"NAME_2\\",\\"class_name\\":\\"CLASS_2\\",\\"script_name\\":\\"SCRIPT_A\\"}
681
+ - {\\"name\\":\\"NAME_4\\",\\"class_name\\":\\"CLASS_4\\",\\"script_name\\":\\"SCRIPT_B\\"}
682
+
683
+ "
684
+ `);
685
+ expect(std.err).toMatchInlineSnapshot(`""`);
686
+ });
687
+ });
688
+
689
+ describe(".dev.vars", () => {
690
+ it("should override `vars` bindings from `wrangler.toml` with values in `.dev.vars`", async () => {
691
+ fs.writeFileSync("index.js", `export default {};`);
692
+
693
+ const localVarsEnvContent = dedent`
694
+ # Preceding comment
695
+ VAR_1="var #1 value" # End of line comment
696
+ VAR_3="var #3 value"
697
+ VAR_MULTI_LINE_1="A: line 1
698
+ line 2"
699
+ VAR_MULTI_LINE_2="B: line 1\\nline 2"
700
+ EMPTY=
701
+ UNQUOTED= unquoted value
702
+ `;
703
+ fs.writeFileSync(".dev.vars", localVarsEnvContent, "utf8");
704
+
705
+ writeWranglerToml({
706
+ main: "index.js",
707
+ vars: {
708
+ VAR_1: "original value 1",
709
+ VAR_2: "original value 2", // should not get overridden
710
+ VAR_3: "original value 3",
711
+ VAR_MULTI_LINE_1: "original multi-line 1",
712
+ VAR_MULTI_LINE_2: "original multi-line 2",
713
+ EMPTY: "original empty",
714
+ UNQUOTED: "original unquoted",
715
+ },
716
+ });
717
+ await runWrangler("dev");
718
+ const varBindings: Record<string, unknown> = (Dev as jest.Mock).mock
719
+ .calls[0][0].bindings.vars;
720
+
721
+ expect(varBindings).toEqual({
722
+ VAR_1: "var #1 value",
723
+ VAR_2: "original value 2",
724
+ VAR_3: "var #3 value",
725
+ VAR_MULTI_LINE_1: "A: line 1\nline 2",
726
+ VAR_MULTI_LINE_2: "B: line 1\nline 2",
727
+ EMPTY: "",
728
+ UNQUOTED: "unquoted value", // Note that whitespace is trimmed
729
+ });
730
+ expect(std.out).toMatchInlineSnapshot(
731
+ `"Using vars defined in .dev.vars"`
732
+ );
733
+ expect(std.warn).toMatchInlineSnapshot(`""`);
734
+ expect(std.err).toMatchInlineSnapshot(`""`);
735
+ });
736
+ });
737
+
738
+ describe("site", () => {
739
+ it("should error if --site is used with no value", async () => {
740
+ await expect(
741
+ runWrangler("dev --site")
742
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
743
+ `"Not enough arguments following: site"`
744
+ );
745
+
746
+ expect(std).toMatchInlineSnapshot(`
747
+ Object {
748
+ "debug": "",
749
+ "err": "wrangler dev [script]
750
+
751
+ 👂 Start a local server for developing your worker
752
+
753
+ Positionals:
754
+ script The path to an entry point for your worker [string]
755
+
756
+ Flags:
757
+ -c, --config Path to .toml configuration file [string]
758
+ -h, --help Show help [boolean]
759
+ -v, --version Show version number [boolean]
760
+
761
+ Options:
762
+ --name Name of the worker [string]
763
+ --format Choose an entry type [deprecated] [choices: \\"modules\\", \\"service-worker\\"]
764
+ -e, --env Perform on a specific environment [string]
765
+ --compatibility-date Date to use for compatibility checks [string]
766
+ --compatibility-flags, --compatibility-flag Flags to use for compatibility checks [array]
767
+ --latest Use the latest version of the worker runtime [boolean] [default: true]
768
+ --ip IP address to listen on, defaults to \`localhost\` [string]
769
+ --port Port to listen on [number]
770
+ --inspector-port Port for devtools to connect to [number]
771
+ --routes, --route Routes to upload [array]
772
+ --host Host to forward requests to, defaults to the zone of project [string]
773
+ --local-protocol Protocol to listen to requests on, defaults to http. [choices: \\"http\\", \\"https\\"]
774
+ --experimental-public Static assets to be served [string]
775
+ --site Root folder of static assets for Workers Sites [string]
776
+ --site-include Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded. [array]
777
+ --site-exclude Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded. [array]
778
+ --upstream-protocol Protocol to forward requests to host on, defaults to https. [choices: \\"http\\", \\"https\\"]
779
+ --jsx-factory The function that is called for each JSX element [string]
780
+ --jsx-fragment The function that is called for each JSX fragment [string]
781
+ --tsconfig Path to a custom tsconfig.json file [string]
782
+ -l, --local Run on my machine [boolean] [default: false]
783
+ --minify Minify the script [boolean]
784
+ --node-compat Enable node.js compatibility [boolean]
785
+ --experimental-enable-local-persistence Enable persistence for this session (only for local mode) [boolean]
786
+ --inspect Enable dev tools [deprecated] [boolean]
787
+ X [ERROR] Not enough arguments following: site
788
+
789
+ ",
790
+ "out": "
791
+ ",
792
+ "warn": "",
793
+ }
794
+ `);
795
+ });
796
+ });
797
+
798
+ describe("--inspect", () => {
799
+ it("should warn if --inspect is used", async () => {
800
+ fs.writeFileSync("index.js", `export default {};`);
801
+ await runWrangler("dev index.js --inspect");
802
+ expect(std).toMatchInlineSnapshot(`
803
+ Object {
804
+ "debug": "",
805
+ "err": "",
806
+ "out": "",
807
+ "warn": "▲ [WARNING] Passing --inspect is unnecessary, now you can always connect to devtools.
808
+
809
+ ",
810
+ }
811
+ `);
812
+ });
233
813
  });
234
814
  });
235
815