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