Commit Graph
3 Commits
Author SHA1 Message Date
Claude 0ab0f79749 Fix SSE pipe: subscriptions never registered, malformed events, fanout skipping
Three bugs preventing any SSE events from reaching clients:

1. SubscriptionRegistry::clone() deep-cloned the DashMaps instead of sharing
   them. The sse_handler spawned a task with a disconnected clone, so
   subscriptions.update() wrote into a throwaway copy — the fanout always saw
   an empty registry and found zero connections to push to. Fixed by wrapping
   both DashMaps in Arc so clone() is a cheap pointer copy sharing live state.

2. The SSE event data payload used .join("\ndata: ") to pre-embed the `data:`
   prefix into the string, then handed it to axum's Event::data() which does
   its own \n-splitting to add `data:` prefixes. This produced double-prefixed
   lines (`data: data: elements ...`) that DataStar couldn't parse. Fixed by
   using .join("\n") and letting axum format the data lines correctly.

3. The fanout skipped connections with None signals (new connections that had
   not yet received a client action). This broke clock-style server-push events
   on fresh connections. Fixed by falling back to "{}" instead of continue-ing.

https://claude.ai/code/session_0168cLRd1wr6LK9FjBsjA37W
2026-03-08 19:24:22 +00:00
Claude 6605bf452f Fix DataStar v1 RC8 signal attribute incompatibilities
Two bugs that caused signals to not work on the frontend:

1. data-on-signal-change → data-on-signal-patch
   The data-on-signal-change attribute was removed in RC8.
   The replacement is data-on-signal-patch.

2. data-bind-newTodo="" → data-bind="newTodo"
   HTML normalises attribute names to lowercase at parse time, so
   data-bind-newTodo becomes data-bind-newtodo in the DOM. DataStar
   would then bind to signal $newtodo instead of $newTodo, breaking
   the two-way binding. The value syntax data-bind="newTodo" preserves
   the camelCase name correctly.

https://claude.ai/code/session_01JThiQbp3Bn9J1VhBpRuz4u
2026-03-06 20:13:55 +00:00
Claude 8535d39012 Refactor: untangle framework library from todo example
The codebase is now split into two clear layers:

Framework library (src/):
- lib.rs — public API surface, re-exports all framework types
- signal.rs — SignalOpts, Signal, SignalStore, mangle/global/client_only helpers
- query.rs — Query trait, CacheKey, query_one!/query_all! macros
  (macro paths updated from $crate::framework::* to $crate::*)
- context.rs — RenderContext, ComponentTree, ComponentNode
- connection.rs — ConnectionManager, SubscriptionRegistry, ConnectionState
- sse.rs — format_patch_elements, format_patch_signals
- server.rs — AppState, SharedState, sse_handler (pure framework plumbing)

Todo example (examples/todo/):
- main.rs — SQLite setup, seeding, server bootstrap
- app.rs — router, document_shell, resolve_and_render, render_page,
  action_then_render, and all HTTP handlers
- queries.rs — Todo model, ListTodos/GetTodo queries, mutation helpers
- todo_list.rs — TodoList page component
- about.rs — About page component

Run the example independently with: cargo run --example todo

https://claude.ai/code/session_01JThiQbp3Bn9J1VhBpRuz4u
2026-03-06 16:51:53 +00:00