Skip to content

Commit 1ad2126

Browse files
authored
Merge pull request #4 from OpenAPI-Qraft/cancel-queries
feat: Query Cancellation support
2 parents c5fcb62 + dcf9acc commit 1ad2126

File tree

9 files changed

+315
-86
lines changed

9 files changed

+315
-86
lines changed

.changeset/thick-kids-double.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@openapi-qraft/react": patch
3+
"@openapi-qraft/cli": patch
4+
"playground": patch
5+
---
6+
7+
feature: add support for `cancelQueries` method

packages/cli/src/lib/ts-factory/getClientFactory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,5 @@ const serviceCallbacks = [
186186
'useQueries',
187187
'useSuspenseQueries',
188188
'invalidateQueries',
189+
'cancelQueries',
189190
] as const;

packages/react-client/README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ function App() {
174174
With the client set up, you can now use the generated Hooks in your React Components to fetch data, execute mutations,
175175
and more.
176176

177-
### [useQuery 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery)
177+
### [useQuery(...) 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery)
178178

179179
```ts
180180
/**
@@ -193,7 +193,7 @@ const { data, error, isPending } = qraft.entities.getEntities.useQuery({
193193
});
194194
```
195195

196-
### [useMutation 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useMutation)
196+
### [useMutation(...) 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useMutation)
197197

198198
#### With predefined parameters
199199

@@ -253,7 +253,7 @@ mutation.mutate({
253253
});
254254
```
255255

256-
### [useMutationState 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useMutationState)
256+
### [useMutationState(...) 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useMutationState)
257257

258258
Mutation state is a helper hook that provides the current state of a mutation globally.
259259
It could be used to track the status of a mutation in any component, which is useful for showing loading spinners or
@@ -281,7 +281,7 @@ useEffect(() => {
281281
}, [mutate, mutationState?.status]);
282282
```
283283

284-
### [useInfiniteQuery 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useInfiniteQuery)
284+
### [useInfiniteQuery(...) 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useInfiniteQuery)
285285

286286
#### _Offset-based_
287287

@@ -358,7 +358,7 @@ infiniteQuery.fetchNextPage();
358358
infiniteQuery.fetchPreviousPage();
359359
```
360360

361-
### [useQueries 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries)
361+
### [useQueries(...) 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries)
362362

363363
```ts
364364
/**
@@ -397,7 +397,7 @@ qraft.entities.getEntities.useQueries({
397397
});
398398
```
399399

400-
### [invalidateQueries 🔗](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientinvalidatequeries)
400+
### [invalidateQueries(...) 🔗](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientinvalidatequeries)
401401

402402
[Queries Invalidation 🔗](https://tanstack.com/query/latest/docs/framework/react/guides/query-invalidation) is possible
403403
using `<operation>.invalidateQueries(..)` method.
@@ -501,13 +501,18 @@ qraft.entities.getEntities.invalidateQueries(
501501
);
502502
```
503503

504+
### [cancelQueries(...) 🔗](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientcancelqueries)
505+
506+
[Query Cancellation](https://tanstack.com/query/latest/docs/framework/react/guides/query-cancellation) has the
507+
same interface as `invalidateQueries(..)`, but it will cancel the queries instead of invalidating them.
508+
504509
### Suspense Queries
505510

506511
Supported Suspense Queries are:
507512

508-
- [useSuspenseQuery 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseQuery)
509-
- [useSuspenseInfiniteQuery 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseInfiniteQuery)
510-
- [useSuspenseQueries 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseQueries)
513+
- [useSuspenseQuery(...) 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseQuery)
514+
- [useSuspenseInfiniteQuery(...) 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseInfiniteQuery)
515+
- [useSuspenseQueries(...) 🔗](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseQueries)
511516

512517
### Documentation in Progress 🚧
513518

packages/react-client/src/ServiceOperation.ts

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {
1+
import type {
2+
CancelOptions,
23
DefaultError,
34
FetchStatus,
45
InfiniteData,
@@ -14,7 +15,7 @@ import {
1415
SetDataOptions,
1516
Updater,
1617
} from '@tanstack/query-core';
17-
import {
18+
import type {
1819
DefinedInitialDataInfiniteOptions,
1920
DefinedInitialDataOptions,
2021
DefinedUseInfiniteQueryResult,
@@ -63,7 +64,8 @@ export interface ServiceOperationQuery<
6364
ServiceOperationGetInfiniteQueryData<TSchema, TData, TParams>,
6465
ServiceOperationSetQueryData<TSchema, TData, TParams>,
6566
ServiceOperationSetInfiniteQueryData<TSchema, TData, TParams>,
66-
ServiceOperationInvalidateQueries<TSchema, TData, TParams, TError> {
67+
ServiceOperationInvalidateQueries<TSchema, TData, TParams, TError>,
68+
ServiceOperationCancelQueries<TSchema, TData, TParams, TError> {
6769
schema: TSchema;
6870
types: {
6971
parameters: TParams;
@@ -144,7 +146,7 @@ interface ServiceOperationUseQueries<
144146

145147
type QueryTypeFilter = 'all' | 'active' | 'inactive';
146148

147-
interface InvalidateQueryFiltersBase<
149+
interface QueryFiltersBase<
148150
TSchema extends { url: string; method: string },
149151
TData,
150152
TParams = {},
@@ -178,56 +180,65 @@ interface InvalidateQueryFiltersBase<
178180
* Include queries matching their fetchStatus
179181
*/
180182
fetchStatus?: FetchStatus;
181-
182-
refetchType?: QueryTypeFilter | 'none';
183183
}
184184

185-
interface InvalidateQueryFiltersByQueryKey<
185+
interface QueryFiltersByQueryKey<
186186
TSchema extends { url: string; method: string },
187187
TData,
188188
TParams = {},
189189
TError = DefaultError,
190-
> extends InvalidateQueryFiltersBase<TSchema, TData, TParams, TError> {
190+
> extends QueryFiltersBase<TSchema, TData, TParams, TError> {
191191
/**
192192
* Include queries matching this query key
193193
*/
194194
queryKey?: ServiceOperationQueryKey<TSchema, TParams>;
195195
}
196196

197-
interface InvalidateQueryFiltersByParameters<
197+
interface QueryFiltersByParameters<
198198
TSchema extends { url: string; method: string },
199199
TData,
200200
TParams = {},
201201
TError = DefaultError,
202-
> extends InvalidateQueryFiltersBase<TSchema, TData, TParams, TError> {
202+
> extends QueryFiltersBase<TSchema, TData, TParams, TError> {
203203
/**
204204
* Include queries matching parameters
205205
*/
206206
parameters?: TParams;
207207
}
208208

209+
type InvalidateQueryFilters<
210+
TSchema extends { url: string; method: string },
211+
TData,
212+
TParams = {},
213+
TError = DefaultError,
214+
> = (
215+
| QueryFiltersByParameters<TSchema, TData, TParams, TError>
216+
| QueryFiltersByQueryKey<TSchema, TData, TParams, TError>
217+
) & {
218+
refetchType?: QueryTypeFilter | 'none';
219+
};
220+
209221
interface ServiceOperationInvalidateQueries<
210222
TSchema extends { url: string; method: string },
211223
TData,
212224
TParams = {},
213225
TError = DefaultError,
214226
> {
215227
invalidateQueries(
216-
filters:
217-
| InvalidateQueryFiltersByParameters<TSchema, TData, TParams, TError>
218-
| InvalidateQueryFiltersByQueryKey<TSchema, TData, TParams, TError>,
228+
filters: InvalidateQueryFilters<TSchema, TData, TParams, TError>,
219229
options: InvalidateOptions,
220230
queryClient: QueryClient
221231
): Promise<void>;
222232
invalidateQueries(
223-
filters:
224-
| InvalidateQueryFiltersByParameters<TSchema, TData, TParams, TError>
225-
| InvalidateQueryFiltersByQueryKey<TSchema, TData, TParams, TError>,
233+
filters: InvalidateQueryFilters<TSchema, TData, TParams, TError>,
226234
queryClient: QueryClient
227235
): Promise<void>;
228236
invalidateQueries(queryClient: QueryClient): Promise<void>;
229237
}
230238

239+
/**
240+
* @internal
241+
*/
231242
export interface ServiceOperationInvalidateQueriesCallback<
232243
TSchema extends { url: string; method: string },
233244
TData,
@@ -236,14 +247,55 @@ export interface ServiceOperationInvalidateQueriesCallback<
236247
> extends ServiceOperationInvalidateQueries<TSchema, TData, TParams, TError> {
237248
invalidateQueries(
238249
filters:
239-
| InvalidateQueryFiltersByParameters<TSchema, TData, TParams, TError>
240-
| InvalidateQueryFiltersByQueryKey<TSchema, TData, TParams, TError>
250+
| QueryFiltersByParameters<TSchema, TData, TParams, TError>
251+
| QueryFiltersByQueryKey<TSchema, TData, TParams, TError>
241252
| QueryClient,
242253
options?: InvalidateOptions | QueryClient,
243254
queryClient?: QueryClient
244255
): Promise<void>;
245256
}
246257

258+
interface ServiceOperationCancelQueries<
259+
TSchema extends { url: string; method: string },
260+
TData,
261+
TParams = {},
262+
TError = DefaultError,
263+
> {
264+
cancelQueries(
265+
filters:
266+
| QueryFiltersByParameters<TSchema, TData, TParams, TError>
267+
| QueryFiltersByQueryKey<TSchema, TData, TParams, TError>,
268+
options: CancelOptions,
269+
queryClient: QueryClient
270+
): Promise<void>;
271+
cancelQueries(
272+
filters:
273+
| QueryFiltersByParameters<TSchema, TData, TParams, TError>
274+
| QueryFiltersByQueryKey<TSchema, TData, TParams, TError>,
275+
queryClient: QueryClient
276+
): Promise<void>;
277+
cancelQueries(queryClient: QueryClient): Promise<void>;
278+
}
279+
280+
/**
281+
* @internal
282+
*/
283+
export interface ServiceOperationCancelQueriesCallback<
284+
TSchema extends { url: string; method: string },
285+
TData,
286+
TParams = {},
287+
TError = DefaultError,
288+
> extends ServiceOperationCancelQueries<TSchema, TData, TParams, TError> {
289+
cancelQueries(
290+
filters:
291+
| QueryFiltersByParameters<TSchema, TData, TParams, TError>
292+
| QueryFiltersByQueryKey<TSchema, TData, TParams, TError>
293+
| QueryClient,
294+
options?: CancelOptions | QueryClient,
295+
queryClient?: QueryClient
296+
): Promise<void>;
297+
}
298+
247299
interface ServiceOperationUseSuspenseQueries<
248300
TSchema extends { url: string; method: string },
249301
TData,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js';
2+
import type { QraftClientOptions } from '../qraftAPIClient.js';
3+
import type { RequestClientSchema } from '../RequestClient.js';
4+
import { ServiceOperationCancelQueriesCallback } from '../ServiceOperation.js';
5+
6+
export function cancelQueries<TData>(
7+
qraftOptions: QraftClientOptions | undefined,
8+
schema: RequestClientSchema,
9+
args: Parameters<
10+
ServiceOperationCancelQueriesCallback<
11+
RequestClientSchema,
12+
unknown,
13+
TData
14+
>['cancelQueries']
15+
>
16+
): Promise<void> {
17+
return callQueryClientMethodWithQueryFilters(
18+
'cancelQueries',
19+
schema,
20+
args as never
21+
) as never;
22+
}
Lines changed: 6 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import type { InvalidateOptions, QueryClient } from '@tanstack/query-core';
2-
3-
import { composeQueryKey } from '../lib/composeQueryKey.js';
1+
import { callQueryClientMethodWithQueryFilters } from '../lib/callQueryClientMethodWithQueryFilters.js';
42
import type { QraftClientOptions } from '../qraftAPIClient.js';
53
import type { RequestClientSchema } from '../RequestClient.js';
64
import type { ServiceOperationInvalidateQueriesCallback } from '../ServiceOperation.js';
@@ -16,54 +14,9 @@ export function invalidateQueries<TData>(
1614
>['invalidateQueries']
1715
>
1816
): Promise<void> {
19-
const queryClient = (
20-
args.length === 1
21-
? args[0]
22-
: args.length === 2
23-
? args[1]
24-
: args.length === 3
25-
? args[2]
26-
: undefined
27-
) as QueryClient | undefined;
28-
29-
const filters = args.length === 1 ? undefined : args[0];
30-
const options = (args.length === 3 ? args[1] : undefined) as
31-
| InvalidateOptions
32-
| undefined;
33-
34-
if (!queryClient) throw new Error('queryClient is required');
35-
if (!queryClient.invalidateQueries) throw new Error('queryClient is invalid');
36-
37-
if (!filters) {
38-
return queryClient.invalidateQueries(
39-
{
40-
queryKey: composeQueryKey(schema, undefined),
41-
},
42-
options
43-
);
44-
}
45-
46-
if ('queryKey' in filters) {
47-
return queryClient.invalidateQueries(filters as never, options);
48-
}
49-
50-
if ('parameters' in filters) {
51-
const { parameters, ...filtersRest } = filters;
52-
53-
return queryClient.invalidateQueries(
54-
{
55-
...filtersRest,
56-
queryKey: composeQueryKey(schema, parameters),
57-
} as never,
58-
options
59-
);
60-
}
61-
62-
return queryClient.invalidateQueries(
63-
{
64-
...filters,
65-
queryKey: composeQueryKey(schema, undefined),
66-
} as never,
67-
options
68-
);
17+
return callQueryClientMethodWithQueryFilters(
18+
'invalidateQueries',
19+
schema,
20+
args as never
21+
) as never;
6922
}

0 commit comments

Comments
 (0)