wrangler 2.6.2 → 2.7.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/bin/wrangler.js +9 -1
- package/miniflare-dist/index.mjs +1 -1
- package/package.json +12 -10
- package/src/__tests__/api-dev.test.ts +65 -36
- package/src/__tests__/api-devregistry.test.js +14 -6
- package/src/__tests__/configuration.test.ts +2 -31
- package/src/__tests__/{d1.test.ts → d1/d1.test.ts} +48 -5
- package/src/__tests__/d1/splitter.test.ts +255 -0
- package/src/__tests__/delete.test.ts +5 -2
- package/src/__tests__/deployments.test.ts +20 -6
- package/src/__tests__/dev.test.tsx +52 -19
- package/src/__tests__/generate.test.ts +7 -4
- package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
- package/src/__tests__/helpers/mock-cfetch.ts +2 -57
- package/src/__tests__/helpers/mock-dialogs.ts +70 -86
- package/src/__tests__/helpers/mock-oauth-flow.ts +64 -49
- package/src/__tests__/helpers/mock-process.ts +8 -13
- package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
- package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
- package/src/__tests__/index.test.ts +46 -44
- package/src/__tests__/init.test.ts +761 -537
- package/src/__tests__/jest.setup.ts +20 -24
- package/src/__tests__/kv.test.ts +286 -173
- package/src/__tests__/logout.test.ts +1 -1
- package/src/__tests__/metrics.test.ts +5 -7
- package/src/__tests__/middleware.scheduled.test.ts +40 -30
- package/src/__tests__/middleware.test.ts +144 -120
- package/src/__tests__/pages.test.ts +1617 -1161
- package/src/__tests__/publish.test.ts +174 -125
- package/src/__tests__/r2.test.ts +2 -2
- package/src/__tests__/secret.test.ts +183 -126
- package/src/__tests__/tail.test.ts +6 -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__/whoami.test.tsx +1 -96
- package/src/api/dev.ts +78 -41
- package/src/api/index.ts +1 -1
- package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
- package/src/cfetch/index.ts +0 -2
- package/src/cfetch/internal.ts +6 -15
- package/src/cli.ts +2 -2
- package/src/config/validation.ts +1 -2
- package/src/create-worker-upload-form.ts +2 -2
- package/src/d1/{delete.tsx → delete.ts} +0 -0
- package/src/d1/execute.tsx +8 -37
- package/src/d1/migrations/apply.tsx +29 -19
- package/src/d1/migrations/{index.tsx → index.ts} +0 -0
- package/src/d1/splitter.ts +161 -0
- package/src/d1/{types.tsx → types.ts} +0 -0
- package/src/delete.ts +3 -8
- package/src/deployments.ts +6 -0
- package/src/deprecated/index.ts +2 -295
- package/src/dev/dev.tsx +2 -2
- package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
- package/src/dev/local.tsx +16 -4
- package/src/dev/remote.tsx +28 -1
- package/src/dev/start-server.ts +19 -11
- package/src/dev/use-esbuild.ts +1 -1
- package/src/{dev-registry.tsx → dev-registry.ts} +0 -0
- package/src/dev.tsx +21 -2
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +1 -1
- package/src/docs/index.ts +3 -0
- package/src/environment-variables/factory.ts +88 -0
- package/src/environment-variables/misc-variables.ts +30 -0
- package/src/generate/index.ts +300 -0
- package/src/{index.tsx → index.ts} +10 -13
- package/src/init.ts +92 -52
- package/src/jest.d.ts +4 -0
- package/src/logger.ts +15 -3
- package/src/metrics/metrics-config.ts +1 -1
- package/src/miniflare-cli/assets.ts +4 -0
- package/src/miniflare-cli/index.ts +1 -5
- 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/pages/{build.tsx → build.ts} +0 -0
- package/src/pages/{deployment-tails.tsx → deployment-tails.ts} +0 -0
- package/src/pages/{dev.tsx → dev.ts} +53 -55
- package/src/pages/functions/buildWorker.ts +1 -1
- package/src/pages/functions/tsconfig.json +8 -0
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
- package/src/pages/{functions.tsx → functions.ts} +0 -0
- package/src/pages/{hash.tsx → hash.ts} +0 -0
- package/src/pages/{index.tsx → index.ts} +0 -0
- package/src/pages/projects.tsx +3 -5
- package/src/pages/publish.tsx +5 -4
- package/src/pages/upload.tsx +1 -1
- package/src/publish/publish.ts +9 -7
- package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +1 -1
- package/src/secret/index.ts +1 -1
- package/src/{sites.tsx → sites.ts} +0 -0
- package/src/tail/index.ts +2 -3
- package/src/tsconfig-sanity.ts +16 -0
- 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} +107 -73
- package/src/{whoami.tsx → whoami.ts} +37 -71
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
- package/templates/d1-beta-facade.js +36 -0
- package/templates/facade.d.ts +14 -0
- package/templates/first-party-worker-module-facade.ts +4 -3
- package/templates/format-dev-errors.ts +7 -6
- 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 +0 -2
- package/templates/middleware/loader-sw.ts +6 -0
- package/templates/pages-dev-pipeline.ts +4 -1
- package/templates/pages-shim.ts +4 -1
- package/templates/pages-template-plugin.ts +12 -7
- package/templates/serve-static-assets.ts +16 -14
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +106 -0
- package/templates/tsconfig.json +5 -103
- package/templates/tsconfig.tsbuildinfo +1 -0
- package/wrangler-dist/cli.d.ts +58 -60
- package/wrangler-dist/cli.js +34440 -55514
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/src/__tests__/dialogs.test.tsx +0 -40
- package/src/dialogs.tsx +0 -168
- package/src/environment-variables.ts +0 -50
- package/src/user/env-vars.ts +0 -46
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { render } from "ink-testing-library";
|
|
2
1
|
import { rest } from "msw";
|
|
3
|
-
import React from "react";
|
|
4
2
|
import { writeAuthConfigFile } from "../user";
|
|
5
|
-
import { getUserInfo
|
|
3
|
+
import { getUserInfo } from "../whoami";
|
|
6
4
|
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
7
5
|
import { useMockIsTTY } from "./helpers/mock-istty";
|
|
8
6
|
import {
|
|
@@ -11,7 +9,6 @@ import {
|
|
|
11
9
|
mswSuccessUserHandlers,
|
|
12
10
|
} from "./helpers/msw";
|
|
13
11
|
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
14
|
-
import type { UserInfo } from "../whoami";
|
|
15
12
|
|
|
16
13
|
describe("getUserInfo()", () => {
|
|
17
14
|
const ENV_COPY = process.env;
|
|
@@ -184,95 +181,3 @@ describe("getUserInfo()", () => {
|
|
|
184
181
|
`);
|
|
185
182
|
});
|
|
186
183
|
});
|
|
187
|
-
|
|
188
|
-
describe("WhoAmI component", () => {
|
|
189
|
-
it("should return undefined if there is no user", async () => {
|
|
190
|
-
const { lastFrame } = render(<WhoAmI user={undefined}></WhoAmI>);
|
|
191
|
-
|
|
192
|
-
expect(lastFrame()).toMatchInlineSnapshot(
|
|
193
|
-
`"You are not authenticated. Please run \`wrangler login\`."`
|
|
194
|
-
);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it("should display the user's email, accounts and OAuth scopes", async () => {
|
|
198
|
-
const user: UserInfo = {
|
|
199
|
-
authType: "OAuth Token",
|
|
200
|
-
apiToken: "some-oauth-token",
|
|
201
|
-
email: "user@example.com",
|
|
202
|
-
tokenPermissions: ["scope1:read", "scope2:write", "scope3"],
|
|
203
|
-
accounts: [
|
|
204
|
-
{ name: "Account One", id: "account-1" },
|
|
205
|
-
{ name: "Account Two", id: "account-2" },
|
|
206
|
-
{ name: "Account Three", id: "account-3" },
|
|
207
|
-
],
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
|
|
211
|
-
|
|
212
|
-
expect(lastFrame()).toContain(
|
|
213
|
-
"You are logged in with an OAuth Token, associated with the email 'user@example.com'!"
|
|
214
|
-
);
|
|
215
|
-
expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
|
|
216
|
-
expect(lastFrame()).toMatch(/Account One .+ account-1/);
|
|
217
|
-
expect(lastFrame()).toMatch(/Account Two .+ account-2/);
|
|
218
|
-
expect(lastFrame()).toMatch(/Account Three .+ account-3/);
|
|
219
|
-
expect(lastFrame()).toContain(
|
|
220
|
-
"Token Permissions: If scopes are missing, you may need to logout and re-login."
|
|
221
|
-
);
|
|
222
|
-
expect(lastFrame()).toContain("- scope1 (read)");
|
|
223
|
-
expect(lastFrame()).toContain("- scope2 (write)");
|
|
224
|
-
expect(lastFrame()).toContain("- scope3");
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// For the case where the cache hasn't updated to include the scopes array
|
|
228
|
-
it("should display the user's email and accounts, but no OAuth scopes if none provided", async () => {
|
|
229
|
-
const user: UserInfo = {
|
|
230
|
-
authType: "OAuth Token",
|
|
231
|
-
apiToken: "some-oauth-token",
|
|
232
|
-
email: "user@example.com",
|
|
233
|
-
tokenPermissions: undefined,
|
|
234
|
-
accounts: [
|
|
235
|
-
{ name: "Account One", id: "account-1" },
|
|
236
|
-
{ name: "Account Two", id: "account-2" },
|
|
237
|
-
{ name: "Account Three", id: "account-3" },
|
|
238
|
-
],
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
|
|
242
|
-
|
|
243
|
-
expect(lastFrame()).toContain(
|
|
244
|
-
"You are logged in with an OAuth Token, associated with the email 'user@example.com'!"
|
|
245
|
-
);
|
|
246
|
-
expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
|
|
247
|
-
expect(lastFrame()).toMatch(/Account One .+ account-1/);
|
|
248
|
-
expect(lastFrame()).toMatch(/Account Two .+ account-2/);
|
|
249
|
-
expect(lastFrame()).toMatch(/Account Three .+ account-3/);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it("should display the user's email, accounts and link to view token permissions for non-OAuth tokens", async () => {
|
|
253
|
-
const user: UserInfo = {
|
|
254
|
-
authType: "API Token",
|
|
255
|
-
apiToken: "some-api-token",
|
|
256
|
-
email: "user@example.com",
|
|
257
|
-
tokenPermissions: undefined,
|
|
258
|
-
accounts: [
|
|
259
|
-
{ name: "Account One", id: "account-1" },
|
|
260
|
-
{ name: "Account Two", id: "account-2" },
|
|
261
|
-
{ name: "Account Three", id: "account-3" },
|
|
262
|
-
],
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
|
|
266
|
-
|
|
267
|
-
expect(lastFrame()).toContain(
|
|
268
|
-
"You are logged in with an API Token, associated with the email 'user@example.com'!"
|
|
269
|
-
);
|
|
270
|
-
expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
|
|
271
|
-
expect(lastFrame()).toMatch(/Account One .+ account-1/);
|
|
272
|
-
expect(lastFrame()).toMatch(/Account Two .+ account-2/);
|
|
273
|
-
expect(lastFrame()).toMatch(/Account Three .+ account-3/);
|
|
274
|
-
expect(lastFrame()).toContain(
|
|
275
|
-
"To see token permissions visit https://dash.cloudflare.com/profile/api-tokens"
|
|
276
|
-
);
|
|
277
|
-
});
|
|
278
|
-
});
|
package/src/api/dev.ts
CHANGED
|
@@ -3,28 +3,26 @@ import { startApiDev, startDev } from "../dev";
|
|
|
3
3
|
import { logger } from "../logger";
|
|
4
4
|
|
|
5
5
|
import type { Environment } from "../config";
|
|
6
|
-
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
6
|
+
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli/types";
|
|
7
7
|
import type { RequestInit, Response, RequestInfo } from "undici";
|
|
8
8
|
|
|
9
|
-
interface
|
|
10
|
-
config?: string;
|
|
11
|
-
env?: string;
|
|
12
|
-
ip?: string;
|
|
13
|
-
port?: number;
|
|
14
|
-
bundle?: boolean;
|
|
15
|
-
inspectorPort?: number;
|
|
16
|
-
localProtocol?: "http" | "https";
|
|
17
|
-
assets?: string;
|
|
18
|
-
site?: string;
|
|
19
|
-
siteInclude?: string[];
|
|
20
|
-
siteExclude?: string[];
|
|
21
|
-
nodeCompat?: boolean;
|
|
22
|
-
compatibilityDate?: string;
|
|
23
|
-
compatibilityFlags?: string[];
|
|
24
|
-
persist?: boolean;
|
|
25
|
-
persistTo?: string;
|
|
26
|
-
liveReload?: boolean;
|
|
27
|
-
watch?: boolean;
|
|
9
|
+
export interface UnstableDevOptions {
|
|
10
|
+
config?: string; // Path to .toml configuration file, relative to cwd
|
|
11
|
+
env?: string; // Environment to use for operations and .env files
|
|
12
|
+
ip?: string; // IP address to listen on
|
|
13
|
+
port?: number; // Port to listen on
|
|
14
|
+
bundle?: boolean; // Set to false to skip internal build steps and directly publish script
|
|
15
|
+
inspectorPort?: number; // Port for devtools to connect to
|
|
16
|
+
localProtocol?: "http" | "https"; // Protocol to listen to requests on, defaults to http.
|
|
17
|
+
assets?: string; // Static assets to be served
|
|
18
|
+
site?: string; // Root folder of static assets for Workers Sites
|
|
19
|
+
siteInclude?: string[]; // Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.
|
|
20
|
+
siteExclude?: string[]; // Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.
|
|
21
|
+
nodeCompat?: boolean; // Enable node.js compatibility
|
|
22
|
+
compatibilityDate?: string; // Date to use for compatibility checks
|
|
23
|
+
compatibilityFlags?: string[]; // Flags to use for compatibility checks
|
|
24
|
+
persist?: boolean; // Enable persistence for local mode, using default path: .wrangler/state
|
|
25
|
+
persistTo?: string; // Specify directory to use for local persistence (implies --persist)
|
|
28
26
|
vars?: {
|
|
29
27
|
[key: string]: unknown;
|
|
30
28
|
};
|
|
@@ -44,25 +42,25 @@ interface DevOptions {
|
|
|
44
42
|
bucket_name: string;
|
|
45
43
|
preview_bucket_name?: string;
|
|
46
44
|
}[];
|
|
47
|
-
|
|
48
|
-
showInteractiveDevSession?: boolean;
|
|
49
|
-
logLevel?: "none" | "info" | "error" | "log" | "warn" | "debug";
|
|
45
|
+
logLevel?: "none" | "info" | "error" | "log" | "warn" | "debug"; // Specify logging level [choices: "debug", "info", "log", "warn", "error", "none"] [default: "log"]
|
|
50
46
|
logPrefix?: string;
|
|
51
47
|
inspect?: boolean;
|
|
52
48
|
local?: boolean;
|
|
53
|
-
forceLocal?: boolean;
|
|
54
|
-
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
55
|
-
_?: (string | number)[]; //yargs wants this
|
|
56
|
-
$0?: string; //yargs wants this
|
|
57
|
-
testScheduled?: boolean;
|
|
58
|
-
experimentalLocal?: boolean;
|
|
59
49
|
accountId?: string;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
50
|
+
experimental?: {
|
|
51
|
+
d1Databases?: Environment["d1_databases"];
|
|
52
|
+
disableExperimentalWarning?: boolean; // Disables wrangler's warning when unstable APIs are used.
|
|
53
|
+
disableDevRegistry?: boolean; // Disables wrangler's support multi-worker setups. May reduce flakiness when used in tests in CI.
|
|
54
|
+
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
55
|
+
experimentalLocal?: boolean; // Use Miniflare 3 instead of Miniflare 2
|
|
56
|
+
experimentalLocalRemoteKv?: boolean;
|
|
57
|
+
forceLocal?: boolean;
|
|
58
|
+
liveReload?: boolean; // Auto reload HTML pages when change is detected in local mode
|
|
59
|
+
showInteractiveDevSession?: boolean;
|
|
60
|
+
testMode?: boolean; // This option shouldn't be used - We plan on removing it eventually
|
|
61
|
+
testScheduled?: boolean; // Test scheduled events by visiting /__scheduled in browser
|
|
62
|
+
watch?: boolean; // unstable_dev doesn't support watch-mode yet in testMode
|
|
63
|
+
};
|
|
66
64
|
}
|
|
67
65
|
|
|
68
66
|
export interface UnstableDevWorker {
|
|
@@ -77,11 +75,33 @@ export interface UnstableDevWorker {
|
|
|
77
75
|
*/
|
|
78
76
|
export async function unstable_dev(
|
|
79
77
|
script: string,
|
|
80
|
-
options?:
|
|
81
|
-
apiOptions?:
|
|
78
|
+
options?: UnstableDevOptions,
|
|
79
|
+
apiOptions?: unknown
|
|
82
80
|
): Promise<UnstableDevWorker> {
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
// Note that not every experimental option is passed directly through to the underlying dev API - experimental options can be used here in unstable_dev. Otherwise we could just pass experimental down to dev blindly.
|
|
82
|
+
const {
|
|
83
|
+
// there are two types of "experimental" options:
|
|
84
|
+
// 1. options to unstable_dev that we're still testing or are unsure of
|
|
85
|
+
disableDevRegistry = false,
|
|
86
|
+
disableExperimentalWarning = false,
|
|
87
|
+
forceLocal,
|
|
88
|
+
liveReload,
|
|
89
|
+
showInteractiveDevSession = false,
|
|
90
|
+
testMode = true,
|
|
91
|
+
testScheduled,
|
|
92
|
+
watch,
|
|
93
|
+
// 2. options for alpha/beta products/libs
|
|
94
|
+
d1Databases,
|
|
95
|
+
experimentalLocal,
|
|
96
|
+
experimentalLocalRemoteKv,
|
|
97
|
+
enablePagesAssetsServiceBinding,
|
|
98
|
+
} = options?.experimental ?? {};
|
|
99
|
+
if (apiOptions) {
|
|
100
|
+
logger.error(
|
|
101
|
+
"unstable_dev's third argument (apiOptions) has been deprecated in favor of an `experimental` property within the second argument (options).\nPlease update your code from:\n`await unstable_dev('...', {...}, {...});`\nto:\n`await unstable_dev('...', {..., experimental: {...}});`"
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
85
105
|
if (!disableExperimentalWarning) {
|
|
86
106
|
logger.warn(
|
|
87
107
|
`unstable_dev() is experimental\nunstable_dev()'s behaviour will likely change in future releases`
|
|
@@ -101,11 +121,20 @@ export async function unstable_dev(
|
|
|
101
121
|
script: script,
|
|
102
122
|
inspect: false,
|
|
103
123
|
logLevel: "none",
|
|
104
|
-
showInteractiveDevSession: false,
|
|
105
124
|
_: [],
|
|
106
125
|
$0: "",
|
|
107
126
|
port: options?.port ?? 0,
|
|
108
127
|
local: true,
|
|
128
|
+
d1Databases,
|
|
129
|
+
disableDevRegistry,
|
|
130
|
+
testScheduled,
|
|
131
|
+
experimentalLocal,
|
|
132
|
+
experimentalLocalRemoteKv,
|
|
133
|
+
enablePagesAssetsServiceBinding,
|
|
134
|
+
liveReload,
|
|
135
|
+
showInteractiveDevSession,
|
|
136
|
+
forceLocal,
|
|
137
|
+
watch,
|
|
109
138
|
...options,
|
|
110
139
|
onReady: (address, port) => {
|
|
111
140
|
readyPort = port;
|
|
@@ -147,10 +176,18 @@ export async function unstable_dev(
|
|
|
147
176
|
const devServer = startDev({
|
|
148
177
|
script: script,
|
|
149
178
|
inspect: false,
|
|
150
|
-
showInteractiveDevSession: false,
|
|
151
179
|
_: [],
|
|
152
180
|
$0: "",
|
|
153
181
|
local: true,
|
|
182
|
+
showInteractiveDevSession,
|
|
183
|
+
d1Databases,
|
|
184
|
+
disableDevRegistry,
|
|
185
|
+
testScheduled,
|
|
186
|
+
experimentalLocal,
|
|
187
|
+
experimentalLocalRemoteKv,
|
|
188
|
+
enablePagesAssetsServiceBinding,
|
|
189
|
+
liveReload,
|
|
190
|
+
watch,
|
|
154
191
|
...options,
|
|
155
192
|
onReady: (address, port) => {
|
|
156
193
|
readyPort = port;
|
package/src/api/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { unstable_dev } from "./dev";
|
|
2
|
-
export type { UnstableDevWorker } from "./dev";
|
|
2
|
+
export type { UnstableDevWorker, UnstableDevOptions } from "./dev";
|
|
File without changes
|
package/src/cfetch/index.ts
CHANGED
package/src/cfetch/internal.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { fetch, File, Headers } from "undici";
|
|
3
3
|
import { version as wranglerVersion } from "../../package.json";
|
|
4
|
-
import {
|
|
4
|
+
import { getCloudflareApiBaseUrl } from "../environment-variables/misc-variables";
|
|
5
5
|
import { logger } from "../logger";
|
|
6
6
|
import { ParseError, parseJSON } from "../parse";
|
|
7
7
|
import { loginOrRefreshIfRequired, requireApiToken } from "../user";
|
|
@@ -9,15 +9,6 @@ import type { ApiCredentials } from "../user";
|
|
|
9
9
|
import type { URLSearchParams } from "node:url";
|
|
10
10
|
import type { RequestInit, HeadersInit, Response } from "undici";
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* Get the URL to use to access the Cloudflare API.
|
|
14
|
-
*/
|
|
15
|
-
export const getCloudflareAPIBaseURL = getEnvironmentVariableFactory({
|
|
16
|
-
variableName: "CLOUDFLARE_API_BASE_URL",
|
|
17
|
-
deprecatedName: "CF_API_BASE_URL",
|
|
18
|
-
defaultValue: "https://api.cloudflare.com/client/v4",
|
|
19
|
-
});
|
|
20
|
-
|
|
21
12
|
/*
|
|
22
13
|
* performApiFetch does everything required to make a CF API request,
|
|
23
14
|
* but doesn't parse the response as JSON. For normal V4 API responses,
|
|
@@ -42,7 +33,7 @@ export async function performApiFetch(
|
|
|
42
33
|
|
|
43
34
|
const queryString = queryParams ? `?${queryParams.toString()}` : "";
|
|
44
35
|
logger.debug(
|
|
45
|
-
`-- START CF API REQUEST: ${method} ${
|
|
36
|
+
`-- START CF API REQUEST: ${method} ${getCloudflareApiBaseUrl()}${resource}${queryString}`
|
|
46
37
|
);
|
|
47
38
|
const logHeaders = cloneHeaders(headers);
|
|
48
39
|
delete logHeaders["Authorization"];
|
|
@@ -52,7 +43,7 @@ export async function performApiFetch(
|
|
|
52
43
|
JSON.stringify({ ...init, headers: logHeaders }, null, 2)
|
|
53
44
|
);
|
|
54
45
|
logger.debug("-- END CF API REQUEST");
|
|
55
|
-
return await fetch(`${
|
|
46
|
+
return await fetch(`${getCloudflareApiBaseUrl()}${resource}${queryString}`, {
|
|
56
47
|
method,
|
|
57
48
|
...init,
|
|
58
49
|
headers,
|
|
@@ -173,7 +164,7 @@ export async function fetchKVGetValue(
|
|
|
173
164
|
const auth = requireApiToken();
|
|
174
165
|
const headers: Record<string, string> = {};
|
|
175
166
|
addAuthorizationHeaderIfUnspecified(headers, auth);
|
|
176
|
-
const resource = `${
|
|
167
|
+
const resource = `${getCloudflareApiBaseUrl()}/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`;
|
|
177
168
|
const response = await fetch(resource, {
|
|
178
169
|
method: "GET",
|
|
179
170
|
headers,
|
|
@@ -206,7 +197,7 @@ export async function fetchR2Objects(
|
|
|
206
197
|
addAuthorizationHeaderIfUnspecified(headers, auth);
|
|
207
198
|
addUserAgent(headers);
|
|
208
199
|
|
|
209
|
-
const response = await fetch(`${
|
|
200
|
+
const response = await fetch(`${getCloudflareApiBaseUrl()}${resource}`, {
|
|
210
201
|
...bodyInit,
|
|
211
202
|
headers,
|
|
212
203
|
});
|
|
@@ -233,7 +224,7 @@ export async function fetchDashboardScript(
|
|
|
233
224
|
addAuthorizationHeaderIfUnspecified(headers, auth);
|
|
234
225
|
addUserAgent(headers);
|
|
235
226
|
|
|
236
|
-
const response = await fetch(`${
|
|
227
|
+
const response = await fetch(`${getCloudflareApiBaseUrl()}${resource}`, {
|
|
237
228
|
...bodyInit,
|
|
238
229
|
headers,
|
|
239
230
|
});
|
package/src/cli.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { unstable_dev } from "./api";
|
|
|
4
4
|
import { FatalError } from "./errors";
|
|
5
5
|
import { main } from ".";
|
|
6
6
|
|
|
7
|
-
import type { UnstableDevWorker } from "./api";
|
|
7
|
+
import type { UnstableDevWorker, UnstableDevOptions } from "./api";
|
|
8
8
|
/**
|
|
9
9
|
* The main entrypoint for the CLI.
|
|
10
10
|
* main only gets called when the script is run directly, not when it's imported as a module.
|
|
@@ -25,4 +25,4 @@ if (typeof jest === "undefined" && require.main === module) {
|
|
|
25
25
|
* and call wrangler.unstable_dev().
|
|
26
26
|
*/
|
|
27
27
|
export { unstable_dev };
|
|
28
|
-
export type { UnstableDevWorker };
|
|
28
|
+
export type { UnstableDevWorker, UnstableDevOptions };
|
package/src/config/validation.ts
CHANGED
|
@@ -909,7 +909,6 @@ function normalizeAndValidateEnvironment(
|
|
|
909
909
|
|
|
910
910
|
experimental(diagnostics, rawEnv, "unsafe");
|
|
911
911
|
experimental(diagnostics, rawEnv, "services");
|
|
912
|
-
experimental(diagnostics, rawEnv, "dispatch_namespaces");
|
|
913
912
|
|
|
914
913
|
const route = normalizeAndValidateRoute(diagnostics, topLevelEnv, rawEnv);
|
|
915
914
|
|
|
@@ -1824,7 +1823,7 @@ const validateD1Binding: ValidatorFn = (diagnostics, field, value) => {
|
|
|
1824
1823
|
}
|
|
1825
1824
|
if (isValid && !process.env.NO_D1_WARNING) {
|
|
1826
1825
|
diagnostics.warnings.push(
|
|
1827
|
-
|
|
1826
|
+
"D1 Bindings are currently in alpha to allow the API to evolve before general availability.\nPlease report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose\nNote: Run this command with the environment variable NO_D1_WARNING=true to hide this message\n\nFor example: `export NO_D1_WARNING=true && wrangler <YOUR COMMAND HERE>`"
|
|
1828
1827
|
);
|
|
1829
1828
|
}
|
|
1830
1829
|
return isValid;
|
|
@@ -44,7 +44,7 @@ type WorkerMetadataBinding =
|
|
|
44
44
|
| { type: "d1"; name: string; id: string; internalEnv?: string }
|
|
45
45
|
| { type: "service"; name: string; service: string; environment?: string }
|
|
46
46
|
| { type: "analytics_engine"; name: string; dataset?: string }
|
|
47
|
-
| { type: "
|
|
47
|
+
| { type: "dispatch_namespace"; name: string; namespace: string }
|
|
48
48
|
| {
|
|
49
49
|
type: "logfwdr";
|
|
50
50
|
name: string;
|
|
@@ -161,7 +161,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
161
161
|
bindings.dispatch_namespaces?.forEach(({ binding, namespace }) => {
|
|
162
162
|
metadataBindings.push({
|
|
163
163
|
name: binding,
|
|
164
|
-
type: "
|
|
164
|
+
type: "dispatch_namespace",
|
|
165
165
|
namespace,
|
|
166
166
|
});
|
|
167
167
|
});
|
|
File without changes
|
package/src/d1/execute.tsx
CHANGED
|
@@ -9,11 +9,13 @@ import React from "react";
|
|
|
9
9
|
import { fetchResult } from "../cfetch";
|
|
10
10
|
import { withConfig } from "../config";
|
|
11
11
|
import { getLocalPersistencePath } from "../dev/get-local-persistence-path";
|
|
12
|
-
import { confirm
|
|
12
|
+
import { confirm } from "../dialogs";
|
|
13
13
|
import { logger } from "../logger";
|
|
14
|
+
import { readFileSync } from "../parse";
|
|
14
15
|
import { readableRelative } from "../paths";
|
|
15
16
|
import { requireAuth } from "../user";
|
|
16
17
|
import * as options from "./options";
|
|
18
|
+
import splitSqlQuery from "./splitter";
|
|
17
19
|
import {
|
|
18
20
|
d1BetaWarning,
|
|
19
21
|
getDatabaseByNameOrBinding,
|
|
@@ -21,8 +23,6 @@ import {
|
|
|
21
23
|
} from "./utils";
|
|
22
24
|
import type { Config, ConfigFields, DevConfig, Environment } from "../config";
|
|
23
25
|
import type { Database } from "./types";
|
|
24
|
-
import type splitSqlQuery from "@databases/split-sql-query";
|
|
25
|
-
import type { SQL, SQLQuery } from "@databases/sql";
|
|
26
26
|
import type { Statement as StatementType } from "@miniflare/d1";
|
|
27
27
|
import type { createSQLiteDB as createSQLiteDBType } from "@miniflare/shared";
|
|
28
28
|
import type { Argv } from "yargs";
|
|
@@ -103,19 +103,15 @@ export async function executeSql(
|
|
|
103
103
|
file?: string,
|
|
104
104
|
command?: string
|
|
105
105
|
) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
const sql = file
|
|
109
|
-
? parser.file(file)
|
|
110
|
-
: command
|
|
111
|
-
? parser.__dangerous__rawValue(command)
|
|
112
|
-
: null;
|
|
106
|
+
const sql = file ? readFileSync(file) : command;
|
|
113
107
|
|
|
114
108
|
if (!sql) throw new Error(`Error: must provide --command or --file.`);
|
|
115
109
|
if (persistTo && !local)
|
|
116
110
|
throw new Error(`Error: can't use --persist-to without --local`);
|
|
117
111
|
|
|
118
|
-
|
|
112
|
+
logger.log(`🌀 Mapping SQL input into an array of statements`);
|
|
113
|
+
const queries = splitSqlQuery(sql);
|
|
114
|
+
|
|
119
115
|
if (file && sql) {
|
|
120
116
|
if (queries[0].startsWith("SQLite format 3")) {
|
|
121
117
|
//TODO: update this error to recommend using `wrangler d1 restore` when it exists
|
|
@@ -211,7 +207,7 @@ async function executeLocally(
|
|
|
211
207
|
const [{ Statement }, { createSQLiteDB }] =
|
|
212
208
|
await npxImport<MiniflareNpxImportTypes>(
|
|
213
209
|
["@miniflare/d1", "@miniflare/shared"],
|
|
214
|
-
|
|
210
|
+
logger.log
|
|
215
211
|
);
|
|
216
212
|
|
|
217
213
|
if (!existsSync(dbDir) && shouldPrompt) {
|
|
@@ -309,18 +305,6 @@ function logResult(r: QueryResult | QueryResult[]) {
|
|
|
309
305
|
);
|
|
310
306
|
}
|
|
311
307
|
|
|
312
|
-
function splitSql(splitter: (query: SQLQuery) => SQLQuery[], sql: SQLQuery) {
|
|
313
|
-
// We have no interpolations, so convert everything to text
|
|
314
|
-
logger.log(`🌀 Mapping SQL input into an array of statements`);
|
|
315
|
-
return splitter(sql).map(
|
|
316
|
-
(q) =>
|
|
317
|
-
q.format({
|
|
318
|
-
escapeIdentifier: (_) => "",
|
|
319
|
-
formatValue: (_, __) => ({ placeholder: "", value: "" }),
|
|
320
|
-
}).text
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
308
|
function batchSplit(queries: string[]) {
|
|
325
309
|
logger.log(`🌀 Parsing ${queries.length} statements`);
|
|
326
310
|
const num_batches = Math.ceil(queries.length / QUERY_LIMIT);
|
|
@@ -337,16 +321,3 @@ function batchSplit(queries: string[]) {
|
|
|
337
321
|
}
|
|
338
322
|
return batches;
|
|
339
323
|
}
|
|
340
|
-
|
|
341
|
-
async function loadSqlUtils() {
|
|
342
|
-
const [
|
|
343
|
-
{ default: parser },
|
|
344
|
-
{
|
|
345
|
-
// No idea why this is doubly-nested, see https://github.com/ForbesLindesay/atdatabases/issues/255
|
|
346
|
-
default: { default: splitter },
|
|
347
|
-
},
|
|
348
|
-
] = await npxImport<
|
|
349
|
-
[{ default: SQL }, { default: { default: typeof splitSqlQuery } }]
|
|
350
|
-
>(["@databases/sql@3.2.0", "@databases/split-sql-query@1.0.3"], logDim);
|
|
351
|
-
return { parser, splitter };
|
|
352
|
-
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "path";
|
|
3
4
|
import { Box, render, Text } from "ink";
|
|
@@ -10,6 +11,7 @@ import isInteractive from "../../is-interactive";
|
|
|
10
11
|
import { logger } from "../../logger";
|
|
11
12
|
import { requireAuth } from "../../user";
|
|
12
13
|
import { createBackup } from "../backups";
|
|
14
|
+
import { DEFAULT_MIGRATION_PATH, DEFAULT_MIGRATION_TABLE } from "../constants";
|
|
13
15
|
import { executeSql } from "../execute";
|
|
14
16
|
import { d1BetaWarning, getDatabaseInfoFromConfig } from "../utils";
|
|
15
17
|
import {
|
|
@@ -28,11 +30,10 @@ export function ApplyOptions(yargs: Argv): Argv<BaseSqlExecuteArgs> {
|
|
|
28
30
|
|
|
29
31
|
export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
|
|
30
32
|
async ({ config, database, local, persistTo }): Promise<void> => {
|
|
31
|
-
const accountId = await requireAuth({});
|
|
32
33
|
logger.log(d1BetaWarning);
|
|
33
34
|
|
|
34
35
|
const databaseInfo = await getDatabaseInfoFromConfig(config, database);
|
|
35
|
-
if (!databaseInfo) {
|
|
36
|
+
if (!databaseInfo && !local) {
|
|
36
37
|
throw new Error(
|
|
37
38
|
`Can't find a DB with name/binding '${database}' in local config. Check info in wrangler.toml...`
|
|
38
39
|
);
|
|
@@ -44,11 +45,14 @@ export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
|
|
|
44
45
|
|
|
45
46
|
const migrationsPath = await getMigrationsPath(
|
|
46
47
|
path.dirname(config.configPath),
|
|
47
|
-
databaseInfo
|
|
48
|
+
databaseInfo?.migrationsFolderPath ?? DEFAULT_MIGRATION_PATH,
|
|
48
49
|
false
|
|
49
50
|
);
|
|
51
|
+
|
|
52
|
+
const migrationTableName =
|
|
53
|
+
databaseInfo?.migrationsTableName ?? DEFAULT_MIGRATION_TABLE;
|
|
50
54
|
await initMigrationsTable(
|
|
51
|
-
|
|
55
|
+
migrationTableName,
|
|
52
56
|
local,
|
|
53
57
|
config,
|
|
54
58
|
database,
|
|
@@ -57,7 +61,7 @@ export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
|
|
|
57
61
|
|
|
58
62
|
const unappliedMigrations = (
|
|
59
63
|
await getUnappliedMigrations(
|
|
60
|
-
|
|
64
|
+
migrationTableName,
|
|
61
65
|
migrationsPath,
|
|
62
66
|
local,
|
|
63
67
|
config,
|
|
@@ -89,22 +93,26 @@ export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
|
|
|
89
93
|
render(<Text>✅ No migrations to apply!</Text>);
|
|
90
94
|
return;
|
|
91
95
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
96
|
+
render(
|
|
97
|
+
<Box flexDirection="column">
|
|
98
|
+
<Text>Migrations to be applied:</Text>
|
|
99
|
+
<Table data={unappliedMigrations} columns={["Name"]}></Table>
|
|
100
|
+
</Box>
|
|
101
|
+
);
|
|
102
|
+
const ok = await confirm(
|
|
103
|
+
`About to apply ${unappliedMigrations.length} migration(s)
|
|
104
|
+
Your database may not be available to serve requests during the migration, continue?`
|
|
105
|
+
);
|
|
106
|
+
if (!ok) return;
|
|
104
107
|
|
|
105
108
|
// don't backup prod db when applying migrations locally
|
|
106
109
|
if (!local) {
|
|
110
|
+
assert(
|
|
111
|
+
databaseInfo,
|
|
112
|
+
"In non-local mode `databaseInfo` should be defined."
|
|
113
|
+
);
|
|
107
114
|
render(<Text>🕒 Creating backup...</Text>);
|
|
115
|
+
const accountId = await requireAuth({});
|
|
108
116
|
await createBackup(accountId, databaseInfo.uuid);
|
|
109
117
|
}
|
|
110
118
|
|
|
@@ -114,7 +122,7 @@ export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
|
|
|
114
122
|
"utf8"
|
|
115
123
|
);
|
|
116
124
|
query += `
|
|
117
|
-
INSERT INTO ${
|
|
125
|
+
INSERT INTO ${migrationTableName} (name)
|
|
118
126
|
values ('${migration.Name}');
|
|
119
127
|
`;
|
|
120
128
|
|
|
@@ -154,7 +162,9 @@ export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
|
|
|
154
162
|
const err = e as ParseError;
|
|
155
163
|
|
|
156
164
|
success = false;
|
|
157
|
-
errorNotes = err.notes
|
|
165
|
+
errorNotes = err.notes?.map((msg) => msg.text) ?? [
|
|
166
|
+
err.message ?? err.toString(),
|
|
167
|
+
];
|
|
158
168
|
}
|
|
159
169
|
|
|
160
170
|
migration.Status = success ? "✅" : "❌";
|
|
File without changes
|