@navios/react-query 0.7.1 → 1.0.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/CHANGELOG.md +171 -1
- package/README.md +152 -4
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/client/declare-client.mts.html +1264 -0
- package/coverage/client/index.html +116 -0
- package/coverage/clover.xml +160 -0
- package/coverage/coverage-final.json +8 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +146 -0
- package/coverage/mutation/index.html +131 -0
- package/coverage/mutation/key-creator.mts.html +277 -0
- package/coverage/mutation/make-hook.mts.html +952 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/query/index.html +161 -0
- package/coverage/query/key-creator.mts.html +415 -0
- package/coverage/query/make-infinite-options.mts.html +601 -0
- package/coverage/query/make-options.mts.html +838 -0
- package/coverage/query/prefetch.mts.html +1063 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/dist/src/__tests__/errorSchema.spec.d.mts +2 -0
- package/dist/src/__tests__/errorSchema.spec.d.mts.map +1 -0
- package/dist/src/__tests__/prefetch.spec.d.mts +2 -0
- package/dist/src/__tests__/prefetch.spec.d.mts.map +1 -0
- package/dist/src/client/__type-tests__/from-endpoint.spec-d.d.mts +2 -0
- package/dist/src/client/__type-tests__/from-endpoint.spec-d.d.mts.map +1 -0
- package/dist/src/client/__type-tests__/infinite-query.spec-d.d.mts +2 -0
- package/dist/src/client/__type-tests__/infinite-query.spec-d.d.mts.map +1 -0
- package/dist/src/client/__type-tests__/multipart-mutation.spec-d.d.mts +2 -0
- package/dist/src/client/__type-tests__/multipart-mutation.spec-d.d.mts.map +1 -0
- package/dist/src/client/__type-tests__/mutation.spec-d.d.mts +2 -0
- package/dist/src/client/__type-tests__/mutation.spec-d.d.mts.map +1 -0
- package/dist/src/client/__type-tests__/query.spec-d.d.mts +2 -0
- package/dist/src/client/__type-tests__/query.spec-d.d.mts.map +1 -0
- package/dist/src/client/declare-client.d.mts +15 -8
- package/dist/src/client/declare-client.d.mts.map +1 -1
- package/dist/src/client/types/from-endpoint.d.mts +130 -0
- package/dist/src/client/types/from-endpoint.d.mts.map +1 -0
- package/dist/src/client/types/helpers.d.mts +74 -0
- package/dist/src/client/types/helpers.d.mts.map +1 -0
- package/dist/src/client/types/index.d.mts +21 -0
- package/dist/src/client/types/index.d.mts.map +1 -0
- package/dist/src/client/types/infinite-query.d.mts +61 -0
- package/dist/src/client/types/infinite-query.d.mts.map +1 -0
- package/dist/src/client/types/multipart-mutation.d.mts +98 -0
- package/dist/src/client/types/multipart-mutation.d.mts.map +1 -0
- package/dist/src/client/types/mutation.d.mts +75 -0
- package/dist/src/client/types/mutation.d.mts.map +1 -0
- package/dist/src/client/types/query.d.mts +65 -0
- package/dist/src/client/types/query.d.mts.map +1 -0
- package/dist/src/client/types.d.mts +1 -608
- package/dist/src/client/types.d.mts.map +1 -1
- package/dist/src/common/types.d.mts +40 -3
- package/dist/src/common/types.d.mts.map +1 -1
- package/dist/src/mutation/index.d.mts +1 -0
- package/dist/src/mutation/index.d.mts.map +1 -1
- package/dist/src/mutation/make-hook.d.mts +42 -16
- package/dist/src/mutation/make-hook.d.mts.map +1 -1
- package/dist/src/mutation/optimistic.d.mts +172 -0
- package/dist/src/mutation/optimistic.d.mts.map +1 -0
- package/dist/src/mutation/types.d.mts +41 -20
- package/dist/src/mutation/types.d.mts.map +1 -1
- package/dist/src/query/index.d.mts +1 -0
- package/dist/src/query/index.d.mts.map +1 -1
- package/dist/src/query/key-creator.d.mts.map +1 -1
- package/dist/src/query/make-infinite-options.d.mts +3 -2
- package/dist/src/query/make-infinite-options.d.mts.map +1 -1
- package/dist/src/query/make-options.d.mts +42 -12
- package/dist/src/query/make-options.d.mts.map +1 -1
- package/dist/src/query/prefetch.d.mts +245 -0
- package/dist/src/query/prefetch.d.mts.map +1 -0
- package/dist/src/query/types.d.mts +25 -18
- package/dist/src/query/types.d.mts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/lib/index.cjs +451 -28
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +1019 -600
- package/lib/index.d.cts.map +1 -1
- package/lib/index.d.mts +1016 -597
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +447 -29
- package/lib/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/declare-client.spec.mts +229 -2
- package/src/__tests__/errorSchema.spec.mts +391 -0
- package/src/__tests__/make-mutation.spec.mts +6 -5
- package/src/__tests__/makeDataTag.spec.mts +2 -1
- package/src/__tests__/makeQueryOptions.spec.mts +2 -1
- package/src/__tests__/prefetch.spec.mts +310 -0
- package/src/client/__type-tests__/from-endpoint.spec-d.mts +550 -0
- package/src/client/__type-tests__/infinite-query.spec-d.mts +648 -0
- package/src/client/__type-tests__/multipart-mutation.spec-d.mts +725 -0
- package/src/client/__type-tests__/mutation.spec-d.mts +757 -0
- package/src/client/__type-tests__/query.spec-d.mts +701 -0
- package/src/client/declare-client.mts +59 -34
- package/src/client/types/from-endpoint.mts +344 -0
- package/src/client/types/helpers.mts +140 -0
- package/src/client/types/index.mts +26 -0
- package/src/client/types/infinite-query.mts +133 -0
- package/src/client/types/multipart-mutation.mts +264 -0
- package/src/client/types/mutation.mts +176 -0
- package/src/client/types/query.mts +132 -0
- package/src/client/types.mts +1 -1935
- package/src/common/types.mts +67 -3
- package/src/mutation/index.mts +1 -0
- package/src/mutation/make-hook.mts +171 -63
- package/src/mutation/optimistic.mts +300 -0
- package/src/mutation/types.mts +87 -30
- package/src/query/index.mts +1 -0
- package/src/query/key-creator.mts +24 -13
- package/src/query/make-infinite-options.mts +53 -10
- package/src/query/make-options.mts +184 -43
- package/src/query/prefetch.mts +326 -0
- package/src/query/types.mts +56 -17
- package/src/client/__type-tests__/client-instance.spec-d.mts +0 -852
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
import type { ErrorSchemaRecord } from '@navios/builder'
|
|
2
|
+
import type {
|
|
3
|
+
DataTag,
|
|
4
|
+
InfiniteData,
|
|
5
|
+
UseSuspenseInfiniteQueryOptions,
|
|
6
|
+
} from '@tanstack/react-query'
|
|
7
|
+
import type { z } from 'zod/v4'
|
|
8
|
+
|
|
9
|
+
import { assertType, describe, test } from 'vitest'
|
|
10
|
+
import { z as zod } from 'zod/v4'
|
|
11
|
+
|
|
12
|
+
import type { Split } from '../../common/types.mjs'
|
|
13
|
+
import type { QueryHelpers } from '../../query/types.mjs'
|
|
14
|
+
import type { ClientInstance, EndpointHelper } from '../types.mjs'
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// TEST SCHEMAS
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
const responseSchema = zod.object({
|
|
21
|
+
id: zod.string(),
|
|
22
|
+
name: zod.string(),
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const querySchema = zod.object({
|
|
26
|
+
page: zod.number(),
|
|
27
|
+
limit: zod.number(),
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const requestSchema = zod.object({
|
|
31
|
+
name: zod.string(),
|
|
32
|
+
email: zod.string(),
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const error400Schema = zod.object({ error: zod.string(), code: zod.number() })
|
|
36
|
+
const error404Schema = zod.object({ notFound: zod.literal(true) })
|
|
37
|
+
const error500Schema = zod.object({ serverError: zod.string() })
|
|
38
|
+
|
|
39
|
+
const errorSchema = {
|
|
40
|
+
400: error400Schema,
|
|
41
|
+
404: error404Schema,
|
|
42
|
+
500: error500Schema,
|
|
43
|
+
} satisfies ErrorSchemaRecord
|
|
44
|
+
|
|
45
|
+
type ResponseType = z.output<typeof responseSchema>
|
|
46
|
+
type QueryType = z.input<typeof querySchema>
|
|
47
|
+
type RequestType = z.input<typeof requestSchema>
|
|
48
|
+
type Error400 = z.output<typeof error400Schema>
|
|
49
|
+
type Error404 = z.output<typeof error404Schema>
|
|
50
|
+
type Error500 = z.output<typeof error500Schema>
|
|
51
|
+
type ErrorUnion = Error400 | Error404 | Error500
|
|
52
|
+
type ResponseWithErrors = ResponseType | ErrorUnion
|
|
53
|
+
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// CLIENT INSTANCE DECLARATIONS
|
|
56
|
+
// ============================================================================
|
|
57
|
+
|
|
58
|
+
declare const client: ClientInstance<false>
|
|
59
|
+
declare const clientWithDiscriminator: ClientInstance<true>
|
|
60
|
+
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// INFINITE QUERY METHOD - DEFAULT MODE (UseDiscriminator=false)
|
|
63
|
+
// ============================================================================
|
|
64
|
+
|
|
65
|
+
describe('ClientInstance<false> infiniteQuery() method', () => {
|
|
66
|
+
describe('GET infinite queries', () => {
|
|
67
|
+
test('basic GET infinite query', () => {
|
|
68
|
+
const query = client.infiniteQuery({
|
|
69
|
+
method: 'GET',
|
|
70
|
+
url: '/users',
|
|
71
|
+
querySchema,
|
|
72
|
+
responseSchema,
|
|
73
|
+
getNextPageParam: (_lastPage, _allPages, _lastPageParam, _allPageParams) =>
|
|
74
|
+
undefined,
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
assertType<
|
|
78
|
+
(params: {
|
|
79
|
+
params: QueryType
|
|
80
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
81
|
+
ResponseType,
|
|
82
|
+
Error,
|
|
83
|
+
InfiniteData<ResponseType>,
|
|
84
|
+
DataTag<Split<'/users', '/'>, ResponseType, Error>,
|
|
85
|
+
z.output<typeof querySchema>
|
|
86
|
+
>
|
|
87
|
+
>(query)
|
|
88
|
+
|
|
89
|
+
// Should have QueryHelpers with isInfinite=true
|
|
90
|
+
assertType<
|
|
91
|
+
QueryHelpers<
|
|
92
|
+
'/users',
|
|
93
|
+
typeof querySchema,
|
|
94
|
+
ResponseType,
|
|
95
|
+
true
|
|
96
|
+
>['queryKey']
|
|
97
|
+
>(query.queryKey)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('GET infinite query with URL params', () => {
|
|
101
|
+
const query = client.infiniteQuery({
|
|
102
|
+
method: 'GET',
|
|
103
|
+
url: '/users/$userId/posts',
|
|
104
|
+
querySchema,
|
|
105
|
+
responseSchema,
|
|
106
|
+
getNextPageParam: () => undefined,
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
assertType<
|
|
110
|
+
(params: {
|
|
111
|
+
urlParams: { userId: string | number }
|
|
112
|
+
params: QueryType
|
|
113
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
114
|
+
ResponseType,
|
|
115
|
+
Error,
|
|
116
|
+
InfiniteData<ResponseType>,
|
|
117
|
+
DataTag<Split<'/users/$userId/posts', '/'>, ResponseType, Error>,
|
|
118
|
+
z.output<typeof querySchema>
|
|
119
|
+
>
|
|
120
|
+
>(query)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('GET infinite query with multiple URL params', () => {
|
|
124
|
+
const query = client.infiniteQuery({
|
|
125
|
+
method: 'GET',
|
|
126
|
+
url: '/orgs/$orgId/users/$userId/posts',
|
|
127
|
+
querySchema,
|
|
128
|
+
responseSchema,
|
|
129
|
+
getNextPageParam: () => undefined,
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
assertType<
|
|
133
|
+
(params: {
|
|
134
|
+
urlParams: { orgId: string | number; userId: string | number }
|
|
135
|
+
params: QueryType
|
|
136
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
137
|
+
ResponseType,
|
|
138
|
+
Error,
|
|
139
|
+
InfiniteData<ResponseType>,
|
|
140
|
+
DataTag<
|
|
141
|
+
Split<'/orgs/$orgId/users/$userId/posts', '/'>,
|
|
142
|
+
ResponseType,
|
|
143
|
+
Error
|
|
144
|
+
>,
|
|
145
|
+
z.output<typeof querySchema>
|
|
146
|
+
>
|
|
147
|
+
>(query)
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('GET infinite query with processResponse transformation', () => {
|
|
151
|
+
const query = client.infiniteQuery({
|
|
152
|
+
method: 'GET',
|
|
153
|
+
url: '/users',
|
|
154
|
+
querySchema,
|
|
155
|
+
responseSchema,
|
|
156
|
+
processResponse: (data) => ({ user: data, timestamp: Date.now() }),
|
|
157
|
+
getNextPageParam: () => undefined,
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
type TransformedType = { user: ResponseType; timestamp: number }
|
|
161
|
+
|
|
162
|
+
assertType<
|
|
163
|
+
(params: {
|
|
164
|
+
params: QueryType
|
|
165
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
166
|
+
TransformedType,
|
|
167
|
+
Error,
|
|
168
|
+
InfiniteData<TransformedType>,
|
|
169
|
+
DataTag<Split<'/users', '/'>, TransformedType, Error>,
|
|
170
|
+
z.output<typeof querySchema>
|
|
171
|
+
>
|
|
172
|
+
>(query)
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
test('GET infinite query with errorSchema (errors thrown)', () => {
|
|
176
|
+
const query = client.infiniteQuery({
|
|
177
|
+
method: 'GET',
|
|
178
|
+
url: '/users',
|
|
179
|
+
querySchema,
|
|
180
|
+
responseSchema,
|
|
181
|
+
errorSchema,
|
|
182
|
+
getNextPageParam: () => undefined,
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
// With UseDiscriminator=false, errors are thrown
|
|
186
|
+
assertType<
|
|
187
|
+
(params: {
|
|
188
|
+
params: QueryType
|
|
189
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
190
|
+
ResponseType,
|
|
191
|
+
Error,
|
|
192
|
+
InfiniteData<ResponseType>,
|
|
193
|
+
DataTag<Split<'/users', '/'>, ResponseType, Error>,
|
|
194
|
+
z.output<typeof querySchema>
|
|
195
|
+
>
|
|
196
|
+
>(query)
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
describe('POST infinite queries', () => {
|
|
201
|
+
test('POST infinite query with request schema', () => {
|
|
202
|
+
const query = client.infiniteQuery({
|
|
203
|
+
method: 'POST',
|
|
204
|
+
url: '/search',
|
|
205
|
+
querySchema,
|
|
206
|
+
requestSchema,
|
|
207
|
+
responseSchema,
|
|
208
|
+
getNextPageParam: () => undefined,
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
assertType<
|
|
212
|
+
(params: {
|
|
213
|
+
params: QueryType
|
|
214
|
+
data: RequestType
|
|
215
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
216
|
+
ResponseType,
|
|
217
|
+
Error,
|
|
218
|
+
InfiniteData<ResponseType>,
|
|
219
|
+
DataTag<Split<'/search', '/'>, ResponseType, Error>,
|
|
220
|
+
z.output<typeof querySchema>
|
|
221
|
+
>
|
|
222
|
+
>(query)
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
test('POST infinite query with URL params and request schema', () => {
|
|
226
|
+
const query = client.infiniteQuery({
|
|
227
|
+
method: 'POST',
|
|
228
|
+
url: '/users/$userId/search',
|
|
229
|
+
querySchema,
|
|
230
|
+
requestSchema,
|
|
231
|
+
responseSchema,
|
|
232
|
+
getNextPageParam: () => undefined,
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
assertType<
|
|
236
|
+
(params: {
|
|
237
|
+
urlParams: { userId: string | number }
|
|
238
|
+
params: QueryType
|
|
239
|
+
data: RequestType
|
|
240
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
241
|
+
ResponseType,
|
|
242
|
+
Error,
|
|
243
|
+
InfiniteData<ResponseType>,
|
|
244
|
+
DataTag<Split<'/users/$userId/search', '/'>, ResponseType, Error>,
|
|
245
|
+
z.output<typeof querySchema>
|
|
246
|
+
>
|
|
247
|
+
>(query)
|
|
248
|
+
})
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
describe('pagination callbacks', () => {
|
|
252
|
+
test('getNextPageParam receives correct types', () => {
|
|
253
|
+
client.infiniteQuery({
|
|
254
|
+
method: 'GET',
|
|
255
|
+
url: '/users',
|
|
256
|
+
querySchema,
|
|
257
|
+
responseSchema,
|
|
258
|
+
getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => {
|
|
259
|
+
assertType<ResponseType>(lastPage)
|
|
260
|
+
assertType<ResponseType[]>(allPages)
|
|
261
|
+
assertType<z.infer<typeof querySchema> | undefined>(lastPageParam)
|
|
262
|
+
assertType<z.infer<typeof querySchema>[] | undefined>(allPageParams)
|
|
263
|
+
return { page: 1, limit: 10 }
|
|
264
|
+
},
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
test('getPreviousPageParam receives correct types', () => {
|
|
269
|
+
client.infiniteQuery({
|
|
270
|
+
method: 'GET',
|
|
271
|
+
url: '/users',
|
|
272
|
+
querySchema,
|
|
273
|
+
responseSchema,
|
|
274
|
+
getNextPageParam: () => undefined,
|
|
275
|
+
getPreviousPageParam: (
|
|
276
|
+
firstPage,
|
|
277
|
+
allPages,
|
|
278
|
+
lastPageParam,
|
|
279
|
+
allPageParams,
|
|
280
|
+
) => {
|
|
281
|
+
assertType<ResponseType>(firstPage)
|
|
282
|
+
assertType<ResponseType[]>(allPages)
|
|
283
|
+
assertType<z.infer<typeof querySchema> | undefined>(lastPageParam)
|
|
284
|
+
assertType<z.infer<typeof querySchema>[] | undefined>(allPageParams)
|
|
285
|
+
return { page: 0, limit: 10 }
|
|
286
|
+
},
|
|
287
|
+
})
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
test('pagination callbacks with transformed page result', () => {
|
|
291
|
+
type TransformedPage = { items: ResponseType[]; hasMore: boolean }
|
|
292
|
+
|
|
293
|
+
client.infiniteQuery({
|
|
294
|
+
method: 'GET',
|
|
295
|
+
url: '/users',
|
|
296
|
+
querySchema,
|
|
297
|
+
responseSchema,
|
|
298
|
+
processResponse: (data): TransformedPage => ({
|
|
299
|
+
items: [data],
|
|
300
|
+
hasMore: true,
|
|
301
|
+
}),
|
|
302
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
303
|
+
assertType<TransformedPage>(lastPage)
|
|
304
|
+
assertType<TransformedPage[]>(allPages)
|
|
305
|
+
return lastPage.hasMore ? { page: 1, limit: 10 } : undefined
|
|
306
|
+
},
|
|
307
|
+
})
|
|
308
|
+
})
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
describe('QueryHelpers', () => {
|
|
312
|
+
test('infinite query has QueryHelpers with isInfinite=true', () => {
|
|
313
|
+
const query = client.infiniteQuery({
|
|
314
|
+
method: 'GET',
|
|
315
|
+
url: '/users',
|
|
316
|
+
querySchema,
|
|
317
|
+
responseSchema,
|
|
318
|
+
getNextPageParam: () => undefined,
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
assertType<
|
|
322
|
+
QueryHelpers<
|
|
323
|
+
'/users',
|
|
324
|
+
typeof querySchema,
|
|
325
|
+
ResponseType,
|
|
326
|
+
true
|
|
327
|
+
>['queryKey']
|
|
328
|
+
>(query.queryKey)
|
|
329
|
+
assertType<
|
|
330
|
+
QueryHelpers<'/users', typeof querySchema, ResponseType, true>['use']
|
|
331
|
+
>(query.use)
|
|
332
|
+
assertType<
|
|
333
|
+
QueryHelpers<
|
|
334
|
+
'/users',
|
|
335
|
+
typeof querySchema,
|
|
336
|
+
ResponseType,
|
|
337
|
+
true
|
|
338
|
+
>['useSuspense']
|
|
339
|
+
>(query.useSuspense)
|
|
340
|
+
assertType<
|
|
341
|
+
QueryHelpers<
|
|
342
|
+
'/users',
|
|
343
|
+
typeof querySchema,
|
|
344
|
+
ResponseType,
|
|
345
|
+
true
|
|
346
|
+
>['invalidate']
|
|
347
|
+
>(query.invalidate)
|
|
348
|
+
assertType<
|
|
349
|
+
QueryHelpers<
|
|
350
|
+
'/users',
|
|
351
|
+
typeof querySchema,
|
|
352
|
+
ResponseType,
|
|
353
|
+
true
|
|
354
|
+
>['invalidateAll']
|
|
355
|
+
>(query.invalidateAll)
|
|
356
|
+
})
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
describe('EndpointHelper', () => {
|
|
360
|
+
test('infinite query exposes endpoint property', () => {
|
|
361
|
+
const query = client.infiniteQuery({
|
|
362
|
+
method: 'GET',
|
|
363
|
+
url: '/users',
|
|
364
|
+
querySchema,
|
|
365
|
+
responseSchema,
|
|
366
|
+
getNextPageParam: () => undefined,
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
assertType<
|
|
370
|
+
EndpointHelper<
|
|
371
|
+
{
|
|
372
|
+
method: 'GET'
|
|
373
|
+
url: '/users'
|
|
374
|
+
querySchema: typeof querySchema
|
|
375
|
+
requestSchema: undefined
|
|
376
|
+
responseSchema: typeof responseSchema
|
|
377
|
+
errorSchema: undefined
|
|
378
|
+
urlParamsSchema: undefined
|
|
379
|
+
},
|
|
380
|
+
false
|
|
381
|
+
>['endpoint']
|
|
382
|
+
>(query.endpoint)
|
|
383
|
+
})
|
|
384
|
+
})
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
// ============================================================================
|
|
388
|
+
// INFINITE QUERY METHOD - DISCRIMINATOR MODE (UseDiscriminator=true)
|
|
389
|
+
// ============================================================================
|
|
390
|
+
|
|
391
|
+
describe('ClientInstance<true> infiniteQuery() method (discriminator mode)', () => {
|
|
392
|
+
describe('errorSchema includes error union in PageResult', () => {
|
|
393
|
+
test('infinite query returns union PageResult', () => {
|
|
394
|
+
const query = clientWithDiscriminator.infiniteQuery({
|
|
395
|
+
method: 'GET',
|
|
396
|
+
url: '/users',
|
|
397
|
+
querySchema,
|
|
398
|
+
responseSchema,
|
|
399
|
+
errorSchema,
|
|
400
|
+
getNextPageParam: (lastPage) => {
|
|
401
|
+
assertType<ResponseWithErrors>(lastPage)
|
|
402
|
+
return undefined
|
|
403
|
+
},
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
assertType<
|
|
407
|
+
(params: {
|
|
408
|
+
params: QueryType
|
|
409
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
410
|
+
ResponseWithErrors,
|
|
411
|
+
Error,
|
|
412
|
+
InfiniteData<ResponseWithErrors>,
|
|
413
|
+
DataTag<Split<'/users', '/'>, ResponseWithErrors, Error>,
|
|
414
|
+
z.output<typeof querySchema>
|
|
415
|
+
>
|
|
416
|
+
>(query)
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
test('processResponse receives union type', () => {
|
|
420
|
+
clientWithDiscriminator.infiniteQuery({
|
|
421
|
+
method: 'GET',
|
|
422
|
+
url: '/users',
|
|
423
|
+
querySchema,
|
|
424
|
+
responseSchema,
|
|
425
|
+
errorSchema,
|
|
426
|
+
processResponse: (data) => {
|
|
427
|
+
assertType<ResponseWithErrors>(data)
|
|
428
|
+
return data
|
|
429
|
+
},
|
|
430
|
+
getNextPageParam: () => undefined,
|
|
431
|
+
})
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
test('processResponse can transform union type', () => {
|
|
435
|
+
type ExpectedResult =
|
|
436
|
+
| { ok: false; error: ErrorUnion }
|
|
437
|
+
| { ok: true; data: ResponseType }
|
|
438
|
+
|
|
439
|
+
const query = clientWithDiscriminator.infiniteQuery({
|
|
440
|
+
method: 'GET',
|
|
441
|
+
url: '/users',
|
|
442
|
+
querySchema,
|
|
443
|
+
responseSchema,
|
|
444
|
+
errorSchema,
|
|
445
|
+
processResponse: (data): ExpectedResult => {
|
|
446
|
+
// Use 'id' property to discriminate - only ResponseType has 'id'
|
|
447
|
+
if ('id' in data) {
|
|
448
|
+
return { ok: true, data }
|
|
449
|
+
}
|
|
450
|
+
return { ok: false, error: data }
|
|
451
|
+
},
|
|
452
|
+
getNextPageParam: (lastPage) => {
|
|
453
|
+
if (!lastPage.ok) return undefined
|
|
454
|
+
return { page: 1, limit: 10 }
|
|
455
|
+
},
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
assertType<
|
|
459
|
+
(params: {
|
|
460
|
+
params: QueryType
|
|
461
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
462
|
+
ExpectedResult,
|
|
463
|
+
Error,
|
|
464
|
+
InfiniteData<ExpectedResult>,
|
|
465
|
+
DataTag<Split<'/users', '/'>, ExpectedResult, Error>,
|
|
466
|
+
z.output<typeof querySchema>
|
|
467
|
+
>
|
|
468
|
+
>(query)
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
test('getNextPageParam receives union type', () => {
|
|
472
|
+
clientWithDiscriminator.infiniteQuery({
|
|
473
|
+
method: 'GET',
|
|
474
|
+
url: '/users',
|
|
475
|
+
querySchema,
|
|
476
|
+
responseSchema,
|
|
477
|
+
errorSchema,
|
|
478
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
479
|
+
assertType<ResponseWithErrors>(lastPage)
|
|
480
|
+
assertType<ResponseWithErrors[]>(allPages)
|
|
481
|
+
return undefined
|
|
482
|
+
},
|
|
483
|
+
})
|
|
484
|
+
})
|
|
485
|
+
})
|
|
486
|
+
|
|
487
|
+
describe('without errorSchema behaves same as default', () => {
|
|
488
|
+
test('infinite query without errorSchema returns only success type', () => {
|
|
489
|
+
const query = clientWithDiscriminator.infiniteQuery({
|
|
490
|
+
method: 'GET',
|
|
491
|
+
url: '/users',
|
|
492
|
+
querySchema,
|
|
493
|
+
responseSchema,
|
|
494
|
+
getNextPageParam: () => undefined,
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
assertType<
|
|
498
|
+
(params: {
|
|
499
|
+
params: QueryType
|
|
500
|
+
}) => UseSuspenseInfiniteQueryOptions<
|
|
501
|
+
ResponseType,
|
|
502
|
+
Error,
|
|
503
|
+
InfiniteData<ResponseType>,
|
|
504
|
+
DataTag<Split<'/users', '/'>, ResponseType, Error>,
|
|
505
|
+
z.output<typeof querySchema>
|
|
506
|
+
>
|
|
507
|
+
>(query)
|
|
508
|
+
})
|
|
509
|
+
})
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
// ============================================================================
|
|
513
|
+
// ERROR CASES - Should fail type checking
|
|
514
|
+
// ============================================================================
|
|
515
|
+
|
|
516
|
+
describe('infiniteQuery() error cases', () => {
|
|
517
|
+
describe('missing required parameters', () => {
|
|
518
|
+
test('infinite query without params when querySchema is defined', () => {
|
|
519
|
+
const query = client.infiniteQuery({
|
|
520
|
+
method: 'GET',
|
|
521
|
+
url: '/users',
|
|
522
|
+
querySchema,
|
|
523
|
+
responseSchema,
|
|
524
|
+
getNextPageParam: () => undefined,
|
|
525
|
+
})
|
|
526
|
+
|
|
527
|
+
// @ts-expect-error - missing params
|
|
528
|
+
query({})
|
|
529
|
+
})
|
|
530
|
+
|
|
531
|
+
test('infinite query without urlParams when URL has params', () => {
|
|
532
|
+
const query = client.infiniteQuery({
|
|
533
|
+
method: 'GET',
|
|
534
|
+
url: '/users/$userId/posts',
|
|
535
|
+
querySchema,
|
|
536
|
+
responseSchema,
|
|
537
|
+
getNextPageParam: () => undefined,
|
|
538
|
+
})
|
|
539
|
+
|
|
540
|
+
// @ts-expect-error - missing urlParams
|
|
541
|
+
query({ params: { page: 1, limit: 10 } })
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
test('POST infinite query without data when requestSchema is defined', () => {
|
|
545
|
+
const query = client.infiniteQuery({
|
|
546
|
+
method: 'POST',
|
|
547
|
+
url: '/search',
|
|
548
|
+
querySchema,
|
|
549
|
+
requestSchema,
|
|
550
|
+
responseSchema,
|
|
551
|
+
getNextPageParam: () => undefined,
|
|
552
|
+
})
|
|
553
|
+
|
|
554
|
+
// @ts-expect-error - missing data
|
|
555
|
+
query({ params: { page: 1, limit: 10 } })
|
|
556
|
+
})
|
|
557
|
+
})
|
|
558
|
+
|
|
559
|
+
describe('wrong parameter types', () => {
|
|
560
|
+
test('params with wrong shape', () => {
|
|
561
|
+
const query = client.infiniteQuery({
|
|
562
|
+
method: 'GET',
|
|
563
|
+
url: '/users',
|
|
564
|
+
querySchema,
|
|
565
|
+
responseSchema,
|
|
566
|
+
getNextPageParam: () => undefined,
|
|
567
|
+
})
|
|
568
|
+
|
|
569
|
+
// @ts-expect-error - wrong property names
|
|
570
|
+
query({ params: { offset: 0, count: 10 } })
|
|
571
|
+
})
|
|
572
|
+
|
|
573
|
+
test('params with wrong value types', () => {
|
|
574
|
+
const query = client.infiniteQuery({
|
|
575
|
+
method: 'GET',
|
|
576
|
+
url: '/users',
|
|
577
|
+
querySchema,
|
|
578
|
+
responseSchema,
|
|
579
|
+
getNextPageParam: () => undefined,
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
// @ts-expect-error - page should be number, not string
|
|
583
|
+
query({ params: { page: '1', limit: 10 } })
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
test('urlParams with wrong type', () => {
|
|
587
|
+
const query = client.infiniteQuery({
|
|
588
|
+
method: 'GET',
|
|
589
|
+
url: '/users/$userId/posts',
|
|
590
|
+
querySchema,
|
|
591
|
+
responseSchema,
|
|
592
|
+
getNextPageParam: () => undefined,
|
|
593
|
+
})
|
|
594
|
+
|
|
595
|
+
// @ts-expect-error - userId should be string | number, not boolean
|
|
596
|
+
query({ urlParams: { userId: true }, params: { page: 1, limit: 10 } })
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
test('data with wrong shape', () => {
|
|
600
|
+
const query = client.infiniteQuery({
|
|
601
|
+
method: 'POST',
|
|
602
|
+
url: '/search',
|
|
603
|
+
querySchema,
|
|
604
|
+
requestSchema,
|
|
605
|
+
responseSchema,
|
|
606
|
+
getNextPageParam: () => undefined,
|
|
607
|
+
})
|
|
608
|
+
|
|
609
|
+
query({
|
|
610
|
+
params: { page: 1, limit: 10 },
|
|
611
|
+
data: {
|
|
612
|
+
// @ts-expect-error - wrong property names
|
|
613
|
+
username: 'test',
|
|
614
|
+
mail: 'test@test.com',
|
|
615
|
+
},
|
|
616
|
+
})
|
|
617
|
+
})
|
|
618
|
+
})
|
|
619
|
+
|
|
620
|
+
describe('getNextPageParam return type', () => {
|
|
621
|
+
test('getNextPageParam must return compatible type', () => {
|
|
622
|
+
client.infiniteQuery({
|
|
623
|
+
method: 'GET',
|
|
624
|
+
url: '/users',
|
|
625
|
+
querySchema,
|
|
626
|
+
responseSchema,
|
|
627
|
+
// @ts-expect-error - return type doesn't match querySchema input
|
|
628
|
+
getNextPageParam: () => ({ wrongKey: 'value' }),
|
|
629
|
+
})
|
|
630
|
+
})
|
|
631
|
+
})
|
|
632
|
+
|
|
633
|
+
describe('processResponse type safety', () => {
|
|
634
|
+
test('processResponse receives correct input type', () => {
|
|
635
|
+
client.infiniteQuery({
|
|
636
|
+
method: 'GET',
|
|
637
|
+
url: '/users',
|
|
638
|
+
querySchema,
|
|
639
|
+
responseSchema,
|
|
640
|
+
processResponse: (data) => {
|
|
641
|
+
// @ts-expect-error - data doesn't have 'nonExistent' property
|
|
642
|
+
return data.nonExistent
|
|
643
|
+
},
|
|
644
|
+
getNextPageParam: () => undefined,
|
|
645
|
+
})
|
|
646
|
+
})
|
|
647
|
+
})
|
|
648
|
+
})
|