wrangler 2.3.2 → 2.4.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "2.3.2",
3
+ "version": "2.4.1",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -119,7 +119,7 @@
119
119
  "@databases/sql": "^3.2.0",
120
120
  "@iarna/toml": "^3.0.0",
121
121
  "@microsoft/api-extractor": "^7.28.3",
122
- "@miniflare/tre": "^3.0.0-next.5",
122
+ "@miniflare/tre": "^3.0.0-next.7",
123
123
  "@types/better-sqlite3": "^7.6.0",
124
124
  "@types/busboy": "^1.5.0",
125
125
  "@types/command-exists": "^1.2.0",
@@ -830,6 +830,31 @@ describe("wrangler dev", () => {
830
830
  });
831
831
 
832
832
  describe("inspector port", () => {
833
+ it("should connect WebSocket server with --experimental-local", async () => {
834
+ writeWranglerToml({
835
+ main: "./index.js",
836
+ });
837
+ fs.writeFileSync(
838
+ "index.js",
839
+ `export default {
840
+ async fetch(request, env, ctx ){
841
+ console.log('Hello World LOGGING');
842
+ },
843
+ };`
844
+ );
845
+ await runWrangler("dev --experimental-local");
846
+
847
+ expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9229);
848
+ expect(std).toMatchInlineSnapshot(`
849
+ Object {
850
+ "debug": "",
851
+ "err": "",
852
+ "out": "",
853
+ "warn": "",
854
+ }
855
+ `);
856
+ });
857
+
833
858
  it("should use 9229 as the default port", async () => {
834
859
  writeWranglerToml({
835
860
  main: "index.js",
@@ -1178,10 +1203,12 @@ describe("wrangler dev", () => {
1178
1203
  --tsconfig Path to a custom tsconfig.json file [string]
1179
1204
  -l, --local Run on my machine [boolean] [default: false]
1180
1205
  --experimental-local Run on my machine using the Cloudflare Workers runtime [boolean] [default: false]
1206
+ --experimental-local-remote-kv Read/write KV data from/to real namespaces on the Cloudflare network [boolean] [default: false]
1181
1207
  --minify Minify the script [boolean]
1182
1208
  --node-compat Enable node.js compatibility [boolean]
1183
1209
  --persist Enable persistence for local mode, using default path: .wrangler/state [boolean]
1184
1210
  --persist-to Specify directory to use for local persistence (implies --persist) [string]
1211
+ --live-reload Auto reload HTML pages when change is detected in local mode [boolean]
1185
1212
  --test-scheduled Test scheduled events by visiting /__scheduled in browser [boolean] [default: false]
1186
1213
  --log-level Specify logging level [choices: \\"debug\\", \\"info\\", \\"log\\", \\"warn\\", \\"error\\", \\"none\\"] [default: \\"log\\"]",
1187
1214
  "warn": "",
@@ -51,6 +51,7 @@ describe("wrangler", () => {
51
51
  wrangler logout 🚪 Logout from Cloudflare
52
52
  wrangler whoami 🕵️ Retrieve your user info and test your auth config
53
53
  wrangler types 📝 Generate types from bindings & module rules in config
54
+ wrangler deployments 🚢 Displays the 10 most recent deployments for a worker
54
55
 
55
56
  Flags:
56
57
  -c, --config Path to .toml configuration file [string]
@@ -96,6 +97,7 @@ describe("wrangler", () => {
96
97
  wrangler logout 🚪 Logout from Cloudflare
97
98
  wrangler whoami 🕵️ Retrieve your user info and test your auth config
98
99
  wrangler types 📝 Generate types from bindings & module rules in config
100
+ wrangler deployments 🚢 Displays the 10 most recent deployments for a worker
99
101
 
100
102
  Flags:
101
103
  -c, --config Path to .toml configuration file [string]
@@ -364,7 +364,7 @@ describe("metrics", () => {
364
364
 
365
365
  expect(std.out).toMatchInlineSnapshot(`
366
366
  "Usage metrics tracking has changed since you last granted permission.
367
- Your choice has been saved in the following file: home/.wrangler/config/metrics.json.
367
+ Your choice has been saved in the following file: test-xdg-config/metrics.json.
368
368
 
369
369
  You can override the user level setting for a project in \`wrangler.toml\`:
370
370
 
@@ -1165,16 +1165,21 @@ describe("pages", () => {
1165
1165
  const body = init.body as FormData;
1166
1166
  const manifest = JSON.parse(body.get("manifest") as string);
1167
1167
 
1168
- // for Functions projects, we auto-generate a `_worker.js` and `_routes.json`
1168
+ // for Functions projects, we auto-generate a `_worker.js`,
1169
+ // `functions-filepath-routing-config.json`, and `_routes.json`
1169
1170
  // file, based on the contents of `/functions`
1170
1171
  const generatedWorkerJS = body.get("_worker.js") as Blob;
1171
1172
  const generatedRoutesJSON = await (
1172
1173
  body.get("_routes.json") as Blob
1173
1174
  ).text();
1175
+ const generatedFilepathRoutingConfig = await (
1176
+ body.get("functions-filepath-routing-config.json") as Blob
1177
+ ).text();
1174
1178
 
1175
1179
  // make sure this is all we uploaded
1176
1180
  expect([...body.keys()]).toEqual([
1177
1181
  "manifest",
1182
+ "functions-filepath-routing-config.json",
1178
1183
  "_worker.js",
1179
1184
  "_routes.json",
1180
1185
  ]);
@@ -1202,6 +1207,25 @@ describe("pages", () => {
1202
1207
  include: ["/hello"],
1203
1208
  exclude: [],
1204
1209
  });
1210
+
1211
+ // Make sure the routing config is valid json
1212
+ const parsedFilepathRoutingConfig = JSON.parse(
1213
+ generatedFilepathRoutingConfig
1214
+ );
1215
+ // The actual shape doesn't matter that much since this
1216
+ // is only used for display in Dash, but it's still useful for
1217
+ // tracking unexpected changes to this config.
1218
+ expect(parsedFilepathRoutingConfig).toStrictEqual({
1219
+ routes: [
1220
+ {
1221
+ routePath: "/hello",
1222
+ mountPath: "/",
1223
+ method: "",
1224
+ module: ["hello.js:onRequest"],
1225
+ },
1226
+ ],
1227
+ baseURL: "/",
1228
+ });
1205
1229
  });
1206
1230
 
1207
1231
  return {
@@ -1456,10 +1480,14 @@ describe("pages", () => {
1456
1480
  const customRoutesJSON = await (
1457
1481
  body.get("_routes.json") as Blob
1458
1482
  ).text();
1483
+ const generatedFilepathRoutingConfig = await (
1484
+ body.get("functions-filepath-routing-config.json") as Blob
1485
+ ).text();
1459
1486
 
1460
1487
  // make sure this is all we uploaded
1461
1488
  expect([...body.keys()]).toEqual([
1462
1489
  "manifest",
1490
+ "functions-filepath-routing-config.json",
1463
1491
  "_worker.js",
1464
1492
  "_routes.json",
1465
1493
  ]);
@@ -1481,6 +1509,32 @@ describe("pages", () => {
1481
1509
  include: ["/hello"],
1482
1510
  exclude: [],
1483
1511
  });
1512
+
1513
+ // Make sure the routing config is valid json
1514
+ const parsedFilepathRoutingConfig = JSON.parse(
1515
+ generatedFilepathRoutingConfig
1516
+ );
1517
+ // The actual shape doesn't matter that much since this
1518
+ // is only used for display in Dash, but it's still useful for
1519
+ // tracking unexpected changes to this config.
1520
+ console.log(generatedFilepathRoutingConfig);
1521
+ expect(parsedFilepathRoutingConfig).toStrictEqual({
1522
+ routes: [
1523
+ {
1524
+ routePath: "/goodbye",
1525
+ mountPath: "/",
1526
+ method: "",
1527
+ module: ["goodbye.ts:onRequest"],
1528
+ },
1529
+ {
1530
+ routePath: "/hello",
1531
+ mountPath: "/",
1532
+ method: "",
1533
+ module: ["hello.js:onRequest"],
1534
+ },
1535
+ ],
1536
+ baseURL: "/",
1537
+ });
1484
1538
  });
1485
1539
 
1486
1540
  return {
package/src/api/dev.ts CHANGED
@@ -56,6 +56,8 @@ interface DevOptions {
56
56
  $0?: string; //yargs wants this
57
57
  testScheduled?: boolean;
58
58
  experimentalLocal?: boolean;
59
+ accountId?: string;
60
+ experimentalLocalRemoteKv?: boolean;
59
61
  }
60
62
 
61
63
  interface DevApiOptions {
package/src/bundle.ts CHANGED
@@ -97,7 +97,6 @@ export async function bundleWorker(
97
97
  targetConsumer: "dev" | "publish";
98
98
  local: boolean;
99
99
  testScheduled?: boolean;
100
- experimentalLocalStubCache?: boolean;
101
100
  inject?: string[];
102
101
  loader?: Record<string, string>;
103
102
  sourcemap?: esbuild.CommonOptions["sourcemap"];
@@ -125,7 +124,6 @@ export async function bundleWorker(
125
124
  firstPartyWorkerDevFacade,
126
125
  targetConsumer,
127
126
  testScheduled,
128
- experimentalLocalStubCache,
129
127
  inject: injectOption,
130
128
  loader,
131
129
  sourcemap,
@@ -277,11 +275,6 @@ export async function bundleWorker(
277
275
 
278
276
  const inject: string[] = injectOption ?? [];
279
277
  if (checkFetch) inject.push(checkedFetchFileToInject);
280
- if (experimentalLocalStubCache) {
281
- inject.push(
282
- path.resolve(getBasePath(), "templates/experimental-local-cache-stubs.js")
283
- );
284
- }
285
278
 
286
279
  const buildOptions: esbuild.BuildOptions & { metafile: true } = {
287
280
  entryPoints: [inputEntry.file],
package/src/dev/dev.tsx CHANGED
@@ -155,6 +155,7 @@ export type DevProps = {
155
155
  sendMetrics: boolean | undefined;
156
156
  testScheduled: boolean | undefined;
157
157
  experimentalLocal: boolean | undefined;
158
+ experimentalLocalRemoteKv: boolean | undefined;
158
159
  };
159
160
 
160
161
  export function DevImplementation(props: DevProps): JSX.Element {
@@ -287,7 +288,6 @@ function DevSession(props: DevSessionProps) {
287
288
  // Enable the bundling to know whether we are using dev or publish
288
289
  targetConsumer: "dev",
289
290
  testScheduled: props.testScheduled ?? false,
290
- experimentalLocalStubCache: props.local && props.experimentalLocal,
291
291
  });
292
292
 
293
293
  // TODO(queues) support remote wrangler dev
@@ -326,6 +326,8 @@ function DevSession(props: DevSessionProps) {
326
326
  onReady={props.onReady}
327
327
  enablePagesAssetsServiceBinding={props.enablePagesAssetsServiceBinding}
328
328
  experimentalLocal={props.experimentalLocal}
329
+ accountId={props.accountId}
330
+ experimentalLocalRemoteKv={props.experimentalLocalRemoteKv}
329
331
  />
330
332
  ) : (
331
333
  <Remote
package/src/dev/local.tsx CHANGED
@@ -4,10 +4,10 @@ import { realpathSync } from "node:fs";
4
4
  import { readFile, writeFile } from "node:fs/promises";
5
5
  import path from "node:path";
6
6
  import chalk from "chalk";
7
- import getPort from "get-port";
8
7
  import { npxImport } from "npx-import";
9
8
  import { useState, useEffect, useRef } from "react";
10
9
  import onExit from "signal-exit";
10
+ import { performApiFetch } from "../cfetch/internal";
11
11
  import { registerWorker } from "../dev-registry";
12
12
  import useInspector from "../inspect";
13
13
  import { logger } from "../logger";
@@ -17,8 +17,10 @@ import {
17
17
  } from "../module-collection";
18
18
  import { getBasePath } from "../paths";
19
19
  import { waitForPortToBeAvailable } from "../proxy";
20
+ import { requireAuth } from "../user";
20
21
  import type { Config } from "../config";
21
22
  import type { WorkerRegistry } from "../dev-registry";
23
+ import type { LoggerLevel } from "../logger";
22
24
  import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
23
25
  import type { AssetPaths } from "../sites";
24
26
  import type {
@@ -38,9 +40,12 @@ import type { EsbuildBundle } from "./use-esbuild";
38
40
  import type {
39
41
  Miniflare as Miniflare3Type,
40
42
  MiniflareOptions as Miniflare3Options,
43
+ Log as Miniflare3LogType,
44
+ CloudflareFetch,
41
45
  } from "@miniflare/tre";
42
46
  import type { MiniflareOptions } from "miniflare";
43
47
  import type { ChildProcess } from "node:child_process";
48
+ import type { RequestInit } from "undici";
44
49
 
45
50
  export interface LocalProps {
46
51
  name: string | undefined;
@@ -67,15 +72,29 @@ export interface LocalProps {
67
72
  logPrefix?: string;
68
73
  enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
69
74
  testScheduled?: boolean;
70
- experimentalLocal?: boolean;
75
+ experimentalLocal: boolean | undefined;
76
+ accountId: string | undefined; // Account ID? In local mode??? :exploding_head:
77
+ experimentalLocalRemoteKv: boolean | undefined;
71
78
  }
72
79
 
80
+ type InspectorJSON = {
81
+ id: string;
82
+ title: string;
83
+ type: "node";
84
+ description: string;
85
+ webSocketDebuggerUrl: string;
86
+ devtoolsFrontendUrl: string;
87
+ devtoolsFrontendUrlCompat: string;
88
+ faviconUrl: string;
89
+ url: string;
90
+ }[];
91
+
73
92
  export function Local(props: LocalProps) {
74
93
  const { inspectorUrl } = useLocalWorker(props);
75
94
  useInspector({
76
95
  inspectorUrl,
77
96
  port: props.inspectorPort,
78
- logToTerminal: false,
97
+ logToTerminal: props.experimentalLocal ?? false,
79
98
  });
80
99
  return null;
81
100
  }
@@ -105,6 +124,8 @@ function useLocalWorker({
105
124
  logPrefix,
106
125
  enablePagesAssetsServiceBinding,
107
126
  experimentalLocal,
127
+ accountId,
128
+ experimentalLocalRemoteKv,
108
129
  }: LocalProps) {
109
130
  // TODO: pass vars via command line
110
131
  const local = useRef<ChildProcess>();
@@ -209,11 +230,24 @@ function useLocalWorker({
209
230
  });
210
231
 
211
232
  if (experimentalLocal) {
212
- const mf3Options = await transformLocalOptions(options, format, bundle);
233
+ const log = await buildMiniflare3Logger(logPrefix);
234
+ const mf3Options = await transformMf2OptionsToMf3Options({
235
+ miniflare2Options: options,
236
+ format,
237
+ bundle,
238
+ log,
239
+ kvNamespaces: bindings?.kv_namespaces,
240
+ r2Buckets: bindings?.r2_buckets,
241
+ authenticatedAccountId: accountId,
242
+ kvRemote: experimentalLocalRemoteKv,
243
+ inspectorPort,
244
+ });
245
+
213
246
  const current = experimentalLocalRef.current;
247
+
214
248
  if (current === undefined) {
215
249
  // If we don't have an active Miniflare instance, create a new one
216
- const Miniflare = await getMiniflare3Constructor();
250
+ const { Miniflare } = await getMiniflare3();
217
251
  if (abortController.signal.aborted) return;
218
252
  const mf = new Miniflare(mf3Options);
219
253
  experimentalLocalRef.current = mf;
@@ -230,6 +264,34 @@ function useLocalWorker({
230
264
  logger.log("⎔ Reloading experimental local server.");
231
265
  await current.setOptions(mf3Options);
232
266
  }
267
+
268
+ try {
269
+ // fetch the inspector JSON response from the DevTools Inspector protocol
270
+ const inspectorJSONArr = (await (
271
+ await fetch(`http://127.0.0.1:${inspectorPort}/json`)
272
+ ).json()) as InspectorJSON;
273
+
274
+ const foundInspectorURL = inspectorJSONArr?.find((inspectorJSON) =>
275
+ inspectorJSON.id.startsWith("core:user")
276
+ )?.webSocketDebuggerUrl;
277
+ if (foundInspectorURL === undefined) {
278
+ setInspectorUrl(undefined);
279
+ } else {
280
+ const url = new URL(foundInspectorURL);
281
+ // Force inspector URL to be different on each reload so `useEffect`
282
+ // in `useInspector` is re-run to connect to newly restarted
283
+ // `workerd` server when updating options. Can't use a query param
284
+ // here as that seems to cause an infinite connection loop, can't
285
+ // use a hash as those are forbidden by `ws`, so username it is.
286
+ url.username = `${Date.now()}-${Math.floor(
287
+ Math.random() * Number.MAX_SAFE_INTEGER
288
+ )}`;
289
+ setInspectorUrl(url.toString());
290
+ }
291
+ } catch (error: unknown) {
292
+ logger.error("Error attempting to retrieve Debugger URL:", error);
293
+ }
294
+
233
295
  return;
234
296
  }
235
297
 
@@ -367,6 +429,8 @@ function useLocalWorker({
367
429
  onReady,
368
430
  enablePagesAssetsServiceBinding,
369
431
  experimentalLocal,
432
+ accountId,
433
+ experimentalLocalRemoteKv,
370
434
  ]);
371
435
 
372
436
  // Rather than disposing the Miniflare instance on every reload, only dispose
@@ -683,24 +747,86 @@ export function setupNodeOptions({
683
747
  return nodeOptions;
684
748
  }
685
749
 
686
- function arrayToObject(values: string[] = []): Record<string, string> {
687
- return Object.fromEntries(values.map((value) => [value, value]));
750
+ export interface SetupMiniflare3Options {
751
+ // Regular Miniflare 2 options to transform
752
+ miniflare2Options: MiniflareOptions;
753
+ // Miniflare 3 requires all modules to be manually specified
754
+ format: CfScriptFormat;
755
+ bundle: EsbuildBundle;
756
+
757
+ // Miniflare's logger
758
+ log: Miniflare3LogType;
759
+
760
+ // Miniflare 3 accepts namespace/bucket names in addition to binding names.
761
+ // This means multiple workers persisting to the same location can have
762
+ // different binding names for the same namespace/bucket. Therefore, we need
763
+ // the full KV/R2 arrays. This is also required for remote KV storage, as
764
+ // we need actual namespace IDs to connect to.
765
+ kvNamespaces: CfKvNamespace[] | undefined;
766
+ r2Buckets: CfR2Bucket[] | undefined;
767
+
768
+ // Account ID to use for authenticated Cloudflare fetch. If true, prompt
769
+ // user for ID if multiple available.
770
+ authenticatedAccountId: string | true | undefined;
771
+ // Whether to read/write from/to real KV namespaces
772
+ kvRemote: boolean | undefined;
773
+
774
+ // Port to start DevTools inspector server on
775
+ inspectorPort: number;
776
+ }
777
+
778
+ export async function buildMiniflare3Logger(
779
+ logPrefix?: string
780
+ ): Promise<Miniflare3LogType> {
781
+ const { Log, NoOpLog, LogLevel } = await getMiniflare3();
782
+
783
+ let level = logger.loggerLevel.toUpperCase() as Uppercase<LoggerLevel>;
784
+ if (level === "LOG") level = "INFO";
785
+ const logLevel = LogLevel[level];
786
+
787
+ return logLevel === LogLevel.NONE
788
+ ? new NoOpLog()
789
+ : new Log(logLevel, { prefix: logPrefix });
688
790
  }
689
791
 
690
- export async function transformLocalOptions(
691
- mf2Options: MiniflareOptions,
692
- format: CfScriptFormat,
693
- bundle: EsbuildBundle
694
- ): Promise<Miniflare3Options> {
792
+ export async function transformMf2OptionsToMf3Options({
793
+ miniflare2Options,
794
+ format,
795
+ bundle,
796
+ log,
797
+ kvNamespaces,
798
+ r2Buckets,
799
+ authenticatedAccountId,
800
+ kvRemote,
801
+ inspectorPort,
802
+ }: SetupMiniflare3Options): Promise<Miniflare3Options> {
803
+ // Build authenticated Cloudflare API fetch function if required
804
+ let cloudflareFetch: CloudflareFetch | undefined;
805
+ if (kvRemote && authenticatedAccountId !== undefined) {
806
+ const preferredAccountId =
807
+ authenticatedAccountId === true ? undefined : authenticatedAccountId;
808
+ const accountId = await requireAuth({ account_id: preferredAccountId });
809
+ cloudflareFetch = (resource, searchParams, init) => {
810
+ resource = `/accounts/${accountId}/${resource}`;
811
+ // Miniflare and Wrangler's `undici` versions may be slightly different,
812
+ // but their `RequestInit` types *should* be compatible
813
+ return performApiFetch(resource, init as RequestInit, searchParams);
814
+ };
815
+ }
816
+
695
817
  const options: Miniflare3Options = {
696
- ...mf2Options,
818
+ ...miniflare2Options,
697
819
  // Miniflare 3 distinguishes between binding name and namespace/bucket IDs.
698
- // For now, just use the same value as we did in Miniflare 2.
699
- // TODO: use defined KV preview ID if any
700
- kvNamespaces: arrayToObject(mf2Options.kvNamespaces),
701
- r2Buckets: arrayToObject(mf2Options.r2Buckets),
702
- inspectorPort: await getPort({ port: 9229 }),
820
+ kvNamespaces: Object.fromEntries(
821
+ kvNamespaces?.map(({ binding, id }) => [binding, id]) ?? []
822
+ ),
823
+ r2Buckets: Object.fromEntries(
824
+ r2Buckets?.map(({ binding, bucket_name }) => [binding, bucket_name]) ?? []
825
+ ),
826
+ inspectorPort,
703
827
  verbose: true,
828
+ cloudflareFetch,
829
+ log,
704
830
  };
705
831
 
706
832
  if (format === "modules") {
@@ -729,18 +855,30 @@ export async function transformLocalOptions(
729
855
  ];
730
856
  }
731
857
 
858
+ if (kvRemote) {
859
+ // `kvPersist` is always assigned a truthy value in `setupMiniflareOptions`
860
+ assert(options.kvPersist);
861
+ const kvRemoteCache =
862
+ options.kvPersist === true
863
+ ? // If storing in temporary directory, find this path from the bundle
864
+ // output path
865
+ path.join(path.dirname(bundle.path), ".mf", "kv-remote")
866
+ : // Otherwise, `kvPersist` looks like `.../kv`, so rewrite it to
867
+ // `kv-remote` since the expected metadata format for remote storage
868
+ // is different to local
869
+ path.join(path.dirname(options.kvPersist), "kv-remote");
870
+ options.kvPersist = `remote:?cache=${encodeURIComponent(kvRemoteCache)}`;
871
+ }
872
+
732
873
  return options;
733
874
  }
734
875
 
735
876
  // Caching of the `npx-import`ed `@miniflare/tre` package
736
877
  // eslint-disable-next-line @typescript-eslint/consistent-type-imports
737
- let Miniflare: typeof import("@miniflare/tre").Miniflare;
738
- export async function getMiniflare3Constructor(): Promise<typeof Miniflare> {
739
- if (Miniflare === undefined) {
740
- ({ Miniflare } = await npxImport<
741
- // eslint-disable-next-line @typescript-eslint/consistent-type-imports
742
- typeof import("@miniflare/tre")
743
- >("@miniflare/tre@3.0.0-next.5"));
744
- }
745
- return Miniflare;
878
+ let miniflare3Module: typeof import("@miniflare/tre");
879
+ export async function getMiniflare3(): Promise<
880
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
881
+ typeof import("@miniflare/tre")
882
+ > {
883
+ return (miniflare3Module ??= await npxImport("@miniflare/tre@3.0.0-next.7"));
746
884
  }
@@ -17,10 +17,11 @@ import { logger } from "../logger";
17
17
  import { waitForPortToBeAvailable } from "../proxy";
18
18
  import {
19
19
  setupBindings,
20
- getMiniflare3Constructor,
20
+ getMiniflare3,
21
+ buildMiniflare3Logger,
21
22
  setupMiniflareOptions,
22
23
  setupNodeOptions,
23
- transformLocalOptions,
24
+ transformMf2OptionsToMf3Options,
24
25
  } from "./local";
25
26
  import { startRemoteServer } from "./remote";
26
27
  import { validateDevProps } from "./validate-dev-props";
@@ -98,7 +99,6 @@ export async function startDevServer(
98
99
  services: props.bindings.services,
99
100
  firstPartyWorkerDevFacade: props.firstPartyWorker,
100
101
  testScheduled: props.testScheduled,
101
- experimentalLocalStubCache: props.experimentalLocal,
102
102
  });
103
103
 
104
104
  if (props.local) {
@@ -127,6 +127,8 @@ export async function startDevServer(
127
127
  usageModel: props.usageModel,
128
128
  workerDefinitions,
129
129
  experimentalLocal: props.experimentalLocal,
130
+ accountId: props.accountId,
131
+ experimentalLocalRemoteKv: props.experimentalLocalRemoteKv,
130
132
  });
131
133
 
132
134
  return {
@@ -204,7 +206,6 @@ async function runEsbuild({
204
206
  services,
205
207
  firstPartyWorkerDevFacade,
206
208
  testScheduled,
207
- experimentalLocalStubCache,
208
209
  }: {
209
210
  entry: Entry;
210
211
  destination: string | undefined;
@@ -223,7 +224,6 @@ async function runEsbuild({
223
224
  workerDefinitions: WorkerRegistry;
224
225
  firstPartyWorkerDevFacade: boolean | undefined;
225
226
  testScheduled?: boolean;
226
- experimentalLocalStubCache: boolean | undefined;
227
227
  }): Promise<EsbuildBundle | undefined> {
228
228
  if (!destination) return;
229
229
 
@@ -264,7 +264,6 @@ async function runEsbuild({
264
264
  targetConsumer: "dev", // We are starting a dev server
265
265
  local: true,
266
266
  testScheduled,
267
- experimentalLocalStubCache,
268
267
  });
269
268
 
270
269
  return {
@@ -303,6 +302,8 @@ export async function startLocalServer({
303
302
  logPrefix,
304
303
  enablePagesAssetsServiceBinding,
305
304
  experimentalLocal,
305
+ accountId,
306
+ experimentalLocalRemoteKv,
306
307
  }: LocalProps) {
307
308
  let local: ChildProcess | undefined;
308
309
  let experimentalLocalRef: Miniflare3Type | undefined;
@@ -396,8 +397,19 @@ export async function startLocalServer({
396
397
  });
397
398
 
398
399
  if (experimentalLocal) {
399
- const mf3Options = await transformLocalOptions(options, format, bundle);
400
- const Miniflare = await getMiniflare3Constructor();
400
+ const log = await buildMiniflare3Logger(logPrefix);
401
+ const mf3Options = await transformMf2OptionsToMf3Options({
402
+ miniflare2Options: options,
403
+ format,
404
+ bundle,
405
+ log,
406
+ kvNamespaces: bindings?.kv_namespaces,
407
+ r2Buckets: bindings?.r2_buckets,
408
+ authenticatedAccountId: accountId,
409
+ kvRemote: experimentalLocalRemoteKv,
410
+ inspectorPort,
411
+ });
412
+ const { Miniflare } = await getMiniflare3();
401
413
  const mf = new Miniflare(mf3Options);
402
414
  const runtimeURL = await mf.ready;
403
415
  experimentalLocalRef = mf;
@@ -41,7 +41,6 @@ export function useEsbuild({
41
41
  local,
42
42
  targetConsumer,
43
43
  testScheduled,
44
- experimentalLocalStubCache,
45
44
  }: {
46
45
  entry: Entry;
47
46
  destination: string | undefined;
@@ -63,7 +62,6 @@ export function useEsbuild({
63
62
  local: boolean;
64
63
  targetConsumer: "dev" | "publish";
65
64
  testScheduled: boolean;
66
- experimentalLocalStubCache: boolean | undefined;
67
65
  }): EsbuildBundle | undefined {
68
66
  const [bundle, setBundle] = useState<EsbuildBundle>();
69
67
  const { exit } = useApp();
@@ -136,7 +134,6 @@ export function useEsbuild({
136
134
  local,
137
135
  targetConsumer,
138
136
  testScheduled,
139
- experimentalLocalStubCache,
140
137
  });
141
138
 
142
139
  // Capture the `stop()` method to use as the `useEffect()` destructor.
@@ -198,7 +195,6 @@ export function useEsbuild({
198
195
  local,
199
196
  targetConsumer,
200
197
  testScheduled,
201
- experimentalLocalStubCache,
202
198
  ]);
203
199
  return bundle;
204
200
  }