wrangler 0.0.0-e95bea2 → 0.0.0-ea8e701

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 (55) hide show
  1. package/README.md +3 -3
  2. package/bin/wrangler.js +10 -1
  3. package/miniflare-dist/index.mjs +79 -0
  4. package/miniflare-dist/index.mjs.map +7 -0
  5. package/package.json +7 -6
  6. package/pages/functions/filepath-routing.test.ts +125 -25
  7. package/pages/functions/filepath-routing.ts +6 -3
  8. package/src/__tests__/configuration.test.ts +826 -223
  9. package/src/__tests__/dev.test.tsx +145 -9
  10. package/src/__tests__/guess-worker-format.test.ts +26 -1
  11. package/src/__tests__/helpers/mock-account-id.ts +4 -0
  12. package/src/__tests__/helpers/mock-kv.ts +9 -16
  13. package/src/__tests__/helpers/mock-oauth-flow.ts +178 -0
  14. package/src/__tests__/helpers/run-in-tmp.ts +3 -0
  15. package/src/__tests__/index.test.ts +9 -13
  16. package/src/__tests__/jest.setup.ts +5 -0
  17. package/src/__tests__/kv.test.ts +43 -71
  18. package/src/__tests__/pages.test.ts +48 -10
  19. package/src/__tests__/publish.test.ts +1456 -327
  20. package/src/__tests__/r2.test.ts +4 -4
  21. package/src/__tests__/tail.test.ts +78 -4
  22. package/src/__tests__/user.test.ts +83 -0
  23. package/src/__tests__/whoami.test.tsx +16 -7
  24. package/src/bundle.ts +15 -2
  25. package/src/cfetch/internal.ts +9 -5
  26. package/src/config/README.md +6 -6
  27. package/src/config/config.ts +17 -78
  28. package/src/config/environment.ts +67 -1
  29. package/src/config/index.ts +13 -3
  30. package/src/config/validation-helpers.ts +177 -11
  31. package/src/config/validation.ts +305 -100
  32. package/src/dev/dev.tsx +76 -41
  33. package/src/dev/local.tsx +105 -114
  34. package/src/dev/remote.tsx +2 -0
  35. package/src/dev/use-esbuild.ts +4 -0
  36. package/src/entry.ts +103 -6
  37. package/src/index.tsx +251 -189
  38. package/src/intl-polyfill.d.ts +139 -0
  39. package/src/{kv/index.tsx → kv.ts} +8 -28
  40. package/src/miniflare-cli/README.md +30 -0
  41. package/src/miniflare-cli/enum-keys.ts +17 -0
  42. package/src/miniflare-cli/index.ts +37 -0
  43. package/src/module-collection.ts +58 -53
  44. package/src/pages.tsx +26 -10
  45. package/src/proxy.ts +5 -3
  46. package/src/publish.ts +17 -21
  47. package/src/sites.tsx +67 -25
  48. package/src/tail/index.ts +1 -1
  49. package/src/tail/printing.ts +2 -2
  50. package/src/user.tsx +161 -81
  51. package/wrangler-dist/cli.js +3418 -1437
  52. package/wrangler-dist/cli.js.map +3 -3
  53. package/src/__tests__/dev2.test.tsx +0 -152
  54. package/src/__tests__/helpers/mock-user.ts +0 -27
  55. package/src/__tests__/logout.test.ts +0 -50
package/src/index.tsx CHANGED
@@ -3,11 +3,13 @@ import { writeFile, mkdir } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { setTimeout } from "node:timers/promises";
5
5
  import TOML from "@iarna/toml";
6
+ import chalk from "chalk";
6
7
  import { findUp } from "find-up";
7
8
  import getPort from "get-port";
8
9
  import { render } from "ink";
9
10
  import React from "react";
10
11
  import onExit from "signal-exit";
12
+ import supportsColor from "supports-color";
11
13
  import makeCLI from "yargs";
12
14
  import { version as wranglerVersion } from "../package.json";
13
15
  import { fetchResult } from "./cfetch";
@@ -30,7 +32,7 @@ import {
30
32
  unexpectedKeyValueProps,
31
33
  } from "./kv";
32
34
  import { getPackageManager } from "./package-manager";
33
- import { pages } from "./pages";
35
+ import { pages, pagesBetaWarning } from "./pages";
34
36
  import { formatMessage, ParseError, parseJSON, readFileSync } from "./parse";
35
37
  import publish from "./publish";
36
38
  import { createR2Bucket, deleteR2Bucket, listR2Buckets } from "./r2";
@@ -45,7 +47,6 @@ import {
45
47
  login,
46
48
  logout,
47
49
  listScopes,
48
- initialise as initialiseUserConfig,
49
50
  loginOrRefreshIfRequired,
50
51
  getAccountId,
51
52
  validateScopeKeys,
@@ -82,25 +83,53 @@ ${TOML.stringify({ rules: config.build.upload.rules })}`
82
83
  return rules;
83
84
  }
84
85
 
85
- function isLegacyEnv(args: unknown, config: Config): boolean {
86
- return (
87
- (args as { "legacy-env": boolean | undefined })["legacy-env"] ??
88
- config.legacy_env
86
+ function printWranglerBanner() {
87
+ // Let's not print this in tests
88
+ if (typeof jest !== "undefined") {
89
+ return;
90
+ }
91
+ const text = ` ⛅️ wrangler ${wranglerVersion} `;
92
+
93
+ console.log(
94
+ text +
95
+ "\n" +
96
+ (supportsColor.stdout
97
+ ? chalk.hex("#FF8800")("-".repeat(text.length))
98
+ : "-".repeat(text.length))
89
99
  );
90
100
  }
91
101
 
102
+ function isLegacyEnv(args: unknown, config: Config): boolean {
103
+ return config.legacy_env;
104
+ }
105
+
92
106
  function getScriptName(
93
107
  args: { name: string | undefined; env: string | undefined },
94
108
  config: Config
95
109
  ): string | undefined {
96
- const shortScriptName = args.name ?? config.name;
97
- if (!shortScriptName) {
98
- return;
110
+ if (args.name && isLegacyEnv(args, config) && args.env) {
111
+ throw new CommandLineArgsError(
112
+ "In legacy environment mode you cannot use --name and --env together. If you want to specify a Worker name for a specific environment you can add the following to your wrangler.toml config:" +
113
+ `
114
+ [env.${args.env}]
115
+ name = "${args.name}"
116
+ `
117
+ );
99
118
  }
100
119
 
101
- return isLegacyEnv(args, config)
102
- ? `${shortScriptName}${args.env ? `-${args.env}` : ""}`
103
- : shortScriptName;
120
+ return args.name ?? config.name;
121
+ }
122
+
123
+ /**
124
+ * Alternative to the getScriptName() because special Legacy cases allowed "name", and "env" together in Wrangler1
125
+ */
126
+ function getLegacyScriptName(
127
+ args: { name: string | undefined; env: string | undefined },
128
+ config: Config
129
+ ) {
130
+ return args.name && args.env && isLegacyEnv(args, config)
131
+ ? `${args.name}-${args.env}`
132
+ : args.name ?? config.name;
104
133
  }
105
134
 
106
135
  /**
@@ -190,6 +219,7 @@ class DeprecationError extends Error {
190
219
 
191
220
  export async function main(argv: string[]): Promise<void> {
192
221
  const wrangler = makeCLI(argv)
222
+ .strict()
193
223
  // We handle errors ourselves in a try-catch around `yargs.parse`.
194
224
  // If you want the "help info" to be displayed then throw an instance of `CommandLineArgsError`.
195
225
  // Otherwise we just log the error that was thrown without any "help info".
@@ -268,6 +298,12 @@ export async function main(argv: string[]): Promise<void> {
268
298
  describe: "The name of your worker",
269
299
  type: "string",
270
300
  })
301
+ .option("type", {
302
+ describe: "The type of worker to create",
303
+ type: "string",
304
+ choices: ["rust", "javascript", "webpack"],
305
+ deprecated: true,
306
+ })
271
307
  .option("yes", {
272
308
  describe: 'Answer "yes" to any prompts for new projects',
273
309
  type: "boolean",
@@ -275,7 +311,8 @@ export async function main(argv: string[]): Promise<void> {
275
311
  });
276
312
  },
277
313
  async (args) => {
278
- if ("type" in args) {
314
+ printWranglerBanner();
315
+ if (args.type) {
279
316
  let message = "The --type option is no longer supported.";
280
317
  if (args.type === "webpack") {
281
318
  message +=
@@ -586,76 +623,6 @@ export async function main(argv: string[]): Promise<void> {
586
623
  }
587
624
  );
588
625
 
589
- // login
590
- wrangler.command(
591
- // this needs scopes as an option?
592
- "login",
593
- false, // we don't need to show this in the menu
594
- // "🔓 Login to Cloudflare",
595
- (yargs) => {
596
- // TODO: This needs some copy editing
597
- // I mean, this entire app does, but this too.
598
- return yargs
599
- .option("scopes-list", {
600
- describe: "List all the available OAuth scopes with descriptions",
601
- })
602
- .option("scopes", {
603
- describe: "Pick the set of applicable OAuth scopes when logging in",
604
- array: true,
605
- type: "string",
606
- });
607
-
608
- // TODO: scopes
609
- },
610
- async (args) => {
611
- if (args["scopes-list"]) {
612
- listScopes();
613
- return;
614
- }
615
- if (args.scopes) {
616
- if (args.scopes.length === 0) {
617
- // don't allow no scopes to be passed, that would be weird
618
- listScopes();
619
- return;
620
- }
621
- if (!validateScopeKeys(args.scopes)) {
622
- throw new CommandLineArgsError(
623
- `One of ${args.scopes} is not a valid authentication scope. Run "wrangler login --list-scopes" to see the valid scopes.`
624
- );
625
- }
626
- await login({ scopes: args.scopes });
627
- return;
628
- }
629
- await login();
630
-
631
- // TODO: would be nice if it optionally saved login
632
- // credentials inside node_modules/.cache or something
633
- // this way you could have multiple users on a single machine
634
- }
635
- );
636
-
637
- // logout
638
- wrangler.command(
639
- // this needs scopes as an option?
640
- "logout",
641
- false, // we don't need to show this in the menu
642
- // "🚪 Logout from Cloudflare",
643
- () => {},
644
- async () => {
645
- await logout();
646
- }
647
- );
648
-
649
- // whoami
650
- wrangler.command(
651
- "whoami",
652
- "🕵️ Retrieve your user info and test your auth config",
653
- () => {},
654
- async () => {
655
- await whoami();
656
- }
657
- );
658
-
659
626
  // config
660
627
  wrangler.command(
661
628
  "config",
@@ -664,7 +631,7 @@ export async function main(argv: string[]): Promise<void> {
664
631
  () => {
665
632
  // "🕵️ Authenticate Wrangler with a Cloudflare API Token",
666
633
  throw new DeprecationError(
667
- "`wrangler config` has been deprecated, please refer to TODO://some/path for alternatives"
634
+ "`wrangler config` has been deprecated, please refer to https://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#config for alternatives"
668
635
  );
669
636
  }
670
637
  );
@@ -690,6 +657,7 @@ export async function main(argv: string[]): Promise<void> {
690
657
  .option("env", {
691
658
  describe: "Perform on a specific environment",
692
659
  type: "string",
660
+ alias: "e",
693
661
  })
694
662
  .option("compatibility-date", {
695
663
  describe: "Date to use for compatibility checks",
@@ -706,9 +674,8 @@ export async function main(argv: string[]): Promise<void> {
706
674
  default: true,
707
675
  })
708
676
  .option("ip", {
709
- describe: "IP address to listen on",
677
+ describe: "IP address to listen on, defaults to `localhost`",
710
678
  type: "string",
711
- default: "127.0.0.1",
712
679
  })
713
680
  .option("port", {
714
681
  describe: "Port to listen on",
@@ -765,6 +732,10 @@ export async function main(argv: string[]): Promise<void> {
765
732
  describe: "The function that is called for each JSX fragment",
766
733
  type: "string",
767
734
  })
735
+ .option("tsconfig", {
736
+ describe: "Path to a custom tsconfig.json file",
737
+ type: "string",
738
+ })
768
739
  .option("local", {
769
740
  alias: "l",
770
741
  describe: "Run on my machine",
@@ -777,10 +748,11 @@ export async function main(argv: string[]): Promise<void> {
777
748
  });
778
749
  },
779
750
  async (args) => {
780
- const config = readConfig(
751
+ printWranglerBanner();
752
+ const configPath =
781
753
  (args.config as ConfigPath) ||
782
- (args.script && findWranglerToml(path.dirname(args.script)))
783
- );
754
+ (args.script && findWranglerToml(path.dirname(args.script)));
755
+ const config = readConfig(configPath, args);
784
756
  const entry = await getEntry(args, config, "dev");
785
757
 
786
758
  if (args["experimental-public"]) {
@@ -836,16 +808,6 @@ export async function main(argv: string[]): Promise<void> {
836
808
  return zones[0]?.id;
837
809
  }
838
810
 
839
- const environments = config.env ?? {};
840
- const envRootObj = args.env ? environments[args.env] || {} : config;
841
-
842
- const hostLike =
843
- args.host ||
844
- config.dev.host ||
845
- (args.routes && args.routes[0]) ||
846
- envRootObj.route ||
847
- (envRootObj.routes && envRootObj.routes[0]);
848
-
849
811
  // When we're given a host (in one of the above ways), we do 2 things:
850
812
  // - We try to extract a host from it
851
813
  // - We try to get a zone id from the host
@@ -856,28 +818,37 @@ export async function main(argv: string[]): Promise<void> {
856
818
  // get a zone id for it, by lopping off subdomains until we get a hit
857
819
  // from the API. That's it!
858
820
 
859
- const host = typeof hostLike === "string" ? getHost(hostLike) : undefined;
860
-
861
- let zoneId: string | undefined;
862
- const hostPieces = typeof host === "string" ? host.split(".") : undefined;
863
-
864
- while (hostPieces && hostPieces.length > 1) {
865
- zoneId = await getZoneId(hostPieces.join("."));
866
- if (zoneId) break;
867
- hostPieces.shift();
868
- }
869
- if (host && !zoneId) {
870
- throw new Error(`Could not find zone for ${hostLike}`);
821
+ let zone: { host: string; id: string } | undefined;
822
+
823
+ if (!args.local) {
824
+ const hostLike =
825
+ args.host ||
826
+ config.dev.host ||
827
+ (args.routes && args.routes[0]) ||
828
+ config.route ||
829
+ (config.routes && config.routes[0]);
830
+ const host =
831
+ typeof hostLike === "string" ? getHost(hostLike) : undefined;
832
+ let zoneId: string | undefined;
833
+ const hostPieces =
834
+ typeof host === "string" ? host.split(".") : undefined;
835
+ while (hostPieces && hostPieces.length > 1) {
836
+ zoneId = await getZoneId(hostPieces.join("."));
837
+ if (zoneId) break;
838
+ hostPieces.shift();
839
+ }
840
+ if (host && !zoneId) {
841
+ throw new Error(`Could not find zone for ${hostLike}`);
842
+ }
843
+ zone =
844
+ typeof zoneId === "string" && typeof host === "string"
845
+ ? {
846
+ host,
847
+ id: zoneId,
848
+ }
849
+ : undefined;
871
850
  }
872
851
 
873
- const zone =
874
- typeof zoneId === "string" && typeof host === "string"
875
- ? {
876
- host,
877
- id: zoneId,
878
- }
879
- : undefined;
880
-
881
852
  const { waitUntilExit } = render(
882
853
  <Dev
883
854
  name={getScriptName(args, config)}
@@ -886,10 +857,11 @@ export async function main(argv: string[]): Promise<void> {
886
857
  zone={zone}
887
858
  rules={getRules(config)}
888
859
  legacyEnv={isLegacyEnv(args, config)}
889
- buildCommand={config.build || {}}
860
+ build={config.build || {}}
890
861
  initialMode={args.local ? "local" : "remote"}
891
- jsxFactory={args["jsx-factory"] || envRootObj?.jsx_factory}
892
- jsxFragment={args["jsx-fragment"] || envRootObj?.jsx_fragment}
862
+ jsxFactory={args["jsx-factory"] || config.jsx_factory}
863
+ jsxFragment={args["jsx-fragment"] || config.jsx_fragment}
864
+ tsconfig={args.tsconfig ?? config.tsconfig}
893
865
  upstreamProtocol={upstreamProtocol}
894
866
  localProtocol={
895
867
  // The typings are not quite clever enough to handle element accesses, only property accesses,
@@ -910,6 +882,7 @@ export async function main(argv: string[]): Promise<void> {
910
882
  port={
911
883
  args.port || config.dev?.port || (await getPort({ port: 8787 }))
912
884
  }
885
+ ip={args.ip || config.dev.ip}
913
886
  inspectorPort={
914
887
  args["inspector-port"] ?? (await getPort({ port: 9229 }))
915
888
  }
@@ -923,9 +896,9 @@ export async function main(argv: string[]): Promise<void> {
923
896
  (args["compatibility-flags"] as string[]) ||
924
897
  config.compatibility_flags
925
898
  }
926
- usageModel={envRootObj.usage_model}
899
+ usageModel={config.usage_model}
927
900
  bindings={{
928
- kv_namespaces: envRootObj.kv_namespaces?.map(
901
+ kv_namespaces: config.kv_namespaces?.map(
929
902
  ({ binding, preview_id, id: _id }) => {
930
903
  // In `dev`, we make folks use a separate kv namespace called
931
904
  // `preview_id` instead of `id` so that they don't
@@ -946,12 +919,12 @@ export async function main(argv: string[]): Promise<void> {
946
919
  };
947
920
  }
948
921
  ),
949
- vars: envRootObj.vars,
922
+ vars: config.vars,
950
923
  wasm_modules: config.wasm_modules,
951
924
  text_blobs: config.text_blobs,
952
- durable_objects: envRootObj.durable_objects,
953
- r2_buckets: envRootObj.r2_buckets,
954
- unsafe: envRootObj.unsafe?.bindings,
925
+ durable_objects: config.durable_objects,
926
+ r2_buckets: config.r2_buckets,
927
+ unsafe: config.unsafe?.bindings,
955
928
  }}
956
929
  />
957
930
  );
@@ -968,6 +941,7 @@ export async function main(argv: string[]): Promise<void> {
968
941
  .option("env", {
969
942
  type: "string",
970
943
  describe: "Perform on a specific environment",
944
+ alias: "e",
971
945
  })
972
946
  .positional("script", {
973
947
  describe: "The path to an entry point for your worker",
@@ -1032,9 +1006,14 @@ export async function main(argv: string[]): Promise<void> {
1032
1006
  .option("jsx-fragment", {
1033
1007
  describe: "The function that is called for each JSX fragment",
1034
1008
  type: "string",
1009
+ })
1010
+ .option("tsconfig", {
1011
+ describe: "Path to a custom tsconfig.json file",
1012
+ type: "string",
1035
1013
  });
1036
1014
  },
1037
1015
  async (args) => {
1016
+ printWranglerBanner();
1038
1017
  if (args["experimental-public"]) {
1039
1018
  console.warn(
1040
1019
  "🚨 The --experimental-public field is experimental and will change in the future."
@@ -1046,10 +1025,10 @@ export async function main(argv: string[]): Promise<void> {
1046
1025
  );
1047
1026
  }
1048
1027
 
1049
- const config = readConfig(
1028
+ const configPath =
1050
1029
  (args.config as ConfigPath) ||
1051
- (args.script && findWranglerToml(path.dirname(args.script)))
1052
- );
1030
+ (args.script && findWranglerToml(path.dirname(args.script)));
1031
+ const config = readConfig(configPath, args);
1053
1032
  const entry = await getEntry(args, config, "publish");
1054
1033
 
1055
1034
  if (args.latest) {
@@ -1080,6 +1059,7 @@ export async function main(argv: string[]): Promise<void> {
1080
1059
  triggers: args.triggers,
1081
1060
  jsxFactory: args["jsx-factory"],
1082
1061
  jsxFragment: args["jsx-fragment"],
1062
+ tsconfig: args.tsconfig,
1083
1063
  routes: args.routes,
1084
1064
  assetPaths,
1085
1065
  legacyEnv: isLegacyEnv(args, config),
@@ -1101,7 +1081,7 @@ export async function main(argv: string[]): Promise<void> {
1101
1081
  })
1102
1082
  // TODO: auto-detect if this should be json or pretty based on atty
1103
1083
  .option("format", {
1104
- default: "json",
1084
+ default: "pretty",
1105
1085
  choices: ["json", "pretty"],
1106
1086
  describe: "The format of log entries",
1107
1087
  })
@@ -1136,6 +1116,7 @@ export async function main(argv: string[]): Promise<void> {
1136
1116
  .option("env", {
1137
1117
  type: "string",
1138
1118
  describe: "Perform on a specific environment",
1119
+ alias: "e",
1139
1120
  })
1140
1121
  .option("debug", {
1141
1122
  type: "boolean",
@@ -1147,9 +1128,12 @@ export async function main(argv: string[]): Promise<void> {
1147
1128
  );
1148
1129
  },
1149
1130
  async (args) => {
1150
- const config = readConfig(args.config as ConfigPath);
1131
+ if (args.format === "pretty") {
1132
+ printWranglerBanner();
1133
+ }
1134
+ const config = readConfig(args.config as ConfigPath, args);
1151
1135
 
1152
- const scriptName = getScriptName(args, config);
1136
+ const scriptName = getLegacyScriptName(args, config);
1153
1137
 
1154
1138
  if (!scriptName) {
1155
1139
  throw new Error("Missing script name");
@@ -1260,14 +1244,11 @@ export async function main(argv: string[]): Promise<void> {
1260
1244
  "***************************************************\n"
1261
1245
  );
1262
1246
 
1263
- const config = readConfig(args.config as ConfigPath);
1247
+ const config = readConfig(args.config as ConfigPath, args);
1264
1248
  const entry = await getEntry({}, config, "dev");
1265
1249
 
1266
1250
  const accountId = await requireAuth(config);
1267
1251
 
1268
- const environments = config.env ?? {};
1269
- const envRootObj = args.env ? environments[args.env] || {} : config;
1270
-
1271
1252
  const { waitUntilExit } = render(
1272
1253
  <Dev
1273
1254
  name={config.name}
@@ -1276,16 +1257,18 @@ export async function main(argv: string[]): Promise<void> {
1276
1257
  env={args.env}
1277
1258
  zone={undefined}
1278
1259
  legacyEnv={isLegacyEnv(args, config)}
1279
- buildCommand={config.build || {}}
1260
+ build={config.build || {}}
1280
1261
  initialMode={args.local ? "local" : "remote"}
1281
- jsxFactory={envRootObj?.jsx_factory}
1282
- jsxFragment={envRootObj?.jsx_fragment}
1262
+ jsxFactory={config.jsx_factory}
1263
+ jsxFragment={config.jsx_fragment}
1264
+ tsconfig={config.tsconfig}
1283
1265
  upstreamProtocol={config.dev.upstream_protocol}
1284
1266
  localProtocol={config.dev.local_protocol}
1285
1267
  enableLocalPersistence={false}
1286
1268
  accountId={accountId}
1287
1269
  assetPaths={undefined}
1288
1270
  port={config.dev?.port}
1271
+ ip={config.dev.ip}
1289
1272
  public={undefined}
1290
1273
  compatibilityDate={
1291
1274
  config.compatibility_date ||
@@ -1297,7 +1280,7 @@ export async function main(argv: string[]): Promise<void> {
1297
1280
  }
1298
1281
  usageModel={config.usage_model}
1299
1282
  bindings={{
1300
- kv_namespaces: envRootObj.kv_namespaces?.map(
1283
+ kv_namespaces: config.kv_namespaces?.map(
1301
1284
  ({ binding, preview_id, id: _id }) => {
1302
1285
  // In `dev`, we make folks use a separate kv namespace called
1303
1286
  // `preview_id` instead of `id` so that they don't
@@ -1318,12 +1301,12 @@ export async function main(argv: string[]): Promise<void> {
1318
1301
  };
1319
1302
  }
1320
1303
  ),
1321
- vars: envRootObj.vars,
1304
+ vars: config.vars,
1322
1305
  wasm_modules: config.wasm_modules,
1323
1306
  text_blobs: config.text_blobs,
1324
- durable_objects: envRootObj.durable_objects,
1325
- r2_buckets: envRootObj.r2_buckets,
1326
- unsafe: envRootObj.unsafe?.bindings,
1307
+ durable_objects: config.durable_objects,
1308
+ r2_buckets: config.r2_buckets,
1309
+ unsafe: config.unsafe?.bindings,
1327
1310
  }}
1328
1311
  inspectorPort={await getPort({ port: 9229 })}
1329
1312
  />
@@ -1371,7 +1354,7 @@ export async function main(argv: string[]): Promise<void> {
1371
1354
  }
1372
1355
  )
1373
1356
  .command(
1374
- "delete",
1357
+ "delete [id]",
1375
1358
  "Delete a route associated with a zone",
1376
1359
  (yargs) => {
1377
1360
  return yargs
@@ -1417,7 +1400,7 @@ export async function main(argv: string[]): Promise<void> {
1417
1400
  },
1418
1401
  () => {
1419
1402
  throw new DeprecationError(
1420
- "`wrangler subdomain` has been deprecated, please refer to TODO://some/path for alternatives"
1403
+ "`wrangler subdomain` has been deprecated, please refer to https://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#subdomain for alternatives"
1421
1404
  );
1422
1405
  }
1423
1406
  );
@@ -1446,12 +1429,14 @@ export async function main(argv: string[]): Promise<void> {
1446
1429
  type: "string",
1447
1430
  describe:
1448
1431
  "Binds the secret to the Worker of the specific environment",
1432
+ alias: "e",
1449
1433
  });
1450
1434
  },
1451
1435
  async (args) => {
1452
- const config = readConfig(args.config as ConfigPath);
1436
+ printWranglerBanner();
1437
+ const config = readConfig(args.config as ConfigPath, args);
1453
1438
 
1454
- const scriptName = getScriptName(args, config);
1439
+ const scriptName = getLegacyScriptName(args, config);
1455
1440
  if (!scriptName) {
1456
1441
  throw new Error("Missing script name");
1457
1442
  }
@@ -1548,6 +1533,7 @@ export async function main(argv: string[]): Promise<void> {
1548
1533
  "delete <key>",
1549
1534
  "Delete a secret variable from a script",
1550
1535
  (yargs) => {
1536
+ printWranglerBanner();
1551
1537
  return yargs
1552
1538
  .positional("key", {
1553
1539
  describe: "The variable name to be accessible in the script",
@@ -1561,12 +1547,13 @@ export async function main(argv: string[]): Promise<void> {
1561
1547
  type: "string",
1562
1548
  describe:
1563
1549
  "Binds the secret to the Worker of the specific environment",
1550
+ alias: "e",
1564
1551
  });
1565
1552
  },
1566
1553
  async (args) => {
1567
- const config = readConfig(args.config as ConfigPath);
1554
+ const config = readConfig(args.config as ConfigPath, args);
1568
1555
 
1569
- const scriptName = getScriptName(args, config);
1556
+ const scriptName = getLegacyScriptName(args, config);
1570
1557
  if (!scriptName) {
1571
1558
  throw new Error("Missing script name");
1572
1559
  }
@@ -1611,12 +1598,13 @@ export async function main(argv: string[]): Promise<void> {
1611
1598
  type: "string",
1612
1599
  describe:
1613
1600
  "Binds the secret to the Worker of the specific environment.",
1601
+ alias: "e",
1614
1602
  });
1615
1603
  },
1616
1604
  async (args) => {
1617
- const config = readConfig(args.config as ConfigPath);
1605
+ const config = readConfig(args.config as ConfigPath, args);
1618
1606
 
1619
- const scriptName = getScriptName(args, config);
1607
+ const scriptName = getLegacyScriptName(args, config);
1620
1608
  if (!scriptName) {
1621
1609
  throw new Error("Missing script name");
1622
1610
  }
@@ -1655,6 +1643,7 @@ export async function main(argv: string[]): Promise<void> {
1655
1643
  .option("env", {
1656
1644
  type: "string",
1657
1645
  describe: "Perform on a specific environment",
1646
+ alias: "e",
1658
1647
  })
1659
1648
  .option("preview", {
1660
1649
  type: "boolean",
@@ -1662,12 +1651,7 @@ export async function main(argv: string[]): Promise<void> {
1662
1651
  });
1663
1652
  },
1664
1653
  async (args) => {
1665
- if (args._.length > 2) {
1666
- const extraArgs = args._.slice(2).join(" ");
1667
- throw new CommandLineArgsError(
1668
- `Unexpected additional positional arguments "${extraArgs}".`
1669
- );
1670
- }
1654
+ printWranglerBanner();
1671
1655
 
1672
1656
  if (!isValidNamespaceBinding(args.namespace)) {
1673
1657
  throw new CommandLineArgsError(
@@ -1675,7 +1659,7 @@ export async function main(argv: string[]): Promise<void> {
1675
1659
  );
1676
1660
  }
1677
1661
 
1678
- const config = readConfig(args.config as ConfigPath);
1662
+ const config = readConfig(args.config as ConfigPath, args);
1679
1663
  if (!config.name) {
1680
1664
  console.warn(
1681
1665
  "No configured name present, using `worker` as a prefix for the title"
@@ -1712,7 +1696,7 @@ export async function main(argv: string[]): Promise<void> {
1712
1696
  "Outputs a list of all KV namespaces associated with your account id.",
1713
1697
  {},
1714
1698
  async (args) => {
1715
- const config = readConfig(args.config as ConfigPath);
1699
+ const config = readConfig(args.config as ConfigPath, args);
1716
1700
 
1717
1701
  const accountId = await requireAuth(config);
1718
1702
 
@@ -1740,6 +1724,7 @@ export async function main(argv: string[]): Promise<void> {
1740
1724
  .option("env", {
1741
1725
  type: "string",
1742
1726
  describe: "Perform on a specific environment",
1727
+ alias: "e",
1743
1728
  })
1744
1729
  .option("preview", {
1745
1730
  type: "boolean",
@@ -1747,7 +1732,8 @@ export async function main(argv: string[]): Promise<void> {
1747
1732
  });
1748
1733
  },
1749
1734
  async (args) => {
1750
- const config = readConfig(args.config as ConfigPath);
1735
+ printWranglerBanner();
1736
+ const config = readConfig(args.config as ConfigPath, args);
1751
1737
 
1752
1738
  let id;
1753
1739
  try {
@@ -1820,6 +1806,7 @@ export async function main(argv: string[]): Promise<void> {
1820
1806
  .option("env", {
1821
1807
  type: "string",
1822
1808
  describe: "Perform on a specific environment",
1809
+ alias: "e",
1823
1810
  })
1824
1811
  .option("preview", {
1825
1812
  type: "boolean",
@@ -1841,7 +1828,8 @@ export async function main(argv: string[]): Promise<void> {
1841
1828
  .check(demandOneOfOption("value", "path"));
1842
1829
  },
1843
1830
  async ({ key, ttl, expiration, ...args }) => {
1844
- const config = readConfig(args.config as ConfigPath);
1831
+ printWranglerBanner();
1832
+ const config = readConfig(args.config as ConfigPath, args);
1845
1833
  const namespaceId = getNamespaceId(args, config);
1846
1834
  // One of `args.path` and `args.value` must be defined
1847
1835
  const value = args.path
@@ -1886,6 +1874,7 @@ export async function main(argv: string[]): Promise<void> {
1886
1874
  .option("env", {
1887
1875
  type: "string",
1888
1876
  describe: "Perform on a specific environment",
1877
+ alias: "e",
1889
1878
  })
1890
1879
  .option("preview", {
1891
1880
  type: "boolean",
@@ -1900,7 +1889,7 @@ export async function main(argv: string[]): Promise<void> {
1900
1889
  },
1901
1890
  async ({ prefix, ...args }) => {
1902
1891
  // TODO: support for limit+cursor (pagination)
1903
- const config = readConfig(args.config as ConfigPath);
1892
+ const config = readConfig(args.config as ConfigPath, args);
1904
1893
  const namespaceId = getNamespaceId(args, config);
1905
1894
 
1906
1895
  const accountId = await requireAuth(config);
@@ -1935,6 +1924,7 @@ export async function main(argv: string[]): Promise<void> {
1935
1924
  .option("env", {
1936
1925
  type: "string",
1937
1926
  describe: "Perform on a specific environment",
1927
+ alias: "e",
1938
1928
  })
1939
1929
  .option("preview", {
1940
1930
  type: "boolean",
@@ -1948,7 +1938,7 @@ export async function main(argv: string[]): Promise<void> {
1948
1938
  });
1949
1939
  },
1950
1940
  async ({ key, ...args }) => {
1951
- const config = readConfig(args.config as ConfigPath);
1941
+ const config = readConfig(args.config as ConfigPath, args);
1952
1942
  const namespaceId = getNamespaceId(args, config);
1953
1943
 
1954
1944
  const accountId = await requireAuth(config);
@@ -1978,6 +1968,7 @@ export async function main(argv: string[]): Promise<void> {
1978
1968
  .option("env", {
1979
1969
  type: "string",
1980
1970
  describe: "Perform on a specific environment",
1971
+ alias: "e",
1981
1972
  })
1982
1973
  .option("preview", {
1983
1974
  type: "boolean",
@@ -1985,7 +1976,8 @@ export async function main(argv: string[]): Promise<void> {
1985
1976
  });
1986
1977
  },
1987
1978
  async ({ key, ...args }) => {
1988
- const config = readConfig(args.config as ConfigPath);
1979
+ printWranglerBanner();
1980
+ const config = readConfig(args.config as ConfigPath, args);
1989
1981
  const namespaceId = getNamespaceId(args, config);
1990
1982
 
1991
1983
  console.log(
@@ -2032,6 +2024,7 @@ export async function main(argv: string[]): Promise<void> {
2032
2024
  .option("env", {
2033
2025
  type: "string",
2034
2026
  describe: "Perform on a specific environment",
2027
+ alias: "e",
2035
2028
  })
2036
2029
  .option("preview", {
2037
2030
  type: "boolean",
@@ -2039,11 +2032,12 @@ export async function main(argv: string[]): Promise<void> {
2039
2032
  });
2040
2033
  },
2041
2034
  async ({ filename, ...args }) => {
2035
+ printWranglerBanner();
2042
2036
  // The simplest implementation I could think of.
2043
2037
  // This could be made more efficient with a streaming parser/uploader
2044
2038
  // but we'll do that in the future if needed.
2045
2039
 
2046
- const config = readConfig(args.config as ConfigPath);
2040
+ const config = readConfig(args.config as ConfigPath, args);
2047
2041
  const namespaceId = getNamespaceId(args, config);
2048
2042
  const content = parseJSON(readFileSync(filename), filename);
2049
2043
 
@@ -2136,6 +2130,7 @@ export async function main(argv: string[]): Promise<void> {
2136
2130
  .option("env", {
2137
2131
  type: "string",
2138
2132
  describe: "Perform on a specific environment",
2133
+ alias: "e",
2139
2134
  })
2140
2135
  .option("preview", {
2141
2136
  type: "boolean",
@@ -2148,7 +2143,8 @@ export async function main(argv: string[]): Promise<void> {
2148
2143
  });
2149
2144
  },
2150
2145
  async ({ filename, ...args }) => {
2151
- const config = readConfig(args.config as ConfigPath);
2146
+ printWranglerBanner();
2147
+ const config = readConfig(args.config as ConfigPath, args);
2152
2148
  const namespaceId = getNamespaceId(args, config);
2153
2149
 
2154
2150
  if (!args.force) {
@@ -2209,8 +2205,12 @@ export async function main(argv: string[]): Promise<void> {
2209
2205
  }
2210
2206
  );
2211
2207
 
2212
- wrangler.command("pages", "⚡️ Configure Cloudflare Pages", (pagesYargs) =>
2213
- pages(pagesYargs.command(subHelp))
2208
+ wrangler.command(
2209
+ "pages",
2210
+ "⚡️ Configure Cloudflare Pages",
2211
+ async (pagesYargs) => {
2212
+ await pages(pagesYargs.command(subHelp).epilogue(pagesBetaWarning));
2213
+ }
2214
2214
  );
2215
2215
 
2216
2216
  wrangler.command("r2", "📦 Interact with an R2 store", (r2Yargs) => {
@@ -2228,15 +2228,9 @@ export async function main(argv: string[]): Promise<void> {
2228
2228
  });
2229
2229
  },
2230
2230
  async (args) => {
2231
- // We expect three values in `_`: `r2`, `bucket`, `create`.
2232
- if (args._.length > 3) {
2233
- const extraArgs = args._.slice(3).join(" ");
2234
- throw new CommandLineArgsError(
2235
- `Unexpected additional positional arguments "${extraArgs}".`
2236
- );
2237
- }
2231
+ printWranglerBanner();
2238
2232
 
2239
- const config = readConfig(args.config as ConfigPath);
2233
+ const config = readConfig(args.config as ConfigPath, args);
2240
2234
 
2241
2235
  const accountId = await requireAuth(config);
2242
2236
 
@@ -2247,7 +2241,7 @@ export async function main(argv: string[]): Promise<void> {
2247
2241
  );
2248
2242
 
2249
2243
  r2BucketYargs.command("list", "List R2 buckets", {}, async (args) => {
2250
- const config = readConfig(args.config as ConfigPath);
2244
+ const config = readConfig(args.config as ConfigPath, args);
2251
2245
 
2252
2246
  const accountId = await requireAuth(config);
2253
2247
 
@@ -2265,15 +2259,9 @@ export async function main(argv: string[]): Promise<void> {
2265
2259
  });
2266
2260
  },
2267
2261
  async (args) => {
2268
- // We expect three values in `_`: `r2`, `bucket`, `delete`.
2269
- if (args._.length > 3) {
2270
- const extraArgs = args._.slice(3).join(" ");
2271
- throw new CommandLineArgsError(
2272
- `Unexpected additional positional arguments "${extraArgs}".`
2273
- );
2274
- }
2262
+ printWranglerBanner();
2275
2263
 
2276
- const config = readConfig(args.config as ConfigPath);
2264
+ const config = readConfig(args.config as ConfigPath, args);
2277
2265
 
2278
2266
  const accountId = await requireAuth(config);
2279
2267
 
@@ -2286,6 +2274,81 @@ export async function main(argv: string[]): Promise<void> {
2286
2274
  });
2287
2275
  });
2288
2276
 
2277
+ /**
2278
+ * User Group: login, logout, and whoami
2279
+ * TODO: group commands into User group similar to .group() for flags in yargs
2280
+ */
2281
+ // login
2282
+ wrangler.command(
2283
+ // this needs scopes as an option?
2284
+ "login",
2285
+ "🔓 Login to Cloudflare",
2286
+ (yargs) => {
2287
+ // TODO: This needs some copy editing
2288
+ // I mean, this entire app does, but this too.
2289
+ return yargs
2290
+ .option("scopes-list", {
2291
+ describe: "List all the available OAuth scopes with descriptions",
2292
+ })
2293
+ .option("scopes", {
2294
+ describe: "Pick the set of applicable OAuth scopes when logging in",
2295
+ array: true,
2296
+ type: "string",
2297
+ });
2298
+
2299
+ // TODO: scopes
2300
+ },
2301
+ async (args) => {
2302
+ printWranglerBanner();
2303
+ if (args["scopes-list"]) {
2304
+ listScopes();
2305
+ return;
2306
+ }
2307
+ if (args.scopes) {
2308
+ if (args.scopes.length === 0) {
2309
+ // don't allow no scopes to be passed, that would be weird
2310
+ listScopes();
2311
+ return;
2312
+ }
2313
+ if (!validateScopeKeys(args.scopes)) {
2314
+ throw new CommandLineArgsError(
2315
+ `One of ${args.scopes} is not a valid authentication scope. Run "wrangler login --list-scopes" to see the valid scopes.`
2316
+ );
2317
+ }
2318
+ await login({ scopes: args.scopes });
2319
+ return;
2320
+ }
2321
+ await login();
2322
+
2323
+ // TODO: would be nice if it optionally saved login
2324
+ // credentials inside node_modules/.cache or something
2325
+ // this way you could have multiple users on a single machine
2326
+ }
2327
+ );
2328
+
2329
+ // logout
2330
+ wrangler.command(
2331
+ // this needs scopes as an option?
2332
+ "logout",
2333
+ "🚪 Logout from Cloudflare",
2334
+ () => {},
2335
+ async () => {
2336
+ printWranglerBanner();
2337
+ await logout();
2338
+ }
2339
+ );
2340
+
2341
+ // whoami
2342
+ wrangler.command(
2343
+ "whoami",
2344
+ "🕵️ Retrieve your user info and test your auth config",
2345
+ () => {},
2346
+ async () => {
2347
+ printWranglerBanner();
2348
+ await whoami();
2349
+ }
2350
+ );
2351
+
2289
2352
  wrangler
2290
2353
  .option("legacy-env", {
2291
2354
  type: "boolean",
@@ -2303,7 +2366,6 @@ export async function main(argv: string[]): Promise<void> {
2303
2366
  wrangler.exitProcess(false);
2304
2367
 
2305
2368
  try {
2306
- await initialiseUserConfig();
2307
2369
  await wrangler.parse();
2308
2370
  } catch (e) {
2309
2371
  if (e instanceof CommandLineArgsError) {