wrangler 2.0.6 → 2.0.9

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 (46) hide show
  1. package/README.md +1 -1
  2. package/bin/wrangler.js +16 -4
  3. package/package.json +6 -4
  4. package/pages/functions/buildPlugin.ts +13 -0
  5. package/pages/functions/buildWorker.ts +13 -0
  6. package/src/__tests__/configuration.test.ts +132 -60
  7. package/src/__tests__/dev.test.tsx +168 -67
  8. package/src/__tests__/helpers/mock-dialogs.ts +41 -1
  9. package/src/__tests__/index.test.ts +25 -10
  10. package/src/__tests__/init.test.ts +252 -131
  11. package/src/__tests__/kv.test.ts +16 -16
  12. package/src/__tests__/package-manager.test.ts +154 -7
  13. package/src/__tests__/pages.test.ts +442 -38
  14. package/src/__tests__/parse.test.ts +5 -1
  15. package/src/__tests__/publish.test.ts +377 -84
  16. package/src/__tests__/secret.test.ts +4 -4
  17. package/src/__tests__/whoami.test.tsx +34 -0
  18. package/src/abort.d.ts +3 -0
  19. package/src/cfetch/index.ts +21 -4
  20. package/src/cfetch/internal.ts +20 -18
  21. package/src/config/config.ts +1 -1
  22. package/src/config/index.ts +162 -0
  23. package/src/config/validation.ts +77 -29
  24. package/src/create-worker-preview.ts +32 -22
  25. package/src/dev/dev.tsx +6 -16
  26. package/src/dev/remote.tsx +40 -16
  27. package/src/dialogs.tsx +48 -0
  28. package/src/durable.ts +102 -0
  29. package/src/index.tsx +291 -207
  30. package/src/inspect.ts +39 -0
  31. package/src/kv.ts +74 -25
  32. package/src/open-in-browser.ts +5 -12
  33. package/src/package-manager.ts +50 -3
  34. package/src/pages.tsx +218 -61
  35. package/src/parse.ts +21 -4
  36. package/src/proxy.ts +38 -22
  37. package/src/publish.ts +166 -108
  38. package/src/sites.tsx +8 -8
  39. package/src/user.tsx +12 -1
  40. package/src/whoami.tsx +3 -2
  41. package/src/worker.ts +2 -1
  42. package/src/zones.ts +73 -0
  43. package/templates/new-worker-scheduled.js +17 -0
  44. package/templates/new-worker-scheduled.ts +32 -0
  45. package/templates/new-worker.ts +16 -1
  46. package/wrangler-dist/cli.js +33066 -20052
package/src/index.tsx CHANGED
@@ -11,14 +11,15 @@ import { render } from "ink";
11
11
  import React from "react";
12
12
  import onExit from "signal-exit";
13
13
  import supportsColor from "supports-color";
14
+ import { setGlobalDispatcher, ProxyAgent } from "undici";
14
15
  import makeCLI from "yargs";
15
16
  import { version as wranglerVersion } from "../package.json";
16
17
  import { fetchResult } from "./cfetch";
17
- import { findWranglerToml, readConfig } from "./config";
18
+ import { findWranglerToml, printBindings, readConfig } from "./config";
18
19
  import { createWorkerUploadForm } from "./create-worker-upload-form";
19
20
  import Dev from "./dev/dev";
20
21
  import { getVarsForDev } from "./dev/dev-vars";
21
- import { confirm, prompt } from "./dialogs";
22
+ import { confirm, prompt, select } from "./dialogs";
22
23
  import { getEntry } from "./entry";
23
24
  import { DeprecationError } from "./errors";
24
25
  import {
@@ -43,6 +44,7 @@ import {
43
44
  formatMessage,
44
45
  ParseError,
45
46
  parseJSON,
47
+ parsePackageJSON,
46
48
  parseTOML,
47
49
  readFileSync,
48
50
  } from "./parse";
@@ -64,6 +66,7 @@ import {
64
66
  requireAuth,
65
67
  } from "./user";
66
68
  import { whoami } from "./whoami";
69
+ import { getZoneIdFromHost, getZoneForRoute } from "./zones";
67
70
 
68
71
  import type { Config } from "./config";
69
72
  import type { TailCLIFilters } from "./tail";
@@ -77,6 +80,17 @@ const resetColor = "\x1b[0m";
77
80
  const fgGreenColor = "\x1b[32m";
78
81
  const DEFAULT_LOCAL_PORT = 8787;
79
82
 
83
+ const proxy =
84
+ process.env.https_proxy ||
85
+ process.env.HTTPS_PROXY ||
86
+ process.env.http_proxy ||
87
+ process.env.HTTP_PROXY ||
88
+ undefined;
89
+
90
+ if (proxy) {
91
+ setGlobalDispatcher(new ProxyAgent(proxy));
92
+ }
93
+
80
94
  function getRules(config: Config): Config["rules"] {
81
95
  const rules = config.rules ?? config.build?.upload?.rules ?? [];
82
96
 
@@ -333,6 +347,9 @@ function createCLIParser(argv: string[]) {
333
347
  throw new CommandLineArgsError(message);
334
348
  }
335
349
 
350
+ const devDepsToInstall: string[] = [];
351
+ const instructions: string[] = [];
352
+ let shouldRunPackageManagerInstall = false;
336
353
  const creationDirectory = path.resolve(process.cwd(), args.name ?? "");
337
354
 
338
355
  if (args.site) {
@@ -428,7 +445,12 @@ function createCLIParser(argv: string[]) {
428
445
  yesFlag ||
429
446
  (await confirm("Would you like to use git to manage this Worker?"));
430
447
  if (shouldInitGit) {
431
- await execa("git", ["init"], { cwd: creationDirectory });
448
+ await execa("git", ["init"], {
449
+ cwd: creationDirectory,
450
+ });
451
+ await execa("git", ["branch", "-m", "main"], {
452
+ cwd: creationDirectory,
453
+ });
432
454
  await writeFile(
433
455
  path.join(creationDirectory, ".gitignore"),
434
456
  readFileSync(path.join(__dirname, "../templates/gitignore"))
@@ -474,7 +496,7 @@ function createCLIParser(argv: string[]) {
474
496
  ) + "\n"
475
497
  );
476
498
 
477
- await packageManager.install();
499
+ shouldRunPackageManagerInstall = true;
478
500
  pathToPackageJson = path.join(creationDirectory, "package.json");
479
501
  logger.log(
480
502
  `✨ Created ${path.relative(process.cwd(), pathToPackageJson)}`
@@ -485,7 +507,7 @@ function createCLIParser(argv: string[]) {
485
507
  } else {
486
508
  // If package.json exists and wrangler isn't installed,
487
509
  // then ask to add wrangler to devDependencies
488
- const packageJson = parseJSON(
510
+ const packageJson = parsePackageJSON(
489
511
  readFileSync(pathToPackageJson),
490
512
  pathToPackageJson
491
513
  );
@@ -504,8 +526,7 @@ function createCLIParser(argv: string[]) {
504
526
  )}?`
505
527
  ));
506
528
  if (shouldInstall) {
507
- await packageManager.addDevDeps(`wrangler@${wranglerVersion}`);
508
- logger.log(`✨ Installed wrangler`);
529
+ devDepsToInstall.push(`wrangler@${wranglerVersion}`);
509
530
  }
510
531
  }
511
532
  }
@@ -523,23 +544,18 @@ function createCLIParser(argv: string[]) {
523
544
  path.join(creationDirectory, "./tsconfig.json"),
524
545
  readFileSync(path.join(__dirname, "../templates/tsconfig.json"))
525
546
  );
526
- await packageManager.addDevDeps(
527
- "@cloudflare/workers-types",
528
- "typescript"
529
- );
547
+ devDepsToInstall.push("@cloudflare/workers-types");
548
+ devDepsToInstall.push("typescript");
530
549
  pathToTSConfig = path.join(creationDirectory, "tsconfig.json");
531
550
  logger.log(
532
- `✨ Created ${path.relative(
533
- process.cwd(),
534
- pathToTSConfig
535
- )}, installed @cloudflare/workers-types into devDependencies`
551
+ `✨ Created ${path.relative(process.cwd(), pathToTSConfig)}`
536
552
  );
537
553
  }
538
554
  } else {
539
555
  isTypescriptProject = true;
540
556
  // If there's a tsconfig, check if @cloudflare/workers-types
541
557
  // is already installed, and offer to install it if not
542
- const packageJson = parseJSON(
558
+ const packageJson = parsePackageJSON(
543
559
  readFileSync(pathToPackageJson),
544
560
  pathToPackageJson
545
561
  );
@@ -553,13 +569,13 @@ function createCLIParser(argv: string[]) {
553
569
  "Would you like to install the type definitions for Workers into your package.json?"
554
570
  );
555
571
  if (shouldInstall) {
556
- await packageManager.addDevDeps("@cloudflare/workers-types");
572
+ devDepsToInstall.push("@cloudflare/workers-types");
557
573
  // We don't update the tsconfig.json because
558
574
  // it could be complicated in existing projects
559
575
  // and we don't want to break them. Instead, we simply
560
576
  // tell the user that they need to update their tsconfig.json
561
- logger.log(
562
- `✨ Installed @cloudflare/workers-types.\nPlease add "@cloudflare/workers-types" to compilerOptions.types in ${path.relative(
577
+ instructions.push(
578
+ `🚨 Please add "@cloudflare/workers-types" to compilerOptions.types in ${path.relative(
563
579
  process.cwd(),
564
580
  pathToTSConfig
565
581
  )}`
@@ -568,7 +584,7 @@ function createCLIParser(argv: string[]) {
568
584
  }
569
585
  }
570
586
 
571
- const packageJsonContent = parseJSON(
587
+ const packageJsonContent = parsePackageJSON(
572
588
  readFileSync(pathToPackageJson),
573
589
  pathToPackageJson
574
590
  );
@@ -577,25 +593,60 @@ function createCLIParser(argv: string[]) {
577
593
  !packageJsonContent.scripts?.publish &&
578
594
  shouldCreatePackageJson;
579
595
 
596
+ /*
597
+ * Passes the array of accumulated devDeps to install through to
598
+ * the package manager. Also generates a human-readable list
599
+ * of packages it installed.
600
+ * If there are no devDeps to install, optionally runs
601
+ * the package manager's install command.
602
+ */
603
+ async function installPackages(
604
+ shouldRunInstall: boolean,
605
+ depsToInstall: string[]
606
+ ) {
607
+ //lets install the devDeps they asked for
608
+ //and run their package manager's install command if needed
609
+ if (depsToInstall.length > 0) {
610
+ const formatter = new Intl.ListFormat("en", {
611
+ style: "long",
612
+ type: "conjunction",
613
+ });
614
+ await packageManager.addDevDeps(...depsToInstall);
615
+ const versionlessPackages = depsToInstall.map((dep) =>
616
+ dep === `wrangler@${wranglerVersion}` ? "wrangler" : dep
617
+ );
618
+
619
+ logger.log(
620
+ `✨ Installed ${formatter.format(
621
+ versionlessPackages
622
+ )} into devDependencies`
623
+ );
624
+ } else {
625
+ if (shouldRunInstall) {
626
+ await packageManager.install();
627
+ }
628
+ }
629
+ }
630
+
580
631
  async function writePackageJsonScriptsAndUpdateWranglerToml(
581
632
  isWritingScripts: boolean,
582
633
  isCreatingWranglerToml: boolean,
583
634
  packagePath: string,
584
- scriptPath: string
635
+ scriptPath: string,
636
+ extraToml: TOML.JsonMap
585
637
  ) {
586
638
  if (isCreatingWranglerToml) {
587
- // rewrite wrangler.toml with main = "path/to/script"
639
+ // rewrite wrangler.toml with main = "path/to/script" and any additional config specified in `extraToml`
588
640
  const parsedWranglerToml = parseTOML(
589
641
  readFileSync(wranglerTomlDestination)
590
642
  );
591
- fs.writeFileSync(
592
- wranglerTomlDestination,
593
- TOML.stringify({
594
- name: parsedWranglerToml.name,
595
- main: scriptPath,
596
- compatibility_date: parsedWranglerToml.compatibility_date,
597
- })
598
- );
643
+ const newToml = {
644
+ name: parsedWranglerToml.name,
645
+ main: scriptPath,
646
+ compatibility_date: parsedWranglerToml.compatibility_date,
647
+ ...extraToml,
648
+ };
649
+ fs.writeFileSync(wranglerTomlDestination, TOML.stringify(newToml));
599
650
  }
600
651
  const isNamedWorker =
601
652
  isCreatingWranglerToml && path.dirname(packagePath) !== process.cwd();
@@ -611,7 +662,7 @@ function createCLIParser(argv: string[]) {
611
662
  start: isCreatingWranglerToml
612
663
  ? `wrangler dev`
613
664
  : `wrangler dev ${scriptPath}`,
614
- publish: isCreatingWranglerToml
665
+ deploy: isCreatingWranglerToml
615
666
  ? `wrangler publish`
616
667
  : `wrangler publish ${scriptPath}`,
617
668
  },
@@ -620,21 +671,21 @@ function createCLIParser(argv: string[]) {
620
671
  2
621
672
  ) + "\n"
622
673
  );
623
- logger.log(
674
+ instructions.push(
624
675
  `\nTo start developing your Worker, run \`${
625
676
  isNamedWorker ? `cd ${args.name} && ` : ""
626
677
  }npm start\``
627
678
  );
628
- logger.log(
629
- `To publish your Worker to the Internet, run \`npm run publish\``
679
+ instructions.push(
680
+ `To publish your Worker to the Internet, run \`npm run deploy\``
630
681
  );
631
682
  } else {
632
- logger.log(
683
+ instructions.push(
633
684
  `\nTo start developing your Worker, run \`npx wrangler dev\`${
634
685
  isCreatingWranglerToml ? "" : ` ${scriptPath}`
635
686
  }`
636
687
  );
637
- logger.log(
688
+ instructions.push(
638
689
  `To publish your Worker to the Internet, run \`npx wrangler publish\`${
639
690
  isCreatingWranglerToml ? "" : ` ${scriptPath}`
640
691
  }`
@@ -642,24 +693,75 @@ function createCLIParser(argv: string[]) {
642
693
  }
643
694
  }
644
695
 
696
+ async function getNewWorkerType(newWorkerFilename: string) {
697
+ return select(
698
+ `Would you like to create a Worker at ${newWorkerFilename}?`,
699
+ [
700
+ {
701
+ value: "none",
702
+ label: "None",
703
+ },
704
+ {
705
+ value: "fetch",
706
+ label: "Fetch handler",
707
+ },
708
+ {
709
+ value: "scheduled",
710
+ label: "Scheduled handler",
711
+ },
712
+ ],
713
+ 1
714
+ ) as Promise<"none" | "fetch" | "scheduled">;
715
+ }
716
+
717
+ function getNewWorkerTemplate(
718
+ lang: "js" | "ts",
719
+ workerType: "fetch" | "scheduled"
720
+ ) {
721
+ const templates = {
722
+ "js-fetch": "new-worker.js",
723
+ "js-scheduled": "new-worker-scheduled.js",
724
+ "ts-fetch": "new-worker.ts",
725
+ "ts-scheduled": "new-worker-scheduled.ts",
726
+ };
727
+
728
+ return templates[`${lang}-${workerType}`];
729
+ }
730
+
731
+ function getNewWorkerToml(
732
+ workerType: "fetch" | "scheduled"
733
+ ): TOML.JsonMap {
734
+ if (workerType === "scheduled") {
735
+ return {
736
+ triggers: {
737
+ crons: ["1 * * * *"],
738
+ },
739
+ };
740
+ }
741
+
742
+ return {};
743
+ }
744
+
645
745
  if (isTypescriptProject) {
646
746
  if (!fs.existsSync(path.join(creationDirectory, "./src/index.ts"))) {
647
- const shouldCreateSource =
648
- yesFlag ||
649
- (await confirm(
650
- `Would you like to create a Worker at ${path.relative(
651
- process.cwd(),
652
- path.join(creationDirectory, "./src/index.ts")
653
- )}?`
654
- ));
747
+ const newWorkerFilename = path.relative(
748
+ process.cwd(),
749
+ path.join(creationDirectory, "./src/index.ts")
750
+ );
751
+
752
+ const newWorkerType = yesFlag
753
+ ? "fetch"
754
+ : await getNewWorkerType(newWorkerFilename);
755
+
756
+ if (newWorkerType !== "none") {
757
+ const template = getNewWorkerTemplate("ts", newWorkerType);
655
758
 
656
- if (shouldCreateSource) {
657
759
  await mkdir(path.join(creationDirectory, "./src"), {
658
760
  recursive: true,
659
761
  });
660
762
  await writeFile(
661
763
  path.join(creationDirectory, "./src/index.ts"),
662
- readFileSync(path.join(__dirname, "../templates/new-worker.ts"))
764
+ readFileSync(path.join(__dirname, `../templates/${template}`))
663
765
  );
664
766
 
665
767
  logger.log(
@@ -673,28 +775,31 @@ function createCLIParser(argv: string[]) {
673
775
  shouldWritePackageJsonScripts,
674
776
  justCreatedWranglerToml,
675
777
  pathToPackageJson,
676
- "src/index.ts"
778
+ "src/index.ts",
779
+ getNewWorkerToml(newWorkerType)
677
780
  );
678
781
  }
679
782
  }
680
783
  } else {
681
784
  if (!fs.existsSync(path.join(creationDirectory, "./src/index.js"))) {
682
- const shouldCreateSource =
683
- yesFlag ||
684
- (await confirm(
685
- `Would you like to create a Worker at ${path.relative(
686
- process.cwd(),
687
- path.join(creationDirectory, "./src/index.js")
688
- )}?`
689
- ));
785
+ const newWorkerFilename = path.relative(
786
+ process.cwd(),
787
+ path.join(creationDirectory, "./src/index.js")
788
+ );
789
+
790
+ const newWorkerType = yesFlag
791
+ ? "fetch"
792
+ : await getNewWorkerType(newWorkerFilename);
793
+
794
+ if (newWorkerType !== "none") {
795
+ const template = getNewWorkerTemplate("js", newWorkerType);
690
796
 
691
- if (shouldCreateSource) {
692
797
  await mkdir(path.join(creationDirectory, "./src"), {
693
798
  recursive: true,
694
799
  });
695
800
  await writeFile(
696
801
  path.join(creationDirectory, "./src/index.js"),
697
- readFileSync(path.join(__dirname, "../templates/new-worker.js"))
802
+ readFileSync(path.join(__dirname, `../templates/${template}`))
698
803
  );
699
804
 
700
805
  logger.log(
@@ -708,11 +813,27 @@ function createCLIParser(argv: string[]) {
708
813
  shouldWritePackageJsonScripts,
709
814
  justCreatedWranglerToml,
710
815
  pathToPackageJson,
711
- "src/index.js"
816
+ "src/index.js",
817
+ getNewWorkerToml(newWorkerType)
712
818
  );
713
819
  }
714
820
  }
715
821
  }
822
+ // install packages as the final step of init
823
+ try {
824
+ await installPackages(shouldRunPackageManagerInstall, devDepsToInstall);
825
+ } catch (e) {
826
+ // fetching packages could fail due to loss of internet, etc
827
+ // we should let folks know we failed to fetch, but their
828
+ // workers project is still ready to go
829
+ logger.error(e instanceof Error ? e.message : e);
830
+ instructions.push(
831
+ "\n🚨 wrangler was unable to fetch your npm packages, but your project is ready to go"
832
+ );
833
+ }
834
+
835
+ // let users know what to do now
836
+ instructions.forEach((instruction) => logger.log(instruction));
716
837
  }
717
838
  );
718
839
 
@@ -723,13 +844,34 @@ function createCLIParser(argv: string[]) {
723
844
  (yargs) => {
724
845
  return yargs.option("env", {
725
846
  describe: "Perform on a specific environment",
847
+ type: "string",
726
848
  });
727
849
  },
728
- () => {
850
+ async (buildArgs) => {
729
851
  // "[DEPRECATED] 🦀 Build your project (if applicable)",
730
- throw new DeprecationError(
731
- "`wrangler build` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build for alternatives"
852
+
853
+ const envFlag = buildArgs.env ? ` --env=${buildArgs.env}` : "";
854
+ logger.log(
855
+ formatMessage({
856
+ kind: "warning",
857
+ text: "Deprecation: `wrangler build` has been deprecated.",
858
+ notes: [
859
+ {
860
+ text: "Please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build for more information.",
861
+ },
862
+ {
863
+ text: `Attempting to run \`wrangler publish --dry-run --outdir=dist${envFlag}\` for you instead:`,
864
+ },
865
+ ],
866
+ })
732
867
  );
868
+
869
+ await createCLIParser([
870
+ "publish",
871
+ "--dry-run",
872
+ "--outdir=dist",
873
+ ...(buildArgs.env ? ["--env", buildArgs.env] : []),
874
+ ]).parse();
733
875
  }
734
876
  );
735
877
 
@@ -941,92 +1083,25 @@ function createCLIParser(argv: string[]) {
941
1083
  );
942
1084
  }
943
1085
 
944
- const accountId = !args.local ? await requireAuth(config) : undefined;
945
-
946
1086
  // TODO: if worker_dev = false and no routes, then error (only for dev)
947
1087
 
948
- /**
949
- * Given something that resembles a URL,
950
- * try to extract a host from it
951
- */
952
- function getHost(urlLike: string): string | undefined {
953
- // strip leading * / *.
954
- urlLike = urlLike.replace(/^\*(\.)?/g, "");
955
-
956
- if (
957
- !(urlLike.startsWith("http://") || urlLike.startsWith("https://"))
958
- ) {
959
- urlLike = "http://" + urlLike;
960
- }
961
- return new URL(urlLike).host;
962
- }
963
-
964
- /**
965
- * Given something that resembles a host,
966
- * try to infer a zone id from it
967
- */
968
- async function getZoneId(host: string): Promise<string | undefined> {
969
- const zones = await fetchResult<{ id: string }[]>(
970
- `/zones`,
971
- {},
972
- new URLSearchParams({ name: host })
973
- );
974
- return zones[0]?.id;
975
- }
976
-
977
- // When we're given a host (in one of the above ways), we do 2 things:
978
- // - We try to extract a host from it
979
- // - We try to get a zone id from the host
980
- //
981
- // So it turns out it's particularly hard to get a 'valid' domain
982
- // from a string, so we don't even try to validate TLDs, etc.
983
- // Once we get something that looks like w.x.y.z-ish, we then try to
984
- // get a zone id for it, by lopping off subdomains until we get a hit
985
- // from the API. That's it!
986
-
987
- let zone: { host: string; id: string } | undefined;
1088
+ // Compute zone info from the `host` and `route` args and config;
1089
+ let host = args.host || config.dev.host;
1090
+ let zoneId: string | undefined;
988
1091
 
989
1092
  if (!args.local) {
990
- const hostLike =
991
- args.host ||
992
- config.dev.host ||
993
- (args.routes && args.routes[0]) ||
994
- config.route ||
995
- (config.routes && config.routes[0]);
996
-
997
- let zoneId: string | undefined =
998
- typeof hostLike === "object" && "zone_id" in hostLike
999
- ? hostLike.zone_id
1000
- : undefined;
1001
-
1002
- const host =
1003
- typeof hostLike === "string"
1004
- ? getHost(hostLike)
1005
- : typeof hostLike === "object"
1006
- ? "zone_name" in hostLike
1007
- ? getHost(hostLike.zone_name)
1008
- : getHost(hostLike.pattern)
1009
- : undefined;
1010
-
1011
- const hostPieces =
1012
- typeof host === "string" ? host.split(".") : undefined;
1013
-
1014
- while (!zoneId && hostPieces && hostPieces.length > 1) {
1015
- zoneId = await getZoneId(hostPieces.join("."));
1016
- hostPieces.shift();
1093
+ if (host) {
1094
+ zoneId = await getZoneIdFromHost(host);
1017
1095
  }
1018
-
1019
- if (host && !zoneId) {
1020
- throw new Error(`Could not find zone for ${hostLike}`);
1096
+ const routes = args.routes || config.route || config.routes;
1097
+ if (!zoneId && routes) {
1098
+ const firstRoute = Array.isArray(routes) ? routes[0] : routes;
1099
+ const zone = await getZoneForRoute(firstRoute);
1100
+ if (zone) {
1101
+ zoneId = zone.id;
1102
+ host = zone.host;
1103
+ }
1021
1104
  }
1022
-
1023
- zone =
1024
- typeof zoneId === "string" && typeof host === "string"
1025
- ? {
1026
- host,
1027
- id: zoneId,
1028
- }
1029
- : undefined;
1030
1105
  }
1031
1106
 
1032
1107
  const nodeCompat = args.nodeCompat ?? config.node_compat;
@@ -1036,12 +1111,77 @@ function createCLIParser(argv: string[]) {
1036
1111
  );
1037
1112
  }
1038
1113
 
1114
+ const bindings = {
1115
+ kv_namespaces: config.kv_namespaces?.map(
1116
+ ({ binding, preview_id, id: _id }) => {
1117
+ // In `dev`, we make folks use a separate kv namespace called
1118
+ // `preview_id` instead of `id` so that they don't
1119
+ // break production data. So here we check that a `preview_id`
1120
+ // has actually been configured.
1121
+ // This whole block of code will be obsoleted in the future
1122
+ // when we have copy-on-write for previews on edge workers.
1123
+ if (!preview_id) {
1124
+ // TODO: This error has to be a _lot_ better, ideally just asking
1125
+ // to create a preview namespace for the user automatically
1126
+ throw new Error(
1127
+ `In development, you should use a separate kv namespace than the one you'd use in production. Please create a new kv namespace with "wrangler kv:namespace create <name> --preview" and add its id as preview_id to the kv_namespace "${binding}" in your wrangler.toml`
1128
+ ); // Ugh, I really don't like this message very much
1129
+ }
1130
+ return {
1131
+ binding,
1132
+ id: preview_id,
1133
+ };
1134
+ }
1135
+ ),
1136
+ // Use a copy of combinedVars since we're modifying it later
1137
+ vars: getVarsForDev(config),
1138
+ wasm_modules: config.wasm_modules,
1139
+ text_blobs: config.text_blobs,
1140
+ data_blobs: config.data_blobs,
1141
+ durable_objects: config.durable_objects,
1142
+ r2_buckets: config.r2_buckets?.map(
1143
+ ({ binding, preview_bucket_name, bucket_name: _bucket_name }) => {
1144
+ // same idea as kv namespace preview id,
1145
+ // same copy-on-write TODO
1146
+ if (!preview_bucket_name) {
1147
+ throw new Error(
1148
+ `In development, you should use a separate r2 bucket than the one you'd use in production. Please create a new r2 bucket with "wrangler r2 bucket create <name>" and add its name as preview_bucket_name to the r2_buckets "${binding}" in your wrangler.toml`
1149
+ );
1150
+ }
1151
+ return {
1152
+ binding,
1153
+ bucket_name: preview_bucket_name,
1154
+ };
1155
+ }
1156
+ ),
1157
+ services: config.services,
1158
+ unsafe: config.unsafe?.bindings,
1159
+ };
1160
+
1161
+ // mask anything that was overridden in .dev.vars
1162
+ // so that we don't log potential secrets into the terminal
1163
+ const maskedVars = { ...bindings.vars };
1164
+ for (const key of Object.keys(maskedVars)) {
1165
+ if (maskedVars[key] !== config.vars[key]) {
1166
+ // This means it was overridden in .dev.vars
1167
+ // so let's mask it
1168
+ maskedVars[key] = "(hidden)";
1169
+ }
1170
+ }
1171
+
1172
+ // now log all available bindings into the terminal
1173
+ printBindings({
1174
+ ...bindings,
1175
+ vars: maskedVars,
1176
+ });
1177
+
1039
1178
  const { waitUntilExit } = render(
1040
1179
  <Dev
1041
1180
  name={getScriptName(args, config)}
1042
1181
  entry={entry}
1043
1182
  env={args.env}
1044
- zone={zone}
1183
+ zone={zoneId}
1184
+ host={host}
1045
1185
  rules={getRules(config)}
1046
1186
  legacyEnv={isLegacyEnv(config)}
1047
1187
  minify={args.minify ?? config.minify}
@@ -1056,7 +1196,7 @@ function createCLIParser(argv: string[]) {
1056
1196
  enableLocalPersistence={
1057
1197
  args["experimental-enable-local-persistence"] || false
1058
1198
  }
1059
- accountId={accountId}
1199
+ accountId={config.account_id}
1060
1200
  assetPaths={getAssetPaths(
1061
1201
  config,
1062
1202
  args.site,
@@ -1081,51 +1221,7 @@ function createCLIParser(argv: string[]) {
1081
1221
  args["compatibility-flags"] || config.compatibility_flags
1082
1222
  }
1083
1223
  usageModel={config.usage_model}
1084
- bindings={{
1085
- kv_namespaces: config.kv_namespaces?.map(
1086
- ({ binding, preview_id, id: _id }) => {
1087
- // In `dev`, we make folks use a separate kv namespace called
1088
- // `preview_id` instead of `id` so that they don't
1089
- // break production data. So here we check that a `preview_id`
1090
- // has actually been configured.
1091
- // This whole block of code will be obsoleted in the future
1092
- // when we have copy-on-write for previews on edge workers.
1093
- if (!preview_id) {
1094
- // TODO: This error has to be a _lot_ better, ideally just asking
1095
- // to create a preview namespace for the user automatically
1096
- throw new Error(
1097
- `In development, you should use a separate kv namespace than the one you'd use in production. Please create a new kv namespace with "wrangler kv:namespace create <name> --preview" and add its id as preview_id to the kv_namespace "${binding}" in your wrangler.toml`
1098
- ); // Ugh, I really don't like this message very much
1099
- }
1100
- return {
1101
- binding,
1102
- id: preview_id,
1103
- };
1104
- }
1105
- ),
1106
- vars: getVarsForDev(config),
1107
- wasm_modules: config.wasm_modules,
1108
- text_blobs: config.text_blobs,
1109
- data_blobs: config.data_blobs,
1110
- durable_objects: config.durable_objects,
1111
- r2_buckets: config.r2_buckets?.map(
1112
- ({ binding, preview_bucket_name, bucket_name: _bucket_name }) => {
1113
- // same idea as kv namespace preview id,
1114
- // same copy-on-write TODO
1115
- if (!preview_bucket_name) {
1116
- throw new Error(
1117
- `In development, you should use a separate r2 bucket than the one you'd use in production. Please create a new r2 bucket with "wrangler r2 bucket create <name>" and add its name as preview_bucket_name to the r2_buckets "${binding}" in your wrangler.toml`
1118
- );
1119
- }
1120
- return {
1121
- binding,
1122
- bucket_name: preview_bucket_name,
1123
- };
1124
- }
1125
- ),
1126
- services: config.services,
1127
- unsafe: config.unsafe?.bindings,
1128
- }}
1224
+ bindings={bindings}
1129
1225
  crons={config.triggers.crons}
1130
1226
  />
1131
1227
  );
@@ -1286,6 +1382,7 @@ function createCLIParser(argv: string[]) {
1286
1382
  args.siteInclude,
1287
1383
  args.siteExclude
1288
1384
  );
1385
+
1289
1386
  await publish({
1290
1387
  config,
1291
1388
  accountId,
@@ -1513,6 +1610,7 @@ function createCLIParser(argv: string[]) {
1513
1610
  rules={getRules(config)}
1514
1611
  env={args.env}
1515
1612
  zone={undefined}
1613
+ host={undefined}
1516
1614
  legacyEnv={isLegacyEnv(config)}
1517
1615
  build={config.build || {}}
1518
1616
  minify={undefined}
@@ -2396,14 +2494,7 @@ function createCLIParser(argv: string[]) {
2396
2494
  }
2397
2495
 
2398
2496
  const accountId = await requireAuth(config);
2399
- await putKVBulkKeyValue(
2400
- accountId,
2401
- namespaceId,
2402
- content,
2403
- (index, total) => {
2404
- logger.log(`Uploaded ${index} of ${total}.`);
2405
- }
2406
- );
2497
+ await putKVBulkKeyValue(accountId, namespaceId, content);
2407
2498
 
2408
2499
  logger.log("Success!");
2409
2500
  }
@@ -2493,14 +2584,7 @@ function createCLIParser(argv: string[]) {
2493
2584
 
2494
2585
  const accountId = await requireAuth(config);
2495
2586
 
2496
- await deleteKVBulkKeyValue(
2497
- accountId,
2498
- namespaceId,
2499
- content,
2500
- (index, total) => {
2501
- logger.log(`Deleted ${index} of ${total}.`);
2502
- }
2503
- );
2587
+ await deleteKVBulkKeyValue(accountId, namespaceId, content);
2504
2588
 
2505
2589
  logger.log("Success!");
2506
2590
  }
@@ -2682,14 +2766,14 @@ export async function main(argv: string[]): Promise<void> {
2682
2766
  await createCLIParser([...argv, "--help"]).parse();
2683
2767
  } else if (e instanceof ParseError) {
2684
2768
  e.notes.push({
2685
- text: "\nIf you think this is a bug, please open an issue at: https://github.com/cloudflare/wrangler2/issues/new",
2769
+ text: "\nIf you think this is a bug, please open an issue at: https://github.com/cloudflare/wrangler2/issues/new/choose",
2686
2770
  });
2687
- logger.error(formatMessage(e));
2771
+ logger.log(formatMessage(e));
2688
2772
  } else {
2689
2773
  logger.error(e instanceof Error ? e.message : e);
2690
2774
  logger.log(
2691
2775
  `${fgGreenColor}%s${resetColor}`,
2692
- "If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2776
+ "If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
2693
2777
  );
2694
2778
  }
2695
2779
  throw e;