@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,300 @@
1
+ import type { QueryClient } from '@tanstack/react-query'
2
+
3
+ /**
4
+ * Configuration for creating optimistic update callbacks.
5
+ *
6
+ * @template TData - The mutation response data type
7
+ * @template TVariables - The mutation variables type
8
+ * @template TQueryData - The query cache data type
9
+ */
10
+ export interface OptimisticUpdateConfig<
11
+ _TData,
12
+ TVariables,
13
+ TQueryData,
14
+ > {
15
+ /**
16
+ * The query key to optimistically update.
17
+ * This should match the query key used for the affected query.
18
+ */
19
+ queryKey: readonly unknown[]
20
+
21
+ /**
22
+ * Function to compute the optimistic cache value.
23
+ * Receives the current cache data and mutation variables.
24
+ *
25
+ * @param oldData - Current data in the cache (may be undefined if not cached)
26
+ * @param variables - The mutation variables being submitted
27
+ * @returns The new optimistic cache value
28
+ */
29
+ updateFn: (oldData: TQueryData | undefined, variables: TVariables) => TQueryData
30
+
31
+ /**
32
+ * Whether to rollback on error.
33
+ * Defaults to true.
34
+ */
35
+ rollbackOnError?: boolean
36
+
37
+ /**
38
+ * Whether to invalidate the query on settlement.
39
+ * Defaults to true.
40
+ */
41
+ invalidateOnSettled?: boolean
42
+ }
43
+
44
+ /**
45
+ * Return type for optimistic update callbacks.
46
+ */
47
+ export interface OptimisticUpdateCallbacks<TData, TVariables, TQueryData> {
48
+ /**
49
+ * Called before the mutation starts. Cancels outgoing refetches,
50
+ * snapshots the current cache value, and applies the optimistic update.
51
+ */
52
+ onMutate: (
53
+ variables: TVariables,
54
+ context: { queryClient: QueryClient },
55
+ ) => Promise<{ previousData: TQueryData | undefined }>
56
+
57
+ /**
58
+ * Called when the mutation fails. Rolls back the cache to the previous
59
+ * value if rollbackOnError is enabled.
60
+ */
61
+ onError: (
62
+ err: Error,
63
+ variables: TVariables,
64
+ context: { previousData?: TQueryData; queryClient: QueryClient },
65
+ ) => void
66
+
67
+ /**
68
+ * Called when the mutation completes (success or error).
69
+ * Invalidates the query if invalidateOnSettled is enabled.
70
+ */
71
+ onSettled: (
72
+ data: TData | undefined,
73
+ error: Error | null,
74
+ variables: TVariables,
75
+ context: { queryClient: QueryClient },
76
+ ) => void
77
+ }
78
+
79
+ /**
80
+ * Creates type-safe optimistic update callbacks for mutations.
81
+ *
82
+ * This helper generates the onMutate, onError, and onSettled callbacks
83
+ * that implement the standard optimistic update pattern:
84
+ *
85
+ * 1. onMutate: Cancel refetches, snapshot cache, apply optimistic update
86
+ * 2. onError: Rollback cache to previous value on failure
87
+ * 3. onSettled: Invalidate query to refetch fresh data
88
+ *
89
+ * @experimental This API is experimental and may change in future versions.
90
+ * Use with caution in production code.
91
+ *
92
+ * @param config - Configuration for the optimistic update
93
+ * @returns Object containing onMutate, onError, and onSettled callbacks
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * // Create a mutation with optimistic updates
98
+ * const updateUser = client.mutation({
99
+ * method: 'PATCH',
100
+ * url: '/users/$userId',
101
+ * requestSchema: updateUserSchema,
102
+ * responseSchema: userSchema,
103
+ * processResponse: (data) => data,
104
+ * ...createOptimisticUpdate({
105
+ * queryKey: ['users', userId],
106
+ * updateFn: (oldData, variables) => ({
107
+ * ...oldData,
108
+ * ...variables.data,
109
+ * }),
110
+ * }),
111
+ * })
112
+ * ```
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * // Optimistic update for adding an item to a list
117
+ * const addTodo = client.mutation({
118
+ * method: 'POST',
119
+ * url: '/todos',
120
+ * requestSchema: createTodoSchema,
121
+ * responseSchema: todoSchema,
122
+ * processResponse: (data) => data,
123
+ * ...createOptimisticUpdate({
124
+ * queryKey: ['todos'],
125
+ * updateFn: (oldData, variables) => [
126
+ * ...(oldData ?? []),
127
+ * { id: 'temp-id', ...variables.data, createdAt: new Date() },
128
+ * ],
129
+ * }),
130
+ * })
131
+ * ```
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * // Optimistic delete
136
+ * const deleteTodo = client.mutation({
137
+ * method: 'DELETE',
138
+ * url: '/todos/$todoId',
139
+ * responseSchema: z.object({ success: z.boolean() }),
140
+ * processResponse: (data) => data,
141
+ * ...createOptimisticUpdate({
142
+ * queryKey: ['todos'],
143
+ * updateFn: (oldData, variables) =>
144
+ * (oldData ?? []).filter((t) => t.id !== variables.urlParams.todoId),
145
+ * }),
146
+ * })
147
+ * ```
148
+ */
149
+ export function createOptimisticUpdate<
150
+ TData,
151
+ TVariables,
152
+ TQueryData,
153
+ >(config: OptimisticUpdateConfig<TData, TVariables, TQueryData>): OptimisticUpdateCallbacks<TData, TVariables, TQueryData> {
154
+ const {
155
+ queryKey,
156
+ updateFn,
157
+ rollbackOnError = true,
158
+ invalidateOnSettled = true,
159
+ } = config
160
+
161
+ return {
162
+ onMutate: async (
163
+ variables: TVariables,
164
+ context: { queryClient: QueryClient },
165
+ ) => {
166
+ // Cancel any outgoing refetches to prevent overwriting optimistic update
167
+ await context.queryClient.cancelQueries({ queryKey })
168
+
169
+ // Snapshot the previous value
170
+ const previousData = context.queryClient.getQueryData<TQueryData>(queryKey)
171
+
172
+ // Optimistically update the cache
173
+ context.queryClient.setQueryData<TQueryData>(
174
+ queryKey,
175
+ (old) => updateFn(old, variables),
176
+ )
177
+
178
+ // Return context with the previous data for potential rollback
179
+ return { previousData }
180
+ },
181
+
182
+ onError: (
183
+ _err: Error,
184
+ _variables: TVariables,
185
+ context: { previousData?: TQueryData; queryClient: QueryClient },
186
+ ) => {
187
+ // Rollback to the previous value on error
188
+ if (rollbackOnError && context?.previousData !== undefined) {
189
+ context.queryClient.setQueryData(queryKey, context.previousData)
190
+ }
191
+ },
192
+
193
+ onSettled: (
194
+ _data: TData | undefined,
195
+ _error: Error | null,
196
+ _variables: TVariables,
197
+ context: { queryClient: QueryClient },
198
+ ) => {
199
+ // Always invalidate to ensure we have the correct server state
200
+ if (invalidateOnSettled) {
201
+ void context.queryClient.invalidateQueries({ queryKey })
202
+ }
203
+ },
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Creates optimistic update callbacks that work with multiple query keys.
209
+ *
210
+ * Useful when a mutation affects multiple cached queries.
211
+ *
212
+ * @experimental This API is experimental and may change in future versions.
213
+ * Use with caution in production code.
214
+ *
215
+ * @param configs - Array of optimistic update configurations
216
+ * @returns Combined callbacks that handle all specified queries
217
+ *
218
+ * @example
219
+ * ```ts
220
+ * // Updating a user affects both user detail and user list queries
221
+ * const updateUser = client.mutation({
222
+ * method: 'PATCH',
223
+ * url: '/users/$userId',
224
+ * requestSchema: updateUserSchema,
225
+ * responseSchema: userSchema,
226
+ * processResponse: (data) => data,
227
+ * ...createMultiOptimisticUpdate([
228
+ * {
229
+ * queryKey: ['users', userId],
230
+ * updateFn: (oldData, variables) => ({ ...oldData, ...variables.data }),
231
+ * },
232
+ * {
233
+ * queryKey: ['users'],
234
+ * updateFn: (oldList, variables) =>
235
+ * (oldList ?? []).map((u) =>
236
+ * u.id === userId ? { ...u, ...variables.data } : u
237
+ * ),
238
+ * },
239
+ * ]),
240
+ * })
241
+ * ```
242
+ */
243
+ export function createMultiOptimisticUpdate<TData, TVariables>(
244
+ configs: Array<OptimisticUpdateConfig<TData, TVariables, unknown>>,
245
+ ): OptimisticUpdateCallbacks<TData, TVariables, Map<string, unknown>> {
246
+ return {
247
+ onMutate: async (
248
+ variables: TVariables,
249
+ context: { queryClient: QueryClient },
250
+ ) => {
251
+ // Cancel and snapshot all queries
252
+ const previousData = new Map<string, unknown>()
253
+
254
+ for (const config of configs) {
255
+ await context.queryClient.cancelQueries({ queryKey: config.queryKey })
256
+ const key = JSON.stringify(config.queryKey)
257
+ previousData.set(key, context.queryClient.getQueryData(config.queryKey))
258
+ context.queryClient.setQueryData(
259
+ config.queryKey,
260
+ (old: unknown) => config.updateFn(old, variables),
261
+ )
262
+ }
263
+
264
+ return { previousData }
265
+ },
266
+
267
+ onError: (
268
+ _err: Error,
269
+ _variables: TVariables,
270
+ context: { previousData?: Map<string, unknown>; queryClient: QueryClient },
271
+ ) => {
272
+ // Rollback all queries
273
+ if (context?.previousData) {
274
+ for (const config of configs) {
275
+ if (config.rollbackOnError !== false) {
276
+ const key = JSON.stringify(config.queryKey)
277
+ const previous = context.previousData.get(key)
278
+ if (previous !== undefined) {
279
+ context.queryClient.setQueryData(config.queryKey, previous)
280
+ }
281
+ }
282
+ }
283
+ }
284
+ },
285
+
286
+ onSettled: (
287
+ _data: TData | undefined,
288
+ _error: Error | null,
289
+ _variables: TVariables,
290
+ context: { queryClient: QueryClient },
291
+ ) => {
292
+ // Invalidate all queries
293
+ for (const config of configs) {
294
+ if (config.invalidateOnSettled !== false) {
295
+ void context.queryClient.invalidateQueries({ queryKey: config.queryKey })
296
+ }
297
+ }
298
+ },
299
+ }
300
+ }
@@ -1,6 +1,8 @@
1
1
  import type {
2
2
  AnyEndpointConfig,
3
- NaviosZodRequest,
3
+ ErrorSchemaRecord,
4
+ InferErrorSchemaOutput,
5
+ RequestArgs,
4
6
  UrlHasParams,
5
7
  UrlParams,
6
8
  } from '@navios/builder'
@@ -9,57 +11,103 @@ import type {
9
11
  MutationFunctionContext,
10
12
  UseMutationOptions,
11
13
  } from '@tanstack/react-query'
12
- import type { z, ZodObject } from 'zod/v4'
14
+ import type { z, ZodObject, ZodType } from 'zod/v4'
13
15
 
14
- import type { ProcessResponseFunction } from '../common/types.mjs'
16
+ import type {
17
+ ComputeResponseInput,
18
+ ProcessResponseFunction,
19
+ } from '../common/types.mjs'
15
20
 
16
21
  /**
17
22
  * Arguments for mutation functions based on URL params, request schema, and query schema.
23
+ * Uses RequestArgs from builder for consistency.
18
24
  */
19
25
  export type MutationArgs<
20
26
  Url extends string = string,
21
- RequestSchema = unknown,
22
- QuerySchema = unknown,
23
- > = (UrlHasParams<Url> extends true ? { urlParams: UrlParams<Url> } : {}) &
24
- (RequestSchema extends ZodObject ? { data: z.input<RequestSchema> } : {}) &
25
- (QuerySchema extends ZodObject ? { params: z.input<QuerySchema> } : {})
27
+ RequestSchema extends ZodType | undefined = undefined,
28
+ QuerySchema extends ZodObject | undefined = undefined,
29
+ > = RequestArgs<Url, QuerySchema, RequestSchema>
26
30
 
27
31
  /**
28
32
  * Helper methods attached to mutation hooks.
33
+ *
34
+ * @template Url - The URL template string
35
+ * @template Result - The mutation result type
29
36
  */
30
37
  export type MutationHelpers<Url extends string, Result = unknown> =
31
38
  UrlHasParams<Url> extends true
32
39
  ? {
33
- mutationKey: (params: UrlParams<Url>) => DataTag<[Url], Result, Error>
34
- useIsMutating: (keyParams: UrlParams<Url>) => boolean
40
+ /**
41
+ * Generates a mutation key for the given URL parameters.
42
+ * Useful for tracking mutations or invalidating related queries.
43
+ */
44
+ mutationKey: (params: {
45
+ urlParams: UrlParams<Url>
46
+ }) => DataTag<[Url], Result, Error>
47
+ /**
48
+ * Returns true if a mutation with the given URL parameters is currently in progress.
49
+ * Requires `useKey: true` to be set when creating the mutation.
50
+ */
51
+ useIsMutating: (keyParams: { urlParams: UrlParams<Url> }) => boolean
35
52
  }
36
53
  : {
54
+ /**
55
+ * Generates a mutation key.
56
+ * Useful for tracking mutations or invalidating related queries.
57
+ */
37
58
  mutationKey: () => DataTag<[Url], Result, Error>
59
+ /**
60
+ * Returns true if a mutation is currently in progress.
61
+ * Requires `useKey: true` to be set when creating the mutation.
62
+ */
38
63
  useIsMutating: () => boolean
39
64
  }
40
65
 
41
66
  /**
42
67
  * Base parameters for mutation configuration.
68
+ *
69
+ * @template UseDiscriminator - When `true`, errors are returned as union types in processResponse.
70
+ * When `false` (default), errors are thrown and not included in TResponse.
43
71
  */
44
72
  export interface MutationParams<
45
73
  Config extends AnyEndpointConfig,
46
74
  TData = unknown,
47
- TVariables = NaviosZodRequest<Config>,
48
- TResponse = z.output<Config['responseSchema']>,
75
+ TVariables = RequestArgs<
76
+ Config['url'],
77
+ Config['querySchema'],
78
+ Config['requestSchema'],
79
+ Config['urlParamsSchema']
80
+ >,
81
+ _TResponse = ComputeResponseInput<false, Config['responseSchema'], Config['errorSchema']>,
49
82
  TOnMutateResult = unknown,
50
83
  TContext = unknown,
51
84
  UseKey extends boolean = false,
85
+ UseDiscriminator extends boolean = false,
86
+ TError = UseDiscriminator extends true
87
+ ? Error
88
+ : Config['errorSchema'] extends ErrorSchemaRecord
89
+ ? InferErrorSchemaOutput<Config['errorSchema']> | Error
90
+ : Error,
52
91
  > extends Omit<
53
- UseMutationOptions<TData, Error, TVariables>,
54
- | 'mutationKey'
55
- | 'mutationFn'
56
- | 'onMutate'
57
- | 'onSuccess'
58
- | 'onError'
59
- | 'onSettled'
60
- | 'scope'
61
- > {
62
- processResponse?: ProcessResponseFunction<TData, TResponse>
92
+ UseMutationOptions<
93
+ TData,
94
+ // When UseDiscriminator is false and errorSchema exists, errors are thrown, so Error is correct.
95
+ // When UseDiscriminator is true, errors are part of the response union, but network/other errors still throw Error.
96
+ TError,
97
+ TVariables
98
+ >,
99
+ | 'mutationKey'
100
+ | 'mutationFn'
101
+ | 'onMutate'
102
+ | 'onSuccess'
103
+ | 'onError'
104
+ | 'onSettled'
105
+ | 'scope'
106
+ > {
107
+ processResponse?: ProcessResponseFunction<
108
+ TData,
109
+ ComputeResponseInput<UseDiscriminator, Config['responseSchema'], Config['errorSchema']>
110
+ >
63
111
  /**
64
112
  * React hooks that will prepare the context for the mutation onSuccess and onError
65
113
  * callbacks. This is useful for when you want to use the context in the callbacks
@@ -72,7 +120,7 @@ export interface MutationParams<
72
120
  MutationFunctionContext & { onMutateResult: TOnMutateResult | undefined },
73
121
  ) => void | Promise<void>
74
122
  onError?: (
75
- err: unknown,
123
+ err: TError,
76
124
  variables: TVariables,
77
125
  context: TContext &
78
126
  MutationFunctionContext & { onMutateResult: TOnMutateResult | undefined },
@@ -83,7 +131,7 @@ export interface MutationParams<
83
131
  ) => TOnMutateResult | Promise<TOnMutateResult>
84
132
  onSettled?: (
85
133
  data: TData | undefined,
86
- error: Error | null,
134
+ error: TError | null,
87
135
  variables: TVariables,
88
136
  context: TContext &
89
137
  MutationFunctionContext & { onMutateResult: TOnMutateResult | undefined },
@@ -109,20 +157,29 @@ export interface MutationParams<
109
157
  /** @deprecated Use MutationArgs instead */
110
158
  export type ClientMutationArgs<
111
159
  Url extends string = string,
112
- RequestSchema = unknown,
113
- QuerySchema = unknown,
160
+ RequestSchema extends ZodType | undefined = undefined,
161
+ QuerySchema extends ZodObject | undefined = undefined,
114
162
  > = MutationArgs<Url, RequestSchema, QuerySchema>
115
163
 
116
164
  /** @deprecated Use MutationParams instead */
117
165
  export type BaseMutationParams<
118
166
  Config extends AnyEndpointConfig,
119
167
  TData = unknown,
120
- TVariables = NaviosZodRequest<Config>,
168
+ TVariables = RequestArgs<
169
+ Config['url'],
170
+ Config['querySchema'],
171
+ Config['requestSchema'],
172
+ Config['urlParamsSchema']
173
+ >,
121
174
  TResponse = z.output<Config['responseSchema']>,
122
175
  TContext = unknown,
123
176
  UseKey extends boolean = false,
124
177
  > = MutationParams<Config, TData, TVariables, TResponse, TContext, UseKey>
125
178
 
126
- /** @deprecated Use NaviosZodRequest from @navios/builder instead */
127
- export type BaseMutationArgs<Config extends AnyEndpointConfig> =
128
- NaviosZodRequest<Config>
179
+ /** @deprecated Use RequestArgs from @navios/builder instead */
180
+ export type BaseMutationArgs<Config extends AnyEndpointConfig> = RequestArgs<
181
+ Config['url'],
182
+ Config['querySchema'],
183
+ Config['requestSchema'],
184
+ Config['urlParamsSchema']
185
+ >
@@ -2,3 +2,4 @@ export * from './types.mjs'
2
2
  export * from './key-creator.mjs'
3
3
  export * from './make-options.mjs'
4
4
  export * from './make-infinite-options.mjs'
5
+ export * from './prefetch.mjs'
@@ -46,14 +46,18 @@ export function createQueryKey<
46
46
  params && 'querySchema' in config && 'params' in params
47
47
  ? config.querySchema?.parse(params.params)
48
48
  : []
49
+
50
+ // Use bindUrlParams to get the bound URL, then split it to get the parts
51
+ const boundUrl = bindUrlParams<Url>(
52
+ url,
53
+ params && 'urlParams' in params ? params : {},
54
+ config.urlParamsSchema,
55
+ )
56
+ const boundUrlParts = boundUrl.split('/').filter(Boolean)
57
+
49
58
  return [
50
59
  ...(options.keyPrefix ?? []),
51
- ...urlParts.map((part) =>
52
- part.startsWith('$')
53
- ? // @ts-expect-error TS2339 We know that the urlParams are defined only if the url has params
54
- params.urlParams[part.slice(1)].toString()
55
- : part,
56
- ),
60
+ ...boundUrlParts,
57
61
  ...(options.keySuffix ?? []),
58
62
  queryParams ?? [],
59
63
  ] as unknown as DataTag<
@@ -68,14 +72,17 @@ export function createQueryKey<
68
72
  },
69
73
  // @ts-expect-error We have correct types in return type
70
74
  filterKey: (params) => {
75
+ // Use bindUrlParams to get the bound URL, then split it to get the parts
76
+ const boundUrl = bindUrlParams<Url>(
77
+ url,
78
+ params && 'urlParams' in params ? params : {},
79
+ config.urlParamsSchema,
80
+ )
81
+ const boundUrlParts = boundUrl.split('/').filter(Boolean)
82
+
71
83
  return [
72
84
  ...(options.keyPrefix ?? []),
73
- ...urlParts.map((part) =>
74
- part.startsWith('$')
75
- ? // @ts-expect-error TS2339 We know that the urlParams are defined only if the url has params
76
- params.urlParams[part.slice(1)].toString()
77
- : part,
78
- ),
85
+ ...boundUrlParts,
79
86
  ...(options.keySuffix ?? []),
80
87
  ] as unknown as DataTag<
81
88
  Split<Url, '/'>,
@@ -89,7 +96,11 @@ export function createQueryKey<
89
96
  },
90
97
 
91
98
  bindToUrl: (params) => {
92
- return bindUrlParams<Url>(url, params ?? ({} as never))
99
+ return bindUrlParams<Url>(
100
+ url,
101
+ params && 'urlParams' in params ? params : {},
102
+ config.urlParamsSchema,
103
+ )
93
104
  },
94
105
  }
95
106
  }
@@ -66,8 +66,12 @@ export function makeInfiniteQueryOptions<
66
66
  : never => {
67
67
  // @ts-expect-error TS2322 We know that the processResponse is defined
68
68
  return infiniteQueryOptions({
69
+ // @ts-expect-error TS2345 We bind the url params only if the url has params
69
70
  queryKey: queryKey.dataTag(params),
70
- queryFn: async ({ signal, pageParam }): Promise<ReturnType<Options['processResponse']>> => {
71
+ queryFn: async ({
72
+ signal,
73
+ pageParam,
74
+ }): Promise<ReturnType<Options['processResponse']>> => {
71
75
  let result
72
76
  try {
73
77
  result = await endpoint({
@@ -92,37 +96,76 @@ export function makeInfiniteQueryOptions<
92
96
  getPreviousPageParam: options.getPreviousPageParam,
93
97
  initialPageParam:
94
98
  options.initialPageParam ??
95
- config.querySchema.parse('params' in params ? params.params : {}),
99
+ config.querySchema?.parse('params' in params ? params.params : {}) ??
100
+ ('params' in params ? params.params : {}),
96
101
  ...baseQuery,
97
102
  })
98
103
  }
104
+ /** The query key creator for this infinite query endpoint */
99
105
  res.queryKey = queryKey
100
106
 
107
+ /**
108
+ * React hook that executes the infinite query.
109
+ * Uses `useInfiniteQuery` from TanStack Query internally.
110
+ *
111
+ * @param params - URL parameters and initial query parameters
112
+ * @returns Infinite query result with pages, fetchNextPage, etc.
113
+ */
101
114
  res.use = (params: QueryArgs<Config['url'], Config['querySchema']>) => {
102
115
  return useInfiniteQuery(res(params))
103
116
  }
104
117
 
105
- res.useSuspense = (params: QueryArgs<Config['url'], Config['querySchema']>) => {
118
+ /**
119
+ * React hook that executes the infinite query with Suspense support.
120
+ * Uses `useSuspenseInfiniteQuery` from TanStack Query internally.
121
+ * The component will suspend while loading and throw on error.
122
+ *
123
+ * @param params - URL parameters and initial query parameters
124
+ * @returns Infinite query result with pages guaranteed to be defined
125
+ */
126
+ res.useSuspense = (
127
+ params: QueryArgs<Config['url'], Config['querySchema']>,
128
+ ) => {
106
129
  return useSuspenseInfiniteQuery(res(params))
107
130
  }
108
131
 
132
+ /**
133
+ * Creates a function that invalidates this specific infinite query in the cache.
134
+ * Call the returned function to trigger the invalidation.
135
+ *
136
+ * @param queryClient - The TanStack Query client instance
137
+ * @param params - The exact parameters used for this query
138
+ * @returns A function that when called invalidates the query
139
+ */
109
140
  res.invalidate = (
110
141
  queryClient: QueryClient,
111
142
  params: QueryArgs<Config['url'], Config['querySchema']>,
112
143
  ) => {
113
- return queryClient.invalidateQueries({
114
- queryKey: res.queryKey.dataTag(params),
115
- })
144
+ return () =>
145
+ queryClient.invalidateQueries({
146
+ // @ts-expect-error TS2345 We bind the url params only if the url has params
147
+ queryKey: res.queryKey.dataTag(params),
148
+ })
116
149
  }
117
150
 
151
+ /**
152
+ * Creates a function that invalidates all infinite queries matching the URL pattern.
153
+ * Useful for invalidating all queries for a resource regardless of query params.
154
+ *
155
+ * @param queryClient - The TanStack Query client instance
156
+ * @param params - URL parameters only (query params are ignored for matching)
157
+ * @returns A function that when called invalidates all matching queries
158
+ */
118
159
  res.invalidateAll = (
119
160
  queryClient: QueryClient,
120
161
  params: QueryArgs<Config['url'], Config['querySchema']>,
121
162
  ) => {
122
- return queryClient.invalidateQueries({
123
- queryKey: res.queryKey.filterKey(params),
124
- exact: false,
125
- })
163
+ return () =>
164
+ queryClient.invalidateQueries({
165
+ // @ts-expect-error TS2345 We bind the url params only if the url has params
166
+ queryKey: res.queryKey.filterKey(params),
167
+ exact: false,
168
+ })
126
169
  }
127
170
 
128
171
  return res