wrangler 2.6.1 → 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 -42
- package/src/__tests__/init.test.ts +782 -522
- 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 +1618 -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 +16 -18
- package/src/cli.ts +2 -2
- package/src/config/index.ts +2 -1
- 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 +32 -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 +35 -11
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +1 -1
- package/src/docs/index.ts +97 -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} +16 -10
- package/src/init.ts +106 -60
- package/src/jest.d.ts +4 -0
- package/src/logger.ts +15 -3
- package/src/metrics/metrics-config.ts +1 -1
- package/src/metrics/send-event.ts +2 -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 +16 -5
- package/src/pages/upload.tsx +27 -6
- 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 +34498 -55459
- 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,12 +33,17 @@ 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}`
|
|
37
|
+
);
|
|
38
|
+
const logHeaders = cloneHeaders(headers);
|
|
39
|
+
delete logHeaders["Authorization"];
|
|
40
|
+
logger.debug("HEADERS:", JSON.stringify(logHeaders, null, 2));
|
|
41
|
+
logger.debug(
|
|
42
|
+
"INIT:",
|
|
43
|
+
JSON.stringify({ ...init, headers: logHeaders }, null, 2)
|
|
46
44
|
);
|
|
47
|
-
logger.debug("HEADERS:", JSON.stringify(headers, null, 2));
|
|
48
|
-
logger.debug("INIT:", JSON.stringify(init, null, 2));
|
|
49
45
|
logger.debug("-- END CF API REQUEST");
|
|
50
|
-
return await fetch(`${
|
|
46
|
+
return await fetch(`${getCloudflareApiBaseUrl()}${resource}${queryString}`, {
|
|
51
47
|
method,
|
|
52
48
|
...init,
|
|
53
49
|
headers,
|
|
@@ -83,7 +79,9 @@ export async function fetchInternal<ResponseType>(
|
|
|
83
79
|
response.statusText,
|
|
84
80
|
response.status
|
|
85
81
|
);
|
|
86
|
-
|
|
82
|
+
const logHeaders = cloneHeaders(response.headers);
|
|
83
|
+
delete logHeaders["Authorization"];
|
|
84
|
+
logger.debug("HEADERS:", JSON.stringify(logHeaders, null, 2));
|
|
87
85
|
logger.debug("RESPONSE:", jsonText);
|
|
88
86
|
logger.debug("-- END CF API RESPONSE");
|
|
89
87
|
|
|
@@ -166,7 +164,7 @@ export async function fetchKVGetValue(
|
|
|
166
164
|
const auth = requireApiToken();
|
|
167
165
|
const headers: Record<string, string> = {};
|
|
168
166
|
addAuthorizationHeaderIfUnspecified(headers, auth);
|
|
169
|
-
const resource = `${
|
|
167
|
+
const resource = `${getCloudflareApiBaseUrl()}/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`;
|
|
170
168
|
const response = await fetch(resource, {
|
|
171
169
|
method: "GET",
|
|
172
170
|
headers,
|
|
@@ -199,7 +197,7 @@ export async function fetchR2Objects(
|
|
|
199
197
|
addAuthorizationHeaderIfUnspecified(headers, auth);
|
|
200
198
|
addUserAgent(headers);
|
|
201
199
|
|
|
202
|
-
const response = await fetch(`${
|
|
200
|
+
const response = await fetch(`${getCloudflareApiBaseUrl()}${resource}`, {
|
|
203
201
|
...bodyInit,
|
|
204
202
|
headers,
|
|
205
203
|
});
|
|
@@ -226,7 +224,7 @@ export async function fetchDashboardScript(
|
|
|
226
224
|
addAuthorizationHeaderIfUnspecified(headers, auth);
|
|
227
225
|
addUserAgent(headers);
|
|
228
226
|
|
|
229
|
-
const response = await fetch(`${
|
|
227
|
+
const response = await fetch(`${getCloudflareApiBaseUrl()}${resource}`, {
|
|
230
228
|
...bodyInit,
|
|
231
229
|
headers,
|
|
232
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/index.ts
CHANGED
|
@@ -166,7 +166,8 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
166
166
|
if (database_name) {
|
|
167
167
|
databaseValue = `${database_name} (${database_id})`;
|
|
168
168
|
}
|
|
169
|
-
|
|
169
|
+
//database_id is local when running `wrangler dev --local`
|
|
170
|
+
if (preview_database_id && database_id !== "local") {
|
|
170
171
|
databaseValue += `, Preview: (${preview_database_id})`;
|
|
171
172
|
}
|
|
172
173
|
return {
|
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,29 +93,36 @@ export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
|
|
|
89
93
|
render(<Text>✅ No migrations to apply!</Text>);
|
|
90
94
|
return;
|
|
91
95
|
}
|
|
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;
|
|
92
107
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<Text>Migrations to be applied:</Text>
|
|
99
|
-
<Table data={unappliedMigrations} columns={["Name"]}></Table>
|
|
100
|
-
</Box>
|
|
108
|
+
// don't backup prod db when applying migrations locally
|
|
109
|
+
if (!local) {
|
|
110
|
+
assert(
|
|
111
|
+
databaseInfo,
|
|
112
|
+
"In non-local mode `databaseInfo` should be defined."
|
|
101
113
|
);
|
|
102
|
-
|
|
114
|
+
render(<Text>🕒 Creating backup...</Text>);
|
|
115
|
+
const accountId = await requireAuth({});
|
|
116
|
+
await createBackup(accountId, databaseInfo.uuid);
|
|
103
117
|
}
|
|
104
118
|
|
|
105
|
-
render(<Text>🕒 Creating backup...</Text>);
|
|
106
|
-
await createBackup(accountId, databaseInfo.uuid);
|
|
107
|
-
|
|
108
119
|
for (const migration of unappliedMigrations) {
|
|
109
120
|
let query = fs.readFileSync(
|
|
110
121
|
`${migrationsPath}/${migration.Name}`,
|
|
111
122
|
"utf8"
|
|
112
123
|
);
|
|
113
124
|
query += `
|
|
114
|
-
INSERT INTO ${
|
|
125
|
+
INSERT INTO ${migrationTableName} (name)
|
|
115
126
|
values ('${migration.Name}');
|
|
116
127
|
`;
|
|
117
128
|
|
|
@@ -151,7 +162,9 @@ export const ApplyHandler = withConfig<BaseSqlExecuteArgs>(
|
|
|
151
162
|
const err = e as ParseError;
|
|
152
163
|
|
|
153
164
|
success = false;
|
|
154
|
-
errorNotes = err.notes
|
|
165
|
+
errorNotes = err.notes?.map((msg) => msg.text) ?? [
|
|
166
|
+
err.message ?? err.toString(),
|
|
167
|
+
];
|
|
155
168
|
}
|
|
156
169
|
|
|
157
170
|
migration.Status = success ? "✅" : "❌";
|
|
File without changes
|