pub const CLOUDFLARE_ADAPTER_SRC: &str = "adapter bynk.cloudflare {\n\tconsumes bynk { Fetch }\n\texports capability { Kv, Service, R2, RateLimit, EdgeCache }\n\texports transparent { R2Object, R2Put, R2Condition, R2Listing }\n\n\t---\n\tA Cloudflare Workers KV namespace: a key/value store with optional per-entry\n\texpiry and prefix listing.\n\t---\n\tcapability Kv {\n\t\tfn get(key: String) -> Effect[Option[String]]\n\t\tfn put(key: String, value: String) -> Effect[()]\n\t\tfn putTtl(key: String, value: String, ttlSeconds: Int) -> Effect[()]\n\t\tfn delete(key: String) -> Effect[()]\n\t\tfn list(prefix: Option[String]) -> Effect[List[String]]\n\t}\n\n\t---\n\tA Service Binding to a Worker that is not part of this Bynk project: an\n\tuntyped HTTP call over Cloudflare\'s private channel, never the public\n\tinternet. Used only through a named instance that names its Worker,\n\t`capability Billing = Service @worker(\"legacy-billing\")`, which binds as\n\t`SERVICE_BILLING`; a bare `given Service` names no Worker and is refused.\n\n\t`send` has `Fetch.send`\'s shape and rules: the same `Request` (its\n\theaders checked the same way, refused as `InvalidHeader` before anything\n\tis sent), the same `Response`, and `Network` when the call itself fails.\n\tThe URL\'s host is not used for routing (the binding decides where the\n\trequest goes), but the URL must be absolute and the callee sees it. A\n\tstatus the Worker returns, 5xx included, is an `Ok` response.\n\n\tThe callee is not Bynk\'s: `bynk deploy` neither creates nor checks its\n\tcontract, and warns when no Worker of that name exists in the account\n\t(Cloudflare itself then rejects the upload). `bynk dev` binds a local\n\ttest double unless `--local-worker` names the Worker, and `bynkc test`\n\tfaults until the call is stubbed. A Bynk callee should be consumed with\n\t`consumes` instead, which checks its contract.\n\n\t`Request`, `Response` and `FetchError` are `bynk`\'s types, so a context\n\tthat calls `send` also writes `consumes bynk` to name them.\n\t---\n\tcapability Service {\n\t\tfn send(req: Request) -> Effect[Result[Response, FetchError]]\n\t}\n\n\t---\n\tAn object in an R2 bucket, as `head`, `put`, `putWith` and `list` report\n\tit: no body. `etag` is R2\'s opaque version tag (what `EtagMatches` compares\n\tagainst), `uploaded` when the object was last written. `contentType` is\n\t`None` when none was stored; `metadata` is the custom metadata written\n\twith the object.\n\t---\n\ttype R2Object = {\n\t\tkey: String,\n\t\tsize: Int,\n\t\tetag: String,\n\t\tuploaded: Instant,\n\t\tcontentType: Option[String],\n\t\tmetadata: Map[String, String],\n\t}\n\n\t---\n\tThe precondition of an `R2.putWith` write. `Always` writes\n\tunconditionally, `Absent` only when the key holds no object (create-only,\n\twhich content-addressed storage needs), and `EtagMatches(etag)` only when\n\tthe current object\'s etag is `etag` (compare-and-swap). R2 has further\n\tconditions, so a `match` over this type needs a wildcard.\n\t---\n\ttype R2Condition =\n\t\t| Always\n\t\t| Absent\n\t\t| EtagMatches(etag: String)\n\n\t---\n\tThe options of an `R2.putWith` write: the content type and custom\n\tmetadata to store, and the precondition (`onlyIf`) the write needs.\n\t---\n\ttype R2Put = {\n\t\tcontentType: Option[String],\n\t\tmetadata: Map[String, String],\n\t\tonlyIf: R2Condition,\n\t}\n\n\t---\n\tOne page of an `R2.list`: the objects it holds, and the cursor of the next\n\tpage, `None` on the last.\n\t---\n\ttype R2Listing = {\n\t\tkeys: List[R2Object],\n\t\tcursor: Option[String],\n\t}\n\n\t---\n\tAn R2 bucket: objects stored and read whole, as `Bytes`, with metadata\n\tand conditional writes. Used only through a named instance,\n\t`capability Archives = R2`, which binds as `R2_ARCHIVES`; a bare\n\t`given R2` names no bucket and is refused. `@jurisdiction(\"eu\")` (or\n\t`\"fedramp\"`) pins the bucket\'s jurisdiction at creation.\n\n\tObjects are buffered in the Worker\'s memory, so each should stay well\n\tunder its 128 MB limit; streamed reads and writes are a later increment.\n\t`get` and `head` give `None` for a missing key; `delete` is idempotent.\n\t`put` writes unconditionally. `putWith` honours its `onlyIf` and gives\n\t`None` when the condition failed (nothing written). `list` returns one\n\tpage of up to 1000 objects (fewer is possible: the cursor decides whether\n\tmore remain) in key order, optionally under a prefix;\n\tpass the previous page\'s `cursor` for the next.\n\n\tBucket names are scoped to the Cloudflare account, so `bynk deploy` names\n\teach `<worker>-<capability, kebab>`, environment-qualified.\n\t---\n\tcapability R2 {\n\t\tfn get(key: String) -> Effect[Option[Bytes]]\n\t\tfn head(key: String) -> Effect[Option[R2Object]]\n\t\tfn put(key: String, body: Bytes) -> Effect[R2Object]\n\t\tfn putWith(key: String, body: Bytes, options: R2Put) -> Effect[Option[R2Object]]\n\t\tfn delete(key: String) -> Effect[()]\n\t\tfn list(prefix: Option[String], cursor: Option[String]) -> Effect[R2Listing]\n\t}\n\n\t---\n\tA Workers Rate Limiting binding: a counter of calls per key over a fixed\n\twindow. Used only through a named instance that sets both,\n\t`capability LoginLimit = RateLimit @limit(100) @period(60.seconds)`, which\n\tbinds as `RATELIMIT_LOGIN_LIMIT`; a bare `given RateLimit` sets neither\n\tand is refused. The period is `10.seconds` or `60.seconds`, the platform\'s\n\tonly windows.\n\n\t`allow(key)` counts one call for `key` and gives `true` while `key` is\n\twithin the limit, `false` once it is over (refuse the request, typically\n\twith `TooManyRequests`). Counting is approximate: it is kept per Cloudflare\n\tlocation and is eventually consistent, so it suits abuse and cost control,\n\tnot billing or exact quotas (use an agent for those). Each instance counts\n\ton its own: `bynk deploy` gives it its own `namespace_id`.\n\t---\n\tcapability RateLimit {\n\t\tfn allow(key: String) -> Effect[Bool]\n\t}\n\n\t---\n\tCloudflare\'s edge cache for this context\'s Worker (Workers Cache), and its\n\tpurge. Used only through a named instance, `capability Edge = EdgeCache`,\n\tat most one per context; declaring it is what turns the cache on, so a bare\n\t`given EdgeCache` is refused.\n\n\tAn opted-in Worker is served through the cache: a `2xx` from a `GET` with\n\t`@cache(scope: public)` is stored at Cloudflare\'s edge and served from\n\tthere, without running the Worker, until its `max-age` runs out or it is\n\tpurged. Every other `GET` or `HEAD` response (a route without `@cache`, or\n\tone that is not a `2xx`, a `404` included) is sent `Cache-Control:\n\tno-store`, so nothing else is kept. A `public` response is shared with\n\tevery caller, even one sent to a request carrying `Authorization`, so a\n\t`@cache(scope: public)` route here must be served by an open actor such as\n\t`Visitor`.\n\n\t`purge(prefixes)` removes every cached response whose path starts with one\n\tof `prefixes`, everywhere, and gives `true` once Cloudflare has accepted the\n\tpurge, `false` when it refused one (purges are rate-limited at Cloudflare\'s\n\tFree-tier limits on every plan), so the caller can retry. Each prefix is a\n\tpath starting with `/`, with no query and no control characters; anything\n\telse faults. An empty list purges nothing and gives `true`.\n\n\tThe purge reaches the cache only from the Worker\'s own `fetch`, so it is\n\tcalled from a service handler or what one calls; never from an agent, a\n\tqueue consumer or `on schedule` (whose purge Cloudflare accepts but which\n\tclears nothing). Under `bynk dev` there is no edge cache: every request runs\n\tthe Worker, and `purge` gives `true` after logging that it did nothing.\n\t---\n\tcapability EdgeCache {\n\t\tfn purge(prefixes: List[String]) -> Effect[Bool]\n\t}\n\n\tprovides Kv = WorkersKv\n\n\tprovides Service = WorkersService\n\n\tprovides R2 = WorkersR2\n\n\tprovides RateLimit = WorkersRateLimit\n\n\tprovides EdgeCache = WorkersEdgeCache\n}\n";Expand description
The first-party Cloudflare platform adapter (v0.19): the platform’s real
infrastructure capabilities, as they are — no portable intersection
(decision 0016). The v0.19 surface was the minimal, collection-free Kv
(decision 0023); v0.23 adds the list drain and putTtl (0050/0051);
structured values are v0.22-codec composition, and Queue remains its
own future increment. Like the bynk surface it has no binding
clause — the toolchain supplies the binding.