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.
Files changed (149) hide show
  1. package/README.md +7 -1
  2. package/bin/wrangler.js +111 -57
  3. package/miniflare-dist/index.mjs +9 -2
  4. package/package.json +156 -154
  5. package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
  6. package/src/__tests__/config-cache.test.ts +30 -24
  7. package/src/__tests__/configuration.test.ts +3935 -3476
  8. package/src/__tests__/dev.test.tsx +1128 -979
  9. package/src/__tests__/guess-worker-format.test.ts +68 -68
  10. package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
  11. package/src/__tests__/helpers/faye-websocket.d.ts +4 -4
  12. package/src/__tests__/helpers/mock-account-id.ts +24 -24
  13. package/src/__tests__/helpers/mock-bin.ts +20 -20
  14. package/src/__tests__/helpers/mock-cfetch.ts +92 -92
  15. package/src/__tests__/helpers/mock-console.ts +49 -39
  16. package/src/__tests__/helpers/mock-dialogs.ts +94 -71
  17. package/src/__tests__/helpers/mock-http-server.ts +30 -30
  18. package/src/__tests__/helpers/mock-istty.ts +65 -18
  19. package/src/__tests__/helpers/mock-kv.ts +26 -26
  20. package/src/__tests__/helpers/mock-oauth-flow.ts +223 -228
  21. package/src/__tests__/helpers/mock-process.ts +39 -0
  22. package/src/__tests__/helpers/mock-stdin.ts +82 -77
  23. package/src/__tests__/helpers/mock-web-socket.ts +21 -21
  24. package/src/__tests__/helpers/run-in-tmp.ts +27 -27
  25. package/src/__tests__/helpers/run-wrangler.ts +8 -8
  26. package/src/__tests__/helpers/write-worker-source.ts +16 -16
  27. package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
  28. package/src/__tests__/https-options.test.ts +104 -104
  29. package/src/__tests__/index.test.ts +239 -234
  30. package/src/__tests__/init.test.ts +1605 -1250
  31. package/src/__tests__/jest.setup.ts +63 -33
  32. package/src/__tests__/kv.test.ts +1128 -1011
  33. package/src/__tests__/logger.test.ts +100 -74
  34. package/src/__tests__/package-manager.test.ts +303 -303
  35. package/src/__tests__/pages.test.ts +1152 -652
  36. package/src/__tests__/parse.test.ts +252 -252
  37. package/src/__tests__/publish.test.ts +6371 -5622
  38. package/src/__tests__/pubsub.test.ts +367 -0
  39. package/src/__tests__/r2.test.ts +133 -133
  40. package/src/__tests__/route.test.ts +18 -18
  41. package/src/__tests__/secret.test.ts +382 -377
  42. package/src/__tests__/tail.test.ts +530 -530
  43. package/src/__tests__/user.test.ts +123 -111
  44. package/src/__tests__/whoami.test.tsx +198 -117
  45. package/src/__tests__/worker-namespace.test.ts +327 -0
  46. package/src/abort.d.ts +1 -1
  47. package/src/api/dev.ts +49 -0
  48. package/src/api/index.ts +1 -0
  49. package/src/bundle-reporter.tsx +29 -0
  50. package/src/bundle.ts +157 -149
  51. package/src/cfetch/index.ts +80 -80
  52. package/src/cfetch/internal.ts +90 -83
  53. package/src/cli.ts +21 -7
  54. package/src/config/config.ts +204 -195
  55. package/src/config/diagnostics.ts +61 -61
  56. package/src/config/environment.ts +390 -357
  57. package/src/config/index.ts +206 -193
  58. package/src/config/validation-helpers.ts +366 -366
  59. package/src/config/validation.ts +1573 -1376
  60. package/src/config-cache.ts +79 -41
  61. package/src/create-worker-preview.ts +206 -136
  62. package/src/create-worker-upload-form.ts +247 -238
  63. package/src/dev/dev-vars.ts +13 -13
  64. package/src/dev/dev.tsx +329 -307
  65. package/src/dev/local.tsx +304 -275
  66. package/src/dev/remote.tsx +366 -224
  67. package/src/dev/use-esbuild.ts +126 -91
  68. package/src/dev.tsx +538 -0
  69. package/src/dialogs.tsx +97 -97
  70. package/src/durable.ts +87 -87
  71. package/src/entry.ts +234 -228
  72. package/src/environment-variables.ts +23 -23
  73. package/src/errors.ts +6 -6
  74. package/src/generate.ts +33 -0
  75. package/src/git-client.ts +42 -0
  76. package/src/https-options.ts +79 -79
  77. package/src/index.tsx +1775 -2763
  78. package/src/init.ts +549 -0
  79. package/src/inspect.ts +593 -593
  80. package/src/intl-polyfill.d.ts +123 -123
  81. package/src/is-interactive.ts +12 -0
  82. package/src/kv.ts +277 -277
  83. package/src/logger.ts +46 -39
  84. package/src/miniflare-cli/enum-keys.ts +8 -8
  85. package/src/miniflare-cli/index.ts +42 -31
  86. package/src/miniflare-cli/request-context.ts +18 -18
  87. package/src/module-collection.ts +212 -212
  88. package/src/open-in-browser.ts +4 -6
  89. package/src/package-manager.ts +123 -123
  90. package/src/pages/build.tsx +202 -0
  91. package/src/pages/constants.ts +7 -0
  92. package/src/pages/deployments.tsx +101 -0
  93. package/src/pages/dev.tsx +964 -0
  94. package/src/pages/functions/buildPlugin.ts +105 -0
  95. package/src/pages/functions/buildWorker.ts +151 -0
  96. package/{pages → src/pages}/functions/filepath-routing.test.ts +113 -113
  97. package/src/pages/functions/filepath-routing.ts +189 -0
  98. package/src/pages/functions/identifiers.ts +78 -0
  99. package/src/pages/functions/routes.ts +151 -0
  100. package/src/pages/index.tsx +84 -0
  101. package/src/pages/projects.tsx +157 -0
  102. package/src/pages/publish.tsx +335 -0
  103. package/src/pages/types.ts +40 -0
  104. package/src/pages/upload.tsx +384 -0
  105. package/src/pages/utils.ts +12 -0
  106. package/src/parse.ts +202 -138
  107. package/src/paths.ts +6 -6
  108. package/src/preview.ts +31 -0
  109. package/src/proxy.ts +400 -402
  110. package/src/publish.ts +667 -621
  111. package/src/pubsub/index.ts +286 -0
  112. package/src/pubsub/pubsub-commands.tsx +577 -0
  113. package/src/r2.ts +19 -19
  114. package/src/selfsigned.d.ts +23 -23
  115. package/src/sites.tsx +271 -225
  116. package/src/tail/filters.ts +108 -108
  117. package/src/tail/index.ts +217 -217
  118. package/src/tail/printing.ts +45 -45
  119. package/src/update-check.ts +11 -11
  120. package/src/user/choose-account.tsx +60 -0
  121. package/src/user/env-vars.ts +46 -0
  122. package/src/user/generate-auth-url.ts +33 -0
  123. package/src/user/generate-random-state.ts +16 -0
  124. package/src/user/index.ts +3 -0
  125. package/src/user/user.tsx +1161 -0
  126. package/src/whoami.tsx +61 -42
  127. package/src/worker-namespace.ts +190 -0
  128. package/src/worker.ts +110 -100
  129. package/src/zones.ts +39 -36
  130. package/templates/checked-fetch.js +17 -0
  131. package/templates/new-worker-scheduled.js +3 -3
  132. package/templates/new-worker-scheduled.ts +15 -15
  133. package/templates/new-worker.js +3 -3
  134. package/templates/new-worker.ts +15 -15
  135. package/templates/no-op-worker.js +10 -0
  136. package/templates/pages-template-plugin.ts +155 -0
  137. package/templates/pages-template-worker.ts +161 -0
  138. package/templates/static-asset-facade.js +31 -31
  139. package/templates/tsconfig.json +95 -95
  140. package/wrangler-dist/cli.js +55383 -54138
  141. package/pages/functions/buildPlugin.ts +0 -105
  142. package/pages/functions/buildWorker.ts +0 -151
  143. package/pages/functions/filepath-routing.ts +0 -189
  144. package/pages/functions/identifiers.ts +0 -78
  145. package/pages/functions/routes.ts +0 -156
  146. package/pages/functions/template-plugin.ts +0 -147
  147. package/pages/functions/template-worker.ts +0 -143
  148. package/src/pages.tsx +0 -2093
  149. package/src/user.tsx +0 -1214
package/src/kv.ts CHANGED
@@ -10,9 +10,9 @@ const API_MAX = 10000;
10
10
  const BATCH_KEY_MAX = API_MAX / 2;
11
11
 
12
12
  type KvArgs = {
13
- binding?: string;
14
- "namespace-id"?: string;
15
- preview?: boolean;
13
+ binding?: string;
14
+ "namespace-id"?: string;
15
+ preview?: boolean;
16
16
  };
17
17
 
18
18
  /**
@@ -21,388 +21,388 @@ type KvArgs = {
21
21
  * @returns the generated id of the created namespace.
22
22
  */
23
23
  export async function createKVNamespace(
24
- accountId: string,
25
- title: string
24
+ accountId: string,
25
+ title: string
26
26
  ): Promise<string> {
27
- const response = await fetchResult<{ id: string }>(
28
- `/accounts/${accountId}/storage/kv/namespaces`,
29
- {
30
- method: "POST",
31
- headers: {
32
- "Content-Type": "application/json",
33
- },
34
- body: JSON.stringify({
35
- title,
36
- }),
37
- }
38
- );
39
-
40
- return response.id;
27
+ const response = await fetchResult<{ id: string }>(
28
+ `/accounts/${accountId}/storage/kv/namespaces`,
29
+ {
30
+ method: "POST",
31
+ headers: {
32
+ "Content-Type": "application/json",
33
+ },
34
+ body: JSON.stringify({
35
+ title,
36
+ }),
37
+ }
38
+ );
39
+
40
+ return response.id;
41
41
  }
42
42
 
43
43
  /**
44
44
  * The information about a namespace that is returned from `listNamespaces()`.
45
45
  */
46
46
  export interface KVNamespaceInfo {
47
- id: string;
48
- title: string;
49
- supports_url_encoding?: boolean;
47
+ id: string;
48
+ title: string;
49
+ supports_url_encoding?: boolean;
50
50
  }
51
51
 
52
52
  /**
53
53
  * Fetch a list of all the namespaces under the given `accountId`.
54
54
  */
55
55
  export async function listKVNamespaces(
56
- accountId: string
56
+ accountId: string
57
57
  ): Promise<KVNamespaceInfo[]> {
58
- const pageSize = 100;
59
- let page = 1;
60
- const results: KVNamespaceInfo[] = [];
61
- while (results.length % pageSize === 0) {
62
- const json = await fetchResult<KVNamespaceInfo[]>(
63
- `/accounts/${accountId}/storage/kv/namespaces`,
64
- {},
65
- new URLSearchParams({
66
- per_page: pageSize.toString(),
67
- order: "title",
68
- direction: "asc",
69
- page: page.toString(),
70
- })
71
- );
72
- page++;
73
- results.push(...json);
74
- if (json.length < pageSize) {
75
- break;
76
- }
77
- }
78
- return results;
58
+ const pageSize = 100;
59
+ let page = 1;
60
+ const results: KVNamespaceInfo[] = [];
61
+ while (results.length % pageSize === 0) {
62
+ const json = await fetchResult<KVNamespaceInfo[]>(
63
+ `/accounts/${accountId}/storage/kv/namespaces`,
64
+ {},
65
+ new URLSearchParams({
66
+ per_page: pageSize.toString(),
67
+ order: "title",
68
+ direction: "asc",
69
+ page: page.toString(),
70
+ })
71
+ );
72
+ page++;
73
+ results.push(...json);
74
+ if (json.length < pageSize) {
75
+ break;
76
+ }
77
+ }
78
+ return results;
79
79
  }
80
80
 
81
81
  export interface NamespaceKeyInfo {
82
- name: string;
83
- expiration?: number;
84
- metadata?: { [key: string]: unknown };
82
+ name: string;
83
+ expiration?: number;
84
+ metadata?: { [key: string]: unknown };
85
85
  }
86
86
 
87
87
  export async function listKVNamespaceKeys(
88
- accountId: string,
89
- namespaceId: string,
90
- prefix = ""
88
+ accountId: string,
89
+ namespaceId: string,
90
+ prefix = ""
91
91
  ) {
92
- return await fetchListResult<NamespaceKeyInfo>(
93
- `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/keys`,
94
- {},
95
- new URLSearchParams({ prefix })
96
- );
92
+ return await fetchListResult<NamespaceKeyInfo>(
93
+ `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/keys`,
94
+ {},
95
+ new URLSearchParams({ prefix })
96
+ );
97
97
  }
98
98
 
99
99
  export async function deleteKVNamespace(
100
- accountId: string,
101
- namespaceId: string
100
+ accountId: string,
101
+ namespaceId: string
102
102
  ) {
103
- return await fetchResult<{ id: string }>(
104
- `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}`,
105
- { method: "DELETE" }
106
- );
103
+ return await fetchResult<{ id: string }>(
104
+ `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}`,
105
+ { method: "DELETE" }
106
+ );
107
107
  }
108
108
 
109
109
  /**
110
110
  * Information about a key-value pair, including its "metadata" fields.
111
111
  */
112
112
  export interface KeyValue {
113
- key: string;
114
- value: string | Buffer;
115
- expiration?: number;
116
- expiration_ttl?: number;
117
- metadata?: object;
118
- base64?: boolean;
113
+ key: string;
114
+ value: string | Buffer;
115
+ expiration?: number;
116
+ expiration_ttl?: number;
117
+ metadata?: object;
118
+ base64?: boolean;
119
119
  }
120
120
 
121
121
  const KeyValueKeys = new Set([
122
- "key",
123
- "value",
124
- "expiration",
125
- "expiration_ttl",
126
- "metadata",
127
- "base64",
122
+ "key",
123
+ "value",
124
+ "expiration",
125
+ "expiration_ttl",
126
+ "metadata",
127
+ "base64",
128
128
  ]);
129
129
 
130
130
  /**
131
131
  * The object has the specified property.
132
132
  */
133
133
  function hasProperty<T extends object>(
134
- obj: object,
135
- property: keyof T
134
+ obj: object,
135
+ property: keyof T
136
136
  ): obj is T {
137
- return property in obj;
137
+ return property in obj;
138
138
  }
139
139
 
140
140
  /**
141
141
  * The object has a required property of the specified type.
142
142
  */
143
143
  function hasTypedProperty<T extends object>(
144
- obj: object,
145
- property: keyof T,
146
- type: string
144
+ obj: object,
145
+ property: keyof T,
146
+ type: string
147
147
  ): obj is T {
148
- return hasProperty(obj, property) && typeof obj[property] === type;
148
+ return hasProperty(obj, property) && typeof obj[property] === type;
149
149
  }
150
150
 
151
151
  /**
152
152
  * The object an optional property, of the specified type.
153
153
  */
154
154
  function hasOptionalTypedProperty<T extends object>(
155
- obj: object,
156
- property: keyof T,
157
- type: string
155
+ obj: object,
156
+ property: keyof T,
157
+ type: string
158
158
  ): obj is Omit<T, typeof property> | T {
159
- return !hasProperty(obj, property) || typeof obj[property] === type;
159
+ return !hasProperty(obj, property) || typeof obj[property] === type;
160
160
  }
161
161
 
162
162
  /**
163
163
  * Is the given object a valid `KeyValue` type?
164
164
  */
165
165
  export function isKVKeyValue(keyValue: unknown): keyValue is KeyValue {
166
- if (
167
- keyValue === null ||
168
- typeof keyValue !== "object" ||
169
- !hasTypedProperty(keyValue, "key", "string") ||
170
- !hasTypedProperty(keyValue, "value", "string") ||
171
- !hasOptionalTypedProperty(keyValue, "expiration", "number") ||
172
- !hasOptionalTypedProperty(keyValue, "expiration_ttl", "number") ||
173
- !hasOptionalTypedProperty(keyValue, "base64", "boolean") ||
174
- !hasOptionalTypedProperty(keyValue, "metadata", "object")
175
- ) {
176
- return false;
177
- }
178
- return true;
166
+ if (
167
+ keyValue === null ||
168
+ typeof keyValue !== "object" ||
169
+ !hasTypedProperty(keyValue, "key", "string") ||
170
+ !hasTypedProperty(keyValue, "value", "string") ||
171
+ !hasOptionalTypedProperty(keyValue, "expiration", "number") ||
172
+ !hasOptionalTypedProperty(keyValue, "expiration_ttl", "number") ||
173
+ !hasOptionalTypedProperty(keyValue, "base64", "boolean") ||
174
+ !hasOptionalTypedProperty(keyValue, "metadata", "object")
175
+ ) {
176
+ return false;
177
+ }
178
+ return true;
179
179
  }
180
180
 
181
181
  /**
182
182
  * Get all the properties on the `keyValue` that are not expected.
183
183
  */
184
184
  export function unexpectedKVKeyValueProps(keyValue: KeyValue): string[] {
185
- const props = Object.keys(keyValue);
186
- return props.filter((prop) => !KeyValueKeys.has(prop));
185
+ const props = Object.keys(keyValue);
186
+ return props.filter((prop) => !KeyValueKeys.has(prop));
187
187
  }
188
188
 
189
189
  export async function putKVKeyValue(
190
- accountId: string,
191
- namespaceId: string,
192
- keyValue: KeyValue
190
+ accountId: string,
191
+ namespaceId: string,
192
+ keyValue: KeyValue
193
193
  ) {
194
- let searchParams: URLSearchParams | undefined;
195
- if (keyValue.expiration || keyValue.expiration_ttl) {
196
- searchParams = new URLSearchParams();
197
- if (keyValue.expiration) {
198
- searchParams.set("expiration", `${keyValue.expiration}`);
199
- }
200
- if (keyValue.expiration_ttl) {
201
- searchParams.set("expiration_ttl", `${keyValue.expiration_ttl}`);
202
- }
203
- }
204
- return await fetchResult(
205
- `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(
206
- keyValue.key
207
- )}`,
208
- { method: "PUT", body: keyValue.value },
209
- searchParams
210
- );
194
+ let searchParams: URLSearchParams | undefined;
195
+ if (keyValue.expiration || keyValue.expiration_ttl) {
196
+ searchParams = new URLSearchParams();
197
+ if (keyValue.expiration) {
198
+ searchParams.set("expiration", `${keyValue.expiration}`);
199
+ }
200
+ if (keyValue.expiration_ttl) {
201
+ searchParams.set("expiration_ttl", `${keyValue.expiration_ttl}`);
202
+ }
203
+ }
204
+ return await fetchResult(
205
+ `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(
206
+ keyValue.key
207
+ )}`,
208
+ { method: "PUT", body: keyValue.value },
209
+ searchParams
210
+ );
211
211
  }
212
212
 
213
213
  export async function getKVKeyValue(
214
- accountId: string,
215
- namespaceId: string,
216
- key: string
217
- ): Promise<string> {
218
- return await fetchKVGetValue(accountId, namespaceId, encodeURIComponent(key));
214
+ accountId: string,
215
+ namespaceId: string,
216
+ key: string
217
+ ): Promise<ArrayBuffer> {
218
+ return await fetchKVGetValue(accountId, namespaceId, encodeURIComponent(key));
219
219
  }
220
220
 
221
221
  export async function deleteKVKeyValue(
222
- accountId: string,
223
- namespaceId: string,
224
- key: string
222
+ accountId: string,
223
+ namespaceId: string,
224
+ key: string
225
225
  ) {
226
- return await fetchResult(
227
- `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(
228
- key
229
- )}`,
230
- { method: "DELETE" }
231
- );
226
+ return await fetchResult(
227
+ `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(
228
+ key
229
+ )}`,
230
+ { method: "DELETE" }
231
+ );
232
232
  }
233
233
 
234
234
  /**
235
235
  * Formatter for converting e.g. 5328 --> 5,328
236
236
  */
237
237
  const formatNumber = new Intl.NumberFormat("en-US", {
238
- notation: "standard",
238
+ notation: "standard",
239
239
  }).format;
240
240
 
241
241
  /**
242
242
  * Helper function for bulk requests, logs ongoing output to console.
243
243
  */
244
244
  function logBulkProgress(
245
- operation: "put" | "delete",
246
- index: number,
247
- total: number
245
+ operation: "put" | "delete",
246
+ index: number,
247
+ total: number
248
248
  ) {
249
- logger.log(
250
- `${operation === "put" ? "Uploaded" : "Deleted"} ${Math.floor(
251
- (100 * index) / total
252
- )}% (${formatNumber(index)} out of ${formatNumber(total)})`
253
- );
249
+ logger.log(
250
+ `${operation === "put" ? "Uploaded" : "Deleted"} ${Math.floor(
251
+ (100 * index) / total
252
+ )}% (${formatNumber(index)} out of ${formatNumber(total)})`
253
+ );
254
254
  }
255
255
 
256
256
  export async function putKVBulkKeyValue(
257
- accountId: string,
258
- namespaceId: string,
259
- keyValues: KeyValue[],
260
- quiet = false
257
+ accountId: string,
258
+ namespaceId: string,
259
+ keyValues: KeyValue[],
260
+ quiet = false
261
261
  ) {
262
- for (let index = 0; index < keyValues.length; index += BATCH_KEY_MAX) {
263
- if (!quiet && keyValues.length > BATCH_KEY_MAX) {
264
- logBulkProgress("put", index, keyValues.length);
265
- }
266
-
267
- await fetchResult(
268
- `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/bulk`,
269
- {
270
- method: "PUT",
271
- body: JSON.stringify(keyValues.slice(index, index + BATCH_KEY_MAX)),
272
- headers: { "Content-Type": "application/json" },
273
- }
274
- );
275
- }
276
-
277
- if (!quiet && keyValues.length > BATCH_KEY_MAX) {
278
- logBulkProgress("put", keyValues.length, keyValues.length);
279
- }
262
+ for (let index = 0; index < keyValues.length; index += BATCH_KEY_MAX) {
263
+ if (!quiet && keyValues.length > BATCH_KEY_MAX) {
264
+ logBulkProgress("put", index, keyValues.length);
265
+ }
266
+
267
+ await fetchResult(
268
+ `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/bulk`,
269
+ {
270
+ method: "PUT",
271
+ body: JSON.stringify(keyValues.slice(index, index + BATCH_KEY_MAX)),
272
+ headers: { "Content-Type": "application/json" },
273
+ }
274
+ );
275
+ }
276
+
277
+ if (!quiet && keyValues.length > BATCH_KEY_MAX) {
278
+ logBulkProgress("put", keyValues.length, keyValues.length);
279
+ }
280
280
  }
281
281
 
282
282
  export async function deleteKVBulkKeyValue(
283
- accountId: string,
284
- namespaceId: string,
285
- keys: string[],
286
- quiet = false
283
+ accountId: string,
284
+ namespaceId: string,
285
+ keys: string[],
286
+ quiet = false
287
287
  ) {
288
- for (let index = 0; index < keys.length; index += BATCH_KEY_MAX) {
289
- if (!quiet && keys.length > BATCH_KEY_MAX) {
290
- logBulkProgress("delete", index, keys.length);
291
- }
292
-
293
- await fetchResult(
294
- `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/bulk`,
295
- {
296
- method: "DELETE",
297
- body: JSON.stringify(keys.slice(index, index + BATCH_KEY_MAX)),
298
- headers: { "Content-Type": "application/json" },
299
- }
300
- );
301
- }
302
- if (!quiet && keys.length > BATCH_KEY_MAX) {
303
- logBulkProgress("delete", keys.length, keys.length);
304
- }
288
+ for (let index = 0; index < keys.length; index += BATCH_KEY_MAX) {
289
+ if (!quiet && keys.length > BATCH_KEY_MAX) {
290
+ logBulkProgress("delete", index, keys.length);
291
+ }
292
+
293
+ await fetchResult(
294
+ `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/bulk`,
295
+ {
296
+ method: "DELETE",
297
+ body: JSON.stringify(keys.slice(index, index + BATCH_KEY_MAX)),
298
+ headers: { "Content-Type": "application/json" },
299
+ }
300
+ );
301
+ }
302
+ if (!quiet && keys.length > BATCH_KEY_MAX) {
303
+ logBulkProgress("delete", keys.length, keys.length);
304
+ }
305
305
  }
306
306
 
307
307
  export function getKVNamespaceId(
308
- { preview, binding, "namespace-id": namespaceId }: KvArgs,
309
- config: Config
308
+ { preview, binding, "namespace-id": namespaceId }: KvArgs,
309
+ config: Config
310
310
  ): string {
311
- // nice
312
- if (namespaceId) {
313
- return namespaceId;
314
- }
315
-
316
- // begin pre-flight checks
317
-
318
- // `--binding` is only valid if there's a wrangler configuration.
319
- if (binding && !config) {
320
- throw new Error("--binding specified, but no config file was found.");
321
- }
322
-
323
- // there's no config. abort here
324
- if (!config) {
325
- throw new Error(
326
- "Failed to find a config file.\n" +
327
- "Either use --namespace-id to upload directly or create a configuration file with a binding."
328
- );
329
- }
330
-
331
- // there's no KV namespaces
332
- if (!config.kv_namespaces || config.kv_namespaces.length === 0) {
333
- throw new Error(
334
- "No KV Namespaces configured! Either use --namespace-id to upload directly or add a KV namespace to your wrangler config file."
335
- );
336
- }
337
-
338
- const namespace = config.kv_namespaces.find((ns) => ns.binding === binding);
339
-
340
- // we couldn't find a namespace with that binding
341
- if (!namespace) {
342
- throw new Error(
343
- `A namespace with binding name "${binding}" was not found in the configured "kv_namespaces".`
344
- );
345
- }
346
-
347
- // end pre-flight checks
348
-
349
- // we're in preview mode, `--preview true` or `--preview` was passed
350
- if (preview && namespace.preview_id) {
351
- namespaceId = namespace.preview_id;
352
- // We don't want to execute code below if preview is set to true, so we just return. Otherwise we will get errors!
353
- return namespaceId;
354
- } else if (preview) {
355
- throw new Error(
356
- `No preview ID found for ${binding}. Add one to your wrangler config file to use a separate namespace for previewing your worker.`
357
- );
358
- }
359
-
360
- // either `--preview false`, or preview wasn't passed
361
- // TODO: should we care? or should we just treat false and undefined the same
362
- const previewIsDefined = typeof preview !== "undefined";
363
-
364
- // --preview false was passed
365
- if (previewIsDefined && namespace.id) {
366
- namespaceId = namespace.id;
367
- // We don't want to execute code below if preview is set to true, so we just return. Otherwise we can get error!
368
- return namespaceId;
369
- } else if (previewIsDefined) {
370
- throw new Error(
371
- `No namespace ID found for ${binding}. Add one to your wrangler config file to use a separate namespace for previewing your worker.`
372
- );
373
- }
374
-
375
- // `--preview` wasn't passed
376
- const bindingHasOnlyOneId =
377
- (namespace.id && !namespace.preview_id) ||
378
- (!namespace.id && namespace.preview_id);
379
- if (bindingHasOnlyOneId) {
380
- namespaceId = namespace.id || namespace.preview_id;
381
- } else {
382
- throw new Error(
383
- `${binding} has both a namespace ID and a preview ID. Specify "--preview" or "--preview false" to avoid writing data to the wrong namespace.`
384
- );
385
- }
386
-
387
- // shouldn't happen. we should be able to prove this with strong typing.
388
- // TODO: when we add strongly typed commands, rewrite these checks so they're exhaustive
389
- if (!namespaceId) {
390
- throw Error(
391
- "Something went wrong trying to determine which namespace to upload to.\n" +
392
- "Please create a github issue with the command you just ran along with your wrangler configuration."
393
- );
394
- }
395
-
396
- return namespaceId;
311
+ // nice
312
+ if (namespaceId) {
313
+ return namespaceId;
314
+ }
315
+
316
+ // begin pre-flight checks
317
+
318
+ // `--binding` is only valid if there's a wrangler configuration.
319
+ if (binding && !config) {
320
+ throw new Error("--binding specified, but no config file was found.");
321
+ }
322
+
323
+ // there's no config. abort here
324
+ if (!config) {
325
+ throw new Error(
326
+ "Failed to find a config file.\n" +
327
+ "Either use --namespace-id to upload directly or create a configuration file with a binding."
328
+ );
329
+ }
330
+
331
+ // there's no KV namespaces
332
+ if (!config.kv_namespaces || config.kv_namespaces.length === 0) {
333
+ throw new Error(
334
+ "No KV Namespaces configured! Either use --namespace-id to upload directly or add a KV namespace to your wrangler config file."
335
+ );
336
+ }
337
+
338
+ const namespace = config.kv_namespaces.find((ns) => ns.binding === binding);
339
+
340
+ // we couldn't find a namespace with that binding
341
+ if (!namespace) {
342
+ throw new Error(
343
+ `A namespace with binding name "${binding}" was not found in the configured "kv_namespaces".`
344
+ );
345
+ }
346
+
347
+ // end pre-flight checks
348
+
349
+ // we're in preview mode, `--preview true` or `--preview` was passed
350
+ if (preview && namespace.preview_id) {
351
+ namespaceId = namespace.preview_id;
352
+ // We don't want to execute code below if preview is set to true, so we just return. Otherwise we will get errors!
353
+ return namespaceId;
354
+ } else if (preview) {
355
+ throw new Error(
356
+ `No preview ID found for ${binding}. Add one to your wrangler config file to use a separate namespace for previewing your worker.`
357
+ );
358
+ }
359
+
360
+ // either `--preview false`, or preview wasn't passed
361
+ // TODO: should we care? or should we just treat false and undefined the same
362
+ const previewIsDefined = typeof preview !== "undefined";
363
+
364
+ // --preview false was passed
365
+ if (previewIsDefined && namespace.id) {
366
+ namespaceId = namespace.id;
367
+ // We don't want to execute code below if preview is set to true, so we just return. Otherwise we can get error!
368
+ return namespaceId;
369
+ } else if (previewIsDefined) {
370
+ throw new Error(
371
+ `No namespace ID found for ${binding}. Add one to your wrangler config file to use a separate namespace for previewing your worker.`
372
+ );
373
+ }
374
+
375
+ // `--preview` wasn't passed
376
+ const bindingHasOnlyOneId =
377
+ (namespace.id && !namespace.preview_id) ||
378
+ (!namespace.id && namespace.preview_id);
379
+ if (bindingHasOnlyOneId) {
380
+ namespaceId = namespace.id || namespace.preview_id;
381
+ } else {
382
+ throw new Error(
383
+ `${binding} has both a namespace ID and a preview ID. Specify "--preview" or "--preview false" to avoid writing data to the wrong namespace.`
384
+ );
385
+ }
386
+
387
+ // shouldn't happen. we should be able to prove this with strong typing.
388
+ // TODO: when we add strongly typed commands, rewrite these checks so they're exhaustive
389
+ if (!namespaceId) {
390
+ throw Error(
391
+ "Something went wrong trying to determine which namespace to upload to.\n" +
392
+ "Please create a github issue with the command you just ran along with your wrangler configuration."
393
+ );
394
+ }
395
+
396
+ return namespaceId;
397
397
  }
398
398
 
399
399
  /**
400
400
  * KV namespace binding names must be valid JS identifiers.
401
401
  */
402
402
  export function isValidKVNamespaceBinding(
403
- binding: string | undefined
403
+ binding: string | undefined
404
404
  ): binding is string {
405
- return (
406
- typeof binding === "string" && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(binding)
407
- );
405
+ return (
406
+ typeof binding === "string" && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(binding)
407
+ );
408
408
  }