wrangler 2.9.1 ā 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/miniflare-dist/index.mjs +1 -1
- package/package.json +8 -8
- package/src/__tests__/configuration.test.ts +70 -0
- package/src/__tests__/d1/d1.test.ts +2 -2
- package/src/__tests__/d1/execute.test.ts +64 -0
- package/src/__tests__/d1/migrate.test.ts +14 -0
- package/src/__tests__/deployments.test.ts +40 -16
- package/src/__tests__/dev.test.tsx +3 -3
- package/src/__tests__/helpers/msw/handlers/deployments.ts +40 -16
- package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
- package/src/__tests__/index.test.ts +2 -0
- package/src/__tests__/kv.test.ts +8 -8
- package/src/__tests__/middleware.test.ts +65 -0
- package/src/__tests__/mtls-certificates.test.ts +585 -0
- package/src/__tests__/pages/functions-build.test.ts +402 -0
- package/src/__tests__/pages/pages.test.ts +7 -7
- package/src/__tests__/pages/publish.test.ts +525 -1
- package/src/__tests__/publish.test.ts +58 -27
- package/src/__tests__/queues.test.ts +2 -2
- package/src/__tests__/secret.test.ts +4 -4
- package/src/__tests__/tsconfig.tsbuildinfo +1 -1
- package/src/__tests__/user.test.ts +1 -1
- package/src/__tests__/whoami.test.tsx +1 -1
- package/src/api/index.ts +8 -0
- package/src/api/mtls-certificate.ts +148 -0
- package/src/api/pages/create-worker-bundle-contents.ts +75 -0
- package/src/api/pages/publish.tsx +52 -8
- package/src/bundle.ts +6 -5
- package/src/config/config.ts +7 -7
- package/src/config/environment.ts +9 -2
- package/src/config/index.ts +13 -0
- package/src/config/validation.ts +50 -3
- package/src/create-worker-upload-form.ts +9 -0
- package/src/d1/execute.tsx +123 -90
- package/src/d1/migrations/apply.tsx +29 -24
- package/src/d1/migrations/create.tsx +7 -7
- package/src/d1/migrations/helpers.ts +63 -38
- package/src/d1/migrations/list.tsx +19 -16
- package/src/d1/migrations/options.ts +6 -1
- package/src/d1/types.ts +1 -0
- package/src/d1/utils.ts +2 -1
- package/src/deployments.ts +62 -39
- package/src/dev/dev.tsx +1 -15
- package/src/dev/remote.tsx +2 -2
- package/src/dev.tsx +9 -6
- package/src/generate/index.ts +1 -1
- package/src/index.ts +15 -5
- package/src/miniflare-cli/assets.ts +1 -1
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -1
- package/src/mtls-certificate/cli.ts +155 -0
- package/src/pages/build.ts +103 -23
- package/src/pages/buildFunctions.ts +32 -31
- package/src/pages/dev.ts +4 -2
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -1
- package/src/pages/publish.tsx +12 -1
- package/src/pages/utils.ts +1 -1
- package/src/publish/publish.ts +3 -2
- package/src/secret/index.ts +1 -0
- package/src/sites.ts +1 -1
- package/src/tail/filters.ts +1 -1
- package/src/user/user.ts +4 -3
- package/src/worker.ts +6 -0
- package/templates/format-dev-errors.ts +1 -0
- package/templates/new-worker.ts +3 -0
- package/templates/serve-static-assets.ts +1 -0
- package/templates/service-bindings-module-facade.js +1 -0
- package/templates/tsconfig.tsbuildinfo +1 -1
- package/wrangler-dist/cli.d.ts +82 -2
- package/wrangler-dist/cli.js +1501 -1031
package/src/d1/execute.tsx
CHANGED
|
@@ -27,17 +27,6 @@ import type {
|
|
|
27
27
|
StrictYargsOptionsToInterface,
|
|
28
28
|
} from "../yargs-types";
|
|
29
29
|
import type { Database } from "./types";
|
|
30
|
-
import type { Statement as StatementType } from "@miniflare/d1";
|
|
31
|
-
import type { createSQLiteDB as createSQLiteDBType } from "@miniflare/shared";
|
|
32
|
-
|
|
33
|
-
type MiniflareNpxImportTypes = [
|
|
34
|
-
{
|
|
35
|
-
Statement: typeof StatementType;
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
createSQLiteDB: typeof createSQLiteDBType;
|
|
39
|
-
}
|
|
40
|
-
];
|
|
41
30
|
|
|
42
31
|
export type QueryResult = {
|
|
43
32
|
results: Record<string, string | number | boolean>[];
|
|
@@ -80,55 +69,19 @@ export function Options(yargs: CommonYargsArgv) {
|
|
|
80
69
|
describe: "Return output as clean JSON",
|
|
81
70
|
type: "boolean",
|
|
82
71
|
default: false,
|
|
72
|
+
})
|
|
73
|
+
.option("preview", {
|
|
74
|
+
describe: "Execute commands/files against a preview D1 DB",
|
|
75
|
+
type: "boolean",
|
|
76
|
+
default: false,
|
|
83
77
|
});
|
|
84
78
|
}
|
|
85
79
|
|
|
86
|
-
function shorten(query: string | undefined, length: number) {
|
|
87
|
-
return query && query.length > length
|
|
88
|
-
? query.slice(0, length) + "..."
|
|
89
|
-
: query;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export async function executeSql(
|
|
93
|
-
local: undefined | boolean,
|
|
94
|
-
config: ConfigFields<DevConfig> & Environment,
|
|
95
|
-
name: string,
|
|
96
|
-
shouldPrompt: boolean | undefined,
|
|
97
|
-
persistTo: undefined | string,
|
|
98
|
-
file?: string,
|
|
99
|
-
command?: string,
|
|
100
|
-
json?: boolean
|
|
101
|
-
) {
|
|
102
|
-
const sql = file ? readFileSync(file) : command;
|
|
103
|
-
if (!sql) throw new Error(`Error: must provide --command or --file.`);
|
|
104
|
-
if (persistTo && !local)
|
|
105
|
-
throw new Error(`Error: can't use --persist-to without --local`);
|
|
106
|
-
logger.log(`š Mapping SQL input into an array of statements`);
|
|
107
|
-
const queries = splitSqlQuery(sql);
|
|
108
|
-
|
|
109
|
-
if (file && sql) {
|
|
110
|
-
if (queries[0].startsWith("SQLite format 3")) {
|
|
111
|
-
//TODO: update this error to recommend using `wrangler d1 restore` when it exists
|
|
112
|
-
throw new Error(
|
|
113
|
-
"Provided file is a binary SQLite database file instead of an SQL text file.\nThe execute command can only process SQL text files.\nPlease export an SQL file from your SQLite database and try again."
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return local
|
|
119
|
-
? await executeLocally(config, name, shouldPrompt, queries, persistTo, json)
|
|
120
|
-
: await executeRemotely(
|
|
121
|
-
config,
|
|
122
|
-
name,
|
|
123
|
-
shouldPrompt,
|
|
124
|
-
batchSplit(queries),
|
|
125
|
-
json
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
80
|
type HandlerOptions = StrictYargsOptionsToInterface<typeof Options>;
|
|
129
81
|
|
|
130
82
|
export const Handler = async (args: HandlerOptions): Promise<void> => {
|
|
131
|
-
const { local, database, yes, persistTo, file, command, json } =
|
|
83
|
+
const { local, database, yes, persistTo, file, command, json, preview } =
|
|
84
|
+
args;
|
|
132
85
|
const existingLogLevel = logger.loggerLevel;
|
|
133
86
|
if (json) {
|
|
134
87
|
// set loggerLevel to error to avoid readConfig warnings appearing in JSON output
|
|
@@ -140,16 +93,17 @@ export const Handler = async (args: HandlerOptions): Promise<void> => {
|
|
|
140
93
|
return logger.error(`Error: can't provide both --command and --file.`);
|
|
141
94
|
|
|
142
95
|
const isInteractive = process.stdout.isTTY;
|
|
143
|
-
const response: QueryResult[] | null = await executeSql(
|
|
96
|
+
const response: QueryResult[] | null = await executeSql({
|
|
144
97
|
local,
|
|
145
98
|
config,
|
|
146
|
-
database,
|
|
147
|
-
isInteractive && !yes,
|
|
99
|
+
name: database,
|
|
100
|
+
shouldPrompt: isInteractive && !yes,
|
|
148
101
|
persistTo,
|
|
149
102
|
file,
|
|
150
103
|
command,
|
|
151
|
-
json
|
|
152
|
-
|
|
104
|
+
json,
|
|
105
|
+
preview,
|
|
106
|
+
});
|
|
153
107
|
|
|
154
108
|
// Early exit if prompt rejected
|
|
155
109
|
if (!response) return;
|
|
@@ -183,14 +137,79 @@ export const Handler = async (args: HandlerOptions): Promise<void> => {
|
|
|
183
137
|
}
|
|
184
138
|
};
|
|
185
139
|
|
|
186
|
-
async function
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
persistTo
|
|
192
|
-
|
|
193
|
-
|
|
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;
|
|
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`);
|
|
165
|
+
if (persistTo && !local)
|
|
166
|
+
throw new Error(`Error: can't use --persist-to without --local`);
|
|
167
|
+
logger.log(`š Mapping SQL input into an array of statements`);
|
|
168
|
+
const queries = splitSqlQuery(sql);
|
|
169
|
+
|
|
170
|
+
if (file && sql) {
|
|
171
|
+
if (queries[0].startsWith("SQLite format 3")) {
|
|
172
|
+
//TODO: update this error to recommend using `wrangler d1 restore` when it exists
|
|
173
|
+
throw new Error(
|
|
174
|
+
"Provided file is a binary SQLite database file instead of an SQL text file.\nThe execute command can only process SQL text files.\nPlease export an SQL file from your SQLite database and try again."
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return local
|
|
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
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
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
|
+
}) {
|
|
194
213
|
const localDB = getDatabaseInfoFromConfig(config, name);
|
|
195
214
|
if (!localDB) {
|
|
196
215
|
throw new Error(
|
|
@@ -206,11 +225,10 @@ async function executeLocally(
|
|
|
206
225
|
|
|
207
226
|
const dbDir = path.join(persistencePath, "d1");
|
|
208
227
|
const dbPath = path.join(dbDir, `${localDB.binding}.sqlite3`);
|
|
209
|
-
const [{
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
);
|
|
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);
|
|
214
232
|
|
|
215
233
|
if (!existsSync(dbDir)) {
|
|
216
234
|
const ok =
|
|
@@ -222,24 +240,28 @@ async function executeLocally(
|
|
|
222
240
|
}
|
|
223
241
|
|
|
224
242
|
logger.log(`š Loading DB at ${readableRelative(dbPath)}`);
|
|
225
|
-
const db = await createSQLiteDB(dbPath);
|
|
226
243
|
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
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[];
|
|
234
248
|
}
|
|
235
249
|
|
|
236
|
-
async function executeRemotely(
|
|
237
|
-
config
|
|
238
|
-
name
|
|
239
|
-
shouldPrompt
|
|
240
|
-
batches
|
|
241
|
-
json
|
|
242
|
-
|
|
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
|
+
}) {
|
|
243
265
|
const multiple_batches = batches.length > 1;
|
|
244
266
|
// in JSON mode, we don't want a prompt here
|
|
245
267
|
if (multiple_batches && !json) {
|
|
@@ -262,8 +284,13 @@ async function executeRemotely(
|
|
|
262
284
|
accountId,
|
|
263
285
|
name
|
|
264
286
|
);
|
|
265
|
-
|
|
266
|
-
|
|
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
|
+
);
|
|
291
|
+
}
|
|
292
|
+
const dbUuid = preview ? db.previewDatabaseUuid : db.uuid;
|
|
293
|
+
logger.log(`š Executing on ${name} (${dbUuid}):`);
|
|
267
294
|
|
|
268
295
|
const results: QueryResult[] = [];
|
|
269
296
|
for (const sql of batches) {
|
|
@@ -273,7 +300,7 @@ async function executeRemotely(
|
|
|
273
300
|
);
|
|
274
301
|
|
|
275
302
|
const result = await fetchResult<QueryResult[]>(
|
|
276
|
-
`/accounts/${accountId}/d1/database/${
|
|
303
|
+
`/accounts/${accountId}/d1/database/${dbUuid}/query`,
|
|
277
304
|
{
|
|
278
305
|
method: "POST",
|
|
279
306
|
headers: {
|
|
@@ -319,3 +346,9 @@ function batchSplit(queries: string[]) {
|
|
|
319
346
|
}
|
|
320
347
|
return batches;
|
|
321
348
|
}
|
|
349
|
+
|
|
350
|
+
function shorten(query: string | undefined, length: number) {
|
|
351
|
+
return query && query.length > length
|
|
352
|
+
? query.slice(0, length) + "..."
|
|
353
|
+
: query;
|
|
354
|
+
}
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
getUnappliedMigrations,
|
|
20
20
|
initMigrationsTable,
|
|
21
21
|
} from "./helpers";
|
|
22
|
-
import {
|
|
22
|
+
import { MigrationOptions } from "./options";
|
|
23
23
|
import type { ParseError } from "../../parse";
|
|
24
24
|
import type {
|
|
25
25
|
CommonYargsArgv,
|
|
@@ -27,13 +27,13 @@ import type {
|
|
|
27
27
|
} from "../../yargs-types";
|
|
28
28
|
|
|
29
29
|
export function ApplyOptions(yargs: CommonYargsArgv) {
|
|
30
|
-
return
|
|
30
|
+
return MigrationOptions(yargs);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
type ApplyHandlerOptions = StrictYargsOptionsToInterface<typeof ApplyOptions>;
|
|
34
34
|
|
|
35
35
|
export const ApplyHandler = withConfig<ApplyHandlerOptions>(
|
|
36
|
-
async ({ config, database, local, persistTo }): Promise<void> => {
|
|
36
|
+
async ({ config, database, local, persistTo, preview }): Promise<void> => {
|
|
37
37
|
logger.log(d1BetaWarning);
|
|
38
38
|
|
|
39
39
|
const databaseInfo = getDatabaseInfoFromConfig(config, database);
|
|
@@ -47,31 +47,34 @@ export const ApplyHandler = withConfig<ApplyHandlerOptions>(
|
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
const migrationsPath = await getMigrationsPath(
|
|
51
|
-
path.dirname(config.configPath),
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
const migrationsPath = await getMigrationsPath({
|
|
51
|
+
projectPath: path.dirname(config.configPath),
|
|
52
|
+
migrationsFolderPath:
|
|
53
|
+
databaseInfo?.migrationsFolderPath ?? DEFAULT_MIGRATION_PATH,
|
|
54
|
+
createIfMissing: false,
|
|
55
|
+
});
|
|
55
56
|
|
|
56
57
|
const migrationsTableName =
|
|
57
58
|
databaseInfo?.migrationsTableName ?? DEFAULT_MIGRATION_TABLE;
|
|
58
|
-
await initMigrationsTable(
|
|
59
|
+
await initMigrationsTable({
|
|
59
60
|
migrationsTableName,
|
|
60
61
|
local,
|
|
61
62
|
config,
|
|
62
|
-
database,
|
|
63
|
-
persistTo
|
|
64
|
-
|
|
63
|
+
name: database,
|
|
64
|
+
persistTo,
|
|
65
|
+
preview,
|
|
66
|
+
});
|
|
65
67
|
|
|
66
68
|
const unappliedMigrations = (
|
|
67
|
-
await getUnappliedMigrations(
|
|
69
|
+
await getUnappliedMigrations({
|
|
68
70
|
migrationsTableName,
|
|
69
71
|
migrationsPath,
|
|
70
72
|
local,
|
|
71
73
|
config,
|
|
72
|
-
database,
|
|
73
|
-
persistTo
|
|
74
|
-
|
|
74
|
+
name: database,
|
|
75
|
+
persistTo,
|
|
76
|
+
preview,
|
|
77
|
+
})
|
|
75
78
|
)
|
|
76
79
|
.map((migration) => {
|
|
77
80
|
return {
|
|
@@ -109,8 +112,8 @@ Your database may not be available to serve requests during the migration, conti
|
|
|
109
112
|
);
|
|
110
113
|
if (!ok) return;
|
|
111
114
|
|
|
112
|
-
// don't backup prod db when applying migrations locally
|
|
113
|
-
if (!local) {
|
|
115
|
+
// don't backup prod db when applying migrations locally or in preview
|
|
116
|
+
if (!local && !preview) {
|
|
114
117
|
assert(
|
|
115
118
|
databaseInfo,
|
|
116
119
|
"In non-local mode `databaseInfo` should be defined."
|
|
@@ -133,15 +136,17 @@ Your database may not be available to serve requests during the migration, conti
|
|
|
133
136
|
let success = true;
|
|
134
137
|
let errorNotes: Array<string> = [];
|
|
135
138
|
try {
|
|
136
|
-
const response = await executeSql(
|
|
139
|
+
const response = await executeSql({
|
|
137
140
|
local,
|
|
138
141
|
config,
|
|
139
|
-
database,
|
|
140
|
-
isInteractive() && !CI.isCI(),
|
|
142
|
+
name: database,
|
|
143
|
+
shouldPrompt: isInteractive() && !CI.isCI(),
|
|
141
144
|
persistTo,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
command: query,
|
|
146
|
+
file: undefined,
|
|
147
|
+
json: undefined,
|
|
148
|
+
preview,
|
|
149
|
+
});
|
|
145
150
|
|
|
146
151
|
if (response === null) {
|
|
147
152
|
// TODO: return error
|
|
@@ -4,7 +4,7 @@ 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 {
|
|
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";
|
|
@@ -25,7 +25,6 @@ type CreateHandlerOptions = StrictYargsOptionsToInterface<typeof CreateOptions>;
|
|
|
25
25
|
|
|
26
26
|
export const CreateHandler = withConfig<CreateHandlerOptions>(
|
|
27
27
|
async ({ config, database, message }): Promise<void> => {
|
|
28
|
-
await requireAuth({});
|
|
29
28
|
logger.log(d1BetaWarning);
|
|
30
29
|
|
|
31
30
|
const databaseInfo = getDatabaseInfoFromConfig(config, database);
|
|
@@ -39,11 +38,12 @@ export const CreateHandler = withConfig<CreateHandlerOptions>(
|
|
|
39
38
|
return;
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
const migrationsPath = await getMigrationsPath(
|
|
43
|
-
path.dirname(config.configPath),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
const migrationsPath = await getMigrationsPath({
|
|
42
|
+
projectPath: path.dirname(config.configPath),
|
|
43
|
+
migrationsFolderPath:
|
|
44
|
+
databaseInfo.migrationsFolderPath ?? DEFAULT_MIGRATION_PATH,
|
|
45
|
+
createIfMissing: true,
|
|
46
|
+
});
|
|
47
47
|
const nextMigrationNumber = pad(getNextMigrationNumber(migrationsPath), 4);
|
|
48
48
|
const migrationName = message.replaceAll(" ", "_");
|
|
49
49
|
|
|
@@ -10,11 +10,15 @@ import type { ConfigFields, DevConfig, Environment } from "../../config";
|
|
|
10
10
|
import type { QueryResult } from "../execute";
|
|
11
11
|
import type { Migration } from "../types";
|
|
12
12
|
|
|
13
|
-
export async function getMigrationsPath(
|
|
14
|
-
projectPath
|
|
15
|
-
migrationsFolderPath
|
|
16
|
-
createIfMissing
|
|
17
|
-
|
|
13
|
+
export async function getMigrationsPath({
|
|
14
|
+
projectPath,
|
|
15
|
+
migrationsFolderPath,
|
|
16
|
+
createIfMissing,
|
|
17
|
+
}: {
|
|
18
|
+
projectPath: string;
|
|
19
|
+
migrationsFolderPath: string;
|
|
20
|
+
createIfMissing: boolean;
|
|
21
|
+
}): Promise<string> {
|
|
18
22
|
const dir = path.resolve(projectPath, migrationsFolderPath);
|
|
19
23
|
if (fs.existsSync(dir)) return dir;
|
|
20
24
|
|
|
@@ -34,21 +38,31 @@ export async function getMigrationsPath(
|
|
|
34
38
|
throw new Error(`No migrations present at ${dir}.`);
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
export async function getUnappliedMigrations(
|
|
38
|
-
migrationsTableName
|
|
39
|
-
migrationsPath
|
|
40
|
-
local
|
|
41
|
-
config
|
|
42
|
-
name
|
|
43
|
-
persistTo
|
|
44
|
-
|
|
41
|
+
export async function getUnappliedMigrations({
|
|
42
|
+
migrationsTableName,
|
|
43
|
+
migrationsPath,
|
|
44
|
+
local,
|
|
45
|
+
config,
|
|
46
|
+
name,
|
|
47
|
+
persistTo,
|
|
48
|
+
preview,
|
|
49
|
+
}: {
|
|
50
|
+
migrationsTableName: string;
|
|
51
|
+
migrationsPath: string;
|
|
52
|
+
local: boolean | undefined;
|
|
53
|
+
config: ConfigFields<DevConfig> & Environment;
|
|
54
|
+
name: string;
|
|
55
|
+
persistTo: string | undefined;
|
|
56
|
+
preview: boolean | undefined;
|
|
57
|
+
}): Promise<Array<string>> {
|
|
45
58
|
const appliedMigrations = (
|
|
46
59
|
await listAppliedMigrations(
|
|
47
60
|
migrationsTableName,
|
|
48
61
|
local,
|
|
49
62
|
config,
|
|
50
63
|
name,
|
|
51
|
-
persistTo
|
|
64
|
+
persistTo,
|
|
65
|
+
preview
|
|
52
66
|
)
|
|
53
67
|
).map((migration) => {
|
|
54
68
|
return migration.name;
|
|
@@ -68,24 +82,25 @@ export async function getUnappliedMigrations(
|
|
|
68
82
|
|
|
69
83
|
const listAppliedMigrations = async (
|
|
70
84
|
migrationsTableName: string,
|
|
71
|
-
local:
|
|
85
|
+
local: boolean | undefined,
|
|
72
86
|
config: ConfigFields<DevConfig> & Environment,
|
|
73
87
|
name: string,
|
|
74
|
-
persistTo:
|
|
88
|
+
persistTo: string | undefined,
|
|
89
|
+
preview: boolean | undefined
|
|
75
90
|
): Promise<Migration[]> => {
|
|
76
|
-
const
|
|
77
|
-
FROM ${migrationsTableName}
|
|
78
|
-
ORDER BY id`;
|
|
79
|
-
|
|
80
|
-
const response: QueryResult[] | null = await executeSql(
|
|
91
|
+
const response: QueryResult[] | null = await executeSql({
|
|
81
92
|
local,
|
|
82
93
|
config,
|
|
83
94
|
name,
|
|
84
|
-
isInteractive() && !CI.isCI(),
|
|
95
|
+
shouldPrompt: isInteractive() && !CI.isCI(),
|
|
85
96
|
persistTo,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
97
|
+
command: `SELECT *
|
|
98
|
+
FROM ${migrationsTableName}
|
|
99
|
+
ORDER BY id`,
|
|
100
|
+
file: undefined,
|
|
101
|
+
json: undefined,
|
|
102
|
+
preview,
|
|
103
|
+
});
|
|
89
104
|
|
|
90
105
|
if (!response || response[0].results.length === 0) return [];
|
|
91
106
|
|
|
@@ -121,27 +136,37 @@ export function getNextMigrationNumber(migrationsPath: string): number {
|
|
|
121
136
|
return highestMigrationNumber + 1;
|
|
122
137
|
}
|
|
123
138
|
|
|
124
|
-
export const initMigrationsTable = async (
|
|
125
|
-
migrationsTableName
|
|
126
|
-
local
|
|
127
|
-
config
|
|
128
|
-
name
|
|
129
|
-
persistTo
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
export const initMigrationsTable = async ({
|
|
140
|
+
migrationsTableName,
|
|
141
|
+
local,
|
|
142
|
+
config,
|
|
143
|
+
name,
|
|
144
|
+
persistTo,
|
|
145
|
+
preview,
|
|
146
|
+
}: {
|
|
147
|
+
migrationsTableName: string;
|
|
148
|
+
local: boolean | undefined;
|
|
149
|
+
config: ConfigFields<DevConfig> & Environment;
|
|
150
|
+
name: string;
|
|
151
|
+
persistTo: string | undefined;
|
|
152
|
+
preview: boolean | undefined;
|
|
153
|
+
}) => {
|
|
154
|
+
return executeSql({
|
|
132
155
|
local,
|
|
133
156
|
config,
|
|
134
157
|
name,
|
|
135
|
-
isInteractive() && !CI.isCI(),
|
|
158
|
+
shouldPrompt: isInteractive() && !CI.isCI(),
|
|
136
159
|
persistTo,
|
|
137
|
-
|
|
138
|
-
`
|
|
160
|
+
command: `
|
|
139
161
|
CREATE TABLE IF NOT EXISTS ${migrationsTableName}
|
|
140
162
|
(
|
|
141
163
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
142
164
|
name TEXT UNIQUE,
|
|
143
165
|
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
|
|
144
166
|
);
|
|
145
|
-
|
|
146
|
-
|
|
167
|
+
`,
|
|
168
|
+
file: undefined,
|
|
169
|
+
json: undefined,
|
|
170
|
+
preview,
|
|
171
|
+
});
|
|
147
172
|
};
|
|
@@ -12,20 +12,20 @@ import {
|
|
|
12
12
|
getUnappliedMigrations,
|
|
13
13
|
initMigrationsTable,
|
|
14
14
|
} from "./helpers";
|
|
15
|
-
import {
|
|
15
|
+
import { MigrationOptions } from "./options";
|
|
16
16
|
import type {
|
|
17
17
|
CommonYargsArgv,
|
|
18
18
|
StrictYargsOptionsToInterface,
|
|
19
19
|
} from "../../yargs-types";
|
|
20
20
|
|
|
21
21
|
export function ListOptions(yargs: CommonYargsArgv) {
|
|
22
|
-
return
|
|
22
|
+
return MigrationOptions(yargs);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
type ListHandlerOptions = StrictYargsOptionsToInterface<typeof ListOptions>;
|
|
26
26
|
|
|
27
27
|
export const ListHandler = withConfig<ListHandlerOptions>(
|
|
28
|
-
async ({ config, database, local, persistTo }): Promise<void> => {
|
|
28
|
+
async ({ config, database, local, persistTo, preview }): Promise<void> => {
|
|
29
29
|
if (!local) {
|
|
30
30
|
await requireAuth({});
|
|
31
31
|
}
|
|
@@ -42,32 +42,35 @@ export const ListHandler = withConfig<ListHandlerOptions>(
|
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const migrationsPath = await getMigrationsPath(
|
|
46
|
-
path.dirname(config.configPath),
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const migrationsPath = await getMigrationsPath({
|
|
46
|
+
projectPath: path.dirname(config.configPath),
|
|
47
|
+
migrationsFolderPath:
|
|
48
|
+
databaseInfo?.migrationsFolderPath ?? DEFAULT_MIGRATION_PATH,
|
|
49
|
+
createIfMissing: false,
|
|
50
|
+
});
|
|
50
51
|
|
|
51
52
|
const migrationsTableName =
|
|
52
53
|
databaseInfo?.migrationsTableName ?? DEFAULT_MIGRATION_TABLE;
|
|
53
54
|
|
|
54
|
-
await initMigrationsTable(
|
|
55
|
+
await initMigrationsTable({
|
|
55
56
|
migrationsTableName,
|
|
56
57
|
local,
|
|
57
58
|
config,
|
|
58
|
-
database,
|
|
59
|
-
persistTo
|
|
60
|
-
|
|
59
|
+
name: database,
|
|
60
|
+
persistTo,
|
|
61
|
+
preview,
|
|
62
|
+
});
|
|
61
63
|
|
|
62
64
|
const unappliedMigrations = (
|
|
63
|
-
await getUnappliedMigrations(
|
|
65
|
+
await getUnappliedMigrations({
|
|
64
66
|
migrationsTableName,
|
|
65
67
|
migrationsPath,
|
|
66
68
|
local,
|
|
67
69
|
config,
|
|
68
|
-
database,
|
|
69
|
-
persistTo
|
|
70
|
-
|
|
70
|
+
name: database,
|
|
71
|
+
persistTo,
|
|
72
|
+
preview,
|
|
73
|
+
})
|
|
71
74
|
).map((migration) => {
|
|
72
75
|
return {
|
|
73
76
|
Name: migration,
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { Database } from "../options";
|
|
2
2
|
import type { CommonYargsArgv } from "../../yargs-types";
|
|
3
3
|
|
|
4
|
-
export function
|
|
4
|
+
export function MigrationOptions(yargs: CommonYargsArgv) {
|
|
5
5
|
return Database(yargs)
|
|
6
6
|
.option("local", {
|
|
7
7
|
describe:
|
|
8
8
|
"Execute commands/files against a local DB for use with wrangler dev --local",
|
|
9
9
|
type: "boolean",
|
|
10
10
|
})
|
|
11
|
+
.option("preview", {
|
|
12
|
+
describe: "Execute commands/files against a preview D1 DB",
|
|
13
|
+
type: "boolean",
|
|
14
|
+
default: false,
|
|
15
|
+
})
|
|
11
16
|
.option("persist-to", {
|
|
12
17
|
describe:
|
|
13
18
|
"Specify directory to use for local persistence (you must use --local with this flag)",
|
package/src/d1/types.ts
CHANGED
package/src/d1/utils.ts
CHANGED
|
@@ -14,6 +14,7 @@ export function getDatabaseInfoFromConfig(
|
|
|
14
14
|
) {
|
|
15
15
|
return {
|
|
16
16
|
uuid: d1Database.database_id,
|
|
17
|
+
previewDatabaseUuid: d1Database.preview_database_id,
|
|
17
18
|
binding: d1Database.binding,
|
|
18
19
|
name: d1Database.database_name,
|
|
19
20
|
migrationsTableName:
|
|
@@ -45,4 +46,4 @@ export const getDatabaseByNameOrBinding = async (
|
|
|
45
46
|
|
|
46
47
|
export const d1BetaWarning = process.env.NO_D1_WARNING
|
|
47
48
|
? ""
|
|
48
|
-
: "--------------------\nš§ D1 is currently in open alpha and is not recommended for production data and traffic\nš§ Please report any bugs to https://github.com/cloudflare/
|
|
49
|
+
: "--------------------\nš§ D1 is currently in open alpha and is not recommended for production data and traffic\nš§ Please report any bugs to https://github.com/cloudflare/workers-sdk/issues/new/choose\nš§ To request features, visit https://community.cloudflare.com/c/developers/d1\nš§ To give feedback, visit https://discord.gg/cloudflaredev\n--------------------\n";
|