wrangler 0.0.0-e2f9bb2 → 0.0.0-e322475

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 (103) hide show
  1. package/Cloudflare_CA.pem +18 -0
  2. package/README.md +3 -1
  3. package/bin/wrangler.js +36 -4
  4. package/kv-asset-handler.js +1 -0
  5. package/package.json +15 -7
  6. package/pages/functions/buildPlugin.ts +13 -0
  7. package/pages/functions/buildWorker.ts +14 -1
  8. package/pages/functions/template-plugin.ts +3 -2
  9. package/src/__tests__/configuration.test.ts +652 -229
  10. package/src/__tests__/dev.test.tsx +372 -79
  11. package/src/__tests__/helpers/mock-cfetch.ts +2 -2
  12. package/src/__tests__/helpers/mock-console.ts +11 -1
  13. package/src/__tests__/helpers/mock-dialogs.ts +75 -11
  14. package/src/__tests__/helpers/mock-process.ts +24 -0
  15. package/src/__tests__/index.test.ts +81 -72
  16. package/src/__tests__/init.test.ts +1360 -410
  17. package/src/__tests__/jest.setup.ts +38 -0
  18. package/src/__tests__/kv.test.ts +218 -152
  19. package/src/__tests__/logger.test.ts +26 -0
  20. package/src/__tests__/package-manager.test.ts +154 -7
  21. package/src/__tests__/pages.test.ts +478 -53
  22. package/src/__tests__/parse.test.ts +8 -0
  23. package/src/__tests__/publish.test.ts +1614 -333
  24. package/src/__tests__/r2.test.ts +55 -36
  25. package/src/__tests__/secret.test.ts +39 -4
  26. package/src/__tests__/user.test.ts +1 -0
  27. package/src/__tests__/whoami.test.tsx +34 -0
  28. package/src/abort.d.ts +3 -0
  29. package/src/bundle-reporter.tsx +29 -0
  30. package/src/bundle.ts +42 -7
  31. package/src/cfetch/index.ts +21 -4
  32. package/src/cfetch/internal.ts +25 -20
  33. package/src/config/config.ts +11 -2
  34. package/src/config/environment.ts +41 -15
  35. package/src/config/index.ts +162 -0
  36. package/src/config/validation-helpers.ts +10 -1
  37. package/src/config/validation.ts +234 -78
  38. package/src/create-worker-preview.ts +32 -22
  39. package/src/create-worker-upload-form.ts +22 -8
  40. package/src/dev/dev.tsx +48 -67
  41. package/src/dev/local.tsx +16 -7
  42. package/src/dev/remote.tsx +57 -21
  43. package/src/dev/use-esbuild.ts +1 -7
  44. package/src/dialogs.tsx +48 -0
  45. package/src/durable.ts +102 -0
  46. package/src/entry.ts +71 -10
  47. package/src/generate-auth-url.ts +33 -0
  48. package/src/generate-random-state.ts +16 -0
  49. package/src/git-client.ts +42 -0
  50. package/src/index.tsx +619 -338
  51. package/src/inspect.ts +39 -0
  52. package/src/kv.ts +116 -27
  53. package/src/logger.ts +8 -1
  54. package/src/open-in-browser.ts +3 -12
  55. package/src/package-manager.ts +50 -3
  56. package/src/pages.tsx +434 -207
  57. package/src/parse.ts +44 -5
  58. package/src/proxy.ts +66 -44
  59. package/src/publish.ts +407 -137
  60. package/src/sites.tsx +103 -28
  61. package/src/user.tsx +35 -26
  62. package/src/whoami.tsx +3 -2
  63. package/src/worker.ts +10 -1
  64. package/src/zones.ts +73 -0
  65. package/templates/new-worker-scheduled.js +17 -0
  66. package/templates/new-worker-scheduled.ts +32 -0
  67. package/templates/new-worker.ts +16 -1
  68. package/templates/no-op-worker.js +10 -0
  69. package/templates/static-asset-facade.js +2 -6
  70. package/wrangler-dist/cli.js +46122 -32396
  71. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  72. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  73. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  74. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  75. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  76. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  77. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  78. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  79. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  80. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  81. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  82. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  83. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  84. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  85. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  86. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  87. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  88. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  89. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  90. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  91. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  92. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  93. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  94. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  95. package/vendor/wrangler-mime/LICENSE +0 -21
  96. package/vendor/wrangler-mime/Mime.js +0 -97
  97. package/vendor/wrangler-mime/README.md +0 -187
  98. package/vendor/wrangler-mime/cli.js +0 -46
  99. package/vendor/wrangler-mime/index.js +0 -4
  100. package/vendor/wrangler-mime/lite.js +0 -4
  101. package/vendor/wrangler-mime/package.json +0 -52
  102. package/vendor/wrangler-mime/types/other.js +0 -1
  103. 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,15 +782,24 @@ 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
  });
670
800
  });
671
801
 
672
- describe("site", () => {
802
+ describe("serve static assets", () => {
673
803
  it("should error if --site is used with no value", async () => {
674
804
  await expect(
675
805
  runWrangler("dev --site")
@@ -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]
@@ -706,7 +839,7 @@ describe("wrangler dev", () => {
706
839
  --routes, --route Routes to upload [array]
707
840
  --host Host to forward requests to, defaults to the zone of project [string]
708
841
  --local-protocol Protocol to listen to requests on, defaults to http. [choices: \\"http\\", \\"https\\"]
709
- --experimental-public Static assets to be served [string]
842
+ --assets Static assets to be served [string]
710
843
  --site Root folder of static assets for Workers Sites [string]
711
844
  --site-include Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded. [array]
712
845
  --site-exclude Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded. [array]
@@ -718,16 +851,83 @@ 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
  `);
730
858
  });
859
+
860
+ it("should error if --assets and --site are used together", async () => {
861
+ writeWranglerToml({
862
+ main: "./index.js",
863
+ });
864
+ fs.writeFileSync("index.js", `export default {};`);
865
+ await expect(
866
+ runWrangler("dev --assets abc --site xyz")
867
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
868
+ `"Cannot use Assets and Workers Sites in the same Worker."`
869
+ );
870
+ });
871
+
872
+ it("should error if --assets and config.site are used together", async () => {
873
+ writeWranglerToml({
874
+ main: "./index.js",
875
+ site: {
876
+ bucket: "xyz",
877
+ },
878
+ });
879
+ fs.writeFileSync("index.js", `export default {};`);
880
+ await expect(
881
+ runWrangler("dev --assets abc")
882
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
883
+ `"Cannot use Assets and Workers Sites in the same Worker."`
884
+ );
885
+ });
886
+
887
+ it("should error if config.assets and --site are used together", async () => {
888
+ writeWranglerToml({
889
+ main: "./index.js",
890
+ assets: "abc",
891
+ });
892
+ fs.writeFileSync("index.js", `export default {};`);
893
+ await expect(
894
+ runWrangler("dev --site xyz")
895
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
896
+ `"Cannot use Assets and Workers Sites in the same Worker."`
897
+ );
898
+ });
899
+
900
+ it("should error if config.assets and config.site are used together", async () => {
901
+ writeWranglerToml({
902
+ main: "./index.js",
903
+ assets: "abc",
904
+ site: {
905
+ bucket: "xyz",
906
+ },
907
+ });
908
+ fs.writeFileSync("index.js", `export default {};`);
909
+ await expect(
910
+ runWrangler("dev --assets abc")
911
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
912
+ `"Cannot use Assets and Workers Sites in the same Worker."`
913
+ );
914
+ });
915
+
916
+ it("should indicate whether Sites is being used", async () => {
917
+ writeWranglerToml({
918
+ main: "index.js",
919
+ });
920
+ fs.writeFileSync("index.js", `export default {};`);
921
+
922
+ await runWrangler("dev");
923
+ expect((Dev as jest.Mock).mock.calls[0][0].isWorkersSite).toEqual(false);
924
+
925
+ await runWrangler("dev --site abc");
926
+ expect((Dev as jest.Mock).mock.calls[1][0].isWorkersSite).toEqual(true);
927
+
928
+ await runWrangler("dev --assets abc");
929
+ expect((Dev as jest.Mock).mock.calls[2][0].isWorkersSite).toEqual(false);
930
+ });
731
931
  });
732
932
 
733
933
  describe("--inspect", () => {
@@ -746,6 +946,99 @@ describe("wrangler dev", () => {
746
946
  `);
747
947
  });
748
948
  });
949
+
950
+ describe("service bindings", () => {
951
+ it("should warn when using service bindings", async () => {
952
+ writeWranglerToml({
953
+ services: [
954
+ { binding: "WorkerA", service: "A" },
955
+ { binding: "WorkerB", service: "B", environment: "staging" },
956
+ ],
957
+ });
958
+ fs.writeFileSync("index.js", `export default {};`);
959
+ await runWrangler("dev index.js");
960
+ expect(std).toMatchInlineSnapshot(`
961
+ Object {
962
+ "debug": "",
963
+ "err": "",
964
+ "out": "Your worker has access to the following bindings:
965
+ - Services:
966
+ - WorkerA: A
967
+ - WorkerB: B - staging",
968
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
969
+
970
+ - \\"services\\" fields are experimental and may change or break at any time.
971
+
972
+
973
+ ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
974
+
975
+ ",
976
+ }
977
+ `);
978
+ });
979
+ });
980
+
981
+ describe("print bindings", () => {
982
+ it("should print bindings", async () => {
983
+ writeWranglerToml({
984
+ services: [
985
+ { binding: "WorkerA", service: "A" },
986
+ { binding: "WorkerB", service: "B", environment: "staging" },
987
+ ],
988
+ });
989
+ fs.writeFileSync("index.js", `export default {};`);
990
+ await runWrangler("dev index.js");
991
+ expect(std).toMatchInlineSnapshot(`
992
+ Object {
993
+ "debug": "",
994
+ "err": "",
995
+ "out": "Your worker has access to the following bindings:
996
+ - Services:
997
+ - WorkerA: A
998
+ - WorkerB: B - staging",
999
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
1000
+
1001
+ - \\"services\\" fields are experimental and may change or break at any time.
1002
+
1003
+
1004
+ ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
1005
+
1006
+ ",
1007
+ }
1008
+ `);
1009
+ });
1010
+
1011
+ it("should mask vars that were overriden in .dev.vars", async () => {
1012
+ writeWranglerToml({
1013
+ vars: {
1014
+ variable: 123,
1015
+ overriden: "original values",
1016
+ },
1017
+ });
1018
+ fs.writeFileSync(
1019
+ ".dev.vars",
1020
+ `
1021
+ SECRET = "A secret"
1022
+ overriden = "overriden value"
1023
+ `
1024
+ );
1025
+ fs.writeFileSync("index.js", `export default {};`);
1026
+ await runWrangler("dev index.js");
1027
+ expect(std).toMatchInlineSnapshot(`
1028
+ Object {
1029
+ "debug": "",
1030
+ "err": "",
1031
+ "out": "Using vars defined in .dev.vars
1032
+ Your worker has access to the following bindings:
1033
+ - Vars:
1034
+ - variable: \\"123\\"
1035
+ - overriden: \\"(hidden)\\"
1036
+ - SECRET: \\"(hidden)\\"",
1037
+ "warn": "",
1038
+ }
1039
+ `);
1040
+ });
1041
+ });
749
1042
  });
750
1043
 
751
1044
  function mockGetZones(domain: string, zones: { id: string }[] = []) {
@@ -179,7 +179,7 @@ export function unsetAllMocks() {
179
179
  * special-case mocking it here.
180
180
  */
181
181
 
182
- const kvGetMocks = new Map<string, string>();
182
+ const kvGetMocks = new Map<string, string | Buffer>();
183
183
 
184
184
  /**
185
185
  * @mocked typeof fetchKVGetValue
@@ -201,7 +201,7 @@ export function setMockFetchKVGetValue(
201
201
  accountId: string,
202
202
  namespaceId: string,
203
203
  key: string,
204
- value: string
204
+ value: string | Buffer
205
205
  ) {
206
206
  kvGetMocks.set(`${accountId}/${namespaceId}/${key}`, value);
207
207
  }
@@ -28,7 +28,9 @@ const std = {
28
28
 
29
29
  function normalizeOutput(spy: jest.SpyInstance): string {
30
30
  return normalizeErrorMarkers(
31
- stripTrailingWhitespace(normalizeSlashes(stripTimings(captureCalls(spy))))
31
+ replaceByte(
32
+ stripTrailingWhitespace(normalizeSlashes(stripTimings(captureCalls(spy))))
33
+ )
32
34
  );
33
35
  }
34
36
 
@@ -85,3 +87,11 @@ export function stripTimings(stdout: string): string {
85
87
  export function stripTrailingWhitespace(str: string): string {
86
88
  return str.replace(/[^\S\n]+\n/g, "\n");
87
89
  }
90
+
91
+ /**
92
+ * Removing leading kilobit (tenth of a byte) from test output due to
93
+ * variation causing every few tests the value to change by ± .01
94
+ */
95
+ function replaceByte(stdout: string): string {
96
+ return stdout.replaceAll(/.[0-9][0-9] KiB/g, "xx KiB");
97
+ }