Skip to content

Conversation

@birkskyum
Copy link
Member

@birkskyum birkskyum commented Dec 27, 2025

Mirror tests from

To vue and solid

Summary by CodeRabbit

  • New Features

    • Added a Raw Stream area with index/overview, navigation link, client-call UI and multiple SSR demo pages (single, multiple, mixed, text-hint, binary-hint).
    • Added a suite of stream utilities and server-side handlers for delayed/variable-delay streams, multiplexing patterns, large binary/mixed content, and edge cases (empty/error).
  • Tests

    • Added comprehensive end-to-end tests covering client RPC, SSR loaders, hint variants, multiplexing, cross-navigation, and edge cases.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 27, 2025

📝 Walkthrough

Walkthrough

Adds a RawStream e2e feature set: shared stream utilities and fixtures, many server-side stream handlers, a /raw-stream route subtree (index, client-call, SSR variants), UI pages that consume/verify streams, and comprehensive browser tests for multiplexing, hinting, and edge cases.

Changes

Cohort / File(s) Summary
Stream utilities & fixtures
e2e/solid-start/basic/src/raw-stream-fns.ts, e2e/vue-start/basic/src/raw-stream-fns.ts
New modules exporting stream builders (createDelayedStream, createVariableDelayStream, encode, concatBytes), consumers (createStreamConsumer, consumeBinaryStream, collectBytes, compareBytes), TEST7–TEST14 chunk fixtures/expectations, multiplexing helpers, and many server handlers (single/multiple, json-vs-raw, largeBinary, mixed, hint variants, interleaved/burst/three-stream, empty/error).
Route tree generation (generated)
e2e/solid-start/basic/src/routeTree.gen.ts, e2e/vue-start/basic/src/routeTree.gen.ts
Adds /raw-stream subtree: imports, RawStreamRoute, RawStreamIndexRoute, child SSR and client-call routes, FileRoutes maps, RootRouteChildren, and router type augmentations.
Root navigation
e2e/solid-start/basic/src/routes/__root.tsx, e2e/vue-start/basic/src/routes/__root.tsx
Adds top-level navigation link to /raw-stream (active styling only).
RawStream layout route
e2e/solid-start/basic/src/routes/raw-stream.tsx, e2e/vue-start/basic/src/routes/raw-stream.tsx
New layout route for /raw-stream rendering header, nav links to client/SSR pages, Back to Home link, and Outlet for nested routes.
Index page
e2e/solid-start/basic/src/routes/raw-stream/index.tsx, e2e/vue-start/basic/src/routes/raw-stream/index.tsx
New index under /raw-stream/ listing links/descriptions for client-call and SSR test pages.
Client-call test pages
e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx, e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
Client-side test harness with 16+ test cases invoking server handlers, consuming/validating streams and binary data, comparing to TEST*_EXPECTED, showing per-test loading/results and error handling.
SSR single/multiple/mixed
e2e/*/src/routes/raw-stream/ssr-single.tsx, .../ssr-multiple.tsx, .../ssr-mixed.tsx
SSR loaders return RawStream-wrapped delayed streams (single/multiple) or mixed payloads (immediate, deferred, RawStream). Components consume streams via stream consumer and render loading/error/results.
SSR text/binary hint routes
e2e/*/src/routes/raw-stream/ssr-text-hint.tsx, .../ssr-binary-hint.tsx
SSR routes emit streams with hint: 'text' or hint: 'binary'; client components collect bytes, compare to expected constants, decode text when applicable, and render match/error state.
E2E test suites
e2e/solid-start/basic/tests/raw-stream.spec.ts, e2e/vue-start/basic/tests/raw-stream.spec.ts
End-to-end tests covering client RPC, SSR loaders, hint variants, multiplexing patterns (interleaved, burst-pause-burst, three-stream), cross-navigation, and edge cases (empty/error streams).

Sequence Diagram(s)

sequenceDiagram
    participant Browser as Client
    participant Router as RouteLoader
    participant Factory as StreamFactory
    participant Server as RawStreamWrapper
    participant Consumer as StreamConsumer
    participant UI

    Browser->>Router: GET /raw-stream/ssr-single (navigation)
    Router->>Factory: createDelayedStream(chunks, delayMs)
    Factory-->>Server: ReadableStream<Uint8Array>
    Router-->>Browser: loader payload { message, rawData: RawStream }

    Browser->>Consumer: createStreamConsumer()
    Browser->>Consumer: consume(rawData)
    activate Consumer
    loop read chunks
        Consumer->>Server: getReader()/read()
        Server-->>Consumer: Uint8Array chunk (delayed)
        Consumer->>Consumer: concatBytes(...)
    end
    Consumer-->>Browser: bytes/string result
    deactivate Consumer
    Browser->>UI: setState(streamContent)
    UI->>Browser: render content + JSON results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • feat: RawStream #6231 — Adds RawStream utilities, TEST fixtures, server handlers, and route scaffolding closely matching these additions.

Suggested labels

ssr, package: solid-router, package: vue-router

Suggested reviewers

  • schiller-manuel
  • brenelz

Poem

🐇 I stitched the bytes and timed the streams,
Hopped through hints and multiplexed dreams.
From SSR hills to client-call glen,
I tested, compared, and hopped again.
— a rabbit celebrating bytey greens 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.89% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding raw stream synchronization tests to the vue-start and solid-start test suites, mirroring functionality from a prior PR.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Dec 27, 2025

View your CI Pipeline Execution ↗ for commit fc217fe

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 9m 14s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 4s View ↗

☁️ Nx Cloud last updated this comment at 2025-12-30 01:05:20 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 27, 2025

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6234

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@6234

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6234

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@6234

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@6234

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@6234

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@6234

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6234

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6234

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6234

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@6234

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@6234

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@6234

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@6234

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@6234

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@6234

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@6234

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@6234

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@6234

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@6234

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@6234

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@6234

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6234

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6234

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6234

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6234

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6234

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6234

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6234

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@6234

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6234

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6234

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6234

@tanstack/vue-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@6234

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@6234

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@6234

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6234

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6234

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6234

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6234

commit: fc217fe

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

🧹 Nitpick comments (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (1)

41-41: Consider: Move export after function definition for clarity.

The export statement at line 41 references concatBytes which is defined later at line 78. While this works due to JavaScript hoisting for function declarations, it can be confusing. Consider moving the export statement after all exported items are defined, or defining concatBytes before the export.

Also applies to: 78-87

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4db7f8c and 761718c.

📒 Files selected for processing (24)
  • e2e/solid-start/basic/src/raw-stream-fns.ts
  • e2e/solid-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routes/__root.tsx
  • e2e/solid-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/index.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/src/raw-stream-fns.ts
  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/vue-start/basic/src/routes/__root.tsx
  • e2e/vue-start/basic/src/routes/raw-stream.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/index.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/index.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/index.tsx
  • e2e/solid-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/tests/raw-stream.spec.ts
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/src/routes/__root.tsx
  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routes/__root.tsx
  • e2e/solid-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/raw-stream-fns.ts
  • e2e/vue-start/basic/src/raw-stream-fns.ts
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/index.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/index.tsx
  • e2e/solid-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/tests/raw-stream.spec.ts
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/src/routes/__root.tsx
  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routes/__root.tsx
  • e2e/solid-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/raw-stream-fns.ts
  • e2e/vue-start/basic/src/raw-stream-fns.ts
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
🧠 Learnings (9)
📓 Common learnings
Learnt from: nlynzaad
Repo: TanStack/router PR: 6215
File: e2e/react-start/custom-basepath/package.json:13-17
Timestamp: 2025-12-25T13:04:55.492Z
Learning: In the TanStack Router repository, e2e test scripts are specifically designed to run in CI (which uses a Unix environment), so Unix-specific commands (like `rm -rf`, `&` for backgrounding, and direct environment variable assignments without `cross-env`) are acceptable in e2e test npm scripts.
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/index.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/index.tsx
  • e2e/solid-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/index.tsx
  • e2e/vue-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/index.tsx
  • e2e/solid-start/basic/src/routes/raw-stream.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/index.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routeTree.gen.ts
📚 Learning: 2025-12-17T02:17:55.086Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:55.086Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream.tsx
  • e2e/solid-start/basic/src/routes/raw-stream.tsx
  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routeTree.gen.ts
📚 Learning: 2025-12-21T12:52:35.231Z
Learnt from: Sheraff
Repo: TanStack/router PR: 6171
File: packages/router-core/src/new-process-route-tree.ts:898-898
Timestamp: 2025-12-21T12:52:35.231Z
Learning: In `packages/router-core/src/new-process-route-tree.ts`, the matching logic intentionally allows paths without trailing slashes to match index routes with trailing slashes (e.g., `/a` can match `/a/` route), but not vice-versa (e.g., `/a/` cannot match `/a` layout route). This is implemented via the condition `!pathIsIndex || node.kind === SEGMENT_TYPE_INDEX` and is a deliberate design decision to provide better UX by being permissive with missing trailing slashes.

Applied to files:

  • e2e/solid-start/basic/src/routes/raw-stream.tsx
  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routeTree.gen.ts
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.

Applied to files:

  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routeTree.gen.ts
📚 Learning: 2025-09-28T21:41:45.233Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5284
File: e2e/react-start/basic/server.js:50-0
Timestamp: 2025-09-28T21:41:45.233Z
Learning: In Express v5, catch-all routes must use named wildcards. Use `/*splat` to match everything except root path, or `/{*splat}` (with braces) to match including root path. The old `*` syntax is not allowed and will cause "Missing parameter name" errors. This breaking change requires explicit naming of wildcard parameters.

Applied to files:

  • e2e/vue-start/basic/src/routeTree.gen.ts
  • e2e/solid-start/basic/src/routeTree.gen.ts
🧬 Code graph analysis (14)
e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (1)
e2e/solid-start/basic/src/raw-stream-fns.ts (2)
  • collectBytes (418-444)
  • compareBytes (447-480)
e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx (2)
e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • Route (10-23)
e2e/solid-start/basic/src/raw-stream-fns.ts (3)
  • createDelayedStream (41-41)
  • encode (41-41)
  • createStreamConsumer (371-394)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (4)
e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
  • Route (22-46)
e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx (1)
  • Route (10-27)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • Route (10-23)
e2e/vue-start/basic/src/raw-stream-fns.ts (3)
  • createDelayedStream (41-41)
  • encode (41-41)
  • createStreamConsumer (371-394)
e2e/vue-start/basic/src/routes/raw-stream/index.tsx (5)
e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx (1)
  • Route (37-39)
e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
  • Route (22-46)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)
  • Route (10-29)
e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx (1)
  • Route (10-27)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • Route (10-23)
e2e/solid-start/basic/src/routes/raw-stream/index.tsx (6)
e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx (1)
  • Route (37-39)
e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
  • Route (22-46)
e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)
  • Route (10-29)
e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx (1)
  • Route (10-27)
e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • Route (10-23)
e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (1)
  • Route (34-69)
e2e/solid-start/basic/src/routes/raw-stream.tsx (6)
e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx (1)
  • Route (37-39)
e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
  • Route (22-46)
e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)
  • Route (10-29)
e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx (1)
  • Route (10-27)
e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • Route (10-23)
e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (1)
  • Route (34-69)
e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx (2)
e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
  • Route (22-46)
e2e/solid-start/basic/src/raw-stream-fns.ts (3)
  • createDelayedStream (41-41)
  • encode (41-41)
  • createStreamConsumer (371-394)
e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
e2e/solid-start/basic/src/raw-stream-fns.ts (2)
  • collectBytes (418-444)
  • compareBytes (447-480)
e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx (4)
e2e/solid-start/basic/src/routes/__root.tsx (1)
  • Route (16-66)
e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • Route (10-23)
e2e/solid-start/basic/src/raw-stream-fns.ts (30)
  • createStreamConsumer (371-394)
  • singleRawStreamFn (90-99)
  • multipleRawStreamsFn (102-116)
  • jsonEndsFirstFn (119-130)
  • rawEndsFirstFn (133-147)
  • largeBinaryFn (150-164)
  • consumeBinaryStream (396-415)
  • mixedStreamingFn (167-180)
  • textHintPureTextFn (183-189)
  • collectBytes (418-444)
  • TEST7_EXPECTED (50-50)
  • textHintPureBinaryFn (192-198)
  • TEST8_EXPECTED (57-57)
  • textHintMixedFn (201-207)
  • TEST9_EXPECTED (65-65)
  • binaryHintTextFn (210-216)
  • TEST10_EXPECTED (69-69)
  • binaryHintBinaryFn (219-225)
  • TEST11_EXPECTED (75-75)
  • interleavedStreamsFn (296-305)
  • TEST12_STREAM_A_EXPECTED (245-247)
  • TEST12_STREAM_B_EXPECTED (248-250)
  • burstPauseBurstFn (308-315)
  • TEST13_EXPECTED (262-264)
  • threeStreamsFn (318-329)
  • TEST14_STREAM_A_EXPECTED (285-287)
  • TEST14_STREAM_B_EXPECTED (288-290)
  • TEST14_STREAM_C_EXPECTED (291-293)
  • emptyStreamFn (336-348)
  • errorStreamFn (351-365)
e2e/vue-start/basic/src/raw-stream-fns.ts (30)
  • createStreamConsumer (371-394)
  • singleRawStreamFn (90-99)
  • multipleRawStreamsFn (102-116)
  • jsonEndsFirstFn (119-130)
  • rawEndsFirstFn (133-147)
  • largeBinaryFn (150-164)
  • consumeBinaryStream (396-415)
  • mixedStreamingFn (167-180)
  • textHintPureTextFn (183-189)
  • collectBytes (418-444)
  • TEST7_EXPECTED (50-50)
  • textHintPureBinaryFn (192-198)
  • TEST8_EXPECTED (57-57)
  • textHintMixedFn (201-207)
  • TEST9_EXPECTED (65-65)
  • binaryHintTextFn (210-216)
  • TEST10_EXPECTED (69-69)
  • binaryHintBinaryFn (219-225)
  • TEST11_EXPECTED (75-75)
  • interleavedStreamsFn (296-305)
  • TEST12_STREAM_A_EXPECTED (245-247)
  • TEST12_STREAM_B_EXPECTED (248-250)
  • burstPauseBurstFn (308-315)
  • TEST13_EXPECTED (262-264)
  • threeStreamsFn (318-329)
  • TEST14_STREAM_A_EXPECTED (285-287)
  • TEST14_STREAM_B_EXPECTED (288-290)
  • TEST14_STREAM_C_EXPECTED (291-293)
  • emptyStreamFn (336-348)
  • errorStreamFn (351-365)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (3)
e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • Route (10-23)
e2e/vue-start/basic/src/raw-stream-fns.ts (3)
  • createDelayedStream (41-41)
  • encode (41-41)
  • createStreamConsumer (371-394)
e2e/react-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • SSRSingleTest (25-75)
e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (2)
  • collectBytes (418-444)
  • compareBytes (447-480)
e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (2)
  • collectBytes (418-444)
  • compareBytes (447-480)
e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx (2)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
  • Route (10-23)
e2e/vue-start/basic/src/raw-stream-fns.ts (3)
  • createDelayedStream (41-41)
  • encode (41-41)
  • createStreamConsumer (371-394)
e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx (2)
e2e/solid-start/basic/src/raw-stream-fns.ts (3)
  • createDelayedStream (41-41)
  • encode (41-41)
  • createStreamConsumer (371-394)
packages/router-core/src/ssr/tsrScript.ts (1)
  • p (16-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: Preview
🔇 Additional comments (14)
e2e/vue-start/basic/src/routes/__root.tsx (1)

142-149: LGTM!

The new "Raw Stream" navigation link follows the same pattern as existing links with consistent styling (activeProps with font-bold). The route path /raw-stream aligns with the new route tree additions.

e2e/solid-start/basic/src/routes/__root.tsx (1)

142-149: LGTM!

The navigation link to /raw-stream is correctly added following the existing pattern. Uses proper Solid.js JSX syntax with class attribute.

e2e/solid-start/basic/src/routes/raw-stream/index.tsx (1)

1-71: LGTM!

This index route is correctly implemented for Solid.js - no React imports, proper use of @tanstack/solid-router, and appropriate JSX syntax. The reloadDocument={true} on SSR links ensures full page reloads for proper SSR testing.

e2e/vue-start/basic/src/routes/raw-stream/index.tsx (1)

1-71: LGTM!

The Vue index route is correctly implemented with proper @tanstack/vue-router imports and appropriate JSX syntax. Structure mirrors the Solid version as intended by the PR objectives.

e2e/vue-start/basic/src/routes/raw-stream.tsx (1)

1-70: LGTM!

The layout route is well-structured with proper navigation to all child routes. The use of reloadDocument={true} for SSR routes ensures full server-side rendering during tests, and the activeProps provide visual feedback for the current route.

e2e/solid-start/basic/src/routes/raw-stream.tsx (1)

1-70: LGTM!

The Solid layout route correctly mirrors the Vue version with appropriate imports from @tanstack/solid-router. The structure is consistent across frameworks, which aids maintainability.

e2e/solid-start/basic/tests/raw-stream.spec.ts (3)

1-17: Well-structured test suite with comprehensive coverage.

The test file is well-organized with clear test blocks covering Client RPC, SSR Loader, Hint Parameters, Multiplexing, Cross Navigation, and Edge Cases. The documentation comment (lines 5-12) clearly explains the RawStream functionality being tested.


186-208: Good handling of prerender limitation.

The conditional skip for prerender mode with a clear explanation of the limitation is a good practice. This prevents flaky tests while documenting the known behavior.

;(isPrerender ? test.skip : test)(
  'SSR mixed streaming - RawStream with deferred data',
  // ...
)

622-666: Edge case coverage is thorough.

Testing empty streams and error propagation are important edge cases. The assertions verify both the error state and the error message content.

e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (1)

12-32: Good practice: Module-level expected data for client-side verification.

Defining the expected byte sequences at module level ensures consistency between what the loader produces and what the client verifies. This pattern is clean and maintainable.

e2e/vue-start/basic/src/routeTree.gen.ts (1)

1-9: Skipping review of autogenerated file.

This is an autogenerated route tree file that should not be manually modified. Based on learnings from the repository.

e2e/solid-start/basic/src/routeTree.gen.ts (1)

1-9: Skipping review of autogenerated file.

This is an autogenerated route tree file that should not be manually modified. Based on learnings from the repository.

e2e/vue-start/basic/src/raw-stream-fns.ts (1)

371-394: Good implementation of stream consumer with dual-type support.

The createStreamConsumer function correctly handles both RawStream (from type system) and ReadableStream (at runtime) with appropriate type checking. The factory pattern provides a clean interface for stream consumption.

e2e/solid-start/basic/src/raw-stream-fns.ts (1)

1-41: LGTM with same optional suggestion as Vue version.

This file correctly imports from @tanstack/solid-start and provides comprehensive test utilities. The same optional refactor suggestion about export ordering applies here as noted for the Vue version.

Comment on lines +14 to +16
// Wait time for hydration to complete after page load
// This needs to be long enough for React hydration to attach event handlers
const HYDRATION_WAIT = 1000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Minor: Comment mentions React hydration in Vue test file.

The comment refers to "React hydration" but this is a Vue test file. Consider updating to "Vue hydration" for accuracy.

 // Wait time for hydration to complete after page load
-// This needs to be long enough for React hydration to attach event handlers
+// This needs to be long enough for Vue hydration to attach event handlers
 const HYDRATION_WAIT = 1000
🤖 Prompt for AI Agents
In e2e/vue-start/basic/tests/raw-stream.spec.ts around lines 14 to 16, the
inline comment incorrectly references "React hydration" in a Vue test file;
update the comment to say "Vue hydration" (or a neutral term like "framework
hydration") so it accurately describes that the wait time is for Vue's hydration
to attach event handlers.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)

83-96: Add explicit return type for improved type safety.

The loader function lacks an explicit return type annotation. Per the coding guidelines requiring "extensive type safety for all code," adding an explicit type improves code clarity and compiler diagnostics.

🔎 Proposed type annotation
 export const Route = createFileRoute('/raw-stream/ssr-single')({
-  loader: async () => {
+  loader: async (): Promise<{
+    message: string
+    timestamp: number
+    rawData: RawStream
+  }> => {
     const stream = createDelayedStream(
       [encode('ssr-chunk1'), encode('ssr-chunk2'), encode('ssr-chunk3')],
       50,
     )
     return {
       message: 'SSR Single Stream Test',
       timestamp: Date.now(),
       rawData: new RawStream(stream),
     }
   },
   component: SSRSingleTest,
 })

As per coding guidelines, extensive type safety is required for all TypeScript code.

e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx (1)

49-61: Consider using reactive object updates instead of spread for state.

The current pattern creates new objects on each state update. While functional, Vue's reactivity works more efficiently with direct property assignment on reactive objects.

🔎 Alternative using reactive
-const results = ref<Record<string, any>>({})
-const loading = ref<Record<string, boolean>>({})
+import { reactive } from 'vue'
+const results = reactive<Record<string, any>>({})
+const loading = reactive<Record<string, boolean>>({})

// Then use direct assignment:
-loading.value = { ...loading.value, [testName]: true }
+loading[testName] = true
e2e/solid-start/basic/src/raw-stream-fns.ts (1)

40-41: Export statement references concatBytes before its definition.

The export at line 41 references concatBytes which is defined at line 78. While JavaScript function hoisting makes this work at runtime, placing exports after definitions improves readability and aligns with common conventions.

🔎 Move export after definitions
-// Export helpers for use in components and SSR routes
-export { encode, createDelayedStream, concatBytes }
-
 // Expected data for hint tests...
 // ... (test data definitions)
 
 // Helper to concatenate byte arrays
 function concatBytes(chunks: Array<Uint8Array>): Uint8Array {
   // ...
 }
+
+// Export helpers for use in components and SSR routes
+export { encode, createDelayedStream, concatBytes }
e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx (1)

41-41: Consider memoizing the stream consumer.

The consumeStream helper is recreated on every component render. While this is likely not a performance issue for test code, you could use Solid's createMemo or move it outside the component for consistency.

🔎 Optional refactor to memoize consumeStream
+import { createFileRoute } from '@tanstack/solid-router'
+import { createSignal, createMemo } from 'solid-js'
-import { createSignal } from 'solid-js'

 function ClientCallTests() {
   const [results, setResults] = createSignal<Record<string, any>>({})
   const [loading, setLoading] = createSignal<Record<string, boolean>>({})
 
-  const consumeStream = createStreamConsumer()
+  const consumeStream = createMemo(() => createStreamConsumer())

Then update usages to call consumeStream()():

-  streamContent: await consumeStream(result.data),
+  streamContent: await consumeStream()(result.data),

Alternatively, move createStreamConsumer() outside the component entirely if the decoder doesn't need to be scoped per component instance.

e2e/vue-start/basic/src/raw-stream-fns.ts (1)

36-41: Refactor: Export after definition for better readability.

Line 41 exports concatBytes before it's defined at line 78. While this works due to function hoisting, it makes the code harder to follow and maintain. Consider moving the export statement after the concatBytes function definition.

🔎 Proposed fix to improve code organization

Move the export statement to after the concatBytes definition:

 // Helper to encode text to Uint8Array
 function encode(text: string): Uint8Array {
   return new TextEncoder().encode(text)
 }
 
-// Export helpers for use in components and SSR routes
-export { encode, createDelayedStream, concatBytes }
-
 // Expected data for hint tests - defined here for both server and client verification
 // Test 7: Text hint with pure text
 export const TEST7_CHUNKS = [
   encode('Hello, '),
   encode('World! '),
   encode('This is text.'),
 ]
 export const TEST7_EXPECTED = concatBytes(TEST7_CHUNKS)

 // ... (other test constants)

 // Helper to concatenate byte arrays
 function concatBytes(chunks: Array<Uint8Array>): Uint8Array {
   const totalLength = chunks.reduce((acc, c) => acc + c.length, 0)
   const result = new Uint8Array(totalLength)
   let offset = 0
   for (const chunk of chunks) {
     result.set(chunk, offset)
     offset += chunk.length
   }
   return result
 }
+
+// Export helpers for use in components and SSR routes
+export { encode, createDelayedStream, concatBytes }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 761718c and 42d5ae1.

📒 Files selected for processing (16)
  • e2e/solid-start/basic/src/raw-stream-fns.ts
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/index.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/raw-stream-fns.ts
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/index.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/index.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/index.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/raw-stream-fns.ts
  • e2e/solid-start/basic/src/raw-stream-fns.ts
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/raw-stream-fns.ts
  • e2e/solid-start/basic/src/raw-stream-fns.ts
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
🧠 Learnings (4)
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Separate framework-agnostic core logic from React/Solid bindings

Applied to files:

  • e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx
🧬 Code graph analysis (7)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (1)
  • createStreamConsumer (371-394)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (1)
  • createStreamConsumer (371-394)
e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (1)
e2e/solid-start/basic/src/raw-stream-fns.ts (2)
  • collectBytes (418-444)
  • compareBytes (447-480)
e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
e2e/solid-start/basic/src/raw-stream-fns.ts (5)
  • encode (41-41)
  • concatBytes (41-41)
  • collectBytes (418-444)
  • compareBytes (447-480)
  • createDelayedStream (41-41)
e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx (2)
e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx (1)
  • Route (84-101)
e2e/solid-start/basic/src/raw-stream-fns.ts (3)
  • createStreamConsumer (371-394)
  • createDelayedStream (41-41)
  • encode (41-41)
e2e/solid-start/basic/src/raw-stream-fns.ts (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (13)
  • createDelayedStream (41-41)
  • encode (41-41)
  • TEST7_CHUNKS (45-49)
  • TEST7_EXPECTED (50-50)
  • concatBytes (41-41)
  • TEST8_CHUNKS (53-56)
  • TEST8_EXPECTED (57-57)
  • TEST9_CHUNKS (60-64)
  • TEST9_EXPECTED (65-65)
  • TEST10_CHUNKS (68-68)
  • TEST10_EXPECTED (69-69)
  • TEST11_CHUNKS (72-74)
  • TEST11_EXPECTED (75-75)
e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)
e2e/solid-start/basic/src/raw-stream-fns.ts (3)
  • createStreamConsumer (371-394)
  • createDelayedStream (41-41)
  • encode (41-41)
🪛 Biome (2.1.2)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx

[error] 58-58: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx

[error] 52-52: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (24)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (2)

1-8: LGTM!

Imports are correct for Vue implementation. The previous issue with React imports has been properly resolved.


39-79: LGTM!

The render function properly handles loading, error, and success states with appropriate test identifiers for e2e testing.

e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (2)

1-8: LGTM - Vue Composition API correctly applied.

The imports and component structure now properly use Vue's defineComponent, ref, watch, and Suspense. The previous React-related issues have been resolved.


53-63: The children prop pattern is the correct API for @tanstack/vue-router's Await component. The component explicitly defines children as a required Function prop, and all usages throughout the codebase follow this exact pattern. Biome's flag is a false positive. No changes needed.

e2e/vue-start/basic/src/routes/raw-stream/client-call.tsx (1)

1-35: LGTM - Correct Vue implementation with comprehensive test coverage.

The component properly uses Vue's defineComponent and ref for reactive state management. All 16 test cases are well-structured with consistent patterns for execution, loading states, and result display.

e2e/solid-start/basic/src/raw-stream-fns.ts (2)

89-99: LGTM - Well-structured server function implementations.

The server functions are correctly implemented using createServerFn().handler() pattern with proper RawStream wrapping. Good coverage of streaming scenarios including single/multiple streams, timing variations, and hint configurations.


371-393: LGTM - Stream consumer with proper type handling.

The createStreamConsumer function correctly handles both RawStream and ReadableStream<Uint8Array> types, with appropriate runtime type checking via instanceof. The eslint-disable for the while loop is appropriate.

e2e/solid-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (2)

1-10: LGTM - Correct Solid.js implementation.

The file properly uses Solid's createSignal and createEffect primitives. The previous React-related issues have been resolved.


58-100: LGTM - Well-structured async effect with proper error handling.

The createEffect correctly:

  • Tracks reactive dependencies via loaderData() access
  • Uses Promise.all for concurrent stream processing
  • Properly handles errors with catch block
  • Updates loading state appropriately
e2e/solid-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (2)

1-10: LGTM - Correct Solid.js implementation with proper primitives.

Imports and component structure correctly use Solid's createSignal and createEffect. The component follows the same well-established pattern as other SSR hint test routes.


117-141: LGTM - Loader correctly configures binary hint.

The loader properly creates two RawStream instances with { hint: 'binary' } configuration, testing both text data and pure binary data with the binary hint setting.

e2e/solid-start/basic/src/routes/raw-stream/ssr-multiple.tsx (2)

1-8: LGTM - Correct Solid.js implementation.

The imports and component structure properly use Solid's createSignal and createEffect primitives. The dual-stream consumption pattern is well-implemented.


80-97: LGTM - Consistent with Vue implementation.

The loader structure matches the Vue counterpart (e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx), ensuring cross-framework test parity with identical stream configurations (multi-1a/1b, multi-2a/2b with 30ms/50ms delays).

e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx (3)

1-8: LGTM - Correct Solid.js implementation.

The imports properly use Solid's primitives (Suspense, createEffect, createSignal) along with TanStack's Await component.


77-96: LGTM - Mixed streaming loader correctly configured.

The loader properly demonstrates the mixed streaming scenario with:

  • Immediate synchronous value
  • Deferred Promise (100ms delay)
  • RawStream with delayed chunks (50ms intervals)

This matches the Vue implementation for cross-framework test consistency.


49-54: The children prop pattern is correct per the Await component's type definition. The component explicitly expects children as a function prop, as shown in the type signature: children: (result: T) => SolidNode. While the JSX children syntax (<Await>{(data) => ...}</Await>) is more idiomatic in Solid and would be functionally equivalent, the current prop-based approach is valid and follows the documented API.

e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (3)

1-10: LGTM - Correct Vue Composition API implementation.

The file properly uses Vue's defineComponent, ref, and watch primitives with the { immediate: true } option for initial execution.


58-107: LGTM - Watch handler with proper async processing.

The watch correctly:

  • Tracks all three loader data properties as dependencies
  • Uses Promise.all for concurrent byte collection
  • Compares collected bytes against expected values
  • Handles errors appropriately

The { immediate: true } option ensures the handler runs on initial mount.


170-205: LGTM - Loader matches Solid counterpart.

The loader configuration is identical to the Solid version, ensuring cross-framework test parity for the text-hint streaming scenario.

e2e/solid-start/basic/src/routes/raw-stream/client-call.tsx (2)

37-61: LGTM! Well-structured test harness.

The component correctly uses Solid primitives (createSignal) and implements a clean, reusable test runner pattern. The error handling and state management are appropriate for this e2e test scenario.


63-484: Excellent test coverage with consistent patterns.

All 16 tests follow a consistent structure with proper test IDs, loading states, error handling, and result displays. The test suite comprehensively covers single/multiple streams, ordering scenarios, large binary data, hints, multiplexing, and edge cases.

e2e/vue-start/basic/src/raw-stream-fns.ts (3)

90-365: Well-structured server function implementations.

All 16 server functions follow consistent patterns and are well-documented with clear test scenarios. The implementations properly use createServerFn().handler() and correctly instantiate RawStream objects with appropriate options (hints, delays, etc.).


371-444: Excellent stream consumer utilities with proper type handling.

The helper functions correctly handle the dual nature of RawStream (type system marker) vs ReadableStream<Uint8Array> (runtime type after SSR deserialization). The ESLint disable comments on lines 385, 407, and 429 are appropriate for the while (true) loops, which have explicit break conditions.


446-480: Robust byte comparison utility.

The compareBytes function provides detailed mismatch information (index, lengths) which is valuable for debugging test failures. The implementation correctly handles both length mismatches and byte-level differences.

Comment on lines 17 to 37
watch(
() => loaderData.value.rawData,
(rawData) => {
if (!rawData) {
return
}
const consumeStream = createStreamConsumer()
isConsuming.value = true
error.value = null
consumeStream(rawData)
.then((content) => {
streamContent.value = content
isConsuming.value = false
})
.catch((err) => {
error.value = String(err)
isConsuming.value = false
})
},
{ immediate: true },
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add cleanup to prevent resource leaks and race conditions.

The watch callback starts async stream consumption but provides no mechanism to cancel it when the component unmounts or when rawData changes before the previous consumption completes. This causes:

  • Resource leaks (ReadableStream reader remains active)
  • Race conditions (multiple concurrent consumptions updating state)
🔎 Proposed fix with cleanup logic
+import { defineComponent, ref, watch, onUnmounted } from 'vue'

 const SSRSingleTest = defineComponent({
   setup() {
     const loaderData = Route.useLoaderData()
     const streamContent = ref('')
     const isConsuming = ref(true)
     const error = ref<string | null>(null)
+    let abortController: AbortController | null = null

-    watch(
+    const stopWatch = watch(
       () => loaderData.value.rawData,
       (rawData) => {
+        // Cancel previous stream consumption if still ongoing
+        if (abortController) {
+          abortController.abort()
+        }
+
         if (!rawData) {
           return
         }
+        abortController = new AbortController()
+        const signal = abortController.signal
+
         const consumeStream = createStreamConsumer()
         isConsuming.value = true
         error.value = null
         consumeStream(rawData)
           .then((content) => {
+            if (!signal.aborted) {
               streamContent.value = content
               isConsuming.value = false
+            }
           })
           .catch((err) => {
+            if (!signal.aborted) {
               error.value = String(err)
               isConsuming.value = false
+            }
           })
       },
       { immediate: true },
     )
+
+    onUnmounted(() => {
+      stopWatch()
+      if (abortController) {
+        abortController.abort()
+      }
+    })

     return () => (

Note: You may also need to update createStreamConsumer in raw-stream-fns.ts to accept an AbortSignal and cancel the reader when the signal is aborted.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
watch(
() => loaderData.value.rawData,
(rawData) => {
if (!rawData) {
return
}
const consumeStream = createStreamConsumer()
isConsuming.value = true
error.value = null
consumeStream(rawData)
.then((content) => {
streamContent.value = content
isConsuming.value = false
})
.catch((err) => {
error.value = String(err)
isConsuming.value = false
})
},
{ immediate: true },
)
let abortController: AbortController | null = null
const stopWatch = watch(
() => loaderData.value.rawData,
(rawData) => {
// Cancel previous stream consumption if still ongoing
if (abortController) {
abortController.abort()
}
if (!rawData) {
return
}
abortController = new AbortController()
const signal = abortController.signal
const consumeStream = createStreamConsumer()
isConsuming.value = true
error.value = null
consumeStream(rawData)
.then((content) => {
if (!signal.aborted) {
streamContent.value = content
isConsuming.value = false
}
})
.catch((err) => {
if (!signal.aborted) {
error.value = String(err)
isConsuming.value = false
}
})
},
{ immediate: true },
)
onUnmounted(() => {
stopWatch()
if (abortController) {
abortController.abort()
}
})
🤖 Prompt for AI Agents
In e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx around lines 17 to
37, the watch callback starts async stream consumption but never cancels it,
causing leaked readers and race conditions; fix by creating an AbortController
for each consumption, pass its signal into createStreamConsumer (update
raw-stream-fns.ts to accept an AbortSignal and cancel the reader when aborted),
store the controller for the active consumption and call controller.abort()
before starting a new one, and register a stop/unmounted cleanup to abort any
in-flight consumption so readers are always released and state updates from
stale consumptions are prevented.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)

22-24: Remove redundant state assignment.

Line 23 sets isConsuming.value = true, but it's already initialized to true on line 14. This assignment is unnecessary.

🔎 Proposed fix
   const consumeStream = createStreamConsumer()
-  isConsuming.value = true
   error.value = null
e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (2)

51-51: Remove redundant state initialization.

isLoading is already initialized to true on line 42, so setting it again here is unnecessary.

🔎 Proposed fix
-    isLoading.value = true
     error.value = null

57-61: Remove redundant field assignments.

compareBytes already returns actualLength and expectedLength, so overwriting these fields with the same values is redundant.

🔎 Proposed fix
       const textComp = compareBytes(textBytes, TEXT_EXPECTED)
       const decoder = new TextDecoder()
       textMatch.value = {
         ...textComp,
-        actualLength: textBytes.length,
-        expectedLength: TEXT_EXPECTED.length,
         asText: decoder.decode(textBytes),
       }

Apply the same pattern for binary match (lines 63-68):

       const binaryComp = compareBytes(binaryBytes, BINARY_EXPECTED)
-      binaryMatch.value = {
-        ...binaryComp,
-        actualLength: binaryBytes.length,
-        expectedLength: BINARY_EXPECTED.length,
-      }
+      binaryMatch.value = binaryComp
e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx (1)

25-26: Consider removing redundant state initialization.

These assignments reset isConsuming and error to their initial values (already set on lines 15-16). While harmless, removing them would reduce redundancy.

🔎 Suggested refactor
     const consumeStream = createStreamConsumer()
-    isConsuming.value = true
-    error.value = null
     Promise.all([consumeStream(first), consumeStream(second)])
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42d5ae1 and 4b3dfe4.

📒 Files selected for processing (5)
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
🧠 Learnings (3)
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
🧬 Code graph analysis (2)
e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (5)
  • encode (41-41)
  • concatBytes (41-41)
  • collectBytes (418-444)
  • compareBytes (447-480)
  • createDelayedStream (41-41)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (1)
  • createStreamConsumer (371-394)
🪛 Biome (2.1.2)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx

[error] 55-55: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
🔇 Additional comments (9)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (3)

1-8: LGTM! Imports are correct for Vue.

The imports properly use Vue-specific APIs (Composition API hooks, Suspense, defineComponent) and TanStack Vue Router/Start libraries. The previous React import issue has been successfully resolved.


50-60: Static analysis false positive: Biome applies React rules to Vue code.

Biome's warning about the children prop on line 55 is a false positive. Biome is applying React-specific linting rules (lint/correctness/noChildrenProp) to Vue code. The Suspense slot object syntax {{ default: ..., fallback: ... }} is the correct Vue JSX pattern, and the children prop usage depends on the Await component's API from @tanstack/vue-router.

Since this code mirrors React tests (per PR objectives) and uses framework-specific imports correctly, the pattern is intentional.


84-103: LGTM! Route configuration is correct.

The loader properly implements the "mixed" streaming pattern by returning:

  • Immediate data available synchronously
  • Deferred promise resolving after 100ms
  • RawStream with delayed chunks for client-side consumption

The component wiring and route export follow Vue Router conventions correctly.

e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (3)

1-10: LGTM! Vue Composition API imports are now correct.

The previous critical issue (React hooks in Vue component) has been successfully resolved. All imports now correctly use Vue's Composition API.


77-125: LGTM! Render function correctly uses Vue refs.

All reactive state is properly accessed with .value syntax, and the conditional rendering logic is sound.


128-152: LGTM! Route definition follows TanStack Router best practices.

The loader correctly creates RawStream instances with binary hints for testing, and the component is properly wired.

e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx (3)

1-8: LGTM! Imports correctly use Vue Composition API.

The imports are now properly aligned with Vue 3 Composition API (defineComponent, onMounted, ref) and the framework-specific router/start packages. The previous React import issue has been addressed.


39-78: LGTM! Render logic correctly implements Vue JSX patterns.

The render function properly accesses reactive values with .value, implements clear loading/error/success states, and includes test-friendly attributes for e2e verification.


82-99: LGTM! Loader correctly creates and wraps multiple streams.

The loader creates two independent delayed streams with different timing characteristics (30ms vs 50ms), properly wraps them in RawStream for SSR serialization, and returns a well-structured payload for concurrent consumption testing.

Comment on lines 48 to 50
if (!textData || !binaryData) {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Handle loading state in early return path.

If textData or binaryData is falsy, the early return leaves isLoading as true indefinitely, causing the UI to display "Loading..." forever.

🔎 Proposed fix
     if (!textData || !binaryData) {
+      isLoading.value = false
+      error.value = 'Missing stream data from loader'
       return
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!textData || !binaryData) {
return
}
if (!textData || !binaryData) {
isLoading.value = false
error.value = 'Missing stream data from loader'
return
}
🤖 Prompt for AI Agents
In e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx around lines 48
to 50, the early return when textData or binaryData is falsy leaves isLoading
true causing a permanent "Loading..." state; update the early-return path to
update loading state (e.g., set isLoading to false) and optionally set an error
or empty-data flag before returning so the UI can render a non-loading state.

Comment on lines 17 to 21
onMounted(() => {
const rawData = loaderData.value.rawData
if (!rawData) {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Misleading state when rawData is missing.

If rawData doesn't exist, the function returns early while isConsuming remains true (initialized on line 14). This causes the UI to display "Loading..." indefinitely even though no stream consumption is happening.

🔎 Proposed fix
 onMounted(() => {
   const rawData = loaderData.value.rawData
   if (!rawData) {
+    isConsuming.value = false
     return
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onMounted(() => {
const rawData = loaderData.value.rawData
if (!rawData) {
return
}
onMounted(() => {
const rawData = loaderData.value.rawData
if (!rawData) {
isConsuming.value = false
return
}
🤖 Prompt for AI Agents
In e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx around lines 17 to
21, the onMounted early-return leaves isConsuming true when
loaderData.value.rawData is missing, causing the UI to show "Loading..."
forever; update the branch so that before returning you set isConsuming to false
(or explicitly toggle the consuming state to false) so the component reflects
that no stream will be consumed, or alternatively check rawData earlier and only
set isConsuming to true after confirming rawData exists.

Comment on lines 21 to 23
if (!first || !second) {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Handle missing streams more gracefully.

The early return leaves isConsuming as true, causing the UI to display "Loading..." indefinitely if streams are missing. While this is a defensive check that shouldn't trigger during normal operation, consider cleaning up the loading state for better UX in edge cases.

🔎 Suggested fix
     const first = loaderData.value.first
     const second = loaderData.value.second
     if (!first || !second) {
+      isConsuming.value = false
+      error.value = 'Streams not available'
       return
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!first || !second) {
return
}
if (!first || !second) {
isConsuming.value = false
error.value = 'Streams not available'
return
}
🤖 Prompt for AI Agents
In e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx around lines 21 to
23, the early return when either `first` or `second` stream is missing leaves
`isConsuming` true and the UI stuck on "Loading..."; fix by clearing the loading
state before returning (set `isConsuming = false`) and optionally set an
error/cleanup flag or call any stream close/cleanup logic so the component exits
the loading state gracefully in this edge case.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
e2e/vue-start/basic/tests/raw-stream.spec.ts (1)

14-16: Comment incorrectly references React instead of Vue.

The comment mentions "React hydration" but this is a Vue test file. This was flagged in a previous review.

🔎 Suggested fix
 // Wait time for hydration to complete after page load
-// This needs to be long enough for React hydration to attach event handlers
+// This needs to be long enough for Vue hydration to attach event handlers
 const HYDRATION_WAIT = 1000
🧹 Nitpick comments (2)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)

102-115: Consider removing unnecessary async keyword.

The loader is marked async but createDelayedStream returns synchronously. The async keyword is not needed here, though it's harmless.

🔎 Suggested simplification
 export const Route = createFileRoute('/raw-stream/ssr-single')({
-  loader: async () => {
+  loader: () => {
     const stream = createDelayedStream(
e2e/vue-start/basic/src/raw-stream-fns.ts (1)

40-41: Export references function defined later in file.

concatBytes is exported on line 41 but defined at line 78. While this works due to JavaScript hoisting for function declarations, placing exports after their definitions improves readability.

🔎 Consider moving exports after definitions
+// Export helpers for use in components and SSR routes
+export { encode, createDelayedStream, concatBytes }
+
 // Helper to concatenate byte arrays
 function concatBytes(chunks: Array<Uint8Array>): Uint8Array {
   ...
 }
-
-// Export helpers for use in components and SSR routes
-export { encode, createDelayedStream, concatBytes }

Alternatively, add export directly to the function definition.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b3dfe4 and 5fb240e.

📒 Files selected for processing (7)
  • e2e/vue-start/basic/src/raw-stream-fns.ts
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/src/raw-stream-fns.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/src/raw-stream-fns.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
🧬 Code graph analysis (3)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (1)
  • createStreamConsumer (392-425)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (2)
e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)
  • Route (77-96)
e2e/vue-start/basic/src/raw-stream-fns.ts (3)
  • createStreamConsumer (392-425)
  • createDelayedStream (41-41)
  • encode (41-41)
e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
e2e/solid-start/basic/src/raw-stream-fns.ts (2)
  • collectBytes (418-444)
  • compareBytes (447-480)
🪛 Biome (2.1.2)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx

[error] 84-84: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (16)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (3)

1-15: Correct Vue imports and setup.

The imports are properly using Vue's Composition API (ref, watch, onMounted, onBeforeUnmount, Suspense, defineComponent) along with TanStack router utilities. This correctly addresses the previous React import issue.


79-89: Vue Await component uses children prop intentionally.

The Biome linter flags the children prop usage, but this is the documented pattern for @tanstack/vue-router's Await component in Vue JSX. Unlike React where children are passed as nested elements, Vue's JSX often uses the children prop for render functions. This is a false positive from Biome which is React-focused.


44-59: Well-structured lifecycle and cleanup handling.

The hasStarted flag prevents duplicate stream consumption, and the watcher is properly stopped in onBeforeUnmount. The guard conditions at line 51 correctly prevent re-consumption when data already exists or errors occurred.

e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (2)

1-8: Proper Vue framework imports.

The file correctly uses Vue's Composition API imports and TanStack router/start utilities. Previous React import issues have been resolved.


37-56: Robust stream consumption lifecycle.

The hasStarted flag and watcher cleanup pattern properly prevents race conditions and resource leaks. The guard at line 44 ensures the stream is consumed only once.

e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (3)

1-10: Correct Vue framework imports and utilities.

The file properly uses Vue's Composition API and TanStack utilities. The binary comparison helpers (collectBytes, compareBytes, concatBytes) are well-structured for byte-level verification.


78-101: Robust lifecycle management with proper cleanup.

The hasStarted flag and stopWatcher cleanup pattern properly prevents duplicate consumption and cleans up the watcher on unmount. The multiple guard conditions ensure streams are only consumed once and only when both are available.


158-182: Binary hint configuration is correct.

Both textData and binaryData RawStreams are properly configured with { hint: 'binary' } to test base64 encoding behavior.

e2e/vue-start/basic/tests/raw-stream.spec.ts (4)

18-148: Comprehensive Client RPC test coverage.

The tests thoroughly cover single streams, multiple streams, timing scenarios (JSON ends first, raw ends first), large binary data, and mixed streaming. Appropriate timeouts and hydration waits are used.


151-262: Well-structured SSR loader tests with proper skip conditions.

Good use of test.skip(isPrerender, ...) for tests that don't work in prerender mode. Both direct navigation and client-side navigation scenarios are covered.


486-553: Thorough multiplexing tests.

The interleaved streams, burst-pause-burst, and three concurrent streams tests provide good coverage for the multiplexing protocol. The JSON parsing and individual stream verification is well done.


631-675: Good edge case coverage.

Empty stream and error stream tests verify important boundary conditions. The error propagation test confirms that stream errors are correctly surfaced to the client.

e2e/vue-start/basic/src/raw-stream-fns.ts (4)

4-38: Well-designed stream creation utilities.

createDelayedStream and createVariableDelayStream provide flexible timing control for tests. The encode helper is a clean abstraction over TextEncoder.


367-496: Robust stream consumption with proper resource management.

The getActualStream helper correctly handles both RawStream and plain ReadableStream types. The WeakMap caches prevent duplicate consumption, and all readers are properly released in finally blocks.


498-532: Clear byte comparison semantics.

compareBytes returns well-documented results: mismatchIndex: -1 for length mismatch, null for full match, or the specific index for byte mismatch. This provides good debugging information for test failures.


335-365: Good edge case test handlers.

emptyStreamFn tests zero-byte streams, and errorStreamFn tests mid-stream errors with proper controller.error() usage. These cover important boundary conditions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)

50-69: Same edge case consideration as ssr-mixed.tsx.

If rawData is never available, isConsuming stays true indefinitely. Consider setting isConsuming.value = false when rawData is falsy for defensive handling.

e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx (1)

58-76: Same edge case as other SSR routes.

If either first or second stream is never available, the UI remains in a loading state indefinitely. For consistency with the pattern across these test routes, consider updating the loading state when streams are unavailable.

e2e/vue-start/basic/tests/raw-stream.spec.ts (1)

14-16: Comment mentions React hydration in Vue test file.

The comment on line 15 refers to "React hydration" but this is a Vue test suite. Update for accuracy.

🔎 Suggested fix
 // Wait time for hydration to complete after page load
-// This needs to be long enough for React hydration to attach event handlers
+// This needs to be long enough for Vue hydration to attach event handlers
 const HYDRATION_WAIT = 1000
🧹 Nitpick comments (1)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)

57-76: Consider handling the edge case when rawData is never available.

If loaderData.value.rawData is undefined on initial mount and never becomes truthy, isConsuming remains true (set at line 22), causing the UI to display "Loading..." indefinitely. While this shouldn't occur in normal operation, adding defensive handling improves robustness.

🔎 Suggested improvement
     onMounted(() => {
       stopWatcher = watch(
         () => loaderData.value.rawData,
         (rawData) => {
-          if (!rawData || rawData === lastRawData) {
+          if (!rawData) {
+            isConsuming.value = false
+            return
+          }
+          if (rawData === lastRawData) {
             return
           }
           lastRawData = rawData
           void consumeRawStream(rawData)
         },
         { immediate: true },
       )
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fb240e and fc217fe.

📒 Files selected for processing (8)
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
  • e2e/vue-start/basic/src/vite-env.d.ts
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/vite.config.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/vite-env.d.ts
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/vite.config.ts
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/vite-env.d.ts
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/vite.config.ts
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
🧠 Learnings (5)
📓 Common learnings
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx
  • e2e/vue-start/basic/tests/raw-stream.spec.ts
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx
  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.

Applied to files:

  • e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx
🧬 Code graph analysis (4)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (2)
e2e/solid-start/basic/src/routes/raw-stream/ssr-mixed.tsx (1)
  • Route (77-96)
e2e/vue-start/basic/src/raw-stream-fns.ts (3)
  • createStreamConsumer (392-425)
  • createDelayedStream (41-41)
  • encode (41-41)
e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (1)
e2e/vue-start/basic/src/raw-stream-fns.ts (1)
  • createStreamConsumer (392-425)
e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (1)
e2e/solid-start/basic/src/raw-stream-fns.ts (2)
  • collectBytes (418-444)
  • compareBytes (447-480)
e2e/vue-start/basic/tests/raw-stream.spec.ts (1)
e2e/react-start/streaming-ssr/tests/fixtures.ts (1)
  • expect (90-90)
🪛 Biome (2.1.2)
e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx

[error] 101-101: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (19)
e2e/vue-start/basic/vite.config.ts (1)

36-38: LGTM!

The define block correctly injects the __TSR_PRERENDER__ compile-time constant using JSON.stringify to ensure proper serialization. This pattern aligns with Vite's best practices for global constants.

e2e/vue-start/basic/src/vite-env.d.ts (1)

12-13: LGTM!

The ambient declaration correctly types __TSR_PRERENDER__ as a boolean, providing proper TypeScript support for the global constant injected via Vite's define configuration.

e2e/vue-start/basic/src/routes/raw-stream/ssr-mixed.tsx (3)

17-51: Race condition handling is well implemented.

The consumeRunId pattern effectively prevents stale async updates from corrupting state when the stream changes or component remounts. Good error handling with proper state cleanup in both success and error paths.


96-106: Vue Suspense slot pattern is correct for JSX.

The static analysis hint about children prop is a false positive. In Vue JSX, the Await component from @tanstack/vue-router uses a render function pattern where children is passed as a prop. This differs from React's JSX children pattern and is the correct approach for Vue TSX.


130-150: Route configuration looks correct.

The loader properly creates delayed streams, wraps them in RawStream, and returns mixed data types (immediate, deferred promise, rawData). The shouldReload: __TSR_PRERENDER__ configuration aligns with the Solid adapter pattern shown in the relevant code snippets.

e2e/vue-start/basic/src/routes/raw-stream/ssr-single.tsx (2)

10-44: Stream consumption logic is well-structured.

The consumeRunId pattern properly handles race conditions, and the error handling covers both success and failure paths with appropriate state updates.


119-133: LGTM!

The loader configuration correctly creates a delayed stream with multiple chunks and returns metadata alongside the RawStream. The shouldReload: __TSR_PRERENDER__ flag ensures proper behavior during prerendering.

e2e/vue-start/basic/src/routes/raw-stream/ssr-multiple.tsx (2)

20-47: Parallel stream consumption is well implemented.

Using Promise.all for concurrent consumption of both streams is appropriate, and the consumeRunId pattern prevents race conditions when streams change.


133-151: LGTM!

The loader correctly creates two independent delayed streams with different timing (30ms vs 50ms), demonstrating the multiplexing capability being tested.

e2e/vue-start/basic/src/routes/raw-stream/ssr-binary-hint.tsx (3)

12-35: Well-structured test data constants.

Defining expected byte sequences at module level enables client-side verification against server-generated streams. The type definitions TextMatch and BinaryMatch provide clear contracts for the verification results.


46-85: Byte collection and comparison logic is correct.

The consumeHintStreams function properly collects bytes from both streams, compares them against expected values, and decodes text content where applicable. The spread operator usage with compareBytes result is clean.


179-204: LGTM!

The loader correctly demonstrates the binary hint feature by creating both text-based and pure binary streams, both configured with { hint: 'binary' }. This validates that the binary hint consistently uses base64 encoding regardless of content type.

e2e/vue-start/basic/tests/raw-stream.spec.ts (4)

18-61: Client RPC tests are well-structured.

Good coverage of single stream, multiple streams, and timing scenarios. The pattern of waiting for visibility, then hydration, then clicking is appropriate for e2e tests.


186-208: Good use of conditional test skip for prerender limitation.

The comment clearly explains why the SSR mixed streaming test is skipped in prerender mode. The IIFE pattern (isPrerender ? test.skip : test)(...) is a clean way to conditionally skip tests.


377-392: Byte-by-byte verification tests are thorough.

Parsing the JSON result and asserting on individual match properties provides strong verification that the streaming and encoding work correctly at the byte level.


622-666: Edge case coverage is excellent.

Testing empty streams (zero-byte) and error propagation ensures the RawStream implementation handles boundary conditions correctly. The assertions verify both the expected state and the error message content.

e2e/vue-start/basic/src/routes/raw-stream/ssr-text-hint.tsx (3)

12-47: Thorough test data setup for text hint validation.

The three test cases (pure text, mixed content with invalid UTF-8, pure binary) comprehensively validate the text hint's behavior:

  • UTF-8 encoding for valid text
  • Base64 fallback for invalid UTF-8 sequences

The type definitions clearly distinguish between text matches (with asText) and binary matches.


59-112: Stream consumption logic handles all three streams correctly.

The parallel consumption via Promise.all is appropriate, and the comparison logic properly handles each stream type with the correct expected bytes.


222-258: LGTM!

The loader correctly demonstrates text hint behavior across three scenarios:

  1. Pure text - should use UTF-8 encoding
  2. Mixed content - UTF-8 for valid text, base64 for invalid UTF-8 chunks
  3. Pure binary - must fallback to base64 entirely

The comments clearly document the expected behavior for each stream.

@birkskyum birkskyum merged commit 325c356 into main Dec 30, 2025
6 checks passed
@birkskyum birkskyum deleted the raw-stream-sync branch December 30, 2025 01:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants