import * as durableObjectsApi from "@distilled.cloud/cloudflare/durable-objects";
import * as Config from "effect/Config";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Path from "effect/Path";
import * as Artifacts from "../../Artifacts.ts";
import * as Provider from "../../Provider.ts";
import { Stack } from "../../Stack.ts";
import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
import { type Reference as ZoneReference } from "../Zone/lookup.ts";
import { Worker, type WorkerProps, type WorkerVersionAffinity } from "./Worker.ts";
declare const DurableObjectTransferRequired_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
readonly _tag: "DurableObjectTransferRequired";
} & Readonly;
/**
* A Durable Object class is being dropped from this Worker while a binding in
* the same deploy still references it on another script — the class moved
* cross-script, but its namespace (and every stored object in it) still lives
* on this Worker. Cloudflare rejects a single upload that both deletes the
* class and ships a binding referencing it, and silently deleting would
* destroy the namespace's data irreversibly, so the deploy fails before any
* upload.
*
* Moving a Durable Object class between Workers is always declared: set
* `transferredFrom` on the Durable Object at its **new host** — naming the
* former host by Worker logical id (same stack) or physical script name — and
* Alchemy performs the data-preserving `transferred_classes` migration on the
* new host's deploy; this deploy then converges on its own. To abandon the
* data instead, remove the binding entirely in one deploy (which deletes the
* class and its data), then add the cross-script binding in a second deploy.
*/
export declare class DurableObjectTransferRequired extends DurableObjectTransferRequired_base<{
scriptName: string;
className: string;
targetScriptName: string | undefined;
}> {
get message(): string;
}
declare const AmbiguousDurableObjectTransfer_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
readonly _tag: "AmbiguousDurableObjectTransfer";
} & Readonly;
/**
* More than one script matches the `transferredFrom` declaration of a Durable
* Object (e.g. an orphaned script left behind by a `name` prop change still
* carries the same alchemy tags, or the host history lists several scripts
* that each still hold a same-class namespace). Alchemy refuses to guess
* which namespace's data to move — narrow the declaration to the exact
* physical script name that holds the data.
*/
export declare class AmbiguousDurableObjectTransfer extends AmbiguousDurableObjectTransfer_base<{
scriptName: string;
logicalId: string;
className: string;
sources: string[];
}> {
get message(): string;
}
/**
* Resolve the Workers for Platforms dispatch-namespace *name* from a resolved
* `namespace` prop or persisted attribute. The engine resolves a passed
* {@link DispatchNamespace} resource to its Attributes object (see
* `Input.Resolve` / Plan.ts), so the value is either the namespace name
* string, that attributes object, or `undefined` for a regular Worker.
*
* @internal
*/
export declare const resolveNamespaceName: (namespace: unknown) => string | undefined;
/**
* Resolve a Worker's `tailConsumers` / `streamingTailConsumers` prop into
* the wire-shape consumer list
* (`[{ service }]`). The engine resolves a passed {@link Worker} to its
* Attributes object — possibly stables-only during planning, but
* `workerName` is always a stable — so each entry is either a script-name
* string or that attributes object. Whole-resource entries are reduced to
* the script name alone so hashing/diffing never sees the consumer's
* per-deploy fields (`hash`, `url`, ...), mirroring
* {@link resolveVersionParentName}.
*
* An empty array resolves to `[]` (explicitly detach every consumer);
* `undefined`/absent resolves to `undefined`.
*
* This is also the seam for local emulation: the local provider lowers this
* same resolved list into workerd's `Worker.tails` / `Worker.streamingTails`
* service designators (`RuntimeWorker.tails` / `RuntimeWorker.streamingTails`).
*
* @internal
*/
export declare const resolveTailConsumers: (tailConsumers: WorkerProps["tailConsumers" | "streamingTailConsumers"]) => {
service: string;
}[] | undefined;
declare const WorkerVersionConfigError_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
readonly _tag: "WorkerVersionConfigError";
} & Readonly;
/**
* A Worker's `version` configuration is invalid — a prop that can't be
* combined with `version.parent` (script-level settings belong to the
* parent), a locally-hosted Durable Object / Workflow class on a version
* worker, an out-of-range `traffic`, or a gradual rollout that requires
* changes the versions API can't carry (assets, DO migrations).
*/
export declare class WorkerVersionConfigError extends WorkerVersionConfigError_base<{
message: string;
}> {
}
/**
* Resolve the parent script *name* from a resolved `version.parent` prop or
* persisted props. The engine resolves a passed {@link Worker} (or
* `Worker.ref(...)`) to its Attributes object — possibly stables-only during
* planning, but `workerName` is always a stable — so the value is either the
* script name string, that attributes object, or `undefined`.
*
* @internal
*/
export declare const resolveVersionParentName: (version: WorkerProps["version"]) => string | undefined;
/**
* `version.affinity` normalized to a single key source plus the optional
* IP fallback.
*
* @internal exported for unit testing.
*/
export interface ResolvedVersionAffinity {
source: {
kind: "cookie" | "header";
name: string;
} | {
kind: "ip";
} | {
kind: "key";
expression: string;
};
ipFallback: boolean;
}
/**
* Validate `version.affinity` and normalize it to its key source: exactly
* one of `cookie` / `header` / `key`, or `ip: true` alone; `ip` combines
* with `cookie` / `header` as the absent-source fallback.
*
* @internal exported for unit testing.
*/
export declare const resolveVersionAffinity: (affinity: WorkerVersionAffinity) => Effect.Effect;
/** A hostname a Worker serves on within one zone. */
interface AffinityZoneHost {
host: string;
/** `true` when `host` came from a route pattern containing `*`. */
wildcard: boolean;
}
/**
* The `http.host` clause scoping a zone's affinity rules to the Worker's
* own hostnames, so unrelated zone traffic — and other Workers' rollouts
* on the same zone — never get this Worker's version key.
*
* @internal exported for unit testing.
*/
export declare const affinityHostExpression: (hosts: readonly AffinityZoneHost[]) => string;
interface AffinityRuleSpec {
description: string;
expression: string;
/** Rules-language expression producing the header value. */
value: string;
}
/**
* The transform rules pinning one zone's traffic: a primary rule filling
* the version-key header from the configured source, plus — for
* `cookie`/`header` sources with `ip: true` — a fallback rule keying
* requests that lack the source by client IP.
*
* @internal exported for unit testing.
*/
export declare const buildAffinityZoneRules: (scriptName: string, affinity: ResolvedVersionAffinity, hosts: readonly AffinityZoneHost[]) => AffinityRuleSpec[];
declare const WorkerDomainConfigError_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
readonly _tag: "WorkerDomainConfigError";
} & Readonly;
/**
* A Worker's `domain` configuration is invalid — a hostname appears in more
* than one role (name/aliases/redirects), or a redirect targets itself.
*/
export declare class WorkerDomainConfigError extends WorkerDomainConfigError_base<{
message: string;
}> {
}
/**
* The resolved shape of `WorkerProps.workersDev`: `enabled` drives the
* stable `..workers.dev` URL, `previewsEnabled` the
* per-version preview URLs. The two toggles are independent on the
* Cloudflare API.
*
* @internal exported for unit testing.
*/
export interface ResolvedWorkersDev {
enabled: boolean;
previewsEnabled: boolean;
}
/**
* Resolve the `workersDev` prop to its full shape. `true` / omitted means
* "default workers.dev behavior" (stable URL + version previews), `false`
* disables both, and the object form fills unset toggles with `true`.
*
* @internal exported for unit testing.
*/
export declare const resolveWorkersDev: (workersDev: WorkerProps["workersDev"]) => ResolvedWorkersDev;
/**
* The resolved shape of `WorkerProps.domain`: the canonical hostname plus
* alias and redirect hostname lists, all punycode-normalized and
* de-duplicated.
*
* @internal exported for unit testing.
*/
export interface ResolvedWorkerDomain {
name: string;
aliases: string[];
redirects: string[];
/** Pinned zone from props, when the caller set zoneId / zone / zoneName. */
zone?: ZoneReference;
}
/** Collapse Worker.domain zone pin fields to one {@link ZoneReference}. */
export declare const resolveWorkerDomainZone: (config: {
readonly zoneId?: unknown;
readonly zoneName?: unknown;
readonly zone?: unknown;
} | undefined) => ZoneReference | undefined;
/** Whether an existing attachment must move to satisfy an explicit zone pin. */
export declare const shouldRecreateWorkerDomainAttachment: (liveZoneId: string, desiredZoneId: string | undefined) => boolean;
/**
* Resolve the `domain` prop to its full shape — a bare string is shorthand
* for `{ name }`. Hostnames are punycode-normalized and de-duplicated;
* a hostname may only play one role, so aliases/redirects that repeat the
* canonical name (or each other) fail with a typed error.
*
* @internal exported for unit testing.
*/
export declare const resolveWorkerDomain: (domain: WorkerProps["domain"] | string[]) => Effect.Effect;
/**
* The *custom domain* hostnames recorded in a Worker's persisted legacy
* `domains` state — minus the workers.dev (stable or preview) and local-dev
* entries that shared the list in older formats.
*
* @internal exported for unit testing.
*/
export declare const stateCustomDomains: (domains: readonly unknown[] | undefined) => string[];
/**
* The Worker's persisted domain configuration: the `domain` attribute for
* state written by the current format, else re-derived from the legacy
* `domains` list (first custom hostname = canonical name, rest = aliases;
* legacy state had no redirects).
*
* @internal exported for unit testing.
*/
export declare const stateWorkerDomain: (output: object | undefined) => ResolvedWorkerDomain | undefined;
declare const WorkerIdNotFound_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
readonly _tag: "WorkerIdNotFound";
} & Readonly;
export declare class WorkerIdNotFound extends WorkerIdNotFound_base<{
scriptName: string;
message: string;
}> {
}
/**
* Normalize a Worker's persisted *legacy* `domains` state to bare
* hostnames. Alchemy <= beta.44 stored each custom domain as a
* `{ id, hostname, zoneId }` object; beta.45+ stored `https://`
* URL strings (with the workers.dev URL mixed in); current state stores the
* `domain` config object instead of a `domains` list. All legacy
* generations coerce to hostnames so the diff never throws on older state
* (#546). Entries that fit no generation are dropped rather than turned
* into a bogus hostname that would skew the diff.
*
* @internal exported for unit testing.
*/
export declare const normalizeStateDomains: (domains: readonly unknown[] | undefined) => string[];
/**
* Custom domains Alchemy is responsible for on this Worker — either declared
* on props (`domain`) or already persisted as non-`workers.dev` URLs in state.
* Used by `read` to skip `listDomains` when the surface is unmanaged (#926).
*
* @internal exported for unit testing.
*/
export declare const shouldObserveWorkerDomains: (olds: Pick | undefined, output: object | undefined) => boolean;
/**
* Zone routes Alchemy is responsible for on this Worker. Used by `read` to
* skip account-wide zone/route fan-out when the surface is unmanaged (#926).
*
* @internal exported for unit testing.
*/
export declare const shouldObserveWorkerRoutes: (olds: Pick | undefined, output: Pick | undefined) => boolean;
/**
* Cron triggers Alchemy is responsible for on this Worker. Used by `read` to
* skip `getScriptSchedule` when the surface is unmanaged (#926). Effect-native
* `cron()` bindings persist into `output.crons` after the first reconcile, so
* subsequent reads still observe them.
*
* @internal exported for unit testing.
*/
export declare const shouldObserveWorkerCrons: (olds: Pick | undefined, output: Pick | undefined) => boolean;
export declare const WorkerProvider: () => Layer.Layer>, Config.ConfigError | import("@alchemy.run/cloudflare-runtime/core").ConfigError | import("effect/PlatformError").PlatformError | import("@alchemy.run/cloudflare-runtime/core").SystemError, import("../../AlchemyContext.ts").AlchemyContext | Artifacts.ArtifactStore | import("effect/unstable/process/ChildProcessSpawner").ChildProcessSpawner | CloudflareEnvironment | import("effect/FileSystem").FileSystem | Path.Path | import("effect/Scope").Scope | Stack | import("../../Stage.ts").Stage | durableObjectsApi.CloudflareOpContext>;
export declare const LiveWorkerProvider: () => Layer.Layer>, never, import("effect/unstable/process/ChildProcessSpawner").ChildProcessSpawner | CloudflareEnvironment | import("effect/FileSystem").FileSystem | Path.Path | import("effect/Scope").Scope | Stack | import("../../Stage.ts").Stage | durableObjectsApi.CloudflareOpContext>;
/**
* Pack Durable Object logical-id→class mappings into `alchemy:dos:` tags.
*
* Each mapping is encoded as `logicalId=className` — elided to just
* `className` when the two are equal (the common case for export-derived
* classes) — with both components `encodeURIComponent`-escaped so the `;`
* pair separator, the `=` delimiter, and Cloudflare's forbidden tag
* characters (`,`, `&`) can never collide with user identifiers. Pairs are
* sorted for deterministic output and greedily packed so each tag stays
* within Cloudflare's 1024-byte tag limit; workers with more DOs than fit in
* one tag spill into additional `alchemy:dos:` tags.
*
* `encodeURIComponent` output is pure ASCII, so `String.length` equals the
* tag's byte length.
*
* @internal exported for unit testing.
*/
export declare function encodeDurableObjectTags(durableObjects: ReadonlyArray<{
logicalId: string;
className: string;
}>): string[];
/**
* Parse the Durable Object logical-id→class mapping from a worker's script
* tags. Reads both formats so workers deployed before the packed format roll
* forward transparently:
*
* - legacy: one `alchemy:do:{logicalId}:{className}` tag per DO
* - packed: `alchemy:dos:{pair};{pair};…` (see {@link encodeDurableObjectTags})
*
* A packed entry wins over a legacy entry for the same logical id.
*
* @internal exported for unit testing.
*/
export declare function getDurableObjectTagMap(tags: ReadonlyArray): Record;
export {};
//# sourceMappingURL=WorkerProvider.d.ts.map