Skip to content

Commit aa557c3

Browse files
committed
feat(vue-query): add new methods to vue-query
1 parent 4006613 commit aa557c3

7 files changed

Lines changed: 554 additions & 5 deletions

File tree

.changeset/cold-islands-move.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/vue-query': minor
3+
---
4+
5+
add new imperitive methods to QueryClient proxy

packages/vue-query/src/__tests__/infiniteQueryOptions.test-d.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { assertType, describe, expectTypeOf, it } from 'vitest'
22
import { dataTagSymbol } from '@tanstack/query-core'
3-
import { reactive } from 'vue-demi'
3+
import { reactive, unref } from 'vue-demi'
44
import { queryKey } from '@tanstack/query-test-utils'
55
import { infiniteQueryOptions } from '../infiniteQueryOptions'
66
import { QueryClient } from '../queryClient'
@@ -49,6 +49,41 @@ describe('infiniteQueryOptions', () => {
4949
InfiniteData<string, unknown> | undefined
5050
>()
5151
})
52+
it('should work when passed to infiniteQuery', async () => {
53+
const options = infiniteQueryOptions({
54+
queryKey: ['key'],
55+
queryFn: () => Promise.resolve('string'),
56+
getNextPageParam: () => 1,
57+
initialPageParam: 1,
58+
})
59+
60+
const data = await new QueryClient().infiniteQuery({
61+
...unref(options),
62+
enabled: true,
63+
staleTime: 0,
64+
pages: 1,
65+
})
66+
67+
expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()
68+
})
69+
it('should work when passed to infiniteQuery with select', async () => {
70+
const options = infiniteQueryOptions({
71+
queryKey: ['key'],
72+
queryFn: () => Promise.resolve('string'),
73+
getNextPageParam: () => 1,
74+
initialPageParam: 1,
75+
select: (data) => data.pages,
76+
})
77+
78+
const data = await new QueryClient().infiniteQuery({
79+
...unref(options),
80+
enabled: true,
81+
staleTime: 0,
82+
pages: 1,
83+
})
84+
85+
expectTypeOf(data).toEqualTypeOf<Array<string>>()
86+
})
5287
it('should tag the queryKey with the result type of the QueryFn', () => {
5388
const key = queryKey()
5489
const { queryKey: tagged } = infiniteQueryOptions({

packages/vue-query/src/__tests__/queryClient.test-d.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { assertType, describe, expectTypeOf, it } from 'vitest'
2+
import { skipToken } from '@tanstack/query-core'
23
import { queryKey } from '@tanstack/query-test-utils'
34
import { QueryClient } from '../queryClient'
45
import type { DataTag, InfiniteData } from '@tanstack/query-core'
@@ -151,3 +152,108 @@ describe('fetchInfiniteQuery', () => {
151152
])
152153
})
153154
})
155+
156+
describe('query', () => {
157+
it('should return the selected type', () => {
158+
const result = new QueryClient().query({
159+
queryKey: ['key'],
160+
queryFn: () => Promise.resolve('string'),
161+
select: (data) => data.length,
162+
})
163+
164+
expectTypeOf(result).toEqualTypeOf<Promise<number>>()
165+
})
166+
167+
it('should infer select type with skipToken', () => {
168+
const result = new QueryClient().query({
169+
queryKey: ['key'],
170+
queryFn: skipToken,
171+
select: (data: string) => data.length,
172+
})
173+
174+
expectTypeOf(result).toEqualTypeOf<Promise<number>>()
175+
})
176+
177+
it('should infer select type with skipToken and enabled false', () => {
178+
const result = new QueryClient().query({
179+
queryKey: ['key'],
180+
queryFn: skipToken,
181+
enabled: false,
182+
select: (data: string) => data.length,
183+
})
184+
185+
expectTypeOf(result).toEqualTypeOf<Promise<number>>()
186+
})
187+
188+
it('should infer select type with skipToken and enabled true', () => {
189+
const result = new QueryClient().query({
190+
queryKey: ['key'],
191+
queryFn: skipToken,
192+
enabled: true,
193+
select: (data: string) => data.length,
194+
})
195+
196+
expectTypeOf(result).toEqualTypeOf<Promise<number>>()
197+
})
198+
})
199+
200+
describe('infiniteQuery', () => {
201+
it('should return infinite data', async () => {
202+
const data = await new QueryClient().infiniteQuery({
203+
queryKey: ['key'],
204+
queryFn: () => Promise.resolve('string'),
205+
getNextPageParam: () => 1,
206+
initialPageParam: 1,
207+
})
208+
209+
expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()
210+
})
211+
212+
it('should return the selected type', () => {
213+
const result = new QueryClient().infiniteQuery({
214+
queryKey: ['key'],
215+
queryFn: () => Promise.resolve({ count: 1 }),
216+
getNextPageParam: () => 2,
217+
initialPageParam: 1,
218+
select: (data) => data.pages.map((page) => page.count),
219+
})
220+
221+
expectTypeOf(result).toEqualTypeOf<Promise<Array<number>>>()
222+
})
223+
224+
it('should allow passing pages with getNextPageParam', () => {
225+
assertType<Parameters<QueryClient['infiniteQuery']>>([
226+
{
227+
queryKey: ['key'],
228+
queryFn: () => Promise.resolve('string'),
229+
initialPageParam: 1,
230+
getNextPageParam: () => 1,
231+
pages: 5,
232+
},
233+
])
234+
})
235+
236+
it('should not allow passing pages without getNextPageParam', () => {
237+
assertType<Parameters<QueryClient['infiniteQuery']>>([
238+
// @ts-expect-error Property 'getNextPageParam' is missing
239+
{
240+
queryKey: ['key'],
241+
queryFn: () => Promise.resolve('string'),
242+
initialPageParam: 1,
243+
pages: 5,
244+
},
245+
])
246+
})
247+
248+
it('should preserve page param inference', () => {
249+
new QueryClient().infiniteQuery({
250+
queryKey: ['key'],
251+
queryFn: ({ pageParam }) => {
252+
expectTypeOf(pageParam).toEqualTypeOf<number>()
253+
return Promise.resolve(pageParam.toString())
254+
},
255+
initialPageParam: 1,
256+
getNextPageParam: () => undefined,
257+
})
258+
})
259+
})

packages/vue-query/src/__tests__/queryClient.test.ts

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2-
import { ref } from 'vue-demi'
2+
import { ref, unref } from 'vue-demi'
33
import { QueryClient as QueryClientOrigin } from '@tanstack/query-core'
44
import { QueryClient } from '../queryClient'
55
import { infiniteQueryOptions } from '../infiniteQueryOptions'
@@ -338,6 +338,41 @@ describe('QueryCache', () => {
338338
})
339339
})
340340

341+
describe('query', () => {
342+
it('should properly unwrap queryKey', () => {
343+
const queryClient = new QueryClient()
344+
345+
queryClient.query({
346+
queryKey: queryKeyRef,
347+
})
348+
349+
expect(QueryClientOrigin.prototype.query).toBeCalledWith({
350+
queryKey: queryKeyUnref,
351+
})
352+
})
353+
354+
it('should properly unwrap enabled, staleTime, and select', () => {
355+
const queryClient = new QueryClient()
356+
const enabled = () => false
357+
const staleTime = () => 1000
358+
const select = (data: string) => data.length
359+
360+
queryClient.query({
361+
queryKey: queryKeyRef,
362+
enabled: ref(enabled),
363+
staleTime: ref(staleTime),
364+
select: ref(select),
365+
})
366+
367+
expect(QueryClientOrigin.prototype.query).toBeCalledWith({
368+
queryKey: queryKeyUnref,
369+
enabled,
370+
staleTime,
371+
select,
372+
})
373+
})
374+
})
375+
341376
describe('prefetchQuery', () => {
342377
it('should properly unwrap parameters', () => {
343378
const queryClient = new QueryClient()
@@ -387,6 +422,59 @@ describe('QueryCache', () => {
387422
})
388423
})
389424

425+
describe('infiniteQuery', () => {
426+
it('should properly unwrap queryKey, initialPageParam, pages, and select', () => {
427+
const queryClient = new QueryClient()
428+
const getNextPageParam = () => 1
429+
const select = (data: { pages: Array<string> }) => data.pages.length
430+
431+
queryClient.infiniteQuery({
432+
queryKey: queryKeyRef,
433+
initialPageParam: ref(0),
434+
pages: ref(2),
435+
getNextPageParam: ref(getNextPageParam),
436+
select: ref(select),
437+
})
438+
439+
expect(QueryClientOrigin.prototype.infiniteQuery).toBeCalledWith(
440+
expect.objectContaining({
441+
queryKey: queryKeyUnref,
442+
initialPageParam: 0,
443+
pages: 2,
444+
getNextPageParam,
445+
select,
446+
}),
447+
)
448+
})
449+
450+
it('should properly unwrap getNextPageParam when using infiniteQueryOptions', () => {
451+
const queryClient = new QueryClient()
452+
const getNextPageParam = () => 12
453+
454+
const options = infiniteQueryOptions({
455+
queryKey: queryKeyRef,
456+
initialPageParam: ref(0),
457+
getNextPageParam: ref(getNextPageParam),
458+
})
459+
460+
queryClient.infiniteQuery({
461+
...unref(options),
462+
enabled: true,
463+
staleTime: 0,
464+
pages: 1,
465+
})
466+
467+
expect(QueryClientOrigin.prototype.infiniteQuery).toBeCalledWith(
468+
expect.objectContaining({
469+
queryKey: queryKeyUnref,
470+
initialPageParam: 0,
471+
pages: 1,
472+
getNextPageParam,
473+
}),
474+
)
475+
})
476+
})
477+
390478
describe('prefetchInfiniteQuery', () => {
391479
it('should properly unwrap parameters', () => {
392480
const queryClient = new QueryClient()

packages/vue-query/src/__tests__/queryOptions.test-d.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,25 @@ describe('queryOptions', () => {
3939
const { data } = reactive(useQuery(options))
4040
expectTypeOf(data).toEqualTypeOf<number | undefined>()
4141
})
42+
it('should work when passed to query', async () => {
43+
const options = queryOptions({
44+
queryKey: ['key'],
45+
queryFn: () => Promise.resolve(5),
46+
})
47+
48+
const data = await new QueryClient().query(options)
49+
expectTypeOf(data).toEqualTypeOf<number>()
50+
})
51+
it('should work when passed to query with select', async () => {
52+
const options = queryOptions({
53+
queryKey: ['key'],
54+
queryFn: () => Promise.resolve(5),
55+
select: (data) => data.toString(),
56+
})
57+
58+
const data = await new QueryClient().query(options)
59+
expectTypeOf(data).toEqualTypeOf<string>()
60+
})
4261
it('should tag the queryKey with the result type of the QueryFn', () => {
4362
const key = queryKey()
4463
const { queryKey: tagged } = queryOptions({
@@ -132,10 +151,13 @@ describe('queryOptions', () => {
132151
// Should not error
133152
const data = queryClient.invalidateQueries(options)
134153
// Should not error
135-
const data2 = queryClient.fetchQuery(options)
154+
const data2 = queryClient.query(options)
155+
// Should not error
156+
const data3 = queryClient.fetchQuery(options)
136157

137158
expectTypeOf(data).toEqualTypeOf<Promise<void>>()
138159
expectTypeOf(data2).toEqualTypeOf<Promise<number>>()
160+
expectTypeOf(data3).toEqualTypeOf<Promise<number>>()
139161
})
140162

141163
it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {

0 commit comments

Comments
 (0)