@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,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
|
+
}
|
package/src/mutation/types.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AnyEndpointConfig,
|
|
3
|
-
|
|
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 {
|
|
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 =
|
|
22
|
-
QuerySchema =
|
|
23
|
-
> =
|
|
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
|
-
|
|
34
|
-
|
|
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 =
|
|
48
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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:
|
|
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:
|
|
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 =
|
|
113
|
-
QuerySchema =
|
|
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 =
|
|
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
|
|
127
|
-
export type BaseMutationArgs<Config extends AnyEndpointConfig> =
|
|
128
|
-
|
|
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
|
+
>
|
package/src/query/index.mts
CHANGED
|
@@ -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
|
-
...
|
|
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
|
-
...
|
|
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>(
|
|
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 ({
|
|
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
|
|
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
|
-
|
|
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
|
|
114
|
-
|
|
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
|
|
123
|
-
|
|
124
|
-
|
|
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
|