@@ -10,12 +10,16 @@ import { BaseQueryBuilder, createLiveQueryCollection } from '@tanstack/db'
1010import type {
1111 ChangeMessage ,
1212 Collection ,
13+ CollectionConfigSingleRowOption ,
1314 CollectionStatus ,
1415 Context ,
1516 GetResult ,
17+ InferResultType ,
1618 InitialQueryBuilder ,
1719 LiveQueryCollectionConfig ,
20+ NonSingleResult ,
1821 QueryBuilder ,
22+ SingleResult ,
1923} from '@tanstack/db'
2024import type { Signal } from '@angular/core'
2125
@@ -24,16 +28,14 @@ import type { Signal } from '@angular/core'
2428 * Contains reactive signals for the query state and data.
2529 */
2630export interface InjectLiveQueryResult <
27- TResult extends object = any ,
28- TKey extends string | number = string | number ,
29- TUtils extends Record < string , any > = { } ,
31+ TContext extends Context ,
3032> {
3133 /** A signal containing the complete state map of results keyed by their ID */
32- state : Signal < Map < TKey , TResult > >
33- /** A signal containing the results as an array */
34- data : Signal < Array < TResult > >
34+ state : Signal < Map < string | number , GetResult < TContext > > >
35+ /** A signal containing the results as an array, or single result for findOne queries */
36+ data : Signal < InferResultType < TContext > >
3537 /** A signal containing the underlying collection instance (null for disabled queries) */
36- collection : Signal < Collection < TResult , TKey , TUtils > | null >
38+ collection : Signal < Collection < GetResult < TContext > , string | number , { } > | null >
3739 /** A signal containing the current status of the collection */
3840 status : Signal < CollectionStatus | `disabled`>
3941 /** A signal indicating whether the collection is currently loading */
@@ -48,6 +50,38 @@ export interface InjectLiveQueryResult<
4850 isCleanedUp : Signal < boolean >
4951}
5052
53+ export interface InjectLiveQueryResultWithCollection <
54+ TResult extends object = any ,
55+ TKey extends string | number = string | number ,
56+ TUtils extends Record < string , any > = { } ,
57+ > {
58+ state : Signal < Map < TKey , TResult > >
59+ data : Signal < Array < TResult > >
60+ collection : Signal < Collection < TResult , TKey , TUtils > | null >
61+ status : Signal < CollectionStatus | `disabled`>
62+ isLoading : Signal < boolean >
63+ isReady : Signal < boolean >
64+ isIdle : Signal < boolean >
65+ isError : Signal < boolean >
66+ isCleanedUp : Signal < boolean >
67+ }
68+
69+ export interface InjectLiveQueryResultWithSingleResultCollection <
70+ TResult extends object = any ,
71+ TKey extends string | number = string | number ,
72+ TUtils extends Record < string , any > = { } ,
73+ > {
74+ state : Signal < Map < TKey , TResult > >
75+ data : Signal < TResult | undefined >
76+ collection : Signal < ( Collection < TResult , TKey , TUtils > & SingleResult ) | null >
77+ status : Signal < CollectionStatus | `disabled`>
78+ isLoading : Signal < boolean >
79+ isReady : Signal < boolean >
80+ isIdle : Signal < boolean >
81+ isError : Signal < boolean >
82+ isCleanedUp : Signal < boolean >
83+ }
84+
5185export function injectLiveQuery <
5286 TContext extends Context ,
5387 TParams extends any ,
@@ -57,7 +91,7 @@ export function injectLiveQuery<
5791 params : TParams
5892 q : InitialQueryBuilder
5993 } ) => QueryBuilder < TContext >
60- } ) : InjectLiveQueryResult < GetResult < TContext > >
94+ } ) : InjectLiveQueryResult < TContext >
6195export function injectLiveQuery <
6296 TContext extends Context ,
6397 TParams extends any ,
@@ -67,25 +101,34 @@ export function injectLiveQuery<
67101 params : TParams
68102 q : InitialQueryBuilder
69103 } ) => QueryBuilder < TContext > | undefined | null
70- } ) : InjectLiveQueryResult < GetResult < TContext > >
104+ } ) : InjectLiveQueryResult < TContext >
71105export function injectLiveQuery < TContext extends Context > (
72106 queryFn : ( q : InitialQueryBuilder ) => QueryBuilder < TContext > ,
73- ) : InjectLiveQueryResult < GetResult < TContext > >
107+ ) : InjectLiveQueryResult < TContext >
74108export function injectLiveQuery < TContext extends Context > (
75109 queryFn : (
76110 q : InitialQueryBuilder ,
77111 ) => QueryBuilder < TContext > | undefined | null ,
78- ) : InjectLiveQueryResult < GetResult < TContext > >
112+ ) : InjectLiveQueryResult < TContext >
79113export function injectLiveQuery < TContext extends Context > (
80114 config : LiveQueryCollectionConfig < TContext > ,
81- ) : InjectLiveQueryResult < GetResult < TContext > >
115+ ) : InjectLiveQueryResult < TContext >
116+ // Pre-created collection without singleResult
117+ export function injectLiveQuery <
118+ TResult extends object ,
119+ TKey extends string | number ,
120+ TUtils extends Record < string , any > ,
121+ > (
122+ liveQueryCollection : Collection < TResult , TKey , TUtils > & NonSingleResult ,
123+ ) : InjectLiveQueryResultWithCollection < TResult , TKey , TUtils >
124+ // Pre-created collection with singleResult
82125export function injectLiveQuery <
83126 TResult extends object ,
84127 TKey extends string | number ,
85128 TUtils extends Record < string , any > ,
86129> (
87- liveQueryCollection : Collection < TResult , TKey , TUtils > ,
88- ) : InjectLiveQueryResult < TResult , TKey , TUtils >
130+ liveQueryCollection : Collection < TResult , TKey , TUtils > & SingleResult ,
131+ ) : InjectLiveQueryResultWithSingleResultCollection < TResult , TKey , TUtils >
89132export function injectLiveQuery ( opts : any ) {
90133 assertInInjectionContext ( injectLiveQuery )
91134 const destroyRef = inject ( DestroyRef )
@@ -156,19 +199,31 @@ export function injectLiveQuery(opts: any) {
156199 } )
157200
158201 const state = signal ( new Map < string | number , any > ( ) )
159- const data = signal < Array < any > > ( [ ] )
202+ const internalData = signal < Array < any > > ( [ ] )
160203 const status = signal < CollectionStatus | `disabled`> (
161204 collection ( ) ? `idle` : `disabled` ,
162205 )
163206
207+ // Returns single item for singleResult collections, array otherwise
208+ const data = computed ( ( ) => {
209+ const currentCollection = collection ( )
210+ if ( ! currentCollection ) {
211+ return internalData ( )
212+ }
213+ const config = ( currentCollection ) . config as
214+ | CollectionConfigSingleRowOption < any , any , any >
215+ | undefined
216+ return config ?. singleResult ? internalData ( ) [ 0 ] : internalData ( )
217+ } )
218+
164219 const syncDataFromCollection = (
165220 currentCollection : Collection < any , any , any > ,
166221 ) => {
167222 const newState = new Map ( currentCollection . entries ( ) )
168223 const newData = Array . from ( currentCollection . values ( ) )
169224
170225 state . set ( newState )
171- data . set ( newData )
226+ internalData . set ( newData )
172227 status . set ( currentCollection . status )
173228 }
174229
@@ -185,7 +240,7 @@ export function injectLiveQuery(opts: any) {
185240 if ( ! currentCollection ) {
186241 status . set ( `disabled` as const )
187242 state . set ( new Map ( ) )
188- data . set ( [ ] )
243+ internalData . set ( [ ] )
189244 cleanup ( )
190245 return
191246 }
0 commit comments