@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.
@@ -1,4 +1,4 @@
1
- import { useQuery } from '@tanstack/react-query';
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 isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
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 (res, rej, queryKey) => {
29
- const [url] = queryKey;
30
- const requestUrl = (url ?? requestPath);
26
+ const sendRequest = async (path) => {
31
27
  const requestOptions = {
32
- path: requestUrl,
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
- res(deleteResponse);
36
+ return deleteResponse;
56
37
  }
57
38
  else {
58
- rej(deleteResponse);
39
+ throw deleteResponse;
59
40
  }
60
41
  };
61
- const query = useQuery({
62
- queryKey: [requestPath, {}],
63
- queryFn: ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)),
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
- const updatedPathAsync = async (link) => {
68
- return setRequestPath(link);
69
- };
70
- const setOptionsAsync = async (fetchOptions) => {
71
- return setOptions(fetchOptions);
72
- };
73
- const destroy = async (link, internalDeleteOptions) => {
74
- if (!isFutureQueriesPaused) {
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({ link, internalDeleteOptions });
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 (!isFutureQueriesPaused && requestPayload) {
90
- destroy(requestPayload.link, requestPayload.internalDeleteOptions);
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
- }, [isFutureQueriesPaused]);
95
- return { destroy, ...query, isLoading: query.isLoading || isFutureQueriesPaused };
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, useEffect, startTransition } from 'react';
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
- let queryClient = useQueryClient();
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
- const sendRequest = async (res, rej, queryKey) => {
42
- const [url] = queryKey;
43
- const requestUrl = (url ?? requestPath);
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
- res(getResponse);
67
+ return getResponse;
71
68
  }
72
69
  else {
73
- rej(getResponse);
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 }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)),
79
- enabled: load && !isFutureQueriesPaused,
80
- ...options,
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
- // The linter thinks query.data is always falsy, but we know it can be defined after a successful query
115
- // Let's restructure to avoid the conditional
116
- const paginationData = query.data && getPaginationData(query.data);
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
- setRequestPath(constructPaginationLink(requestPath, paginationData.next_page));
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
- // The linter thinks query.data is always falsy, but we know it can be defined after a successful query
129
- // Let's restructure to avoid the conditional
130
- const paginationData = query.data && getPaginationData(query.data);
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
- setRequestPath(constructPaginationLink(requestPath, paginationData.previous_page));
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
- * Construct a pagination URL using the configured builder
161
+ * Navigate to a specific page
140
162
  */
141
- const constructPaginationLink = (link, pageNumber) => {
142
- // Use the configured pagination URL builder or fall back to default
143
- const buildPaginationUrl = pagination.buildPaginationUrl ||
144
- ((url, page) => {
145
- const [pathname, queryString] = url.split('?');
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
- * Navigate to a specific page
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 gotoPage = (pageNumber) => {
163
- setRequestPath(constructPaginationLink(requestPath, pageNumber));
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
- // eslint-disable-next-line react-hooks/exhaustive-deps
192
- }, [isFutureQueriesPaused]);
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
- // Add pagination data accessor - restructured to avoid linter error
204
- getPaginationData: function () {
205
- return query.data ? getPaginationData(query.data) : undefined;
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 { context, headerProvider } = useStore(bootStore);
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 { context, headerProvider } = useStore(bootStore);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ventlio/tanstack-query",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "contributors": [
@@ -1,3 +1,2 @@
1
1
  export { result } from './result';
2
- export * from './scrollToTop';
3
2
  export * from './timeFuncs';
@@ -1,5 +1,5 @@
1
- import type { QueryKey, UseQueryOptions } from '@tanstack/react-query';
2
- import { useQuery } from '@tanstack/react-query';
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<Record<any, any>>();
16
+ const [requestPayload, setRequestPayload] = useState<{ path: string; options?: any }>();
19
17
 
20
- const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
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 (res: (value: any) => void, rej: (reason?: any) => void, queryKey: QueryKey) => {
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: requestUrl,
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
- res(deleteResponse as IRequestSuccess<TResponse>);
42
+ return deleteResponse as IRequestSuccess<TResponse>;
63
43
  } else {
64
- rej(deleteResponse);
44
+ throw deleteResponse;
65
45
  }
66
46
  };
67
47
 
68
- const query = useQuery<any, any, IRequestSuccess<TResponse>>({
69
- queryKey: [requestPath, {}],
70
- queryFn: ({ queryKey }) =>
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
- const updatedPathAsync = async (link: string) => {
77
- return setRequestPath(link);
78
- };
79
-
80
- const setOptionsAsync = async (fetchOptions: any) => {
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
- link: string,
86
- internalDeleteOptions?: UseQueryOptions<
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 (!isFutureQueriesPaused) {
94
- // set enabled to be true for every delete
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({ link, internalDeleteOptions });
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 (!isFutureQueriesPaused && requestPayload) {
111
- destroy(requestPayload.link, requestPayload.internalDeleteOptions);
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
- }, [isFutureQueriesPaused]);
116
-
117
- return { destroy, ...query, isLoading: (query.isLoading as boolean) || isFutureQueriesPaused };
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
  };