wrangler 0.0.0-e6c9c5c0 → 0.0.0-e6e1daba

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 (126) hide show
  1. package/README.md +3 -3
  2. package/miniflare-dist/index.mjs +22 -18
  3. package/package.json +12 -12
  4. package/src/__tests__/configuration.test.ts +70 -0
  5. package/src/__tests__/d1/d1.test.ts +13 -58
  6. package/src/__tests__/d1/execute.test.ts +64 -0
  7. package/src/__tests__/d1/migrate.test.ts +155 -0
  8. package/src/__tests__/deployments.test.ts +40 -16
  9. package/src/__tests__/dev.test.tsx +8 -7
  10. package/src/__tests__/generate.test.ts +1 -1
  11. package/src/__tests__/guess-worker-format.test.ts +35 -0
  12. package/src/__tests__/helpers/end-event-loop.ts +6 -0
  13. package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
  14. package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
  15. package/src/__tests__/helpers/msw/handlers/deployments.ts +40 -16
  16. package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
  17. package/src/__tests__/index.test.ts +38 -32
  18. package/src/__tests__/init.test.ts +1 -1
  19. package/src/__tests__/kv.test.ts +63 -52
  20. package/src/__tests__/middleware.test.ts +65 -0
  21. package/src/__tests__/mtls-certificates.test.ts +585 -0
  22. package/src/__tests__/pages/deployment-list.test.ts +78 -0
  23. package/src/__tests__/pages/functions-build.test.ts +402 -0
  24. package/src/__tests__/pages/pages.test.ts +81 -0
  25. package/src/__tests__/pages/project-create.test.ts +63 -0
  26. package/src/__tests__/pages/project-list.test.ts +108 -0
  27. package/src/__tests__/pages/project-upload.test.ts +481 -0
  28. package/src/__tests__/pages/publish.test.ts +2745 -0
  29. package/src/__tests__/parse.test.ts +106 -0
  30. package/src/__tests__/publish.test.ts +80 -30
  31. package/src/__tests__/pubsub.test.ts +15 -12
  32. package/src/__tests__/queues.test.ts +37 -30
  33. package/src/__tests__/r2.test.ts +25 -20
  34. package/src/__tests__/secret.test.ts +4 -4
  35. package/src/__tests__/tsconfig.tsbuildinfo +1 -1
  36. package/src/__tests__/user.test.ts +1 -1
  37. package/src/__tests__/whoami.test.tsx +1 -1
  38. package/src/__tests__/worker-namespace.test.ts +26 -21
  39. package/src/api/dev.ts +80 -11
  40. package/src/api/index.ts +8 -0
  41. package/src/api/mtls-certificate.ts +148 -0
  42. package/src/api/pages/create-worker-bundle-contents.ts +75 -0
  43. package/src/api/pages/publish.tsx +59 -12
  44. package/src/bundle.ts +9 -7
  45. package/src/config/config.ts +14 -7
  46. package/src/config/environment.ts +9 -2
  47. package/src/config/index.ts +37 -20
  48. package/src/config/validation.ts +50 -3
  49. package/src/create-worker-preview.ts +19 -8
  50. package/src/create-worker-upload-form.ts +9 -0
  51. package/src/d1/backups.tsx +20 -24
  52. package/src/d1/create.tsx +6 -5
  53. package/src/d1/delete.ts +7 -10
  54. package/src/d1/execute.tsx +174 -143
  55. package/src/d1/index.ts +5 -6
  56. package/src/d1/list.tsx +21 -9
  57. package/src/d1/migrations/apply.tsx +42 -33
  58. package/src/d1/migrations/create.tsx +16 -17
  59. package/src/d1/migrations/helpers.ts +63 -38
  60. package/src/d1/migrations/list.tsx +37 -24
  61. package/src/d1/migrations/options.ts +7 -2
  62. package/src/d1/options.ts +3 -3
  63. package/src/d1/types.ts +1 -0
  64. package/src/d1/utils.ts +2 -1
  65. package/src/delete.ts +5 -8
  66. package/src/deployments.ts +62 -39
  67. package/src/deprecated/index.ts +7 -8
  68. package/src/dev/dev.tsx +1 -15
  69. package/src/dev/local.tsx +5 -6
  70. package/src/dev/remote.tsx +2 -2
  71. package/src/dev.tsx +51 -86
  72. package/src/dispatch-namespace.ts +20 -16
  73. package/src/docs/index.ts +7 -8
  74. package/src/entry.ts +1 -2
  75. package/src/generate/index.ts +6 -8
  76. package/src/index.ts +37 -26
  77. package/src/init.ts +5 -7
  78. package/src/inspect.ts +16 -1
  79. package/src/kv/index.ts +15 -17
  80. package/src/miniflare-cli/assets.ts +9 -8
  81. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -1
  82. package/src/mtls-certificate/cli.ts +155 -0
  83. package/src/pages/build.ts +109 -27
  84. package/src/pages/buildFunctions.ts +32 -31
  85. package/src/pages/deployment-tails.ts +7 -10
  86. package/src/pages/deployments.tsx +6 -4
  87. package/src/pages/dev.ts +19 -19
  88. package/src/pages/functions/tsconfig.tsbuildinfo +1 -1
  89. package/src/pages/functions.ts +8 -4
  90. package/src/pages/index.ts +3 -3
  91. package/src/pages/projects.tsx +7 -12
  92. package/src/pages/publish.tsx +18 -5
  93. package/src/pages/types.ts +5 -0
  94. package/src/pages/upload.tsx +6 -4
  95. package/src/pages/utils.ts +1 -1
  96. package/src/parse.ts +23 -1
  97. package/src/publish/index.ts +19 -15
  98. package/src/publish/publish.ts +5 -4
  99. package/src/pubsub/pubsub-commands.ts +18 -19
  100. package/src/queues/cli/commands/consumer/add.ts +18 -24
  101. package/src/queues/cli/commands/consumer/index.ts +3 -6
  102. package/src/queues/cli/commands/consumer/remove.ts +11 -18
  103. package/src/queues/cli/commands/create.ts +8 -8
  104. package/src/queues/cli/commands/delete.ts +8 -8
  105. package/src/queues/cli/commands/index.ts +3 -4
  106. package/src/queues/cli/commands/list.ts +8 -8
  107. package/src/r2/helpers.ts +1 -0
  108. package/src/r2/index.ts +28 -28
  109. package/src/secret/index.ts +10 -14
  110. package/src/sites.ts +1 -1
  111. package/src/tail/filters.ts +1 -1
  112. package/src/tail/index.ts +6 -8
  113. package/src/user/user.ts +4 -3
  114. package/src/worker.ts +6 -0
  115. package/src/yargs-types.ts +18 -5
  116. package/templates/checked-fetch.js +9 -1
  117. package/templates/format-dev-errors.ts +1 -0
  118. package/templates/new-worker.ts +3 -0
  119. package/templates/pages-template-plugin.ts +7 -3
  120. package/templates/serve-static-assets.ts +1 -0
  121. package/templates/service-bindings-module-facade.js +1 -0
  122. package/templates/tsconfig.init.json +1 -1
  123. package/templates/tsconfig.tsbuildinfo +1 -1
  124. package/wrangler-dist/cli.d.ts +596 -3
  125. package/wrangler-dist/cli.js +14276 -6748
  126. package/src/__tests__/pages.test.ts +0 -2898
@@ -7,7 +7,7 @@ import Table from "ink-table";
7
7
  import { npxImport } from "npx-import";
8
8
  import React from "react";
9
9
  import { fetchResult } from "../cfetch";
10
- import { withConfig } from "../config";
10
+ import { readConfig } from "../config";
11
11
  import { getLocalPersistencePath } from "../dev/get-local-persistence-path";
12
12
  import { confirm } from "../dialogs";
13
13
  import { logger } from "../logger";
@@ -22,32 +22,11 @@ import {
22
22
  getDatabaseInfoFromConfig,
23
23
  } from "./utils";
24
24
  import type { Config, ConfigFields, DevConfig, Environment } from "../config";
25
+ import type {
26
+ CommonYargsArgv,
27
+ StrictYargsOptionsToInterface,
28
+ } from "../yargs-types";
25
29
  import type { Database } from "./types";
26
- import type { Statement as StatementType } from "@miniflare/d1";
27
- import type { createSQLiteDB as createSQLiteDBType } from "@miniflare/shared";
28
- import type { Argv } from "yargs";
29
-
30
- type MiniflareNpxImportTypes = [
31
- {
32
- Statement: typeof StatementType;
33
- },
34
- {
35
- createSQLiteDB: typeof createSQLiteDBType;
36
- }
37
- ];
38
-
39
- export type BaseSqlExecuteArgs = {
40
- config?: string;
41
- database: string;
42
- local?: boolean;
43
- "persist-to"?: string;
44
- yes?: boolean;
45
- };
46
-
47
- type ExecuteArgs = BaseSqlExecuteArgs & {
48
- file?: string;
49
- command?: string;
50
- };
51
30
 
52
31
  export type QueryResult = {
53
32
  results: Record<string, string | number | boolean>[];
@@ -60,7 +39,7 @@ export type QueryResult = {
60
39
  // Max number of bytes to send in a single /execute call
61
40
  const QUERY_LIMIT = 10_000;
62
41
 
63
- export function Options(yargs: Argv): Argv<ExecuteArgs> {
42
+ export function Options(yargs: CommonYargsArgv) {
64
43
  return options
65
44
  .Database(yargs)
66
45
  .option("yes", {
@@ -74,7 +53,7 @@ export function Options(yargs: Argv): Argv<ExecuteArgs> {
74
53
  type: "boolean",
75
54
  })
76
55
  .option("file", {
77
- describe: "A .sql file to injest",
56
+ describe: "A .sql file to ingest",
78
57
  type: "string",
79
58
  })
80
59
  .option("command", {
@@ -85,30 +64,106 @@ export function Options(yargs: Argv): Argv<ExecuteArgs> {
85
64
  describe: "Specify directory to use for local persistence (for --local)",
86
65
  type: "string",
87
66
  requiresArg: true,
67
+ })
68
+ .option("json", {
69
+ describe: "Return output as clean JSON",
70
+ type: "boolean",
71
+ default: false,
72
+ })
73
+ .option("preview", {
74
+ describe: "Execute commands/files against a preview D1 DB",
75
+ type: "boolean",
76
+ default: false,
88
77
  });
89
78
  }
90
79
 
91
- function shorten(query: string | undefined, length: number) {
92
- return query && query.length > length
93
- ? query.slice(0, length) + "..."
94
- : query;
95
- }
80
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof Options>;
96
81
 
97
- export async function executeSql(
98
- local: undefined | boolean,
99
- config: ConfigFields<DevConfig> & Environment,
100
- name: string,
101
- shouldPrompt: boolean | undefined,
102
- persistTo: undefined | string,
103
- file?: string,
104
- command?: string
105
- ) {
106
- const sql = file ? readFileSync(file) : command;
82
+ export const Handler = async (args: HandlerOptions): Promise<void> => {
83
+ const { local, database, yes, persistTo, file, command, json, preview } =
84
+ args;
85
+ const existingLogLevel = logger.loggerLevel;
86
+ if (json) {
87
+ // set loggerLevel to error to avoid readConfig warnings appearing in JSON output
88
+ logger.loggerLevel = "error";
89
+ }
90
+ const config = readConfig(args.config, args);
91
+ logger.log(d1BetaWarning);
92
+ if (file && command)
93
+ return logger.error(`Error: can't provide both --command and --file.`);
107
94
 
95
+ const isInteractive = process.stdout.isTTY;
96
+ const response: QueryResult[] | null = await executeSql({
97
+ local,
98
+ config,
99
+ name: database,
100
+ shouldPrompt: isInteractive && !yes,
101
+ persistTo,
102
+ file,
103
+ command,
104
+ json,
105
+ preview,
106
+ });
107
+
108
+ // Early exit if prompt rejected
109
+ if (!response) return;
110
+
111
+ if (isInteractive && !json) {
112
+ // Render table if single result
113
+ render(
114
+ <Static items={response}>
115
+ {(result) => {
116
+ // batch results
117
+ if (!Array.isArray(result)) {
118
+ const { results, query } = result;
119
+
120
+ if (Array.isArray(results) && results.length > 0) {
121
+ const shortQuery = shorten(query, 48);
122
+ return (
123
+ <>
124
+ {shortQuery ? <Text dimColor>{shortQuery}</Text> : null}
125
+ <Table data={results}></Table>
126
+ </>
127
+ );
128
+ }
129
+ }
130
+ }}
131
+ </Static>
132
+ );
133
+ } else {
134
+ // set loggerLevel back to what it was before to actually output the JSON in stdout
135
+ logger.loggerLevel = existingLogLevel;
136
+ logger.log(JSON.stringify(response, null, 2));
137
+ }
138
+ };
139
+
140
+ export async function executeSql({
141
+ local,
142
+ config,
143
+ name,
144
+ shouldPrompt,
145
+ persistTo,
146
+ file,
147
+ command,
148
+ json,
149
+ preview,
150
+ }: {
151
+ local: boolean | undefined;
152
+ config: ConfigFields<DevConfig> & Environment;
153
+ name: string;
154
+ shouldPrompt: boolean | undefined;
155
+ persistTo: string | undefined;
156
+ file: string | undefined;
157
+ command: string | undefined;
158
+ json: boolean | undefined;
159
+ preview: boolean | undefined;
160
+ }) {
161
+ const sql = file ? readFileSync(file) : command;
108
162
  if (!sql) throw new Error(`Error: must provide --command or --file.`);
163
+ if (preview && local)
164
+ throw new Error(`Error: can't use --preview with --local`);
109
165
  if (persistTo && !local)
110
166
  throw new Error(`Error: can't use --persist-to without --local`);
111
-
112
167
  logger.log(`🌀 Mapping SQL input into an array of statements`);
113
168
  const queries = splitSqlQuery(sql);
114
169
 
@@ -122,73 +177,39 @@ export async function executeSql(
122
177
  }
123
178
 
124
179
  return local
125
- ? await executeLocally(config, name, shouldPrompt, queries, persistTo)
126
- : await executeRemotely(config, name, shouldPrompt, batchSplit(queries));
180
+ ? await executeLocally({
181
+ config,
182
+ name,
183
+ shouldPrompt,
184
+ queries,
185
+ persistTo,
186
+ json,
187
+ })
188
+ : await executeRemotely({
189
+ config,
190
+ name,
191
+ shouldPrompt,
192
+ batches: batchSplit(queries),
193
+ json,
194
+ preview,
195
+ });
127
196
  }
128
197
 
129
- export const Handler = withConfig<ExecuteArgs>(
130
- async ({
131
- config,
132
- database,
133
- file,
134
- command,
135
- local,
136
- persistTo,
137
- yes,
138
- }): Promise<void> => {
139
- logger.log(d1BetaWarning);
140
- if (file && command)
141
- return logger.error(`Error: can't provide both --command and --file.`);
142
-
143
- const isInteractive = process.stdout.isTTY;
144
- const response: QueryResult[] | null = await executeSql(
145
- local,
146
- config,
147
- database,
148
- isInteractive && !yes,
149
- persistTo,
150
- file,
151
- command
152
- );
153
-
154
- // Early exit if prompt rejected
155
- if (!response) return;
156
-
157
- if (isInteractive) {
158
- // Render table if single result
159
- render(
160
- <Static items={response}>
161
- {(result) => {
162
- // batch results
163
- if (!Array.isArray(result)) {
164
- const { results, query } = result;
165
-
166
- if (Array.isArray(results) && results.length > 0) {
167
- const shortQuery = shorten(query, 48);
168
- return (
169
- <>
170
- {shortQuery ? <Text dimColor>{shortQuery}</Text> : null}
171
- <Table data={results}></Table>
172
- </>
173
- );
174
- }
175
- }
176
- }}
177
- </Static>
178
- );
179
- } else {
180
- logger.log(JSON.stringify(response, null, 2));
181
- }
182
- }
183
- );
184
-
185
- async function executeLocally(
186
- config: Config,
187
- name: string,
188
- shouldPrompt: boolean | undefined,
189
- queries: string[],
190
- persistTo: string | undefined
191
- ) {
198
+ async function executeLocally({
199
+ config,
200
+ name,
201
+ shouldPrompt,
202
+ queries,
203
+ persistTo,
204
+ json,
205
+ }: {
206
+ config: Config;
207
+ name: string;
208
+ shouldPrompt: boolean | undefined;
209
+ queries: string[];
210
+ persistTo: string | undefined;
211
+ json: boolean | undefined;
212
+ }) {
192
213
  const localDB = getDatabaseInfoFromConfig(config, name);
193
214
  if (!localDB) {
194
215
  throw new Error(
@@ -204,40 +225,46 @@ async function executeLocally(
204
225
 
205
226
  const dbDir = path.join(persistencePath, "d1");
206
227
  const dbPath = path.join(dbDir, `${localDB.binding}.sqlite3`);
207
- const [{ Statement }, { createSQLiteDB }] =
208
- await npxImport<MiniflareNpxImportTypes>(
209
- ["@miniflare/d1", "@miniflare/shared"],
210
- logger.log
211
- );
212
-
213
- if (!existsSync(dbDir) && shouldPrompt) {
214
- const ok = await confirm(
215
- `About to create ${readableRelative(dbPath)}, ok?`
216
- );
228
+ const [{ D1Database, D1DatabaseAPI }, { createSQLiteDB }] = await npxImport<
229
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
230
+ [typeof import("@miniflare/d1"), typeof import("@miniflare/shared")]
231
+ >(["@miniflare/d1", "@miniflare/shared"], logger.log);
232
+
233
+ if (!existsSync(dbDir)) {
234
+ const ok =
235
+ json ||
236
+ !shouldPrompt ||
237
+ (await confirm(`About to create ${readableRelative(dbPath)}, ok?`));
217
238
  if (!ok) return null;
218
239
  await mkdir(dbDir, { recursive: true });
219
240
  }
220
241
 
221
242
  logger.log(`🌀 Loading DB at ${readableRelative(dbPath)}`);
222
- const db = await createSQLiteDB(dbPath);
223
-
224
- const results: QueryResult[] = [];
225
- for (const sql of queries) {
226
- const statement = new Statement(db, sql);
227
- results.push((await statement.all()) as QueryResult);
228
- }
229
243
 
230
- return results;
244
+ const sqliteDb = await createSQLiteDB(dbPath);
245
+ const db = new D1Database(new D1DatabaseAPI(sqliteDb));
246
+ const stmts = queries.map((query) => db.prepare(query));
247
+ return (await db.batch(stmts)) as QueryResult[];
231
248
  }
232
249
 
233
- async function executeRemotely(
234
- config: Config,
235
- name: string,
236
- shouldPrompt: boolean | undefined,
237
- batches: string[]
238
- ) {
250
+ async function executeRemotely({
251
+ config,
252
+ name,
253
+ shouldPrompt,
254
+ batches,
255
+ json,
256
+ preview,
257
+ }: {
258
+ config: Config;
259
+ name: string;
260
+ shouldPrompt: boolean | undefined;
261
+ batches: string[];
262
+ json: boolean | undefined;
263
+ preview: boolean | undefined;
264
+ }) {
239
265
  const multiple_batches = batches.length > 1;
240
- if (multiple_batches) {
266
+ // in JSON mode, we don't want a prompt here
267
+ if (multiple_batches && !json) {
241
268
  const warning = `⚠️ Too much SQL to send at once, this execution will be sent as ${batches.length} batches.`;
242
269
 
243
270
  if (shouldPrompt) {
@@ -257,15 +284,13 @@ async function executeRemotely(
257
284
  accountId,
258
285
  name
259
286
  );
260
-
261
- if (shouldPrompt) {
262
- logger.log(`🌀 Executing on ${name} (${db.uuid}):`);
263
-
264
- // Don't output if shouldPrompt is undefined
265
- } else if (shouldPrompt !== undefined) {
266
- // Pipe to error so we don't break jq
267
- logger.error(`Executing on ${name} (${db.uuid}):`);
287
+ if (preview && !db.previewDatabaseUuid) {
288
+ throw logger.error(
289
+ "Please define a `preview_database_id` in your wrangler.toml to execute your queries against a preview database"
290
+ );
268
291
  }
292
+ const dbUuid = preview ? db.previewDatabaseUuid : db.uuid;
293
+ logger.log(`🌀 Executing on ${name} (${dbUuid}):`);
269
294
 
270
295
  const results: QueryResult[] = [];
271
296
  for (const sql of batches) {
@@ -275,7 +300,7 @@ async function executeRemotely(
275
300
  );
276
301
 
277
302
  const result = await fetchResult<QueryResult[]>(
278
- `/accounts/${accountId}/d1/database/${db.uuid}/query`,
303
+ `/accounts/${accountId}/d1/database/${dbUuid}/query`,
279
304
  {
280
305
  method: "POST",
281
306
  headers: {
@@ -321,3 +346,9 @@ function batchSplit(queries: string[]) {
321
346
  }
322
347
  return batches;
323
348
  }
349
+
350
+ function shorten(query: string | undefined, length: number) {
351
+ return query && query.length > length
352
+ ? query.slice(0, length) + "..."
353
+ : query;
354
+ }
package/src/d1/index.ts CHANGED
@@ -5,10 +5,9 @@ import * as Execute from "./execute";
5
5
  import * as List from "./list";
6
6
  import * as Migrations from "./migrations";
7
7
  import { d1BetaWarning } from "./utils";
8
- import type { CommonYargsOptions } from "../yargs-types";
9
- import type { Argv } from "yargs";
8
+ import type { CommonYargsArgv } from "../yargs-types";
10
9
 
11
- export const d1 = (yargs: Argv<CommonYargsOptions>) => {
10
+ export function d1(yargs: CommonYargsArgv) {
12
11
  return (
13
12
  yargs
14
13
  .command("list", "List D1 databases", List.Options, List.Handler)
@@ -24,8 +23,8 @@ export const d1 = (yargs: Argv<CommonYargsOptions>) => {
24
23
  Delete.Options,
25
24
  Delete.Handler
26
25
  )
27
- .command("backup", "Interact with D1 Backups", (yargs2) =>
28
- yargs2
26
+ .command("backup", "Interact with D1 Backups", (backupArgs) =>
27
+ backupArgs
29
28
  .demandCommand()
30
29
  .command(
31
30
  "list <name>",
@@ -98,4 +97,4 @@ export const d1 = (yargs: Argv<CommonYargsOptions>) => {
98
97
  )
99
98
  .epilogue(d1BetaWarning)
100
99
  );
101
- };
100
+ }
package/src/d1/list.tsx CHANGED
@@ -5,22 +5,34 @@ import { fetchResult } from "../cfetch";
5
5
  import { logger } from "../logger";
6
6
  import { requireAuth } from "../user";
7
7
  import { d1BetaWarning } from "./utils";
8
+ import type {
9
+ CommonYargsArgv,
10
+ StrictYargsOptionsToInterface,
11
+ } from "../yargs-types";
8
12
  import type { Database } from "./types";
9
- import type { ArgumentsCamelCase, Argv } from "yargs";
10
13
 
11
- type ListArgs = Record<string, never>;
12
-
13
- export function Options(d1ListYargs: Argv): Argv<ListArgs> {
14
- return d1ListYargs.epilogue(d1BetaWarning);
14
+ export function Options(d1ListYargs: CommonYargsArgv) {
15
+ return d1ListYargs
16
+ .option("json", {
17
+ describe: "return output as clean JSON",
18
+ type: "boolean",
19
+ default: false,
20
+ })
21
+ .epilogue(d1BetaWarning);
15
22
  }
16
23
 
17
- export async function Handler(_: ArgumentsCamelCase<ListArgs>): Promise<void> {
24
+ export async function Handler({
25
+ json,
26
+ }: StrictYargsOptionsToInterface<typeof Options>): Promise<void> {
18
27
  const accountId = await requireAuth({});
19
- logger.log(d1BetaWarning);
20
-
21
28
  const dbs: Array<Database> = await listDatabases(accountId);
22
29
 
23
- render(<Table data={dbs}></Table>);
30
+ if (json) {
31
+ logger.log(JSON.stringify(dbs, null, 2));
32
+ } else {
33
+ logger.log(d1BetaWarning);
34
+ render(<Table data={dbs}></Table>);
35
+ }
24
36
  }
25
37
 
26
38
  export const listDatabases = async (
@@ -19,20 +19,24 @@ import {
19
19
  getUnappliedMigrations,
20
20
  initMigrationsTable,
21
21
  } from "./helpers";
22
- import { DatabaseWithLocal } from "./options";
22
+ import { MigrationOptions } from "./options";
23
23
  import type { ParseError } from "../../parse";
24
- import type { BaseSqlExecuteArgs } from "../execute";
25
- import type { Argv } from "yargs";
24
+ import type {
25
+ CommonYargsArgv,
26
+ StrictYargsOptionsToInterface,
27
+ } from "../../yargs-types";
26
28
 
27
- export function ApplyOptions(yargs: Argv): Argv<BaseSqlExecuteArgs> {
28
- return DatabaseWithLocal(yargs);
29
+ export function ApplyOptions(yargs: CommonYargsArgv) {
30
+ return MigrationOptions(yargs);
29
31
  }
30
32
 
31
- export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
32
- async ({ config, database, local, persistTo }): Promise<void> => {
33
+ type ApplyHandlerOptions = StrictYargsOptionsToInterface<typeof ApplyOptions>;
34
+
35
+ export const ApplyHandler = withConfig<ApplyHandlerOptions>(
36
+ async ({ config, database, local, persistTo, preview }): Promise<void> => {
33
37
  logger.log(d1BetaWarning);
34
38
 
35
- const databaseInfo = await getDatabaseInfoFromConfig(config, database);
39
+ const databaseInfo = getDatabaseInfoFromConfig(config, database);
36
40
  if (!databaseInfo && !local) {
37
41
  throw new Error(
38
42
  `Can't find a DB with name/binding '${database}' in local config. Check info in wrangler.toml...`
@@ -43,31 +47,34 @@ export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
43
47
  return;
44
48
  }
45
49
 
46
- const migrationsPath = await getMigrationsPath(
47
- path.dirname(config.configPath),
48
- databaseInfo?.migrationsFolderPath ?? DEFAULT_MIGRATION_PATH,
49
- false
50
- );
50
+ const migrationsPath = await getMigrationsPath({
51
+ projectPath: path.dirname(config.configPath),
52
+ migrationsFolderPath:
53
+ databaseInfo?.migrationsFolderPath ?? DEFAULT_MIGRATION_PATH,
54
+ createIfMissing: false,
55
+ });
51
56
 
52
- const migrationTableName =
57
+ const migrationsTableName =
53
58
  databaseInfo?.migrationsTableName ?? DEFAULT_MIGRATION_TABLE;
54
- await initMigrationsTable(
55
- migrationTableName,
59
+ await initMigrationsTable({
60
+ migrationsTableName,
56
61
  local,
57
62
  config,
58
- database,
59
- persistTo
60
- );
63
+ name: database,
64
+ persistTo,
65
+ preview,
66
+ });
61
67
 
62
68
  const unappliedMigrations = (
63
- await getUnappliedMigrations(
64
- migrationTableName,
69
+ await getUnappliedMigrations({
70
+ migrationsTableName,
65
71
  migrationsPath,
66
72
  local,
67
73
  config,
68
- database,
69
- persistTo
70
- )
74
+ name: database,
75
+ persistTo,
76
+ preview,
77
+ })
71
78
  )
72
79
  .map((migration) => {
73
80
  return {
@@ -105,8 +112,8 @@ Your database may not be available to serve requests during the migration, conti
105
112
  );
106
113
  if (!ok) return;
107
114
 
108
- // don't backup prod db when applying migrations locally
109
- if (!local) {
115
+ // don't backup prod db when applying migrations locally or in preview
116
+ if (!local && !preview) {
110
117
  assert(
111
118
  databaseInfo,
112
119
  "In non-local mode `databaseInfo` should be defined."
@@ -122,22 +129,24 @@ Your database may not be available to serve requests during the migration, conti
122
129
  "utf8"
123
130
  );
124
131
  query += `
125
- INSERT INTO ${migrationTableName} (name)
132
+ INSERT INTO ${migrationsTableName} (name)
126
133
  values ('${migration.Name}');
127
134
  `;
128
135
 
129
136
  let success = true;
130
137
  let errorNotes: Array<string> = [];
131
138
  try {
132
- const response = await executeSql(
139
+ const response = await executeSql({
133
140
  local,
134
141
  config,
135
- database,
136
- isInteractive() && !CI.isCI(),
142
+ name: database,
143
+ shouldPrompt: isInteractive() && !CI.isCI(),
137
144
  persistTo,
138
- undefined,
139
- query
140
- );
145
+ command: query,
146
+ file: undefined,
147
+ json: undefined,
148
+ preview,
149
+ });
141
150
 
142
151
  if (response === null) {
143
152
  // TODO: return error
@@ -4,19 +4,16 @@ import { Box, render, Text } from "ink";
4
4
  import React from "react";
5
5
  import { withConfig } from "../../config";
6
6
  import { logger } from "../../logger";
7
- import { requireAuth } from "../../user";
7
+ import { DEFAULT_MIGRATION_PATH } from "../constants";
8
8
  import { Database } from "../options";
9
9
  import { d1BetaWarning, getDatabaseInfoFromConfig } from "../utils";
10
10
  import { getMigrationsPath, getNextMigrationNumber } from "./helpers";
11
- import type { Argv } from "yargs";
11
+ import type {
12
+ CommonYargsArgv,
13
+ StrictYargsOptionsToInterface,
14
+ } from "../../yargs-types";
12
15
 
13
- type MigrationsCreateArgs = {
14
- config?: string;
15
- database: string;
16
- message: string;
17
- };
18
-
19
- export function CreateOptions(yargs: Argv): Argv<MigrationsCreateArgs> {
16
+ export function CreateOptions(yargs: CommonYargsArgv) {
20
17
  return Database(yargs).positional("message", {
21
18
  describe: "The Migration message",
22
19
  type: "string",
@@ -24,12 +21,13 @@ export function CreateOptions(yargs: Argv): Argv<MigrationsCreateArgs> {
24
21
  });
25
22
  }
26
23
 
27
- export const CreateHandler = withConfig<MigrationsCreateArgs>(
24
+ type CreateHandlerOptions = StrictYargsOptionsToInterface<typeof CreateOptions>;
25
+
26
+ export const CreateHandler = withConfig<CreateHandlerOptions>(
28
27
  async ({ config, database, message }): Promise<void> => {
29
- await requireAuth({});
30
28
  logger.log(d1BetaWarning);
31
29
 
32
- const databaseInfo = await getDatabaseInfoFromConfig(config, database);
30
+ const databaseInfo = getDatabaseInfoFromConfig(config, database);
33
31
  if (!databaseInfo) {
34
32
  throw new Error(
35
33
  `Can't find a DB with name/binding '${database}' in local config. Check info in wrangler.toml...`
@@ -40,11 +38,12 @@ export const CreateHandler = withConfig<MigrationsCreateArgs>(
40
38
  return;
41
39
  }
42
40
 
43
- const migrationsPath = await getMigrationsPath(
44
- path.dirname(config.configPath),
45
- databaseInfo.migrationsFolderPath,
46
- true
47
- );
41
+ const migrationsPath = await getMigrationsPath({
42
+ projectPath: path.dirname(config.configPath),
43
+ migrationsFolderPath:
44
+ databaseInfo.migrationsFolderPath ?? DEFAULT_MIGRATION_PATH,
45
+ createIfMissing: true,
46
+ });
48
47
  const nextMigrationNumber = pad(getNextMigrationNumber(migrationsPath), 4);
49
48
  const migrationName = message.replaceAll(" ", "_");
50
49