Xantham
A TypeScript → F# bindings generator, built on the TypeScript 7 compiler's own API server.
Xantham is a hard fork of Glutinum. It is mid-rebuild.
The whole project now sits on Xantham.TypeScript.Wire — a .NET client that runs the Go tsc
binary as tsc --api, speaks its msgpack protocol over stdio, and reads the binary AST it returns
in place, without JSON in the middle. The compiler's own schema generates the API surface, the
kinds, the child slots and the typed node layer, so the client tracks upstream rather than
paraphrasing it.
The earlier design — a Fable extractor crawling the TypeScript 5 JavaScript compiler API, a common
JSON schema as the hand-off point, and a .NET decoder plus generator — has been retired. See
.archive/ below.
Xantham.TypeScript.Wire
A standalone NuGet package, usable on its own with no dependency on the rest of Xantham.
-
The full API surface, generated from the compiler's shipped schema: 142 synchronous calls,
the same set again as
Async, and typed records for every parameter and response. -
The binary AST, read in place. A node is a struct over the blob and an index, not an object
graph, and the typed layer gives each one a tag —
Node<FunctionDeclaration>— so narrowing is a compile-time question. -
*
Session<'T>*, which binds the snapshot and project that 126 of the 142 calls repeat, so a call site carries only what varies. - A batching mailbox that collects overlapping calls into one
batchRequestsround trip. - A virtual filesystem, so the compiler can be pointed at sources that exist only in memory.
Targets net10.0, net8.0 and netstandard2.1. See the
package README to get started.
Documentation
- Using the client — install, lifecycle, calling conventions and common patterns.
- Navigating the AST — tags,
Node<'Tag>, views and the escape hatches. - The hand-written register — every fact transcribed from upstream rather than derived from its schema, and how to update each one.
- The wire protocol — framing, error model and the binary AST format, verified against live byte traces.
- Remaining work — what is still outstanding, in phases.
- Generator architecture — the nano-pass pipeline, its decisions, and what each phase landed.
- Type mapping — how each TypeScript construct becomes F#, and what it costs when it cannot.
-
The
@types/threerung — reconnaissance on the largest litmus rung attempted, why it does not land yet, and the reproducers it yielded. - Fable 5 workarounds — the six losses that come from how Fable 5 compiles F#, each with F# a consumer can write instead, and what that costs.
The generator
Xantham.Generator turns a package's .d.ts into an F# binding file through four tiers —
Harvest, Resolve, Shape, Render — each a linear list of small passes over an accumulating
record. Alongside the binding it writes a manifest.json grading every symbol Exact,
Ergonomic, Widened or Escape, so what a mapping cost is reported rather than discovered.
Each finding carries a stable catalogue key (SI001), the pass that raised it, the qualified
symbol and the declaring file, and the manifest tallies findings per pass.
Output targets Fable 5.x only, and depends on Fable.Core together with the
Fable.Browser.* family — the DOM binding table is generated by intersecting those packages
with the pinned compiler's own lib.*.d.ts. Progress is measured on a ladder of real npm
packages pinned by version, each generated into a committed golden that is compiled as F# on
every build.
Repository layout
Path |
Role |
|---|---|
|
The client. Published to NuGet, usable on its own. |
|
The bindings generator: Harvest → Resolve → Shape → Render over Wire. |
|
The support library generated bindings open (erased |
|
Expecto suite against the root pinned |
|
Expecto suite plus the golden corpus the generator is pinned against. |
|
Compiles the committed goldens as F# on every build. |
|
Vendors upstream compiler sources and emits the AST and enum F# layers. |
|
Emits the protocol F# layers from the shipped |
|
Emits the session layer over the protocol surface. |
|
Emits the generator's DOM binding table from the |
|
The build pipeline. |
|
Obsolete pre-Wire work. Nothing in here is live. |
.archive/
Everything under .archive/ is retired: Xantham.Common, Xantham.Fable,
Xantham.Decoder, Xantham.Generator and their tests and docs, the superseded plans, and the old
build system. It is kept as a record of obstacles already met, not as a source of truth — it does
not build, is not referenced by the solution, and should not be read as a description of how
Xantham works today.
Current Status
Component |
Status |
Notes |
|---|---|---|
Wire ( |
🟢 Shipped |
Generated from the compiler's own schema; packaged for NuGet. |
Generator ( |
🟡 In progress |
Phases A–C landed; phase D (erased idioms) is most of the way through. Not yet packaged. |
Support ( |
🟡 In progress |
Erased |