@navios/react-query 0.5.2 → 0.6.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.
- package/CHANGELOG.md +51 -10
- package/README.md +405 -273
- package/dist/src/client/declare-client.d.mts +13 -4
- package/dist/src/client/declare-client.d.mts.map +1 -1
- package/dist/src/client/types.d.mts +337 -113
- package/dist/src/client/types.d.mts.map +1 -1
- package/dist/src/mutation/make-hook.d.mts +2 -2
- package/dist/src/mutation/make-hook.d.mts.map +1 -1
- package/dist/src/mutation/types.d.mts +12 -4
- package/dist/src/mutation/types.d.mts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/lib/_tsup-dts-rollup.d.mts +362 -120
- package/lib/_tsup-dts-rollup.d.ts +362 -120
- package/lib/index.js +51 -27
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +52 -28
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/declare-client.spec.mts +24 -5
- package/src/__tests__/make-mutation.spec.mts +150 -8
- package/src/client/__type-tests__/client-instance.spec-d.mts +2 -2
- package/src/client/declare-client.mts +33 -8
- package/src/client/types.mts +617 -141
- package/src/mutation/make-hook.mts +96 -42
- package/src/mutation/types.mts +28 -6
|
@@ -10,6 +10,7 @@ import { declareClient } from '../client/declare-client.mjs'
|
|
|
10
10
|
|
|
11
11
|
vi.mock('@tanstack/react-query', async (importReal) => {
|
|
12
12
|
const actual = await importReal<typeof import('@tanstack/react-query')>()
|
|
13
|
+
const mockMutationContext = { mutationId: 1, meta: undefined }
|
|
13
14
|
return {
|
|
14
15
|
...actual,
|
|
15
16
|
useQueryClient: () => ({
|
|
@@ -22,11 +23,27 @@ vi.mock('@tanstack/react-query', async (importReal) => {
|
|
|
22
23
|
...req,
|
|
23
24
|
mutateAsync: async (data: unknown) => {
|
|
24
25
|
try {
|
|
26
|
+
const onMutateResult = await req.onMutate?.(data, mockMutationContext)
|
|
25
27
|
const res = await req.mutationFn(data)
|
|
26
|
-
await req.onSuccess?.(res, data)
|
|
28
|
+
await req.onSuccess?.(res, data, onMutateResult, mockMutationContext)
|
|
29
|
+
await req.onSettled?.(
|
|
30
|
+
res,
|
|
31
|
+
null,
|
|
32
|
+
data,
|
|
33
|
+
onMutateResult,
|
|
34
|
+
mockMutationContext,
|
|
35
|
+
)
|
|
27
36
|
return res
|
|
28
37
|
} catch (err) {
|
|
29
|
-
|
|
38
|
+
const onMutateResult = undefined
|
|
39
|
+
await req.onError?.(err, data, onMutateResult, mockMutationContext)
|
|
40
|
+
await req.onSettled?.(
|
|
41
|
+
undefined,
|
|
42
|
+
err,
|
|
43
|
+
data,
|
|
44
|
+
onMutateResult,
|
|
45
|
+
mockMutationContext,
|
|
46
|
+
)
|
|
30
47
|
throw err
|
|
31
48
|
}
|
|
32
49
|
},
|
|
@@ -147,7 +164,7 @@ describe('declareClient', () => {
|
|
|
147
164
|
}
|
|
148
165
|
return data
|
|
149
166
|
},
|
|
150
|
-
onSuccess(
|
|
167
|
+
onSuccess(data, variables, context) {
|
|
151
168
|
expect(data).toMatchObject({
|
|
152
169
|
success: true,
|
|
153
170
|
test: 'test',
|
|
@@ -161,9 +178,11 @@ describe('declareClient', () => {
|
|
|
161
178
|
testId: 'test',
|
|
162
179
|
},
|
|
163
180
|
})
|
|
181
|
+
expect(context).toHaveProperty('mutationId')
|
|
182
|
+
expect(context).toHaveProperty('onMutateResult')
|
|
164
183
|
},
|
|
165
|
-
onError: (err) => {
|
|
166
|
-
console.log('onError', err)
|
|
184
|
+
onError: (err, _variables, context) => {
|
|
185
|
+
console.log('onError', err, context)
|
|
167
186
|
},
|
|
168
187
|
})
|
|
169
188
|
|
|
@@ -10,6 +10,7 @@ import { makeMutation } from '../mutation/make-hook.mjs'
|
|
|
10
10
|
|
|
11
11
|
vi.mock('@tanstack/react-query', async (importReal) => {
|
|
12
12
|
const actual = await importReal<typeof import('@tanstack/react-query')>()
|
|
13
|
+
const mockMutationContext = { mutationId: 1, meta: undefined }
|
|
13
14
|
return {
|
|
14
15
|
...actual,
|
|
15
16
|
useQueryClient: () => ({
|
|
@@ -22,11 +23,27 @@ vi.mock('@tanstack/react-query', async (importReal) => {
|
|
|
22
23
|
...req,
|
|
23
24
|
mutateAsync: async (data: unknown) => {
|
|
24
25
|
try {
|
|
26
|
+
const onMutateResult = await req.onMutate?.(data, mockMutationContext)
|
|
25
27
|
const res = await req.mutationFn(data)
|
|
26
|
-
await req.onSuccess?.(res, data)
|
|
28
|
+
await req.onSuccess?.(res, data, onMutateResult, mockMutationContext)
|
|
29
|
+
await req.onSettled?.(
|
|
30
|
+
res,
|
|
31
|
+
null,
|
|
32
|
+
data,
|
|
33
|
+
onMutateResult,
|
|
34
|
+
mockMutationContext,
|
|
35
|
+
)
|
|
27
36
|
return res
|
|
28
37
|
} catch (err) {
|
|
29
|
-
|
|
38
|
+
const onMutateResult = undefined
|
|
39
|
+
await req.onError?.(err, data, onMutateResult, mockMutationContext)
|
|
40
|
+
await req.onSettled?.(
|
|
41
|
+
undefined,
|
|
42
|
+
err,
|
|
43
|
+
data,
|
|
44
|
+
onMutateResult,
|
|
45
|
+
mockMutationContext,
|
|
46
|
+
)
|
|
30
47
|
throw err
|
|
31
48
|
}
|
|
32
49
|
},
|
|
@@ -77,7 +94,7 @@ describe('makeMutation', () => {
|
|
|
77
94
|
}
|
|
78
95
|
return data
|
|
79
96
|
},
|
|
80
|
-
onSuccess: (
|
|
97
|
+
onSuccess: (data, variables, context) => {
|
|
81
98
|
expect(data).toMatchObject({
|
|
82
99
|
success: true,
|
|
83
100
|
test: 'test',
|
|
@@ -95,10 +112,12 @@ describe('makeMutation', () => {
|
|
|
95
112
|
foo: 'bar',
|
|
96
113
|
},
|
|
97
114
|
})
|
|
115
|
+
expect(context).toHaveProperty('mutationId')
|
|
116
|
+
expect(context).toHaveProperty('onMutateResult')
|
|
98
117
|
},
|
|
99
118
|
|
|
100
|
-
onError: (err) => {
|
|
101
|
-
console.log('onError', err)
|
|
119
|
+
onError: (err, _variables, context) => {
|
|
120
|
+
console.log('onError', err, context)
|
|
102
121
|
},
|
|
103
122
|
})
|
|
104
123
|
// @ts-expect-error internal type
|
|
@@ -184,7 +203,7 @@ describe('makeMutation', () => {
|
|
|
184
203
|
expect(result).toContain('blob:')
|
|
185
204
|
})
|
|
186
205
|
|
|
187
|
-
it('should call onSuccess with Blob data', async () => {
|
|
206
|
+
it('should call onSuccess with Blob data and context', async () => {
|
|
188
207
|
const onSuccess = vi.fn()
|
|
189
208
|
// @ts-expect-error stream endpoint type differs from regular endpoint
|
|
190
209
|
const mutation = makeMutation(streamEndpoint, {
|
|
@@ -198,10 +217,133 @@ describe('makeMutation', () => {
|
|
|
198
217
|
})
|
|
199
218
|
|
|
200
219
|
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
201
|
-
expect(onSuccess.mock.calls[0][
|
|
202
|
-
expect(onSuccess.mock.calls[0][
|
|
220
|
+
expect(onSuccess.mock.calls[0][0]).toBeInstanceOf(Blob)
|
|
221
|
+
expect(onSuccess.mock.calls[0][1]).toMatchObject({
|
|
203
222
|
urlParams: { fileId: '123' },
|
|
204
223
|
})
|
|
224
|
+
// Third argument should be context with onMutateResult and mutationId
|
|
225
|
+
expect(onSuccess.mock.calls[0][2]).toHaveProperty('onMutateResult')
|
|
226
|
+
expect(onSuccess.mock.calls[0][2]).toHaveProperty('mutationId')
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
describe('mutation callbacks', () => {
|
|
231
|
+
it('should call onMutate before mutation and pass result to other callbacks', async () => {
|
|
232
|
+
const callOrder: string[] = []
|
|
233
|
+
const onMutate = vi.fn((_variables, _context) => {
|
|
234
|
+
callOrder.push('onMutate')
|
|
235
|
+
return { optimisticId: 'temp-123' }
|
|
236
|
+
})
|
|
237
|
+
const onSuccess = vi.fn((_data, _variables, context) => {
|
|
238
|
+
callOrder.push('onSuccess')
|
|
239
|
+
expect(context.onMutateResult).toEqual({ optimisticId: 'temp-123' })
|
|
240
|
+
})
|
|
241
|
+
const onSettled = vi.fn((_data, _error, _variables, context) => {
|
|
242
|
+
callOrder.push('onSettled')
|
|
243
|
+
expect(context.onMutateResult).toEqual({ optimisticId: 'temp-123' })
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
const mutation = makeMutation(endpoint, {
|
|
247
|
+
processResponse: (data) => {
|
|
248
|
+
if (!data.success) throw new Error(data.message)
|
|
249
|
+
return data
|
|
250
|
+
},
|
|
251
|
+
onMutate,
|
|
252
|
+
onSuccess,
|
|
253
|
+
onSettled,
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
// @ts-expect-error internal type
|
|
257
|
+
const mutationResult = mutation()
|
|
258
|
+
await mutationResult.mutateAsync({
|
|
259
|
+
urlParams: { testId: '1', fooId: '2' },
|
|
260
|
+
data: { testId: '1', fooId: '2' },
|
|
261
|
+
params: { foo: 'bar' },
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
expect(callOrder).toEqual(['onMutate', 'onSuccess', 'onSettled'])
|
|
265
|
+
expect(onMutate).toHaveBeenCalledTimes(1)
|
|
266
|
+
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
267
|
+
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('should call onError and onSettled on failure', async () => {
|
|
271
|
+
adapter.mock('/test/1/foo/2', 'POST', () => {
|
|
272
|
+
return new Response(
|
|
273
|
+
JSON.stringify({ success: false, message: 'Test error' }),
|
|
274
|
+
{ status: 200, headers: { 'content-type': 'application/json' } },
|
|
275
|
+
)
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
const onError = vi.fn()
|
|
279
|
+
const onSettled = vi.fn()
|
|
280
|
+
|
|
281
|
+
const mutation = makeMutation(endpoint, {
|
|
282
|
+
processResponse: (data) => {
|
|
283
|
+
if (!data.success) throw new Error(data.message)
|
|
284
|
+
return data
|
|
285
|
+
},
|
|
286
|
+
onError,
|
|
287
|
+
onSettled,
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
// @ts-expect-error internal type
|
|
291
|
+
const mutationResult = mutation()
|
|
292
|
+
|
|
293
|
+
await expect(
|
|
294
|
+
mutationResult.mutateAsync({
|
|
295
|
+
urlParams: { testId: '1', fooId: '2' },
|
|
296
|
+
data: { testId: '1', fooId: '2' },
|
|
297
|
+
params: { foo: 'bar' },
|
|
298
|
+
}),
|
|
299
|
+
).rejects.toThrow('Test error')
|
|
300
|
+
|
|
301
|
+
expect(onError).toHaveBeenCalledTimes(1)
|
|
302
|
+
expect(onError.mock.calls[0][0]).toBeInstanceOf(Error)
|
|
303
|
+
expect(onError.mock.calls[0][0].message).toBe('Test error')
|
|
304
|
+
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
305
|
+
expect(onSettled.mock.calls[0][1]).toBeInstanceOf(Error)
|
|
306
|
+
|
|
307
|
+
// Restore the mock
|
|
308
|
+
adapter.mock('/test/1/foo/2', 'POST', () => {
|
|
309
|
+
return new Response(
|
|
310
|
+
JSON.stringify({ success: true, test: 'test' }),
|
|
311
|
+
{ status: 200, headers: { 'content-type': 'application/json' } },
|
|
312
|
+
)
|
|
313
|
+
})
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
it('should merge useContext result with MutationFunctionContext', async () => {
|
|
317
|
+
const useContext = () => ({
|
|
318
|
+
queryClient: { invalidate: vi.fn() },
|
|
319
|
+
customValue: 'test',
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
const onSuccess = vi.fn()
|
|
323
|
+
|
|
324
|
+
const mutation = makeMutation(endpoint, {
|
|
325
|
+
processResponse: (data) => {
|
|
326
|
+
if (!data.success) throw new Error(data.message)
|
|
327
|
+
return data
|
|
328
|
+
},
|
|
329
|
+
useContext,
|
|
330
|
+
onSuccess,
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
// @ts-expect-error internal type
|
|
334
|
+
const mutationResult = mutation()
|
|
335
|
+
await mutationResult.mutateAsync({
|
|
336
|
+
urlParams: { testId: '1', fooId: '2' },
|
|
337
|
+
data: { testId: '1', fooId: '2' },
|
|
338
|
+
params: { foo: 'bar' },
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
342
|
+
const context = onSuccess.mock.calls[0][2]
|
|
343
|
+
expect(context).toHaveProperty('queryClient')
|
|
344
|
+
expect(context).toHaveProperty('customValue', 'test')
|
|
345
|
+
expect(context).toHaveProperty('mutationId')
|
|
346
|
+
expect(context).toHaveProperty('onMutateResult')
|
|
205
347
|
})
|
|
206
348
|
})
|
|
207
349
|
})
|
|
@@ -758,7 +758,7 @@ describe('mutationFromEndpoint() with stream endpoints', () => {
|
|
|
758
758
|
|
|
759
759
|
test('stream mutation with onSuccess callback', () => {
|
|
760
760
|
const mutation = client.mutationFromEndpoint(streamEndpointGet, {
|
|
761
|
-
onSuccess: (
|
|
761
|
+
onSuccess: (data, variables) => {
|
|
762
762
|
// data should be Blob
|
|
763
763
|
assertType<Blob>(data)
|
|
764
764
|
// variables should have urlParams
|
|
@@ -778,7 +778,7 @@ describe('mutationFromEndpoint() with stream endpoints', () => {
|
|
|
778
778
|
test('stream mutation with custom processResponse and onSuccess', () => {
|
|
779
779
|
const mutation = client.mutationFromEndpoint(streamEndpointGet, {
|
|
780
780
|
processResponse: (blob) => ({ url: URL.createObjectURL(blob), size: blob.size }),
|
|
781
|
-
onSuccess: (
|
|
781
|
+
onSuccess: (data) => {
|
|
782
782
|
// data should be the transformed type
|
|
783
783
|
assertType<{ url: string; size: number }>(data)
|
|
784
784
|
},
|
|
@@ -5,10 +5,17 @@ import type {
|
|
|
5
5
|
AnyStreamConfig,
|
|
6
6
|
HttpMethod,
|
|
7
7
|
} from '@navios/builder'
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
InfiniteData,
|
|
10
|
+
MutationFunctionContext,
|
|
11
|
+
QueryClient,
|
|
12
|
+
} from '@tanstack/react-query'
|
|
9
13
|
import type { z, ZodObject, ZodType } from 'zod/v4'
|
|
10
14
|
|
|
11
|
-
import type {
|
|
15
|
+
import type {
|
|
16
|
+
ClientOptions,
|
|
17
|
+
ProcessResponseFunction,
|
|
18
|
+
} from '../common/types.mjs'
|
|
12
19
|
import type { MutationArgs } from '../mutation/types.mjs'
|
|
13
20
|
import type { ClientInstance } from './types.mjs'
|
|
14
21
|
|
|
@@ -84,6 +91,7 @@ export interface MutationConfig<
|
|
|
84
91
|
Response extends ZodType = ZodType,
|
|
85
92
|
ReqResult = z.output<Response>,
|
|
86
93
|
Result = unknown,
|
|
94
|
+
TOnMutateResult = unknown,
|
|
87
95
|
Context = unknown,
|
|
88
96
|
UseKey extends boolean = false,
|
|
89
97
|
> {
|
|
@@ -95,18 +103,30 @@ export interface MutationConfig<
|
|
|
95
103
|
processResponse: ProcessResponseFunction<Result, ReqResult>
|
|
96
104
|
useContext?: () => Context
|
|
97
105
|
onSuccess?: (
|
|
98
|
-
|
|
99
|
-
data: NoInfer<Result>,
|
|
106
|
+
data: Result,
|
|
100
107
|
variables: MutationArgs<Url, RequestSchema, QuerySchema>,
|
|
101
|
-
context: Context
|
|
108
|
+
context: Context &
|
|
109
|
+
MutationFunctionContext & { onMutateResult: TOnMutateResult | undefined },
|
|
102
110
|
) => void | Promise<void>
|
|
103
111
|
onError?: (
|
|
104
|
-
|
|
105
|
-
error: Error,
|
|
112
|
+
err: unknown,
|
|
106
113
|
variables: MutationArgs<Url, RequestSchema, QuerySchema>,
|
|
107
|
-
context: Context
|
|
114
|
+
context: Context &
|
|
115
|
+
MutationFunctionContext & { onMutateResult: TOnMutateResult | undefined },
|
|
116
|
+
) => void | Promise<void>
|
|
117
|
+
onMutate?: (
|
|
118
|
+
variables: MutationArgs<Url, RequestSchema, QuerySchema>,
|
|
119
|
+
context: Context & MutationFunctionContext,
|
|
120
|
+
) => TOnMutateResult | Promise<TOnMutateResult>
|
|
121
|
+
onSettled?: (
|
|
122
|
+
data: Result | undefined,
|
|
123
|
+
error: Error | null,
|
|
124
|
+
variables: MutationArgs<Url, RequestSchema, QuerySchema>,
|
|
125
|
+
context: Context &
|
|
126
|
+
MutationFunctionContext & { onMutateResult: TOnMutateResult | undefined },
|
|
108
127
|
) => void | Promise<void>
|
|
109
128
|
useKey?: UseKey
|
|
129
|
+
meta?: Record<string, unknown>
|
|
110
130
|
}
|
|
111
131
|
|
|
112
132
|
/**
|
|
@@ -237,6 +257,7 @@ export function declareClient<Options extends ClientOptions>({
|
|
|
237
257
|
// @ts-expect-error We forgot about the DELETE method in original makeMutation
|
|
238
258
|
onError: config.onError,
|
|
239
259
|
useKey: config.useKey,
|
|
260
|
+
meta: config.meta,
|
|
240
261
|
...defaults,
|
|
241
262
|
})
|
|
242
263
|
|
|
@@ -293,6 +314,10 @@ export function declareClient<Options extends ClientOptions>({
|
|
|
293
314
|
onSuccess: config.onSuccess,
|
|
294
315
|
// @ts-expect-error We forgot about the DELETE method in original makeMutation
|
|
295
316
|
onError: config.onError,
|
|
317
|
+
// @ts-expect-error We forgot about the DELETE method in original makeMutation
|
|
318
|
+
onMutate: config.onMutate,
|
|
319
|
+
// @ts-expect-error We forgot about the DELETE method in original makeMutation
|
|
320
|
+
onSettled: config.onSettled,
|
|
296
321
|
useKey: config.useKey,
|
|
297
322
|
...defaults,
|
|
298
323
|
})
|