wrangler 2.0.23 → 2.0.26

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 (80) hide show
  1. package/README.md +20 -2
  2. package/bin/wrangler.js +1 -1
  3. package/miniflare-dist/index.mjs +235 -47
  4. package/package.json +11 -6
  5. package/src/__tests__/configuration.test.ts +89 -17
  6. package/src/__tests__/dev.test.tsx +29 -4
  7. package/src/__tests__/generate.test.ts +93 -0
  8. package/src/__tests__/helpers/mock-cfetch.ts +87 -2
  9. package/src/__tests__/index.test.ts +10 -27
  10. package/src/__tests__/init.test.ts +537 -359
  11. package/src/__tests__/jest.setup.ts +34 -1
  12. package/src/__tests__/kv.test.ts +2 -2
  13. package/src/__tests__/metrics.test.ts +5 -0
  14. package/src/__tests__/pages.test.ts +14 -0
  15. package/src/__tests__/publish.test.ts +497 -254
  16. package/src/__tests__/r2.test.ts +173 -71
  17. package/src/__tests__/tail.test.ts +112 -42
  18. package/src/__tests__/user.test.ts +1 -0
  19. package/src/__tests__/validate-dev-props.test.ts +56 -0
  20. package/src/__tests__/whoami.test.tsx +60 -1
  21. package/src/api/dev.ts +7 -0
  22. package/src/bundle.ts +279 -44
  23. package/src/cfetch/internal.ts +73 -2
  24. package/src/config/config.ts +8 -3
  25. package/src/config/environment.ts +40 -8
  26. package/src/config/index.ts +13 -0
  27. package/src/config/validation.ts +102 -8
  28. package/src/create-worker-upload-form.ts +25 -0
  29. package/src/dev/dev.tsx +121 -28
  30. package/src/dev/local.tsx +88 -14
  31. package/src/dev/remote.tsx +39 -8
  32. package/src/dev/use-esbuild.ts +28 -0
  33. package/src/dev/validate-dev-props.ts +31 -0
  34. package/src/dev-registry.tsx +160 -0
  35. package/src/dev.tsx +107 -80
  36. package/src/generate.ts +112 -14
  37. package/src/index.tsx +212 -4
  38. package/src/init.ts +111 -38
  39. package/src/inspect.ts +90 -5
  40. package/src/metrics/index.ts +1 -0
  41. package/src/metrics/metrics-dispatcher.ts +1 -0
  42. package/src/metrics/metrics-usage-headers.ts +24 -0
  43. package/src/metrics/send-event.ts +2 -2
  44. package/src/miniflare-cli/assets.ts +27 -16
  45. package/src/miniflare-cli/index.ts +124 -2
  46. package/src/module-collection.ts +3 -3
  47. package/src/pages/build.tsx +75 -41
  48. package/src/pages/constants.ts +5 -0
  49. package/src/pages/deployments.tsx +10 -10
  50. package/src/pages/dev.tsx +177 -52
  51. package/src/pages/errors.ts +22 -0
  52. package/src/pages/functions/buildPlugin.ts +4 -0
  53. package/src/pages/functions/buildWorker.ts +4 -0
  54. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  55. package/src/pages/functions/routes-consolidation.ts +73 -0
  56. package/src/pages/functions/routes-transformation.test.ts +271 -0
  57. package/src/pages/functions/routes-transformation.ts +122 -0
  58. package/src/pages/functions.tsx +96 -0
  59. package/src/pages/index.tsx +65 -55
  60. package/src/pages/projects.tsx +9 -3
  61. package/src/pages/publish.tsx +76 -23
  62. package/src/pages/types.ts +9 -0
  63. package/src/pages/upload.tsx +38 -21
  64. package/src/publish.ts +126 -112
  65. package/src/r2.ts +81 -0
  66. package/src/tail/filters.ts +3 -1
  67. package/src/tail/index.ts +15 -2
  68. package/src/tail/printing.ts +43 -3
  69. package/src/user/user.tsx +20 -2
  70. package/src/whoami.tsx +79 -1
  71. package/src/worker.ts +12 -0
  72. package/templates/first-party-worker-module-facade.ts +18 -0
  73. package/templates/format-dev-errors.ts +32 -0
  74. package/templates/pages-template-plugin.ts +16 -4
  75. package/templates/pages-template-worker.ts +16 -5
  76. package/templates/{static-asset-facade.js → serve-static-assets.ts} +21 -7
  77. package/templates/service-bindings-module-facade.js +54 -0
  78. package/templates/service-bindings-sw-facade.js +42 -0
  79. package/wrangler-dist/cli.d.ts +7 -0
  80. package/wrangler-dist/cli.js +40851 -15332
@@ -26,7 +26,7 @@ describe("normalizeAndValidateConfig()", () => {
26
26
  compatibility_flags: [],
27
27
  configPath: undefined,
28
28
  dev: {
29
- ip: "localhost",
29
+ ip: "0.0.0.0",
30
30
  local_protocol: "http",
31
31
  port: undefined, // the default of 8787 is set at runtime
32
32
  upstream_protocol: "https",
@@ -40,6 +40,10 @@ describe("normalizeAndValidateConfig()", () => {
40
40
  tsconfig: undefined,
41
41
  kv_namespaces: [],
42
42
  legacy_env: true,
43
+ logfwdr: {
44
+ bindings: [],
45
+ schema: undefined,
46
+ },
43
47
  send_metrics: undefined,
44
48
  main: undefined,
45
49
  migrations: [],
@@ -68,6 +72,7 @@ describe("normalizeAndValidateConfig()", () => {
68
72
  no_bundle: undefined,
69
73
  minify: undefined,
70
74
  node_compat: undefined,
75
+ first_party_worker: undefined,
71
76
  });
72
77
  expect(diagnostics.hasErrors()).toBe(false);
73
78
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -463,6 +468,56 @@ describe("normalizeAndValidateConfig()", () => {
463
468
  });
464
469
 
465
470
  describe("[assets]", () => {
471
+ it("normalizes a string input to an object", () => {
472
+ const { config, diagnostics } = normalizeAndValidateConfig(
473
+ {
474
+ assets: "path/to/assets",
475
+ } as unknown as RawConfig,
476
+ undefined,
477
+ { env: undefined }
478
+ );
479
+
480
+ expect(config.assets).toMatchInlineSnapshot(`
481
+ Object {
482
+ "browser_TTL": undefined,
483
+ "bucket": "path/to/assets",
484
+ "exclude": Array [],
485
+ "include": Array [],
486
+ "serve_single_page_app": false,
487
+ }
488
+ `);
489
+ expect(diagnostics.hasWarnings()).toBe(true);
490
+ expect(diagnostics.hasErrors()).toBe(false);
491
+
492
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
493
+ "Processing wrangler configuration:
494
+ - \\"assets\\" fields are experimental and may change or break at any time."
495
+ `);
496
+ });
497
+
498
+ it("errors when input is not a string or object", () => {
499
+ const { config, diagnostics } = normalizeAndValidateConfig(
500
+ {
501
+ assets: 123,
502
+ } as unknown as RawConfig,
503
+ undefined,
504
+ { env: undefined }
505
+ );
506
+
507
+ expect(config.assets).toBeUndefined();
508
+ expect(diagnostics.hasWarnings()).toBe(true);
509
+ expect(diagnostics.hasErrors()).toBe(true);
510
+
511
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
512
+ "Processing wrangler configuration:
513
+ - \\"assets\\" fields are experimental and may change or break at any time."
514
+ `);
515
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
516
+ "Processing wrangler configuration:
517
+ - Expected the \`assets\` field to be a string or an object, but got number."
518
+ `);
519
+ });
520
+
466
521
  it("should error if `assets` config is missing `bucket`", () => {
467
522
  const expectedConfig: RawConfig = {
468
523
  // @ts-expect-error we're intentionally passing an invalid configuration here
@@ -478,7 +533,9 @@ describe("normalizeAndValidateConfig()", () => {
478
533
  { env: undefined }
479
534
  );
480
535
 
481
- expect(config).toEqual(expect.objectContaining(expectedConfig));
536
+ expect(config.assets).toEqual(
537
+ expect.objectContaining(expectedConfig.assets)
538
+ );
482
539
  expect(diagnostics.hasWarnings()).toBe(true);
483
540
  expect(diagnostics.hasErrors()).toBe(true);
484
541
 
@@ -498,6 +555,8 @@ describe("normalizeAndValidateConfig()", () => {
498
555
  bucket: "BUCKET",
499
556
  include: [222, 333],
500
557
  exclude: [444, 555],
558
+ browser_TTL: "not valid",
559
+ serve_single_page_app: "INVALID",
501
560
  },
502
561
  };
503
562
 
@@ -514,12 +573,14 @@ describe("normalizeAndValidateConfig()", () => {
514
573
  - \\"assets\\" fields are experimental and may change or break at any time."
515
574
  `);
516
575
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
517
- "Processing wrangler configuration:
518
- - Expected \\"assets.include.[0]\\" to be of type string but got 222.
519
- - Expected \\"assets.include.[1]\\" to be of type string but got 333.
520
- - Expected \\"assets.exclude.[0]\\" to be of type string but got 444.
521
- - Expected \\"assets.exclude.[1]\\" to be of type string but got 555."
522
- `);
576
+ "Processing wrangler configuration:
577
+ - Expected \\"assets.include.[0]\\" to be of type string but got 222.
578
+ - Expected \\"assets.include.[1]\\" to be of type string but got 333.
579
+ - Expected \\"assets.exclude.[0]\\" to be of type string but got 444.
580
+ - Expected \\"assets.exclude.[1]\\" to be of type string but got 555.
581
+ - Expected \\"assets.browser_TTL\\" to be of type number but got \\"not valid\\".
582
+ - Expected \\"assets.serve_single_page_app\\" to be of type boolean but got \\"INVALID\\"."
583
+ `);
523
584
  });
524
585
  });
525
586
 
@@ -858,6 +919,7 @@ describe("normalizeAndValidateConfig()", () => {
858
919
  no_bundle: true,
859
920
  minify: true,
860
921
  node_compat: true,
922
+ first_party_worker: true,
861
923
  };
862
924
 
863
925
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -931,6 +993,7 @@ describe("normalizeAndValidateConfig()", () => {
931
993
  no_bundle: "INVALID",
932
994
  minify: "INVALID",
933
995
  node_compat: "INVALID",
996
+ first_party_worker: "INVALID",
934
997
  } as unknown as RawEnvironment;
935
998
 
936
999
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -997,7 +1060,8 @@ describe("normalizeAndValidateConfig()", () => {
997
1060
  - The field \\"define.DEF1\\" should be a string but got 1777.
998
1061
  - Expected \\"no_bundle\\" to be of type boolean but got \\"INVALID\\".
999
1062
  - Expected \\"minify\\" to be of type boolean but got \\"INVALID\\".
1000
- - Expected \\"node_compat\\" to be of type boolean but got \\"INVALID\\"."
1063
+ - Expected \\"node_compat\\" to be of type boolean but got \\"INVALID\\".
1064
+ - Expected \\"first_party_worker\\" to be of type boolean but got \\"INVALID\\"."
1001
1065
  `);
1002
1066
  });
1003
1067
 
@@ -2311,6 +2375,7 @@ describe("normalizeAndValidateConfig()", () => {
2311
2375
  no_bundle: true,
2312
2376
  minify: true,
2313
2377
  node_compat: true,
2378
+ first_party_worker: true,
2314
2379
  };
2315
2380
 
2316
2381
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -2354,6 +2419,7 @@ describe("normalizeAndValidateConfig()", () => {
2354
2419
  no_bundle: false,
2355
2420
  minify: false,
2356
2421
  node_compat: false,
2422
+ first_party_worker: false,
2357
2423
  };
2358
2424
  const rawConfig: RawConfig = {
2359
2425
  name: "mock-name",
@@ -2376,6 +2442,7 @@ describe("normalizeAndValidateConfig()", () => {
2376
2442
  no_bundle: true,
2377
2443
  minify: true,
2378
2444
  node_compat: true,
2445
+ first_party_worker: true,
2379
2446
  env: {
2380
2447
  ENV1: rawEnv,
2381
2448
  },
@@ -2637,6 +2704,7 @@ describe("normalizeAndValidateConfig()", () => {
2637
2704
  no_bundle: "INVALID",
2638
2705
  minify: "INVALID",
2639
2706
  node_compat: "INVALID",
2707
+ first_party_worker: "INVALID",
2640
2708
  } as unknown as RawEnvironment;
2641
2709
 
2642
2710
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -2672,7 +2740,8 @@ describe("normalizeAndValidateConfig()", () => {
2672
2740
  - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\".
2673
2741
  - Expected \\"no_bundle\\" to be of type boolean but got \\"INVALID\\".
2674
2742
  - Expected \\"minify\\" to be of type boolean but got \\"INVALID\\".
2675
- - Expected \\"node_compat\\" to be of type boolean but got \\"INVALID\\"."
2743
+ - Expected \\"node_compat\\" to be of type boolean but got \\"INVALID\\".
2744
+ - Expected \\"first_party_worker\\" to be of type boolean but got \\"INVALID\\"."
2676
2745
  `);
2677
2746
  });
2678
2747
 
@@ -3670,6 +3739,7 @@ describe("normalizeAndValidateConfig()", () => {
3670
3739
  it("should remove and warn about deprecated properties", () => {
3671
3740
  const environment: RawEnvironment = {
3672
3741
  zone_id: "ZONE_ID",
3742
+ "kv-namespaces": "BAD_KV_NAMESPACE",
3673
3743
  experimental_services: [
3674
3744
  {
3675
3745
  name: "mock-name",
@@ -3695,14 +3765,16 @@ describe("normalizeAndValidateConfig()", () => {
3695
3765
  expect(diagnostics.hasErrors()).toBe(false);
3696
3766
  expect(diagnostics.hasWarnings()).toBe(true);
3697
3767
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
3698
- "Processing wrangler configuration:
3768
+ "Processing wrangler configuration:
3699
3769
 
3700
- - \\"env.ENV1\\" environment configuration
3701
- - Deprecation: \\"zone_id\\":
3702
- This is unnecessary since we can deduce this from routes directly.
3703
- - Deprecation: \\"experimental_services\\":
3704
- The \\"experimental_services\\" field is no longer supported. Simply rename the [experimental_services] field to [services]."
3705
- `);
3770
+ - \\"env.ENV1\\" environment configuration
3771
+ - Deprecation: \\"kv-namespaces\\":
3772
+ The \\"kv-namespaces\\" field is no longer supported, please rename to \\"kv_namespaces\\"
3773
+ - Deprecation: \\"zone_id\\":
3774
+ This is unnecessary since we can deduce this from routes directly.
3775
+ - Deprecation: \\"experimental_services\\":
3776
+ The \\"experimental_services\\" field is no longer supported. Simply rename the [experimental_services] field to [services]."
3777
+ `);
3706
3778
  });
3707
3779
  });
3708
3780
 
@@ -68,6 +68,28 @@ describe("wrangler dev", () => {
68
68
  });
69
69
  });
70
70
 
71
+ describe("usage-model", () => {
72
+ it("should read wrangler.toml's usage_model", async () => {
73
+ writeWranglerToml({
74
+ main: "index.js",
75
+ usage_model: "unbound",
76
+ });
77
+ fs.writeFileSync("index.js", `export default {};`);
78
+ await runWrangler("dev");
79
+ expect((Dev as jest.Mock).mock.calls[0][0].usageModel).toEqual("unbound");
80
+ });
81
+
82
+ it("should read wrangler.toml's usage_model in local mode", async () => {
83
+ writeWranglerToml({
84
+ main: "index.js",
85
+ usage_model: "unbound",
86
+ });
87
+ fs.writeFileSync("index.js", `export default {};`);
88
+ await runWrangler("dev --local");
89
+ expect((Dev as jest.Mock).mock.calls[0][0].usageModel).toEqual("unbound");
90
+ });
91
+ });
92
+
71
93
  describe("entry-points", () => {
72
94
  it("should error if there is no entry-point specified", async () => {
73
95
  writeWranglerToml();
@@ -630,13 +652,13 @@ describe("wrangler dev", () => {
630
652
  });
631
653
 
632
654
  describe("ip", () => {
633
- it("should default ip to localhost", async () => {
655
+ it("should default ip to 0.0.0.0", async () => {
634
656
  writeWranglerToml({
635
657
  main: "index.js",
636
658
  });
637
659
  fs.writeFileSync("index.js", `export default {};`);
638
660
  await runWrangler("dev");
639
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
661
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
640
662
  expect(std.out).toMatchInlineSnapshot(`""`);
641
663
  expect(std.warn).toMatchInlineSnapshot(`""`);
642
664
  expect(std.err).toMatchInlineSnapshot(`""`);
@@ -849,7 +871,7 @@ describe("wrangler dev", () => {
849
871
  });
850
872
  fs.writeFileSync("index.js", `export default {};`);
851
873
  await runWrangler("dev");
852
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
874
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
853
875
  expect(std.out).toMatchInlineSnapshot(`
854
876
  "Your worker has access to the following bindings:
855
877
  - Durable Objects:
@@ -983,7 +1005,7 @@ describe("wrangler dev", () => {
983
1005
  --compatibility-date Date to use for compatibility checks [string]
984
1006
  --compatibility-flags, --compatibility-flag Flags to use for compatibility checks [array]
985
1007
  --latest Use the latest version of the worker runtime [boolean] [default: true]
986
- --ip IP address to listen on, defaults to \`localhost\` [string]
1008
+ --ip IP address to listen on [string] [default: \\"0.0.0.0\\"]
987
1009
  --port Port to listen on [number]
988
1010
  --inspector-port Port for devtools to connect to [number]
989
1011
  --routes, --route Routes to upload [array]
@@ -1038,6 +1060,7 @@ describe("wrangler dev", () => {
1038
1060
  it("should error if config.assets and --site are used together", async () => {
1039
1061
  writeWranglerToml({
1040
1062
  main: "./index.js",
1063
+ // @ts-expect-error we allow string inputs here
1041
1064
  assets: "abc",
1042
1065
  });
1043
1066
  fs.writeFileSync("index.js", `export default {};`);
@@ -1051,6 +1074,7 @@ describe("wrangler dev", () => {
1051
1074
  it("should error if config.assets and config.site are used together", async () => {
1052
1075
  writeWranglerToml({
1053
1076
  main: "./index.js",
1077
+ // @ts-expect-error we allow string inputs here
1054
1078
  assets: "abc",
1055
1079
  site: {
1056
1080
  bucket: "xyz",
@@ -1102,6 +1126,7 @@ describe("wrangler dev", () => {
1102
1126
  it("should warn if config.assets is used", async () => {
1103
1127
  writeWranglerToml({
1104
1128
  main: "./index.js",
1129
+ // @ts-expect-error we allow string inputs here
1105
1130
  assets: "./assets",
1106
1131
  });
1107
1132
  fs.writeFileSync("index.js", `export default {};`);
@@ -0,0 +1,93 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import { setup } from "create-cloudflare";
5
+ import { mockConsoleMethods } from "./helpers/mock-console";
6
+ import { mockConfirm, clearConfirmMocks } from "./helpers/mock-dialogs";
7
+ import { runInTempDir } from "./helpers/run-in-tmp";
8
+ import { runWrangler } from "./helpers/run-wrangler";
9
+
10
+ const createCloudflareMock = setup as jest.Mock;
11
+
12
+ describe("generate", () => {
13
+ runInTempDir();
14
+ const std = mockConsoleMethods();
15
+
16
+ afterEach(() => {
17
+ clearConfirmMocks();
18
+ });
19
+
20
+ it("defers to `wrangler init` when no template is given", async () => {
21
+ mockConfirm(
22
+ {
23
+ text: "Would you like to use git to manage this Worker?",
24
+ result: false,
25
+ },
26
+ {
27
+ text: "No package.json found. Would you like to create one?",
28
+ result: false,
29
+ }
30
+ );
31
+ await runWrangler("generate no-template");
32
+ expect(std.out).toMatchInlineSnapshot(
33
+ `"✨ Created no-template/wrangler.toml"`
34
+ );
35
+ });
36
+
37
+ it("runs `create-cloudflare` when a template is given", async () => {
38
+ await expect(
39
+ runWrangler("generate my-worker some-template")
40
+ ).resolves.toBeUndefined();
41
+
42
+ expect(createCloudflareMock).toBeCalled();
43
+ });
44
+
45
+ it("complains when given the --type argument", async () => {
46
+ await expect(
47
+ runWrangler("generate worker-name worker-template --type rust")
48
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
49
+ `"The --type option is no longer supported."`
50
+ );
51
+ });
52
+
53
+ it("complains when given the --site argument", async () => {
54
+ await expect(runWrangler("generate worker-name worker-template --site"))
55
+ .rejects.toThrowErrorMatchingInlineSnapshot(`
56
+ "The --site option is no longer supported.
57
+ If you wish to create a brand new Worker Sites project then clone the \`worker-sites-template\` starter repository:
58
+
59
+ \`\`\`
60
+ git clone --depth=1 --branch=wrangler2 https://github.com/cloudflare/worker-sites-template worker-name
61
+ cd worker-name
62
+ \`\`\`
63
+
64
+ Find out more about how to create and maintain Sites projects at https://developers.cloudflare.com/workers/platform/sites.
65
+ Have you considered using Cloudflare Pages instead? See https://pages.cloudflare.com/."
66
+ `);
67
+ });
68
+
69
+ it("auto-increments the worker directory name", async () => {
70
+ fs.mkdirSync("my-worker");
71
+ await expect(
72
+ runWrangler("generate my-worker some-template")
73
+ ).resolves.toBeUndefined();
74
+
75
+ expect(createCloudflareMock).lastCalledWith(
76
+ path.resolve(process.cwd(), "my-worker-1"),
77
+ "some-template",
78
+ { debug: false, force: false, init: true }
79
+ );
80
+
81
+ fs.mkdirSync("my-worker-1");
82
+
83
+ await expect(
84
+ runWrangler("generate my-worker some-template")
85
+ ).resolves.toBeUndefined();
86
+
87
+ expect(createCloudflareMock).lastCalledWith(
88
+ path.resolve(process.cwd(), "my-worker-2"),
89
+ "some-template",
90
+ { debug: false, force: false, init: true }
91
+ );
92
+ });
93
+ });
@@ -1,8 +1,10 @@
1
+ import { Readable } from "node:stream";
1
2
  import { URL, URLSearchParams } from "node:url";
2
3
  import { pathToRegexp } from "path-to-regexp";
4
+ import { Response } from "undici";
3
5
  import { getCloudflareApiBaseUrl } from "../../cfetch";
4
6
  import type { FetchResult, FetchError } from "../../cfetch";
5
- import type { RequestInit } from "undici";
7
+ import type { RequestInit, BodyInit, HeadersInit } from "undici";
6
8
 
7
9
  /**
8
10
  * The signature of the function that will handle a mock request.
@@ -180,6 +182,8 @@ export function unsetAllMocks() {
180
182
  */
181
183
 
182
184
  const kvGetMocks = new Map<string, string | Buffer>();
185
+ const r2GetMocks = new Map<string, string | undefined>();
186
+ const dashScriptMocks = new Map<string, string | undefined>();
183
187
 
184
188
  /**
185
189
  * @mocked typeof fetchKVGetValue
@@ -206,6 +210,87 @@ export function setMockFetchKVGetValue(
206
210
  kvGetMocks.set(`${accountId}/${namespaceId}/${key}`, value);
207
211
  }
208
212
 
209
- export function unsetMockFetchKVGetValues() {
213
+ /**
214
+ * @mocked typeof fetchR2Objects
215
+ */
216
+ export async function mockFetchR2Objects(
217
+ resource: string,
218
+ bodyInit: {
219
+ body: BodyInit | Readable;
220
+ headers: HeadersInit | undefined;
221
+ method: "PUT" | "GET" | "DELETE";
222
+ }
223
+ ): Promise<Response> {
224
+ /**
225
+ * Here we destroy & removeListeners to "drain" the stream, for testing purposes
226
+ * mimicking the fetch request taking in the stream and draining it.
227
+ */
228
+ if (bodyInit.body instanceof Readable) {
229
+ bodyInit.body.destroy();
230
+ bodyInit.body.removeAllListeners();
231
+ }
232
+
233
+ if (r2GetMocks.has(resource)) {
234
+ const value = r2GetMocks.get(resource);
235
+
236
+ return new Response(value);
237
+ }
238
+ throw new Error(`no mock found for \`r2 object\` - ${resource}`);
239
+ }
240
+
241
+ /**
242
+ * Mock setter for usage within test blocks, companion helper to `mockFetchR2Objects`
243
+ */
244
+ export function setMockFetchR2Objects({
245
+ accountId,
246
+ bucketName,
247
+ objectName,
248
+ mockResponse,
249
+ }: {
250
+ accountId: string;
251
+ bucketName: string;
252
+ objectName: string;
253
+ mockResponse?: string;
254
+ }) {
255
+ r2GetMocks.set(
256
+ `/accounts/${accountId}/r2/buckets/${bucketName}/objects/${objectName}`,
257
+ mockResponse
258
+ );
259
+ }
260
+
261
+ export function unsetSpecialMockFns() {
210
262
  kvGetMocks.clear();
263
+ r2GetMocks.clear();
264
+ dashScriptMocks.clear();
265
+ }
266
+
267
+ /**
268
+ * @mocked typeof fetchDashScript
269
+ * multipart/form-data is the response for modules and raw text for the Script endpoint.
270
+ */
271
+ export async function mockFetchDashScript(resource: string): Promise<string> {
272
+ if (dashScriptMocks.has(resource)) {
273
+ const value = dashScriptMocks.get(resource) ?? "";
274
+
275
+ return value;
276
+ }
277
+ throw new Error(`no mock found for \`init from-dash\` - ${resource}`);
278
+ }
279
+
280
+ /**
281
+ * Mock setter for usage within test blocks, companion helper to `mockFetchDashScript`
282
+ */
283
+ export function setMockFetchDashScript({
284
+ accountId,
285
+ fromDashScriptName,
286
+ mockResponse,
287
+ }: {
288
+ accountId: string;
289
+ fromDashScriptName: string;
290
+ mockResponse?: string;
291
+ }) {
292
+ dashScriptMocks.set(
293
+ `/accounts/${accountId}/workers/scripts/${fromDashScriptName}`,
294
+ mockResponse
295
+ );
211
296
  }
@@ -203,36 +203,19 @@ describe("wrangler", () => {
203
203
  await runWrangler("r2");
204
204
  await endEventLoop();
205
205
  expect(std.out).toMatchInlineSnapshot(`
206
- "wrangler r2
206
+ "wrangler r2
207
207
 
208
- 📦 Interact with an R2 store
208
+ 📦 Interact with an R2 store
209
209
 
210
- Commands:
211
- wrangler r2 bucket Manage R2 buckets
212
-
213
- Flags:
214
- -c, --config Path to .toml configuration file [string]
215
- -h, --help Show help [boolean]
216
- -v, --version Show version number [boolean]"
217
- `);
218
- });
219
- });
210
+ Commands:
211
+ wrangler r2 object Manage R2 objects
212
+ wrangler r2 bucket Manage R2 buckets
220
213
 
221
- describe("Deprecated commands", () => {
222
- it("should print a deprecation message for 'generate'", async () => {
223
- await runWrangler("generate").catch((err) => {
224
- expect(err.message).toMatchInlineSnapshot(`
225
- "Deprecation:
226
- \`wrangler generate\` has been deprecated.
227
- Try running \`wrangler init\` to generate a basic Worker, or cloning the template repository instead:
228
-
229
- \`\`\`
230
- git clone https://github.com/cloudflare/worker-template
231
- \`\`\`
232
-
233
- Please refer to https://developers.cloudflare.com/workers/wrangler/deprecations/#generate for more information."
234
- `);
235
- });
214
+ Flags:
215
+ -c, --config Path to .toml configuration file [string]
216
+ -h, --help Show help [boolean]
217
+ -v, --version Show version number [boolean]"
218
+ `);
236
219
  });
237
220
  });
238
221