@navios/react-query 0.1.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/README.md +370 -0
- package/dist/index.d.mts +346 -0
- package/dist/index.d.ts +346 -0
- package/dist/index.js +345 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +325 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +43 -0
- package/src/__tests__/client-type-check.spec.mts +61 -0
- package/src/__tests__/declare-client.spec.mts +187 -0
- package/src/__tests__/make-mutation.spec.mts +140 -0
- package/src/__tests__/makeDataTag.spec.mts +70 -0
- package/src/__tests__/makeInfiniteQueryOptions.spec.mts +45 -0
- package/src/__tests__/makeQueryOptions.spec.mts +43 -0
- package/src/declare-client.mts +215 -0
- package/src/index.mts +8 -0
- package/src/make-infinite-query-options.mts +115 -0
- package/src/make-mutation.mts +121 -0
- package/src/make-query-options.mts +113 -0
- package/src/types/client-instance.mts +502 -0
- package/src/types/index.mts +6 -0
- package/src/types/mutation-args.mts +10 -0
- package/src/types/mutation-helpers.mts +13 -0
- package/src/types/query-args.mts +8 -0
- package/src/types/query-helpers.mts +34 -0
- package/src/types/query-url-params-args.mts +6 -0
- package/src/types.mts +118 -0
- package/src/utils/mutation-key.creator.mts +61 -0
- package/src/utils/query-key-creator.mts +125 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { create } from 'navios'
|
|
2
|
+
import { makeNaviosFakeAdapter } from 'navios/testing'
|
|
3
|
+
|
|
4
|
+
import { builder } from '@navios/common'
|
|
5
|
+
|
|
6
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
7
|
+
import { z } from 'zod'
|
|
8
|
+
|
|
9
|
+
import { makeMutation } from '../make-mutation.mjs'
|
|
10
|
+
|
|
11
|
+
vi.mock('@tanstack/react-query', async (importReal) => {
|
|
12
|
+
const actual = await importReal<typeof import('@tanstack/react-query')>()
|
|
13
|
+
return {
|
|
14
|
+
...actual,
|
|
15
|
+
useQueryClient: () => ({
|
|
16
|
+
getQueryData: vi.fn(),
|
|
17
|
+
setQueryData: vi.fn(),
|
|
18
|
+
invalidateQueries: vi.fn(),
|
|
19
|
+
removeQueries: vi.fn(),
|
|
20
|
+
}),
|
|
21
|
+
useMutation: vi.fn((req) => ({
|
|
22
|
+
...req,
|
|
23
|
+
mutateAsync: async (data: unknown) => {
|
|
24
|
+
try {
|
|
25
|
+
const res = await req.mutationFn(data)
|
|
26
|
+
await req.onSuccess?.(res, data)
|
|
27
|
+
return res
|
|
28
|
+
} catch (err) {
|
|
29
|
+
req.onError?.(err, data)
|
|
30
|
+
throw err
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
mutate: req.mutationFn,
|
|
34
|
+
})),
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('makeMutation', () => {
|
|
39
|
+
const adapter = makeNaviosFakeAdapter()
|
|
40
|
+
const api = builder({})
|
|
41
|
+
api.provideClient(create({ adapter: adapter.fetch }))
|
|
42
|
+
const responseSchema = z.discriminatedUnion('success', [
|
|
43
|
+
z.object({ success: z.literal(true), test: z.string() }),
|
|
44
|
+
z.object({ success: z.literal(false), message: z.string() }),
|
|
45
|
+
])
|
|
46
|
+
const endpoint = api.declareEndpoint({
|
|
47
|
+
method: 'POST',
|
|
48
|
+
url: '/test/$testId/foo/$fooId' as const,
|
|
49
|
+
requestSchema: z.object({
|
|
50
|
+
testId: z.string(),
|
|
51
|
+
fooId: z.string(),
|
|
52
|
+
}),
|
|
53
|
+
querySchema: z.object({ foo: z.string() }),
|
|
54
|
+
responseSchema,
|
|
55
|
+
})
|
|
56
|
+
adapter.mock('/test/1/foo/2', 'POST', () => {
|
|
57
|
+
return new Response(
|
|
58
|
+
JSON.stringify({
|
|
59
|
+
success: true,
|
|
60
|
+
test: 'test',
|
|
61
|
+
}),
|
|
62
|
+
{
|
|
63
|
+
status: 200,
|
|
64
|
+
statusText: 'OK',
|
|
65
|
+
headers: {
|
|
66
|
+
'content-type': 'application/json',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('should just work', async () => {
|
|
73
|
+
const mutation = makeMutation(endpoint, {
|
|
74
|
+
processResponse: (data) => {
|
|
75
|
+
if (!data.success) {
|
|
76
|
+
throw new Error(data.message)
|
|
77
|
+
}
|
|
78
|
+
return data
|
|
79
|
+
},
|
|
80
|
+
onSuccess: (queryClient, data, variables) => {
|
|
81
|
+
expect(data).toMatchObject({
|
|
82
|
+
success: true,
|
|
83
|
+
test: 'test',
|
|
84
|
+
})
|
|
85
|
+
expect(variables).toMatchObject({
|
|
86
|
+
urlParams: {
|
|
87
|
+
testId: '1',
|
|
88
|
+
fooId: '2',
|
|
89
|
+
},
|
|
90
|
+
data: {
|
|
91
|
+
testId: '1',
|
|
92
|
+
fooId: '2',
|
|
93
|
+
},
|
|
94
|
+
params: {
|
|
95
|
+
foo: 'bar',
|
|
96
|
+
},
|
|
97
|
+
})
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
onError: (err) => {
|
|
101
|
+
console.log('onError', err)
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
// @ts-expect-error internal type
|
|
105
|
+
const mutationResult = mutation()
|
|
106
|
+
await mutationResult.mutateAsync({
|
|
107
|
+
urlParams: {
|
|
108
|
+
testId: '1',
|
|
109
|
+
fooId: '2',
|
|
110
|
+
},
|
|
111
|
+
data: {
|
|
112
|
+
testId: '1',
|
|
113
|
+
fooId: '2',
|
|
114
|
+
},
|
|
115
|
+
params: {
|
|
116
|
+
foo: 'bar',
|
|
117
|
+
},
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('should work with a key', async () => {
|
|
122
|
+
const mutation = makeMutation(endpoint, {
|
|
123
|
+
processResponse: (data) => {
|
|
124
|
+
if (!data.success) {
|
|
125
|
+
throw new Error(data.message)
|
|
126
|
+
}
|
|
127
|
+
return data
|
|
128
|
+
},
|
|
129
|
+
useKey: true,
|
|
130
|
+
})
|
|
131
|
+
const mutationResult = mutation({
|
|
132
|
+
fooId: '2',
|
|
133
|
+
testId: '1',
|
|
134
|
+
})
|
|
135
|
+
console.log('mutationResult', mutationResult)
|
|
136
|
+
|
|
137
|
+
// @ts-expect-error from mock
|
|
138
|
+
expect(mutationResult.mutationKey).toMatchObject(['test', '1', 'foo', '2'])
|
|
139
|
+
})
|
|
140
|
+
})
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { builder } from '@navios/common'
|
|
2
|
+
|
|
3
|
+
import { QueryClient } from '@tanstack/react-query'
|
|
4
|
+
import { describe, expect, it } from 'vitest'
|
|
5
|
+
import { z } from 'zod'
|
|
6
|
+
|
|
7
|
+
import { makeQueryOptions } from '../make-query-options.mjs'
|
|
8
|
+
|
|
9
|
+
describe('makeDataTag', () => {
|
|
10
|
+
it('should return a string', () => {
|
|
11
|
+
const api = builder({})
|
|
12
|
+
const responseSchema = z.discriminatedUnion('success', [
|
|
13
|
+
z.object({ success: z.literal(true), test: z.string() }),
|
|
14
|
+
z.object({ success: z.literal(false), message: z.string() }),
|
|
15
|
+
])
|
|
16
|
+
const endpoint = api.declareEndpoint({
|
|
17
|
+
method: 'GET',
|
|
18
|
+
url: '/test/$testId/foo/$fooId' as const,
|
|
19
|
+
responseSchema,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const result = makeQueryOptions(endpoint, {
|
|
23
|
+
processResponse(data) {
|
|
24
|
+
return data
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
expect(typeof result.queryKey.dataTag).toBe('function')
|
|
28
|
+
expect(
|
|
29
|
+
result.queryKey.dataTag({
|
|
30
|
+
urlParams: { testId: '1', fooId: 'bar' },
|
|
31
|
+
}),
|
|
32
|
+
).toMatchInlineSnapshot(`
|
|
33
|
+
[
|
|
34
|
+
"test",
|
|
35
|
+
"1",
|
|
36
|
+
"foo",
|
|
37
|
+
"bar",
|
|
38
|
+
[],
|
|
39
|
+
]
|
|
40
|
+
`)
|
|
41
|
+
})
|
|
42
|
+
it('should return a string with the correct format', () => {
|
|
43
|
+
const queryClient = new QueryClient()
|
|
44
|
+
const api = builder({})
|
|
45
|
+
const responseSchema = z.discriminatedUnion('success', [
|
|
46
|
+
z.object({ success: z.literal(true), test: z.string() }),
|
|
47
|
+
z.object({ success: z.literal(false), message: z.string() }),
|
|
48
|
+
])
|
|
49
|
+
const endpoint = api.declareEndpoint({
|
|
50
|
+
method: 'GET',
|
|
51
|
+
url: '/test/$testId/foo/$fooId' as const,
|
|
52
|
+
responseSchema,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const result = makeQueryOptions(endpoint, {
|
|
56
|
+
processResponse(data) {
|
|
57
|
+
if (!data.success) {
|
|
58
|
+
throw new Error(data.message)
|
|
59
|
+
}
|
|
60
|
+
return data
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
expect(typeof result.queryKey.dataTag).toBe('function')
|
|
64
|
+
const queryKey = result.queryKey.dataTag({
|
|
65
|
+
urlParams: { testId: '1', fooId: 'bar' },
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
queryClient.setQueryData(queryKey, { success: true, test: 'bar' })
|
|
69
|
+
})
|
|
70
|
+
})
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { builder } from '@navios/common'
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
|
|
6
|
+
import { makeInfiniteQueryOptions } from '../make-infinite-query-options.mjs'
|
|
7
|
+
|
|
8
|
+
describe('makeInfiniteQueryOptions', () => {
|
|
9
|
+
const api = builder({})
|
|
10
|
+
const responseSchema = z.discriminatedUnion('success', [
|
|
11
|
+
z.object({ success: z.literal(true), test: z.string() }),
|
|
12
|
+
z.object({ success: z.literal(false), message: z.string() }),
|
|
13
|
+
])
|
|
14
|
+
const endpoint = api.declareEndpoint({
|
|
15
|
+
method: 'GET',
|
|
16
|
+
url: '/test/$testId/foo/$fooId' as const,
|
|
17
|
+
querySchema: z.object({ foo: z.string().optional() }),
|
|
18
|
+
responseSchema,
|
|
19
|
+
})
|
|
20
|
+
it('should work with types', () => {
|
|
21
|
+
const makeOptions = makeInfiniteQueryOptions(
|
|
22
|
+
endpoint,
|
|
23
|
+
{
|
|
24
|
+
getNextPageParam: (lastPage) => ({
|
|
25
|
+
foo: 'test' in lastPage ? lastPage.test : undefined,
|
|
26
|
+
}),
|
|
27
|
+
processResponse: (data) => {
|
|
28
|
+
if (!data.success) {
|
|
29
|
+
throw new Error(data.message)
|
|
30
|
+
}
|
|
31
|
+
return data
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
select: (data) => data.pages.map((page) => page.test).flat(),
|
|
36
|
+
},
|
|
37
|
+
)
|
|
38
|
+
const options = makeOptions({
|
|
39
|
+
// @ts-expect-error it's internal type
|
|
40
|
+
urlParams: { testId: '1', fooId: '2' },
|
|
41
|
+
params: {},
|
|
42
|
+
})
|
|
43
|
+
expect(options).toBeDefined()
|
|
44
|
+
})
|
|
45
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { builder } from '@navios/common'
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
|
|
6
|
+
import { makeQueryOptions } from '../make-query-options.mjs'
|
|
7
|
+
|
|
8
|
+
describe('makeQueryOptions', () => {
|
|
9
|
+
const api = builder({})
|
|
10
|
+
const responseSchema = z.discriminatedUnion('success', [
|
|
11
|
+
z.object({ success: z.literal(true), test: z.string() }),
|
|
12
|
+
z.object({ success: z.literal(false), message: z.string() }),
|
|
13
|
+
])
|
|
14
|
+
const endpoint = api.declareEndpoint({
|
|
15
|
+
method: 'GET',
|
|
16
|
+
url: '/test/$testId/foo/$fooId' as const,
|
|
17
|
+
querySchema: z.object({ foo: z.string() }),
|
|
18
|
+
responseSchema,
|
|
19
|
+
})
|
|
20
|
+
it('should work with types', () => {
|
|
21
|
+
const makeOptions = makeQueryOptions(
|
|
22
|
+
endpoint,
|
|
23
|
+
{
|
|
24
|
+
processResponse: (data) => {
|
|
25
|
+
if (!data.success) {
|
|
26
|
+
throw new Error(data.message)
|
|
27
|
+
}
|
|
28
|
+
return data
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
select: (data) => data.test,
|
|
33
|
+
},
|
|
34
|
+
)
|
|
35
|
+
const options = makeOptions({
|
|
36
|
+
urlParams: { testId: '1', fooId: '2' },
|
|
37
|
+
params: {
|
|
38
|
+
foo: 'bar',
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
expect(options).toBeDefined()
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AbstractEndpoint,
|
|
3
|
+
AnyEndpointConfig,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
Util_FlatObject,
|
|
6
|
+
} from '@navios/common'
|
|
7
|
+
import type { InfiniteData, QueryClient } from '@tanstack/react-query'
|
|
8
|
+
import type { AnyZodObject, z, ZodType } from 'zod'
|
|
9
|
+
|
|
10
|
+
import type { ClientOptions, ProcessResponseFunction } from './types.mjs'
|
|
11
|
+
import type { ClientInstance, ClientMutationArgs } from './types/index.mjs'
|
|
12
|
+
|
|
13
|
+
import { makeInfiniteQueryOptions } from './make-infinite-query-options.mjs'
|
|
14
|
+
import { makeMutation } from './make-mutation.mjs'
|
|
15
|
+
import { makeQueryOptions } from './make-query-options.mjs'
|
|
16
|
+
|
|
17
|
+
export interface ClientEndpoint<
|
|
18
|
+
Method = HttpMethod,
|
|
19
|
+
Url = string,
|
|
20
|
+
QuerySchema = unknown,
|
|
21
|
+
Response = ZodType,
|
|
22
|
+
> {
|
|
23
|
+
method: Method
|
|
24
|
+
url: Url
|
|
25
|
+
querySchema?: QuerySchema
|
|
26
|
+
responseSchema: Response
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ClientQueryConfig<
|
|
30
|
+
Method = HttpMethod,
|
|
31
|
+
Url = string,
|
|
32
|
+
QuerySchema = AnyZodObject,
|
|
33
|
+
Response extends ZodType = ZodType,
|
|
34
|
+
Result = z.output<Response>,
|
|
35
|
+
> extends ClientEndpoint<Method, Url, QuerySchema, Response> {
|
|
36
|
+
processResponse?: (data: z.output<Response>) => Result
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type ClientInfiniteQueryConfig<
|
|
40
|
+
Method = HttpMethod,
|
|
41
|
+
Url = string,
|
|
42
|
+
QuerySchema extends AnyZodObject = AnyZodObject,
|
|
43
|
+
Response extends ZodType = ZodType,
|
|
44
|
+
PageResult = z.output<Response>,
|
|
45
|
+
Result = InfiniteData<PageResult>,
|
|
46
|
+
> = Required<ClientEndpoint<Method, Url, QuerySchema, Response>> & {
|
|
47
|
+
processResponse?: (data: z.output<Response>) => PageResult
|
|
48
|
+
select?: (data: InfiniteData<PageResult>) => Result
|
|
49
|
+
getNextPageParam: (
|
|
50
|
+
lastPage: PageResult,
|
|
51
|
+
allPages: PageResult[],
|
|
52
|
+
lastPageParam: z.infer<QuerySchema> | undefined,
|
|
53
|
+
allPageParams: z.infer<QuerySchema>[] | undefined,
|
|
54
|
+
) => z.input<QuerySchema> | undefined
|
|
55
|
+
getPreviousPageParam?: (
|
|
56
|
+
firstPage: PageResult,
|
|
57
|
+
allPages: PageResult[],
|
|
58
|
+
lastPageParam: z.infer<QuerySchema> | undefined,
|
|
59
|
+
allPageParams: z.infer<QuerySchema>[] | undefined,
|
|
60
|
+
) => z.input<QuerySchema>
|
|
61
|
+
initialPageParam?: z.input<QuerySchema>
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ClientMutationDataConfig<
|
|
65
|
+
Method extends 'POST' | 'PUT' | 'PATCH' | 'DELETE' =
|
|
66
|
+
| 'POST'
|
|
67
|
+
| 'PUT'
|
|
68
|
+
| 'PATCH'
|
|
69
|
+
| 'DELETE',
|
|
70
|
+
Url extends string = string,
|
|
71
|
+
RequestSchema = Method extends 'DELETE' ? never : AnyZodObject,
|
|
72
|
+
QuerySchema = unknown,
|
|
73
|
+
Response extends ZodType = ZodType,
|
|
74
|
+
ReqResult = z.output<Response>,
|
|
75
|
+
Result = unknown,
|
|
76
|
+
Context = unknown,
|
|
77
|
+
UseKey extends boolean = false,
|
|
78
|
+
> extends ClientEndpoint<Method, Url, QuerySchema, Response> {
|
|
79
|
+
requestSchema?: RequestSchema
|
|
80
|
+
processResponse: ProcessResponseFunction<Result, ReqResult>
|
|
81
|
+
useContext?: () => Context
|
|
82
|
+
onSuccess?: (
|
|
83
|
+
queryClient: QueryClient,
|
|
84
|
+
data: NoInfer<Result>,
|
|
85
|
+
variables: Util_FlatObject<
|
|
86
|
+
ClientMutationArgs<Url, RequestSchema, QuerySchema>
|
|
87
|
+
>,
|
|
88
|
+
context: Context,
|
|
89
|
+
) => void | Promise<void>
|
|
90
|
+
onError?: (
|
|
91
|
+
queryClient: QueryClient,
|
|
92
|
+
error: Error,
|
|
93
|
+
variables: Util_FlatObject<
|
|
94
|
+
ClientMutationArgs<Url, RequestSchema, QuerySchema>
|
|
95
|
+
>,
|
|
96
|
+
context: Context,
|
|
97
|
+
) => void | Promise<void>
|
|
98
|
+
useKey?: UseKey
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function declareClient<Options extends ClientOptions>({
|
|
102
|
+
api,
|
|
103
|
+
defaults = {},
|
|
104
|
+
}: Options): ClientInstance {
|
|
105
|
+
function query(config: ClientQueryConfig) {
|
|
106
|
+
const endpoint = api.declareEndpoint({
|
|
107
|
+
// @ts-expect-error we accept only specific methods
|
|
108
|
+
method: config.method,
|
|
109
|
+
url: config.url,
|
|
110
|
+
querySchema: config.querySchema,
|
|
111
|
+
responseSchema: config.responseSchema,
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
return makeQueryOptions(endpoint, {
|
|
115
|
+
...defaults,
|
|
116
|
+
processResponse: config.processResponse ?? ((data) => data),
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function queryFromEndpoint(
|
|
121
|
+
endpoint: AbstractEndpoint<AnyEndpointConfig>,
|
|
122
|
+
options?: {
|
|
123
|
+
processResponse?: (
|
|
124
|
+
data: z.output<AnyEndpointConfig['responseSchema']>,
|
|
125
|
+
) => unknown
|
|
126
|
+
},
|
|
127
|
+
) {
|
|
128
|
+
return makeQueryOptions(endpoint, {
|
|
129
|
+
...defaults,
|
|
130
|
+
processResponse: options?.processResponse ?? ((data) => data),
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function infiniteQuery(config: ClientInfiniteQueryConfig) {
|
|
135
|
+
const endpoint = api.declareEndpoint({
|
|
136
|
+
// @ts-expect-error we accept only specific methods
|
|
137
|
+
method: config.method,
|
|
138
|
+
url: config.url,
|
|
139
|
+
querySchema: config.querySchema,
|
|
140
|
+
responseSchema: config.responseSchema,
|
|
141
|
+
})
|
|
142
|
+
return makeInfiniteQueryOptions(endpoint, {
|
|
143
|
+
...defaults,
|
|
144
|
+
processResponse: config.processResponse ?? ((data) => data),
|
|
145
|
+
getNextPageParam: config.getNextPageParam,
|
|
146
|
+
getPreviousPageParam: config.getPreviousPageParam,
|
|
147
|
+
initialPageParam: config.initialPageParam,
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function infiniteQueryFromEndpoint(
|
|
152
|
+
endpoint: AbstractEndpoint<AnyEndpointConfig>,
|
|
153
|
+
options: {
|
|
154
|
+
processResponse?: (
|
|
155
|
+
data: z.output<AnyEndpointConfig['responseSchema']>,
|
|
156
|
+
) => unknown
|
|
157
|
+
getNextPageParam: (
|
|
158
|
+
lastPage: z.infer<AnyEndpointConfig['responseSchema']>,
|
|
159
|
+
allPages: z.infer<AnyEndpointConfig['responseSchema']>[],
|
|
160
|
+
lastPageParam: z.infer<AnyEndpointConfig['querySchema']> | undefined,
|
|
161
|
+
allPageParams: z.infer<AnyEndpointConfig['querySchema']>[] | undefined,
|
|
162
|
+
) => z.input<AnyEndpointConfig['querySchema']> | undefined
|
|
163
|
+
getPreviousPageParam?: (
|
|
164
|
+
firstPage: z.infer<AnyEndpointConfig['responseSchema']>,
|
|
165
|
+
allPages: z.infer<AnyEndpointConfig['responseSchema']>[],
|
|
166
|
+
lastPageParam: z.infer<AnyEndpointConfig['querySchema']> | undefined,
|
|
167
|
+
allPageParams: z.infer<AnyEndpointConfig['querySchema']>[] | undefined,
|
|
168
|
+
) => z.input<AnyEndpointConfig['querySchema']>
|
|
169
|
+
initialPageParam?: z.input<AnyEndpointConfig['querySchema']>
|
|
170
|
+
},
|
|
171
|
+
) {
|
|
172
|
+
return makeInfiniteQueryOptions(endpoint, {
|
|
173
|
+
...defaults,
|
|
174
|
+
processResponse: options?.processResponse ?? ((data) => data),
|
|
175
|
+
getNextPageParam: options.getNextPageParam,
|
|
176
|
+
getPreviousPageParam: options?.getPreviousPageParam,
|
|
177
|
+
initialPageParam: options?.initialPageParam,
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function mutation(config: ClientMutationDataConfig) {
|
|
182
|
+
const endpoint = api.declareEndpoint({
|
|
183
|
+
// @ts-expect-error We forgot about the DELETE method in original makeMutation
|
|
184
|
+
method: config.method,
|
|
185
|
+
url: config.url,
|
|
186
|
+
querySchema: config.querySchema,
|
|
187
|
+
requestSchema: config.requestSchema,
|
|
188
|
+
responseSchema: config.responseSchema,
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
return makeMutation(endpoint, {
|
|
192
|
+
processResponse: config.processResponse ?? ((data) => data),
|
|
193
|
+
useContext: config.useContext,
|
|
194
|
+
// @ts-expect-error We forgot about the DELETE method in original makeMutation
|
|
195
|
+
onSuccess: config.onSuccess,
|
|
196
|
+
// @ts-expect-error We forgot about the DELETE method in original makeMutation
|
|
197
|
+
onError: config.onError,
|
|
198
|
+
useKey: config.useKey,
|
|
199
|
+
...defaults,
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
// @ts-expect-error We simplified types here
|
|
205
|
+
query,
|
|
206
|
+
// @ts-expect-error We simplified types here
|
|
207
|
+
queryFromEndpoint,
|
|
208
|
+
// @ts-expect-error We simplified types here
|
|
209
|
+
infiniteQuery,
|
|
210
|
+
// @ts-expect-error We simplified types here
|
|
211
|
+
infiniteQueryFromEndpoint,
|
|
212
|
+
// @ts-expect-error We simplified types here
|
|
213
|
+
mutation,
|
|
214
|
+
}
|
|
215
|
+
}
|
package/src/index.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './types/index.mjs'
|
|
2
|
+
export * from './utils/mutation-key.creator.mjs'
|
|
3
|
+
export * from './utils/query-key-creator.mjs'
|
|
4
|
+
export * from './declare-client.mjs'
|
|
5
|
+
export * from './make-mutation.mjs'
|
|
6
|
+
export * from './make-infinite-query-options.mjs'
|
|
7
|
+
export * from './make-query-options.mjs'
|
|
8
|
+
export * from './types.mjs'
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AbstractEndpoint,
|
|
3
|
+
AnyEndpointConfig,
|
|
4
|
+
UrlParams,
|
|
5
|
+
} from '@navios/common'
|
|
6
|
+
import type {
|
|
7
|
+
InfiniteData,
|
|
8
|
+
QueryClient,
|
|
9
|
+
UseInfiniteQueryOptions,
|
|
10
|
+
UseSuspenseInfiniteQueryOptions,
|
|
11
|
+
} from '@tanstack/react-query'
|
|
12
|
+
import type { z } from 'zod'
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
infiniteQueryOptions,
|
|
16
|
+
useInfiniteQuery,
|
|
17
|
+
useSuspenseInfiniteQuery,
|
|
18
|
+
} from '@tanstack/react-query'
|
|
19
|
+
|
|
20
|
+
import type { InfiniteQueryOptions } from './types.mjs'
|
|
21
|
+
import type { ClientQueryArgs } from './types/index.mjs'
|
|
22
|
+
|
|
23
|
+
import { queryKeyCreator } from './utils/query-key-creator.mjs'
|
|
24
|
+
|
|
25
|
+
export function makeInfiniteQueryOptions<
|
|
26
|
+
Config extends AnyEndpointConfig,
|
|
27
|
+
Options extends InfiniteQueryOptions<Config>,
|
|
28
|
+
BaseQuery extends Omit<
|
|
29
|
+
UseInfiniteQueryOptions<ReturnType<Options['processResponse']>, Error, any>,
|
|
30
|
+
| 'queryKey'
|
|
31
|
+
| 'queryFn'
|
|
32
|
+
| 'getNextPageParam'
|
|
33
|
+
| 'initialPageParam'
|
|
34
|
+
| 'placeholderData'
|
|
35
|
+
| 'throwOnError'
|
|
36
|
+
>,
|
|
37
|
+
>(
|
|
38
|
+
endpoint: AbstractEndpoint<Config>,
|
|
39
|
+
options: Options,
|
|
40
|
+
baseQuery: BaseQuery = {} as BaseQuery,
|
|
41
|
+
) {
|
|
42
|
+
const config = endpoint.config
|
|
43
|
+
const queryKey = queryKeyCreator(config, options, true)
|
|
44
|
+
|
|
45
|
+
const processResponse = options.processResponse
|
|
46
|
+
const res = (
|
|
47
|
+
params: ClientQueryArgs,
|
|
48
|
+
): Options['processResponse'] extends (...args: any[]) => infer Result
|
|
49
|
+
? UseSuspenseInfiniteQueryOptions<
|
|
50
|
+
Result,
|
|
51
|
+
Error,
|
|
52
|
+
BaseQuery['select'] extends (...args: any[]) => infer T
|
|
53
|
+
? T
|
|
54
|
+
: InfiniteData<Result>
|
|
55
|
+
>
|
|
56
|
+
: never => {
|
|
57
|
+
// @ts-expect-error TS2322 We know that the processResponse is defined
|
|
58
|
+
return infiniteQueryOptions({
|
|
59
|
+
// @ts-expect-error TS2322 We know the type
|
|
60
|
+
queryKey: queryKey.dataTag(params),
|
|
61
|
+
queryFn: async ({ signal, pageParam }) => {
|
|
62
|
+
let result
|
|
63
|
+
try {
|
|
64
|
+
result = await endpoint({
|
|
65
|
+
signal,
|
|
66
|
+
// @ts-expect-error TS2345 We bind the url params only if the url has params
|
|
67
|
+
urlParams: params.urlParams as z.infer<UrlParams<Config['url']>>,
|
|
68
|
+
params: {
|
|
69
|
+
...('params' in params ? params.params : {}),
|
|
70
|
+
...(pageParam as z.infer<Config['querySchema']>),
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (options.onFail) {
|
|
75
|
+
options.onFail(err)
|
|
76
|
+
}
|
|
77
|
+
throw err
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return processResponse(result)
|
|
81
|
+
},
|
|
82
|
+
getNextPageParam: options.getNextPageParam,
|
|
83
|
+
initialPageParam:
|
|
84
|
+
options.initialPageParam ??
|
|
85
|
+
config.querySchema.parse('params' in params ? params.params : {}),
|
|
86
|
+
...baseQuery,
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
res.queryKey = queryKey
|
|
90
|
+
|
|
91
|
+
res.use = (params: ClientQueryArgs) => {
|
|
92
|
+
return useInfiniteQuery(res(params))
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
res.useSuspense = (params: ClientQueryArgs) => {
|
|
96
|
+
return useSuspenseInfiniteQuery(res(params))
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
res.invalidate = (queryClient: QueryClient, params: ClientQueryArgs) => {
|
|
100
|
+
return queryClient.invalidateQueries({
|
|
101
|
+
// @ts-expect-error We add additional function to the result
|
|
102
|
+
queryKey: res.queryKey.dataTag(params),
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
res.invalidateAll = (queryClient: QueryClient, params: ClientQueryArgs) => {
|
|
107
|
+
return queryClient.invalidateQueries({
|
|
108
|
+
// @ts-expect-error We add additional function to the result
|
|
109
|
+
queryKey: res.queryKey.filterKey(params),
|
|
110
|
+
exact: false,
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return res
|
|
115
|
+
}
|