wrangler 0.0.0-e6e1daba → 0.0.0-e7cf0caa
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/bin/wrangler.js +1 -1
- package/miniflare-dist/index.mjs +1 -1
- package/package.json +14 -9
- package/src/__tests__/api-devregistry.test.ts +121 -0
- package/src/__tests__/api.test.ts +27 -5
- package/src/__tests__/configuration.test.ts +294 -18
- package/src/__tests__/d1/execute.test.ts +3 -1
- package/src/__tests__/d1/migrate.test.ts +2 -0
- package/src/__tests__/delete.test.ts +6 -0
- package/src/__tests__/deployments.test.ts +335 -95
- package/src/__tests__/dev.test.tsx +87 -57
- package/src/__tests__/generate.test.ts +3 -4
- package/src/__tests__/helpers/mock-console.ts +6 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +70 -3
- package/src/__tests__/helpers/msw/index.ts +4 -2
- package/src/__tests__/helpers/worker-scripts/parent-worker.js +4 -1
- package/src/__tests__/index.test.ts +10 -4
- package/src/__tests__/init.test.ts +136 -104
- package/src/__tests__/jest.setup.ts +4 -0
- package/src/__tests__/kv.test.ts +9 -9
- package/src/__tests__/logger.test.ts +68 -2
- package/src/__tests__/middleware.scheduled.test.ts +2 -2
- package/src/__tests__/middleware.test.ts +4 -3
- package/src/__tests__/mtls-certificates.test.ts +5 -2
- package/src/__tests__/pages/deployment-list.test.ts +2 -0
- package/src/__tests__/pages/functions-build.test.ts +91 -41
- package/src/__tests__/pages/project-list.test.ts +2 -0
- package/src/__tests__/pages/project-upload.test.ts +43 -24
- package/src/__tests__/pages/publish.test.ts +267 -148
- package/src/__tests__/publish.test.ts +420 -164
- package/src/__tests__/pubsub.test.ts +3 -0
- package/src/__tests__/queues.test.ts +5 -2
- package/src/__tests__/test-old-node-version.js +3 -3
- package/src/__tests__/traverse-module-graph.test.ts +220 -0
- package/src/__tests__/tsconfig.tsbuildinfo +1 -1
- package/src/__tests__/type-generation.test.ts +1 -0
- package/src/__tests__/user.test.ts +1 -1
- package/src/__tests__/worker-namespace.test.ts +1 -0
- package/src/api/dev.ts +10 -22
- package/src/api/pages/create-worker-bundle-contents.ts +1 -0
- package/src/api/pages/publish.tsx +38 -51
- package/src/bundle.ts +44 -13
- package/src/config/environment.ts +36 -4
- package/src/config/index.ts +30 -2
- package/src/config/validation-helpers.ts +1 -1
- package/src/config/validation.ts +149 -5
- package/src/create-worker-upload-form.ts +28 -3
- package/src/d1/backups.tsx +15 -11
- package/src/d1/create.tsx +20 -16
- package/src/d1/execute.tsx +22 -19
- package/src/d1/list.tsx +2 -2
- package/src/d1/migrations/apply.tsx +35 -29
- package/src/d1/migrations/create.tsx +15 -12
- package/src/d1/migrations/list.tsx +10 -7
- package/src/deployments.ts +260 -8
- package/src/dev/dev.tsx +4 -4
- package/src/dev/local.tsx +14 -16
- package/src/dev/start-server.ts +12 -16
- package/src/dev/use-esbuild.ts +11 -13
- package/src/dev/validate-dev-props.ts +9 -0
- package/src/dev-registry.ts +2 -1
- package/src/dev.tsx +28 -13
- package/src/entry.ts +18 -8
- package/src/generate/index.ts +2 -2
- package/src/index.ts +76 -23
- package/src/init.ts +144 -134
- package/src/logger.ts +18 -3
- package/src/metrics/send-event.ts +2 -1
- package/src/miniflare-cli/index.ts +1 -1
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -1
- package/src/module-collection.ts +91 -25
- package/src/pages/build.ts +277 -99
- package/src/pages/buildFunctions.ts +20 -10
- package/src/pages/deployments.tsx +3 -5
- package/src/pages/dev.ts +21 -21
- package/src/pages/errors.ts +1 -0
- package/src/pages/functions/buildPlugin.ts +57 -34
- package/src/pages/functions/buildWorker.ts +34 -31
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -1
- package/src/pages/projects.tsx +2 -5
- package/src/pages/publish.tsx +1 -10
- package/src/pages/upload.tsx +29 -9
- package/src/paths.ts +1 -1
- package/src/publish/index.ts +1 -1
- package/src/publish/publish.ts +29 -34
- package/src/queues/cli/commands/consumer/add.ts +6 -0
- package/src/queues/client.ts +1 -0
- package/src/secret/index.ts +2 -1
- package/src/traverse-module-graph.ts +53 -0
- package/src/type-generation.ts +1 -1
- package/src/user/user.ts +1 -1
- package/src/utils/render.ts +93 -0
- package/src/worker.ts +18 -1
- package/templates/d1-beta-facade.js +5 -2
- package/templates/gitignore +1 -0
- package/templates/middleware/middleware-miniflare3-json-error.ts +17 -5
- package/templates/tsconfig.init.json +1 -2
- package/templates/tsconfig.tsbuildinfo +1 -1
- package/wrangler-dist/cli.d.ts +33 -13
- package/wrangler-dist/cli.js +20732 -19984
- package/src/__tests__/api-devregistry.test.js +0 -64
package/src/config/validation.ts
CHANGED
|
@@ -358,6 +358,26 @@ function normalizeAndValidateMainField(
|
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
+
/**
|
|
362
|
+
* Validate the `base_dir` field and return the normalized values.
|
|
363
|
+
*/
|
|
364
|
+
function normalizeAndValidateBaseDirField(
|
|
365
|
+
configPath: string | undefined,
|
|
366
|
+
rawDir: string | undefined
|
|
367
|
+
): string | undefined {
|
|
368
|
+
const configDir = path.dirname(configPath ?? "wrangler.toml");
|
|
369
|
+
if (rawDir !== undefined) {
|
|
370
|
+
if (typeof rawDir === "string") {
|
|
371
|
+
const directory = path.resolve(configDir);
|
|
372
|
+
return path.resolve(directory, rawDir);
|
|
373
|
+
} else {
|
|
374
|
+
return rawDir;
|
|
375
|
+
}
|
|
376
|
+
} else {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
361
381
|
/**
|
|
362
382
|
* Validate the `dev` configuration and return the normalized values.
|
|
363
383
|
*/
|
|
@@ -1011,6 +1031,17 @@ function normalizeAndValidateEnvironment(
|
|
|
1011
1031
|
),
|
|
1012
1032
|
deprecatedUpload
|
|
1013
1033
|
),
|
|
1034
|
+
base_dir: normalizeAndValidateBaseDirField(
|
|
1035
|
+
configPath,
|
|
1036
|
+
inheritable(
|
|
1037
|
+
diagnostics,
|
|
1038
|
+
topLevelEnv,
|
|
1039
|
+
rawEnv,
|
|
1040
|
+
"base_dir",
|
|
1041
|
+
isString,
|
|
1042
|
+
undefined
|
|
1043
|
+
)
|
|
1044
|
+
),
|
|
1014
1045
|
route,
|
|
1015
1046
|
routes,
|
|
1016
1047
|
triggers: inheritable(
|
|
@@ -1074,6 +1105,16 @@ function normalizeAndValidateEnvironment(
|
|
|
1074
1105
|
validateBindingArray(envName, validateKVBinding),
|
|
1075
1106
|
[]
|
|
1076
1107
|
),
|
|
1108
|
+
send_email: notInheritable(
|
|
1109
|
+
diagnostics,
|
|
1110
|
+
topLevelEnv,
|
|
1111
|
+
rawConfig,
|
|
1112
|
+
rawEnv,
|
|
1113
|
+
envName,
|
|
1114
|
+
"send_email",
|
|
1115
|
+
validateBindingArray(envName, validateSendEmailBinding),
|
|
1116
|
+
[]
|
|
1117
|
+
),
|
|
1077
1118
|
queues: notInheritable(
|
|
1078
1119
|
diagnostics,
|
|
1079
1120
|
topLevelEnv,
|
|
@@ -1162,10 +1203,8 @@ function normalizeAndValidateEnvironment(
|
|
|
1162
1203
|
rawEnv,
|
|
1163
1204
|
envName,
|
|
1164
1205
|
"unsafe",
|
|
1165
|
-
|
|
1166
|
-
{
|
|
1167
|
-
bindings: [],
|
|
1168
|
-
}
|
|
1206
|
+
validateUnsafeSettings(envName),
|
|
1207
|
+
{}
|
|
1169
1208
|
),
|
|
1170
1209
|
zone_id: rawEnv.zone_id,
|
|
1171
1210
|
no_bundle: inheritable(
|
|
@@ -1495,6 +1534,62 @@ const validateBindingsProperty =
|
|
|
1495
1534
|
return isValid;
|
|
1496
1535
|
};
|
|
1497
1536
|
|
|
1537
|
+
const validateUnsafeSettings =
|
|
1538
|
+
(envName: string): ValidatorFn =>
|
|
1539
|
+
(diagnostics, field, value, config) => {
|
|
1540
|
+
const fieldPath =
|
|
1541
|
+
config === undefined ? `${field}` : `env.${envName}.${field}`;
|
|
1542
|
+
|
|
1543
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1544
|
+
diagnostics.errors.push(
|
|
1545
|
+
`The field "${fieldPath}" should be an object but got ${JSON.stringify(
|
|
1546
|
+
value
|
|
1547
|
+
)}.`
|
|
1548
|
+
);
|
|
1549
|
+
return false;
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
// At least one of bindings and metadata must exist
|
|
1553
|
+
if (!hasProperty(value, "bindings") && !hasProperty(value, "metadata")) {
|
|
1554
|
+
diagnostics.errors.push(
|
|
1555
|
+
`The field "${fieldPath}" should contain at least one of "bindings" or "metadata" properties but got ${JSON.stringify(
|
|
1556
|
+
value
|
|
1557
|
+
)}.`
|
|
1558
|
+
);
|
|
1559
|
+
return false;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// unsafe.bindings
|
|
1563
|
+
if (hasProperty(value, "bindings") && value.bindings !== undefined) {
|
|
1564
|
+
const validateBindingsFn = validateBindingsProperty(
|
|
1565
|
+
envName,
|
|
1566
|
+
validateUnsafeBinding
|
|
1567
|
+
);
|
|
1568
|
+
const valid = validateBindingsFn(diagnostics, field, value, config);
|
|
1569
|
+
if (!valid) {
|
|
1570
|
+
return false;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
// unsafe.metadata
|
|
1575
|
+
if (
|
|
1576
|
+
hasProperty(value, "metadata") &&
|
|
1577
|
+
value.metadata !== undefined &&
|
|
1578
|
+
(typeof value.metadata !== "object" ||
|
|
1579
|
+
value.metadata === null ||
|
|
1580
|
+
Array.isArray(value.metadata))
|
|
1581
|
+
) {
|
|
1582
|
+
diagnostics.errors.push(
|
|
1583
|
+
`The field "${fieldPath}.metadata" should be an object but got ${JSON.stringify(
|
|
1584
|
+
value.metadata
|
|
1585
|
+
)}.`
|
|
1586
|
+
);
|
|
1587
|
+
return false;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
return true;
|
|
1591
|
+
};
|
|
1592
|
+
|
|
1498
1593
|
/**
|
|
1499
1594
|
* Check that the given field is a valid "durable_object" binding object.
|
|
1500
1595
|
*/
|
|
@@ -1711,6 +1806,53 @@ const validateKVBinding: ValidatorFn = (diagnostics, field, value) => {
|
|
|
1711
1806
|
return isValid;
|
|
1712
1807
|
};
|
|
1713
1808
|
|
|
1809
|
+
const validateSendEmailBinding: ValidatorFn = (diagnostics, field, value) => {
|
|
1810
|
+
if (typeof value !== "object" || value === null) {
|
|
1811
|
+
diagnostics.errors.push(
|
|
1812
|
+
`"send_email" bindings should be objects, but got ${JSON.stringify(
|
|
1813
|
+
value
|
|
1814
|
+
)}`
|
|
1815
|
+
);
|
|
1816
|
+
return false;
|
|
1817
|
+
}
|
|
1818
|
+
let isValid = true;
|
|
1819
|
+
// send email bindings must have a name.
|
|
1820
|
+
if (!isRequiredProperty(value, "name", "string")) {
|
|
1821
|
+
diagnostics.errors.push(
|
|
1822
|
+
`"${field}" bindings should have a string "name" field but got ${JSON.stringify(
|
|
1823
|
+
value
|
|
1824
|
+
)}.`
|
|
1825
|
+
);
|
|
1826
|
+
isValid = false;
|
|
1827
|
+
}
|
|
1828
|
+
if (!isOptionalProperty(value, "destination_address", "string")) {
|
|
1829
|
+
diagnostics.errors.push(
|
|
1830
|
+
`"${field}" bindings should, optionally, have a string "destination_address" field but got ${JSON.stringify(
|
|
1831
|
+
value
|
|
1832
|
+
)}.`
|
|
1833
|
+
);
|
|
1834
|
+
isValid = false;
|
|
1835
|
+
}
|
|
1836
|
+
if (!isOptionalProperty(value, "allowed_destination_addresses", "object")) {
|
|
1837
|
+
diagnostics.errors.push(
|
|
1838
|
+
`"${field}" bindings should, optionally, have a []string "allowed_destination_addresses" field but got ${JSON.stringify(
|
|
1839
|
+
value
|
|
1840
|
+
)}.`
|
|
1841
|
+
);
|
|
1842
|
+
isValid = false;
|
|
1843
|
+
}
|
|
1844
|
+
if (
|
|
1845
|
+
"destination_address" in value &&
|
|
1846
|
+
"allowed_destination_addresses" in value
|
|
1847
|
+
) {
|
|
1848
|
+
diagnostics.errors.push(
|
|
1849
|
+
`"${field}" bindings should have either a "destination_address" or "allowed_destination_addresses" field, but not both.`
|
|
1850
|
+
);
|
|
1851
|
+
isValid = false;
|
|
1852
|
+
}
|
|
1853
|
+
return isValid;
|
|
1854
|
+
};
|
|
1855
|
+
|
|
1714
1856
|
const validateQueueBinding: ValidatorFn = (diagnostics, field, value) => {
|
|
1715
1857
|
if (typeof value !== "object" || value === null) {
|
|
1716
1858
|
diagnostics.errors.push(
|
|
@@ -2161,6 +2303,7 @@ const validateConsumer: ValidatorFn = (diagnostics, field, value, _config) => {
|
|
|
2161
2303
|
"max_batch_timeout",
|
|
2162
2304
|
"max_retries",
|
|
2163
2305
|
"dead_letter_queue",
|
|
2306
|
+
"max_concurrency",
|
|
2164
2307
|
])
|
|
2165
2308
|
) {
|
|
2166
2309
|
isValid = false;
|
|
@@ -2176,12 +2319,13 @@ const validateConsumer: ValidatorFn = (diagnostics, field, value, _config) => {
|
|
|
2176
2319
|
|
|
2177
2320
|
const options: {
|
|
2178
2321
|
key: string;
|
|
2179
|
-
type: "number" | "string";
|
|
2322
|
+
type: "number" | "string" | "boolean";
|
|
2180
2323
|
}[] = [
|
|
2181
2324
|
{ key: "max_batch_size", type: "number" },
|
|
2182
2325
|
{ key: "max_batch_timeout", type: "number" },
|
|
2183
2326
|
{ key: "max_retries", type: "number" },
|
|
2184
2327
|
{ key: "dead_letter_queue", type: "string" },
|
|
2328
|
+
{ key: "max_concurrency", type: "number" },
|
|
2185
2329
|
];
|
|
2186
2330
|
for (const optionalOpt of options) {
|
|
2187
2331
|
if (!isOptionalProperty(value, optionalOpt.key, optionalOpt.type)) {
|
|
@@ -23,7 +23,7 @@ export function toMimeType(type: CfModuleType): string {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
type WorkerMetadataBinding =
|
|
26
|
+
export type WorkerMetadataBinding =
|
|
27
27
|
// If you add any new binding types here, also add it to safeBindings
|
|
28
28
|
// under validateUnsafeBinding in config/validation.ts
|
|
29
29
|
| { type: "plain_text"; name: string; text: string }
|
|
@@ -32,6 +32,12 @@ type WorkerMetadataBinding =
|
|
|
32
32
|
| { type: "text_blob"; name: string; part: string }
|
|
33
33
|
| { type: "data_blob"; name: string; part: string }
|
|
34
34
|
| { type: "kv_namespace"; name: string; namespace_id: string }
|
|
35
|
+
| {
|
|
36
|
+
type: "send_email";
|
|
37
|
+
name: string;
|
|
38
|
+
destination_address?: string;
|
|
39
|
+
allowed_destination_addresses?: string[];
|
|
40
|
+
}
|
|
35
41
|
| {
|
|
36
42
|
type: "durable_object_namespace";
|
|
37
43
|
name: string;
|
|
@@ -65,6 +71,8 @@ export interface WorkerMetadata {
|
|
|
65
71
|
bindings: WorkerMetadataBinding[];
|
|
66
72
|
keep_bindings?: WorkerMetadataBinding["type"][];
|
|
67
73
|
logpush?: boolean;
|
|
74
|
+
// Allow unsafe.metadata to add arbitary properties at runtime
|
|
75
|
+
[key: string]: unknown;
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
/**
|
|
@@ -103,6 +111,17 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
103
111
|
});
|
|
104
112
|
});
|
|
105
113
|
|
|
114
|
+
bindings.send_email?.forEach(
|
|
115
|
+
({ name, destination_address, allowed_destination_addresses }) => {
|
|
116
|
+
metadataBindings.push({
|
|
117
|
+
name: name,
|
|
118
|
+
type: "send_email",
|
|
119
|
+
destination_address,
|
|
120
|
+
allowed_destination_addresses,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
|
|
106
125
|
bindings.durable_objects?.bindings.forEach(
|
|
107
126
|
({ name, class_name, script_name, environment }) => {
|
|
108
127
|
metadataBindings.push({
|
|
@@ -284,9 +303,9 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
284
303
|
}
|
|
285
304
|
}
|
|
286
305
|
|
|
287
|
-
if (bindings.unsafe) {
|
|
306
|
+
if (bindings.unsafe?.bindings) {
|
|
288
307
|
// @ts-expect-error unsafe bindings don't need to match a specific type here
|
|
289
|
-
metadataBindings.push(...bindings.unsafe);
|
|
308
|
+
metadataBindings.push(...bindings.unsafe.bindings);
|
|
290
309
|
}
|
|
291
310
|
|
|
292
311
|
const metadata: WorkerMetadata = {
|
|
@@ -303,6 +322,12 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
303
322
|
...(logpush !== undefined && { logpush }),
|
|
304
323
|
};
|
|
305
324
|
|
|
325
|
+
if (bindings.unsafe?.metadata !== undefined) {
|
|
326
|
+
for (const key of Object.keys(bindings.unsafe.metadata)) {
|
|
327
|
+
metadata[key] = bindings.unsafe.metadata[key];
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
306
331
|
formData.set("metadata", JSON.stringify(metadata));
|
|
307
332
|
|
|
308
333
|
if (main.type === "commonjs" && modules && modules.length > 0) {
|
package/src/d1/backups.tsx
CHANGED
|
@@ -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,6 +7,7 @@ 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";
|
|
@@ -33,11 +33,13 @@ export const ListHandler = withConfig<ListHandlerOptions>(
|
|
|
33
33
|
);
|
|
34
34
|
|
|
35
35
|
const backups: Backup[] = await listBackups(accountId, db.uuid);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
logger.log(
|
|
37
|
+
renderToString(
|
|
38
|
+
<Table
|
|
39
|
+
data={backups}
|
|
40
|
+
columns={["created_at", "id", "num_tables", "size"]}
|
|
41
|
+
></Table>
|
|
42
|
+
)
|
|
41
43
|
);
|
|
42
44
|
}
|
|
43
45
|
);
|
|
@@ -94,11 +96,13 @@ export const CreateHandler = withConfig<CreateHandlerOptions>(
|
|
|
94
96
|
);
|
|
95
97
|
|
|
96
98
|
const backup: Backup = await createBackup(accountId, db.uuid);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
);
|
package/src/d1/create.tsx
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Text, Box } from "ink";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { fetchResult } from "../cfetch";
|
|
4
4
|
import { logger } from "../logger";
|
|
5
5
|
import { requireAuth } from "../user";
|
|
6
|
+
import { renderToString } from "../utils/render";
|
|
6
7
|
import { d1BetaWarning } from "./utils";
|
|
7
8
|
import type {
|
|
8
9
|
CommonYargsArgv,
|
|
@@ -45,20 +46,23 @@ export async function Handler({
|
|
|
45
46
|
throw e;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
logger.log(
|
|
50
|
+
renderToString(
|
|
51
|
+
<Box flexDirection="column">
|
|
52
|
+
<Text>✅ Successfully created DB '{db.name}'!</Text>
|
|
53
|
+
<Text> </Text>
|
|
54
|
+
<Text>
|
|
55
|
+
Add the following to your wrangler.toml to connect to it from a
|
|
56
|
+
Worker:
|
|
57
|
+
</Text>
|
|
58
|
+
<Text> </Text>
|
|
59
|
+
<Text>[[ d1_databases ]]</Text>
|
|
60
|
+
<Text>
|
|
61
|
+
binding = "DB" # i.e. available in your Worker on env.DB
|
|
62
|
+
</Text>
|
|
63
|
+
<Text>database_name = "{db.name}"</Text>
|
|
64
|
+
<Text>database_id = "{db.uuid}"</Text>
|
|
65
|
+
</Box>
|
|
66
|
+
)
|
|
63
67
|
);
|
|
64
68
|
}
|
package/src/d1/execute.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { mkdir } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import chalk from "chalk";
|
|
5
|
-
import {
|
|
5
|
+
import { Static, Text } from "ink";
|
|
6
6
|
import Table from "ink-table";
|
|
7
7
|
import { npxImport } from "npx-import";
|
|
8
8
|
import React from "react";
|
|
@@ -14,6 +14,7 @@ import { logger } from "../logger";
|
|
|
14
14
|
import { readFileSync } from "../parse";
|
|
15
15
|
import { readableRelative } from "../paths";
|
|
16
16
|
import { requireAuth } from "../user";
|
|
17
|
+
import { renderToString } from "../utils/render";
|
|
17
18
|
import * as options from "./options";
|
|
18
19
|
import splitSqlQuery from "./splitter";
|
|
19
20
|
import {
|
|
@@ -36,7 +37,7 @@ export type QueryResult = {
|
|
|
36
37
|
};
|
|
37
38
|
query?: string;
|
|
38
39
|
};
|
|
39
|
-
// Max number of
|
|
40
|
+
// Max number of statements to send in a single /execute call
|
|
40
41
|
const QUERY_LIMIT = 10_000;
|
|
41
42
|
|
|
42
43
|
export function Options(yargs: CommonYargsArgv) {
|
|
@@ -110,25 +111,27 @@ export const Handler = async (args: HandlerOptions): Promise<void> => {
|
|
|
110
111
|
|
|
111
112
|
if (isInteractive && !json) {
|
|
112
113
|
// Render table if single result
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
logger.log(
|
|
115
|
+
renderToString(
|
|
116
|
+
<Static items={response}>
|
|
117
|
+
{(result) => {
|
|
118
|
+
// batch results
|
|
119
|
+
if (!Array.isArray(result)) {
|
|
120
|
+
const { results, query } = result;
|
|
119
121
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
if (Array.isArray(results) && results.length > 0) {
|
|
123
|
+
const shortQuery = shorten(query, 48);
|
|
124
|
+
return (
|
|
125
|
+
<>
|
|
126
|
+
{shortQuery ? <Text dimColor>{shortQuery}</Text> : null}
|
|
127
|
+
<Table data={results}></Table>
|
|
128
|
+
</>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
128
131
|
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
}}
|
|
133
|
+
</Static>
|
|
134
|
+
)
|
|
132
135
|
);
|
|
133
136
|
} else {
|
|
134
137
|
// set loggerLevel back to what it was before to actually output the JSON in stdout
|
package/src/d1/list.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { render } from "ink";
|
|
2
1
|
import Table from "ink-table";
|
|
3
2
|
import React from "react";
|
|
4
3
|
import { fetchResult } from "../cfetch";
|
|
5
4
|
import { logger } from "../logger";
|
|
6
5
|
import { requireAuth } from "../user";
|
|
6
|
+
import { renderToString } from "../utils/render";
|
|
7
7
|
import { d1BetaWarning } from "./utils";
|
|
8
8
|
import type {
|
|
9
9
|
CommonYargsArgv,
|
|
@@ -31,7 +31,7 @@ export async function Handler({
|
|
|
31
31
|
logger.log(JSON.stringify(dbs, null, 2));
|
|
32
32
|
} else {
|
|
33
33
|
logger.log(d1BetaWarning);
|
|
34
|
-
|
|
34
|
+
logger.log(renderToString(<Table data={dbs}></Table>));
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { Box,
|
|
4
|
+
import { Box, Text } from "ink";
|
|
5
5
|
import Table from "ink-table";
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { withConfig } from "../../config";
|
|
@@ -10,6 +10,7 @@ import { CI } from "../../is-ci";
|
|
|
10
10
|
import isInteractive from "../../is-interactive";
|
|
11
11
|
import { logger } from "../../logger";
|
|
12
12
|
import { requireAuth } from "../../user";
|
|
13
|
+
import { renderToString } from "../../utils/render";
|
|
13
14
|
import { createBackup } from "../backups";
|
|
14
15
|
import { DEFAULT_MIGRATION_PATH, DEFAULT_MIGRATION_TABLE } from "../constants";
|
|
15
16
|
import { executeSql } from "../execute";
|
|
@@ -97,14 +98,16 @@ export const ApplyHandler = withConfig<ApplyHandlerOptions>(
|
|
|
97
98
|
});
|
|
98
99
|
|
|
99
100
|
if (unappliedMigrations.length === 0) {
|
|
100
|
-
|
|
101
|
+
logger.log(renderToString(<Text>✅ No migrations to apply!</Text>));
|
|
101
102
|
return;
|
|
102
103
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
logger.log(
|
|
105
|
+
renderToString(
|
|
106
|
+
<Box flexDirection="column">
|
|
107
|
+
<Text>Migrations to be applied:</Text>
|
|
108
|
+
<Table data={unappliedMigrations} columns={["Name"]}></Table>
|
|
109
|
+
</Box>
|
|
110
|
+
)
|
|
108
111
|
);
|
|
109
112
|
const ok = await confirm(
|
|
110
113
|
`About to apply ${unappliedMigrations.length} migration(s)
|
|
@@ -118,7 +121,7 @@ Your database may not be available to serve requests during the migration, conti
|
|
|
118
121
|
databaseInfo,
|
|
119
122
|
"In non-local mode `databaseInfo` should be defined."
|
|
120
123
|
);
|
|
121
|
-
|
|
124
|
+
logger.log(renderToString(<Text>🕒 Creating backup...</Text>));
|
|
122
125
|
const accountId = await requireAuth({});
|
|
123
126
|
await createBackup(accountId, databaseInfo.uuid);
|
|
124
127
|
}
|
|
@@ -169,35 +172,38 @@ Your database may not be available to serve requests during the migration, conti
|
|
|
169
172
|
}
|
|
170
173
|
} catch (e) {
|
|
171
174
|
const err = e as ParseError;
|
|
175
|
+
const maybeCause = (err.cause ?? err) as Error;
|
|
172
176
|
|
|
173
177
|
success = false;
|
|
174
178
|
errorNotes = err.notes?.map((msg) => msg.text) ?? [
|
|
175
|
-
|
|
179
|
+
maybeCause?.message ?? maybeCause.toString(),
|
|
176
180
|
];
|
|
177
181
|
}
|
|
178
182
|
|
|
179
183
|
migration.Status = success ? "✅" : "❌";
|
|
180
184
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
<
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
185
|
+
logger.log(
|
|
186
|
+
renderToString(
|
|
187
|
+
<Box flexDirection="column">
|
|
188
|
+
<Table
|
|
189
|
+
data={unappliedMigrations}
|
|
190
|
+
columns={["Name", "Status"]}
|
|
191
|
+
></Table>
|
|
192
|
+
{errorNotes.length > 0 && (
|
|
193
|
+
<Box flexDirection="column">
|
|
194
|
+
<Text> </Text>
|
|
195
|
+
<Text>
|
|
196
|
+
❌ Migration {migration.Name} failed with following Errors
|
|
197
|
+
</Text>
|
|
198
|
+
<Table
|
|
199
|
+
data={errorNotes.map((err) => {
|
|
200
|
+
return { Error: err };
|
|
201
|
+
})}
|
|
202
|
+
></Table>
|
|
203
|
+
</Box>
|
|
204
|
+
)}
|
|
205
|
+
</Box>
|
|
206
|
+
)
|
|
201
207
|
);
|
|
202
208
|
|
|
203
209
|
if (errorNotes.length > 0) return;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { Box,
|
|
3
|
+
import { Box, Text } from "ink";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { withConfig } from "../../config";
|
|
6
6
|
import { logger } from "../../logger";
|
|
7
|
+
import { renderToString } from "../../utils/render";
|
|
7
8
|
import { DEFAULT_MIGRATION_PATH } from "../constants";
|
|
8
9
|
import { Database } from "../options";
|
|
9
10
|
import { d1BetaWarning, getDatabaseInfoFromConfig } from "../utils";
|
|
@@ -54,17 +55,19 @@ export const CreateHandler = withConfig<CreateHandlerOptions>(
|
|
|
54
55
|
`-- Migration number: ${nextMigrationNumber} \t ${new Date().toISOString()}\n`
|
|
55
56
|
);
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
logger.log(
|
|
59
|
+
renderToString(
|
|
60
|
+
<Box flexDirection="column">
|
|
61
|
+
<Text>
|
|
62
|
+
✅ Successfully created Migration '{newMigrationName}'!
|
|
63
|
+
</Text>
|
|
64
|
+
<Text> </Text>
|
|
65
|
+
<Text>The migration is available for editing here</Text>
|
|
66
|
+
<Text>
|
|
67
|
+
{migrationsPath}/{newMigrationName}
|
|
68
|
+
</Text>
|
|
69
|
+
</Box>
|
|
70
|
+
)
|
|
68
71
|
);
|
|
69
72
|
}
|
|
70
73
|
);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import { Box,
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
3
|
import Table from "ink-table";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { withConfig } from "../../config";
|
|
6
6
|
import { logger } from "../../logger";
|
|
7
7
|
import { requireAuth } from "../../user";
|
|
8
|
+
import { renderToString } from "../../utils/render";
|
|
8
9
|
import { DEFAULT_MIGRATION_PATH, DEFAULT_MIGRATION_TABLE } from "../constants";
|
|
9
10
|
import { d1BetaWarning, getDatabaseInfoFromConfig } from "../utils";
|
|
10
11
|
import {
|
|
@@ -78,15 +79,17 @@ export const ListHandler = withConfig<ListHandlerOptions>(
|
|
|
78
79
|
});
|
|
79
80
|
|
|
80
81
|
if (unappliedMigrations.length === 0) {
|
|
81
|
-
|
|
82
|
+
logger.log(renderToString(<Text>✅ No migrations to apply!</Text>));
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
logger.log(
|
|
87
|
+
renderToString(
|
|
88
|
+
<Box flexDirection="column">
|
|
89
|
+
<Text>Migrations to be applied:</Text>
|
|
90
|
+
<Table data={unappliedMigrations} columns={["Name"]}></Table>
|
|
91
|
+
</Box>
|
|
92
|
+
)
|
|
90
93
|
);
|
|
91
94
|
}
|
|
92
95
|
);
|