wrangler 0.0.0-e95e5a0 → 0.0.0-e978986

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 (52) 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 +11 -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 +336 -87
  9. package/src/__tests__/dev.test.tsx +243 -25
  10. package/src/__tests__/helpers/mock-dialogs.ts +41 -1
  11. package/src/__tests__/index.test.ts +79 -72
  12. package/src/__tests__/init.test.ts +182 -131
  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 +381 -53
  17. package/src/__tests__/parse.test.ts +8 -0
  18. package/src/__tests__/publish.test.ts +682 -89
  19. package/src/__tests__/r2.test.ts +55 -36
  20. package/src/__tests__/secret.test.ts +39 -4
  21. package/src/abort.d.ts +3 -0
  22. package/src/bundle.ts +33 -2
  23. package/src/cfetch/index.ts +21 -4
  24. package/src/cfetch/internal.ts +17 -9
  25. package/src/config/config.ts +1 -1
  26. package/src/config/environment.ts +40 -14
  27. package/src/config/index.ts +162 -0
  28. package/src/config/validation.ts +180 -65
  29. package/src/create-worker-preview.ts +17 -7
  30. package/src/create-worker-upload-form.ts +22 -8
  31. package/src/dev/dev.tsx +7 -6
  32. package/src/dev/local.tsx +6 -0
  33. package/src/dev/remote.tsx +15 -1
  34. package/src/dialogs.tsx +48 -0
  35. package/src/durable.ts +102 -0
  36. package/src/entry.ts +64 -9
  37. package/src/index.tsx +357 -177
  38. package/src/inspect.ts +39 -0
  39. package/src/kv.ts +114 -25
  40. package/src/open-in-browser.ts +5 -12
  41. package/src/package-manager.ts +50 -3
  42. package/src/pages.tsx +271 -110
  43. package/src/parse.ts +23 -4
  44. package/src/proxy.ts +38 -22
  45. package/src/publish.ts +227 -113
  46. package/src/sites.tsx +19 -17
  47. package/src/user.tsx +11 -1
  48. package/src/worker.ts +8 -0
  49. package/templates/new-worker-scheduled.js +17 -0
  50. package/templates/new-worker-scheduled.ts +32 -0
  51. package/templates/new-worker.ts +16 -1
  52. package/wrangler-dist/cli.js +36017 -22687
@@ -1,6 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import * as TOML from "@iarna/toml";
4
+ import * as esbuild from "esbuild";
4
5
  import { writeAuthConfigFile } from "../user";
5
6
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
6
7
  import {
@@ -11,6 +12,7 @@ import {
11
12
  unsetMockFetchKVGetValues,
12
13
  } from "./helpers/mock-cfetch";
13
14
  import { mockConsoleMethods, normalizeSlashes } from "./helpers/mock-console";
15
+ import { mockConfirm } from "./helpers/mock-dialogs";
14
16
  import { useMockIsTTY } from "./helpers/mock-istty";
15
17
  import { mockKeyListRequest } from "./helpers/mock-kv";
16
18
  import { mockOAuthFlow } from "./helpers/mock-oauth-flow";
@@ -469,7 +471,10 @@ describe("publish", () => {
469
471
  mockSubDomainRequest();
470
472
  await runWrangler("publish ./some-path/worker/index.js");
471
473
  expect(std.out).toMatchInlineSnapshot(`
472
- "Uploaded test-name (TIMINGS)
474
+ "Your worker has access to the following bindings:
475
+ - Vars:
476
+ - xyz: \\"123\\"
477
+ Uploaded test-name (TIMINGS)
473
478
  Published test-name (TIMINGS)
474
479
  test-name.test-sub-domain.workers.dev"
475
480
  `);
@@ -644,6 +649,136 @@ describe("publish", () => {
644
649
  await runWrangler("publish ./index --env dev --legacy-env false");
645
650
  });
646
651
 
652
+ describe("custom domains", () => {
653
+ it("should publish routes marked with 'custom_domain' as seperate custom domains", async () => {
654
+ writeWranglerToml({
655
+ routes: [{ pattern: "api.example.com", custom_domain: true }],
656
+ });
657
+ writeWorkerSource();
658
+ mockUpdateWorkerRequest({ enabled: false });
659
+ mockUploadWorkerRequest({ expectedType: "esm" });
660
+ mockPublishCustomDomainsRequest({
661
+ publishFlags: {
662
+ override_scope: true,
663
+ override_existing_origin: false,
664
+ override_existing_dns_record: false,
665
+ },
666
+ domains: [{ hostname: "api.example.com" }],
667
+ });
668
+ await runWrangler("publish ./index");
669
+ expect(std.out).toContain("api.example.com (custom domain)");
670
+ });
671
+
672
+ it("should allow retrying if publish fails with a conflicting custom domain error", async () => {
673
+ writeWranglerToml({
674
+ routes: [{ pattern: "api.example.com", custom_domain: true }],
675
+ });
676
+ writeWorkerSource();
677
+ mockUpdateWorkerRequest({ enabled: false });
678
+ mockUploadWorkerRequest({ expectedType: "esm" });
679
+ mockPublishCustomDomainsRequestConflictWithoutOverride({
680
+ originConflicts: true,
681
+ domains: [{ hostname: "api.example.com" }],
682
+ });
683
+ mockConfirm({
684
+ text: `Custom Domains already exist for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
685
+ result: true,
686
+ });
687
+ await runWrangler("publish ./index");
688
+ expect(std.out).toContain("api.example.com (custom domain)");
689
+ });
690
+
691
+ it("should allow retrying if publish fails with a conflicting DNS record error", async () => {
692
+ writeWranglerToml({
693
+ routes: [{ pattern: "api.example.com", custom_domain: true }],
694
+ });
695
+ writeWorkerSource();
696
+ mockUpdateWorkerRequest({ enabled: false });
697
+ mockUploadWorkerRequest({ expectedType: "esm" });
698
+ mockPublishCustomDomainsRequestConflictWithoutOverride({
699
+ dnsRecordConflicts: true,
700
+ domains: [{ hostname: "api.example.com" }],
701
+ });
702
+ mockConfirm({
703
+ text: `You already have conflicting DNS records for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
704
+ result: true,
705
+ });
706
+ await runWrangler("publish ./index");
707
+ expect(std.out).toContain("api.example.com (custom domain)");
708
+ });
709
+
710
+ it("should allow retrying for conflicting custom domains and then again for conflicting dns", async () => {
711
+ writeWranglerToml({
712
+ routes: [{ pattern: "api.example.com", custom_domain: true }],
713
+ });
714
+ writeWorkerSource();
715
+ mockUpdateWorkerRequest({ enabled: false });
716
+ mockUploadWorkerRequest({ expectedType: "esm" });
717
+ mockPublishCustomDomainsRequestConflictWithoutOverride({
718
+ originConflicts: true,
719
+ dnsRecordConflicts: true,
720
+ domains: [{ hostname: "api.example.com" }],
721
+ });
722
+ mockConfirm(
723
+ {
724
+ text: `Custom Domains already exist for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
725
+ result: true,
726
+ },
727
+ {
728
+ text: `You already have conflicting DNS records for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
729
+ result: true,
730
+ }
731
+ );
732
+ await runWrangler("publish ./index");
733
+ expect(std.out).toContain("api.example.com (custom domain)");
734
+ });
735
+
736
+ it("should throw if an invalid custom domain is requested", async () => {
737
+ writeWranglerToml({
738
+ routes: [{ pattern: "*.example.com", custom_domain: true }],
739
+ });
740
+ writeWorkerSource();
741
+ await expect(
742
+ runWrangler("publish ./index")
743
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
744
+ `"Cannot use \\"*.example.com\\" as a Custom Domain; wildcard operators (*) are not allowed"`
745
+ );
746
+
747
+ writeWranglerToml({
748
+ routes: [
749
+ { pattern: "api.example.com/at/a/path", custom_domain: true },
750
+ ],
751
+ });
752
+ writeWorkerSource();
753
+ await expect(
754
+ runWrangler("publish ./index")
755
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
756
+ `"Cannot use \\"api.example.com/at/a/path\\" as a Custom Domain; paths are not allowed"`
757
+ );
758
+ });
759
+
760
+ it("should not retry publish on error if user does not confirm", async () => {
761
+ writeWranglerToml({
762
+ routes: [{ pattern: "api.example.com", custom_domain: true }],
763
+ });
764
+ writeWorkerSource();
765
+ mockUpdateWorkerRequest({ enabled: false });
766
+ mockUploadWorkerRequest({ expectedType: "esm" });
767
+ mockPublishCustomDomainsRequestConflictWithoutOverride({
768
+ dnsRecordConflicts: true,
769
+ domains: [{ hostname: "api.example.com" }],
770
+ });
771
+ mockConfirm({
772
+ text: `You already have conflicting DNS records for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
773
+ result: false,
774
+ });
775
+ await runWrangler("publish ./index");
776
+ expect(std.out).toContain(
777
+ 'Publishing to Custom Domain "api.example.com" was skipped, fix conflict and try again'
778
+ );
779
+ });
780
+ });
781
+
647
782
  it.todo("should error if it's a workers.dev route");
648
783
  });
649
784
 
@@ -878,6 +1013,78 @@ export default{
878
1013
  expect(std.err).toMatchInlineSnapshot(`""`);
879
1014
  });
880
1015
 
1016
+ it("should preserve exports on a module format worker", async () => {
1017
+ writeWranglerToml();
1018
+ fs.writeFileSync(
1019
+ "index.js",
1020
+ `
1021
+ export const abc = 123;
1022
+ export const def = "show me the money";
1023
+ export default {};`
1024
+ );
1025
+
1026
+ await runWrangler("publish index.js --dry-run --outdir out");
1027
+
1028
+ expect(
1029
+ (
1030
+ await esbuild.build({
1031
+ entryPoints: [path.resolve("./out/index.js")],
1032
+ metafile: true,
1033
+ write: false,
1034
+ })
1035
+ ).metafile?.outputs["index.js"].exports
1036
+ ).toMatchInlineSnapshot(`
1037
+ Array [
1038
+ "abc",
1039
+ "def",
1040
+ "default",
1041
+ ]
1042
+ `);
1043
+
1044
+ expect(std).toMatchInlineSnapshot(`
1045
+ Object {
1046
+ "debug": "",
1047
+ "err": "",
1048
+ "out": "--dry-run: exiting now.",
1049
+ "warn": "",
1050
+ }
1051
+ `);
1052
+ });
1053
+
1054
+ it("should not preserve exports on a service-worker format worker", async () => {
1055
+ writeWranglerToml();
1056
+ fs.writeFileSync(
1057
+ "index.js",
1058
+ `
1059
+ export const abc = 123;
1060
+ export const def = "show me the money";
1061
+ addEventListener('fetch', event => {});`
1062
+ );
1063
+
1064
+ await runWrangler("publish index.js --dry-run --outdir out");
1065
+
1066
+ expect(
1067
+ (
1068
+ await esbuild.build({
1069
+ entryPoints: [path.resolve("./out/index.js")],
1070
+ metafile: true,
1071
+ write: false,
1072
+ })
1073
+ ).metafile?.outputs["index.js"].exports
1074
+ ).toMatchInlineSnapshot(`Array []`);
1075
+
1076
+ expect(std).toMatchInlineSnapshot(`
1077
+ Object {
1078
+ "debug": "",
1079
+ "err": "",
1080
+ "out": "--dry-run: exiting now.",
1081
+ "warn": "▲ [WARNING] The entrypoint index.js has exports like an ES Module, but hasn't defined a default export like a module worker normally would. Building the worker using \\"service-worker\\" format...
1082
+
1083
+ ",
1084
+ }
1085
+ `);
1086
+ });
1087
+
881
1088
  it("should be able to transpile entry-points in sub-directories (sw)", async () => {
882
1089
  writeWranglerToml();
883
1090
  writeWorkerSource({ basePath: "./src", type: "sw" });
@@ -914,7 +1121,7 @@ export default{
914
1121
 
915
1122
  expect(std.out).toMatchInlineSnapshot(`
916
1123
  "
917
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1124
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
918
1125
  `);
919
1126
  expect(std.err).toMatchInlineSnapshot(`
920
1127
  "X [ERROR] Processing wrangler.toml configuration:
@@ -1072,7 +1279,7 @@ export default{
1072
1279
 
1073
1280
  expect(std.out).toMatchInlineSnapshot(`
1074
1281
  "
1075
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1282
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1076
1283
  `);
1077
1284
  expect(std.err).toMatchInlineSnapshot(`
1078
1285
  "X [ERROR] Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`main\` config field.
@@ -1120,6 +1327,56 @@ export default{
1120
1327
  expect(std.err).toMatchInlineSnapshot(`""`);
1121
1328
  });
1122
1329
 
1330
+ it("should not contain backslash for assets with nested directories", async () => {
1331
+ const assets = [
1332
+ { filePath: "assets/subdir/file-1.txt", content: "Content of file-1" },
1333
+ { filePath: "assets/subdir/file-2.txt", content: "Content of file-2" },
1334
+ ];
1335
+ const kvNamespace = {
1336
+ title: "__test-name-workers_sites_assets",
1337
+ id: "__test-name-workers_sites_assets-id",
1338
+ };
1339
+ writeWranglerToml({
1340
+ main: "./index.js",
1341
+ site: {
1342
+ bucket: "assets",
1343
+ },
1344
+ });
1345
+ writeWorkerSource();
1346
+ writeAssets(assets);
1347
+ mockUploadWorkerRequest({
1348
+ expectedBindings: [
1349
+ {
1350
+ name: "__STATIC_CONTENT",
1351
+ namespace_id: "__test-name-workers_sites_assets-id",
1352
+ type: "kv_namespace",
1353
+ },
1354
+ ],
1355
+ expectedModules: {
1356
+ __STATIC_CONTENT_MANIFEST:
1357
+ '{"subdir/file-1.txt":"assets/subdir/file-1.2ca234f380.txt","subdir/file-2.txt":"assets/subdir/file-2.5938485188.txt"}',
1358
+ },
1359
+ });
1360
+ mockSubDomainRequest();
1361
+ mockListKVNamespacesRequest(kvNamespace);
1362
+ mockKeyListRequest(kvNamespace.id, []);
1363
+ mockUploadAssetsToKVRequest(kvNamespace.id, assets);
1364
+
1365
+ await runWrangler("publish");
1366
+
1367
+ expect(std.out).toMatchInlineSnapshot(`
1368
+ "Reading assets/subdir/file-1.txt...
1369
+ Uploading as assets/subdir/file-1.2ca234f380.txt...
1370
+ Reading assets/subdir/file-2.txt...
1371
+ Uploading as assets/subdir/file-2.5938485188.txt...
1372
+ ↗️ Done syncing assets
1373
+ Uploaded test-name (TIMINGS)
1374
+ Published test-name (TIMINGS)
1375
+ test-name.test-sub-domain.workers.dev"
1376
+ `);
1377
+ expect(std.err).toMatchInlineSnapshot(`""`);
1378
+ });
1379
+
1123
1380
  it("when using a service-worker type, it should add an asset manifest as a text_blob, and bind to a namespace", async () => {
1124
1381
  const assets = [
1125
1382
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
@@ -1733,7 +1990,7 @@ export default{
1733
1990
  "Reading assets/large-file.txt...
1734
1991
  Uploading as assets/large-file.0ea0637a45.txt...
1735
1992
 
1736
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1993
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1737
1994
  `);
1738
1995
  expect(std.err).toMatchInlineSnapshot(`
1739
1996
  "X [ERROR] File assets/too-large-file.txt is too big, it should be under 25 MiB. See https://developers.cloudflare.com/workers/platform/limits#kv-limits
@@ -1773,7 +2030,7 @@ export default{
1773
2030
  expect(std.out).toMatchInlineSnapshot(`
1774
2031
  "Reading assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.txt...
1775
2032
 
1776
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2033
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1777
2034
  `);
1778
2035
  expect(std.err).toMatchInlineSnapshot(`
1779
2036
  "X [ERROR] The asset path key \\"assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.3da0d0cd12.txt\\" exceeds the maximum key size limit of 512. See https://developers.cloudflare.com/workers/platform/limits#kv-limits\\",
@@ -2476,18 +2733,66 @@ export default{
2476
2733
  },
2477
2734
  });
2478
2735
 
2479
- await expect(
2480
- runWrangler("publish index.js")
2481
- ).rejects.toThrowErrorMatchingInlineSnapshot(
2482
- `"Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\""`
2483
- );
2736
+ await expect(runWrangler("publish index.js")).rejects
2737
+ .toThrowErrorMatchingInlineSnapshot(`
2738
+ "The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
2739
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build."
2740
+ `);
2741
+ expect(std.out).toMatchInlineSnapshot(`
2742
+ "Running custom build: node -e \\"console.log('custom build');\\"
2743
+
2744
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
2745
+ `);
2746
+ expect(std.err).toMatchInlineSnapshot(`
2747
+ "X [ERROR] The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
2748
+
2749
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build.
2750
+
2751
+ "
2752
+ `);
2753
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2754
+ });
2755
+
2756
+ it("should throw an error if the entry is a directory after the build finishes", async () => {
2757
+ writeWranglerToml({
2758
+ main: "./",
2759
+ build: {
2760
+ command: `node -e "console.log('custom build');"`,
2761
+ },
2762
+ });
2763
+
2764
+ fs.writeFileSync("./worker.js", "some content", "utf-8");
2765
+ fs.mkdirSync("./dist");
2766
+ fs.writeFileSync("./dist/index.ts", "some content", "utf-8");
2767
+
2768
+ await expect(runWrangler("publish")).rejects
2769
+ .toThrowErrorMatchingInlineSnapshot(`
2770
+ "The expected output file at \\".\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
2771
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build.
2772
+ The provided entry-point path, \\".\\", points to a directory, rather than a file.
2773
+
2774
+ Did you mean to set the main field to one of:
2775
+ \`\`\`
2776
+ main = \\"./worker.js\\"
2777
+ main = \\"./dist/index.ts\\"
2778
+ \`\`\`"
2779
+ `);
2484
2780
  expect(std.out).toMatchInlineSnapshot(`
2485
2781
  "Running custom build: node -e \\"console.log('custom build');\\"
2486
2782
 
2487
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2783
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
2488
2784
  `);
2489
2785
  expect(std.err).toMatchInlineSnapshot(`
2490
- "X [ERROR] Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\"
2786
+ "X [ERROR] The expected output file at \\".\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
2787
+
2788
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build.
2789
+ The provided entry-point path, \\".\\", points to a directory, rather than a file.
2790
+
2791
+ Did you mean to set the main field to one of:
2792
+ \`\`\`
2793
+ main = \\"./worker.js\\"
2794
+ main = \\"./dist/index.ts\\"
2795
+ \`\`\`
2491
2796
 
2492
2797
  "
2493
2798
  `);
@@ -2577,13 +2882,30 @@ export default{
2577
2882
  mockUploadWorkerRequest();
2578
2883
  await runWrangler("publish index.js");
2579
2884
  expect(std.out).toMatchInlineSnapshot(`
2580
- "Uploaded test-name (TIMINGS)
2885
+ "Your worker has access to the following bindings:
2886
+ - Durable Objects:
2887
+ - SOMENAME: SomeClass
2888
+ Uploaded test-name (TIMINGS)
2581
2889
  Published test-name (TIMINGS)
2582
2890
  test-name.test-sub-domain.workers.dev"
2583
2891
  `);
2584
2892
  expect(std.err).toMatchInlineSnapshot(`""`);
2585
2893
  expect(std.warn).toMatchInlineSnapshot(`
2586
- "▲ [WARNING] In wrangler.toml, you have configured [durable_objects] exported by this Worker (SomeClass), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml. Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details.
2894
+ "▲ [WARNING] Processing wrangler.toml configuration:
2895
+
2896
+ - In wrangler.toml, you have configured [durable_objects] exported by this Worker (SomeClass),
2897
+ but no [migrations] for them. This may not work as expected until you add a [migrations] section
2898
+ to your wrangler.toml. Add this configuration to your wrangler.toml:
2899
+
2900
+ \`\`\`
2901
+ [[migrations]]
2902
+ tag = \\"v1\\" # Should be unique for each entry
2903
+ new_classes = [\\"SomeClass\\"]
2904
+ \`\`\`
2905
+
2906
+ Refer to
2907
+ https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml
2908
+ for more details.
2587
2909
 
2588
2910
  "
2589
2911
  `);
@@ -2609,7 +2931,10 @@ export default{
2609
2931
  mockUploadWorkerRequest();
2610
2932
  await runWrangler("publish index.js");
2611
2933
  expect(std.out).toMatchInlineSnapshot(`
2612
- "Uploaded test-name (TIMINGS)
2934
+ "Your worker has access to the following bindings:
2935
+ - Durable Objects:
2936
+ - SOMENAME: SomeClass (defined in some-script)
2937
+ Uploaded test-name (TIMINGS)
2613
2938
  Published test-name (TIMINGS)
2614
2939
  test-name.test-sub-domain.workers.dev"
2615
2940
  `);
@@ -2648,7 +2973,11 @@ export default{
2648
2973
 
2649
2974
  await runWrangler("publish index.js");
2650
2975
  expect(std.out).toMatchInlineSnapshot(`
2651
- "Uploaded test-name (TIMINGS)
2976
+ "Your worker has access to the following bindings:
2977
+ - Durable Objects:
2978
+ - SOMENAME: SomeClass
2979
+ - SOMEOTHERNAME: SomeOtherClass
2980
+ Uploaded test-name (TIMINGS)
2652
2981
  Published test-name (TIMINGS)
2653
2982
  test-name.test-sub-domain.workers.dev"
2654
2983
  `);
@@ -2694,7 +3023,11 @@ export default{
2694
3023
  Object {
2695
3024
  "debug": "",
2696
3025
  "err": "",
2697
- "out": "Uploaded test-name (TIMINGS)
3026
+ "out": "Your worker has access to the following bindings:
3027
+ - Durable Objects:
3028
+ - SOMENAME: SomeClass
3029
+ - SOMEOTHERNAME: SomeOtherClass
3030
+ Uploaded test-name (TIMINGS)
2698
3031
  Published test-name (TIMINGS)
2699
3032
  test-name.test-sub-domain.workers.dev",
2700
3033
  "warn": "",
@@ -2733,7 +3066,11 @@ export default{
2733
3066
  Object {
2734
3067
  "debug": "",
2735
3068
  "err": "",
2736
- "out": "Uploaded test-name (TIMINGS)
3069
+ "out": "Your worker has access to the following bindings:
3070
+ - Durable Objects:
3071
+ - SOMENAME: SomeClass
3072
+ - SOMEOTHERNAME: SomeOtherClass
3073
+ Uploaded test-name (TIMINGS)
2737
3074
  Published test-name (TIMINGS)
2738
3075
  test-name.test-sub-domain.workers.dev",
2739
3076
  "warn": "",
@@ -2774,7 +3111,11 @@ export default{
2774
3111
 
2775
3112
  await runWrangler("publish index.js --legacy-env false");
2776
3113
  expect(std.out).toMatchInlineSnapshot(`
2777
- "Uploaded test-name (TIMINGS)
3114
+ "Your worker has access to the following bindings:
3115
+ - Durable Objects:
3116
+ - SOMENAME: SomeClass
3117
+ - SOMEOTHERNAME: SomeOtherClass
3118
+ Uploaded test-name (TIMINGS)
2778
3119
  Published test-name (TIMINGS)
2779
3120
  test-name.test-sub-domain.workers.dev"
2780
3121
  `);
@@ -2832,7 +3173,11 @@ export default{
2832
3173
 
2833
3174
  await runWrangler("publish index.js --legacy-env false --env xyz");
2834
3175
  expect(std.out).toMatchInlineSnapshot(`
2835
- "Uploaded test-name (xyz) (TIMINGS)
3176
+ "Your worker has access to the following bindings:
3177
+ - Durable Objects:
3178
+ - SOMENAME: SomeClass
3179
+ - SOMEOTHERNAME: SomeOtherClass
3180
+ Uploaded test-name (xyz) (TIMINGS)
2836
3181
  Published test-name (xyz) (TIMINGS)
2837
3182
  xyz.test-name.test-sub-domain.workers.dev"
2838
3183
  `);
@@ -2886,7 +3231,11 @@ export default{
2886
3231
  Object {
2887
3232
  "debug": "",
2888
3233
  "err": "",
2889
- "out": "Uploaded test-name (TIMINGS)
3234
+ "out": "Your worker has access to the following bindings:
3235
+ - Durable Objects:
3236
+ - SOMENAME: SomeClass
3237
+ - SOMEOTHERNAME: SomeOtherClass
3238
+ Uploaded test-name (TIMINGS)
2890
3239
  Published test-name (TIMINGS)
2891
3240
  test-name.test-sub-domain.workers.dev",
2892
3241
  "warn": "▲ [WARNING] Processing wrangler.toml configuration:
@@ -2950,7 +3299,11 @@ export default{
2950
3299
  Object {
2951
3300
  "debug": "",
2952
3301
  "err": "",
2953
- "out": "Uploaded test-name (xyz) (TIMINGS)
3302
+ "out": "Your worker has access to the following bindings:
3303
+ - Durable Objects:
3304
+ - SOMENAME: SomeClass
3305
+ - SOMEOTHERNAME: SomeOtherClass
3306
+ Uploaded test-name (xyz) (TIMINGS)
2954
3307
  Published test-name (xyz) (TIMINGS)
2955
3308
  xyz.test-name.test-sub-domain.workers.dev",
2956
3309
  "warn": "▲ [WARNING] Processing wrangler.toml configuration:
@@ -2985,6 +3338,7 @@ export default{
2985
3338
  name: "DURABLE_OBJECT_TWO",
2986
3339
  class_name: "AnotherDurableObject",
2987
3340
  script_name: "another-durable-object-worker",
3341
+ environment: "staging",
2988
3342
  },
2989
3343
  ],
2990
3344
  },
@@ -3043,6 +3397,12 @@ export default{
3043
3397
  mockUploadWorkerRequest({
3044
3398
  expectedType: "sw",
3045
3399
  expectedBindings: [
3400
+ { json: 123, name: "ENV_VAR_ONE", type: "json" },
3401
+ {
3402
+ name: "ENV_VAR_TWO",
3403
+ text: "Hello, I'm an environment variable",
3404
+ type: "plain_text",
3405
+ },
3046
3406
  {
3047
3407
  name: "KV_NAMESPACE_ONE",
3048
3408
  namespace_id: "kv-ns-one-id",
@@ -3061,6 +3421,7 @@ export default{
3061
3421
  },
3062
3422
  {
3063
3423
  class_name: "AnotherDurableObject",
3424
+ environment: "staging",
3064
3425
  name: "DURABLE_OBJECT_TWO",
3065
3426
  script_name: "another-durable-object-worker",
3066
3427
  type: "durable_object_namespace",
@@ -3075,12 +3436,6 @@ export default{
3075
3436
  name: "R2_BUCKET_TWO",
3076
3437
  type: "r2_bucket",
3077
3438
  },
3078
- { json: 123, name: "ENV_VAR_ONE", type: "json" },
3079
- {
3080
- name: "ENV_VAR_TWO",
3081
- text: "Hello, I'm an environment variable",
3082
- type: "plain_text",
3083
- },
3084
3439
  {
3085
3440
  name: "WASM_MODULE_ONE",
3086
3441
  part: "WASM_MODULE_ONE",
@@ -3112,7 +3467,32 @@ export default{
3112
3467
 
3113
3468
  await expect(runWrangler("publish index.js")).resolves.toBeUndefined();
3114
3469
  expect(std.out).toMatchInlineSnapshot(`
3115
- "Uploaded test-name (TIMINGS)
3470
+ "Your worker has access to the following bindings:
3471
+ - Data Blobs:
3472
+ - DATA_BLOB_ONE: some-data-blob.bin
3473
+ - DATA_BLOB_TWO: more-data-blob.bin
3474
+ - Durable Objects:
3475
+ - DURABLE_OBJECT_ONE: SomeDurableObject (defined in some-durable-object-worker)
3476
+ - DURABLE_OBJECT_TWO: AnotherDurableObject (defined in another-durable-object-worker) - staging
3477
+ - KV Namespaces:
3478
+ - KV_NAMESPACE_ONE: kv-ns-one-id
3479
+ - KV_NAMESPACE_TWO: kv-ns-two-id
3480
+ - R2 Buckets:
3481
+ - R2_BUCKET_ONE: r2-bucket-one-name
3482
+ - R2_BUCKET_TWO: r2-bucket-two-name
3483
+ - Text Blobs:
3484
+ - TEXT_BLOB_ONE: my-entire-app-depends-on-this.cfg
3485
+ - TEXT_BLOB_TWO: the-entirety-of-human-knowledge.txt
3486
+ - Unsafe:
3487
+ - some unsafe thing: UNSAFE_BINDING_ONE
3488
+ - another unsafe thing: UNSAFE_BINDING_TWO
3489
+ - Vars:
3490
+ - ENV_VAR_ONE: \\"123\\"
3491
+ - ENV_VAR_TWO: \\"Hello, I'm an environment variable\\"
3492
+ - Wasm Modules:
3493
+ - WASM_MODULE_ONE: some_wasm.wasm
3494
+ - WASM_MODULE_TWO: more_wasm.wasm
3495
+ Uploaded test-name (TIMINGS)
3116
3496
  Published test-name (TIMINGS)
3117
3497
  test-name.test-sub-domain.workers.dev"
3118
3498
  `);
@@ -3209,7 +3589,7 @@ export default{
3209
3589
  `);
3210
3590
  expect(std.out).toMatchInlineSnapshot(`
3211
3591
  "
3212
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3592
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
3213
3593
  `);
3214
3594
  expect(std.err).toMatchInlineSnapshot(`
3215
3595
  "X [ERROR] Processing wrangler.toml configuration:
@@ -3308,7 +3688,7 @@ export default{
3308
3688
  `);
3309
3689
  expect(std.out).toMatchInlineSnapshot(`
3310
3690
  "
3311
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3691
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
3312
3692
  `);
3313
3693
  expect(std.err).toMatchInlineSnapshot(`
3314
3694
  "X [ERROR] Processing wrangler.toml configuration:
@@ -3442,7 +3822,7 @@ export default{
3442
3822
  `);
3443
3823
  expect(std.out).toMatchInlineSnapshot(`
3444
3824
  "
3445
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3825
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
3446
3826
  `);
3447
3827
  expect(std.err).toMatchInlineSnapshot(`
3448
3828
  "X [ERROR] Processing wrangler.toml configuration:
@@ -3488,10 +3868,13 @@ export default{
3488
3868
  mockSubDomainRequest();
3489
3869
  await runWrangler("publish index.js");
3490
3870
  expect(std.out).toMatchInlineSnapshot(`
3491
- "Uploaded test-name (TIMINGS)
3492
- Published test-name (TIMINGS)
3493
- test-name.test-sub-domain.workers.dev"
3494
- `);
3871
+ "Your worker has access to the following bindings:
3872
+ - Wasm Modules:
3873
+ - TESTWASMNAME: path/to/test.wasm
3874
+ Uploaded test-name (TIMINGS)
3875
+ Published test-name (TIMINGS)
3876
+ test-name.test-sub-domain.workers.dev"
3877
+ `);
3495
3878
  expect(std.err).toMatchInlineSnapshot(`""`);
3496
3879
  expect(std.warn).toMatchInlineSnapshot(`""`);
3497
3880
  });
@@ -3513,7 +3896,7 @@ export default{
3513
3896
  );
3514
3897
  expect(std.out).toMatchInlineSnapshot(`
3515
3898
  "
3516
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3899
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
3517
3900
  `);
3518
3901
  expect(std.err).toMatchInlineSnapshot(`
3519
3902
  "X [ERROR] You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code
@@ -3554,10 +3937,13 @@ export default{
3554
3937
  mockSubDomainRequest();
3555
3938
  await runWrangler("publish index.js --config ./path/to/wrangler.toml");
3556
3939
  expect(std.out).toMatchInlineSnapshot(`
3557
- "Uploaded test-name (TIMINGS)
3558
- Published test-name (TIMINGS)
3559
- test-name.test-sub-domain.workers.dev"
3560
- `);
3940
+ "Your worker has access to the following bindings:
3941
+ - Wasm Modules:
3942
+ - TESTWASMNAME: path/to/and/the/path/to/test.wasm
3943
+ Uploaded test-name (TIMINGS)
3944
+ Published test-name (TIMINGS)
3945
+ test-name.test-sub-domain.workers.dev"
3946
+ `);
3561
3947
  expect(std.err).toMatchInlineSnapshot(`""`);
3562
3948
  expect(std.warn).toMatchInlineSnapshot(`""`);
3563
3949
  });
@@ -3619,10 +4005,13 @@ export default{
3619
4005
  mockSubDomainRequest();
3620
4006
  await runWrangler("publish index.js");
3621
4007
  expect(std.out).toMatchInlineSnapshot(`
3622
- "Uploaded test-name (TIMINGS)
3623
- Published test-name (TIMINGS)
3624
- test-name.test-sub-domain.workers.dev"
3625
- `);
4008
+ "Your worker has access to the following bindings:
4009
+ - Text Blobs:
4010
+ - TESTTEXTBLOBNAME: path/to/text.file
4011
+ Uploaded test-name (TIMINGS)
4012
+ Published test-name (TIMINGS)
4013
+ test-name.test-sub-domain.workers.dev"
4014
+ `);
3626
4015
  expect(std.err).toMatchInlineSnapshot(`""`);
3627
4016
  expect(std.warn).toMatchInlineSnapshot(`""`);
3628
4017
  });
@@ -3644,7 +4033,7 @@ export default{
3644
4033
  );
3645
4034
  expect(std.out).toMatchInlineSnapshot(`
3646
4035
  "
3647
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
4036
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
3648
4037
  `);
3649
4038
  expect(std.err).toMatchInlineSnapshot(`
3650
4039
  "X [ERROR] You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your wrangler.toml
@@ -3689,10 +4078,13 @@ export default{
3689
4078
  mockSubDomainRequest();
3690
4079
  await runWrangler("publish index.js --config ./path/to/wrangler.toml");
3691
4080
  expect(std.out).toMatchInlineSnapshot(`
3692
- "Uploaded test-name (TIMINGS)
3693
- Published test-name (TIMINGS)
3694
- test-name.test-sub-domain.workers.dev"
3695
- `);
4081
+ "Your worker has access to the following bindings:
4082
+ - Text Blobs:
4083
+ - TESTTEXTBLOBNAME: path/to/and/the/path/to/text.file
4084
+ Uploaded test-name (TIMINGS)
4085
+ Published test-name (TIMINGS)
4086
+ test-name.test-sub-domain.workers.dev"
4087
+ `);
3696
4088
  expect(std.err).toMatchInlineSnapshot(`""`);
3697
4089
  expect(std.warn).toMatchInlineSnapshot(`""`);
3698
4090
  });
@@ -3722,10 +4114,13 @@ export default{
3722
4114
  mockSubDomainRequest();
3723
4115
  await runWrangler("publish index.js");
3724
4116
  expect(std.out).toMatchInlineSnapshot(`
3725
- "Uploaded test-name (TIMINGS)
3726
- Published test-name (TIMINGS)
3727
- test-name.test-sub-domain.workers.dev"
3728
- `);
4117
+ "Your worker has access to the following bindings:
4118
+ - Data Blobs:
4119
+ - TESTDATABLOBNAME: path/to/data.bin
4120
+ Uploaded test-name (TIMINGS)
4121
+ Published test-name (TIMINGS)
4122
+ test-name.test-sub-domain.workers.dev"
4123
+ `);
3729
4124
  expect(std.err).toMatchInlineSnapshot(`""`);
3730
4125
  expect(std.warn).toMatchInlineSnapshot(`""`);
3731
4126
  });
@@ -3747,7 +4142,7 @@ export default{
3747
4142
  );
3748
4143
  expect(std.out).toMatchInlineSnapshot(`
3749
4144
  "
3750
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
4145
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
3751
4146
  `);
3752
4147
  expect(std.err).toMatchInlineSnapshot(`
3753
4148
  "X [ERROR] You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your wrangler.toml
@@ -3792,10 +4187,13 @@ export default{
3792
4187
  mockSubDomainRequest();
3793
4188
  await runWrangler("publish index.js --config ./path/to/wrangler.toml");
3794
4189
  expect(std.out).toMatchInlineSnapshot(`
3795
- "Uploaded test-name (TIMINGS)
3796
- Published test-name (TIMINGS)
3797
- test-name.test-sub-domain.workers.dev"
3798
- `);
4190
+ "Your worker has access to the following bindings:
4191
+ - Data Blobs:
4192
+ - TESTDATABLOBNAME: path/to/and/the/path/to/data.bin
4193
+ Uploaded test-name (TIMINGS)
4194
+ Published test-name (TIMINGS)
4195
+ test-name.test-sub-domain.workers.dev"
4196
+ `);
3799
4197
  expect(std.err).toMatchInlineSnapshot(`""`);
3800
4198
  expect(std.warn).toMatchInlineSnapshot(`""`);
3801
4199
  });
@@ -3826,10 +4224,15 @@ export default{
3826
4224
 
3827
4225
  await runWrangler("publish index.js");
3828
4226
  expect(std.out).toMatchInlineSnapshot(`
3829
- "Uploaded test-name (TIMINGS)
3830
- Published test-name (TIMINGS)
3831
- test-name.test-sub-domain.workers.dev"
3832
- `);
4227
+ "Your worker has access to the following bindings:
4228
+ - Vars:
4229
+ - text: \\"plain ol' string\\"
4230
+ - count: \\"1\\"
4231
+ - complex: \\"[object Object]\\"
4232
+ Uploaded test-name (TIMINGS)
4233
+ Published test-name (TIMINGS)
4234
+ test-name.test-sub-domain.workers.dev"
4235
+ `);
3833
4236
  expect(std.err).toMatchInlineSnapshot(`""`);
3834
4237
  expect(std.warn).toMatchInlineSnapshot(`""`);
3835
4238
  });
@@ -3850,10 +4253,13 @@ export default{
3850
4253
 
3851
4254
  await runWrangler("publish index.js");
3852
4255
  expect(std.out).toMatchInlineSnapshot(`
3853
- "Uploaded test-name (TIMINGS)
3854
- Published test-name (TIMINGS)
3855
- test-name.test-sub-domain.workers.dev"
3856
- `);
4256
+ "Your worker has access to the following bindings:
4257
+ - R2 Buckets:
4258
+ - FOO: foo-bucket
4259
+ Uploaded test-name (TIMINGS)
4260
+ Published test-name (TIMINGS)
4261
+ test-name.test-sub-domain.workers.dev"
4262
+ `);
3857
4263
  expect(std.err).toMatchInlineSnapshot(`""`);
3858
4264
  expect(std.warn).toMatchInlineSnapshot(`""`);
3859
4265
  });
@@ -3892,10 +4298,13 @@ export default{
3892
4298
 
3893
4299
  await runWrangler("publish index.js");
3894
4300
  expect(std.out).toMatchInlineSnapshot(`
3895
- "Uploaded test-name (TIMINGS)
3896
- Published test-name (TIMINGS)
3897
- test-name.test-sub-domain.workers.dev"
3898
- `);
4301
+ "Your worker has access to the following bindings:
4302
+ - Durable Objects:
4303
+ - EXAMPLE_DO_BINDING: ExampleDurableObject
4304
+ Uploaded test-name (TIMINGS)
4305
+ Published test-name (TIMINGS)
4306
+ test-name.test-sub-domain.workers.dev"
4307
+ `);
3899
4308
  expect(std.err).toMatchInlineSnapshot(`""`);
3900
4309
  expect(std.warn).toMatchInlineSnapshot(`""`);
3901
4310
  });
@@ -3928,10 +4337,13 @@ export default{
3928
4337
 
3929
4338
  await runWrangler("publish index.js");
3930
4339
  expect(std.out).toMatchInlineSnapshot(`
3931
- "Uploaded test-name (TIMINGS)
3932
- Published test-name (TIMINGS)
3933
- test-name.test-sub-domain.workers.dev"
3934
- `);
4340
+ "Your worker has access to the following bindings:
4341
+ - Durable Objects:
4342
+ - EXAMPLE_DO_BINDING: ExampleDurableObject (defined in example-do-binding-worker)
4343
+ Uploaded test-name (TIMINGS)
4344
+ Published test-name (TIMINGS)
4345
+ test-name.test-sub-domain.workers.dev"
4346
+ `);
3935
4347
  expect(std.err).toMatchInlineSnapshot(`""`);
3936
4348
  expect(std.warn).toMatchInlineSnapshot(`""`);
3937
4349
  });
@@ -3969,10 +4381,13 @@ export default{
3969
4381
 
3970
4382
  await runWrangler("publish index.js");
3971
4383
  expect(std.out).toMatchInlineSnapshot(`
3972
- "Uploaded test-name (TIMINGS)
3973
- Published test-name (TIMINGS)
3974
- test-name.test-sub-domain.workers.dev"
3975
- `);
4384
+ "Your worker has access to the following bindings:
4385
+ - Durable Objects:
4386
+ - EXAMPLE_DO_BINDING: ExampleDurableObject
4387
+ Uploaded test-name (TIMINGS)
4388
+ Published test-name (TIMINGS)
4389
+ test-name.test-sub-domain.workers.dev"
4390
+ `);
3976
4391
  expect(std.err).toMatchInlineSnapshot(`""`);
3977
4392
  expect(std.warn).toMatchInlineSnapshot(`""`);
3978
4393
  });
@@ -4002,6 +4417,50 @@ export default{
4002
4417
  });
4003
4418
  });
4004
4419
 
4420
+ describe("[services]", () => {
4421
+ it("should support service bindings", async () => {
4422
+ writeWranglerToml({
4423
+ services: [
4424
+ {
4425
+ binding: "FOO",
4426
+ service: "foo-service",
4427
+ environment: "production",
4428
+ },
4429
+ ],
4430
+ });
4431
+ writeWorkerSource();
4432
+ mockSubDomainRequest();
4433
+ mockUploadWorkerRequest({
4434
+ expectedBindings: [
4435
+ {
4436
+ type: "service",
4437
+ name: "FOO",
4438
+ service: "foo-service",
4439
+ environment: "production",
4440
+ },
4441
+ ],
4442
+ });
4443
+
4444
+ await runWrangler("publish index.js");
4445
+ expect(std.out).toMatchInlineSnapshot(`
4446
+ "Your worker has access to the following bindings:
4447
+ - Services:
4448
+ - FOO: foo-service - production
4449
+ Uploaded test-name (TIMINGS)
4450
+ Published test-name (TIMINGS)
4451
+ test-name.test-sub-domain.workers.dev"
4452
+ `);
4453
+ expect(std.err).toMatchInlineSnapshot(`""`);
4454
+ expect(std.warn).toMatchInlineSnapshot(`
4455
+ "▲ [WARNING] Processing wrangler.toml configuration:
4456
+
4457
+ - \\"services\\" fields are experimental and may change or break at any time.
4458
+
4459
+ "
4460
+ `);
4461
+ });
4462
+ });
4463
+
4005
4464
  describe("[unsafe]", () => {
4006
4465
  it("should warn if using unsafe bindings", async () => {
4007
4466
  writeWranglerToml({
@@ -4029,10 +4488,13 @@ export default{
4029
4488
 
4030
4489
  await runWrangler("publish index.js");
4031
4490
  expect(std.out).toMatchInlineSnapshot(`
4032
- "Uploaded test-name (TIMINGS)
4033
- Published test-name (TIMINGS)
4034
- test-name.test-sub-domain.workers.dev"
4035
- `);
4491
+ "Your worker has access to the following bindings:
4492
+ - Unsafe:
4493
+ - binding-type: my-binding
4494
+ Uploaded test-name (TIMINGS)
4495
+ Published test-name (TIMINGS)
4496
+ test-name.test-sub-domain.workers.dev"
4497
+ `);
4036
4498
  expect(std.err).toMatchInlineSnapshot(`""`);
4037
4499
  expect(std.warn).toMatchInlineSnapshot(`
4038
4500
  "▲ [WARNING] Processing wrangler.toml configuration:
@@ -4068,10 +4530,13 @@ export default{
4068
4530
 
4069
4531
  await runWrangler("publish index.js");
4070
4532
  expect(std.out).toMatchInlineSnapshot(`
4071
- "Uploaded test-name (TIMINGS)
4072
- Published test-name (TIMINGS)
4073
- test-name.test-sub-domain.workers.dev"
4074
- `);
4533
+ "Your worker has access to the following bindings:
4534
+ - Unsafe:
4535
+ - plain_text: my-binding
4536
+ Uploaded test-name (TIMINGS)
4537
+ Published test-name (TIMINGS)
4538
+ test-name.test-sub-domain.workers.dev"
4539
+ `);
4075
4540
  expect(std.err).toMatchInlineSnapshot(`""`);
4076
4541
  expect(std.warn).toMatchInlineSnapshot(`
4077
4542
  "▲ [WARNING] Processing wrangler.toml configuration:
@@ -4504,14 +4969,25 @@ export default{
4504
4969
 
4505
4970
  describe("--dry-run", () => {
4506
4971
  it("should not publish the worker if --dry-run is specified", async () => {
4507
- writeWranglerToml();
4972
+ writeWranglerToml({
4973
+ // add a durable object with migrations
4974
+ // to make sure we _don't_ fetch migration status
4975
+ durable_objects: {
4976
+ bindings: [{ name: "NAME", class_name: "SomeClass" }],
4977
+ },
4978
+ migrations: [{ tag: "v1", new_classes: ["SomeClass"] }],
4979
+ });
4508
4980
  writeWorkerSource();
4981
+ process.env.CLOUDFLARE_ACCOUNT_ID = "";
4509
4982
  await runWrangler("publish index.js --dry-run");
4510
4983
  expect(std).toMatchInlineSnapshot(`
4511
4984
  Object {
4512
4985
  "debug": "",
4513
4986
  "err": "",
4514
- "out": "--dry-run: exiting now.",
4987
+ "out": "Your worker has access to the following bindings:
4988
+ - Durable Objects:
4989
+ - NAME: SomeClass
4990
+ --dry-run: exiting now.",
4515
4991
  "warn": "",
4516
4992
  }
4517
4993
  `);
@@ -4535,6 +5011,27 @@ export default{
4535
5011
  `);
4536
5012
  });
4537
5013
 
5014
+ it("should recommend node compatibility mode when using node builtins and node-compat isn't enabled", async () => {
5015
+ writeWranglerToml();
5016
+ fs.writeFileSync(
5017
+ "index.js",
5018
+ `
5019
+ import path from 'path';
5020
+ console.log(path.join("some/path/to", "a/file.txt"));
5021
+ export default {}
5022
+ `
5023
+ );
5024
+ let err: Error | undefined;
5025
+ try {
5026
+ await runWrangler("publish index.js --dry-run"); // expecting this to throw, as node compatibility isn't enabled
5027
+ } catch (e) {
5028
+ err = e as Error;
5029
+ }
5030
+ expect(err?.message).toMatch(
5031
+ `Detected a Node builtin module import while Node compatibility is disabled.\nAdd node_compat = true to your wrangler.toml file to enable Node compatibility.`
5032
+ );
5033
+ });
5034
+
4538
5035
  it("should polyfill node builtins when enabled", async () => {
4539
5036
  writeWranglerToml();
4540
5037
  fs.writeFileSync(
@@ -4729,6 +5226,102 @@ function mockPublishRoutesRequest({
4729
5226
  );
4730
5227
  }
4731
5228
 
5229
+ function mockPublishCustomDomainsRequest({
5230
+ publishFlags,
5231
+ domains = [],
5232
+ env = undefined,
5233
+ legacyEnv = false,
5234
+ }: {
5235
+ publishFlags: {
5236
+ override_scope: boolean;
5237
+ override_existing_origin: boolean;
5238
+ override_existing_dns_record: boolean;
5239
+ };
5240
+ domains: Array<
5241
+ { hostname: string } & ({ zone_id?: string } | { zone_name?: string })
5242
+ >;
5243
+ env?: string | undefined;
5244
+ legacyEnv?: boolean | undefined;
5245
+ }) {
5246
+ const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
5247
+ const environment = env && !legacyEnv ? "/environments/:envName" : "";
5248
+
5249
+ setMockResponse(
5250
+ `/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/domains`,
5251
+ "PUT",
5252
+ ([_url, accountId, scriptName, envName], { body }) => {
5253
+ expect(accountId).toEqual("some-account-id");
5254
+ expect(scriptName).toEqual(
5255
+ legacyEnv && env ? `test-name-${env}` : "test-name"
5256
+ );
5257
+ if (!legacyEnv) {
5258
+ expect(envName).toEqual(env);
5259
+ }
5260
+
5261
+ expect(JSON.parse(body as string)).toEqual({
5262
+ ...publishFlags,
5263
+ origins: domains,
5264
+ });
5265
+
5266
+ return null;
5267
+ }
5268
+ );
5269
+ }
5270
+
5271
+ function mockPublishCustomDomainsRequestConflictWithoutOverride({
5272
+ domains = [],
5273
+ originConflicts = false,
5274
+ dnsRecordConflicts = false,
5275
+ env = undefined,
5276
+ legacyEnv = false,
5277
+ }: {
5278
+ originConflicts?: boolean;
5279
+ dnsRecordConflicts?: boolean;
5280
+ domains: Array<
5281
+ { hostname: string } & ({ zone_id?: string } | { zone_name?: string })
5282
+ >;
5283
+ env?: string | undefined;
5284
+ legacyEnv?: boolean | undefined;
5285
+ }) {
5286
+ const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
5287
+ const environment = env && !legacyEnv ? "/environments/:envName" : "";
5288
+
5289
+ setMockRawResponse(
5290
+ `/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/domains`,
5291
+ "PUT",
5292
+ ([_url, accountId, scriptName, envName], { body }) => {
5293
+ expect(accountId).toEqual("some-account-id");
5294
+ expect(scriptName).toEqual(
5295
+ legacyEnv && env ? `test-name-${env}` : "test-name"
5296
+ );
5297
+ if (!legacyEnv) {
5298
+ expect(envName).toEqual(env);
5299
+ }
5300
+
5301
+ const parsed = JSON.parse(body as string);
5302
+ expect(parsed.origins).toEqual(domains);
5303
+
5304
+ if (originConflicts && !parsed.override_existing_origin) {
5305
+ return createFetchResult(null, false, [
5306
+ {
5307
+ code: 100116,
5308
+ message: `Cannot create Custom Domain "${domains[0].hostname}": Custom Domain already exists and points to a different script; retry and use option "override_existing_origin" to override`,
5309
+ },
5310
+ ]);
5311
+ }
5312
+ if (dnsRecordConflicts && !parsed.override_existing_dns_record) {
5313
+ return createFetchResult(null, false, [
5314
+ {
5315
+ code: 100117,
5316
+ message: `Cannot create Custom Domain "${domains[0].hostname}": a DNS record already exists for this origin; retry and use option "override_existing_dns_record" to override`,
5317
+ },
5318
+ ]);
5319
+ }
5320
+ return createFetchResult(null, true);
5321
+ }
5322
+ );
5323
+ }
5324
+
4732
5325
  /** Create a mock handler for the request to get a list of all KV namespaces. */
4733
5326
  function mockListKVNamespacesRequest(...namespaces: KVNamespaceInfo[]) {
4734
5327
  setMockResponse(