wrangler 0.0.0-e151223 → 0.0.0-e29a241

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 (92) hide show
  1. package/miniflare-dist/index.mjs +79 -0
  2. package/miniflare-dist/index.mjs.map +7 -0
  3. package/package.json +29 -13
  4. package/pages/functions/filepath-routing.test.ts +212 -36
  5. package/pages/functions/filepath-routing.ts +69 -119
  6. package/pages/functions/routes.ts +8 -17
  7. package/pages/functions/template-worker.ts +3 -9
  8. package/src/__tests__/configuration.test.ts +2754 -0
  9. package/src/__tests__/dev.test.tsx +488 -63
  10. package/src/__tests__/dev2.test.tsx +154 -0
  11. package/src/__tests__/guess-worker-format.test.ts +58 -0
  12. package/src/__tests__/helpers/cmd-shim.d.ts +11 -0
  13. package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
  14. package/src/__tests__/helpers/mock-account-id.ts +26 -8
  15. package/src/__tests__/helpers/mock-bin.ts +36 -0
  16. package/src/__tests__/helpers/mock-cfetch.ts +44 -10
  17. package/src/__tests__/helpers/mock-console.ts +21 -7
  18. package/src/__tests__/helpers/mock-kv.ts +9 -16
  19. package/src/__tests__/helpers/mock-stdin.ts +103 -0
  20. package/src/__tests__/helpers/mock-web-socket.ts +29 -0
  21. package/src/__tests__/helpers/run-in-tmp.ts +3 -0
  22. package/src/__tests__/helpers/run-wrangler.ts +5 -3
  23. package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
  24. package/src/__tests__/https-options.test.ts +127 -0
  25. package/src/__tests__/index.test.ts +617 -32
  26. package/src/__tests__/jest.setup.ts +41 -6
  27. package/src/__tests__/kv.test.ts +455 -222
  28. package/src/__tests__/logout.test.ts +15 -13
  29. package/src/__tests__/package-manager.test.ts +206 -0
  30. package/src/__tests__/pages.test.ts +44 -0
  31. package/src/__tests__/parse.test.ts +322 -0
  32. package/src/__tests__/publish.test.ts +1919 -437
  33. package/src/__tests__/r2.test.ts +198 -0
  34. package/src/__tests__/route.test.ts +45 -0
  35. package/src/__tests__/secret.test.ts +301 -86
  36. package/src/__tests__/sentry.test.ts +146 -0
  37. package/src/__tests__/tail.test.ts +564 -0
  38. package/src/__tests__/whoami.test.tsx +21 -7
  39. package/src/bundle.ts +142 -0
  40. package/src/cfetch/index.ts +9 -16
  41. package/src/cfetch/internal.ts +89 -22
  42. package/src/cli.ts +10 -0
  43. package/src/config/README.md +107 -0
  44. package/src/config/config.ts +274 -0
  45. package/src/config/diagnostics.ts +80 -0
  46. package/src/config/environment.ts +310 -0
  47. package/src/config/index.ts +56 -0
  48. package/src/config/validation-helpers.ts +486 -0
  49. package/src/config/validation.ts +1096 -0
  50. package/src/{api/preview.ts → create-worker-preview.ts} +59 -21
  51. package/src/create-worker-upload-form.ts +217 -0
  52. package/src/dev/dev.tsx +364 -0
  53. package/src/dev/local.tsx +226 -0
  54. package/src/dev/remote.tsx +203 -0
  55. package/src/dev/use-esbuild.ts +100 -0
  56. package/src/entry.ts +208 -0
  57. package/src/environment-variables.ts +33 -0
  58. package/src/https-options.ts +122 -0
  59. package/src/index.tsx +1079 -766
  60. package/src/inspect.ts +25 -4
  61. package/src/{kv.tsx → kv.ts} +104 -61
  62. package/src/miniflare-cli/README.md +30 -0
  63. package/src/miniflare-cli/enum-keys.ts +17 -0
  64. package/src/miniflare-cli/index.ts +37 -0
  65. package/src/module-collection.ts +226 -31
  66. package/src/open-in-browser.ts +25 -0
  67. package/src/package-manager.ts +126 -0
  68. package/src/pages.tsx +11 -11
  69. package/src/parse.ts +183 -0
  70. package/src/proxy.ts +115 -45
  71. package/src/publish.ts +265 -328
  72. package/src/r2.ts +50 -0
  73. package/src/reporting.ts +131 -0
  74. package/src/selfsigned.d.ts +29 -0
  75. package/src/sites.tsx +83 -43
  76. package/src/tail/filters.ts +279 -0
  77. package/src/tail/index.ts +299 -0
  78. package/src/tail/printing.ts +62 -0
  79. package/src/user.tsx +223 -124
  80. package/src/{api/worker.ts → worker.ts} +44 -36
  81. package/templates/new-worker.js +15 -0
  82. package/templates/new-worker.ts +15 -0
  83. package/{static-asset-facade.js → templates/static-asset-facade.js} +0 -0
  84. package/templates/tsconfig.json +105 -0
  85. package/wrangler-dist/cli.js +60837 -43876
  86. package/wrangler-dist/cli.js.map +3 -3
  87. package/src/__tests__/helpers/mock-user.ts +0 -27
  88. package/src/api/form_data.ts +0 -134
  89. package/src/config.ts +0 -641
  90. package/src/dev.tsx +0 -834
  91. package/src/npm-installer.ts +0 -20
  92. package/src/tail.tsx +0 -73
@@ -1,15 +1,18 @@
1
1
  import { writeFileSync } from "node:fs";
2
+ import { Headers } from "undici";
2
3
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
3
4
  import {
4
5
  setMockResponse,
5
- setMockRawResponse,
6
6
  unsetAllMocks,
7
+ unsetMockFetchKVGetValues,
8
+ setMockFetchKVGetValue,
7
9
  } from "./helpers/mock-cfetch";
8
10
  import { mockConsoleMethods } from "./helpers/mock-console";
11
+ import { mockConfirm } from "./helpers/mock-dialogs";
9
12
  import { mockKeyListRequest } from "./helpers/mock-kv";
10
13
  import { runInTempDir } from "./helpers/run-in-tmp";
11
14
  import { runWrangler } from "./helpers/run-wrangler";
12
- import type { KVNamespaceInfo } from "../kv";
15
+ import type { KeyValue, KVNamespaceInfo, NamespaceKeyInfo } from "../kv";
13
16
 
14
17
  describe("wrangler", () => {
15
18
  mockAccountId();
@@ -52,13 +55,13 @@ describe("wrangler", () => {
52
55
  namespace The name of the new namespace [string] [required]
53
56
 
54
57
  Flags:
55
- -c, --config Path to .toml configuration file [string]
56
- -h, --help Show help [boolean]
57
- -v, --version Show version number [boolean]
58
+ -c, --config Path to .toml configuration file [string]
59
+ -h, --help Show help [boolean]
60
+ -v, --version Show version number [boolean]
61
+ --legacy-env Use legacy environments [boolean]
58
62
 
59
63
  Options:
60
- -l, --local Run on my machine [boolean] [default: false]
61
- --env Perform on a specific environment [string]
64
+ -e, --env Perform on a specific environment [string]
62
65
  --preview Interact with a preview namespace [boolean]
63
66
 
64
67
  Not enough non-option arguments: got 0, need at least 1"
@@ -81,13 +84,13 @@ describe("wrangler", () => {
81
84
  namespace The name of the new namespace [string] [required]
82
85
 
83
86
  Flags:
84
- -c, --config Path to .toml configuration file [string]
85
- -h, --help Show help [boolean]
86
- -v, --version Show version number [boolean]
87
+ -c, --config Path to .toml configuration file [string]
88
+ -h, --help Show help [boolean]
89
+ -v, --version Show version number [boolean]
90
+ --legacy-env Use legacy environments [boolean]
87
91
 
88
92
  Options:
89
- -l, --local Run on my machine [boolean] [default: false]
90
- --env Perform on a specific environment [string]
93
+ -e, --env Perform on a specific environment [string]
91
94
  --preview Interact with a preview namespace [boolean]
92
95
 
93
96
  Unexpected additional positional arguments \\"def ghi\\"."
@@ -111,13 +114,13 @@ describe("wrangler", () => {
111
114
  namespace The name of the new namespace [string] [required]
112
115
 
113
116
  Flags:
114
- -c, --config Path to .toml configuration file [string]
115
- -h, --help Show help [boolean]
116
- -v, --version Show version number [boolean]
117
+ -c, --config Path to .toml configuration file [string]
118
+ -h, --help Show help [boolean]
119
+ -v, --version Show version number [boolean]
120
+ --legacy-env Use legacy environments [boolean]
117
121
 
118
122
  Options:
119
- -l, --local Run on my machine [boolean] [default: false]
120
- --env Perform on a specific environment [string]
123
+ -e, --env Perform on a specific environment [string]
121
124
  --preview Interact with a preview namespace [boolean]
122
125
 
123
126
  The namespace binding name \\"abc-def\\" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number."
@@ -275,15 +278,15 @@ describe("wrangler", () => {
275
278
  Deletes a given namespace.
276
279
 
277
280
  Flags:
278
- -c, --config Path to .toml configuration file [string]
279
- -h, --help Show help [boolean]
280
- -v, --version Show version number [boolean]
281
+ -c, --config Path to .toml configuration file [string]
282
+ -h, --help Show help [boolean]
283
+ -v, --version Show version number [boolean]
284
+ --legacy-env Use legacy environments [boolean]
281
285
 
282
286
  Options:
283
- -l, --local Run on my machine [boolean] [default: false]
284
287
  --binding The name of the namespace to delete [string]
285
288
  --namespace-id The id of the namespace to delete [string]
286
- --env Perform on a specific environment [string]
289
+ -e, --env Perform on a specific environment [string]
287
290
  --preview Interact with a preview namespace [boolean]
288
291
 
289
292
  Not able to delete namespace.
@@ -318,10 +321,7 @@ describe("wrangler", () => {
318
321
  describe("put", () => {
319
322
  function mockKeyPutRequest(
320
323
  expectedNamespaceId: string,
321
- expectedKey: string,
322
- expectedValue: string,
323
- expiration?: number,
324
- expirationTtl?: number
324
+ expectedKV: KeyValue
325
325
  ) {
326
326
  const requests = { count: 0 };
327
327
  setMockResponse(
@@ -331,15 +331,19 @@ describe("wrangler", () => {
331
331
  requests.count++;
332
332
  expect(accountId).toEqual("some-account-id");
333
333
  expect(namespaceId).toEqual(expectedNamespaceId);
334
- expect(key).toEqual(expectedKey);
335
- expect(body).toEqual(expectedValue);
336
- if (expiration !== undefined) {
337
- expect(query.get("expiration")).toEqual(`${expiration}`);
334
+ expect(key).toEqual(expectedKV.key);
335
+ expect(body).toEqual(expectedKV.value);
336
+ if (expectedKV.expiration !== undefined) {
337
+ expect(query.get("expiration")).toEqual(
338
+ `${expectedKV.expiration}`
339
+ );
338
340
  } else {
339
341
  expect(query.has("expiration")).toBe(false);
340
342
  }
341
- if (expirationTtl) {
342
- expect(query.get("expiration_ttl")).toEqual(`${expirationTtl}`);
343
+ if (expectedKV.expiration_ttl) {
344
+ expect(query.get("expiration_ttl")).toEqual(
345
+ `${expectedKV.expiration_ttl}`
346
+ );
343
347
  } else {
344
348
  expect(query.has("expiration_ttl")).toBe(false);
345
349
  }
@@ -350,11 +354,10 @@ describe("wrangler", () => {
350
354
  }
351
355
 
352
356
  it("should put a key in a given namespace specified by namespace-id", async () => {
353
- const requests = mockKeyPutRequest(
354
- "some-namespace-id",
355
- "my-key",
356
- "my-value"
357
- );
357
+ const requests = mockKeyPutRequest("some-namespace-id", {
358
+ key: "my-key",
359
+ value: "my-value",
360
+ });
358
361
 
359
362
  await runWrangler(
360
363
  "kv:key put my-key my-value --namespace-id some-namespace-id"
@@ -369,7 +372,10 @@ describe("wrangler", () => {
369
372
 
370
373
  it("should put a key in a given namespace specified by binding", async () => {
371
374
  writeWranglerConfig();
372
- const requests = mockKeyPutRequest("bound-id", "my-key", "my-value");
375
+ const requests = mockKeyPutRequest("bound-id", {
376
+ key: "my-key",
377
+ value: "my-value",
378
+ });
373
379
  await runWrangler(
374
380
  "kv:key put my-key my-value --binding someBinding --preview false"
375
381
  );
@@ -383,11 +389,10 @@ describe("wrangler", () => {
383
389
 
384
390
  it("should put a key in a given preview namespace specified by binding", async () => {
385
391
  writeWranglerConfig();
386
- const requests = mockKeyPutRequest(
387
- "preview-bound-id",
388
- "my-key",
389
- "my-value"
390
- );
392
+ const requests = mockKeyPutRequest("preview-bound-id", {
393
+ key: "my-key",
394
+ value: "my-value",
395
+ });
391
396
 
392
397
  await runWrangler(
393
398
  "kv:key put my-key my-value --binding someBinding --preview"
@@ -401,13 +406,12 @@ describe("wrangler", () => {
401
406
  });
402
407
 
403
408
  it("should add expiration and ttl properties when putting a key", async () => {
404
- const requests = mockKeyPutRequest(
405
- "some-namespace-id",
406
- "my-key",
407
- "my-value",
408
- 10,
409
- 20
410
- );
409
+ const requests = mockKeyPutRequest("some-namespace-id", {
410
+ key: "my-key",
411
+ value: "my-value",
412
+ expiration: 10,
413
+ expiration_ttl: 20,
414
+ });
411
415
  await runWrangler(
412
416
  "kv:key put my-key my-value --namespace-id some-namespace-id --expiration 10 --ttl 20"
413
417
  );
@@ -420,11 +424,10 @@ describe("wrangler", () => {
420
424
 
421
425
  it("should put a key to the specified environment in a given namespace", async () => {
422
426
  writeWranglerConfig();
423
- const requests = mockKeyPutRequest(
424
- "env-bound-id",
425
- "my-key",
426
- "my-value"
427
- );
427
+ const requests = mockKeyPutRequest("env-bound-id", {
428
+ key: "my-key",
429
+ value: "my-value",
430
+ });
428
431
  await runWrangler(
429
432
  "kv:key put my-key my-value --binding someBinding --env some-environment --preview false"
430
433
  );
@@ -437,11 +440,10 @@ describe("wrangler", () => {
437
440
 
438
441
  it("should put a key with a value loaded from a given path", async () => {
439
442
  writeFileSync("foo.txt", "file-contents", "utf-8");
440
- const requests = mockKeyPutRequest(
441
- "some-namespace-id",
442
- "my-key",
443
- "file-contents"
444
- );
443
+ const requests = mockKeyPutRequest("some-namespace-id", {
444
+ key: "my-key",
445
+ value: "file-contents",
446
+ });
445
447
  await runWrangler(
446
448
  "kv:key put my-key --namespace-id some-namespace-id --path foo.txt"
447
449
  );
@@ -466,23 +468,23 @@ describe("wrangler", () => {
466
468
  Writes a single key/value pair to the given namespace.
467
469
 
468
470
  Positionals:
469
- key The key to write to. [string] [required]
470
- value The value to write. [string]
471
+ key The key to write to [string] [required]
472
+ value The value to write [string]
471
473
 
472
474
  Flags:
473
- -c, --config Path to .toml configuration file [string]
474
- -h, --help Show help [boolean]
475
- -v, --version Show version number [boolean]
475
+ -c, --config Path to .toml configuration file [string]
476
+ -h, --help Show help [boolean]
477
+ -v, --version Show version number [boolean]
478
+ --legacy-env Use legacy environments [boolean]
476
479
 
477
480
  Options:
478
- -l, --local Run on my machine [boolean] [default: false]
479
- --binding The binding of the namespace to write to. [string]
480
- --namespace-id The id of the namespace to write to. [string]
481
- --env Perform on a specific environment [string]
481
+ --binding The binding of the namespace to write to [string]
482
+ --namespace-id The id of the namespace to write to [string]
483
+ -e, --env Perform on a specific environment [string]
482
484
  --preview Interact with a preview namespace [boolean]
483
- --ttl Time for which the entries should be visible. [number]
485
+ --ttl Time for which the entries should be visible [number]
484
486
  --expiration Time since the UNIX epoch after which the entry expires [number]
485
- --path Read value from the file at a given path. [string]
487
+ --path Read value from the file at a given path [string]
486
488
 
487
489
  Not enough non-option arguments: got 0, need at least 1"
488
490
  `);
@@ -502,23 +504,23 @@ describe("wrangler", () => {
502
504
  Writes a single key/value pair to the given namespace.
503
505
 
504
506
  Positionals:
505
- key The key to write to. [string] [required]
506
- value The value to write. [string]
507
+ key The key to write to [string] [required]
508
+ value The value to write [string]
507
509
 
508
510
  Flags:
509
- -c, --config Path to .toml configuration file [string]
510
- -h, --help Show help [boolean]
511
- -v, --version Show version number [boolean]
511
+ -c, --config Path to .toml configuration file [string]
512
+ -h, --help Show help [boolean]
513
+ -v, --version Show version number [boolean]
514
+ --legacy-env Use legacy environments [boolean]
512
515
 
513
516
  Options:
514
- -l, --local Run on my machine [boolean] [default: false]
515
- --binding The binding of the namespace to write to. [string]
516
- --namespace-id The id of the namespace to write to. [string]
517
- --env Perform on a specific environment [string]
517
+ --binding The binding of the namespace to write to [string]
518
+ --namespace-id The id of the namespace to write to [string]
519
+ -e, --env Perform on a specific environment [string]
518
520
  --preview Interact with a preview namespace [boolean]
519
- --ttl Time for which the entries should be visible. [number]
521
+ --ttl Time for which the entries should be visible [number]
520
522
  --expiration Time since the UNIX epoch after which the entry expires [number]
521
- --path Read value from the file at a given path. [string]
523
+ --path Read value from the file at a given path [string]
522
524
 
523
525
  Exactly one of the arguments binding and namespace-id is required"
524
526
  `);
@@ -538,23 +540,23 @@ describe("wrangler", () => {
538
540
  Writes a single key/value pair to the given namespace.
539
541
 
540
542
  Positionals:
541
- key The key to write to. [string] [required]
542
- value The value to write. [string]
543
+ key The key to write to [string] [required]
544
+ value The value to write [string]
543
545
 
544
546
  Flags:
545
- -c, --config Path to .toml configuration file [string]
546
- -h, --help Show help [boolean]
547
- -v, --version Show version number [boolean]
547
+ -c, --config Path to .toml configuration file [string]
548
+ -h, --help Show help [boolean]
549
+ -v, --version Show version number [boolean]
550
+ --legacy-env Use legacy environments [boolean]
548
551
 
549
552
  Options:
550
- -l, --local Run on my machine [boolean] [default: false]
551
- --binding The binding of the namespace to write to. [string]
552
- --namespace-id The id of the namespace to write to. [string]
553
- --env Perform on a specific environment [string]
553
+ --binding The binding of the namespace to write to [string]
554
+ --namespace-id The id of the namespace to write to [string]
555
+ -e, --env Perform on a specific environment [string]
554
556
  --preview Interact with a preview namespace [boolean]
555
- --ttl Time for which the entries should be visible. [number]
557
+ --ttl Time for which the entries should be visible [number]
556
558
  --expiration Time since the UNIX epoch after which the entry expires [number]
557
- --path Read value from the file at a given path. [string]
559
+ --path Read value from the file at a given path [string]
558
560
 
559
561
  Arguments binding and namespace-id are mutually exclusive"
560
562
  `);
@@ -574,23 +576,23 @@ describe("wrangler", () => {
574
576
  Writes a single key/value pair to the given namespace.
575
577
 
576
578
  Positionals:
577
- key The key to write to. [string] [required]
578
- value The value to write. [string]
579
+ key The key to write to [string] [required]
580
+ value The value to write [string]
579
581
 
580
582
  Flags:
581
- -c, --config Path to .toml configuration file [string]
582
- -h, --help Show help [boolean]
583
- -v, --version Show version number [boolean]
583
+ -c, --config Path to .toml configuration file [string]
584
+ -h, --help Show help [boolean]
585
+ -v, --version Show version number [boolean]
586
+ --legacy-env Use legacy environments [boolean]
584
587
 
585
588
  Options:
586
- -l, --local Run on my machine [boolean] [default: false]
587
- --binding The binding of the namespace to write to. [string]
588
- --namespace-id The id of the namespace to write to. [string]
589
- --env Perform on a specific environment [string]
589
+ --binding The binding of the namespace to write to [string]
590
+ --namespace-id The id of the namespace to write to [string]
591
+ -e, --env Perform on a specific environment [string]
590
592
  --preview Interact with a preview namespace [boolean]
591
- --ttl Time for which the entries should be visible. [number]
593
+ --ttl Time for which the entries should be visible [number]
592
594
  --expiration Time since the UNIX epoch after which the entry expires [number]
593
- --path Read value from the file at a given path. [string]
595
+ --path Read value from the file at a given path [string]
594
596
 
595
597
  Exactly one of the arguments value and path is required"
596
598
  `);
@@ -610,23 +612,23 @@ describe("wrangler", () => {
610
612
  Writes a single key/value pair to the given namespace.
611
613
 
612
614
  Positionals:
613
- key The key to write to. [string] [required]
614
- value The value to write. [string]
615
+ key The key to write to [string] [required]
616
+ value The value to write [string]
615
617
 
616
618
  Flags:
617
- -c, --config Path to .toml configuration file [string]
618
- -h, --help Show help [boolean]
619
- -v, --version Show version number [boolean]
619
+ -c, --config Path to .toml configuration file [string]
620
+ -h, --help Show help [boolean]
621
+ -v, --version Show version number [boolean]
622
+ --legacy-env Use legacy environments [boolean]
620
623
 
621
624
  Options:
622
- -l, --local Run on my machine [boolean] [default: false]
623
- --binding The binding of the namespace to write to. [string]
624
- --namespace-id The id of the namespace to write to. [string]
625
- --env Perform on a specific environment [string]
625
+ --binding The binding of the namespace to write to [string]
626
+ --namespace-id The id of the namespace to write to [string]
627
+ -e, --env Perform on a specific environment [string]
626
628
  --preview Interact with a preview namespace [boolean]
627
- --ttl Time for which the entries should be visible. [number]
629
+ --ttl Time for which the entries should be visible [number]
628
630
  --expiration Time since the UNIX epoch after which the entry expires [number]
629
- --path Read value from the file at a given path. [string]
631
+ --path Read value from the file at a given path [string]
630
632
 
631
633
  Arguments value and path are mutually exclusive"
632
634
  `);
@@ -644,18 +646,16 @@ describe("wrangler", () => {
644
646
  expect(std.err).toMatchInlineSnapshot(`
645
647
  "A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
646
648
 
647
- %s
648
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
649
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
649
650
  `);
650
651
  });
651
652
 
652
653
  it("should error if a given binding has both preview and non-preview and --preview is not specified", async () => {
653
654
  writeWranglerConfig();
654
- const requests = mockKeyPutRequest(
655
- "preview-bound-id",
656
- "my-key",
657
- "my-value"
658
- );
655
+ const requests = mockKeyPutRequest("preview-bound-id", {
656
+ key: "my-key",
657
+ value: "my-value",
658
+ });
659
659
  await expect(
660
660
  runWrangler("kv:key put my-key my-value --binding someBinding")
661
661
  ).rejects.toThrowErrorMatchingInlineSnapshot(
@@ -665,8 +665,7 @@ describe("wrangler", () => {
665
665
  expect(std.err).toMatchInlineSnapshot(`
666
666
  "someBinding has both a namespace ID and a preview ID. Specify \\"--preview\\" or \\"--preview false\\" to avoid writing data to the wrong namespace.
667
667
 
668
- %s
669
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
668
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
670
669
  `);
671
670
  expect(requests.count).toEqual(0);
672
671
  });
@@ -674,26 +673,26 @@ describe("wrangler", () => {
674
673
 
675
674
  describe("list", () => {
676
675
  it("should list the keys of a namespace specified by namespace-id", async () => {
677
- const keys = ["key-1", "key-2", "key-3"];
676
+ const keys = [
677
+ { name: "key-1" },
678
+ { name: "key-2", expiration: 123456789 },
679
+ { name: "key-3", expiration_ttl: 666 },
680
+ ];
678
681
  mockKeyListRequest("some-namespace-id", keys);
679
682
  await runWrangler("kv:key list --namespace-id some-namespace-id");
680
683
  expect(std.err).toMatchInlineSnapshot(`""`);
681
684
  expect(std.out).toMatchInlineSnapshot(`
682
685
  "[
683
686
  {
684
- \\"name\\": \\"key-1\\",
685
- \\"expiration\\": 123456789,
686
- \\"metadata\\": {}
687
+ \\"name\\": \\"key-1\\"
687
688
  },
688
689
  {
689
690
  \\"name\\": \\"key-2\\",
690
- \\"expiration\\": 123456789,
691
- \\"metadata\\": {}
691
+ \\"expiration\\": 123456789
692
692
  },
693
693
  {
694
694
  \\"name\\": \\"key-3\\",
695
- \\"expiration\\": 123456789,
696
- \\"metadata\\": {}
695
+ \\"expiration_ttl\\": 666
697
696
  }
698
697
  ]"
699
698
  `);
@@ -701,7 +700,7 @@ describe("wrangler", () => {
701
700
 
702
701
  it("should list the keys of a namespace specified by binding", async () => {
703
702
  writeWranglerConfig();
704
- const keys = ["key-1", "key-2", "key-3"];
703
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
705
704
  mockKeyListRequest("bound-id", keys);
706
705
 
707
706
  await runWrangler("kv:key list --binding someBinding");
@@ -709,19 +708,13 @@ describe("wrangler", () => {
709
708
  expect(std.out).toMatchInlineSnapshot(`
710
709
  "[
711
710
  {
712
- \\"name\\": \\"key-1\\",
713
- \\"expiration\\": 123456789,
714
- \\"metadata\\": {}
711
+ \\"name\\": \\"key-1\\"
715
712
  },
716
713
  {
717
- \\"name\\": \\"key-2\\",
718
- \\"expiration\\": 123456789,
719
- \\"metadata\\": {}
714
+ \\"name\\": \\"key-2\\"
720
715
  },
721
716
  {
722
- \\"name\\": \\"key-3\\",
723
- \\"expiration\\": 123456789,
724
- \\"metadata\\": {}
717
+ \\"name\\": \\"key-3\\"
725
718
  }
726
719
  ]"
727
720
  `);
@@ -729,26 +722,20 @@ describe("wrangler", () => {
729
722
 
730
723
  it("should list the keys of a preview namespace specified by binding", async () => {
731
724
  writeWranglerConfig();
732
- const keys = ["key-1", "key-2", "key-3"];
725
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
733
726
  mockKeyListRequest("preview-bound-id", keys);
734
727
  await runWrangler("kv:key list --binding someBinding --preview");
735
728
  expect(std.err).toMatchInlineSnapshot(`""`);
736
729
  expect(std.out).toMatchInlineSnapshot(`
737
730
  "[
738
731
  {
739
- \\"name\\": \\"key-1\\",
740
- \\"expiration\\": 123456789,
741
- \\"metadata\\": {}
732
+ \\"name\\": \\"key-1\\"
742
733
  },
743
734
  {
744
- \\"name\\": \\"key-2\\",
745
- \\"expiration\\": 123456789,
746
- \\"metadata\\": {}
735
+ \\"name\\": \\"key-2\\"
747
736
  },
748
737
  {
749
- \\"name\\": \\"key-3\\",
750
- \\"expiration\\": 123456789,
751
- \\"metadata\\": {}
738
+ \\"name\\": \\"key-3\\"
752
739
  }
753
740
  ]"
754
741
  `);
@@ -756,7 +743,7 @@ describe("wrangler", () => {
756
743
 
757
744
  it("should list the keys of a namespace specified by binding, in a given environment", async () => {
758
745
  writeWranglerConfig();
759
- const keys = ["key-1", "key-2", "key-3"];
746
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
760
747
  mockKeyListRequest("env-bound-id", keys);
761
748
  await runWrangler(
762
749
  "kv:key list --binding someBinding --env some-environment"
@@ -765,19 +752,13 @@ describe("wrangler", () => {
765
752
  expect(std.out).toMatchInlineSnapshot(`
766
753
  "[
767
754
  {
768
- \\"name\\": \\"key-1\\",
769
- \\"expiration\\": 123456789,
770
- \\"metadata\\": {}
755
+ \\"name\\": \\"key-1\\"
771
756
  },
772
757
  {
773
- \\"name\\": \\"key-2\\",
774
- \\"expiration\\": 123456789,
775
- \\"metadata\\": {}
758
+ \\"name\\": \\"key-2\\"
776
759
  },
777
760
  {
778
- \\"name\\": \\"key-3\\",
779
- \\"expiration\\": 123456789,
780
- \\"metadata\\": {}
761
+ \\"name\\": \\"key-3\\"
781
762
  }
782
763
  ]"
783
764
  `);
@@ -785,7 +766,7 @@ describe("wrangler", () => {
785
766
 
786
767
  it("should list the keys of a preview namespace specified by binding, in a given environment", async () => {
787
768
  writeWranglerConfig();
788
- const keys = ["key-1", "key-2", "key-3"];
769
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
789
770
  mockKeyListRequest("preview-env-bound-id", keys);
790
771
  await runWrangler(
791
772
  "kv:key list --binding someBinding --preview --env some-environment"
@@ -794,19 +775,13 @@ describe("wrangler", () => {
794
775
  expect(std.out).toMatchInlineSnapshot(`
795
776
  "[
796
777
  {
797
- \\"name\\": \\"key-1\\",
798
- \\"expiration\\": 123456789,
799
- \\"metadata\\": {}
778
+ \\"name\\": \\"key-1\\"
800
779
  },
801
780
  {
802
- \\"name\\": \\"key-2\\",
803
- \\"expiration\\": 123456789,
804
- \\"metadata\\": {}
781
+ \\"name\\": \\"key-2\\"
805
782
  },
806
783
  {
807
- \\"name\\": \\"key-3\\",
808
- \\"expiration\\": 123456789,
809
- \\"metadata\\": {}
784
+ \\"name\\": \\"key-3\\"
810
785
  }
811
786
  ]"
812
787
  `);
@@ -823,9 +798,9 @@ describe("wrangler", () => {
823
798
  describe(`cursor - ${blankCursorValue}`, () => {
824
799
  it("should make multiple requests for paginated results", async () => {
825
800
  // Create a lot of mock keys, so that the fetch requests will be paginated
826
- const keys: string[] = [];
801
+ const keys: NamespaceKeyInfo[] = [];
827
802
  for (let i = 0; i < 550; i++) {
828
- keys.push("key-" + i);
803
+ keys.push({ name: "key-" + i });
829
804
  }
830
805
  // Ask for the keys in pages of size 100.
831
806
  const requests = mockKeyListRequest(
@@ -838,7 +813,7 @@ describe("wrangler", () => {
838
813
  "kv:key list --namespace-id some-namespace-id --limit 100"
839
814
  );
840
815
  expect(std.err).toMatchInlineSnapshot(`""`);
841
- expect(JSON.parse(std.out).map((k) => k.name)).toEqual(keys);
816
+ expect(JSON.parse(std.out)).toEqual(keys);
842
817
  expect(requests.count).toEqual(6);
843
818
  });
844
819
  });
@@ -854,35 +829,20 @@ describe("wrangler", () => {
854
829
  expect(std.err).toMatchInlineSnapshot(`
855
830
  "A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
856
831
 
857
- %s
858
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
832
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
859
833
  `);
860
834
  expect(std.out).toMatchInlineSnapshot(`""`);
861
835
  });
862
836
  });
863
837
 
864
838
  describe("get", () => {
865
- function mockKeyGetRequest(
866
- expectedNamespaceId: string,
867
- expectedKey: string,
868
- expectedValue: string
869
- ) {
870
- const requests = { count: 0 };
871
- setMockRawResponse(
872
- "/accounts/:accountId/storage/kv/namespaces/:namespaceId/values/:key",
873
- ([_url, accountId, namespaceId, key]) => {
874
- requests.count++;
875
- expect(accountId).toEqual("some-account-id");
876
- expect(namespaceId).toEqual(expectedNamespaceId);
877
- expect(key).toEqual(expectedKey);
878
- return expectedValue;
879
- }
880
- );
881
- return requests;
882
- }
839
+ afterEach(() => {
840
+ unsetMockFetchKVGetValues();
841
+ });
883
842
 
884
843
  it("should get a key in a given namespace specified by namespace-id", async () => {
885
- const requests = mockKeyGetRequest(
844
+ setMockFetchKVGetValue(
845
+ "some-account-id",
886
846
  "some-namespace-id",
887
847
  "my-key",
888
848
  "my-value"
@@ -890,23 +850,27 @@ describe("wrangler", () => {
890
850
  await runWrangler("kv:key get my-key --namespace-id some-namespace-id");
891
851
  expect(std.out).toMatchInlineSnapshot(`"my-value"`);
892
852
  expect(std.err).toMatchInlineSnapshot(`""`);
893
- expect(requests.count).toEqual(1);
894
853
  });
895
854
 
896
855
  it("should get a key in a given namespace specified by binding", async () => {
897
856
  writeWranglerConfig();
898
- const requests = mockKeyGetRequest("bound-id", "my-key", "my-value");
857
+ setMockFetchKVGetValue(
858
+ "some-account-id",
859
+ "bound-id",
860
+ "my-key",
861
+ "my-value"
862
+ );
899
863
  await runWrangler(
900
864
  "kv:key get my-key --binding someBinding --preview false"
901
865
  );
902
866
  expect(std.out).toMatchInlineSnapshot(`"my-value"`);
903
867
  expect(std.err).toMatchInlineSnapshot(`""`);
904
- expect(requests.count).toEqual(1);
905
868
  });
906
869
 
907
870
  it("should get a key in a given preview namespace specified by binding", async () => {
908
871
  writeWranglerConfig();
909
- const requests = mockKeyGetRequest(
872
+ setMockFetchKVGetValue(
873
+ "some-account-id",
910
874
  "preview-bound-id",
911
875
  "my-key",
912
876
  "my-value"
@@ -914,12 +878,12 @@ describe("wrangler", () => {
914
878
  await runWrangler("kv:key get my-key --binding someBinding --preview");
915
879
  expect(std.out).toMatchInlineSnapshot(`"my-value"`);
916
880
  expect(std.err).toMatchInlineSnapshot(`""`);
917
- expect(requests.count).toEqual(1);
918
881
  });
919
882
 
920
883
  it("should get a key for the specified environment in a given namespace", async () => {
921
884
  writeWranglerConfig();
922
- const requests = mockKeyGetRequest(
885
+ setMockFetchKVGetValue(
886
+ "some-account-id",
923
887
  "env-bound-id",
924
888
  "my-key",
925
889
  "my-value"
@@ -929,7 +893,6 @@ describe("wrangler", () => {
929
893
  );
930
894
  expect(std.out).toMatchInlineSnapshot(`"my-value"`);
931
895
  expect(std.err).toMatchInlineSnapshot(`""`);
932
- expect(requests.count).toEqual(1);
933
896
  });
934
897
 
935
898
  it("should error if no key is provided", async () => {
@@ -948,15 +911,15 @@ describe("wrangler", () => {
948
911
  key The key value to get. [string] [required]
949
912
 
950
913
  Flags:
951
- -c, --config Path to .toml configuration file [string]
952
- -h, --help Show help [boolean]
953
- -v, --version Show version number [boolean]
914
+ -c, --config Path to .toml configuration file [string]
915
+ -h, --help Show help [boolean]
916
+ -v, --version Show version number [boolean]
917
+ --legacy-env Use legacy environments [boolean]
954
918
 
955
919
  Options:
956
- -l, --local Run on my machine [boolean] [default: false]
957
920
  --binding The name of the namespace to get from [string]
958
921
  --namespace-id The id of the namespace to get from [string]
959
- --env Perform on a specific environment [string]
922
+ -e, --env Perform on a specific environment [string]
960
923
  --preview Interact with a preview namespace [boolean] [default: false]
961
924
 
962
925
  Not enough non-option arguments: got 0, need at least 1"
@@ -979,15 +942,15 @@ describe("wrangler", () => {
979
942
  key The key value to get. [string] [required]
980
943
 
981
944
  Flags:
982
- -c, --config Path to .toml configuration file [string]
983
- -h, --help Show help [boolean]
984
- -v, --version Show version number [boolean]
945
+ -c, --config Path to .toml configuration file [string]
946
+ -h, --help Show help [boolean]
947
+ -v, --version Show version number [boolean]
948
+ --legacy-env Use legacy environments [boolean]
985
949
 
986
950
  Options:
987
- -l, --local Run on my machine [boolean] [default: false]
988
951
  --binding The name of the namespace to get from [string]
989
952
  --namespace-id The id of the namespace to get from [string]
990
- --env Perform on a specific environment [string]
953
+ -e, --env Perform on a specific environment [string]
991
954
  --preview Interact with a preview namespace [boolean] [default: false]
992
955
 
993
956
  Exactly one of the arguments binding and namespace-id is required"
@@ -1011,15 +974,15 @@ describe("wrangler", () => {
1011
974
  key The key value to get. [string] [required]
1012
975
 
1013
976
  Flags:
1014
- -c, --config Path to .toml configuration file [string]
1015
- -h, --help Show help [boolean]
1016
- -v, --version Show version number [boolean]
977
+ -c, --config Path to .toml configuration file [string]
978
+ -h, --help Show help [boolean]
979
+ -v, --version Show version number [boolean]
980
+ --legacy-env Use legacy environments [boolean]
1017
981
 
1018
982
  Options:
1019
- -l, --local Run on my machine [boolean] [default: false]
1020
983
  --binding The name of the namespace to get from [string]
1021
984
  --namespace-id The id of the namespace to get from [string]
1022
- --env Perform on a specific environment [string]
985
+ -e, --env Perform on a specific environment [string]
1023
986
  --preview Interact with a preview namespace [boolean] [default: false]
1024
987
 
1025
988
  Arguments binding and namespace-id are mutually exclusive"
@@ -1037,8 +1000,7 @@ describe("wrangler", () => {
1037
1000
  expect(std.err).toMatchInlineSnapshot(`
1038
1001
  "A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
1039
1002
 
1040
- %s
1041
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1003
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1042
1004
  `);
1043
1005
  });
1044
1006
  });
@@ -1100,8 +1062,7 @@ describe("wrangler", () => {
1100
1062
  expect(std.err).toMatchInlineSnapshot(`
1101
1063
  "A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
1102
1064
 
1103
- %s
1104
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1065
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1105
1066
  `);
1106
1067
  });
1107
1068
 
@@ -1128,6 +1089,278 @@ describe("wrangler", () => {
1128
1089
  });
1129
1090
  });
1130
1091
  });
1092
+
1093
+ describe("kv:bulk", () => {
1094
+ describe("put", () => {
1095
+ function mockPutRequest(
1096
+ expectedNamespaceId: string,
1097
+ expectedKeyValues: KeyValue[]
1098
+ ) {
1099
+ const requests = { count: 0 };
1100
+ setMockResponse(
1101
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
1102
+ "PUT",
1103
+ ([_url, accountId, namespaceId], { body }) => {
1104
+ requests.count++;
1105
+ expect(accountId).toEqual("some-account-id");
1106
+ expect(namespaceId).toEqual(expectedNamespaceId);
1107
+ expect(JSON.parse(body as string)).toEqual(
1108
+ expectedKeyValues.slice(
1109
+ (requests.count - 1) * 5000,
1110
+ requests.count * 5000
1111
+ )
1112
+ );
1113
+ return null;
1114
+ }
1115
+ );
1116
+ return requests;
1117
+ }
1118
+
1119
+ it("should put the key-values parsed from a file", async () => {
1120
+ const keyValues: KeyValue[] = [
1121
+ { key: "someKey1", value: "someValue1" },
1122
+ { key: "ns:someKey2", value: "123", base64: true },
1123
+ { key: "someKey3", value: "someValue3", expiration: 100 },
1124
+ { key: "someKey4", value: "someValue4", expiration_ttl: 500 },
1125
+ ];
1126
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1127
+ const requests = mockPutRequest("some-namespace-id", keyValues);
1128
+ await runWrangler(
1129
+ `kv:bulk put --namespace-id some-namespace-id keys.json`
1130
+ );
1131
+ expect(requests.count).toEqual(1);
1132
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1133
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1134
+ expect(std.err).toMatchInlineSnapshot(`""`);
1135
+ });
1136
+
1137
+ it("should put the key-values in batches of 5000 parsed from a file", async () => {
1138
+ const keyValues: KeyValue[] = new Array(12000).fill({
1139
+ key: "someKey1",
1140
+ value: "someValue1",
1141
+ });
1142
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1143
+ const requests = mockPutRequest("some-namespace-id", keyValues);
1144
+ await runWrangler(
1145
+ `kv:bulk put --namespace-id some-namespace-id keys.json`
1146
+ );
1147
+ expect(requests.count).toEqual(3);
1148
+ expect(std.out).toMatchInlineSnapshot(`
1149
+ "Uploaded 0 of 12000.
1150
+ Uploaded 5000 of 12000.
1151
+ Uploaded 10000 of 12000.
1152
+ Uploaded 12000 of 12000.
1153
+ Success!"
1154
+ `);
1155
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1156
+ expect(std.err).toMatchInlineSnapshot(`""`);
1157
+ });
1158
+
1159
+ it("should error if the file is not a JSON array", async () => {
1160
+ const keyValues = { key: "someKey1", value: "someValue1" };
1161
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1162
+ await expect(
1163
+ runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1164
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1165
+ "Unexpected JSON input from \\"keys.json\\".
1166
+ Expected an array of key-value objects but got type \\"object\\"."
1167
+ `);
1168
+ expect(std.out).toMatchInlineSnapshot(`""`);
1169
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1170
+ });
1171
+
1172
+ it("should error if the array contains items that are not key-value objects", async () => {
1173
+ const keyValues = [
1174
+ 123,
1175
+ "a string",
1176
+ { key: "someKey" },
1177
+ { value: "someValue" },
1178
+ { key: "someKey1", value: "someValue1", invalid: true },
1179
+ ];
1180
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1181
+ await expect(
1182
+ runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1183
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1184
+ "Unexpected JSON input from \\"keys.json\\".
1185
+ Each item in the array should be an object that matches:
1186
+
1187
+ interface KeyValue {
1188
+ key: string;
1189
+ value: string;
1190
+ expiration?: number;
1191
+ expiration_ttl?: number;
1192
+ metadata?: object;
1193
+ base64?: boolean;
1194
+ }
1195
+
1196
+ The item at index 0 is type: \\"number\\" - 123
1197
+ The item at index 1 is type: \\"string\\" - \\"a string\\"
1198
+ The item at index 2 is {\\"key\\":\\"someKey\\"}
1199
+ The item at index 3 is {\\"value\\":\\"someValue\\"}"
1200
+ `);
1201
+
1202
+ expect(std.out).toMatchInlineSnapshot(`""`);
1203
+ expect(std.warn).toMatchInlineSnapshot(`
1204
+ "Unexpected key-value properties in \\"keys.json\\".
1205
+ The item at index 4 contains unexpected properties: [\\"invalid\\"]."
1206
+ `);
1207
+ });
1208
+ });
1209
+
1210
+ describe("delete", () => {
1211
+ function mockDeleteRequest(
1212
+ expectedNamespaceId: string,
1213
+ expectedKeys: string[]
1214
+ ) {
1215
+ const requests = { count: 0 };
1216
+ setMockResponse(
1217
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
1218
+ "DELETE",
1219
+ ([_url, accountId, namespaceId], { headers, body }) => {
1220
+ requests.count++;
1221
+ expect(accountId).toEqual("some-account-id");
1222
+ expect(namespaceId).toEqual(expectedNamespaceId);
1223
+ expect(new Headers(headers ?? []).get("Content-Type")).toEqual(
1224
+ "application/json"
1225
+ );
1226
+ expect(JSON.parse(body as string)).toEqual(
1227
+ expectedKeys.slice(
1228
+ (requests.count - 1) * 5000,
1229
+ requests.count * 5000
1230
+ )
1231
+ );
1232
+ return null;
1233
+ }
1234
+ );
1235
+ return requests;
1236
+ }
1237
+
1238
+ it("should delete the keys parsed from a file", async () => {
1239
+ const keys = ["someKey1", "ns:someKey2"];
1240
+ writeFileSync("./keys.json", JSON.stringify(keys));
1241
+ mockConfirm({
1242
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1243
+ result: true,
1244
+ });
1245
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1246
+ await runWrangler(
1247
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1248
+ );
1249
+ expect(requests.count).toEqual(1);
1250
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1251
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1252
+ expect(std.err).toMatchInlineSnapshot(`""`);
1253
+ });
1254
+
1255
+ it("should delete the keys in batches of 5000 parsed from a file", async () => {
1256
+ const keys = new Array(12000).fill("some-key");
1257
+ writeFileSync("./keys.json", JSON.stringify(keys));
1258
+ mockConfirm({
1259
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1260
+ result: true,
1261
+ });
1262
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1263
+ await runWrangler(
1264
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1265
+ );
1266
+ expect(requests.count).toEqual(3);
1267
+ expect(std.out).toMatchInlineSnapshot(`
1268
+ "Deleted 0 of 12000.
1269
+ Deleted 5000 of 12000.
1270
+ Deleted 10000 of 12000.
1271
+ Deleted 12000 of 12000.
1272
+ Success!"
1273
+ `);
1274
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1275
+ expect(std.err).toMatchInlineSnapshot(`""`);
1276
+ });
1277
+
1278
+ it("should not delete the keys if the user confirms no", async () => {
1279
+ const keys = ["someKey1", "ns:someKey2"];
1280
+ writeFileSync("./keys.json", JSON.stringify(keys));
1281
+ mockConfirm({
1282
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1283
+ result: false,
1284
+ });
1285
+ await runWrangler(
1286
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1287
+ );
1288
+ expect(std.out).toMatchInlineSnapshot(
1289
+ `"Not deleting keys read from \\"keys.json\\"."`
1290
+ );
1291
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1292
+ expect(std.err).toMatchInlineSnapshot(`""`);
1293
+ });
1294
+
1295
+ it("should delete the keys without asking if --force is provided", async () => {
1296
+ const keys = ["someKey1", "ns:someKey2"];
1297
+ writeFileSync("./keys.json", JSON.stringify(keys));
1298
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1299
+ await runWrangler(
1300
+ `kv:bulk delete --namespace-id some-namespace-id keys.json --force`
1301
+ );
1302
+ expect(requests.count).toEqual(1);
1303
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1304
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1305
+ expect(std.err).toMatchInlineSnapshot(`""`);
1306
+ });
1307
+
1308
+ it("should delete the keys without asking if -f is provided", async () => {
1309
+ const keys = ["someKey1", "ns:someKey2"];
1310
+ writeFileSync("./keys.json", JSON.stringify(keys));
1311
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1312
+ await runWrangler(
1313
+ `kv:bulk delete --namespace-id some-namespace-id keys.json -f`
1314
+ );
1315
+ expect(requests.count).toEqual(1);
1316
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1317
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1318
+ expect(std.err).toMatchInlineSnapshot(`""`);
1319
+ });
1320
+
1321
+ it("should error if the file is not a JSON array", async () => {
1322
+ const keys = 12354;
1323
+ writeFileSync("./keys.json", JSON.stringify(keys));
1324
+ mockConfirm({
1325
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1326
+ result: true,
1327
+ });
1328
+ await expect(
1329
+ runWrangler(
1330
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1331
+ )
1332
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1333
+ "Unexpected JSON input from \\"keys.json\\".
1334
+ Expected an array of strings but got:
1335
+ 12354"
1336
+ `);
1337
+ expect(std.out).toMatchInlineSnapshot(`""`);
1338
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1339
+ });
1340
+
1341
+ it("should error if the file contains non-string items", async () => {
1342
+ const keys = ["good", 12354, { key: "someKey" }, null];
1343
+ writeFileSync("./keys.json", JSON.stringify(keys));
1344
+ mockConfirm({
1345
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1346
+ result: true,
1347
+ });
1348
+ await expect(
1349
+ runWrangler(
1350
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1351
+ )
1352
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1353
+ "Unexpected JSON input from \\"keys.json\\".
1354
+ Expected an array of strings.
1355
+ The item at index 1 is type: \\"number\\" - 12354
1356
+ The item at index 2 is type: \\"object\\" - {\\"key\\":\\"someKey\\"}
1357
+ The item at index 3 is type: \\"object\\" - null"
1358
+ `);
1359
+ expect(std.out).toMatchInlineSnapshot(`""`);
1360
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1361
+ });
1362
+ });
1363
+ });
1131
1364
  });
1132
1365
 
1133
1366
  function writeWranglerConfig() {