@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.
Files changed (117) hide show
  1. package/CHANGELOG.md +171 -1
  2. package/README.md +152 -4
  3. package/coverage/base.css +224 -0
  4. package/coverage/block-navigation.js +87 -0
  5. package/coverage/client/declare-client.mts.html +1264 -0
  6. package/coverage/client/index.html +116 -0
  7. package/coverage/clover.xml +160 -0
  8. package/coverage/coverage-final.json +8 -0
  9. package/coverage/favicon.png +0 -0
  10. package/coverage/index.html +146 -0
  11. package/coverage/mutation/index.html +131 -0
  12. package/coverage/mutation/key-creator.mts.html +277 -0
  13. package/coverage/mutation/make-hook.mts.html +952 -0
  14. package/coverage/prettify.css +1 -0
  15. package/coverage/prettify.js +2 -0
  16. package/coverage/query/index.html +161 -0
  17. package/coverage/query/key-creator.mts.html +415 -0
  18. package/coverage/query/make-infinite-options.mts.html +601 -0
  19. package/coverage/query/make-options.mts.html +838 -0
  20. package/coverage/query/prefetch.mts.html +1063 -0
  21. package/coverage/sort-arrow-sprite.png +0 -0
  22. package/coverage/sorter.js +210 -0
  23. package/dist/src/__tests__/errorSchema.spec.d.mts +2 -0
  24. package/dist/src/__tests__/errorSchema.spec.d.mts.map +1 -0
  25. package/dist/src/__tests__/prefetch.spec.d.mts +2 -0
  26. package/dist/src/__tests__/prefetch.spec.d.mts.map +1 -0
  27. package/dist/src/client/__type-tests__/from-endpoint.spec-d.d.mts +2 -0
  28. package/dist/src/client/__type-tests__/from-endpoint.spec-d.d.mts.map +1 -0
  29. package/dist/src/client/__type-tests__/infinite-query.spec-d.d.mts +2 -0
  30. package/dist/src/client/__type-tests__/infinite-query.spec-d.d.mts.map +1 -0
  31. package/dist/src/client/__type-tests__/multipart-mutation.spec-d.d.mts +2 -0
  32. package/dist/src/client/__type-tests__/multipart-mutation.spec-d.d.mts.map +1 -0
  33. package/dist/src/client/__type-tests__/mutation.spec-d.d.mts +2 -0
  34. package/dist/src/client/__type-tests__/mutation.spec-d.d.mts.map +1 -0
  35. package/dist/src/client/__type-tests__/query.spec-d.d.mts +2 -0
  36. package/dist/src/client/__type-tests__/query.spec-d.d.mts.map +1 -0
  37. package/dist/src/client/declare-client.d.mts +15 -8
  38. package/dist/src/client/declare-client.d.mts.map +1 -1
  39. package/dist/src/client/types/from-endpoint.d.mts +130 -0
  40. package/dist/src/client/types/from-endpoint.d.mts.map +1 -0
  41. package/dist/src/client/types/helpers.d.mts +74 -0
  42. package/dist/src/client/types/helpers.d.mts.map +1 -0
  43. package/dist/src/client/types/index.d.mts +21 -0
  44. package/dist/src/client/types/index.d.mts.map +1 -0
  45. package/dist/src/client/types/infinite-query.d.mts +61 -0
  46. package/dist/src/client/types/infinite-query.d.mts.map +1 -0
  47. package/dist/src/client/types/multipart-mutation.d.mts +98 -0
  48. package/dist/src/client/types/multipart-mutation.d.mts.map +1 -0
  49. package/dist/src/client/types/mutation.d.mts +75 -0
  50. package/dist/src/client/types/mutation.d.mts.map +1 -0
  51. package/dist/src/client/types/query.d.mts +65 -0
  52. package/dist/src/client/types/query.d.mts.map +1 -0
  53. package/dist/src/client/types.d.mts +1 -608
  54. package/dist/src/client/types.d.mts.map +1 -1
  55. package/dist/src/common/types.d.mts +40 -3
  56. package/dist/src/common/types.d.mts.map +1 -1
  57. package/dist/src/mutation/index.d.mts +1 -0
  58. package/dist/src/mutation/index.d.mts.map +1 -1
  59. package/dist/src/mutation/make-hook.d.mts +42 -16
  60. package/dist/src/mutation/make-hook.d.mts.map +1 -1
  61. package/dist/src/mutation/optimistic.d.mts +172 -0
  62. package/dist/src/mutation/optimistic.d.mts.map +1 -0
  63. package/dist/src/mutation/types.d.mts +41 -20
  64. package/dist/src/mutation/types.d.mts.map +1 -1
  65. package/dist/src/query/index.d.mts +1 -0
  66. package/dist/src/query/index.d.mts.map +1 -1
  67. package/dist/src/query/key-creator.d.mts.map +1 -1
  68. package/dist/src/query/make-infinite-options.d.mts +3 -2
  69. package/dist/src/query/make-infinite-options.d.mts.map +1 -1
  70. package/dist/src/query/make-options.d.mts +42 -12
  71. package/dist/src/query/make-options.d.mts.map +1 -1
  72. package/dist/src/query/prefetch.d.mts +245 -0
  73. package/dist/src/query/prefetch.d.mts.map +1 -0
  74. package/dist/src/query/types.d.mts +25 -18
  75. package/dist/src/query/types.d.mts.map +1 -1
  76. package/dist/tsconfig.tsbuildinfo +1 -1
  77. package/lib/index.cjs +451 -28
  78. package/lib/index.cjs.map +1 -1
  79. package/lib/index.d.cts +1019 -600
  80. package/lib/index.d.cts.map +1 -1
  81. package/lib/index.d.mts +1016 -597
  82. package/lib/index.d.mts.map +1 -1
  83. package/lib/index.mjs +447 -29
  84. package/lib/index.mjs.map +1 -1
  85. package/package.json +3 -3
  86. package/src/__tests__/declare-client.spec.mts +229 -2
  87. package/src/__tests__/errorSchema.spec.mts +391 -0
  88. package/src/__tests__/make-mutation.spec.mts +6 -5
  89. package/src/__tests__/makeDataTag.spec.mts +2 -1
  90. package/src/__tests__/makeQueryOptions.spec.mts +2 -1
  91. package/src/__tests__/prefetch.spec.mts +310 -0
  92. package/src/client/__type-tests__/from-endpoint.spec-d.mts +550 -0
  93. package/src/client/__type-tests__/infinite-query.spec-d.mts +648 -0
  94. package/src/client/__type-tests__/multipart-mutation.spec-d.mts +725 -0
  95. package/src/client/__type-tests__/mutation.spec-d.mts +757 -0
  96. package/src/client/__type-tests__/query.spec-d.mts +701 -0
  97. package/src/client/declare-client.mts +59 -34
  98. package/src/client/types/from-endpoint.mts +344 -0
  99. package/src/client/types/helpers.mts +140 -0
  100. package/src/client/types/index.mts +26 -0
  101. package/src/client/types/infinite-query.mts +133 -0
  102. package/src/client/types/multipart-mutation.mts +264 -0
  103. package/src/client/types/mutation.mts +176 -0
  104. package/src/client/types/query.mts +132 -0
  105. package/src/client/types.mts +1 -1935
  106. package/src/common/types.mts +67 -3
  107. package/src/mutation/index.mts +1 -0
  108. package/src/mutation/make-hook.mts +171 -63
  109. package/src/mutation/optimistic.mts +300 -0
  110. package/src/mutation/types.mts +87 -30
  111. package/src/query/index.mts +1 -0
  112. package/src/query/key-creator.mts +24 -13
  113. package/src/query/make-infinite-options.mts +53 -10
  114. package/src/query/make-options.mts +184 -43
  115. package/src/query/prefetch.mts +326 -0
  116. package/src/query/types.mts +56 -17
  117. 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
+ })