wrangler 0.0.0-e7a0cd5b → 0.0.0-e87ad068

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 (255) hide show
  1. package/README.md +3 -3
  2. package/bin/wrangler.js +30 -10
  3. package/miniflare-dist/index.mjs +254 -128
  4. package/package.json +27 -19
  5. package/src/__tests__/api-dev.test.ts +65 -36
  6. package/src/__tests__/api-devregistry.test.ts +121 -0
  7. package/src/__tests__/api.test.ts +27 -5
  8. package/src/__tests__/configuration.test.ts +797 -98
  9. package/src/__tests__/constellation.test.ts +371 -0
  10. package/src/__tests__/d1/d1.test.ts +82 -0
  11. package/src/__tests__/d1/execute.test.ts +66 -0
  12. package/src/__tests__/d1/migrate.test.ts +257 -0
  13. package/src/__tests__/d1/splitter.test.ts +255 -0
  14. package/src/__tests__/delete.test.ts +91 -49
  15. package/src/__tests__/deployments.test.ts +330 -56
  16. package/src/__tests__/dev.test.tsx +198 -90
  17. package/src/__tests__/generate.test.ts +12 -10
  18. package/src/__tests__/guess-worker-format.test.ts +35 -0
  19. package/src/__tests__/helpers/end-event-loop.ts +6 -0
  20. package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
  21. package/src/__tests__/helpers/mock-console.ts +6 -0
  22. package/src/__tests__/helpers/mock-dialogs.ts +71 -85
  23. package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
  24. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -5
  25. package/src/__tests__/helpers/mock-known-routes.ts +7 -2
  26. package/src/__tests__/helpers/mock-kv.ts +29 -16
  27. package/src/__tests__/helpers/mock-oauth-flow.ts +103 -92
  28. package/src/__tests__/helpers/mock-process.ts +8 -13
  29. package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
  30. package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
  31. package/src/__tests__/helpers/msw/handlers/deployments.ts +128 -27
  32. package/src/__tests__/helpers/msw/handlers/namespaces.ts +18 -41
  33. package/src/__tests__/helpers/msw/handlers/oauth.ts +13 -18
  34. package/src/__tests__/helpers/msw/handlers/r2.ts +14 -34
  35. package/src/__tests__/helpers/msw/handlers/script.ts +9 -28
  36. package/src/__tests__/helpers/msw/handlers/user.ts +13 -24
  37. package/src/__tests__/helpers/msw/handlers/zones.ts +6 -8
  38. package/src/__tests__/helpers/msw/index.ts +32 -1
  39. package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
  40. package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
  41. package/src/__tests__/helpers/worker-scripts/parent-worker.js +4 -1
  42. package/src/__tests__/index.test.ts +92 -72
  43. package/src/__tests__/init.test.ts +1033 -631
  44. package/src/__tests__/jest.setup.ts +19 -42
  45. package/src/__tests__/kv.test.ts +355 -231
  46. package/src/__tests__/logger.test.ts +68 -2
  47. package/src/__tests__/logout.test.ts +47 -0
  48. package/src/__tests__/metrics.test.ts +94 -51
  49. package/src/__tests__/middleware.scheduled.test.ts +42 -32
  50. package/src/__tests__/middleware.test.ts +212 -122
  51. package/src/__tests__/mtls-certificates.test.ts +589 -0
  52. package/src/__tests__/pages/deployment-list.test.ts +80 -0
  53. package/src/__tests__/pages/functions-build.test.ts +529 -0
  54. package/src/__tests__/pages/pages.test.ts +81 -0
  55. package/src/__tests__/pages/project-create.test.ts +63 -0
  56. package/src/__tests__/pages/project-list.test.ts +110 -0
  57. package/src/__tests__/pages/project-upload.test.ts +500 -0
  58. package/src/__tests__/pages/publish.test.ts +2864 -0
  59. package/src/__tests__/pages-deployment-tail.test.ts +957 -0
  60. package/src/__tests__/parse.test.ts +106 -0
  61. package/src/__tests__/publish.test.ts +2227 -1005
  62. package/src/__tests__/pubsub.test.ts +226 -100
  63. package/src/__tests__/queues.test.ts +238 -77
  64. package/src/__tests__/r2.test.ts +55 -57
  65. package/src/__tests__/secret.test.ts +179 -130
  66. package/src/__tests__/tail.test.ts +313 -113
  67. package/src/__tests__/test-old-node-version.js +3 -3
  68. package/src/__tests__/traverse-module-graph.test.ts +220 -0
  69. package/src/__tests__/tsconfig-sanity.ts +12 -0
  70. package/src/__tests__/tsconfig.json +8 -0
  71. package/src/__tests__/tsconfig.tsbuildinfo +1 -0
  72. package/src/__tests__/type-generation.test.ts +43 -26
  73. package/src/__tests__/unstableDev.test.ts +61 -0
  74. package/src/__tests__/user.test.ts +35 -72
  75. package/src/__tests__/whoami.test.tsx +8 -114
  76. package/src/__tests__/worker-namespace.test.ts +83 -69
  77. package/src/api/dev.ts +180 -60
  78. package/src/api/index.ts +10 -1
  79. package/src/api/mtls-certificate.ts +148 -0
  80. package/src/api/pages/create-worker-bundle-contents.ts +80 -0
  81. package/src/api/pages/index.ts +5 -0
  82. package/src/api/pages/publish.tsx +371 -0
  83. package/src/bundle.ts +315 -148
  84. package/src/cfetch/index.ts +0 -2
  85. package/src/cfetch/internal.ts +33 -33
  86. package/src/cli.ts +4 -4
  87. package/src/config/config.ts +14 -7
  88. package/src/config/environment.ts +120 -24
  89. package/src/config/index.ts +117 -35
  90. package/src/config/validation-helpers.ts +1 -1
  91. package/src/config/validation.ts +430 -19
  92. package/src/constellation/createProject.tsx +51 -0
  93. package/src/constellation/deleteProject.ts +51 -0
  94. package/src/constellation/deleteProjectModel.ts +76 -0
  95. package/src/constellation/index.ts +75 -0
  96. package/src/constellation/listCatalog.tsx +35 -0
  97. package/src/constellation/listModel.tsx +49 -0
  98. package/src/constellation/listProject.tsx +28 -0
  99. package/src/constellation/listRuntime.tsx +28 -0
  100. package/src/constellation/options.ts +17 -0
  101. package/src/constellation/types.ts +17 -0
  102. package/src/constellation/uploadModel.tsx +84 -0
  103. package/src/constellation/utils.ts +90 -0
  104. package/src/create-worker-preview.ts +19 -8
  105. package/src/create-worker-upload-form.ts +81 -18
  106. package/src/d1/backups.tsx +47 -46
  107. package/src/d1/constants.ts +5 -0
  108. package/src/d1/create.tsx +85 -37
  109. package/src/d1/{delete.tsx → delete.ts} +12 -15
  110. package/src/d1/execute.tsx +228 -156
  111. package/src/d1/index.ts +31 -7
  112. package/src/d1/list.tsx +27 -13
  113. package/src/d1/migrations/apply.tsx +235 -0
  114. package/src/d1/migrations/create.tsx +79 -0
  115. package/src/d1/migrations/helpers.ts +171 -0
  116. package/src/d1/migrations/index.ts +3 -0
  117. package/src/d1/migrations/list.tsx +95 -0
  118. package/src/d1/migrations/options.ts +23 -0
  119. package/src/d1/options.ts +12 -2
  120. package/src/d1/splitter.ts +161 -0
  121. package/src/d1/types.ts +32 -0
  122. package/src/d1/utils.ts +12 -2
  123. package/src/delete.ts +8 -16
  124. package/src/deployments.ts +340 -46
  125. package/src/deprecated/index.ts +8 -302
  126. package/src/dev/dev.tsx +66 -46
  127. package/src/dev/local.tsx +339 -104
  128. package/src/dev/remote.tsx +36 -3
  129. package/src/dev/start-server.ts +146 -101
  130. package/src/dev/use-esbuild.ts +82 -56
  131. package/src/dev/validate-dev-props.ts +9 -0
  132. package/src/{dev-registry.tsx → dev-registry.ts} +13 -1
  133. package/src/dev.tsx +202 -125
  134. package/src/dialogs.ts +136 -0
  135. package/src/dispatch-namespace.ts +21 -17
  136. package/src/docs/helpers.ts +50 -0
  137. package/src/docs/index.ts +54 -0
  138. package/src/entry.ts +26 -11
  139. package/src/environment-variables/factory.ts +89 -0
  140. package/src/environment-variables/misc-variables.ts +30 -0
  141. package/src/generate/index.ts +303 -0
  142. package/src/git-client.ts +15 -4
  143. package/src/{index.tsx → index.ts} +148 -63
  144. package/src/init.ts +301 -197
  145. package/src/inspect.ts +122 -6
  146. package/src/jest.d.ts +4 -0
  147. package/src/kv/helpers.ts +7 -4
  148. package/src/kv/index.ts +15 -17
  149. package/src/logger.ts +36 -5
  150. package/src/metrics/metrics-config.ts +3 -3
  151. package/src/metrics/send-event.ts +6 -1
  152. package/src/miniflare-cli/assets.ts +64 -28
  153. package/src/miniflare-cli/index.ts +6 -9
  154. package/src/miniflare-cli/tsconfig.json +9 -0
  155. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
  156. package/src/miniflare-cli/types.ts +11 -0
  157. package/src/module-collection.ts +92 -26
  158. package/src/mtls-certificate/cli.ts +155 -0
  159. package/src/pages/build.ts +423 -0
  160. package/src/pages/buildFunctions.ts +140 -0
  161. package/src/pages/deployment-tails.ts +281 -0
  162. package/src/pages/deployments.tsx +11 -33
  163. package/src/pages/{dev.tsx → dev.ts} +192 -126
  164. package/src/pages/errors.ts +1 -0
  165. package/src/pages/functions/buildPlugin.ts +73 -69
  166. package/src/pages/functions/buildWorker.ts +342 -117
  167. package/src/pages/functions/tsconfig.json +8 -0
  168. package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
  169. package/src/pages/{functions.tsx → functions.ts} +8 -4
  170. package/src/pages/{index.tsx → index.ts} +11 -3
  171. package/src/pages/projects.tsx +12 -22
  172. package/src/pages/prompt-select-project.tsx +31 -0
  173. package/src/pages/publish.tsx +45 -214
  174. package/src/pages/types.ts +6 -9
  175. package/src/pages/upload.tsx +58 -14
  176. package/src/pages/utils.ts +14 -3
  177. package/src/parse.ts +23 -1
  178. package/src/paths.ts +1 -1
  179. package/src/proxy.ts +5 -0
  180. package/src/publish/index.ts +20 -16
  181. package/src/publish/publish.ts +81 -48
  182. package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +19 -20
  183. package/src/queues/cli/commands/consumer/add.ts +24 -24
  184. package/src/queues/cli/commands/consumer/index.ts +3 -6
  185. package/src/queues/cli/commands/consumer/remove.ts +11 -18
  186. package/src/queues/cli/commands/create.ts +8 -8
  187. package/src/queues/cli/commands/delete.ts +8 -8
  188. package/src/queues/cli/commands/index.ts +6 -4
  189. package/src/queues/cli/commands/list.ts +8 -8
  190. package/src/queues/client.ts +1 -0
  191. package/src/queues/utils.ts +18 -0
  192. package/src/r2/constants.ts +4 -0
  193. package/src/r2/helpers.ts +1 -0
  194. package/src/r2/index.ts +40 -28
  195. package/src/secret/index.ts +18 -17
  196. package/src/{sites.tsx → sites.ts} +165 -53
  197. package/src/tail/createTail.ts +103 -3
  198. package/src/tail/filters.ts +1 -1
  199. package/src/tail/index.ts +8 -11
  200. package/src/tail/printing.ts +27 -0
  201. package/src/traverse-module-graph.ts +54 -0
  202. package/src/tsconfig-sanity.ts +16 -0
  203. package/src/type-generation.ts +85 -57
  204. package/src/user/access.ts +0 -1
  205. package/src/user/auth-variables.ts +113 -0
  206. package/src/user/choose-account.tsx +1 -31
  207. package/src/user/index.ts +0 -1
  208. package/src/user/{user.tsx → user.ts} +124 -82
  209. package/src/utils/render.ts +93 -0
  210. package/src/{whoami.tsx → whoami.ts} +37 -71
  211. package/src/worker.ts +61 -3
  212. package/src/yargs-types.ts +22 -5
  213. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  214. package/templates/__tests__/tsconfig.json +8 -0
  215. package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
  216. package/templates/checked-fetch.js +9 -3
  217. package/templates/d1-beta-facade.js +95 -25
  218. package/templates/facade.d.ts +14 -0
  219. package/templates/first-party-worker-module-facade.ts +4 -3
  220. package/templates/format-dev-errors.ts +8 -6
  221. package/templates/gitignore +1 -0
  222. package/templates/init-tests/test-jest-new-worker.js +3 -5
  223. package/templates/init-tests/test-vitest-new-worker.js +3 -5
  224. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  225. package/templates/middleware/loader-modules.ts +2 -2
  226. package/templates/middleware/loader-sw.ts +51 -31
  227. package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
  228. package/templates/new-worker.ts +3 -0
  229. package/templates/pages-dev-pipeline.ts +4 -1
  230. package/templates/pages-dev-util.ts +4 -1
  231. package/templates/pages-shim.ts +4 -1
  232. package/templates/pages-template-plugin.ts +19 -10
  233. package/templates/serve-static-assets.ts +17 -14
  234. package/templates/service-bindings-module-facade.js +1 -0
  235. package/templates/tsconfig-sanity.ts +11 -0
  236. package/templates/tsconfig.init.json +105 -0
  237. package/templates/tsconfig.json +5 -103
  238. package/templates/tsconfig.tsbuildinfo +1 -0
  239. package/wrangler-dist/cli.d.ts +902 -77
  240. package/wrangler-dist/cli.js +131685 -140615
  241. package/wrangler-dist/wasm-sync.wasm +0 -0
  242. package/src/__tests__/api-devregistry.test.js +0 -57
  243. package/src/__tests__/d1.test.ts +0 -72
  244. package/src/__tests__/dialogs.test.tsx +0 -40
  245. package/src/__tests__/helpers/mock-cfetch.ts +0 -333
  246. package/src/__tests__/pages.test.ts +0 -2223
  247. package/src/d1/types.tsx +0 -14
  248. package/src/dialogs.tsx +0 -163
  249. package/src/environment-variables.ts +0 -50
  250. package/src/pages/build.tsx +0 -238
  251. package/src/user/env-vars.ts +0 -46
  252. package/templates/experimental-local-cache-stubs.js +0 -27
  253. /package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
  254. /package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
  255. /package/src/pages/{hash.tsx → hash.ts} +0 -0
@@ -4,6 +4,8 @@ import type {
4
4
  CfWorkerInit,
5
5
  CfModuleType,
6
6
  CfDurableObjectMigrations,
7
+ CfPlacement,
8
+ CfTailConsumer,
7
9
  } from "./worker.js";
8
10
 
9
11
  export function toMimeType(type: CfModuleType): string {
@@ -23,15 +25,22 @@ export function toMimeType(type: CfModuleType): string {
23
25
  }
24
26
  }
25
27
 
26
- type WorkerMetadataBinding =
28
+ export type WorkerMetadataBinding =
27
29
  // If you add any new binding types here, also add it to safeBindings
28
30
  // under validateUnsafeBinding in config/validation.ts
29
31
  | { type: "plain_text"; name: string; text: string }
30
32
  | { type: "json"; name: string; json: unknown }
31
33
  | { type: "wasm_module"; name: string; part: string }
32
34
  | { type: "text_blob"; name: string; part: string }
35
+ | { type: "browser"; name: string }
33
36
  | { type: "data_blob"; name: string; part: string }
34
37
  | { type: "kv_namespace"; name: string; namespace_id: string }
38
+ | {
39
+ type: "send_email";
40
+ name: string;
41
+ destination_address?: string;
42
+ allowed_destination_addresses?: string[];
43
+ }
35
44
  | {
36
45
  type: "durable_object_namespace";
37
46
  name: string;
@@ -41,15 +50,17 @@ type WorkerMetadataBinding =
41
50
  }
42
51
  | { type: "queue"; name: string; queue_name: string }
43
52
  | { type: "r2_bucket"; name: string; bucket_name: string }
44
- | { type: "d1"; name: string; id: string }
53
+ | { type: "d1"; name: string; id: string; internalEnv?: string }
54
+ | { type: "constellation"; name: string; project: string }
45
55
  | { type: "service"; name: string; service: string; environment?: string }
46
- | { type: "namespace"; name: string; namespace: string }
56
+ | { type: "analytics_engine"; name: string; dataset?: string }
57
+ | { type: "dispatch_namespace"; name: string; namespace: string }
58
+ | { type: "mtls_certificate"; name: string; certificate_id: string }
47
59
  | {
48
60
  type: "logfwdr";
49
61
  name: string;
50
62
  destination: string;
51
- }
52
- | { type: "metadata"; name: string };
63
+ };
53
64
 
54
65
  export interface WorkerMetadata {
55
66
  /** The name of the entry point module. Only exists when the worker is in the ES module format */
@@ -64,6 +75,10 @@ export interface WorkerMetadata {
64
75
  bindings: WorkerMetadataBinding[];
65
76
  keep_bindings?: WorkerMetadataBinding["type"][];
66
77
  logpush?: boolean;
78
+ placement?: CfPlacement;
79
+ tail_consumers?: CfTailConsumer[];
80
+ // Allow unsafe.metadata to add arbitary properties at runtime
81
+ [key: string]: unknown;
67
82
  }
68
83
 
69
84
  /**
@@ -80,19 +95,14 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
80
95
  compatibility_flags,
81
96
  keepVars,
82
97
  logpush,
98
+ placement,
99
+ tail_consumers,
83
100
  } = worker;
84
101
 
85
102
  let { modules } = worker;
86
103
 
87
104
  const metadataBindings: WorkerMetadata["bindings"] = [];
88
105
 
89
- if (bindings.metadata_binding) {
90
- metadataBindings.push({
91
- name: bindings.metadata_binding,
92
- type: "metadata",
93
- });
94
- }
95
-
96
106
  Object.entries(bindings.vars || {})?.forEach(([key, value]) => {
97
107
  if (typeof value === "string") {
98
108
  metadataBindings.push({ name: key, type: "plain_text", text: value });
@@ -109,6 +119,17 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
109
119
  });
110
120
  });
111
121
 
122
+ bindings.send_email?.forEach(
123
+ ({ name, destination_address, allowed_destination_addresses }) => {
124
+ metadataBindings.push({
125
+ name: name,
126
+ type: "send_email",
127
+ destination_address,
128
+ allowed_destination_addresses,
129
+ });
130
+ }
131
+ );
132
+
112
133
  bindings.durable_objects?.bindings.forEach(
113
134
  ({ name, class_name, script_name, environment }) => {
114
135
  metadataBindings.push({
@@ -137,11 +158,22 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
137
158
  });
138
159
  });
139
160
 
140
- bindings.d1_databases?.forEach(({ binding, database_id }) => {
161
+ bindings.d1_databases?.forEach(
162
+ ({ binding, database_id, database_internal_env }) => {
163
+ metadataBindings.push({
164
+ name: binding,
165
+ type: "d1",
166
+ id: database_id,
167
+ internalEnv: database_internal_env,
168
+ });
169
+ }
170
+ );
171
+
172
+ bindings.constellation?.forEach(({ binding, project_id }) => {
141
173
  metadataBindings.push({
142
174
  name: binding,
143
- type: "d1",
144
- id: database_id,
175
+ type: "constellation",
176
+ project: project_id,
145
177
  });
146
178
  });
147
179
 
@@ -154,14 +186,30 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
154
186
  });
155
187
  });
156
188
 
189
+ bindings.analytics_engine_datasets?.forEach(({ binding, dataset }) => {
190
+ metadataBindings.push({
191
+ name: binding,
192
+ type: "analytics_engine",
193
+ dataset,
194
+ });
195
+ });
196
+
157
197
  bindings.dispatch_namespaces?.forEach(({ binding, namespace }) => {
158
198
  metadataBindings.push({
159
199
  name: binding,
160
- type: "namespace",
200
+ type: "dispatch_namespace",
161
201
  namespace,
162
202
  });
163
203
  });
164
204
 
205
+ bindings.mtls_certificates?.forEach(({ binding, certificate_id }) => {
206
+ metadataBindings.push({
207
+ name: binding,
208
+ type: "mtls_certificate",
209
+ certificate_id,
210
+ });
211
+ });
212
+
165
213
  bindings.logfwdr?.bindings.forEach(({ name, destination }) => {
166
214
  metadataBindings.push({
167
215
  name: name,
@@ -185,6 +233,13 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
185
233
  );
186
234
  }
187
235
 
236
+ if (bindings.browser !== undefined) {
237
+ metadataBindings.push({
238
+ name: bindings.browser.binding,
239
+ type: "browser",
240
+ });
241
+ }
242
+
188
243
  for (const [name, filePath] of Object.entries(bindings.text_blobs || {})) {
189
244
  metadataBindings.push({
190
245
  name,
@@ -271,9 +326,9 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
271
326
  }
272
327
  }
273
328
 
274
- if (bindings.unsafe) {
329
+ if (bindings.unsafe?.bindings) {
275
330
  // @ts-expect-error unsafe bindings don't need to match a specific type here
276
- metadataBindings.push(...bindings.unsafe);
331
+ metadataBindings.push(...bindings.unsafe.bindings);
277
332
  }
278
333
 
279
334
  const metadata: WorkerMetadata = {
@@ -288,8 +343,16 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
288
343
  capnp_schema: bindings.logfwdr?.schema,
289
344
  ...(keepVars && { keep_bindings: ["plain_text", "json"] }),
290
345
  ...(logpush !== undefined && { logpush }),
346
+ ...(placement && { placement }),
347
+ ...(tail_consumers && { tail_consumers }),
291
348
  };
292
349
 
350
+ if (bindings.unsafe?.metadata !== undefined) {
351
+ for (const key of Object.keys(bindings.unsafe.metadata)) {
352
+ metadata[key] = bindings.unsafe.metadata[key];
353
+ }
354
+ }
355
+
293
356
  formData.set("metadata", JSON.stringify(metadata));
294
357
 
295
358
  if (main.type === "commonjs" && modules && modules.length > 0) {
@@ -1,6 +1,5 @@
1
1
  import fs from "node:fs/promises";
2
2
  import * as path from "path";
3
- import { render } from "ink";
4
3
  import Table from "ink-table";
5
4
  import React from "react";
6
5
  import { fetchResult } from "../cfetch";
@@ -8,22 +7,24 @@ import { performApiFetch } from "../cfetch/internal";
8
7
  import { withConfig } from "../config";
9
8
  import { logger } from "../logger";
10
9
  import { requireAuth } from "../user";
10
+ import { renderToString } from "../utils/render";
11
11
  import { formatBytes, formatTimeAgo } from "./formatTimeAgo";
12
12
  import { Name } from "./options";
13
13
  import { d1BetaWarning, getDatabaseByNameOrBinding } from "./utils";
14
+ import type {
15
+ CommonYargsArgv,
16
+ StrictYargsOptionsToInterface,
17
+ } from "../yargs-types";
14
18
  import type { Backup, Database } from "./types";
15
19
  import type { Response } from "undici";
16
- import type { Argv } from "yargs";
17
20
 
18
- type BackupListArgs = { config?: string; name: string };
19
-
20
- export function ListOptions(yargs: Argv): Argv<BackupListArgs> {
21
+ export function ListOptions(yargs: CommonYargsArgv) {
21
22
  return Name(yargs);
22
23
  }
23
-
24
- export const ListHandler = withConfig<BackupListArgs>(
24
+ type ListHandlerOptions = StrictYargsOptionsToInterface<typeof ListOptions>;
25
+ export const ListHandler = withConfig<ListHandlerOptions>(
25
26
  async ({ config, name }): Promise<void> => {
26
- const accountId = await requireAuth({});
27
+ const accountId = await requireAuth(config);
27
28
  logger.log(d1BetaWarning);
28
29
  const db: Database = await getDatabaseByNameOrBinding(
29
30
  config,
@@ -32,11 +33,13 @@ export const ListHandler = withConfig<BackupListArgs>(
32
33
  );
33
34
 
34
35
  const backups: Backup[] = await listBackups(accountId, db.uuid);
35
- render(
36
- <Table
37
- data={backups}
38
- columns={["created_at", "id", "num_tables", "size"]}
39
- ></Table>
36
+ logger.log(
37
+ renderToString(
38
+ <Table
39
+ data={backups}
40
+ columns={["created_at", "id", "num_tables", "size"]}
41
+ ></Table>
42
+ )
40
43
  );
41
44
  }
42
45
  );
@@ -77,15 +80,14 @@ export const listBackups = async (
77
80
  return Object.values(results);
78
81
  };
79
82
 
80
- type BackupCreateArgs = BackupListArgs;
81
-
82
- export function CreateOptions(yargs: Argv): Argv<BackupCreateArgs> {
83
+ export function CreateOptions(yargs: CommonYargsArgv) {
83
84
  return ListOptions(yargs);
84
85
  }
86
+ type CreateHandlerOptions = StrictYargsOptionsToInterface<typeof CreateOptions>;
85
87
 
86
- export const CreateHandler = withConfig<BackupCreateArgs>(
88
+ export const CreateHandler = withConfig<CreateHandlerOptions>(
87
89
  async ({ config, name }): Promise<void> => {
88
- const accountId = await requireAuth({});
90
+ const accountId = await requireAuth(config);
89
91
  logger.log(d1BetaWarning);
90
92
  const db: Database = await getDatabaseByNameOrBinding(
91
93
  config,
@@ -94,11 +96,13 @@ export const CreateHandler = withConfig<BackupCreateArgs>(
94
96
  );
95
97
 
96
98
  const backup: Backup = await createBackup(accountId, db.uuid);
97
- render(
98
- <Table
99
- data={[backup]}
100
- columns={["created_at", "id", "num_tables", "size", "state"]}
101
- ></Table>
99
+ logger.log(
100
+ renderToString(
101
+ <Table
102
+ data={[backup]}
103
+ columns={["created_at", "id", "num_tables", "size", "state"]}
104
+ ></Table>
105
+ )
102
106
  );
103
107
  }
104
108
  );
@@ -119,21 +123,19 @@ export const createBackup = async (
119
123
  };
120
124
  };
121
125
 
122
- type BackupRestoreArgs = BackupListArgs & {
123
- "backup-id": string;
124
- };
125
-
126
- export function RestoreOptions(yargs: Argv): Argv<BackupRestoreArgs> {
126
+ export function RestoreOptions(yargs: CommonYargsArgv) {
127
127
  return ListOptions(yargs).positional("backup-id", {
128
128
  describe: "The Backup ID to restore",
129
129
  type: "string",
130
130
  demandOption: true,
131
131
  });
132
132
  }
133
-
134
- export const RestoreHandler = withConfig<BackupRestoreArgs>(
133
+ type RestoreHandlerOptions = StrictYargsOptionsToInterface<
134
+ typeof RestoreOptions
135
+ >;
136
+ export const RestoreHandler = withConfig<RestoreHandlerOptions>(
135
137
  async ({ config, name, backupId }): Promise<void> => {
136
- const accountId = await requireAuth({});
138
+ const accountId = await requireAuth(config);
137
139
  logger.log(d1BetaWarning);
138
140
  const db: Database = await getDatabaseByNameOrBinding(
139
141
  config,
@@ -141,9 +143,9 @@ export const RestoreHandler = withConfig<BackupRestoreArgs>(
141
143
  name
142
144
  );
143
145
 
144
- console.log(`Restoring ${name} from backup ${backupId}....`);
146
+ logger.log(`Restoring ${name} from backup ${backupId}....`);
145
147
  await restoreBackup(accountId, db.uuid, backupId);
146
- console.log(`Done!`);
148
+ logger.log(`Done!`);
147
149
  }
148
150
  );
149
151
 
@@ -163,11 +165,7 @@ export const restoreBackup = async (
163
165
  );
164
166
  };
165
167
 
166
- type BackupDownloadArgs = BackupRestoreArgs & {
167
- output?: string;
168
- };
169
-
170
- export function DownloadOptions(yargs: Argv): Argv<BackupDownloadArgs> {
168
+ export function DownloadOptions(yargs: CommonYargsArgv) {
171
169
  return ListOptions(yargs)
172
170
  .positional("backup-id", {
173
171
  describe: "The Backup ID to download",
@@ -180,10 +178,12 @@ export function DownloadOptions(yargs: Argv): Argv<BackupDownloadArgs> {
180
178
  type: "string",
181
179
  });
182
180
  }
183
-
184
- export const DownloadHandler = withConfig<BackupDownloadArgs>(
181
+ type DownloadHandlerOptions = StrictYargsOptionsToInterface<
182
+ typeof DownloadOptions
183
+ >;
184
+ export const DownloadHandler = withConfig<DownloadHandlerOptions>(
185
185
  async ({ name, backupId, output, config }): Promise<void> => {
186
- const accountId = await requireAuth({});
186
+ const accountId = await requireAuth(config);
187
187
  logger.log(d1BetaWarning);
188
188
  const db: Database = await getDatabaseByNameOrBinding(
189
189
  config,
@@ -191,14 +191,15 @@ export const DownloadHandler = withConfig<BackupDownloadArgs>(
191
191
  name
192
192
  );
193
193
  const filename =
194
- output ||
195
- path.join(
196
- process.env.INIT_CWD as string,
197
- `${name}.${backupId.slice(0, 8)}.sqlite3`
198
- );
194
+ output || path.resolve(`${name}.${backupId.slice(0, 8)}.sqlite3`);
199
195
 
200
196
  logger.log(`🌀 Downloading backup ${backupId} from '${name}'`);
201
197
  const response = await getBackupResponse(accountId, db.uuid, backupId);
198
+ if (!response.ok) {
199
+ throw new Error(
200
+ `Failed to download backup ${backupId} from '${name}' - got ${response.status} from the API`
201
+ );
202
+ }
202
203
  logger.log(`🌀 Saving to ${filename}`);
203
204
  // TODO: stream this once we upgrade to Node18 and can use Writable.fromWeb
204
205
  const buffer = await response.arrayBuffer();
@@ -0,0 +1,5 @@
1
+ export const DEFAULT_MIGRATION_PATH = "./migrations";
2
+ export const DEFAULT_MIGRATION_TABLE = "d1_migrations";
3
+ export const LOCATION_CHOICES = ["weur", "eeur", "apac", "wnam", "enam"];
4
+ // Max number of statements to send in a single /execute call
5
+ export const DEFAULT_BATCH_SIZE = 10_000;
package/src/d1/create.tsx CHANGED
@@ -1,54 +1,102 @@
1
- import { render, Text, Box } from "ink";
1
+ import { Box, Text } from "ink";
2
2
  import React from "react";
3
3
  import { fetchResult } from "../cfetch";
4
+ import { withConfig } from "../config";
4
5
  import { logger } from "../logger";
5
6
  import { requireAuth } from "../user";
7
+ import { renderToString } from "../utils/render";
8
+ import { LOCATION_CHOICES } from "./constants";
6
9
  import { d1BetaWarning } from "./utils";
7
- import type { Database } from "./types";
8
- import type { ArgumentsCamelCase, Argv } from "yargs";
10
+ import type {
11
+ CommonYargsArgv,
12
+ StrictYargsOptionsToInterface,
13
+ } from "../yargs-types";
14
+ import type { DatabaseCreationResult } from "./types";
9
15
 
10
- type CreateArgs = { name: string };
11
-
12
- export function Options(yargs: Argv): Argv<CreateArgs> {
16
+ export function Options(yargs: CommonYargsArgv) {
13
17
  return yargs
14
18
  .positional("name", {
15
19
  describe: "The name of the new DB",
16
20
  type: "string",
17
21
  demandOption: true,
18
22
  })
23
+ .option("location", {
24
+ describe:
25
+ "A hint for the primary location of the new DB. Options:\nweur: Western Europe\neeur: Eastern Europe\napac: Asia Pacific\nwnam: Western North America\nenam: Eastern North America \n",
26
+ type: "string",
27
+ })
28
+ .option("experimental-backend", {
29
+ default: false,
30
+ describe: "Use new experimental DB backend",
31
+ type: "boolean",
32
+ })
19
33
  .epilogue(d1BetaWarning);
20
34
  }
21
35
 
22
- export async function Handler({
23
- name,
24
- }: ArgumentsCamelCase<CreateArgs>): Promise<void> {
25
- const accountId = await requireAuth({});
26
- logger.log(d1BetaWarning);
36
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof Options>;
37
+ export const Handler = withConfig<HandlerOptions>(
38
+ async ({ name, config, location, experimentalBackend }): Promise<void> => {
39
+ const accountId = await requireAuth(config);
27
40
 
28
- const db: Database = await fetchResult(`/accounts/${accountId}/d1/database`, {
29
- method: "POST",
30
- headers: {
31
- "Content-Type": "application/json",
32
- },
33
- body: JSON.stringify({
34
- name,
35
- }),
36
- });
41
+ logger.log(d1BetaWarning);
37
42
 
38
- render(
39
- <Box flexDirection="column">
40
- <Text>✅ Successfully created DB &apos;{db.name}&apos;!</Text>
41
- <Text>&nbsp;</Text>
42
- <Text>
43
- Add the following to your wrangler.toml to connect to it from a Worker:
44
- </Text>
45
- <Text>&nbsp;</Text>
46
- <Text>[[ d1_databases ]]</Text>
47
- <Text>
48
- binding = &quot;DB&quot; # i.e. available in your Worker on env.DB
49
- </Text>
50
- <Text>database_name = &quot;{db.name}&quot;</Text>
51
- <Text>database_id = &quot;{db.uuid}&quot;</Text>
52
- </Box>
53
- );
54
- }
43
+ if (!experimentalBackend && location) {
44
+ if (LOCATION_CHOICES.indexOf(location.toLowerCase()) === -1) {
45
+ throw new Error(
46
+ `Location '${location}' invalid. Valid values are ${LOCATION_CHOICES.join(
47
+ ","
48
+ )}`
49
+ );
50
+ }
51
+ }
52
+
53
+ let db: DatabaseCreationResult;
54
+ try {
55
+ db = await fetchResult(`/accounts/${accountId}/d1/database`, {
56
+ method: "POST",
57
+ headers: {
58
+ "Content-Type": "application/json",
59
+ },
60
+ body: JSON.stringify({
61
+ name,
62
+ ...(location && { primary_location_hint: location }),
63
+ ...(experimentalBackend && { experimental: true }),
64
+ }),
65
+ });
66
+ } catch (e) {
67
+ if ((e as { code: number }).code === 7502) {
68
+ throw new Error("A database with that name already exists");
69
+ }
70
+ throw e;
71
+ }
72
+
73
+ logger.log(
74
+ renderToString(
75
+ <Box flexDirection="column">
76
+ <Text>
77
+ ✅ Successfully created DB &apos;{db.name}&apos;
78
+ {db.created_in_region
79
+ ? ` in region ${db.created_in_region}`
80
+ : location
81
+ ? ` using primary location hint ${location}`
82
+ : ``}
83
+ </Text>
84
+ {experimentalBackend && (
85
+ <Text>
86
+ Created your database using D1&apos;s new storage backend. The new
87
+ storage backend is not yet recommended for production workloads
88
+ and does not yet support backups.
89
+ </Text>
90
+ )}
91
+ <Text>&nbsp;</Text>
92
+ <Text>[[d1_databases]]</Text>
93
+ <Text>
94
+ binding = &quot;DB&quot; # i.e. available in your Worker on env.DB
95
+ </Text>
96
+ <Text>database_name = &quot;{db.name}&quot;</Text>
97
+ <Text>database_id = &quot;{db.uuid}&quot;</Text>
98
+ </Box>
99
+ )
100
+ );
101
+ }
102
+ );
@@ -5,16 +5,13 @@ import { logger } from "../logger";
5
5
  import { requireAuth } from "../user";
6
6
  import { Name } from "./options";
7
7
  import { d1BetaWarning, getDatabaseByNameOrBinding } from "./utils";
8
+ import type {
9
+ CommonYargsArgv,
10
+ StrictYargsOptionsToInterface,
11
+ } from "../yargs-types";
8
12
  import type { Database } from "./types";
9
- import type { Argv } from "yargs";
10
13
 
11
- type CreateArgs = {
12
- config?: string;
13
- name: string;
14
- "skip-confirmation": boolean;
15
- };
16
-
17
- export function Options(d1ListYargs: Argv): Argv<CreateArgs> {
14
+ export function Options(d1ListYargs: CommonYargsArgv) {
18
15
  return Name(d1ListYargs)
19
16
  .option("skip-confirmation", {
20
17
  describe: "Skip confirmation",
@@ -24,10 +21,10 @@ export function Options(d1ListYargs: Argv): Argv<CreateArgs> {
24
21
  })
25
22
  .epilogue(d1BetaWarning);
26
23
  }
27
-
28
- export const Handler = withConfig<CreateArgs>(
24
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof Options>;
25
+ export const Handler = withConfig<HandlerOptions>(
29
26
  async ({ name, skipConfirmation, config }): Promise<void> => {
30
- const accountId = await requireAuth({});
27
+ const accountId = await requireAuth(config);
31
28
  logger.log(d1BetaWarning);
32
29
 
33
30
  const db: Database = await getDatabaseByNameOrBinding(
@@ -36,21 +33,21 @@ export const Handler = withConfig<CreateArgs>(
36
33
  name
37
34
  );
38
35
 
39
- console.log(`About to delete DB '${name}' (${db.uuid}).`);
36
+ logger.log(`About to delete DB '${name}' (${db.uuid}).`);
40
37
  if (!skipConfirmation) {
41
38
  const response = await confirm(`Ok to proceed?`);
42
39
  if (!response) {
43
- console.log(`Not deleting.`);
40
+ logger.log(`Not deleting.`);
44
41
  return;
45
42
  }
46
43
  }
47
44
 
48
- console.log("Deleting...");
45
+ logger.log("Deleting...");
49
46
 
50
47
  await fetchResult(`/accounts/${accountId}/d1/database/${db.uuid}`, {
51
48
  method: "DELETE",
52
49
  });
53
50
 
54
- console.log(`Deleted '${name}' successfully.`);
51
+ logger.log(`Deleted '${name}' successfully.`);
55
52
  }
56
53
  );