wrangler 0.0.0-e33294b0 → 0.0.0-e3c036d7

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 (58) hide show
  1. package/bin/wrangler.js +1 -1
  2. package/miniflare-dist/index.mjs +21 -4
  3. package/package.json +8 -8
  4. package/src/__tests__/configuration.test.ts +235 -6
  5. package/src/__tests__/d1/execute.test.ts +1 -1
  6. package/src/__tests__/dev.test.tsx +16 -1
  7. package/src/__tests__/guess-worker-format.test.ts +35 -0
  8. package/src/__tests__/init.test.ts +8 -7
  9. package/src/__tests__/middleware.test.ts +2 -1
  10. package/src/__tests__/pages/functions-build.test.ts +51 -0
  11. package/src/__tests__/publish.test.ts +122 -8
  12. package/src/__tests__/test-old-node-version.js +3 -3
  13. package/src/__tests__/tsconfig.tsbuildinfo +1 -1
  14. package/src/__tests__/type-generation.test.ts +1 -0
  15. package/src/__tests__/user.test.ts +1 -1
  16. package/src/api/dev.ts +3 -4
  17. package/src/api/pages/publish.tsx +7 -0
  18. package/src/bundle.ts +23 -9
  19. package/src/config/environment.ts +9 -4
  20. package/src/config/index.ts +12 -2
  21. package/src/config/validation-helpers.ts +1 -1
  22. package/src/config/validation.ts +58 -4
  23. package/src/create-worker-preview.ts +19 -8
  24. package/src/create-worker-upload-form.ts +10 -2
  25. package/src/dev/dev.tsx +4 -4
  26. package/src/dev/local.tsx +17 -20
  27. package/src/dev/start-server.ts +10 -8
  28. package/src/dev/use-esbuild.ts +9 -5
  29. package/src/dev/validate-dev-props.ts +9 -0
  30. package/src/dev.tsx +27 -13
  31. package/src/entry.ts +1 -2
  32. package/src/index.ts +1 -1
  33. package/src/init.ts +1 -0
  34. package/src/inspect.ts +16 -1
  35. package/src/miniflare-cli/assets.ts +8 -7
  36. package/src/miniflare-cli/index.ts +1 -1
  37. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -1
  38. package/src/pages/build.ts +25 -5
  39. package/src/pages/buildFunctions.ts +7 -4
  40. package/src/pages/dev.ts +18 -8
  41. package/src/pages/functions/buildPlugin.ts +10 -3
  42. package/src/pages/functions/buildWorker.ts +12 -6
  43. package/src/pages/functions/tsconfig.tsbuildinfo +1 -1
  44. package/src/paths.ts +1 -1
  45. package/src/publish/index.ts +1 -1
  46. package/src/publish/publish.ts +19 -8
  47. package/src/r2/helpers.ts +1 -0
  48. package/src/secret/index.ts +1 -1
  49. package/src/type-generation.ts +1 -1
  50. package/src/user/user.ts +1 -1
  51. package/src/worker.ts +8 -1
  52. package/templates/d1-beta-facade.js +2 -2
  53. package/templates/gitignore +1 -0
  54. package/templates/middleware/middleware-miniflare3-json-error.ts +17 -5
  55. package/templates/pages-template-plugin.ts +7 -3
  56. package/templates/tsconfig.tsbuildinfo +1 -1
  57. package/wrangler-dist/cli.d.ts +522 -6
  58. package/wrangler-dist/cli.js +11004 -4192
@@ -76,6 +76,7 @@ const bindingsConfigMock: Partial<Config> = {
76
76
  wasm_modules: { MODULE1: "module1.wasm", MODULE2: "module2.wasm" },
77
77
  unsafe: {
78
78
  bindings: [{ name: "testing_unsafe", type: "plain_text" }],
79
+ metadata: { some_key: "some_value" },
79
80
  },
80
81
  rules: [
81
82
  {
@@ -85,7 +85,7 @@ describe("User", () => {
85
85
  await expect(
86
86
  requireAuth({} as Config)
87
87
  ).rejects.toThrowErrorMatchingInlineSnapshot(
88
- `"In a non-interactive environment, it's necessary to set a CLOUDFLARE_API_TOKEN environment variable for wrangler to work. Please go to https://developers.cloudflare.com/api/tokens/create/ for instructions on how to create an api token, and assign its value to CLOUDFLARE_API_TOKEN."`
88
+ `"In a non-interactive environment, it's necessary to set a CLOUDFLARE_API_TOKEN environment variable for wrangler to work. Please go to https://developers.cloudflare.com/fundamentals/api/get-started/create-token/ for instructions on how to create an api token, and assign its value to CLOUDFLARE_API_TOKEN."`
89
89
  );
90
90
  });
91
91
 
package/src/api/dev.ts CHANGED
@@ -18,7 +18,7 @@ export interface UnstableDevOptions {
18
18
  site?: string; // Root folder of static assets for Workers Sites
19
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
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
21
+ nodeCompat?: boolean; // Enable Node.js compatibility
22
22
  compatibilityDate?: string; // Date to use for compatibility checks
23
23
  compatibilityFlags?: string[]; // Flags to use for compatibility checks
24
24
  persist?: boolean; // Enable persistence for local mode, using default path: .wrangler/state
@@ -43,7 +43,6 @@ export interface UnstableDevOptions {
43
43
  preview_bucket_name?: string;
44
44
  }[];
45
45
  logLevel?: "none" | "info" | "error" | "log" | "warn" | "debug"; // Specify logging level [choices: "debug", "info", "log", "warn", "error", "none"] [default: "log"]
46
- logPrefix?: string;
47
46
  inspect?: boolean;
48
47
  local?: boolean;
49
48
  accountId?: string;
@@ -163,7 +162,7 @@ export async function unstable_dev(
163
162
  site: options?.site, // Root folder of static assets for Workers Sites
164
163
  siteInclude: options?.siteInclude, // Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.
165
164
  siteExclude: options?.siteExclude, // Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.
166
- nodeCompat: options?.nodeCompat, // Enable node.js compatibility
165
+ nodeCompat: options?.nodeCompat, // Enable Node.js compatibility
167
166
  persist: options?.persist, // Enable persistence for local mode, using default path: .wrangler/state
168
167
  persistTo: options?.persistTo, // Specify directory to use for local persistence (implies --persist)
169
168
  experimentalJsonConfig: undefined,
@@ -252,7 +251,7 @@ export async function unstable_dev(
252
251
  site: options?.site, // Root folder of static assets for Workers Sites
253
252
  siteInclude: options?.siteInclude, // Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.
254
253
  siteExclude: options?.siteExclude, // Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.
255
- nodeCompat: options?.nodeCompat, // Enable node.js compatibility
254
+ nodeCompat: options?.nodeCompat, // Enable Node.js compatibility
256
255
  persist: options?.persist, // Enable persistence for local mode, using default path: .wrangler/state
257
256
  persistTo: options?.persistTo, // Specify directory to use for local persistence (implies --persist)
258
257
  experimentalJsonConfig: undefined,
@@ -137,6 +137,11 @@ export async function publish({
137
137
  isProduction = project.production_branch === branch;
138
138
  }
139
139
 
140
+ const deploymentConfig =
141
+ project.deployment_configs[isProduction ? "production" : "preview"];
142
+ const nodejsCompat =
143
+ deploymentConfig.compatibility_flags?.includes("nodejs_compat");
144
+
140
145
  /**
141
146
  * Evaluate if this is an Advanced Mode or Pages Functions project. If Advanced Mode, we'll
142
147
  * go ahead and upload `_worker.js` as is, but if Pages Functions, we need to attempt to build
@@ -176,6 +181,7 @@ export async function publish({
176
181
  routesOutputPath,
177
182
  local: false,
178
183
  d1Databases,
184
+ nodejsCompat,
179
185
  experimentalWorkerBundle,
180
186
  });
181
187
 
@@ -261,6 +267,7 @@ export async function publish({
261
267
  watch: false,
262
268
  onEnd: () => {},
263
269
  betaD1Shims: d1Databases,
270
+ nodejsCompat,
264
271
  experimentalWorkerBundle,
265
272
  });
266
273
  workerFileContents = readFileSync(outfile, "utf8");
package/src/bundle.ts CHANGED
@@ -85,6 +85,15 @@ Add "node_compat = true" to your wrangler.toml file to enable Node compatibility
85
85
  }
86
86
  }
87
87
 
88
+ const nodejsCompatPlugin: esbuild.Plugin = {
89
+ name: "nodejs_compat Plugin",
90
+ setup(pluginBuild) {
91
+ pluginBuild.onResolve({ filter: /node:.*/ }, () => {
92
+ return { external: true };
93
+ });
94
+ },
95
+ };
96
+
88
97
  /**
89
98
  * Generate a bundle for the worker identified by the arguments passed in.
90
99
  */
@@ -102,7 +111,8 @@ export async function bundleWorker(
102
111
  watch?: esbuild.WatchMode | boolean;
103
112
  tsconfig?: string;
104
113
  minify?: boolean;
105
- nodeCompat?: boolean;
114
+ legacyNodeCompat?: boolean;
115
+ nodejsCompat?: boolean;
106
116
  define: Config["define"];
107
117
  checkFetch: boolean;
108
118
  services?: Config["services"];
@@ -131,7 +141,8 @@ export async function bundleWorker(
131
141
  watch,
132
142
  tsconfig,
133
143
  minify,
134
- nodeCompat,
144
+ legacyNodeCompat,
145
+ nodejsCompat,
135
146
  checkFetch,
136
147
  local,
137
148
  assets,
@@ -277,7 +288,7 @@ export async function bundleWorker(
277
288
  currentEntry,
278
289
  tmpDir.path,
279
290
  betaD1Shims,
280
- local,
291
+ local && !experimentalLocal,
281
292
  doBindings
282
293
  );
283
294
  }),
@@ -333,7 +344,8 @@ export async function bundleWorker(
333
344
  inject,
334
345
  external: ["__STATIC_CONTENT_MANIFEST"],
335
346
  format: entry.format === "modules" ? "esm" : "iife",
336
- target: "es2020",
347
+ // Our workerd runtime uses the same V8 version as recent Chrome, which is highly ES2022 compliant: https://kangax.github.io/compat-table/es2016plus/
348
+ target: "es2022",
337
349
  sourcemap: sourcemap ?? true, // this needs to use ?? to accept false
338
350
  // Include a reference to the output folder in the sourcemap.
339
351
  // This is omitted by default, but we need it to properly resolve source paths in error output.
@@ -346,7 +358,7 @@ export async function bundleWorker(
346
358
  // use process.env["NODE_ENV" + ""] so that esbuild doesn't replace it
347
359
  // when we do a build of wrangler. (re: https://github.com/cloudflare/workers-sdk/issues/1477)
348
360
  "process.env.NODE_ENV": `"${process.env["NODE_ENV" + ""]}"`,
349
- ...(nodeCompat ? { global: "globalThis" } : {}),
361
+ ...(legacyNodeCompat ? { global: "globalThis" } : {}),
350
362
  ...(checkFetch ? { fetch: "checkedFetch" } : {}),
351
363
  ...options.define,
352
364
  },
@@ -359,9 +371,10 @@ export async function bundleWorker(
359
371
  },
360
372
  plugins: [
361
373
  moduleCollector.plugin,
362
- ...(nodeCompat
374
+ ...(legacyNodeCompat
363
375
  ? [NodeGlobalsPolyfills({ buffer: true }), NodeModulesPolyfills()]
364
376
  : []),
377
+ ...(nodejsCompat ? [nodejsCompatPlugin] : []),
365
378
  ...(plugins || []),
366
379
  ],
367
380
  ...(jsxFactory && { jsxFactory }),
@@ -377,7 +390,8 @@ export async function bundleWorker(
377
390
  try {
378
391
  result = await esbuild.build(buildOptions);
379
392
  } catch (e) {
380
- if (!nodeCompat && isBuildFailure(e)) rewriteNodeCompatBuildFailure(e);
393
+ if (!legacyNodeCompat && isBuildFailure(e))
394
+ rewriteNodeCompatBuildFailure(e);
381
395
  throw e;
382
396
  }
383
397
 
@@ -802,7 +816,7 @@ async function applyD1BetaFacade(
802
816
  entry: Entry,
803
817
  tmpDirPath: string,
804
818
  betaD1Shims: string[],
805
- local: boolean,
819
+ miniflare2: boolean,
806
820
  doBindings: DurableObjectBindings
807
821
  ): Promise<Entry> {
808
822
  let entrypointPath = path.resolve(
@@ -853,7 +867,7 @@ async function applyD1BetaFacade(
853
867
  ],
854
868
  define: {
855
869
  __D1_IMPORTS__: JSON.stringify(betaD1Shims),
856
- __LOCAL_MODE__: JSON.stringify(local),
870
+ __LOCAL_MODE__: JSON.stringify(miniflare2),
857
871
  },
858
872
  outfile: targetPath,
859
873
  });
@@ -463,7 +463,6 @@ interface EnvironmentNonInheritable {
463
463
  * NOTE: This field is not automatically inherited from the top level environment,
464
464
  * and so must be specified in every named environment.
465
465
  *
466
- * @default `{ bindings: [] }`
467
466
  * @nonInheritable
468
467
  */
469
468
  unsafe: {
@@ -471,14 +470,20 @@ interface EnvironmentNonInheritable {
471
470
  * A set of bindings that should be put into a Worker's upload metadata without changes. These
472
471
  * can be used to implement bindings for features that haven't released and aren't supported
473
472
  * directly by wrangler or miniflare.
474
- *
475
- * @default []
476
473
  */
477
- bindings: {
474
+ bindings?: {
478
475
  name: string;
479
476
  type: string;
480
477
  [key: string]: unknown;
481
478
  }[];
479
+
480
+ /**
481
+ * Arbitrary key/value pairs that will be included in the uploaded metadata. Values specified
482
+ * here will always be applied to metadata last, so can add new or override existing fields.
483
+ */
484
+ metadata?: {
485
+ [key: string]: string;
486
+ };
482
487
  };
483
488
 
484
489
  mtls_certificates: {
@@ -255,10 +255,10 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
255
255
  });
256
256
  }
257
257
 
258
- if (unsafe !== undefined && unsafe.length > 0) {
258
+ if (unsafe?.bindings !== undefined && unsafe.bindings.length > 0) {
259
259
  output.push({
260
260
  type: "Unsafe",
261
- entries: unsafe.map(({ name, type }) => ({
261
+ entries: unsafe.bindings.map(({ name, type }) => ({
262
262
  key: type,
263
263
  value: name,
264
264
  })),
@@ -319,6 +319,16 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
319
319
  });
320
320
  }
321
321
 
322
+ if (unsafe?.metadata !== undefined) {
323
+ output.push({
324
+ type: "Unsafe Metadata",
325
+ entries: Object.entries(unsafe.metadata).map(([key, value]) => ({
326
+ key,
327
+ value: `${value}`,
328
+ })),
329
+ });
330
+ }
331
+
322
332
  if (output.length === 0) {
323
333
  return;
324
334
  }
@@ -550,7 +550,7 @@ export const getBindingNames = (value: unknown): string[] => {
550
550
  } else if (isNamespaceList(value)) {
551
551
  return value.map(({ binding }) => binding);
552
552
  } else if (isRecord(value)) {
553
- return Object.keys(value);
553
+ return Object.keys(value).filter((k) => value[k] !== undefined);
554
554
  } else {
555
555
  return [];
556
556
  }
@@ -1162,10 +1162,8 @@ function normalizeAndValidateEnvironment(
1162
1162
  rawEnv,
1163
1163
  envName,
1164
1164
  "unsafe",
1165
- validateBindingsProperty(envName, validateUnsafeBinding),
1166
- {
1167
- bindings: [],
1168
- }
1165
+ validateUnsafeSettings(envName),
1166
+ {}
1169
1167
  ),
1170
1168
  zone_id: rawEnv.zone_id,
1171
1169
  no_bundle: inheritable(
@@ -1495,6 +1493,62 @@ const validateBindingsProperty =
1495
1493
  return isValid;
1496
1494
  };
1497
1495
 
1496
+ const validateUnsafeSettings =
1497
+ (envName: string): ValidatorFn =>
1498
+ (diagnostics, field, value, config) => {
1499
+ const fieldPath =
1500
+ config === undefined ? `${field}` : `env.${envName}.${field}`;
1501
+
1502
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1503
+ diagnostics.errors.push(
1504
+ `The field "${fieldPath}" should be an object but got ${JSON.stringify(
1505
+ value
1506
+ )}.`
1507
+ );
1508
+ return false;
1509
+ }
1510
+
1511
+ // At least one of bindings and metadata must exist
1512
+ if (!hasProperty(value, "bindings") && !hasProperty(value, "metadata")) {
1513
+ diagnostics.errors.push(
1514
+ `The field "${fieldPath}" should contain at least one of "bindings" or "metadata" properties but got ${JSON.stringify(
1515
+ value
1516
+ )}.`
1517
+ );
1518
+ return false;
1519
+ }
1520
+
1521
+ // unsafe.bindings
1522
+ if (hasProperty(value, "bindings") && value.bindings !== undefined) {
1523
+ const validateBindingsFn = validateBindingsProperty(
1524
+ envName,
1525
+ validateUnsafeBinding
1526
+ );
1527
+ const valid = validateBindingsFn(diagnostics, field, value, config);
1528
+ if (!valid) {
1529
+ return false;
1530
+ }
1531
+ }
1532
+
1533
+ // unsafe.metadata
1534
+ if (
1535
+ hasProperty(value, "metadata") &&
1536
+ value.metadata !== undefined &&
1537
+ (typeof value.metadata !== "object" ||
1538
+ value.metadata === null ||
1539
+ Array.isArray(value.metadata))
1540
+ ) {
1541
+ diagnostics.errors.push(
1542
+ `The field "${fieldPath}.metadata" should be an object but got ${JSON.stringify(
1543
+ value.metadata
1544
+ )}.`
1545
+ );
1546
+ return false;
1547
+ }
1548
+
1549
+ return true;
1550
+ };
1551
+
1498
1552
  /**
1499
1553
  * Check that the given field is a valid "durable_object" binding object.
1500
1554
  */
@@ -109,6 +109,14 @@ function randomId(): string {
109
109
  });
110
110
  }
111
111
 
112
+ // URLs are often relative to the zone. Sometimes the base zone
113
+ // will be grey-clouded, and so the host must be swapped out for
114
+ // the worker route host, which is more likely to be orange-clouded
115
+ function switchHost(originalUrl: string, host?: string): URL {
116
+ const url = new URL(originalUrl);
117
+ url.hostname = host ?? url.hostname;
118
+ return url;
119
+ }
112
120
  /**
113
121
  * Generates a preview session token.
114
122
  */
@@ -129,9 +137,13 @@ export async function createPreviewSession(
129
137
  abortSignal
130
138
  );
131
139
 
132
- logger.debug(`-- START EXCHANGE API REQUEST: GET ${exchange_url}`);
140
+ const switchedExchangeUrl = switchHost(exchange_url, ctx.host).toString();
141
+
142
+ logger.debug(`-- START EXCHANGE API REQUEST: GET ${switchedExchangeUrl}`);
133
143
  logger.debug("-- END EXCHANGE API REQUEST");
134
- const exchangeResponse = await fetch(exchange_url, { signal: abortSignal });
144
+ const exchangeResponse = await fetch(switchedExchangeUrl, {
145
+ signal: abortSignal,
146
+ });
135
147
  const bodyText = await exchangeResponse.text();
136
148
  logger.debug(
137
149
  "-- START EXCHANGE API RESPONSE:",
@@ -147,16 +159,15 @@ export async function createPreviewSession(
147
159
  token: string;
148
160
  prewarm: string;
149
161
  }>(bodyText);
150
-
151
- const { host } = new URL(inspector_websocket);
152
- const query = `cf_workers_preview_token=${token}`;
162
+ const inspector = new URL(inspector_websocket);
163
+ inspector.searchParams.append("cf_workers_preview_token", token);
153
164
 
154
165
  return {
155
166
  id: randomId(),
156
167
  value: token,
157
- host,
158
- inspectorUrl: new URL(`${inspector_websocket}?${query}`),
159
- prewarmUrl: new URL(prewarm),
168
+ host: ctx.host ?? inspector.host,
169
+ inspectorUrl: switchHost(inspector.href, ctx.host),
170
+ prewarmUrl: switchHost(prewarm, ctx.host),
160
171
  };
161
172
  }
162
173
 
@@ -65,6 +65,8 @@ export interface WorkerMetadata {
65
65
  bindings: WorkerMetadataBinding[];
66
66
  keep_bindings?: WorkerMetadataBinding["type"][];
67
67
  logpush?: boolean;
68
+ // Allow unsafe.metadata to add arbitary properties at runtime
69
+ [key: string]: unknown;
68
70
  }
69
71
 
70
72
  /**
@@ -284,9 +286,9 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
284
286
  }
285
287
  }
286
288
 
287
- if (bindings.unsafe) {
289
+ if (bindings.unsafe?.bindings) {
288
290
  // @ts-expect-error unsafe bindings don't need to match a specific type here
289
- metadataBindings.push(...bindings.unsafe);
291
+ metadataBindings.push(...bindings.unsafe.bindings);
290
292
  }
291
293
 
292
294
  const metadata: WorkerMetadata = {
@@ -303,6 +305,12 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
303
305
  ...(logpush !== undefined && { logpush }),
304
306
  };
305
307
 
308
+ if (bindings.unsafe?.metadata !== undefined) {
309
+ for (const key of Object.keys(bindings.unsafe.metadata)) {
310
+ metadata[key] = bindings.unsafe.metadata[key];
311
+ }
312
+ }
313
+
306
314
  formData.set("metadata", JSON.stringify(metadata));
307
315
 
308
316
  if (main.type === "commonjs" && modules && modules.length > 0) {
package/src/dev/dev.tsx CHANGED
@@ -138,7 +138,8 @@ export type DevProps = {
138
138
  compatibilityFlags: string[] | undefined;
139
139
  usageModel: "bundled" | "unbound" | undefined;
140
140
  minify: boolean | undefined;
141
- nodeCompat: boolean | undefined;
141
+ legacyNodeCompat: boolean | undefined;
142
+ nodejsCompat: boolean | undefined;
142
143
  build: Config["build"];
143
144
  env: string | undefined;
144
145
  legacyEnv: boolean;
@@ -146,7 +147,6 @@ export type DevProps = {
146
147
  host: string | undefined;
147
148
  routes: Route[] | undefined;
148
149
  inspect: boolean;
149
- logPrefix?: string;
150
150
  onReady: ((ip: string, port: number) => void) | undefined;
151
151
  showInteractiveDevSession: boolean | undefined;
152
152
  forceLocal: boolean | undefined;
@@ -278,7 +278,8 @@ function DevSession(props: DevSessionProps) {
278
278
  ),
279
279
  tsconfig: props.tsconfig,
280
280
  minify: props.minify,
281
- nodeCompat: props.nodeCompat,
281
+ legacyNodeCompat: props.legacyNodeCompat,
282
+ nodejsCompat: props.nodejsCompat,
282
283
  betaD1Shims,
283
284
  define: props.define,
284
285
  noBundle: props.noBundle,
@@ -341,7 +342,6 @@ function DevSession(props: DevSessionProps) {
341
342
  queueConsumers={props.queueConsumers}
342
343
  localProtocol={props.localProtocol}
343
344
  localUpstream={props.localUpstream}
344
- logPrefix={props.logPrefix}
345
345
  inspect={props.inspect}
346
346
  onReady={announceAndOnReady}
347
347
  enablePagesAssetsServiceBinding={props.enablePagesAssetsServiceBinding}
package/src/dev/local.tsx CHANGED
@@ -47,7 +47,6 @@ import type {
47
47
  } from "@miniflare/tre";
48
48
  import type { MiniflareOptions } from "miniflare";
49
49
  import type { ChildProcess } from "node:child_process";
50
- import type { RequestInit } from "undici";
51
50
 
52
51
  export interface LocalProps {
53
52
  name: string | undefined;
@@ -71,7 +70,6 @@ export interface LocalProps {
71
70
  localUpstream: string | undefined;
72
71
  inspect: boolean;
73
72
  onReady: ((ip: string, port: number) => void) | undefined;
74
- logPrefix?: string;
75
73
  enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
76
74
  testScheduled?: boolean;
77
75
  experimentalLocal: boolean | undefined;
@@ -122,7 +120,6 @@ function useLocalWorker({
122
120
  localUpstream,
123
121
  inspect,
124
122
  onReady,
125
- logPrefix,
126
123
  enablePagesAssetsServiceBinding,
127
124
  experimentalLocal,
128
125
  accountId,
@@ -217,13 +214,12 @@ function useLocalWorker({
217
214
  dataBlobBindings,
218
215
  crons,
219
216
  upstream,
220
- logPrefix,
221
217
  workerDefinitions,
222
218
  enablePagesAssetsServiceBinding,
223
219
  });
224
220
 
225
221
  if (experimentalLocal) {
226
- const log = await buildMiniflare3Logger(logPrefix);
222
+ const log = await buildMiniflare3Logger();
227
223
  const mf3Options = await transformMf2OptionsToMf3Options({
228
224
  miniflare2Options: options,
229
225
  format,
@@ -232,6 +228,7 @@ function useLocalWorker({
232
228
  enablePagesAssetsServiceBinding,
233
229
  kvNamespaces: bindings?.kv_namespaces,
234
230
  r2Buckets: bindings?.r2_buckets,
231
+ d1Databases: bindings?.d1_databases,
235
232
  authenticatedAccountId: accountId,
236
233
  kvRemote: experimentalLocalRemoteKv,
237
234
  inspectorPort: runtimeInspectorPort,
@@ -438,7 +435,6 @@ function useLocalWorker({
438
435
  localProtocol,
439
436
  localUpstream,
440
437
  inspect,
441
- logPrefix,
442
438
  onReady,
443
439
  enablePagesAssetsServiceBinding,
444
440
  experimentalLocal,
@@ -577,7 +573,6 @@ interface SetupMiniflareOptionsProps {
577
573
  dataBlobBindings: Record<string, string>;
578
574
  crons: Config["triggers"]["crons"];
579
575
  upstream: string | undefined;
580
- logPrefix: string | undefined;
581
576
  workerDefinitions: WorkerRegistry | undefined;
582
577
  enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
583
578
  }
@@ -609,7 +604,6 @@ export function setupMiniflareOptions({
609
604
  dataBlobBindings,
610
605
  crons,
611
606
  upstream,
612
- logPrefix,
613
607
  workerDefinitions,
614
608
  enablePagesAssetsServiceBinding,
615
609
  }: SetupMiniflareOptionsProps): {
@@ -722,7 +716,6 @@ export function setupMiniflareOptions({
722
716
  crons,
723
717
  upstream,
724
718
  logLevel: logger.loggerLevel,
725
- logOptions: logPrefix ? { prefix: logPrefix } : undefined,
726
719
  enablePagesAssetsServiceBinding,
727
720
  };
728
721
  // The path to the Miniflare CLI assumes that this file is being run from
@@ -777,6 +770,7 @@ export interface SetupMiniflare3Options {
777
770
  // we need actual namespace IDs to connect to.
778
771
  kvNamespaces: CfKvNamespace[] | undefined;
779
772
  r2Buckets: CfR2Bucket[] | undefined;
773
+ d1Databases: CfD1Database[] | undefined;
780
774
 
781
775
  // Account ID to use for authenticated Cloudflare fetch. If true, prompt
782
776
  // user for ID if multiple available.
@@ -788,18 +782,14 @@ export interface SetupMiniflare3Options {
788
782
  inspectorPort: number;
789
783
  }
790
784
 
791
- export async function buildMiniflare3Logger(
792
- logPrefix?: string
793
- ): Promise<Miniflare3LogType> {
785
+ export async function buildMiniflare3Logger(): Promise<Miniflare3LogType> {
794
786
  const { Log, NoOpLog, LogLevel } = await getMiniflare3();
795
787
 
796
788
  let level = logger.loggerLevel.toUpperCase() as Uppercase<LoggerLevel>;
797
789
  if (level === "LOG") level = "INFO";
798
790
  const logLevel = LogLevel[level];
799
791
 
800
- return logLevel === LogLevel.NONE
801
- ? new NoOpLog()
802
- : new Log(logLevel, { prefix: logPrefix });
792
+ return logLevel === LogLevel.NONE ? new NoOpLog() : new Log(logLevel);
803
793
  }
804
794
 
805
795
  export async function transformMf2OptionsToMf3Options({
@@ -810,6 +800,7 @@ export async function transformMf2OptionsToMf3Options({
810
800
  enablePagesAssetsServiceBinding,
811
801
  kvNamespaces,
812
802
  r2Buckets,
803
+ d1Databases,
813
804
  authenticatedAccountId,
814
805
  kvRemote,
815
806
  inspectorPort,
@@ -817,14 +808,14 @@ export async function transformMf2OptionsToMf3Options({
817
808
  // Build authenticated Cloudflare API fetch function if required
818
809
  let cloudflareFetch: CloudflareFetch | undefined;
819
810
  if (kvRemote && authenticatedAccountId !== undefined) {
811
+ const { Response: Miniflare3Response } = await getMiniflare3();
820
812
  const preferredAccountId =
821
813
  authenticatedAccountId === true ? undefined : authenticatedAccountId;
822
814
  const accountId = await requireAuth({ account_id: preferredAccountId });
823
- cloudflareFetch = (resource, searchParams, init) => {
815
+ cloudflareFetch = async (resource, searchParams, init) => {
824
816
  resource = `/accounts/${accountId}/${resource}`;
825
- // Miniflare and Wrangler's `undici` versions may be slightly different,
826
- // but their `RequestInit` types *should* be compatible
827
- return performApiFetch(resource, init as RequestInit, searchParams);
817
+ const response = await performApiFetch(resource, init, searchParams);
818
+ return new Miniflare3Response(response.body, response);
828
819
  };
829
820
  }
830
821
 
@@ -837,6 +828,12 @@ export async function transformMf2OptionsToMf3Options({
837
828
  r2Buckets: Object.fromEntries(
838
829
  r2Buckets?.map(({ binding, bucket_name }) => [binding, bucket_name]) ?? []
839
830
  ),
831
+ d1Databases: Object.fromEntries(
832
+ d1Databases?.map(({ binding, database_id, preview_database_id }) => [
833
+ binding,
834
+ preview_database_id ?? database_id,
835
+ ]) ?? []
836
+ ),
840
837
  inspectorPort,
841
838
  verbose: true,
842
839
  cloudflareFetch,
@@ -919,5 +916,5 @@ export async function getMiniflare3(): Promise<
919
916
  // eslint-disable-next-line @typescript-eslint/consistent-type-imports
920
917
  typeof import("@miniflare/tre")
921
918
  > {
922
- return (miniflare3Module ??= await npxImport("@miniflare/tre@3.0.0-next.8"));
919
+ return (miniflare3Module ??= await npxImport("@miniflare/tre@3.0.0-next.12"));
923
920
  }
@@ -98,7 +98,8 @@ export async function startDevServer(
98
98
  ),
99
99
  tsconfig: props.tsconfig,
100
100
  minify: props.minify,
101
- nodeCompat: props.nodeCompat,
101
+ legacyNodeCompat: props.legacyNodeCompat,
102
+ nodejsCompat: props.nodejsCompat,
102
103
  define: props.define,
103
104
  noBundle: props.noBundle,
104
105
  assets: props.assetsConfig,
@@ -131,7 +132,6 @@ export async function startDevServer(
131
132
  queueConsumers: props.queueConsumers,
132
133
  localProtocol: props.localProtocol,
133
134
  localUpstream: props.localUpstream,
134
- logPrefix: props.logPrefix,
135
135
  inspect: props.inspect,
136
136
  onReady: props.onReady,
137
137
  enablePagesAssetsServiceBinding: props.enablePagesAssetsServiceBinding,
@@ -210,7 +210,8 @@ async function runEsbuild({
210
210
  serveAssetsFromWorker,
211
211
  tsconfig,
212
212
  minify,
213
- nodeCompat,
213
+ legacyNodeCompat,
214
+ nodejsCompat,
214
215
  define,
215
216
  noBundle,
216
217
  workerDefinitions,
@@ -233,7 +234,8 @@ async function runEsbuild({
233
234
  serveAssetsFromWorker: boolean;
234
235
  tsconfig: string | undefined;
235
236
  minify: boolean | undefined;
236
- nodeCompat: boolean | undefined;
237
+ legacyNodeCompat: boolean | undefined;
238
+ nodejsCompat: boolean | undefined;
237
239
  noBundle: boolean;
238
240
  workerDefinitions: WorkerRegistry;
239
241
  firstPartyWorkerDevFacade: boolean | undefined;
@@ -266,7 +268,8 @@ async function runEsbuild({
266
268
  rules,
267
269
  tsconfig,
268
270
  minify,
269
- nodeCompat,
271
+ legacyNodeCompat,
272
+ nodejsCompat,
270
273
  define,
271
274
  checkFetch: true,
272
275
  assets: assets && {
@@ -318,7 +321,6 @@ export async function startLocalServer({
318
321
  localUpstream,
319
322
  inspect,
320
323
  onReady,
321
- logPrefix,
322
324
  enablePagesAssetsServiceBinding,
323
325
  experimentalLocal,
324
326
  accountId,
@@ -398,13 +400,12 @@ export async function startLocalServer({
398
400
  dataBlobBindings,
399
401
  crons,
400
402
  upstream,
401
- logPrefix,
402
403
  workerDefinitions,
403
404
  enablePagesAssetsServiceBinding,
404
405
  });
405
406
 
406
407
  if (experimentalLocal) {
407
- const log = await buildMiniflare3Logger(logPrefix);
408
+ const log = await buildMiniflare3Logger();
408
409
  const mf3Options = await transformMf2OptionsToMf3Options({
409
410
  miniflare2Options: options,
410
411
  format,
@@ -412,6 +413,7 @@ export async function startLocalServer({
412
413
  log,
413
414
  kvNamespaces: bindings?.kv_namespaces,
414
415
  r2Buckets: bindings?.r2_buckets,
416
+ d1Databases: bindings?.d1_databases,
415
417
  authenticatedAccountId: accountId,
416
418
  kvRemote: experimentalLocalRemoteKv,
417
419
  inspectorPort,