wrangler 2.1.7 → 2.1.8

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.1.7",
3
+ "version": "2.1.8",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -112,6 +112,7 @@
112
112
  "@databases/sql": "^3.2.0",
113
113
  "@iarna/toml": "^3.0.0",
114
114
  "@microsoft/api-extractor": "^7.28.3",
115
+ "@miniflare/tre": "3.0.0-next.1",
115
116
  "@types/better-sqlite3": "^7.6.0",
116
117
  "@types/busboy": "^1.5.0",
117
118
  "@types/command-exists": "^1.2.0",
@@ -157,7 +158,7 @@
157
158
  "jest-websocket-mock": "^2.3.0",
158
159
  "mime": "^3.0.0",
159
160
  "msw": "^0.47.1",
160
- "npx-import": "^1.0.2",
161
+ "npx-import": "^1.1.3",
161
162
  "open": "^8.4.0",
162
163
  "p-queue": "^7.2.0",
163
164
  "pretty-bytes": "^6.0.0",
package/src/bundle.ts CHANGED
@@ -79,6 +79,7 @@ export async function bundleWorker(
79
79
  targetConsumer: "dev" | "publish";
80
80
  local: boolean;
81
81
  testScheduled?: boolean | undefined;
82
+ experimentalLocalStubCache: boolean | undefined;
82
83
  }
83
84
  ): Promise<BundleResult> {
84
85
  const {
@@ -99,6 +100,7 @@ export async function bundleWorker(
99
100
  firstPartyWorkerDevFacade,
100
101
  targetConsumer,
101
102
  testScheduled,
103
+ experimentalLocalStubCache,
102
104
  } = options;
103
105
 
104
106
  // We create a temporary directory for any oneoff files we
@@ -233,12 +235,20 @@ export async function bundleWorker(
233
235
 
234
236
  // At this point, inputEntry points to the entry point we want to build.
235
237
 
238
+ const inject: string[] = [];
239
+ if (checkFetch) inject.push(checkedFetchFileToInject);
240
+ if (experimentalLocalStubCache) {
241
+ inject.push(
242
+ path.resolve(getBasePath(), "templates/experimental-local-cache-stubs.js")
243
+ );
244
+ }
245
+
236
246
  const result = await esbuild.build({
237
247
  entryPoints: [inputEntry.file],
238
248
  bundle: true,
239
249
  absWorkingDir: entry.directory,
240
250
  outdir: destination,
241
- inject: checkFetch ? [checkedFetchFileToInject] : [],
251
+ inject,
242
252
  external: ["__STATIC_CONTENT_MANIFEST"],
243
253
  format: entry.format === "modules" ? "esm" : "iife",
244
254
  target: "es2020",
package/src/dev/dev.tsx CHANGED
@@ -153,6 +153,7 @@ export type DevProps = {
153
153
  firstPartyWorker: boolean | undefined;
154
154
  sendMetrics: boolean | undefined;
155
155
  testScheduled: boolean | undefined;
156
+ experimentalLocal: boolean | undefined;
156
157
  };
157
158
 
158
159
  export function DevImplementation(props: DevProps): JSX.Element {
@@ -213,6 +214,7 @@ function InteractiveDevSession(props: DevProps) {
213
214
 
214
215
  type DevSessionProps = DevProps & {
215
216
  local: boolean;
217
+ experimentalLocal?: boolean;
216
218
  };
217
219
 
218
220
  function DevSession(props: DevSessionProps) {
@@ -274,6 +276,7 @@ function DevSession(props: DevSessionProps) {
274
276
  // Enable the bundling to know whether we are using dev or publish
275
277
  targetConsumer: "dev",
276
278
  testScheduled: props.testScheduled ?? false,
279
+ experimentalLocalStubCache: props.local && props.experimentalLocal,
277
280
  });
278
281
 
279
282
  return props.local ? (
@@ -300,6 +303,7 @@ function DevSession(props: DevSessionProps) {
300
303
  inspect={props.inspect}
301
304
  onReady={props.onReady}
302
305
  enablePagesAssetsServiceBinding={props.enablePagesAssetsServiceBinding}
306
+ experimentalLocal={props.experimentalLocal}
303
307
  />
304
308
  ) : (
305
309
  <Remote
package/src/dev/local.tsx CHANGED
@@ -2,6 +2,7 @@ import { fork } from "node:child_process";
2
2
  import { realpathSync } from "node:fs";
3
3
  import { writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
+ import { npxImport } from "npx-import";
5
6
  import { useState, useEffect, useRef } from "react";
6
7
  import onExit from "signal-exit";
7
8
  import { registerWorker } from "../dev-registry";
@@ -27,8 +28,17 @@ import type {
27
28
  CfD1Database,
28
29
  } from "../worker";
29
30
  import type { EsbuildBundle } from "./use-esbuild";
31
+ import type {
32
+ Miniflare as Miniflare3Type,
33
+ MiniflareOptions as Miniflare3Options,
34
+ } from "@miniflare/tre";
30
35
  import type { MiniflareOptions } from "miniflare";
31
36
  import type { ChildProcess } from "node:child_process";
37
+
38
+ // caching of the miniflare package
39
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
40
+ let Miniflare: typeof import("@miniflare/tre")["Miniflare"];
41
+
32
42
  export interface LocalProps {
33
43
  name: string | undefined;
34
44
  bundle: EsbuildBundle | undefined;
@@ -53,6 +63,7 @@ export interface LocalProps {
53
63
  logPrefix?: string;
54
64
  enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
55
65
  testScheduled?: boolean;
66
+ experimentalLocal?: boolean;
56
67
  }
57
68
 
58
69
  export function Local(props: LocalProps) {
@@ -65,6 +76,10 @@ export function Local(props: LocalProps) {
65
76
  return null;
66
77
  }
67
78
 
79
+ function arrayToObject(values: string[] = []): Record<string, string> {
80
+ return Object.fromEntries(values.map((value) => [value, value]));
81
+ }
82
+
68
83
  function useLocalWorker({
69
84
  name: workerName,
70
85
  bundle,
@@ -88,9 +103,11 @@ function useLocalWorker({
88
103
  onReady,
89
104
  logPrefix,
90
105
  enablePagesAssetsServiceBinding,
106
+ experimentalLocal,
91
107
  }: LocalProps) {
92
108
  // TODO: pass vars via command line
93
109
  const local = useRef<ChildProcess>();
110
+ const experimentalLocalRef = useRef<Miniflare3Type>();
94
111
  const removeSignalExitListener = useRef<() => void>();
95
112
  const [inspectorUrl, setInspectorUrl] = useState<string | undefined>();
96
113
 
@@ -187,6 +204,40 @@ function useLocalWorker({
187
204
  enablePagesAssetsServiceBinding,
188
205
  });
189
206
 
207
+ if (experimentalLocal) {
208
+ // TODO: refactor setupMiniflareOptions so we don't need to parse here
209
+ const miniflare2Options: MiniflareOptions = JSON.parse(forkOptions[0]);
210
+ const options: Miniflare3Options = {
211
+ ...miniflare2Options,
212
+ // Miniflare 3 distinguishes between binding name and namespace/bucket
213
+ // IDs. For now, just use the same value as we did in Miniflare 2.
214
+ // TODO: use defined KV preview ID if any
215
+ kvNamespaces: arrayToObject(miniflare2Options.kvNamespaces),
216
+ r2Buckets: arrayToObject(miniflare2Options.r2Buckets),
217
+ // TODO: pass-through collected modules instead of getting Miniflare
218
+ // to collect them again
219
+ };
220
+
221
+ logger.log("⎔ Starting an experimental local server...");
222
+
223
+ if (Miniflare === undefined) {
224
+ ({ Miniflare } = await npxImport<
225
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
226
+ typeof import("@miniflare/tre")
227
+ >("@miniflare/tre"));
228
+ }
229
+
230
+ const mf = new Miniflare(options);
231
+ experimentalLocalRef.current = mf;
232
+ removeSignalExitListener.current = onExit((_code, _signal) => {
233
+ logger.log("⎔ Shutting down experimental local server.");
234
+ mf.dispose();
235
+ experimentalLocalRef.current = undefined;
236
+ });
237
+ await mf.ready;
238
+ return;
239
+ }
240
+
190
241
  const nodeOptions = setupNodeOptions({ inspect, ip, inspectorPort });
191
242
  logger.log("⎔ Starting a local server...");
192
243
 
@@ -279,9 +330,16 @@ function useLocalWorker({
279
330
  logger.log("⎔ Shutting down local server.");
280
331
  local.current?.kill();
281
332
  local.current = undefined;
282
- removeSignalExitListener.current && removeSignalExitListener.current();
283
- removeSignalExitListener.current = undefined;
284
333
  }
334
+ if (experimentalLocalRef.current) {
335
+ logger.log("⎔ Shutting down experimental local server.");
336
+ // Initialisation errors are also thrown asynchronously by dispose().
337
+ // The catch() above should've caught them though.
338
+ experimentalLocalRef.current?.dispose().catch(() => {});
339
+ experimentalLocalRef.current = undefined;
340
+ }
341
+ removeSignalExitListener.current?.();
342
+ removeSignalExitListener.current = undefined;
285
343
  };
286
344
  }, [
287
345
  bundle,
@@ -314,6 +372,7 @@ function useLocalWorker({
314
372
  logPrefix,
315
373
  onReady,
316
374
  enablePagesAssetsServiceBinding,
375
+ experimentalLocal,
317
376
  ]);
318
377
  return { inspectorUrl };
319
378
  }
@@ -458,7 +517,10 @@ export function setupMiniflareOptions({
458
517
  logPrefix,
459
518
  workerDefinitions,
460
519
  enablePagesAssetsServiceBinding,
461
- }: SetupMiniflareOptionsProps): MiniflareOptions {
520
+ }: SetupMiniflareOptionsProps): {
521
+ miniflareCLIPath: string;
522
+ forkOptions: string[];
523
+ } {
462
524
  // It's now getting _really_ messy now with Pages ASSETS binding outside and the external Durable Objects inside.
463
525
  const options = {
464
526
  name: workerName,
@@ -91,6 +91,7 @@ export async function startDevServer(
91
91
  services: props.bindings.services,
92
92
  firstPartyWorkerDevFacade: props.firstPartyWorker,
93
93
  testScheduled: props.testScheduled,
94
+ experimentalLocalStubCache: props.experimentalLocal,
94
95
  });
95
96
 
96
97
  //run local now
@@ -159,6 +160,7 @@ async function runEsbuild({
159
160
  services,
160
161
  firstPartyWorkerDevFacade,
161
162
  testScheduled,
163
+ experimentalLocalStubCache,
162
164
  }: {
163
165
  entry: Entry;
164
166
  destination: string | undefined;
@@ -176,6 +178,7 @@ async function runEsbuild({
176
178
  workerDefinitions: WorkerRegistry;
177
179
  firstPartyWorkerDevFacade: boolean | undefined;
178
180
  testScheduled?: boolean;
181
+ experimentalLocalStubCache: boolean | undefined;
179
182
  }): Promise<EsbuildBundle | undefined> {
180
183
  if (!destination) return;
181
184
 
@@ -213,6 +216,7 @@ async function runEsbuild({
213
216
  targetConsumer: "dev", // We are starting a dev server
214
217
  local: false,
215
218
  testScheduled,
219
+ experimentalLocalStubCache,
216
220
  });
217
221
 
218
222
  return {
@@ -40,6 +40,7 @@ export function useEsbuild({
40
40
  local,
41
41
  targetConsumer,
42
42
  testScheduled,
43
+ experimentalLocalStubCache,
43
44
  }: {
44
45
  entry: Entry;
45
46
  destination: string | undefined;
@@ -61,6 +62,7 @@ export function useEsbuild({
61
62
  local: boolean;
62
63
  targetConsumer: "dev" | "publish";
63
64
  testScheduled: boolean;
65
+ experimentalLocalStubCache: boolean | undefined;
64
66
  }): EsbuildBundle | undefined {
65
67
  const [bundle, setBundle] = useState<EsbuildBundle>();
66
68
  const { exit } = useApp();
@@ -128,6 +130,7 @@ export function useEsbuild({
128
130
  local,
129
131
  targetConsumer,
130
132
  testScheduled,
133
+ experimentalLocalStubCache,
131
134
  });
132
135
 
133
136
  // Capture the `stop()` method to use as the `useEffect()` destructor.
@@ -188,6 +191,7 @@ export function useEsbuild({
188
191
  local,
189
192
  targetConsumer,
190
193
  testScheduled,
194
+ experimentalLocalStubCache,
191
195
  ]);
192
196
  return bundle;
193
197
  }
package/src/dev.tsx CHANGED
@@ -62,6 +62,7 @@ interface DevArgs {
62
62
  "jsx-fragment"?: string;
63
63
  tsconfig?: string;
64
64
  local?: boolean;
65
+ "experimental-local"?: boolean;
65
66
  minify?: boolean;
66
67
  var?: string[];
67
68
  define?: string[];
@@ -234,6 +235,20 @@ export function devOptions(yargs: Argv): Argv<DevArgs> {
234
235
  type: "boolean",
235
236
  default: false, // I bet this will a point of contention. We'll revisit it.
236
237
  })
238
+ .option("experimental-local", {
239
+ describe: "Run on my machine using the Cloudflare Workers runtime",
240
+ type: "boolean",
241
+ default: false,
242
+ })
243
+ .check((argv) => {
244
+ if (argv.local && argv["experimental-local"]) {
245
+ throw new Error(
246
+ "--local and --experimental-local are mutually exclusive. " +
247
+ "Please select one or the other."
248
+ );
249
+ }
250
+ return true;
251
+ })
237
252
  .option("minify", {
238
253
  describe: "Minify the script",
239
254
  type: "boolean",
@@ -405,7 +420,9 @@ export async function startDev(args: StartDevOptions) {
405
420
  nodeCompat={nodeCompat}
406
421
  build={configParam.build || {}}
407
422
  define={{ ...configParam.define, ...cliDefines }}
408
- initialMode={args.local ? "local" : "remote"}
423
+ initialMode={
424
+ args.local || args.experimentalLocal ? "local" : "remote"
425
+ }
409
426
  jsxFactory={args["jsx-factory"] || configParam.jsx_factory}
410
427
  jsxFragment={args["jsx-fragment"] || configParam.jsx_fragment}
411
428
  tsconfig={args.tsconfig ?? configParam.tsconfig}
@@ -444,6 +461,7 @@ export async function startDev(args: StartDevOptions) {
444
461
  firstPartyWorker={configParam.first_party_worker}
445
462
  sendMetrics={configParam.send_metrics}
446
463
  testScheduled={args["test-scheduled"]}
464
+ experimentalLocal={args.experimentalLocal}
447
465
  />
448
466
  );
449
467
  }
@@ -560,6 +578,7 @@ export async function startApiDev(args: StartDevOptions) {
560
578
  firstPartyWorker: configParam.first_party_worker,
561
579
  sendMetrics: configParam.send_metrics,
562
580
  testScheduled: args.testScheduled,
581
+ experimentalLocal: undefined,
563
582
  });
564
583
  }
565
584
 
package/src/publish.ts CHANGED
@@ -434,6 +434,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
434
434
  // This could potentially cause issues as we no longer have identical behaviour between dev and publish?
435
435
  targetConsumer: "publish",
436
436
  local: false,
437
+ experimentalLocalStubCache: false,
437
438
  }
438
439
  );
439
440
 
@@ -0,0 +1,27 @@
1
+ // `workerd` currently throws on any use of the Cache API. Workers Sites
2
+ // requires the Cache API to function though, so stub it out to no-ops, like in
3
+ // regular `wrangler dev`.
4
+
5
+ class Cache {
6
+ async put(req, res) {}
7
+
8
+ async match(req, options) {}
9
+
10
+ async delete(req, options) {
11
+ return false;
12
+ }
13
+ }
14
+
15
+ class CacheStorage {
16
+ #cache = new Cache();
17
+
18
+ get default() {
19
+ return this.#cache;
20
+ }
21
+
22
+ async open(cacheName) {
23
+ return this.#cache;
24
+ }
25
+ }
26
+
27
+ globalThis.caches = new CacheStorage();