[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"JcOl2EQPTP":3},"\u003Cp align=\"center\">\u003Cimg width=\"150\" height=\"150\" src=\"https://data-star.dev/static/images/rocket-512x512.png\">\u003C/p>\n\n# Datastar Lean SDK\n\n[Lean 4](https://lean-lang.org) implementation of the [Datastar](https://data-star.dev/) SDK for building real-time hypermedia applications with server-sent events (SSE). Inspired by the [Haskell SDK](https://github.com/starfederation/datastar-haskell).\n\n## License\n\nThis package is licensed for free under the [MIT License](LICENSE).\n\n## Design\n\n- **No dependencies** -- only Lean's standard library.\n- **Std.Http streaming** -- `sseResponse` gives you a `ServerSentEventGenerator`\ncallback, and `sse.send` takes any event.\n\n## API Overview\n\n```lean\nimport Datastar\n\n-- Create an SSE response\nsseResponse : (ServerSentEventGenerator → ContextAsync Unit) → ContextAsync (Response Body.Any)\n\n-- Create a compressed SSE response; optionally (strategy := .clientPriority) or .forced\nsseResponseWith : List Compressor → Request β → (ServerSentEventGenerator → ContextAsync Unit)\n  → ContextAsync (Response Body.Any)\n\n-- Build events; options are named arguments, e.g. (selector := \"#feed\") (mode := .append)\npatchElements  : String → PatchElements\nremoveElements : String → PatchElements\npatchSignals   : String → PatchSignals\nexecuteScript  : String → ExecuteScript\n\n-- Send an event\nServerSentEventGenerator.send : [ToEvent α] → ServerSentEventGenerator → α → Async Unit\n\n-- Read signals from a request\nreadSignals : [FromJson α] → Request Body.Stream → ContextAsync (Except String α)\n```\n\n## Quick Start\n\nAdd the package to `lakefile.toml`:\n\n```toml\n[[require]]\nname = \"datastar\"\ngit = \"https://github.com/carlohamalainen/datastar-lean\"\nrev = \"v0.1.0\"\n```\n\nTested with Lean 4.34.1, see [lean-toolchain](lean-toolchain).\n\nthen:\n\n```lean\nimport Datastar\n\nopen Std Async Http Server\nopen Datastar\n\ndef app (req : Request Body.Stream) : ContextAsync (Response Body.Any) := do\n  match req.line.method, toString req.line.uri.path with\n  | .get, \"/hello\" =>\n    sseResponse fun sse =>\n      sse.send \u003C| patchElements \"\u003Cdiv id=\\\"message\\\">Hello!\u003C/div>\"\n  | _, _ => Response.notFound |>.text \"Not found\"\n\ndef main : IO Unit := Async.block do\n  let addr : Std.Net.SocketAddressV4 := ⟨.ofParts 127 0 0 1, 3000⟩\n  let server ← Server.serve addr \u003C| Handler.ofFn app\n  server.waitShutdown\n```\n\n## Compression\n\n`sseResponseWith` negotiates a `Content-Encoding` against the request's `Accept-Encoding`. Pass\nthe compressors in preference order:\n\n```lean\nsseResponseWith [brotli, gzip] req fun sse =>\n  sse.send \u003C| patchElements \"\u003Cdiv id=\\\"message\\\">Hello!\u003C/div>\"\n```\n\nIf the client accepts none of them, the stream is sent uncompressed.\n\n**No codecs ship with this package yet.**\n\nA codec is a `Compressor`, see [Datastar/Compression.lean](Datastar/Compression.lean).\n\n## Examples\n\n```\nlake build\n.lake/build/bin/hello-world\n```\n\nThen open \u003Chttp://127.0.0.1:3000>. Each example takes the port as an optional argument.\n\n| Executable | What it shows |\n| --- | --- |\n| `hello-world` | Reads a signal, streams `patchElements` one character at a time. |\n| `hello-world-channel` | State shared between connections; Start restarts the animation on every open page. |\n| `activity-feed` | `patchSignals` with `patchElements`; `@post` requests with signals in the body. |\n\n## SDK tests\n\nThe official [Datastar SDK test suite](https://github.com/starfederation/datastar/tree/main/sdk/tests)\nruns against `sdk-test-server` (`Test/SdkTestServer.lean`, port 7331). It needs Go:\n\n```\nscripts/test-sdk.sh\n```\n\n## End-to-end tests\n\nPlaywright drives a browser against `e2e-server` (`Test/E2EServer.lean`, port 3113), which it\nstarts itself.\n\n```\ncd e2e\nnpm ci\nnpx playwright install chromium\nnpx playwright test\n```\n",1791085029875]