Skip to main content

bynk_check/
firstparty.rs

1//! First-party standard adapters embedded in the toolchain (v0.17 §4.2).
2//!
3//! The `bynk` conformance surface is shipped with the compiler rather than
4//! authored by the user. When a project `consumes bynk`, the driver injects the
5//! adapter source below as a synthetic unit and provides its binding for the
6//! selected [`Platform`]. The `bynk` root namespace is reserved
7//! (`bynk.namespace.reserved`) so user code can never collide with it.
8
9/// The deploy platform — a selection axis distinct from the `--target
10/// {bundle,workers}` emit mode (§6.2). It chooses which `bynk-<platform>.ts`
11/// binding is linked for the `bynk` surface. v0.17 shipped `cloudflare`;
12/// v0.18 adds `node`, making the axis observable (and giving v0.19's
13/// platform-lock enforcement a second platform to fire against).
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
15pub enum Platform {
16    #[default]
17    Cloudflare,
18    Node,
19    /// The browser (in-browser track, slice 1 — the REPL/playground host). A
20    /// Tier-3 binding exposing the `bynk` surface over Web APIs, composed with
21    /// `BuildTarget::Bundle` only (a browser cannot do the Workers wire model).
22    Browser,
23}
24
25impl Platform {
26    /// The output filename of this platform's `bynk` binding module.
27    pub fn bynk_binding_filename(self) -> &'static str {
28        match self {
29            Platform::Cloudflare => "bynk-cloudflare.ts",
30            Platform::Node => "bynk-node.ts",
31            Platform::Browser => "bynk-browser.ts",
32        }
33    }
34
35    /// The TypeScript source of this platform's `bynk` binding.
36    pub fn bynk_binding_source(self) -> &'static str {
37        match self {
38            Platform::Cloudflare => BYNK_CLOUDFLARE_BINDING,
39            Platform::Node => BYNK_NODE_BINDING,
40            Platform::Browser => BYNK_BROWSER_BINDING,
41        }
42    }
43
44    /// The platform's stable name (for the `--platform` flag and diagnostics).
45    pub fn as_str(self) -> &'static str {
46        match self {
47            Platform::Cloudflare => "cloudflare",
48            Platform::Node => "node",
49            Platform::Browser => "browser",
50        }
51    }
52}
53
54/// The unit name of the reserved first-party surface adapter.
55pub const BYNK_UNIT: &str = "bynk";
56
57/// The unit name of the first-party Cloudflare platform adapter (v0.19,
58/// decision 0026): inside the reserved `bynk.*` prefix, so no separate
59/// reservation rule is needed. The surface unit `bynk` stays the portability
60/// marker; `bynk.<platform>` units are the platform-locked ones.
61pub const CLOUDFLARE_UNIT: &str = "bynk.cloudflare";
62
63/// The fixed Worker binding name for the Kv namespace (decision C1, v0.19):
64/// one namespace, one `[[kv_namespaces]]` stanza, one `env.KV` field.
65pub const KV_BINDING_NAME: &str = "KV";
66
67/// v0.18 decision 0021 / v0.19 decision 0025: which first-party provider
68/// classes take the Worker `env` as a constructor argument, keyed by
69/// (unit, provider class). `SecretsProvider` accepts an optional env with a
70/// `globalThis` probe fallback; `WorkersKv` *requires* env on use — KV
71/// namespaces exist only on the Worker `env`, never on `globalThis`.
72pub fn provider_takes_env(unit: &str, provider: &str) -> bool {
73    matches!(
74        (unit, provider),
75        (BYNK_UNIT, "SecretsProvider") | (CLOUDFLARE_UNIT, "WorkersKv")
76    )
77}
78
79/// v0.19 decision 0024: which first-party units are **platform-native** —
80/// consuming one locks its deployment unit to the returned platform. This is
81/// the metadata that drives effective-platform computation, `env` resource
82/// typing, and `wrangler.toml` stanza derivation; no user-facing marker
83/// syntax exists (additive later, when third-party platform adapters become
84/// a goal).
85pub fn platform_of(unit: &str) -> Option<Platform> {
86    match unit {
87        CLOUDFLARE_UNIT => Some(Platform::Cloudflare),
88        _ => None,
89    }
90}
91
92/// The unit names of the first-party collection commons (v0.20b): the
93/// Bynk-written combinator stdlib over the built-in `List`/`Map` kernel.
94/// Inside the reserved `bynk.*` prefix; injected when `uses`-imported.
95pub const LIST_UNIT: &str = "bynk.list";
96pub const MAP_UNIT: &str = "bynk.map";
97
98/// `bynk.list` — combinators over the `List` kernel (`fold`, `prepend`,
99/// `length`, `get`, `foldEff`), written in ordinary Bynk (decision 0034):
100/// the first real consumer of v0.20a generics, lambdas, and effectful
101/// traversal. Order-preserving combinators build with `fold` + `prepend`
102/// and a final `reverse` — O(n) builds, never `append` (which would be
103/// O(n²) over the array lowering).
104pub const BYNK_LIST_SRC: &str = include_str!("firstparty/bynk.list.bynk");
105
106/// `bynk.map` — combinators over the `Map` kernel (`empty`, `insert`, `get`,
107/// `keys`, `length`). `fromList` is deliberately absent: Bynk has no pair
108/// type to spell a `List[(K, V)]` with, so map construction is `Map.empty()`
109/// + `insert` (revisit with tuples or generic records).
110pub const BYNK_MAP_SRC: &str = include_str!("firstparty/bynk.map.bynk");
111
112/// Inside the reserved `bynk.*` prefix; injected when `uses`-imported.
113pub const STRING_UNIT: &str = "bynk.string";
114
115/// `bynk.string` — Bynk-written helpers over the v0.22a string kernel
116/// (`concat`, the `List` `fold`, and the `Option` kernel methods). The
117/// kernel itself is compiler built-in (ADR 0046); only derived helpers
118/// live here. `join` folds to `Option[String]` so empty-string *elements*
119/// are joined faithfully (a bare `""` accumulator could not tell "nothing
120/// yet" from "first element was empty").
121pub const BYNK_STRING_SRC: &str = include_str!("firstparty/bynk.string.bynk");
122
123/// The reserved `bynk` conformance-surface adapter (env-free core). It has no
124/// `binding` clause — the toolchain supplies one per platform (see
125/// [`Platform::bynk_binding_source`]).
126pub const BYNK_ADAPTER_SRC: &str = include_str!("firstparty/bynk.bynk");
127
128/// The Cloudflare binding for the `bynk` surface. Implements the canonical
129/// provider symbols against the platform host API. The refined `Uuid` is built
130/// through its emitted validating `.of` constructor (§4.4), treating the
131/// unreachable `Err` as a bug rather than trusting the value away.
132const BYNK_CLOUDFLARE_BINDING: &str = include_str!("firstparty/bindings/bynk-cloudflare.ts");
133
134/// The Node (≥ [`NODE_MAJOR_FLOOR`](crate::NODE_MAJOR_FLOOR)) binding for the
135/// `bynk` surface (v0.18). Deliberately
136/// near-identical to the cloudflare binding: `Date.now`, the global
137/// `crypto`/`fetch`, and `console` are the same host API on both runtimes —
138/// which is exactly the ambient-surface portability claim (spec §4.2). The
139/// `SecretsProvider` reads `process.env` through the same `globalThis` probe
140/// (never bare `process`, which would demand @types/node at the tsc gate).
141const BYNK_NODE_BINDING: &str = include_str!("firstparty/bindings/bynk-node.ts");
142
143/// The Browser binding for the `bynk` surface (in-browser track, slice 1). Tier-3:
144/// the same capability surface over Web APIs. `Clock`/`Random`/`Logger` are
145/// byte-identical to the Node binding (`Date.now`, Web Crypto `crypto.randomUUID`,
146/// `console` — all Web standards); the two substitutions are the playground safety
147/// boundary — `Fetch` is **withheld** (throws; no outbound egress from the
148/// playground origin) and `Secrets` is **unavailable** (throws; a browser has no
149/// secret store), both failing loudly rather than silently degrading.
150const BYNK_BROWSER_BINDING: &str = include_str!("firstparty/bindings/bynk-browser.ts");
151
152/// The first-party Cloudflare platform adapter (v0.19): the platform's real
153/// infrastructure capabilities, as they are — no portable intersection
154/// (decision 0016). The v0.19 surface was the minimal, collection-free `Kv`
155/// (decision 0023); v0.23 adds the `list` drain and `putTtl` (0050/0051);
156/// structured values are v0.22-codec composition, and `Queue` remains its
157/// own future increment. Like the `bynk` surface it has no `binding`
158/// clause — the toolchain supplies the binding.
159pub const CLOUDFLARE_ADAPTER_SRC: &str = include_str!("firstparty/bynk.cloudflare.bynk");
160
161/// The output path of the Cloudflare platform adapter's binding module,
162/// beside the adapter's emitted `bynk/cloudflare.ts` (distinct from the
163/// `bynk` *surface*'s per-platform `bynk-cloudflare.ts`).
164pub const CLOUDFLARE_BINDING_FILENAME: &str = "bynk/cloudflare.binding.ts";
165
166/// The Cloudflare platform adapter's binding. `WorkersKv` reads the Worker
167/// `env` explicitly (decision 0025): KV namespaces exist only on `env` —
168/// there is no `globalThis` path — so a missing binding is a clear runtime
169/// error rather than a silent fallback.
170const CLOUDFLARE_BINDING: &str = include_str!("firstparty/bindings/cloudflare.binding.ts");
171
172/// The toolchain-supplied binding for the Cloudflare platform adapter.
173pub fn cloudflare_binding_source() -> &'static str {
174    CLOUDFLARE_BINDING
175}