wrangler 4.110.0 → 4.112.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.
@@ -110,7 +110,6 @@ function createDevOptions(parsedArgs) {
110
110
  jsxFragment: undefined,
111
111
  tsconfig: undefined,
112
112
  minify: undefined,
113
- legacyEnv: undefined,
114
113
  logLevel: undefined,
115
114
  showInteractiveDevSession: undefined,
116
115
  liveReload: undefined,
@@ -1638,11 +1638,6 @@
1638
1638
  "description": "The directory of static assets to serve.\n\nThe presence of this field in a Wrangler configuration file indicates a Pages project, and will prompt the handling of the configuration file according to the Pages-specific validation rules.",
1639
1639
  "markdownDescription": "The directory of static assets to serve.\n\nThe presence of this field in a Wrangler configuration file indicates a Pages project,\nand will prompt the handling of the configuration file according to the\nPages-specific validation rules."
1640
1640
  },
1641
- "legacy_env": {
1642
- "type": "boolean",
1643
- "description": "A boolean to enable \"legacy\" style wrangler environments (from Wrangler v1). These have been superseded by Services, but there may be projects that won't (or can't) use them. If you're using a legacy environment, you can set this to `true` to enable it.",
1644
- "markdownDescription": "A boolean to enable \"legacy\" style wrangler environments (from Wrangler v1).\nThese have been superseded by Services, but there may be projects that won't\n(or can't) use them. If you're using a legacy environment, you can set this\nto `true` to enable it."
1645
- },
1646
1641
  "send_metrics": {
1647
1642
  "type": "boolean",
1648
1643
  "description": "Whether Wrangler should send usage metrics to Cloudflare for this project.\n\nWhen defined this will override any user settings. Otherwise, Wrangler will use the user's preference.",
@@ -1746,6 +1741,14 @@
1746
1741
  "description": "By default, the Wrangler configuration file is the source of truth for your environment configuration, like a terraform file.\n\nIf you change your vars in the dashboard, wrangler *will* override/delete them on its next deploy.\n\nIf you want to keep your dashboard vars when wrangler deploys, set this field to true.",
1747
1742
  "markdownDescription": "By default, the Wrangler configuration file is the source of truth for your environment configuration, like a terraform file.\n\nIf you change your vars in the dashboard, wrangler *will* override/delete them on its next deploy.\n\nIf you want to keep your dashboard vars when wrangler deploys, set this field to true.",
1748
1743
  "default": false
1744
+ },
1745
+ "addresses": {
1746
+ "type": "array",
1747
+ "items": {
1748
+ "type": "string"
1749
+ },
1750
+ "description": "The inbound email addresses handled by the Worker being deployed.\n\nEach entry is a literal recipient address (e.g. `\"support@example.com\"`) or a `*@domain` catch-all (e.g. `\"*@example.com\"`). Every entry creates an Email Routing rule whose action routes mail to this Worker.\n\nThis field is top-level only and applies to every environment of the Worker; it cannot be set under `env.*`.",
1751
+ "markdownDescription": "The inbound email addresses handled by the Worker being deployed.\n\nEach entry is a literal recipient address (e.g. `\"support@example.com\"`)\nor a `*@domain` catch-all (e.g. `\"*@example.com\"`). Every entry creates an\nEmail Routing rule whose action routes mail to this Worker.\n\nThis field is top-level only and applies to every environment of the\nWorker; it cannot be set under `env.*`."
1749
1752
  }
1750
1753
  }
1751
1754
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "4.110.0",
3
+ "version": "4.112.0",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "assembly",
@@ -66,16 +66,16 @@
66
66
  "esbuild": "0.28.1",
67
67
  "path-to-regexp": "6.3.0",
68
68
  "unenv": "2.0.0-rc.24",
69
- "workerd": "1.20260708.1",
70
- "@cloudflare/kv-asset-handler": "0.5.0",
69
+ "workerd": "1.20260714.1",
71
70
  "@cloudflare/unenv-preset": "2.16.1",
72
- "miniflare": "4.20260708.1"
71
+ "miniflare": "4.20260714.0",
72
+ "@cloudflare/kv-asset-handler": "0.5.0"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@aws-sdk/client-s3": "^3.721.0",
76
76
  "@bomb.sh/tab": "^0.0.12",
77
77
  "@cloudflare/types": "6.18.4",
78
- "@cloudflare/workers-types": "^5.20260708.1",
78
+ "@cloudflare/workers-types": "^5.20260714.1",
79
79
  "@cspotcode/source-map-support": "0.8.1",
80
80
  "@netlify/build-info": "^10.5.1",
81
81
  "@sentry/node": "^7.86.0",
@@ -154,23 +154,23 @@
154
154
  "xxhash-wasm": "^1.0.1",
155
155
  "yaml": "^2.8.1",
156
156
  "yargs": "^17.7.2",
157
- "zod": "^4.4.3",
158
- "@cloudflare/autoconfig": "0.1.4",
159
- "@cloudflare/cli-shared-helpers": "0.1.13",
157
+ "zod": "4.4.3",
158
+ "@cloudflare/autoconfig": "0.1.6",
160
159
  "@cloudflare/codemod": "1.1.0",
160
+ "@cloudflare/config": "0.2.1",
161
161
  "@cloudflare/containers-shared": "0.16.0",
162
- "@cloudflare/deploy-helpers": "0.4.0",
163
- "@cloudflare/pages-shared": "^0.13.156",
164
- "@cloudflare/runtime-types": "0.0.1",
165
- "@cloudflare/workers-shared": "0.19.7",
166
- "@cloudflare/workers-auth": "0.4.2",
162
+ "@cloudflare/deploy-helpers": "0.5.1",
163
+ "@cloudflare/cli-shared-helpers": "0.1.15",
164
+ "@cloudflare/pages-shared": "^0.13.158",
165
+ "@cloudflare/runtime-types": "0.0.3",
166
+ "@cloudflare/workers-auth": "0.5.0",
167
+ "@cloudflare/workers-shared": "0.19.9",
167
168
  "@cloudflare/workers-tsconfig": "0.0.0",
168
- "@cloudflare/workers-utils": "0.26.0",
169
- "@cloudflare/workflows-shared": "0.12.0",
170
- "@cloudflare/config": "0.0.0"
169
+ "@cloudflare/workers-utils": "0.27.0",
170
+ "@cloudflare/workflows-shared": "0.12.1"
171
171
  },
172
172
  "peerDependencies": {
173
- "@cloudflare/workers-types": "^5.20260708.1"
173
+ "@cloudflare/workers-types": "^5.20260714.1"
174
174
  },
175
175
  "peerDependenciesMeta": {
176
176
  "@cloudflare/workers-types": {
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  createDeferred,
3
3
  DeferredPromise,
4
+ rewriteUrlInHeaderValue,
4
5
  urlFromParts,
5
6
  } from "../../src/api/startDevWorker/utils";
6
7
  import type {
@@ -350,10 +351,7 @@ function rewriteUrlRelatedHeaders(headers: Headers, from: URL, to: URL) {
350
351
  headers.delete("Set-Cookie");
351
352
  headers.forEach((value, key) => {
352
353
  if (typeof value === "string" && value.includes(from.host)) {
353
- headers.set(
354
- key,
355
- value.replaceAll(from.origin, to.origin).replaceAll(from.host, to.host)
356
- );
354
+ headers.set(key, rewriteUrlInHeaderValue(value, from, to));
357
355
  }
358
356
  });
359
357
  for (const cookie of setCookie) {
@@ -21,6 +21,23 @@ function urlFromParts(parts, base = "http://localhost") {
21
21
  Object.assign(url, parts);
22
22
  return url;
23
23
  }
24
+ function rewriteUrlInHeaderValue(value, from, to) {
25
+ return value.replace(
26
+ /(https?:\/\/[^/?#\s,;"']+)([^\s,;"']*)/gi,
27
+ (match, origin, rest) => {
28
+ let url;
29
+ try {
30
+ url = new URL(origin);
31
+ } catch {
32
+ return match;
33
+ }
34
+ if (url.host !== from.host) {
35
+ return match;
36
+ }
37
+ return to.origin + rest;
38
+ }
39
+ );
40
+ }
24
41
 
25
42
  // templates/startDevWorker/ProxyWorker.ts
26
43
  var LIVE_RELOAD_PROTOCOL = "WRANGLER_PROXYWORKER_LIVE_RELOAD_PROTOCOL";
@@ -231,10 +248,7 @@ function rewriteUrlRelatedHeaders(headers, from, to) {
231
248
  headers.delete("Set-Cookie");
232
249
  headers.forEach((value, key) => {
233
250
  if (typeof value === "string" && value.includes(from.host)) {
234
- headers.set(
235
- key,
236
- value.replaceAll(from.origin, to.origin).replaceAll(from.host, to.host)
237
- );
251
+ headers.set(key, rewriteUrlInHeaderValue(value, from, to));
238
252
  }
239
253
  });
240
254
  for (const cookie of setCookie) {
@@ -1,10 +1,11 @@
1
- import { Rule as Rule$1, CfModule, Environment as Environment$1, Entry, CfModuleType, StartDevWorkerInput, Config as Config$1, NodeJSCompatMode, CfScriptFormat, AsyncHook, CfAccount as CfAccount$1, AssetsOptions as AssetsOptions$1, Binding, ConfigBindingFieldName, RawConfig as RawConfig$1, NormalizeAndValidateConfigArgs, ResolveConfigPathOptions, ApiCredentials, ParseError, LoggerLevel, ComplianceConfig, UserError, FatalError } from '@cloudflare/workers-utils';
1
+ import { Rule as Rule$1, CfModule, Environment as Environment$1, Entry, CfModuleType, Config as Config$1, StartDevWorkerInput, NodeJSCompatMode, CfScriptFormat, AsyncHook, CfAccount as CfAccount$1, AssetsOptions as AssetsOptions$1, Binding, ConfigBindingFieldName, RawConfig as RawConfig$1, NormalizeAndValidateConfigArgs, ResolveConfigPathOptions, ApiCredentials, ParseError, LoggerLevel, ComplianceConfig, UserError, FatalError } from '@cloudflare/workers-utils';
2
2
  export { Binding, experimental_patchConfig, experimental_readRawConfig, defaultWranglerConfig as unstable_defaultWranglerConfig } from '@cloudflare/workers-utils';
3
- import { Json as Json$1, WorkerdStructuredLog, DispatchFetch, Miniflare, WorkerRegistry, MiniflareOptions, Mutex, Response as Response$1, RemoteProxyConnectionString, WorkerOptions, ModuleRule, Request } from 'miniflare';
3
+ import { Json as Json$1, WorkerdStructuredLog, DispatchFetch, Miniflare, WorkerRegistry, MiniflareOptions, Mutex, Response as Response$1, DurableObjectStorageOptions, DurableObjectStorageHandle, RemoteProxyConnectionString, WorkerOptions, ModuleRule, Request } from 'miniflare';
4
4
  import * as undici from 'undici';
5
5
  import { RequestInfo, RequestInit, Response, FormData } from 'undici';
6
6
  import { Metafile } from 'esbuild';
7
7
  import Protocol from 'devtools-protocol/types/protocol-mapping';
8
+ import Protocol$1 from 'devtools-protocol';
8
9
  import { EventEmitter } from 'node:events';
9
10
  import { ContainerNormalizedConfig } from '@cloudflare/containers-shared';
10
11
  import { Rpc, ExportedHandler, DurableObjectNamespace, D1Database, Workflow, Service } from '@cloudflare/workers-types';
@@ -335,17 +336,29 @@ type EsbuildBundle = {
335
336
 
336
337
  declare class ConfigController extends Controller {
337
338
  #private;
338
- latestInput?: StartDevWorkerInput;
339
+ latestInput?: WranglerStartDevWorkerInput;
339
340
  latestWranglerConfig?: Config$1;
340
341
  latestConfig?: StartDevWorkerOptions;
341
- set(input: StartDevWorkerInput, throwErrors?: boolean): Promise<StartDevWorkerOptions | undefined>;
342
- patch(input: Partial<StartDevWorkerInput>): Promise<StartDevWorkerOptions | undefined>;
342
+ set(input: WranglerStartDevWorkerInput, throwErrors?: boolean): Promise<StartDevWorkerOptions | undefined>;
343
+ patch(input: Partial<WranglerStartDevWorkerInput>): Promise<StartDevWorkerOptions | undefined>;
343
344
  onDevRegistryUpdate(event: DevRegistryUpdateEvent): void;
344
345
  teardown(): Promise<void>;
345
346
  emitConfigUpdateEvent(config: StartDevWorkerOptions): void;
346
347
  }
347
348
 
348
349
  type MiniflareWorker = Awaited<ReturnType<Miniflare["getWorker"]>>;
350
+ /**
351
+ * Extended StartDevWorkerInput with wrangler-specific fields that depend on miniflare types.
352
+ * The base StartDevWorkerInput in workers-utils is kept dependency-free.
353
+ */
354
+ type WranglerStartDevWorkerInput = Omit<StartDevWorkerInput, "dev"> & {
355
+ dev?: StartDevWorkerInput["dev"] & {
356
+ /** Handles structured runtime logs. */
357
+ structuredLogsHandler?: (log: WorkerdStructuredLog) => void;
358
+ /** An undici MockAgent to declaratively mock fetch calls to particular resources. */
359
+ mockFetch?: undici.MockAgent;
360
+ };
361
+ };
349
362
  interface Worker {
350
363
  ready: Promise<void>;
351
364
  url: Promise<URL>;
@@ -435,6 +448,17 @@ type DevRegistryUpdateEvent = {
435
448
  type: "devRegistryUpdate";
436
449
  registry: WorkerRegistry;
437
450
  };
451
+ type RuntimeErrorEvent = {
452
+ type: "runtimeError";
453
+ source: "LocalRuntimeController" | "ProxyController";
454
+ /** The exception summary line. */
455
+ text: string;
456
+ /** The source-mapped stack. */
457
+ stack: string;
458
+ /** The raw Chrome DevTools Protocol exception details, when the event
459
+ * came over the inspector. */
460
+ exceptionDetails?: Protocol$1.Runtime.ExceptionDetails;
461
+ };
438
462
  type PreviewTokenExpiredEvent = {
439
463
  type: "previewTokenExpired";
440
464
  proxyData: ProxyData;
@@ -501,7 +525,7 @@ type ProxyData = {
501
525
  proxyLogsToController?: boolean;
502
526
  };
503
527
 
504
- type ControllerEvent = ErrorEvent | ConfigUpdateEvent | BundleStartEvent | BundleCompleteEvent | ReloadStartEvent | ReloadCompleteEvent | DevRegistryUpdateEvent | PreviewTokenExpiredEvent;
528
+ type ControllerEvent = ErrorEvent | ConfigUpdateEvent | BundleStartEvent | BundleCompleteEvent | ReloadStartEvent | ReloadCompleteEvent | DevRegistryUpdateEvent | RuntimeErrorEvent | PreviewTokenExpiredEvent;
505
529
  interface ControllerBus {
506
530
  dispatch(event: ControllerEvent): void;
507
531
  }
@@ -573,7 +597,7 @@ declare class DevEnv extends EventEmitter implements ControllerBus {
573
597
  bundler: BundlerController;
574
598
  runtimes: RuntimeController[];
575
599
  proxy: ProxyController;
576
- startWorker(options: StartDevWorkerInput): Promise<Worker>;
600
+ startWorker(options: WranglerStartDevWorkerInput): Promise<Worker>;
577
601
  constructor({ configFactory, bundlerFactory, runtimeFactories, proxyFactory, }?: {
578
602
  configFactory?: ControllerFactory<ConfigController>;
579
603
  bundlerFactory?: ControllerFactory<BundlerController>;
@@ -603,7 +627,7 @@ declare class DevEnv extends EventEmitter implements ControllerBus {
603
627
  teardown(): Promise<void>;
604
628
  }
605
629
 
606
- declare function startWorker(options: StartDevWorkerInput): Promise<Worker>;
630
+ declare function startWorker(options: WranglerStartDevWorkerInput): Promise<Worker>;
607
631
 
608
632
  declare const dev: {
609
633
  args: {
@@ -651,7 +675,6 @@ declare const dev: {
651
675
  nodeCompat: boolean | undefined;
652
676
  persistTo: string | undefined;
653
677
  liveReload: boolean | undefined;
654
- legacyEnv: boolean | undefined;
655
678
  testScheduled: boolean;
656
679
  logLevel: "debug" | "none" | "error" | "log" | "info" | "warn" | undefined;
657
680
  showInteractiveDevSession: boolean | undefined;
@@ -777,16 +800,25 @@ type TestHarnessOptions = {
777
800
  */
778
801
  workers: WorkerInput[];
779
802
  };
803
+ type ExportName<Module, Type> = string extends keyof Module ? string : Extract<{
804
+ [K in keyof Module]-?: NonNullable<Module[K]> extends Type | (abstract new (...args: any[]) => Type) ? K : never;
805
+ }[keyof Module], string>;
780
806
  type BindingName<Env, Type> = string extends keyof Env ? string : Extract<{
781
807
  [K in keyof Env]-?: NonNullable<Env[K]> extends Type ? K : never;
782
808
  }[keyof Env], string>;
809
+ type DurableObjectIdentifier = {
810
+ name: string;
811
+ id?: never;
812
+ } | {
813
+ id: string;
814
+ name?: never;
815
+ };
816
+ type WorkerDefaultExport = (new (...args: any[]) => Rpc.WorkerEntrypointBranded) | Rpc.WorkerEntrypointBranded | AnyExportedHandler;
783
817
  type WorkerModule = {
784
- default: WorkerExport;
785
- [key: string]: WorkerExport | undefined;
818
+ default: WorkerDefaultExport;
786
819
  };
787
820
  type AnyExportedHandler = ExportedHandler<any, any, any, any>;
788
821
  type AnyEnv = Record<string, any>;
789
- type WorkerExport = (new (...args: any[]) => Rpc.WorkerEntrypointBranded) | Rpc.WorkerEntrypointBranded | AnyExportedHandler;
790
822
  type WorkerHandle<Env = AnyEnv, Module extends WorkerModule = {
791
823
  default: AnyExportedHandler;
792
824
  }> = {
@@ -829,9 +861,27 @@ type WorkerHandle<Env = AnyEnv, Module extends WorkerModule = {
829
861
  */
830
862
  getEnv(): Promise<Env>;
831
863
  /**
832
- * Lists the string IDs of Durable Object instances with persisted storage for a binding.
864
+ * Lists the string IDs of Durable Object instances with persisted storage.
865
+ * Pass an exported Durable Object class name, or a Durable Object binding name.
866
+ */
867
+ listDurableObjectIds(classNameOrBindingName: ExportName<Module, Rpc.DurableObjectBranded> | BindingName<Env, DurableObjectNamespace>): Promise<string[]>;
868
+ /**
869
+ * Evicts a currently running Durable Object instance while preserving its durable storage.
870
+ * In-memory state is reset the next time the object starts.
871
+ * Pass an exported Durable Object class name, or a Durable Object binding name.
872
+ * Class names are resolved before binding names.
873
+ *
874
+ * @example
875
+ * ```ts
876
+ * await worker.evictDurableObject("Counter", {
877
+ * name: "user-123",
878
+ * webSockets: "hibernate",
879
+ * });
880
+ * ```
833
881
  */
834
- listDurableObjectIds(bindingName: BindingName<Env, DurableObjectNamespace>): Promise<string[]>;
882
+ evictDurableObject(classNameOrBindingName: ExportName<Module, Rpc.DurableObjectBranded> | BindingName<Env, DurableObjectNamespace>, options: DurableObjectIdentifier & {
883
+ webSockets?: "close" | "hibernate";
884
+ }): Promise<void>;
835
885
  /**
836
886
  * Applies D1 migration files that have not already run to a D1 binding on this Worker.
837
887
  *
@@ -843,6 +893,25 @@ type WorkerHandle<Env = AnyEnv, Module extends WorkerModule = {
843
893
  * ```
844
894
  */
845
895
  applyD1Migrations(bindingName: BindingName<Env, D1Database>): Promise<void>;
896
+ /**
897
+ * Returns remote storage access for a Durable Object instance.
898
+ * Pass an exported Durable Object class name, or a Durable Object binding name.
899
+ * Class names are resolved before binding names.
900
+ *
901
+ * Use this to seed state before sending requests to the object, or to inspect
902
+ * state after awaited requests. Calling `exec()` runs SQL inside the target
903
+ * Durable Object and returns all rows. It may start the object if it is not
904
+ * already active.
905
+ *
906
+ * @example
907
+ * ```ts
908
+ * const sql = await worker.getDurableObjectStorage("COUNTER", {
909
+ * name: "user-123"
910
+ * });
911
+ * const rows = await sql.exec("SELECT count FROM counters WHERE id = ?", "user-123");
912
+ * ```
913
+ */
914
+ getDurableObjectStorage(classNameOrBindingName: ExportName<Module, Rpc.DurableObjectBranded> | BindingName<Env, DurableObjectNamespace>, options: DurableObjectStorageOptions): Promise<DurableObjectStorageHandle>;
846
915
  /**
847
916
  * Creates an introspector for a specific Workflow instance.
848
917
  */
@@ -2742,13 +2811,6 @@ interface ComputedFields {
2742
2811
  targetEnvironment: string | undefined;
2743
2812
  }
2744
2813
  interface ConfigFields<Dev extends RawDevConfig> {
2745
- /**
2746
- * A boolean to enable "legacy" style wrangler environments (from Wrangler v1).
2747
- * These have been superseded by Services, but there may be projects that won't
2748
- * (or can't) use them. If you're using a legacy environment, you can set this
2749
- * to `true` to enable it.
2750
- */
2751
- legacy_env: boolean;
2752
2814
  /**
2753
2815
  * Whether Wrangler should send usage metrics to Cloudflare for this project.
2754
2816
  *
@@ -2868,6 +2930,19 @@ interface ConfigFields<Dev extends RawDevConfig> {
2868
2930
  * @nonInheritable
2869
2931
  */
2870
2932
  keep_vars?: boolean;
2933
+ /**
2934
+ * The inbound email addresses handled by the Worker being deployed.
2935
+ *
2936
+ * Each entry is a literal recipient address (e.g. `"support@example.com"`)
2937
+ * or a `*@domain` catch-all (e.g. `"*@example.com"`). Every entry creates an
2938
+ * Email Routing rule whose action routes mail to this Worker.
2939
+ *
2940
+ * This field is top-level only and applies to every environment of the
2941
+ * Worker; it cannot be set under `env.*`.
2942
+ *
2943
+ * @nonInheritable
2944
+ */
2945
+ addresses?: string[];
2871
2946
  }
2872
2947
  interface PagesConfigFields {
2873
2948
  /**
@@ -3161,6 +3236,11 @@ type WorkerConfigObject = {
3161
3236
  complianceRegion?: Config$1["compliance_region"];
3162
3237
  /** Id of the account owning the worker */
3163
3238
  account_id?: Config$1["account_id"];
3239
+ /**
3240
+ * directory used to resolve the auth profile from directory bindings.
3241
+ * Falls back to `process.cwd()` when not provided.
3242
+ */
3243
+ profileDir?: string;
3164
3244
  };
3165
3245
  /**
3166
3246
  * Utility for potentially starting or updating a remote proxy session.
@@ -3633,6 +3713,20 @@ declare class CommandRegistry {
3633
3713
  * Includes both registry-defined commands & legacy commands.
3634
3714
  */
3635
3715
  get topLevelCommands(): Set<string>;
3716
+ /**
3717
+ * Get the set of valid subcommand names at a given command path.
3718
+ *
3719
+ * Walks the definition tree along the given path segments, then returns
3720
+ * the keys of the subtree at that node. Returns `undefined` if the path
3721
+ * does not exist in the tree or has no subcommands.
3722
+ *
3723
+ * @param pathSegments - The command path segments to walk (e.g., `["kv"]`
3724
+ * returns `namespace`, `key`, `bulk`; `["kv", "namespace"]` returns
3725
+ * `create`, `list`, `delete`, etc.)
3726
+ * @returns A set of valid subcommand names, or `undefined` if the path is
3727
+ * invalid or has no subcommands
3728
+ */
3729
+ getSubcommands(pathSegments: string[]): Set<string> | undefined;
3636
3730
  /**
3637
3731
  * Returns the map of categories to command segments, ordered according to
3638
3732
  * the category order. Commands within each category are sorted alphabetically.