@navios/react-query 0.7.1 → 1.0.0-alpha.1

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 (94) hide show
  1. package/CHANGELOG.md +161 -1
  2. package/README.md +152 -4
  3. package/dist/src/__tests__/errorSchema.spec.d.mts +2 -0
  4. package/dist/src/__tests__/errorSchema.spec.d.mts.map +1 -0
  5. package/dist/src/client/__type-tests__/from-endpoint.spec-d.d.mts +2 -0
  6. package/dist/src/client/__type-tests__/from-endpoint.spec-d.d.mts.map +1 -0
  7. package/dist/src/client/__type-tests__/infinite-query.spec-d.d.mts +2 -0
  8. package/dist/src/client/__type-tests__/infinite-query.spec-d.d.mts.map +1 -0
  9. package/dist/src/client/__type-tests__/multipart-mutation.spec-d.d.mts +2 -0
  10. package/dist/src/client/__type-tests__/multipart-mutation.spec-d.d.mts.map +1 -0
  11. package/dist/src/client/__type-tests__/mutation.spec-d.d.mts +2 -0
  12. package/dist/src/client/__type-tests__/mutation.spec-d.d.mts.map +1 -0
  13. package/dist/src/client/__type-tests__/query.spec-d.d.mts +2 -0
  14. package/dist/src/client/__type-tests__/query.spec-d.d.mts.map +1 -0
  15. package/dist/src/client/declare-client.d.mts +15 -8
  16. package/dist/src/client/declare-client.d.mts.map +1 -1
  17. package/dist/src/client/types/from-endpoint.d.mts +130 -0
  18. package/dist/src/client/types/from-endpoint.d.mts.map +1 -0
  19. package/dist/src/client/types/helpers.d.mts +74 -0
  20. package/dist/src/client/types/helpers.d.mts.map +1 -0
  21. package/dist/src/client/types/index.d.mts +21 -0
  22. package/dist/src/client/types/index.d.mts.map +1 -0
  23. package/dist/src/client/types/infinite-query.d.mts +61 -0
  24. package/dist/src/client/types/infinite-query.d.mts.map +1 -0
  25. package/dist/src/client/types/multipart-mutation.d.mts +98 -0
  26. package/dist/src/client/types/multipart-mutation.d.mts.map +1 -0
  27. package/dist/src/client/types/mutation.d.mts +75 -0
  28. package/dist/src/client/types/mutation.d.mts.map +1 -0
  29. package/dist/src/client/types/query.d.mts +65 -0
  30. package/dist/src/client/types/query.d.mts.map +1 -0
  31. package/dist/src/client/types.d.mts +1 -608
  32. package/dist/src/client/types.d.mts.map +1 -1
  33. package/dist/src/common/types.d.mts +30 -3
  34. package/dist/src/common/types.d.mts.map +1 -1
  35. package/dist/src/mutation/index.d.mts +1 -0
  36. package/dist/src/mutation/index.d.mts.map +1 -1
  37. package/dist/src/mutation/make-hook.d.mts +42 -16
  38. package/dist/src/mutation/make-hook.d.mts.map +1 -1
  39. package/dist/src/mutation/optimistic.d.mts +166 -0
  40. package/dist/src/mutation/optimistic.d.mts.map +1 -0
  41. package/dist/src/mutation/types.d.mts +51 -19
  42. package/dist/src/mutation/types.d.mts.map +1 -1
  43. package/dist/src/query/index.d.mts +1 -0
  44. package/dist/src/query/index.d.mts.map +1 -1
  45. package/dist/src/query/key-creator.d.mts.map +1 -1
  46. package/dist/src/query/make-infinite-options.d.mts +3 -2
  47. package/dist/src/query/make-infinite-options.d.mts.map +1 -1
  48. package/dist/src/query/make-options.d.mts +42 -12
  49. package/dist/src/query/make-options.d.mts.map +1 -1
  50. package/dist/src/query/prefetch.d.mts +245 -0
  51. package/dist/src/query/prefetch.d.mts.map +1 -0
  52. package/dist/src/query/types.d.mts +35 -17
  53. package/dist/src/query/types.d.mts.map +1 -1
  54. package/dist/tsconfig.tsbuildinfo +1 -1
  55. package/lib/index.cjs +445 -28
  56. package/lib/index.cjs.map +1 -1
  57. package/lib/index.d.cts +1022 -599
  58. package/lib/index.d.cts.map +1 -1
  59. package/lib/index.d.mts +1019 -596
  60. package/lib/index.d.mts.map +1 -1
  61. package/lib/index.mjs +441 -29
  62. package/lib/index.mjs.map +1 -1
  63. package/package.json +3 -3
  64. package/src/__tests__/declare-client.spec.mts +1 -2
  65. package/src/__tests__/errorSchema.spec.mts +391 -0
  66. package/src/__tests__/make-mutation.spec.mts +6 -5
  67. package/src/__tests__/makeDataTag.spec.mts +2 -1
  68. package/src/__tests__/makeQueryOptions.spec.mts +2 -1
  69. package/src/client/__type-tests__/from-endpoint.spec-d.mts +550 -0
  70. package/src/client/__type-tests__/infinite-query.spec-d.mts +648 -0
  71. package/src/client/__type-tests__/multipart-mutation.spec-d.mts +725 -0
  72. package/src/client/__type-tests__/mutation.spec-d.mts +757 -0
  73. package/src/client/__type-tests__/query.spec-d.mts +701 -0
  74. package/src/client/declare-client.mts +59 -34
  75. package/src/client/types/from-endpoint.mts +345 -0
  76. package/src/client/types/helpers.mts +140 -0
  77. package/src/client/types/index.mts +26 -0
  78. package/src/client/types/infinite-query.mts +133 -0
  79. package/src/client/types/multipart-mutation.mts +264 -0
  80. package/src/client/types/mutation.mts +176 -0
  81. package/src/client/types/query.mts +132 -0
  82. package/src/client/types.mts +1 -1935
  83. package/src/common/types.mts +48 -3
  84. package/src/mutation/index.mts +1 -0
  85. package/src/mutation/make-hook.mts +171 -63
  86. package/src/mutation/optimistic.mts +294 -0
  87. package/src/mutation/types.mts +102 -29
  88. package/src/query/index.mts +1 -0
  89. package/src/query/key-creator.mts +24 -13
  90. package/src/query/make-infinite-options.mts +53 -10
  91. package/src/query/make-options.mts +184 -43
  92. package/src/query/prefetch.mts +326 -0
  93. package/src/query/types.mts +76 -16
  94. package/src/client/__type-tests__/client-instance.spec-d.mts +0 -852
@@ -0,0 +1,757 @@
1
+ import type { ErrorSchemaRecord } from '@navios/builder'
2
+ import type { UseMutationResult } 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 { MutationHelpers } from '../../mutation/types.mjs'
9
+ import type { ClientInstance, EndpointHelper } from '../types.mjs'
10
+
11
+ // ============================================================================
12
+ // TEST SCHEMAS
13
+ // ============================================================================
14
+
15
+ const responseSchema = zod.object({
16
+ id: zod.string(),
17
+ name: zod.string(),
18
+ })
19
+
20
+ const querySchema = zod.object({
21
+ page: zod.number(),
22
+ limit: zod.number(),
23
+ })
24
+
25
+ const requestSchema = zod.object({
26
+ name: zod.string(),
27
+ email: zod.string(),
28
+ })
29
+
30
+ const error400Schema = zod.object({ error: zod.string(), code: zod.number() })
31
+ const error404Schema = zod.object({ notFound: zod.literal(true) })
32
+ const error500Schema = zod.object({ serverError: zod.string() })
33
+
34
+ const errorSchema = {
35
+ 400: error400Schema,
36
+ 404: error404Schema,
37
+ 500: error500Schema,
38
+ } satisfies ErrorSchemaRecord
39
+
40
+ type ResponseType = z.output<typeof responseSchema>
41
+ type QueryType = z.input<typeof querySchema>
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
+ // MUTATION METHOD - DEFAULT MODE (UseDiscriminator=false)
58
+ // ============================================================================
59
+
60
+ describe('ClientInstance<false> mutation() method', () => {
61
+ describe('POST mutations', () => {
62
+ test('POST mutation with request schema only', () => {
63
+ const mutation = client.mutation({
64
+ method: 'POST',
65
+ url: '/users',
66
+ requestSchema,
67
+ responseSchema,
68
+ })
69
+
70
+ assertType<
71
+ () => UseMutationResult<ResponseType, Error, { data: RequestType }>
72
+ >(mutation)
73
+ })
74
+
75
+ test('POST mutation with processResponse', () => {
76
+ const mutation = client.mutation({
77
+ method: 'POST',
78
+ url: '/users',
79
+ requestSchema,
80
+ responseSchema,
81
+ processResponse: (data) => data,
82
+ })
83
+
84
+ assertType<
85
+ () => UseMutationResult<ResponseType, Error, { data: RequestType }>
86
+ >(mutation)
87
+ })
88
+
89
+ test('POST mutation with URL params', () => {
90
+ const mutation = client.mutation({
91
+ method: 'POST',
92
+ url: '/users/$userId/posts',
93
+ requestSchema,
94
+ responseSchema,
95
+ })
96
+
97
+ assertType<
98
+ () => UseMutationResult<
99
+ ResponseType,
100
+ Error,
101
+ { urlParams: { userId: string | number }; data: RequestType }
102
+ >
103
+ >(mutation)
104
+ })
105
+
106
+ test('POST mutation with multiple URL params', () => {
107
+ const mutation = client.mutation({
108
+ method: 'POST',
109
+ url: '/orgs/$orgId/users/$userId/posts',
110
+ requestSchema,
111
+ responseSchema,
112
+ })
113
+
114
+ assertType<
115
+ () => UseMutationResult<
116
+ ResponseType,
117
+ Error,
118
+ {
119
+ urlParams: { orgId: string | number; userId: string | number }
120
+ data: RequestType
121
+ }
122
+ >
123
+ >(mutation)
124
+ })
125
+
126
+ test('POST mutation with query schema', () => {
127
+ const mutation = client.mutation({
128
+ method: 'POST',
129
+ url: '/users',
130
+ requestSchema,
131
+ querySchema,
132
+ responseSchema,
133
+ })
134
+
135
+ assertType<
136
+ () => UseMutationResult<
137
+ ResponseType,
138
+ Error,
139
+ { data: RequestType; params: QueryType }
140
+ >
141
+ >(mutation)
142
+ })
143
+
144
+ test('POST mutation with all schemas', () => {
145
+ const mutation = client.mutation({
146
+ method: 'POST',
147
+ url: '/users/$userId',
148
+ requestSchema,
149
+ querySchema,
150
+ responseSchema,
151
+ })
152
+
153
+ assertType<
154
+ () => UseMutationResult<
155
+ ResponseType,
156
+ Error,
157
+ {
158
+ urlParams: { userId: string | number }
159
+ data: RequestType
160
+ params: QueryType
161
+ }
162
+ >
163
+ >(mutation)
164
+ })
165
+
166
+ test('POST mutation with custom result type', () => {
167
+ const mutation = client.mutation({
168
+ method: 'POST',
169
+ url: '/users',
170
+ requestSchema,
171
+ responseSchema,
172
+ processResponse: (data) => ({ processed: true, name: data.name }),
173
+ })
174
+
175
+ assertType<
176
+ () => UseMutationResult<
177
+ { processed: boolean; name: string },
178
+ Error,
179
+ { data: RequestType }
180
+ >
181
+ >(mutation)
182
+ })
183
+ })
184
+
185
+ describe('PUT mutations', () => {
186
+ test('PUT mutation with URL params', () => {
187
+ const mutation = client.mutation({
188
+ method: 'PUT',
189
+ url: '/users/$userId',
190
+ requestSchema,
191
+ responseSchema,
192
+ })
193
+
194
+ assertType<
195
+ () => UseMutationResult<
196
+ ResponseType,
197
+ Error,
198
+ { urlParams: { userId: string | number }; data: RequestType }
199
+ >
200
+ >(mutation)
201
+ })
202
+ })
203
+
204
+ describe('PATCH mutations', () => {
205
+ test('PATCH mutation with URL params and query schema', () => {
206
+ const mutation = client.mutation({
207
+ method: 'PATCH',
208
+ url: '/users/$userId',
209
+ requestSchema,
210
+ querySchema,
211
+ responseSchema,
212
+ })
213
+
214
+ assertType<
215
+ () => UseMutationResult<
216
+ ResponseType,
217
+ Error,
218
+ {
219
+ urlParams: { userId: string | number }
220
+ data: RequestType
221
+ params: QueryType
222
+ }
223
+ >
224
+ >(mutation)
225
+ })
226
+ })
227
+
228
+ describe('DELETE mutations', () => {
229
+ test('DELETE mutation without request schema', () => {
230
+ const mutation = client.mutation({
231
+ method: 'DELETE',
232
+ url: '/users/$userId',
233
+ responseSchema,
234
+ })
235
+
236
+ assertType<
237
+ () => UseMutationResult<
238
+ ResponseType,
239
+ Error,
240
+ { urlParams: { userId: string | number } }
241
+ >
242
+ >(mutation)
243
+ })
244
+
245
+ test('DELETE mutation with query schema', () => {
246
+ const mutation = client.mutation({
247
+ method: 'DELETE',
248
+ url: '/cache',
249
+ querySchema,
250
+ responseSchema,
251
+ })
252
+
253
+ assertType<
254
+ () => UseMutationResult<ResponseType, Error, { params: QueryType }>
255
+ >(mutation)
256
+ })
257
+
258
+ test('DELETE mutation with URL params and query schema', () => {
259
+ const mutation = client.mutation({
260
+ method: 'DELETE',
261
+ url: '/users/$userId',
262
+ querySchema,
263
+ responseSchema,
264
+ })
265
+
266
+ assertType<
267
+ () => UseMutationResult<
268
+ ResponseType,
269
+ Error,
270
+ { urlParams: { userId: string | number }; params: QueryType }
271
+ >
272
+ >(mutation)
273
+ })
274
+ })
275
+
276
+ describe('useKey option', () => {
277
+ test('POST mutation with useKey requires urlParams in call', () => {
278
+ const mutation = client.mutation({
279
+ method: 'POST',
280
+ url: '/users/$userId',
281
+ useKey: true,
282
+ requestSchema,
283
+ responseSchema,
284
+ })
285
+
286
+ assertType<
287
+ (params: {
288
+ urlParams: { userId: string | number }
289
+ }) => UseMutationResult<
290
+ ResponseType,
291
+ Error,
292
+ { urlParams: { userId: string | number }; data: RequestType }
293
+ >
294
+ >(mutation)
295
+ })
296
+
297
+ test('mutation with useKey has MutationHelpers', () => {
298
+ const mutation = client.mutation({
299
+ method: 'POST',
300
+ url: '/users/$userId',
301
+ useKey: true,
302
+ requestSchema,
303
+ responseSchema,
304
+ })
305
+
306
+ assertType<MutationHelpers<'/users/$userId', ResponseType>['mutationKey']>(
307
+ mutation.mutationKey,
308
+ )
309
+ assertType<
310
+ MutationHelpers<'/users/$userId', ResponseType>['useIsMutating']
311
+ >(mutation.useIsMutating)
312
+ })
313
+
314
+ test('DELETE mutation with useKey and URL params', () => {
315
+ const mutation = client.mutation({
316
+ method: 'DELETE',
317
+ url: '/users/$userId',
318
+ useKey: true,
319
+ responseSchema,
320
+ })
321
+
322
+ assertType<
323
+ (params: {
324
+ urlParams: { userId: string | number }
325
+ }) => UseMutationResult<
326
+ ResponseType,
327
+ Error,
328
+ { urlParams: { userId: string | number } }
329
+ >
330
+ >(mutation)
331
+ })
332
+
333
+ test('DELETE mutation with useKey and querySchema', () => {
334
+ const mutation = client.mutation({
335
+ method: 'DELETE',
336
+ url: '/users/$userId',
337
+ useKey: true,
338
+ querySchema,
339
+ responseSchema,
340
+ })
341
+
342
+ assertType<
343
+ (params: {
344
+ urlParams: { userId: string | number }
345
+ }) => UseMutationResult<
346
+ ResponseType,
347
+ Error,
348
+ { urlParams: { userId: string | number }; params: QueryType }
349
+ >
350
+ >(mutation)
351
+ })
352
+
353
+ test('mutation with useKey without URL params', () => {
354
+ const mutation = client.mutation({
355
+ method: 'DELETE',
356
+ url: '/cache',
357
+ useKey: true,
358
+ responseSchema,
359
+ })
360
+
361
+ assertType<(params: {}) => UseMutationResult<ResponseType, Error, {}>>(
362
+ mutation,
363
+ )
364
+ })
365
+ })
366
+
367
+ describe('callback options', () => {
368
+ test('onMutate receives variables and context', () => {
369
+ client.mutation({
370
+ method: 'POST',
371
+ url: '/users',
372
+ requestSchema,
373
+ responseSchema,
374
+ onMutate: (variables, context) => {
375
+ assertType<{ data: RequestType }>(variables)
376
+ assertType<{ meta: Record<string, unknown> | undefined }>(context)
377
+ return { previousData: [] }
378
+ },
379
+ })
380
+ })
381
+
382
+ test('onSuccess receives data, variables, and context', () => {
383
+ client.mutation({
384
+ method: 'POST',
385
+ url: '/users',
386
+ requestSchema,
387
+ responseSchema,
388
+ processResponse: (data) => data,
389
+ onSuccess: (data, variables, context) => {
390
+ assertType<ResponseType>(data)
391
+ assertType<{ data: RequestType }>(variables)
392
+ assertType<{ onMutateResult: unknown }>(context)
393
+ },
394
+ })
395
+ })
396
+
397
+ test('onError receives error, variables, and context', () => {
398
+ client.mutation({
399
+ method: 'POST',
400
+ url: '/users',
401
+ requestSchema,
402
+ responseSchema,
403
+ onError: (error, variables, context) => {
404
+ assertType<Error>(error)
405
+ assertType<{ data: RequestType }>(variables)
406
+ assertType<{ onMutateResult: unknown }>(context)
407
+ },
408
+ })
409
+ })
410
+
411
+ test('onSettled receives data, error, variables, and context', () => {
412
+ client.mutation({
413
+ method: 'POST',
414
+ url: '/users',
415
+ requestSchema,
416
+ responseSchema,
417
+ processResponse: (data) => data,
418
+ onSettled: (data, error, variables, context) => {
419
+ assertType<ResponseType | undefined>(data)
420
+ assertType<Error | null>(error)
421
+ assertType<{ data: RequestType }>(variables)
422
+ assertType<{ onMutateResult: unknown }>(context)
423
+ },
424
+ })
425
+ })
426
+
427
+ test('useContext provides custom context', () => {
428
+ client.mutation({
429
+ method: 'POST',
430
+ url: '/users',
431
+ requestSchema,
432
+ responseSchema,
433
+ useContext: () => ({ queryClient: {} as unknown }),
434
+ onMutate: (_variables, context) => {
435
+ assertType<{ queryClient: unknown }>(context)
436
+ },
437
+ })
438
+ })
439
+ })
440
+
441
+ describe('errorSchema (errors thrown, not in return type)', () => {
442
+ test('mutation with errorSchema returns only success type', () => {
443
+ const mutation = client.mutation({
444
+ method: 'POST',
445
+ url: '/users',
446
+ requestSchema,
447
+ responseSchema,
448
+ errorSchema,
449
+ })
450
+
451
+ assertType<
452
+ () => UseMutationResult<
453
+ ResponseType,
454
+ Error,
455
+ { data: RequestType },
456
+ unknown
457
+ >
458
+ >(mutation)
459
+ })
460
+
461
+ test('processResponse receives only success type', () => {
462
+ client.mutation({
463
+ method: 'POST',
464
+ url: '/users',
465
+ requestSchema,
466
+ responseSchema,
467
+ errorSchema,
468
+ processResponse: (data) => {
469
+ assertType<ResponseType>(data)
470
+ return data
471
+ },
472
+ })
473
+ })
474
+ })
475
+
476
+ describe('EndpointHelper', () => {
477
+ test('mutation exposes endpoint property', () => {
478
+ const mutation = client.mutation({
479
+ method: 'POST',
480
+ url: '/users',
481
+ requestSchema,
482
+ responseSchema,
483
+ })
484
+
485
+ assertType<
486
+ EndpointHelper<
487
+ {
488
+ method: 'POST'
489
+ url: '/users'
490
+ querySchema: undefined
491
+ requestSchema: typeof requestSchema
492
+ responseSchema: typeof responseSchema
493
+ errorSchema: undefined
494
+ urlParamsSchema: undefined
495
+ },
496
+ false
497
+ >['endpoint']
498
+ >(mutation.endpoint)
499
+ })
500
+ })
501
+ })
502
+
503
+ // ============================================================================
504
+ // MUTATION METHOD - DISCRIMINATOR MODE (UseDiscriminator=true)
505
+ // ============================================================================
506
+
507
+ describe('ClientInstance<true> mutation() method (discriminator mode)', () => {
508
+ describe('errorSchema includes error union in TData', () => {
509
+ test('POST mutation with errorSchema returns union result type', () => {
510
+ const mutation = clientWithDiscriminator.mutation({
511
+ method: 'POST',
512
+ url: '/users',
513
+ requestSchema,
514
+ responseSchema,
515
+ errorSchema,
516
+ })
517
+
518
+ assertType<
519
+ () => UseMutationResult<
520
+ ResponseWithErrors,
521
+ Error,
522
+ { data: RequestType },
523
+ unknown
524
+ >
525
+ >(mutation)
526
+ })
527
+
528
+ test('processResponse receives union type', () => {
529
+ clientWithDiscriminator.mutation({
530
+ method: 'POST',
531
+ url: '/users',
532
+ requestSchema,
533
+ responseSchema,
534
+ errorSchema,
535
+ processResponse: (data) => {
536
+ assertType<ResponseWithErrors>(data)
537
+ return data
538
+ },
539
+ })
540
+ })
541
+
542
+ test('processResponse can transform union type', () => {
543
+ // Note: This test verifies processResponse receives the union type.
544
+ // The exact return type assertion is complex due to readonly inference.
545
+ clientWithDiscriminator.mutation({
546
+ method: 'POST',
547
+ url: '/users',
548
+ requestSchema,
549
+ responseSchema,
550
+ errorSchema,
551
+ processResponse: (data): { handled: boolean; original: typeof data } => {
552
+ assertType<ResponseWithErrors>(data)
553
+ return { handled: true, original: data }
554
+ },
555
+ })
556
+ })
557
+
558
+ test('onSuccess receives union type', () => {
559
+ clientWithDiscriminator.mutation({
560
+ method: 'POST',
561
+ url: '/users',
562
+ requestSchema,
563
+ responseSchema,
564
+ errorSchema,
565
+ processResponse: (data) => data,
566
+ onSuccess: (data) => {
567
+ assertType<ResponseWithErrors>(data)
568
+ },
569
+ })
570
+ })
571
+ })
572
+
573
+ describe('without errorSchema behaves same as default', () => {
574
+ test('mutation without errorSchema returns only success type', () => {
575
+ const mutation = clientWithDiscriminator.mutation({
576
+ method: 'POST',
577
+ url: '/users',
578
+ requestSchema,
579
+ responseSchema,
580
+ })
581
+
582
+ assertType<
583
+ () => UseMutationResult<
584
+ ResponseType,
585
+ Error,
586
+ { data: RequestType },
587
+ unknown
588
+ >
589
+ >(mutation)
590
+ })
591
+ })
592
+ })
593
+
594
+ // ============================================================================
595
+ // ERROR CASES - Should fail type checking
596
+ // ============================================================================
597
+
598
+ describe('mutation() error cases', () => {
599
+ describe('missing required parameters in variables', () => {
600
+ test('mutation().mutate() without data when requestSchema is defined', () => {
601
+ const mutation = client.mutation({
602
+ method: 'POST',
603
+ url: '/users',
604
+ requestSchema,
605
+ responseSchema,
606
+ })
607
+
608
+ const { mutate } = mutation()
609
+
610
+ // @ts-expect-error - missing data
611
+ mutate({})
612
+ })
613
+
614
+ test('mutation().mutate() without urlParams when URL has params', () => {
615
+ const mutation = client.mutation({
616
+ method: 'POST',
617
+ url: '/users/$userId',
618
+ requestSchema,
619
+ responseSchema,
620
+ })
621
+
622
+ const { mutate } = mutation()
623
+
624
+ // @ts-expect-error - missing urlParams
625
+ mutate({ data: { name: 'test', email: 'test@test.com' } })
626
+ })
627
+
628
+ test('mutation().mutate() without params when querySchema is defined', () => {
629
+ const mutation = client.mutation({
630
+ method: 'POST',
631
+ url: '/users',
632
+ requestSchema,
633
+ querySchema,
634
+ responseSchema,
635
+ })
636
+
637
+ const { mutate } = mutation()
638
+
639
+ // @ts-expect-error - missing params
640
+ mutate({ data: { name: 'test', email: 'test@test.com' } })
641
+ })
642
+ })
643
+
644
+ describe('missing useKey call params', () => {
645
+ test('mutation with useKey called without urlParams', () => {
646
+ const mutation = client.mutation({
647
+ method: 'POST',
648
+ url: '/users/$userId',
649
+ useKey: true,
650
+ requestSchema,
651
+ responseSchema,
652
+ })
653
+
654
+ // @ts-expect-error - missing urlParams in call
655
+ mutation()
656
+ })
657
+ })
658
+
659
+ describe('wrong parameter types in variables', () => {
660
+ test('data with wrong shape', () => {
661
+ const mutation = client.mutation({
662
+ method: 'POST',
663
+ url: '/users',
664
+ requestSchema,
665
+ responseSchema,
666
+ })
667
+
668
+ const { mutate } = mutation()
669
+
670
+ // @ts-expect-error - wrong property names
671
+ mutate({ data: { username: 'test', mail: 'test@test.com' } })
672
+ })
673
+
674
+ test('data with wrong value types', () => {
675
+ const mutation = client.mutation({
676
+ method: 'POST',
677
+ url: '/users',
678
+ requestSchema,
679
+ responseSchema,
680
+ })
681
+
682
+ const { mutate } = mutation()
683
+
684
+ // @ts-expect-error - name should be string, not number
685
+ mutate({ data: { name: 123, email: 'test@test.com' } })
686
+ })
687
+
688
+ test('urlParams with wrong type', () => {
689
+ const mutation = client.mutation({
690
+ method: 'POST',
691
+ url: '/users/$userId',
692
+ requestSchema,
693
+ responseSchema,
694
+ })
695
+
696
+ const { mutate } = mutation()
697
+
698
+ mutate({
699
+ // @ts-expect-error - userId should be string | number, not boolean
700
+ urlParams: { userId: true },
701
+ data: { name: 'test', email: 'test@test.com' },
702
+ })
703
+ })
704
+
705
+ test('params with wrong shape', () => {
706
+ const mutation = client.mutation({
707
+ method: 'POST',
708
+ url: '/users',
709
+ requestSchema,
710
+ querySchema,
711
+ responseSchema,
712
+ })
713
+
714
+ const { mutate } = mutation()
715
+
716
+ mutate({
717
+ data: { name: 'test', email: 'test@test.com' },
718
+ params: {
719
+ // @ts-expect-error - wrong property names
720
+ offset: 0,
721
+ count: 10,
722
+ },
723
+ })
724
+ })
725
+ })
726
+
727
+ describe('processResponse type safety', () => {
728
+ test('processResponse receives correct input type', () => {
729
+ client.mutation({
730
+ method: 'POST',
731
+ url: '/users',
732
+ requestSchema,
733
+ responseSchema,
734
+ processResponse: (data) => {
735
+ // @ts-expect-error - data doesn't have 'nonExistent' property
736
+ return data.nonExistent
737
+ },
738
+ })
739
+ })
740
+ })
741
+
742
+ describe('callback type safety', () => {
743
+ test('onSuccess data type matches processResponse result', () => {
744
+ client.mutation({
745
+ method: 'POST',
746
+ url: '/users',
747
+ requestSchema,
748
+ responseSchema,
749
+ processResponse: (data) => ({ transformed: data.name }),
750
+ onSuccess: (data) => {
751
+ // @ts-expect-error - data is { transformed: string }, not ResponseType
752
+ const _id: string = data.id
753
+ },
754
+ })
755
+ })
756
+ })
757
+ })