@ventlio/tanstack-query 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helpers/index.d.ts +0 -1
- package/dist/index.mjs +121 -162
- package/dist/index.mjs.map +1 -1
- package/dist/queries/useDeleteRequest.d.ts +93 -39
- package/dist/queries/useGetRequest.d.ts +125 -12
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/queries/useDeleteRequest.js +29 -50
- package/dist/src/queries/useDeleteRequest.js.map +1 -1
- package/dist/src/queries/useGetRequest.js +89 -86
- package/dist/src/queries/useGetRequest.js.map +1 -1
- package/dist/src/queries/usePatchRequest.js +1 -10
- package/dist/src/queries/usePatchRequest.js.map +1 -1
- package/dist/src/queries/usePostRequest.js +1 -10
- package/dist/src/queries/usePostRequest.js.map +1 -1
- package/package.json +1 -1
- package/src/helpers/index.ts +0 -1
- package/src/queries/useDeleteRequest.ts +33 -65
- package/src/queries/useGetRequest.ts +158 -156
- package/src/queries/usePatchRequest.ts +1 -10
- package/src/queries/usePostRequest.ts +1 -11
- package/src/queries/usePutRequest.ts +1 -10
- package/dist/helpers/scrollToTop.d.ts +0 -1
- package/dist/src/helpers/scrollToTop.js +0 -9
- package/dist/src/helpers/scrollToTop.js.map +0 -1
- package/src/helpers/scrollToTop.ts +0 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMutation } from '@tanstack/react-query';
|
|
2
2
|
import { useStore } from '../../node_modules/@tanstack/react-store/dist/esm/index.js';
|
|
3
3
|
import { useState, useMemo, useEffect } from 'react';
|
|
4
4
|
import 'url-search-params-polyfill';
|
|
@@ -13,11 +13,9 @@ import { HttpMethod } from '../request/request.enum.js';
|
|
|
13
13
|
|
|
14
14
|
const useDeleteRequest = (deleteOptions) => {
|
|
15
15
|
const { baseUrl, headers } = deleteOptions ?? {};
|
|
16
|
-
const [requestPath, setRequestPath] = useState('');
|
|
17
|
-
const [options, setOptions] = useState();
|
|
18
16
|
const { headerProvider } = useStore(bootStore);
|
|
19
17
|
const [requestPayload, setRequestPayload] = useState();
|
|
20
|
-
const
|
|
18
|
+
const isFutureMutationsPaused = usePauseFutureRequests((state) => state.isFutureMutationsPaused);
|
|
21
19
|
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
22
20
|
const storeHeaders = useHeaderStore((state) => state.headers);
|
|
23
21
|
// Get headers from both the store and the headerProvider (if configured)
|
|
@@ -25,74 +23,55 @@ const useDeleteRequest = (deleteOptions) => {
|
|
|
25
23
|
const providerHeaders = headerProvider ? headerProvider() : undefined;
|
|
26
24
|
return { ...providerHeaders, ...storeHeaders };
|
|
27
25
|
}, [storeHeaders, headerProvider]);
|
|
28
|
-
const sendRequest = async (
|
|
29
|
-
const [url] = queryKey;
|
|
30
|
-
const requestUrl = (url ?? requestPath);
|
|
26
|
+
const sendRequest = async (path) => {
|
|
31
27
|
const requestOptions = {
|
|
32
|
-
path
|
|
28
|
+
path,
|
|
33
29
|
headers: { ...globalHeaders, ...headers },
|
|
34
30
|
baseURL: baseUrl ?? API_URL,
|
|
35
31
|
method: HttpMethod.DELETE,
|
|
36
32
|
timeout: TIMEOUT,
|
|
37
33
|
};
|
|
38
|
-
// let deleteResponse: IRequestError | IRequestSuccess<TResponse>;
|
|
39
|
-
// if (middleware) {
|
|
40
|
-
// // perform global middleware
|
|
41
|
-
// deleteResponse = await middleware(
|
|
42
|
-
// async (middlewareOptions) =>
|
|
43
|
-
// await makeRequest<TResponse>(
|
|
44
|
-
// middlewareOptions ? { ...requestOptions, ...middlewareOptions } : requestOptions
|
|
45
|
-
// ),
|
|
46
|
-
// {
|
|
47
|
-
// path: requestUrl,
|
|
48
|
-
// baseUrl: baseUrl ?? API_URL,
|
|
49
|
-
// }
|
|
50
|
-
// );
|
|
51
|
-
// } else {
|
|
52
34
|
const deleteResponse = await makeRequest(requestOptions);
|
|
53
|
-
// }
|
|
54
35
|
if (deleteResponse.status) {
|
|
55
|
-
|
|
36
|
+
return deleteResponse;
|
|
56
37
|
}
|
|
57
38
|
else {
|
|
58
|
-
|
|
39
|
+
throw deleteResponse;
|
|
59
40
|
}
|
|
60
41
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
enabled: false,
|
|
65
|
-
...options,
|
|
42
|
+
// Use mutation instead of query for DELETE operations
|
|
43
|
+
const mutation = useMutation({
|
|
44
|
+
mutationFn: async ({ path }) => sendRequest(path),
|
|
66
45
|
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// set enabled to be true for every delete
|
|
76
|
-
internalDeleteOptions = internalDeleteOptions
|
|
77
|
-
? { ...internalDeleteOptions, queryKey: [link, {}], enabled: true }
|
|
78
|
-
: { queryKey: [link, {}], enabled: true };
|
|
79
|
-
await setOptionsAsync(internalDeleteOptions);
|
|
80
|
-
await updatedPathAsync(link);
|
|
81
|
-
return query.data;
|
|
46
|
+
/**
|
|
47
|
+
* Perform a DELETE request to the specified path
|
|
48
|
+
* @param path - The API path to send the DELETE request to
|
|
49
|
+
* @param options - Optional mutation options (onSuccess, onError, etc.)
|
|
50
|
+
*/
|
|
51
|
+
const destroy = async (path, options) => {
|
|
52
|
+
if (!isFutureMutationsPaused) {
|
|
53
|
+
return mutation.mutateAsync({ path }, options);
|
|
82
54
|
}
|
|
83
55
|
else {
|
|
84
|
-
setRequestPayload({
|
|
56
|
+
setRequestPayload({ path, options });
|
|
85
57
|
return undefined;
|
|
86
58
|
}
|
|
87
59
|
};
|
|
60
|
+
// Resume paused requests when mutations are unpaused
|
|
88
61
|
useEffect(() => {
|
|
89
|
-
if (!
|
|
90
|
-
destroy(requestPayload.
|
|
62
|
+
if (!isFutureMutationsPaused && requestPayload) {
|
|
63
|
+
destroy(requestPayload.path, requestPayload.options);
|
|
91
64
|
setRequestPayload(undefined);
|
|
92
65
|
}
|
|
93
66
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
94
|
-
}, [
|
|
95
|
-
return {
|
|
67
|
+
}, [isFutureMutationsPaused]);
|
|
68
|
+
return {
|
|
69
|
+
destroy,
|
|
70
|
+
...mutation,
|
|
71
|
+
isLoading: mutation.isPending || isFutureMutationsPaused,
|
|
72
|
+
// For backward compatibility - mutations don't have initial loading state
|
|
73
|
+
isInitialLoading: false,
|
|
74
|
+
};
|
|
96
75
|
};
|
|
97
76
|
|
|
98
77
|
export { useDeleteRequest };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDeleteRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useDeleteRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useQueryClient, useQuery } from '@tanstack/react-query';
|
|
2
|
-
import { useState, useMemo,
|
|
2
|
+
import { useState, useMemo, useCallback, useEffect } from 'react';
|
|
3
3
|
import 'url-search-params-polyfill';
|
|
4
4
|
import { bootStore } from '../config/bootStore.js';
|
|
5
5
|
import { useEnvironmentVariables } from '../config/useEnvironmentVariables.js';
|
|
@@ -16,7 +16,6 @@ import '../request/request.enum.js';
|
|
|
16
16
|
*/
|
|
17
17
|
const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, paginationConfig, }) => {
|
|
18
18
|
const [requestPath, setRequestPath] = useState(path);
|
|
19
|
-
const [options, setOptions] = useState(queryOptions);
|
|
20
19
|
const [page, setPage] = useState(1);
|
|
21
20
|
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
22
21
|
const { middleware, pagination: globalPaginationConfig, headerProvider } = useStore(bootStore);
|
|
@@ -28,19 +27,17 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
28
27
|
// Merge: store headers take precedence over provider headers
|
|
29
28
|
return { ...providerHeaders, ...storeHeaders };
|
|
30
29
|
}, [storeHeaders, headerProvider]);
|
|
31
|
-
const [requestPayload, setRequestPayload] = useState();
|
|
32
30
|
const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
|
|
33
|
-
|
|
34
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35
|
-
queryClient = useMemo(() => queryClient, []);
|
|
31
|
+
const queryClient = useQueryClient();
|
|
36
32
|
// Merge global and local pagination config
|
|
37
33
|
const pagination = useMemo(() => ({
|
|
38
34
|
...globalPaginationConfig,
|
|
39
35
|
...paginationConfig,
|
|
40
36
|
}), [globalPaginationConfig, paginationConfig]);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Core request function that makes the actual HTTP request
|
|
39
|
+
*/
|
|
40
|
+
const executeRequest = useCallback(async (requestUrl) => {
|
|
44
41
|
const requestOptions = {
|
|
45
42
|
path: requestUrl,
|
|
46
43
|
headers: { ...globalHeaders, ...headers },
|
|
@@ -67,26 +64,32 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
67
64
|
getResponse = await makeRequest(requestOptions);
|
|
68
65
|
}
|
|
69
66
|
if (getResponse.status) {
|
|
70
|
-
|
|
67
|
+
return getResponse;
|
|
71
68
|
}
|
|
72
69
|
else {
|
|
73
|
-
|
|
70
|
+
throw getResponse;
|
|
74
71
|
}
|
|
75
|
-
};
|
|
72
|
+
}, [globalHeaders, headers, baseUrl, API_URL, TIMEOUT, middleware]);
|
|
73
|
+
// The declarative query - only runs when load is true
|
|
76
74
|
const query = useQuery({
|
|
77
75
|
queryKey: [requestPath, {}],
|
|
78
|
-
queryFn: ({ queryKey }) =>
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
queryFn: async ({ queryKey }) => {
|
|
77
|
+
const [url] = queryKey;
|
|
78
|
+
return executeRequest(url);
|
|
79
|
+
},
|
|
80
|
+
// Only enable when load is explicitly true AND queries aren't paused
|
|
81
|
+
enabled: load === true && !isFutureQueriesPaused,
|
|
82
|
+
...queryOptions,
|
|
81
83
|
});
|
|
84
|
+
// Update request path when prop changes
|
|
82
85
|
useEffect(() => {
|
|
83
|
-
if (path) {
|
|
86
|
+
if (path && path !== requestPath) {
|
|
84
87
|
setRequestPath(path);
|
|
85
88
|
}
|
|
86
|
-
}, [path]);
|
|
89
|
+
}, [path, requestPath]);
|
|
90
|
+
// Track query key for external reference
|
|
87
91
|
useEffect(() => {
|
|
88
92
|
if (keyTracker) {
|
|
89
|
-
// set expiration time for the tracker
|
|
90
93
|
queryClient.setQueryDefaults([keyTracker], {
|
|
91
94
|
staleTime: Infinity,
|
|
92
95
|
});
|
|
@@ -96,8 +99,7 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
96
99
|
/**
|
|
97
100
|
* Extract pagination data from response using configured extractor
|
|
98
101
|
*/
|
|
99
|
-
const getPaginationData = (response) => {
|
|
100
|
-
// Use the configured pagination extractor or fall back to default
|
|
102
|
+
const getPaginationData = useCallback((response) => {
|
|
101
103
|
const extractPagination = pagination.extractPagination ||
|
|
102
104
|
((res) => {
|
|
103
105
|
if ('pagination' in res.data) {
|
|
@@ -106,90 +108,90 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
106
108
|
return undefined;
|
|
107
109
|
});
|
|
108
110
|
return extractPagination(response);
|
|
109
|
-
};
|
|
111
|
+
}, [pagination.extractPagination]);
|
|
112
|
+
/**
|
|
113
|
+
* Construct a pagination URL using the configured builder
|
|
114
|
+
*/
|
|
115
|
+
const constructPaginationLink = useCallback((link, pageNumber) => {
|
|
116
|
+
const buildPaginationUrl = pagination.buildPaginationUrl ||
|
|
117
|
+
((url, targetPage) => {
|
|
118
|
+
const [pathname, queryString] = url.split('?');
|
|
119
|
+
const queryParams = new URLSearchParams(queryString || '');
|
|
120
|
+
const pageParamName = pagination.pageParamName || 'page';
|
|
121
|
+
queryParams.set(pageParamName, String(targetPage));
|
|
122
|
+
return pathname + '?' + queryParams.toString();
|
|
123
|
+
});
|
|
124
|
+
return buildPaginationUrl(link, pageNumber);
|
|
125
|
+
}, [pagination.buildPaginationUrl, pagination.pageParamName]);
|
|
110
126
|
/**
|
|
111
127
|
* Navigate to the next page if available
|
|
112
128
|
*/
|
|
113
|
-
const nextPage = () => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
129
|
+
const nextPage = useCallback(() => {
|
|
130
|
+
const data = query.data;
|
|
131
|
+
if (!data)
|
|
132
|
+
return;
|
|
133
|
+
const paginationData = getPaginationData(data);
|
|
117
134
|
if (!paginationData)
|
|
118
135
|
return;
|
|
119
136
|
if (paginationData.next_page !== paginationData.current_page &&
|
|
120
137
|
paginationData.next_page > paginationData.current_page) {
|
|
121
|
-
|
|
138
|
+
const newPath = constructPaginationLink(requestPath, paginationData.next_page);
|
|
139
|
+
setRequestPath(newPath);
|
|
140
|
+
setPage(paginationData.next_page);
|
|
122
141
|
}
|
|
123
|
-
};
|
|
142
|
+
}, [query.data, getPaginationData, constructPaginationLink, requestPath]);
|
|
124
143
|
/**
|
|
125
144
|
* Navigate to the previous page if available
|
|
126
145
|
*/
|
|
127
|
-
const prevPage = () => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
146
|
+
const prevPage = useCallback(() => {
|
|
147
|
+
const data = query.data;
|
|
148
|
+
if (!data)
|
|
149
|
+
return;
|
|
150
|
+
const paginationData = getPaginationData(data);
|
|
131
151
|
if (!paginationData)
|
|
132
152
|
return;
|
|
133
153
|
if (paginationData.previous_page !== paginationData.current_page &&
|
|
134
154
|
paginationData.previous_page < paginationData.current_page) {
|
|
135
|
-
|
|
155
|
+
const newPath = constructPaginationLink(requestPath, paginationData.previous_page);
|
|
156
|
+
setRequestPath(newPath);
|
|
157
|
+
setPage(paginationData.previous_page);
|
|
136
158
|
}
|
|
137
|
-
};
|
|
159
|
+
}, [query.data, getPaginationData, constructPaginationLink, requestPath]);
|
|
138
160
|
/**
|
|
139
|
-
*
|
|
161
|
+
* Navigate to a specific page
|
|
140
162
|
*/
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const queryParams = new URLSearchParams(queryString || '');
|
|
147
|
-
const pageParamName = pagination.pageParamName || 'page';
|
|
148
|
-
const oldPage = Number(queryParams.get(pageParamName));
|
|
149
|
-
queryParams.set(pageParamName, String(page));
|
|
150
|
-
const newUrl = pathname + '?' + queryParams.toString();
|
|
151
|
-
// only update page when pagination number changed
|
|
152
|
-
if (oldPage !== pageNumber) {
|
|
153
|
-
setPage(pageNumber);
|
|
154
|
-
}
|
|
155
|
-
return newUrl;
|
|
156
|
-
});
|
|
157
|
-
return buildPaginationUrl(link, pageNumber);
|
|
158
|
-
};
|
|
163
|
+
const gotoPage = useCallback((pageNumber) => {
|
|
164
|
+
const newPath = constructPaginationLink(requestPath, pageNumber);
|
|
165
|
+
setRequestPath(newPath);
|
|
166
|
+
setPage(pageNumber);
|
|
167
|
+
}, [constructPaginationLink, requestPath]);
|
|
159
168
|
/**
|
|
160
|
-
*
|
|
169
|
+
* Imperative GET request - fetches data from a dynamic URL
|
|
170
|
+
* Uses queryClient.fetchQuery for proper caching and deduplication
|
|
171
|
+
*
|
|
172
|
+
* @param url - The URL to fetch from
|
|
173
|
+
* @param fetchOptions - Optional query options (staleTime, gcTime, etc.)
|
|
174
|
+
* @returns Promise resolving to the response data
|
|
161
175
|
*/
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const updatedPathAsync = async (link) => {
|
|
166
|
-
startTransition(() => {
|
|
167
|
-
setRequestPath(link);
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
const setOptionsAsync = async (fetchOptions) => {
|
|
171
|
-
startTransition(() => {
|
|
172
|
-
setOptions(fetchOptions);
|
|
173
|
-
});
|
|
174
|
-
};
|
|
175
|
-
const get = async (link, fetchOptions) => {
|
|
176
|
-
if (!isFutureQueriesPaused) {
|
|
177
|
-
await setOptionsAsync(fetchOptions);
|
|
178
|
-
await updatedPathAsync(link);
|
|
179
|
-
return query.data;
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
setRequestPayload({ link, fetchOptions });
|
|
183
|
-
return undefined;
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
useEffect(() => {
|
|
187
|
-
if (!isFutureQueriesPaused && requestPayload) {
|
|
188
|
-
get(requestPayload.link, requestPayload.fetchOptions);
|
|
189
|
-
setRequestPayload(undefined);
|
|
176
|
+
const get = useCallback(async (url, fetchOptions) => {
|
|
177
|
+
if (isFutureQueriesPaused) {
|
|
178
|
+
throw new Error('Queries are currently paused');
|
|
190
179
|
}
|
|
191
|
-
//
|
|
192
|
-
|
|
180
|
+
// Use fetchQuery for imperative fetching - this properly handles caching
|
|
181
|
+
const result = await queryClient.fetchQuery({
|
|
182
|
+
queryKey: [url, {}],
|
|
183
|
+
queryFn: () => executeRequest(url),
|
|
184
|
+
staleTime: fetchOptions?.staleTime,
|
|
185
|
+
gcTime: fetchOptions?.gcTime,
|
|
186
|
+
});
|
|
187
|
+
return result;
|
|
188
|
+
}, [queryClient, executeRequest, isFutureQueriesPaused]);
|
|
189
|
+
/**
|
|
190
|
+
* Refetch the current query with the existing path
|
|
191
|
+
*/
|
|
192
|
+
const refetch = useCallback(() => {
|
|
193
|
+
return query.refetch();
|
|
194
|
+
}, [query]);
|
|
193
195
|
return {
|
|
194
196
|
...query,
|
|
195
197
|
isLoading: query.isLoading || isFutureQueriesPaused,
|
|
@@ -199,10 +201,11 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
199
201
|
get,
|
|
200
202
|
gotoPage,
|
|
201
203
|
page,
|
|
204
|
+
refetch,
|
|
202
205
|
queryKey: [requestPath, {}],
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
return
|
|
206
|
+
getPaginationData: () => {
|
|
207
|
+
const data = query.data;
|
|
208
|
+
return data ? getPaginationData(data) : undefined;
|
|
206
209
|
},
|
|
207
210
|
};
|
|
208
211
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGetRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useGetRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -7,7 +7,6 @@ import { useEnvironmentVariables } from '../config/useEnvironmentVariables.js';
|
|
|
7
7
|
import '../stores/useBaseUrlStore.js';
|
|
8
8
|
import { useHeaderStore } from '../stores/useHeaderStore.js';
|
|
9
9
|
import { usePauseFutureRequests } from '../stores/usePauseFutureRequests.js';
|
|
10
|
-
import { scrollToTop } from '../helpers/scrollToTop.js';
|
|
11
10
|
import { useUploadProgress } from '../hooks/useUploadProgress.js';
|
|
12
11
|
import 'axios';
|
|
13
12
|
import { makeRequest } from '../request/make-request.js';
|
|
@@ -16,7 +15,7 @@ import { HttpMethod } from '../request/request.enum.js';
|
|
|
16
15
|
const usePatchRequest = ({ path, baseUrl, headers }) => {
|
|
17
16
|
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
18
17
|
const { uploadProgressPercent, onUploadProgress } = useUploadProgress();
|
|
19
|
-
const {
|
|
18
|
+
const { headerProvider } = useStore(bootStore);
|
|
20
19
|
const storeHeaders = useHeaderStore((state) => state.headers);
|
|
21
20
|
// Get headers from both the store and the headerProvider (if configured)
|
|
22
21
|
const globalHeaders = useMemo(() => {
|
|
@@ -55,17 +54,9 @@ const usePatchRequest = ({ path, baseUrl, headers }) => {
|
|
|
55
54
|
const patchResponse = await makeRequest(requestOptions);
|
|
56
55
|
// }
|
|
57
56
|
if (patchResponse.status) {
|
|
58
|
-
// scroll to top after success
|
|
59
|
-
if (context !== 'app') {
|
|
60
|
-
scrollToTop();
|
|
61
|
-
}
|
|
62
57
|
res(patchResponse);
|
|
63
58
|
}
|
|
64
59
|
else {
|
|
65
|
-
// scroll to top after error
|
|
66
|
-
if (context !== 'app') {
|
|
67
|
-
scrollToTop();
|
|
68
|
-
}
|
|
69
60
|
rej(patchResponse);
|
|
70
61
|
}
|
|
71
62
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePatchRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePatchRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -8,7 +8,6 @@ import { usePauseFutureRequests } from '../stores/usePauseFutureRequests.js';
|
|
|
8
8
|
import { useReactNativeEnv } from '../config/useReactNativeEnv.js';
|
|
9
9
|
import { useStore } from '../../node_modules/@tanstack/react-store/dist/esm/index.js';
|
|
10
10
|
import { useMemo, useState, useEffect } from 'react';
|
|
11
|
-
import { scrollToTop } from '../helpers/scrollToTop.js';
|
|
12
11
|
import { useUploadProgress } from '../hooks/useUploadProgress.js';
|
|
13
12
|
import 'axios';
|
|
14
13
|
import { makeRequest } from '../request/make-request.js';
|
|
@@ -16,7 +15,7 @@ import { HttpMethod } from '../request/request.enum.js';
|
|
|
16
15
|
|
|
17
16
|
const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelectors, }) => {
|
|
18
17
|
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
19
|
-
const {
|
|
18
|
+
const { headerProvider } = useStore(bootStore);
|
|
20
19
|
const storeHeaders = useHeaderStore((state) => state.headers);
|
|
21
20
|
// Get headers from both the store and the headerProvider (if configured)
|
|
22
21
|
// headerProvider allows reading from cookies/localStorage synchronously
|
|
@@ -66,17 +65,9 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelect
|
|
|
66
65
|
const postResponse = await makeRequest(requestOptions);
|
|
67
66
|
// }
|
|
68
67
|
if (postResponse.status) {
|
|
69
|
-
// scroll to top after success
|
|
70
|
-
if (context !== 'app') {
|
|
71
|
-
scrollToTop();
|
|
72
|
-
}
|
|
73
68
|
res(postResponse);
|
|
74
69
|
}
|
|
75
70
|
else {
|
|
76
|
-
// scroll to top after error
|
|
77
|
-
if (context !== 'app') {
|
|
78
|
-
scrollToTop();
|
|
79
|
-
}
|
|
80
71
|
rej(postResponse);
|
|
81
72
|
}
|
|
82
73
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePostRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePostRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
package/src/helpers/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { MutateOptions } from '@tanstack/react-query';
|
|
2
|
+
import { useMutation } from '@tanstack/react-query';
|
|
3
3
|
import { useStore } from '@tanstack/react-store';
|
|
4
4
|
import { useEffect, useMemo, useState } from 'react';
|
|
5
5
|
import { useEnvironmentVariables } from '../config';
|
|
@@ -11,13 +11,11 @@ import type { DefaultRequestOptions } from './queries.interface';
|
|
|
11
11
|
|
|
12
12
|
export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOptions) => {
|
|
13
13
|
const { baseUrl, headers } = deleteOptions ?? {};
|
|
14
|
-
const [requestPath, setRequestPath] = useState<string>('');
|
|
15
|
-
const [options, setOptions] = useState<any>();
|
|
16
14
|
|
|
17
15
|
const { headerProvider } = useStore(bootStore);
|
|
18
|
-
const [requestPayload, setRequestPayload] = useState<
|
|
16
|
+
const [requestPayload, setRequestPayload] = useState<{ path: string; options?: any }>();
|
|
19
17
|
|
|
20
|
-
const
|
|
18
|
+
const isFutureMutationsPaused = usePauseFutureRequests((state) => state.isFutureMutationsPaused);
|
|
21
19
|
|
|
22
20
|
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
23
21
|
|
|
@@ -29,90 +27,60 @@ export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOption
|
|
|
29
27
|
return { ...providerHeaders, ...storeHeaders };
|
|
30
28
|
}, [storeHeaders, headerProvider]);
|
|
31
29
|
|
|
32
|
-
const sendRequest = async (
|
|
33
|
-
const [url] = queryKey;
|
|
34
|
-
const requestUrl = (url ?? requestPath) as string;
|
|
35
|
-
|
|
30
|
+
const sendRequest = async (path: string): Promise<IRequestSuccess<TResponse>> => {
|
|
36
31
|
const requestOptions = {
|
|
37
|
-
path
|
|
32
|
+
path,
|
|
38
33
|
headers: { ...globalHeaders, ...headers },
|
|
39
34
|
baseURL: baseUrl ?? API_URL,
|
|
40
35
|
method: HttpMethod.DELETE,
|
|
41
36
|
timeout: TIMEOUT,
|
|
42
37
|
};
|
|
43
38
|
|
|
44
|
-
// let deleteResponse: IRequestError | IRequestSuccess<TResponse>;
|
|
45
|
-
// if (middleware) {
|
|
46
|
-
// // perform global middleware
|
|
47
|
-
// deleteResponse = await middleware(
|
|
48
|
-
// async (middlewareOptions) =>
|
|
49
|
-
// await makeRequest<TResponse>(
|
|
50
|
-
// middlewareOptions ? { ...requestOptions, ...middlewareOptions } : requestOptions
|
|
51
|
-
// ),
|
|
52
|
-
// {
|
|
53
|
-
// path: requestUrl,
|
|
54
|
-
// baseUrl: baseUrl ?? API_URL,
|
|
55
|
-
// }
|
|
56
|
-
// );
|
|
57
|
-
// } else {
|
|
58
39
|
const deleteResponse = await makeRequest<TResponse>(requestOptions);
|
|
59
|
-
// }
|
|
60
40
|
|
|
61
41
|
if (deleteResponse.status) {
|
|
62
|
-
|
|
42
|
+
return deleteResponse as IRequestSuccess<TResponse>;
|
|
63
43
|
} else {
|
|
64
|
-
|
|
44
|
+
throw deleteResponse;
|
|
65
45
|
}
|
|
66
46
|
};
|
|
67
47
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej, queryKey)),
|
|
72
|
-
enabled: false,
|
|
73
|
-
...options,
|
|
48
|
+
// Use mutation instead of query for DELETE operations
|
|
49
|
+
const mutation = useMutation<IRequestSuccess<TResponse>, IRequestError, { path: string }>({
|
|
50
|
+
mutationFn: async ({ path }) => sendRequest(path),
|
|
74
51
|
});
|
|
75
52
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return setOptions(fetchOptions);
|
|
82
|
-
};
|
|
83
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Perform a DELETE request to the specified path
|
|
55
|
+
* @param path - The API path to send the DELETE request to
|
|
56
|
+
* @param options - Optional mutation options (onSuccess, onError, etc.)
|
|
57
|
+
*/
|
|
84
58
|
const destroy = async (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
IRequestSuccess<TResponse | undefined>,
|
|
88
|
-
IRequestError,
|
|
89
|
-
IRequestSuccess<TResponse | undefined>,
|
|
90
|
-
Array<any>
|
|
91
|
-
> & { cached?: boolean }
|
|
59
|
+
path: string,
|
|
60
|
+
options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, { path: string }, unknown>
|
|
92
61
|
): Promise<IRequestSuccess<TResponse> | undefined> => {
|
|
93
|
-
if (!
|
|
94
|
-
|
|
95
|
-
internalDeleteOptions = internalDeleteOptions
|
|
96
|
-
? { ...internalDeleteOptions, queryKey: [link, {}], enabled: true }
|
|
97
|
-
: { queryKey: [link, {}], enabled: true };
|
|
98
|
-
|
|
99
|
-
await setOptionsAsync(internalDeleteOptions);
|
|
100
|
-
await updatedPathAsync(link);
|
|
101
|
-
|
|
102
|
-
return query.data;
|
|
62
|
+
if (!isFutureMutationsPaused) {
|
|
63
|
+
return mutation.mutateAsync({ path }, options);
|
|
103
64
|
} else {
|
|
104
|
-
setRequestPayload({
|
|
65
|
+
setRequestPayload({ path, options });
|
|
105
66
|
return undefined;
|
|
106
67
|
}
|
|
107
68
|
};
|
|
108
69
|
|
|
70
|
+
// Resume paused requests when mutations are unpaused
|
|
109
71
|
useEffect(() => {
|
|
110
|
-
if (!
|
|
111
|
-
destroy(requestPayload.
|
|
72
|
+
if (!isFutureMutationsPaused && requestPayload) {
|
|
73
|
+
destroy(requestPayload.path, requestPayload.options);
|
|
112
74
|
setRequestPayload(undefined);
|
|
113
75
|
}
|
|
114
76
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
115
|
-
}, [
|
|
116
|
-
|
|
117
|
-
return {
|
|
77
|
+
}, [isFutureMutationsPaused]);
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
destroy,
|
|
81
|
+
...mutation,
|
|
82
|
+
isLoading: mutation.isPending || isFutureMutationsPaused,
|
|
83
|
+
// For backward compatibility - mutations don't have initial loading state
|
|
84
|
+
isInitialLoading: false,
|
|
85
|
+
};
|
|
118
86
|
};
|