///
import type { Pipeline } from "cloudflare:pipelines";
import type * as Effect from "effect/Effect";
import type { Redacted } from "effect/Redacted";
import type * as Stream from "effect/Stream";
import type { Output } from "../../Output.ts";
// Aliased so the ambient Cloudflare `Rpc` namespace (from
// @cloudflare/workers-types, referenced above) stays reachable for
// `Rpc.DurableObjectBranded`.
import type { Rpc as AlchemyRpc } from "../../Rpc.ts";
import type { WorkflowLike } from "../Workflows/Workflow.ts";
// NOTE: import the service modules directly rather than `import * as Cloudflare
// from "../index.ts"`. Importing the whole Cloudflare barrel here creates a
// circular re-export when the barrel does `export * from "./Workers/index.ts"`
// (the barrel must enumerate this module, which imports the barrel back), which
// collapses inference of the large `providers()` collection to `unknown`.
import type * as AI from "../AI/index.ts";
import type * as AnalyticsEngine from "../AnalyticsEngine/index.ts";
import type * as ArtifactsNs from "../Artifacts/index.ts";
import type { Container } from "../Containers/Container.ts";
import type * as D1 from "../D1/index.ts";
import type * as Email from "../Email/index.ts";
import type * as FlagshipNs from "../Flagship/index.ts";
import type * as HyperdriveNs from "../Hyperdrive/index.ts";
import type * as ImagesNs from "../Images/index.ts";
import type * as KV from "../KV/index.ts";
import type * as PipelinesNs from "../Pipelines/index.ts";
import type * as Queues from "../Queues/index.ts";
import type * as R2 from "../R2/index.ts";
import type * as StreamNs from "../Stream/index.ts";
import type { VpcService } from "../VpcService/VpcService.ts";
import type { VpcServiceLookup } from "../VpcService/VpcServiceLookup.ts";
import type { DispatchNamespace as DispatchNamespaceResource } from "../WorkersForPlatforms/DispatchNamespace.ts";
import type { AIBinding } from "./AIBinding.ts";
import type { Assets } from "./Assets.ts";
import type * as WorkerOnlyBinding from "./Binding.ts";
import type { BrowserBinding } from "./BrowserBinding.ts";
import type { DurableObjectLike } from "./DurableObject.ts";
import type { RateLimitBinding } from "./RateLimitBinding.ts";
import type { RpcErrorEnvelope, RpcStreamEnvelope } from "./Rpc.ts";
import type { SecretKeyBinding } from "./SecretKeyBinding.ts";
import type { VersionMetadataBinding } from "./VersionMetadataBinding.ts";
import type { Worker } from "./Worker.ts";
import type { WorkerEntrypointBinding } from "./WorkerEntrypoint.ts";
import type { WorkerLoader as WorkerLoaderResource } from "./WorkerLoader.ts";
export type InferEnv =
W extends Effect.Effect
? InferEnv
: W extends Worker
? InferEnv>
: {
[k in keyof W]: GetBindingType;
};
export type GetBindingType =
// A named-entrypoint service binding (`Cloudflare.WorkerEntrypoint`).
// Tested first: the marker *contains* a Worker, so the later Worker
// branches must never see it.
T extends WorkerEntrypointBinding
? Fetcher
: // A Container bound in `env` is a container-backed Durable Object class —
// the runtime binding is the class's namespace. Must be tested BEFORE the
// generic Effect unwrap: a Container declaration is itself an Effect.
T extends Container.Decl
? DurableObjectNamespace
: // A Worker-only binding lifted by `.pipe(Alchemy.remote())` — the brand
// carries the underlying binding value type; recurse on it. Must also
// be tested BEFORE the generic Effect unwrap (its Effect `A` is the
// runtime client, not the binding value).
T extends WorkerOnlyBinding.BindingEffect
? GetBindingType
: // `Worker.URL` (an Effect resolving to a deferred string accessor) needs
// no case of its own: the generic Effect unwrap below reduces it to
// `string` via the fallthrough.
T extends
| Output
| Effect.Effect
? GetBindingType
: T extends FlagshipNs.App
? Flagship
: T extends Assets
? Service
: T extends AlchemyRpc
? RpcWireShape & Service
: T extends D1.Database
? D1Database
: T extends R2.Bucket
? R2Bucket
: T extends KV.Namespace
? KVNamespace
: T extends DispatchNamespaceResource
? DispatchNamespace
: T extends Queues.Queue
? Queue
: T extends AI.Gateway
? Ai
: T extends AIBinding
? Ai
: T extends AI.Search
? AiSearchInstance
: T extends AI.SearchNamespace
? AiSearchNamespace
: T extends Email.SendEmail
? SendEmail
: T extends AnalyticsEngine.Dataset
? AnalyticsEngineDataset
: T extends ArtifactsNs.Namespace
? Artifacts
: T extends RateLimitBinding
? RateLimit
: T extends SecretKeyBinding
? CryptoKey
: T extends ImagesNs.ImagesBinding
? ImagesBinding
: T extends BrowserBinding
? BrowserRun
: // The ambient global `StreamBinding` from
// @cloudflare/workers-types (the alchemy binding value
// type of the same name is only reachable as
// `StreamNs.StreamBinding`).
T extends StreamNs.StreamBinding
? StreamBinding
: T extends HyperdriveNs.Connection
? Hyperdrive
: T extends VersionMetadataBinding
? WorkerVersionMetadata
: T extends WorkerLoaderResource
? WorkerLoader
: T extends WorkflowLike<
infer Params
>
? Workflow
: T extends DurableObjectLike
? DurableObjectNamespace<
Exclude<
T["Shape"],
undefined
>
>
: T extends
| VpcService
| VpcServiceLookup
? Fetcher
: T extends
| PipelinesNs.Stream
| PipelinesNs.LegacyPipeline
? Pipeline
: T extends Redacted
? // redacteds are always stored as secret_text, so are always string
// we JSON.stringify when not a Redacted
string
: T;
/**
* Cloudflare service-binding wire shape for an Effect-native Worker.
*
* Effect/Stream return values are encoded as envelopes on the wire (see
* `RpcErrorEnvelope`, `RpcStreamEnvelope`), so the mapped types reflect what
* the raw binding actually resolves to. `fetch` is dropped from the user
* shape and re-introduced via `Service` so callers get the standard
* `(input, init?) => Promise` signature.
*
* Use {@link toRpcAsync} to wrap a binding into a Promise-flavored view
* where envelopes are decoded for you.
*/
export type RpcWireShape = {
[K in keyof Shape as K extends "fetch" ? never : K]: Shape[K] extends (
...args: infer A
) => Effect.Effect
? (...args: A) => Promise
: Shape[K] extends (...args: infer A) => Stream.Stream
? (...args: A) => Promise
: Shape[K] extends Effect.Effect
? Promise
: Shape[K] extends Stream.Stream
? Promise
: Shape[K] extends (...args: infer A) => infer R
? (...args: A) => Promise>
: Promise;
};