Skip to content

feat: streaming RPC results (return a ReadableStream/AsyncIterable from an action) #489

@vivek7405

Description

@vivek7405

Sub-issue of #488. webjs's RPC is request/response only. An action cannot return a ReadableStream / AsyncIterable and have it stream to the client (AI token streams, progress, large result sets). TanStack Start supports this via a multiplexed frame protocol (packages/start-server-core/src/frame-protocol.ts) + a raw-response marker (x-tss-raw) + late stream registration, serialized with seroval's toCrossJSONStream.

Design / approach

When an action (any verb, typically GET or POST) returns a ReadableStream / AsyncIterable / async generator, stream it over the RPC wire instead of buffering. The client stub returns an async iterable / stream the component consumes. Reuse webjs's existing streaming infra where possible (<webjs-stream> / Suspense streaming are render-side; this is RPC-result-side). Consider a framed wire (length-prefixed chunks) so a stream can interleave with the serialized envelope. Compose with #472 seeding (a streamed result is not seeded) and the verb work in #488.

Acceptance criteria

  • An action returning a ReadableStream / AsyncIterable streams over the RPC; the client stub yields chunks as they arrive.
  • Back-pressure respected; the stream cancels when the client disconnects (ties into the AbortSignal sub-issue).
  • Rich values inside the stream round-trip through webjs's serializer.
  • Tests: unit (framed encode/decode), integration (createRequestHandler streams), browser/e2e (a token stream renders incrementally).
  • Docs updated (agent-docs/advanced.md, data-fetching page).

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions