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.
Files changed (128) hide show
  1. package/bin/wrangler.js +9 -1
  2. package/miniflare-dist/index.mjs +1 -1
  3. package/package.json +12 -10
  4. package/src/__tests__/api-dev.test.ts +65 -36
  5. package/src/__tests__/api-devregistry.test.js +14 -6
  6. package/src/__tests__/configuration.test.ts +2 -31
  7. package/src/__tests__/{d1.test.ts → d1/d1.test.ts} +48 -5
  8. package/src/__tests__/d1/splitter.test.ts +255 -0
  9. package/src/__tests__/delete.test.ts +5 -2
  10. package/src/__tests__/deployments.test.ts +20 -6
  11. package/src/__tests__/dev.test.tsx +52 -19
  12. package/src/__tests__/generate.test.ts +7 -4
  13. package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
  14. package/src/__tests__/helpers/mock-cfetch.ts +2 -57
  15. package/src/__tests__/helpers/mock-dialogs.ts +70 -86
  16. package/src/__tests__/helpers/mock-oauth-flow.ts +64 -49
  17. package/src/__tests__/helpers/mock-process.ts +8 -13
  18. package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
  19. package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
  20. package/src/__tests__/index.test.ts +46 -44
  21. package/src/__tests__/init.test.ts +761 -537
  22. package/src/__tests__/jest.setup.ts +20 -24
  23. package/src/__tests__/kv.test.ts +286 -173
  24. package/src/__tests__/logout.test.ts +1 -1
  25. package/src/__tests__/metrics.test.ts +5 -7
  26. package/src/__tests__/middleware.scheduled.test.ts +40 -30
  27. package/src/__tests__/middleware.test.ts +144 -120
  28. package/src/__tests__/pages.test.ts +1617 -1161
  29. package/src/__tests__/publish.test.ts +174 -125
  30. package/src/__tests__/r2.test.ts +2 -2
  31. package/src/__tests__/secret.test.ts +183 -126
  32. package/src/__tests__/tail.test.ts +6 -0
  33. package/src/__tests__/tsconfig-sanity.ts +12 -0
  34. package/src/__tests__/tsconfig.json +8 -0
  35. package/src/__tests__/tsconfig.tsbuildinfo +1 -0
  36. package/src/__tests__/whoami.test.tsx +1 -96
  37. package/src/api/dev.ts +78 -41
  38. package/src/api/index.ts +1 -1
  39. package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
  40. package/src/cfetch/index.ts +0 -2
  41. package/src/cfetch/internal.ts +6 -15
  42. package/src/cli.ts +2 -2
  43. package/src/config/validation.ts +1 -2
  44. package/src/create-worker-upload-form.ts +2 -2
  45. package/src/d1/{delete.tsx → delete.ts} +0 -0
  46. package/src/d1/execute.tsx +8 -37
  47. package/src/d1/migrations/apply.tsx +29 -19
  48. package/src/d1/migrations/{index.tsx → index.ts} +0 -0
  49. package/src/d1/splitter.ts +161 -0
  50. package/src/d1/{types.tsx → types.ts} +0 -0
  51. package/src/delete.ts +3 -8
  52. package/src/deployments.ts +6 -0
  53. package/src/deprecated/index.ts +2 -295
  54. package/src/dev/dev.tsx +2 -2
  55. package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
  56. package/src/dev/local.tsx +16 -4
  57. package/src/dev/remote.tsx +28 -1
  58. package/src/dev/start-server.ts +19 -11
  59. package/src/dev/use-esbuild.ts +1 -1
  60. package/src/{dev-registry.tsx → dev-registry.ts} +0 -0
  61. package/src/dev.tsx +21 -2
  62. package/src/dialogs.ts +136 -0
  63. package/src/dispatch-namespace.ts +1 -1
  64. package/src/docs/index.ts +3 -0
  65. package/src/environment-variables/factory.ts +88 -0
  66. package/src/environment-variables/misc-variables.ts +30 -0
  67. package/src/generate/index.ts +300 -0
  68. package/src/{index.tsx → index.ts} +10 -13
  69. package/src/init.ts +92 -52
  70. package/src/jest.d.ts +4 -0
  71. package/src/logger.ts +15 -3
  72. package/src/metrics/metrics-config.ts +1 -1
  73. package/src/miniflare-cli/assets.ts +4 -0
  74. package/src/miniflare-cli/index.ts +1 -5
  75. package/src/miniflare-cli/tsconfig.json +9 -0
  76. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
  77. package/src/miniflare-cli/types.ts +11 -0
  78. package/src/pages/{build.tsx → build.ts} +0 -0
  79. package/src/pages/{deployment-tails.tsx → deployment-tails.ts} +0 -0
  80. package/src/pages/{dev.tsx → dev.ts} +53 -55
  81. package/src/pages/functions/buildWorker.ts +1 -1
  82. package/src/pages/functions/tsconfig.json +8 -0
  83. package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
  84. package/src/pages/{functions.tsx → functions.ts} +0 -0
  85. package/src/pages/{hash.tsx → hash.ts} +0 -0
  86. package/src/pages/{index.tsx → index.ts} +0 -0
  87. package/src/pages/projects.tsx +3 -5
  88. package/src/pages/publish.tsx +5 -4
  89. package/src/pages/upload.tsx +1 -1
  90. package/src/publish/publish.ts +9 -7
  91. package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +1 -1
  92. package/src/secret/index.ts +1 -1
  93. package/src/{sites.tsx → sites.ts} +0 -0
  94. package/src/tail/index.ts +2 -3
  95. package/src/tsconfig-sanity.ts +16 -0
  96. package/src/user/access.ts +0 -1
  97. package/src/user/auth-variables.ts +113 -0
  98. package/src/user/choose-account.tsx +1 -31
  99. package/src/user/index.ts +0 -1
  100. package/src/user/{user.tsx → user.ts} +107 -73
  101. package/src/{whoami.tsx → whoami.ts} +37 -71
  102. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  103. package/templates/__tests__/tsconfig.json +8 -0
  104. package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
  105. package/templates/d1-beta-facade.js +36 -0
  106. package/templates/facade.d.ts +14 -0
  107. package/templates/first-party-worker-module-facade.ts +4 -3
  108. package/templates/format-dev-errors.ts +7 -6
  109. package/templates/init-tests/test-jest-new-worker.js +3 -5
  110. package/templates/init-tests/test-vitest-new-worker.js +3 -5
  111. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  112. package/templates/middleware/loader-modules.ts +0 -2
  113. package/templates/middleware/loader-sw.ts +6 -0
  114. package/templates/pages-dev-pipeline.ts +4 -1
  115. package/templates/pages-shim.ts +4 -1
  116. package/templates/pages-template-plugin.ts +12 -7
  117. package/templates/serve-static-assets.ts +16 -14
  118. package/templates/tsconfig-sanity.ts +11 -0
  119. package/templates/tsconfig.init.json +106 -0
  120. package/templates/tsconfig.json +5 -103
  121. package/templates/tsconfig.tsbuildinfo +1 -0
  122. package/wrangler-dist/cli.d.ts +58 -60
  123. package/wrangler-dist/cli.js +34440 -55514
  124. package/wrangler-dist/wasm-sync.wasm +0 -0
  125. package/src/__tests__/dialogs.test.tsx +0 -40
  126. package/src/dialogs.tsx +0 -168
  127. package/src/environment-variables.ts +0 -50
  128. 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, WhoAmI } from "../whoami";
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 DevOptions {
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
- d1Databases?: Environment["d1_databases"];
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
- experimentalLocalRemoteKv?: boolean;
61
- }
62
-
63
- interface DevApiOptions {
64
- testMode?: boolean;
65
- disableExperimentalWarning?: boolean;
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?: DevOptions,
81
- apiOptions?: DevApiOptions
78
+ options?: UnstableDevOptions,
79
+ apiOptions?: unknown
82
80
  ): Promise<UnstableDevWorker> {
83
- const { testMode = true, disableExperimentalWarning = false } =
84
- apiOptions || {};
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
@@ -6,8 +6,6 @@ import type { RequestInit } from "undici";
6
6
 
7
7
  // Check out https://api.cloudflare.com/ for API docs.
8
8
 
9
- export { getCloudflareAPIBaseURL as getCloudflareApiBaseUrl } from "./internal";
10
-
11
9
  export interface FetchError {
12
10
  code: number;
13
11
  message: string;
@@ -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 { getEnvironmentVariableFactory } from "../environment-variables";
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} ${getCloudflareAPIBaseURL()}${resource}${queryString}`
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(`${getCloudflareAPIBaseURL()}${resource}${queryString}`, {
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 = `${getCloudflareAPIBaseURL()}/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`;
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(`${getCloudflareAPIBaseURL()}${resource}`, {
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(`${getCloudflareAPIBaseURL()}${resource}`, {
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 };
@@ -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
- `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: set NO_D1_WARNING=true to hide this message`
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: "namespace"; name: string; namespace: string }
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: "namespace",
164
+ type: "dispatch_namespace",
165
165
  namespace,
166
166
  });
167
167
  });
File without changes
@@ -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, logDim } from "../dialogs";
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 { parser, splitter } = await loadSqlUtils();
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
- const queries = splitSql(splitter, sql);
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
- logDim
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.migrationsFolderPath,
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
- databaseInfo.migrationsTableName,
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
- databaseInfo.migrationsTableName,
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
- if (isInteractive() && !CI.isCI()) {
94
- const ok = await confirm(
95
- `About to apply ${unappliedMigrations.length} migration(s)\n` +
96
- "Your database may not be available to serve requests during the migration, continue?",
97
- <Box flexDirection="column">
98
- <Text>Migrations to be applied:</Text>
99
- <Table data={unappliedMigrations} columns={["Name"]}></Table>
100
- </Box>
101
- );
102
- if (!ok) return;
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 ${databaseInfo.migrationsTableName} (name)
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.map((msg) => msg.text);
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