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