wrangler 0.0.0-e2a26a0 → 0.0.0-e322475

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 (157) hide show
  1. package/Cloudflare_CA.pem +18 -0
  2. package/README.md +27 -14
  3. package/bin/wrangler.js +49 -5
  4. package/kv-asset-handler.js +1 -0
  5. package/miniflare-dist/index.mjs +4886 -0
  6. package/package.json +54 -27
  7. package/pages/functions/buildPlugin.ts +105 -0
  8. package/pages/functions/buildWorker.ts +93 -4
  9. package/pages/functions/filepath-routing.test.ts +223 -36
  10. package/pages/functions/filepath-routing.ts +78 -120
  11. package/pages/functions/routes.ts +13 -17
  12. package/pages/functions/template-plugin.ts +147 -0
  13. package/pages/functions/template-worker.ts +24 -17
  14. package/src/__tests__/config-cache.test.ts +36 -0
  15. package/src/__tests__/configuration.test.ts +3548 -0
  16. package/src/__tests__/dev.test.tsx +1049 -65
  17. package/src/__tests__/guess-worker-format.test.ts +85 -0
  18. package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
  19. package/src/__tests__/helpers/mock-account-id.ts +26 -8
  20. package/src/__tests__/helpers/mock-bin.ts +4 -1
  21. package/src/__tests__/helpers/mock-cfetch.ts +12 -8
  22. package/src/__tests__/helpers/mock-console.ts +49 -8
  23. package/src/__tests__/helpers/mock-dialogs.ts +99 -11
  24. package/src/__tests__/helpers/mock-http-server.ts +46 -0
  25. package/src/__tests__/helpers/mock-istty.ts +27 -0
  26. package/src/__tests__/helpers/mock-kv.ts +9 -16
  27. package/src/__tests__/helpers/mock-oauth-flow.ts +255 -0
  28. package/src/__tests__/helpers/mock-process.ts +24 -0
  29. package/src/__tests__/helpers/mock-stdin.ts +103 -0
  30. package/src/__tests__/helpers/mock-web-socket.ts +29 -0
  31. package/src/__tests__/helpers/run-in-tmp.ts +10 -0
  32. package/src/__tests__/helpers/run-wrangler.ts +5 -3
  33. package/src/__tests__/helpers/write-worker-source.ts +31 -0
  34. package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
  35. package/src/__tests__/https-options.test.ts +130 -0
  36. package/src/__tests__/index.test.ts +150 -435
  37. package/src/__tests__/init.test.ts +1992 -0
  38. package/src/__tests__/jest.setup.ts +75 -5
  39. package/src/__tests__/kv.test.ts +634 -253
  40. package/src/__tests__/logger.test.ts +141 -0
  41. package/src/__tests__/package-manager.test.ts +156 -9
  42. package/src/__tests__/pages.test.ts +754 -0
  43. package/src/__tests__/parse.test.ts +330 -0
  44. package/src/__tests__/publish.test.ts +5895 -961
  45. package/src/__tests__/r2.test.ts +233 -0
  46. package/src/__tests__/route.test.ts +45 -0
  47. package/src/__tests__/secret.test.ts +362 -91
  48. package/src/__tests__/tail.test.ts +690 -0
  49. package/src/__tests__/user.test.ts +132 -0
  50. package/src/__tests__/whoami.test.tsx +60 -7
  51. package/src/abort.d.ts +3 -0
  52. package/src/bundle-reporter.tsx +29 -0
  53. package/src/bundle.ts +204 -0
  54. package/src/cfetch/index.ts +27 -8
  55. package/src/cfetch/internal.ts +75 -34
  56. package/src/cli.ts +6 -2
  57. package/src/config/README.md +107 -0
  58. package/src/config/config.ts +243 -0
  59. package/src/config/diagnostics.ts +80 -0
  60. package/src/config/environment.ts +420 -0
  61. package/src/config/index.ts +225 -0
  62. package/src/config/validation-helpers.ts +584 -0
  63. package/src/config/validation.ts +1580 -0
  64. package/src/config-cache.ts +45 -0
  65. package/src/create-worker-preview.ts +185 -0
  66. package/src/create-worker-upload-form.ts +254 -0
  67. package/src/dev/dev-vars.ts +36 -0
  68. package/src/dev/dev.tsx +399 -0
  69. package/src/dev/local.tsx +321 -0
  70. package/src/dev/remote.tsx +249 -0
  71. package/src/dev/use-esbuild.ts +112 -0
  72. package/src/dialogs.tsx +64 -6
  73. package/src/durable.ts +102 -0
  74. package/src/entry.ts +328 -0
  75. package/src/environment-variables.ts +35 -0
  76. package/src/errors.ts +11 -0
  77. package/src/generate-auth-url.ts +33 -0
  78. package/src/generate-random-state.ts +16 -0
  79. package/src/git-client.ts +42 -0
  80. package/src/https-options.ts +123 -0
  81. package/src/index.tsx +1804 -1009
  82. package/src/inspect.ts +80 -14
  83. package/src/intl-polyfill.d.ts +139 -0
  84. package/src/{kv.tsx → kv.ts} +193 -69
  85. package/src/logger.ts +73 -0
  86. package/src/miniflare-cli/README.md +30 -0
  87. package/src/miniflare-cli/enum-keys.ts +17 -0
  88. package/src/miniflare-cli/index.ts +41 -0
  89. package/src/miniflare-cli/request-context.ts +40 -0
  90. package/src/module-collection.ts +226 -31
  91. package/src/open-in-browser.ts +17 -0
  92. package/src/package-manager.ts +79 -25
  93. package/src/pages.tsx +1131 -84
  94. package/src/parse.ts +222 -0
  95. package/src/proxy.ts +176 -70
  96. package/src/publish.ts +637 -308
  97. package/src/r2.ts +50 -0
  98. package/src/selfsigned.d.ts +29 -0
  99. package/src/sites.tsx +185 -57
  100. package/src/tail/filters.ts +279 -0
  101. package/src/tail/index.ts +299 -0
  102. package/src/tail/printing.ts +67 -0
  103. package/src/update-check.ts +19 -0
  104. package/src/user.tsx +349 -166
  105. package/src/whoami.tsx +5 -3
  106. package/src/{api/worker.ts → worker.ts} +65 -39
  107. package/src/zones.ts +73 -0
  108. package/templates/gitignore +171 -0
  109. package/templates/new-worker-scheduled.js +17 -0
  110. package/templates/new-worker-scheduled.ts +32 -0
  111. package/templates/new-worker.js +1 -1
  112. package/templates/new-worker.ts +17 -2
  113. package/templates/no-op-worker.js +10 -0
  114. package/templates/static-asset-facade.js +3 -7
  115. package/templates/tsconfig.json +105 -0
  116. package/wrangler-dist/cli.js +77463 -75999
  117. package/src/__tests__/helpers/mock-user.ts +0 -27
  118. package/src/__tests__/logout.test.ts +0 -50
  119. package/src/api/form_data.ts +0 -134
  120. package/src/api/preview.ts +0 -128
  121. package/src/config.ts +0 -641
  122. package/src/dev.tsx +0 -834
  123. package/src/tail.tsx +0 -73
  124. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  125. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  126. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  127. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  128. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  129. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  130. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  131. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  132. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  133. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  134. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  135. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  136. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  137. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  138. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  139. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  140. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  141. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  142. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  143. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  144. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  145. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  146. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  147. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  148. package/vendor/wrangler-mime/LICENSE +0 -21
  149. package/vendor/wrangler-mime/Mime.js +0 -97
  150. package/vendor/wrangler-mime/README.md +0 -187
  151. package/vendor/wrangler-mime/cli.js +0 -46
  152. package/vendor/wrangler-mime/index.js +0 -4
  153. package/vendor/wrangler-mime/lite.js +0 -4
  154. package/vendor/wrangler-mime/package.json +0 -52
  155. package/vendor/wrangler-mime/types/other.js +0 -1
  156. package/vendor/wrangler-mime/types/standard.js +0 -1
  157. package/wrangler-dist/cli.js.map +0 -7
@@ -1,4 +1,5 @@
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,
@@ -7,19 +8,23 @@ import {
7
8
  setMockFetchKVGetValue,
8
9
  } from "./helpers/mock-cfetch";
9
10
  import { mockConsoleMethods } from "./helpers/mock-console";
11
+ import { clearConfirmMocks, mockConfirm } from "./helpers/mock-dialogs";
10
12
  import { mockKeyListRequest } from "./helpers/mock-kv";
13
+ import { mockProcess } from "./helpers/mock-process";
11
14
  import { runInTempDir } from "./helpers/run-in-tmp";
12
15
  import { runWrangler } from "./helpers/run-wrangler";
13
- import type { KVNamespaceInfo } from "../kv";
16
+ import type { KeyValue, KVNamespaceInfo, NamespaceKeyInfo } from "../kv";
14
17
 
15
18
  describe("wrangler", () => {
16
19
  mockAccountId();
17
20
  mockApiToken();
18
21
  runInTempDir();
19
22
  const std = mockConsoleMethods();
23
+ const proc = mockProcess();
20
24
 
21
25
  afterEach(() => {
22
26
  unsetAllMocks();
27
+ clearConfirmMocks();
23
28
  });
24
29
 
25
30
  describe("kv:namespace", () => {
@@ -43,9 +48,9 @@ describe("wrangler", () => {
43
48
  ).rejects.toThrowErrorMatchingInlineSnapshot(
44
49
  `"Not enough non-option arguments: got 0, need at least 1"`
45
50
  );
46
- expect(std.out).toMatchInlineSnapshot(`""`);
47
- expect(std.err).toMatchInlineSnapshot(`
48
- "wrangler kv:namespace create <namespace>
51
+ expect(std.out).toMatchInlineSnapshot(`
52
+ "
53
+ wrangler kv:namespace create <namespace>
49
54
 
50
55
  Create a new namespace
51
56
 
@@ -58,11 +63,13 @@ describe("wrangler", () => {
58
63
  -v, --version Show version number [boolean]
59
64
 
60
65
  Options:
61
- -l, --local Run on my machine [boolean] [default: false]
62
- --env Perform on a specific environment [string]
63
- --preview Interact with a preview namespace [boolean]
66
+ -e, --env Perform on a specific environment [string]
67
+ --preview Interact with a preview namespace [boolean]"
68
+ `);
69
+ expect(std.err).toMatchInlineSnapshot(`
70
+ "X [ERROR] Not enough non-option arguments: got 0, need at least 1
64
71
 
65
- Not enough non-option arguments: got 0, need at least 1"
72
+ "
66
73
  `);
67
74
  });
68
75
 
@@ -70,11 +77,11 @@ describe("wrangler", () => {
70
77
  await expect(
71
78
  runWrangler("kv:namespace create abc def ghi")
72
79
  ).rejects.toThrowErrorMatchingInlineSnapshot(
73
- `"Unexpected additional positional arguments \\"def ghi\\"."`
80
+ `"Unknown arguments: def, ghi"`
74
81
  );
75
- expect(std.out).toMatchInlineSnapshot(`""`);
76
- expect(std.err).toMatchInlineSnapshot(`
77
- "wrangler kv:namespace create <namespace>
82
+ expect(std.out).toMatchInlineSnapshot(`
83
+ "
84
+ wrangler kv:namespace create <namespace>
78
85
 
79
86
  Create a new namespace
80
87
 
@@ -87,11 +94,13 @@ describe("wrangler", () => {
87
94
  -v, --version Show version number [boolean]
88
95
 
89
96
  Options:
90
- -l, --local Run on my machine [boolean] [default: false]
91
- --env Perform on a specific environment [string]
92
- --preview Interact with a preview namespace [boolean]
97
+ -e, --env Perform on a specific environment [string]
98
+ --preview Interact with a preview namespace [boolean]"
99
+ `);
100
+ expect(std.err).toMatchInlineSnapshot(`
101
+ "X [ERROR] Unknown arguments: def, ghi
93
102
 
94
- Unexpected additional positional arguments \\"def ghi\\"."
103
+ "
95
104
  `);
96
105
  });
97
106
 
@@ -102,9 +111,9 @@ describe("wrangler", () => {
102
111
  `"The namespace binding name \\"abc-def\\" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number."`
103
112
  );
104
113
 
105
- expect(std.out).toMatchInlineSnapshot(`""`);
106
- expect(std.err).toMatchInlineSnapshot(`
107
- "wrangler kv:namespace create <namespace>
114
+ expect(std.out).toMatchInlineSnapshot(`
115
+ "
116
+ wrangler kv:namespace create <namespace>
108
117
 
109
118
  Create a new namespace
110
119
 
@@ -117,11 +126,13 @@ describe("wrangler", () => {
117
126
  -v, --version Show version number [boolean]
118
127
 
119
128
  Options:
120
- -l, --local Run on my machine [boolean] [default: false]
121
- --env Perform on a specific environment [string]
122
- --preview Interact with a preview namespace [boolean]
129
+ -e, --env Perform on a specific environment [string]
130
+ --preview Interact with a preview namespace [boolean]"
131
+ `);
132
+ expect(std.err).toMatchInlineSnapshot(`
133
+ "X [ERROR] The namespace binding name \\"abc-def\\" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number.
123
134
 
124
- The namespace binding name \\"abc-def\\" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number."
135
+ "
125
136
  `);
126
137
  });
127
138
 
@@ -148,11 +159,11 @@ describe("wrangler", () => {
148
159
  });
149
160
 
150
161
  it("should create a namespace using configured worker name", async () => {
151
- writeFileSync("./wrangler.toml", 'name = "otherWorker"', "utf-8");
152
- mockCreateRequest("otherWorker-UnitTestNamespace");
162
+ writeFileSync("./wrangler.toml", 'name = "other-worker"', "utf-8");
163
+ mockCreateRequest("other-worker-UnitTestNamespace");
153
164
  await runWrangler("kv:namespace create UnitTestNamespace");
154
165
  expect(std.out).toMatchInlineSnapshot(`
155
- "🌀 Creating namespace with title \\"otherWorker-UnitTestNamespace\\"
166
+ "🌀 Creating namespace with title \\"other-worker-UnitTestNamespace\\"
156
167
  ✨ Success!
157
168
  Add the following to your configuration file in your kv_namespaces array:
158
169
  { binding = \\"UnitTestNamespace\\", id = \\"some-namespace-id\\" }"
@@ -271,24 +282,11 @@ describe("wrangler", () => {
271
282
  A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."
272
283
  `);
273
284
  expect(std.err).toMatchInlineSnapshot(`
274
- "wrangler kv:namespace delete
285
+ "X [ERROR] Not able to delete namespace.
275
286
 
276
- Deletes a given namespace.
287
+ A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
277
288
 
278
- Flags:
279
- -c, --config Path to .toml configuration file [string]
280
- -h, --help Show help [boolean]
281
- -v, --version Show version number [boolean]
282
-
283
- Options:
284
- -l, --local Run on my machine [boolean] [default: false]
285
- --binding The name of the namespace to delete [string]
286
- --namespace-id The id of the namespace to delete [string]
287
- --env Perform on a specific environment [string]
288
- --preview Interact with a preview namespace [boolean]
289
-
290
- Not able to delete namespace.
291
- A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."
289
+ "
292
290
  `);
293
291
  });
294
292
 
@@ -319,10 +317,7 @@ describe("wrangler", () => {
319
317
  describe("put", () => {
320
318
  function mockKeyPutRequest(
321
319
  expectedNamespaceId: string,
322
- expectedKey: string,
323
- expectedValue: string,
324
- expiration?: number,
325
- expirationTtl?: number
320
+ expectedKV: KeyValue
326
321
  ) {
327
322
  const requests = { count: 0 };
328
323
  setMockResponse(
@@ -332,15 +327,19 @@ describe("wrangler", () => {
332
327
  requests.count++;
333
328
  expect(accountId).toEqual("some-account-id");
334
329
  expect(namespaceId).toEqual(expectedNamespaceId);
335
- expect(key).toEqual(expectedKey);
336
- expect(body).toEqual(expectedValue);
337
- if (expiration !== undefined) {
338
- expect(query.get("expiration")).toEqual(`${expiration}`);
330
+ expect(key).toEqual(expectedKV.key);
331
+ expect(body).toEqual(expectedKV.value);
332
+ if (expectedKV.expiration !== undefined) {
333
+ expect(query.get("expiration")).toEqual(
334
+ `${expectedKV.expiration}`
335
+ );
339
336
  } else {
340
337
  expect(query.has("expiration")).toBe(false);
341
338
  }
342
- if (expirationTtl) {
343
- expect(query.get("expiration_ttl")).toEqual(`${expirationTtl}`);
339
+ if (expectedKV.expiration_ttl) {
340
+ expect(query.get("expiration_ttl")).toEqual(
341
+ `${expectedKV.expiration_ttl}`
342
+ );
344
343
  } else {
345
344
  expect(query.has("expiration_ttl")).toBe(false);
346
345
  }
@@ -351,11 +350,10 @@ describe("wrangler", () => {
351
350
  }
352
351
 
353
352
  it("should put a key in a given namespace specified by namespace-id", async () => {
354
- const requests = mockKeyPutRequest(
355
- "some-namespace-id",
356
- "my-key",
357
- "my-value"
358
- );
353
+ const requests = mockKeyPutRequest("some-namespace-id", {
354
+ key: "my-key",
355
+ value: "my-value",
356
+ });
359
357
 
360
358
  await runWrangler(
361
359
  "kv:key put my-key my-value --namespace-id some-namespace-id"
@@ -363,20 +361,38 @@ describe("wrangler", () => {
363
361
 
364
362
  expect(requests.count).toEqual(1);
365
363
  expect(std.out).toMatchInlineSnapshot(
366
- `"writing the value \\"my-value\\" to key \\"my-key\\" on namespace some-namespace-id"`
364
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace some-namespace-id."`
365
+ );
366
+ expect(std.err).toMatchInlineSnapshot(`""`);
367
+ });
368
+
369
+ it("should encode the key in the api request to put a value", async () => {
370
+ const requests = mockKeyPutRequest("DS9", {
371
+ key: "%2Fmy-key",
372
+ value: "my-value",
373
+ });
374
+
375
+ await runWrangler("kv:key put /my-key my-value --namespace-id DS9");
376
+
377
+ expect(requests.count).toEqual(1);
378
+ expect(std.out).toMatchInlineSnapshot(
379
+ `"Writing the value \\"my-value\\" to key \\"/my-key\\" on namespace DS9."`
367
380
  );
368
381
  expect(std.err).toMatchInlineSnapshot(`""`);
369
382
  });
370
383
 
371
384
  it("should put a key in a given namespace specified by binding", async () => {
372
385
  writeWranglerConfig();
373
- const requests = mockKeyPutRequest("bound-id", "my-key", "my-value");
386
+ const requests = mockKeyPutRequest("bound-id", {
387
+ key: "my-key",
388
+ value: "my-value",
389
+ });
374
390
  await runWrangler(
375
391
  "kv:key put my-key my-value --binding someBinding --preview false"
376
392
  );
377
393
 
378
394
  expect(std.out).toMatchInlineSnapshot(
379
- `"writing the value \\"my-value\\" to key \\"my-key\\" on namespace bound-id"`
395
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace bound-id."`
380
396
  );
381
397
  expect(std.err).toMatchInlineSnapshot(`""`);
382
398
  expect(requests.count).toEqual(1);
@@ -384,70 +400,87 @@ describe("wrangler", () => {
384
400
 
385
401
  it("should put a key in a given preview namespace specified by binding", async () => {
386
402
  writeWranglerConfig();
387
- const requests = mockKeyPutRequest(
388
- "preview-bound-id",
389
- "my-key",
390
- "my-value"
391
- );
403
+ const requests = mockKeyPutRequest("preview-bound-id", {
404
+ key: "my-key",
405
+ value: "my-value",
406
+ });
392
407
 
393
408
  await runWrangler(
394
409
  "kv:key put my-key my-value --binding someBinding --preview"
395
410
  );
396
411
 
397
412
  expect(std.out).toMatchInlineSnapshot(
398
- `"writing the value \\"my-value\\" to key \\"my-key\\" on namespace preview-bound-id"`
413
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace preview-bound-id."`
399
414
  );
400
415
  expect(std.err).toMatchInlineSnapshot(`""`);
401
416
  expect(requests.count).toEqual(1);
402
417
  });
403
418
 
404
419
  it("should add expiration and ttl properties when putting a key", async () => {
405
- const requests = mockKeyPutRequest(
406
- "some-namespace-id",
407
- "my-key",
408
- "my-value",
409
- 10,
410
- 20
411
- );
420
+ const requests = mockKeyPutRequest("some-namespace-id", {
421
+ key: "my-key",
422
+ value: "my-value",
423
+ expiration: 10,
424
+ expiration_ttl: 20,
425
+ });
412
426
  await runWrangler(
413
427
  "kv:key put my-key my-value --namespace-id some-namespace-id --expiration 10 --ttl 20"
414
428
  );
415
429
  expect(requests.count).toEqual(1);
416
430
  expect(std.out).toMatchInlineSnapshot(
417
- `"writing the value \\"my-value\\" to key \\"my-key\\" on namespace some-namespace-id"`
431
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace some-namespace-id."`
418
432
  );
419
433
  expect(std.err).toMatchInlineSnapshot(`""`);
420
434
  });
421
435
 
422
436
  it("should put a key to the specified environment in a given namespace", async () => {
423
437
  writeWranglerConfig();
424
- const requests = mockKeyPutRequest(
425
- "env-bound-id",
426
- "my-key",
427
- "my-value"
428
- );
438
+ const requests = mockKeyPutRequest("env-bound-id", {
439
+ key: "my-key",
440
+ value: "my-value",
441
+ });
429
442
  await runWrangler(
430
443
  "kv:key put my-key my-value --binding someBinding --env some-environment --preview false"
431
444
  );
432
445
  expect(std.out).toMatchInlineSnapshot(
433
- `"writing the value \\"my-value\\" to key \\"my-key\\" on namespace env-bound-id"`
446
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace env-bound-id."`
434
447
  );
435
448
  expect(std.err).toMatchInlineSnapshot(`""`);
436
449
  expect(requests.count).toEqual(1);
437
450
  });
438
451
 
439
452
  it("should put a key with a value loaded from a given path", async () => {
440
- writeFileSync("foo.txt", "file-contents", "utf-8");
441
- const requests = mockKeyPutRequest(
442
- "some-namespace-id",
443
- "my-key",
444
- "file-contents"
445
- );
453
+ const buf = Buffer.from("file-contents", "utf-8");
454
+ writeFileSync("foo.txt", buf);
455
+ const requests = mockKeyPutRequest("some-namespace-id", {
456
+ key: "my-key",
457
+ value: buf,
458
+ });
446
459
  await runWrangler(
447
460
  "kv:key put my-key --namespace-id some-namespace-id --path foo.txt"
448
461
  );
449
462
  expect(std.out).toMatchInlineSnapshot(
450
- `"writing the contents of foo.txt to the key \\"my-key\\" on namespace some-namespace-id"`
463
+ `"Writing the contents of foo.txt to the key \\"my-key\\" on namespace some-namespace-id."`
464
+ );
465
+ expect(std.err).toMatchInlineSnapshot(`""`);
466
+ expect(requests.count).toEqual(1);
467
+ });
468
+
469
+ it("should put a key with a binary value loaded from a given path", async () => {
470
+ const buf = Buffer.from(
471
+ "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC",
472
+ "base64"
473
+ );
474
+ writeFileSync("test.png", buf);
475
+ const requests = mockKeyPutRequest("another-namespace-id", {
476
+ key: "my-key",
477
+ value: buf,
478
+ });
479
+ await runWrangler(
480
+ "kv:key put my-key --namespace-id another-namespace-id --path test.png"
481
+ );
482
+ expect(std.out).toMatchInlineSnapshot(
483
+ `"Writing the contents of test.png to the key \\"my-key\\" on namespace another-namespace-id."`
451
484
  );
452
485
  expect(std.err).toMatchInlineSnapshot(`""`);
453
486
  expect(requests.count).toEqual(1);
@@ -460,15 +493,15 @@ describe("wrangler", () => {
460
493
  `"Not enough non-option arguments: got 0, need at least 1"`
461
494
  );
462
495
 
463
- expect(std.out).toMatchInlineSnapshot(`""`);
464
- expect(std.err).toMatchInlineSnapshot(`
465
- "wrangler kv:key put <key> [value]
496
+ expect(std.out).toMatchInlineSnapshot(`
497
+ "
498
+ wrangler kv:key put <key> [value]
466
499
 
467
500
  Writes a single key/value pair to the given namespace.
468
501
 
469
502
  Positionals:
470
- key The key to write to. [string] [required]
471
- value The value to write. [string]
503
+ key The key to write to [string] [required]
504
+ value The value to write [string]
472
505
 
473
506
  Flags:
474
507
  -c, --config Path to .toml configuration file [string]
@@ -476,16 +509,18 @@ describe("wrangler", () => {
476
509
  -v, --version Show version number [boolean]
477
510
 
478
511
  Options:
479
- -l, --local Run on my machine [boolean] [default: false]
480
- --binding The binding of the namespace to write to. [string]
481
- --namespace-id The id of the namespace to write to. [string]
482
- --env Perform on a specific environment [string]
512
+ --binding The binding of the namespace to write to [string]
513
+ --namespace-id The id of the namespace to write to [string]
514
+ -e, --env Perform on a specific environment [string]
483
515
  --preview Interact with a preview namespace [boolean]
484
- --ttl Time for which the entries should be visible. [number]
516
+ --ttl Time for which the entries should be visible [number]
485
517
  --expiration Time since the UNIX epoch after which the entry expires [number]
486
- --path Read value from the file at a given path. [string]
518
+ --path Read value from the file at a given path [string]"
519
+ `);
520
+ expect(std.err).toMatchInlineSnapshot(`
521
+ "X [ERROR] Not enough non-option arguments: got 0, need at least 1
487
522
 
488
- Not enough non-option arguments: got 0, need at least 1"
523
+ "
489
524
  `);
490
525
  });
491
526
 
@@ -496,15 +531,15 @@ describe("wrangler", () => {
496
531
  `"Exactly one of the arguments binding and namespace-id is required"`
497
532
  );
498
533
 
499
- expect(std.out).toMatchInlineSnapshot(`""`);
500
- expect(std.err).toMatchInlineSnapshot(`
501
- "wrangler kv:key put <key> [value]
534
+ expect(std.out).toMatchInlineSnapshot(`
535
+ "
536
+ wrangler kv:key put <key> [value]
502
537
 
503
538
  Writes a single key/value pair to the given namespace.
504
539
 
505
540
  Positionals:
506
- key The key to write to. [string] [required]
507
- value The value to write. [string]
541
+ key The key to write to [string] [required]
542
+ value The value to write [string]
508
543
 
509
544
  Flags:
510
545
  -c, --config Path to .toml configuration file [string]
@@ -512,16 +547,18 @@ describe("wrangler", () => {
512
547
  -v, --version Show version number [boolean]
513
548
 
514
549
  Options:
515
- -l, --local Run on my machine [boolean] [default: false]
516
- --binding The binding of the namespace to write to. [string]
517
- --namespace-id The id of the namespace to write to. [string]
518
- --env Perform on a specific environment [string]
550
+ --binding The binding of the namespace to write to [string]
551
+ --namespace-id The id of the namespace to write to [string]
552
+ -e, --env Perform on a specific environment [string]
519
553
  --preview Interact with a preview namespace [boolean]
520
- --ttl Time for which the entries should be visible. [number]
554
+ --ttl Time for which the entries should be visible [number]
521
555
  --expiration Time since the UNIX epoch after which the entry expires [number]
522
- --path Read value from the file at a given path. [string]
556
+ --path Read value from the file at a given path [string]"
557
+ `);
558
+ expect(std.err).toMatchInlineSnapshot(`
559
+ "X [ERROR] Exactly one of the arguments binding and namespace-id is required
523
560
 
524
- Exactly one of the arguments binding and namespace-id is required"
561
+ "
525
562
  `);
526
563
  });
527
564
 
@@ -532,15 +569,15 @@ describe("wrangler", () => {
532
569
  `"Arguments binding and namespace-id are mutually exclusive"`
533
570
  );
534
571
 
535
- expect(std.out).toMatchInlineSnapshot(`""`);
536
- expect(std.err).toMatchInlineSnapshot(`
537
- "wrangler kv:key put <key> [value]
572
+ expect(std.out).toMatchInlineSnapshot(`
573
+ "
574
+ wrangler kv:key put <key> [value]
538
575
 
539
576
  Writes a single key/value pair to the given namespace.
540
577
 
541
578
  Positionals:
542
- key The key to write to. [string] [required]
543
- value The value to write. [string]
579
+ key The key to write to [string] [required]
580
+ value The value to write [string]
544
581
 
545
582
  Flags:
546
583
  -c, --config Path to .toml configuration file [string]
@@ -548,16 +585,18 @@ describe("wrangler", () => {
548
585
  -v, --version Show version number [boolean]
549
586
 
550
587
  Options:
551
- -l, --local Run on my machine [boolean] [default: false]
552
- --binding The binding of the namespace to write to. [string]
553
- --namespace-id The id of the namespace to write to. [string]
554
- --env Perform on a specific environment [string]
588
+ --binding The binding of the namespace to write to [string]
589
+ --namespace-id The id of the namespace to write to [string]
590
+ -e, --env Perform on a specific environment [string]
555
591
  --preview Interact with a preview namespace [boolean]
556
- --ttl Time for which the entries should be visible. [number]
592
+ --ttl Time for which the entries should be visible [number]
557
593
  --expiration Time since the UNIX epoch after which the entry expires [number]
558
- --path Read value from the file at a given path. [string]
594
+ --path Read value from the file at a given path [string]"
595
+ `);
596
+ expect(std.err).toMatchInlineSnapshot(`
597
+ "X [ERROR] Arguments binding and namespace-id are mutually exclusive
559
598
 
560
- Arguments binding and namespace-id are mutually exclusive"
599
+ "
561
600
  `);
562
601
  });
563
602
 
@@ -568,15 +607,15 @@ describe("wrangler", () => {
568
607
  `"Exactly one of the arguments value and path is required"`
569
608
  );
570
609
 
571
- expect(std.out).toMatchInlineSnapshot(`""`);
572
- expect(std.err).toMatchInlineSnapshot(`
573
- "wrangler kv:key put <key> [value]
610
+ expect(std.out).toMatchInlineSnapshot(`
611
+ "
612
+ wrangler kv:key put <key> [value]
574
613
 
575
614
  Writes a single key/value pair to the given namespace.
576
615
 
577
616
  Positionals:
578
- key The key to write to. [string] [required]
579
- value The value to write. [string]
617
+ key The key to write to [string] [required]
618
+ value The value to write [string]
580
619
 
581
620
  Flags:
582
621
  -c, --config Path to .toml configuration file [string]
@@ -584,16 +623,18 @@ describe("wrangler", () => {
584
623
  -v, --version Show version number [boolean]
585
624
 
586
625
  Options:
587
- -l, --local Run on my machine [boolean] [default: false]
588
- --binding The binding of the namespace to write to. [string]
589
- --namespace-id The id of the namespace to write to. [string]
590
- --env Perform on a specific environment [string]
626
+ --binding The binding of the namespace to write to [string]
627
+ --namespace-id The id of the namespace to write to [string]
628
+ -e, --env Perform on a specific environment [string]
591
629
  --preview Interact with a preview namespace [boolean]
592
- --ttl Time for which the entries should be visible. [number]
630
+ --ttl Time for which the entries should be visible [number]
593
631
  --expiration Time since the UNIX epoch after which the entry expires [number]
594
- --path Read value from the file at a given path. [string]
632
+ --path Read value from the file at a given path [string]"
633
+ `);
634
+ expect(std.err).toMatchInlineSnapshot(`
635
+ "X [ERROR] Exactly one of the arguments value and path is required
595
636
 
596
- Exactly one of the arguments value and path is required"
637
+ "
597
638
  `);
598
639
  });
599
640
 
@@ -604,15 +645,15 @@ describe("wrangler", () => {
604
645
  `"Arguments value and path are mutually exclusive"`
605
646
  );
606
647
 
607
- expect(std.out).toMatchInlineSnapshot(`""`);
608
- expect(std.err).toMatchInlineSnapshot(`
609
- "wrangler kv:key put <key> [value]
648
+ expect(std.out).toMatchInlineSnapshot(`
649
+ "
650
+ wrangler kv:key put <key> [value]
610
651
 
611
652
  Writes a single key/value pair to the given namespace.
612
653
 
613
654
  Positionals:
614
- key The key to write to. [string] [required]
615
- value The value to write. [string]
655
+ key The key to write to [string] [required]
656
+ value The value to write [string]
616
657
 
617
658
  Flags:
618
659
  -c, --config Path to .toml configuration file [string]
@@ -620,16 +661,18 @@ describe("wrangler", () => {
620
661
  -v, --version Show version number [boolean]
621
662
 
622
663
  Options:
623
- -l, --local Run on my machine [boolean] [default: false]
624
- --binding The binding of the namespace to write to. [string]
625
- --namespace-id The id of the namespace to write to. [string]
626
- --env Perform on a specific environment [string]
664
+ --binding The binding of the namespace to write to [string]
665
+ --namespace-id The id of the namespace to write to [string]
666
+ -e, --env Perform on a specific environment [string]
627
667
  --preview Interact with a preview namespace [boolean]
628
- --ttl Time for which the entries should be visible. [number]
668
+ --ttl Time for which the entries should be visible [number]
629
669
  --expiration Time since the UNIX epoch after which the entry expires [number]
630
- --path Read value from the file at a given path. [string]
670
+ --path Read value from the file at a given path [string]"
671
+ `);
672
+ expect(std.err).toMatchInlineSnapshot(`
673
+ "X [ERROR] Arguments value and path are mutually exclusive
631
674
 
632
- Arguments value and path are mutually exclusive"
675
+ "
633
676
  `);
634
677
  });
635
678
 
@@ -641,33 +684,36 @@ describe("wrangler", () => {
641
684
  `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
642
685
  );
643
686
 
644
- expect(std.out).toMatchInlineSnapshot(`""`);
687
+ expect(std.out).toMatchInlineSnapshot(`
688
+ "
689
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
690
+ `);
645
691
  expect(std.err).toMatchInlineSnapshot(`
646
- "A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
692
+ "X [ERROR] A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
647
693
 
648
- %s
649
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
694
+ "
650
695
  `);
651
696
  });
652
697
 
653
698
  it("should error if a given binding has both preview and non-preview and --preview is not specified", async () => {
654
699
  writeWranglerConfig();
655
- const requests = mockKeyPutRequest(
656
- "preview-bound-id",
657
- "my-key",
658
- "my-value"
659
- );
700
+ const requests = mockKeyPutRequest("preview-bound-id", {
701
+ key: "my-key",
702
+ value: "my-value",
703
+ });
660
704
  await expect(
661
705
  runWrangler("kv:key put my-key my-value --binding someBinding")
662
706
  ).rejects.toThrowErrorMatchingInlineSnapshot(
663
707
  `"someBinding has both a namespace ID and a preview ID. Specify \\"--preview\\" or \\"--preview false\\" to avoid writing data to the wrong namespace."`
664
708
  );
665
- expect(std.out).toMatchInlineSnapshot(`""`);
709
+ expect(std.out).toMatchInlineSnapshot(`
710
+ "
711
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
712
+ `);
666
713
  expect(std.err).toMatchInlineSnapshot(`
667
- "someBinding has both a namespace ID and a preview ID. Specify \\"--preview\\" or \\"--preview false\\" to avoid writing data to the wrong namespace.
714
+ "X [ERROR] someBinding has both a namespace ID and a preview ID. Specify \\"--preview\\" or \\"--preview false\\" to avoid writing data to the wrong namespace.
668
715
 
669
- %s
670
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
716
+ "
671
717
  `);
672
718
  expect(requests.count).toEqual(0);
673
719
  });
@@ -675,26 +721,26 @@ describe("wrangler", () => {
675
721
 
676
722
  describe("list", () => {
677
723
  it("should list the keys of a namespace specified by namespace-id", async () => {
678
- const keys = ["key-1", "key-2", "key-3"];
724
+ const keys = [
725
+ { name: "key-1" },
726
+ { name: "key-2", expiration: 123456789 },
727
+ { name: "key-3", expiration_ttl: 666 },
728
+ ];
679
729
  mockKeyListRequest("some-namespace-id", keys);
680
730
  await runWrangler("kv:key list --namespace-id some-namespace-id");
681
731
  expect(std.err).toMatchInlineSnapshot(`""`);
682
732
  expect(std.out).toMatchInlineSnapshot(`
683
733
  "[
684
734
  {
685
- \\"name\\": \\"key-1\\",
686
- \\"expiration\\": 123456789,
687
- \\"metadata\\": {}
735
+ \\"name\\": \\"key-1\\"
688
736
  },
689
737
  {
690
738
  \\"name\\": \\"key-2\\",
691
- \\"expiration\\": 123456789,
692
- \\"metadata\\": {}
739
+ \\"expiration\\": 123456789
693
740
  },
694
741
  {
695
742
  \\"name\\": \\"key-3\\",
696
- \\"expiration\\": 123456789,
697
- \\"metadata\\": {}
743
+ \\"expiration_ttl\\": 666
698
744
  }
699
745
  ]"
700
746
  `);
@@ -702,7 +748,7 @@ describe("wrangler", () => {
702
748
 
703
749
  it("should list the keys of a namespace specified by binding", async () => {
704
750
  writeWranglerConfig();
705
- const keys = ["key-1", "key-2", "key-3"];
751
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
706
752
  mockKeyListRequest("bound-id", keys);
707
753
 
708
754
  await runWrangler("kv:key list --binding someBinding");
@@ -710,19 +756,13 @@ describe("wrangler", () => {
710
756
  expect(std.out).toMatchInlineSnapshot(`
711
757
  "[
712
758
  {
713
- \\"name\\": \\"key-1\\",
714
- \\"expiration\\": 123456789,
715
- \\"metadata\\": {}
759
+ \\"name\\": \\"key-1\\"
716
760
  },
717
761
  {
718
- \\"name\\": \\"key-2\\",
719
- \\"expiration\\": 123456789,
720
- \\"metadata\\": {}
762
+ \\"name\\": \\"key-2\\"
721
763
  },
722
764
  {
723
- \\"name\\": \\"key-3\\",
724
- \\"expiration\\": 123456789,
725
- \\"metadata\\": {}
765
+ \\"name\\": \\"key-3\\"
726
766
  }
727
767
  ]"
728
768
  `);
@@ -730,26 +770,20 @@ describe("wrangler", () => {
730
770
 
731
771
  it("should list the keys of a preview namespace specified by binding", async () => {
732
772
  writeWranglerConfig();
733
- const keys = ["key-1", "key-2", "key-3"];
773
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
734
774
  mockKeyListRequest("preview-bound-id", keys);
735
775
  await runWrangler("kv:key list --binding someBinding --preview");
736
776
  expect(std.err).toMatchInlineSnapshot(`""`);
737
777
  expect(std.out).toMatchInlineSnapshot(`
738
778
  "[
739
779
  {
740
- \\"name\\": \\"key-1\\",
741
- \\"expiration\\": 123456789,
742
- \\"metadata\\": {}
780
+ \\"name\\": \\"key-1\\"
743
781
  },
744
782
  {
745
- \\"name\\": \\"key-2\\",
746
- \\"expiration\\": 123456789,
747
- \\"metadata\\": {}
783
+ \\"name\\": \\"key-2\\"
748
784
  },
749
785
  {
750
- \\"name\\": \\"key-3\\",
751
- \\"expiration\\": 123456789,
752
- \\"metadata\\": {}
786
+ \\"name\\": \\"key-3\\"
753
787
  }
754
788
  ]"
755
789
  `);
@@ -757,7 +791,7 @@ describe("wrangler", () => {
757
791
 
758
792
  it("should list the keys of a namespace specified by binding, in a given environment", async () => {
759
793
  writeWranglerConfig();
760
- const keys = ["key-1", "key-2", "key-3"];
794
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
761
795
  mockKeyListRequest("env-bound-id", keys);
762
796
  await runWrangler(
763
797
  "kv:key list --binding someBinding --env some-environment"
@@ -766,19 +800,13 @@ describe("wrangler", () => {
766
800
  expect(std.out).toMatchInlineSnapshot(`
767
801
  "[
768
802
  {
769
- \\"name\\": \\"key-1\\",
770
- \\"expiration\\": 123456789,
771
- \\"metadata\\": {}
803
+ \\"name\\": \\"key-1\\"
772
804
  },
773
805
  {
774
- \\"name\\": \\"key-2\\",
775
- \\"expiration\\": 123456789,
776
- \\"metadata\\": {}
806
+ \\"name\\": \\"key-2\\"
777
807
  },
778
808
  {
779
- \\"name\\": \\"key-3\\",
780
- \\"expiration\\": 123456789,
781
- \\"metadata\\": {}
809
+ \\"name\\": \\"key-3\\"
782
810
  }
783
811
  ]"
784
812
  `);
@@ -786,7 +814,7 @@ describe("wrangler", () => {
786
814
 
787
815
  it("should list the keys of a preview namespace specified by binding, in a given environment", async () => {
788
816
  writeWranglerConfig();
789
- const keys = ["key-1", "key-2", "key-3"];
817
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
790
818
  mockKeyListRequest("preview-env-bound-id", keys);
791
819
  await runWrangler(
792
820
  "kv:key list --binding someBinding --preview --env some-environment"
@@ -795,19 +823,13 @@ describe("wrangler", () => {
795
823
  expect(std.out).toMatchInlineSnapshot(`
796
824
  "[
797
825
  {
798
- \\"name\\": \\"key-1\\",
799
- \\"expiration\\": 123456789,
800
- \\"metadata\\": {}
826
+ \\"name\\": \\"key-1\\"
801
827
  },
802
828
  {
803
- \\"name\\": \\"key-2\\",
804
- \\"expiration\\": 123456789,
805
- \\"metadata\\": {}
829
+ \\"name\\": \\"key-2\\"
806
830
  },
807
831
  {
808
- \\"name\\": \\"key-3\\",
809
- \\"expiration\\": 123456789,
810
- \\"metadata\\": {}
832
+ \\"name\\": \\"key-3\\"
811
833
  }
812
834
  ]"
813
835
  `);
@@ -824,9 +846,9 @@ describe("wrangler", () => {
824
846
  describe(`cursor - ${blankCursorValue}`, () => {
825
847
  it("should make multiple requests for paginated results", async () => {
826
848
  // Create a lot of mock keys, so that the fetch requests will be paginated
827
- const keys: string[] = [];
849
+ const keys: NamespaceKeyInfo[] = [];
828
850
  for (let i = 0; i < 550; i++) {
829
- keys.push("key-" + i);
851
+ keys.push({ name: "key-" + i });
830
852
  }
831
853
  // Ask for the keys in pages of size 100.
832
854
  const requests = mockKeyListRequest(
@@ -835,11 +857,9 @@ describe("wrangler", () => {
835
857
  100,
836
858
  blankCursorValue
837
859
  );
838
- await runWrangler(
839
- "kv:key list --namespace-id some-namespace-id --limit 100"
840
- );
860
+ await runWrangler("kv:key list --namespace-id some-namespace-id");
841
861
  expect(std.err).toMatchInlineSnapshot(`""`);
842
- expect(JSON.parse(std.out).map((k) => k.name)).toEqual(keys);
862
+ expect(JSON.parse(std.out)).toEqual(keys);
843
863
  expect(requests.count).toEqual(6);
844
864
  });
845
865
  });
@@ -853,12 +873,14 @@ describe("wrangler", () => {
853
873
  `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
854
874
  );
855
875
  expect(std.err).toMatchInlineSnapshot(`
856
- "A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
876
+ "X [ERROR] A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
857
877
 
858
- %s
859
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
878
+ "
879
+ `);
880
+ expect(std.out).toMatchInlineSnapshot(`
881
+ "
882
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
860
883
  `);
861
- expect(std.out).toMatchInlineSnapshot(`""`);
862
884
  });
863
885
  });
864
886
 
@@ -875,7 +897,23 @@ describe("wrangler", () => {
875
897
  "my-value"
876
898
  );
877
899
  await runWrangler("kv:key get my-key --namespace-id some-namespace-id");
878
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
900
+ expect(proc.write).toEqual(Buffer.from("my-value"));
901
+ expect(std.err).toMatchInlineSnapshot(`""`);
902
+ });
903
+
904
+ it("should get a binary file by key in a given namespace specified by namespace-id", async () => {
905
+ const buf = Buffer.from(
906
+ "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC",
907
+ "base64"
908
+ );
909
+ setMockFetchKVGetValue(
910
+ "some-account-id",
911
+ "some-namespace-id",
912
+ "my-key",
913
+ buf
914
+ );
915
+ await runWrangler("kv:key get my-key --namespace-id some-namespace-id");
916
+ expect(proc.write).toEqual(buf);
879
917
  expect(std.err).toMatchInlineSnapshot(`""`);
880
918
  });
881
919
 
@@ -890,7 +928,7 @@ describe("wrangler", () => {
890
928
  await runWrangler(
891
929
  "kv:key get my-key --binding someBinding --preview false"
892
930
  );
893
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
931
+ expect(proc.write).toEqual(Buffer.from("my-value"));
894
932
  expect(std.err).toMatchInlineSnapshot(`""`);
895
933
  });
896
934
 
@@ -903,7 +941,7 @@ describe("wrangler", () => {
903
941
  "my-value"
904
942
  );
905
943
  await runWrangler("kv:key get my-key --binding someBinding --preview");
906
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
944
+ expect(proc.write).toEqual(Buffer.from("my-value"));
907
945
  expect(std.err).toMatchInlineSnapshot(`""`);
908
946
  });
909
947
 
@@ -916,9 +954,23 @@ describe("wrangler", () => {
916
954
  "my-value"
917
955
  );
918
956
  await runWrangler(
919
- "kv:key get my-key my-value --binding someBinding --env some-environment --preview false"
957
+ "kv:key get my-key --binding someBinding --env some-environment --preview false"
920
958
  );
921
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
959
+ expect(proc.write).toEqual(Buffer.from("my-value"));
960
+ expect(std.err).toMatchInlineSnapshot(`""`);
961
+ });
962
+
963
+ it("should encode the key in the api request to get a value", async () => {
964
+ setMockFetchKVGetValue(
965
+ "some-account-id",
966
+ "some-namespace-id",
967
+ "%2Fmy%2Ckey",
968
+ "my-value"
969
+ );
970
+ await runWrangler(
971
+ "kv:key get /my,key --namespace-id some-namespace-id"
972
+ );
973
+ expect(proc.write).toEqual(Buffer.from("my-value"));
922
974
  expect(std.err).toMatchInlineSnapshot(`""`);
923
975
  });
924
976
 
@@ -928,9 +980,9 @@ describe("wrangler", () => {
928
980
  ).rejects.toThrowErrorMatchingInlineSnapshot(
929
981
  `"Not enough non-option arguments: got 0, need at least 1"`
930
982
  );
931
- expect(std.out).toMatchInlineSnapshot(`""`);
932
- expect(std.err).toMatchInlineSnapshot(`
933
- "wrangler kv:key get <key>
983
+ expect(std.out).toMatchInlineSnapshot(`
984
+ "
985
+ wrangler kv:key get <key>
934
986
 
935
987
  Reads a single value by key from the given namespace.
936
988
 
@@ -943,13 +995,15 @@ describe("wrangler", () => {
943
995
  -v, --version Show version number [boolean]
944
996
 
945
997
  Options:
946
- -l, --local Run on my machine [boolean] [default: false]
947
998
  --binding The name of the namespace to get from [string]
948
999
  --namespace-id The id of the namespace to get from [string]
949
- --env Perform on a specific environment [string]
950
- --preview Interact with a preview namespace [boolean] [default: false]
1000
+ -e, --env Perform on a specific environment [string]
1001
+ --preview Interact with a preview namespace [boolean] [default: false]"
1002
+ `);
1003
+ expect(std.err).toMatchInlineSnapshot(`
1004
+ "X [ERROR] Not enough non-option arguments: got 0, need at least 1
951
1005
 
952
- Not enough non-option arguments: got 0, need at least 1"
1006
+ "
953
1007
  `);
954
1008
  });
955
1009
 
@@ -959,9 +1013,9 @@ describe("wrangler", () => {
959
1013
  ).rejects.toThrowErrorMatchingInlineSnapshot(
960
1014
  `"Exactly one of the arguments binding and namespace-id is required"`
961
1015
  );
962
- expect(std.out).toMatchInlineSnapshot(`""`);
963
- expect(std.err).toMatchInlineSnapshot(`
964
- "wrangler kv:key get <key>
1016
+ expect(std.out).toMatchInlineSnapshot(`
1017
+ "
1018
+ wrangler kv:key get <key>
965
1019
 
966
1020
  Reads a single value by key from the given namespace.
967
1021
 
@@ -974,13 +1028,15 @@ describe("wrangler", () => {
974
1028
  -v, --version Show version number [boolean]
975
1029
 
976
1030
  Options:
977
- -l, --local Run on my machine [boolean] [default: false]
978
1031
  --binding The name of the namespace to get from [string]
979
1032
  --namespace-id The id of the namespace to get from [string]
980
- --env Perform on a specific environment [string]
981
- --preview Interact with a preview namespace [boolean] [default: false]
1033
+ -e, --env Perform on a specific environment [string]
1034
+ --preview Interact with a preview namespace [boolean] [default: false]"
1035
+ `);
1036
+ expect(std.err).toMatchInlineSnapshot(`
1037
+ "X [ERROR] Exactly one of the arguments binding and namespace-id is required
982
1038
 
983
- Exactly one of the arguments binding and namespace-id is required"
1039
+ "
984
1040
  `);
985
1041
  });
986
1042
 
@@ -991,9 +1047,9 @@ describe("wrangler", () => {
991
1047
  `"Arguments binding and namespace-id are mutually exclusive"`
992
1048
  );
993
1049
 
994
- expect(std.out).toMatchInlineSnapshot(`""`);
995
- expect(std.err).toMatchInlineSnapshot(`
996
- "wrangler kv:key get <key>
1050
+ expect(std.out).toMatchInlineSnapshot(`
1051
+ "
1052
+ wrangler kv:key get <key>
997
1053
 
998
1054
  Reads a single value by key from the given namespace.
999
1055
 
@@ -1006,13 +1062,15 @@ describe("wrangler", () => {
1006
1062
  -v, --version Show version number [boolean]
1007
1063
 
1008
1064
  Options:
1009
- -l, --local Run on my machine [boolean] [default: false]
1010
1065
  --binding The name of the namespace to get from [string]
1011
1066
  --namespace-id The id of the namespace to get from [string]
1012
- --env Perform on a specific environment [string]
1013
- --preview Interact with a preview namespace [boolean] [default: false]
1067
+ -e, --env Perform on a specific environment [string]
1068
+ --preview Interact with a preview namespace [boolean] [default: false]"
1069
+ `);
1070
+ expect(std.err).toMatchInlineSnapshot(`
1071
+ "X [ERROR] Arguments binding and namespace-id are mutually exclusive
1014
1072
 
1015
- Arguments binding and namespace-id are mutually exclusive"
1073
+ "
1016
1074
  `);
1017
1075
  });
1018
1076
 
@@ -1023,12 +1081,14 @@ describe("wrangler", () => {
1023
1081
  ).rejects.toThrowErrorMatchingInlineSnapshot(
1024
1082
  `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
1025
1083
  );
1026
- expect(std.out).toMatchInlineSnapshot(`""`);
1084
+ expect(std.out).toMatchInlineSnapshot(`
1085
+ "
1086
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1087
+ `);
1027
1088
  expect(std.err).toMatchInlineSnapshot(`
1028
- "A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
1089
+ "X [ERROR] A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
1029
1090
 
1030
- %s
1031
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1091
+ "
1032
1092
  `);
1033
1093
  });
1034
1094
  });
@@ -1061,6 +1121,16 @@ describe("wrangler", () => {
1061
1121
  expect(requests.count).toEqual(1);
1062
1122
  });
1063
1123
 
1124
+ it("should encode the key in the api request to delete a value", async () => {
1125
+ const requests = mockDeleteRequest("voyager", "%2FNCC-74656");
1126
+ await runWrangler(`kv:key delete --namespace-id voyager /NCC-74656`);
1127
+ expect(requests.count).toEqual(1);
1128
+ expect(std.out).toMatchInlineSnapshot(
1129
+ `"Deleting the key \\"/NCC-74656\\" on namespace voyager."`
1130
+ );
1131
+ expect(std.err).toMatchInlineSnapshot(`""`);
1132
+ });
1133
+
1064
1134
  it("should delete a key in a namespace specified by binding name", async () => {
1065
1135
  writeWranglerConfig();
1066
1136
  const requests = mockDeleteRequest("bound-id", "someKey");
@@ -1088,10 +1158,9 @@ describe("wrangler", () => {
1088
1158
  );
1089
1159
 
1090
1160
  expect(std.err).toMatchInlineSnapshot(`
1091
- "A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
1161
+ "X [ERROR] A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
1092
1162
 
1093
- %s
1094
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1163
+ "
1095
1164
  `);
1096
1165
  });
1097
1166
 
@@ -1102,7 +1171,7 @@ describe("wrangler", () => {
1102
1171
  `kv:key delete --binding someBinding --env some-environment --preview false someKey`
1103
1172
  );
1104
1173
  expect(std.out).toMatchInlineSnapshot(
1105
- `"deleting the key \\"someKey\\" on namespace env-bound-id"`
1174
+ `"Deleting the key \\"someKey\\" on namespace env-bound-id."`
1106
1175
  );
1107
1176
  expect(std.err).toMatchInlineSnapshot(`""`);
1108
1177
  expect(requests.count).toEqual(1);
@@ -1118,13 +1187,325 @@ describe("wrangler", () => {
1118
1187
  });
1119
1188
  });
1120
1189
  });
1190
+
1191
+ describe("kv:bulk", () => {
1192
+ describe("put", () => {
1193
+ function mockPutRequest(
1194
+ expectedNamespaceId: string,
1195
+ expectedKeyValues: KeyValue[]
1196
+ ) {
1197
+ const requests = { count: 0 };
1198
+ setMockResponse(
1199
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
1200
+ "PUT",
1201
+ ([_url, accountId, namespaceId], { body }) => {
1202
+ requests.count++;
1203
+ expect(accountId).toEqual("some-account-id");
1204
+ expect(namespaceId).toEqual(expectedNamespaceId);
1205
+ expect(JSON.parse(body as string)).toEqual(
1206
+ expectedKeyValues.slice(
1207
+ (requests.count - 1) * 5000,
1208
+ requests.count * 5000
1209
+ )
1210
+ );
1211
+ return null;
1212
+ }
1213
+ );
1214
+ return requests;
1215
+ }
1216
+
1217
+ it("should put the key-values parsed from a file", async () => {
1218
+ const keyValues: KeyValue[] = [
1219
+ { key: "someKey1", value: "someValue1" },
1220
+ { key: "ns:someKey2", value: "123", base64: true },
1221
+ { key: "someKey3", value: "someValue3", expiration: 100 },
1222
+ { key: "someKey4", value: "someValue4", expiration_ttl: 500 },
1223
+ ];
1224
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1225
+ const requests = mockPutRequest("some-namespace-id", keyValues);
1226
+ await runWrangler(
1227
+ `kv:bulk put --namespace-id some-namespace-id keys.json`
1228
+ );
1229
+ expect(requests.count).toEqual(1);
1230
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1231
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1232
+ expect(std.err).toMatchInlineSnapshot(`""`);
1233
+ });
1234
+
1235
+ it("should put the key-values in batches of 5000 parsed from a file", async () => {
1236
+ const keyValues: KeyValue[] = new Array(12000).fill({
1237
+ key: "someKey1",
1238
+ value: "someValue1",
1239
+ });
1240
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1241
+ const requests = mockPutRequest("some-namespace-id", keyValues);
1242
+ await runWrangler(
1243
+ `kv:bulk put --namespace-id some-namespace-id keys.json`
1244
+ );
1245
+ expect(requests.count).toEqual(3);
1246
+ expect(std.out).toMatchInlineSnapshot(`
1247
+ "Uploaded 0% (0 out of 12,000)
1248
+ Uploaded 41% (5,000 out of 12,000)
1249
+ Uploaded 83% (10,000 out of 12,000)
1250
+ Uploaded 100% (12,000 out of 12,000)
1251
+ Success!"
1252
+ `);
1253
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1254
+ expect(std.err).toMatchInlineSnapshot(`""`);
1255
+ });
1256
+
1257
+ it("should error if the file is not a JSON array", async () => {
1258
+ const keyValues = { key: "someKey1", value: "someValue1" };
1259
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1260
+ await expect(
1261
+ runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1262
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1263
+ "Unexpected JSON input from \\"keys.json\\".
1264
+ Expected an array of key-value objects but got type \\"object\\"."
1265
+ `);
1266
+ expect(std.out).toMatchInlineSnapshot(`
1267
+ "
1268
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1269
+ `);
1270
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1271
+ });
1272
+
1273
+ it("should error if the array contains items that are not key-value objects", async () => {
1274
+ const keyValues = [
1275
+ 123,
1276
+ "a string",
1277
+ { key: "someKey" },
1278
+ { value: "someValue" },
1279
+ // add a valid object here to make sure it's not included
1280
+ { key: "someKey1", value: "someValue1" },
1281
+ // this one will only add a warning
1282
+ { key: "someKey1", value: "someValue1", invalid: true },
1283
+ // back to the invalid ones
1284
+ { key: 123, value: "somevalue" },
1285
+ { key: "somekey", value: 123 },
1286
+ { key: "someKey1", value: "someValue1", expiration: "string" },
1287
+ { key: "someKey1", value: "someValue1", expiration_ttl: "string" },
1288
+ {
1289
+ key: 123,
1290
+ value: {
1291
+ a: {
1292
+ nested: "object",
1293
+ },
1294
+ },
1295
+ },
1296
+ { key: "someKey1", value: "someValue1", metadata: 123 },
1297
+ { key: "someKey1", value: "someValue1", base64: "string" },
1298
+ ];
1299
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1300
+ await expect(
1301
+ runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1302
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1303
+ "Unexpected JSON input from \\"keys.json\\".
1304
+ Each item in the array should be an object that matches:
1305
+
1306
+ interface KeyValue {
1307
+ key: string;
1308
+ value: string;
1309
+ expiration?: number;
1310
+ expiration_ttl?: number;
1311
+ metadata?: object;
1312
+ base64?: boolean;
1313
+ }
1314
+
1315
+ The item at index 0 is 123
1316
+ The item at index 1 is \\"a string\\"
1317
+ The item at index 2 is {\\"key\\":\\"someKey\\"}
1318
+ The item at index 3 is {\\"value\\":\\"someValue\\"}
1319
+ The item at index 6 is {\\"key\\":123,\\"value\\":\\"somevalue\\"}
1320
+ The item at index 7 is {\\"key\\":\\"somekey\\",\\"value\\":123}
1321
+ The item at index 8 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration\\":\\"string\\"}
1322
+ The item at index 9 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration_ttl\\":\\"string\\"}
1323
+ The item at index 10 is {\\"key\\":123,\\"value\\":{\\"a\\":{\\"nested\\":\\"object\\"}}}
1324
+ The item at index 11 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"metadata\\":123}
1325
+ The item at index 12 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"base64\\":\\"string\\"}"
1326
+ `);
1327
+
1328
+ expect(std.out).toMatchInlineSnapshot(`
1329
+ "
1330
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1331
+ `);
1332
+ expect(std.warn).toMatchInlineSnapshot(`
1333
+ "▲ [WARNING] Unexpected key-value properties in \\"keys.json\\".
1334
+
1335
+ The item at index 5 contains unexpected properties: [\\"invalid\\"].
1336
+
1337
+ "
1338
+ `);
1339
+ });
1340
+ });
1341
+
1342
+ describe("delete", () => {
1343
+ function mockDeleteRequest(
1344
+ expectedNamespaceId: string,
1345
+ expectedKeys: string[]
1346
+ ) {
1347
+ const requests = { count: 0 };
1348
+ setMockResponse(
1349
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
1350
+ "DELETE",
1351
+ ([_url, accountId, namespaceId], { headers, body }) => {
1352
+ requests.count++;
1353
+ expect(accountId).toEqual("some-account-id");
1354
+ expect(namespaceId).toEqual(expectedNamespaceId);
1355
+ expect(new Headers(headers ?? []).get("Content-Type")).toEqual(
1356
+ "application/json"
1357
+ );
1358
+ expect(JSON.parse(body as string)).toEqual(
1359
+ expectedKeys.slice(
1360
+ (requests.count - 1) * 5000,
1361
+ requests.count * 5000
1362
+ )
1363
+ );
1364
+ return null;
1365
+ }
1366
+ );
1367
+ return requests;
1368
+ }
1369
+
1370
+ it("should delete the keys parsed from a file", async () => {
1371
+ const keys = ["someKey1", "ns:someKey2"];
1372
+ writeFileSync("./keys.json", JSON.stringify(keys));
1373
+ mockConfirm({
1374
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1375
+ result: true,
1376
+ });
1377
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1378
+ await runWrangler(
1379
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1380
+ );
1381
+ expect(requests.count).toEqual(1);
1382
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1383
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1384
+ expect(std.err).toMatchInlineSnapshot(`""`);
1385
+ });
1386
+
1387
+ it("should delete the keys in batches of 5000 parsed from a file", async () => {
1388
+ const keys = new Array(12000).fill("some-key");
1389
+ writeFileSync("./keys.json", JSON.stringify(keys));
1390
+ mockConfirm({
1391
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1392
+ result: true,
1393
+ });
1394
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1395
+ await runWrangler(
1396
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1397
+ );
1398
+ expect(requests.count).toEqual(3);
1399
+ expect(std.out).toMatchInlineSnapshot(`
1400
+ "Deleted 0% (0 out of 12,000)
1401
+ Deleted 41% (5,000 out of 12,000)
1402
+ Deleted 83% (10,000 out of 12,000)
1403
+ Deleted 100% (12,000 out of 12,000)
1404
+ Success!"
1405
+ `);
1406
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1407
+ expect(std.err).toMatchInlineSnapshot(`""`);
1408
+ });
1409
+
1410
+ it("should not delete the keys if the user confirms no", async () => {
1411
+ const keys = ["someKey1", "ns:someKey2"];
1412
+ writeFileSync("./keys.json", JSON.stringify(keys));
1413
+ mockConfirm({
1414
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1415
+ result: false,
1416
+ });
1417
+ await runWrangler(
1418
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1419
+ );
1420
+ expect(std.out).toMatchInlineSnapshot(
1421
+ `"Not deleting keys read from \\"keys.json\\"."`
1422
+ );
1423
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1424
+ expect(std.err).toMatchInlineSnapshot(`""`);
1425
+ });
1426
+
1427
+ it("should delete the keys without asking if --force is provided", async () => {
1428
+ const keys = ["someKey1", "ns:someKey2"];
1429
+ writeFileSync("./keys.json", JSON.stringify(keys));
1430
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1431
+ await runWrangler(
1432
+ `kv:bulk delete --namespace-id some-namespace-id keys.json --force`
1433
+ );
1434
+ expect(requests.count).toEqual(1);
1435
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1436
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1437
+ expect(std.err).toMatchInlineSnapshot(`""`);
1438
+ });
1439
+
1440
+ it("should delete the keys without asking if -f is provided", async () => {
1441
+ const keys = ["someKey1", "ns:someKey2"];
1442
+ writeFileSync("./keys.json", JSON.stringify(keys));
1443
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1444
+ await runWrangler(
1445
+ `kv:bulk delete --namespace-id some-namespace-id keys.json -f`
1446
+ );
1447
+ expect(requests.count).toEqual(1);
1448
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1449
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1450
+ expect(std.err).toMatchInlineSnapshot(`""`);
1451
+ });
1452
+
1453
+ it("should error if the file is not a JSON array", async () => {
1454
+ const keys = 12354;
1455
+ writeFileSync("./keys.json", JSON.stringify(keys));
1456
+ mockConfirm({
1457
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1458
+ result: true,
1459
+ });
1460
+ await expect(
1461
+ runWrangler(
1462
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1463
+ )
1464
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1465
+ "Unexpected JSON input from \\"keys.json\\".
1466
+ Expected an array of strings but got:
1467
+ 12354"
1468
+ `);
1469
+ expect(std.out).toMatchInlineSnapshot(`
1470
+ "
1471
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1472
+ `);
1473
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1474
+ });
1475
+
1476
+ it("should error if the file contains non-string items", async () => {
1477
+ const keys = ["good", 12354, { key: "someKey" }, null];
1478
+ writeFileSync("./keys.json", JSON.stringify(keys));
1479
+ mockConfirm({
1480
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1481
+ result: true,
1482
+ });
1483
+ await expect(
1484
+ runWrangler(
1485
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1486
+ )
1487
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1488
+ "Unexpected JSON input from \\"keys.json\\".
1489
+ Expected an array of strings.
1490
+ The item at index 1 is type: \\"number\\" - 12354
1491
+ The item at index 2 is type: \\"object\\" - {\\"key\\":\\"someKey\\"}
1492
+ The item at index 3 is type: \\"object\\" - null"
1493
+ `);
1494
+ expect(std.out).toMatchInlineSnapshot(`
1495
+ "
1496
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1497
+ `);
1498
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1499
+ });
1500
+ });
1501
+ });
1121
1502
  });
1122
1503
 
1123
1504
  function writeWranglerConfig() {
1124
1505
  writeFileSync(
1125
1506
  "./wrangler.toml",
1126
1507
  [
1127
- 'name = "otherWorker"',
1508
+ 'name = "other-worker"',
1128
1509
  "kv_namespaces = [",
1129
1510
  ' { binding = "someBinding", id = "bound-id", preview_id = "preview-bound-id" }',
1130
1511
  "]",