wrangler
Version:
Command-line interface for all things Cloudflare Workers
1,447 lines (1,416 loc) • 144 kB
TypeScript
import { Rule as Rule$1, CfModule, Environment as Environment$1, Entry, CfModuleType, Config as Config$1, StartDevWorkerInput, NodeJSCompatMode, CfScriptFormat, AsyncHook, CfAccount, AssetsOptions as AssetsOptions$1, Binding, ConfigBindingFieldName, RawConfig as RawConfig$1, NormalizeAndValidateConfigArgs, ResolveConfigPathOptions, ParseError, LoggerLevel, ComplianceConfig, ApiCredentials, UserError, FatalError } from '@cloudflare/workers-utils';
export { Binding, experimental_patchConfig, experimental_readRawConfig, defaultWranglerConfig as unstable_defaultWranglerConfig } from '@cloudflare/workers-utils';
import { Json as Json$1, WorkerdStructuredLog, DispatchFetch, Miniflare, WorkerRegistry, MiniflareOptions, Mutex, Response as Response$1, DurableObjectStorageOptions, DurableObjectStorageHandle, RemoteProxyConnectionString, WorkerOptions, ModuleRule, Request } from 'miniflare';
import * as undici from 'undici';
import { RequestInfo, RequestInit, Response, FormData } from 'undici';
import { Metafile } from 'esbuild';
import Protocol from 'devtools-protocol/types/protocol-mapping';
import Protocol$1 from 'devtools-protocol';
import { EventEmitter } from 'node:events';
import { ContainerNormalizedConfig } from '@cloudflare/containers-shared';
import { Rpc, ExportedHandler, DurableObjectNamespace, D1Database, Workflow, Service } from '@cloudflare/workers-types';
import { FetcherScheduledOptions, FetcherScheduledResult, IncomingRequestCfProperties } from '@cloudflare/workers-types/experimental';
import { RouterConfig, AssetConfig } from '@cloudflare/workers-shared';
import { StartRemoteProxySessionOptions as StartRemoteProxySessionOptions$1, RemoteProxySession, WorkerConfigObject, RemoteProxySessionData } from '@cloudflare/remote-bindings';
export { RemoteProxySession } from '@cloudflare/remote-bindings';
export { printBindings as unstable_printBindings } from '@cloudflare/deploy-helpers';
import { URLSearchParams } from 'node:url';
import { Argv, PositionalOptions, Options, ArgumentsCamelCase, InferredOptionTypes, InferredOptionType } from 'yargs';
import Cloudflare from 'cloudflare';
interface EnablePagesAssetsServiceBindingOptions {
proxyPort?: number;
directory?: string;
}
interface Unstable_DevOptions {
config?: string;
env?: string;
envFiles?: string[];
ip?: string;
port?: number;
bundle?: boolean;
inspectorPort?: number;
localProtocol?: "http" | "https";
httpsKeyPath?: string;
httpsCertPath?: string;
assets?: string;
site?: string;
siteInclude?: string[];
siteExclude?: string[];
compatibilityDate?: string;
compatibilityFlags?: string[];
persist?: boolean;
persistTo?: string;
vars?: Record<string, string | Json$1>;
kv?: {
binding: string;
id?: string;
preview_id?: string;
remote?: boolean;
}[];
durableObjects?: {
name: string;
class_name: string;
script_name?: string | undefined;
environment?: string | undefined;
}[];
services?: {
binding: string;
service: string;
environment?: string | undefined;
entrypoint?: string | undefined;
remote?: boolean;
}[];
r2?: {
binding: string;
bucket_name?: string;
preview_bucket_name?: string;
remote?: boolean;
}[];
ai?: {
binding: string;
};
version_metadata?: {
binding: string;
};
moduleRoot?: string;
rules?: Rule$1[];
logLevel?: "none" | "info" | "error" | "log" | "warn" | "debug";
inspect?: boolean;
local?: boolean;
accountId?: string;
experimental?: {
processEntrypoint?: boolean;
additionalModules?: CfModule[];
d1Databases?: Environment$1["d1_databases"];
disableExperimentalWarning?: boolean;
disableDevRegistry?: boolean;
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
forceLocal?: boolean;
liveReload?: boolean;
showInteractiveDevSession?: boolean;
testScheduled?: boolean;
watch?: boolean;
fileBasedRegistry?: boolean;
enableIpc?: boolean;
enableContainers?: boolean;
dockerPath?: string;
containerEngine?: string;
};
}
interface Unstable_DevWorker {
port: number;
address: string;
stop: () => Promise<void>;
fetch: (input?: RequestInfo, init?: RequestInit) => Promise<Response>;
waitUntilExit: () => Promise<void>;
}
/**
* unstable_dev starts a wrangler dev server, and returns a promise that resolves with utility functions to interact with it.
*/
declare function unstable_dev(script: string, options?: Unstable_DevOptions, apiOptions?: unknown): Promise<Unstable_DevWorker>;
interface PagesDeployOptions {
/**
* Path to static assets to deploy to Pages
*/
directory: string;
/**
* The Cloudflare Account ID that owns the project that's
* being published
*/
accountId: string;
/**
* The name of the project to be published
*/
projectName: string;
/**
* Branch name to use. Defaults to production branch
*/
branch?: string;
/**
* Whether or not to skip local file upload result caching
*/
skipCaching?: boolean;
/**
* Commit message associated to deployment
*/
commitMessage?: string;
/**
* Commit hash associated to deployment
*/
commitHash?: string;
/**
* Whether or not the deployment should be considered to be
* in a dirty commit state
*/
commitDirty?: boolean;
/**
* Path to the project's functions directory. Default uses
* the current working directory + /functions since this is
* typically called in a CLI
*/
functionsDirectory?: string;
/**
* Whether to run bundling on `_worker.js` before deploying.
* Default: true
*/
bundle?: boolean;
/**
* Whether to upload any server-side sourcemaps with this deployment
*/
sourceMaps: boolean;
/**
* Command line args passed to the `pages deploy` cmd
*/
args?: Record<string, unknown>;
}
/**
* Publish a directory to an account/project.
* NOTE: You will need the `CLOUDFLARE_API_KEY` environment
* variable set
*/
declare function deploy({ directory, accountId, projectName, branch, skipCaching, commitMessage, commitHash, commitDirty, functionsDirectory: customFunctionsDirectory, bundle, sourceMaps, args, }: PagesDeployOptions): Promise<{
deploymentResponse: {
id: string;
url: string;
environment: "production" | "preview";
build_config: {
build_command: string;
destination_dir: string;
root_dir: string;
web_analytics_tag?: string | undefined;
web_analytics_token?: string | undefined;
fast_builds?: boolean | undefined;
};
created_on: string;
production_branch: string;
project_id: string;
project_name: string;
deployment_trigger: {
type: string;
metadata: {
branch: string;
commit_hash: string;
commit_message: string;
};
};
latest_stage: {
status: "success" | "skipped" | "active" | "canceled" | "idle" | "failure";
name: "queued" | "build" | "deploy" | "initialize" | "clone_repo";
started_on: string | null;
ended_on: string | null;
};
stages: {
status: "success" | "skipped" | "active" | "canceled" | "idle" | "failure";
name: "queued" | "build" | "deploy" | "initialize" | "clone_repo";
started_on: string | null;
ended_on: string | null;
}[];
aliases: string[];
modified_on: string;
short_id: string;
build_image_major_version: number;
source?: {
type: "github" | "gitlab";
config: {
owner: string;
repo_name: string;
production_branch?: string | undefined;
pr_comments_enabled?: boolean | undefined;
deployments_enabled?: boolean | undefined;
production_deployments_enabled?: boolean | undefined;
preview_deployment_setting?: "custom" | "none" | "all" | undefined;
preview_branch_includes?: string[] | undefined;
preview_branch_excludes?: string[] | undefined;
};
} | undefined;
kv_namespaces?: any;
env_vars?: any;
durable_object_namespaces?: any;
is_skipped?: boolean | undefined;
files?: {
[x: string]: string | undefined;
} | undefined;
};
formData: FormData;
}>;
declare const unstable_pages: {
deploy: typeof deploy;
};
interface GenerateTypesOptions {
/**
* Path to the Wrangler config file to use. Can be an array for multi-config type resolution.
*/
config?: string | string[];
/**
* Name of the Wrangler environment to generate types for.
*/
env?: string;
/**
* Paths to `.env` files to load when inferring local variables and secrets.
*/
envFile?: string[];
/**
* Name of the generated environment interface.
*/
envInterface?: string;
/**
* Whether to include environment/bindings types in the output.
*/
includeEnv?: boolean;
/**
* Whether to include runtime types in the output.
*/
includeRuntime?: boolean;
/**
* Path to the declaration file for generated types.
*/
path?: string;
/**
* Whether to generate strict literal/union variable types.
*/
strictVars?: boolean;
}
type Experimental_GenerateTypesOptions = GenerateTypesOptions;
interface GenerateTypesResult {
/**
* Combined formatted output containing all generated sections.
*/
content: string;
/**
* Generated environment/bindings types, or `null` when env types are excluded.
*/
env: string | null;
/**
* Target declaration file path associated with this generation run.
*/
path: string;
/**
* Generated runtime types, or `null` when runtime types are excluded.
*/
runtime: string | null;
}
type Experimental_GenerateTypesResult = GenerateTypesResult;
/**
* Generate types from your Worker configuration
*
* @description Programmatically generate TypeScript type definitions for your
* Worker, using the same logic that powers the `wrangler types` CLI command.
*
* @param options - Type generation configuration options that mirror the `wrangler types` CLI flags
*
* @returns Structured output containing combined content & split env/runtime sections.
*/
declare function generateTypes(options: Experimental_GenerateTypesOptions): Promise<Experimental_GenerateTypesResult>;
type _Params<ParamsArray extends [unknown?]> = ParamsArray extends [infer P] ? P : undefined;
type _EventMethods = keyof Protocol.Events;
type DevToolsEvent<Method extends _EventMethods> = Method extends unknown ? {
method: Method;
params: _Params<Protocol.Events[Method]>;
} : never;
/**
* Information about Wrangler's bundling process that needs passed through
* for DevTools sourcemap transformation
*/
interface SourceMapMetadata {
tmpDir: string;
entryDirectory: string;
}
type EsbuildBundle = {
id: number;
path: string;
entrypointSource: string;
entry: Entry;
type: CfModuleType;
modules: CfModule[];
dependencies: Metafile["outputs"][string]["inputs"];
sourceMapPath: string | undefined;
sourceMapMetadata: SourceMapMetadata | undefined;
};
declare class ConfigController extends Controller {
#private;
latestInput?: WranglerStartDevWorkerInput;
latestWranglerConfig?: Config$1;
latestConfig?: StartDevWorkerOptions;
set(input: WranglerStartDevWorkerInput, throwErrors?: boolean): Promise<StartDevWorkerOptions | undefined>;
patch(input: Partial<WranglerStartDevWorkerInput>): Promise<StartDevWorkerOptions | undefined>;
onDevRegistryUpdate(event: DevRegistryUpdateEvent): void;
teardown(): Promise<void>;
emitConfigUpdateEvent(config: StartDevWorkerOptions): void;
}
type MiniflareWorker = Awaited<ReturnType<Miniflare["getWorker"]>>;
/**
* Extended StartDevWorkerInput with wrangler-specific fields that depend on miniflare types.
* The base StartDevWorkerInput in workers-utils is kept dependency-free.
*/
type WranglerStartDevWorkerInput = Omit<StartDevWorkerInput, "dev"> & {
dev?: StartDevWorkerInput["dev"] & {
/** Handles structured runtime logs. */
structuredLogsHandler?: (log: WorkerdStructuredLog) => void;
/** An undici MockAgent to declaratively mock fetch calls to particular resources. */
mockFetch?: undici.MockAgent;
};
};
interface Worker {
ready: Promise<void>;
url: Promise<URL>;
inspectorUrl: Promise<URL | undefined>;
config: StartDevWorkerOptions;
setConfig: ConfigController["set"];
patchConfig: ConfigController["patch"];
fetch: DispatchFetch;
scheduled: MiniflareWorker["scheduled"];
queue: MiniflareWorker["queue"];
dispose(): Promise<void>;
raw: DevEnv;
}
type StartDevWorkerOptions = Omit<StartDevWorkerInput, "assets" | "config" | "containers" | "dev"> & {
/** The configuration path of the worker */
config?: string;
/** A worker's directory. Usually where the Wrangler configuration file is located */
projectRoot: string;
build: StartDevWorkerInput["build"] & {
nodejsCompatMode: NodeJSCompatMode;
format: CfScriptFormat;
moduleRoot: string;
moduleRules: Rule$1[];
define: Record<string, string>;
additionalModules: CfModule[];
exports: string[];
processEntrypoint: boolean;
};
legacy: StartDevWorkerInput["legacy"] & {
site?: Config$1["site"];
};
dev: StartDevWorkerInput["dev"] & {
persist: string | false;
auth?: AsyncHook<CfAccount>;
/** Handles structured runtime logs. */
structuredLogsHandler?: (log: WorkerdStructuredLog) => void;
/** An undici MockAgent to declaratively mock fetch calls to particular resources. */
mockFetch?: undici.MockAgent;
};
entrypoint: string;
assets?: AssetsOptions$1;
containers?: ContainerNormalizedConfig[];
name: string;
complianceRegion: Config$1["compliance_region"];
};
type Bundle = EsbuildBundle;
type ErrorEvent = BaseErrorEvent<"ConfigController" | "BundlerController" | "LocalRuntimeController" | "RemoteRuntimeController" | "ProxyWorker" | "InspectorProxyWorker" | "MultiworkerRuntimeController"> | BaseErrorEvent<"ProxyController", {
config?: StartDevWorkerOptions;
bundle?: Bundle;
}> | BaseErrorEvent<"BundlerController", {
config?: StartDevWorkerOptions;
filePath?: string;
}>;
type BaseErrorEvent<Source = string, Data = undefined> = {
type: "error";
reason: string;
cause: Error | SerializedError;
source: Source;
data: Data;
};
type ConfigUpdateEvent = {
type: "configUpdate";
config: StartDevWorkerOptions;
};
type BundleStartEvent = {
type: "bundleStart";
config: StartDevWorkerOptions;
};
type BundleCompleteEvent = {
type: "bundleComplete";
config: StartDevWorkerOptions;
bundle: Bundle;
};
type ReloadStartEvent = {
type: "reloadStart";
config: StartDevWorkerOptions;
bundle: Bundle;
};
type ReloadCompleteEvent = {
type: "reloadComplete";
config: StartDevWorkerOptions;
bundle: Bundle;
proxyData: ProxyData;
};
type DevRegistryUpdateEvent = {
type: "devRegistryUpdate";
registry: WorkerRegistry;
};
type RuntimeErrorEvent = {
type: "runtimeError";
source: "LocalRuntimeController" | "ProxyController";
/** The exception summary line. */
text: string;
/** The source-mapped stack. */
stack: string;
/** The raw Chrome DevTools Protocol exception details, when the event
* came over the inspector. */
exceptionDetails?: Protocol$1.Runtime.ExceptionDetails;
};
type PreviewTokenExpiredEvent = {
type: "previewTokenExpired";
proxyData: ProxyData;
};
type ReadyEvent = {
type: "ready";
proxyWorker: Miniflare;
url: URL;
inspectorUrl: URL | undefined;
};
type ProxyWorkerIncomingRequestBody = {
type: "play";
proxyData: ProxyData;
} | {
type: "pause";
};
type ProxyWorkerOutgoingRequestBody = {
type: "error";
error: SerializedError;
} | {
type: "sseResponseDetected";
} | {
type: "previewTokenExpired";
proxyData: ProxyData;
} | {
type: "debug-log";
args: Parameters<typeof console.debug>;
};
type InspectorProxyWorkerIncomingWebSocketMessage = {
type: ReloadStartEvent["type"];
} | {
type: ReloadCompleteEvent["type"];
proxyData: ProxyData;
};
type InspectorProxyWorkerOutgoingWebsocketMessage = DevToolsEvent<"Runtime.consoleAPICalled"> | DevToolsEvent<"Runtime.exceptionThrown">;
type InspectorProxyWorkerOutgoingRequestBody = {
type: "error";
error: SerializedError;
} | {
type: "runtime-websocket-error";
error: SerializedError;
} | {
type: "debug-log";
args: Parameters<typeof console.debug>;
} | {
type: "load-network-resource";
url: string;
};
type SerializedError = {
message: string;
name?: string;
stack?: string | undefined;
cause?: unknown;
};
type UrlOriginParts = Pick<URL, "protocol" | "hostname" | "port">;
type UrlOriginAndPathnameParts = Pick<URL, "protocol" | "hostname" | "port" | "pathname">;
type ProxyData = {
userWorkerUrl: UrlOriginParts;
userWorkerInspectorUrl?: UrlOriginAndPathnameParts;
userWorkerInnerUrlOverrides?: Partial<UrlOriginParts>;
headers: Record<string, string>;
liveReload?: boolean;
proxyLogsToController?: boolean;
};
type ControllerEvent = ErrorEvent | ConfigUpdateEvent | BundleStartEvent | BundleCompleteEvent | ReloadStartEvent | ReloadCompleteEvent | DevRegistryUpdateEvent | RuntimeErrorEvent | PreviewTokenExpiredEvent;
interface ControllerBus {
dispatch(event: ControllerEvent): void;
}
declare abstract class Controller {
#private;
protected bus: ControllerBus;
constructor(bus: ControllerBus);
teardown(): Promise<void>;
/**
* Whether `teardown()` has been called, which subclasses should check before
* starting any new work.
*/
protected get tearingDown(): boolean;
protected emitErrorEvent(event: ErrorEvent): void;
}
declare abstract class RuntimeController extends Controller {
abstract onBundleStart(_: BundleStartEvent): void;
abstract onBundleComplete(_: BundleCompleteEvent): void;
abstract onPreviewTokenExpired(_: PreviewTokenExpiredEvent): void;
abstract get mf(): Miniflare | undefined;
protected emitReloadStartEvent(data: ReloadStartEvent): void;
protected emitReloadCompleteEvent(data: ReloadCompleteEvent): void;
protected emitDevRegistryUpdateEvent(data: DevRegistryUpdateEvent): void;
}
declare class BundlerController extends Controller {
#private;
onConfigUpdate(event: ConfigUpdateEvent): void;
teardown(): Promise<void>;
emitBundleStartEvent(config: StartDevWorkerOptions): void;
emitBundleCompleteEvent(config: StartDevWorkerOptions, bundle: EsbuildBundle): void;
}
type MaybePromise<T> = T | Promise<T>;
type DeferredPromise<T> = {
promise: Promise<T>;
resolve: (_: MaybePromise<T>) => void;
reject: (_: Error) => void;
};
declare class ProxyController extends Controller {
ready: DeferredPromise<ReadyEvent>;
localServerReady: DeferredPromise<void>;
proxyWorker?: Miniflare;
proxyWorkerOptions?: MiniflareOptions;
private inspectorProxyWorkerWebSocket?;
protected latestConfig?: StartDevWorkerOptions;
protected latestBundle?: EsbuildBundle;
secret: `${string}-${string}-${string}-${string}-${string}`;
protected createProxyWorker(): void;
private reconnectInspectorProxyWorker;
runtimeMessageMutex: Mutex;
sendMessageToProxyWorker(message: ProxyWorkerIncomingRequestBody, retries?: number): Promise<void>;
sendMessageToInspectorProxyWorker(message: InspectorProxyWorkerIncomingWebSocketMessage, retries?: number): Promise<void>;
get inspectorEnabled(): boolean;
onConfigUpdate(data: ConfigUpdateEvent): void;
onBundleStart(data: BundleStartEvent): void;
onReloadStart(data: ReloadStartEvent): void;
onReloadComplete(data: ReloadCompleteEvent): void;
onProxyWorkerMessage(message: ProxyWorkerOutgoingRequestBody): void;
onInspectorProxyWorkerMessage(message: InspectorProxyWorkerOutgoingWebsocketMessage): void;
onInspectorProxyWorkerRequest(message: InspectorProxyWorkerOutgoingRequestBody): Promise<Response$1>;
_torndown: boolean;
teardown(): Promise<void>;
emitReadyEvent(proxyWorker: Miniflare, url: URL, inspectorUrl: URL | undefined): void;
emitPreviewTokenExpiredEvent(proxyData: ProxyData): void;
emitErrorEvent(data: ErrorEvent): void;
emitErrorEvent(reason: string, cause?: Error | SerializedError): void;
}
type ControllerFactory<C extends Controller> = (devEnv: DevEnv) => C;
declare class DevEnv extends EventEmitter implements ControllerBus {
config: ConfigController;
bundler: BundlerController;
runtimes: RuntimeController[];
proxy: ProxyController;
startWorker(options: WranglerStartDevWorkerInput): Promise<Worker>;
constructor({ configFactory, bundlerFactory, runtimeFactories, proxyFactory, }?: {
configFactory?: ControllerFactory<ConfigController>;
bundlerFactory?: ControllerFactory<BundlerController>;
runtimeFactories?: ControllerFactory<RuntimeController>[];
proxyFactory?: ControllerFactory<ProxyController>;
});
/**
* Central message bus dispatch method.
* All events from controllers flow through here, making the event routing explicit and traceable.
*
* Event flow:
* - ConfigController emits configUpdate → BundlerController, ProxyController
* - BundlerController emits bundleStart → ProxyController, RuntimeControllers
* - BundlerController emits bundleComplete → RuntimeControllers
* - RuntimeController emits reloadStart → ProxyController
* - RuntimeController emits reloadComplete → ProxyController
* - RuntimeController emits devRegistryUpdate → ConfigController
* - ProxyController emits previewTokenExpired → RuntimeControllers
* - Any controller emits error → DevEnv error handler
*
* `reloadComplete` is also re-emitted as an external EventEmitter event
* (`devEnv.on("reloadComplete", ...)`) so callers like
* `RemoteProxySession.updateBindings` can wait for the reload to finish.
*/
dispatch(event: ControllerEvent): void;
private handleErrorEvent;
teardown(): Promise<void>;
}
declare function startWorker(options: WranglerStartDevWorkerInput): Promise<Worker>;
declare const dev: {
args: {
v: boolean | undefined;
cwd: string | undefined;
config: string | undefined;
env: string | undefined;
envFile: string[] | undefined;
experimentalProvision: boolean | undefined;
experimentalAutoCreate: boolean;
installSkills: boolean;
profile: string | undefined;
script: string | undefined;
name: string | undefined;
compatibilityDate: string | undefined;
compatibilityFlags: string[] | undefined;
latest: boolean;
assets: string | undefined;
bundle: boolean | undefined;
noBundle: boolean;
ip: string | undefined;
port: number | undefined;
inspectorPort: number | undefined;
inspectorIp: string | undefined;
routes: string[] | undefined;
host: string | undefined;
localProtocol: "http" | "https" | undefined;
httpsKeyPath: string | undefined;
httpsCertPath: string | undefined;
localUpstream: string | undefined;
enableContainers: boolean | undefined;
site: string | undefined;
siteInclude: string[] | undefined;
siteExclude: string[] | undefined;
upstreamProtocol: "http" | "https" | undefined;
var: string[] | undefined;
define: string[] | undefined;
alias: string[] | undefined;
jsxFactory: string | undefined;
jsxFragment: string | undefined;
tsconfig: string | undefined;
remote: boolean;
local: boolean | undefined;
minify: boolean | undefined;
nodeCompat: boolean | undefined;
persistTo: string | undefined;
liveReload: boolean | undefined;
testScheduled: boolean;
logLevel: "debug" | "none" | "error" | "log" | "info" | "warn" | undefined;
showInteractiveDevSession: boolean | undefined;
types: boolean | undefined;
tunnel: boolean | undefined;
tunnelName: string | undefined;
experimentalNewConfig: boolean;
_: (string | number)[];
$0: string;
};
};
type AdditionalDevProps = {
/**
* Default vars that can be overridden by config vars.
* Useful for injecting environment-specific defaults like CF_PAGES variables.
*/
defaultBindings?: Record<string, Extract<Binding, {
type: "plain_text";
}>>;
vars?: Record<string, string | Json$1>;
kv?: {
binding: string;
id?: string;
preview_id?: string;
}[];
durableObjects?: {
name: string;
class_name: string;
script_name?: string | undefined;
environment?: string | undefined;
}[];
services?: {
binding: string;
service: string;
environment?: string;
entrypoint?: string;
}[];
r2?: {
binding: string;
bucket_name?: string;
preview_bucket_name?: string;
jurisdiction?: string;
}[];
ai?: {
binding: string;
};
stream?: {
binding: string;
remote?: boolean;
};
version_metadata?: {
binding: string;
};
d1Databases?: Array<Omit<Environment$1["d1_databases"][number], "database_id"> & {
database_id?: string;
}>;
processEntrypoint?: boolean;
additionalModules?: CfModule[];
moduleRoot?: string;
rules?: Rule$1[];
showInteractiveDevSession?: boolean;
showLocalExplorerAgentHint?: boolean;
};
type DevArguments = Omit<(typeof dev)["args"], "installSkills" | "profile">;
type StartDevOptions = DevArguments & AdditionalDevProps & {
forceLocal?: boolean;
accountId?: string;
disableDevRegistry?: boolean;
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
onReady?: (ip: string, port: number) => void;
enableIpc?: boolean;
dockerPath?: string;
containerEngine?: string;
/** Set to `false` to disable persistence. When `true` or `undefined`, uses default persistence path. */
persist?: boolean;
};
declare function convertConfigBindingsToStartWorkerBindings(configBindings: Partial<Pick<Config$1, ConfigBindingFieldName>>): StartDevWorkerOptions["bindings"];
type WorkflowStepSelector = {
name: string;
index?: number;
};
type WorkflowInstanceModifier = {
disableSleeps(steps?: WorkflowStepSelector[]): Promise<void>;
disableRetryDelays(steps?: WorkflowStepSelector[]): Promise<void>;
mockStepResult(step: WorkflowStepSelector, stepResult: unknown): Promise<void>;
mockStepError(step: WorkflowStepSelector, error: Error, times?: number): Promise<void>;
forceStepTimeout(step: WorkflowStepSelector, times?: number): Promise<void>;
mockEvent(event: {
type: string;
payload: unknown;
}): Promise<void>;
forceEventTimeout(step: WorkflowStepSelector): Promise<void>;
};
type ModifierCallback = (modifier: WorkflowInstanceModifier) => Promise<void>;
interface WorkflowInstanceIntrospector {
modify(fn: ModifierCallback): Promise<WorkflowInstanceIntrospector>;
waitForStepResult(step: WorkflowStepSelector): Promise<unknown>;
waitForStatus(status: string): Promise<void>;
getOutput(): Promise<unknown>;
getError(): Promise<{
name: string;
message: string;
}>;
dispose(): Promise<void>;
[Symbol.asyncDispose](): Promise<void>;
}
interface WorkflowIntrospector {
modifyAll(fn: ModifierCallback): Promise<void>;
get(): Promise<WorkflowInstanceIntrospector[]>;
dispose(): Promise<void>;
[Symbol.asyncDispose](): Promise<void>;
}
type TestHarnessOptions = {
/**
* Base directory used to resolve relative worker config paths.
* Defaults to `process.cwd()`.
*/
root?: string | undefined;
/**
* Workers to run in this server. The first worker is the primary worker.
*/
workers: WorkerInput[];
};
type ExportName<Module, Type> = string extends keyof Module ? string : Extract<{
[K in keyof Module]-?: NonNullable<Module[K]> extends Type | (abstract new (...args: any[]) => Type) ? K : never;
}[keyof Module], string>;
type BindingName<Env, Type> = string extends keyof Env ? string : Extract<{
[K in keyof Env]-?: NonNullable<Env[K]> extends Type ? K : never;
}[keyof Env], string>;
type DurableObjectIdentifier = {
name: string;
id?: never;
} | {
id: string;
name?: never;
};
type FetcherEmailOptions = {
from: string;
to: string;
raw: string | ReadableStream<Uint8Array>;
};
type FetcherEmailResult = {
outcome: "ok" | "exception";
rejectReason?: string;
forwards: Array<{
messageId: string;
recipient: string;
headers: [string, string][];
}>;
replies: Array<{
messageId: string;
sender: string;
raw: string;
}>;
events: Array<{
type: "forward" | "reply";
timestamp: string;
messageId: string;
} | {
type: "reject";
timestamp: string;
}>;
};
type WorkerDefaultExport = (new (...args: any[]) => Rpc.WorkerEntrypointBranded) | Rpc.WorkerEntrypointBranded | AnyExportedHandler;
type WorkerModule = {
default: WorkerDefaultExport;
};
type AnyExportedHandler = ExportedHandler<any, any, any, any>;
type AnyEnv = Record<string, any>;
type WorkerHandle<Env = AnyEnv, Module extends WorkerModule = {
default: AnyExportedHandler;
}> = {
/**
* Dispatches a fetch event directly to this worker.
* Relative URL inputs are resolved against the URL returned by `listen()`.
*
* @example
* ```ts
* const response = await worker.fetch("/", {
* method: "POST",
* body: "Hello, world!"
* });
* ```
*/
fetch: DispatchFetch;
/**
* Dispatches an email event directly to this Worker.
*
* @example
* ```ts
* const result = await worker.email({
* from: "sender@example.com",
* to: "recipient@example.com",
* raw: "From: sender@example.com\\r\\n...",
* });
* ```
*/
email(options: FetcherEmailOptions): Promise<FetcherEmailResult>;
/**
* Dispatches a scheduled event directly to this Worker.
*
* @example
* ```ts
* const result = await worker.scheduled({
* cron: "0 * * * *",
* scheduledTime: new Date(),
* });
* ```
*/
scheduled(options: FetcherScheduledOptions): Promise<FetcherScheduledResult>;
/**
* Returns the full environment object configured on this Worker, including
* vars, secrets, and bindings.
*
* @example
* ```ts
* type Env = { GREETING: string; STORE: KVNamespace };
* const worker = server.getWorker<Env>();
* const env = await worker.getEnv();
* await env.STORE.put("key", env.GREETING);
* ```
*/
getEnv(): Promise<Env>;
/**
* Lists the string IDs of Durable Object instances with persisted storage.
* Pass an exported Durable Object class name, or a Durable Object binding name.
*/
listDurableObjectIds(classNameOrBindingName: ExportName<Module, Rpc.DurableObjectBranded> | BindingName<Env, DurableObjectNamespace>): Promise<string[]>;
/**
* Evicts a currently running Durable Object instance while preserving its durable storage.
* In-memory state is reset the next time the object starts.
* Pass an exported Durable Object class name, or a Durable Object binding name.
* Class names are resolved before binding names.
*
* @example
* ```ts
* await worker.evictDurableObject("Counter", {
* name: "user-123",
* webSockets: "hibernate",
* });
* ```
*/
evictDurableObject(classNameOrBindingName: ExportName<Module, Rpc.DurableObjectBranded> | BindingName<Env, DurableObjectNamespace>, options: DurableObjectIdentifier & {
webSockets?: "close" | "hibernate";
}): Promise<void>;
/**
* Applies D1 migration files that have not already run to a D1 binding on this Worker.
*
* @example
* ```ts
* beforeEach(async () => {
* await worker.applyD1Migrations("DATABASE");
* });
* ```
*/
applyD1Migrations(bindingName: BindingName<Env, D1Database>): Promise<void>;
/**
* Returns remote storage access for a Durable Object instance.
* Pass an exported Durable Object class name, or a Durable Object binding name.
* Class names are resolved before binding names.
*
* Use this to seed state before sending requests to the object, or to inspect
* state after awaited requests. Calling `exec()` runs SQL inside the target
* Durable Object and returns all rows. It may start the object if it is not
* already active.
*
* @example
* ```ts
* const sql = await worker.getDurableObjectStorage("COUNTER", {
* name: "user-123"
* });
* const rows = await sql.exec("SELECT count FROM counters WHERE id = ?", "user-123");
* ```
*/
getDurableObjectStorage(classNameOrBindingName: ExportName<Module, Rpc.DurableObjectBranded> | BindingName<Env, DurableObjectNamespace>, options: DurableObjectStorageOptions): Promise<DurableObjectStorageHandle>;
/**
* Creates an introspector for a specific Workflow instance.
*/
introspectWorkflowInstance(bindingName: BindingName<Env, Workflow>, instanceId: string): Promise<WorkflowInstanceIntrospector>;
/**
* Creates an introspector for Workflow instances created after this method is called.
*/
introspectWorkflow(bindingName: BindingName<Env, Workflow>): Promise<WorkflowIntrospector>;
/**
* Returns the default Worker export, including JSRPC methods.
*
* @example
* ```ts
* type ApiWorkerModule = typeof import("../src/api-worker");
*
* const worker = server.getWorker<Cloudflare.Env, ApiWorkerModule>("api-worker");
* const api = await worker.getExport();
* api.getMessage();
* ```
*/
getExport(): Promise<Service<Module["default"]>>;
};
type TestHarness = {
/**
* Starts the server and returns its current URL.
* Calling this more than once returns the same running server session until
* the server is closed or reset.
*
* If no options were passed to `createTestHarness()`, call `update(options)`
* before starting the server.
*/
listen(): Promise<{
url: URL;
}>;
/**
* Dispatches a fetch request through the server.
*
* - Relative URLs are resolved against the current server URL. Absolute URLs
* are also accepted, and can be used to control the hostname seen by the Worker.
* - Requests are matched against each Worker's configured routes and dispatched to
* the first matching Worker, or to the primary Worker if no routes match.
* - To dispatch directly to a specific Worker, use `server.getWorker(name).fetch()`.
*
* @example
* ```ts
* const server = createTestHarness({
* workers: [
* { configPath: "./wrangler.dashboard.jsonc" }, // No route pattern
* { configPath: "./wrangler.api.jsonc" }, // Route pattern: "example.com/api/*"
* { configPath: "./wrangler.admin.jsonc" }, // Route pattern: "admin.example.com/*"
* ]
* });
*
* await server.fetch("/users");
* // Dispatches a request to the dashboard Worker (the first Worker) with URL "http://localhost:{port}/users"
*
* await server.fetch("http://admin.example.com/accounts");
* // Dispatches a request to the admin Worker with URL "http://admin.example.com/accounts"
*
* await server.fetch("http://example.com/api/data");
* // Dispatches a request to the API Worker with URL "http://example.com/api/data"
* ```
*/
fetch: DispatchFetch;
/**
* Returns a handle for dispatching events directly to a Worker.
* When no name is provided, this returns the primary Worker, which is the first
* Worker in the server's `workers` options.
*/
getWorker<Env = AnyEnv, Module extends WorkerModule = {
default: AnyExportedHandler;
}>(name?: string): WorkerHandle<Env, Module>;
/**
* Returns captured Workers runtime logs since the current server session
* started or `clearLogs()` was last called.
*/
getLogs(): WorkerdStructuredLog[];
/**
* Clears captured Workers runtime logs.
*/
clearLogs(): void;
/**
* Prints a diagnostic timeline for this test server.
*
* Use this to trace the sequence of server events and Workers runtime logs
* leading up to a test failure. Call `server.debug()` from your test runner's
* failure or cleanup hook when the current test has failed.
*/
debug(): void;
/**
* Updates the server configuration and reloads the running Workers.
*
* If the server has not started yet, this configures the options that will be
* used by `listen()`.
*/
update(options: TestHarnessOptions | ((currentOptions: TestHarnessOptions) => TestHarnessOptions)): Promise<void>;
/**
* Restores the server to the options used when the current session first
* started. Storage is recreated, and the server URL may change after reset.
*/
reset(): Promise<void>;
/**
* Stops the server and releases all runtime resources.
*/
close(): Promise<void>;
};
type InlineConfig = Omit<RawConfig$1, "env">;
type WorkerInput = {
/**
* Path to a Wrangler config file for this Worker.
* Relative paths resolve from server `root`.
*/
configPath: string | URL;
/**
* Wrangler environment to load from the config file.
*/
env?: string;
/**
* Test-only vars that override vars from the Wrangler config.
*/
vars?: Record<string, Json$1>;
/**
* Test-only secrets that override values loaded from `.dev.vars` and `.env` files.
*/
secrets?: Record<string, string>;
/**
* Test-only service binding overrides. Keys are binding names in this
* Worker's environment, and values are Worker names in this test harness.
*/
bindingOverrides?: Record<string, string>;
} | {
/**
* Inline Wrangler config for this Worker.
*/
config: InlineConfig;
};
/**
* Creates a local test server for running Workers.
*
* The server can run one or more Workers from Wrangler config files, including
* generated configs from Vite, or from inline configuration objects.
*
* @example
* ```ts
* const server = createTestHarness({
* workers: [{ configPath: "./wrangler.jsonc" }],
* });
* await server.listen();
* const response = await server.fetch("/api/users");
* await server.close();
* ```
*/
declare function createTestHarness(options?: TestHarnessOptions): TestHarness;
type ReadConfigCommandArgs = NormalizeAndValidateConfigArgs & {
config?: string;
script?: string;
};
type ReadConfigOptions = ResolveConfigPathOptions & {
hideWarnings?: boolean;
preserveOriginalMain?: boolean;
};
/**
* Get the Wrangler configuration; read it from the give `configPath` if available.
*/
declare function readConfig(args: ReadConfigCommandArgs, options?: ReadConfigOptions): Config$1;
/**
* Infer Durable Object class names and storage backends from migrations and
* live declarative `exports` entries.
*
* In practice only one of `migrations` or `exports` will have the Durable Object configuration.
*/
declare function getDurableObjectClassNameToUseSQLiteMap(migrations: Config$1["migrations"] | undefined, exports?: Config$1["exports"] | undefined): Map<string, boolean>;
/**
* Note about this file:
*
* Here we are providing a no-op implementation of the runtime Cache API instead of using
* the miniflare implementation (via `mf.getCaches()`).
*
* We are not using miniflare's implementation because that would require the user to provide
* miniflare-specific Request objects and they would receive back miniflare-specific Response
* objects, this (in particular the Request part) is not really suitable for `getPlatformProxy`
* as people would ideally interact with their bindings in a very production-like manner and
* requiring them to deal with miniflare-specific classes defeats a bit the purpose of the utility.
*
* Similarly the Request and Response types here are set to `undefined` as not to use specific ones
* that would require us to make a choice right now or the user to adapt their code in order to work
* with the api.
*
* We need to find a better/generic manner in which we can reuse the miniflare cache implementation,
* but until then the no-op implementation below will have to do.
*/
/**
* No-op implementation of CacheStorage
*/
declare class CacheStorage {
constructor();
open(_cacheName: string): Promise<Cache>;
get default(): Cache;
}
type CacheRequest = any;
type CacheResponse = any;
/**
* No-op implementation of Cache
*/
declare class Cache {
delete(_request: CacheRequest, _options?: CacheQueryOptions): Promise<boolean>;
match(_request: CacheRequest, _options?: CacheQueryOptions): Promise<CacheResponse | undefined>;
put(_request: CacheRequest, _response: CacheResponse): Promise<void>;
}
type CacheQueryOptions = {
ignoreMethod?: boolean;
};
declare class ExecutionContext {
waitUntil(promise: Promise<any>): void;
passThroughOnException(): void;
props: any;
}
type Json = string | number | boolean | null | Json[] | {
[id: string]: Json;
};
type AssetsOptions = {
directory: string;
binding?: string;
routerConfig: RouterConfig;
assetConfig: AssetConfig;
_redirects?: string;
_headers?: string;
run_worker_first?: boolean | string[];
};
/**
* Wrangler configuration types. The JSDoc on these fields is also the source
* of truth for the equivalent fields in `@cloudflare/config`
* (`packages/config/src/types.ts` — `WorkerConfig` — and the binding option
* interfaces in `packages/config/src/config.ts`). When editing prose here,
* mirror the changes there.
*/
/**
* The `Environment` interface declares all the configuration fields that
* can be specified for an environment.
*
* This could be the top-level default environment, or a specific named environment.
*/
interface Environment extends EnvironmentInheritable, EnvironmentNonInheritable {
}
type SimpleRoute = string;
/** AWS SigV4 credentials for miniflare's local S3-compatible endpoint */
interface LocalS3Credentials {
accessKeyId: string;
secretAccessKey: string;
}
type ZoneIdRoute = {
pattern: string;
zone_id: string;
custom_domain?: boolean;
};
type ZoneNameRoute = {
pattern: string;
zone_name: string;
custom_domain?: boolean;
};
type CustomDomainRoute = {
pattern: string;
custom_domain: boolean;
enabled?: boolean;
previews_enabled?: boolean;
};
type Route = SimpleRoute | ZoneIdRoute | ZoneNameRoute | CustomDomainRoute;
/**
* Configuration in wrangler for Cloudchamber
*/
type CloudchamberConfig = {
image?: string;
location?: string;
instance_type?: "dev" | "basic" | "standard" | "lite" | "standard-1" | "standard-2" | "standard-3" | "standard-4";
vcpu?: number;
memory?: string;
ipv4?: boolean;
};
type UnsafeBinding = {
/**
* The name of the binding provided to the Worker
*/
name: string;
/**
* The 'type' of the unsafe binding.
*/
type: string;
dev?: {
plugin: {
/**
* Package is the bare specifier of the package that exposes plugins to integrate into Miniflare via a named `plugins` export.
* @example "@cloudflare/my-external-miniflare-plugin"
*/
package: string;
/**
* Plugin is the name of the plugin exposed by the package.
* @example "MY_UNSAFE_PLUGIN"
*/
name: string;
};
/**
* Optional mapping of unsafe bindings names to options provided for the plugin.
*/
options?: Record<string, unknown>;
};
[key: string]: unknown;
};
/**
* Configuration for a container application
*/
type ContainerApp = {
/**
* Name of the application
* @optional Defaults to `worker_name-class_name` if not specified.
*/
name?: string;
/**
* Number of application instances
* @deprecated
* @hidden
*/
instances?: number;
/**
* Number of maximum application instances.
* @optional
*/
max_instances?: number;
/**
* The path to a Dockerfile, or an image URI for the Cloudflare registry.
*/
image: string;
/**
* Build context of the application.
* @optional - defaults to the directory of `image`.
*/
image_build_context?: string;
/**
* Image variables available to the image at build-time only.
* For runtime env vars, refer to https://developers.cloudflare.com/containers/examples/env-vars-and-secrets/
* @optional
*/
image_vars?: Record<string, string>;
/**
* The class name of the Durable Object the container is connected to.
*/
class_name: string;
/**
* The scheduling policy of the application
* @optional
* @default "default"
*/
scheduling_policy?: "default" | "moon" | "regional";
/**
* The instance type to be used for the container.
* Select from one of the following named instance types:
* - lite: 1/16 vCPU, 256 MiB memory, and 2 GB disk
* - basic: 1/4 vCPU, 1 GiB memory, and 4 GB disk
* - standard-1: 1/2 vCPU, 4 GiB memory, and 8 GB disk
* - standard-2: 1 vCPU, 6 GiB memory, and 12 GB disk
* - standard-3: 2 vCPU, 8 GiB memory, and 16 GB disk
* - standard-4: 4 vCPU, 12 GiB memory, and 20 GB disk
* - dev: 1/16 vCPU, 256 MiB memory, and 2 GB disk (deprecated, use "lite" instead)
* - standard: 1 vCPU, 4 GiB memory, and 4 GB disk (deprecated, use "standard-1" instead)
*
* Customers on an enterprise plan have the additional option to set custom limits.
*
* @optional
* @default "dev"
*/
instance_type?: "dev" | "basic" | "standard" | "lite" | "standard-1" | "standard-2" | "standard-3" | "standard-4" | {
/** @defaults to 0.0625 (1/16 vCPU) */
vcpu?: number;
/** @defaults to 256 MiB */
memory_mib?: number;
/** @defaults to 2 GB */
disk_mb?: number;
};
ssh?: {
/**
* If enabled, those with write access to a container will be able to SSH into it through Wrangler.
* @default false
*/
enabled: boolean;
/**
* Port that the SSH service is running on
* @defaults to 22
*/
port?: number;
};
/**
* @deprecated Use `ssh` instead.
* @hidden
*/
wrangler_ssh?: {
enabled: boolean;
port?: number;
};
/**
* SSH public keys to put in the container's authorized_keys file.
*/
authorized_keys?: {
name: string;
public_key: string;
}[];
/**
* Trusted user CA keys to put in the container's trusted_user_ca_keys file.
*/
trusted_user_ca_keys?: {
name?: string;
public_key: string;
}[];
/**
* @deprecated Use top level `containers` fields instead.
* `configuration.image` should be `image`
* limits should be set via `instance_type`
* @hidden
*/
configuration?: {
image?: string;
labels?: {
name: string;
value: string;
}[];
secrets?: {
name: string;
type: "env";
secret: string;
}[];
disk?: {
size_mb: number;
};
vcpu?: number;
memory_mib?: number;
};
/**
* Scheduling constraints for container placement.
*/
constraints?: {
/**
* Limit container placement to specific geographic regions.
*/
regions?: ("ENAM" | "WNAM" | "EEUR" | "WEUR" | "APAC" | "SAM" | "ME" | "OC" | "AFR")[];
/**
* Restrict containers to compliance boundaries.
*/
jurisdiction?: "eu" | "fedramp";
/**
* @hidden
*/
cities?: string[];
/**
* @deprecated Use `tiers` instead
* @hidden
*/
tier?: number;
/**
* @hidden
*/
tiers?: number[];
};
/**
* Scheduling affinities
* @hidden
*/
affinities?: {
colocation?: "datacenter";
hardware_generation?: "highest-overall-performance";
};
/**
* @deprecated use the `class_name` field instead.
* @hidden
*/
durable_objects?: {
namespace_id: string;
};
/**
* Configures what percentage of instances should be