Skip to content

Commit 5a48f18

Browse files
authored
fix(query): fix select option (#561)
1 parent a0ee91d commit 5a48f18

9 files changed

Lines changed: 152 additions & 53 deletions

File tree

.changeset/pretty-shoes-breathe.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@ts-rest/react-query': patch
3+
'@ts-rest/solid-query': patch
4+
'@ts-rest/vue-query': patch
5+
---
6+
7+
Fix `select` option

apps/example-next/tests/react-query.spec.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,48 @@ describe('react-query', () => {
199199
expect(result.current.data).toStrictEqual(SUCCESS_RESPONSE);
200200
});
201201

202+
it('useQuery with select should handle success', async () => {
203+
api.mockResolvedValue({ status: 200, body: { message: 'hello world' } });
204+
205+
const { result } = renderHook(
206+
() =>
207+
client.health.useQuery(
208+
['health'],
209+
{},
210+
{
211+
select: (data) => data.body.message,
212+
},
213+
),
214+
{
215+
wrapper,
216+
},
217+
);
218+
219+
expect(result.current.data).toStrictEqual(undefined);
220+
221+
expect(result.current.isLoading).toStrictEqual(true);
222+
223+
expect(api).toHaveBeenCalledWith({
224+
method: 'GET',
225+
path: 'https://api.com/health',
226+
body: undefined,
227+
headers: {
228+
'x-test': 'test',
229+
},
230+
route: router.health,
231+
signal: expect.any(AbortSignal),
232+
fetchOptions: {
233+
signal: expect.any(AbortSignal),
234+
},
235+
});
236+
237+
await waitFor(() => {
238+
expect(result.current.isLoading).toStrictEqual(false);
239+
});
240+
241+
expect(result.current.data).toStrictEqual('hello world');
242+
});
243+
202244
it('useQuery should accept extra headers', async () => {
203245
api.mockResolvedValue(SUCCESS_RESPONSE);
204246

libs/ts-rest/react-query/src/lib/inner-types.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,16 @@ export type DataReturnQuery<
109109
TClientArgs extends ClientArgs,
110110
TArgs = PartialClientInferRequest<TAppRoute, TClientArgs>,
111111
> = AreAllPropertiesOptional<TArgs> extends true
112-
? (
112+
? <TData = DataResponse<TAppRoute>>(
113113
queryKey: QueryKey,
114114
args?: TArgs,
115-
options?: UseQueryOptions<TAppRoute>,
116-
) => UseQueryResult<TAppRoute>
117-
: (
115+
options?: UseQueryOptions<TAppRoute, TData>,
116+
) => UseQueryResult<TAppRoute, TData>
117+
: <TData = DataResponse<TAppRoute>>(
118118
queryKey: QueryKey,
119119
args: TArgs,
120-
options?: UseQueryOptions<TAppRoute>,
121-
) => UseQueryResult<TAppRoute>;
120+
options?: UseQueryOptions<TAppRoute, TData>,
121+
) => UseQueryResult<TAppRoute, TData>;
122122

123123
export type DataReturnQueriesOptions<
124124
TAppRoute extends AppRoute,
@@ -141,13 +141,13 @@ export type DataReturnQueries<
141141
export type DataReturnInfiniteQuery<
142142
TAppRoute extends AppRoute,
143143
TClientArgs extends ClientArgs,
144-
> = (
144+
> = <TData = DataResponse<TAppRoute>>(
145145
queryKey: QueryKey,
146146
args: (
147147
context: QueryFunctionContext<QueryKey>,
148148
) => PartialClientInferRequest<TAppRoute, TClientArgs>,
149-
options?: UseInfiniteQueryOptions<TAppRoute>,
150-
) => UseInfiniteQueryResult<TAppRoute>;
149+
options?: UseInfiniteQueryOptions<TAppRoute, TData>,
150+
) => UseInfiniteQueryResult<TAppRoute, TData>;
151151

152152
// Used pn X.useMutation
153153
export type DataReturnMutation<

libs/ts-rest/react-query/src/lib/types.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,33 @@ export type ErrorResponse<TAppRoute extends AppRoute> = ClientInferResponses<
3131
'ignore'
3232
>;
3333

34-
export type UseQueryOptions<TAppRoute extends AppRoute> =
35-
TanStackUseQueryOptions<DataResponse<TAppRoute>, ErrorResponse<TAppRoute>>;
36-
37-
export type UseQueryResult<TAppRoute extends AppRoute> = TanStackUseQueryResult<
34+
export type UseQueryOptions<
35+
TAppRoute extends AppRoute,
36+
TData = DataResponse<TAppRoute>,
37+
> = TanStackUseQueryOptions<
3838
DataResponse<TAppRoute>,
39-
ErrorResponse<TAppRoute>
39+
ErrorResponse<TAppRoute>,
40+
TData
4041
>;
4142

42-
export type UseInfiniteQueryOptions<TAppRoute extends AppRoute> =
43-
TanStackUseInfiniteQueryOptions<
44-
DataResponse<TAppRoute>,
45-
ErrorResponse<TAppRoute>
46-
>;
43+
export type UseQueryResult<
44+
TAppRoute extends AppRoute,
45+
TData = DataResponse<TAppRoute>,
46+
> = TanStackUseQueryResult<TData, ErrorResponse<TAppRoute>>;
47+
48+
export type UseInfiniteQueryOptions<
49+
TAppRoute extends AppRoute,
50+
TData = DataResponse<TAppRoute>,
51+
> = TanStackUseInfiniteQueryOptions<
52+
DataResponse<TAppRoute>,
53+
ErrorResponse<TAppRoute>,
54+
TData
55+
>;
4756

48-
export type UseInfiniteQueryResult<TAppRoute extends AppRoute> =
49-
TanStackUseInfiniteQueryResult<
50-
DataResponse<TAppRoute>,
51-
ErrorResponse<TAppRoute>
52-
>;
57+
export type UseInfiniteQueryResult<
58+
TAppRoute extends AppRoute,
59+
TData = DataResponse<TAppRoute>,
60+
> = TanStackUseInfiniteQueryResult<TData, ErrorResponse<TAppRoute>>;
5361

5462
type InferClientArgs<TClient extends InitClientReturn<any, any>> =
5563
TClient extends InitClientReturn<any, infer TClientArgs>

libs/ts-rest/solid-query/src/lib/solid-query.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,32 +79,31 @@ type ErrorResponse<TAppRoute extends AppRoute> = ClientInferResponses<
7979
type DataReturnQuery<
8080
TAppRoute extends AppRoute,
8181
TClientArgs extends ClientArgs,
82-
> = (
82+
> = <TData = DataResponse<TAppRoute>>(
8383
queryKey: () => QueryKey,
8484
args: PartialClientInferRequest<TAppRoute, TClientArgs>,
8585
options?: CreateQueryOptions<
8686
DataResponse<TAppRoute>,
87-
ErrorResponse<TAppRoute>
87+
ErrorResponse<TAppRoute>,
88+
TData
8889
>,
89-
) => CreateQueryResult<DataResponse<TAppRoute>, ErrorResponse<TAppRoute>>;
90+
) => CreateQueryResult<TData, ErrorResponse<TAppRoute>>;
9091

9192
// Used on X.useInfiniteQuery
9293
type DataReturnInfiniteQuery<
9394
TAppRoute extends AppRoute,
9495
TClientArgs extends ClientArgs,
95-
> = (
96+
> = <TData = DataResponse<TAppRoute>>(
9697
queryKey: () => QueryKey,
9798
args: (
9899
context: QueryFunctionContext<QueryKey>,
99100
) => PartialClientInferRequest<TAppRoute, TClientArgs>,
100101
options?: CreateInfiniteQueryOptions<
101102
DataResponse<TAppRoute>,
102-
ErrorResponse<TAppRoute>
103+
ErrorResponse<TAppRoute>,
104+
TData
103105
>,
104-
) => CreateInfiniteQueryResult<
105-
DataResponse<TAppRoute>,
106-
ErrorResponse<TAppRoute>
107-
>;
106+
) => CreateInfiniteQueryResult<TData, ErrorResponse<TAppRoute>>;
108107

109108
// Used pn X.createMutation
110109
type DataReturnMutation<

libs/ts-rest/vue-query/src/lib/common.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const queryFn = <
4040
| ((
4141
context: QueryFunctionContext<QueryKey>,
4242
) => ClientInferRequest<AppRouteMutation, ClientArgs>),
43-
): QueryFunction<TAppRoute['responses']> => {
43+
): QueryFunction<DataResponse<TAppRoute>> => {
4444
return async (queryFnContext: QueryFunctionContext) => {
4545
const args =
4646
typeof argsMapper === 'function'
@@ -61,6 +61,6 @@ export const queryFn = <
6161
throw result;
6262
}
6363

64-
return result;
64+
return result as DataResponse<TAppRoute>;
6565
};
6666
};

libs/ts-rest/vue-query/src/lib/use-infinite-query.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,17 @@ import { DataResponse, ErrorResponse, queryFn } from './common';
1919
export type DataReturnInfiniteQuery<
2020
TAppRoute extends AppRoute,
2121
TClientArgs extends ClientArgs,
22-
> = (
22+
> = <TData = DataResponse<TAppRoute>>(
2323
queryKey: QueryKey,
2424
args: (
25-
context: QueryFunctionContext<QueryKey>,
25+
context: QueryFunctionContext,
2626
) => PartialClientInferRequest<TAppRoute, TClientArgs>,
2727
options?: UseInfiniteQueryOptions<
2828
DataResponse<TAppRoute>,
2929
ErrorResponse<TAppRoute>,
30-
TAppRoute
30+
TData
3131
>,
32-
) => UseInfiniteQueryReturnType<
33-
DataResponse<TAppRoute>,
34-
ErrorResponse<TAppRoute>
35-
>;
32+
) => UseInfiniteQueryReturnType<TData, ErrorResponse<TAppRoute>>;
3633

3734
export const getRouteUseInfiniteQuery =
3835
<TAppRoute extends AppRoute, TClientArgs extends ClientArgs>(
@@ -44,9 +41,9 @@ export const getRouteUseInfiniteQuery =
4441
argsMapper: (
4542
context: QueryFunctionContext,
4643
) => ClientInferRequest<AppRouteMutation, ClientArgs>,
47-
options?: UseInfiniteQueryOptions<TAppRoute['responses']>,
44+
options?: UseInfiniteQueryOptions<DataResponse<TAppRoute>>,
4845
) => {
49-
const dataFn: QueryFunction<TAppRoute['responses']> = async (context) => {
46+
const dataFn: QueryFunction<DataResponse<TAppRoute>> = async (context) => {
5047
const resultingQueryArgs = argsMapper(context);
5148

5249
const innerDataFn = queryFn(route, clientArgs, resultingQueryArgs);

libs/ts-rest/vue-query/src/lib/use-query.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
useQuery,
3-
type QueryKey,
4-
type UseQueryReturnType,
3+
QueryKey,
4+
UseQueryReturnType,
55
UseQueryOptions,
66
QueryFunctionContext,
77
} from '@tanstack/vue-query';
@@ -21,16 +21,24 @@ export type DataReturnQuery<
2121
TClientArgs extends ClientArgs,
2222
TArgs = PartialClientInferRequest<TAppRoute, TClientArgs>,
2323
> = AreAllPropertiesOptional<TArgs> extends true
24-
? (
24+
? <TData = DataResponse<TAppRoute>>(
2525
queryKey: QueryKey,
2626
args?: (context: QueryFunctionContext<QueryKey>) => TArgs,
27-
options?: UseQueryOptions<TAppRoute>,
28-
) => UseQueryReturnType<DataResponse<TAppRoute>, ErrorResponse<TAppRoute>>
29-
: (
27+
options?: UseQueryOptions<
28+
DataResponse<TAppRoute>,
29+
ErrorResponse<TAppRoute>,
30+
TData
31+
>,
32+
) => UseQueryReturnType<TData, ErrorResponse<TAppRoute>>
33+
: <TData = DataResponse<TAppRoute>>(
3034
queryKey: QueryKey,
3135
args: (context: QueryFunctionContext<QueryKey>) => TArgs,
32-
options?: UseQueryOptions<TAppRoute>,
33-
) => UseQueryReturnType<DataResponse<TAppRoute>, ErrorResponse<TAppRoute>>;
36+
options?: UseQueryOptions<
37+
DataResponse<TAppRoute>,
38+
ErrorResponse<TAppRoute>,
39+
TData
40+
>,
41+
) => UseQueryReturnType<TData, ErrorResponse<TAppRoute>>;
3442

3543
export const getRouteUseQuery = <
3644
TAppRoute extends AppRoute,
@@ -44,7 +52,7 @@ export const getRouteUseQuery = <
4452
args?: (
4553
context: QueryFunctionContext<QueryKey>,
4654
) => ClientInferRequest<AppRouteMutation, ClientArgs>,
47-
options?: UseQueryOptions<TAppRoute['responses']>,
55+
options?: UseQueryOptions<DataResponse<TAppRoute>>,
4856
) => {
4957
const dataFn = queryFn(route, clientArgs, args);
5058

libs/ts-rest/vue-query/src/lib/vue-query.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,44 @@ describe('vue-query', () => {
220220
expect(unref(result.current.data)).toStrictEqual(SUCCESS_RESPONSE);
221221
});
222222

223+
it('useQuery with select should handle success', async () => {
224+
api.mockResolvedValue({ status: 200, body: { message: 'hello world' } });
225+
226+
const { result } = renderHook(
227+
() =>
228+
client.health.useQuery(['health'], () => ({}), {
229+
select: (data) => data.body.message,
230+
}),
231+
{
232+
wrapper,
233+
},
234+
);
235+
236+
expect(unref(result.current.data)).toStrictEqual(undefined);
237+
238+
expect(unref(result.current.isLoading)).toStrictEqual(true);
239+
240+
expect(api).toHaveBeenCalledWith({
241+
method: 'GET',
242+
path: 'https://api.com/health',
243+
body: undefined,
244+
headers: {
245+
'x-test': 'test',
246+
},
247+
route: router.health,
248+
signal: expect.any(AbortSignal),
249+
fetchOptions: {
250+
signal: expect.any(AbortSignal),
251+
},
252+
});
253+
254+
await waitFor(() => {
255+
expect(unref(result.current.isLoading)).toStrictEqual(false);
256+
});
257+
258+
expect(unref(result.current.data)).toStrictEqual('hello world');
259+
});
260+
223261
it('useQuery should accept extra headers', async () => {
224262
api.mockResolvedValue(SUCCESS_RESPONSE);
225263

0 commit comments

Comments
 (0)