wrangler 0.0.0-e2f9bb2 → 0.0.0-e3278fa

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 (90) hide show
  1. package/Cloudflare_CA.pem +18 -0
  2. package/README.md +3 -1
  3. package/bin/wrangler.js +36 -4
  4. package/package.json +12 -7
  5. package/pages/functions/buildPlugin.ts +13 -0
  6. package/pages/functions/buildWorker.ts +14 -1
  7. package/pages/functions/template-plugin.ts +3 -2
  8. package/src/__tests__/configuration.test.ts +370 -87
  9. package/src/__tests__/dev.test.tsx +298 -77
  10. package/src/__tests__/helpers/mock-dialogs.ts +43 -2
  11. package/src/__tests__/index.test.ts +79 -72
  12. package/src/__tests__/init.test.ts +718 -123
  13. package/src/__tests__/jest.setup.ts +8 -0
  14. package/src/__tests__/kv.test.ts +173 -146
  15. package/src/__tests__/package-manager.test.ts +154 -7
  16. package/src/__tests__/pages.test.ts +478 -53
  17. package/src/__tests__/parse.test.ts +8 -0
  18. package/src/__tests__/publish.test.ts +1094 -215
  19. package/src/__tests__/r2.test.ts +55 -36
  20. package/src/__tests__/secret.test.ts +39 -4
  21. package/src/__tests__/whoami.test.tsx +34 -0
  22. package/src/abort.d.ts +3 -0
  23. package/src/bundle.ts +34 -6
  24. package/src/cfetch/index.ts +21 -4
  25. package/src/cfetch/internal.ts +23 -18
  26. package/src/config/config.ts +2 -2
  27. package/src/config/environment.ts +40 -14
  28. package/src/config/index.ts +162 -0
  29. package/src/config/validation-helpers.ts +10 -1
  30. package/src/config/validation.ts +180 -65
  31. package/src/create-worker-preview.ts +32 -22
  32. package/src/create-worker-upload-form.ts +22 -8
  33. package/src/dev/dev.tsx +12 -18
  34. package/src/dev/local.tsx +10 -0
  35. package/src/dev/remote.tsx +40 -16
  36. package/src/dialogs.tsx +48 -0
  37. package/src/durable.ts +102 -0
  38. package/src/entry.ts +64 -9
  39. package/src/index.tsx +548 -317
  40. package/src/inspect.ts +39 -0
  41. package/src/kv.ts +114 -25
  42. package/src/open-in-browser.ts +5 -12
  43. package/src/package-manager.ts +50 -3
  44. package/src/pages.tsx +434 -207
  45. package/src/parse.ts +23 -4
  46. package/src/proxy.ts +59 -35
  47. package/src/publish.ts +374 -127
  48. package/src/sites.tsx +61 -28
  49. package/src/user.tsx +23 -2
  50. package/src/whoami.tsx +3 -2
  51. package/src/worker.ts +10 -1
  52. package/src/zones.ts +73 -0
  53. package/templates/new-worker-scheduled.js +17 -0
  54. package/templates/new-worker-scheduled.ts +32 -0
  55. package/templates/new-worker.ts +16 -1
  56. package/templates/static-asset-facade.js +0 -4
  57. package/wrangler-dist/cli.js +96965 -83414
  58. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  59. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  60. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  61. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  62. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  63. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  64. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  65. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  66. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  67. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  68. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  69. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  70. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  71. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  72. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  73. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  74. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  75. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  76. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  77. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  78. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  79. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  80. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  81. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  82. package/vendor/wrangler-mime/LICENSE +0 -21
  83. package/vendor/wrangler-mime/Mime.js +0 -97
  84. package/vendor/wrangler-mime/README.md +0 -187
  85. package/vendor/wrangler-mime/cli.js +0 -46
  86. package/vendor/wrangler-mime/index.js +0 -4
  87. package/vendor/wrangler-mime/lite.js +0 -4
  88. package/vendor/wrangler-mime/package.json +0 -52
  89. package/vendor/wrangler-mime/types/other.js +0 -1
  90. package/vendor/wrangler-mime/types/standard.js +0 -1
@@ -1,8 +1,8 @@
1
1
  import * as fs from "node:fs";
2
+ import getPort from "get-port";
2
3
  import patchConsole from "patch-console";
3
4
  import dedent from "ts-dedent";
4
5
  import Dev from "../dev/dev";
5
- import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
6
6
  import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
7
7
  import { mockConsoleMethods } from "./helpers/mock-console";
8
8
  import { runInTempDir } from "./helpers/run-in-tmp";
@@ -10,8 +10,6 @@ import { runWrangler } from "./helpers/run-wrangler";
10
10
  import writeWranglerToml from "./helpers/write-wrangler-toml";
11
11
 
12
12
  describe("wrangler dev", () => {
13
- mockAccountId();
14
- mockApiToken();
15
13
  runInTempDir();
16
14
  const std = mockConsoleMethods();
17
15
  afterEach(() => {
@@ -82,7 +80,7 @@ describe("wrangler dev", () => {
82
80
 
83
81
  expect(std.out).toMatchInlineSnapshot(`
84
82
  "
85
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
83
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
86
84
  `);
87
85
  expect(std.err).toMatchInlineSnapshot(`
88
86
  "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.
@@ -151,10 +149,12 @@ describe("wrangler dev", () => {
151
149
  fs.writeFileSync("index.js", `export default {};`);
152
150
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
153
151
  await runWrangler("dev --host some-host.com");
154
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
155
- host: "some-host.com",
156
- id: "some-zone-id",
157
- });
152
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
153
+ expect.objectContaining({
154
+ host: "some-host.com",
155
+ zone: "some-zone-id",
156
+ })
157
+ );
158
158
  });
159
159
 
160
160
  it("should read wrangler.toml's dev.host", async () => {
@@ -167,9 +167,7 @@ describe("wrangler dev", () => {
167
167
  fs.writeFileSync("index.js", `export default {};`);
168
168
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
169
169
  await runWrangler("dev");
170
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
171
- "some-host.com"
172
- );
170
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
173
171
  });
174
172
 
175
173
  it("should read --route", async () => {
@@ -179,9 +177,7 @@ describe("wrangler dev", () => {
179
177
  fs.writeFileSync("index.js", `export default {};`);
180
178
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
181
179
  await runWrangler("dev --route http://some-host.com/some/path/*");
182
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
183
- "some-host.com"
184
- );
180
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
185
181
  });
186
182
 
187
183
  it("should read wrangler.toml's routes", async () => {
@@ -195,9 +191,7 @@ describe("wrangler dev", () => {
195
191
  fs.writeFileSync("index.js", `export default {};`);
196
192
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
197
193
  await runWrangler("dev");
198
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
199
- "some-host.com"
200
- );
194
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
201
195
  });
202
196
 
203
197
  it("should read wrangler.toml's environment specific routes", async () => {
@@ -219,9 +213,29 @@ describe("wrangler dev", () => {
219
213
  fs.writeFileSync("index.js", `export default {};`);
220
214
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
221
215
  await runWrangler("dev --env staging");
222
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
223
- "some-host.com"
224
- );
216
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
217
+ });
218
+
219
+ it("should strip leading `*` from given host when deducing a zone id", async () => {
220
+ writeWranglerToml({
221
+ main: "index.js",
222
+ route: "*some-host.com/some/path/*",
223
+ });
224
+ fs.writeFileSync("index.js", `export default {};`);
225
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
226
+ await runWrangler("dev");
227
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
228
+ });
229
+
230
+ it("should strip leading `*.` from given host when deducing a zone id", async () => {
231
+ writeWranglerToml({
232
+ main: "index.js",
233
+ route: "*.some-host.com/some/path/*",
234
+ });
235
+ fs.writeFileSync("index.js", `export default {};`);
236
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
237
+ await runWrangler("dev");
238
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
225
239
  });
226
240
 
227
241
  it("should, when provided, use a configured zone_id", async () => {
@@ -233,10 +247,12 @@ describe("wrangler dev", () => {
233
247
  });
234
248
  fs.writeFileSync("index.js", `export default {};`);
235
249
  await runWrangler("dev");
236
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
237
- host: "some-domain.com",
238
- id: "some-zone-id",
239
- });
250
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
251
+ expect.objectContaining({
252
+ host: "some-domain.com",
253
+ zone: "some-zone-id",
254
+ })
255
+ );
240
256
  });
241
257
 
242
258
  it("should, when provided, use a zone_name to get a zone_id", async () => {
@@ -249,11 +265,13 @@ describe("wrangler dev", () => {
249
265
  fs.writeFileSync("index.js", `export default {};`);
250
266
  mockGetZones("some-zone.com", [{ id: "a-zone-id" }]);
251
267
  await runWrangler("dev");
252
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
253
- // note that it uses the provided zone_name as a host too
254
- host: "some-zone.com",
255
- id: "a-zone-id",
256
- });
268
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
269
+ expect.objectContaining({
270
+ // note that it uses the provided zone_name as a host too
271
+ host: "some-zone.com",
272
+ zone: "a-zone-id",
273
+ })
274
+ );
257
275
  });
258
276
 
259
277
  it("given a long host, it should use the longest subdomain that resolves to a zone", async () => {
@@ -265,10 +283,12 @@ describe("wrangler dev", () => {
265
283
  mockGetZones("222.333.some-host.com", []);
266
284
  mockGetZones("333.some-host.com", [{ id: "some-zone-id" }]);
267
285
  await runWrangler("dev --host 111.222.333.some-host.com");
268
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
269
- host: "111.222.333.some-host.com",
270
- id: "some-zone-id",
271
- });
286
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
287
+ expect.objectContaining({
288
+ host: "111.222.333.some-host.com",
289
+ zone: "some-zone-id",
290
+ })
291
+ );
272
292
  });
273
293
 
274
294
  it("should, in order, use args.host/config.dev.host/args.routes/(config.route|config.routes)", async () => {
@@ -283,10 +303,12 @@ describe("wrangler dev", () => {
283
303
  routes: ["http://5.some-host.com/some/path/*"],
284
304
  });
285
305
  await runWrangler("dev");
286
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
287
- host: "5.some-host.com",
288
- id: "some-zone-id-5",
289
- });
306
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
307
+ expect.objectContaining({
308
+ host: "5.some-host.com",
309
+ zone: "some-zone-id-5",
310
+ })
311
+ );
290
312
  (Dev as jest.Mock).mockClear();
291
313
 
292
314
  // config.route
@@ -296,10 +318,12 @@ describe("wrangler dev", () => {
296
318
  route: "https://4.some-host.com/some/path/*",
297
319
  });
298
320
  await runWrangler("dev");
299
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
300
- host: "4.some-host.com",
301
- id: "some-zone-id-4",
302
- });
321
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
322
+ expect.objectContaining({
323
+ host: "4.some-host.com",
324
+ zone: "some-zone-id-4",
325
+ })
326
+ );
303
327
  (Dev as jest.Mock).mockClear();
304
328
 
305
329
  // --routes
@@ -309,10 +333,12 @@ describe("wrangler dev", () => {
309
333
  route: "https://4.some-host.com/some/path/*",
310
334
  });
311
335
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
312
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
313
- host: "3.some-host.com",
314
- id: "some-zone-id-3",
315
- });
336
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
337
+ expect.objectContaining({
338
+ host: "3.some-host.com",
339
+ zone: "some-zone-id-3",
340
+ })
341
+ );
316
342
  (Dev as jest.Mock).mockClear();
317
343
 
318
344
  // config.dev.host
@@ -325,10 +351,12 @@ describe("wrangler dev", () => {
325
351
  route: "4.some-host.com/some/path/*",
326
352
  });
327
353
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
328
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
329
- host: "2.some-host.com",
330
- id: "some-zone-id-2",
331
- });
354
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
355
+ expect.objectContaining({
356
+ host: "2.some-host.com",
357
+ zone: "some-zone-id-2",
358
+ })
359
+ );
332
360
  (Dev as jest.Mock).mockClear();
333
361
 
334
362
  // --host
@@ -343,10 +371,12 @@ describe("wrangler dev", () => {
343
371
  await runWrangler(
344
372
  "dev --routes http://3.some-host.com/some/path/* --host 1.some-host.com"
345
373
  );
346
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
347
- host: "1.some-host.com",
348
- id: "some-zone-id-1",
349
- });
374
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
375
+ expect.objectContaining({
376
+ host: "1.some-host.com",
377
+ zone: "some-zone-id-1",
378
+ })
379
+ );
350
380
  (Dev as jest.Mock).mockClear();
351
381
  });
352
382
 
@@ -432,18 +462,20 @@ describe("wrangler dev", () => {
432
462
  },
433
463
  });
434
464
 
435
- await expect(
436
- runWrangler("dev")
437
- ).rejects.toThrowErrorMatchingInlineSnapshot(
438
- `"Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\""`
439
- );
465
+ await expect(runWrangler("dev")).rejects
466
+ .toThrowErrorMatchingInlineSnapshot(`
467
+ "The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
468
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build."
469
+ `);
440
470
  expect(std.out).toMatchInlineSnapshot(`
441
471
  "Running custom build: node -e \\"console.log('custom build');\\"
442
472
 
443
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
473
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
444
474
  `);
445
475
  expect(std.err).toMatchInlineSnapshot(`
446
- "X [ERROR] Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\"
476
+ "X [ERROR] The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
477
+
478
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build.
447
479
 
448
480
  "
449
481
  `);
@@ -580,8 +612,73 @@ describe("wrangler dev", () => {
580
612
  });
581
613
  });
582
614
 
615
+ describe("port", () => {
616
+ it("should default port to 8787 if it is not in use", async () => {
617
+ writeWranglerToml({
618
+ main: "index.js",
619
+ });
620
+ fs.writeFileSync("index.js", `export default {};`);
621
+ await runWrangler("dev");
622
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8787);
623
+ expect(std.out).toMatchInlineSnapshot(`""`);
624
+ expect(std.warn).toMatchInlineSnapshot(`""`);
625
+ expect(std.err).toMatchInlineSnapshot(`""`);
626
+ });
627
+
628
+ it("should use to `port` from `wrangler.toml`, if available", async () => {
629
+ writeWranglerToml({
630
+ main: "index.js",
631
+ dev: {
632
+ port: 8888,
633
+ },
634
+ });
635
+ fs.writeFileSync("index.js", `export default {};`);
636
+ // Mock `getPort()` to resolve to a completely different port.
637
+ (getPort as jest.Mock).mockResolvedValue(98765);
638
+
639
+ await runWrangler("dev");
640
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8888);
641
+ expect(std.out).toMatchInlineSnapshot(`""`);
642
+ expect(std.warn).toMatchInlineSnapshot(`""`);
643
+ expect(std.err).toMatchInlineSnapshot(`""`);
644
+ });
645
+
646
+ it("should use --port command line arg, if provided", async () => {
647
+ writeWranglerToml({
648
+ main: "index.js",
649
+ dev: {
650
+ port: 8888,
651
+ },
652
+ });
653
+ fs.writeFileSync("index.js", `export default {};`);
654
+ // Mock `getPort()` to resolve to a completely different port.
655
+ (getPort as jest.Mock).mockResolvedValue(98765);
656
+
657
+ await runWrangler("dev --port=9999");
658
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(9999);
659
+ expect(std.out).toMatchInlineSnapshot(`""`);
660
+ expect(std.warn).toMatchInlineSnapshot(`""`);
661
+ expect(std.err).toMatchInlineSnapshot(`""`);
662
+ });
663
+
664
+ it("should use a different port to the default if it is in use", async () => {
665
+ writeWranglerToml({
666
+ main: "index.js",
667
+ });
668
+ fs.writeFileSync("index.js", `export default {};`);
669
+ // Mock `getPort()` to resolve to a completely different port.
670
+ (getPort as jest.Mock).mockResolvedValue(98765);
671
+
672
+ await runWrangler("dev");
673
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(98765);
674
+ expect(std.out).toMatchInlineSnapshot(`""`);
675
+ expect(std.warn).toMatchInlineSnapshot(`""`);
676
+ expect(std.err).toMatchInlineSnapshot(`""`);
677
+ });
678
+ });
679
+
583
680
  describe("durable_objects", () => {
584
- it("should warn if there is one or more remote Durable Object", async () => {
681
+ it("should warn if there are remote Durable Objects, or missing migrations for local Durable Objects", async () => {
585
682
  writeWranglerToml({
586
683
  main: "index.js",
587
684
  durable_objects: {
@@ -604,9 +701,33 @@ describe("wrangler dev", () => {
604
701
  fs.writeFileSync("index.js", `export default {};`);
605
702
  await runWrangler("dev");
606
703
  expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
607
- expect(std.out).toMatchInlineSnapshot(`""`);
704
+ expect(std.out).toMatchInlineSnapshot(`
705
+ "Your worker has access to the following bindings:
706
+ - Durable Objects:
707
+ - NAME_1: CLASS_1
708
+ - NAME_2: CLASS_2 (defined in SCRIPT_A)
709
+ - NAME_3: CLASS_3
710
+ - NAME_4: CLASS_4 (defined in SCRIPT_B)"
711
+ `);
608
712
  expect(std.warn).toMatchInlineSnapshot(`
609
- "▲ [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed.
713
+ "▲ [WARNING] Processing wrangler.toml configuration:
714
+
715
+ - In wrangler.toml, you have configured [durable_objects] exported by this Worker (CLASS_1,
716
+ CLASS_3), but no [migrations] for them. This may not work as expected until you add a [migrations]
717
+ section to your wrangler.toml. Add this configuration to your wrangler.toml:
718
+
719
+ \`\`\`
720
+ [[migrations]]
721
+ tag = \\"v1\\" # Should be unique for each entry
722
+ new_classes = [\\"CLASS_1\\", \\"CLASS_3\\"]
723
+ \`\`\`
724
+
725
+ Refer to
726
+ https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml
727
+ for more details.
728
+
729
+
730
+ ▲ [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed.
610
731
 
611
732
  Be aware that changes to the data stored in these Durable Objects will be permanent and affect the
612
733
  live instances.
@@ -661,9 +782,18 @@ describe("wrangler dev", () => {
661
782
  EMPTY: "",
662
783
  UNQUOTED: "unquoted value", // Note that whitespace is trimmed
663
784
  });
664
- expect(std.out).toMatchInlineSnapshot(
665
- `"Using vars defined in .dev.vars"`
666
- );
785
+ expect(std.out).toMatchInlineSnapshot(`
786
+ "Using vars defined in .dev.vars
787
+ Your worker has access to the following bindings:
788
+ - Vars:
789
+ - VAR_1: \\"(hidden)\\"
790
+ - VAR_2: \\"original value 2\\"
791
+ - VAR_3: \\"(hidden)\\"
792
+ - VAR_MULTI_LINE_1: \\"(hidden)\\"
793
+ - VAR_MULTI_LINE_2: \\"(hidden)\\"
794
+ - EMPTY: \\"(hidden)\\"
795
+ - UNQUOTED: \\"(hidden)\\""
796
+ `);
667
797
  expect(std.warn).toMatchInlineSnapshot(`""`);
668
798
  expect(std.err).toMatchInlineSnapshot(`""`);
669
799
  });
@@ -680,7 +810,11 @@ describe("wrangler dev", () => {
680
810
  expect(std).toMatchInlineSnapshot(`
681
811
  Object {
682
812
  "debug": "",
683
- "err": "wrangler dev [script]
813
+ "err": "X [ERROR] Not enough arguments following: site
814
+
815
+ ",
816
+ "out": "
817
+ wrangler dev [script]
684
818
 
685
819
  👂 Start a local server for developing your worker
686
820
 
@@ -688,10 +822,9 @@ describe("wrangler dev", () => {
688
822
  script The path to an entry point for your worker [string]
689
823
 
690
824
  Flags:
691
- -c, --config Path to .toml configuration file [string]
692
- -h, --help Show help [boolean]
693
- -v, --version Show version number [boolean]
694
- --legacy-env Use legacy environments [boolean]
825
+ -c, --config Path to .toml configuration file [string]
826
+ -h, --help Show help [boolean]
827
+ -v, --version Show version number [boolean]
695
828
 
696
829
  Options:
697
830
  --name Name of the worker [string]
@@ -718,12 +851,7 @@ describe("wrangler dev", () => {
718
851
  --minify Minify the script [boolean]
719
852
  --node-compat Enable node.js compatibility [boolean]
720
853
  --experimental-enable-local-persistence Enable persistence for this session (only for local mode) [boolean]
721
- --inspect Enable dev tools [deprecated] [boolean]
722
- X [ERROR] Not enough arguments following: site
723
-
724
- ",
725
- "out": "
726
- ",
854
+ --inspect Enable dev tools [deprecated] [boolean]",
727
855
  "warn": "",
728
856
  }
729
857
  `);
@@ -746,6 +874,99 @@ describe("wrangler dev", () => {
746
874
  `);
747
875
  });
748
876
  });
877
+
878
+ describe("service bindings", () => {
879
+ it("should warn when using service bindings", async () => {
880
+ writeWranglerToml({
881
+ services: [
882
+ { binding: "WorkerA", service: "A" },
883
+ { binding: "WorkerB", service: "B", environment: "staging" },
884
+ ],
885
+ });
886
+ fs.writeFileSync("index.js", `export default {};`);
887
+ await runWrangler("dev index.js");
888
+ expect(std).toMatchInlineSnapshot(`
889
+ Object {
890
+ "debug": "",
891
+ "err": "",
892
+ "out": "Your worker has access to the following bindings:
893
+ - Services:
894
+ - WorkerA: A
895
+ - WorkerB: B - staging",
896
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
897
+
898
+ - \\"services\\" fields are experimental and may change or break at any time.
899
+
900
+
901
+ ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
902
+
903
+ ",
904
+ }
905
+ `);
906
+ });
907
+ });
908
+
909
+ describe("print bindings", () => {
910
+ it("should print bindings", async () => {
911
+ writeWranglerToml({
912
+ services: [
913
+ { binding: "WorkerA", service: "A" },
914
+ { binding: "WorkerB", service: "B", environment: "staging" },
915
+ ],
916
+ });
917
+ fs.writeFileSync("index.js", `export default {};`);
918
+ await runWrangler("dev index.js");
919
+ expect(std).toMatchInlineSnapshot(`
920
+ Object {
921
+ "debug": "",
922
+ "err": "",
923
+ "out": "Your worker has access to the following bindings:
924
+ - Services:
925
+ - WorkerA: A
926
+ - WorkerB: B - staging",
927
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
928
+
929
+ - \\"services\\" fields are experimental and may change or break at any time.
930
+
931
+
932
+ ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
933
+
934
+ ",
935
+ }
936
+ `);
937
+ });
938
+
939
+ it("should mask vars that were overriden in .dev.vars", async () => {
940
+ writeWranglerToml({
941
+ vars: {
942
+ variable: 123,
943
+ overriden: "original values",
944
+ },
945
+ });
946
+ fs.writeFileSync(
947
+ ".dev.vars",
948
+ `
949
+ SECRET = "A secret"
950
+ overriden = "overriden value"
951
+ `
952
+ );
953
+ fs.writeFileSync("index.js", `export default {};`);
954
+ await runWrangler("dev index.js");
955
+ expect(std).toMatchInlineSnapshot(`
956
+ Object {
957
+ "debug": "",
958
+ "err": "",
959
+ "out": "Using vars defined in .dev.vars
960
+ Your worker has access to the following bindings:
961
+ - Vars:
962
+ - variable: \\"123\\"
963
+ - overriden: \\"(hidden)\\"
964
+ - SECRET: \\"(hidden)\\"",
965
+ "warn": "",
966
+ }
967
+ `);
968
+ });
969
+ });
749
970
  });
750
971
 
751
972
  function mockGetZones(domain: string, zones: { id: string }[] = []) {
@@ -1,4 +1,5 @@
1
- import { confirm, prompt } from "../../dialogs";
1
+ import { confirm, prompt, select } from "../../dialogs";
2
+ import { normalizeSlashes } from "./mock-console";
2
3
 
3
4
  /**
4
5
  * The expected values for a confirmation request.
@@ -20,7 +21,7 @@ export interface ConfirmExpectation {
20
21
  export function mockConfirm(...expectations: ConfirmExpectation[]) {
21
22
  (confirm as jest.Mock).mockImplementation((text: string) => {
22
23
  for (const { text: expectedText, result } of expectations) {
23
- if (text === expectedText) {
24
+ if (normalizeSlashes(text) === normalizeSlashes(expectedText)) {
24
25
  return Promise.resolve(result);
25
26
  }
26
27
  }
@@ -87,3 +88,43 @@ export function clearPromptMocks() {
87
88
  );
88
89
  });
89
90
  }
91
+
92
+ /**
93
+ * The expected values for a select request.
94
+ */
95
+ export interface SelectExpectation {
96
+ /** The text expected to be seen in the select dialog. */
97
+ text: string;
98
+ /** The mock response send back from the select dialog. */
99
+ result: string;
100
+ }
101
+
102
+ /**
103
+ * Mock the implementation of `select()` that will respond with configured results
104
+ * for configured select text messages.
105
+ *
106
+ * If there is a call to `select()` that does not match any of the expectations
107
+ * then an error is thrown.
108
+ */
109
+ export function mockSelect(...expectations: SelectExpectation[]) {
110
+ (select as jest.Mock).mockImplementation((text: string) => {
111
+ for (const { text: expectedText, result } of expectations) {
112
+ if (normalizeSlashes(text) === normalizeSlashes(expectedText)) {
113
+ return Promise.resolve(result);
114
+ }
115
+ }
116
+ throw new Error(`Unexpected select message: ${text}`);
117
+ });
118
+ }
119
+
120
+ export function clearSelectMocks() {
121
+ (select as jest.Mock).mockReset();
122
+ // Because select was originally a spy, calling mockReset will simply reset
123
+ // it as a function with no return value (!), so we need to additionally reset
124
+ // the mock implementation to the one that throws (from jest.setup.js).
125
+ (select as jest.Mock).mockImplementation((text: string) => {
126
+ throw new Error(
127
+ `Unexpected call to \`select("${text}")\`.\nYou should use \`mockSelect()\` to mock calls to \`select()\` with expectations. Search the codebase for \`mockSelect\` to learn more.`
128
+ );
129
+ });
130
+ }