wrangler 0.0.0-e64812e → 0.0.0-e8e684c7

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 (214) hide show
  1. package/README.md +27 -3
  2. package/bin/wrangler.js +150 -62
  3. package/kv-asset-handler.js +1 -0
  4. package/miniflare-dist/index.mjs +663 -7
  5. package/package.json +173 -152
  6. package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
  7. package/src/__tests__/config-cache.test.ts +30 -24
  8. package/src/__tests__/configuration.test.ts +4015 -3363
  9. package/src/__tests__/dev.test.tsx +1290 -952
  10. package/src/__tests__/generate.test.ts +91 -0
  11. package/src/__tests__/guess-worker-format.test.ts +68 -68
  12. package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
  13. package/src/__tests__/helpers/mock-account-id.ts +24 -24
  14. package/src/__tests__/helpers/mock-bin.ts +20 -20
  15. package/src/__tests__/helpers/mock-cfetch.ts +179 -94
  16. package/src/__tests__/helpers/mock-console.ts +49 -39
  17. package/src/__tests__/helpers/mock-dialogs.ts +94 -71
  18. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
  19. package/src/__tests__/helpers/mock-http-server.ts +30 -30
  20. package/src/__tests__/helpers/mock-istty.ts +65 -18
  21. package/src/__tests__/helpers/mock-known-routes.ts +7 -0
  22. package/src/__tests__/helpers/mock-kv.ts +26 -26
  23. package/src/__tests__/helpers/mock-oauth-flow.ts +223 -228
  24. package/src/__tests__/helpers/mock-process.ts +39 -0
  25. package/src/__tests__/helpers/mock-stdin.ts +82 -77
  26. package/src/__tests__/helpers/mock-web-socket.ts +21 -21
  27. package/src/__tests__/helpers/run-in-tmp.ts +27 -28
  28. package/src/__tests__/helpers/run-wrangler.ts +8 -8
  29. package/src/__tests__/helpers/write-worker-source.ts +16 -16
  30. package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
  31. package/src/__tests__/https-options.test.ts +142 -109
  32. package/src/__tests__/index.test.ts +222 -233
  33. package/src/__tests__/init.test.ts +2139 -1603
  34. package/src/__tests__/jest.setup.ts +114 -34
  35. package/src/__tests__/kv.test.ts +1222 -1032
  36. package/src/__tests__/logger.test.ts +100 -74
  37. package/src/__tests__/metrics.test.ts +450 -0
  38. package/src/__tests__/package-manager.test.ts +303 -303
  39. package/src/__tests__/pages.test.ts +1173 -652
  40. package/src/__tests__/parse.test.ts +252 -252
  41. package/src/__tests__/publish.test.ts +6788 -5301
  42. package/src/__tests__/pubsub.test.ts +367 -0
  43. package/src/__tests__/r2.test.ts +328 -225
  44. package/src/__tests__/route.test.ts +18 -18
  45. package/src/__tests__/secret.test.ts +470 -459
  46. package/src/__tests__/tail.test.ts +676 -564
  47. package/src/__tests__/test-old-node-version.js +31 -0
  48. package/src/__tests__/user.test.ts +136 -112
  49. package/src/__tests__/validate-dev-props.test.ts +56 -0
  50. package/src/__tests__/version.test.ts +35 -0
  51. package/src/__tests__/whoami.test.tsx +267 -83
  52. package/src/__tests__/worker-namespace.test.ts +329 -0
  53. package/src/abort.d.ts +1 -1
  54. package/src/api/dev.ts +93 -0
  55. package/src/api/index.ts +1 -0
  56. package/src/bundle-reporter.tsx +29 -0
  57. package/src/bundle.ts +430 -157
  58. package/src/cfetch/index.ts +80 -80
  59. package/src/cfetch/internal.ts +244 -91
  60. package/src/cli.ts +21 -7
  61. package/src/config/config.ts +224 -195
  62. package/src/config/diagnostics.ts +61 -61
  63. package/src/config/environment.ts +422 -357
  64. package/src/config/index.ts +219 -193
  65. package/src/config/validation-helpers.ts +379 -357
  66. package/src/config/validation.ts +1690 -1367
  67. package/src/config-cache.ts +81 -41
  68. package/src/create-worker-preview.ts +208 -136
  69. package/src/create-worker-upload-form.ts +275 -238
  70. package/src/dev/dev-vars.ts +13 -13
  71. package/src/dev/dev.tsx +477 -351
  72. package/src/dev/local.tsx +426 -295
  73. package/src/dev/remote.tsx +406 -211
  74. package/src/dev/use-esbuild.ts +154 -94
  75. package/src/dev/validate-dev-props.ts +31 -0
  76. package/src/dev-registry.tsx +160 -0
  77. package/src/dev.tsx +696 -0
  78. package/src/dialogs.tsx +97 -97
  79. package/src/dispatch-namespace.ts +206 -0
  80. package/src/durable.ts +87 -87
  81. package/src/entry.ts +234 -228
  82. package/src/environment-variables.ts +23 -23
  83. package/src/errors.ts +6 -6
  84. package/src/faye-websocket.d.ts +6 -0
  85. package/src/generate.ts +131 -0
  86. package/src/git-client.ts +42 -0
  87. package/src/global-wrangler-config-path.ts +26 -0
  88. package/src/https-options.ts +84 -80
  89. package/src/index.tsx +2164 -2768
  90. package/src/init.ts +622 -0
  91. package/src/inspect.ts +678 -593
  92. package/src/intl-polyfill.d.ts +123 -123
  93. package/src/is-ci.ts +14 -0
  94. package/src/is-interactive.ts +12 -0
  95. package/src/kv.ts +299 -277
  96. package/src/logger.ts +46 -39
  97. package/src/metrics/index.ts +5 -0
  98. package/src/metrics/metrics-config.ts +239 -0
  99. package/src/metrics/metrics-dispatcher.ts +96 -0
  100. package/src/metrics/metrics-usage-headers.ts +24 -0
  101. package/src/metrics/send-event.ts +92 -0
  102. package/src/miniflare-cli/assets.ts +554 -0
  103. package/src/miniflare-cli/enum-keys.ts +8 -8
  104. package/src/miniflare-cli/index.ts +198 -32
  105. package/src/miniflare-cli/request-context.ts +18 -18
  106. package/src/module-collection.ts +212 -212
  107. package/src/open-in-browser.ts +4 -6
  108. package/src/package-manager.ts +173 -128
  109. package/src/pages/build.tsx +238 -0
  110. package/src/pages/constants.ts +12 -0
  111. package/src/pages/deployments.tsx +106 -0
  112. package/src/pages/dev.tsx +528 -0
  113. package/src/pages/errors.ts +22 -0
  114. package/src/pages/functions/buildPlugin.ts +109 -0
  115. package/src/pages/functions/buildWorker.ts +155 -0
  116. package/{pages → src/pages}/functions/filepath-routing.test.ts +113 -113
  117. package/src/pages/functions/filepath-routing.ts +189 -0
  118. package/src/pages/functions/identifiers.ts +78 -0
  119. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  120. package/src/pages/functions/routes-consolidation.ts +73 -0
  121. package/src/pages/functions/routes-transformation.test.ts +271 -0
  122. package/src/pages/functions/routes-transformation.ts +122 -0
  123. package/src/pages/functions/routes.ts +151 -0
  124. package/src/pages/functions.tsx +96 -0
  125. package/src/pages/index.tsx +94 -0
  126. package/src/pages/projects.tsx +169 -0
  127. package/src/pages/publish.tsx +391 -0
  128. package/src/pages/types.ts +49 -0
  129. package/src/pages/upload.tsx +413 -0
  130. package/src/pages/utils.ts +12 -0
  131. package/src/parse.ts +209 -125
  132. package/src/paths.ts +6 -6
  133. package/src/preview.ts +31 -0
  134. package/src/proxy.ts +410 -389
  135. package/src/publish.ts +773 -534
  136. package/src/pubsub/index.ts +286 -0
  137. package/src/pubsub/pubsub-commands.tsx +623 -0
  138. package/src/r2.ts +100 -19
  139. package/src/selfsigned.d.ts +23 -23
  140. package/src/sites.tsx +278 -201
  141. package/src/tail/filters.ts +111 -109
  142. package/src/tail/index.ts +230 -217
  143. package/src/tail/printing.ts +86 -46
  144. package/src/update-check.ts +11 -11
  145. package/src/user/choose-account.tsx +69 -0
  146. package/src/user/env-vars.ts +46 -0
  147. package/src/user/generate-auth-url.ts +33 -0
  148. package/src/user/generate-random-state.ts +16 -0
  149. package/src/user/index.ts +3 -0
  150. package/src/user/user.tsx +1191 -0
  151. package/src/whoami.tsx +141 -42
  152. package/src/worker.ts +123 -99
  153. package/src/zones.ts +167 -0
  154. package/templates/checked-fetch.js +17 -0
  155. package/templates/first-party-worker-module-facade.ts +18 -0
  156. package/templates/format-dev-errors.ts +32 -0
  157. package/templates/new-worker-scheduled.js +3 -3
  158. package/templates/new-worker-scheduled.ts +15 -15
  159. package/templates/new-worker.js +3 -3
  160. package/templates/new-worker.ts +15 -15
  161. package/templates/no-op-worker.js +10 -0
  162. package/templates/pages-shim.ts +9 -0
  163. package/templates/pages-template-plugin.ts +167 -0
  164. package/templates/pages-template-worker.ts +172 -0
  165. package/templates/serve-static-assets.ts +63 -0
  166. package/templates/service-bindings-module-facade.js +54 -0
  167. package/templates/service-bindings-sw-facade.js +42 -0
  168. package/templates/tsconfig.json +95 -95
  169. package/wrangler-dist/cli.d.ts +338 -0
  170. package/wrangler-dist/cli.js +95449 -67524
  171. package/pages/functions/buildPlugin.ts +0 -105
  172. package/pages/functions/buildWorker.ts +0 -151
  173. package/pages/functions/filepath-routing.ts +0 -189
  174. package/pages/functions/identifiers.ts +0 -78
  175. package/pages/functions/routes.ts +0 -156
  176. package/pages/functions/template-plugin.ts +0 -147
  177. package/pages/functions/template-worker.ts +0 -143
  178. package/src/__tests__/helpers/faye-websocket.d.ts +0 -6
  179. package/src/pages.tsx +0 -2038
  180. package/src/user.tsx +0 -1203
  181. package/templates/static-asset-facade.js +0 -47
  182. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  183. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  184. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  185. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  186. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  187. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  188. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  189. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  190. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  191. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  192. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  193. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  194. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  195. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  196. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  197. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  198. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  199. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  200. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  201. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  202. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  203. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  204. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  205. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  206. package/vendor/wrangler-mime/LICENSE +0 -21
  207. package/vendor/wrangler-mime/Mime.js +0 -97
  208. package/vendor/wrangler-mime/README.md +0 -187
  209. package/vendor/wrangler-mime/cli.js +0 -46
  210. package/vendor/wrangler-mime/index.js +0 -4
  211. package/vendor/wrangler-mime/lite.js +0 -4
  212. package/vendor/wrangler-mime/package.json +0 -52
  213. package/vendor/wrangler-mime/types/other.js +0 -1
  214. package/vendor/wrangler-mime/types/standard.js +0 -1
@@ -1,52 +1,58 @@
1
1
  import { writeFileSync } from "node:fs";
2
- import { Headers } from "undici";
2
+ import { FormData, Headers } from "undici";
3
3
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
4
4
  import {
5
- setMockResponse,
6
- unsetAllMocks,
7
- unsetMockFetchKVGetValues,
8
- setMockFetchKVGetValue,
5
+ setMockResponse,
6
+ unsetAllMocks,
7
+ unsetSpecialMockFns,
8
+ setMockFetchKVGetValue,
9
+ setMockRawResponse,
10
+ createFetchResult,
9
11
  } from "./helpers/mock-cfetch";
10
12
  import { mockConsoleMethods } from "./helpers/mock-console";
11
13
  import { clearConfirmMocks, mockConfirm } from "./helpers/mock-dialogs";
14
+ import { useMockIsTTY } from "./helpers/mock-istty";
12
15
  import { mockKeyListRequest } from "./helpers/mock-kv";
16
+ import { mockGetMemberships } from "./helpers/mock-oauth-flow";
17
+ import { mockProcess } from "./helpers/mock-process";
13
18
  import { runInTempDir } from "./helpers/run-in-tmp";
14
19
  import { runWrangler } from "./helpers/run-wrangler";
15
20
  import type { KeyValue, KVNamespaceInfo, NamespaceKeyInfo } from "../kv";
16
21
 
17
22
  describe("wrangler", () => {
18
- mockAccountId();
19
- mockApiToken();
20
- runInTempDir();
21
- const std = mockConsoleMethods();
22
-
23
- afterEach(() => {
24
- unsetAllMocks();
25
- clearConfirmMocks();
26
- });
27
-
28
- describe("kv:namespace", () => {
29
- describe("create", () => {
30
- function mockCreateRequest(expectedTitle: string) {
31
- setMockResponse(
32
- "/accounts/:accountId/storage/kv/namespaces",
33
- "POST",
34
- ([_url, accountId], { body }) => {
35
- expect(accountId).toEqual("some-account-id");
36
- const title = JSON.parse(body as string).title;
37
- expect(title).toEqual(expectedTitle);
38
- return { id: "some-namespace-id" };
39
- }
40
- );
41
- }
42
-
43
- it("should error if no namespace is given", async () => {
44
- await expect(
45
- runWrangler("kv:namespace create")
46
- ).rejects.toThrowErrorMatchingInlineSnapshot(
47
- `"Not enough non-option arguments: got 0, need at least 1"`
48
- );
49
- expect(std.out).toMatchInlineSnapshot(`
23
+ mockAccountId();
24
+ mockApiToken();
25
+ runInTempDir();
26
+ const std = mockConsoleMethods();
27
+ const proc = mockProcess();
28
+
29
+ afterEach(() => {
30
+ unsetAllMocks();
31
+ clearConfirmMocks();
32
+ });
33
+
34
+ describe("kv:namespace", () => {
35
+ describe("create", () => {
36
+ function mockCreateRequest(expectedTitle: string) {
37
+ setMockResponse(
38
+ "/accounts/:accountId/storage/kv/namespaces",
39
+ "POST",
40
+ ([_url, accountId], { body }) => {
41
+ expect(accountId).toEqual("some-account-id");
42
+ const title = JSON.parse(body as string).title;
43
+ expect(title).toEqual(expectedTitle);
44
+ return { id: "some-namespace-id" };
45
+ }
46
+ );
47
+ }
48
+
49
+ it("should error if no namespace is given", async () => {
50
+ await expect(
51
+ runWrangler("kv:namespace create")
52
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
53
+ `"Not enough non-option arguments: got 0, need at least 1"`
54
+ );
55
+ expect(std.out).toMatchInlineSnapshot(`
50
56
  "
51
57
  wrangler kv:namespace create <namespace>
52
58
 
@@ -64,20 +70,20 @@ describe("wrangler", () => {
64
70
  -e, --env Perform on a specific environment [string]
65
71
  --preview Interact with a preview namespace [boolean]"
66
72
  `);
67
- expect(std.err).toMatchInlineSnapshot(`
73
+ expect(std.err).toMatchInlineSnapshot(`
68
74
  "X [ERROR] Not enough non-option arguments: got 0, need at least 1
69
75
 
70
76
  "
71
77
  `);
72
- });
73
-
74
- it("should error if the namespace to create contains spaces", async () => {
75
- await expect(
76
- runWrangler("kv:namespace create abc def ghi")
77
- ).rejects.toThrowErrorMatchingInlineSnapshot(
78
- `"Unknown arguments: def, ghi"`
79
- );
80
- expect(std.out).toMatchInlineSnapshot(`
78
+ });
79
+
80
+ it("should error if the namespace to create contains spaces", async () => {
81
+ await expect(
82
+ runWrangler("kv:namespace create abc def ghi")
83
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
84
+ `"Unknown arguments: def, ghi"`
85
+ );
86
+ expect(std.out).toMatchInlineSnapshot(`
81
87
  "
82
88
  wrangler kv:namespace create <namespace>
83
89
 
@@ -95,21 +101,21 @@ describe("wrangler", () => {
95
101
  -e, --env Perform on a specific environment [string]
96
102
  --preview Interact with a preview namespace [boolean]"
97
103
  `);
98
- expect(std.err).toMatchInlineSnapshot(`
104
+ expect(std.err).toMatchInlineSnapshot(`
99
105
  "X [ERROR] Unknown arguments: def, ghi
100
106
 
101
107
  "
102
108
  `);
103
- });
109
+ });
104
110
 
105
- it("should error if the namespace to create is not valid", async () => {
106
- await expect(
107
- runWrangler("kv:namespace create abc-def")
108
- ).rejects.toThrowErrorMatchingInlineSnapshot(
109
- `"The namespace binding name \\"abc-def\\" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number."`
110
- );
111
+ it("should error if the namespace to create is not valid", async () => {
112
+ await expect(
113
+ runWrangler("kv:namespace create abc-def")
114
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
115
+ `"The namespace binding name \\"abc-def\\" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number."`
116
+ );
111
117
 
112
- expect(std.out).toMatchInlineSnapshot(`
118
+ expect(std.out).toMatchInlineSnapshot(`
113
119
  "
114
120
  wrangler kv:namespace create <namespace>
115
121
 
@@ -127,350 +133,400 @@ describe("wrangler", () => {
127
133
  -e, --env Perform on a specific environment [string]
128
134
  --preview Interact with a preview namespace [boolean]"
129
135
  `);
130
- expect(std.err).toMatchInlineSnapshot(`
136
+ expect(std.err).toMatchInlineSnapshot(`
131
137
  "X [ERROR] The namespace binding name \\"abc-def\\" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number.
132
138
 
133
139
  "
134
140
  `);
135
- });
141
+ });
136
142
 
137
- it("should create a namespace", async () => {
138
- mockCreateRequest("worker-UnitTestNamespace");
139
- await runWrangler("kv:namespace create UnitTestNamespace");
140
- expect(std.out).toMatchInlineSnapshot(`
143
+ it("should create a namespace", async () => {
144
+ mockCreateRequest("worker-UnitTestNamespace");
145
+ await runWrangler("kv:namespace create UnitTestNamespace");
146
+ expect(std.out).toMatchInlineSnapshot(`
141
147
  "🌀 Creating namespace with title \\"worker-UnitTestNamespace\\"
142
148
  ✨ Success!
143
149
  Add the following to your configuration file in your kv_namespaces array:
144
150
  { binding = \\"UnitTestNamespace\\", id = \\"some-namespace-id\\" }"
145
151
  `);
146
- });
152
+ });
147
153
 
148
- it("should create a preview namespace if configured to do so", async () => {
149
- mockCreateRequest("worker-UnitTestNamespace_preview");
150
- await runWrangler("kv:namespace create UnitTestNamespace --preview");
151
- expect(std.out).toMatchInlineSnapshot(`
154
+ it("should create a preview namespace if configured to do so", async () => {
155
+ mockCreateRequest("worker-UnitTestNamespace_preview");
156
+ await runWrangler("kv:namespace create UnitTestNamespace --preview");
157
+ expect(std.out).toMatchInlineSnapshot(`
152
158
  "🌀 Creating namespace with title \\"worker-UnitTestNamespace_preview\\"
153
159
  ✨ Success!
154
160
  Add the following to your configuration file in your kv_namespaces array:
155
161
  { binding = \\"UnitTestNamespace\\", preview_id = \\"some-namespace-id\\" }"
156
162
  `);
157
- });
163
+ });
158
164
 
159
- it("should create a namespace using configured worker name", async () => {
160
- writeFileSync("./wrangler.toml", 'name = "other-worker"', "utf-8");
161
- mockCreateRequest("other-worker-UnitTestNamespace");
162
- await runWrangler("kv:namespace create UnitTestNamespace");
163
- expect(std.out).toMatchInlineSnapshot(`
165
+ it("should create a namespace using configured worker name", async () => {
166
+ writeFileSync("./wrangler.toml", 'name = "other-worker"', "utf-8");
167
+ mockCreateRequest("other-worker-UnitTestNamespace");
168
+ await runWrangler("kv:namespace create UnitTestNamespace");
169
+ expect(std.out).toMatchInlineSnapshot(`
164
170
  "🌀 Creating namespace with title \\"other-worker-UnitTestNamespace\\"
165
171
  ✨ Success!
166
172
  Add the following to your configuration file in your kv_namespaces array:
167
173
  { binding = \\"UnitTestNamespace\\", id = \\"some-namespace-id\\" }"
168
174
  `);
169
- });
170
-
171
- it("should create a namespace in an environment if configured to do so", async () => {
172
- mockCreateRequest("worker-customEnv-UnitTestNamespace");
173
- await runWrangler(
174
- "kv:namespace create UnitTestNamespace --env customEnv"
175
- );
176
- expect(std.out).toMatchInlineSnapshot(`
175
+ });
176
+
177
+ it("should create a namespace in an environment if configured to do so", async () => {
178
+ mockCreateRequest("worker-customEnv-UnitTestNamespace");
179
+ await runWrangler(
180
+ "kv:namespace create UnitTestNamespace --env customEnv"
181
+ );
182
+ expect(std.out).toMatchInlineSnapshot(`
177
183
  "🌀 Creating namespace with title \\"worker-customEnv-UnitTestNamespace\\"
178
184
  ✨ Success!
179
185
  Add the following to your configuration file in your kv_namespaces array under [env.customEnv]:
180
186
  { binding = \\"UnitTestNamespace\\", id = \\"some-namespace-id\\" }"
181
187
  `);
182
- });
183
- });
184
-
185
- describe("list", () => {
186
- function mockListRequest(namespaces: unknown[]) {
187
- const requests = { count: 0 };
188
- setMockResponse(
189
- "/accounts/:accountId/storage/kv/namespaces",
190
- ([_url, accountId], init, query) => {
191
- requests.count++;
192
- expect(accountId).toEqual("some-account-id");
193
- expect(query.get("per_page")).toEqual("100");
194
- expect(query.get("order")).toEqual("title");
195
- expect(query.get("direction")).toEqual("asc");
196
- expect(query.get("page")).toEqual(`${requests.count}`);
197
- expect(init).toEqual({});
198
- const pageSize = Number(query.get("per_page"));
199
- const page = Number(query.get("page"));
200
- return namespaces.slice((page - 1) * pageSize, page * pageSize);
201
- }
202
- );
203
- return requests;
204
- }
205
-
206
- it("should list namespaces", async () => {
207
- const kvNamespaces: KVNamespaceInfo[] = [
208
- { title: "title-1", id: "id-1" },
209
- { title: "title-2", id: "id-2" },
210
- ];
211
- mockListRequest(kvNamespaces);
212
- await runWrangler("kv:namespace list");
213
-
214
- expect(std.err).toMatchInlineSnapshot(`""`);
215
- const namespaces = JSON.parse(std.out);
216
- expect(namespaces).toEqual(kvNamespaces);
217
- });
218
-
219
- it("should make multiple requests for paginated results", async () => {
220
- // Create a lot of mock namespaces, so that the fetch requests will be paginated
221
- const kvNamespaces: KVNamespaceInfo[] = [];
222
- for (let i = 0; i < 550; i++) {
223
- kvNamespaces.push({ title: "title-" + i, id: "id-" + i });
224
- }
225
- const requests = mockListRequest(kvNamespaces);
226
- await runWrangler("kv:namespace list");
227
- const namespaces = JSON.parse(std.out);
228
- expect(namespaces).toEqual(kvNamespaces);
229
- expect(requests.count).toEqual(6);
230
- });
231
- });
232
-
233
- describe("delete", () => {
234
- function mockDeleteRequest(expectedNamespaceId: string) {
235
- const requests = { count: 0 };
236
- setMockResponse(
237
- "/accounts/:accountId/storage/kv/namespaces/:namespaceId",
238
- "DELETE",
239
- ([_url, accountId, namespaceId]) => {
240
- requests.count++;
241
- expect(accountId).toEqual("some-account-id");
242
- expect(namespaceId).toEqual(expectedNamespaceId);
243
- return null;
244
- }
245
- );
246
- return requests;
247
- }
248
-
249
- it("should delete a namespace specified by id", async () => {
250
- const requests = mockDeleteRequest("some-namespace-id");
251
- await runWrangler(
252
- `kv:namespace delete --namespace-id some-namespace-id`
253
- );
254
- expect(requests.count).toEqual(1);
255
- });
256
-
257
- it("should delete a namespace specified by binding name", async () => {
258
- writeWranglerConfig();
259
- const requests = mockDeleteRequest("bound-id");
260
- await runWrangler(
261
- `kv:namespace delete --binding someBinding --preview false`
262
- );
263
- expect(requests.count).toEqual(1);
264
- });
265
-
266
- it("should delete a preview namespace specified by binding name", async () => {
267
- writeWranglerConfig();
268
- const requests = mockDeleteRequest("preview-bound-id");
269
- await runWrangler(
270
- `kv:namespace delete --binding someBinding --preview`
271
- );
272
- expect(requests.count).toEqual(1);
273
- });
274
-
275
- it("should error if a given binding name is not in the configured kv namespaces", async () => {
276
- writeWranglerConfig();
277
- await expect(runWrangler("kv:namespace delete --binding otherBinding"))
278
- .rejects.toThrowErrorMatchingInlineSnapshot(`
279
- "Not able to delete namespace.
280
- A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."
281
- `);
282
- expect(std.err).toMatchInlineSnapshot(`
188
+ });
189
+ });
190
+
191
+ describe("list", () => {
192
+ function mockListRequest(namespaces: unknown[]) {
193
+ const requests = { count: 0 };
194
+ setMockResponse(
195
+ "/accounts/:accountId/storage/kv/namespaces",
196
+ ([_url, accountId], init, query) => {
197
+ requests.count++;
198
+ expect(accountId).toEqual("some-account-id");
199
+ expect(query.get("per_page")).toEqual("100");
200
+ expect(query.get("order")).toEqual("title");
201
+ expect(query.get("direction")).toEqual("asc");
202
+ expect(query.get("page")).toEqual(`${requests.count}`);
203
+ expect(init).toEqual({});
204
+ const pageSize = Number(query.get("per_page"));
205
+ const page = Number(query.get("page"));
206
+ return namespaces.slice((page - 1) * pageSize, page * pageSize);
207
+ }
208
+ );
209
+ return requests;
210
+ }
211
+
212
+ it("should list namespaces", async () => {
213
+ const kvNamespaces: KVNamespaceInfo[] = [
214
+ { title: "title-1", id: "id-1" },
215
+ { title: "title-2", id: "id-2" },
216
+ ];
217
+ mockListRequest(kvNamespaces);
218
+ await runWrangler("kv:namespace list");
219
+
220
+ expect(std.err).toMatchInlineSnapshot(`""`);
221
+ const namespaces = JSON.parse(std.out);
222
+ expect(namespaces).toEqual(kvNamespaces);
223
+ });
224
+
225
+ it("should make multiple requests for paginated results", async () => {
226
+ // Create a lot of mock namespaces, so that the fetch requests will be paginated
227
+ const kvNamespaces: KVNamespaceInfo[] = [];
228
+ for (let i = 0; i < 550; i++) {
229
+ kvNamespaces.push({ title: "title-" + i, id: "id-" + i });
230
+ }
231
+ const requests = mockListRequest(kvNamespaces);
232
+ await runWrangler("kv:namespace list");
233
+ const namespaces = JSON.parse(std.out);
234
+ expect(namespaces).toEqual(kvNamespaces);
235
+ expect(requests.count).toEqual(6);
236
+ });
237
+ });
238
+
239
+ describe("delete", () => {
240
+ function mockDeleteRequest(expectedNamespaceId: string) {
241
+ const requests = { count: 0 };
242
+ setMockResponse(
243
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId",
244
+ "DELETE",
245
+ ([_url, accountId, namespaceId]) => {
246
+ requests.count++;
247
+ expect(accountId).toEqual("some-account-id");
248
+ expect(namespaceId).toEqual(expectedNamespaceId);
249
+ return null;
250
+ }
251
+ );
252
+ return requests;
253
+ }
254
+
255
+ it("should delete a namespace specified by id", async () => {
256
+ const requests = mockDeleteRequest("some-namespace-id");
257
+ await runWrangler(
258
+ `kv:namespace delete --namespace-id some-namespace-id`
259
+ );
260
+ expect(requests.count).toEqual(1);
261
+ });
262
+
263
+ it("should delete a namespace specified by binding name", async () => {
264
+ writeWranglerConfig();
265
+ const requests = mockDeleteRequest("bound-id");
266
+ await runWrangler(
267
+ `kv:namespace delete --binding someBinding --preview false`
268
+ );
269
+ expect(requests.count).toEqual(1);
270
+ });
271
+
272
+ it("should delete a preview namespace specified by binding name", async () => {
273
+ writeWranglerConfig();
274
+ const requests = mockDeleteRequest("preview-bound-id");
275
+ await runWrangler(
276
+ `kv:namespace delete --binding someBinding --preview`
277
+ );
278
+ expect(requests.count).toEqual(1);
279
+ });
280
+
281
+ it("should error if a given binding name is not in the configured kv namespaces", async () => {
282
+ writeWranglerConfig();
283
+ await expect(runWrangler("kv:namespace delete --binding otherBinding"))
284
+ .rejects.toThrowErrorMatchingInlineSnapshot(`
285
+ "Not able to delete namespace.
286
+ A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."
287
+ `);
288
+ expect(std.err).toMatchInlineSnapshot(`
283
289
  "X [ERROR] Not able to delete namespace.
284
290
 
285
291
  A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
286
292
 
287
293
  "
288
294
  `);
289
- });
290
-
291
- it("should delete a namespace specified by binding name in a given environment", async () => {
292
- writeWranglerConfig();
293
- const requests = mockDeleteRequest("env-bound-id");
294
- await runWrangler(
295
- "kv:namespace delete --binding someBinding --env some-environment --preview false"
296
- );
297
-
298
- expect(std.out).toMatchInlineSnapshot(`""`);
299
- expect(std.err).toMatchInlineSnapshot(`""`);
300
- expect(requests.count).toEqual(1);
301
- });
302
-
303
- it("should delete a preview namespace specified by binding name in a given environment", async () => {
304
- writeWranglerConfig();
305
- const requests = mockDeleteRequest("preview-env-bound-id");
306
- await runWrangler(
307
- `kv:namespace delete --binding someBinding --env some-environment --preview`
308
- );
309
- expect(requests.count).toEqual(1);
310
- });
311
- });
312
- });
313
-
314
- describe("kv:key", () => {
315
- describe("put", () => {
316
- function mockKeyPutRequest(
317
- expectedNamespaceId: string,
318
- expectedKV: KeyValue
319
- ) {
320
- const requests = { count: 0 };
321
- setMockResponse(
322
- "/accounts/:accountId/storage/kv/namespaces/:namespaceId/values/:key",
323
- "PUT",
324
- ([_url, accountId, namespaceId, key], { body }, query) => {
325
- requests.count++;
326
- expect(accountId).toEqual("some-account-id");
327
- expect(namespaceId).toEqual(expectedNamespaceId);
328
- expect(key).toEqual(expectedKV.key);
329
- expect(body).toEqual(expectedKV.value);
330
- if (expectedKV.expiration !== undefined) {
331
- expect(query.get("expiration")).toEqual(
332
- `${expectedKV.expiration}`
333
- );
334
- } else {
335
- expect(query.has("expiration")).toBe(false);
336
- }
337
- if (expectedKV.expiration_ttl) {
338
- expect(query.get("expiration_ttl")).toEqual(
339
- `${expectedKV.expiration_ttl}`
340
- );
341
- } else {
342
- expect(query.has("expiration_ttl")).toBe(false);
343
- }
344
- return null;
345
- }
346
- );
347
- return requests;
348
- }
349
-
350
- it("should put a key in a given namespace specified by namespace-id", async () => {
351
- const requests = mockKeyPutRequest("some-namespace-id", {
352
- key: "my-key",
353
- value: "my-value",
354
- });
355
-
356
- await runWrangler(
357
- "kv:key put my-key my-value --namespace-id some-namespace-id"
358
- );
359
-
360
- expect(requests.count).toEqual(1);
361
- expect(std.out).toMatchInlineSnapshot(
362
- `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace some-namespace-id."`
363
- );
364
- expect(std.err).toMatchInlineSnapshot(`""`);
365
- });
366
-
367
- it("should encode the key in the api request to put a value", async () => {
368
- const requests = mockKeyPutRequest("DS9", {
369
- key: "%2Fmy-key",
370
- value: "my-value",
371
- });
372
-
373
- await runWrangler("kv:key put /my-key my-value --namespace-id DS9");
374
-
375
- expect(requests.count).toEqual(1);
376
- expect(std.out).toMatchInlineSnapshot(
377
- `"Writing the value \\"my-value\\" to key \\"/my-key\\" on namespace DS9."`
378
- );
379
- expect(std.err).toMatchInlineSnapshot(`""`);
380
- });
381
-
382
- it("should put a key in a given namespace specified by binding", async () => {
383
- writeWranglerConfig();
384
- const requests = mockKeyPutRequest("bound-id", {
385
- key: "my-key",
386
- value: "my-value",
387
- });
388
- await runWrangler(
389
- "kv:key put my-key my-value --binding someBinding --preview false"
390
- );
391
-
392
- expect(std.out).toMatchInlineSnapshot(
393
- `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace bound-id."`
394
- );
395
- expect(std.err).toMatchInlineSnapshot(`""`);
396
- expect(requests.count).toEqual(1);
397
- });
398
-
399
- it("should put a key in a given preview namespace specified by binding", async () => {
400
- writeWranglerConfig();
401
- const requests = mockKeyPutRequest("preview-bound-id", {
402
- key: "my-key",
403
- value: "my-value",
404
- });
405
-
406
- await runWrangler(
407
- "kv:key put my-key my-value --binding someBinding --preview"
408
- );
409
-
410
- expect(std.out).toMatchInlineSnapshot(
411
- `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace preview-bound-id."`
412
- );
413
- expect(std.err).toMatchInlineSnapshot(`""`);
414
- expect(requests.count).toEqual(1);
415
- });
416
-
417
- it("should add expiration and ttl properties when putting a key", async () => {
418
- const requests = mockKeyPutRequest("some-namespace-id", {
419
- key: "my-key",
420
- value: "my-value",
421
- expiration: 10,
422
- expiration_ttl: 20,
423
- });
424
- await runWrangler(
425
- "kv:key put my-key my-value --namespace-id some-namespace-id --expiration 10 --ttl 20"
426
- );
427
- expect(requests.count).toEqual(1);
428
- expect(std.out).toMatchInlineSnapshot(
429
- `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace some-namespace-id."`
430
- );
431
- expect(std.err).toMatchInlineSnapshot(`""`);
432
- });
433
-
434
- it("should put a key to the specified environment in a given namespace", async () => {
435
- writeWranglerConfig();
436
- const requests = mockKeyPutRequest("env-bound-id", {
437
- key: "my-key",
438
- value: "my-value",
439
- });
440
- await runWrangler(
441
- "kv:key put my-key my-value --binding someBinding --env some-environment --preview false"
442
- );
443
- expect(std.out).toMatchInlineSnapshot(
444
- `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace env-bound-id."`
445
- );
446
- expect(std.err).toMatchInlineSnapshot(`""`);
447
- expect(requests.count).toEqual(1);
448
- });
449
-
450
- it("should put a key with a value loaded from a given path", async () => {
451
- writeFileSync("foo.txt", "file-contents", "utf-8");
452
- const requests = mockKeyPutRequest("some-namespace-id", {
453
- key: "my-key",
454
- value: "file-contents",
455
- });
456
- await runWrangler(
457
- "kv:key put my-key --namespace-id some-namespace-id --path foo.txt"
458
- );
459
- expect(std.out).toMatchInlineSnapshot(
460
- `"Writing the contents of foo.txt to the key \\"my-key\\" on namespace some-namespace-id."`
461
- );
462
- expect(std.err).toMatchInlineSnapshot(`""`);
463
- expect(requests.count).toEqual(1);
464
- });
465
-
466
- it("should error if no key is provided", async () => {
467
- await expect(
468
- runWrangler("kv:key put")
469
- ).rejects.toThrowErrorMatchingInlineSnapshot(
470
- `"Not enough non-option arguments: got 0, need at least 1"`
471
- );
472
-
473
- expect(std.out).toMatchInlineSnapshot(`
295
+ });
296
+
297
+ it("should delete a namespace specified by binding name in a given environment", async () => {
298
+ writeWranglerConfig();
299
+ const requests = mockDeleteRequest("env-bound-id");
300
+ await runWrangler(
301
+ "kv:namespace delete --binding someBinding --env some-environment --preview false"
302
+ );
303
+
304
+ expect(std.out).toMatchInlineSnapshot(`
305
+ "Deleting KV namespace env-bound-id.
306
+ Deleted KV namespace env-bound-id."
307
+ `);
308
+ expect(std.err).toMatchInlineSnapshot(`""`);
309
+ expect(requests.count).toEqual(1);
310
+ });
311
+
312
+ it("should delete a preview namespace specified by binding name in a given environment", async () => {
313
+ writeWranglerConfig();
314
+ const requests = mockDeleteRequest("preview-env-bound-id");
315
+ await runWrangler(
316
+ `kv:namespace delete --binding someBinding --env some-environment --preview`
317
+ );
318
+ expect(requests.count).toEqual(1);
319
+ });
320
+ });
321
+ });
322
+
323
+ describe("kv:key", () => {
324
+ describe("put", () => {
325
+ function mockKeyPutRequest(
326
+ expectedNamespaceId: string,
327
+ expectedKV: KeyValue
328
+ ) {
329
+ const requests = { count: 0 };
330
+ setMockResponse(
331
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/values/:key",
332
+ "PUT",
333
+ ([_url, accountId, namespaceId, key], { body }, query) => {
334
+ requests.count++;
335
+ expect(accountId).toEqual("some-account-id");
336
+ expect(namespaceId).toEqual(expectedNamespaceId);
337
+ expect(key).toEqual(expectedKV.key);
338
+ if (expectedKV.metadata) {
339
+ expect(body).toBeInstanceOf(FormData);
340
+ expect((body as FormData).get("value")).toEqual(expectedKV.value);
341
+ expect((body as FormData).get("metadata")).toEqual(
342
+ JSON.stringify(expectedKV.metadata)
343
+ );
344
+ } else {
345
+ expect(body).toEqual(expectedKV.value);
346
+ }
347
+ if (expectedKV.expiration !== undefined) {
348
+ expect(query.get("expiration")).toEqual(
349
+ `${expectedKV.expiration}`
350
+ );
351
+ } else {
352
+ expect(query.has("expiration")).toBe(false);
353
+ }
354
+ if (expectedKV.expiration_ttl) {
355
+ expect(query.get("expiration_ttl")).toEqual(
356
+ `${expectedKV.expiration_ttl}`
357
+ );
358
+ } else {
359
+ expect(query.has("expiration_ttl")).toBe(false);
360
+ }
361
+ return null;
362
+ }
363
+ );
364
+ return requests;
365
+ }
366
+
367
+ it("should put a key in a given namespace specified by namespace-id", async () => {
368
+ const requests = mockKeyPutRequest("some-namespace-id", {
369
+ key: "my-key",
370
+ value: "my-value",
371
+ });
372
+
373
+ await runWrangler(
374
+ "kv:key put my-key my-value --namespace-id some-namespace-id"
375
+ );
376
+
377
+ expect(requests.count).toEqual(1);
378
+ expect(std.out).toMatchInlineSnapshot(
379
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace some-namespace-id."`
380
+ );
381
+ expect(std.err).toMatchInlineSnapshot(`""`);
382
+ });
383
+
384
+ it("should encode the key in the api request to put a value", async () => {
385
+ const requests = mockKeyPutRequest("DS9", {
386
+ key: "%2Fmy-key",
387
+ value: "my-value",
388
+ });
389
+
390
+ await runWrangler("kv:key put /my-key my-value --namespace-id DS9");
391
+
392
+ expect(requests.count).toEqual(1);
393
+ expect(std.out).toMatchInlineSnapshot(
394
+ `"Writing the value \\"my-value\\" to key \\"/my-key\\" on namespace DS9."`
395
+ );
396
+ expect(std.err).toMatchInlineSnapshot(`""`);
397
+ });
398
+
399
+ it("should put a key in a given namespace specified by binding", async () => {
400
+ writeWranglerConfig();
401
+ const requests = mockKeyPutRequest("bound-id", {
402
+ key: "my-key",
403
+ value: "my-value",
404
+ });
405
+ await runWrangler(
406
+ "kv:key put my-key my-value --binding someBinding --preview false"
407
+ );
408
+
409
+ expect(std.out).toMatchInlineSnapshot(
410
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace bound-id."`
411
+ );
412
+ expect(std.err).toMatchInlineSnapshot(`""`);
413
+ expect(requests.count).toEqual(1);
414
+ });
415
+
416
+ it("should put a key in a given preview namespace specified by binding", async () => {
417
+ writeWranglerConfig();
418
+ const requests = mockKeyPutRequest("preview-bound-id", {
419
+ key: "my-key",
420
+ value: "my-value",
421
+ });
422
+
423
+ await runWrangler(
424
+ "kv:key put my-key my-value --binding someBinding --preview"
425
+ );
426
+
427
+ expect(std.out).toMatchInlineSnapshot(
428
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace preview-bound-id."`
429
+ );
430
+ expect(std.err).toMatchInlineSnapshot(`""`);
431
+ expect(requests.count).toEqual(1);
432
+ });
433
+
434
+ it("should add expiration and ttl properties when putting a key", async () => {
435
+ const requests = mockKeyPutRequest("some-namespace-id", {
436
+ key: "my-key",
437
+ value: "my-value",
438
+ expiration: 10,
439
+ expiration_ttl: 20,
440
+ });
441
+ await runWrangler(
442
+ "kv:key put my-key my-value --namespace-id some-namespace-id --expiration 10 --ttl 20"
443
+ );
444
+ expect(requests.count).toEqual(1);
445
+ expect(std.out).toMatchInlineSnapshot(
446
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace some-namespace-id."`
447
+ );
448
+ expect(std.err).toMatchInlineSnapshot(`""`);
449
+ });
450
+
451
+ it("should put a key to the specified environment in a given namespace", async () => {
452
+ writeWranglerConfig();
453
+ const requests = mockKeyPutRequest("env-bound-id", {
454
+ key: "my-key",
455
+ value: "my-value",
456
+ });
457
+ await runWrangler(
458
+ "kv:key put my-key my-value --binding someBinding --env some-environment --preview false"
459
+ );
460
+ expect(std.out).toMatchInlineSnapshot(
461
+ `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace env-bound-id."`
462
+ );
463
+ expect(std.err).toMatchInlineSnapshot(`""`);
464
+ expect(requests.count).toEqual(1);
465
+ });
466
+
467
+ it("should put a key with a value loaded from a given path", async () => {
468
+ const buf = Buffer.from("file-contents", "utf-8");
469
+ writeFileSync("foo.txt", buf);
470
+ const requests = mockKeyPutRequest("some-namespace-id", {
471
+ key: "my-key",
472
+ value: buf,
473
+ });
474
+ await runWrangler(
475
+ "kv:key put my-key --namespace-id some-namespace-id --path foo.txt"
476
+ );
477
+ expect(std.out).toMatchInlineSnapshot(
478
+ `"Writing the contents of foo.txt to the key \\"my-key\\" on namespace some-namespace-id."`
479
+ );
480
+ expect(std.err).toMatchInlineSnapshot(`""`);
481
+ expect(requests.count).toEqual(1);
482
+ });
483
+
484
+ it("should put a key with a binary value loaded from a given path", async () => {
485
+ const buf = Buffer.from(
486
+ "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC",
487
+ "base64"
488
+ );
489
+ writeFileSync("test.png", buf);
490
+ const requests = mockKeyPutRequest("another-namespace-id", {
491
+ key: "my-key",
492
+ value: buf,
493
+ });
494
+ await runWrangler(
495
+ "kv:key put my-key --namespace-id another-namespace-id --path test.png"
496
+ );
497
+ expect(std.out).toMatchInlineSnapshot(
498
+ `"Writing the contents of test.png to the key \\"my-key\\" on namespace another-namespace-id."`
499
+ );
500
+ expect(std.err).toMatchInlineSnapshot(`""`);
501
+ expect(requests.count).toEqual(1);
502
+ });
503
+
504
+ it("should put a key with metadata", async () => {
505
+ const requests = mockKeyPutRequest("some-namespace-id", {
506
+ key: "dKey",
507
+ value: "dVal",
508
+ metadata: {
509
+ mKey: "mValue",
510
+ },
511
+ });
512
+ await runWrangler(
513
+ `kv:key put dKey dVal --namespace-id some-namespace-id --metadata {"mKey":"mValue"}`
514
+ );
515
+ expect(requests.count).toEqual(1);
516
+ expect(std.out).toMatchInlineSnapshot(
517
+ `"Writing the value \\"dVal\\" to key \\"dKey\\" on namespace some-namespace-id with metadata \\"{\\"mKey\\":\\"mValue\\"}\\"."`
518
+ );
519
+ expect(std.err).toMatchInlineSnapshot(`""`);
520
+ });
521
+
522
+ it("should error if no key is provided", async () => {
523
+ await expect(
524
+ runWrangler("kv:key put")
525
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
526
+ `"Not enough non-option arguments: got 0, need at least 1"`
527
+ );
528
+
529
+ expect(std.out).toMatchInlineSnapshot(`
474
530
  "
475
531
  wrangler kv:key put <key> [value]
476
532
 
@@ -492,23 +548,24 @@ describe("wrangler", () => {
492
548
  --preview Interact with a preview namespace [boolean]
493
549
  --ttl Time for which the entries should be visible [number]
494
550
  --expiration Time since the UNIX epoch after which the entry expires [number]
551
+ --metadata Arbitrary JSON that is associated with a key [string]
495
552
  --path Read value from the file at a given path [string]"
496
553
  `);
497
- expect(std.err).toMatchInlineSnapshot(`
554
+ expect(std.err).toMatchInlineSnapshot(`
498
555
  "X [ERROR] Not enough non-option arguments: got 0, need at least 1
499
556
 
500
557
  "
501
558
  `);
502
- });
559
+ });
503
560
 
504
- it("should error if no binding nor namespace is provided", async () => {
505
- await expect(
506
- runWrangler("kv:key put foo bar")
507
- ).rejects.toThrowErrorMatchingInlineSnapshot(
508
- `"Exactly one of the arguments binding and namespace-id is required"`
509
- );
561
+ it("should error if no binding nor namespace is provided", async () => {
562
+ await expect(
563
+ runWrangler("kv:key put foo bar")
564
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
565
+ `"Exactly one of the arguments binding and namespace-id is required"`
566
+ );
510
567
 
511
- expect(std.out).toMatchInlineSnapshot(`
568
+ expect(std.out).toMatchInlineSnapshot(`
512
569
  "
513
570
  wrangler kv:key put <key> [value]
514
571
 
@@ -530,23 +587,24 @@ describe("wrangler", () => {
530
587
  --preview Interact with a preview namespace [boolean]
531
588
  --ttl Time for which the entries should be visible [number]
532
589
  --expiration Time since the UNIX epoch after which the entry expires [number]
590
+ --metadata Arbitrary JSON that is associated with a key [string]
533
591
  --path Read value from the file at a given path [string]"
534
592
  `);
535
- expect(std.err).toMatchInlineSnapshot(`
593
+ expect(std.err).toMatchInlineSnapshot(`
536
594
  "X [ERROR] Exactly one of the arguments binding and namespace-id is required
537
595
 
538
596
  "
539
597
  `);
540
- });
598
+ });
541
599
 
542
- it("should error if both binding and namespace is provided", async () => {
543
- await expect(
544
- runWrangler("kv:key put foo bar --binding x --namespace-id y")
545
- ).rejects.toThrowErrorMatchingInlineSnapshot(
546
- `"Arguments binding and namespace-id are mutually exclusive"`
547
- );
600
+ it("should error if both binding and namespace is provided", async () => {
601
+ await expect(
602
+ runWrangler("kv:key put foo bar --binding x --namespace-id y")
603
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
604
+ `"Arguments binding and namespace-id are mutually exclusive"`
605
+ );
548
606
 
549
- expect(std.out).toMatchInlineSnapshot(`
607
+ expect(std.out).toMatchInlineSnapshot(`
550
608
  "
551
609
  wrangler kv:key put <key> [value]
552
610
 
@@ -568,23 +626,24 @@ describe("wrangler", () => {
568
626
  --preview Interact with a preview namespace [boolean]
569
627
  --ttl Time for which the entries should be visible [number]
570
628
  --expiration Time since the UNIX epoch after which the entry expires [number]
629
+ --metadata Arbitrary JSON that is associated with a key [string]
571
630
  --path Read value from the file at a given path [string]"
572
631
  `);
573
- expect(std.err).toMatchInlineSnapshot(`
632
+ expect(std.err).toMatchInlineSnapshot(`
574
633
  "X [ERROR] Arguments binding and namespace-id are mutually exclusive
575
634
 
576
635
  "
577
636
  `);
578
- });
637
+ });
579
638
 
580
- it("should error if no value nor path is provided", async () => {
581
- await expect(
582
- runWrangler("kv:key put key --namespace-id 12345")
583
- ).rejects.toThrowErrorMatchingInlineSnapshot(
584
- `"Exactly one of the arguments value and path is required"`
585
- );
639
+ it("should error if no value nor path is provided", async () => {
640
+ await expect(
641
+ runWrangler("kv:key put key --namespace-id 12345")
642
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
643
+ `"Exactly one of the arguments value and path is required"`
644
+ );
586
645
 
587
- expect(std.out).toMatchInlineSnapshot(`
646
+ expect(std.out).toMatchInlineSnapshot(`
588
647
  "
589
648
  wrangler kv:key put <key> [value]
590
649
 
@@ -606,23 +665,24 @@ describe("wrangler", () => {
606
665
  --preview Interact with a preview namespace [boolean]
607
666
  --ttl Time for which the entries should be visible [number]
608
667
  --expiration Time since the UNIX epoch after which the entry expires [number]
668
+ --metadata Arbitrary JSON that is associated with a key [string]
609
669
  --path Read value from the file at a given path [string]"
610
670
  `);
611
- expect(std.err).toMatchInlineSnapshot(`
671
+ expect(std.err).toMatchInlineSnapshot(`
612
672
  "X [ERROR] Exactly one of the arguments value and path is required
613
673
 
614
674
  "
615
675
  `);
616
- });
676
+ });
617
677
 
618
- it("should error if both value and path is provided", async () => {
619
- await expect(
620
- runWrangler("kv:key put key value --path xyz --namespace-id 12345")
621
- ).rejects.toThrowErrorMatchingInlineSnapshot(
622
- `"Arguments value and path are mutually exclusive"`
623
- );
678
+ it("should error if both value and path is provided", async () => {
679
+ await expect(
680
+ runWrangler("kv:key put key value --path xyz --namespace-id 12345")
681
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
682
+ `"Arguments value and path are mutually exclusive"`
683
+ );
624
684
 
625
- expect(std.out).toMatchInlineSnapshot(`
685
+ expect(std.out).toMatchInlineSnapshot(`
626
686
  "
627
687
  wrangler kv:key put <key> [value]
628
688
 
@@ -644,69 +704,70 @@ describe("wrangler", () => {
644
704
  --preview Interact with a preview namespace [boolean]
645
705
  --ttl Time for which the entries should be visible [number]
646
706
  --expiration Time since the UNIX epoch after which the entry expires [number]
707
+ --metadata Arbitrary JSON that is associated with a key [string]
647
708
  --path Read value from the file at a given path [string]"
648
709
  `);
649
- expect(std.err).toMatchInlineSnapshot(`
710
+ expect(std.err).toMatchInlineSnapshot(`
650
711
  "X [ERROR] Arguments value and path are mutually exclusive
651
712
 
652
713
  "
653
714
  `);
654
- });
715
+ });
655
716
 
656
- it("should error if a given binding name is not in the configured kv namespaces", async () => {
657
- writeWranglerConfig();
658
- await expect(
659
- runWrangler("kv:key put key value --binding otherBinding")
660
- ).rejects.toThrowErrorMatchingInlineSnapshot(
661
- `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
662
- );
717
+ it("should error if a given binding name is not in the configured kv namespaces", async () => {
718
+ writeWranglerConfig();
719
+ await expect(
720
+ runWrangler("kv:key put key value --binding otherBinding")
721
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
722
+ `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
723
+ );
663
724
 
664
- expect(std.out).toMatchInlineSnapshot(`
725
+ expect(std.out).toMatchInlineSnapshot(`
665
726
  "
666
727
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
667
728
  `);
668
- expect(std.err).toMatchInlineSnapshot(`
729
+ expect(std.err).toMatchInlineSnapshot(`
669
730
  "X [ERROR] A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
670
731
 
671
732
  "
672
733
  `);
673
- });
674
-
675
- it("should error if a given binding has both preview and non-preview and --preview is not specified", async () => {
676
- writeWranglerConfig();
677
- const requests = mockKeyPutRequest("preview-bound-id", {
678
- key: "my-key",
679
- value: "my-value",
680
- });
681
- await expect(
682
- runWrangler("kv:key put my-key my-value --binding someBinding")
683
- ).rejects.toThrowErrorMatchingInlineSnapshot(
684
- `"someBinding has both a namespace ID and a preview ID. Specify \\"--preview\\" or \\"--preview false\\" to avoid writing data to the wrong namespace."`
685
- );
686
- expect(std.out).toMatchInlineSnapshot(`
734
+ });
735
+
736
+ it("should error if a given binding has both preview and non-preview and --preview is not specified", async () => {
737
+ writeWranglerConfig();
738
+ const requests = mockKeyPutRequest("preview-bound-id", {
739
+ key: "my-key",
740
+ value: "my-value",
741
+ });
742
+ await expect(
743
+ runWrangler("kv:key put my-key my-value --binding someBinding")
744
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
745
+ `"someBinding has both a namespace ID and a preview ID. Specify \\"--preview\\" or \\"--preview false\\" to avoid writing data to the wrong namespace."`
746
+ );
747
+ expect(std.out).toMatchInlineSnapshot(`
687
748
  "
688
749
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
689
750
  `);
690
- expect(std.err).toMatchInlineSnapshot(`
751
+ expect(std.err).toMatchInlineSnapshot(`
691
752
  "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.
692
753
 
693
754
  "
694
755
  `);
695
- expect(requests.count).toEqual(0);
696
- });
697
- });
698
-
699
- describe("list", () => {
700
- it("should list the keys of a namespace specified by namespace-id", async () => {
701
- const keys = [
702
- { name: "key-1" },
703
- { name: "key-2", expiration: 123456789 },
704
- { name: "key-3", expiration_ttl: 666 },
705
- ];
706
- mockKeyListRequest("some-namespace-id", keys);
707
- await runWrangler("kv:key list --namespace-id some-namespace-id");
708
- expect(std.err).toMatchInlineSnapshot(`""`);
709
- expect(std.out).toMatchInlineSnapshot(`
756
+ expect(requests.count).toEqual(0);
757
+ });
758
+ });
759
+
760
+ describe("list", () => {
761
+ it("should list the keys of a namespace specified by namespace-id", async () => {
762
+ const keys = [
763
+ { name: "key-1" },
764
+ { name: "key-2", expiration: 123456789 },
765
+ { name: "key-3", expiration_ttl: 666 },
766
+ ];
767
+ mockKeyListRequest("some-namespace-id", keys);
768
+ await runWrangler("kv:key list --namespace-id some-namespace-id");
769
+ expect(std.err).toMatchInlineSnapshot(`""`);
770
+ expect(std.out).toMatchInlineSnapshot(`
710
771
  "[
711
772
  {
712
773
  \\"name\\": \\"key-1\\"
@@ -721,16 +782,16 @@ describe("wrangler", () => {
721
782
  }
722
783
  ]"
723
784
  `);
724
- });
785
+ });
725
786
 
726
- it("should list the keys of a namespace specified by binding", async () => {
727
- writeWranglerConfig();
728
- const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
729
- mockKeyListRequest("bound-id", keys);
787
+ it("should list the keys of a namespace specified by binding", async () => {
788
+ writeWranglerConfig();
789
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
790
+ mockKeyListRequest("bound-id", keys);
730
791
 
731
- await runWrangler("kv:key list --binding someBinding");
732
- expect(std.err).toMatchInlineSnapshot(`""`);
733
- expect(std.out).toMatchInlineSnapshot(`
792
+ await runWrangler("kv:key list --binding someBinding");
793
+ expect(std.err).toMatchInlineSnapshot(`""`);
794
+ expect(std.out).toMatchInlineSnapshot(`
734
795
  "[
735
796
  {
736
797
  \\"name\\": \\"key-1\\"
@@ -743,15 +804,15 @@ describe("wrangler", () => {
743
804
  }
744
805
  ]"
745
806
  `);
746
- });
747
-
748
- it("should list the keys of a preview namespace specified by binding", async () => {
749
- writeWranglerConfig();
750
- const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
751
- mockKeyListRequest("preview-bound-id", keys);
752
- await runWrangler("kv:key list --binding someBinding --preview");
753
- expect(std.err).toMatchInlineSnapshot(`""`);
754
- expect(std.out).toMatchInlineSnapshot(`
807
+ });
808
+
809
+ it("should list the keys of a preview namespace specified by binding", async () => {
810
+ writeWranglerConfig();
811
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
812
+ mockKeyListRequest("preview-bound-id", keys);
813
+ await runWrangler("kv:key list --binding someBinding --preview");
814
+ expect(std.err).toMatchInlineSnapshot(`""`);
815
+ expect(std.out).toMatchInlineSnapshot(`
755
816
  "[
756
817
  {
757
818
  \\"name\\": \\"key-1\\"
@@ -764,17 +825,17 @@ describe("wrangler", () => {
764
825
  }
765
826
  ]"
766
827
  `);
767
- });
768
-
769
- it("should list the keys of a namespace specified by binding, in a given environment", async () => {
770
- writeWranglerConfig();
771
- const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
772
- mockKeyListRequest("env-bound-id", keys);
773
- await runWrangler(
774
- "kv:key list --binding someBinding --env some-environment"
775
- );
776
- expect(std.err).toMatchInlineSnapshot(`""`);
777
- expect(std.out).toMatchInlineSnapshot(`
828
+ });
829
+
830
+ it("should list the keys of a namespace specified by binding, in a given environment", async () => {
831
+ writeWranglerConfig();
832
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
833
+ mockKeyListRequest("env-bound-id", keys);
834
+ await runWrangler(
835
+ "kv:key list --binding someBinding --env some-environment"
836
+ );
837
+ expect(std.err).toMatchInlineSnapshot(`""`);
838
+ expect(std.out).toMatchInlineSnapshot(`
778
839
  "[
779
840
  {
780
841
  \\"name\\": \\"key-1\\"
@@ -787,17 +848,17 @@ describe("wrangler", () => {
787
848
  }
788
849
  ]"
789
850
  `);
790
- });
791
-
792
- it("should list the keys of a preview namespace specified by binding, in a given environment", async () => {
793
- writeWranglerConfig();
794
- const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
795
- mockKeyListRequest("preview-env-bound-id", keys);
796
- await runWrangler(
797
- "kv:key list --binding someBinding --preview --env some-environment"
798
- );
799
- expect(std.err).toMatchInlineSnapshot(`""`);
800
- expect(std.out).toMatchInlineSnapshot(`
851
+ });
852
+
853
+ it("should list the keys of a preview namespace specified by binding, in a given environment", async () => {
854
+ writeWranglerConfig();
855
+ const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }];
856
+ mockKeyListRequest("preview-env-bound-id", keys);
857
+ await runWrangler(
858
+ "kv:key list --binding someBinding --preview --env some-environment"
859
+ );
860
+ expect(std.err).toMatchInlineSnapshot(`""`);
861
+ expect(std.out).toMatchInlineSnapshot(`
801
862
  "[
802
863
  {
803
864
  \\"name\\": \\"key-1\\"
@@ -810,138 +871,195 @@ describe("wrangler", () => {
810
871
  }
811
872
  ]"
812
873
  `);
813
- });
814
-
815
- // We'll run the next test with variations on the cursor
816
- // that's returned on cloudflare's API after all results
817
- // have been drained.
818
- for (const blankCursorValue of [undefined, null, ""] as [
819
- undefined,
820
- null,
821
- ""
822
- ]) {
823
- describe(`cursor - ${blankCursorValue}`, () => {
824
- it("should make multiple requests for paginated results", async () => {
825
- // Create a lot of mock keys, so that the fetch requests will be paginated
826
- const keys: NamespaceKeyInfo[] = [];
827
- for (let i = 0; i < 550; i++) {
828
- keys.push({ name: "key-" + i });
829
- }
830
- // Ask for the keys in pages of size 100.
831
- const requests = mockKeyListRequest(
832
- "some-namespace-id",
833
- keys,
834
- 100,
835
- blankCursorValue
836
- );
837
- await runWrangler("kv:key list --namespace-id some-namespace-id");
838
- expect(std.err).toMatchInlineSnapshot(`""`);
839
- expect(JSON.parse(std.out)).toEqual(keys);
840
- expect(requests.count).toEqual(6);
841
- });
842
- });
843
- }
844
-
845
- it("should error if a given binding name is not in the configured kv namespaces", async () => {
846
- writeWranglerConfig();
847
- await expect(
848
- runWrangler("kv:key list --binding otherBinding")
849
- ).rejects.toThrowErrorMatchingInlineSnapshot(
850
- `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
851
- );
852
- expect(std.err).toMatchInlineSnapshot(`
874
+ });
875
+
876
+ // We'll run the next test with variations on the cursor
877
+ // that's returned on cloudflare's API after all results
878
+ // have been drained.
879
+ for (const blankCursorValue of [undefined, null, ""] as [
880
+ undefined,
881
+ null,
882
+ ""
883
+ ]) {
884
+ describe(`cursor - ${blankCursorValue}`, () => {
885
+ it("should make multiple requests for paginated results", async () => {
886
+ // Create a lot of mock keys, so that the fetch requests will be paginated
887
+ const keys: NamespaceKeyInfo[] = [];
888
+ for (let i = 0; i < 550; i++) {
889
+ keys.push({ name: "key-" + i });
890
+ }
891
+ // Ask for the keys in pages of size 100.
892
+ const requests = mockKeyListRequest(
893
+ "some-namespace-id",
894
+ keys,
895
+ 100,
896
+ blankCursorValue
897
+ );
898
+ await runWrangler("kv:key list --namespace-id some-namespace-id");
899
+ expect(std.err).toMatchInlineSnapshot(`""`);
900
+ expect(JSON.parse(std.out)).toEqual(keys);
901
+ expect(requests.count).toEqual(6);
902
+ });
903
+ });
904
+ }
905
+
906
+ it("should error if a given binding name is not in the configured kv namespaces", async () => {
907
+ writeWranglerConfig();
908
+ await expect(
909
+ runWrangler("kv:key list --binding otherBinding")
910
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
911
+ `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
912
+ );
913
+ expect(std.err).toMatchInlineSnapshot(`
853
914
  "X [ERROR] A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
854
915
 
855
916
  "
856
917
  `);
857
- expect(std.out).toMatchInlineSnapshot(`
918
+ expect(std.out).toMatchInlineSnapshot(`
858
919
  "
859
920
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
860
921
  `);
861
- });
862
- });
863
-
864
- describe("get", () => {
865
- afterEach(() => {
866
- unsetMockFetchKVGetValues();
867
- });
868
-
869
- it("should get a key in a given namespace specified by namespace-id", async () => {
870
- setMockFetchKVGetValue(
871
- "some-account-id",
872
- "some-namespace-id",
873
- "my-key",
874
- "my-value"
875
- );
876
- await runWrangler("kv:key get my-key --namespace-id some-namespace-id");
877
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
878
- expect(std.err).toMatchInlineSnapshot(`""`);
879
- });
880
-
881
- it("should get a key in a given namespace specified by binding", async () => {
882
- writeWranglerConfig();
883
- setMockFetchKVGetValue(
884
- "some-account-id",
885
- "bound-id",
886
- "my-key",
887
- "my-value"
888
- );
889
- await runWrangler(
890
- "kv:key get my-key --binding someBinding --preview false"
891
- );
892
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
893
- expect(std.err).toMatchInlineSnapshot(`""`);
894
- });
895
-
896
- it("should get a key in a given preview namespace specified by binding", async () => {
897
- writeWranglerConfig();
898
- setMockFetchKVGetValue(
899
- "some-account-id",
900
- "preview-bound-id",
901
- "my-key",
902
- "my-value"
903
- );
904
- await runWrangler("kv:key get my-key --binding someBinding --preview");
905
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
906
- expect(std.err).toMatchInlineSnapshot(`""`);
907
- });
908
-
909
- it("should get a key for the specified environment in a given namespace", async () => {
910
- writeWranglerConfig();
911
- setMockFetchKVGetValue(
912
- "some-account-id",
913
- "env-bound-id",
914
- "my-key",
915
- "my-value"
916
- );
917
- await runWrangler(
918
- "kv:key get my-key --binding someBinding --env some-environment --preview false"
919
- );
920
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
921
- expect(std.err).toMatchInlineSnapshot(`""`);
922
- });
923
-
924
- it("should encode the key in the api request to get a value", async () => {
925
- setMockFetchKVGetValue(
926
- "some-account-id",
927
- "some-namespace-id",
928
- "%2Fmy%2Ckey",
929
- "my-value"
930
- );
931
- await runWrangler(
932
- "kv:key get /my,key --namespace-id some-namespace-id"
933
- );
934
- expect(std.out).toMatchInlineSnapshot(`"my-value"`);
935
- expect(std.err).toMatchInlineSnapshot(`""`);
936
- });
937
-
938
- it("should error if no key is provided", async () => {
939
- await expect(
940
- runWrangler("kv:key get")
941
- ).rejects.toThrowErrorMatchingInlineSnapshot(
942
- `"Not enough non-option arguments: got 0, need at least 1"`
943
- );
944
- expect(std.out).toMatchInlineSnapshot(`
922
+ });
923
+ });
924
+
925
+ describe("get", () => {
926
+ afterEach(() => {
927
+ unsetSpecialMockFns();
928
+ });
929
+
930
+ it("should get a key in a given namespace specified by namespace-id", async () => {
931
+ setMockFetchKVGetValue(
932
+ "some-account-id",
933
+ "some-namespace-id",
934
+ "my-key",
935
+ "my-value"
936
+ );
937
+ await runWrangler("kv:key get my-key --namespace-id some-namespace-id");
938
+ expect(proc.write).toEqual(Buffer.from("my-value"));
939
+ expect(std.err).toMatchInlineSnapshot(`""`);
940
+ });
941
+
942
+ it("should get a key and decode the value from the response as a utf8 string if the `--text` flag is passed", async () => {
943
+ setMockFetchKVGetValue(
944
+ "some-account-id",
945
+ "some-namespace-id",
946
+ "my-key",
947
+ "my-value"
948
+ );
949
+ await runWrangler(
950
+ "kv:key get my-key --text --namespace-id some-namespace-id"
951
+ );
952
+ expect(proc.write).not.toEqual(Buffer.from("my-value"));
953
+ expect(std).toMatchInlineSnapshot(`
954
+ Object {
955
+ "debug": "",
956
+ "err": "",
957
+ "out": "my-value",
958
+ "warn": "",
959
+ }
960
+ `);
961
+ });
962
+
963
+ it("should get a binary and decode as utf8 text, resulting in improper decoding", async () => {
964
+ const buf = Buffer.from(
965
+ "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC",
966
+ "base64"
967
+ );
968
+ setMockFetchKVGetValue(
969
+ "some-account-id",
970
+ "some-namespace-id",
971
+ "my-key",
972
+ buf
973
+ );
974
+ await runWrangler(
975
+ "kv:key get my-key --text --namespace-id some-namespace-id"
976
+ );
977
+ expect(proc.write).not.toEqual(buf);
978
+ expect(JSON.stringify(std)).toMatchInlineSnapshot(
979
+ `"{\\"debug\\":\\"\\",\\"out\\":\\"�PNG\\\\n\\\\u001a\\\\n\\\\u0000\\\\u0000\\\\u0000\\\\rIHDR\\\\u0000\\\\u0000\\\\u0000\\\\n\\\\u0000\\\\u0000\\\\u0000\\\\n\\\\b\\\\u0006\\\\u0000\\\\u0000\\\\u0000�2Ͻ\\\\u0000\\\\u0000\\\\u0000\\\\tpHYs\\\\u0000\\\\u0000\\\\u000b\\\\u0013\\\\u0000\\\\u0000\\\\u000b\\\\u0013\\\\u0001\\\\u0000��\\\\u0018\\\\u0000\\\\u0000\\\\u0000\\\\u0001sRGB\\\\u0000��\\\\u001c�\\\\u0000\\\\u0000\\\\u0000\\\\u0004gAMA\\\\u0000\\\\u0000��\\\\u000b�a\\\\u0005\\\\u0000\\\\u0000\\\\u0000\\\\\\"IDATx\\\\u0001��1\\\\u0011\\\\u0000\\\\u0000\\\\b���π\\\\u0003:tl.����׈\\\\u0005z�\\\\u0002=�\\\\u0002\\\\u0012\\\\u0005O�1\\\\u0000\\\\u0000\\\\u0000\\\\u0000IEND�B\`�\\",\\"err\\":\\"\\",\\"warn\\":\\"\\"}"`
980
+ );
981
+ });
982
+
983
+ it("should get a binary file by key in a given namespace specified by namespace-id", async () => {
984
+ const buf = Buffer.from(
985
+ "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC",
986
+ "base64"
987
+ );
988
+ setMockFetchKVGetValue(
989
+ "some-account-id",
990
+ "some-namespace-id",
991
+ "my-key",
992
+ buf
993
+ );
994
+ await runWrangler("kv:key get my-key --namespace-id some-namespace-id");
995
+ expect(proc.write).toEqual(buf);
996
+ expect(std.err).toMatchInlineSnapshot(`""`);
997
+ });
998
+
999
+ it("should get a key in a given namespace specified by binding", async () => {
1000
+ writeWranglerConfig();
1001
+ setMockFetchKVGetValue(
1002
+ "some-account-id",
1003
+ "bound-id",
1004
+ "my-key",
1005
+ "my-value"
1006
+ );
1007
+ await runWrangler(
1008
+ "kv:key get my-key --binding someBinding --preview false"
1009
+ );
1010
+ expect(proc.write).toEqual(Buffer.from("my-value"));
1011
+ expect(std.err).toMatchInlineSnapshot(`""`);
1012
+ });
1013
+
1014
+ it("should get a key in a given preview namespace specified by binding", async () => {
1015
+ writeWranglerConfig();
1016
+ setMockFetchKVGetValue(
1017
+ "some-account-id",
1018
+ "preview-bound-id",
1019
+ "my-key",
1020
+ "my-value"
1021
+ );
1022
+ await runWrangler("kv:key get my-key --binding someBinding --preview");
1023
+ expect(proc.write).toEqual(Buffer.from("my-value"));
1024
+ expect(std.err).toMatchInlineSnapshot(`""`);
1025
+ });
1026
+
1027
+ it("should get a key for the specified environment in a given namespace", async () => {
1028
+ writeWranglerConfig();
1029
+ setMockFetchKVGetValue(
1030
+ "some-account-id",
1031
+ "env-bound-id",
1032
+ "my-key",
1033
+ "my-value"
1034
+ );
1035
+ await runWrangler(
1036
+ "kv:key get my-key --binding someBinding --env some-environment --preview false"
1037
+ );
1038
+ expect(proc.write).toEqual(Buffer.from("my-value"));
1039
+ expect(std.err).toMatchInlineSnapshot(`""`);
1040
+ });
1041
+
1042
+ it("should encode the key in the api request to get a value", async () => {
1043
+ setMockFetchKVGetValue(
1044
+ "some-account-id",
1045
+ "some-namespace-id",
1046
+ "%2Fmy%2Ckey",
1047
+ "my-value"
1048
+ );
1049
+ await runWrangler(
1050
+ "kv:key get /my,key --namespace-id some-namespace-id"
1051
+ );
1052
+ expect(proc.write).toEqual(Buffer.from("my-value"));
1053
+ expect(std.err).toMatchInlineSnapshot(`""`);
1054
+ });
1055
+
1056
+ it("should error if no key is provided", async () => {
1057
+ await expect(
1058
+ runWrangler("kv:key get")
1059
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1060
+ `"Not enough non-option arguments: got 0, need at least 1"`
1061
+ );
1062
+ expect(std.out).toMatchInlineSnapshot(`
945
1063
  "
946
1064
  wrangler kv:key get <key>
947
1065
 
@@ -959,22 +1077,23 @@ describe("wrangler", () => {
959
1077
  --binding The name of the namespace to get from [string]
960
1078
  --namespace-id The id of the namespace to get from [string]
961
1079
  -e, --env Perform on a specific environment [string]
962
- --preview Interact with a preview namespace [boolean] [default: false]"
1080
+ --preview Interact with a preview namespace [boolean] [default: false]
1081
+ --text Decode the returned value as a utf8 string [boolean] [default: false]"
963
1082
  `);
964
- expect(std.err).toMatchInlineSnapshot(`
1083
+ expect(std.err).toMatchInlineSnapshot(`
965
1084
  "X [ERROR] Not enough non-option arguments: got 0, need at least 1
966
1085
 
967
1086
  "
968
1087
  `);
969
- });
970
-
971
- it("should error if no binding nor namespace is provided", async () => {
972
- await expect(
973
- runWrangler("kv:key get foo")
974
- ).rejects.toThrowErrorMatchingInlineSnapshot(
975
- `"Exactly one of the arguments binding and namespace-id is required"`
976
- );
977
- expect(std.out).toMatchInlineSnapshot(`
1088
+ });
1089
+
1090
+ it("should error if no binding nor namespace is provided", async () => {
1091
+ await expect(
1092
+ runWrangler("kv:key get foo")
1093
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1094
+ `"Exactly one of the arguments binding and namespace-id is required"`
1095
+ );
1096
+ expect(std.out).toMatchInlineSnapshot(`
978
1097
  "
979
1098
  wrangler kv:key get <key>
980
1099
 
@@ -992,23 +1111,24 @@ describe("wrangler", () => {
992
1111
  --binding The name of the namespace to get from [string]
993
1112
  --namespace-id The id of the namespace to get from [string]
994
1113
  -e, --env Perform on a specific environment [string]
995
- --preview Interact with a preview namespace [boolean] [default: false]"
1114
+ --preview Interact with a preview namespace [boolean] [default: false]
1115
+ --text Decode the returned value as a utf8 string [boolean] [default: false]"
996
1116
  `);
997
- expect(std.err).toMatchInlineSnapshot(`
1117
+ expect(std.err).toMatchInlineSnapshot(`
998
1118
  "X [ERROR] Exactly one of the arguments binding and namespace-id is required
999
1119
 
1000
1120
  "
1001
1121
  `);
1002
- });
1122
+ });
1003
1123
 
1004
- it("should error if both binding and namespace is provided", async () => {
1005
- await expect(
1006
- runWrangler("kv:key get foo --binding x --namespace-id y")
1007
- ).rejects.toThrowErrorMatchingInlineSnapshot(
1008
- `"Arguments binding and namespace-id are mutually exclusive"`
1009
- );
1124
+ it("should error if both binding and namespace is provided", async () => {
1125
+ await expect(
1126
+ runWrangler("kv:key get foo --binding x --namespace-id y")
1127
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1128
+ `"Arguments binding and namespace-id are mutually exclusive"`
1129
+ );
1010
1130
 
1011
- expect(std.out).toMatchInlineSnapshot(`
1131
+ expect(std.out).toMatchInlineSnapshot(`
1012
1132
  "
1013
1133
  wrangler kv:key get <key>
1014
1134
 
@@ -1026,456 +1146,526 @@ describe("wrangler", () => {
1026
1146
  --binding The name of the namespace to get from [string]
1027
1147
  --namespace-id The id of the namespace to get from [string]
1028
1148
  -e, --env Perform on a specific environment [string]
1029
- --preview Interact with a preview namespace [boolean] [default: false]"
1149
+ --preview Interact with a preview namespace [boolean] [default: false]
1150
+ --text Decode the returned value as a utf8 string [boolean] [default: false]"
1030
1151
  `);
1031
- expect(std.err).toMatchInlineSnapshot(`
1152
+ expect(std.err).toMatchInlineSnapshot(`
1032
1153
  "X [ERROR] Arguments binding and namespace-id are mutually exclusive
1033
1154
 
1034
1155
  "
1035
1156
  `);
1036
- });
1037
-
1038
- it("should error if a given binding name is not in the configured kv namespaces", async () => {
1039
- writeWranglerConfig();
1040
- await expect(
1041
- runWrangler("kv:key get key --binding otherBinding")
1042
- ).rejects.toThrowErrorMatchingInlineSnapshot(
1043
- `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
1044
- );
1045
- expect(std.out).toMatchInlineSnapshot(`
1157
+ });
1158
+
1159
+ it("should error if a given binding name is not in the configured kv namespaces", async () => {
1160
+ writeWranglerConfig();
1161
+ await expect(
1162
+ runWrangler("kv:key get key --binding otherBinding")
1163
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1164
+ `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
1165
+ );
1166
+ expect(std.out).toMatchInlineSnapshot(`
1046
1167
  "
1047
1168
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1048
1169
  `);
1049
- expect(std.err).toMatchInlineSnapshot(`
1170
+ expect(std.err).toMatchInlineSnapshot(`
1050
1171
  "X [ERROR] A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
1051
1172
 
1052
1173
  "
1053
1174
  `);
1054
- });
1055
- });
1056
-
1057
- describe("delete", () => {
1058
- function mockDeleteRequest(
1059
- expectedNamespaceId: string,
1060
- expectedKey: string
1061
- ) {
1062
- const requests = { count: 0 };
1063
- setMockResponse(
1064
- "/accounts/:accountId/storage/kv/namespaces/:namespaceId/values/:key",
1065
- "DELETE",
1066
- ([_url, accountId, namespaceId, key]) => {
1067
- requests.count++;
1068
- expect(accountId).toEqual("some-account-id");
1069
- expect(namespaceId).toEqual(expectedNamespaceId);
1070
- expect(key).toEqual(expectedKey);
1071
- return null;
1072
- }
1073
- );
1074
- return requests;
1075
- }
1076
-
1077
- it("should delete a key in a namespace specified by id", async () => {
1078
- const requests = mockDeleteRequest("some-namespace-id", "someKey");
1079
- await runWrangler(
1080
- `kv:key delete --namespace-id some-namespace-id someKey`
1081
- );
1082
- expect(requests.count).toEqual(1);
1083
- });
1084
-
1085
- it("should encode the key in the api request to delete a value", async () => {
1086
- const requests = mockDeleteRequest("voyager", "%2FNCC-74656");
1087
- await runWrangler(`kv:key delete --namespace-id voyager /NCC-74656`);
1088
- expect(requests.count).toEqual(1);
1089
- expect(std.out).toMatchInlineSnapshot(
1090
- `"Deleting the key \\"/NCC-74656\\" on namespace voyager."`
1091
- );
1092
- expect(std.err).toMatchInlineSnapshot(`""`);
1093
- });
1094
-
1095
- it("should delete a key in a namespace specified by binding name", async () => {
1096
- writeWranglerConfig();
1097
- const requests = mockDeleteRequest("bound-id", "someKey");
1098
- await runWrangler(
1099
- `kv:key delete --binding someBinding --preview false someKey`
1100
- );
1101
- expect(requests.count).toEqual(1);
1102
- });
1103
-
1104
- it("should delete a key in a preview namespace specified by binding name", async () => {
1105
- writeWranglerConfig();
1106
- const requests = mockDeleteRequest("preview-bound-id", "someKey");
1107
- await runWrangler(
1108
- `kv:key delete --binding someBinding --preview someKey`
1109
- );
1110
- expect(requests.count).toEqual(1);
1111
- });
1112
-
1113
- it("should error if a given binding name is not in the configured kv namespaces", async () => {
1114
- writeWranglerConfig();
1115
- await expect(
1116
- runWrangler(`kv:key delete --binding otherBinding someKey`)
1117
- ).rejects.toThrowErrorMatchingInlineSnapshot(
1118
- `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
1119
- );
1120
-
1121
- expect(std.err).toMatchInlineSnapshot(`
1175
+ });
1176
+
1177
+ describe("non-interactive", () => {
1178
+ const { setIsTTY } = useMockIsTTY();
1179
+ mockAccountId({ accountId: null });
1180
+
1181
+ it("should error if there are multiple accounts available but not interactive on stdin", async () => {
1182
+ mockGetMemberships([
1183
+ { id: "xxx", account: { id: "1", name: "one" } },
1184
+ { id: "yyy", account: { id: "2", name: "two" } },
1185
+ ]);
1186
+ setIsTTY({ stdin: false, stdout: true });
1187
+ await expect(runWrangler("kv:key get key --namespace-id=xxxx"))
1188
+ .rejects.toThrowErrorMatchingInlineSnapshot(`
1189
+ "More than one account available but unable to select one in non-interactive mode.
1190
+ Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1191
+ Available accounts are (\\"<name>\\" - \\"<id>\\"):
1192
+ \\"one\\" - \\"1\\")
1193
+ \\"two\\" - \\"2\\")"
1194
+ `);
1195
+ });
1196
+
1197
+ it("should error if there are multiple accounts available but not interactive on stdout", async () => {
1198
+ mockGetMemberships([
1199
+ { id: "xxx", account: { id: "1", name: "one" } },
1200
+ { id: "yyy", account: { id: "2", name: "two" } },
1201
+ ]);
1202
+ setIsTTY({ stdin: true, stdout: false });
1203
+ await expect(runWrangler("kv:key get key --namespace-id=xxxx"))
1204
+ .rejects.toThrowErrorMatchingInlineSnapshot(`
1205
+ "More than one account available but unable to select one in non-interactive mode.
1206
+ Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1207
+ Available accounts are (\\"<name>\\" - \\"<id>\\"):
1208
+ \\"one\\" - \\"1\\")
1209
+ \\"two\\" - \\"2\\")"
1210
+ `);
1211
+ });
1212
+
1213
+ it("should recommend using a configuration if unable to fetch memberships", async () => {
1214
+ setMockRawResponse("/memberships", () => {
1215
+ return createFetchResult(undefined, false, [
1216
+ {
1217
+ code: 9109,
1218
+ message: "Uauthorized to access requested resource",
1219
+ },
1220
+ ]);
1221
+ });
1222
+ await expect(runWrangler("kv:key get key --namespace-id=xxxx"))
1223
+ .rejects.toThrowErrorMatchingInlineSnapshot(`
1224
+ "Failed to automatically retrieve account IDs for the logged in user.
1225
+ You may have incorrect permissions on your API token. You can skip this account check by adding an \`account_id\` in your \`wrangler.toml\`, or by setting the value of CLOUDFLARE_ACCOUNT_ID\\""
1226
+ `);
1227
+ });
1228
+
1229
+ it("should error if there are multiple accounts available but not interactive at all", async () => {
1230
+ mockGetMemberships([
1231
+ { id: "xxx", account: { id: "1", name: "one" } },
1232
+ { id: "yyy", account: { id: "2", name: "two" } },
1233
+ ]);
1234
+ setIsTTY(false);
1235
+ await expect(runWrangler("kv:key get key --namespace-id=xxxx"))
1236
+ .rejects.toThrowErrorMatchingInlineSnapshot(`
1237
+ "More than one account available but unable to select one in non-interactive mode.
1238
+ Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1239
+ Available accounts are (\\"<name>\\" - \\"<id>\\"):
1240
+ \\"one\\" - \\"1\\")
1241
+ \\"two\\" - \\"2\\")"
1242
+ `);
1243
+ });
1244
+ });
1245
+ });
1246
+
1247
+ describe("delete", () => {
1248
+ function mockDeleteRequest(
1249
+ expectedNamespaceId: string,
1250
+ expectedKey: string
1251
+ ) {
1252
+ const requests = { count: 0 };
1253
+ setMockResponse(
1254
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/values/:key",
1255
+ "DELETE",
1256
+ ([_url, accountId, namespaceId, key]) => {
1257
+ requests.count++;
1258
+ expect(accountId).toEqual("some-account-id");
1259
+ expect(namespaceId).toEqual(expectedNamespaceId);
1260
+ expect(key).toEqual(expectedKey);
1261
+ return null;
1262
+ }
1263
+ );
1264
+ return requests;
1265
+ }
1266
+
1267
+ it("should delete a key in a namespace specified by id", async () => {
1268
+ const requests = mockDeleteRequest("some-namespace-id", "someKey");
1269
+ await runWrangler(
1270
+ `kv:key delete --namespace-id some-namespace-id someKey`
1271
+ );
1272
+ expect(requests.count).toEqual(1);
1273
+ });
1274
+
1275
+ it("should encode the key in the api request to delete a value", async () => {
1276
+ const requests = mockDeleteRequest("voyager", "%2FNCC-74656");
1277
+ await runWrangler(`kv:key delete --namespace-id voyager /NCC-74656`);
1278
+ expect(requests.count).toEqual(1);
1279
+ expect(std.out).toMatchInlineSnapshot(
1280
+ `"Deleting the key \\"/NCC-74656\\" on namespace voyager."`
1281
+ );
1282
+ expect(std.err).toMatchInlineSnapshot(`""`);
1283
+ });
1284
+
1285
+ it("should delete a key in a namespace specified by binding name", async () => {
1286
+ writeWranglerConfig();
1287
+ const requests = mockDeleteRequest("bound-id", "someKey");
1288
+ await runWrangler(
1289
+ `kv:key delete --binding someBinding --preview false someKey`
1290
+ );
1291
+ expect(requests.count).toEqual(1);
1292
+ });
1293
+
1294
+ it("should delete a key in a preview namespace specified by binding name", async () => {
1295
+ writeWranglerConfig();
1296
+ const requests = mockDeleteRequest("preview-bound-id", "someKey");
1297
+ await runWrangler(
1298
+ `kv:key delete --binding someBinding --preview someKey`
1299
+ );
1300
+ expect(requests.count).toEqual(1);
1301
+ });
1302
+
1303
+ it("should error if a given binding name is not in the configured kv namespaces", async () => {
1304
+ writeWranglerConfig();
1305
+ await expect(
1306
+ runWrangler(`kv:key delete --binding otherBinding someKey`)
1307
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1308
+ `"A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."`
1309
+ );
1310
+
1311
+ expect(std.err).toMatchInlineSnapshot(`
1122
1312
  "X [ERROR] A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\".
1123
1313
 
1124
1314
  "
1125
1315
  `);
1126
- });
1127
-
1128
- it("should delete a key in a namespace specified by binding name in a given environment", async () => {
1129
- writeWranglerConfig();
1130
- const requests = mockDeleteRequest("env-bound-id", "someKey");
1131
- await runWrangler(
1132
- `kv:key delete --binding someBinding --env some-environment --preview false someKey`
1133
- );
1134
- expect(std.out).toMatchInlineSnapshot(
1135
- `"Deleting the key \\"someKey\\" on namespace env-bound-id."`
1136
- );
1137
- expect(std.err).toMatchInlineSnapshot(`""`);
1138
- expect(requests.count).toEqual(1);
1139
- });
1140
-
1141
- it("should delete a key in a preview namespace specified by binding name in a given environment", async () => {
1142
- writeWranglerConfig();
1143
- const requests = mockDeleteRequest("preview-env-bound-id", "someKey");
1144
- await runWrangler(
1145
- `kv:key delete --binding someBinding --env some-environment --preview someKey`
1146
- );
1147
- expect(requests.count).toEqual(1);
1148
- });
1149
- });
1150
- });
1151
-
1152
- describe("kv:bulk", () => {
1153
- describe("put", () => {
1154
- function mockPutRequest(
1155
- expectedNamespaceId: string,
1156
- expectedKeyValues: KeyValue[]
1157
- ) {
1158
- const requests = { count: 0 };
1159
- setMockResponse(
1160
- "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
1161
- "PUT",
1162
- ([_url, accountId, namespaceId], { body }) => {
1163
- requests.count++;
1164
- expect(accountId).toEqual("some-account-id");
1165
- expect(namespaceId).toEqual(expectedNamespaceId);
1166
- expect(JSON.parse(body as string)).toEqual(
1167
- expectedKeyValues.slice(
1168
- (requests.count - 1) * 5000,
1169
- requests.count * 5000
1170
- )
1171
- );
1172
- return null;
1173
- }
1174
- );
1175
- return requests;
1176
- }
1177
-
1178
- it("should put the key-values parsed from a file", async () => {
1179
- const keyValues: KeyValue[] = [
1180
- { key: "someKey1", value: "someValue1" },
1181
- { key: "ns:someKey2", value: "123", base64: true },
1182
- { key: "someKey3", value: "someValue3", expiration: 100 },
1183
- { key: "someKey4", value: "someValue4", expiration_ttl: 500 },
1184
- ];
1185
- writeFileSync("./keys.json", JSON.stringify(keyValues));
1186
- const requests = mockPutRequest("some-namespace-id", keyValues);
1187
- await runWrangler(
1188
- `kv:bulk put --namespace-id some-namespace-id keys.json`
1189
- );
1190
- expect(requests.count).toEqual(1);
1191
- expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1192
- expect(std.warn).toMatchInlineSnapshot(`""`);
1193
- expect(std.err).toMatchInlineSnapshot(`""`);
1194
- });
1195
-
1196
- it("should put the key-values in batches of 5000 parsed from a file", async () => {
1197
- const keyValues: KeyValue[] = new Array(12000).fill({
1198
- key: "someKey1",
1199
- value: "someValue1",
1200
- });
1201
- writeFileSync("./keys.json", JSON.stringify(keyValues));
1202
- const requests = mockPutRequest("some-namespace-id", keyValues);
1203
- await runWrangler(
1204
- `kv:bulk put --namespace-id some-namespace-id keys.json`
1205
- );
1206
- expect(requests.count).toEqual(3);
1207
- expect(std.out).toMatchInlineSnapshot(`
1316
+ });
1317
+
1318
+ it("should delete a key in a namespace specified by binding name in a given environment", async () => {
1319
+ writeWranglerConfig();
1320
+ const requests = mockDeleteRequest("env-bound-id", "someKey");
1321
+ await runWrangler(
1322
+ `kv:key delete --binding someBinding --env some-environment --preview false someKey`
1323
+ );
1324
+ expect(std.out).toMatchInlineSnapshot(
1325
+ `"Deleting the key \\"someKey\\" on namespace env-bound-id."`
1326
+ );
1327
+ expect(std.err).toMatchInlineSnapshot(`""`);
1328
+ expect(requests.count).toEqual(1);
1329
+ });
1330
+
1331
+ it("should delete a key in a preview namespace specified by binding name in a given environment", async () => {
1332
+ writeWranglerConfig();
1333
+ const requests = mockDeleteRequest("preview-env-bound-id", "someKey");
1334
+ await runWrangler(
1335
+ `kv:key delete --binding someBinding --env some-environment --preview someKey`
1336
+ );
1337
+ expect(requests.count).toEqual(1);
1338
+ });
1339
+ });
1340
+ });
1341
+
1342
+ describe("kv:bulk", () => {
1343
+ describe("put", () => {
1344
+ function mockPutRequest(
1345
+ expectedNamespaceId: string,
1346
+ expectedKeyValues: KeyValue[]
1347
+ ) {
1348
+ const requests = { count: 0 };
1349
+ setMockResponse(
1350
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
1351
+ "PUT",
1352
+ ([_url, accountId, namespaceId], { body }) => {
1353
+ requests.count++;
1354
+ expect(accountId).toEqual("some-account-id");
1355
+ expect(namespaceId).toEqual(expectedNamespaceId);
1356
+ expect(JSON.parse(body as string)).toEqual(
1357
+ expectedKeyValues.slice(
1358
+ (requests.count - 1) * 5000,
1359
+ requests.count * 5000
1360
+ )
1361
+ );
1362
+ return null;
1363
+ }
1364
+ );
1365
+ return requests;
1366
+ }
1367
+
1368
+ it("should put the key-values parsed from a file", async () => {
1369
+ const keyValues: KeyValue[] = [
1370
+ { key: "someKey1", value: "someValue1" },
1371
+ { key: "ns:someKey2", value: "123", base64: true },
1372
+ { key: "someKey3", value: "someValue3", expiration: 100 },
1373
+ { key: "someKey4", value: "someValue4", expiration_ttl: 500 },
1374
+ ];
1375
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1376
+ const requests = mockPutRequest("some-namespace-id", keyValues);
1377
+ await runWrangler(
1378
+ `kv:bulk put --namespace-id some-namespace-id keys.json`
1379
+ );
1380
+ expect(requests.count).toEqual(1);
1381
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1382
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1383
+ expect(std.err).toMatchInlineSnapshot(`""`);
1384
+ });
1385
+
1386
+ it("should put the key-values in batches of 5000 parsed from a file", async () => {
1387
+ const keyValues: KeyValue[] = new Array(12000).fill({
1388
+ key: "someKey1",
1389
+ value: "someValue1",
1390
+ });
1391
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1392
+ const requests = mockPutRequest("some-namespace-id", keyValues);
1393
+ await runWrangler(
1394
+ `kv:bulk put --namespace-id some-namespace-id keys.json`
1395
+ );
1396
+ expect(requests.count).toEqual(3);
1397
+ expect(std.out).toMatchInlineSnapshot(`
1208
1398
  "Uploaded 0% (0 out of 12,000)
1209
1399
  Uploaded 41% (5,000 out of 12,000)
1210
1400
  Uploaded 83% (10,000 out of 12,000)
1211
1401
  Uploaded 100% (12,000 out of 12,000)
1212
1402
  Success!"
1213
1403
  `);
1214
- expect(std.warn).toMatchInlineSnapshot(`""`);
1215
- expect(std.err).toMatchInlineSnapshot(`""`);
1216
- });
1217
-
1218
- it("should error if the file is not a JSON array", async () => {
1219
- const keyValues = { key: "someKey1", value: "someValue1" };
1220
- writeFileSync("./keys.json", JSON.stringify(keyValues));
1221
- await expect(
1222
- runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1223
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1224
- "Unexpected JSON input from \\"keys.json\\".
1225
- Expected an array of key-value objects but got type \\"object\\"."
1226
- `);
1227
- expect(std.out).toMatchInlineSnapshot(`
1404
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1405
+ expect(std.err).toMatchInlineSnapshot(`""`);
1406
+ });
1407
+
1408
+ it("should error if the file is not a JSON array", async () => {
1409
+ const keyValues = { key: "someKey1", value: "someValue1" };
1410
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1411
+ await expect(
1412
+ runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1413
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1414
+ "Unexpected JSON input from \\"keys.json\\".
1415
+ Expected an array of key-value objects but got type \\"object\\"."
1416
+ `);
1417
+ expect(std.out).toMatchInlineSnapshot(`
1228
1418
  "
1229
1419
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1230
1420
  `);
1231
- expect(std.warn).toMatchInlineSnapshot(`""`);
1232
- });
1233
-
1234
- it("should error if the array contains items that are not key-value objects", async () => {
1235
- const keyValues = [
1236
- 123,
1237
- "a string",
1238
- { key: "someKey" },
1239
- { value: "someValue" },
1240
- // add a valid object here to make sure it's not included
1241
- { key: "someKey1", value: "someValue1" },
1242
- // this one will only add a warning
1243
- { key: "someKey1", value: "someValue1", invalid: true },
1244
- // back to the invalid ones
1245
- { key: 123, value: "somevalue" },
1246
- { key: "somekey", value: 123 },
1247
- { key: "someKey1", value: "someValue1", expiration: "string" },
1248
- { key: "someKey1", value: "someValue1", expiration_ttl: "string" },
1249
- {
1250
- key: 123,
1251
- value: {
1252
- a: {
1253
- nested: "object",
1254
- },
1255
- },
1256
- },
1257
- { key: "someKey1", value: "someValue1", metadata: 123 },
1258
- { key: "someKey1", value: "someValue1", base64: "string" },
1259
- ];
1260
- writeFileSync("./keys.json", JSON.stringify(keyValues));
1261
- await expect(
1262
- runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1263
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1264
- "Unexpected JSON input from \\"keys.json\\".
1265
- Each item in the array should be an object that matches:
1266
-
1267
- interface KeyValue {
1268
- key: string;
1269
- value: string;
1270
- expiration?: number;
1271
- expiration_ttl?: number;
1272
- metadata?: object;
1273
- base64?: boolean;
1274
- }
1275
-
1276
- The item at index 0 is 123
1277
- The item at index 1 is \\"a string\\"
1278
- The item at index 2 is {\\"key\\":\\"someKey\\"}
1279
- The item at index 3 is {\\"value\\":\\"someValue\\"}
1280
- The item at index 6 is {\\"key\\":123,\\"value\\":\\"somevalue\\"}
1281
- The item at index 7 is {\\"key\\":\\"somekey\\",\\"value\\":123}
1282
- The item at index 8 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration\\":\\"string\\"}
1283
- The item at index 9 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration_ttl\\":\\"string\\"}
1284
- The item at index 10 is {\\"key\\":123,\\"value\\":{\\"a\\":{\\"nested\\":\\"object\\"}}}
1285
- The item at index 11 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"metadata\\":123}
1286
- The item at index 12 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"base64\\":\\"string\\"}"
1287
- `);
1288
-
1289
- expect(std.out).toMatchInlineSnapshot(`
1421
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1422
+ });
1423
+
1424
+ it("should error if the array contains items that are not key-value objects", async () => {
1425
+ const keyValues = [
1426
+ 123,
1427
+ "a string",
1428
+ { key: "someKey" },
1429
+ { value: "someValue" },
1430
+ // add a valid object here to make sure it's not included
1431
+ { key: "someKey1", value: "someValue1" },
1432
+ // this one will only add a warning
1433
+ { key: "someKey1", value: "someValue1", invalid: true },
1434
+ // back to the invalid ones
1435
+ { key: 123, value: "somevalue" },
1436
+ { key: "somekey", value: 123 },
1437
+ { key: "someKey1", value: "someValue1", expiration: "string" },
1438
+ { key: "someKey1", value: "someValue1", expiration_ttl: "string" },
1439
+ {
1440
+ key: 123,
1441
+ value: {
1442
+ a: {
1443
+ nested: "object",
1444
+ },
1445
+ },
1446
+ },
1447
+ { key: "someKey1", value: "someValue1", metadata: 123 },
1448
+ { key: "someKey1", value: "someValue1", base64: "string" },
1449
+ ];
1450
+ writeFileSync("./keys.json", JSON.stringify(keyValues));
1451
+ await expect(
1452
+ runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1453
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1454
+ "Unexpected JSON input from \\"keys.json\\".
1455
+ Each item in the array should be an object that matches:
1456
+
1457
+ interface KeyValue {
1458
+ key: string;
1459
+ value: string;
1460
+ expiration?: number;
1461
+ expiration_ttl?: number;
1462
+ metadata?: object;
1463
+ base64?: boolean;
1464
+ }
1465
+
1466
+ The item at index 0 is 123
1467
+ The item at index 1 is \\"a string\\"
1468
+ The item at index 2 is {\\"key\\":\\"someKey\\"}
1469
+ The item at index 3 is {\\"value\\":\\"someValue\\"}
1470
+ The item at index 6 is {\\"key\\":123,\\"value\\":\\"somevalue\\"}
1471
+ The item at index 7 is {\\"key\\":\\"somekey\\",\\"value\\":123}
1472
+ The item at index 8 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration\\":\\"string\\"}
1473
+ The item at index 9 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration_ttl\\":\\"string\\"}
1474
+ The item at index 10 is {\\"key\\":123,\\"value\\":{\\"a\\":{\\"nested\\":\\"object\\"}}}
1475
+ The item at index 11 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"metadata\\":123}
1476
+ The item at index 12 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"base64\\":\\"string\\"}"
1477
+ `);
1478
+
1479
+ expect(std.out).toMatchInlineSnapshot(`
1290
1480
  "
1291
1481
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1292
1482
  `);
1293
- expect(std.warn).toMatchInlineSnapshot(`
1483
+ expect(std.warn).toMatchInlineSnapshot(`
1294
1484
  "▲ [WARNING] Unexpected key-value properties in \\"keys.json\\".
1295
1485
 
1296
1486
  The item at index 5 contains unexpected properties: [\\"invalid\\"].
1297
1487
 
1298
1488
  "
1299
1489
  `);
1300
- });
1301
- });
1302
-
1303
- describe("delete", () => {
1304
- function mockDeleteRequest(
1305
- expectedNamespaceId: string,
1306
- expectedKeys: string[]
1307
- ) {
1308
- const requests = { count: 0 };
1309
- setMockResponse(
1310
- "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
1311
- "DELETE",
1312
- ([_url, accountId, namespaceId], { headers, body }) => {
1313
- requests.count++;
1314
- expect(accountId).toEqual("some-account-id");
1315
- expect(namespaceId).toEqual(expectedNamespaceId);
1316
- expect(new Headers(headers ?? []).get("Content-Type")).toEqual(
1317
- "application/json"
1318
- );
1319
- expect(JSON.parse(body as string)).toEqual(
1320
- expectedKeys.slice(
1321
- (requests.count - 1) * 5000,
1322
- requests.count * 5000
1323
- )
1324
- );
1325
- return null;
1326
- }
1327
- );
1328
- return requests;
1329
- }
1330
-
1331
- it("should delete the keys parsed from a file", async () => {
1332
- const keys = ["someKey1", "ns:someKey2"];
1333
- writeFileSync("./keys.json", JSON.stringify(keys));
1334
- mockConfirm({
1335
- text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1336
- result: true,
1337
- });
1338
- const requests = mockDeleteRequest("some-namespace-id", keys);
1339
- await runWrangler(
1340
- `kv:bulk delete --namespace-id some-namespace-id keys.json`
1341
- );
1342
- expect(requests.count).toEqual(1);
1343
- expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1344
- expect(std.warn).toMatchInlineSnapshot(`""`);
1345
- expect(std.err).toMatchInlineSnapshot(`""`);
1346
- });
1347
-
1348
- it("should delete the keys in batches of 5000 parsed from a file", async () => {
1349
- const keys = new Array(12000).fill("some-key");
1350
- writeFileSync("./keys.json", JSON.stringify(keys));
1351
- mockConfirm({
1352
- text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1353
- result: true,
1354
- });
1355
- const requests = mockDeleteRequest("some-namespace-id", keys);
1356
- await runWrangler(
1357
- `kv:bulk delete --namespace-id some-namespace-id keys.json`
1358
- );
1359
- expect(requests.count).toEqual(3);
1360
- expect(std.out).toMatchInlineSnapshot(`
1490
+ });
1491
+ });
1492
+
1493
+ describe("delete", () => {
1494
+ function mockDeleteRequest(
1495
+ expectedNamespaceId: string,
1496
+ expectedKeys: string[]
1497
+ ) {
1498
+ const requests = { count: 0 };
1499
+ setMockResponse(
1500
+ "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
1501
+ "DELETE",
1502
+ ([_url, accountId, namespaceId], { headers, body }) => {
1503
+ requests.count++;
1504
+ expect(accountId).toEqual("some-account-id");
1505
+ expect(namespaceId).toEqual(expectedNamespaceId);
1506
+ expect(new Headers(headers ?? []).get("Content-Type")).toEqual(
1507
+ "application/json"
1508
+ );
1509
+ expect(JSON.parse(body as string)).toEqual(
1510
+ expectedKeys.slice(
1511
+ (requests.count - 1) * 5000,
1512
+ requests.count * 5000
1513
+ )
1514
+ );
1515
+ return null;
1516
+ }
1517
+ );
1518
+ return requests;
1519
+ }
1520
+
1521
+ it("should delete the keys parsed from a file", async () => {
1522
+ const keys = ["someKey1", "ns:someKey2"];
1523
+ writeFileSync("./keys.json", JSON.stringify(keys));
1524
+ mockConfirm({
1525
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1526
+ result: true,
1527
+ });
1528
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1529
+ await runWrangler(
1530
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1531
+ );
1532
+ expect(requests.count).toEqual(1);
1533
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1534
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1535
+ expect(std.err).toMatchInlineSnapshot(`""`);
1536
+ });
1537
+
1538
+ it("should delete the keys in batches of 5000 parsed from a file", async () => {
1539
+ const keys = new Array(12000).fill("some-key");
1540
+ writeFileSync("./keys.json", JSON.stringify(keys));
1541
+ mockConfirm({
1542
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1543
+ result: true,
1544
+ });
1545
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1546
+ await runWrangler(
1547
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1548
+ );
1549
+ expect(requests.count).toEqual(3);
1550
+ expect(std.out).toMatchInlineSnapshot(`
1361
1551
  "Deleted 0% (0 out of 12,000)
1362
1552
  Deleted 41% (5,000 out of 12,000)
1363
1553
  Deleted 83% (10,000 out of 12,000)
1364
1554
  Deleted 100% (12,000 out of 12,000)
1365
1555
  Success!"
1366
1556
  `);
1367
- expect(std.warn).toMatchInlineSnapshot(`""`);
1368
- expect(std.err).toMatchInlineSnapshot(`""`);
1369
- });
1370
-
1371
- it("should not delete the keys if the user confirms no", async () => {
1372
- const keys = ["someKey1", "ns:someKey2"];
1373
- writeFileSync("./keys.json", JSON.stringify(keys));
1374
- mockConfirm({
1375
- text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1376
- result: false,
1377
- });
1378
- await runWrangler(
1379
- `kv:bulk delete --namespace-id some-namespace-id keys.json`
1380
- );
1381
- expect(std.out).toMatchInlineSnapshot(
1382
- `"Not deleting keys read from \\"keys.json\\"."`
1383
- );
1384
- expect(std.warn).toMatchInlineSnapshot(`""`);
1385
- expect(std.err).toMatchInlineSnapshot(`""`);
1386
- });
1387
-
1388
- it("should delete the keys without asking if --force is provided", async () => {
1389
- const keys = ["someKey1", "ns:someKey2"];
1390
- writeFileSync("./keys.json", JSON.stringify(keys));
1391
- const requests = mockDeleteRequest("some-namespace-id", keys);
1392
- await runWrangler(
1393
- `kv:bulk delete --namespace-id some-namespace-id keys.json --force`
1394
- );
1395
- expect(requests.count).toEqual(1);
1396
- expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1397
- expect(std.warn).toMatchInlineSnapshot(`""`);
1398
- expect(std.err).toMatchInlineSnapshot(`""`);
1399
- });
1400
-
1401
- it("should delete the keys without asking if -f is provided", async () => {
1402
- const keys = ["someKey1", "ns:someKey2"];
1403
- writeFileSync("./keys.json", JSON.stringify(keys));
1404
- const requests = mockDeleteRequest("some-namespace-id", keys);
1405
- await runWrangler(
1406
- `kv:bulk delete --namespace-id some-namespace-id keys.json -f`
1407
- );
1408
- expect(requests.count).toEqual(1);
1409
- expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1410
- expect(std.warn).toMatchInlineSnapshot(`""`);
1411
- expect(std.err).toMatchInlineSnapshot(`""`);
1412
- });
1413
-
1414
- it("should error if the file is not a JSON array", async () => {
1415
- const keys = 12354;
1416
- writeFileSync("./keys.json", JSON.stringify(keys));
1417
- mockConfirm({
1418
- text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1419
- result: true,
1420
- });
1421
- await expect(
1422
- runWrangler(
1423
- `kv:bulk delete --namespace-id some-namespace-id keys.json`
1424
- )
1425
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1426
- "Unexpected JSON input from \\"keys.json\\".
1427
- Expected an array of strings but got:
1428
- 12354"
1429
- `);
1430
- expect(std.out).toMatchInlineSnapshot(`
1557
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1558
+ expect(std.err).toMatchInlineSnapshot(`""`);
1559
+ });
1560
+
1561
+ it("should not delete the keys if the user confirms no", async () => {
1562
+ const keys = ["someKey1", "ns:someKey2"];
1563
+ writeFileSync("./keys.json", JSON.stringify(keys));
1564
+ mockConfirm({
1565
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1566
+ result: false,
1567
+ });
1568
+ await runWrangler(
1569
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1570
+ );
1571
+ expect(std.out).toMatchInlineSnapshot(
1572
+ `"Not deleting keys read from \\"keys.json\\"."`
1573
+ );
1574
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1575
+ expect(std.err).toMatchInlineSnapshot(`""`);
1576
+ });
1577
+
1578
+ it("should delete the keys without asking if --force is provided", async () => {
1579
+ const keys = ["someKey1", "ns:someKey2"];
1580
+ writeFileSync("./keys.json", JSON.stringify(keys));
1581
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1582
+ await runWrangler(
1583
+ `kv:bulk delete --namespace-id some-namespace-id keys.json --force`
1584
+ );
1585
+ expect(requests.count).toEqual(1);
1586
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1587
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1588
+ expect(std.err).toMatchInlineSnapshot(`""`);
1589
+ });
1590
+
1591
+ it("should delete the keys without asking if -f is provided", async () => {
1592
+ const keys = ["someKey1", "ns:someKey2"];
1593
+ writeFileSync("./keys.json", JSON.stringify(keys));
1594
+ const requests = mockDeleteRequest("some-namespace-id", keys);
1595
+ await runWrangler(
1596
+ `kv:bulk delete --namespace-id some-namespace-id keys.json -f`
1597
+ );
1598
+ expect(requests.count).toEqual(1);
1599
+ expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1600
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1601
+ expect(std.err).toMatchInlineSnapshot(`""`);
1602
+ });
1603
+
1604
+ it("should error if the file is not a JSON array", async () => {
1605
+ const keys = 12354;
1606
+ writeFileSync("./keys.json", JSON.stringify(keys));
1607
+ mockConfirm({
1608
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1609
+ result: true,
1610
+ });
1611
+ await expect(
1612
+ runWrangler(
1613
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1614
+ )
1615
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1616
+ "Unexpected JSON input from \\"keys.json\\".
1617
+ Expected an array of strings but got:
1618
+ 12354"
1619
+ `);
1620
+ expect(std.out).toMatchInlineSnapshot(`
1431
1621
  "
1432
1622
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1433
1623
  `);
1434
- expect(std.warn).toMatchInlineSnapshot(`""`);
1435
- });
1436
-
1437
- it("should error if the file contains non-string items", async () => {
1438
- const keys = ["good", 12354, { key: "someKey" }, null];
1439
- writeFileSync("./keys.json", JSON.stringify(keys));
1440
- mockConfirm({
1441
- text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1442
- result: true,
1443
- });
1444
- await expect(
1445
- runWrangler(
1446
- `kv:bulk delete --namespace-id some-namespace-id keys.json`
1447
- )
1448
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
1449
- "Unexpected JSON input from \\"keys.json\\".
1450
- Expected an array of strings.
1451
- The item at index 1 is type: \\"number\\" - 12354
1452
- The item at index 2 is type: \\"object\\" - {\\"key\\":\\"someKey\\"}
1453
- The item at index 3 is type: \\"object\\" - null"
1454
- `);
1455
- expect(std.out).toMatchInlineSnapshot(`
1624
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1625
+ });
1626
+
1627
+ it("should error if the file contains non-string items", async () => {
1628
+ const keys = ["good", 12354, { key: "someKey" }, null];
1629
+ writeFileSync("./keys.json", JSON.stringify(keys));
1630
+ mockConfirm({
1631
+ text: `Are you sure you want to delete all the keys read from "keys.json" from kv-namespace with id "some-namespace-id"?`,
1632
+ result: true,
1633
+ });
1634
+ await expect(
1635
+ runWrangler(
1636
+ `kv:bulk delete --namespace-id some-namespace-id keys.json`
1637
+ )
1638
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
1639
+ "Unexpected JSON input from \\"keys.json\\".
1640
+ Expected an array of strings.
1641
+ The item at index 1 is type: \\"number\\" - 12354
1642
+ The item at index 2 is type: \\"object\\" - {\\"key\\":\\"someKey\\"}
1643
+ The item at index 3 is type: \\"object\\" - null"
1644
+ `);
1645
+ expect(std.out).toMatchInlineSnapshot(`
1456
1646
  "
1457
1647
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
1458
1648
  `);
1459
- expect(std.warn).toMatchInlineSnapshot(`""`);
1460
- });
1461
- });
1462
- });
1649
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1650
+ });
1651
+ });
1652
+ });
1463
1653
  });
1464
1654
 
1465
1655
  function writeWranglerConfig() {
1466
- writeFileSync(
1467
- "./wrangler.toml",
1468
- [
1469
- 'name = "other-worker"',
1470
- "kv_namespaces = [",
1471
- ' { binding = "someBinding", id = "bound-id", preview_id = "preview-bound-id" }',
1472
- "]",
1473
- "",
1474
- "[env.some-environment]",
1475
- "kv_namespaces = [",
1476
- ' { binding = "someBinding", id = "env-bound-id", preview_id = "preview-env-bound-id" }',
1477
- "]",
1478
- ].join("\n"),
1479
- "utf-8"
1480
- );
1656
+ writeFileSync(
1657
+ "./wrangler.toml",
1658
+ [
1659
+ 'name = "other-worker"',
1660
+ "kv_namespaces = [",
1661
+ ' { binding = "someBinding", id = "bound-id", preview_id = "preview-bound-id" }',
1662
+ "]",
1663
+ "",
1664
+ "[env.some-environment]",
1665
+ "kv_namespaces = [",
1666
+ ' { binding = "someBinding", id = "env-bound-id", preview_id = "preview-env-bound-id" }',
1667
+ "]",
1668
+ ].join("\n"),
1669
+ "utf-8"
1670
+ );
1481
1671
  }