wrangler 2.1.7 → 2.1.9

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/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
  }
@@ -543,10 +561,13 @@ export async function startApiDev(args: StartDevOptions) {
543
561
  isWorkersSite: Boolean(args.site || configParam.site),
544
562
  compatibilityDate: getDevCompatibilityDate(
545
563
  config,
546
- args["compatibility-date"]
564
+ // Only `compatibilityDate` will be set when using `unstable_dev`
565
+ args["compatibility-date"] ?? args.compatibilityDate
547
566
  ),
548
567
  compatibilityFlags:
549
- args["compatibility-flags"] || configParam.compatibility_flags,
568
+ args["compatibility-flags"] ??
569
+ args.compatibilityFlags ??
570
+ configParam.compatibility_flags,
550
571
  usageModel: configParam.usage_model,
551
572
  bindings: bindings,
552
573
  crons: configParam.triggers.crons,
@@ -560,6 +581,7 @@ export async function startApiDev(args: StartDevOptions) {
560
581
  firstPartyWorker: configParam.first_party_worker,
561
582
  sendMetrics: configParam.send_metrics,
562
583
  testScheduled: args.testScheduled,
584
+ experimentalLocal: args.experimentalLocal,
563
585
  });
564
586
  }
565
587
 
package/src/init.ts CHANGED
@@ -946,12 +946,16 @@ async function getWorkerConfig(
946
946
  new Date().toISOString().substring(0, 10),
947
947
  ...routeOrRoutesToConfig,
948
948
  usage_model: serviceEnvMetadata.script.usage_model,
949
- migrations: [
950
- {
951
- tag: serviceEnvMetadata.script.migration_tag,
952
- new_classes: durableObjectClassNames,
953
- },
954
- ],
949
+ ...(durableObjectClassNames.length
950
+ ? {
951
+ migrations: [
952
+ {
953
+ tag: serviceEnvMetadata.script.migration_tag,
954
+ new_classes: durableObjectClassNames,
955
+ },
956
+ ],
957
+ }
958
+ : {}),
955
959
  triggers: {
956
960
  crons: cronTriggers.schedules.map((scheduled) => scheduled.cron),
957
961
  },
@@ -7,6 +7,13 @@ import type { Config, ConfigModuleRuleType } from "./config";
7
7
  import type { CfModule, CfModuleType, CfScriptFormat } from "./worker";
8
8
  import type esbuild from "esbuild";
9
9
 
10
+ function flipObject<
11
+ K extends string | number | symbol,
12
+ V extends string | number | symbol
13
+ >(obj: Record<K, V>): Record<V, K> {
14
+ return Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]));
15
+ }
16
+
10
17
  const RuleTypeToModuleType: Record<ConfigModuleRuleType, CfModuleType> = {
11
18
  ESModule: "esm",
12
19
  CommonJS: "commonjs",
@@ -15,6 +22,8 @@ const RuleTypeToModuleType: Record<ConfigModuleRuleType, CfModuleType> = {
15
22
  Text: "text",
16
23
  };
17
24
 
25
+ export const ModuleTypeToRuleType = flipObject(RuleTypeToModuleType);
26
+
18
27
  // This is a combination of an esbuild plugin and a mutable array
19
28
  // that we use to collect module references from source code.
20
29
  // There will be modules that _shouldn't_ be inlined directly into
package/src/proxy.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createServer as createHttpServer } from "node:http";
2
2
  import { connect } from "node:http2";
3
3
  import { createServer as createHttpsServer } from "node:https";
4
+ import https from "node:https";
4
5
  import { networkInterfaces } from "node:os";
5
- import WebSocket from "faye-websocket";
6
6
  import { createHttpTerminator } from "http-terminator";
7
7
  import { useEffect, useRef, useState } from "react";
8
8
  import serveStatic from "serve-static";
@@ -19,12 +19,7 @@ import type {
19
19
  } from "node:http";
20
20
  import type { ClientHttp2Session, ServerHttp2Stream } from "node:http2";
21
21
  import type { Server as HttpsServer } from "node:https";
22
- import type ws from "ws";
23
-
24
- interface IWebsocket extends ws {
25
- // Pipe implements .on("message", ...)
26
- pipe<T>(fn: T): IWebsocket;
27
- }
22
+ import type { Duplex, Writable } from "node:stream";
28
23
 
29
24
  /**
30
25
  * `usePreviewServer` is a React hook that creates a local development
@@ -70,6 +65,26 @@ function rewriteRemoteHostToLocalHostInHeaders(
70
65
  }
71
66
  }
72
67
 
68
+ function writeHead(
69
+ socket: Writable,
70
+ res: Pick<
71
+ IncomingMessage,
72
+ "httpVersion" | "statusCode" | "statusMessage" | "headers"
73
+ >
74
+ ) {
75
+ socket.write(
76
+ `HTTP/${res.httpVersion} ${res.statusCode} ${res.statusMessage}\r\n`
77
+ );
78
+ for (const [key, values] of Object.entries(res.headers)) {
79
+ if (Array.isArray(values)) {
80
+ for (const value of values) socket.write(`${key}: ${value}\r\n`);
81
+ } else {
82
+ socket.write(`${key}: ${values}\r\n`);
83
+ }
84
+ }
85
+ socket.write("\r\n");
86
+ }
87
+
73
88
  type PreviewProxy = {
74
89
  server: HttpServer | HttpsServer;
75
90
  terminator: HttpTerminator;
@@ -273,27 +288,47 @@ export function usePreviewServer({
273
288
 
274
289
  /** HTTP/1 -> WebSocket (over HTTP/1) */
275
290
  const handleUpgrade = (
276
- message: IncomingMessage,
277
- socket: WebSocket,
278
- body: Buffer
291
+ originalMessage: IncomingMessage,
292
+ originalSocket: Duplex,
293
+ originalHead: Buffer
279
294
  ) => {
280
- const { headers, url } = message;
295
+ const { headers, method, url } = originalMessage;
281
296
  addCfPreviewTokenHeader(headers, previewToken.value);
282
297
  headers["host"] = previewToken.host;
283
- const localWebsocket = new WebSocket(message, socket, body) as IWebsocket;
284
- // TODO(soon): Custom WebSocket protocol is not working?
285
- const remoteWebsocketClient = new WebSocket.Client(
286
- `wss://${previewToken.host}${url}`,
287
- [],
288
- { headers }
289
- ) as IWebsocket;
290
- localWebsocket.pipe(remoteWebsocketClient).pipe(localWebsocket);
291
- // We close down websockets whenever we refresh the token.
292
- cleanupListeners.push(() => {
293
- localWebsocket.close();
294
- remoteWebsocketClient.close();
295
- });
298
+
299
+ if (originalHead?.byteLength) originalSocket.unshift(originalHead);
300
+
301
+ const runtimeRequest = https.request(
302
+ {
303
+ hostname: previewToken.host,
304
+ path: url,
305
+ method,
306
+ headers,
307
+ },
308
+ (runtimeResponse) => {
309
+ if (!(runtimeResponse as { upgrade?: boolean }).upgrade) {
310
+ writeHead(originalSocket, runtimeResponse);
311
+ runtimeResponse.pipe(originalSocket);
312
+ }
313
+ }
314
+ );
315
+
316
+ runtimeRequest.on(
317
+ "upgrade",
318
+ (runtimeResponse, runtimeSocket, runtimeHead) => {
319
+ if (runtimeHead?.byteLength) runtimeSocket.unshift(runtimeHead);
320
+ writeHead(originalSocket, {
321
+ httpVersion: "1.1",
322
+ statusCode: 101,
323
+ statusMessage: "Switching Protocols",
324
+ headers: runtimeResponse.headers,
325
+ });
326
+ runtimeSocket.pipe(originalSocket).pipe(runtimeSocket);
327
+ }
328
+ );
329
+ originalMessage.pipe(runtimeRequest);
296
330
  };
331
+
297
332
  proxy.server.on("upgrade", handleUpgrade);
298
333
  cleanupListeners.push(() => proxy.server.off("upgrade", handleUpgrade));
299
334
 
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();
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  export default {
12
- async fetch(request) {
12
+ async fetch(request, env, ctx) {
13
13
  return new Response("Hello World!");
14
14
  },
15
15
  };
@@ -127,6 +127,7 @@ declare interface DevOptions {
127
127
  _?: (string | number)[];
128
128
  $0?: string;
129
129
  testScheduled?: boolean;
130
+ experimentalLocal?: boolean;
130
131
  }
131
132
 
132
133
  declare interface EnablePagesAssetsServiceBindingOptions {