feat(tanstack-query): live query options#721
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis update introduces "live query" support to the TanStack Query integration. It adds new utilities, types, and documentation for live queries, including Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Hook as Query Hook (e.g., useQuery)
participant Utils as ProcedureUtils.experimental_liveOptions
participant Client as Query Client
participant LiveQuery as experimental_liveQuery
User->>Hook: Calls useQuery with liveOptions
Hook->>Utils: Requests liveOptions (input, context)
Utils->>Client: Prepares queryFn (expects async iterable)
Hook->>LiveQuery: Calls queryFn (via experimental_liveQuery)
LiveQuery->>Client: Invokes client with input/context
Client-->>LiveQuery: Returns async iterable
loop For each chunk
LiveQuery->>Hook: Updates query cache with chunk
end
LiveQuery->>Hook: Returns last chunk as result
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Summary of Changes
Hello @unnoq, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request significantly enhances the TanStack Query integration by introducing a new "live query" mechanism. This feature enables applications to consume real-time data streams where each new data point completely replaces the previous one, offering a distinct and powerful alternative to the existing streamed queries that accumulate data. The changes include core implementation, comprehensive documentation, and extensive testing across multiple frontend frameworks to ensure broad compatibility and stability.
Highlights
- New Live Query Functionality: Introduced
experimental_liveQueryandexperimental_liveOptionsto support real-time data updates. Unlike streamed queries that accumulate chunks, live queries replace the entire query result with each new chunk received from an Event Iterator, providing immediate reflection of the latest state. - Comprehensive Documentation: Added a new section in the
tanstack-query.mddocumentation detailing the usage and behavior of.liveOptions, including code examples and notes on integration with Client Retry for enhanced reliability. - Cross-Framework Integration: Extended type definition tests and utility functions to ensure seamless integration and correct type inference for live queries across various frontend frameworks, including React, Angular, Solid.js, Svelte, and Vue.js.
- Robust Testing: Introduced new unit tests for
experimental_liveQueryandexperimental_liveOptions, covering core functionality, abort signal handling,skipTokenbehavior, and error handling for unsupported output types, ensuring the reliability of the new feature.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
Codecov ReportAll modified and coverable lines are covered by tests ✅ 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Code Review
This pull request introduces liveOptions for live queries with TanStack Query. I've found one critical issue that could lead to a runtime error and a few medium-severity suggestions to improve test clarity. Once these are addressed, this will be a solid contribution.
More templates
@orpc/arktype
@orpc/client
@orpc/contract
@orpc/experimental-durable-event-iterator
@orpc/hey-api
@orpc/nest
@orpc/openapi
@orpc/openapi-client
@orpc/react
@orpc/react-query
@orpc/server
@orpc/shared
@orpc/solid-query
@orpc/standard-server
@orpc/standard-server-aws-lambda
@orpc/standard-server-fetch
@orpc/standard-server-node
@orpc/standard-server-peer
@orpc/svelte-query
@orpc/tanstack-query
@orpc/trpc
@orpc/valibot
@orpc/vue-colada
@orpc/vue-query
@orpc/zod
commit: |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/tanstack-query/src/live-query.ts (1)
12-24: Solid implementation with minor safety concerns.The core logic correctly implements live query behavior:
- Proper async iteration with abort signal checking
- Cache updates on each chunk (replacing vs accumulating)
- Clean integration with TanStack Query's QueryFunction interface
However, consider these improvements:
return async (context) => { const stream = await queryFn(context) + let lastData: TQueryFnData | undefined for await (const chunk of stream) { if (context.signal.aborted) { break } + lastData = chunk context.client.setQueryData<TQueryFnData>(context.queryKey, chunk) } - return context.client.getQueryData(context.queryKey)! + return lastData ?? context.client.getQueryData(context.queryKey) as TQueryFnData }This ensures we return the last emitted value even if cache retrieval fails, and removes the unsafe non-null assertion.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
apps/content/docs/integrations/tanstack-query.md(3 hunks)packages/tanstack-query/src/live-query.test.ts(1 hunks)packages/tanstack-query/src/live-query.ts(1 hunks)packages/tanstack-query/src/procedure-utils.angular.test-d.ts(1 hunks)packages/tanstack-query/src/procedure-utils.react.test-d.ts(1 hunks)packages/tanstack-query/src/procedure-utils.solid.test-d.ts(1 hunks)packages/tanstack-query/src/procedure-utils.svelte.test-d.ts(1 hunks)packages/tanstack-query/src/procedure-utils.test-d.ts(1 hunks)packages/tanstack-query/src/procedure-utils.test.ts(3 hunks)packages/tanstack-query/src/procedure-utils.ts(5 hunks)packages/tanstack-query/src/procedure-utils.vue.test-d.ts(1 hunks)packages/tanstack-query/src/types.ts(1 hunks)packages/tanstack-query/tests/live-query.test.tsx(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (9)
packages/tanstack-query/src/procedure-utils.solid.test-d.ts (1)
packages/tanstack-query/tests/shared.tsx (1)
queryClient(8-14)
packages/tanstack-query/src/procedure-utils.svelte.test-d.ts (1)
packages/tanstack-query/tests/shared.tsx (1)
queryClient(8-14)
packages/tanstack-query/src/procedure-utils.react.test-d.ts (1)
packages/tanstack-query/tests/shared.tsx (1)
queryClient(8-14)
packages/tanstack-query/src/procedure-utils.test.ts (3)
packages/tanstack-query/tests/shared.tsx (1)
queryClient(8-14)packages/tanstack-query/src/types.ts (1)
OPERATION_CONTEXT_SYMBOL(30-30)packages/tanstack-query/src/index.ts (1)
OPERATION_CONTEXT_SYMBOL(8-8)
packages/tanstack-query/src/procedure-utils.angular.test-d.ts (1)
packages/tanstack-query/tests/shared.tsx (1)
queryClient(8-14)
packages/tanstack-query/src/live-query.ts (1)
packages/shared/src/index.ts (1)
Promisable(16-16)
packages/tanstack-query/src/procedure-utils.vue.test-d.ts (1)
packages/tanstack-query/tests/shared.tsx (1)
queryClient(8-14)
packages/tanstack-query/src/procedure-utils.test-d.ts (1)
packages/tanstack-query/tests/shared.tsx (1)
queryClient(8-14)
packages/tanstack-query/src/procedure-utils.ts (5)
packages/shared/src/args.ts (1)
MaybeOptionalOptions(1-3)packages/tanstack-query/src/types.ts (6)
QueryKeyOptions(39-41)experimental_LiveQueryOutput(16-16)QueryOptionsIn(43-46)QueryOptionsBase(48-54)OPERATION_CONTEXT_SYMBOL(30-30)OperationContext(32-37)packages/tanstack-query/src/key.ts (1)
generateOperationKey(3-12)packages/tanstack-query/src/live-query.ts (1)
experimental_liveQuery(4-25)packages/shared/src/iterator.ts (1)
isAsyncIteratorObject(4-10)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: lint
- GitHub Check: publish-commit
🔇 Additional comments (21)
packages/tanstack-query/src/types.ts (2)
16-16: LGTM! Clean type extraction for live queries.The
experimental_LiveQueryOutputtype correctly extracts the yielded item type from anAsyncIterable, which is exactly what's needed for live queries that emit individual chunks rather than accumulated arrays.
20-20: Approve the OperationType extension.Adding
'live'to the union type is consistent with the existing operation types and follows the established pattern.packages/tanstack-query/tests/live-query.test.tsx (1)
7-40: Comprehensive test coverage for live query React integration.This test effectively verifies the core live query behavior:
- Sequential data updates replacing previous values (not accumulating)
- Proper async state handling with
act()andvi.waitFor()- Refetch functionality resetting to the first value
The test structure is solid and covers the key differences between live and streamed queries.
packages/tanstack-query/src/live-query.test.ts (1)
8-70: Excellent test coverage for live query core functionality.These tests comprehensively verify:
- Sequential cache updates as chunks are yielded
- Proper resolution with the final value
- Abort signal handling with early termination
- Cleanup execution in generator finally blocks
The test structure effectively validates the live query contract and error handling.
packages/tanstack-query/src/procedure-utils.angular.test-d.ts (1)
161-225: Comprehensive type safety validation for Angular live queries.This test suite effectively validates:
- Correct data type inference (
UtilsOutput[number]vsUtilsOutput)- Error type propagation across all Angular Query hooks
- Integration with
select,initialData, and error handling options- Consistency with the existing test patterns
The
@ts-expect-errorannotations appropriately document known TypeScript inference limitations withinjectQueries.packages/tanstack-query/src/procedure-utils.solid.test-d.ts (1)
152-213: LGTM! Comprehensive type testing for live queries.The
.liveOptionstest suite correctly implements type validation for the new live query feature. The key insight that data should be typed asUtilsOutput[number](individual items) rather thanUtilsOutput(arrays) properly reflects the live query semantics where each chunk replaces the entire result.packages/tanstack-query/src/procedure-utils.svelte.test-d.ts (1)
153-214: LGTM! Proper Svelte adaptation of live query tests.The test suite correctly adapts the live query functionality for Svelte's reactive store patterns, using
createQuery,createQueries, andget()appropriately. Type expectations are consistent with other framework implementations.apps/content/docs/integrations/tanstack-query.md (2)
118-133: Excellent documentation for the live query feature.The documentation clearly explains the key difference between
.liveOptionsand.streamedOptions- that live queries replace the entire result with each chunk rather than accumulating them. The example usage and recommendation to combine with Client Retry plugin provide practical guidance for users.
292-305: Good update to include live queries in operation context.The addition of
'live'to theGET_OPERATION_TYPEset properly extends the HTTP method selection logic to handle the new live query operation type, maintaining consistency with existing query types.packages/tanstack-query/src/procedure-utils.test-d.ts (2)
301-351: Comprehensive testing for live query keys.The
.liveKeytest suite thoroughly validates all aspects of live query key generation, including optional/required input handling, type inference, skipToken support, and query key overrides. The tests ensure type safety and proper integration with the broader query system.
353-429: Thorough validation of live query options.The
.liveOptionstests comprehensively cover the live query functionality, correctly validating that data types areUtilsOutput[number](individual items) rather thanUtilsOutput(arrays). The inclusion of error cases for non-async-iterable outputs provides important type safety guarantees.packages/tanstack-query/src/procedure-utils.vue.test-d.ts (1)
161-226: Proper Vue integration for live query tests.The test suite correctly adapts live query functionality for Vue's reactive system using
computed()and.valueaccessors. The TODO comments appropriately acknowledge Vue Query's type handling limitations while ensuring the core live query functionality is properly tested.packages/tanstack-query/src/procedure-utils.react.test-d.ts (1)
256-368: Excellent type inference for live queries!The
.liveOptionstest suite correctly verifies that live queries returnUtilsOutput[number](individual items from the async iterable) rather thanUtilsOutput(the full array). This properly reflects the live query behavior where each chunk replaces the entire result. The test coverage is comprehensive across all React Query hooks.packages/tanstack-query/src/procedure-utils.test.ts (4)
3-3: Good integration of live query dependency.The import and spy setup for
experimental_liveQueryproperly integrates the live query functionality for testing.
16-16: Proper test spy setup.The spy on
experimental_liveQueryenables verification of the integration between the utility functions and the core live query implementation.
169-176: Correct key generation for live queries.The
.liveKeytest verifies that query keys are generated with the correct'live'operation type, following the established pattern from other query utilities.
178-249: Comprehensive live query options testing.The test suite excellently covers all aspects of live query behavior:
- Normal operation: Verifies that the last yielded value (
'__2__') is returned and cached, demonstrating the data replacement behavior that distinguishes live queries from streamed queries- SkipToken handling: Properly tests disabled state and error throwing
- Error handling: Validates appropriate error message for unsupported output types
- Integration: Confirms proper integration with
experimental_liveQueryfunctionThe test structure mirrors existing patterns while correctly testing the unique live query semantics.
packages/tanstack-query/src/procedure-utils.ts (4)
5-5: Good type import for live query support.The import of
experimental_LiveQueryOutputproperly enables type inference for live queries that extract individual items from async iterables.
22-22: Proper import of live query implementation.The import of
experimental_liveQueryintegrates the core live query functionality from the dedicated module.
81-103: Excellent API design and documentation.The
experimental_liveKeyandexperimental_liveOptionsmethods follow the established patterns from existing query utilities while providing clear documentation that distinguishes live queries from streamed queries. The key insight that "live queries replace the entire result with each new chunk received" is well-explained.
234-270: Solid implementation following established patterns.The live query utilities implementation is excellent:
- Consistent API: Mirrors the structure of existing
experimental_streamedOptions- Proper integration: Uses
experimental_liveQuerywrapper correctly- Error handling: Validates async iterator with appropriate error message
- Type safety: Works with
experimental_LiveQueryOutputfor correct type inference- Operation context: Properly sets operation type to
'live'for consistent trackingThe implementation maintains consistency with existing utilities while properly integrating the live query functionality.
There was a problem hiding this comment.
Pull Request Overview
Adds experimental "live" query support to the Tanstack Query integration, enabling full-result replacement on each emitted chunk.
- Introduces
experimental_liveOptionsandexperimental_liveKeyutilities alongside type updates and key generation. - Implements
experimental_liveQueryruntime to drive live updates via anAsyncIterable. - Updates test suites across frameworks and documentation to cover live-query features.
Reviewed Changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/live-query.test.tsx | Adds React hook test for streamed vs. live query behavior |
| src/types.ts | Introduces experimental_LiveQueryOutput and adds 'live' to OperationType |
| src/procedure-utils.ts | Implements experimental_liveKey & .experimental_liveOptions methods |
| src/procedure-utils.*.test-d.ts (all flavors) | Expands type-level tests for live options/key in Vue, Svelte, Solid, React, Angular |
| src/live-query.ts & src/live-query.test.ts | Implements and tests the runtime for live queries |
| apps/content/docs/integrations/tanstack-query.md | Adds documentation for live query options |
Comments suppressed due to low confidence (4)
apps/content/docs/integrations/tanstack-query.md:61
- Several stray comment lines (
//) were added here without context. These should be removed to clean up the markdown and avoid confusion.
//
packages/tanstack-query/src/procedure-utils.ts:88
- The
QueryKeyOptionsgeneric expects both a type and input parameter. For clarity and type safety, specify the operation type explicitly (e.g.QueryKeyOptions<'live', TInput>).
QueryKeyOptions<TInput>
packages/tanstack-query/tests/live-query.test.tsx:2
- renderHook is not exported from '@testing-library/react'; it should be imported from '@testing-library/react-hooks' (or the appropriate testing library package) to ensure the hook renders correctly.
import { renderHook } from '@testing-library/react'
packages/tanstack-query/src/live-query.test.ts:1
- Relative import path appears incorrect; the shared test helper is under
tests/shared, so fromsrcthis should likely be../../tests/shared.
import { queryClient } from '../tests/shared'
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
packages/tanstack-query/src/live-query.test.ts (1)
8-8: Remove the async modifier from the describe callback.The describe callback should be synchronous to avoid unexpected test runner behavior.
🧹 Nitpick comments (3)
packages/tanstack-query/src/live-query.test.ts (3)
20-24: Improve type safety by avoidingas anyassertion.The
as anytype assertion bypasses type checking and could mask potential type issues. Consider defining a proper type interface or using more specific typing.- const resultPromise = expect(queryFn({ - queryKey: ['live-query'], - signal: controller.signal, - client: queryClient, - } as any)).resolves.toEqual(3) + const resultPromise = expect(queryFn({ + queryKey: ['live-query'], + signal: controller.signal, + client: queryClient, + })).resolves.toEqual(3)
55-59: Improve type safety by avoidingas anyassertion.Similar to the previous test, consider removing the
as anyassertion for better type safety.- const resultPromise = expect(queryFn({ - queryKey: ['live-query'], - signal: controller.signal, - client: queryClient, - } as any)).resolves.toEqual(1) + const resultPromise = expect(queryFn({ + queryKey: ['live-query'], + signal: controller.signal, + client: queryClient, + })).resolves.toEqual(1)
76-82: Improve type safety by avoidingas anyassertion.Consider removing the
as anyassertion here as well for consistency and better type safety.- await expect(queryFn({ - queryKey: ['live-query'], - signal: new AbortController().signal, - client: queryClient, - } as any)).rejects.toThrowError( + await expect(queryFn({ + queryKey: ['live-query'], + signal: new AbortController().signal, + client: queryClient, + })).rejects.toThrowError(
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/tanstack-query/src/live-query.test.ts(1 hunks)packages/tanstack-query/src/live-query.ts(1 hunks)packages/tanstack-query/src/procedure-utils.test-d.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/tanstack-query/src/live-query.ts
- packages/tanstack-query/src/procedure-utils.test-d.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: lint
- GitHub Check: publish-commit
🔇 Additional comments (3)
packages/tanstack-query/src/live-query.test.ts (3)
26-32: Well-structured async testing pattern.Good use of
vi.waitForto handle async assertions and verify that the query client cache updates correctly with each yielded value.
37-69: Excellent test coverage for abort signal behavior.This test comprehensively validates the cleanup logic when an abort signal is triggered, ensuring the finally block executes and the query resolves with the last yielded value.
71-84: Comprehensive error handling test with descriptive error message.The test properly validates the error case when no data is yielded, and the error message is informative and includes the query key for debugging.
Use
.liveOptionsto configure live queries for Event Iterator. Unlike.streamedOptionswhich accumulates chunks, live queries replace the entire result with each new chunk receivedSummary by CodeRabbit
New Features
Bug Fixes
Tests