wrangler 0.0.0-e178d6fb → 0.0.0-e1c2f5b9

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 (239) hide show
  1. package/README.md +16 -2
  2. package/bin/wrangler.js +31 -11
  3. package/miniflare-dist/index.mjs +1340 -330
  4. package/package.json +40 -13
  5. package/src/__tests__/access.test.ts +25 -0
  6. package/src/__tests__/api-dev.test.ts +238 -0
  7. package/src/__tests__/api-devregistry.test.js +64 -0
  8. package/src/__tests__/api.test.ts +80 -0
  9. package/src/__tests__/configuration.test.ts +683 -470
  10. package/src/__tests__/d1.test.ts +123 -0
  11. package/src/__tests__/delete.test.ts +263 -0
  12. package/src/__tests__/deployments.test.ts +105 -0
  13. package/src/__tests__/dev.test.tsx +453 -70
  14. package/src/__tests__/dialogs.test.tsx +40 -0
  15. package/src/__tests__/generate.test.ts +235 -0
  16. package/src/__tests__/get-host-from-url.test.ts +16 -0
  17. package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
  18. package/src/__tests__/helpers/mock-cfetch.ts +92 -26
  19. package/src/__tests__/helpers/mock-console.ts +11 -2
  20. package/src/__tests__/helpers/mock-dialogs.ts +1 -1
  21. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
  22. package/src/__tests__/helpers/mock-known-routes.ts +7 -0
  23. package/src/__tests__/helpers/mock-kv.ts +1 -1
  24. package/src/__tests__/helpers/mock-oauth-flow.ts +74 -53
  25. package/src/__tests__/helpers/mock-process.ts +8 -13
  26. package/src/__tests__/helpers/msw/handlers/access.ts +13 -0
  27. package/src/__tests__/helpers/msw/handlers/deployments.ts +59 -0
  28. package/src/__tests__/helpers/msw/handlers/namespaces.ts +104 -0
  29. package/src/__tests__/helpers/msw/handlers/oauth.ts +31 -0
  30. package/src/__tests__/helpers/msw/handlers/r2.ts +80 -0
  31. package/src/__tests__/helpers/msw/handlers/script.ts +75 -0
  32. package/src/__tests__/helpers/msw/handlers/user.ts +63 -0
  33. package/src/__tests__/helpers/msw/handlers/zones.ts +22 -0
  34. package/src/__tests__/helpers/msw/index.ts +21 -0
  35. package/src/__tests__/helpers/worker-scripts/child-wrangler.toml +1 -0
  36. package/src/__tests__/helpers/worker-scripts/hello-world-worker.js +5 -0
  37. package/src/__tests__/helpers/worker-scripts/hello-world-wrangler.toml +1 -0
  38. package/src/__tests__/helpers/worker-scripts/parent-worker.js +8 -0
  39. package/src/__tests__/helpers/worker-scripts/parent-wrangler.toml +5 -0
  40. package/src/__tests__/index.test.ts +103 -97
  41. package/src/__tests__/init.test.ts +1484 -382
  42. package/src/__tests__/jest.setup.ts +88 -5
  43. package/src/__tests__/kv.test.ts +655 -540
  44. package/src/__tests__/logout.test.ts +47 -0
  45. package/src/__tests__/metrics.test.ts +95 -45
  46. package/src/__tests__/middleware.scheduled.test.ts +145 -0
  47. package/src/__tests__/middleware.test.ts +750 -0
  48. package/src/__tests__/pages-deployment-tail.test.ts +884 -0
  49. package/src/__tests__/pages.test.ts +1301 -119
  50. package/src/__tests__/paths.test.ts +39 -0
  51. package/src/__tests__/publish.test.ts +2266 -1180
  52. package/src/__tests__/pubsub.test.ts +211 -88
  53. package/src/__tests__/queues.test.ts +522 -0
  54. package/src/__tests__/r2.test.ts +363 -203
  55. package/src/__tests__/secret.test.ts +261 -59
  56. package/src/__tests__/tail.test.ts +352 -151
  57. package/src/__tests__/test-old-node-version.js +3 -3
  58. package/src/__tests__/tsconfig-sanity.ts +12 -0
  59. package/src/__tests__/tsconfig.json +8 -0
  60. package/src/__tests__/tsconfig.tsbuildinfo +1 -0
  61. package/src/__tests__/type-generation.test.ts +233 -0
  62. package/src/__tests__/user.test.ts +59 -73
  63. package/src/__tests__/utils-collectKeyValues.test.ts +47 -0
  64. package/src/__tests__/validate-dev-props.test.ts +56 -0
  65. package/src/__tests__/whoami.test.tsx +114 -66
  66. package/src/__tests__/worker-namespace.test.ts +154 -155
  67. package/src/api/dev.ts +170 -38
  68. package/src/api/index.ts +1 -0
  69. package/src/bundle-reporter.tsx +41 -2
  70. package/src/bundle.ts +668 -81
  71. package/src/cfetch/index.ts +40 -3
  72. package/src/cfetch/internal.ts +144 -32
  73. package/src/cli.ts +4 -3
  74. package/src/config/config.ts +27 -3
  75. package/src/config/environment.ts +131 -7
  76. package/src/config/index.ts +128 -8
  77. package/src/config/validation-helpers.ts +19 -6
  78. package/src/config/validation.ts +411 -14
  79. package/src/config-cache.ts +3 -2
  80. package/src/create-worker-preview.ts +31 -6
  81. package/src/create-worker-upload-form.ts +84 -22
  82. package/src/d1/backups.tsx +223 -0
  83. package/src/d1/constants.ts +2 -0
  84. package/src/d1/create.tsx +63 -0
  85. package/src/d1/delete.tsx +56 -0
  86. package/src/d1/execute.tsx +352 -0
  87. package/src/d1/formatTimeAgo.ts +14 -0
  88. package/src/d1/index.ts +101 -0
  89. package/src/d1/list.tsx +48 -0
  90. package/src/d1/migrations/apply.tsx +196 -0
  91. package/src/d1/migrations/create.tsx +77 -0
  92. package/src/d1/migrations/helpers.ts +147 -0
  93. package/src/d1/migrations/index.tsx +3 -0
  94. package/src/d1/migrations/list.tsx +79 -0
  95. package/src/d1/migrations/options.ts +18 -0
  96. package/src/d1/options.ts +22 -0
  97. package/src/d1/types.tsx +24 -0
  98. package/src/d1/utils.ts +48 -0
  99. package/src/delete.ts +108 -0
  100. package/src/deployments.ts +83 -0
  101. package/src/deprecated/index.ts +145 -0
  102. package/src/dev/dev-vars.ts +11 -8
  103. package/src/dev/dev.tsx +220 -58
  104. package/src/dev/get-local-persistence-path.tsx +31 -0
  105. package/src/dev/local.tsx +740 -181
  106. package/src/dev/remote.tsx +340 -123
  107. package/src/dev/start-server.ts +543 -0
  108. package/src/dev/use-esbuild.ts +61 -7
  109. package/src/dev/validate-dev-props.ts +31 -0
  110. package/src/dev-registry.tsx +201 -0
  111. package/src/dev.tsx +614 -258
  112. package/src/dialogs.tsx +41 -8
  113. package/src/{worker-namespace.ts → dispatch-namespace.ts} +23 -22
  114. package/src/docs/index.ts +97 -0
  115. package/src/entry.ts +3 -2
  116. package/src/environment-variables/factory.ts +88 -0
  117. package/src/environment-variables/misc-variables.ts +30 -0
  118. package/src/generate/index.ts +300 -0
  119. package/src/git-client.ts +100 -7
  120. package/src/index.tsx +249 -1560
  121. package/src/init.ts +626 -150
  122. package/src/inspect.ts +137 -32
  123. package/src/{metrics/is-ci.ts → is-ci.ts} +0 -0
  124. package/src/is-interactive.ts +4 -0
  125. package/src/jest.d.ts +4 -0
  126. package/src/{kv.ts → kv/helpers.ts} +3 -3
  127. package/src/kv/index.ts +596 -0
  128. package/src/logger.ts +27 -8
  129. package/src/metrics/index.ts +1 -0
  130. package/src/metrics/metrics-config.ts +4 -4
  131. package/src/metrics/metrics-dispatcher.ts +1 -0
  132. package/src/metrics/metrics-usage-headers.ts +24 -0
  133. package/src/metrics/send-event.ts +13 -8
  134. package/src/miniflare-cli/assets.ts +172 -465
  135. package/src/miniflare-cli/index.ts +149 -24
  136. package/src/miniflare-cli/tsconfig.json +9 -0
  137. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
  138. package/src/miniflare-cli/types.ts +11 -0
  139. package/src/module-collection.ts +12 -3
  140. package/src/pages/build.tsx +108 -42
  141. package/src/pages/constants.ts +11 -0
  142. package/src/pages/deployment-tails.tsx +284 -0
  143. package/src/pages/deployments.tsx +9 -31
  144. package/src/pages/dev.tsx +417 -108
  145. package/src/pages/errors.ts +66 -0
  146. package/src/pages/functions/buildPlugin.ts +86 -84
  147. package/src/pages/functions/buildWorker.ts +121 -106
  148. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  149. package/src/pages/functions/routes-consolidation.ts +73 -0
  150. package/src/pages/functions/routes-transformation.test.ts +282 -0
  151. package/src/pages/functions/routes-transformation.ts +115 -0
  152. package/src/pages/functions/routes-validation.test.ts +403 -0
  153. package/src/pages/functions/routes-validation.ts +202 -0
  154. package/src/pages/functions/tsconfig.json +8 -0
  155. package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
  156. package/src/pages/functions.tsx +82 -0
  157. package/src/pages/hash.tsx +13 -0
  158. package/src/pages/index.tsx +73 -55
  159. package/src/pages/projects.tsx +9 -3
  160. package/src/pages/prompt-select-project.tsx +31 -0
  161. package/src/pages/publish.tsx +183 -60
  162. package/src/pages/types.ts +1 -0
  163. package/src/pages/upload.tsx +107 -56
  164. package/src/pages/utils.ts +13 -2
  165. package/src/paths.ts +49 -4
  166. package/src/proxy.ts +375 -157
  167. package/src/publish/index.ts +270 -0
  168. package/src/{publish.ts → publish/publish.ts} +431 -188
  169. package/src/pubsub/pubsub-commands.tsx +4 -3
  170. package/src/queues/cli/commands/consumer/add.ts +71 -0
  171. package/src/queues/cli/commands/consumer/index.ts +22 -0
  172. package/src/queues/cli/commands/consumer/remove.ts +38 -0
  173. package/src/queues/cli/commands/create.ts +25 -0
  174. package/src/queues/cli/commands/delete.ts +26 -0
  175. package/src/queues/cli/commands/index.ts +36 -0
  176. package/src/queues/cli/commands/list.ts +25 -0
  177. package/src/queues/client.ts +135 -0
  178. package/src/queues/utils.ts +18 -0
  179. package/src/r2/constants.ts +4 -0
  180. package/src/r2/helpers.ts +131 -0
  181. package/src/r2/index.ts +289 -0
  182. package/src/routes.ts +140 -0
  183. package/src/secret/index.ts +379 -0
  184. package/src/sites.tsx +3 -3
  185. package/src/tail/createTail.ts +379 -0
  186. package/src/tail/filters.ts +4 -6
  187. package/src/tail/index.ts +199 -284
  188. package/src/tail/printing.ts +43 -3
  189. package/src/tsconfig-sanity.ts +16 -0
  190. package/src/type-generation.ts +181 -0
  191. package/src/user/access.ts +68 -0
  192. package/src/user/auth-variables.ts +113 -0
  193. package/src/user/choose-account.tsx +1 -1
  194. package/src/user/index.ts +0 -1
  195. package/src/user/user.tsx +116 -49
  196. package/src/utils/collectKeyValues.ts +14 -0
  197. package/src/whoami.tsx +80 -2
  198. package/src/worker.ts +69 -9
  199. package/src/yargs-types.ts +24 -0
  200. package/src/zones.ts +124 -9
  201. package/templates/__tests__/pages-dev-util.test.ts +128 -0
  202. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  203. package/templates/__tests__/tsconfig.json +8 -0
  204. package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
  205. package/templates/d1-beta-facade.js +205 -0
  206. package/templates/facade.d.ts +14 -0
  207. package/templates/first-party-worker-module-facade.ts +19 -0
  208. package/templates/format-dev-errors.ts +33 -0
  209. package/templates/init-tests/test-jest-new-worker.js +23 -0
  210. package/templates/init-tests/test-vitest-new-worker.js +24 -0
  211. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  212. package/templates/middleware/common.ts +62 -0
  213. package/templates/middleware/loader-modules.ts +82 -0
  214. package/templates/middleware/loader-sw.ts +233 -0
  215. package/templates/middleware/middleware-miniflare3-json-error.ts +20 -0
  216. package/templates/middleware/middleware-pretty-error.ts +40 -0
  217. package/templates/middleware/middleware-scheduled.ts +15 -0
  218. package/templates/new-worker.js +1 -1
  219. package/templates/pages-dev-pipeline.ts +31 -0
  220. package/templates/pages-dev-util.ts +52 -0
  221. package/templates/pages-shim.ts +4 -1
  222. package/templates/pages-template-plugin.ts +21 -5
  223. package/templates/pages-template-worker.ts +37 -9
  224. package/templates/{static-asset-facade.js → serve-static-assets.ts} +23 -7
  225. package/templates/service-bindings-module-facade.js +54 -0
  226. package/templates/service-bindings-sw-facade.js +42 -0
  227. package/templates/tsconfig-sanity.ts +11 -0
  228. package/templates/tsconfig.init.json +106 -0
  229. package/templates/tsconfig.json +5 -102
  230. package/templates/tsconfig.tsbuildinfo +1 -0
  231. package/wrangler-dist/cli.d.ts +621 -42
  232. package/wrangler-dist/cli.js +144441 -102606
  233. package/src/environment-variables.ts +0 -35
  234. package/src/faye-websocket.d.ts +0 -6
  235. package/src/generate.ts +0 -33
  236. package/src/miniflare-cli/enum-keys.ts +0 -17
  237. package/src/preview.ts +0 -31
  238. package/src/r2.ts +0 -50
  239. package/src/user/env-vars.ts +0 -46
@@ -23,6 +23,34 @@ export function toMimeType(type: CfModuleType): string {
23
23
  }
24
24
  }
25
25
 
26
+ type WorkerMetadataBinding =
27
+ // If you add any new binding types here, also add it to safeBindings
28
+ // under validateUnsafeBinding in config/validation.ts
29
+ | { type: "plain_text"; name: string; text: string }
30
+ | { type: "json"; name: string; json: unknown }
31
+ | { type: "wasm_module"; name: string; part: string }
32
+ | { type: "text_blob"; name: string; part: string }
33
+ | { type: "data_blob"; name: string; part: string }
34
+ | { type: "kv_namespace"; name: string; namespace_id: string }
35
+ | {
36
+ type: "durable_object_namespace";
37
+ name: string;
38
+ class_name: string;
39
+ script_name?: string;
40
+ environment?: string;
41
+ }
42
+ | { type: "queue"; name: string; queue_name: string }
43
+ | { type: "r2_bucket"; name: string; bucket_name: string }
44
+ | { type: "d1"; name: string; id: string; internalEnv?: string }
45
+ | { type: "service"; name: string; service: string; environment?: string }
46
+ | { type: "analytics_engine"; name: string; dataset?: string }
47
+ | { type: "dispatch_namespace"; name: string; namespace: string }
48
+ | {
49
+ type: "logfwdr";
50
+ name: string;
51
+ destination: string;
52
+ };
53
+
26
54
  export interface WorkerMetadata {
27
55
  /** The name of the entry point module. Only exists when the worker is in the ES module format */
28
56
  main_module?: string;
@@ -32,26 +60,10 @@ export interface WorkerMetadata {
32
60
  compatibility_flags?: string[];
33
61
  usage_model?: "bundled" | "unbound";
34
62
  migrations?: CfDurableObjectMigrations;
35
- // If you add any new binding types here, also add it to safeBindings
36
- // under validateUnsafeBinding in config/validation.ts
37
- bindings: (
38
- | { type: "plain_text"; name: string; text: string }
39
- | { type: "json"; name: string; json: unknown }
40
- | { type: "wasm_module"; name: string; part: string }
41
- | { type: "text_blob"; name: string; part: string }
42
- | { type: "data_blob"; name: string; part: string }
43
- | { type: "kv_namespace"; name: string; namespace_id: string }
44
- | {
45
- type: "durable_object_namespace";
46
- name: string;
47
- class_name: string;
48
- script_name?: string;
49
- environment?: string;
50
- }
51
- | { type: "r2_bucket"; name: string; bucket_name: string }
52
- | { type: "service"; name: string; service: string; environment?: string }
53
- | { type: "namespace"; name: string; namespace: string }
54
- )[];
63
+ capnp_schema?: string;
64
+ bindings: WorkerMetadataBinding[];
65
+ keep_bindings?: WorkerMetadataBinding["type"][];
66
+ logpush?: boolean;
55
67
  }
56
68
 
57
69
  /**
@@ -66,6 +78,8 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
66
78
  usage_model,
67
79
  compatibility_date,
68
80
  compatibility_flags,
81
+ keepVars,
82
+ logpush,
69
83
  } = worker;
70
84
 
71
85
  let { modules } = worker;
@@ -100,6 +114,14 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
100
114
  }
101
115
  );
102
116
 
117
+ bindings.queues?.forEach(({ binding, queue_name }) => {
118
+ metadataBindings.push({
119
+ type: "queue",
120
+ name: binding,
121
+ queue_name,
122
+ });
123
+ });
124
+
103
125
  bindings.r2_buckets?.forEach(({ binding, bucket_name }) => {
104
126
  metadataBindings.push({
105
127
  name: binding,
@@ -108,6 +130,17 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
108
130
  });
109
131
  });
110
132
 
133
+ bindings.d1_databases?.forEach(
134
+ ({ binding, database_id, database_internal_env }) => {
135
+ metadataBindings.push({
136
+ name: binding,
137
+ type: "d1",
138
+ id: database_id,
139
+ internalEnv: database_internal_env,
140
+ });
141
+ }
142
+ );
143
+
111
144
  bindings.services?.forEach(({ binding, service, environment }) => {
112
145
  metadataBindings.push({
113
146
  name: binding,
@@ -117,14 +150,30 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
117
150
  });
118
151
  });
119
152
 
120
- bindings.worker_namespaces?.forEach(({ binding, namespace }) => {
153
+ bindings.analytics_engine_datasets?.forEach(({ binding, dataset }) => {
121
154
  metadataBindings.push({
122
155
  name: binding,
123
- type: "namespace",
156
+ type: "analytics_engine",
157
+ dataset,
158
+ });
159
+ });
160
+
161
+ bindings.dispatch_namespaces?.forEach(({ binding, namespace }) => {
162
+ metadataBindings.push({
163
+ name: binding,
164
+ type: "dispatch_namespace",
124
165
  namespace,
125
166
  });
126
167
  });
127
168
 
169
+ bindings.logfwdr?.bindings.forEach(({ name, destination }) => {
170
+ metadataBindings.push({
171
+ name: name,
172
+ type: "logfwdr",
173
+ destination,
174
+ });
175
+ });
176
+
128
177
  for (const [name, filePath] of Object.entries(bindings.wasm_modules || {})) {
129
178
  metadataBindings.push({
130
179
  name,
@@ -240,6 +289,9 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
240
289
  ...(compatibility_flags && { compatibility_flags }),
241
290
  ...(usage_model && { usage_model }),
242
291
  ...(migrations && { migrations }),
292
+ capnp_schema: bindings.logfwdr?.schema,
293
+ ...(keepVars && { keep_bindings: ["plain_text", "json"] }),
294
+ ...(logpush !== undefined && { logpush }),
243
295
  };
244
296
 
245
297
  formData.set("metadata", JSON.stringify(metadata));
@@ -259,5 +311,15 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
259
311
  );
260
312
  }
261
313
 
314
+ if (bindings.logfwdr && bindings.logfwdr.schema) {
315
+ const filePath = bindings.logfwdr.schema;
316
+ formData.set(
317
+ filePath,
318
+ new File([readFileSync(filePath)], filePath, {
319
+ type: "application/octet-stream",
320
+ })
321
+ );
322
+ }
323
+
262
324
  return formData;
263
325
  }
@@ -0,0 +1,223 @@
1
+ import fs from "node:fs/promises";
2
+ import * as path from "path";
3
+ import { render } from "ink";
4
+ import Table from "ink-table";
5
+ import React from "react";
6
+ import { fetchResult } from "../cfetch";
7
+ import { performApiFetch } from "../cfetch/internal";
8
+ import { withConfig } from "../config";
9
+ import { logger } from "../logger";
10
+ import { requireAuth } from "../user";
11
+ import { formatBytes, formatTimeAgo } from "./formatTimeAgo";
12
+ import { Name } from "./options";
13
+ import { d1BetaWarning, getDatabaseByNameOrBinding } from "./utils";
14
+ import type { Backup, Database } from "./types";
15
+ import type { Response } from "undici";
16
+ import type { Argv } from "yargs";
17
+
18
+ type BackupListArgs = { config?: string; name: string };
19
+
20
+ export function ListOptions(yargs: Argv): Argv<BackupListArgs> {
21
+ return Name(yargs);
22
+ }
23
+
24
+ export const ListHandler = withConfig<BackupListArgs>(
25
+ async ({ config, name }): Promise<void> => {
26
+ const accountId = await requireAuth({});
27
+ logger.log(d1BetaWarning);
28
+ const db: Database = await getDatabaseByNameOrBinding(
29
+ config,
30
+ accountId,
31
+ name
32
+ );
33
+
34
+ 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>
40
+ );
41
+ }
42
+ );
43
+
44
+ export const listBackups = async (
45
+ accountId: string,
46
+ uuid: string
47
+ ): Promise<Array<Backup>> => {
48
+ const json: Backup[] = await fetchResult(
49
+ `/accounts/${accountId}/d1/database/${uuid}/backup`,
50
+ {}
51
+ );
52
+ const results: Record<string, Backup> = {};
53
+
54
+ json
55
+ // First, convert created_at to a Date
56
+ .map((backup) => ({
57
+ ...backup,
58
+ created_at: new Date(backup.created_at),
59
+ }))
60
+ // Then, sort descending based on created_at
61
+ .sort((a, b) => +b.created_at - +a.created_at)
62
+ // then group_by their human-readable timestamp i.e. "2 days ago"
63
+ // (storing only the first of each group)
64
+ // and replace the Date version with this new human-readable one
65
+ .forEach((backup) => {
66
+ const timeAgo = formatTimeAgo(backup.created_at);
67
+ if (!results[timeAgo]) {
68
+ results[timeAgo] = {
69
+ ...backup,
70
+ created_at: timeAgo,
71
+ size: formatBytes(backup.file_size),
72
+ };
73
+ }
74
+ });
75
+
76
+ // Take advantage of JS objects' sorting to return the newest backup of a certain age
77
+ return Object.values(results);
78
+ };
79
+
80
+ type BackupCreateArgs = BackupListArgs;
81
+
82
+ export function CreateOptions(yargs: Argv): Argv<BackupCreateArgs> {
83
+ return ListOptions(yargs);
84
+ }
85
+
86
+ export const CreateHandler = withConfig<BackupCreateArgs>(
87
+ async ({ config, name }): Promise<void> => {
88
+ const accountId = await requireAuth({});
89
+ logger.log(d1BetaWarning);
90
+ const db: Database = await getDatabaseByNameOrBinding(
91
+ config,
92
+ accountId,
93
+ name
94
+ );
95
+
96
+ 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>
102
+ );
103
+ }
104
+ );
105
+
106
+ export const createBackup = async (
107
+ accountId: string,
108
+ uuid: string
109
+ ): Promise<Backup> => {
110
+ const backup: Backup = await fetchResult(
111
+ `/accounts/${accountId}/d1/database/${uuid}/backup`,
112
+ {
113
+ method: "POST",
114
+ }
115
+ );
116
+ return {
117
+ ...backup,
118
+ size: formatBytes(backup.file_size),
119
+ };
120
+ };
121
+
122
+ type BackupRestoreArgs = BackupListArgs & {
123
+ "backup-id": string;
124
+ };
125
+
126
+ export function RestoreOptions(yargs: Argv): Argv<BackupRestoreArgs> {
127
+ return ListOptions(yargs).positional("backup-id", {
128
+ describe: "The Backup ID to restore",
129
+ type: "string",
130
+ demandOption: true,
131
+ });
132
+ }
133
+
134
+ export const RestoreHandler = withConfig<BackupRestoreArgs>(
135
+ async ({ config, name, backupId }): Promise<void> => {
136
+ const accountId = await requireAuth({});
137
+ logger.log(d1BetaWarning);
138
+ const db: Database = await getDatabaseByNameOrBinding(
139
+ config,
140
+ accountId,
141
+ name
142
+ );
143
+
144
+ logger.log(`Restoring ${name} from backup ${backupId}....`);
145
+ await restoreBackup(accountId, db.uuid, backupId);
146
+ logger.log(`Done!`);
147
+ }
148
+ );
149
+
150
+ export const restoreBackup = async (
151
+ accountId: string,
152
+ uuid: string,
153
+ backupId: string
154
+ ): Promise<void> => {
155
+ await fetchResult(
156
+ `/accounts/${accountId}/d1/database/${uuid}/backup/${backupId}/restore`,
157
+ {
158
+ method: "POST",
159
+ headers: {
160
+ "Content-Type": "application/json",
161
+ },
162
+ }
163
+ );
164
+ };
165
+
166
+ type BackupDownloadArgs = BackupRestoreArgs & {
167
+ output?: string;
168
+ };
169
+
170
+ export function DownloadOptions(yargs: Argv): Argv<BackupDownloadArgs> {
171
+ return ListOptions(yargs)
172
+ .positional("backup-id", {
173
+ describe: "The Backup ID to download",
174
+ type: "string",
175
+ demandOption: true,
176
+ })
177
+ .option("output", {
178
+ describe:
179
+ "The .sqlite3 file to write to (defaults to '<db-name>.<short-backup-id>.sqlite3'",
180
+ type: "string",
181
+ });
182
+ }
183
+
184
+ export const DownloadHandler = withConfig<BackupDownloadArgs>(
185
+ async ({ name, backupId, output, config }): Promise<void> => {
186
+ const accountId = await requireAuth({});
187
+ logger.log(d1BetaWarning);
188
+ const db: Database = await getDatabaseByNameOrBinding(
189
+ config,
190
+ accountId,
191
+ name
192
+ );
193
+ const filename =
194
+ output ||
195
+ path.join(
196
+ process.env.INIT_CWD as string,
197
+ `${name}.${backupId.slice(0, 8)}.sqlite3`
198
+ );
199
+
200
+ logger.log(`🌀 Downloading backup ${backupId} from '${name}'`);
201
+ const response = await getBackupResponse(accountId, db.uuid, backupId);
202
+ if (!response.ok) {
203
+ throw new Error(
204
+ `Failed to download backup ${backupId} from '${name}' - got ${response.status} from the API`
205
+ );
206
+ }
207
+ logger.log(`🌀 Saving to ${filename}`);
208
+ // TODO: stream this once we upgrade to Node18 and can use Writable.fromWeb
209
+ const buffer = await response.arrayBuffer();
210
+ await fs.writeFile(filename, new Buffer(buffer));
211
+ logger.log(`🌀 Done!`);
212
+ }
213
+ );
214
+
215
+ export const getBackupResponse = async (
216
+ accountId: string,
217
+ uuid: string,
218
+ backupId: string
219
+ ): Promise<Response> => {
220
+ return await performApiFetch(
221
+ `/accounts/${accountId}/d1/database/${uuid}/backup/${backupId}/download`
222
+ );
223
+ };
@@ -0,0 +1,2 @@
1
+ export const DEFAULT_MIGRATION_PATH = "./migrations";
2
+ export const DEFAULT_MIGRATION_TABLE = "d1_migrations";
@@ -0,0 +1,63 @@
1
+ import { render, Text, Box } from "ink";
2
+ import React from "react";
3
+ import { fetchResult } from "../cfetch";
4
+ import { logger } from "../logger";
5
+ import { requireAuth } from "../user";
6
+ import { d1BetaWarning } from "./utils";
7
+ import type { Database } from "./types";
8
+ import type { ArgumentsCamelCase, Argv } from "yargs";
9
+
10
+ type CreateArgs = { name: string };
11
+
12
+ export function Options(yargs: Argv): Argv<CreateArgs> {
13
+ return yargs
14
+ .positional("name", {
15
+ describe: "The name of the new DB",
16
+ type: "string",
17
+ demandOption: true,
18
+ })
19
+ .epilogue(d1BetaWarning);
20
+ }
21
+
22
+ export async function Handler({
23
+ name,
24
+ }: ArgumentsCamelCase<CreateArgs>): Promise<void> {
25
+ const accountId = await requireAuth({});
26
+
27
+ logger.log(d1BetaWarning);
28
+
29
+ let db: Database;
30
+ try {
31
+ db = await fetchResult(`/accounts/${accountId}/d1/database`, {
32
+ method: "POST",
33
+ headers: {
34
+ "Content-Type": "application/json",
35
+ },
36
+ body: JSON.stringify({
37
+ name,
38
+ }),
39
+ });
40
+ } catch (e) {
41
+ if ((e as { code: number }).code === 7502) {
42
+ throw new Error("A database with that name already exists");
43
+ }
44
+ throw e;
45
+ }
46
+
47
+ render(
48
+ <Box flexDirection="column">
49
+ <Text>✅ Successfully created DB &apos;{db.name}&apos;!</Text>
50
+ <Text>&nbsp;</Text>
51
+ <Text>
52
+ Add the following to your wrangler.toml to connect to it from a Worker:
53
+ </Text>
54
+ <Text>&nbsp;</Text>
55
+ <Text>[[ d1_databases ]]</Text>
56
+ <Text>
57
+ binding = &quot;DB&quot; # i.e. available in your Worker on env.DB
58
+ </Text>
59
+ <Text>database_name = &quot;{db.name}&quot;</Text>
60
+ <Text>database_id = &quot;{db.uuid}&quot;</Text>
61
+ </Box>
62
+ );
63
+ }
@@ -0,0 +1,56 @@
1
+ import { fetchResult } from "../cfetch";
2
+ import { withConfig } from "../config";
3
+ import { confirm } from "../dialogs";
4
+ import { logger } from "../logger";
5
+ import { requireAuth } from "../user";
6
+ import { Name } from "./options";
7
+ import { d1BetaWarning, getDatabaseByNameOrBinding } from "./utils";
8
+ import type { Database } from "./types";
9
+ import type { Argv } from "yargs";
10
+
11
+ type CreateArgs = {
12
+ config?: string;
13
+ name: string;
14
+ "skip-confirmation": boolean;
15
+ };
16
+
17
+ export function Options(d1ListYargs: Argv): Argv<CreateArgs> {
18
+ return Name(d1ListYargs)
19
+ .option("skip-confirmation", {
20
+ describe: "Skip confirmation",
21
+ type: "boolean",
22
+ alias: "y",
23
+ default: false,
24
+ })
25
+ .epilogue(d1BetaWarning);
26
+ }
27
+
28
+ export const Handler = withConfig<CreateArgs>(
29
+ async ({ name, skipConfirmation, config }): Promise<void> => {
30
+ const accountId = await requireAuth({});
31
+ logger.log(d1BetaWarning);
32
+
33
+ const db: Database = await getDatabaseByNameOrBinding(
34
+ config,
35
+ accountId,
36
+ name
37
+ );
38
+
39
+ logger.log(`About to delete DB '${name}' (${db.uuid}).`);
40
+ if (!skipConfirmation) {
41
+ const response = await confirm(`Ok to proceed?`);
42
+ if (!response) {
43
+ logger.log(`Not deleting.`);
44
+ return;
45
+ }
46
+ }
47
+
48
+ logger.log("Deleting...");
49
+
50
+ await fetchResult(`/accounts/${accountId}/d1/database/${db.uuid}`, {
51
+ method: "DELETE",
52
+ });
53
+
54
+ logger.log(`Deleted '${name}' successfully.`);
55
+ }
56
+ );