@ventlio/tanstack-query 0.3.1 → 0.3.3

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.
Files changed (35) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +127 -33
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/queries/useDeleteRequest.d.ts +4 -4
  7. package/dist/queries/useDeleteRequest.js +26 -9
  8. package/dist/queries/useDeleteRequest.js.map +1 -1
  9. package/dist/queries/useGetInfiniteRequest.d.ts +4 -4
  10. package/dist/queries/useGetInfiniteRequest.js +21 -4
  11. package/dist/queries/useGetInfiniteRequest.js.map +1 -1
  12. package/dist/queries/useGetRequest.d.ts +4 -4
  13. package/dist/queries/useGetRequest.js +21 -4
  14. package/dist/queries/useGetRequest.js.map +1 -1
  15. package/dist/queries/usePatchRequest.d.ts +8 -8
  16. package/dist/queries/usePatchRequest.js +19 -2
  17. package/dist/queries/usePatchRequest.js.map +1 -1
  18. package/dist/queries/usePostRequest.d.ts +8 -8
  19. package/dist/queries/usePostRequest.js +20 -3
  20. package/dist/queries/usePostRequest.js.map +1 -1
  21. package/dist/stores/index.d.ts +1 -0
  22. package/dist/stores/usePauseFutureRequests.d.ts +7 -0
  23. package/dist/stores/usePauseFutureRequests.js +19 -0
  24. package/dist/stores/usePauseFutureRequests.js.map +1 -0
  25. package/package.json +4 -2
  26. package/src/__tests__/queries/usePostRequest.spec.tsx +84 -0
  27. package/src/index.ts +2 -0
  28. package/src/queries/useDeleteRequest.ts +27 -9
  29. package/src/queries/useGetInfiniteRequest.ts +22 -4
  30. package/src/queries/useGetRequest.ts +22 -4
  31. package/src/queries/usePatchRequest.ts +22 -3
  32. package/src/queries/usePostRequest.ts +22 -4
  33. package/src/stores/index.ts +1 -0
  34. package/src/stores/usePauseFutureRequests.ts +25 -0
  35. package/src/__tests__/queries/usePostRequest.spec.ts +0 -77
@@ -7,6 +7,7 @@ import { useQueryHeaders } from '../config/useQueryHeaders.js';
7
7
  import 'axios';
8
8
  import { makeRequest } from '../request/make-request.js';
9
9
  import '../request/request.enum.js';
10
+ import { usePauseFutureRequests } from '../stores/usePauseFutureRequests.js';
10
11
 
11
12
  const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, }) => {
12
13
  const [requestPath, setRequestPath] = useState(path);
@@ -15,6 +16,8 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
15
16
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
16
17
  const { getHeaders } = useQueryHeaders();
17
18
  const { options: queryConfigOptions } = useQueryConfig();
19
+ const [requestPayload, setRequestPayload] = useState();
20
+ const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
18
21
  let queryClient = useQueryClient();
19
22
  // eslint-disable-next-line react-hooks/exhaustive-deps
20
23
  queryClient = useMemo(() => queryClient, []);
@@ -52,7 +55,7 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
52
55
  }
53
56
  };
54
57
  const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), {
55
- enabled: load,
58
+ enabled: load && !isFutureQueriesPaused,
56
59
  ...options,
57
60
  });
58
61
  useEffect(() => {
@@ -112,12 +115,26 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
112
115
  });
113
116
  };
114
117
  const get = async (link, fetchOptions) => {
115
- await setOptionsAsync(fetchOptions);
116
- await updatedPathAsync(link);
117
- return query.data;
118
+ if (!isFutureQueriesPaused) {
119
+ await setOptionsAsync(fetchOptions);
120
+ await updatedPathAsync(link);
121
+ return query.data;
122
+ }
123
+ else {
124
+ setRequestPayload({ link, fetchOptions });
125
+ return undefined;
126
+ }
118
127
  };
128
+ useEffect(() => {
129
+ if (!isFutureQueriesPaused && requestPayload) {
130
+ get(requestPayload.link, requestPayload.fetchOptions);
131
+ setRequestPayload(undefined);
132
+ }
133
+ // eslint-disable-next-line react-hooks/exhaustive-deps
134
+ }, [isFutureQueriesPaused]);
119
135
  return {
120
136
  ...query,
137
+ isLoading: query.isLoading || isFutureQueriesPaused,
121
138
  setRequestPath,
122
139
  nextPage,
123
140
  prevPage,
@@ -1 +1 @@
1
- {"version":3,"file":"useGetRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useGetRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -4,11 +4,11 @@ import type { DefaultRequestOptions } from './queries.interface';
4
4
  export declare const usePatchRequest: <TResponse>({ path, baseUrl, headers }: {
5
5
  path: string;
6
6
  } & DefaultRequestOptions) => {
7
+ isLoading: boolean;
7
8
  data: undefined;
8
9
  error: null;
9
10
  isError: false;
10
11
  isIdle: true;
11
- isLoading: false;
12
12
  isSuccess: false;
13
13
  status: "idle";
14
14
  mutate: import("@tanstack/react-query").UseMutateFunction<IRequestSuccess<TResponse>, IRequestError, void, unknown>;
@@ -19,14 +19,14 @@ export declare const usePatchRequest: <TResponse>({ path, baseUrl, headers }: {
19
19
  isPaused: boolean;
20
20
  variables: void | undefined;
21
21
  mutateAsync: import("@tanstack/react-query").UseMutateAsyncFunction<IRequestSuccess<TResponse>, IRequestError, void, unknown>;
22
- patch: (data: any, options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined) => Promise<IRequestSuccess<TResponse>>;
22
+ patch: (data: any, options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined) => Promise<IRequestSuccess<TResponse> | undefined>;
23
23
  uploadProgressPercent: number;
24
24
  } | {
25
+ isLoading: boolean;
25
26
  data: undefined;
26
27
  error: null;
27
28
  isError: false;
28
29
  isIdle: false;
29
- isLoading: true;
30
30
  isSuccess: false;
31
31
  status: "loading";
32
32
  mutate: import("@tanstack/react-query").UseMutateFunction<IRequestSuccess<TResponse>, IRequestError, void, unknown>;
@@ -37,14 +37,14 @@ export declare const usePatchRequest: <TResponse>({ path, baseUrl, headers }: {
37
37
  isPaused: boolean;
38
38
  variables: void | undefined;
39
39
  mutateAsync: import("@tanstack/react-query").UseMutateAsyncFunction<IRequestSuccess<TResponse>, IRequestError, void, unknown>;
40
- patch: (data: any, options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined) => Promise<IRequestSuccess<TResponse>>;
40
+ patch: (data: any, options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined) => Promise<IRequestSuccess<TResponse> | undefined>;
41
41
  uploadProgressPercent: number;
42
42
  } | {
43
+ isLoading: boolean;
43
44
  data: undefined;
44
45
  error: IRequestError;
45
46
  isError: true;
46
47
  isIdle: false;
47
- isLoading: false;
48
48
  isSuccess: false;
49
49
  status: "error";
50
50
  mutate: import("@tanstack/react-query").UseMutateFunction<IRequestSuccess<TResponse>, IRequestError, void, unknown>;
@@ -55,14 +55,14 @@ export declare const usePatchRequest: <TResponse>({ path, baseUrl, headers }: {
55
55
  isPaused: boolean;
56
56
  variables: void | undefined;
57
57
  mutateAsync: import("@tanstack/react-query").UseMutateAsyncFunction<IRequestSuccess<TResponse>, IRequestError, void, unknown>;
58
- patch: (data: any, options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined) => Promise<IRequestSuccess<TResponse>>;
58
+ patch: (data: any, options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined) => Promise<IRequestSuccess<TResponse> | undefined>;
59
59
  uploadProgressPercent: number;
60
60
  } | {
61
+ isLoading: boolean;
61
62
  data: IRequestSuccess<TResponse>;
62
63
  error: null;
63
64
  isError: false;
64
65
  isIdle: false;
65
- isLoading: false;
66
66
  isSuccess: true;
67
67
  status: "success";
68
68
  mutate: import("@tanstack/react-query").UseMutateFunction<IRequestSuccess<TResponse>, IRequestError, void, unknown>;
@@ -73,6 +73,6 @@ export declare const usePatchRequest: <TResponse>({ path, baseUrl, headers }: {
73
73
  isPaused: boolean;
74
74
  variables: void | undefined;
75
75
  mutateAsync: import("@tanstack/react-query").UseMutateAsyncFunction<IRequestSuccess<TResponse>, IRequestError, void, unknown>;
76
- patch: (data: any, options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined) => Promise<IRequestSuccess<TResponse>>;
76
+ patch: (data: any, options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined) => Promise<IRequestSuccess<TResponse> | undefined>;
77
77
  uploadProgressPercent: number;
78
78
  };
@@ -1,4 +1,5 @@
1
1
  import { useMutation } from '@tanstack/react-query';
2
+ import { useState, useEffect } from 'react';
2
3
  import 'url-search-params-polyfill';
3
4
  import { useEnvironmentVariables } from '../config/useEnvironmentVariables.js';
4
5
  import { useQueryConfig } from '../config/useQueryConfig.js';
@@ -8,10 +9,13 @@ import { useUploadProgress } from '../hooks/useUploadProgress.js';
8
9
  import 'axios';
9
10
  import { makeRequest } from '../request/make-request.js';
10
11
  import { HttpMethod } from '../request/request.enum.js';
12
+ import { usePauseFutureRequests } from '../stores/usePauseFutureRequests.js';
11
13
 
12
14
  const usePatchRequest = ({ path, baseUrl, headers }) => {
13
15
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
14
16
  const { uploadProgressPercent, onUploadProgress } = useUploadProgress();
17
+ const [requestPayload, setRequestPayload] = useState();
18
+ const isFutureMutationsPaused = usePauseFutureRequests((state) => state.isFutureMutationsPaused);
15
19
  const { getHeaders } = useQueryHeaders();
16
20
  const config = useQueryConfig();
17
21
  const sendRequest = async (res, rej, data) => {
@@ -59,9 +63,22 @@ const usePatchRequest = ({ path, baseUrl, headers }) => {
59
63
  return sendRequest(res, rej, dataData);
60
64
  }), { mutationKey: [path, { type: 'mutation' }] });
61
65
  const patch = async (data, options) => {
62
- return mutation.mutateAsync(data, options);
66
+ if (!isFutureMutationsPaused) {
67
+ return mutation.mutateAsync(data, options);
68
+ }
69
+ else {
70
+ setRequestPayload({ data, options });
71
+ return undefined;
72
+ }
63
73
  };
64
- return { patch, uploadProgressPercent, ...mutation };
74
+ useEffect(() => {
75
+ if (!isFutureMutationsPaused && requestPayload) {
76
+ patch(requestPayload.data, requestPayload.options);
77
+ setRequestPayload(undefined);
78
+ }
79
+ // eslint-disable-next-line react-hooks/exhaustive-deps
80
+ }, [isFutureMutationsPaused]);
81
+ return { patch, uploadProgressPercent, ...mutation, isLoading: mutation.isLoading || isFutureMutationsPaused };
65
82
  };
66
83
 
67
84
  export { usePatchRequest };
@@ -1 +1 @@
1
- {"version":3,"file":"usePatchRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"usePatchRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -6,11 +6,11 @@ export declare const usePostRequest: <TResponse>({ path, isFormData, baseUrl, he
6
6
  isFormData?: boolean | undefined;
7
7
  fileSelectors?: string[] | undefined;
8
8
  } & DefaultRequestOptions) => {
9
+ isLoading: boolean;
9
10
  data: undefined;
10
11
  error: null;
11
12
  isError: false;
12
13
  isIdle: true;
13
- isLoading: false;
14
14
  isSuccess: false;
15
15
  status: "idle";
16
16
  mutate: import("@tanstack/react-query").UseMutateFunction<IRequestSuccess<TResponse>, IRequestError, {
@@ -39,14 +39,14 @@ export declare const usePostRequest: <TResponse>({ path, isFormData, baseUrl, he
39
39
  requestConfig?: Partial<Omit<IMakeRequest, "body">> | undefined;
40
40
  } & {
41
41
  requestConfig?: Partial<Omit<IMakeRequest, "body">> | undefined;
42
- }) | undefined) => Promise<IRequestSuccess<TResponse>>;
42
+ }) | undefined) => Promise<IRequestSuccess<TResponse> | undefined>;
43
43
  uploadProgressPercent: number;
44
44
  } | {
45
+ isLoading: boolean;
45
46
  data: undefined;
46
47
  error: null;
47
48
  isError: false;
48
49
  isIdle: false;
49
- isLoading: true;
50
50
  isSuccess: false;
51
51
  status: "loading";
52
52
  mutate: import("@tanstack/react-query").UseMutateFunction<IRequestSuccess<TResponse>, IRequestError, {
@@ -75,14 +75,14 @@ export declare const usePostRequest: <TResponse>({ path, isFormData, baseUrl, he
75
75
  requestConfig?: Partial<Omit<IMakeRequest, "body">> | undefined;
76
76
  } & {
77
77
  requestConfig?: Partial<Omit<IMakeRequest, "body">> | undefined;
78
- }) | undefined) => Promise<IRequestSuccess<TResponse>>;
78
+ }) | undefined) => Promise<IRequestSuccess<TResponse> | undefined>;
79
79
  uploadProgressPercent: number;
80
80
  } | {
81
+ isLoading: boolean;
81
82
  data: undefined;
82
83
  error: IRequestError;
83
84
  isError: true;
84
85
  isIdle: false;
85
- isLoading: false;
86
86
  isSuccess: false;
87
87
  status: "error";
88
88
  mutate: import("@tanstack/react-query").UseMutateFunction<IRequestSuccess<TResponse>, IRequestError, {
@@ -111,14 +111,14 @@ export declare const usePostRequest: <TResponse>({ path, isFormData, baseUrl, he
111
111
  requestConfig?: Partial<Omit<IMakeRequest, "body">> | undefined;
112
112
  } & {
113
113
  requestConfig?: Partial<Omit<IMakeRequest, "body">> | undefined;
114
- }) | undefined) => Promise<IRequestSuccess<TResponse>>;
114
+ }) | undefined) => Promise<IRequestSuccess<TResponse> | undefined>;
115
115
  uploadProgressPercent: number;
116
116
  } | {
117
+ isLoading: boolean;
117
118
  data: IRequestSuccess<TResponse>;
118
119
  error: null;
119
120
  isError: false;
120
121
  isIdle: false;
121
- isLoading: false;
122
122
  isSuccess: true;
123
123
  status: "success";
124
124
  mutate: import("@tanstack/react-query").UseMutateFunction<IRequestSuccess<TResponse>, IRequestError, {
@@ -147,6 +147,6 @@ export declare const usePostRequest: <TResponse>({ path, isFormData, baseUrl, he
147
147
  requestConfig?: Partial<Omit<IMakeRequest, "body">> | undefined;
148
148
  } & {
149
149
  requestConfig?: Partial<Omit<IMakeRequest, "body">> | undefined;
150
- }) | undefined) => Promise<IRequestSuccess<TResponse>>;
150
+ }) | undefined) => Promise<IRequestSuccess<TResponse> | undefined>;
151
151
  uploadProgressPercent: number;
152
152
  };
@@ -4,11 +4,13 @@ import { useEnvironmentVariables } from '../config/useEnvironmentVariables.js';
4
4
  import { useQueryConfig } from '../config/useQueryConfig.js';
5
5
  import { useQueryHeaders } from '../config/useQueryHeaders.js';
6
6
  import { useReactNativeEnv } from '../config/useReactNativeEnv.js';
7
+ import { useState, useEffect } from 'react';
7
8
  import { scrollToTop } from '../helpers/scrollToTop.js';
8
9
  import { useUploadProgress } from '../hooks/useUploadProgress.js';
9
10
  import 'axios';
10
11
  import { makeRequest } from '../request/make-request.js';
11
12
  import { HttpMethod } from '../request/request.enum.js';
13
+ import { usePauseFutureRequests } from '../stores/usePauseFutureRequests.js';
12
14
 
13
15
  const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelectors, }) => {
14
16
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
@@ -16,6 +18,8 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelect
16
18
  const { getHeaders } = useQueryHeaders();
17
19
  const { isApp } = useReactNativeEnv();
18
20
  const { uploadProgressPercent, onUploadProgress } = useUploadProgress();
21
+ const [requestPayload, setRequestPayload] = useState();
22
+ const isFutureMutationsPaused = usePauseFutureRequests((state) => state.isFutureMutationsPaused);
19
23
  const sendRequest = async (res, rej, postData) => {
20
24
  // get request headers
21
25
  const globalHeaders = getHeaders();
@@ -69,10 +73,23 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelect
69
73
  mutationKey: [path, { type: 'mutation' }],
70
74
  });
71
75
  const post = async (data, options) => {
72
- const { requestConfig, ...otherOptions } = options ?? {};
73
- return mutation.mutateAsync({ data, requestConfig }, otherOptions);
76
+ if (!isFutureMutationsPaused) {
77
+ const { requestConfig, ...otherOptions } = options ?? {};
78
+ return mutation.mutateAsync({ data, requestConfig }, otherOptions);
79
+ }
80
+ else {
81
+ setRequestPayload({ data, options });
82
+ return undefined;
83
+ }
74
84
  };
75
- return { post, uploadProgressPercent, ...mutation };
85
+ useEffect(() => {
86
+ if (!isFutureMutationsPaused && requestPayload) {
87
+ post(requestPayload.data, requestPayload.options);
88
+ setRequestPayload(undefined);
89
+ }
90
+ // eslint-disable-next-line react-hooks/exhaustive-deps
91
+ }, [isFutureMutationsPaused]);
92
+ return { post, uploadProgressPercent, ...mutation, isLoading: mutation.isLoading || isFutureMutationsPaused };
76
93
  };
77
94
 
78
95
  export { usePostRequest };
@@ -1 +1 @@
1
- {"version":3,"file":"usePostRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"usePostRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1 @@
1
+ export * from './usePauseFutureRequests';
@@ -0,0 +1,7 @@
1
+ export interface PauseFutureRequest {
2
+ isFutureQueriesPaused: boolean;
3
+ isFutureMutationsPaused: boolean;
4
+ pauseFutureMutation: (status: boolean) => void;
5
+ pauseFutureQueries: (status: boolean) => void;
6
+ }
7
+ export declare const usePauseFutureRequests: import("zustand").UseBoundStore<import("zustand").StoreApi<PauseFutureRequest>>;
@@ -0,0 +1,19 @@
1
+ import { create } from 'zustand';
2
+
3
+ const usePauseFutureRequests = create((set) => {
4
+ const pauseFutureQueries = (status) => {
5
+ return set({ isFutureQueriesPaused: status });
6
+ };
7
+ const pauseFutureMutation = (status) => {
8
+ return set({ isFutureQueriesPaused: status });
9
+ };
10
+ return {
11
+ isFutureMutationsPaused: false,
12
+ isFutureQueriesPaused: false,
13
+ pauseFutureQueries,
14
+ pauseFutureMutation,
15
+ };
16
+ });
17
+
18
+ export { usePauseFutureRequests };
19
+ //# sourceMappingURL=usePauseFutureRequests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePauseFutureRequests.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ventlio/tanstack-query",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "contributors": [
@@ -48,6 +48,7 @@
48
48
  "@rollup/plugin-node-resolve": "^15.0.1",
49
49
  "@rollup/plugin-typescript": "^11.0.0",
50
50
  "@tanstack/react-query": "^4.26.1",
51
+ "@testing-library/react": "^13.1",
51
52
  "@testing-library/react-hooks": "^8.0.1",
52
53
  "@types/axios": "^0.14.0",
53
54
  "@types/jest": "^29.5.1",
@@ -88,6 +89,7 @@
88
89
  "dependencies": {
89
90
  "lodash.result": "^4.5.2",
90
91
  "lodash.set": "^4.3.2",
91
- "url-search-params-polyfill": "^8.2.5"
92
+ "url-search-params-polyfill": "^8.2.5",
93
+ "zustand": "^4.4.6"
92
94
  }
93
95
  }
@@ -0,0 +1,84 @@
1
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2
+ import { renderHook } from '@testing-library/react';
3
+ import axios from 'axios';
4
+ import MockAdapter from 'axios-mock-adapter';
5
+ import type { ReactNode } from 'react';
6
+ import React from 'react';
7
+ import { useGetRequest } from '../../queries';
8
+
9
+ const mockAxios = new MockAdapter(axios);
10
+
11
+ describe('usePostRequest', () => {
12
+ const path = '/test';
13
+ const postData = { name: 'John Doe' };
14
+ const response = { id: 123, name: 'John Doe' };
15
+
16
+ const wrapper = ({ children }: { children: ReactNode }) => (
17
+ <QueryClientProvider client={new QueryClient()}>{children}</QueryClientProvider>
18
+ );
19
+ beforeEach(() => {
20
+ mockAxios.reset();
21
+ });
22
+
23
+ it('should return post function and mutation object', () => {
24
+ const { result } = renderHook(() => useGetRequest<{ id: number; name: string }>({ path, load: false }), {
25
+ wrapper,
26
+ });
27
+
28
+ expect(result.current.isLoading).toBe(false);
29
+ expect(result.current.isSuccess).toBe(false);
30
+ expect(result.current.isError).toBe(false);
31
+ });
32
+
33
+ // it('should make post request and return response data', async () => {
34
+ // mockAxios.onPost(path).reply(200, response);
35
+
36
+ // const { result, waitForNextUpdate } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path }));
37
+
38
+ // const responsePromise = result.current.post(postData);
39
+
40
+ // expect(result.current.isLoading).toBe(true);
41
+
42
+ // await waitForNextUpdate();
43
+
44
+ // expect(result.current.isLoading).toBe(false);
45
+ // expect(result.current.isSuccess).toBe(true);
46
+ // expect(result.current.data).toEqual(response);
47
+ // expect(await responsePromise).toEqual(response);
48
+ // });
49
+
50
+ // it('should make post request and return error', async () => {
51
+ // const errorMessage = 'Request failed with status code 500';
52
+ // mockAxios.onPost(path).reply(500, { message: errorMessage });
53
+
54
+ // const { result, waitForNextUpdate } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path }));
55
+
56
+ // const responsePromise = result.current.post(postData);
57
+
58
+ // expect(result.current.isLoading).toBe(true);
59
+
60
+ // await waitForNextUpdate();
61
+
62
+ // expect(result.current.isLoading).toBe(false);
63
+ // expect(result.current.isError).toBe(true);
64
+ // expect(result.current.error?.message).toBe(errorMessage);
65
+
66
+ // await expect(responsePromise).rejects.toEqual({
67
+ // message: errorMessage,
68
+ // });
69
+ // });
70
+
71
+ // it('should make post request with FormData', async () => {
72
+ // const formData = new FormData();
73
+ // formData.append('name', 'John Doe');
74
+ // mockAxios.onPost(path).reply(200, response);
75
+
76
+ // const { result } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path, isFormData: true }));
77
+
78
+ // const responsePromise = result.current.post(formData);
79
+
80
+ // expect(result.current.isLoading).toBe(true);
81
+
82
+ // await expect(responsePromise).resolves.toEqual(response);
83
+ // });
84
+ });
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export * from './config';
2
2
  export * from './helpers';
3
+ export * from './hooks';
3
4
  export * from './model';
4
5
  export * from './queries';
5
6
  export * from './request';
7
+ export * from './stores';
6
8
  export * from './types';
@@ -1,10 +1,11 @@
1
1
  import type { QueryKey, UseQueryOptions } from '@tanstack/react-query';
2
2
  import { useQuery } from '@tanstack/react-query';
3
3
  import type { RawAxiosRequestHeaders } from 'axios';
4
- import { useState } from 'react';
4
+ import { useEffect, useState } from 'react';
5
5
  import { useEnvironmentVariables, useQueryConfig, useQueryHeaders } from '../config';
6
6
  import type { IRequestError, IRequestSuccess } from '../request';
7
- import { makeRequest } from '../request';
7
+ import { HttpMethod, makeRequest } from '../request';
8
+ import { usePauseFutureRequests } from '../stores';
8
9
  import type { DefaultRequestOptions } from './queries.interface';
9
10
 
10
11
  export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOptions) => {
@@ -13,6 +14,9 @@ export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOption
13
14
  const [options, setOptions] = useState<any>();
14
15
 
15
16
  const { options: queryConfigOptions } = useQueryConfig();
17
+ const [requestPayload, setRequestPayload] = useState<Record<any, any>>();
18
+
19
+ const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
16
20
 
17
21
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
18
22
 
@@ -29,6 +33,7 @@ export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOption
29
33
  path: requestUrl,
30
34
  headers: { ...globalHeaders, ...headers },
31
35
  baseURL: baseUrl ?? API_URL,
36
+ method: HttpMethod.DELETE,
32
37
  timeout: TIMEOUT,
33
38
  };
34
39
 
@@ -75,15 +80,28 @@ export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOption
75
80
  Array<any>
76
81
  > & { cached?: boolean }
77
82
  ): Promise<IRequestSuccess<TResponse> | undefined> => {
78
- // set enabled to be true for every delete
79
- internalDeleteOptions = internalDeleteOptions ?? {};
80
- internalDeleteOptions.enabled = true;
83
+ if (!isFutureQueriesPaused) {
84
+ // set enabled to be true for every delete
85
+ internalDeleteOptions = internalDeleteOptions ?? {};
86
+ internalDeleteOptions.enabled = true;
81
87
 
82
- await setOptionsAsync(internalDeleteOptions);
83
- await updatedPathAsync(link);
88
+ await setOptionsAsync(internalDeleteOptions);
89
+ await updatedPathAsync(link);
84
90
 
85
- return query.data;
91
+ return query.data;
92
+ } else {
93
+ setRequestPayload({ link, internalDeleteOptions });
94
+ return undefined;
95
+ }
86
96
  };
87
97
 
88
- return { destroy, ...query };
98
+ useEffect(() => {
99
+ if (!isFutureQueriesPaused && requestPayload) {
100
+ destroy(requestPayload.link, requestPayload.internalDeleteOptions);
101
+ setRequestPayload(undefined);
102
+ }
103
+ // eslint-disable-next-line react-hooks/exhaustive-deps
104
+ }, [isFutureQueriesPaused]);
105
+
106
+ return { destroy, ...query, isLoading: query.isLoading || isFutureQueriesPaused };
89
107
  };
@@ -6,6 +6,7 @@ import { useEnvironmentVariables, useQueryConfig, useQueryHeaders } from '../con
6
6
 
7
7
  import type { IRequestError, IRequestSuccess } from '../request';
8
8
  import { makeRequest } from '../request';
9
+ import { usePauseFutureRequests } from '../stores';
9
10
  import type { DefaultRequestOptions, TanstackInfiniteQueryOption } from './queries.interface';
10
11
 
11
12
  interface Pagination {
@@ -36,6 +37,9 @@ export const useGetInfiniteRequest = <TResponse extends Record<string, any>>({
36
37
 
37
38
  const [options, setOptions] = useState<any>(queryOptions);
38
39
  const { options: queryConfigOptions } = useQueryConfig();
40
+ const [requestPayload, setRequestPayload] = useState<Record<any, any>>();
41
+
42
+ const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
39
43
 
40
44
  let queryClient = useQueryClient();
41
45
 
@@ -115,7 +119,7 @@ export const useGetInfiniteRequest = <TResponse extends Record<string, any>>({
115
119
  sendRequest(res, rej, queryKey, pageParam)
116
120
  ),
117
121
  {
118
- enabled: load,
122
+ enabled: load && !isFutureQueriesPaused,
119
123
  getNextPageParam: (lastPage) => constructPaginationLink('next_page', lastPage),
120
124
  getPreviousPageParam: (lastPage) => constructPaginationLink('previous_page', lastPage),
121
125
  ...options,
@@ -146,12 +150,25 @@ export const useGetInfiniteRequest = <TResponse extends Record<string, any>>({
146
150
  >
147
151
  | undefined
148
152
  > => {
149
- await setOptionsAsync(fetchOptions);
150
- await updatedPathAsync(link);
153
+ if (!isFutureQueriesPaused) {
154
+ await setOptionsAsync(fetchOptions);
155
+ await updatedPathAsync(link);
151
156
 
152
- return query.data;
157
+ return query.data;
158
+ } else {
159
+ setRequestPayload({ link, fetchOptions });
160
+ return undefined;
161
+ }
153
162
  };
154
163
 
164
+ useEffect(() => {
165
+ if (!isFutureQueriesPaused && requestPayload) {
166
+ get(requestPayload.link, requestPayload.fetchOptions);
167
+ setRequestPayload(undefined);
168
+ }
169
+ // eslint-disable-next-line react-hooks/exhaustive-deps
170
+ }, [isFutureQueriesPaused]);
171
+
155
172
  const updatedPathAsync = async (link: string) => {
156
173
  startTransition(() => {
157
174
  setRequestPath(link);
@@ -173,5 +190,6 @@ export const useGetInfiniteRequest = <TResponse extends Record<string, any>>({
173
190
  return {
174
191
  get,
175
192
  ...query,
193
+ isLoading: query.isLoading || isFutureQueriesPaused,
176
194
  };
177
195
  };
@@ -6,6 +6,7 @@ import { useEnvironmentVariables, useQueryConfig, useQueryHeaders } from '../con
6
6
 
7
7
  import type { IRequestError, IRequestSuccess } from '../request';
8
8
  import { makeRequest } from '../request';
9
+ import { usePauseFutureRequests } from '../stores';
9
10
  import type { DefaultRequestOptions, IPagination, TanstackQueryOption } from './queries.interface';
10
11
 
11
12
  export const useGetRequest = <TResponse extends Record<string, any>>({
@@ -28,6 +29,9 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
28
29
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
29
30
  const { getHeaders } = useQueryHeaders();
30
31
  const { options: queryConfigOptions } = useQueryConfig();
32
+ const [requestPayload, setRequestPayload] = useState<Record<any, any>>();
33
+
34
+ const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
31
35
 
32
36
  let queryClient = useQueryClient();
33
37
 
@@ -82,7 +86,7 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
82
86
  ({ queryKey }) =>
83
87
  new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej, queryKey)),
84
88
  {
85
- enabled: load,
89
+ enabled: load && !isFutureQueriesPaused,
86
90
  ...options,
87
91
  }
88
92
  );
@@ -165,14 +169,28 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
165
169
  Array<any>
166
170
  >
167
171
  ): Promise<IRequestSuccess<TResponse> | undefined> => {
168
- await setOptionsAsync(fetchOptions);
169
- await updatedPathAsync(link);
172
+ if (!isFutureQueriesPaused) {
173
+ await setOptionsAsync(fetchOptions);
174
+ await updatedPathAsync(link);
170
175
 
171
- return query.data;
176
+ return query.data;
177
+ } else {
178
+ setRequestPayload({ link, fetchOptions });
179
+ return undefined;
180
+ }
172
181
  };
173
182
 
183
+ useEffect(() => {
184
+ if (!isFutureQueriesPaused && requestPayload) {
185
+ get(requestPayload.link, requestPayload.fetchOptions);
186
+ setRequestPayload(undefined);
187
+ }
188
+ // eslint-disable-next-line react-hooks/exhaustive-deps
189
+ }, [isFutureQueriesPaused]);
190
+
174
191
  return {
175
192
  ...query,
193
+ isLoading: query.isLoading || isFutureQueriesPaused,
176
194
  setRequestPath,
177
195
  nextPage,
178
196
  prevPage,