@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,550 @@
|
|
|
1
|
+
import type { EndpointHandler, ErrorSchemaRecord } from '@navios/builder'
|
|
2
|
+
import type { DataTag, UseSuspenseQueryOptions } from '@tanstack/react-query'
|
|
3
|
+
import type { z } from 'zod/v4'
|
|
4
|
+
|
|
5
|
+
import { assertType, describe, test } from 'vitest'
|
|
6
|
+
import { z as zod } from 'zod/v4'
|
|
7
|
+
|
|
8
|
+
import type { Split } from '../../index.mjs'
|
|
9
|
+
import type { QueryHelpers } from '../../query/types.mjs'
|
|
10
|
+
import type { ClientInstance } from '../types.mjs'
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// TEST SCHEMAS
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
const responseSchema = zod.object({
|
|
17
|
+
id: zod.string(),
|
|
18
|
+
name: zod.string(),
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const querySchema = zod.object({
|
|
22
|
+
page: zod.number(),
|
|
23
|
+
limit: zod.number(),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const requestSchema = zod.object({
|
|
27
|
+
name: zod.string(),
|
|
28
|
+
email: zod.string(),
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const error400Schema = zod.object({ error: zod.string(), code: zod.number() })
|
|
32
|
+
const error404Schema = zod.object({ notFound: zod.literal(true) })
|
|
33
|
+
const error500Schema = zod.object({ serverError: zod.string() })
|
|
34
|
+
|
|
35
|
+
const errorSchema = {
|
|
36
|
+
400: error400Schema,
|
|
37
|
+
404: error404Schema,
|
|
38
|
+
500: error500Schema,
|
|
39
|
+
} satisfies ErrorSchemaRecord
|
|
40
|
+
|
|
41
|
+
type ResponseType = z.output<typeof responseSchema>
|
|
42
|
+
type RequestType = z.input<typeof requestSchema>
|
|
43
|
+
type Error400 = z.output<typeof error400Schema>
|
|
44
|
+
type Error404 = z.output<typeof error404Schema>
|
|
45
|
+
type Error500 = z.output<typeof error500Schema>
|
|
46
|
+
type ErrorUnion = Error400 | Error404 | Error500
|
|
47
|
+
type ResponseWithErrors = ResponseType | ErrorUnion
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// CLIENT INSTANCE DECLARATIONS
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
declare const client: ClientInstance<false>
|
|
54
|
+
declare const clientWithDiscriminator: ClientInstance<true>
|
|
55
|
+
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// MOCK ENDPOINTS FOR TESTING - Using EndpointHandler type from builder
|
|
58
|
+
// ============================================================================
|
|
59
|
+
|
|
60
|
+
// Regular endpoints using EndpointHandler
|
|
61
|
+
declare const getEndpoint: EndpointHandler<
|
|
62
|
+
{
|
|
63
|
+
method: 'GET'
|
|
64
|
+
url: '/users'
|
|
65
|
+
responseSchema: typeof responseSchema
|
|
66
|
+
},
|
|
67
|
+
false
|
|
68
|
+
>
|
|
69
|
+
|
|
70
|
+
declare const getEndpointWithUrlParams: EndpointHandler<
|
|
71
|
+
{
|
|
72
|
+
method: 'GET'
|
|
73
|
+
url: '/users/$userId'
|
|
74
|
+
responseSchema: typeof responseSchema
|
|
75
|
+
},
|
|
76
|
+
false
|
|
77
|
+
>
|
|
78
|
+
|
|
79
|
+
declare const getEndpointWithQuery: EndpointHandler<
|
|
80
|
+
{
|
|
81
|
+
method: 'GET'
|
|
82
|
+
url: '/users'
|
|
83
|
+
querySchema: typeof querySchema
|
|
84
|
+
responseSchema: typeof responseSchema
|
|
85
|
+
},
|
|
86
|
+
false
|
|
87
|
+
>
|
|
88
|
+
|
|
89
|
+
declare const getEndpointWithUrlParamsAndQuery: EndpointHandler<
|
|
90
|
+
{
|
|
91
|
+
method: 'GET'
|
|
92
|
+
url: '/users/$userId/posts'
|
|
93
|
+
querySchema: typeof querySchema
|
|
94
|
+
responseSchema: typeof responseSchema
|
|
95
|
+
},
|
|
96
|
+
false
|
|
97
|
+
>
|
|
98
|
+
|
|
99
|
+
declare const postEndpoint: EndpointHandler<
|
|
100
|
+
{
|
|
101
|
+
method: 'POST'
|
|
102
|
+
url: '/users'
|
|
103
|
+
requestSchema: typeof requestSchema
|
|
104
|
+
responseSchema: typeof responseSchema
|
|
105
|
+
},
|
|
106
|
+
false
|
|
107
|
+
>
|
|
108
|
+
|
|
109
|
+
declare const postEndpointWithUrlParams: EndpointHandler<
|
|
110
|
+
{
|
|
111
|
+
method: 'POST'
|
|
112
|
+
url: '/users/$userId/posts'
|
|
113
|
+
requestSchema: typeof requestSchema
|
|
114
|
+
responseSchema: typeof responseSchema
|
|
115
|
+
},
|
|
116
|
+
false
|
|
117
|
+
>
|
|
118
|
+
|
|
119
|
+
declare const endpointWithErrors: EndpointHandler<
|
|
120
|
+
{
|
|
121
|
+
method: 'GET'
|
|
122
|
+
url: '/users'
|
|
123
|
+
responseSchema: typeof responseSchema
|
|
124
|
+
errorSchema: typeof errorSchema
|
|
125
|
+
},
|
|
126
|
+
false
|
|
127
|
+
>
|
|
128
|
+
|
|
129
|
+
// NOTE: Stream endpoints are not tested here due to type compatibility issues
|
|
130
|
+
// with mutationFromEndpoint. StreamHandler<Config> doesn't match the expected
|
|
131
|
+
// EndpointOptions | BaseEndpointOptions constraint correctly.
|
|
132
|
+
|
|
133
|
+
// Discriminator mode endpoints
|
|
134
|
+
declare const endpointWithErrorsDiscriminator: EndpointHandler<
|
|
135
|
+
{
|
|
136
|
+
method: 'GET'
|
|
137
|
+
url: '/users'
|
|
138
|
+
responseSchema: typeof responseSchema
|
|
139
|
+
errorSchema: typeof errorSchema
|
|
140
|
+
},
|
|
141
|
+
true
|
|
142
|
+
>
|
|
143
|
+
|
|
144
|
+
declare const infiniteEndpointWithErrors: EndpointHandler<
|
|
145
|
+
{
|
|
146
|
+
method: 'GET'
|
|
147
|
+
url: '/users'
|
|
148
|
+
querySchema: typeof querySchema
|
|
149
|
+
responseSchema: typeof responseSchema
|
|
150
|
+
errorSchema: typeof errorSchema
|
|
151
|
+
},
|
|
152
|
+
true
|
|
153
|
+
>
|
|
154
|
+
|
|
155
|
+
declare const mutationEndpointWithErrors: EndpointHandler<
|
|
156
|
+
{
|
|
157
|
+
method: 'POST'
|
|
158
|
+
url: '/users'
|
|
159
|
+
requestSchema: typeof requestSchema
|
|
160
|
+
responseSchema: typeof responseSchema
|
|
161
|
+
errorSchema: typeof errorSchema
|
|
162
|
+
},
|
|
163
|
+
true
|
|
164
|
+
>
|
|
165
|
+
|
|
166
|
+
// ============================================================================
|
|
167
|
+
// queryFromEndpoint - DEFAULT MODE (UseDiscriminator=false)
|
|
168
|
+
// ============================================================================
|
|
169
|
+
|
|
170
|
+
describe('ClientInstance<false> queryFromEndpoint() method', () => {
|
|
171
|
+
describe('basic usage', () => {
|
|
172
|
+
test('simple GET endpoint - result is callable with optional signal/headers only', () => {
|
|
173
|
+
const query = client.queryFromEndpoint(getEndpoint)
|
|
174
|
+
// Should NOT require params or data for simple GET endpoints
|
|
175
|
+
const options = query({})
|
|
176
|
+
assertType<
|
|
177
|
+
UseSuspenseQueryOptions<
|
|
178
|
+
ResponseType,
|
|
179
|
+
Error,
|
|
180
|
+
ResponseType,
|
|
181
|
+
DataTag<Split<'/users', '/'>, ResponseType, Error>
|
|
182
|
+
>
|
|
183
|
+
>(options)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
test('endpoint type structure is correct', () => {
|
|
187
|
+
// Verify the endpoint has the expected config structure
|
|
188
|
+
assertType<typeof responseSchema>(getEndpoint.config.responseSchema)
|
|
189
|
+
assertType<'GET'>(getEndpoint.config.method)
|
|
190
|
+
assertType<'/users'>(getEndpoint.config.url)
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
test('GET endpoint with URL params requires urlParams', () => {
|
|
194
|
+
const query = client.queryFromEndpoint(getEndpointWithUrlParams)
|
|
195
|
+
// Should require urlParams
|
|
196
|
+
query({ urlParams: { userId: '123' } })
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
test('GET endpoint with query schema requires params', () => {
|
|
200
|
+
const query = client.queryFromEndpoint(getEndpointWithQuery)
|
|
201
|
+
// Should require params
|
|
202
|
+
query({ params: { page: 1, limit: 10 } })
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
test('GET endpoint with URL params and query requires both', () => {
|
|
206
|
+
const query = client.queryFromEndpoint(getEndpointWithUrlParamsAndQuery)
|
|
207
|
+
// Should require both urlParams and params
|
|
208
|
+
query({
|
|
209
|
+
urlParams: { userId: '123' },
|
|
210
|
+
params: { page: 1, limit: 10 },
|
|
211
|
+
})
|
|
212
|
+
})
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
describe('QueryHelpers', () => {
|
|
216
|
+
test('queryFromEndpoint has QueryHelpers attached', () => {
|
|
217
|
+
const query = client.queryFromEndpoint(getEndpoint)
|
|
218
|
+
|
|
219
|
+
// QueryHelpers are attached regardless of the params issue
|
|
220
|
+
assertType<QueryHelpers<'/users', undefined, ResponseType>['queryKey']>(
|
|
221
|
+
query.queryKey,
|
|
222
|
+
)
|
|
223
|
+
assertType<QueryHelpers<'/users', undefined, ResponseType>['use']>(
|
|
224
|
+
query.use,
|
|
225
|
+
)
|
|
226
|
+
assertType<
|
|
227
|
+
QueryHelpers<'/users', undefined, ResponseType>['useSuspense']
|
|
228
|
+
>(query.useSuspense)
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
test('queryFromEndpoint with query schema has typed QueryHelpers', () => {
|
|
232
|
+
const query = client.queryFromEndpoint(getEndpointWithQuery)
|
|
233
|
+
|
|
234
|
+
assertType<
|
|
235
|
+
QueryHelpers<'/users', typeof querySchema, ResponseType>['queryKey']
|
|
236
|
+
>(query.queryKey)
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
describe('processResponse option', () => {
|
|
241
|
+
test('processResponse receives correct input type', () => {
|
|
242
|
+
client.queryFromEndpoint(getEndpoint, {
|
|
243
|
+
processResponse: (data) => {
|
|
244
|
+
// data should be ResponseType
|
|
245
|
+
assertType<ResponseType>(data)
|
|
246
|
+
return data.name.toUpperCase()
|
|
247
|
+
},
|
|
248
|
+
})
|
|
249
|
+
})
|
|
250
|
+
})
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
// ============================================================================
|
|
254
|
+
// infiniteQueryFromEndpoint - DEFAULT MODE (UseDiscriminator=false)
|
|
255
|
+
// ============================================================================
|
|
256
|
+
|
|
257
|
+
describe('ClientInstance<false> infiniteQueryFromEndpoint() method', () => {
|
|
258
|
+
describe('QueryHelpers for infinite', () => {
|
|
259
|
+
test('infiniteQueryFromEndpoint has QueryHelpers with isInfinite=true', () => {
|
|
260
|
+
const query = client.infiniteQueryFromEndpoint(getEndpointWithQuery, {
|
|
261
|
+
getNextPageParam: () => undefined,
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
assertType<
|
|
265
|
+
QueryHelpers<
|
|
266
|
+
'/users',
|
|
267
|
+
typeof querySchema,
|
|
268
|
+
ResponseType,
|
|
269
|
+
true
|
|
270
|
+
>['queryKey']
|
|
271
|
+
>(query.queryKey)
|
|
272
|
+
})
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
describe('pagination callbacks', () => {
|
|
276
|
+
test('getNextPageParam receives correct types', () => {
|
|
277
|
+
client.infiniteQueryFromEndpoint(getEndpointWithQuery, {
|
|
278
|
+
getNextPageParam: (
|
|
279
|
+
lastPage,
|
|
280
|
+
allPages,
|
|
281
|
+
lastPageParam,
|
|
282
|
+
allPageParams,
|
|
283
|
+
) => {
|
|
284
|
+
assertType<ResponseType>(lastPage)
|
|
285
|
+
assertType<ResponseType[]>(allPages)
|
|
286
|
+
assertType<z.infer<typeof querySchema> | undefined>(lastPageParam)
|
|
287
|
+
assertType<z.infer<typeof querySchema>[] | undefined>(allPageParams)
|
|
288
|
+
return { page: 1, limit: 10 }
|
|
289
|
+
},
|
|
290
|
+
})
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
test('getPreviousPageParam receives correct types', () => {
|
|
294
|
+
client.infiniteQueryFromEndpoint(getEndpointWithQuery, {
|
|
295
|
+
getNextPageParam: () => undefined,
|
|
296
|
+
getPreviousPageParam: (
|
|
297
|
+
firstPage,
|
|
298
|
+
allPages,
|
|
299
|
+
lastPageParam,
|
|
300
|
+
allPageParams,
|
|
301
|
+
) => {
|
|
302
|
+
assertType<ResponseType>(firstPage)
|
|
303
|
+
assertType<ResponseType[]>(allPages)
|
|
304
|
+
assertType<z.infer<typeof querySchema> | undefined>(lastPageParam)
|
|
305
|
+
assertType<z.infer<typeof querySchema>[] | undefined>(allPageParams)
|
|
306
|
+
return { page: 0, limit: 10 }
|
|
307
|
+
},
|
|
308
|
+
})
|
|
309
|
+
})
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
describe('processResponse option', () => {
|
|
313
|
+
test('processResponse receives correct type', () => {
|
|
314
|
+
client.infiniteQueryFromEndpoint(getEndpointWithQuery, {
|
|
315
|
+
processResponse: (data) => {
|
|
316
|
+
assertType<ResponseType>(data)
|
|
317
|
+
return { items: [data], hasMore: true }
|
|
318
|
+
},
|
|
319
|
+
getNextPageParam: (lastPage) => {
|
|
320
|
+
// lastPage should be the transformed type
|
|
321
|
+
assertType<{ items: ResponseType[]; hasMore: boolean }>(lastPage)
|
|
322
|
+
return lastPage.hasMore ? { page: 1, limit: 10 } : undefined
|
|
323
|
+
},
|
|
324
|
+
})
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
// ============================================================================
|
|
330
|
+
// mutationFromEndpoint - DEFAULT MODE (UseDiscriminator=false)
|
|
331
|
+
// ============================================================================
|
|
332
|
+
|
|
333
|
+
describe('ClientInstance<false> mutationFromEndpoint() method', () => {
|
|
334
|
+
describe('regular endpoints', () => {
|
|
335
|
+
test('POST endpoint returns mutation with correct mutate signature', () => {
|
|
336
|
+
const mutation = client.mutationFromEndpoint(postEndpoint)
|
|
337
|
+
|
|
338
|
+
const { mutate } = mutation()
|
|
339
|
+
// Can call mutate with data
|
|
340
|
+
mutate({ data: { name: 'test', email: 'test@test.com' } })
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
test('POST endpoint with URL params', () => {
|
|
344
|
+
const mutation = client.mutationFromEndpoint(postEndpointWithUrlParams)
|
|
345
|
+
|
|
346
|
+
const { mutate } = mutation()
|
|
347
|
+
mutate({
|
|
348
|
+
urlParams: { userId: '123' },
|
|
349
|
+
data: { name: 'test', email: 'test@test.com' },
|
|
350
|
+
})
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
test('mutationFromEndpoint with processResponse', () => {
|
|
354
|
+
client.mutationFromEndpoint(postEndpoint, {
|
|
355
|
+
processResponse: (data) => {
|
|
356
|
+
assertType<ResponseType>(data)
|
|
357
|
+
return { created: true, user: data }
|
|
358
|
+
},
|
|
359
|
+
})
|
|
360
|
+
})
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
// NOTE: Stream endpoints with mutationFromEndpoint are commented out due to type issues.
|
|
364
|
+
// The mutationFromEndpoint signature expects EndpointOptions | BaseEndpointOptions,
|
|
365
|
+
// but StreamHandler doesn't match correctly, resulting in `never` return type.
|
|
366
|
+
|
|
367
|
+
describe('callback options', () => {
|
|
368
|
+
test('onMutate receives variables and context', () => {
|
|
369
|
+
client.mutationFromEndpoint(postEndpoint, {
|
|
370
|
+
onMutate: (variables, context) => {
|
|
371
|
+
assertType<{ data: RequestType }>(variables)
|
|
372
|
+
assertType<{ meta: Record<string, unknown> | undefined }>(context)
|
|
373
|
+
return { previousData: [] }
|
|
374
|
+
},
|
|
375
|
+
})
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
test('onSuccess receives data, variables, and context', () => {
|
|
379
|
+
client.mutationFromEndpoint(postEndpoint, {
|
|
380
|
+
processResponse: (data) => data,
|
|
381
|
+
onSuccess: (data, variables, context) => {
|
|
382
|
+
assertType<ResponseType>(data)
|
|
383
|
+
assertType<{ data: RequestType }>(variables)
|
|
384
|
+
assertType<{ onMutateResult: unknown }>(context)
|
|
385
|
+
},
|
|
386
|
+
})
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
test('onError receives error, variables, and context', () => {
|
|
390
|
+
client.mutationFromEndpoint(postEndpoint, {
|
|
391
|
+
onError: (error, variables, context) => {
|
|
392
|
+
assertType<Error>(error)
|
|
393
|
+
assertType<{ data: RequestType }>(variables)
|
|
394
|
+
assertType<{ onMutateResult: unknown }>(context)
|
|
395
|
+
},
|
|
396
|
+
})
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
test('onSettled receives data, error, variables, and context', () => {
|
|
400
|
+
client.mutationFromEndpoint(postEndpoint, {
|
|
401
|
+
processResponse: (data) => data,
|
|
402
|
+
onSettled: (data, error, variables, context) => {
|
|
403
|
+
assertType<ResponseType | undefined>(data)
|
|
404
|
+
assertType<Error | null>(error)
|
|
405
|
+
assertType<{ data: RequestType }>(variables)
|
|
406
|
+
assertType<{ onMutateResult: unknown }>(context)
|
|
407
|
+
},
|
|
408
|
+
})
|
|
409
|
+
})
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
describe('errorSchema (errors thrown)', () => {
|
|
413
|
+
test('processResponse receives only success type when UseDiscriminator=false', () => {
|
|
414
|
+
client.mutationFromEndpoint(endpointWithErrors, {
|
|
415
|
+
processResponse: (data) => {
|
|
416
|
+
// With UseDiscriminator=false, data should only be ResponseType
|
|
417
|
+
assertType<ResponseType>(data)
|
|
418
|
+
return data
|
|
419
|
+
},
|
|
420
|
+
})
|
|
421
|
+
})
|
|
422
|
+
})
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
// ============================================================================
|
|
426
|
+
// DISCRIMINATOR MODE (UseDiscriminator=true)
|
|
427
|
+
// ============================================================================
|
|
428
|
+
|
|
429
|
+
describe('ClientInstance<true> fromEndpoint methods (discriminator mode)', () => {
|
|
430
|
+
describe('queryFromEndpoint with errorSchema includes union', () => {
|
|
431
|
+
test('processResponse receives union type', () => {
|
|
432
|
+
clientWithDiscriminator.queryFromEndpoint(
|
|
433
|
+
endpointWithErrorsDiscriminator,
|
|
434
|
+
{
|
|
435
|
+
processResponse: (data) => {
|
|
436
|
+
assertType<ResponseWithErrors>(data)
|
|
437
|
+
return data
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
)
|
|
441
|
+
})
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
describe('infiniteQueryFromEndpoint with errorSchema', () => {
|
|
445
|
+
test('getNextPageParam receives union type', () => {
|
|
446
|
+
clientWithDiscriminator.infiniteQueryFromEndpoint(
|
|
447
|
+
infiniteEndpointWithErrors,
|
|
448
|
+
{
|
|
449
|
+
getNextPageParam: (lastPage) => {
|
|
450
|
+
assertType<ResponseWithErrors>(lastPage)
|
|
451
|
+
return undefined
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
)
|
|
455
|
+
})
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
describe('mutationFromEndpoint with errorSchema', () => {
|
|
459
|
+
test('processResponse receives union type', () => {
|
|
460
|
+
clientWithDiscriminator.mutationFromEndpoint(mutationEndpointWithErrors, {
|
|
461
|
+
processResponse: (data) => {
|
|
462
|
+
assertType<ResponseWithErrors>(data)
|
|
463
|
+
return data
|
|
464
|
+
},
|
|
465
|
+
})
|
|
466
|
+
})
|
|
467
|
+
})
|
|
468
|
+
})
|
|
469
|
+
|
|
470
|
+
// ============================================================================
|
|
471
|
+
// ERROR CASES - Should fail type checking
|
|
472
|
+
// ============================================================================
|
|
473
|
+
|
|
474
|
+
describe('fromEndpoint() error cases', () => {
|
|
475
|
+
describe('queryFromEndpoint errors', () => {
|
|
476
|
+
test('queryFromEndpoint with URL params - missing urlParams', () => {
|
|
477
|
+
const query = client.queryFromEndpoint(getEndpointWithUrlParams)
|
|
478
|
+
|
|
479
|
+
// @ts-expect-error - missing urlParams
|
|
480
|
+
query({})
|
|
481
|
+
})
|
|
482
|
+
|
|
483
|
+
test('queryFromEndpoint with query schema - missing params', () => {
|
|
484
|
+
const query = client.queryFromEndpoint(getEndpointWithQuery)
|
|
485
|
+
|
|
486
|
+
// @ts-expect-error - missing params
|
|
487
|
+
query({})
|
|
488
|
+
})
|
|
489
|
+
|
|
490
|
+
test('queryFromEndpoint with URL params and query - missing urlParams', () => {
|
|
491
|
+
const query = client.queryFromEndpoint(getEndpointWithUrlParamsAndQuery)
|
|
492
|
+
|
|
493
|
+
// @ts-expect-error - missing urlParams
|
|
494
|
+
query({ params: { page: 1, limit: 10 } })
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
test('queryFromEndpoint with URL params and query - missing params', () => {
|
|
498
|
+
const query = client.queryFromEndpoint(getEndpointWithUrlParamsAndQuery)
|
|
499
|
+
|
|
500
|
+
// @ts-expect-error - missing params
|
|
501
|
+
query({ urlParams: { userId: '123' } })
|
|
502
|
+
})
|
|
503
|
+
})
|
|
504
|
+
|
|
505
|
+
describe('mutationFromEndpoint errors', () => {
|
|
506
|
+
test('mutationFromEndpoint().mutate() missing data', () => {
|
|
507
|
+
const mutation = client.mutationFromEndpoint(postEndpoint)
|
|
508
|
+
const { mutate } = mutation()
|
|
509
|
+
|
|
510
|
+
// @ts-expect-error - missing data
|
|
511
|
+
mutate({})
|
|
512
|
+
})
|
|
513
|
+
|
|
514
|
+
test('mutationFromEndpoint().mutate() missing urlParams', () => {
|
|
515
|
+
const mutation = client.mutationFromEndpoint(postEndpointWithUrlParams)
|
|
516
|
+
const { mutate } = mutation()
|
|
517
|
+
|
|
518
|
+
// @ts-expect-error - missing urlParams
|
|
519
|
+
mutate({ data: { name: 'test', email: 'test@test.com' } })
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
test('mutationFromEndpoint().mutate() wrong data shape', () => {
|
|
523
|
+
const mutation = client.mutationFromEndpoint(postEndpoint)
|
|
524
|
+
const { mutate } = mutation()
|
|
525
|
+
|
|
526
|
+
// @ts-expect-error - wrong property names
|
|
527
|
+
mutate({ data: { username: 'test', mail: 'test@test.com' } })
|
|
528
|
+
})
|
|
529
|
+
})
|
|
530
|
+
|
|
531
|
+
describe('processResponse type safety', () => {
|
|
532
|
+
test('queryFromEndpoint processResponse receives correct type', () => {
|
|
533
|
+
client.queryFromEndpoint(getEndpoint, {
|
|
534
|
+
processResponse: (data) => {
|
|
535
|
+
// @ts-expect-error - data doesn't have 'nonExistent' property
|
|
536
|
+
return data.nonExistent
|
|
537
|
+
},
|
|
538
|
+
})
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
test('mutationFromEndpoint processResponse receives correct type', () => {
|
|
542
|
+
client.mutationFromEndpoint(postEndpoint, {
|
|
543
|
+
processResponse: (data) => {
|
|
544
|
+
// @ts-expect-error - data doesn't have 'nonExistent' property
|
|
545
|
+
return data.nonExistent
|
|
546
|
+
},
|
|
547
|
+
})
|
|
548
|
+
})
|
|
549
|
+
})
|
|
550
|
+
})
|