Fuaran.UI.ServerDriven
0.78.1
Prefix Reserved
See the version list below for details.
dotnet add package Fuaran.UI.ServerDriven --version 0.78.1
NuGet\Install-Package Fuaran.UI.ServerDriven -Version 0.78.1
<PackageReference Include="Fuaran.UI.ServerDriven" Version="0.78.1" />
<PackageVersion Include="Fuaran.UI.ServerDriven" Version="0.78.1" />
<PackageReference Include="Fuaran.UI.ServerDriven" />
paket add Fuaran.UI.ServerDriven --version 0.78.1
#r "nuget: Fuaran.UI.ServerDriven, 0.78.1"
#:package Fuaran.UI.ServerDriven@0.78.1
#addin nuget:?package=Fuaran.UI.ServerDriven&version=0.78.1
#tool nuget:?package=Fuaran.UI.ServerDriven&version=0.78.1
Fuaran.UI.ServerDriven
The transport-agnostic core for server-driven interactivity over a Fuaran tree — the third client tier (alongside the Fable client renderer and the Phase 143 hydrateRoot hydration), HTMX / Phoenix-LiveView / Blazor-Server-shaped: keep the Elmish update loop on the server, ship one tiny generic JS shim to the browser, and patch the DOM in place.
The loop: browser event on a [data-fuaran-node-id] element → server runs update → re-renders the tree → diffs old→new into a TreeOp list (Fuaran.UI.OpStream.Replay.TreeOpDiff) → lowers each op to a DomPatch (rendering HTML fragments via Fuaran.UI.Renderer.Server for structure-adding ops) → sends the patch → the shim applies it (targeted, no full re-render, no flash).
What's here
DomPatch— the lowered, closure-free, browser-applyable patch vocabulary (8 primitives:SetAttr/RemoveAttr/SetText/ReplaceFragment/InsertFragment/RemoveNode/ReorderChildren/MoveNode). The shim's entire instruction set. Tagged-object camelCase JSON.ClientEffect— the parallel channel for client-only effects the server decides but the shim performs (WriteToClipboard/Navigate/Focus/Download/ReadFileBody), because they are inherently browser-side and have no DOM-mutation form.Lowering—TreeOp → DomPatch(Lowering.lower : renderFragment -> newTree -> TreeOp list -> DomPatch list). Structural ops lower directly (RemoveNode/ReorderChildren/MoveNode/InsertChild→InsertFragment); content ops re-render the changed node (looked up in the post-apply tree) into a targetedReplaceFragment;Batchflattens. The HTML renderer is injected (renderFragment : Node<'Msg> -> string) rather than a hardRenderer.Serverdependency — keeps the core Fable-clean + dependency-light and dodges theNode<obj>cast; the host wiresRender.render.content/fuaran-live-patch.js— the generic browser shim (shipped as package content undercontent/). App-agnostic, framework-free vanilla JS (~a few KB): event delegation on[data-fuaran-node-id], a transport adapter (connect/send— the client mirror ofIFuaranLiveChannel, default SSE-push + POST-receive), theDomPatchapplier (addresses by node id;MoveNode/ReorderChildrenrelocate the live element, identity-preserving), and theClientEffectperformer. Auto-starts from<script src="fuaran-live-patch.js" data-fuaran-live-stream="/live/stream" data-fuaran-live-send="/live/event">, or callFuaranLive.start(config, adapterFactory?)explicitly (a WebSocket adapter is a drop-in — only the adapter object changes; the patch/effect/delegation core is transport-identical).start()is restartable — hosts that swap the live tree per page state call it repeatedly: each call closes the previous stream and re-points the once-wired document-level delegation at the new transport (no leakedEventSource, no duplicate sends). Click payloads bridge layout interactivity server-side: a tab-header click carriespayload.index(from the server renderer'sdata-tab-index), a disclosure summary click carriespayload.open(from the<details>state). Browser-verified viasamples/server-driven(tabs + disclosure + repeatedstart()); no headless unit tests.
Roadmap (Phase 152)
- ✅ Track A — the
TreeOp-emitting diff (Fuaran.UI.OpStream.Replay.TreeOpDiff). - Track B (in progress) — ✅ the
DomPatch/ClientEffectwire vocabularies (this package), ✅ theTreeOp → DomPatchlowering (renderer injected), ✅ the generic JS shim. Remaining: the granularSetText/SetAttrlowering follow-on (currently content ops re-render the node viaReplaceFragment— correct + targeted, just not field-level). - Track C (in progress) — ✅ the G1 inbound trust boundary (
Validation.fs— the non-negotiable default-deny gate: node-exists / event-legitimate-for-kind / payload-in-bounds / dispatch-policy-gated, mirroring the clientrunActiongate server-side), ✅ the per-connection driver (Driver.fs—LiveSession+step: validate → interpret →update→ re-view → diff → lower →DomPatch/ClientEffect, with the server-closure win + the server-executable/client-only split). Remaining: the explicit per-fieldBinding.Local/CommitLocalform-buffer protocol (the floor — client-buffered, server-sees-the-flush — already holds). - Track D ✅ — the
IFuaranLiveChanneltransport seam +Frame+InMemoryChannel+LiveConnection(Channel.fs), transport-agnostic reconnect replay (LiveConnection.Resync), the SSE frame wire encoding (FrameWire.fs), and both backends:Fuaran.UI.ServerDriven.AspNetCore(SSE+POST, the v1 default — verified end-to-end via the sample) andFuaran.UI.ServerDriven.WebSocket(the lower-latency drop-in; its structural identity to the SSE backend proves the seam is transport-neutral). - Track E ✅ —
fuaran-dotnet/docs/SERVER_DRIVEN.md(architecture + transport analysis + the per-arm tables) andsamples/server-driven(an SSR counter made live via the shim + the SSE backend, no client bundle).
No platform-SDK dependency appears anywhere here — the SSE framing is implemented here, not depended on.
Apache-2.0 licensed — see the repo LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Fable.Core (>= 5.0.0)
- FSharp.Core (>= 10.1.300)
- Fuaran.Core.Column (>= 0.21.0)
- Fuaran.Core.DataFrame (>= 0.21.0)
- Fuaran.Core.Function (>= 0.21.0)
- Fuaran.Core.Ops (>= 0.21.0)
- Fuaran.Core.OpStream (>= 0.21.0)
- Fuaran.Core.Tree (>= 0.21.0)
- Fuaran.Core.Validator (>= 0.21.0)
- Fuaran.Core.Wire (>= 0.21.0)
- Fuaran.UI (>= 0.78.1)
- Fuaran.UI.Ops (>= 0.78.1)
- Fuaran.UI.OpStream.Replay (>= 0.78.1)
- Fuaran.UI.Renderer.Core (>= 0.78.1)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Fuaran.UI.ServerDriven:
| Package | Downloads |
|---|---|
|
Fuaran.UI.ServerDriven.WebSocket
Fuaran server-driven backend 2 — one bidirectional WebSocket channel over ASP.NET. The lower-latency transport for measured high-frequency interaction (per-keystroke, drag, live cursors). A first-class second backend whose structural identity to the SSE backend (differing only in channel + endpoint glue) is the architectural-integrity check that IFuaranLiveChannel is genuinely transport-neutral. No platform-SDK dependency. Apache-2.0 licensed. |
|
|
Fuaran.UI.ServerDriven.AspNetCore
Fuaran server-driven backend 1 (v1 default) — SSE-push + POST-receive over ASP.NET. The thin transport glue around the Fuaran.UI.ServerDriven core: an SSE IFuaranLiveChannel, the POST inbound parser, the connection registry, and the GET-stream / POST-event endpoint wiring (mapFuaranLive). Default because SSE+POST rides natively through proxies/CDNs/WAFs, gets per-event HTTP governance for free, and maps reconnect 1:1 onto the journal via Last-Event-ID. No platform-SDK dependency (the SSE framing is self-contained). Apache-2.0 licensed. |
|
|
Fuaran.Program.Server.UI
Fuaran.Program.Server.UI — the UI adapter for the server placement of the domain-generic bounded program core: the pre-0.6.0 server names as aliases over the UI witness, and the UI event step (the validation gate in front of the core's dispatch) for the server session, the durable interpreter and the operator controls. .NET only. Released in the same version as the core it instantiates. Apache-2.0 licensed. |
|
|
Fuaran.Program.UI
Fuaran.Program.UI — the UI adapter for the domain-generic bounded program core: the UI witness (the UI tier's action union, node tree, binding store, tree-ops and client effects seen through the core's witness contract), the pre-0.6.0 names as aliases over it, and the UI transport loop (the bounded driver, its channel glue and the client runtime). Fable-clean. Released in the same version as the core it instantiates. Apache-2.0 licensed. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.86.0 | 54 | 9/28/2026 |
| 0.85.0 | 156 | 9/20/2026 |
| 0.84.0 | 125 | 9/17/2026 |
| 0.83.0 | 111 | 9/15/2026 |
| 0.81.0 | 112 | 9/12/2026 |
| 0.80.0 | 174 | 9/9/2026 |
| 0.79.0 | 253 | 9/9/2026 |
| 0.78.1 | 283 | 9/8/2026 |
| 0.78.0 | 124 | 9/7/2026 |
| 0.77.0 | 216 | 9/6/2026 |
| 0.76.0 | 121 | 9/6/2026 |
| 0.75.0 | 203 | 9/4/2026 |
| 0.71.0 | 113 | 9/4/2026 |
| 0.70.0 | 163 | 9/4/2026 |
| 0.46.0 | 130 | 8/28/2026 |
| 0.39.0 | 130 | 8/27/2026 |
| 0.35.0 | 244 | 8/24/2026 |
| 0.32.0 | 139 | 8/23/2026 |
| 0.31.0 | 150 | 8/21/2026 |
| 0.30.0 | 128 | 8/21/2026 |