wrangler 0.0.0-e7a0cd5b → 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/README.md +3 -3
- package/bin/wrangler.js +30 -10
- package/miniflare-dist/index.mjs +126 -74
- package/package.json +27 -19
- package/src/__tests__/api-dev.test.ts +65 -36
- package/src/__tests__/api-devregistry.test.ts +121 -0
- package/src/__tests__/api.test.ts +27 -5
- package/src/__tests__/configuration.test.ts +567 -86
- package/src/__tests__/d1/d1.test.ts +82 -0
- package/src/__tests__/d1/execute.test.ts +66 -0
- package/src/__tests__/d1/migrate.test.ts +157 -0
- package/src/__tests__/d1/splitter.test.ts +255 -0
- package/src/__tests__/delete.test.ts +91 -49
- package/src/__tests__/deployments.test.ts +330 -56
- package/src/__tests__/dev.test.tsx +198 -90
- package/src/__tests__/generate.test.ts +12 -10
- package/src/__tests__/guess-worker-format.test.ts +35 -0
- package/src/__tests__/helpers/end-event-loop.ts +6 -0
- package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
- package/src/__tests__/helpers/mock-console.ts +6 -0
- package/src/__tests__/helpers/mock-dialogs.ts +71 -85
- package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
- package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -5
- package/src/__tests__/helpers/mock-known-routes.ts +7 -2
- package/src/__tests__/helpers/mock-kv.ts +29 -16
- package/src/__tests__/helpers/mock-oauth-flow.ts +103 -92
- package/src/__tests__/helpers/mock-process.ts +8 -13
- package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
- package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +128 -27
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +18 -41
- package/src/__tests__/helpers/msw/handlers/oauth.ts +13 -18
- package/src/__tests__/helpers/msw/handlers/r2.ts +14 -34
- package/src/__tests__/helpers/msw/handlers/script.ts +9 -28
- package/src/__tests__/helpers/msw/handlers/user.ts +13 -24
- package/src/__tests__/helpers/msw/handlers/zones.ts +6 -8
- package/src/__tests__/helpers/msw/index.ts +32 -1
- package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
- package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
- package/src/__tests__/helpers/worker-scripts/parent-worker.js +4 -1
- package/src/__tests__/index.test.ts +90 -72
- package/src/__tests__/init.test.ts +927 -631
- package/src/__tests__/jest.setup.ts +19 -42
- package/src/__tests__/kv.test.ts +355 -231
- package/src/__tests__/logger.test.ts +68 -2
- package/src/__tests__/logout.test.ts +47 -0
- package/src/__tests__/metrics.test.ts +94 -51
- package/src/__tests__/middleware.scheduled.test.ts +42 -32
- package/src/__tests__/middleware.test.ts +212 -122
- package/src/__tests__/mtls-certificates.test.ts +588 -0
- package/src/__tests__/pages/deployment-list.test.ts +80 -0
- package/src/__tests__/pages/functions-build.test.ts +452 -0
- package/src/__tests__/pages/pages.test.ts +81 -0
- package/src/__tests__/pages/project-create.test.ts +63 -0
- package/src/__tests__/pages/project-list.test.ts +110 -0
- package/src/__tests__/pages/project-upload.test.ts +500 -0
- package/src/__tests__/pages/publish.test.ts +2864 -0
- package/src/__tests__/pages-deployment-tail.test.ts +955 -0
- package/src/__tests__/parse.test.ts +106 -0
- package/src/__tests__/publish.test.ts +1615 -852
- package/src/__tests__/pubsub.test.ts +226 -100
- package/src/__tests__/queues.test.ts +238 -77
- package/src/__tests__/r2.test.ts +55 -57
- package/src/__tests__/secret.test.ts +179 -130
- package/src/__tests__/tail.test.ts +267 -109
- package/src/__tests__/test-old-node-version.js +3 -3
- package/src/__tests__/traverse-module-graph.test.ts +220 -0
- package/src/__tests__/tsconfig-sanity.ts +12 -0
- package/src/__tests__/tsconfig.json +8 -0
- package/src/__tests__/tsconfig.tsbuildinfo +1 -0
- package/src/__tests__/type-generation.test.ts +43 -26
- package/src/__tests__/user.test.ts +35 -72
- package/src/__tests__/whoami.test.tsx +8 -114
- package/src/__tests__/worker-namespace.test.ts +83 -69
- package/src/api/dev.ts +168 -60
- package/src/api/index.ts +10 -1
- package/src/api/mtls-certificate.ts +148 -0
- package/src/api/pages/create-worker-bundle-contents.ts +76 -0
- package/src/api/pages/index.ts +5 -0
- package/src/api/pages/publish.tsx +355 -0
- package/src/bundle.ts +263 -140
- package/src/cfetch/index.ts +0 -2
- package/src/cfetch/internal.ts +16 -21
- package/src/cli.ts +4 -4
- package/src/config/config.ts +14 -7
- package/src/config/environment.ts +79 -24
- package/src/config/index.ts +99 -38
- package/src/config/validation-helpers.ts +1 -1
- package/src/config/validation.ts +248 -19
- package/src/create-worker-preview.ts +19 -8
- package/src/create-worker-upload-form.ts +60 -22
- package/src/d1/backups.tsx +43 -42
- package/src/d1/constants.ts +2 -0
- package/src/d1/create.tsx +44 -30
- package/src/d1/{delete.tsx → delete.ts} +11 -14
- package/src/d1/execute.tsx +209 -151
- package/src/d1/index.ts +31 -7
- package/src/d1/list.tsx +22 -10
- package/src/d1/migrations/apply.tsx +212 -0
- package/src/d1/migrations/create.tsx +79 -0
- package/src/d1/migrations/helpers.ts +172 -0
- package/src/d1/migrations/index.ts +3 -0
- package/src/d1/migrations/list.tsx +95 -0
- package/src/d1/migrations/options.ts +23 -0
- package/src/d1/options.ts +12 -2
- package/src/d1/splitter.ts +161 -0
- package/src/d1/{types.tsx → types.ts} +11 -0
- package/src/d1/utils.ts +12 -2
- package/src/delete.ts +8 -16
- package/src/deployments.ts +340 -46
- package/src/deprecated/index.ts +8 -302
- package/src/dev/dev.tsx +57 -44
- package/src/dev/local.tsx +294 -91
- package/src/dev/remote.tsx +32 -3
- package/src/dev/start-server.ts +89 -68
- package/src/dev/use-esbuild.ts +17 -18
- package/src/dev/validate-dev-props.ts +9 -0
- package/src/{dev-registry.tsx → dev-registry.ts} +2 -1
- package/src/dev.tsx +178 -118
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +21 -17
- package/src/docs/index.ts +97 -0
- package/src/entry.ts +19 -11
- package/src/environment-variables/factory.ts +88 -0
- package/src/environment-variables/misc-variables.ts +30 -0
- package/src/generate/index.ts +298 -0
- package/src/git-client.ts +15 -4
- package/src/{index.tsx → index.ts} +137 -63
- package/src/init.ts +249 -187
- package/src/inspect.ts +16 -1
- package/src/jest.d.ts +4 -0
- package/src/kv/index.ts +15 -17
- package/src/logger.ts +32 -5
- package/src/metrics/metrics-config.ts +3 -3
- package/src/metrics/send-event.ts +6 -1
- package/src/miniflare-cli/assets.ts +64 -28
- package/src/miniflare-cli/index.ts +4 -7
- package/src/miniflare-cli/tsconfig.json +9 -0
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
- package/src/miniflare-cli/types.ts +11 -0
- package/src/module-collection.ts +91 -25
- package/src/mtls-certificate/cli.ts +155 -0
- package/src/pages/build.ts +410 -0
- package/src/pages/buildFunctions.ts +140 -0
- package/src/pages/deployment-tails.ts +281 -0
- package/src/pages/deployments.tsx +11 -33
- package/src/pages/{dev.tsx → dev.ts} +147 -124
- package/src/pages/errors.ts +1 -0
- package/src/pages/functions/buildPlugin.ts +72 -69
- package/src/pages/functions/buildWorker.ts +249 -114
- package/src/pages/functions/tsconfig.json +8 -0
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
- package/src/pages/{functions.tsx → functions.ts} +8 -4
- package/src/pages/{index.tsx → index.ts} +11 -3
- package/src/pages/projects.tsx +12 -22
- package/src/pages/prompt-select-project.tsx +31 -0
- package/src/pages/publish.tsx +45 -214
- package/src/pages/types.ts +6 -9
- package/src/pages/upload.tsx +58 -14
- package/src/pages/utils.ts +14 -3
- package/src/parse.ts +23 -1
- package/src/paths.ts +1 -1
- package/src/proxy.ts +5 -0
- package/src/publish/index.ts +20 -16
- package/src/publish/publish.ts +72 -47
- package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +19 -20
- package/src/queues/cli/commands/consumer/add.ts +24 -24
- package/src/queues/cli/commands/consumer/index.ts +3 -6
- package/src/queues/cli/commands/consumer/remove.ts +11 -18
- package/src/queues/cli/commands/create.ts +8 -8
- package/src/queues/cli/commands/delete.ts +8 -8
- package/src/queues/cli/commands/index.ts +6 -4
- package/src/queues/cli/commands/list.ts +8 -8
- package/src/queues/client.ts +1 -0
- package/src/queues/utils.ts +18 -0
- package/src/r2/constants.ts +4 -0
- package/src/r2/helpers.ts +1 -0
- package/src/r2/index.ts +40 -28
- package/src/secret/index.ts +14 -17
- package/src/{sites.tsx → sites.ts} +1 -1
- package/src/tail/createTail.ts +94 -3
- package/src/tail/filters.ts +1 -1
- package/src/tail/index.ts +8 -11
- package/src/tail/printing.ts +15 -0
- package/src/traverse-module-graph.ts +53 -0
- package/src/tsconfig-sanity.ts +16 -0
- package/src/type-generation.ts +79 -57
- package/src/user/access.ts +0 -1
- package/src/user/auth-variables.ts +113 -0
- package/src/user/choose-account.tsx +1 -31
- package/src/user/index.ts +0 -1
- package/src/user/{user.tsx → user.ts} +123 -82
- package/src/utils/render.ts +93 -0
- package/src/{whoami.tsx → whoami.ts} +37 -71
- package/src/worker.ts +35 -3
- package/src/yargs-types.ts +22 -5
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
- package/templates/checked-fetch.js +9 -3
- package/templates/d1-beta-facade.js +95 -25
- package/templates/facade.d.ts +14 -0
- package/templates/first-party-worker-module-facade.ts +4 -3
- package/templates/format-dev-errors.ts +8 -6
- package/templates/gitignore +1 -0
- package/templates/init-tests/test-jest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.ts +25 -0
- package/templates/middleware/loader-modules.ts +2 -2
- package/templates/middleware/loader-sw.ts +51 -31
- package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
- package/templates/new-worker.ts +3 -0
- package/templates/pages-dev-pipeline.ts +4 -1
- package/templates/pages-shim.ts +4 -1
- package/templates/pages-template-plugin.ts +19 -10
- package/templates/serve-static-assets.ts +17 -14
- package/templates/service-bindings-module-facade.js +1 -0
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +105 -0
- package/templates/tsconfig.json +5 -103
- package/templates/tsconfig.tsbuildinfo +1 -0
- package/wrangler-dist/cli.d.ts +826 -77
- package/wrangler-dist/cli.js +130734 -140838
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/src/__tests__/api-devregistry.test.js +0 -57
- package/src/__tests__/d1.test.ts +0 -72
- package/src/__tests__/dialogs.test.tsx +0 -40
- package/src/__tests__/helpers/mock-cfetch.ts +0 -333
- package/src/__tests__/pages.test.ts +0 -2223
- package/src/dialogs.tsx +0 -163
- package/src/environment-variables.ts +0 -50
- package/src/pages/build.tsx +0 -238
- package/src/user/env-vars.ts +0 -46
- package/templates/experimental-local-cache-stubs.js +0 -27
- /package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
- /package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
- /package/src/pages/{hash.tsx → hash.ts} +0 -0
package/src/d1/execute.tsx
CHANGED
|
@@ -1,67 +1,60 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { mkdir } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { Static, Text } from "ink";
|
|
5
6
|
import Table from "ink-table";
|
|
6
7
|
import { npxImport } from "npx-import";
|
|
7
8
|
import React from "react";
|
|
8
9
|
import { fetchResult } from "../cfetch";
|
|
9
|
-
import {
|
|
10
|
+
import { readConfig } from "../config";
|
|
10
11
|
import { getLocalPersistencePath } from "../dev/get-local-persistence-path";
|
|
11
|
-
import { confirm
|
|
12
|
+
import { confirm } from "../dialogs";
|
|
12
13
|
import { logger } from "../logger";
|
|
14
|
+
import { readFileSync } from "../parse";
|
|
13
15
|
import { readableRelative } from "../paths";
|
|
14
16
|
import { requireAuth } from "../user";
|
|
15
|
-
import {
|
|
17
|
+
import { renderToString } from "../utils/render";
|
|
18
|
+
import * as options from "./options";
|
|
19
|
+
import splitSqlQuery from "./splitter";
|
|
16
20
|
import {
|
|
17
21
|
d1BetaWarning,
|
|
18
22
|
getDatabaseByNameOrBinding,
|
|
19
23
|
getDatabaseInfoFromConfig,
|
|
20
24
|
} from "./utils";
|
|
21
|
-
import type { Config } from "../config";
|
|
25
|
+
import type { Config, ConfigFields, DevConfig, Environment } from "../config";
|
|
26
|
+
import type {
|
|
27
|
+
CommonYargsArgv,
|
|
28
|
+
StrictYargsOptionsToInterface,
|
|
29
|
+
} from "../yargs-types";
|
|
22
30
|
import type { Database } from "./types";
|
|
23
|
-
import type splitSqlQuery from "@databases/split-sql-query";
|
|
24
|
-
import type { SQL, SQLQuery } from "@databases/sql";
|
|
25
|
-
import type { Statement as StatementType } from "@miniflare/d1";
|
|
26
|
-
import type { createSQLiteDB as createSQLiteDBType } from "@miniflare/shared";
|
|
27
|
-
import type { Argv } from "yargs";
|
|
28
31
|
|
|
29
|
-
type
|
|
30
|
-
{
|
|
31
|
-
Statement: typeof StatementType;
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
createSQLiteDB: typeof createSQLiteDBType;
|
|
35
|
-
}
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
type ExecuteArgs = {
|
|
39
|
-
config?: string;
|
|
40
|
-
name: string;
|
|
41
|
-
file?: string;
|
|
42
|
-
command?: string;
|
|
43
|
-
local?: boolean;
|
|
44
|
-
"persist-to"?: string;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
type QueryResult = {
|
|
32
|
+
export type QueryResult = {
|
|
48
33
|
results: Record<string, string | number | boolean>[];
|
|
49
34
|
success: boolean;
|
|
50
|
-
|
|
35
|
+
meta?: {
|
|
36
|
+
duration?: number;
|
|
37
|
+
};
|
|
51
38
|
query?: string;
|
|
52
39
|
};
|
|
53
|
-
// Max number of
|
|
40
|
+
// Max number of statements to send in a single /execute call
|
|
54
41
|
const QUERY_LIMIT = 10_000;
|
|
55
42
|
|
|
56
|
-
export function Options(yargs:
|
|
57
|
-
return
|
|
43
|
+
export function Options(yargs: CommonYargsArgv) {
|
|
44
|
+
return options
|
|
45
|
+
.Database(yargs)
|
|
46
|
+
.option("yes", {
|
|
47
|
+
describe: 'Answer "yes" to any prompts',
|
|
48
|
+
type: "boolean",
|
|
49
|
+
alias: "y",
|
|
50
|
+
})
|
|
58
51
|
.option("local", {
|
|
59
52
|
describe:
|
|
60
53
|
"Execute commands/files against a local DB for use with wrangler dev",
|
|
61
54
|
type: "boolean",
|
|
62
55
|
})
|
|
63
56
|
.option("file", {
|
|
64
|
-
describe: "A .sql file to
|
|
57
|
+
describe: "A .sql file to ingest",
|
|
65
58
|
type: "string",
|
|
66
59
|
})
|
|
67
60
|
.option("command", {
|
|
@@ -72,54 +65,54 @@ export function Options(yargs: Argv): Argv<ExecuteArgs> {
|
|
|
72
65
|
describe: "Specify directory to use for local persistence (for --local)",
|
|
73
66
|
type: "string",
|
|
74
67
|
requiresArg: true,
|
|
68
|
+
})
|
|
69
|
+
.option("json", {
|
|
70
|
+
describe: "Return output as clean JSON",
|
|
71
|
+
type: "boolean",
|
|
72
|
+
default: false,
|
|
73
|
+
})
|
|
74
|
+
.option("preview", {
|
|
75
|
+
describe: "Execute commands/files against a preview D1 DB",
|
|
76
|
+
type: "boolean",
|
|
77
|
+
default: false,
|
|
75
78
|
});
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
return query && query.length > length
|
|
80
|
-
? query.slice(0, length) + "..."
|
|
81
|
-
: query;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export const Handler = withConfig<ExecuteArgs>(
|
|
85
|
-
async ({ config, name, file, command, local, persistTo }): Promise<void> => {
|
|
86
|
-
logger.log(d1BetaWarning);
|
|
87
|
-
if (file && command)
|
|
88
|
-
return console.error(`Error: can't provide both --command and --file.`);
|
|
89
|
-
const { parser, splitter } = await loadSqlUtils();
|
|
81
|
+
type HandlerOptions = StrictYargsOptionsToInterface<typeof Options>;
|
|
90
82
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
83
|
+
export const Handler = async (args: HandlerOptions): Promise<void> => {
|
|
84
|
+
const { local, database, yes, persistTo, file, command, json, preview } =
|
|
85
|
+
args;
|
|
86
|
+
const existingLogLevel = logger.loggerLevel;
|
|
87
|
+
if (json) {
|
|
88
|
+
// set loggerLevel to error to avoid readConfig warnings appearing in JSON output
|
|
89
|
+
logger.loggerLevel = "error";
|
|
90
|
+
}
|
|
91
|
+
const config = readConfig(args.config, args);
|
|
92
|
+
logger.log(d1BetaWarning);
|
|
93
|
+
if (file && command)
|
|
94
|
+
return logger.error(`Error: can't provide both --command and --file.`);
|
|
100
95
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
isInteractive,
|
|
114
|
-
batchSplit(splitter, sql)
|
|
115
|
-
);
|
|
96
|
+
const isInteractive = process.stdout.isTTY;
|
|
97
|
+
const response: QueryResult[] | null = await executeSql({
|
|
98
|
+
local,
|
|
99
|
+
config,
|
|
100
|
+
name: database,
|
|
101
|
+
shouldPrompt: isInteractive && !yes,
|
|
102
|
+
persistTo,
|
|
103
|
+
file,
|
|
104
|
+
command,
|
|
105
|
+
json,
|
|
106
|
+
preview,
|
|
107
|
+
});
|
|
116
108
|
|
|
117
|
-
|
|
118
|
-
|
|
109
|
+
// Early exit if prompt rejected
|
|
110
|
+
if (!response) return;
|
|
119
111
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
112
|
+
if (isInteractive && !json) {
|
|
113
|
+
// Render table if single result
|
|
114
|
+
logger.log(
|
|
115
|
+
renderToString(
|
|
123
116
|
<Static items={response}>
|
|
124
117
|
{(result) => {
|
|
125
118
|
// batch results
|
|
@@ -138,20 +131,88 @@ export const Handler = withConfig<ExecuteArgs>(
|
|
|
138
131
|
}
|
|
139
132
|
}}
|
|
140
133
|
</Static>
|
|
134
|
+
)
|
|
135
|
+
);
|
|
136
|
+
} else {
|
|
137
|
+
// set loggerLevel back to what it was before to actually output the JSON in stdout
|
|
138
|
+
logger.loggerLevel = existingLogLevel;
|
|
139
|
+
logger.log(JSON.stringify(response, null, 2));
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export async function executeSql({
|
|
144
|
+
local,
|
|
145
|
+
config,
|
|
146
|
+
name,
|
|
147
|
+
shouldPrompt,
|
|
148
|
+
persistTo,
|
|
149
|
+
file,
|
|
150
|
+
command,
|
|
151
|
+
json,
|
|
152
|
+
preview,
|
|
153
|
+
}: {
|
|
154
|
+
local: boolean | undefined;
|
|
155
|
+
config: ConfigFields<DevConfig> & Environment;
|
|
156
|
+
name: string;
|
|
157
|
+
shouldPrompt: boolean | undefined;
|
|
158
|
+
persistTo: string | undefined;
|
|
159
|
+
file: string | undefined;
|
|
160
|
+
command: string | undefined;
|
|
161
|
+
json: boolean | undefined;
|
|
162
|
+
preview: boolean | undefined;
|
|
163
|
+
}) {
|
|
164
|
+
const sql = file ? readFileSync(file) : command;
|
|
165
|
+
if (!sql) throw new Error(`Error: must provide --command or --file.`);
|
|
166
|
+
if (preview && local)
|
|
167
|
+
throw new Error(`Error: can't use --preview with --local`);
|
|
168
|
+
if (persistTo && !local)
|
|
169
|
+
throw new Error(`Error: can't use --persist-to without --local`);
|
|
170
|
+
logger.log(`🌀 Mapping SQL input into an array of statements`);
|
|
171
|
+
const queries = splitSqlQuery(sql);
|
|
172
|
+
|
|
173
|
+
if (file && sql) {
|
|
174
|
+
if (queries[0].startsWith("SQLite format 3")) {
|
|
175
|
+
//TODO: update this error to recommend using `wrangler d1 restore` when it exists
|
|
176
|
+
throw new Error(
|
|
177
|
+
"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."
|
|
141
178
|
);
|
|
142
|
-
} else {
|
|
143
|
-
console.log(JSON.stringify(response, null, 2));
|
|
144
179
|
}
|
|
145
180
|
}
|
|
146
|
-
);
|
|
147
181
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
182
|
+
return local
|
|
183
|
+
? await executeLocally({
|
|
184
|
+
config,
|
|
185
|
+
name,
|
|
186
|
+
shouldPrompt,
|
|
187
|
+
queries,
|
|
188
|
+
persistTo,
|
|
189
|
+
json,
|
|
190
|
+
})
|
|
191
|
+
: await executeRemotely({
|
|
192
|
+
config,
|
|
193
|
+
name,
|
|
194
|
+
shouldPrompt,
|
|
195
|
+
batches: batchSplit(queries),
|
|
196
|
+
json,
|
|
197
|
+
preview,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function executeLocally({
|
|
202
|
+
config,
|
|
203
|
+
name,
|
|
204
|
+
shouldPrompt,
|
|
205
|
+
queries,
|
|
206
|
+
persistTo,
|
|
207
|
+
json,
|
|
208
|
+
}: {
|
|
209
|
+
config: Config;
|
|
210
|
+
name: string;
|
|
211
|
+
shouldPrompt: boolean | undefined;
|
|
212
|
+
queries: string[];
|
|
213
|
+
persistTo: string | undefined;
|
|
214
|
+
json: boolean | undefined;
|
|
215
|
+
}) {
|
|
155
216
|
const localDB = getDatabaseInfoFromConfig(config, name);
|
|
156
217
|
if (!localDB) {
|
|
157
218
|
throw new Error(
|
|
@@ -167,49 +228,56 @@ async function executeLocally(
|
|
|
167
228
|
|
|
168
229
|
const dbDir = path.join(persistencePath, "d1");
|
|
169
230
|
const dbPath = path.join(dbDir, `${localDB.binding}.sqlite3`);
|
|
170
|
-
const [{
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
);
|
|
231
|
+
const [{ D1Database, D1DatabaseAPI }, { createSQLiteDB }] = await npxImport<
|
|
232
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
233
|
+
[typeof import("@miniflare/d1"), typeof import("@miniflare/shared")]
|
|
234
|
+
>(["@miniflare/d1", "@miniflare/shared"], logger.log);
|
|
175
235
|
|
|
176
|
-
if (!existsSync(dbDir)
|
|
177
|
-
const ok =
|
|
178
|
-
|
|
179
|
-
|
|
236
|
+
if (!existsSync(dbDir)) {
|
|
237
|
+
const ok =
|
|
238
|
+
json ||
|
|
239
|
+
!shouldPrompt ||
|
|
240
|
+
(await confirm(`About to create ${readableRelative(dbPath)}, ok?`));
|
|
180
241
|
if (!ok) return null;
|
|
181
242
|
await mkdir(dbDir, { recursive: true });
|
|
182
243
|
}
|
|
183
244
|
|
|
184
245
|
logger.log(`🌀 Loading DB at ${readableRelative(dbPath)}`);
|
|
185
|
-
const db = await createSQLiteDB(dbPath);
|
|
186
|
-
|
|
187
|
-
const results: QueryResult[] = [];
|
|
188
|
-
for (const sql of queries) {
|
|
189
|
-
const statement = new Statement(db, sql);
|
|
190
|
-
results.push((await statement.all()) as QueryResult);
|
|
191
|
-
}
|
|
192
246
|
|
|
193
|
-
|
|
247
|
+
const sqliteDb = await createSQLiteDB(dbPath);
|
|
248
|
+
const db = new D1Database(new D1DatabaseAPI(sqliteDb));
|
|
249
|
+
const stmts = queries.map((query) => db.prepare(query));
|
|
250
|
+
return (await db.batch(stmts)) as QueryResult[];
|
|
194
251
|
}
|
|
195
252
|
|
|
196
|
-
async function executeRemotely(
|
|
197
|
-
config
|
|
198
|
-
name
|
|
199
|
-
|
|
200
|
-
batches
|
|
201
|
-
|
|
202
|
-
|
|
253
|
+
async function executeRemotely({
|
|
254
|
+
config,
|
|
255
|
+
name,
|
|
256
|
+
shouldPrompt,
|
|
257
|
+
batches,
|
|
258
|
+
json,
|
|
259
|
+
preview,
|
|
260
|
+
}: {
|
|
261
|
+
config: Config;
|
|
262
|
+
name: string;
|
|
263
|
+
shouldPrompt: boolean | undefined;
|
|
264
|
+
batches: string[];
|
|
265
|
+
json: boolean | undefined;
|
|
266
|
+
preview: boolean | undefined;
|
|
267
|
+
}) {
|
|
268
|
+
const multiple_batches = batches.length > 1;
|
|
269
|
+
// in JSON mode, we don't want a prompt here
|
|
270
|
+
if (multiple_batches && !json) {
|
|
203
271
|
const warning = `⚠️ Too much SQL to send at once, this execution will be sent as ${batches.length} batches.`;
|
|
204
272
|
|
|
205
|
-
if (
|
|
273
|
+
if (shouldPrompt) {
|
|
206
274
|
const ok = await confirm(
|
|
207
275
|
`${warning}\nℹ️ Each batch is sent individually and may leave your DB in an unexpected state if a later batch fails.\n⚠️ Make sure you have a recent backup. Ok to proceed?`
|
|
208
276
|
);
|
|
209
277
|
if (!ok) return null;
|
|
210
278
|
logger.log(`🌀 Let's go`);
|
|
211
279
|
} else {
|
|
212
|
-
|
|
280
|
+
logger.error(warning);
|
|
213
281
|
}
|
|
214
282
|
}
|
|
215
283
|
|
|
@@ -219,22 +287,28 @@ async function executeRemotely(
|
|
|
219
287
|
accountId,
|
|
220
288
|
name
|
|
221
289
|
);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
// Pipe to error so we don't break jq
|
|
227
|
-
console.error(`Executing on ${name} (${db.uuid}):`);
|
|
290
|
+
if (preview && !db.previewDatabaseUuid) {
|
|
291
|
+
throw logger.error(
|
|
292
|
+
"Please define a `preview_database_id` in your wrangler.toml to execute your queries against a preview database"
|
|
293
|
+
);
|
|
228
294
|
}
|
|
295
|
+
const dbUuid = preview ? db.previewDatabaseUuid : db.uuid;
|
|
296
|
+
logger.log(`🌀 Executing on ${name} (${dbUuid}):`);
|
|
229
297
|
|
|
230
298
|
const results: QueryResult[] = [];
|
|
231
299
|
for (const sql of batches) {
|
|
300
|
+
if (multiple_batches)
|
|
301
|
+
logger.log(
|
|
302
|
+
chalk.gray(` ${sql.slice(0, 70)}${sql.length > 70 ? "..." : ""}`)
|
|
303
|
+
);
|
|
304
|
+
|
|
232
305
|
const result = await fetchResult<QueryResult[]>(
|
|
233
|
-
`/accounts/${accountId}/d1/database/${
|
|
306
|
+
`/accounts/${accountId}/d1/database/${dbUuid}/query`,
|
|
234
307
|
{
|
|
235
308
|
method: "POST",
|
|
236
309
|
headers: {
|
|
237
310
|
"Content-Type": "application/json",
|
|
311
|
+
...(db.internal_env ? { "x-d1-internal-env": db.internal_env } : {}),
|
|
238
312
|
},
|
|
239
313
|
body: JSON.stringify({ sql }),
|
|
240
314
|
}
|
|
@@ -247,53 +321,37 @@ async function executeRemotely(
|
|
|
247
321
|
|
|
248
322
|
function logResult(r: QueryResult | QueryResult[]) {
|
|
249
323
|
logger.log(
|
|
250
|
-
`🚣 Executed ${
|
|
324
|
+
`🚣 Executed ${
|
|
325
|
+
Array.isArray(r) ? `${r.length} commands` : "1 command"
|
|
326
|
+
} in ${
|
|
251
327
|
Array.isArray(r)
|
|
252
328
|
? r
|
|
253
|
-
.map((d: QueryResult) => d.duration)
|
|
329
|
+
.map((d: QueryResult) => d.meta?.duration || 0)
|
|
254
330
|
.reduce((a: number, b: number) => a + b, 0)
|
|
255
|
-
: r.duration
|
|
331
|
+
: r.meta?.duration
|
|
256
332
|
}ms`
|
|
257
333
|
);
|
|
258
334
|
}
|
|
259
335
|
|
|
260
|
-
function
|
|
261
|
-
// We have no interpolations, so convert everything to text
|
|
262
|
-
logger.log(`🌀 Mapping SQL input into an array of statements`);
|
|
263
|
-
return splitter(sql).map(
|
|
264
|
-
(q) =>
|
|
265
|
-
q.format({
|
|
266
|
-
escapeIdentifier: (_) => "",
|
|
267
|
-
formatValue: (_, __) => ({ placeholder: "", value: "" }),
|
|
268
|
-
}).text
|
|
269
|
-
);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
function batchSplit(splitter: typeof splitSqlQuery, sql: SQLQuery) {
|
|
273
|
-
const queries = splitSql(splitter, sql);
|
|
336
|
+
function batchSplit(queries: string[]) {
|
|
274
337
|
logger.log(`🌀 Parsing ${queries.length} statements`);
|
|
338
|
+
const num_batches = Math.ceil(queries.length / QUERY_LIMIT);
|
|
275
339
|
const batches: string[] = [];
|
|
276
|
-
|
|
277
|
-
for (let i = 0; i <= nbatches; i++) {
|
|
340
|
+
for (let i = 0; i < num_batches; i++) {
|
|
278
341
|
batches.push(
|
|
279
342
|
queries.slice(i * QUERY_LIMIT, (i + 1) * QUERY_LIMIT).join("; ")
|
|
280
343
|
);
|
|
281
344
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
345
|
+
if (num_batches > 1) {
|
|
346
|
+
logger.log(
|
|
347
|
+
`🌀 We are sending ${num_batches} batch(es) to D1 (limited to ${QUERY_LIMIT} statements per batch)`
|
|
348
|
+
);
|
|
349
|
+
}
|
|
285
350
|
return batches;
|
|
286
351
|
}
|
|
287
352
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
// No idea why this is doubly-nested, see https://github.com/ForbesLindesay/atdatabases/issues/255
|
|
293
|
-
default: { default: splitter },
|
|
294
|
-
},
|
|
295
|
-
] = await npxImport<
|
|
296
|
-
[{ default: SQL }, { default: { default: typeof splitSqlQuery } }]
|
|
297
|
-
>(["@databases/sql@3.2.0", "@databases/split-sql-query@1.0.3"], logDim);
|
|
298
|
-
return { parser, splitter };
|
|
353
|
+
function shorten(query: string | undefined, length: number) {
|
|
354
|
+
return query && query.length > length
|
|
355
|
+
? query.slice(0, length) + "..."
|
|
356
|
+
: query;
|
|
299
357
|
}
|
package/src/d1/index.ts
CHANGED
|
@@ -3,11 +3,11 @@ import * as Create from "./create";
|
|
|
3
3
|
import * as Delete from "./delete";
|
|
4
4
|
import * as Execute from "./execute";
|
|
5
5
|
import * as List from "./list";
|
|
6
|
+
import * as Migrations from "./migrations";
|
|
6
7
|
import { d1BetaWarning } from "./utils";
|
|
7
|
-
import type {
|
|
8
|
-
import type { Argv } from "yargs";
|
|
8
|
+
import type { CommonYargsArgv } from "../yargs-types";
|
|
9
9
|
|
|
10
|
-
export
|
|
10
|
+
export function d1(yargs: CommonYargsArgv) {
|
|
11
11
|
return (
|
|
12
12
|
yargs
|
|
13
13
|
.command("list", "List D1 databases", List.Options, List.Handler)
|
|
@@ -23,8 +23,9 @@ export const d1 = (yargs: Argv<CommonYargsOptions>) => {
|
|
|
23
23
|
Delete.Options,
|
|
24
24
|
Delete.Handler
|
|
25
25
|
)
|
|
26
|
-
.command("backup", "Interact with D1 Backups", (
|
|
27
|
-
|
|
26
|
+
.command("backup", "Interact with D1 Backups", (backupArgs) =>
|
|
27
|
+
backupArgs
|
|
28
|
+
.demandCommand()
|
|
28
29
|
.command(
|
|
29
30
|
"list <name>",
|
|
30
31
|
"List your D1 backups",
|
|
@@ -66,11 +67,34 @@ export const d1 = (yargs: Argv<CommonYargsOptions>) => {
|
|
|
66
67
|
// }
|
|
67
68
|
// )
|
|
68
69
|
.command(
|
|
69
|
-
"execute <
|
|
70
|
+
"execute <database>",
|
|
70
71
|
"Executed command or SQL file",
|
|
71
72
|
Execute.Options,
|
|
72
73
|
Execute.Handler
|
|
73
74
|
)
|
|
75
|
+
.command("migrations", "Interact with D1 Migrations", (yargs2) =>
|
|
76
|
+
yargs2
|
|
77
|
+
.demandCommand()
|
|
78
|
+
.command(
|
|
79
|
+
"list <database>",
|
|
80
|
+
"List your D1 migrations",
|
|
81
|
+
Migrations.ListOptions,
|
|
82
|
+
Migrations.ListHandler
|
|
83
|
+
)
|
|
84
|
+
.command(
|
|
85
|
+
"create <database> <message>",
|
|
86
|
+
"Create a new Migration",
|
|
87
|
+
Migrations.CreateOptions,
|
|
88
|
+
Migrations.CreateHandler
|
|
89
|
+
)
|
|
90
|
+
.command(
|
|
91
|
+
"apply <database>",
|
|
92
|
+
"Apply D1 Migrations",
|
|
93
|
+
Migrations.ApplyOptions,
|
|
94
|
+
Migrations.ApplyHandler
|
|
95
|
+
)
|
|
96
|
+
.epilogue(d1BetaWarning)
|
|
97
|
+
)
|
|
74
98
|
.epilogue(d1BetaWarning)
|
|
75
99
|
);
|
|
76
|
-
}
|
|
100
|
+
}
|
package/src/d1/list.tsx
CHANGED
|
@@ -1,26 +1,38 @@
|
|
|
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
|
+
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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(
|
|
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
|
-
|
|
30
|
+
if (json) {
|
|
31
|
+
logger.log(JSON.stringify(dbs, null, 2));
|
|
32
|
+
} else {
|
|
33
|
+
logger.log(d1BetaWarning);
|
|
34
|
+
logger.log(renderToString(<Table data={dbs}></Table>));
|
|
35
|
+
}
|
|
24
36
|
}
|
|
25
37
|
|
|
26
38
|
export const listDatabases = async (
|