wrangler 0.0.0-e1c615f → 0.0.0-e5d3690

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.
package/src/index.tsx CHANGED
@@ -6,7 +6,9 @@ import makeCLI from "yargs";
6
6
  import type Yargs from "yargs";
7
7
  import { findUp } from "find-up";
8
8
  import TOML from "@iarna/toml";
9
+ import { normaliseAndValidateEnvironmentsConfig } from "./config";
9
10
  import type { Config } from "./config";
11
+ import { getAssetPaths } from "./sites";
10
12
  import { confirm, prompt } from "./dialogs";
11
13
  import { version as wranglerVersion } from "../package.json";
12
14
  import {
@@ -16,6 +18,7 @@ import {
16
18
  initialise as initialiseUserConfig,
17
19
  loginOrRefreshIfRequired,
18
20
  getAccountId,
21
+ validateScopeKeys,
19
22
  } from "./user";
20
23
  import {
21
24
  getNamespaceId,
@@ -42,6 +45,10 @@ import onExit from "signal-exit";
42
45
  import { setTimeout } from "node:timers/promises";
43
46
  import * as fs from "node:fs";
44
47
  import { execa } from "execa";
48
+ import { whoami } from "./whoami";
49
+
50
+ const resetColor = "\x1b[0m";
51
+ const fgGreenColor = "\x1b[32m";
45
52
 
46
53
  async function readConfig(configPath?: string): Promise<Config> {
47
54
  const config: Config = {};
@@ -56,48 +63,7 @@ async function readConfig(configPath?: string): Promise<Config> {
56
63
  Object.assign(config, parsed);
57
64
  }
58
65
 
59
- const inheritedFields = [
60
- "name",
61
- "account_id",
62
- "workers_dev",
63
- "compatibility_date",
64
- "compatibility_flags",
65
- "zone_id",
66
- "routes",
67
- "route",
68
- "jsx_factory",
69
- "jsx_fragment",
70
- "site",
71
- "triggers",
72
- "usage_model",
73
- ];
74
-
75
- Object.keys(config.env || {}).forEach((env) => {
76
- inheritedFields.forEach((field) => {
77
- if (config[field] !== undefined && config.env[env][field] === undefined) {
78
- config.env[env][field] = config[field]; // TODO: - shallow copy?
79
- }
80
- });
81
- });
82
-
83
- const mirroredFields = [
84
- "vars",
85
- "kv_namespaces",
86
- "durable_objects",
87
- "experimental_services",
88
- ];
89
- Object.keys(config.env || {}).forEach((env) => {
90
- mirroredFields.forEach((field) => {
91
- // if it exists on top level, it should exist on env definitions
92
- Object.keys(config[field] || {}).forEach((fieldKey) => {
93
- if (!(fieldKey in config.env[env][field])) {
94
- console.warn(
95
- `In your configuration, "${field}.${fieldKey}" exists at a top level, but not on "env.${env}". This is not what you probably want, since the field "${field}" is not inherited by environments. Please add "${field}.${fieldKey}" to "env.${env}".`
96
- );
97
- }
98
- });
99
- });
100
- });
66
+ normaliseAndValidateEnvironmentsConfig(config);
101
67
 
102
68
  if ("experimental_services" in config) {
103
69
  console.warn(
@@ -368,6 +334,11 @@ export async function main(argv: string[]): Promise<void> {
368
334
  listScopes();
369
335
  return;
370
336
  }
337
+ if (!validateScopeKeys(args.scopes)) {
338
+ throw new CommandLineArgsError(
339
+ `One of ${args.scopes} is not a valid authentication scope. Run "wrangler login --list-scopes" to see the valid scopes.`
340
+ );
341
+ }
371
342
  await login({ scopes: args.scopes });
372
343
  return;
373
344
  }
@@ -394,11 +365,10 @@ export async function main(argv: string[]): Promise<void> {
394
365
  // whoami
395
366
  wrangler.command(
396
367
  "whoami",
397
- false, // we don't need to show this the menu
398
- // "🕵️ Retrieve your user info and test your auth config",
368
+ "🕵️ Retrieve your user info and test your auth config",
399
369
  () => {},
400
- (args) => {
401
- console.log(":whoami", args);
370
+ async () => {
371
+ await whoami();
402
372
  }
403
373
  );
404
374
 
@@ -421,7 +391,11 @@ export async function main(argv: string[]): Promise<void> {
421
391
  "👂 Start a local server for developing your worker",
422
392
  (yargs) => {
423
393
  return yargs
424
- .positional("filename", { describe: "entry point", type: "string" })
394
+ .positional("filename", {
395
+ describe: "entry point",
396
+ type: "string",
397
+ demandOption: true,
398
+ })
425
399
  .option("name", {
426
400
  describe: "name of the script",
427
401
  type: "string",
@@ -435,6 +409,20 @@ export async function main(argv: string[]): Promise<void> {
435
409
  type: "string",
436
410
  // TODO: get choices for the toml file?
437
411
  })
412
+ .option("compatibility-date", {
413
+ describe: "Date to use for compatibility checks",
414
+ type: "string",
415
+ })
416
+ .option("compatibility-flags", {
417
+ describe: "Flags to use for compatibility checks",
418
+ type: "array",
419
+ alias: "compatibility-flag",
420
+ })
421
+ .option("latest", {
422
+ describe: "Use the latest version of the worker runtime",
423
+ type: "boolean",
424
+ default: true,
425
+ })
438
426
  .option("ip", {
439
427
  describe: "IP address to listen on",
440
428
  type: "string",
@@ -463,6 +451,18 @@ export async function main(argv: string[]): Promise<void> {
463
451
  describe: "Root folder of static assets for Workers Sites",
464
452
  type: "string",
465
453
  })
454
+ .option("site-include", {
455
+ describe:
456
+ "Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.",
457
+ type: "string",
458
+ array: true,
459
+ })
460
+ .option("site-exclude", {
461
+ describe:
462
+ "Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.",
463
+ type: "string",
464
+ array: true,
465
+ })
466
466
  .option("upstream-protocol", {
467
467
  default: "https",
468
468
  describe:
@@ -494,33 +494,33 @@ export async function main(argv: string[]): Promise<void> {
494
494
  );
495
495
  }
496
496
 
497
- // -- snip, extract --
498
-
499
497
  if (!args.local) {
498
+ // -- snip, extract --
500
499
  const loggedIn = await loginOrRefreshIfRequired();
501
500
  if (!loggedIn) {
502
501
  // didn't login, let's just quit
503
502
  console.log("Did not login, quitting...");
504
503
  return;
505
504
  }
505
+
506
506
  if (!config.account_id) {
507
507
  config.account_id = await getAccountId();
508
508
  if (!config.account_id) {
509
509
  throw new Error("No account id found, quitting...");
510
510
  }
511
511
  }
512
+ // -- snip, end --
512
513
  }
513
514
 
514
- // -- snip, end --
515
-
516
- const envRootObj = args.env ? config.env[args.env] || {} : config;
515
+ const environments = config.env ?? {};
516
+ const envRootObj = args.env ? environments[args.env] || {} : config;
517
517
 
518
518
  // TODO: this error shouldn't actually happen,
519
519
  // but we haven't fixed it internally yet
520
520
  if ("durable_objects" in envRootObj) {
521
521
  if (!(args.name || config.name)) {
522
522
  console.warn(
523
- 'A worker with durable objects need to be named, or it may not work as expected. Add a "name" into wrangler.toml, or pass it in the command line with --name.'
523
+ 'A worker with durable objects needs to be named, or it may not work as expected. Add a "name" into wrangler.toml, or pass it in the command line with --name.'
524
524
  );
525
525
  }
526
526
  // TODO: if not already published, publish a draft worker
@@ -536,11 +536,23 @@ export async function main(argv: string[]): Promise<void> {
536
536
  jsxFactory={args["jsx-factory"] || envRootObj?.jsx_factory}
537
537
  jsxFragment={args["jsx-fragment"] || envRootObj?.jsx_fragment}
538
538
  accountId={config.account_id}
539
- site={args.site || config.site?.bucket}
539
+ assetPaths={getAssetPaths(
540
+ config,
541
+ args.site,
542
+ args.siteInclude,
543
+ args.siteExclude
544
+ )}
540
545
  port={args.port || config.dev?.port}
541
546
  public={args["experimental-public"]}
542
- compatibilityDate={config.compatibility_date}
543
- compatibilityFlags={config.compatibility_flags}
547
+ compatibilityDate={
548
+ args["compatibility-date"] ||
549
+ config.compatibility_date ||
550
+ new Date().toISOString().substring(0, 10)
551
+ }
552
+ compatibilityFlags={
553
+ (args["compatibility-flags"] as string[]) ||
554
+ config.compatibility_flags
555
+ }
544
556
  usageModel={config.usage_model}
545
557
  bindings={{
546
558
  kv_namespaces: envRootObj.kv_namespaces?.map(
@@ -592,6 +604,20 @@ export async function main(argv: string[]): Promise<void> {
592
604
  describe: "name to use when uploading",
593
605
  type: "string",
594
606
  })
607
+ .option("compatibility-date", {
608
+ describe: "Date to use for compatibility checks",
609
+ type: "string",
610
+ })
611
+ .option("compatibility-flags", {
612
+ describe: "Flags to use for compatibility checks",
613
+ type: "array",
614
+ alias: "compatibility-flag",
615
+ })
616
+ .option("latest", {
617
+ describe: "Use the latest version of the worker runtime",
618
+ type: "boolean",
619
+ default: false,
620
+ })
595
621
  .option("experimental-public", {
596
622
  describe: "Static assets to be served",
597
623
  type: "string",
@@ -600,6 +626,18 @@ export async function main(argv: string[]): Promise<void> {
600
626
  describe: "Root folder of static assets for Workers Sites",
601
627
  type: "string",
602
628
  })
629
+ .option("site-include", {
630
+ describe:
631
+ "Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.",
632
+ type: "string",
633
+ array: true,
634
+ })
635
+ .option("site-exclude", {
636
+ describe:
637
+ "Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.",
638
+ type: "string",
639
+ array: true,
640
+ })
603
641
  .option("triggers", {
604
642
  describe: "cron schedules to attach",
605
643
  alias: ["schedule", "schedules"],
@@ -645,35 +683,53 @@ export async function main(argv: string[]): Promise<void> {
645
683
 
646
684
  const config = args.config as Config;
647
685
 
648
- // -- snip, extract --
686
+ if (args.latest) {
687
+ console.warn(
688
+ "⚠️ Using the latest version of the Workers runtime. To silence this warning, please choose a specific version of the runtime with --compatibility-date, or add a compatibility_date to your wrangler.toml.\n"
689
+ );
690
+ }
691
+
649
692
  if (!args.local) {
693
+ // -- snip, extract --
650
694
  const loggedIn = await loginOrRefreshIfRequired();
651
695
  if (!loggedIn) {
652
696
  // didn't login, let's just quit
653
697
  console.log("Did not login, quitting...");
654
698
  return;
655
699
  }
700
+
656
701
  if (!config.account_id) {
657
702
  config.account_id = await getAccountId();
658
703
  if (!config.account_id) {
659
704
  throw new Error("No account id found, quitting...");
660
705
  }
661
706
  }
707
+ // -- snip, end --
662
708
  }
663
709
 
664
- // -- snip, end --
665
-
710
+ const assetPaths = getAssetPaths(
711
+ config,
712
+ args["experimental-public"] || args.site,
713
+ args.siteInclude,
714
+ args.siteExclude
715
+ );
666
716
  await publish({
667
717
  config: args.config as Config,
668
718
  name: args.name,
669
719
  script: args.script,
670
720
  env: args.env,
721
+ compatibilityDate: args.latest
722
+ ? new Date().toISOString().substring(0, 10)
723
+ : args["compatibility-date"],
724
+ compatibilityFlags: args["compatibility-flags"] as string[],
671
725
  triggers: args.triggers,
672
726
  jsxFactory: args["jsx-factory"],
673
727
  jsxFragment: args["jsx-fragment"],
674
728
  routes: args.routes,
675
- public: args["experimental-public"],
676
- site: args.site,
729
+ assetPaths,
730
+ format: undefined, // TODO: add args for this
731
+ legacyEnv: undefined, // TODO: get this from somewhere... config?
732
+ experimentalPublic: args["experimental-public"] !== undefined,
677
733
  });
678
734
  }
679
735
  );
@@ -723,6 +779,12 @@ export async function main(argv: string[]): Promise<void> {
723
779
  // TODO: filter by client ip, which can be 'self' or an ip address
724
780
  },
725
781
  async (args) => {
782
+ if (args.local) {
783
+ throw new NotImplementedError(
784
+ `local mode is not yet supported for this command`
785
+ );
786
+ }
787
+
726
788
  const config = args.config as Config;
727
789
 
728
790
  if (!(args.name || config.name)) {
@@ -733,22 +795,19 @@ export async function main(argv: string[]): Promise<void> {
733
795
  }`;
734
796
 
735
797
  // -- snip, extract --
798
+ const loggedIn = await loginOrRefreshIfRequired();
799
+ if (!loggedIn) {
800
+ // didn't login, let's just quit
801
+ console.log("Did not login, quitting...");
802
+ return;
803
+ }
736
804
 
737
- if (!args.local) {
738
- const loggedIn = await loginOrRefreshIfRequired();
739
- if (!loggedIn) {
740
- // didn't login, let's just quit
741
- console.log("Did not login, quitting...");
742
- return;
743
- }
805
+ if (!config.account_id) {
806
+ config.account_id = await getAccountId();
744
807
  if (!config.account_id) {
745
- config.account_id = await getAccountId();
746
- if (!config.account_id) {
747
- throw new Error("No account id found, quitting...");
748
- }
808
+ throw new Error("No account id found, quitting...");
749
809
  }
750
810
  }
751
-
752
811
  // -- snip, end --
753
812
 
754
813
  const accountId = config.account_id;
@@ -954,25 +1013,24 @@ export async function main(argv: string[]): Promise<void> {
954
1013
  throw new Error("Missing script name");
955
1014
  }
956
1015
 
957
- // -- snip, extract --
958
-
959
1016
  if (!args.local) {
1017
+ // -- snip, extract --
960
1018
  const loggedIn = await loginOrRefreshIfRequired();
961
1019
  if (!loggedIn) {
962
1020
  // didn't login, let's just quit
963
1021
  console.log("Did not login, quitting...");
964
1022
  return;
965
1023
  }
1024
+
966
1025
  if (!config.account_id) {
967
1026
  config.account_id = await getAccountId();
968
1027
  if (!config.account_id) {
969
1028
  throw new Error("No account id found, quitting...");
970
1029
  }
971
1030
  }
1031
+ // -- snip, end --
972
1032
  }
973
1033
 
974
- // -- snip, end --
975
-
976
1034
  const secretValue = await prompt(
977
1035
  "Enter a secret value:",
978
1036
  "password"
@@ -1058,25 +1116,24 @@ export async function main(argv: string[]): Promise<void> {
1058
1116
  throw new Error("Missing script name");
1059
1117
  }
1060
1118
 
1061
- // -- snip, extract --
1062
-
1063
1119
  if (!args.local) {
1120
+ // -- snip, extract --
1064
1121
  const loggedIn = await loginOrRefreshIfRequired();
1065
1122
  if (!loggedIn) {
1066
1123
  // didn't login, let's just quit
1067
1124
  console.log("Did not login, quitting...");
1068
1125
  return;
1069
1126
  }
1127
+
1070
1128
  if (!config.account_id) {
1071
1129
  config.account_id = await getAccountId();
1072
1130
  if (!config.account_id) {
1073
1131
  throw new Error("No account id found, quitting...");
1074
1132
  }
1075
1133
  }
1134
+ // -- snip, end --
1076
1135
  }
1077
1136
 
1078
- // -- snip, end --
1079
-
1080
1137
  if (await confirm("Are you sure you want to delete this secret?")) {
1081
1138
  console.log(
1082
1139
  `Deleting the secret ${args.key} on script ${scriptName}.`
@@ -1120,25 +1177,24 @@ export async function main(argv: string[]): Promise<void> {
1120
1177
  throw new Error("Missing script name");
1121
1178
  }
1122
1179
 
1123
- // -- snip, extract --
1124
-
1125
1180
  if (!args.local) {
1181
+ // -- snip, extract --
1126
1182
  const loggedIn = await loginOrRefreshIfRequired();
1127
1183
  if (!loggedIn) {
1128
1184
  // didn't login, let's just quit
1129
1185
  console.log("Did not login, quitting...");
1130
1186
  return;
1131
1187
  }
1188
+
1132
1189
  if (!config.account_id) {
1133
1190
  config.account_id = await getAccountId();
1134
1191
  if (!config.account_id) {
1135
1192
  throw new Error("No account id found, quitting...");
1136
1193
  }
1137
1194
  }
1195
+ // -- snip, end --
1138
1196
  }
1139
1197
 
1140
- // -- snip, end --
1141
-
1142
1198
  console.log(
1143
1199
  await fetchResult(
1144
1200
  `/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets`
@@ -1164,6 +1220,7 @@ export async function main(argv: string[]): Promise<void> {
1164
1220
  .positional("namespace", {
1165
1221
  describe: "The name of the new namespace",
1166
1222
  type: "string",
1223
+ demandOption: true,
1167
1224
  })
1168
1225
  .option("env", {
1169
1226
  type: "string",
@@ -1209,44 +1266,43 @@ export async function main(argv: string[]): Promise<void> {
1209
1266
  });
1210
1267
  await mf.getKVNamespace(title); // this should "create" the namespace
1211
1268
  console.log(`✨ Success! Created KV namespace ${title}`);
1212
- return;
1213
- }
1214
-
1215
- // -- snip, extract --
1216
-
1217
- if (!args.local) {
1269
+ } else {
1270
+ // -- snip, extract --
1218
1271
  const loggedIn = await loginOrRefreshIfRequired();
1219
1272
  if (!loggedIn) {
1220
1273
  // didn't login, let's just quit
1221
1274
  console.log("Did not login, quitting...");
1222
1275
  return;
1223
1276
  }
1277
+
1224
1278
  if (!config.account_id) {
1225
1279
  config.account_id = await getAccountId();
1226
1280
  if (!config.account_id) {
1227
1281
  throw new Error("No account id found, quitting...");
1228
1282
  }
1229
1283
  }
1230
- }
1231
-
1232
- // -- snip, end --
1284
+ // -- snip, end --
1233
1285
 
1234
- // TODO: generate a binding name stripping non alphanumeric chars
1286
+ // TODO: generate a binding name stripping non alphanumeric chars
1235
1287
 
1236
- console.log(`🌀 Creating namespace with title "${title}"`);
1237
- const namespaceId = await createNamespace(config.account_id, title);
1288
+ console.log(`🌀 Creating namespace with title "${title}"`);
1289
+ const namespaceId = await createNamespace(
1290
+ config.account_id,
1291
+ title
1292
+ );
1238
1293
 
1239
- console.log("✨ Success!");
1240
- const envString = args.env ? ` under [env.${args.env}]` : "";
1241
- const previewString = args.preview ? "preview_" : "";
1242
- console.log(
1243
- `Add the following to your configuration file in your kv_namespaces array${envString}:`
1244
- );
1245
- console.log(
1246
- `{ binding = "${args.namespace}", ${previewString}id = "${namespaceId}" }`
1247
- );
1294
+ console.log("✨ Success!");
1295
+ const envString = args.env ? ` under [env.${args.env}]` : "";
1296
+ const previewString = args.preview ? "preview_" : "";
1297
+ console.log(
1298
+ `Add the following to your configuration file in your kv_namespaces array${envString}:`
1299
+ );
1300
+ console.log(
1301
+ `{ binding = "${args.namespace}", ${previewString}id = "${namespaceId}" }`
1302
+ );
1248
1303
 
1249
- // TODO: automatically write this block to the wrangler.toml config file??
1304
+ // TODO: automatically write this block to the wrangler.toml config file??
1305
+ }
1250
1306
  }
1251
1307
  )
1252
1308
  .command(
@@ -1254,42 +1310,39 @@ export async function main(argv: string[]): Promise<void> {
1254
1310
  "Outputs a list of all KV namespaces associated with your account id.",
1255
1311
  {},
1256
1312
  async (args) => {
1313
+ const config = args.config as Config;
1314
+
1257
1315
  if (args.local) {
1258
1316
  throw new NotImplementedError(
1259
1317
  `local mode is not yet supported for this command`
1260
1318
  );
1261
- }
1262
-
1263
- const config = args.config as Config;
1264
-
1265
- // -- snip, extract --
1266
-
1267
- if (!args.local) {
1319
+ } else {
1320
+ // -- snip, extract --
1268
1321
  const loggedIn = await loginOrRefreshIfRequired();
1269
1322
  if (!loggedIn) {
1270
1323
  // didn't login, let's just quit
1271
1324
  console.log("Did not login, quitting...");
1272
1325
  return;
1273
1326
  }
1327
+
1274
1328
  if (!config.account_id) {
1275
1329
  config.account_id = await getAccountId();
1276
1330
  if (!config.account_id) {
1277
1331
  throw new Error("No account id found, quitting...");
1278
1332
  }
1279
1333
  }
1280
- }
1334
+ // -- snip, end --
1281
1335
 
1282
- // -- snip, end --
1336
+ // TODO: we should show bindings if they exist for given ids
1283
1337
 
1284
- // TODO: we should show bindings if they exist for given ids
1285
-
1286
- console.log(
1287
- JSON.stringify(
1288
- await listNamespaces(config.account_id),
1289
- null,
1290
- " "
1291
- )
1292
- );
1338
+ console.log(
1339
+ JSON.stringify(
1340
+ await listNamespaces(config.account_id),
1341
+ null,
1342
+ " "
1343
+ )
1344
+ );
1345
+ }
1293
1346
  }
1294
1347
  )
1295
1348
  .command(
@@ -1316,25 +1369,23 @@ export async function main(argv: string[]): Promise<void> {
1316
1369
  });
1317
1370
  },
1318
1371
  async (args) => {
1372
+ const config = args.config as Config;
1373
+
1319
1374
  if (args.local) {
1320
1375
  throw new NotImplementedError(
1321
1376
  `local mode is not yet supported for this command`
1322
1377
  );
1323
- }
1324
- const config = args.config as Config;
1325
-
1326
- let id;
1327
- try {
1328
- id = getNamespaceId(args);
1329
- } catch (e) {
1330
- throw new CommandLineArgsError(
1331
- "Not able to delete namespace.\n" + e.message
1332
- );
1333
- }
1334
-
1335
- // -- snip, extract --
1378
+ } else {
1379
+ let id;
1380
+ try {
1381
+ id = getNamespaceId(args);
1382
+ } catch (e) {
1383
+ throw new CommandLineArgsError(
1384
+ "Not able to delete namespace.\n" + e.message
1385
+ );
1386
+ }
1336
1387
 
1337
- if (!args.local) {
1388
+ // -- snip, extract --
1338
1389
  const loggedIn = await loginOrRefreshIfRequired();
1339
1390
  if (!loggedIn) {
1340
1391
  // didn't login, let's just quit
@@ -1348,32 +1399,31 @@ export async function main(argv: string[]): Promise<void> {
1348
1399
  throw new Error("No account id found, quitting...");
1349
1400
  }
1350
1401
  }
1351
- }
1402
+ // -- snip, end --
1352
1403
 
1353
- // -- snip, end --
1354
-
1355
- await fetchResult<{ id: string }>(
1356
- `/accounts/${config.account_id}/storage/kv/namespaces/${id}`,
1357
- { method: "DELETE" }
1358
- );
1404
+ await fetchResult<{ id: string }>(
1405
+ `/accounts/${config.account_id}/storage/kv/namespaces/${id}`,
1406
+ { method: "DELETE" }
1407
+ );
1359
1408
 
1360
- // TODO: recommend they remove it from wrangler.toml
1409
+ // TODO: recommend they remove it from wrangler.toml
1361
1410
 
1362
- // test-mf wrangler kv:namespace delete --namespace-id 2a7d3d8b23fc4159b5afa489d6cfd388
1363
- // Are you sure you want to delete namespace 2a7d3d8b23fc4159b5afa489d6cfd388? [y/n]
1364
- // n
1365
- // 💁 Not deleting namespace 2a7d3d8b23fc4159b5afa489d6cfd388
1366
- // ➜ test-mf wrangler kv:namespace delete --namespace-id 2a7d3d8b23fc4159b5afa489d6cfd388
1367
- // Are you sure you want to delete namespace 2a7d3d8b23fc4159b5afa489d6cfd388? [y/n]
1368
- // y
1369
- // 🌀 Deleting namespace 2a7d3d8b23fc4159b5afa489d6cfd388
1370
- // ✨ Success
1371
- // ⚠️ Make sure to remove this "kv-namespace" entry from your configuration file!
1372
- // ➜ test-mf
1411
+ // test-mf wrangler kv:namespace delete --namespace-id 2a7d3d8b23fc4159b5afa489d6cfd388
1412
+ // Are you sure you want to delete namespace 2a7d3d8b23fc4159b5afa489d6cfd388? [y/n]
1413
+ // n
1414
+ // 💁 Not deleting namespace 2a7d3d8b23fc4159b5afa489d6cfd388
1415
+ // ➜ test-mf wrangler kv:namespace delete --namespace-id 2a7d3d8b23fc4159b5afa489d6cfd388
1416
+ // Are you sure you want to delete namespace 2a7d3d8b23fc4159b5afa489d6cfd388? [y/n]
1417
+ // y
1418
+ // 🌀 Deleting namespace 2a7d3d8b23fc4159b5afa489d6cfd388
1419
+ // ✨ Success
1420
+ // ⚠️ Make sure to remove this "kv-namespace" entry from your configuration file!
1421
+ // ➜ test-mf
1373
1422
 
1374
- // TODO: do it automatically
1423
+ // TODO: do it automatically
1375
1424
 
1376
- // TODO: delete the preview namespace as well?
1425
+ // TODO: delete the preview namespace as well?
1426
+ }
1377
1427
  }
1378
1428
  );
1379
1429
  }
@@ -1393,6 +1443,7 @@ export async function main(argv: string[]): Promise<void> {
1393
1443
  .positional("key", {
1394
1444
  type: "string",
1395
1445
  describe: "The key to write to.",
1446
+ demandOption: true,
1396
1447
  })
1397
1448
  .positional("value", {
1398
1449
  type: "string",
@@ -1432,9 +1483,11 @@ export async function main(argv: string[]): Promise<void> {
1432
1483
  },
1433
1484
  async ({ key, ttl, expiration, ...args }) => {
1434
1485
  const namespaceId = getNamespaceId(args);
1486
+ // One of `args.path` and `args.value` must be defined
1435
1487
  const value = args.path
1436
1488
  ? await readFile(args.path, "utf-8")
1437
- : args.value;
1489
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1490
+ args.value!;
1438
1491
  const config = args.config as Config;
1439
1492
 
1440
1493
  if (args.path) {
@@ -1456,11 +1509,8 @@ export async function main(argv: string[]): Promise<void> {
1456
1509
  });
1457
1510
  const ns = await mf.getKVNamespace(namespaceId);
1458
1511
  await ns.put(key, value, { expiration, expirationTtl: ttl });
1459
- return;
1460
- }
1461
- // -- snip, extract --
1462
-
1463
- if (!args.local) {
1512
+ } else {
1513
+ // -- snip, extract --
1464
1514
  const loggedIn = await loginOrRefreshIfRequired();
1465
1515
  if (!loggedIn) {
1466
1516
  // didn't login, let's just quit
@@ -1474,14 +1524,13 @@ export async function main(argv: string[]): Promise<void> {
1474
1524
  throw new Error("No account id found, quitting...");
1475
1525
  }
1476
1526
  }
1477
- }
1478
-
1479
- // -- snip, end --
1527
+ // -- snip, end --
1480
1528
 
1481
- await putKeyValue(config.account_id, namespaceId, key, value, {
1482
- expiration,
1483
- expiration_ttl: ttl,
1484
- });
1529
+ await putKeyValue(config.account_id, namespaceId, key, value, {
1530
+ expiration,
1531
+ expiration_ttl: ttl,
1532
+ });
1533
+ }
1485
1534
  }
1486
1535
  )
1487
1536
  .command(
@@ -1529,12 +1578,8 @@ export async function main(argv: string[]): Promise<void> {
1529
1578
  const ns = await mf.getKVNamespace(namespaceId);
1530
1579
  const listResponse = await ns.list({ prefix });
1531
1580
  console.log(JSON.stringify(listResponse.keys, null, " ")); // TODO: paginate, collate
1532
- return;
1533
- }
1534
-
1535
- // -- snip, extract --
1536
-
1537
- if (!args.local) {
1581
+ } else {
1582
+ // -- snip, extract --
1538
1583
  const loggedIn = await loginOrRefreshIfRequired();
1539
1584
  if (!loggedIn) {
1540
1585
  // didn't login, let's just quit
@@ -1548,13 +1593,15 @@ export async function main(argv: string[]): Promise<void> {
1548
1593
  throw new Error("No account id found, quitting...");
1549
1594
  }
1550
1595
  }
1551
- }
1596
+ // -- snip, end --
1552
1597
 
1553
- // -- snip, end --
1554
-
1555
- console.log(
1556
- await listNamespaceKeys(config.account_id, namespaceId, prefix)
1557
- );
1598
+ const results = await listNamespaceKeys(
1599
+ config.account_id,
1600
+ namespaceId,
1601
+ prefix
1602
+ );
1603
+ console.log(JSON.stringify(results, undefined, 2));
1604
+ }
1558
1605
  }
1559
1606
  )
1560
1607
  .command(
@@ -1565,6 +1612,7 @@ export async function main(argv: string[]): Promise<void> {
1565
1612
  .positional("key", {
1566
1613
  describe: "The key value to get.",
1567
1614
  type: "string",
1615
+ demandOption: true,
1568
1616
  })
1569
1617
  .option("binding", {
1570
1618
  type: "string",
@@ -1606,9 +1654,8 @@ export async function main(argv: string[]): Promise<void> {
1606
1654
  return;
1607
1655
  }
1608
1656
 
1609
- // -- snip, extract --
1610
-
1611
1657
  if (!args.local) {
1658
+ // -- snip, extract --
1612
1659
  const loggedIn = await loginOrRefreshIfRequired();
1613
1660
  if (!loggedIn) {
1614
1661
  // didn't login, let's just quit
@@ -1622,10 +1669,9 @@ export async function main(argv: string[]): Promise<void> {
1622
1669
  throw new Error("No account id found, quitting...");
1623
1670
  }
1624
1671
  }
1672
+ // -- snip, end --
1625
1673
  }
1626
1674
 
1627
- // -- snip, end --
1628
-
1629
1675
  console.log(
1630
1676
  await fetchRaw(
1631
1677
  `/accounts/${config.account_id}/storage/kv/namespaces/${namespaceId}/values/${key}`
@@ -1641,6 +1687,7 @@ export async function main(argv: string[]): Promise<void> {
1641
1687
  .positional("key", {
1642
1688
  describe: "The key value to delete",
1643
1689
  type: "string",
1690
+ demandOption: true,
1644
1691
  })
1645
1692
  .option("binding", {
1646
1693
  type: "string",
@@ -1681,9 +1728,8 @@ export async function main(argv: string[]): Promise<void> {
1681
1728
 
1682
1729
  const config = args.config as Config;
1683
1730
 
1684
- // -- snip, extract --
1685
-
1686
1731
  if (!args.local) {
1732
+ // -- snip, extract --
1687
1733
  const loggedIn = await loginOrRefreshIfRequired();
1688
1734
  if (!loggedIn) {
1689
1735
  // didn't login, let's just quit
@@ -1697,10 +1743,9 @@ export async function main(argv: string[]): Promise<void> {
1697
1743
  throw new Error("No account id found, quitting...");
1698
1744
  }
1699
1745
  }
1746
+ // -- snip, end --
1700
1747
  }
1701
1748
 
1702
- // -- snip, end --
1703
-
1704
1749
  await fetchResult(
1705
1750
  `/accounts/${config.account_id}/storage/kv/namespaces/${namespaceId}/values/${key}`,
1706
1751
  { method: "DELETE" }
@@ -1724,6 +1769,7 @@ export async function main(argv: string[]): Promise<void> {
1724
1769
  .positional("filename", {
1725
1770
  describe: `The JSON file of key-value pairs to upload, in form [{"key":..., "value":...}"...]`,
1726
1771
  type: "string",
1772
+ demandOption: true,
1727
1773
  })
1728
1774
  .option("binding", {
1729
1775
  type: "string",
@@ -1779,13 +1825,8 @@ export async function main(argv: string[]): Promise<void> {
1779
1825
  expirationTtl: expiration_ttl,
1780
1826
  });
1781
1827
  }
1782
-
1783
- return;
1784
- }
1785
-
1786
- // -- snip, extract --
1787
-
1788
- if (!args.local) {
1828
+ } else {
1829
+ // -- snip, extract --
1789
1830
  const loggedIn = await loginOrRefreshIfRequired();
1790
1831
  if (!loggedIn) {
1791
1832
  // didn't login, let's just quit
@@ -1799,23 +1840,23 @@ export async function main(argv: string[]): Promise<void> {
1799
1840
  throw new Error("No account id found, quitting...");
1800
1841
  }
1801
1842
  }
1802
- }
1803
-
1804
- // -- snip, end --
1843
+ // -- snip, end --
1805
1844
 
1806
- console.log(
1807
- await putBulkKeyValue(config.account_id, namespaceId, content)
1808
- );
1845
+ console.log(
1846
+ await putBulkKeyValue(config.account_id, namespaceId, content)
1847
+ );
1848
+ }
1809
1849
  }
1810
1850
  )
1811
1851
  .command(
1812
1852
  "delete <filename>",
1813
- "Upload multiple key-value pairs to a namespace",
1853
+ "Delete multiple key-value pairs from a namespace",
1814
1854
  (yargs) => {
1815
1855
  return yargs
1816
1856
  .positional("filename", {
1817
- describe: `The JSON file of key-value pairs to upload, in form ["key1", "key2", ...]`,
1857
+ describe: `The JSON file of keys to delete, in the form ["key1", "key2", ...]`,
1818
1858
  type: "string",
1859
+ demandOption: true,
1819
1860
  })
1820
1861
  .option("binding", {
1821
1862
  type: "string",
@@ -1859,13 +1900,8 @@ export async function main(argv: string[]): Promise<void> {
1859
1900
  for (const key of parsedContent) {
1860
1901
  await ns.delete(key);
1861
1902
  }
1862
-
1863
- return;
1864
- }
1865
-
1866
- // -- snip, extract --
1867
-
1868
- if (!args.local) {
1903
+ } else {
1904
+ // -- snip, extract --
1869
1905
  const loggedIn = await loginOrRefreshIfRequired();
1870
1906
  if (!loggedIn) {
1871
1907
  // didn't login, let's just quit
@@ -1879,13 +1915,16 @@ export async function main(argv: string[]): Promise<void> {
1879
1915
  throw new Error("No account id found, quitting...");
1880
1916
  }
1881
1917
  }
1882
- }
1918
+ // -- snip, end --
1883
1919
 
1884
- // -- snip, end --
1885
-
1886
- console.log(
1887
- await deleteBulkKeyValue(config.account_id, namespaceId, content)
1888
- );
1920
+ console.log(
1921
+ await deleteBulkKeyValue(
1922
+ config.account_id,
1923
+ namespaceId,
1924
+ content
1925
+ )
1926
+ );
1927
+ }
1889
1928
  }
1890
1929
  );
1891
1930
  }
@@ -1922,8 +1961,15 @@ export async function main(argv: string[]): Promise<void> {
1922
1961
  if (e instanceof CommandLineArgsError) {
1923
1962
  wrangler.showHelp("error");
1924
1963
  console.error(""); // Just adds a bit of space
1964
+ console.error(e.message);
1965
+ } else {
1966
+ console.error(e.message);
1967
+ console.error(""); // Just adds a bit of space
1968
+ console.error(
1969
+ `${fgGreenColor}%s${resetColor}`,
1970
+ "If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1971
+ );
1925
1972
  }
1926
- console.error(e.message);
1927
1973
  throw e;
1928
1974
  }
1929
1975
  }