@ventlio/tanstack-query 0.2.6 → 0.2.7-2.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/LICENSE +21 -0
- package/README.md +532 -2
- package/dist/config/bootstrapQueryRequest.d.ts +4 -0
- package/dist/config/bootstrapQueryRequest.js +19 -0
- package/dist/config/bootstrapQueryRequest.js.map +1 -0
- package/dist/config/config.interface.d.ts +4 -0
- package/dist/config/index.d.ts +4 -2
- package/dist/config/useEnvironmentVariables.d.ts +2 -0
- package/dist/config/useEnvironmentVariables.js +14 -0
- package/dist/config/useEnvironmentVariables.js.map +1 -0
- package/dist/config/useQueryConfig.js +5 -9
- package/dist/config/useQueryConfig.js.map +1 -1
- package/dist/config/useQueryHeaders.js +19 -10
- package/dist/config/useQueryHeaders.js.map +1 -1
- package/dist/config/useReactNativeEnv.d.ts +5 -0
- package/dist/config/useReactNativeEnv.js +13 -0
- package/dist/config/useReactNativeEnv.js.map +1 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/scrollToTop.js +1 -3
- package/dist/helpers/scrollToTop.js.map +1 -1
- package/dist/helpers/timeFuncs.d.ts +1 -0
- package/dist/helpers/timeFuncs.js +11 -0
- package/dist/helpers/timeFuncs.js.map +1 -0
- package/dist/index.js +19 -43
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +417 -143
- package/dist/index.mjs.map +1 -1
- package/dist/model/index.d.ts +3 -0
- package/dist/model/model.interface.d.ts +11 -0
- package/dist/model/useKeyTrackerModel.d.ts +4 -0
- package/dist/model/useKeyTrackerModel.js +20 -0
- package/dist/model/useKeyTrackerModel.js.map +1 -0
- package/dist/model/useQueryModel.d.ts +2 -2
- package/dist/model/useQueryModel.js +119 -7
- package/dist/model/useQueryModel.js.map +1 -1
- package/dist/model/useRefetchQuery.d.ts +3 -0
- package/dist/model/useRefetchQuery.js +16 -0
- package/dist/model/useRefetchQuery.js.map +1 -0
- package/dist/queries/queries.interface.d.ts +5 -0
- package/dist/queries/useDeleteRequest.d.ts +14 -5
- package/dist/queries/useDeleteRequest.js +37 -37
- package/dist/queries/useGetRequest.d.ts +4 -3
- package/dist/queries/useGetRequest.js +53 -37
- package/dist/queries/useGetRequest.js.map +1 -1
- package/dist/queries/usePatchRequest.d.ts +7 -7
- package/dist/queries/usePatchRequest.js +42 -34
- package/dist/queries/usePatchRequest.js.map +1 -1
- package/dist/queries/usePostRequest.d.ts +8 -6
- package/dist/queries/usePostRequest.js +47 -37
- package/dist/queries/usePostRequest.js.map +1 -1
- package/dist/request/axios-instance.d.ts +1 -1
- package/dist/request/axios-instance.js +3 -5
- package/dist/request/axios-instance.js.map +1 -1
- package/dist/request/buildFormData.d.ts +1 -1
- package/dist/request/buildFormData.js +36 -6
- package/dist/request/buildFormData.js.map +1 -1
- package/dist/request/make-request.d.ts +1 -1
- package/dist/request/make-request.js +55 -17
- package/dist/request/make-request.js.map +1 -1
- package/dist/request/request.enum.js +6 -6
- package/dist/request/request.interface.d.ts +5 -0
- package/dist/request/transformer.js +1 -4
- package/dist/request/transformer.js.map +1 -1
- package/dist/types/index.d.ts +14 -11
- package/package.json +29 -5
- package/src/__tests__/queries/usePostRequest.spec.ts +77 -0
- package/src/config/bootstrapQueryRequest.ts +19 -0
- package/src/config/config.interface.ts +4 -0
- package/src/config/index.ts +4 -2
- package/src/config/useEnvironmentVariables.ts +13 -0
- package/src/config/useQueryConfig.ts +2 -5
- package/src/config/useQueryHeaders.ts +23 -6
- package/src/config/useReactNativeEnv.ts +13 -0
- package/src/env.d.ts +4 -0
- package/src/helpers/index.ts +1 -0
- package/src/helpers/timeFuncs.ts +10 -0
- package/src/model/index.ts +3 -0
- package/src/model/model.interface.ts +12 -0
- package/src/model/useKeyTrackerModel.ts +22 -0
- package/src/model/useQueryModel.ts +139 -6
- package/src/model/useRefetchQuery.ts +19 -0
- package/src/queries/queries.interface.ts +6 -0
- package/src/queries/useDeleteRequest.ts +34 -30
- package/src/queries/useGetRequest.ts +55 -38
- package/src/queries/usePatchRequest.ts +45 -40
- package/src/queries/usePostRequest.ts +54 -37
- package/src/request/axios-instance.ts +1 -5
- package/src/request/buildFormData.ts +34 -4
- package/src/request/make-request.ts +47 -7
- package/src/request/request.interface.ts +5 -0
- package/src/request/transformer.ts +3 -12
- package/src/types/index.ts +16 -13
- package/dist/config/useQueryBaseURL.d.ts +0 -2
- package/dist/config/useQueryBaseURL.js +0 -19
- package/dist/config/useQueryBaseURL.js.map +0 -1
- package/dist/config/useQueryTimeout.d.ts +0 -2
- package/dist/config/useQueryTimeout.js +0 -19
- package/dist/config/useQueryTimeout.js.map +0 -1
- package/src/config/useQueryBaseURL.ts +0 -17
- package/src/config/useQueryTimeout.ts +0 -17
|
@@ -1,54 +1,68 @@
|
|
|
1
1
|
import type { UseQueryOptions } from '@tanstack/react-query';
|
|
2
|
-
import { useQuery } from '@tanstack/react-query';
|
|
3
|
-
import { startTransition, useEffect, useState } from 'react';
|
|
4
|
-
import {
|
|
2
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
3
|
+
import { startTransition, useEffect, useMemo, useState } from 'react';
|
|
4
|
+
import type { RawAxiosRequestHeaders } from '../../node_modules/axios/index';
|
|
5
|
+
import { useEnvironmentVariables, useQueryHeaders } from '../config';
|
|
6
|
+
|
|
5
7
|
import type { IRequestError, IRequestSuccess } from '../request';
|
|
6
8
|
import { makeRequest } from '../request';
|
|
7
|
-
import type { IPagination, TanstackQueryOption } from './queries.interface';
|
|
9
|
+
import type { DefaultRequestOptions, IPagination, TanstackQueryOption } from './queries.interface';
|
|
8
10
|
|
|
9
11
|
export const useGetRequest = <TResponse extends Record<string, any>>({
|
|
10
12
|
path,
|
|
11
13
|
load = false,
|
|
12
14
|
queryOptions,
|
|
15
|
+
keyTracker,
|
|
16
|
+
baseUrl,
|
|
17
|
+
headers,
|
|
13
18
|
}: {
|
|
14
19
|
path: string;
|
|
15
20
|
load?: boolean;
|
|
16
21
|
queryOptions?: TanstackQueryOption<TResponse>;
|
|
17
|
-
|
|
22
|
+
keyTracker?: string;
|
|
23
|
+
} & DefaultRequestOptions) => {
|
|
18
24
|
const [requestPath, updatePath] = useState<string>(path);
|
|
19
25
|
const [options, setOptions] = useState<any>(queryOptions);
|
|
20
26
|
const [page, setPage] = useState<number>(1);
|
|
21
27
|
|
|
22
|
-
const {
|
|
28
|
+
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
29
|
+
const { getHeaders } = useQueryHeaders();
|
|
30
|
+
|
|
31
|
+
let queryClient = useQueryClient();
|
|
32
|
+
|
|
33
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
34
|
+
queryClient = useMemo(() => queryClient, []);
|
|
23
35
|
|
|
24
36
|
const sendRequest = async (
|
|
25
37
|
res: (
|
|
26
|
-
value:
|
|
27
|
-
| IRequestError
|
|
28
|
-
| IRequestSuccess<TResponse>
|
|
29
|
-
| PromiseLike<IRequestError | IRequestSuccess<TResponse>>
|
|
38
|
+
value: IRequestError | IRequestSuccess<TResponse> | PromiseLike<IRequestError | IRequestSuccess<TResponse>>
|
|
30
39
|
) => void,
|
|
31
40
|
rej: (reason?: any) => void
|
|
32
41
|
) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
if (load) {
|
|
43
|
+
// get request headers
|
|
44
|
+
const globalHeaders: RawAxiosRequestHeaders = getHeaders();
|
|
45
|
+
|
|
46
|
+
const getResponse = await makeRequest<TResponse>({
|
|
47
|
+
path: requestPath,
|
|
48
|
+
headers: { ...globalHeaders, ...headers },
|
|
49
|
+
baseURL: baseUrl ?? API_URL,
|
|
50
|
+
timeout: TIMEOUT,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (getResponse.status) {
|
|
54
|
+
res(getResponse as IRequestSuccess<TResponse>);
|
|
55
|
+
} else {
|
|
56
|
+
rej(getResponse);
|
|
57
|
+
}
|
|
41
58
|
} else {
|
|
42
|
-
|
|
59
|
+
res(null as any);
|
|
43
60
|
}
|
|
44
61
|
};
|
|
45
62
|
|
|
46
63
|
const query = useQuery<any, any, IRequestSuccess<TResponse>>(
|
|
47
64
|
[requestPath, {}],
|
|
48
|
-
() =>
|
|
49
|
-
new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => {
|
|
50
|
-
return sendRequest(res, rej);
|
|
51
|
-
}),
|
|
65
|
+
() => new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej)),
|
|
52
66
|
{
|
|
53
67
|
enabled: load,
|
|
54
68
|
...options,
|
|
@@ -61,13 +75,22 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
|
|
|
61
75
|
}
|
|
62
76
|
}, [path]);
|
|
63
77
|
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (keyTracker) {
|
|
80
|
+
// set expiration time for the tracker
|
|
81
|
+
queryClient.setQueryDefaults([keyTracker], {
|
|
82
|
+
cacheTime: Infinity,
|
|
83
|
+
staleTime: Infinity,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
queryClient.setQueryData([keyTracker], [requestPath, {}]);
|
|
87
|
+
}
|
|
88
|
+
}, [keyTracker, requestPath, queryClient, queryOptions?.staleTime]);
|
|
89
|
+
|
|
64
90
|
const nextPage = () => {
|
|
65
91
|
if (query.data?.data.pagination) {
|
|
66
92
|
const pagination: IPagination = query.data.data.pagination;
|
|
67
|
-
if (
|
|
68
|
-
pagination.next_page !== pagination.current_page &&
|
|
69
|
-
pagination.next_page > pagination.current_page
|
|
70
|
-
) {
|
|
93
|
+
if (pagination.next_page !== pagination.current_page && pagination.next_page > pagination.current_page) {
|
|
71
94
|
updatePath(constructPaginationLink(requestPath, pagination.next_page));
|
|
72
95
|
}
|
|
73
96
|
}
|
|
@@ -76,23 +99,17 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
|
|
|
76
99
|
const prevPage = () => {
|
|
77
100
|
if (query.data?.data.pagination) {
|
|
78
101
|
const pagination: IPagination = query.data.data.pagination;
|
|
79
|
-
if (
|
|
80
|
-
pagination.previous_page
|
|
81
|
-
pagination.previous_page < pagination.current_page
|
|
82
|
-
) {
|
|
83
|
-
updatePath(
|
|
84
|
-
constructPaginationLink(requestPath, pagination.previous_page)
|
|
85
|
-
);
|
|
102
|
+
if (pagination.previous_page !== pagination.current_page && pagination.previous_page < pagination.current_page) {
|
|
103
|
+
updatePath(constructPaginationLink(requestPath, pagination.previous_page));
|
|
86
104
|
}
|
|
87
105
|
}
|
|
88
106
|
};
|
|
89
107
|
|
|
90
108
|
const constructPaginationLink = (link: string, pageNumber: number) => {
|
|
91
|
-
const
|
|
92
|
-
const
|
|
109
|
+
const [pathname, queryString] = link.split('?');
|
|
110
|
+
const queryParams = new URLSearchParams(queryString);
|
|
93
111
|
|
|
94
|
-
const
|
|
95
|
-
const queryParams = new URLSearchParams(queryStrings ?? '');
|
|
112
|
+
const oldPage = Number(queryParams.get('page'));
|
|
96
113
|
|
|
97
114
|
queryParams.set('page', pageNumber as any);
|
|
98
115
|
|
|
@@ -1,57 +1,62 @@
|
|
|
1
1
|
import type { MutateOptions } from '@tanstack/react-query';
|
|
2
|
-
import { useMutation } from '@tanstack/react-query';
|
|
2
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
3
|
+
import type { RawAxiosRequestHeaders } from 'axios';
|
|
4
|
+
import { useEnvironmentVariables, useQueryHeaders } from '../config';
|
|
3
5
|
import { scrollToTop } from '../helpers';
|
|
4
6
|
import { HttpMethod, makeRequest } from '../request';
|
|
7
|
+
import type { IRequestError, IRequestSuccess } from '../request/request.interface';
|
|
8
|
+
import type { TanstackQueryConfig } from '../types';
|
|
9
|
+
import type { DefaultRequestOptions } from './queries.interface';
|
|
5
10
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
IRequestError,
|
|
9
|
-
IRequestSuccess,
|
|
10
|
-
} from '../request/request.interface';
|
|
11
|
+
export const usePatchRequest = <TResponse>({ path, baseUrl, headers }: { path: string } & DefaultRequestOptions) => {
|
|
12
|
+
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
const { getHeaders } = useQueryHeaders();
|
|
15
|
+
const queryClient = useQueryClient();
|
|
16
|
+
|
|
17
|
+
const config = queryClient.getQueryData<TanstackQueryConfig>(['config']);
|
|
18
|
+
|
|
19
|
+
const sendRequest = async (res: (value: any) => void, rej: (reason?: any) => void, data: any) => {
|
|
20
|
+
// get request headers
|
|
21
|
+
const globalHeaders: RawAxiosRequestHeaders = getHeaders();
|
|
22
|
+
|
|
23
|
+
const patchResponse = await makeRequest<TResponse>({
|
|
24
|
+
path: path,
|
|
25
|
+
body: data,
|
|
26
|
+
method: HttpMethod.PATCH,
|
|
27
|
+
headers: { ...globalHeaders, ...headers },
|
|
28
|
+
baseURL: baseUrl ?? API_URL,
|
|
29
|
+
timeout: TIMEOUT,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (patchResponse.status) {
|
|
33
|
+
// scroll to top after success
|
|
34
|
+
if (config?.options?.context !== 'app') {
|
|
35
|
+
scrollToTop();
|
|
36
|
+
}
|
|
37
|
+
res(patchResponse as IRequestSuccess<TResponse>);
|
|
38
|
+
} else {
|
|
39
|
+
// scroll to top after error
|
|
40
|
+
if (config?.options?.context !== 'app') {
|
|
41
|
+
scrollToTop();
|
|
42
|
+
}
|
|
43
|
+
rej(patchResponse);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
19
46
|
|
|
20
47
|
// register post mutation
|
|
21
48
|
const mutation = useMutation<IRequestSuccess<TResponse>, IRequestError>(
|
|
22
|
-
(
|
|
49
|
+
(dataData: any) =>
|
|
23
50
|
new Promise<IRequestSuccess<TResponse>>((res, rej) => {
|
|
24
|
-
|
|
25
|
-
path: path,
|
|
26
|
-
body: postData,
|
|
27
|
-
method: HttpMethod.PATCH,
|
|
28
|
-
headers,
|
|
29
|
-
baseURL,
|
|
30
|
-
timeout,
|
|
31
|
-
}).then((postResponse) => {
|
|
32
|
-
if (postResponse.status) {
|
|
33
|
-
// scroll to top after success
|
|
34
|
-
scrollToTop();
|
|
35
|
-
res(postResponse as IRequestSuccess<TResponse>);
|
|
36
|
-
} else {
|
|
37
|
-
// scroll to top after error
|
|
38
|
-
window.scrollTo({
|
|
39
|
-
top: 0,
|
|
40
|
-
behavior: 'smooth',
|
|
41
|
-
});
|
|
42
|
-
rej(postResponse);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
51
|
+
return sendRequest(res, rej, dataData);
|
|
45
52
|
})
|
|
46
53
|
);
|
|
47
54
|
|
|
48
55
|
const patch = async (
|
|
49
|
-
|
|
50
|
-
options?:
|
|
51
|
-
| MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown>
|
|
52
|
-
| undefined
|
|
56
|
+
data: any,
|
|
57
|
+
options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined
|
|
53
58
|
): Promise<IRequestSuccess<TResponse>> => {
|
|
54
|
-
return mutation.mutateAsync(
|
|
59
|
+
return mutation.mutateAsync(data, options);
|
|
55
60
|
};
|
|
56
61
|
|
|
57
62
|
return { patch, ...mutation };
|
|
@@ -1,56 +1,73 @@
|
|
|
1
1
|
import type { MutateOptions } from '@tanstack/react-query';
|
|
2
|
-
import { useMutation } from '@tanstack/react-query';
|
|
3
|
-
import {
|
|
2
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
3
|
+
import { useEnvironmentVariables, useQueryHeaders, useReactNativeEnv } from '../config';
|
|
4
|
+
|
|
5
|
+
import type { RawAxiosRequestHeaders } from 'axios';
|
|
6
|
+
import { scrollToTop } from '../helpers';
|
|
4
7
|
import type { IRequestError, IRequestSuccess } from '../request';
|
|
5
8
|
import { HttpMethod, makeRequest } from '../request';
|
|
9
|
+
import type { TanstackQueryConfig } from '../types';
|
|
10
|
+
import type { DefaultRequestOptions } from './queries.interface';
|
|
6
11
|
|
|
7
12
|
export const usePostRequest = <TResponse>({
|
|
8
13
|
path,
|
|
9
14
|
isFormData = false,
|
|
15
|
+
baseUrl,
|
|
16
|
+
headers,
|
|
17
|
+
fileSelectors,
|
|
10
18
|
}: {
|
|
11
19
|
path: string;
|
|
12
20
|
isFormData?: boolean;
|
|
13
|
-
|
|
14
|
-
|
|
21
|
+
fileSelectors?: string[];
|
|
22
|
+
} & DefaultRequestOptions) => {
|
|
23
|
+
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
24
|
+
const queryClient = useQueryClient();
|
|
25
|
+
const { getHeaders } = useQueryHeaders();
|
|
26
|
+
const { isApp } = useReactNativeEnv();
|
|
27
|
+
const sendRequest = async (res: (value: any) => void, rej: (reason?: any) => void, postData: any) => {
|
|
28
|
+
// get request headers
|
|
29
|
+
const globalHeaders: RawAxiosRequestHeaders = getHeaders();
|
|
30
|
+
const config = queryClient.getQueryData<TanstackQueryConfig>(['config']);
|
|
31
|
+
|
|
32
|
+
const postResponse = await makeRequest<TResponse>({
|
|
33
|
+
path,
|
|
34
|
+
body: postData,
|
|
35
|
+
method: HttpMethod.POST,
|
|
36
|
+
isFormData,
|
|
37
|
+
headers: { ...globalHeaders, ...headers },
|
|
38
|
+
baseURL: baseUrl ?? API_URL,
|
|
39
|
+
timeout: TIMEOUT,
|
|
40
|
+
appFileConfig: {
|
|
41
|
+
isApp,
|
|
42
|
+
fileSelectors,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (postResponse.status) {
|
|
47
|
+
// scroll to top after success
|
|
48
|
+
|
|
49
|
+
if (config?.options?.context !== 'app') {
|
|
50
|
+
scrollToTop();
|
|
51
|
+
}
|
|
52
|
+
res(postResponse as IRequestSuccess<TResponse>);
|
|
53
|
+
} else {
|
|
54
|
+
// scroll to top after error
|
|
55
|
+
if (config?.options?.context !== 'app') {
|
|
56
|
+
scrollToTop();
|
|
57
|
+
}
|
|
58
|
+
rej(postResponse);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
15
61
|
|
|
16
62
|
// register post mutation
|
|
17
63
|
const mutation = useMutation<IRequestSuccess<TResponse>, IRequestError>(
|
|
18
|
-
async (postData: any) =>
|
|
19
|
-
new Promise<IRequestSuccess<TResponse>>((res, rej) => {
|
|
20
|
-
makeRequest<TResponse>({
|
|
21
|
-
path: path,
|
|
22
|
-
body: postData,
|
|
23
|
-
method: HttpMethod.POST,
|
|
24
|
-
isFormData,
|
|
25
|
-
headers,
|
|
26
|
-
baseURL,
|
|
27
|
-
timeout,
|
|
28
|
-
}).then((postResponse) => {
|
|
29
|
-
if (postResponse.status) {
|
|
30
|
-
// scroll to top after success
|
|
31
|
-
window.scrollTo({
|
|
32
|
-
top: 0,
|
|
33
|
-
behavior: 'smooth',
|
|
34
|
-
});
|
|
35
|
-
res(postResponse as IRequestSuccess<TResponse>);
|
|
36
|
-
} else {
|
|
37
|
-
// scroll to top after error
|
|
38
|
-
window.scrollTo({
|
|
39
|
-
top: 0,
|
|
40
|
-
behavior: 'smooth',
|
|
41
|
-
});
|
|
42
|
-
rej(postResponse);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
})
|
|
64
|
+
async (postData: any) => new Promise<IRequestSuccess<TResponse>>((res, rej) => sendRequest(res, rej, postData))
|
|
46
65
|
);
|
|
47
66
|
const post = async (
|
|
48
|
-
|
|
49
|
-
options?:
|
|
50
|
-
| MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown>
|
|
51
|
-
| undefined
|
|
67
|
+
data: any,
|
|
68
|
+
options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined
|
|
52
69
|
): Promise<IRequestSuccess<TResponse>> => {
|
|
53
|
-
return mutation.mutateAsync(
|
|
70
|
+
return mutation.mutateAsync(data, options);
|
|
54
71
|
};
|
|
55
72
|
|
|
56
73
|
return { post, ...mutation };
|
|
@@ -2,11 +2,7 @@ import type { AxiosInstance } from 'axios';
|
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import type { IMakeRequest } from './request.interface';
|
|
4
4
|
|
|
5
|
-
export const axiosInstance = ({
|
|
6
|
-
baseURL,
|
|
7
|
-
timeout,
|
|
8
|
-
headers,
|
|
9
|
-
}: Partial<IMakeRequest>): AxiosInstance => {
|
|
5
|
+
export const axiosInstance = ({ baseURL, timeout, headers }: Partial<IMakeRequest>): AxiosInstance => {
|
|
10
6
|
return axios.create({
|
|
11
7
|
baseURL,
|
|
12
8
|
timeout,
|
|
@@ -1,13 +1,43 @@
|
|
|
1
1
|
export const buildFormData = (body: Record<string, any>) => {
|
|
2
2
|
const formData = new FormData();
|
|
3
3
|
|
|
4
|
+
const handleArrayValue = (key: string, value: any) => {
|
|
5
|
+
for (const item of value) {
|
|
6
|
+
if (item instanceof File) {
|
|
7
|
+
formData.append(key, item);
|
|
8
|
+
} else if (item instanceof Object) {
|
|
9
|
+
formData.append(key, JSON.stringify(item));
|
|
10
|
+
} else {
|
|
11
|
+
formData.append(key, item);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const handleObjectValue = (key: string, value: any) => {
|
|
17
|
+
if (value instanceof File) {
|
|
18
|
+
formData.append(key, value);
|
|
19
|
+
} else {
|
|
20
|
+
formData.append(key, JSON.stringify(value));
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const handlePrimitiveValue = (key: string, value: any) => {
|
|
25
|
+
formData.append(key, value);
|
|
26
|
+
};
|
|
27
|
+
|
|
4
28
|
const bodyKeys = Object.keys(body);
|
|
5
29
|
|
|
6
30
|
bodyKeys.forEach((key) => {
|
|
7
|
-
|
|
8
|
-
});
|
|
31
|
+
const inputValue = body[key];
|
|
9
32
|
|
|
10
|
-
|
|
33
|
+
if (Array.isArray(inputValue) && inputValue.length > 0) {
|
|
34
|
+
handleArrayValue(key, inputValue);
|
|
35
|
+
} else if (inputValue instanceof Object) {
|
|
36
|
+
handleObjectValue(key, inputValue);
|
|
37
|
+
} else {
|
|
38
|
+
handlePrimitiveValue(key, inputValue);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
11
41
|
|
|
12
|
-
return
|
|
42
|
+
return formData;
|
|
13
43
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
1
2
|
import { axiosInstance } from './axios-instance';
|
|
2
3
|
|
|
3
|
-
import { buildFormData } from './buildFormData';
|
|
4
4
|
import { ContentType, HttpMethod } from './request.enum';
|
|
5
5
|
import type { IMakeRequest } from './request.interface';
|
|
6
6
|
import { errorTransformer, successTransformer } from './transformer';
|
|
@@ -13,21 +13,43 @@ export async function makeRequest<TResponse>({
|
|
|
13
13
|
headers = {},
|
|
14
14
|
baseURL,
|
|
15
15
|
timeout,
|
|
16
|
+
appFileConfig,
|
|
16
17
|
}: IMakeRequest) {
|
|
17
|
-
//
|
|
18
|
-
|
|
18
|
+
// check if file is included in mobile app environment and extract all file input to avoid
|
|
19
|
+
// it being formatted to object using axios formData builder
|
|
20
|
+
const isApp = appFileConfig?.isApp;
|
|
21
|
+
const appFiles: Record<string, string> = isApp ? getAppFiles(body, appFileConfig.fileSelectors) : {};
|
|
19
22
|
|
|
20
|
-
// configure
|
|
23
|
+
// configure body
|
|
24
|
+
body = (isFormData ? axios.toFormData(body as FormData) : body) as FormData;
|
|
21
25
|
|
|
26
|
+
// configure request header1
|
|
22
27
|
if (!isFormData) {
|
|
23
28
|
headers['Content-Type'] = ContentType.APPLICATION_JSON;
|
|
29
|
+
} else {
|
|
30
|
+
if (isApp) {
|
|
31
|
+
headers['Content-Type'] = ContentType.MULTIPART_FORM_DATA;
|
|
32
|
+
// add the app files
|
|
33
|
+
for (const fileKey in appFiles) {
|
|
34
|
+
const currentFile = appFiles[fileKey];
|
|
35
|
+
if (Array.isArray(currentFile)) {
|
|
36
|
+
for (const innerFile of currentFile) {
|
|
37
|
+
body.append(fileKey, innerFile);
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
body.append(fileKey, currentFile);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
delete headers['Content-Type'];
|
|
45
|
+
}
|
|
24
46
|
}
|
|
25
47
|
|
|
26
48
|
try {
|
|
27
|
-
const
|
|
49
|
+
const axiosRequest = axiosInstance({ baseURL, headers, timeout });
|
|
28
50
|
|
|
29
51
|
// send request
|
|
30
|
-
const resp = await
|
|
52
|
+
const resp = await axiosRequest({
|
|
31
53
|
url: path,
|
|
32
54
|
method,
|
|
33
55
|
data: body,
|
|
@@ -45,14 +67,32 @@ export async function makeRequest<TResponse>({
|
|
|
45
67
|
}
|
|
46
68
|
|
|
47
69
|
return successTransformer<TResponse>({
|
|
48
|
-
data: jsonResp,
|
|
49
70
|
statusCode: responseCode,
|
|
71
|
+
...jsonResp,
|
|
72
|
+
status: resp.status,
|
|
50
73
|
});
|
|
51
74
|
} catch (error: any) {
|
|
75
|
+
const errorData = error?.response?.data;
|
|
52
76
|
return errorTransformer({
|
|
53
77
|
statusCode: error.status,
|
|
54
78
|
message: error.message,
|
|
55
79
|
code: error.status || error.statusCode,
|
|
80
|
+
...errorData,
|
|
56
81
|
});
|
|
57
82
|
}
|
|
58
83
|
}
|
|
84
|
+
function getAppFiles(body: any, fileSelectors: string[] = []) {
|
|
85
|
+
const files: Record<string, string> = {};
|
|
86
|
+
|
|
87
|
+
if (body) {
|
|
88
|
+
if (fileSelectors.length > 0) {
|
|
89
|
+
//
|
|
90
|
+
for (const fileKey of fileSelectors) {
|
|
91
|
+
files[fileKey] = body[fileKey];
|
|
92
|
+
delete body[fileKey];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return files;
|
|
98
|
+
}
|
|
@@ -9,8 +9,13 @@ export interface IMakeRequest {
|
|
|
9
9
|
method?: HttpMethod;
|
|
10
10
|
isFormData?: boolean;
|
|
11
11
|
headers: RawAxiosRequestHeaders;
|
|
12
|
+
appFileConfig?: AppFileConfig;
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
export interface AppFileConfig {
|
|
16
|
+
fileSelectors?: string[];
|
|
17
|
+
isApp: boolean;
|
|
18
|
+
}
|
|
14
19
|
export interface AxiosInstanceOption {
|
|
15
20
|
bearerToken?: string;
|
|
16
21
|
contentType?: string;
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
IRequestError,
|
|
3
|
-
IRequestSuccess,
|
|
4
|
-
IServerRequestError,
|
|
5
|
-
IServerRequestSuccess,
|
|
6
|
-
} from './request.interface';
|
|
1
|
+
import type { IRequestError, IRequestSuccess, IServerRequestError, IServerRequestSuccess } from './request.interface';
|
|
7
2
|
|
|
8
3
|
//
|
|
9
|
-
export const errorTransformer = (
|
|
10
|
-
data: IServerRequestError & { statusCode: number }
|
|
11
|
-
): IRequestError => {
|
|
4
|
+
export const errorTransformer = (data: IServerRequestError & { statusCode: number }): IRequestError => {
|
|
12
5
|
return {
|
|
13
6
|
message: data.message,
|
|
14
7
|
statusCode: data.statusCode,
|
|
@@ -19,9 +12,7 @@ export const errorTransformer = (
|
|
|
19
12
|
};
|
|
20
13
|
|
|
21
14
|
//
|
|
22
|
-
export const successTransformer = <T>(
|
|
23
|
-
data: IServerRequestSuccess & { statusCode: number }
|
|
24
|
-
): IRequestSuccess<T> => {
|
|
15
|
+
export const successTransformer = <T>(data: IServerRequestSuccess & { statusCode: number }): IRequestSuccess<T> => {
|
|
25
16
|
return {
|
|
26
17
|
message: data.message ?? 'Request successful',
|
|
27
18
|
statusCode: data.statusCode,
|
package/src/types/index.ts
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import type { RawAxiosRequestHeaders } from 'axios';
|
|
2
2
|
|
|
3
|
-
export interface
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
export interface BootstrapConfig {
|
|
4
|
+
environments?: {
|
|
5
|
+
appBaseUrl: string;
|
|
6
|
+
appTimeout: number;
|
|
7
|
+
};
|
|
8
|
+
context?: ContextType;
|
|
9
|
+
modelConfig?: BootstrapModelConfig;
|
|
7
10
|
}
|
|
8
11
|
|
|
9
|
-
export interface
|
|
10
|
-
|
|
11
|
-
setQueryHeaders: (header: TanstackQueryConfig['headers']) => void;
|
|
12
|
+
export interface BootstrapModelConfig {
|
|
13
|
+
idColumn: string;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export type ContextType = 'app' | 'web' | 'electronjs';
|
|
17
|
+
export interface TanstackQueryConfig {
|
|
18
|
+
headers: RawAxiosRequestHeaders;
|
|
19
|
+
options?: BootstrapConfig;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
export interface
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
export interface IUseQueryHeaders {
|
|
23
|
+
getHeaders: () => TanstackQueryConfig['headers'];
|
|
24
|
+
setQueryHeaders: (header: TanstackQueryConfig['headers']) => void;
|
|
22
25
|
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var reactQuery = require('@tanstack/react-query');
|
|
4
|
-
var useQueryConfig = require('./useQueryConfig.js');
|
|
5
|
-
|
|
6
|
-
const useQueryBaseURL = () => {
|
|
7
|
-
const { baseURL } = useQueryConfig.useQueryConfig();
|
|
8
|
-
const queryClient = reactQuery.useQueryClient();
|
|
9
|
-
const setQueryBaseUrl = (newBaseUrl) => {
|
|
10
|
-
queryClient.setQueryData(['config'], (config) => {
|
|
11
|
-
config.baseURL = newBaseUrl;
|
|
12
|
-
return config;
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
return { baseURL, setQueryBaseUrl };
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
exports.useQueryBaseURL = useQueryBaseURL;
|
|
19
|
-
//# sourceMappingURL=useQueryBaseURL.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useQueryBaseURL.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var reactQuery = require('@tanstack/react-query');
|
|
4
|
-
var useQueryConfig = require('./useQueryConfig.js');
|
|
5
|
-
|
|
6
|
-
const useQueryTimeout = () => {
|
|
7
|
-
const { timeout } = useQueryConfig.useQueryConfig();
|
|
8
|
-
const queryClient = reactQuery.useQueryClient();
|
|
9
|
-
const setQueryTimeout = (newTimeout) => {
|
|
10
|
-
queryClient.setQueryData(['config'], (config) => {
|
|
11
|
-
config.timeout = newTimeout;
|
|
12
|
-
return config;
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
return { timeout, setQueryTimeout };
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
exports.useQueryTimeout = useQueryTimeout;
|
|
19
|
-
//# sourceMappingURL=useQueryTimeout.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useQueryTimeout.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { useQueryClient } from '@tanstack/react-query';
|
|
2
|
-
import type { IUseQueryBaseURL, TanstackQueryConfig } from '../types';
|
|
3
|
-
import { useQueryConfig } from './useQueryConfig';
|
|
4
|
-
|
|
5
|
-
export const useQueryBaseURL = (): IUseQueryBaseURL => {
|
|
6
|
-
const { baseURL } = useQueryConfig();
|
|
7
|
-
const queryClient = useQueryClient();
|
|
8
|
-
|
|
9
|
-
const setQueryBaseUrl = (newBaseUrl: TanstackQueryConfig['baseURL']) => {
|
|
10
|
-
queryClient.setQueryData<TanstackQueryConfig>(['config'], (config) => {
|
|
11
|
-
(config as TanstackQueryConfig).baseURL = newBaseUrl;
|
|
12
|
-
return config;
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
return { baseURL, setQueryBaseUrl };
|
|
17
|
-
};
|