11import { type CompilableQuery , parseQuery } from '@powersync/common' ;
22import { usePowerSync } from '@powersync/react' ;
33import * as Tanstack from '@tanstack/react-query' ;
4- import { useEffect , useMemo , useState } from 'react' ;
4+ import { useEffect , useMemo , useState , useCallback } from 'react' ;
55
66export type PowerSyncQueryOptions < T > = {
77 query ?: string | CompilableQuery < T > ;
88 parameters ?: any [ ] ;
99} ;
1010
11- export type UseBaseQueryOptions < TQueryOptions > = TQueryOptions & PowerSyncQueryOptions < any > ;
12-
13- export type PowerSyncQueriesOptions < T extends any [ ] > = {
14- [ K in keyof T ] : Tanstack . UseQueryOptions < T [ K ] , any > & PowerSyncQueryOptions < T [ K ] > ;
15- } ;
16-
1711type PowerSyncQueryOption < T = any > = Tanstack . UseQueryOptions < T [ ] , any > & PowerSyncQueryOptions < T > ;
1812
1913type InferQueryResults < TQueries extends readonly any [ ] > = {
@@ -75,8 +69,10 @@ export function useQueries<TQueries extends readonly PowerSyncQueryOption[]>(
7569// Implementation
7670export function useQueries (
7771 options : {
78- queries : readonly ( Tanstack . UseQueryOptions < any , any > & PowerSyncQueryOptions < any > ) [ ] ;
79- combine ?: ( results : ( Tanstack . UseQueryResult < any , any > & { queryKey : Tanstack . QueryKey } ) [ ] ) => any ;
72+ queries : readonly ( Tanstack . UseQueryOptions & PowerSyncQueryOptions < unknown > ) [ ] ;
73+ combine ?: (
74+ results : ( Tanstack . UseQueryResult < unknown , Tanstack . DefaultError > & { queryKey : Tanstack . QueryKey } ) [ ]
75+ ) => unknown ;
8076 } ,
8177 queryClient : Tanstack . QueryClient = Tanstack . useQueryClient ( )
8278) {
@@ -85,24 +81,56 @@ export function useQueries(
8581 const [ tablesArr , setTablesArr ] = useState < string [ ] [ ] > ( ( ) => queriesInput . map ( ( ) => [ ] ) ) ;
8682 const [ errorsArr , setErrorsArr ] = useState < ( Error | undefined ) [ ] > ( ( ) => queriesInput . map ( ( ) => undefined ) ) ;
8783
88- const parsedQueries = useMemo ( ( ) => {
89- return queriesInput . map ( ( queryOptions : Tanstack . UseQueryOptions < any , any > & PowerSyncQueryOptions < any > ) => {
90- const { query, parameters = [ ] , ...rest } = queryOptions ;
91- let sqlStatement = '' ;
92- let queryParameters : any [ ] = [ ] ;
93- let error : Error | undefined = undefined ;
94- if ( query ) {
95- try {
96- const parsedQuery = parseQuery ( query , parameters ) ;
97- sqlStatement = parsedQuery . sqlStatement ;
98- queryParameters = parsedQuery . parameters ;
99- } catch ( e ) {
100- error = e as Error ;
101- }
102- }
103- return { query, parameters, rest, sqlStatement, queryParameters, error } ;
84+ const updateTablesArr = useCallback ( ( tables : string [ ] , idx : number ) => {
85+ setTablesArr ( ( prev ) => {
86+ if ( JSON . stringify ( prev [ idx ] ) === JSON . stringify ( tables ) ) return prev ;
87+ const next = [ ...prev ] ;
88+ next [ idx ] = tables ;
89+ return next ;
90+ } ) ;
91+ } , [ ] ) ;
92+
93+ const updateErrorsArr = useCallback ( ( error : Error , idx : number ) => {
94+ setErrorsArr ( ( prev ) => {
95+ if ( prev [ idx ] ?. message === error . message ) return prev ;
96+ const next = [ ...prev ] ;
97+ next [ idx ] = error ;
98+ return next ;
10499 } ) ;
105- } , [ queriesInput ] ) ;
100+ } , [ ] ) ;
101+
102+ const parsedQueries = useMemo ( ( ) => queriesInput . map ( ( queryOptions : Tanstack . UseQueryOptions < any , any > & PowerSyncQueryOptions < any > ) => {
103+ const { query, parameters = [ ] , ...rest } = queryOptions ;
104+ const parsed = ( ( ) => {
105+ if ( ! query ) {
106+ return { sqlStatement : '' , queryParameters : [ ] , error : undefined } ;
107+ }
108+
109+ try {
110+ const parsedQuery = parseQuery ( query , parameters ) ;
111+ return {
112+ sqlStatement : parsedQuery . sqlStatement ,
113+ queryParameters : parsedQuery . parameters ,
114+ error : undefined
115+ } ;
116+ } catch ( e ) {
117+ return {
118+ sqlStatement : '' ,
119+ queryParameters : [ ] ,
120+ error : e as Error
121+ } ;
122+ }
123+ } ) ( ) ;
124+
125+ return { query, parameters, rest, ...parsed } ;
126+ } ) , [ queriesInput ] ) ;
127+
128+ const stringifiedQueriesDeps = JSON . stringify (
129+ parsedQueries . map ( q => ( {
130+ sql : q . sqlStatement ,
131+ params : q . queryParameters ,
132+ } ) )
133+ ) ;
106134
107135 useEffect ( ( ) => {
108136 const listeners : ( undefined | ( ( ) => void ) ) [ ] = [ ] ;
@@ -111,39 +139,19 @@ export function useQueries(
111139 ( async ( ) => {
112140 try {
113141 const t = await powerSync . resolveTables ( q . sqlStatement , q . queryParameters ) ;
114- setTablesArr ( ( prev ) => {
115- if ( JSON . stringify ( prev [ idx ] ) === JSON . stringify ( t ) ) return prev ;
116- const next = prev . slice ( ) ;
117- next [ idx ] = t ;
118- return next ;
119- } ) ;
142+ updateTablesArr ( t , idx ) ;
120143 } catch ( e ) {
121- setErrorsArr ( ( prev ) => {
122- if ( prev [ idx ] ?. message === ( e as Error ) . message ) return prev ;
123- const next = prev . slice ( ) ;
124- next [ idx ] = e as Error ;
125- return next ;
126- } ) ;
144+ updateErrorsArr ( e , idx ) ;
127145 }
128146 } ) ( ) ;
129147 const l = powerSync . registerListener ( {
130148 schemaChanged : async ( ) => {
131149 try {
132150 const t = await powerSync . resolveTables ( q . sqlStatement , q . queryParameters ) ;
133- setTablesArr ( ( prev ) => {
134- if ( JSON . stringify ( prev [ idx ] ) === JSON . stringify ( t ) ) return prev ;
135- const next = prev . slice ( ) ;
136- next [ idx ] = t ;
137- return next ;
138- } ) ;
151+ updateTablesArr ( t , idx ) ;
139152 queryClient . invalidateQueries ( { queryKey : q . rest . queryKey } ) ;
140153 } catch ( e ) {
141- setErrorsArr ( ( prev ) => {
142- if ( prev [ idx ] ?. message === ( e as Error ) . message ) return prev ;
143- const next = prev . slice ( ) ;
144- next [ idx ] = e as Error ;
145- return next ;
146- } ) ;
154+ updateErrorsArr ( e , idx ) ;
147155 }
148156 } ,
149157 } ) ;
@@ -153,7 +161,9 @@ export function useQueries(
153161 return ( ) => {
154162 listeners . forEach ( ( l ) => l ?.( ) ) ;
155163 } ;
156- } , [ powerSync , parsedQueries , queryClient ] ) ;
164+ } , [ powerSync , queryClient , stringifiedQueriesDeps , updateErrorsArr , updateTablesArr ] ) ;
165+
166+ const stringifiedQueryKeys = JSON . stringify ( parsedQueries . map ( ( q ) => q . rest . queryKey ) ) ;
157167
158168 useEffect ( ( ) => {
159169 const aborts : AbortController [ ] = [ ] ;
@@ -167,12 +177,7 @@ export function useQueries(
167177 queryClient . invalidateQueries ( { queryKey : q . rest . queryKey } ) ;
168178 } ,
169179 onError : ( e ) => {
170- setErrorsArr ( ( prev ) => {
171- if ( prev [ idx ] ?. message === ( e as Error ) . message ) return prev ;
172- const next = prev . slice ( ) ;
173- next [ idx ] = e as Error ;
174- return next ;
175- } ) ;
180+ updateErrorsArr ( e , idx ) ;
176181 } ,
177182 } ,
178183 {
@@ -182,13 +187,14 @@ export function useQueries(
182187 ) ;
183188 } ) ;
184189 return ( ) => aborts . forEach ( ( a ) => a ?. abort ( ) ) ;
185- } , [ powerSync , parsedQueries , queryClient , tablesArr ] ) ;
190+ } , [ powerSync , queryClient , tablesArr , updateErrorsArr , stringifiedQueryKeys ] ) ;
186191
187192 const queries = useMemo ( ( ) => {
188193 return parsedQueries . map ( ( q , idx ) => {
189194 const error = q . error || errorsArr [ idx ] ;
190195 const queryFn = async ( ) => {
191196 if ( error ) throw error ;
197+
192198 try {
193199 return typeof q . query === 'string'
194200 ? powerSync . getAll ( q . sqlStatement , q . queryParameters )
@@ -203,19 +209,19 @@ export function useQueries(
203209 queryKey : q . rest . queryKey ,
204210 } ;
205211 } ) ;
206- } , [ parsedQueries , errorsArr , powerSync ] ) ;
212+ } , [ stringifiedQueriesDeps , errorsArr ] ) ;
207213
208214 return Tanstack . useQueries (
209215 {
210216 queries : queries as Tanstack . QueriesOptions < any > ,
211217 combine : options . combine
212218 ? ( results ) => {
213- const enhancedResults = results . map ( ( result , index ) => ( {
219+ const enhancedResultsWithQueryKey = results . map ( ( result , index ) => ( {
214220 ...result ,
215221 queryKey : queries [ index ] . queryKey ,
216222 } ) ) ;
217223
218- return options . combine ?.( enhancedResults ) ;
224+ return options . combine ?.( enhancedResultsWithQueryKey as any ) ;
219225 }
220226 : undefined ,
221227 } ,
0 commit comments