@ventlio/tanstack-query 0.2.5 → 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 +6 -0
- 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 +10 -0
- package/dist/{queries → config}/useQueryConfig.js.map +1 -1
- package/dist/config/useQueryHeaders.d.ts +2 -0
- package/dist/config/useQueryHeaders.js +28 -0
- package/dist/config/useQueryHeaders.js.map +1 -0
- 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.d.ts +2 -0
- package/dist/index.js +19 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +434 -119
- package/dist/index.mjs.map +1 -1
- package/dist/model/index.d.ts +4 -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 -0
- package/dist/model/useQueryModel.js +123 -0
- package/dist/model/useQueryModel.js.map +1 -0
- 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/index.d.ts +0 -1
- 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 +17 -2
- 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/queries/useQueryConfig.js +0 -14
- package/src/config/useQueryBaseURL.ts +0 -17
- package/src/config/useQueryTimeout.ts +0 -17
- /package/dist/{queries → config}/useQueryConfig.d.ts +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
4
|
+
import { usePostRequest } from '../../queries';
|
|
5
|
+
|
|
6
|
+
const mockAxios = new MockAdapter(axios);
|
|
7
|
+
|
|
8
|
+
describe('usePostRequest', () => {
|
|
9
|
+
const path = '/test';
|
|
10
|
+
const postData = { name: 'John Doe' };
|
|
11
|
+
const response = { id: 123, name: 'John Doe' };
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
mockAxios.reset();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should return post function and mutation object', () => {
|
|
18
|
+
const { result } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path }));
|
|
19
|
+
|
|
20
|
+
expect(result.current.post).toBeInstanceOf(Function);
|
|
21
|
+
expect(result.current.isLoading).toBe(false);
|
|
22
|
+
expect(result.current.isSuccess).toBe(false);
|
|
23
|
+
expect(result.current.isError).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should make post request and return response data', async () => {
|
|
27
|
+
mockAxios.onPost(path).reply(200, response);
|
|
28
|
+
|
|
29
|
+
const { result, waitForNextUpdate } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path }));
|
|
30
|
+
|
|
31
|
+
const responsePromise = result.current.post(postData);
|
|
32
|
+
|
|
33
|
+
expect(result.current.isLoading).toBe(true);
|
|
34
|
+
|
|
35
|
+
await waitForNextUpdate();
|
|
36
|
+
|
|
37
|
+
expect(result.current.isLoading).toBe(false);
|
|
38
|
+
expect(result.current.isSuccess).toBe(true);
|
|
39
|
+
expect(result.current.data).toEqual(response);
|
|
40
|
+
expect(await responsePromise).toEqual(response);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should make post request and return error', async () => {
|
|
44
|
+
const errorMessage = 'Request failed with status code 500';
|
|
45
|
+
mockAxios.onPost(path).reply(500, { message: errorMessage });
|
|
46
|
+
|
|
47
|
+
const { result, waitForNextUpdate } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path }));
|
|
48
|
+
|
|
49
|
+
const responsePromise = result.current.post(postData);
|
|
50
|
+
|
|
51
|
+
expect(result.current.isLoading).toBe(true);
|
|
52
|
+
|
|
53
|
+
await waitForNextUpdate();
|
|
54
|
+
|
|
55
|
+
expect(result.current.isLoading).toBe(false);
|
|
56
|
+
expect(result.current.isError).toBe(true);
|
|
57
|
+
expect(result.current.error?.message).toBe(errorMessage);
|
|
58
|
+
|
|
59
|
+
await expect(responsePromise).rejects.toEqual({
|
|
60
|
+
message: errorMessage,
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should make post request with FormData', async () => {
|
|
65
|
+
const formData = new FormData();
|
|
66
|
+
formData.append('name', 'John Doe');
|
|
67
|
+
mockAxios.onPost(path).reply(200, response);
|
|
68
|
+
|
|
69
|
+
const { result } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path, isFormData: true }));
|
|
70
|
+
|
|
71
|
+
const responsePromise = result.current.post(formData);
|
|
72
|
+
|
|
73
|
+
expect(result.current.isLoading).toBe(true);
|
|
74
|
+
|
|
75
|
+
await expect(responsePromise).resolves.toEqual(response);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
import 'url-search-params-polyfill';
|
|
3
|
+
import type { BootstrapConfig, TanstackQueryConfig } from '../types';
|
|
4
|
+
|
|
5
|
+
export const bootstrapQueryRequest = (queryClient: QueryClient, options?: BootstrapConfig): void => {
|
|
6
|
+
// make query config doesn't expire
|
|
7
|
+
queryClient.setQueryDefaults(['config'], {
|
|
8
|
+
staleTime: Infinity,
|
|
9
|
+
cacheTime: Infinity,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// set default query config
|
|
13
|
+
queryClient.setQueryData<TanstackQueryConfig>(['config'], {
|
|
14
|
+
headers: {
|
|
15
|
+
Authorization: ``,
|
|
16
|
+
},
|
|
17
|
+
options,
|
|
18
|
+
});
|
|
19
|
+
};
|
package/src/config/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './bootstrapQueryRequest';
|
|
2
|
+
export * from './config.interface';
|
|
3
|
+
export * from './useEnvironmentVariables';
|
|
2
4
|
export * from './useQueryConfig';
|
|
3
5
|
export * from './useQueryHeaders';
|
|
4
|
-
export * from './
|
|
6
|
+
export * from './useReactNativeEnv';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IConfig } from './config.interface';
|
|
2
|
+
import { useReactNativeEnv } from './useReactNativeEnv';
|
|
3
|
+
|
|
4
|
+
export const useEnvironmentVariables = (): IConfig => {
|
|
5
|
+
const { appTimeout, appUrl } = useReactNativeEnv();
|
|
6
|
+
const url = process.env.REACT_APP_API_URL ?? process.env.NEXT_PUBLIC_API_URL ?? appUrl;
|
|
7
|
+
const timeout = process.env.REACT_APP_API_TIMEOUT ?? process.env.NEXT_PUBLIC_API_TIMEOUT ?? appTimeout;
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
API_URL: url as string,
|
|
11
|
+
TIMEOUT: Number(timeout),
|
|
12
|
+
};
|
|
13
|
+
};
|
|
@@ -4,10 +4,7 @@ import type { TanstackQueryConfig } from '../types';
|
|
|
4
4
|
export const useQueryConfig = (): TanstackQueryConfig => {
|
|
5
5
|
const queryClient = useQueryClient();
|
|
6
6
|
|
|
7
|
-
const { headers
|
|
8
|
-
queryClient.getQueryData<TanstackQueryConfig>([
|
|
9
|
-
'config',
|
|
10
|
-
]) as TanstackQueryConfig;
|
|
7
|
+
const { headers = {}, options = {} } = queryClient.getQueryData<TanstackQueryConfig>(['config']) ?? {};
|
|
11
8
|
|
|
12
|
-
return { headers,
|
|
9
|
+
return { headers, options };
|
|
13
10
|
};
|
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
import { useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import { getDateInFuture } from '../helpers';
|
|
2
3
|
import type { IUseQueryHeaders, TanstackQueryConfig } from '../types';
|
|
3
|
-
import { useQueryConfig } from './useQueryConfig';
|
|
4
4
|
|
|
5
5
|
export const useQueryHeaders = (): IUseQueryHeaders => {
|
|
6
|
-
const { headers } = useQueryConfig();
|
|
7
6
|
const queryClient = useQueryClient();
|
|
8
7
|
|
|
8
|
+
const getHeaders = (): TanstackQueryConfig['headers'] => {
|
|
9
|
+
const config = queryClient.getQueryData(['config']) as TanstackQueryConfig;
|
|
10
|
+
return config.headers;
|
|
11
|
+
};
|
|
12
|
+
|
|
9
13
|
const setQueryHeaders = (newHeaders: TanstackQueryConfig['headers']) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
// make sure the config does not expire
|
|
15
|
+
queryClient.setQueryDefaults(['config'], {
|
|
16
|
+
staleTime: Infinity,
|
|
17
|
+
cacheTime: Infinity,
|
|
13
18
|
});
|
|
19
|
+
|
|
20
|
+
// set the config
|
|
21
|
+
queryClient.setQueryData<TanstackQueryConfig>(
|
|
22
|
+
['config'],
|
|
23
|
+
(config): TanstackQueryConfig => {
|
|
24
|
+
const newConfig = { ...config, headers: newHeaders };
|
|
25
|
+
return newConfig;
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
updatedAt: getDateInFuture(2),
|
|
29
|
+
}
|
|
30
|
+
);
|
|
14
31
|
};
|
|
15
32
|
|
|
16
|
-
return {
|
|
33
|
+
return { setQueryHeaders, getHeaders };
|
|
17
34
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import type { TanstackQueryConfig } from '../types';
|
|
3
|
+
|
|
4
|
+
export const useReactNativeEnv = () => {
|
|
5
|
+
const queryClient = useQueryClient();
|
|
6
|
+
const config = queryClient.getQueryData<TanstackQueryConfig>(['config']);
|
|
7
|
+
|
|
8
|
+
const appUrl: string | undefined = config?.options?.environments?.appBaseUrl;
|
|
9
|
+
const appTimeout: number | undefined = config?.options?.environments?.appTimeout;
|
|
10
|
+
const isApp = config?.options?.context === 'app';
|
|
11
|
+
|
|
12
|
+
return { appUrl, appTimeout, isApp };
|
|
13
|
+
};
|
package/src/env.d.ts
ADDED
package/src/helpers/index.ts
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function getDateInFuture(days: number) {
|
|
2
|
+
// Create a new Date object
|
|
3
|
+
const date = new Date();
|
|
4
|
+
|
|
5
|
+
// Add the specified number of days to the date
|
|
6
|
+
date.setDate(date.getDate() + days);
|
|
7
|
+
|
|
8
|
+
// Get the Unix timestamp of the date (in milliseconds)
|
|
9
|
+
return date.getTime();
|
|
10
|
+
}
|
package/src/model/index.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface QueryModelBuilder<T> {
|
|
2
|
+
add: (data: T, position?: QueryModelAddPosition, path?: string) => T | undefined;
|
|
3
|
+
findAll: (path?: string) => T[] | T | undefined;
|
|
4
|
+
findMany: (selector: (record: T) => boolean, path?: string) => T[];
|
|
5
|
+
find: (id: number | string, path?: string) => T | undefined;
|
|
6
|
+
update: (id: number | string, data: Partial<T>, path?: string) => T | undefined;
|
|
7
|
+
remove: (id: number, path?: string) => boolean;
|
|
8
|
+
get: (path?: string) => T | undefined;
|
|
9
|
+
set: <DataType>(data: Partial<DataType>, path?: string) => DataType | undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type QueryModelAddPosition = 'start' | 'end';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
|
|
3
|
+
export const useKeyTrackerModel = <T>(keyTracker: string) => {
|
|
4
|
+
const queryClient = useQueryClient();
|
|
5
|
+
|
|
6
|
+
const getQueryKey = (innerKeyTracker?: string) => {
|
|
7
|
+
const queryKey: any[] | undefined = queryClient.getQueryData([innerKeyTracker ?? keyTracker]);
|
|
8
|
+
|
|
9
|
+
return queryKey;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const refetchQuery = async (innerKeyTracker?: string) => {
|
|
13
|
+
const queryKey: any = getQueryKey(innerKeyTracker ?? keyTracker);
|
|
14
|
+
|
|
15
|
+
await queryClient.refetchQueries<T>({
|
|
16
|
+
queryKey,
|
|
17
|
+
exact: true,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return { refetchQuery, getQueryKey };
|
|
22
|
+
};
|
|
@@ -1,11 +1,144 @@
|
|
|
1
|
-
import type { QueryFilters } from '@tanstack/react-query';
|
|
2
1
|
import { useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import result from 'lodash.result';
|
|
3
|
+
import { default as lodashSet } from 'lodash.set';
|
|
4
|
+
import type { TanstackQueryConfig } from '../types';
|
|
5
|
+
import type { QueryModelAddPosition, QueryModelBuilder } from './model.interface';
|
|
6
|
+
import { useKeyTrackerModel } from './useKeyTrackerModel';
|
|
3
7
|
|
|
4
|
-
export const useQueryModel = (
|
|
5
|
-
queryKey: any[],
|
|
6
|
-
filters?: QueryFilters | undefined
|
|
7
|
-
) => {
|
|
8
|
+
export const useQueryModel = <T>(keyTracker: string, exact: boolean = true): QueryModelBuilder<T> => {
|
|
8
9
|
const queryClient = useQueryClient();
|
|
10
|
+
const { getQueryKey } = useKeyTrackerModel(keyTracker);
|
|
11
|
+
const queryKey = getQueryKey() as any[];
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
const add = (data: T, position?: QueryModelAddPosition, path?: string): T | undefined => {
|
|
14
|
+
let records = (findAll(path) ?? []) as T[];
|
|
15
|
+
|
|
16
|
+
if (!position || position === 'end') {
|
|
17
|
+
records = [...records, data];
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
19
|
+
} else if (position === 'start') {
|
|
20
|
+
records = [data, ...records];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!path) {
|
|
24
|
+
queryClient.setQueryData(queryKey, records);
|
|
25
|
+
} else {
|
|
26
|
+
const queryData = queryClient.getQueryData(queryKey, { exact }) ?? {};
|
|
27
|
+
queryClient.setQueryData(queryKey, lodashSet(queryData, path, records));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return data;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const findAll = (path?: string): T[] | T | undefined => {
|
|
34
|
+
const data = queryClient.getQueryData(queryKey, { exact });
|
|
35
|
+
|
|
36
|
+
if (!data) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!path) {
|
|
41
|
+
return Array.isArray(data) ? data : [data];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return result<T[]>(data, path, []);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const findMany = (selector: (record: T) => boolean, path?: string): T[] => {
|
|
48
|
+
const data = (findAll(path) ?? []) as T[];
|
|
49
|
+
return data.filter(selector);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const find = (id: string | number, path?: string): T | undefined => {
|
|
53
|
+
const modelConfig = getModelConfig();
|
|
54
|
+
|
|
55
|
+
if (!modelConfig?.idColumn) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
const data = (findAll(path) ?? []) as T[];
|
|
59
|
+
|
|
60
|
+
return data.find((record) => (record as Record<string, any>)[modelConfig.idColumn] === id);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const get = (path?: string): T | undefined => {
|
|
64
|
+
let data = queryClient.getQueryData(queryKey, { exact });
|
|
65
|
+
if (path) {
|
|
66
|
+
data = result<T>(data, path);
|
|
67
|
+
}
|
|
68
|
+
return data as T;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const set = <DataType>(newData: Partial<DataType>, path?: string): DataType | undefined => {
|
|
72
|
+
if (path) {
|
|
73
|
+
const data = get() as any;
|
|
74
|
+
newData = lodashSet(data, path, newData);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return queryClient.setQueryData(queryKey, newData) as DataType;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const getModelConfig = () => {
|
|
81
|
+
const { options } = queryClient.getQueryData<TanstackQueryConfig>(['config']) ?? {};
|
|
82
|
+
const { modelConfig } = options ?? {};
|
|
83
|
+
|
|
84
|
+
return modelConfig;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const update = (id: string | number, data: Partial<T>, path?: string): T | undefined => {
|
|
88
|
+
const oldData = (findAll(path) ?? []) as T[];
|
|
89
|
+
const modelConfig = getModelConfig();
|
|
90
|
+
|
|
91
|
+
if (!modelConfig?.idColumn) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
const idColumn = modelConfig.idColumn;
|
|
95
|
+
|
|
96
|
+
let updatedRecord: T | undefined = undefined;
|
|
97
|
+
const newData = oldData.map((record) => {
|
|
98
|
+
let dataRecord = record as Record<string, any>;
|
|
99
|
+
if (dataRecord[idColumn] === id) {
|
|
100
|
+
dataRecord = { ...dataRecord, ...data };
|
|
101
|
+
updatedRecord = dataRecord as T;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return dataRecord;
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (!path) {
|
|
108
|
+
queryClient.setQueryData(queryKey, newData);
|
|
109
|
+
} else {
|
|
110
|
+
const queryData = queryClient.getQueryData(queryKey, { exact }) ?? {};
|
|
111
|
+
queryClient.setQueryData(queryKey, lodashSet(queryData, path, newData));
|
|
112
|
+
}
|
|
113
|
+
return updatedRecord;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const remove = (id: number | string, path?: string): boolean => {
|
|
117
|
+
const oldData = (findAll(path) ?? []) as T[];
|
|
118
|
+
const modelConfig = getModelConfig();
|
|
119
|
+
|
|
120
|
+
if (!modelConfig?.idColumn) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
const idColumn = modelConfig.idColumn;
|
|
124
|
+
let updated = false;
|
|
125
|
+
const newData = oldData.filter((record) => {
|
|
126
|
+
const dataRecord = record as Record<string, any>;
|
|
127
|
+
if (dataRecord[idColumn] === id) {
|
|
128
|
+
updated = true;
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
if (!path) {
|
|
135
|
+
queryClient.setQueryData(queryKey, newData);
|
|
136
|
+
} else {
|
|
137
|
+
const queryData = queryClient.getQueryData(queryKey, { exact }) ?? {};
|
|
138
|
+
queryClient.setQueryData(queryKey, lodashSet(queryData, path, newData));
|
|
139
|
+
}
|
|
140
|
+
return updated;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
return { find, findAll, findMany, remove, update, add, get, set };
|
|
11
144
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
|
|
3
|
+
export const useRefetchQuery = async (queryKey: any[]) => {
|
|
4
|
+
const queryClient = useQueryClient();
|
|
5
|
+
|
|
6
|
+
const refetchQuery = async <T>(innerQueryKey?: any[]) => {
|
|
7
|
+
await queryClient.invalidateQueries(
|
|
8
|
+
{
|
|
9
|
+
queryKey: innerQueryKey ?? queryKey,
|
|
10
|
+
exact: true,
|
|
11
|
+
},
|
|
12
|
+
{ throwOnError: true, cancelRefetch: true }
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
return queryClient.getQueriesData<T>(innerQueryKey ?? queryKey);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return { refetchQuery };
|
|
19
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { UseQueryOptions } from '@tanstack/react-query';
|
|
2
|
+
import type { RawAxiosRequestHeaders } from 'axios';
|
|
2
3
|
import type { IRequestError, IRequestSuccess } from '../request';
|
|
3
4
|
|
|
4
5
|
export interface IPagination {
|
|
@@ -16,3 +17,8 @@ export type TanstackQueryOption<TResponse> = UseQueryOptions<
|
|
|
16
17
|
IRequestSuccess<TResponse | undefined>,
|
|
17
18
|
Array<any>
|
|
18
19
|
>;
|
|
20
|
+
|
|
21
|
+
export interface DefaultRequestOptions {
|
|
22
|
+
baseUrl?: string;
|
|
23
|
+
headers?: RawAxiosRequestHeaders;
|
|
24
|
+
}
|
|
@@ -1,36 +1,44 @@
|
|
|
1
1
|
import type { UseQueryOptions } from '@tanstack/react-query';
|
|
2
2
|
import { useQuery } from '@tanstack/react-query';
|
|
3
|
+
import type { RawAxiosRequestHeaders } from 'axios';
|
|
3
4
|
import { useState } from 'react';
|
|
4
|
-
import {
|
|
5
|
+
import { useEnvironmentVariables, useQueryHeaders } from '../config';
|
|
5
6
|
import type { IRequestError, IRequestSuccess } from '../request';
|
|
6
7
|
import { HttpMethod, makeRequest } from '../request';
|
|
8
|
+
import type { DefaultRequestOptions } from './queries.interface';
|
|
7
9
|
|
|
8
|
-
export const useDeleteRequest = <TResponse>() => {
|
|
10
|
+
export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOptions) => {
|
|
11
|
+
const { baseUrl, headers } = deleteOptions ?? {};
|
|
9
12
|
const [requestPath, updateDeletePath] = useState<string>('');
|
|
10
13
|
const [options, setOptions] = useState<any>();
|
|
11
14
|
|
|
12
|
-
const {
|
|
15
|
+
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
16
|
+
|
|
17
|
+
const { getHeaders } = useQueryHeaders();
|
|
18
|
+
|
|
19
|
+
const sendRequest = async (res: (value: any) => void, rej: (reason?: any) => void) => {
|
|
20
|
+
// get request headers
|
|
21
|
+
const globalHeaders: RawAxiosRequestHeaders = getHeaders();
|
|
22
|
+
|
|
23
|
+
const postResponse = await makeRequest<TResponse>({
|
|
24
|
+
path: requestPath,
|
|
25
|
+
headers: { ...globalHeaders, ...headers },
|
|
26
|
+
method: HttpMethod.DELETE,
|
|
27
|
+
baseURL: baseUrl ?? API_URL,
|
|
28
|
+
timeout: TIMEOUT,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (postResponse.status) {
|
|
32
|
+
res(postResponse as IRequestSuccess<TResponse>);
|
|
33
|
+
} else {
|
|
34
|
+
rej(postResponse);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
13
37
|
|
|
14
38
|
const query = useQuery<any, any, IRequestSuccess<TResponse>>(
|
|
15
39
|
[requestPath, {}],
|
|
16
|
-
() =>
|
|
17
|
-
|
|
18
|
-
setTimeout(async () => {
|
|
19
|
-
const postResponse = await makeRequest<TResponse>({
|
|
20
|
-
path: requestPath,
|
|
21
|
-
headers,
|
|
22
|
-
method: HttpMethod.DELETE,
|
|
23
|
-
baseURL,
|
|
24
|
-
timeout,
|
|
25
|
-
});
|
|
26
|
-
if (postResponse.status) {
|
|
27
|
-
res(postResponse as IRequestSuccess<TResponse>);
|
|
28
|
-
} else {
|
|
29
|
-
rej(postResponse);
|
|
30
|
-
}
|
|
31
|
-
}, 200);
|
|
32
|
-
}),
|
|
33
|
-
{ ...options }
|
|
40
|
+
() => new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej)),
|
|
41
|
+
{ enabled: false, ...options }
|
|
34
42
|
);
|
|
35
43
|
|
|
36
44
|
const updatedPathAsync = async (link: string) => {
|
|
@@ -43,23 +51,19 @@ export const useDeleteRequest = <TResponse>() => {
|
|
|
43
51
|
|
|
44
52
|
const destroy = async (
|
|
45
53
|
link: string,
|
|
46
|
-
|
|
54
|
+
internalDeleteOptions?: UseQueryOptions<
|
|
47
55
|
IRequestSuccess<TResponse | undefined>,
|
|
48
56
|
IRequestError,
|
|
49
57
|
IRequestSuccess<TResponse | undefined>,
|
|
50
58
|
Array<any>
|
|
51
|
-
>
|
|
59
|
+
> & { cached?: boolean }
|
|
52
60
|
): Promise<IRequestSuccess<TResponse> | undefined> => {
|
|
53
61
|
// set enabled to be true for every delete
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
internalDeleteOptions = internalDeleteOptions ?? {};
|
|
63
|
+
internalDeleteOptions.enabled = true;
|
|
56
64
|
|
|
65
|
+
await setOptionsAsync(internalDeleteOptions);
|
|
57
66
|
await updatedPathAsync(link);
|
|
58
|
-
await setOptionsAsync(deleteOptions);
|
|
59
|
-
|
|
60
|
-
// return query.refetch<TResponse>({
|
|
61
|
-
// queryKey: [link, {}],
|
|
62
|
-
// });
|
|
63
67
|
|
|
64
68
|
return query.data;
|
|
65
69
|
};
|