@powersync/tanstack-react-query 0.1.15 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/hooks/usePowerSyncQueries.d.ts +11 -6
- package/lib/hooks/usePowerSyncQueries.js +34 -25
- package/lib/hooks/usePowerSyncQueries.js.map +1 -1
- package/lib/hooks/useQueries.d.ts +13 -0
- package/lib/hooks/useQueries.js +5 -3
- package/lib/hooks/useQueries.js.map +1 -1
- package/lib/hooks/useQuery.d.ts +13 -0
- package/lib/hooks/useQuery.js +6 -4
- package/lib/hooks/useQuery.js.map +1 -1
- package/package.json +4 -3
- package/src/hooks/usePowerSyncQueries.ts +46 -30
- package/src/hooks/useQueries.ts +18 -4
- package/src/hooks/useQuery.ts +19 -5
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { type CompilableQuery } from '@powersync/common';
|
|
2
|
+
import { QuerySyncStreamOptions } from '@powersync/react';
|
|
2
3
|
import * as Tanstack from '@tanstack/react-query';
|
|
3
4
|
export type UsePowerSyncQueriesInput = {
|
|
4
5
|
query?: string | CompilableQuery<unknown>;
|
|
5
6
|
parameters?: unknown[];
|
|
6
7
|
queryKey: Tanstack.QueryKey;
|
|
8
|
+
streams?: QuerySyncStreamOptions[];
|
|
7
9
|
}[];
|
|
8
10
|
export type UsePowerSyncQueriesOutput = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
queries: {
|
|
12
|
+
sqlStatement: string;
|
|
13
|
+
queryParameters: unknown[];
|
|
14
|
+
tables: string[];
|
|
15
|
+
error?: Error;
|
|
16
|
+
queryFn: () => Promise<unknown[]>;
|
|
17
|
+
}[];
|
|
18
|
+
streamsHaveSynced: boolean;
|
|
19
|
+
};
|
|
15
20
|
export declare function usePowerSyncQueries(queries: UsePowerSyncQueriesInput, queryClient: Tanstack.QueryClient): UsePowerSyncQueriesOutput;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseQuery } from '@powersync/common';
|
|
2
|
-
import { usePowerSync } from '@powersync/react';
|
|
2
|
+
import { useAllSyncStreamsHaveSynced, usePowerSync } from '@powersync/react';
|
|
3
3
|
import { useEffect, useState, useCallback, useMemo } from 'react';
|
|
4
4
|
export function usePowerSyncQueries(queries, queryClient) {
|
|
5
5
|
const powerSync = usePowerSync();
|
|
@@ -14,6 +14,12 @@ export function usePowerSyncQueries(queries, queryClient) {
|
|
|
14
14
|
return next;
|
|
15
15
|
});
|
|
16
16
|
}, []);
|
|
17
|
+
// Collect all streams from all query entries into a single flat list for sync tracking.
|
|
18
|
+
const allStreams = useMemo(() => {
|
|
19
|
+
const streams = queries.flatMap(q => q.streams ?? []);
|
|
20
|
+
return streams.length > 0 ? streams : undefined;
|
|
21
|
+
}, [queries]);
|
|
22
|
+
const streamsHaveSynced = useAllSyncStreamsHaveSynced(powerSync, allStreams);
|
|
17
23
|
const updateErrorsArr = useCallback((error, idx) => {
|
|
18
24
|
setErrorsArr((prev) => {
|
|
19
25
|
if (prev[idx]?.message === error?.message)
|
|
@@ -122,30 +128,33 @@ export function usePowerSyncQueries(queries, queryClient) {
|
|
|
122
128
|
return () => aborts.forEach((a) => a?.abort());
|
|
123
129
|
}, [powerSync, queryClient, tablesArr, updateErrorsArr, stringifiedQueryKeys]);
|
|
124
130
|
return useMemo(() => {
|
|
125
|
-
return
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
131
|
+
return {
|
|
132
|
+
queries: parsedQueries.map((pq, idx) => {
|
|
133
|
+
const error = errorsArr[idx] || pq.parseError;
|
|
134
|
+
const queryFn = async () => {
|
|
135
|
+
if (error)
|
|
136
|
+
throw error;
|
|
137
|
+
if (!pq.query)
|
|
138
|
+
throw new Error('No query provided');
|
|
139
|
+
try {
|
|
140
|
+
return typeof pq.query === 'string'
|
|
141
|
+
? await powerSync.getAll(pq.sqlStatement, pq.queryParameters)
|
|
142
|
+
: await pq.query.execute();
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
throw e;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
return {
|
|
149
|
+
sqlStatement: pq.sqlStatement,
|
|
150
|
+
queryParameters: pq.queryParameters,
|
|
151
|
+
tables: tablesArr[idx],
|
|
152
|
+
error,
|
|
153
|
+
queryFn
|
|
154
|
+
};
|
|
155
|
+
}),
|
|
156
|
+
streamsHaveSynced
|
|
157
|
+
};
|
|
149
158
|
}, [parsedQueries, errorsArr, tablesArr, powerSync]);
|
|
150
159
|
}
|
|
151
160
|
//# sourceMappingURL=usePowerSyncQueries.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePowerSyncQueries.js","sourceRoot":"","sources":["../../src/hooks/usePowerSyncQueries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"usePowerSyncQueries.js","sourceRoot":"","sources":["../../src/hooks/usePowerSyncQueries.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { type CompilableQuery } from '@powersync/common';
|
|
2
|
+
import { QuerySyncStreamOptions } from '@powersync/react';
|
|
2
3
|
import * as Tanstack from '@tanstack/react-query';
|
|
3
4
|
export type PowerSyncQueryOptions<T> = {
|
|
4
5
|
query?: string | CompilableQuery<T>;
|
|
5
6
|
parameters?: any[];
|
|
7
|
+
/**
|
|
8
|
+
* An optional array of sync streams (with names and parameters) backing the query.
|
|
9
|
+
*
|
|
10
|
+
* When set, `useQuery` will subscribe to those streams (and automatically handle unsubscribing from them, too).
|
|
11
|
+
*
|
|
12
|
+
* If {@link QuerySyncStreamOptions} is set on a stream, `useQuery` will remain in a loading state until that stream
|
|
13
|
+
* is marked as {@link SyncSubscriptionDescription.hasSynced}. This ensures the query is not missing rows that haven't
|
|
14
|
+
* been downloaded.
|
|
15
|
+
* Note however that after an initial sync, the query will not block itself while new rows are downloading. Instead,
|
|
16
|
+
* consistent sync snapshots will be made available as they've been processed by PowerSync.
|
|
17
|
+
**/
|
|
18
|
+
streams?: QuerySyncStreamOptions[];
|
|
6
19
|
};
|
|
7
20
|
export type PowerSyncQueryOption<T = unknown[]> = Tanstack.UseQueryOptions<T[]> & PowerSyncQueryOptions<T>;
|
|
8
21
|
export type InferQueryResults<TQueries extends readonly unknown[]> = {
|
package/lib/hooks/useQueries.js
CHANGED
|
@@ -40,9 +40,10 @@ export function useQueries(options, queryClient = Tanstack.useQueryClient()) {
|
|
|
40
40
|
const powerSyncQueriesInput = useMemo(() => queriesInput.map((queryOptions) => ({
|
|
41
41
|
query: queryOptions.query,
|
|
42
42
|
parameters: queryOptions.parameters,
|
|
43
|
-
queryKey: queryOptions.queryKey
|
|
43
|
+
queryKey: queryOptions.queryKey,
|
|
44
|
+
streams: queryOptions.streams
|
|
44
45
|
})), [queriesInput]);
|
|
45
|
-
const states = usePowerSyncQueries(powerSyncQueriesInput, queryClient);
|
|
46
|
+
const { queries: states, streamsHaveSynced } = usePowerSyncQueries(powerSyncQueriesInput, queryClient);
|
|
46
47
|
const queries = useMemo(() => {
|
|
47
48
|
return queriesInput.map((queryOptions, idx) => {
|
|
48
49
|
const { query, parameters, ...rest } = queryOptions;
|
|
@@ -50,7 +51,8 @@ export function useQueries(options, queryClient = Tanstack.useQueryClient()) {
|
|
|
50
51
|
return {
|
|
51
52
|
...rest,
|
|
52
53
|
queryFn: query ? state.queryFn : rest.queryFn,
|
|
53
|
-
queryKey: rest.queryKey
|
|
54
|
+
queryKey: rest.queryKey,
|
|
55
|
+
enabled: streamsHaveSynced
|
|
54
56
|
};
|
|
55
57
|
});
|
|
56
58
|
}, [queriesInput, states]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useQueries.js","sourceRoot":"","sources":["../../src/hooks/useQueries.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"useQueries.js","sourceRoot":"","sources":["../../src/hooks/useQueries.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,KAAK,QAAQ,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AA0F/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,UAAU,CACxB,OAA8B,EAC9B,cAAoC,QAAQ,CAAC,cAAc,EAAE;IAE7D,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAErC,MAAM,qBAAqB,GAAG,OAAO,CACnC,GAAG,EAAE,CACH,YAAY,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAClC,KAAK,EAAE,YAAY,CAAC,KAAK;QACzB,UAAU,EAAE,YAAY,CAAC,UAAU;QACnC,QAAQ,EAAE,YAAY,CAAC,QAAQ;QAC/B,OAAO,EAAE,YAAY,CAAC,OAAO;KAC9B,CAAC,CAAC,EACL,CAAC,YAAY,CAAC,CACf,CAAC;IAEF,MAAM,EAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAC,GAAG,mBAAmB,CAAC,qBAAqB,EAAE,WAAW,CAAC,CAAC;IAErG,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE;QAC3B,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,GAAG,EAAE,EAAE;YAC5C,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,YAAY,CAAC;YACpD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YAE1B,OAAO;gBACL,GAAG,IAAI;gBACP,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO;gBAC7C,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,iBAAiB;aAC3B,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAE3B,OAAO,QAAQ,CAAC,UAAU,CACxB;QACE,OAAO,EAAE,OAAuC;QAChD,OAAO,EAAE,OAAO,CAAC,OAAO;YACtB,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE;gBACV,MAAM,2BAA2B,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;oBAClE,GAAG,MAAM;oBACT,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ;iBAClC,CAAC,CAAC,CAAC;gBAEJ,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC,2BAA2B,CAAC,CAAC;YACxD,CAAC;YACH,CAAC,CAAC,SAAS;KACd,EACD,WAAW,CACZ,CAAC;AACJ,CAAC"}
|
package/lib/hooks/useQuery.d.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { type CompilableQuery } from '@powersync/common';
|
|
2
|
+
import { QuerySyncStreamOptions } from '@powersync/react';
|
|
2
3
|
import * as Tanstack from '@tanstack/react-query';
|
|
3
4
|
export type PowerSyncQueryOptions<T> = {
|
|
4
5
|
query?: string | CompilableQuery<T>;
|
|
5
6
|
parameters?: any[];
|
|
7
|
+
/**
|
|
8
|
+
* An optional array of sync streams (with names and parameters) backing the query.
|
|
9
|
+
*
|
|
10
|
+
* When set, `useQuery` will subscribe to those streams (and automatically handle unsubscribing from them, too).
|
|
11
|
+
*
|
|
12
|
+
* If {@link QuerySyncStreamOptions} is set on a stream, `useQuery` will remain in a loading state until that stream
|
|
13
|
+
* is marked as {@link SyncSubscriptionDescription.hasSynced}. This ensures the query is not missing rows that haven't
|
|
14
|
+
* been downloaded.
|
|
15
|
+
* Note however that after an initial sync, the query will not block itself while new rows are downloading. Instead,
|
|
16
|
+
* consistent sync snapshots will be made available as they've been processed by PowerSync.
|
|
17
|
+
**/
|
|
18
|
+
streams?: QuerySyncStreamOptions[];
|
|
6
19
|
};
|
|
7
20
|
export type UseBaseQueryOptions<TQueryOptions> = TQueryOptions & PowerSyncQueryOptions<any>;
|
|
8
21
|
/**
|
package/lib/hooks/useQuery.js
CHANGED
|
@@ -12,18 +12,20 @@ function useQueryCore(options, queryClient, useQueryFn) {
|
|
|
12
12
|
if (!powerSync) {
|
|
13
13
|
throw new Error('PowerSync is not available');
|
|
14
14
|
}
|
|
15
|
-
const { query, parameters, queryKey, ...resolvedOptions } = options;
|
|
16
|
-
const [{ queryFn }] = usePowerSyncQueries([
|
|
15
|
+
const { query, parameters, queryKey, streams, ...resolvedOptions } = options;
|
|
16
|
+
const { queries: [{ queryFn }], streamsHaveSynced } = usePowerSyncQueries([
|
|
17
17
|
{
|
|
18
18
|
query,
|
|
19
19
|
parameters,
|
|
20
|
-
queryKey
|
|
20
|
+
queryKey,
|
|
21
|
+
streams
|
|
21
22
|
}
|
|
22
23
|
], queryClient);
|
|
23
24
|
return useQueryFn({
|
|
24
25
|
...resolvedOptions,
|
|
25
26
|
queryKey,
|
|
26
|
-
queryFn: query ? queryFn : resolvedOptions.queryFn
|
|
27
|
+
queryFn: query ? queryFn : resolvedOptions.queryFn,
|
|
28
|
+
enabled: streamsHaveSynced
|
|
27
29
|
}, queryClient);
|
|
28
30
|
}
|
|
29
31
|
//# sourceMappingURL=useQuery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useQuery.js","sourceRoot":"","sources":["../../src/hooks/useQuery.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"useQuery.js","sourceRoot":"","sources":["../../src/hooks/useQuery.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,KAAK,QAAQ,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAgE/D,MAAM,UAAU,QAAQ,CACtB,OAAqE,EACrE,cAAoC,QAAQ,CAAC,cAAc,EAAE;IAE7D,OAAO,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC/D,CAAC;AAuCD,MAAM,UAAU,gBAAgB,CAC9B,OAA6E,EAC7E,cAAoC,QAAQ,CAAC,cAAc,EAAE;IAE7D,OAAO,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,YAAY,CAMnB,OAA2C,EAC3C,WAAiC,EACjC,UAAwF;IAExF,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;IAE7E,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,CACvE;QACE;YACE,KAAK;YACL,UAAU;YACV,QAAQ;YACR,OAAO;SACR;KACF,EACD,WAAW,CACZ,CAAC;IAEF,OAAO,UAAU,CACf;QACE,GAAI,eAAiC;QACrC,QAAQ;QACR,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO;QAClD,OAAO,EAAE,iBAAiB;KACV,EAClB,WAAW,CACZ,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powersync/tanstack-react-query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -30,14 +30,15 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@tanstack/react-query": "^5.70.0",
|
|
32
32
|
"@powersync/common": "1.47.0",
|
|
33
|
-
"@powersync/react": "1.
|
|
33
|
+
"@powersync/react": "1.9.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@testing-library/react": "^15.0.2",
|
|
37
37
|
"@types/react": "18.3.1",
|
|
38
38
|
"jsdom": "^24.0.0",
|
|
39
39
|
"react": "18.3.1",
|
|
40
|
-
"react-dom": "^18.3.1"
|
|
40
|
+
"react-dom": "^18.3.1",
|
|
41
|
+
"@powersync/web": "1.34.0"
|
|
41
42
|
},
|
|
42
43
|
"scripts": {
|
|
43
44
|
"build": "tsc -b",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CompilableQuery, parseQuery } from '@powersync/common';
|
|
2
|
-
import { usePowerSync } from '@powersync/react';
|
|
2
|
+
import { QuerySyncStreamOptions, useAllSyncStreamsHaveSynced, usePowerSync } from '@powersync/react';
|
|
3
3
|
import { useEffect, useState, useCallback, useMemo } from 'react';
|
|
4
4
|
import * as Tanstack from '@tanstack/react-query';
|
|
5
5
|
|
|
@@ -7,15 +7,19 @@ export type UsePowerSyncQueriesInput = {
|
|
|
7
7
|
query?: string | CompilableQuery<unknown>;
|
|
8
8
|
parameters?: unknown[];
|
|
9
9
|
queryKey: Tanstack.QueryKey;
|
|
10
|
+
streams?: QuerySyncStreamOptions[];
|
|
10
11
|
}[];
|
|
11
12
|
|
|
12
13
|
export type UsePowerSyncQueriesOutput = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
queries: {
|
|
15
|
+
sqlStatement: string;
|
|
16
|
+
queryParameters: unknown[];
|
|
17
|
+
tables: string[];
|
|
18
|
+
error?: Error;
|
|
19
|
+
queryFn: () => Promise<unknown[]>;
|
|
20
|
+
}[];
|
|
21
|
+
streamsHaveSynced: boolean;
|
|
22
|
+
};
|
|
19
23
|
|
|
20
24
|
export function usePowerSyncQueries(
|
|
21
25
|
queries: UsePowerSyncQueriesInput,
|
|
@@ -35,6 +39,14 @@ export function usePowerSyncQueries(
|
|
|
35
39
|
});
|
|
36
40
|
}, []);
|
|
37
41
|
|
|
42
|
+
// Collect all streams from all query entries into a single flat list for sync tracking.
|
|
43
|
+
const allStreams = useMemo(() => {
|
|
44
|
+
const streams = queries.flatMap(q => q.streams ?? []);
|
|
45
|
+
return streams.length > 0 ? streams : undefined;
|
|
46
|
+
}, [queries]);
|
|
47
|
+
|
|
48
|
+
const streamsHaveSynced = useAllSyncStreamsHaveSynced(powerSync, allStreams);
|
|
49
|
+
|
|
38
50
|
const updateErrorsArr = useCallback((error: Error | undefined, idx: number) => {
|
|
39
51
|
setErrorsArr((prev) => {
|
|
40
52
|
if (prev[idx]?.message === error?.message) return prev;
|
|
@@ -164,29 +176,33 @@ export function usePowerSyncQueries(
|
|
|
164
176
|
}, [powerSync, queryClient, tablesArr, updateErrorsArr, stringifiedQueryKeys]);
|
|
165
177
|
|
|
166
178
|
return useMemo(() => {
|
|
167
|
-
return parsedQueries.map((pq, idx) => {
|
|
168
|
-
const error = errorsArr[idx] || pq.parseError;
|
|
169
|
-
|
|
170
|
-
const queryFn = async () => {
|
|
171
|
-
if (error) throw error;
|
|
172
|
-
if (!pq.query) throw new Error('No query provided');
|
|
173
179
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
throw
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
180
|
+
return {
|
|
181
|
+
queries: parsedQueries.map((pq, idx) => {
|
|
182
|
+
const error = errorsArr[idx] || pq.parseError;
|
|
183
|
+
|
|
184
|
+
const queryFn = async () => {
|
|
185
|
+
if (error) throw error;
|
|
186
|
+
if (!pq.query) throw new Error('No query provided');
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
return typeof pq.query === 'string'
|
|
190
|
+
? await powerSync.getAll(pq.sqlStatement, pq.queryParameters)
|
|
191
|
+
: await pq.query.execute();
|
|
192
|
+
} catch (e) {
|
|
193
|
+
throw e;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
sqlStatement: pq.sqlStatement,
|
|
199
|
+
queryParameters: pq.queryParameters,
|
|
200
|
+
tables: tablesArr[idx],
|
|
201
|
+
error,
|
|
202
|
+
queryFn
|
|
203
|
+
};
|
|
204
|
+
}),
|
|
205
|
+
streamsHaveSynced
|
|
206
|
+
};
|
|
191
207
|
}, [parsedQueries, errorsArr, tablesArr, powerSync]);
|
|
192
208
|
}
|
package/src/hooks/useQueries.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CompilableQuery } from '@powersync/common';
|
|
2
|
-
import { usePowerSync } from '@powersync/react';
|
|
2
|
+
import { QuerySyncStreamOptions, usePowerSync } from '@powersync/react';
|
|
3
3
|
import * as Tanstack from '@tanstack/react-query';
|
|
4
4
|
import { useMemo } from 'react';
|
|
5
5
|
import { usePowerSyncQueries } from './usePowerSyncQueries.js';
|
|
@@ -7,6 +7,18 @@ import { usePowerSyncQueries } from './usePowerSyncQueries.js';
|
|
|
7
7
|
export type PowerSyncQueryOptions<T> = {
|
|
8
8
|
query?: string | CompilableQuery<T>;
|
|
9
9
|
parameters?: any[];
|
|
10
|
+
/**
|
|
11
|
+
* An optional array of sync streams (with names and parameters) backing the query.
|
|
12
|
+
*
|
|
13
|
+
* When set, `useQuery` will subscribe to those streams (and automatically handle unsubscribing from them, too).
|
|
14
|
+
*
|
|
15
|
+
* If {@link QuerySyncStreamOptions} is set on a stream, `useQuery` will remain in a loading state until that stream
|
|
16
|
+
* is marked as {@link SyncSubscriptionDescription.hasSynced}. This ensures the query is not missing rows that haven't
|
|
17
|
+
* been downloaded.
|
|
18
|
+
* Note however that after an initial sync, the query will not block itself while new rows are downloading. Instead,
|
|
19
|
+
* consistent sync snapshots will be made available as they've been processed by PowerSync.
|
|
20
|
+
**/
|
|
21
|
+
streams?: QuerySyncStreamOptions[];
|
|
10
22
|
};
|
|
11
23
|
|
|
12
24
|
export type PowerSyncQueryOption<T = unknown[]> = Tanstack.UseQueryOptions<T[]> & PowerSyncQueryOptions<T>;
|
|
@@ -126,12 +138,13 @@ export function useQueries(
|
|
|
126
138
|
queriesInput.map((queryOptions) => ({
|
|
127
139
|
query: queryOptions.query,
|
|
128
140
|
parameters: queryOptions.parameters,
|
|
129
|
-
queryKey: queryOptions.queryKey
|
|
141
|
+
queryKey: queryOptions.queryKey,
|
|
142
|
+
streams: queryOptions.streams
|
|
130
143
|
})),
|
|
131
144
|
[queriesInput]
|
|
132
145
|
);
|
|
133
146
|
|
|
134
|
-
const states = usePowerSyncQueries(powerSyncQueriesInput, queryClient);
|
|
147
|
+
const {queries: states, streamsHaveSynced} = usePowerSyncQueries(powerSyncQueriesInput, queryClient);
|
|
135
148
|
|
|
136
149
|
const queries = useMemo(() => {
|
|
137
150
|
return queriesInput.map((queryOptions, idx) => {
|
|
@@ -141,7 +154,8 @@ export function useQueries(
|
|
|
141
154
|
return {
|
|
142
155
|
...rest,
|
|
143
156
|
queryFn: query ? state.queryFn : rest.queryFn,
|
|
144
|
-
queryKey: rest.queryKey
|
|
157
|
+
queryKey: rest.queryKey,
|
|
158
|
+
enabled: streamsHaveSynced
|
|
145
159
|
};
|
|
146
160
|
});
|
|
147
161
|
}, [queriesInput, states]);
|
package/src/hooks/useQuery.ts
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { type CompilableQuery } from '@powersync/common';
|
|
2
|
-
import { usePowerSync } from '@powersync/react';
|
|
2
|
+
import { QuerySyncStreamOptions, usePowerSync } from '@powersync/react';
|
|
3
3
|
import * as Tanstack from '@tanstack/react-query';
|
|
4
4
|
import { usePowerSyncQueries } from './usePowerSyncQueries.js';
|
|
5
5
|
|
|
6
6
|
export type PowerSyncQueryOptions<T> = {
|
|
7
7
|
query?: string | CompilableQuery<T>;
|
|
8
8
|
parameters?: any[];
|
|
9
|
+
/**
|
|
10
|
+
* An optional array of sync streams (with names and parameters) backing the query.
|
|
11
|
+
*
|
|
12
|
+
* When set, `useQuery` will subscribe to those streams (and automatically handle unsubscribing from them, too).
|
|
13
|
+
*
|
|
14
|
+
* If {@link QuerySyncStreamOptions} is set on a stream, `useQuery` will remain in a loading state until that stream
|
|
15
|
+
* is marked as {@link SyncSubscriptionDescription.hasSynced}. This ensures the query is not missing rows that haven't
|
|
16
|
+
* been downloaded.
|
|
17
|
+
* Note however that after an initial sync, the query will not block itself while new rows are downloading. Instead,
|
|
18
|
+
* consistent sync snapshots will be made available as they've been processed by PowerSync.
|
|
19
|
+
**/
|
|
20
|
+
streams?: QuerySyncStreamOptions[];
|
|
9
21
|
};
|
|
10
22
|
|
|
11
23
|
export type UseBaseQueryOptions<TQueryOptions> = TQueryOptions & PowerSyncQueryOptions<any>;
|
|
@@ -120,14 +132,15 @@ function useQueryCore<
|
|
|
120
132
|
throw new Error('PowerSync is not available');
|
|
121
133
|
}
|
|
122
134
|
|
|
123
|
-
const { query, parameters, queryKey, ...resolvedOptions } = options;
|
|
135
|
+
const { query, parameters, queryKey, streams, ...resolvedOptions } = options;
|
|
124
136
|
|
|
125
|
-
const [{ queryFn }] = usePowerSyncQueries(
|
|
137
|
+
const { queries: [{ queryFn }], streamsHaveSynced } = usePowerSyncQueries(
|
|
126
138
|
[
|
|
127
139
|
{
|
|
128
140
|
query,
|
|
129
141
|
parameters,
|
|
130
|
-
queryKey
|
|
142
|
+
queryKey,
|
|
143
|
+
streams
|
|
131
144
|
}
|
|
132
145
|
],
|
|
133
146
|
queryClient
|
|
@@ -137,7 +150,8 @@ function useQueryCore<
|
|
|
137
150
|
{
|
|
138
151
|
...(resolvedOptions as TQueryOptions),
|
|
139
152
|
queryKey,
|
|
140
|
-
queryFn: query ? queryFn : resolvedOptions.queryFn
|
|
153
|
+
queryFn: query ? queryFn : resolvedOptions.queryFn,
|
|
154
|
+
enabled: streamsHaveSynced
|
|
141
155
|
} as TQueryOptions,
|
|
142
156
|
queryClient
|
|
143
157
|
);
|